MWE
To generate PlantUML diagrams in (sub)folder: /Diagrams/ I use the following python script:
from plantuml import PlantUML
import os
from os.path import abspath
from shutil import copyfile
os.environ['PLANTUML_LIMIT_SIZE'] = str(4096 * 4) # set max with to 4 times the default (16,384)
server = PlantUML(url='http://www.plantuml.com/plantuml/img/',
basic_auth={},
form_auth={}, http_opts={}, request_opts={})
diagram_dir = "./Diagrams"
#directory = os.fsencode()
for file in os.listdir(diagram_dir):
filename = os.fsdecode(file)
if filename.endswith(".txt"):
server.processes_file(abspath(f'./Diagrams/{filename}'))
It is used to generate for example the following test.txt file:
#startuml
'Enforce straight lines
skinparam linetype ortho
' Set direction of graph hierarchy
Left to Right direction
' create work package data
rectangle "something something something" as ffd0
rectangle "something something something" as ffd1
rectangle "something something something something something" as ffd2
rectangle "something something something something" as ffd3
rectangle "something something somethingsomethingsomething" as ffd4
rectangle "something something something something something something" as ffd5
rectangle "something something something something" as ffd6
rectangle "something something something " as ffd7
' Implement graph hierarchy
ffd0-->ffd1
ffd1-->ffd2
ffd2-->ffd3
ffd3-->ffd4
ffd4-->ffd5
ffd5-->ffd6
ffd6-->ffd7
#enduml
Expected behavior
Because I set the PLANTUML_LIMIT_SIZE variable to 16384 (pixels) as the FAQ suggests, I would expect this to fill up the picture of the diagram with all the blocks connected side by side up to a max width of 4096 * 4 pixels.
To test whether perhaps setting it from the python script was implemented incorrectly I also tried to set it manually with: set PLANTUML_LIMIT_SIZE=16384 to expect the same behavior as explained in the above paragraph (a picture filled up till 16384 pixels).
Observed behavior
Instead PlantUML cuts off the picture at 2000 horizontal pictures as shown in the figure below:
Question
How can I ensure the PlantUML does not cut off the blocks of the diagrams of n pixels (height or width), from a python script?
The best way I've found to prevent diagrams from being cut off, without trying to guess at the size or picking some arbitrarily large limit, is to select SVG output.
Note that setting PLANTUML_LIMIT_SIZE is only going to have an effect if you're running PlantUML locally, but it appears the Python interface you're using sends the diagram to the online service. I don't know the internals of that interface, but per the documentation you should be able to get SVG output by using http://www.plantuml.com/plantuml/svg/ as the service URL.
If you need the final image in PNG format, you will need to convert it with another tool.
Approach 1:
To prevent the diagram from being cut off I followed the following steps:
Downloaded the plantuml.jar from this location http://sourceforge.net/projects/plantuml/files/plantuml.jar/download
Put the diagram which I wrote in a someLargeDiagram.txt file, in the same directory as the plantuml.jar file.
Opened terminal on Ubuntu 20.04 in that same directory and ran:
java -jar plantuml.jar -verbose someLargeDiagram.txt
That successfully generated the diagram as .png file, which was not cut off.
Approach 2:
After creating even larger graphs, they got cut-off again, and it gave the message to increase the PLANTUML_LIMIT_SIZE. I tried passing the size as an argument in the commandline using: java -jar plantuml.jar -verbose -PLANTUML_LIMIT_SIZE=8192 Diagrams/latest.uml however that did not work, nor did ..-PLANTUML_LIMIT_SIZE 8192... This link suggested one could set it as an environment variable, so I did that in Ubuntu 20.04 using command: export PLANTUML_LIMIT_SIZE 8192, after which I successfully created a larger diagram that was not cut-off with command:
java -jar plantuml.jar -verbose Diagrams/latest.uml
Related
I have been working on this code for a project at work which will (hopefully) take in images from a scanning electron microscope and generate 3D STL files of the structures were imaging. I'm at the stage with the code where I'm trying to generate a 3D structure from a 'coloured in' binary image I've made with some edge detection code I wrote. I came across this post How can i extrude a stl with python that basically does exactly what I need (generating a meshed 3D structure from a binary image). I've tried using/adapting the code in the answer to that post (see below) but I keep running into the following error: polyline2 = mr.distanceMapTo2DIsoPolyline(dm.value(), isoValue=127) RuntimeError: Bad expected access. I cant find anything online about why this is happening and I'm no expert in Python so have no idea myself. If anyone has an idea, I'd really appreciate it!
Code from answer to above post:
import meshlib.mrmeshpy as mr
# load image as Distance Map object:
dm = mr.loadDistanceMapFromImage(mr.Path("your-image.png"), 0)
# find boundary contour of the letter:
polyline2 = mr.distanceMapTo2DIsoPolyline(dm.value(), isoValue=127)
# triangulate the contour
mesh = mr.triangulateContours(polyline2.contours2())
# extrude itself:
mr.addBaseToPlanarMesh(mesh, zOffset=30)
# export the result:
mr.saveMesh(mesh, mr.Path("output-mesh.stl"))
I have tried the following:
Reconfigured the MeshLib package that this command uses. Package docs here: https://meshinspector.github.io/MeshLib/html/index.html#PythonIntegration
Updating VS studio/python/MeshLib
In older version of meshlib python module RuntimeError: Bad expected access indicated that mr.loadDistanceMapFromImage had failed, you should had checked it like this:
import meshlib.mrmeshpy as mr
# load image as Distance Map object:
dm = mr.loadDistanceMapFromImage(mr.Path("your-image.png"), 0)
# check dm
if ( not dm.has_value() ):
raise Exception(dm.error())
# find boundary contour of the letter:
polyline2 = mr.distanceMapTo2DIsoPolyline(dm.value(), isoValue=127)
# triangulate the contour
mesh = mr.triangulateContours(polyline2.contours2())
# extrude itself:
mr.addBaseToPlanarMesh(mesh, zOffset=30)
# export the result:
mr.saveMesh(mesh, mr.Path("output-mesh.stl"))
But in actual release your code will rise exception with real error.
Please make sure that path is correct, if it doesn't help please provide more info like png file and version of python and version of MeshLib and anything else you find related.
P.S. If there is real problem with MeshLib better open issue in github.
i'm not a professional coder and i'm so sorry for my english :)
i hope you understand.
I'm trying to automate part of my job.
i have to create dwg; every layer for me is a sheet (like A4 paper), for that reason i have to change layer and import specific dwg/dxf from my repository symbol.
For example i have to:
(start new project)
open newproject.dwg
(paste dwg)
import C:\repository_cad\symbol1.dwg in layer n°3 with coordinate X 100 Y 200.
(write text in the middle of symbol)
write "SYMBOL_1" layer n°3 coordinate X 150 Y200 alignment center.
(insert logo image)
import C:\repository_cad\image1.jpg in coordinate X 10 Y 20
i'm trying to use pyautocad, but i cant find a command for import dxf, and i dont find information about changing layer.
i find out only the command for draw the line, circle ecc, but if i have to re-draw all my repository by python i need to much time, i hope is possible copy draw from another dwg and paste it in my new dwg.
can someone give to me a little help with these 3 command?
maybe is not possible making this stuff on pyautocad? is there other library for python?
i read the docs but i dont see info about some import function.
so, i tried:
from pyautocad import Autocad, APoint
acad = Autocad(create_if_not_exists=False)
acad.prompt("Hello, Autocad from Python\n")
print (acad.doc.Name)
and it's works, on autocad terminal i can see "Hello, Autocad from Python"
in the Docs i find out how write a autocad-command from python.
The function is:
prompt()
i tried:
acad.prompt('-INSERT') #-INSERT is the autocad command for import dxf or dwg
acad.prompt('C:\SPAC\Librerie\Elettr\02-15-04.dwg')#this is the path of the cad
acad.prompt('-15 -15') #coord X Y of the point where i want to paste
acad.prompt('1') # 1 is the scale factor in X
acad.prompt('1') # 1 is the scale factor in Y (autocad askt first in X and after in Y
acad.prompt('0') #degree of rotation
at this point i havent error on python and no error on autocad terminal, but the draw not appear on cad
thanks
Max
acad.prompt() will just echo the string to the command line. What you are looking for is acad.doc.SendCommand(), e.g.
acad.doc.SendCommand('-INSERT ')
Notice there is a blank space after the autocad command, that stands for to activate the command.
So this GIF looks perfectly fine before opening:
But, when opened using Pillow using
imageObject = Image.open(path.join(petGifs, f"{pokemonName}.gif"))
it bugs out, adding various boxes that have colors similar to that of the source image. This is an example frame, but almost every frame is different, and it's in different spots depending on the GIF:
The only thing, that has worked to fix this, is ezgif's unoptimize option (found in their optimize page). But, I'd need to do that on each GIF, and there's a lot of them.
I need either a way to bulk unoptimize, or a new way to open the GIF in Python (currently using Pillow), that will handle this.
At least for extracting proper single frames there might be a solution.
The disposal method for all frames (except the first) is set to 2, which is "restore to background color".
Diving through Pillow's source code, you'll find the according line where the disposal method 2 is considered, and, in the following, you'll find:
# by convention, attempt to use transparency first
color = (
frame_transparency
if frame_transparency is not None
else self.info.get("background", 0)
)
self.dispose = Image.core.fill("P", dispose_size, color)
If you check the faulty frames, you'll notice that this dark green color of the unwanted boxes is located at position 0 of the palette. So, it seems, the wrong color is picked for the disposal, because – I don't know why, yet – the above else case is picked instead of using the transparency information – which would be there!
So, let's just override the possibly faulty stuff:
from PIL import Image, ImageSequence
# Open GIF
gif = Image.open('223vK.gif')
# Initialize list of extracted frames
frames = []
for frame in ImageSequence.Iterator(gif):
# If dispose is set, and color is set to 0, use transparency information
if frame.dispose is not None and frame.dispose[0] == 0:
frame.dispose = Image.core.fill('P', frame.dispose.size,
frame.info['transparency'])
# Convert frame to RGBA
frames.append(frame.convert('RGBA'))
# Visualization overhead
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 8))
for i, f in enumerate(frames, start=1):
plt.subplot(8, 8, i), plt.imshow(f), plt.axis('off')
plt.tight_layout(), plt.show()
The extracted frames look like this:
That seems fine to me.
If, by chance, the transparency information is actually set to 0, no harm should be done here, since we (re)set with the still correct transparency information.
I don't know, if (re)saving to GIF will work, since frames are now in RGBA mode, and saving to GIF from there is tricky as well.
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.19041-SP0
Python: 3.9.1
PyCharm: 2021.1.3
Matplotlib: 3.4.2
Pillow: 8.3.1
----------------------------------------
You can try to use:
from PIL import Image, ImageSequence
im = Image.open(f"{pokemonName}.gif")
index = 1
for frame in ImageSequence.Iterator(im):
frame.save("frame%d.png" % index)
index += 1
I've found a solution that I like for unoptimizing gifs which might be of use to you.
It uses the gifsicle library, which is a command line tool for working with gifs. Crucially, gifsicle lets you unoptimize gifs like yours (I think the specific name of the optimization in your gif is "cumulative layers").
Once you install it with your package manager of choice, you can either call it within your code via Python's subprocess library, or use it yourself from the command line.
You specifically mentioned a way to bulk unoptimize, and you can do that very easily with gifsicle via something like:
gifsicle -U -b *.gif
This will overwrite every gif in the working directory with an unoptimized version simultaneously. If you want to keep optimized copies make backups. See the manual page for more info about how to use gifsicle.
Once the gif is unoptimized python should be able to open it normally.
I have a 2D shell part containing a number of shell faces. I would like to extract one different sketch for each of the faces in the part. So far I know how to create a single sketch containing all the shell faces information but this is not what I want. I would like to know how to create one sketch per shell face. This is what I have done (not right).
stest= model.ConstrainedSketch(name='__polyTest__',sheetSize=2000.0)
mdb.models['Model-1'].parts['Result'].projectReferencesOntoSketch(filter=
COPLANAR_EDGES, sketch=mdb.models['Model-1'].sketches['__polyTest__'])
Many thanks for your help.
Open your part in the current viewport and try this:
from part import *
from sketch import *
p=session.viewports[session.currentViewportName].displayedObject
currentModel=mdb.models[p.modelName]
for faceNum,face in enumerate(p.faces):
try: # Will only work on valid sketch planes. Must be a flat face
t = p.MakeSketchTransform(sketchPlane=face, sketchUpEdge=p.edges[0],
sketchPlaneSide=SIDE1, origin=(659.077803, 0.256062, -816.16))
s = currentModel.ConstrainedSketch(name='__profile__',
sheetSize=834.36, gridSpacing=20.85, transform=t)
edgeList=[p.edges[edgeNum] for edgeNum in face.getEdges()]
p.projectEdgesOntoSketch(sketch=s, edges=tuple(edgeList))
currentModel.ConstrainedSketch(name='Sketch-face' + str(edgeNum), objectToCopy=s)
except:
pass
I am interested in creating a dmg disk image on MacOS X from Python, and came across the following solution: How do I create a nice-looking DMG for Mac OS X using command-line tools?
However, I am running into a strange issue related to path lengths. The following script illustrates my problem:
import os
import Image
for NAME in ['works', 'doesnotwork']:
if os.path.exists(NAME + '.dmg'):
os.remove(NAME + '.dmg')
if os.path.exists('/Volumes/' + NAME):
raise Exception("Need to eject /Volumes/%s first" % NAME)
nx = 256
ny = 256
image = Image.new("RGB", (nx, ny))
for i in range(nx):
for j in range(ny):
image.putpixel((i, j), (i, 0, j))
os.system('hdiutil create -volname %s -fs HFS+ -size 10m %s.dmg' % (NAME, NAME))
os.system('hdiutil attach -readwrite -noverify -noautoopen %s.dmg' % NAME)
os.mkdir('/Volumes/%s/.background' % NAME)
image.save('/Volumes/%s/.background/background.png' % NAME, 'PNG')
apple_script = """osascript<<END
tell application "Finder"
tell disk "%s"
open
set current view of container window to icon view
set toolbar visible of container window to false
set statusbar visible of container window to false
set the bounds of container window to {{100, 100, 355, 355}}
set theViewOptions to the icon view options of container window
set the background picture of theViewOptions to file ".background:background.png"
close
open
end tell
end tell
END""" % NAME
os.system(apple_script)
If run, the background will get correctly set in the disk image called 'works', and not in the one called 'doesnotwork'. It seems that I am limited to 5 characters for the volume name. However, if I shorten the name of the folder use to store the background, e.g. to .bkg instead of .background, then I can use a longer volume name, which suggests this is an issue related to the length of the overall path. Does anyone know at what level there is a limit on the path length? Is there a workaround to allow arbitrarily long paths?
EDIT: I am using MacOS 10.6 - the script seems to work correctly on 10.7
I believe you have to escape your quotes. You can't have quotes inside of quotes without escaping them. For example it should be, tell application \"Finder\". You have many places where your quotes are not used properly. If you look at the example script you linked to that person used single and double quotes cleverly to avoid this issue. My suggestion is you fix that.
Plus you can't refer to a file in applescript like this... ".background:background.png". Applescript doesn't know what that means when a path begins with a period. A path in applescript begins with the name of the hard drive like Macintosh HD. You need to put the whole path there in a proper applescript format. And that needs to be quoted too with escaped quotes.
Good luck.