Plotting a Cube#
Iris utilises the power of Python’s
Matplotlib package in order to generate
high quality, production ready 1D and 2D plots.
The functionality of the Matplotlib pyplot
module has
been extended within Iris to facilitate easy visualisation of a cube’s data.
See also
Relevant gallery example: Zonal Mean Diagram of Air Temperature (Plotting with multiple axes)
Matplotlib’s Pyplot Basics#
A simple line plot can be created using the
matplotlib.pyplot.plot()
function:
import matplotlib.pyplot as plt
plt.plot([1, 2, 2.5])
plt.show()
This code will automatically create a figure with appropriate axes for the plot and show it on screen. The call to plt.plot([1, 2, 2.5]) will create a line plot with appropriate axes for the data (x=0, y=1; x=1, y=2; x=2, y=2.5). The call to plt.show() tells Matplotlib that you have finished with this plot and that you would like to visualise it in a window. This is an example of using matplotlib in non-interactive mode.
There are two modes of rendering within Matplotlib; interactive and non-interactive.
Interactive Plot Rendering#
The previous example was non-interactive as the figure is only rendered
after the call to plt.show()
.
Rendering plots interactively can be achieved by changing the interactive
mode:
import matplotlib.pyplot as plt
plt.interactive(True)
plt.plot([1, 2, 2.5])
In this case the plot is rendered automatically with no need to explicitly call
matplotlib.pyplot.show()
after plt.plot.
Subsequent changes to your figure will be automatically rendered in the window.
The current rendering mode can be determined as follows:
import matplotlib.pyplot as plt
print(plt.isinteractive())
Note
For clarity, each example includes all of the imports required to run on its own; when combining examples such as the two above, it would not be necessary to repeat the import statement more than once:
import matplotlib.pyplot as plt
plt.interactive(True)
plt.plot([1, 2, 2.5])
print(plt.isinteractive())
Interactive mode does not clear out the figure buffer, so figures have to be explicitly closed when they are finished with:
plt.close()
– or just close the figure window.
Interactive mode sometimes requires an extra draw command to update all changes, which can be done with:
plt.draw()
For the remainder of this tutorial we will work in non-interactive mode, so ensure that interactive mode is turned off with:
plt.interactive(False)
Saving a Plot#
The matplotlib.pyplot.savefig()
function is similar to plt.show()
in that they are both non-interactive visualisation modes.
As you might expect, plt.savefig saves your figure as an image:
import matplotlib.pyplot as plt
plt.plot([1, 2, 2.5])
plt.savefig('plot123.png')
The filename extension passed to the matplotlib.pyplot.savefig()
function can be used to control the output file format of the plot
(keywords can also be used to control this and other aspects,
see matplotlib.pyplot.savefig()
).
Some of the formats which are supported by plt.savefig:
Format |
Type |
Description |
---|---|---|
EPS |
Vector |
Encapsulated PostScript |
Vector |
Portable Document Format |
|
PNG |
Raster |
Portable Network Graphics, a format with a lossless compression method |
PS |
Vector |
PostScript, ideal for printer output |
SVG |
Vector |
Scalable Vector Graphics, XML based |
Iris Cube Plotting#
The Iris modules iris.quickplot
and iris.plot
extend the
Matplotlib pyplot interface by implementing thin wrapper functions.
These wrapper functions simply bridge the gap between an Iris cube and
the data expected by standard Matplotlib pyplot functions.
This means that all Matplotlib pyplot functionality,
including keyword options, are still available through the Iris plotting
wrapper functions.
As a rule of thumb:
if you wish to do a visualisation with a cube, use
iris.plot
oriris.quickplot
.if you wish to show, save or manipulate any visualisation, including ones created with Iris, use
matplotlib.pyplot
.if you wish to create a non cube visualisation, also use
matplotlib.pyplot
.
The iris.quickplot
module is exactly the same as the iris.plot
module,
except that quickplot
will add a title, x and y labels and a colorbar
where appropriate.
Note
In all subsequent examples the matplotlib.pyplot
, iris.plot
and
iris.quickplot
modules are imported as plt
, iplt
and qplt
respectively in order to make the code more readable.
This is equivalent to:
import matplotlib.pyplot as plt
import iris.plot as iplt
import iris.quickplot as qplt
Plotting 1-Dimensional Cubes#
The simplest 1D plot is achieved with the iris.plot.plot()
function.
The syntax is very similar to that which you would provide to Matplotlib’s
equivalent matplotlib.pyplot.plot()
and indeed all of the
keyword arguments are equivalent:
"""Simple 1D plot using iris.plot.plot()."""
import matplotlib.pyplot as plt
import iris
import iris.plot as iplt
fname = iris.sample_data_path("air_temp.pp")
temperature = iris.load_cube(fname)
# Take a 1d slice using array style indexing.
temperature_1d = temperature[5, :]
iplt.plot(temperature_1d)
plt.show()
(Source code
, png
)

