Open mtryan83 opened 1 year ago
@neutrinoceros suggested on slack that this was related to PhasePlot
not having the export_to_mpl_figure
method found in PWViewerMPL
and copy/pasting the method fixes the issue (as a quick hack, not a final solution). I haven't had luck with that solution, though I might not have put it in the correct spot.
Thanks for reporting. So indeed my suggestion has no effect here because I was looking at a different animation example that relies on export_to_mpl_figure
, which is currently not inherited by the PhasePlot
class, but the example you're actually using doesn't do that. Sorry about the confusion !
So I went back to the example straight from the docs (using SlicePlot
, and retriving the figure as fig = plot.plots[("gas", "density")].figure
) and I can confirm that it works, which is a start.
Is the embedded mp4 supposed to be playable directly on GitHub ? I can seem to get it working in my browser.
Sorry about the embedded file, I accidentally deleted a new line after the file when I added the note. Should be fixed now.
I had looked at a different animation example as well (hopefully similar to what you were using) that relied on export_to_mpl_figure
as well. Here's the test code I used:
import yt
from yt.testing import fake_amr_ds
from matplotlib.animation import FuncAnimation
yt.set_log_level("error")
# Modified from @neutrinoceros' cookbook example
# mock a time series
# *Note the seed parameter!*
ts = [fake_amr_ds(seed=s*100,fields=[("gas", "field1"),("gas","field2")], units=["code_length"]*2) for s in range(3)]
for i, ds in enumerate(ts):
ds.current_time = ds.quan(i, "code_time")
z_field = ("gas","field1")
# SlicePlots (for example) work correctly
#p = yt.SlicePlot(ts[0],"z", z_field, window_size=2)
#p.annotate_timestamp()
# Need to specify z field since ("all","particle_ones") does not exist
p = yt.ParticlePhasePlot(ts[0], ("gas","field1"), ("gas","field2"), z_field, figure_size=2)
# PhasePlots don't have annotate_timestamp(), here's a quick & dirty version
time = ts[0].current_time.to("s")
timetxt = p.annotate_text(1e-5,1e-5,f"T={time}")
p.set_log("all",False)
p.set_zlim(("gas","field1"),0.1,1)
# Neither one of these work
#fig = p.plots[z_field].figure
fig = p.export_to_mpl_figure((1, 1))
def animate(i):
print(f"{i=}", end="\r")
ds = ts[i]
#p.annotate_timestamp()
time = ds.current_time.to("s")
timetxt._plot_text[z_field]=f"T={time:0.3g}"
p._switch_ds(ds)
animation = FuncAnimation(fig, animate, frames=len(ts), interval=500)
animation.save("./testFA.gif")
animation
This required a change to the fake_amr_ds
method in lines 311 and 326:
# line 311
fields=None, units=None, geometry="cartesian", particles=0, length_unit=None, seed=0x4D3D3D3,
...
# line 326
prng = RandomState(seed)
This example still seems to show the same, non-updating behavior: Actual:
Expected (using the save each plot as file and recombine approach):
Thanks a bunch, I can read the new videos without problem. For some reason my favourite browser still doesn't want to play the ones in your OP, but I was able to watch them using another one.
It's getting late in my time zone, I'll do my best to have a real look at it tomorrow. In the mean times here are some pointers off the top of my head:
PhasePlot
/ParticlePhasePlot
classes, and compare that with SlicePlot
(possibly it's actually hard to track through class hierarchy).@invalidate_data
/@invalidate_plot
/@invalidate_figure
family (and there validate
counterparts).render
methodsBeen hacking at it for two hours tonight, here's what I think is happening:
the data which is held by a PhasePlot
(or ParticlePhasePlot
, the parts I care about here are not overridden in the child class) lives in self.profile
, but this attribute is not updated when _switch_ds
is called. I find that overriding the _switch_ds
method for PhasePlot
resolves the "nothing is happening" situation and I can get the plot to update:
I'll open a PR with my patch
@mtryan83 my patch is in #4295, feel free to try it out and/or give some feedback.
Bug report
Bug summary
The cookbook recipe (Time Series Movie) for animating plots suggests using
plot._switch_ds(new_ds)
to update the plot as part of the animation function. This does not work forParticlePhasePlot
s (and likelyPhasePlot
s in general). Relevant to #4288.Code for reproduction
Actual outcome
https://user-images.githubusercontent.com/1833991/211651361-c05f464a-f339-4597-9880-576b085c3724.mp4
Note that the figure is updating, you can add a timestamp for example that will update correctly in each frame, but the underlying plot is not being replotted or something.
Expected outcome
https://user-images.githubusercontent.com/1833991/211652283-2db846ee-76ec-4e91-a6cf-4b8c4ea3c8bd.mp4
This was generated by generating each plot individually, saving them to separate files, and then using
imageio
to combine them into an mp4:Version Information
yt installed from source