From c046ffd1ac3d4e0d723fbd80bfae7ffa742fdacd Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Sun, 29 Nov 2020 20:28:44 +0000 Subject: [PATCH 1/5] update seasonal example --- .../meteorology/plot_lagged_ensemble.py | 38 ++++++------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py b/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py index cb82a663d4..d46982035f 100644 --- a/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py +++ b/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py @@ -19,6 +19,7 @@ """ import matplotlib.pyplot as plt +import matplotlib.ticker import numpy as np import iris @@ -51,7 +52,7 @@ def main(): # coordinate, adding appropriate lagged ensemble metadata surface_temp = iris.load_cube( iris.sample_data_path("GloSea4", "ensemble_???.pp"), - iris.Constraint("surface_temperature", realization=lambda value: True), + iris.Constraint("surface_temperature"), callback=realization_metadata, ) @@ -102,11 +103,9 @@ def main(): # 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("%s" % last_timestep.units) + colorbar.set_label(last_timestep.units) # limit the colorbar to 8 tick marks - import matplotlib.ticker - colorbar.locator = matplotlib.ticker.MaxNLocator(8) colorbar.update_ticks() @@ -116,10 +115,8 @@ def main(): # set a global title for the postage stamps with the date formated by # "monthname year" - plt.suptitle( - "Surface temperature ensemble forecasts for %s" - % (time.strftime("%B %Y"),) - ) + title = "Surface temperature ensemble forecasts for {}" + plt.suptitle(title.format(time.strftime("%B %Y"))) iplt.show() @@ -127,31 +124,20 @@ def main(): # Plot #2: ENSO plumes # ------------------------------------------------------------------------- - # Nino 3.4 lies between: 170W and 120W, 5N and 5S, so define a constraint - # which matches this - nino_3_4_constraint = iris.Constraint( - longitude=lambda v: -170 + 360 <= v <= -120 + 360, - latitude=lambda v: -5 <= v <= 5, + # 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] ) - nino_cube = surface_temp.extract(nino_3_4_constraint) - - # Subsetting a circular longitude coordinate always results in a circular - # coordinate, so set the coordinate to be non-circular - nino_cube.coord("longitude").circular = False - - # Calculate the horizontal mean for the nino region + # 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. To do this, remove - # the "forecast_period" and "forecast_reference_time" coordinates which - # span both "relalization" and "time". - mean.remove_coord("forecast_reference_time") - mean.remove_coord("forecast_period") + # 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.data + mean -= ensemble_mean plt.figure() From 97b31500d762c280b5e2fa07f23e5cda7caa89e3 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Sun, 29 Nov 2020 20:38:48 +0000 Subject: [PATCH 2/5] add whatsnew --- docs/iris/src/whatsnew/latest.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/iris/src/whatsnew/latest.rst b/docs/iris/src/whatsnew/latest.rst index 919b9ee6e6..e9fb007aca 100644 --- a/docs/iris/src/whatsnew/latest.rst +++ b/docs/iris/src/whatsnew/latest.rst @@ -47,7 +47,8 @@ This document explains the changes made to Iris for this release 📚 Documentation ================ -* N/A +* `@rcomer`_ updated the "Seasonal ensemble model plots" Gallery example. + (:pull:`3933`) 💼 Internal @@ -56,3 +57,4 @@ This document explains the changes made to Iris for this release * N/A .. _@gcaria: https://github.com/gcaria +.. _@rcomer: https://github.com/rcomer From 080c86a426111d092d0b0ac978af29b24f43f7db Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Sun, 29 Nov 2020 21:38:28 +0000 Subject: [PATCH 3/5] have matplotlib do contour choosing work --- .../meteorology/plot_lagged_ensemble.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py b/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py index d46982035f..e4d63f5ed3 100644 --- a/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py +++ b/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py @@ -63,10 +63,9 @@ def main(): # for the purposes of this example, take the last time element of the cube last_timestep = surface_temp[:, -1, :, :] - # Make 50 evenly spaced levels which span the dataset - contour_levels = np.linspace( - np.min(last_timestep.data), np.max(last_timestep.data), 50 - ) + # 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) @@ -88,14 +87,15 @@ def main(): 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 + # 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) - cf = iplt.contourf(cube, contour_levels) + # 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() From e632a949cfe9bf83dbdc677c6b2789a66535fa3f Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Sun, 29 Nov 2020 21:47:53 +0000 Subject: [PATCH 4/5] remove redundant import --- docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py b/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py index e4d63f5ed3..78b19f3337 100644 --- a/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py +++ b/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py @@ -38,9 +38,6 @@ def realization_metadata(cube, field, fname): # the ensemble member is encoded in the filename as *_???.pp where ??? # is the ensemble member realization_number = fname[-6:-3] - - import iris.coords - realization_coord = iris.coords.AuxCoord( np.int32(realization_number), "realization", units="1" ) From 060e82a9d6a6c427a5e5ecfaca15297f119a5691 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Sat, 5 Dec 2020 11:48:21 +0000 Subject: [PATCH 5/5] review changes and grammar --- .../meteorology/plot_lagged_ensemble.py | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py b/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py index 78b19f3337..cdd39028c8 100644 --- a/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py +++ b/docs/iris/gallery_code/meteorology/plot_lagged_ensemble.py @@ -33,10 +33,10 @@ def realization_metadata(cube, field, fname): in the cube. """ - # add an ensemble member coordinate if one doesn't already exist + # 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 + # 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" @@ -45,11 +45,16 @@ def realization_metadata(cube, field, fname): def main(): - # extract surface temperature cubes which have an ensemble member - # coordinate, adding appropriate lagged ensemble metadata + # 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"), - iris.Constraint("surface_temperature"), + constraint, callback=realization_metadata, ) @@ -57,17 +62,19 @@ def main(): # Plot #1: Ensemble postage stamps # ------------------------------------------------------------------------- - # for the purposes of this example, take the last time element of the cube - last_timestep = surface_temp[:, -1, :, :] + # 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 + # 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 + # Also manually adjust the spacings which are used when creating subplots. plt.gcf().subplots_adjust( hspace=0.05, wspace=0.05, @@ -77,13 +84,13 @@ def main(): right=0.925, ) - # iterate over all possible latitude longitude slices + # Iterate over all possible latitude longitude slices. for cube in last_timestep.slices(["latitude", "longitude"]): - # get the ensemble member number from the ensemble coordinate + # 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 + # 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: @@ -94,26 +101,25 @@ def main(): # Plot with 50 evenly spaced contour levels (49 intervals). cf = iplt.contourf(cube, 49, vmin=data_min, vmax=data_max) - # add coastlines + # Add coastlines. plt.gca().coastlines() - # make an axes to put the shared colorbar in + # 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 + # Limit the colorbar to 8 tick marks. colorbar.locator = matplotlib.ticker.MaxNLocator(8) colorbar.update_ticks() - # get the time for the entire plot - time_coord = last_timestep.coord("time") - time = time_coord.units.num2date(time_coord.bounds[0, 0]) + # 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 formated by - # "monthname year" - title = "Surface temperature ensemble forecasts for {}" - plt.suptitle(title.format(time.strftime("%B %Y"))) + # Set a global title for the postage stamps with the date formated by + # "monthname year". + time_string = time.strftime("%B %Y") + plt.suptitle(f"Surface temperature ensemble forecasts for {time_string}") iplt.show() @@ -133,13 +139,13 @@ def main(): # Calculate the ensemble mean of the horizontal mean. ensemble_mean = mean.collapsed("realization", iris.analysis.MEAN) - # take the ensemble mean from each ensemble member + # 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 + # 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")