Domains and projections¶
earthkit-plots makes it simple to produce maps over any geographic extent, using whichever map projection suits your data best. The domain argument is accepted by ekp.Map, Figure.add_map(), and all high-level namespace functions such as ekp.geo.contourf.
This notebook covers:
Named domains — built-in country and region names
Combining domains — union of multiple named regions
Custom bounding-box domains —
[lon_min, lon_max, lat_min, lat_max]Overriding the projection — passing a cartopy CRS
Domain objects — for full control over extent and CRS
Throughout the examples we use the {domain} and {crs} format strings in titles so the chosen domain and projection are always visible.
[1]:
import earthkit.data as ekd
import earthkit.plots as ekp
data = ekd.from_source("sample", "era5-monthly-mean-2t-199312.grib")
Named domains¶
Pass any of the following as the domain argument:
A country name from Natural Earth Admin-0 — e.g.
"France"A continent — e.g.
"Africa"A built-in named region packaged with earthkit-plots — e.g.
"Europe","Arctic"None(default) — extent and projection are inferred from the first dataset plotted
earthkit-plots automatically selects an appropriate projection for each named domain. Notice how "Europe" uses a Lambert Azimuthal Equal Area projection while "Arctic" uses a North Polar Stereographic.
[2]:
figure = ekp.Figure(rows=2, columns=2)
for domain in ["Europe", "Arctic", "Africa", "Japan"]:
subplot = figure.add_map(domain=domain)
subplot.contourf(data, units="celsius", style="auto")
subplot.title("{domain} - {crs}")
figure.coastlines()
figure.borders()
figure.gridlines()
figure.legend()
figure.show()
Combining domains¶
Pass a list of names to take the union of multiple regions. earthkit-plots computes the bounding box that encloses all listed regions and picks an appropriate projection for the combined extent.
[3]:
chart = ekp.Map(domain=["Spain", "France", "Italy"])
chart.contourf(data, units="celsius", style="auto")
chart.coastlines()
chart.borders()
chart.gridlines()
chart.legend()
chart.title("{domain} - {crs}")
chart.show()
Custom bounding-box domains¶
Pass a list of four values [lon_min, lon_max, lat_min, lat_max] to define your own extent. earthkit-plots will still choose a sensible default projection for the given bounds.
[4]:
chart = ekp.Map(domain=[-30, 50, 25, 70])
chart.contourf(data, units="celsius", style="auto")
chart.coastlines()
chart.borders()
chart.gridlines()
chart.legend()
chart.title("Custom domain - {crs}")
chart.show()
Overriding the coordinate system¶
Any domain argument can be paired with an explicit crs argument to override the default projection. Pass any cartopy CRS.
[5]:
import cartopy.crs as ccrs
chart = ekp.Map(domain="Europe", crs=ccrs.NorthPolarStereo(central_longitude=10))
chart.contourf(data, units="celsius", style="auto")
chart.coastlines()
chart.borders()
chart.gridlines()
chart.legend()
chart.title("{domain} - {crs}")
chart.show()
Automatic CRS detection¶
If your data is defined on a coordinate reference system, by default earthkit-plots will attempt to plot your data on its native CRS and domain. This does of course depend on your data having standard metadata about its coordinate system - for example a CF-compliant grid_mapping.
We can demonstrate this with some data from the European Flood Awareness System (EFAS) defined on a speficific Lambert Azimuthal Equal Area coordinate system. First, we can get the data and inspect its geography to get its projection:
[6]:
efas_laea = ekd.from_source("sample", "efas.nc").to_fieldlist()
efas_laea.geography.projection()
[6]:
<Projected CRS: +proj=laea +ellps=GRS80 +lon_0=10.0 +lat_0=52.0 +x ...>
Name: unknown
Axis Info [cartesian]:
- E[east]: Easting (metre)
- N[north]: Northing (metre)
Area of Use:
- undefined
Coordinate Operation:
- name: unknown
- method: Lambert Azimuthal Equal Area
Datum: Unknown based on GRS 1980 ellipsoid
- Ellipsoid: GRS 1980
- Prime Meridian: Greenwich
This shows us that earthkit-data has successfully identified the coordinate system of the data. When we plot this data, it will use the exact coordinate system (and bounding box) that it found in the data.
[7]:
style = ekp.styles.Style(
colors="Blues",
levels=[0.1, 0.5, 1, 2, 5, 10, 50, 100, 500, 1000, 2000, 3000, 4000],
extend="max",
units="m3 s-1",
)
ekp.geo.grid_cells(
efas_laea[0],
style=style,
title="EFAS data on {crs}",
).gridlines(
xstep=10,
ystep=10,
).show()
[7]:
<earthkit.plots.components.figures.Figure at 0x177c00f50>
You can of course choose to plot this data with a different domain and/or CRS if you wish!
[8]:
import cartopy.crs as ccrs
chart = ekp.geo.grid_cells(
efas_laea[0],
domain=["Norway", "Sweden", "Finland"],
crs=ccrs.NorthPolarStereo(),
style=style,
title="EFAS data on {crs}",
).gridlines(
xstep=10,
ystep=10,
)
chart.show()
[8]:
<earthkit.plots.components.figures.Figure at 0x177c02e50>
What’s next?¶
Now that you know how to control map extents and projections, the next notebook explores how to combine multiple data layers and subplot layouts using the Figure class.