For more information on how this example reduced the 2D cube to 1 dimension see the previous section entitled Subsetting a Cube.
Note
Axis labels and a plot title can be added using the
plt.title()
,
plt.xlabel()
and
plt.ylabel()
functions.
As well as providing simple Matplotlib wrappers, Iris also has a
iris.quickplot
module, which adds extra cube based metadata
to a plot.
For example, the previous plot can be improved quickly by replacing
iris.plot with iris.quickplot:
"""Simple 1D plot using iris.quickplot.plot()."""
import matplotlib.pyplot as plt
import iris
import iris.quickplot as qplt
fname = iris.sample_data_path("air_temp.pp")
temperature = iris.load_cube(fname)
# Take a 1d slice using array style indexing.
temperature_1d = temperature[5, :]
qplt.plot(temperature_1d)
plt.show()
(Source code
, png
)

Multi-Line Plot#
A multi-lined (or over-plotted) plot, with a legend, can be achieved easily by
calling iris.plot.plot()
or iris.quickplot.plot()
consecutively
and providing the label keyword to identify it.
Once all of the lines have been added the matplotlib.pyplot.legend()
function can be called to indicate that a legend is desired:
"""
Multi-Line Temperature Profile Plot
===================================
""" # noqa: D205, D212, D400
import matplotlib.pyplot as plt
import iris
import iris.plot as iplt
import iris.quickplot as qplt
def main():
fname = iris.sample_data_path("air_temp.pp")
# Load exactly one cube from the given file.
temperature = iris.load_cube(fname)
# We only want a small number of latitudes, so filter some out
# using "extract".
temperature = temperature.extract(
iris.Constraint(latitude=lambda cell: 68 <= cell < 78)
)
for cube in temperature.slices("longitude"):
# Create a string label to identify this cube (i.e. latitude: value).
cube_label = "latitude: %s" % cube.coord("latitude").points[0]
# Plot the cube, and associate it with a label.
qplt.plot(cube, label=cube_label)
# Add the legend with 2 columns.
plt.legend(ncol=2)
# Put a grid on the plot.
plt.grid(True)
# Tell matplotlib not to extend the plot axes range to nicely
# rounded numbers.
plt.axis("tight")
# Finally, show it.
iplt.show()
if __name__ == "__main__":
main()
(Source code
, png
)

This example of consecutive qplt.plot
calls coupled with the
Cube.slices()
method on a cube shows
the temperature at some latitude cross-sections.
Note
The previous example uses the if __name__ == "__main__"
style to run
the desired code if and only if the script is run from the command line.
This is a good habit to get into when writing scripts in Python as it means that any useful functions or variables defined within the script can be imported into other scripts without running all of the code and thus creating an unwanted plot. This is discussed in more detail at https://effbot.org/pyfaq/tutor-what-is-if-name-main-for.htm.
In order to run this example, you will need to copy the code into a file
and run it using python my_file.py
.
Plotting 2-Dimensional Cubes#
Creating Maps#
Whenever a 2D plot is created using an iris.coord_systems.CoordSystem
,
a cartopy GeoAxes
instance is created, which can be
accessed with the matplotlib.pyplot.gca()
function.
Given the current map, you can draw gridlines and coastlines amongst other things.
See also
Cube Contour#
A simple contour plot of a cube can be created with either the
iris.plot.contour()
or iris.quickplot.contour()
functions:
"""Simple contour plot of a cube.
Can use iris.plot.contour() or iris.quicplot.contour().
"""
import matplotlib.pyplot as plt
import iris
import iris.quickplot as qplt
fname = iris.sample_data_path("air_temp.pp")
temperature_cube = iris.load_cube(fname)
# Add a contour, and put the result in a variable called contour.
contour = qplt.contour(temperature_cube)
# Add coastlines to the map created by contour.
plt.gca().coastlines()
# Add contour labels based on the contour we have just created.
plt.clabel(contour, inline=False)
plt.show()
(Source code
, png
)

