.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "generated/gallery/meteorology/plot_lagged_ensemble.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_generated_gallery_meteorology_plot_lagged_ensemble.py: Seasonal Ensemble Model Plots ============================= This example demonstrates the loading of a lagged ensemble dataset from the GloSea4 model, which is then used to produce two types of plot: * The first shows the "postage stamp" style image with an array of 14 images, one for each ensemble member with a shared colorbar. (The missing image in this example represents ensemble member number 6 which was a failed run) * The second plot shows the data limited to a region of interest, in this case a region defined for forecasting ENSO (El Nino-Southern Oscillation), which, for the purposes of this example, has had the ensemble mean subtracted from each ensemble member to give an anomaly surface temperature. In practice a better approach would be to take the climatological mean, calibrated to the model, from each ensemble member. .. GENERATED FROM PYTHON SOURCE LINES 20-156 .. rst-class:: sphx-glr-horizontal * .. image-sg:: /generated/gallery/meteorology/images/sphx_glr_plot_lagged_ensemble_001.png :alt: Surface temperature ensemble forecasts for January 2012 :srcset: /generated/gallery/meteorology/images/sphx_glr_plot_lagged_ensemble_001.png :class: sphx-glr-multi-img * .. image-sg:: /generated/gallery/meteorology/images/sphx_glr_plot_lagged_ensemble_002.png :alt: Mean temperature anomaly for ENSO 3.4 region :srcset: /generated/gallery/meteorology/images/sphx_glr_plot_lagged_ensemble_002.png :class: sphx-glr-multi-img .. code-block:: Python import matplotlib.pyplot as plt import matplotlib.ticker import numpy as np import iris import iris.plot as iplt def realization_metadata(cube, field, fname): """Modify the cube's metadata to add a "realization" coordinate. A function which modifies the cube's metadata to add a "realization" (ensemble member) coordinate from the filename if one doesn't already exist in the cube. """ # Add an ensemble member coordinate if one doesn't already exist. if not cube.coords("realization"): # The ensemble member is encoded in the filename as *_???.pp where ??? # is the ensemble member. realization_number = fname[-6:-3] realization_coord = iris.coords.AuxCoord( np.int32(realization_number), "realization", units="1" ) cube.add_aux_coord(realization_coord) def main(): # Create a constraint to extract surface temperature cubes which have a # "realization" coordinate. constraint = iris.Constraint("surface_temperature", realization=lambda value: True) # Use this to load our ensemble. The callback ensures all our members # have the "realization" coordinate and therefore they will all be loaded. surface_temp = iris.load_cube( iris.sample_data_path("GloSea4", "ensemble_???.pp"), constraint, callback=realization_metadata, ) # ------------------------------------------------------------------------- # Plot #1: Ensemble postage stamps # ------------------------------------------------------------------------- # For the purposes of this example, take the last time element of the cube. # First get hold of the last time by slicing the coordinate. last_time_coord = surface_temp.coord("time")[-1] last_timestep = surface_temp.subset(last_time_coord) # Find the maximum and minimum across the dataset. data_min = np.min(last_timestep.data) data_max = np.max(last_timestep.data) # Create a wider than normal figure to support our many plots. plt.figure(figsize=(12, 6), dpi=100) # Also manually adjust the spacings which are used when creating subplots. plt.gcf().subplots_adjust( hspace=0.05, wspace=0.05, top=0.95, bottom=0.05, left=0.075, right=0.925, ) # Iterate over all possible latitude longitude slices. for cube in last_timestep.slices(["latitude", "longitude"]): # Get the ensemble member number from the ensemble coordinate. ens_member = cube.coord("realization").points[0] # Plot the data in a 4x4 grid, with each plot's position in the grid # being determined by ensemble member number. The special case for the # 13th ensemble member is to have the plot at the bottom right. if ens_member == 13: plt.subplot(4, 4, 16) else: plt.subplot(4, 4, ens_member + 1) # Plot with 50 evenly spaced contour levels (49 intervals). cf = iplt.contourf(cube, 49, vmin=data_min, vmax=data_max) # Add coastlines. plt.gca().coastlines() # Make an axes to put the shared colorbar in. colorbar_axes = plt.gcf().add_axes([0.35, 0.1, 0.3, 0.05]) colorbar = plt.colorbar(cf, colorbar_axes, orientation="horizontal") colorbar.set_label(last_timestep.units) # Limit the colorbar to 8 tick marks. colorbar.locator = matplotlib.ticker.MaxNLocator(8) colorbar.update_ticks() # Get the time for the entire plot. time = last_time_coord.units.num2date(last_time_coord.bounds[0, 0]) # Set a global title for the postage stamps with the date formatted by # "monthname year". time_string = time.strftime("%B %Y") plt.suptitle(f"Surface temperature ensemble forecasts for {time_string}") iplt.show() # ------------------------------------------------------------------------- # Plot #2: ENSO plumes # ------------------------------------------------------------------------- # Nino 3.4 lies between: 170W and 120W, 5N and 5S, so use the intersection # method to restrict to this region. nino_cube = surface_temp.intersection(latitude=[-5, 5], longitude=[-170, -120]) # Calculate the horizontal mean for the nino region. mean = nino_cube.collapsed(["latitude", "longitude"], iris.analysis.MEAN) # Calculate the ensemble mean of the horizontal mean. ensemble_mean = mean.collapsed("realization", iris.analysis.MEAN) # Take the ensemble mean from each ensemble member. mean -= ensemble_mean plt.figure() for ensemble_member in mean.slices(["time"]): # Draw each ensemble member as a dashed line in black. iplt.plot(ensemble_member, "--k") plt.title("Mean temperature anomaly for ENSO 3.4 region") plt.xlabel("Time") plt.ylabel("Temperature anomaly / K") iplt.show() if __name__ == "__main__": main() .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 26.262 seconds) .. _sphx_glr_download_generated_gallery_meteorology_plot_lagged_ensemble.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_lagged_ensemble.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_lagged_ensemble.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_