I am writing a python program to do some data analysis, and while developing the code, I have notived that if I do plt.show() at the end of my code, the windows stay on forever unless I manually close each one.
I would like to be able to
1. Either close the old plot when I rerun the program, i.e. at the beginning of each execution, the program should check for any pyplot instances running and close them, or
2. Update the existing figures with the new data, although this would be the less favorable solution, since I am also changing plot types and am unsure how that will affect the replotting.
For the first choice I have tried plt.close('all') at various locations in my code but it either does nothing or immedeately closes the window after it is being shown.
I have also seen people suggesting to just kill the associated process. How would I do that from within the python program?
Any help would be appreciated
Related
I have been trying to understand the matplotlib interactive figure documentation and links therein as part of several days of research into trying to understand how to draw my matplotlib plots. Some of my lack of understanding I put down to poor familiarity with the concepts and phrases.
However, one thing that completely escapes me is the difference between the event loop integration and interactive mode. Quoting the documentation:
The GUI event loop being integrated with your command prompt and the figures being in interactive mode are independent of each other.
They explain this futher:
If you use pyplot.ion but have not arranged for the event loop integration, your figures will appear but will not be interactive while the prompt is waiting for input. You will not be able to pan/zoom and the figure may not even render
I understand this event loop integration to be implemented using plt.pause() or FigureCanvasBase.flush_events(), something that would allow "communication": a GUI event loop. Indeed my experience in spyder has been that my figures in a loop in a class are not drawn at all unless I use plt.pause() (flush doesn't work). However, just above this, they seem to contradict this statement when listing the behavior of interactive figures:
newly created figures will be displayed immediately & figures will automatically redraw when elements are changed
Even looking at the accepted answer to this related question, the figure is not drawn in interactive mode until plt.pause(.1) is called. The explanation therein confuses things more:
This means that a figure can be drawn inside a GUI without starting the GUI event loop.
This is wrong because the documentation states that plt.pause() DOES cause an event loop:
pyplot.pause - Run the GUI event loop for interval seconds.
However that answer does give me the idea that a main difference, despite the documentation wording is that interactive mode makes it so that plt.show() does not cause blocking and allows the script to still run while the figures are open. The answer also suggests to me that interactive does not mean responsive and that ironically blocking during a non-interactive plt.show() or timed plt.pause() is the only time where figures become responsive.
the disadvantage is that you do not have an event loop - hence the GUI may quickly become unresponsive and you are responsible yourself for letting it manage events.
Perhaps this is why I cannot resize, minimize, close , or plt.close('all') my figures even after my script stops even after using plt.ion (though this will be a future question to explore elsewhere). This debunks my earlier hypothesis that interactivity functions as a way to for users to "push buttons" (to be very coloquial) on the plot at any time rather than during times when the plt.pause() or plt.show() had blocked the script and the interactivity turned on temporarily.
Any help with these contradictory statements about the roles of command prompt integration and interactivity would be greatly appreciated.
I am running a python code that produces some figures with Matplotlib and Pandas. After a few runs of the code, I am getting to following error:
RuntimeWarning: More than 20 figures have been opened. Figures created
through the pyplot interface (matplotlib.pyplot.figure) are retained
until explicitly closed and may consume too much memory. (To control
this warning, see the rcParam figure.max_open_warning)
I think this is because I forgot to close the figures after each run of the code. I have tried
plt.close('all')
but it does not close the figures from previous sessions. Restarting the terminal (conda) did not help either.
You have a really similar issue with really good and detailed answers in this thread.
I can tell you that you are probably creating figures in a loop or over and over with more than one execution, so you need to use the methods .clf and .cla to close the figures you are creating. But, you have all the detailed info in the above thread.
I'm trying to make an interactive GUI using MatPlotLib, and the thing users notice most is the latency between, say, changing a slider, and the GUI responding.
Currently, I am using plt.draw() at the end of every event, which works well, except for the fact that it causes 256ms of the function's 259ms runtime.
In researching alternatives to plt.draw(), I came across this post: why is plotting with Matplotlib so slow? , in which it was recommended to use fig.canvas.blit(ax1.bbox) as an alternative which reloads just the graph, and not the entire figure.
When I use this, the event handler runs in 3ms, however the GUI updates during the following event, rather than at the end of the current event as if the event was caught in a buffer: User input 1>pause>User input 2>GUI responds to input 1>pause>User input 3>GUI responds to input 2, making the program unusable.
So what alternatives do I have? Fixing either one of these problems would allow me to run a very fast GUI. I'll post code if you need it.
Note 1: When using fig.canvas.blit(ax1.bbox), the sliders, buttons, etc will change immediately, and only the subplots will behave as described above.
Note 2: fig.canvas.draw_idle(), as used in the widgets example here http://matplotlib.org/examples/widgets/slider_demo.html, and fig.canvas.draw(), perform identically to plt.draw()
I"m running into issues when trying to interactively make plots with matplotlib.pyplot.
The general sequence of events is as follows:
1) open terminal, type ipython, copy and paste commands from my sublime text into ipython, eventually typing plt.show().
2) viewing my nice pretty plot be made, but with one small issue I want to fix or build upon
3) closing the window that houses the plot
4) seeing the command line return to normal again. Typing plt.close(), just to make sure the plot really closed
5) copying and pasting commands again, again ending with plt.show().
Only, the result of #5 results in no plot this time!
This seems to be a problem that repeats itself, so if anyone has any input I'd be very grateful. I noticed that when I create the plot the first time, it creates a plot window (which I can see with Command-Tab Application Switcher). When I try to close this after making the plot the first time, this window never actually disappears from the Application Switcher.
Thanks
Is there any way to show a pyplot figure in Python 2.65, Matplotlib 0.99, without locking everything else?
I have a program with a Pmw GUI running on Python 2.75 with Matplotlib 1.3.1. on Windows (64-bit Winpython).
Everytime a figure is drawn (or everytime something is added to an existing one), the routine calls plt.show().
It is possible to show pyplot figures while allowing the user to keep using the GUI and manipulate the figures, nothing blocks anything, as I want it to be since I need the user to look at the plots when deciding what to do next in the GUI, and to have several plots next to each other for comparison.
Now, I need to make all of this work on a system with Python 2.65 and Matplotlib 0.99. The behaviour now seems to be that nothing is visible unless plt.show() is called, and then it will block everything until the plot window is closed.
I tried using plt.draw() instead but then the figure does not even show up.
Worse: Some routines who draw into existing figures never get a chance because they can't execute while the figure is being shown, and when they can, the figure is gone already. I cannot wait until the last drawing operation because the graphs are meant to build up incremental, adding information to existing graphs which the user needs to be able to see.
I am not allowed to update matplotlib. I am allowed to use non-binary parts of libraries if I make them part of "my" software package.
Ideally, I am looking for code that will work in both environments I'm working in, but at this point I am willing to make compromises...
Update:
I have found some code running in the same environment that is able to do all of these things, where I can remove the plt.show() calls, even run it in IDLE (which according to matplotlib docs has problems in these regards), and it "just works" -- I haven't been able to find any difference in how the two codes handle the task: Both define a figure.axes object, pass it to routines that draw into them (using plt.plot()) and store it for future use.
I've also found that my current code will change its behaviour on the current set of libraries, depending on how I run it: In a "regular" console in Spyder or a system console, all's fine, but on a dedicated console in Spyder, the first plot will lock up the interface
=> I'm beginning to think this isn't about the matplotlib version after all, but have no idea where else to look --is there anything else that changes matplotlib's behaviour, based on how it's launched?
It looks like you are looking for:
plt.show(block=False)
or plt.ion:
plt.ion()
plt.show()
# update figure, calc stuff
plt.pause()
Not really sure if they are available in 0.99.
elyase's answer sent me into the right direction:
import matplotlib
matplotlib.interactive(True)
This at the beginning of a script is what it takes to make sure that matplotlib will always and in all environments create plots in a way that allows scripts to continue running, while allowing the user to manipulate the figure and the code to keep drawing into it.
Matplotlib has two modes of operating: The interactive and the non-interactive, and my script going into the latter mode was the problem.
I have still no idea why this is the default behaviour in some cases and not in others (had believed it was one standard setting per matplotlib installation). Since other scripts are able to run without the above. and there must be something that my script inadvertently does to land in non-interactive mode, but the above code is what will override the setting, come what may; at least in all scenarios I've tried so far: python 2.75, matplotlib 1.3.1 using Spyder's regular and dedicated shells and system shells, and Py 2.65, matplotlib 0.99, using system shells and IDLE.
P.S.:
This does not seem to help on Linux. I tried to run the same skript (Tkinter GUI that opens plots, is able to draw into existing plots) on SuSE 13.1 (current version of python 2.7 and all libraries) and no single plot window pops up until the GUI is closed, and then they all jump at me ... it seems that it's not trivial to make matplotlib behave the same everywhere.