visclaw
visclaw copied to clipboard
`make plots` is slow
Hi! I' new here but I'd like to make a suggestion.
The make plots
command can be frustratingly long when debugging. A faster solution would be to use Iplotclaw
but I did not appreciate having to use the terminal at the same time (and having to minimize windows because I have a small screen).
So I wrote a small script making use of the plotframe(..., refresh=True)
function and matplotlib's mpl_connect to change frames with just the arrow keys. I ended up adding numerical input (press 49 then press enter to show frame 49) and a FuncAnimation when passing the FPS=<some_frames_per_second_value>
argument to make iplot
.
Could this be a good addition to visclaw? Here my code
from pathlib import Path
from argparse import ArgumentParser
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
from clawpack.visclaw.Iplotclaw import Iplotclaw
from clawpack.visclaw.frametools import plotframe
def interactive_plot(fps=0, **kwargs):
"""Take advantage of Iplotclaw to make an interactive plotting session."""
ip = Iplotclaw(**kwargs)
counter = dict(current=0, max=0, right=1, left=-1, up=1, down=-1)
counter["max"] = len(list(Path(ip.plotdata.outdir).glob("fort.q*")))
def update(i):
plotframe(i, ip.plotdata, simple=ip.simple, refresh=True)
update(0)
def arrow_key(event):
"""If pressed key is in counter, increment index and update plot."""
if event.key in counter:
counter["current"]=(counter["current"]+counter[event.key])%counter["max"]
update(counter["current"])
frame = dict(n="")
def to_frame(event):
if event.key.isnumeric():
frame["n"] += event.key
elif event.key == "enter":
counter["current"] = int(frame["n"] or 0)
frame["n"] = ""
update(counter["current"])
if fps:
anim = FuncAnimation(plt.gcf(), update, frames=counter["max"], interval=1e3/fps)
return anim
else:
for fn in plt.get_fignums():
plt.figure(fn).canvas.mpl_connect('key_press_event', arrow_key)
plt.figure(fn).canvas.mpl_connect('key_press_event', to_frame)
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("fps", default=0, type=float)
args = parser.parse_args()
anim = interactive_plot(**args.__dict__)
plt.show(block=True)
And this is what I added to the Makefile.common
in clawutil
to have it avaliable from any folder:
FPS = 0
iplot:
$(CLAW_PYTHON) $(CLAW)/visclaw/src/python/visclaw/arrowkeyplot.py $(FPS)
So for example, here are the possible uses of the above code:
- Run
make iplot
then...- Enter some frame number (say
10
) then pressenter
(carriage return) to show the 11th frame (frame index 10). - then use the left/right or up/down arrow keys to navigate through the frames.
- Enter some frame number (say
- Run
make iplot FPS=10
and watch a looping animation.
The plt.show()
command is outside the function so that one is free to import the interactive_plot
function and either show it later or save the FuncAnimation
.
Edit: I forgot to mention the main advantage of this script: you don't have to wait for the figures to be saved in .png
, .html
and .tex
! I find that step painful when debugging.