make_fgout_animation.py.html | |
Source file: make_fgout_animation.py | |
Directory: /Users/rjl/clawpack_src/clawpack_master/geoclaw/examples/tsunami/chile2010_fgmax-fgout | |
Converted: Mon Feb 19 2024 at 14:27:24 using clawcode2html | |
This documentation file will not reflect any later changes in the source file. |
""" Make an mp4 animation of fgout grid results. This is done in a way that makes the animation quickly and with minimum storage required, by making one plot and then defining an update function that only changes the parts of the plot that change in each frame. The tuple update_artists contains the list of Artists that must be changed in update. Modify this as needed. """ from pylab import * import os from clawpack.visclaw import plottools, geoplot from clawpack.visclaw import animation_tools from matplotlib import animation, colors from datetime import timedelta from clawpack.geoclaw import fgout_tools fgno = 1 # which fgout grid outdir = '_output' format = 'binary' # format of fgout grid output fgframes = range(1,26) # frames of fgout solution to use in animation figsize = (10,8) # Instantiate object for reading fgout frames: fgout_grid = fgout_tools.FGoutGrid(fgno, outdir, format) # Plot one frame of fgout data and define the Artists that will need to # be updated in subsequent frames: fgout1 = fgout_grid.read_frame(fgframes[0]) plot_extent = fgout1.extent_edges ylat = fgout1.Y.mean() # for aspect ratio of plots fig,ax = subplots(figsize=figsize) ax.set_xlim(plot_extent[:2]) ax.set_ylim(plot_extent[2:]) plottools.pcolorcells(fgout1.X,fgout1.Y,fgout1.B, cmap=geoplot.land_colors) clim(0,100) eta = ma.masked_where(fgout1.h<0.001, fgout1.eta) eta_plot = plottools.pcolorcells(fgout1.X,fgout1.Y,eta, cmap=geoplot.tsunami_colormap) clim(-0.3,0.3) cb = colorbar(eta_plot, extend='both', shrink=0.7) cb.set_label('meters') title_text = title('Surface at time %s' % timedelta(seconds=fgout1.t)) ax.set_aspect(1./cos(ylat*pi/180.)) ticklabel_format(useOffset=False) xticks(rotation=20) ax.set_xlim(plot_extent[:2]) ax.set_ylim(plot_extent[2:]) # The artists that will be updated for subsequent frames: update_artists = (eta_plot, title_text) def update(fgframeno, *update_artists): """ Update an exisiting plot with solution from fgout frame fgframeno. The artists in update_artists must have new data assigned. """ fgout = fgout_grid.read_frame(fgframeno) print('Updating plot at time %s' % timedelta(seconds=fgout.t)) # unpack update_artists (must agree with definition above): eta_plot, title_text = update_artists # reset title to current time: title_text.set_text('Surface at time %s' % timedelta(seconds=fgout.t)) # reset surface eta to current state: eta = ma.masked_where(fgout.h<0.001, fgout.eta) eta_plot.set_array(eta.T.flatten()) update_artists = (eta_plot, title_text) return update_artists def plot_fgframe(fgframeno): """ Convenience function for plotting one frame. But if you use this function in IPython and then try to make the animation, it may get into an infinite loop (not sure why). Close the figure to abort. """ update(fgframeno, *update_artists) def make_anim(): print('Making anim...') anim = animation.FuncAnimation(fig, update, frames=fgframes, fargs=update_artists, interval=200, blit=True) return anim if __name__ == '__main__': anim = make_anim() # Output files: name = 'fgout_animation' fname_mp4 = name + '.mp4' #fname_html = None fname_html = name + '.html' if fname_mp4: fps = 5 print('Making mp4...') writer = animation.writers['ffmpeg'](fps=fps) anim.save(fname_mp4, writer=writer) print("Created %s" % fname_mp4) if fname_html: # html version: animation_tools.make_html(anim, file_name=fname_html, title=name)