Cube Filled Contour#
Similarly a filled contour plot of a cube can be created with the
iris.plot.contourf()
or iris.quickplot.contourf()
functions:
"""Simple filled contour plot of a cube.
Can use iris.plot.contour() or iris.quickplot.contour().
"""
import matplotlib.pyplot as plt
import iris
import iris.quickplot as qplt
fname = iris.sample_data_path("air_temp.pp")
temperature_cube = iris.load_cube(fname)
# Draw the contour with 25 levels.
qplt.contourf(temperature_cube, 25)
# Add coastlines to the map created by contourf.
plt.gca().coastlines()
plt.show()
(Source code
, png
)

Cube Block Plot#
In some situations the underlying coordinates are better represented with a
continuous bounded coordinate, in which case a “block” plot may be more
appropriate.
Continuous block plots can be achieved with either iris.plot.pcolormesh()
or iris.quickplot.pcolormesh()
.
Note
If the cube’s coordinates do not have bounds, iris.plot.pcolormesh()
and iris.quickplot.pcolormesh()
will attempt to guess suitable values
based on their points (see also iris.coords.Coord.guess_bounds()
).
"""Cube block plot using using iris.plot.pcolormesh()."""
import matplotlib.pyplot as plt
import iris
import iris.quickplot as qplt
# Load the data for a single value of model level number.
fname = iris.sample_data_path("hybrid_height.nc")
temperature_cube = iris.load_cube(fname, iris.Constraint(model_level_number=1))
# Draw the block plot.
qplt.pcolormesh(temperature_cube)
plt.show()
(Source code
, png
)

Brewer Colour Palettes#
Iris includes colour specifications and designs developed by Cynthia Brewer These colour schemes are freely available under the following licence:
Apache-Style Software License for ColorBrewer software and ColorBrewer Color Schemes
Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania State University.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
To include a reference in a journal article or report please refer to section 5 in the citation guidance provided by Cynthia Brewer.
For adding citations to Iris plots, see Adding a Citation (below).
Available Brewer Schemes#
The following subset of Brewer palettes found at colorbrewer2.org are available within Iris.
(Source code
, png
)

Plotting With Brewer#
To plot a cube using a Brewer colour palette, simply select one of the Iris
registered Brewer colour palettes and plot the cube as normal. The Brewer palettes
become available once iris.plot
or iris.quickplot
are imported.
"""Plot a cube with a Brewer colour palette using iris.quickplot.contourf()."""
import matplotlib.cm as mpl_cm
import matplotlib.pyplot as plt
import iris
import iris.quickplot as qplt
fname = iris.sample_data_path("air_temp.pp")
temperature_cube = iris.load_cube(fname)
# Load a Cynthia Brewer palette.
brewer_cmap = mpl_cm.get_cmap("brewer_OrRd_09")
# Draw the contours, with n-levels set for the map colours (9).
# NOTE: needed as the map is non-interpolated, but matplotlib does not provide
# any special behaviour for these.
qplt.contourf(temperature_cube, brewer_cmap.N, cmap=brewer_cmap)
# Add coastlines to the map created by contourf.
plt.gca().coastlines()
plt.show()
(Source code
, png
)

Adding a Citation#
Citations can be easily added to a plot using the
iris.plot.citation()
function.
The recommended text for the Cynthia Brewer citation is provided by
iris.plot.BREWER_CITE
.
"""Adding a citation for a plot using iris.plot.citation()."""
import matplotlib.pyplot as plt
import iris
import iris.plot as iplt
import iris.quickplot as qplt
fname = iris.sample_data_path("air_temp.pp")
temperature_cube = iris.load_cube(fname)
# Get the Purples "Brewer" palette.
brewer_cmap = plt.get_cmap("brewer_Purples_09")
# Draw the contours, with n-levels set for the map colours (9).
# NOTE: needed as the map is non-interpolated, but matplotlib does not provide
# any special behaviour for these.
qplt.contourf(temperature_cube, brewer_cmap.N, cmap=brewer_cmap)
# Add a citation to the plot.
iplt.citation(iris.plot.BREWER_CITE)
# Add coastlines to the map created by contourf.
plt.gca().coastlines()
plt.show()
(Source code
, png
)
