Creating animations in the browser using JSAnimation

This example shows how to create an interactive animation from a matplolib figure, using the JSAnimation package package.

To install the package (assuming that you have installed PyGChem using conda, in a virtual environment which is activated), run the following command:

conda install -c https://conda.binstar.org/benbovy jsanimation

First, we import the data:


In [2]:
from pygchem import datafields

# change the path to your local copy of benchmark results
bmk_root = '/home/benbovy/Aldebaran/ScientificResearch/geoschem'

%cd {bmk_root}/1yr_benchmarks/v10-01/v10-01c/Run1

filename = 'bpch/ctm.bpch.v10-01c-geosfp-Run1.*'
diagnostics = ["BXHGHT_S__BXHEIGHT",
               "BXHGHT_S__N(AIR)",
               "IJ_AVG_S__NO2"]
dataset = datafields.load(filename, diagnostics)


/mnt/hgfs/Aldebaran/ScientificResearch/geoschem/1yr_benchmarks/v10-01/v10-01c/Run1
/mnt/hgfs/Altair/GitRepos/PyGChem/pygchem/tools/irisutil.py:210: UserWarning: Invalid udunits2 'kg/m2/s'
  warnings.warn("Invalid udunits2 '{0}'".format(units))
/mnt/hgfs/Altair/GitRepos/PyGChem/pygchem/tools/irisutil.py:210: UserWarning: Invalid udunits2 'mm/day'
  warnings.warn("Invalid udunits2 '{0}'".format(units))

We then calculate the total columns for the NO2 tracer:


In [8]:
import iris.analysis

# extract each data field (cube) needed to compute the tracer columns
no2_tracer = dataset.extract_strict("IJ_AVG_S__NO2")
box_heights = dataset.extract_strict("BXHGHT_S__BXHEIGHT")
n_air = dataset.extract_strict("BXHGHT_S__N(AIR)")

# calculate the columns
no2_columns = (box_heights * n_air * no2_tracer).collapsed('model_level_number',
                                                           iris.analysis.SUM)

# set name convert units to count/cm2 (count is used for #molecules)
no2_columns.rename("NO2 columns")
no2_columns.convert_units('count/cm2')

print no2_columns


NO2 columns / (count/cm2)           (time: 12; longitude: 72; latitude: 46)
     Dimension coordinates:
          time                           x              -             -
          longitude                      -              x             -
          latitude                       -              -             x
     Scalar coordinates:
          model_level_number: 36, bound=(1, 72)
     Cell methods:
          sum: model_level_number

Plot the first time slice:


In [85]:
import cartopy.crs as ccrs
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
import matplotlib.pyplot as plt
import iris.quickplot as qplt
import iris.plot as iplt
%matplotlib inline

fig = plt.figure(figsize=(10, 8))

def draw_columns(ts):
    qplt.contourf(no2_columns[ts], 15)
    fig.gca().coastlines()

    # grid and axis labels
    gl = fig.gca().gridlines(draw_labels=True,
                             linewidth=1.5, color='gray', alpha=0.5)
    gl.xlabels_top = False
    gl.ylabels_right = False
    gl.xformatter = LONGITUDE_FORMATTER
    gl.yformatter = LATITUDE_FORMATTER

    # time annotation
    time_coord = no2_columns.coord('time')
    t = time_coord.units.num2date(time_coord.points[ts])
    iplt.citation(t.strftime('%Y-%m-%d'))

draw_columns(0)


Create the animation:


In [88]:
from JSAnimation import IPython_display
from matplotlib.animation import FuncAnimation

def update_contourf(ts):
    plt.gca().cla()
    draw_columns(ts)

FuncAnimation(fig, update_contourf, interval=100, frames=12, blit=True)


Out[88]:


Once Loop Reflect

In [ ]: