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:

  1. Named domains — built-in country and region names

  2. Combining domains — union of multiple named regions

  3. Custom bounding-box domains[lon_min, lon_max, lat_min, lat_max]

  4. Overriding the projection — passing a cartopy CRS

  5. 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()
../../../_images/examples_examples_introduction_07-domains_3_0.png

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()
../../../_images/examples_examples_introduction_07-domains_5_0.png

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()
../../../_images/examples_examples_introduction_07-domains_7_0.png

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()
../../../_images/examples_examples_introduction_07-domains_9_0.png

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()
../../../_images/examples_examples_introduction_07-domains_13_0.png
[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()
../../../_images/examples_examples_introduction_07-domains_15_0.png
[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.