Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plot windows close automatically #15

Open
djagodzinski opened this issue Feb 2, 2025 · 5 comments
Open

Plot windows close automatically #15

djagodzinski opened this issue Feb 2, 2025 · 5 comments

Comments

@djagodzinski
Copy link

Hi Dan,

First off, you built a great package. I am having issues using the .plot() and .plot_coordinate() methods. The plot windows open for a fraction of a second then close automatically. I think I am seeing similar behavior as described in pyvista/pyvista-support#139. Just curious if you have run into this before.

Thanks,
Daniel

@djagodzinski
Copy link
Author

djagodzinski commented Feb 3, 2025

Here is a simple example that demonstrates this behavior:

import sdynpy as sdpy
import numpy as np

# Create node data
node_data = [
    (1, np.array([0, 0, 0]), 1, 0, 0),
    (2, np.array([1, 0, 0]), 1, 0, 0),
    (3, np.array([0, 1, 0]), 1, 0, 0)
]

# Create node array
dt = [
    ('id', '<u8'),
    ('coordinate', '<f8', (3,)),
    ('color', '<u2'),
    ('def_cs', '<u8'),
    ('disp_cs', '<u8')
]
node_data_struct = np.array(node_data, dtype=dt)
nodes = sdpy.core.geometry.node_array(structured_array=node_data_struct)

# Create coordinate system data
coord_data = [
    (0,
     "MyCoordSys",
     1,
     0,
     np.array([
         [1, 0, 0],
         [1, 0, 0],
         [0, 1, 0],
         [0, 0, 1]
     ]))
]

# Create coordinate system array
dt = [
    ('id', '<u8'),
    ('name', '<U40'),
    ('color', '<u2'),
    ('cs_type', '<u2'),
    ('matrix', '<f8', (4,3))
]
coord_data_struct = np.array(coord_data, dtype=dt)
css = sdpy.core.geometry.coordinate_system_array(structured_array=coord_data_struct)

# Create a geometry with nodes and coordinate system
geometry = sdpy.core.geometry.Geometry(nodes, css)

# Plot
geometry.plot()

If you replace geometry.plot() with the below, it will work as intended but you will lose the fancy plot features.

import pyvista as pv
p = pv.Plotter()
geometry.plot(plotter=p)
p.show()

@dprohe
Copy link
Collaborator

dprohe commented Feb 3, 2025

Daniel,

There are a few reasons that this might happen, and some of it depends on what environment you are running in.

The first thing that comes to mind is that windows sometimes close in Python due to how the garbage collector works. Basically, Python "cleans up after itself" by keeping track of references to objects. If an object as no references referring to it, the garbage collector recognizes that nothing is referencing the value anymore, and it will go delete the object from memory. In the context of a GUI window, this will generally trigger the window's destructor, which closes the window. So my first suggestion would be to assign the output from geometry.plot() to a variable and see if the window still closes.

Otherwise there are various environment reasons why a window might not pop up or might close. This could depend on if you are using IPython or not, if there is a QApplication running already in the background, or other things. In the referenced issue, they talk about the Python script ending because the opening of the window does not block the progress of the script, and when the script ends, the Python program terminates, and the operating system cleans up after it, meaning again the window is closed and removed from memory.

Can you let me know what kind of environment you are running? That would help me debug a bit more.

As an example, I use Spyder most of the time, and Spyder runs in an interactive terminal, so if I run a script, when it finishes it lands me back in my interactive terminal, so the window is not closed automatically.

Everything works for me as expected with a fresh Python 3.13.1 install (just installed tonight) on my Windows laptop, after
pip install spyder (I got version 6.0.3)
and
pip install sdynpy (I got version 0.14.2)
then running your script:

Image

(as an aside, your coordinate system transformation matrix looks kind of strange, because your local X and local Y directions are both along global X. I therefore changed the transformation matrix in your script from np.array([ [1, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1] ]) to np.array([ [1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0] ])

Note that if I instead run the script instead in an external terminal (e.g. via cmd), the window closes as soon as the Python script ends, because nothing is blocking the script from ending, and when the program ends, all memory used by the program is cleared. The p.show() in your second snippet blocks execution while you interact with your window, but like you say, a lot of the menus and things are missing in that plotter.

@djagodzinski
Copy link
Author

I am using VS Code on Windows at the moment. I will be using the code on Linux in the future so maybe this wouldn't be an issue if it's just a Windows thing. I appreciate you taking a look at this for me!

Also, I did try assigning a variable to the plotter variable returned by the .plot() method and it didn't change the behavior. I also tried assigning that as a global variable to no effect.

@dprohe
Copy link
Collaborator

dprohe commented Feb 3, 2025

I don't use VSCode, because I find Spyder is better for interactively working with the data, which is the use-case I typically use with SDynPy. However, I talked to my colleague who uses VSCode, and it looks like there are a couple options, depending on what you want to do with your code. The primary issue you're seeing is that your script is ending, and so the operating system is cleaning up after the process and ends up deleting your window.

  1. You can initialize a QApplication using the code
from qtpy import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

and then after you do the plot you can do

app.exec()

This method will block execution of the script until all windows are closed, at which point, it will unblock and the script will end. This has the disadvantage of being blocking, so you cannot further work with your variables in an interactive way while the window is open, and then your variables will be destroyed after the windows are closed due to the script ending.

  1. You can run it in a debug console (click Debug Python File from the run dropdown menu). You will have to put breakpoints in place after the plot function so the script stops proceeding. At this point, you can explore variables further in the debug console (e.g. if you type in a variable name it will show you the repr). You can also plot additional windows in that terminal as well. We found that we either needed the app = QtWidgets.QApplication(...) line of code shown above to be executed, or at least one geometry window to be open already when the breakpoint is hit, if one of these was not done, then opening new windows in the debug terminal caused the window to hang.

  2. VSCode appears to have an "interactive window" which appears to be very similar to what you get in Spyder. My colleague right-clicks on his code and in the context menu there is a dropdown that says "Run in Interactive Window". It may ask you to install some extensions to enable this feature (Jupyter?). Anyways, this would then run the script in an interactive window, the plots remain open after execution of the script, and there was no need to modify the source code to add calls to QApplication or put breakpoints. The only downside I can see with this approach is it does open a new window with a copy of your code which maybe is a bit ugly to look at, but functionally, it seems like the best approach in my mind.

  3. VSCode also has a jupyter notebook extension that also appears to give interactive functionality, however it generally prefer to work with a terminal versus a notebook, but your preference may vary.
    If you are eventually going to move to Linux and run with just a basic python sdynpy_script.py environment, then probably the first choice will work best for you. However, I will put another plug for Spyder in that it can also run on Linux.

@djagodzinski
Copy link
Author

Hi Dan, thank you for your help with this. I'll give your suggestions a try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants