NeuroML / pyNeuroML

A single package in Python unifying scripts and modules for reading, writing, simulating and analysing NeuroML2/LEMS models.
https://docs.neuroml.org/Userdocs/Software/pyNeuroML.html
GNU Lesser General Public License v3.0
34 stars 30 forks source link

Include generation of animated matplotlib plots #279

Closed sanjayankur31 closed 4 days ago

sanjayankur31 commented 7 months ago

Matplotlib allows animations, this could be useful when people are looking at the temporal evolution of recorded data:

https://matplotlib.org/stable/users/explain/animations/animations.html#sphx-glr-users-explain-animations-animations-py

sanjayankur31 commented 6 months ago

https://spikesandbursts.wordpress.com/2024/01/04/patch-clamp-data-analysis-animate-time-series/

https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.FuncAnimation.html

YBCS commented 2 months ago

@sanjayankur31 can I work on this ?

sanjayankur31 commented 2 months ago

Sure, assigning to you now.

YBCS commented 2 months ago

@sanjayankur31 there are many plotting functions, should I start with one in particular or should I try to implement something generic and can work with many different types of data.

sanjayankur31 commented 2 months ago

Ideally, I think we'd like to add an argument to the generate_plot to make it also generate animated matplotlib plots. So, maybe start there?

YBCS commented 2 months ago

@sanjayankur31 Screencast from 24-04-24 12:49:46 AM IST.webm I got the animation to work but there are some limitations I wanted to confirm before I raise my PR

so this will only work if show_plot_already is True. The reason is that for animating we have to write an animate function and it needs to be passed to FuncAnimation and this needs to happen in the same context in which plt.show() is called otherwise the canvas is wiped and nothing gets plotted.

sanjayankur31 commented 2 months ago

OK, I think that's good for the first iteration. Later, we can see if there's a way of recording the animation (maybe as a gif/mp4), with and if possible in matplotlib, without showing the window.

What we could do is add a new "animate" argument to the function, and if that is given, we toggle "show_plots_already" to true? How does that sound?

As an additional note, in another PR, there's also code to make a video from multiple "frames". Maybe we could use that in other plotting code (like a wrapper around plot_2d_cell_morphology) to generate multiple images and then stitch them together into a video?

https://github.com/NeuroML/pyNeuroML/pull/342/files

YBCS commented 2 months ago

OK, I think that's good for the first iteration. Later, we can see if there's a way of recording the animation (maybe as a gif/mp4), with and if possible in matplotlib, without showing the window.

yeah FuncAnimation has the method save which can save video/gif but I think it will show the window anyway.

What we could do is add a new "animate" argument to the function, and if that is given, we toggle "show_plots_already" to true? How does that sound?

Some of the use case of generate_plot looks like this

ax = generate_plot(**args)
// plot more stuff
plt.show()

in this case if we passed animate asTrue it would animate what was passed in generate_plot but the plots which are done after the call of generate_plot will neither be animated nor plotted. Because I think plt.show() can only be called once. If this is acceptable I will go ahead and implement it.

As an additional note, in another PR, there's also code to make a video from multiple "frames". Maybe we could use that in other plotting code (like a wrapper around plot_2d_cell_morphology) to generate multiple images and then stitch them together into a video?

https://github.com/NeuroML/pyNeuroML/pull/342/files

yeah FuncAnimation also has new_frame_seq which can export frames. so maybe it can be used with it. But if the purpose is to save video or gif, then save method mentioned above should be enough ?

sanjayankur31 commented 2 months ago

OK, yeh, if animate is used, then show_plots_already will be true, which means that "this is the final plot" and so people cannot use plt.show() in the future. They'll have to create new plots. That sounds find. Play around it with it and see how it goes? And we'll make sure we update the docstring to note these features..

YBCS commented 2 months ago

okay can you please suggest me some files to test this on. I want some examples to work on. I think the challenging part now would be to infer the interval arg (funcAnimation) and also how many frames to process at a time. Some data can be like just 10 items while something like sin plot may have 20,000 items so to make sure the animation is not too fast or too slow, it would be nice If you could point me to more files I can test this plotting on.

sanjayankur31 commented 2 months ago

Maybe save the data from the test_plot_time_series.py tests and start with those?

Later, we can think about maybe letting users provide a total time for the animation that can be used to adjust the speed---or something like that.

YBCS commented 2 months ago

@sanjayankur31 I have added new changes to #348 So it will only animate if both animate and show_plots_already is True. I did it like this because so far if show_plots_already is True then it was expected that that was the final plot and so it naturally follows that animate can only be done if show_plots_already is True. Please take a look

sanjayankur31 commented 2 months ago

That sounds good. I'll take a look at the PR next.