earthkit-plots is a Python library for visualising weather and climate science data quickly and efficiently, both in terms of reducing the amount of code you need to write and the time needed to produce publication-quality figures.
It is built on top of the well-established matplotlib and cartopy libraries and is underpinned by earthkit-data, making it highlighy compatible with many data formats (GRIB, NetCDF, Zarr, CSV, shapefiles and more) and Python data abstractions (numpy, xarray, FieldList and more).
Key features¶
Concise, high-level API that greatly reduces the amount of code needed to produce high-quality visualisations.
Automatic interpolation of complex grids like HEALPix and reduced Gaussian, making it just as easy to visualise these grids as regular gridded data.
Metadata-aware styling, including unit conversion at plot time, reducing the amount of pre-processing you need to do to your data.
Intelligent formatting of titles and labels using formattable strings that pull metadata directly from your datasets.
Here is an example of what earthkit-plots can do:
# Import earthkit-data for accessing sample datasets
import earthkit.data as ekd
# Import earthkit-plots to visualise them
import earthkit.plots as ekp
# Download some sample data - ERA5 monthly averaged temperature
era5_2t = ekd.from_source("sample", "era5-monthly-mean-2t-199312.grib")
# Create a map which shows a sub-domain over Europe
chart = ekp.Map(domain="Europe")
# Do a filled contour plot, with units of celsius and an automatic style
chart.contourf(era5_2t, units="celsius", style="auto")
# Add a title with formattable parameters
chart.title("ERA5 monthly averaged {variable_name} over {domain} - {time:%B %Y}")
# Add ancillary layers (coastlines, borders and gridlines)
chart.coastlines()
chart.borders()
chart.gridlines()
# Add a legend to the plot
chart.legend(label="{variable_name} ({units})")
# Show the plot
chart.show()Let’s explore what has happened step-by-step.
# Import earthkit-data for accessing sample datasets
import earthkit.data as ekd
# Import earthkit-plots to visualise them
import earthkit.plots as ekpThe earthkit ecosystem provides tools for accessing, processing and visualising weather and climate datasets. For this example, we need earthkit-data to get some sample data, and earthkit-plots to plot it. No other libraries need to be imported.
# Download some sample data - ERA5 monthly averaged temperature
era5_2t = ekd.from_source("sample", "era5-monthly-mean-2t-199312.grib")Here we load a sample GRIB file containing ERA5 monthly averaged 2-metre temperature for December 1993. earthkit-data handles accessing and decoding the remote dataset and provides a consistent interface regardless of the underlying format.
📖 For comprehensive documentation about accessing various data sources with earthkit-data, see the earthkit-data documentation.
# Create a map which shows a sub-domain over Europe
chart = ekp.Map(domain="Europe")This creates a new map canvas. By passing domain="Europe", we use one of earthkit-plots’ built-in named domains. Under-the-hood, earthkit-plots automatically selects an appropriate map projection for the given domain.
You can also:
Pass a country name, e.g.
domain="France".Pass a bounding box as
[lon_min, lon_max, lat_min, lat_max].Include a
crsargument, passing a cartopy coordinate system to control the map projection.Omit the argument entirely, in which case the extent and CRS is inferred from your data.
# Do a filled contour plot, with units of celsius and an automatic style
chart.contourf(era5_2t, units="celsius", style="auto")earthkit-plots augments matplotlib’s standard plotting methods (such as contourf, pcolormesh, scatter) with extra functionality:
units="celsius"converts the data from its native units (Kelvin) to Celsius at plot time, with no need to modify the underlying data.style="auto"— selects a pre-defined colour scheme appropriate for the variable being plotted.
Any additional keyword arguments supported by matplotlib’s contourf can be passed here too.
# Add a title with formattable parameters
chart.title("ERA5 monthly averaged {variable_name} over {domain} - {time:%B %Y}")earthkit-plots supports metadata-aware format strings in titles and labels. These curly-brace placeholders are automatically populated from your dataset’s metadata.
This works with GRIB keys, CF-conventions, and simple xarray attributes. You can make use of protected magic strings to avoid having to adapt titles to different metadata formats - for example:
The
{variable_name}key tries to find a human-readable variable name (checkslong_name,standard_name,short_name, and GRIB keys in priority order).The
{domain}key adapts to the selected named map domain.The
{time}key searches for well-established time-related metadata structures whatever format your input data comes from. You can also use format specs to format the time into a format of your choice with Python’s standard strftime formats.
# Add ancillary layers (coastlines, borders and gridlines)
chart.coastlines()
chart.borders()
chart.gridlines()These convenience methods are based on cartopy’s methods like coastlines and gridlines. Additional methods like borders, administrative_regions and more are included in earthkit-plots for convenience.
# Add a legend to the plot
chart.legend(label="{variable_name} ({units})")The legend method in earthkit-plots unifies matplotlib’s colorbar and legend into a single call. It adds a legend for every plotted layer, styled appropriately. The label argument supports the same metadata format strings as the title - here {units} resolves to the units that were passed to contourf (or the data’s original units if none were specified).
# Show the plot
chart.show()Finally, we show the plot. This is a simple wrapper around plt.show() for convenience (you can use either interchangeably, or omit it altogether if you are in a Jupyter notebook).
Going (a little bit) deeper¶
This first example has demonstrated how to make use of the high-level, automatic features of earthkit-plots to quickly visualise your data. But what if you want to customise the plot? How would you use a different map projection, colour scheme or levels?
Since earthkit-plots is underpinned by matplotlib and cartopy, we can make use of those libraries - matplotlib for styling, cartopy for map projections - to customise our plot.
# Import cartopy's coordinate systems
import cartopy.crs as ccrs
chart = ekp.Map(domain="Europe", crs=ccrs.NorthPolarStereo())
chart.contourf(
era5_2t, units="celsius",
# Matplotlib-style colormap and levels
cmap="RdBu_r", levels=range(-20, 21), extend="both",
)
chart.coastlines()
chart.borders()
chart.gridlines()
chart.legend(label="{units}")
# Custom title with metadata formatting
chart.title("ERA5 monthly averaged {variable_name} over {domain} - {time:%B %Y}")
chart.show()Feel free to experiment with the domain, CRS, styles and titles!
An even higher-level API¶
As well as the flexible and high-level object-oriented interface described above, earthkit-plots also provides super high-level shortcut functions that handle most of the plotting workflow for you.
This level of API can help you quickly visualise your data without having to give it too much thought, but has been demonstrated after the objected-oriented API to clarify that this approach, while more convenient and much less code, may not be a good starting point if you want more control over your plots.
chart = ekp.geo.contourf(era5_2t, domain="Europe", units="celsius", style="auto")Exercises¶
Using either earthkit-plots API, can you plot this 2m temperature data over Australia, using the matplotlib cmap of your choice and levels that range from 0 to 40 celsius in steps of 1?
Now try adding your own custom title, custom legend label, country borders, gridlines, and cities (hint:
Maps have a.cities()method).