Python - Stop FuncAnimation - python

Does anyone know the preferred method for stopping FuncAnimation? I am using it to record data from a oscilloscope and would like to be able to pause and restart the data on demand. Is there any way I can send a button click event to it?
Thanks, Derek

The FuncAnimation is a subclass of TimedAnimation. It takes frames as an input for update functionm, which could be a number or a generator. It takes repeat as an argument, which is inherited from TimedAnimation, by setting reapeat to False you could stop the animation to repeat itself.
PS: Matplotlib documentation is lame, mistakes, lazy writing style, unclear explanation. Sometime, I really have to dig into the source code to figure out what to do.
Like FuncAnimation, it also takes fargs as an extra arguments for update function, but in its documentation, it doesn't say the type of fargs. In fact, what I found in its source code, fargs is used as a list.

There may be some modules but I define my own pause function. It freezes the animation by clicking somewhere on the figure. When you click again, it continues to plot the animation.
You have to define a flag before the begin of your animation. Inside your animation function (the function which will be called during you animation is plotted), you have to define a a control block like: if not pause: and then write your codes for plotting the function below.
You may have already checked, but this page gives an example of what I mean. I guess, many people do it in this way.
Notice that, the switch for pause is done with the following function:
def onClick(event):
global pause
pause ^= True
And you have to further add this line somewhere before you call FuncAnimation
fig.canvas.mpl_connect('button_press_event', onClick)

Related

matplotlib understanding the difference between command prompt integration and interactivity

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.

How to pause animations with kivy

I'm using kivy to develop a small project. Currently, I use the animation utility to animate Widgets (change position, cycle through a sprite atlas, etc.). Everything works great so far, but I have no idea how I am supposed to pause animations and continue them at a later point. I know that I could use the Clock schedule mechanism and clock.cancel, but that would make the whole ànimation` class pointless.
The Animation class has start, stop and cancel methods you can use to manipulate it how you like. Perhaps we should have a pause too, but you can achieve the same effect with those.

Ignore all mouse clicks on a matplotlib plot

I've recently built a python script that interacts with an Arduino and a piece of hardware that uses LIDAR to map out a room. Everything works great, but anytime you click on the plot that is generated with maptotlib, the computer freaks out and crashes the script that is running. This is partly because I was given a $300 computer to run this on, so it's not very powerful. However, I feel like even a $300 computer should be able to handle a mouse click.
How can I ignore mouse clicks entirely with matplotlib so that the computer doesn't freak out and crash the script?
If that's not the correct solution, what might be a better solution?
Edit: This is an interactive plotting session (sort of, I just replace the old data with the new data, there is no plot.ion() command called). So, I cannot just save the plot and show it. The Arduino transmits data constantly.
You can try bypassing the click event on your plot:
import matplotlib.pyplot as plt
fig = plt.figure()
plt.axes(xlim = (0, 3), ylim = (0, 3))
def onclick(event):
pass
fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()
, but I doubt this will work. What I recommend as a solution (if the stuff above does not work) is to make your plot and save it to file (without showing it):
plt.savefig('fname.png')
plt.close()
Than make python open the image (using subprocess for example) with whatever external tool you prefer in your OS.
I'm saying this because I suspect you might have some kind of packages incompatibility that is causing your script to crash (maybe a backend from mpl or whatever other library you are using over mpl). If this is the case more information is needed to try solving the issue.
I feel that this might be more easily resolved by altering the hardware - can you temporarily unplug the mouse, or tape over the track pad to stop people fiddling with it?
I suggest this because your crashing script will always process mouse-clicks in some way, and if you don't know what's causing the crashes then you may be better off just ensuring that there are no clicks.

More Efficient Alternatives to plt.draw() in MatPlotLib

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()

Exact semantics of Matplotlib's "interactive mode" (ion(), ioff())?

The documentation for the "interactive mode" in Matplotlib's pyplot reads:
The interactive property of the pyplot interface controls whether a figure canvas is drawn on every pyplot command. If interactive is False, then the figure state is updated on every plot command, but will only be drawn on explicit calls to draw(). When interactive is True, then every pyplot command triggers a draw.
This seems clear enough: when the interactive mode is on, one can do plot() without having to do draw(). However, doing draw() in the following code does not do anything:
from matplotlib import pyplot as pp
# Interactive mode is off by default
pp.plot([10, 20, 50])
pp.draw()
raw_input('Press enter...') # No graph displayed?!!
(on Windows XP, Matplotlib 1.0.1).
Adding ion() at the beginning makes the figure(s) appear, while waiting for the user to type enter (which conveniently closes all the figures):
from matplotlib import pyplot as pp
ion()
pp.plot([10, 20, 50]) # No draw() is necessary
raw_input('Press enter...') # The graph is interactive *and* the terminal responds to enter
Thus, it looks like ion() does more than just adding automatic graph updates after each plotting command, and I unfortunately can't find anything in the documentation. Another, more important problem with the latter program is that ion() makes all plot commands update the graph, which is time consuming when a single graph is updated multiple times.
So, is there a way of:
having the terminal wait for enter, after which all the figures are automatically closed,
having interactive Matplotlib graphs,
… without forcing the interactive mode to be on at the beginning (so as to not force auto-updates of the graphs, which could be time consuming)?
Here is the summary of an interesting discussion on this subject in the Matplotlib mailing list. The executive summary is:
The interactive mode (activated with ion()) automates many things. In particular, pyplot.* commands automatically update on the screen the relevant axes. However, method calls on Matplotlib objects like ax.plot() (ax being an Axes object) do not normally perform automatic updates; in this case, pyplot.draw() performs the necessary update.)
The non-interactive mode is less convenient. draw() does not normally update the figure on screen. The fact that draw() is somewhat "inactive" in non-interactive mode is not mentioned in the current documentation, but will hopefully be included there soon.
In the mean time, more information on the interactive and non-interactive modes can be found in a current branch of Matplotlib. A better documentation for draw(), show() and friends can also be found in the same branch.
I would suggest that you follow the last comment of 'Thomas K'. I remember a similar question on the mailing list, but I couldn't find it after several minutes of searching. Sorry.
I had also this problem and the better easier way for me was/is to use ipython --pylab. I have a much older version of matplotlib installed which have some problems with ion(). Beside this, matplotlib had also some problems with draw() on Windows. Maybe it was fixed in the last versions.
p.s.: Sorry that I couldn't helped you really well.
Best regards.

Categories