Problem with non interactive visualization?
Opened this issue · 13 comments
Hi!,
I am starting to use vtkplotlib for plotting STL files in a Programming subject in the first year of a Mechanical Engineering degree because it is super-simple and nice to use!!. But non interactive visualization seems to be not working (window never opens). Wouldn't these sentences be enough?
...
vpl.mesh_plot(some_mesh)
vpl.gcf().update()
vpl.show(block=False)
...
Regards,
Jose.
Hmm, that should open a window but not start the event loop (i.e. the window won't respond to being clicked on). So, yes those lines should be enough (and do the job on my machine). Can I have some specs?
- OS
- VTK version (use
pip show vtk
) - vtkplotlib version
Hi!,
- OS => macOS 11.1 (Big Sur)
- Python => 3.9.1 (installed with homebrew)
- VTK => 9.0.1 (installed with homebrew also, because it seems there are not wheels for VTK and Python 3.9.x)
- vtkplotlib => 1.4.0 (installed with pip)
A student told me that it successfully runs on Windows 10 with the same version of Python and using a wheel for VTK downloaded from https://download.lfd.uci.edu/pythonlibs/z4tqcw5k/VTK-9.0.1-cp39-cp39-win_amd64.whl
Ahh, perfect timing. I just happen to have access to a Big Sur right now (normally I have to test macOS on a mac mini from 2008) and I can reproduce using with macOS 11.0 and Python 3.7.9 and VTK from PyPI. I also see no window although a blank icon appears on the bar at the bottom (the dock?). I also notice that, after calling show(block=True)
then quiting, the window won't go away until I kill Python. Have you been seeing this too?
I tried a minimal hello world VTK example and I get the same behaviour so it looks like this issue is VTK's. (Commenting out the iren.Start()
at the end is supposed to prevent it entering interactive mode.) I know that these issues aren't present on macOS 10.15 so I guess this is a Big Sur transition induced bug. Not sure there's much we can do about it...
I have not the problem with block=True, I mean, I don't need to kill Python in that case. If I close the window, the program continues / ends normally. I will use a virtualized Windows 10 and I will check this from time to time to see if this problem is eventually fixed.
Thanks a lot for your quick answer! And thanks for vtkplotlib. It allows to do cool things with no learning curve at all! 😄
I notice the PyQt5 figure behaves itself. Not only that but recent versions of PyQt5 have moved the event loop into a continuously running background thread so that it's interactive even without using the blocking show(block=True)
.
pip install PyQt5
Then inject the line:
vpl.QtFigure()
before any kind of vpl.plot_something()
commands. You'll probably need to either call vpl.gcf().update()
or click on the window to get it to redraw.
And thanks for vtkplotlib. It allows to do cool things with no learning curve at all!
You're welcome!
It works! I can even rotate the camera during the animation!
The only colateral effect is that there is more empty background around the scene (I tried vpl.zoom_to_contents(padding=0) with no success).
Finally, is there a way of cleaning the figure between calls to show() or removing previous added meshes? (I am trying to do an animation of a crane moving a load from a ship to a truck).
Oh wow! That's much cooler than what I do with vtkplotlib. I just make teeth go funny colours. vpl.zoom_to_contents(padding=0)
is the correct code but I see that's broken. I know where to fix that - should be able to push a fix in a couple of days or so. In the meantime you can use the raw VTK vpl.gcf().camera.Zoom(1.5)
(number > 1 means zoom in, < 1 means zoom out). Obviously, you'll need to be a bit more careful not to call it more than once.
I keep meaning to document showing/hiding/removing but still haven't. Here's something I wrote when someone else asked me the same question:
There’s several ways. You generally need to retain references to everything you wish to alter. So you may need to change your setup to something like the following if you’re not already doing this:
fig = vpl.figure() # To create a new figure.
# Or
fig = vpl.gcf() # To get the current one.
mesh = vpl.mesh_plot(...)
Once you have these references you can use any of:
# To hide it
mesh.visible = False
# To make it fully transparent (effectively hiding it).
mesh.opacity = 0
Or if you’re unlikely to want to reshow that mesh again then you can remove it from the figure (and save some RAM).
fig.remove_plot(mesh) # also accepts iterables of plots.
# Or by the shorthand:
fig -= mesh
# Optionally, release the `mesh` reference so Python can have its RAM
# back.
del mesh
The figure does keep its contents in fig.plots. So if you’re feeling lazy you could just use:
fig -= fig.plots
which will remove everything. (You may need to call fig.reset_camera()
after you’ve added the next mesh if it’s very different is size/position.)
Zoom does not seem to work properly. Maybe I am doing something wrong, I don't know. Anyway, as I can do zoom with the mouse, it is not so important. Removing objects works, great!!. Being this an exercise for students in the first year of an industrial engineering degree, it's perfect 😄. Example:
grua.mov
Again, thanks a lot for you library!
That video is really cool.
I've just pushed a fix for zoom_to_contents()
. Mind guinea pig-ing it?
pip install -U https://github.com/bwoodsend/vtkplotlib/archive/fix-zoom.zip
If it works, I'll merge it into the master branch and run a patch release 1.4.1 to PyPI.
Hi! Now, "padding" works :-) Nevertheless, I observe some things a little weird:
- padding=0 does nothing. Positive or negative values work as expected.
- If I try to use zoom_to_contents() inside a loop (so zoom is dynamically adapted to the meshes present in each frame of the animation):
- If a mesh is added to "plots_to_exclude", it flickers when doing calls to show(block=False). It is not painted sometimes. I am 99% sure that this is not due to some bug in my code because that mesh (the dock in the video) is added at the beginning of the execution and is not referenced anymore except to be added to "plots_to_exclude".
- At a given point, zoom_to_contents() starts to zoom in (?!). I attach the function where things are painted and a small video showing both things.
def paint(meshes, dock):
"""
Paint everything.
'meshes' include the crane and the load.
'dock' is added outside because it doesn't change.
"""
vpl_meshes = []
for mesh in meshes:
vpl_meshes.append(vpl.mesh_plot(mesh))
vpl.zoom_to_contents(plots_to_exclude=[dock])
figure = vpl.gcf()
figure.update()
figure.show(block=False)
for mesh in vpl_meshes:
figure.remove_plot(mesh)
test.mov
Ughh, that flickering is not pretty. Well there's two problems here. Firstly zoom_to_contents()
only zooms in. If you're going to call it repeatedly you should use vpl.reset_camera()
first which will zoom out, giving zoom_to_contents()
some space to work with. However this will make problem two even worse...
The second problem is that:
vpl.zoom_to_contents(plots_to_exclude=[dock])
performs a render with dock
temporarily hidden to work out how much to zoom in. I see now that this isn't a very smart thing to do! This is why the dock is flickering, because it's being hidden, rendered then reshown between every frame. I think the only fix for this is for me to think of a proper implementation for zoom_to_contents()
.
Hello, when I try to remove figures, I get an error saying "Unhashable type mesh" is there any known fix to this?
You're not giving me much to go on here but I'm guessing that you're passing the original mesh instead of the output of vpl.mesh_plot()
to fig.remove_plot()
? i.e. something like:
mesh = Mesh.from_file("some-file.stl")
vpl.mesh_plot(mesh)
...
fig.remove_plot(mesh)
You should instead be doing:
mesh = Mesh.from_file("some-file.stl")
mesh_plot = vpl.mesh_plot(mesh)
...
fig.remove_plot(mesh_plot)