Input and output formats¶
earthkit-plots is designed to be format-agnostic: the same plotting code works regardless of where your data comes from or what format it is stored in. This notebook covers the most common input formats and shows how to save your plots to various output formats.
Input formats¶
earthkit-plots accepts data from four main sources:
Source |
How to load |
|---|---|
GRIB |
|
NetCDF |
|
xarray |
|
NumPy |
Plain |
Whichever format you use, the plotting call stays the same — only the data loading line changes.
[1]:
import earthkit.data as ekd
import earthkit.plots as ekp
GRIB¶
GRIB (GRIdded Binary) is the standard format for numerical weather prediction output at operational centres such as ECMWF. GRIB files carry rich metadata — parameter name, units, level type, valid time — which earthkit-plots uses automatically for titles, unit conversion and style selection.
Load a GRIB file with ekd.from_source. For a local file, use ekd.from_source("file", "/path/to/data.grib").
[2]:
grib = ekd.from_source("sample", "era5-monthly-mean-2t-199312.grib")
grib
[2]:
| path | /var/folders/vt/7j2c2tmx4m14gn_sg3zpf5l00000gn/T/tmpwdbm3bb6/url-954df2739db5b12ef733b2749696756c344293e9bf26ea49fe2991c9aae6a16a.grib |
| size | 2 MiB |
| types | fieldlist, pandas, xarray, numpy, array |
[3]:
chart = ekp.Map(domain="Europe")
chart.contourf(grib, units="celsius", style="auto")
chart.coastlines()
chart.legend(label="{variable_name} ({units})")
chart.title("{variable_name} – {time:%B %Y}")
chart.show()
NetCDF¶
NetCDF is one of the most widely used formats in climate science and follows the CF conventions. earthkit-plots reads netCDF files via earthkit-data and extracts coordinates and metadata automatically.
[4]:
nc = ekd.from_source("sample", "era5-monthly-mean-2t-199312.nc")
nc
[4]:
| path | /var/folders/vt/7j2c2tmx4m14gn_sg3zpf5l00000gn/T/tmpwdbm3bb6/url-7ef6aa12ddec2125e8c0a38727ccba97540d137ddbb4c12abf72f9b35b3f2ad9.nc |
| size | 2 MiB |
| types | xarray, pandas, fieldlist, numpy, array |
[5]:
chart = ekp.Map(domain="Europe")
chart.contourf(nc, units="celsius", style="auto")
chart.coastlines()
chart.legend(label="{variable_name} ({units})")
chart.title("{variable_name} – {time:%B %Y}")
chart.show()
xarray¶
xarray DataArray and Dataset objects are accepted directly — no conversion step is required. This is the most common path when you want to pre-process data (slicing, arithmetic, resampling) before plotting.
You can convert from an earthkit-data object using .to_xarray(), or pass any xarray object you have created yourself.
[6]:
ds = ekd.from_source("sample", "era5-monthly-mean-2t-199312.nc").to_xarray()
ds
[6]:
<xarray.Dataset> Size: 8MB
Dimensions: (time: 1, latitude: 721, longitude: 1440)
Coordinates:
* time (time) datetime64[ns] 8B 1993-12-01
* latitude (latitude) float32 3kB 90.0 89.75 89.5 ... -89.5 -89.75 -90.0
* longitude (longitude) float32 6kB 0.0 0.25 0.5 0.75 ... 359.2 359.5 359.8
Data variables:
t2m (time, latitude, longitude) float64 8MB ...
Attributes:
Conventions: CF-1.6
history: 2024-05-21 15:58:02 GMT by grib_to_netcdf-2.28.1: /opt/ecmw...Pass the Dataset directly, or select a single DataArray by variable name:
[7]:
chart = ekp.Map(domain="Europe")
chart.contourf(ds["t2m"], units="celsius", style="auto")
chart.coastlines()
chart.legend(label="{variable_name} ({units})")
chart.title("{variable_name} – {time:%B %Y}")
chart.show()
NumPy arrays¶
Plain NumPy arrays are also supported. The trade-off is that NumPy arrays carry no geographical or meteorological metadata, so you must supply coordinate arrays explicitly via x= and y=. Unit conversion and automatic titles require an optional metadata dict.
The simplest way to get coordinates for a GRIB or netCDF field is from earthkit-data:
[8]:
from datetime import datetime
fl = ekd.from_source("sample", "era5-monthly-mean-2t-199312.grib").to_fieldlist()
lats, lons = fl.geography.latlons()
t2m = fl.to_numpy().squeeze()
print(f"data shape: {t2m.shape}, lats: {lats.shape}, lons: {lons.shape}")
data shape: (721, 1440), lats: (721, 1440), lons: (721, 1440)
Without metadata the plot still works, but titles and unit conversion are unavailable:
[9]:
chart = ekp.Map(domain="Europe")
chart.contourf(t2m, x=lons, y=lats)
chart.coastlines()
chart.legend()
chart.show()
Supplying a metadata dict restores automatic titles, unit conversion and auto-styles. Valid keys mirror CF-convention attributes — units, long_name, time, and so on:
[10]:
metadata = {
"units": "K",
"long_name": "2 metre temperature",
"time": datetime(1993, 12, 1),
}
chart = ekp.Map(domain="Europe")
chart.contourf(t2m, x=lons, y=lats, metadata=metadata, units="celsius", style="auto")
chart.coastlines()
chart.legend(label="{variable_name} ({units})")
chart.title("{variable_name} – {time:%B %Y}")
chart.show()
Format agnosticism¶
The four examples above produce identical plots. The only difference is the data loading line — the plotting code is unchanged:
# GRIB
data = ekd.from_source("sample", "era5-monthly-mean-2t-199312.grib")
# NetCDF
data = ekd.from_source("sample", "era5-monthly-mean-2t-199312.nc")
# xarray
data = ekd.from_source("sample", "era5-monthly-mean-2t-199312.nc").to_xarray()["t2m"]
# NumPy (extra setup required)
fl = ekd.from_source("sample", "era5-monthly-mean-2t-199312.grib").to_fieldlist()
lats, lons = fl.geography.latlons()
data = fl.to_numpy().squeeze()
# In every case, the plot call is the same:
chart = ekp.Map(domain="Europe")
chart.contourf(data, units="celsius", style="auto") # add x=, y=, metadata= for NumPy
This format agnosticism is a deliberate design goal of earthkit-plots: your visualisation code should not need to change just because your data arrives in a different format.
Output formats¶
earthkit-plots wraps matplotlib’s savefig, so you can save to any format that matplotlib supports. The output format is inferred from the file extension.
Use figure.save() in place of figure.show():
[11]:
chart = ekp.Map(domain="Europe")
chart.contourf(grib, units="celsius", style="auto")
chart.coastlines()
chart.legend(label="{variable_name} ({units})")
chart.title("{variable_name} – {time:%B %Y}")
# PNG — raster, good for web and presentations
chart.save("temperature.png", dpi=150)
# PDF — vector, good for publications and print
chart.save("temperature.pdf")
# SVG — vector, good for further editing in Inkscape / Illustrator
chart.save("temperature.svg")
Key arguments:
``dpi`` — dots per inch for raster formats (PNG, JPEG). 150 is good for screen; 300 for print.
``bbox_inches`` — defaults to
"tight", which crops whitespace around the figure. PassNoneto use the figure’s exact size.Any other keyword argument accepted by
`matplotlib.pyplot.savefig<https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html>`__ is passed through.
Supported formats include: png, pdf, svg, eps, jpeg, tiff, and more — see the matplotlib documentation for the full list.