-
Notifications
You must be signed in to change notification settings - Fork 35
animate matplotlib plots #348
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
animate matplotlib plots #348
Conversation
* development: test(annotations): add more assertions feat(annotations): improve docstring feat(annotations): improve for use as embedded annotations chore: to 1.2.13 feat(annotations): extend to allow both miriam and biosimulations styles
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. I've added a test and opened a PR for you to add that to your branch:
Can we also add saving of animations? Looks simple enough?
https://matplotlib.org/stable/users/explain/animations/animations.html#funcanimation
pyneuroml/plot/Plot.py
Outdated
|
|
||
| if show_plot_already: | ||
| if animate: | ||
| duration = 5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering if there was a way to make this an argument? Perhaps animate can be a bool or an int, and if it's an int, we use that as the "duration". That way users will be able to set the duration of their animations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
duration varibale is not consistent. "duration" will depend of lots of factors including data calculation and actual length of data to plot and machine configuration. Even If I try to calculate the "hyperparameter" variables to make it perform the animation in required duration, the actuall outcome usually differs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, if we say duration "5", that doesn't mean that the animation will be 5s long? 🤔
pyneuroml/plot/Plot.py
Outdated
| if animate: | ||
| duration = 5 | ||
| num_frames = len(xvalues[0]) | ||
| interval = duration * 1000 / num_frames |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should have a sensible minimum value that the interval can take. Maybe 5?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I will update this.
Interval is simply " Delay between frames in milliseconds", it can be harcoded. Most tutorial I have seen uses 50 or 100 ms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool--yeh, I think 50ms (20fps) is good for a default minimum value.
Saving animation is simple. But after some testing with the plots in the codebase I have identified some issues. Animation is actually very expensive and so it takes lots of time. I have encountered plots with >= 10000 (link) On the other hand the script can choose not to save animation if the provided data point is too long. |
test(plotting): add test for animated plots
…a-plt * 'buda-plt' of https://github.com/YBCS/pyNeuroML: test(plotting): add test for animated plots
* development: fix(nml-channel-analysis): include `ionChannelVShift` Updates to pynml-channelanalysis to allow plotting subgates Updates to xpp running/plotting Indeces -> indices chore: improve annotation tests feat(annotations): make annotations comply with NeuroML/LEMS requirements chore: remove ruff linter pre-commit hook Improved xpp handling Quick & dirty implementation of running xpp files in xppaut & plotting results
| ys2 = random.choices(list(range(0, 1500)), k=numpoints) | ||
|
|
||
| generate_plot( | ||
| [xs, xs], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[xs1, xs2] is it possible that this list contains items with differing lengths. can xs1 and xs2 have different lengths ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think they can, but [y1, y2] must have the same lengths as [x1, x2] so that matplotlib has complete (x,y) co-ordinates for each point.
For animation, one will have to find the values with the longest length and use that to calculate duration and all that then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"For animation, one will have to find the values with the longest length and use that to calculate duration and all that then?"
Yeah that will be correct as, [plt1, plt2] are individual plots and we only care of the total duration which means the max of the lengths
We can probably just document this in the method docstring and leave it for the user to decide. Often people in research labs have quite good computers, with lots of memory + good cores + gpus and all that. So, in such cases, they may be able to generate animations with more data points. So, it's best to include the functionality and document it. That way users can play around with a few parameters like "duration" and generate what works for them. What do you think? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there, I just have a few things I'm unclear on.
pyneuroml/plot/Plot.py
Outdated
| (save_animation_to)) | ||
| ani.save( | ||
| filename=save_animation_to, | ||
| writer="pillow", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should make this an argument too, to allow the user to choose different writers? ffmpeg/imagemagick may be quicker than pillow and support more formats:
https://matplotlib.org/stable/users/explain/animations/animations.html
How about making it an argument of the form:
writer={ 'writer name': ["extra args list"] }
with default value:
writer = { "pillow": [] }
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also add this link to the docstring around these arguments:
https://matplotlib.org/stable/users/explain/animations/animations.html#saving-animations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should I include this in the same PR or should it be done in another PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can roll this in here too?
pyneuroml/plot/Plot.py
Outdated
| ) | ||
|
|
||
| frame_length_threshold = 5000 | ||
| if len(xvalues[0]) < frame_length_threshold and save_animation_to: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to limit animations to 5000 frames only? If this depends on the users' setups (how good their hardware etc. is), let's not add this check like this. Maybe we can just add a warning that is thrown if there are more than 5000 points that says "too many data points, this may take a while"? That way the user can still go ahead and use it if they wish. Maybe they'll start it and go eat lunch, and it'll be complete by the time they return (we do this a lot with our simulations :))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. I will add a warning and it will ask for user input to continue with the saving or not (possibly showing approx time (minutes) it might take to complete the entire process. )
It will then save or discard based on the user input.
How does that sound ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd skip the user input entirely. Just make it an argument and if it's more than something, just print a warning saying "this could take a while". If it takes too long, the user can always interrupt it and use a smaller value.
(Adding interaction to take user input will make it trickier to do batch analyses, so we want to avoid that as much as possible)
pyneuroml/plot/Plot.py
Outdated
|
|
||
| if show_plot_already: | ||
| if animate: | ||
| d = 5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to test this out more. I thought the idea was that if I set duration to 5000ms, the animation would be 5000ms, but I think you're saying that this is not the case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, that is what is happening with my current implementation.
My calculations could be improved I think and it should be possible to atleast get as close as possible to set duration, let me try again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't worry about getting it exactly right---close enough will do and it can be tweaked later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that looks good. I'll just test it locally once and then merge ✨
|
LGTM, merging. I'll make a few tweaks in my branch and merge to development 👍 |
|
@all-contributors please add @YBCS for code, test |
|
I've put up a pull request to add @YBCS! 🎉 |
#279 wip fix
we can only use this feature if
show_plot_alreadyis set toTrue