Grid explorer¶
In this notebook you will see how to:
inspect the grid properties of GRIB data
access the latitudes/longitudes of a field
plot the gridpoints of a field
interpolate GRIB data from one grid to another (regridding)
extract the nearest gridpoint from a field
Components of earthkit¶
This tutorial uses the following earthkit components - click any logo to open the package documentation:
1. Getting the data¶
The input data is a GRIB file containing 1000 hPa temperature fields on 3 different global grids.
First, fetch the file and list its contents.
[1]:
import earthkit.data as ekd
ds = ekd.from_source("sample", "grids_3.grib").to_fieldlist()
ds.ls()
[1]:
| parameter.variable | time.valid_datetime | time.base_datetime | time.step | vertical.level | vertical.level_type | ensemble.member | geography.grid_type | |
|---|---|---|---|---|---|---|---|---|
| 0 | t | 2015-04-22 12:00:00 | 2015-04-22 12:00:00 | 0 days | 1000 | pressure | None | regular_ll |
| 1 | t | 2015-04-22 12:00:00 | 2015-04-22 12:00:00 | 0 days | 1000 | pressure | None | reduced_gg |
| 2 | t | 2015-04-22 12:00:00 | 2015-04-22 12:00:00 | 0 days | 1000 | pressure | None | healpix |
Next, select the field you will inspect in the rest of the notebook.
To try another grid type change the gridType in the sel() call below and rerun the notebook.
[2]:
# choose one from: regular_ll, reduced_gg, healpix
f = ds.sel({"geography.grid_type": "regular_ll"})[0]
f.ls()
[2]:
| parameter.variable | time.valid_datetime | time.base_datetime | time.step | vertical.level | vertical.level_type | ensemble.member | geography.grid_type | |
|---|---|---|---|---|---|---|---|---|
| 0 | t | 2015-04-22 12:00:00 | 2015-04-22 12:00:00 | 0 days | 1000 | pressure | None | regular_ll |
2. Inspecting the grid¶
With .get() you can inspect the relevant metadata.
[3]:
f.get("parameter.variable"), f.get("geography.grid_type")
[3]:
('t', 'regular_ll')
The field’s shape is related to the geography. For grids with regular 2D structure, like regular latitude-longitude grids, the geography’s shape is always 2D. Otherwise, like for reduced Gaussian grids, it is 1D.
[4]:
f.geography.shape()
[4]:
(37, 72)
When you access the latitudes and longitudes via .geography.latlons() you get numpy arrays with the field’s shape.
[5]:
lat, lon = f.geography.latlons()
lat.shape, lon.shape
[5]:
((37, 72), (37, 72))
You can access the field values either with to_numpy() or via the values property. By default, to_numpy() respects the field’s shape unless you use the flatten=True option.
[6]:
f.to_numpy().shape, f.to_numpy(flatten=True).shape
[6]:
((37, 72), (2664,))
When using the values property always a 1D array is returned.
[7]:
f.values.shape
[7]:
(2664,)
3. Plotting the gridpoints¶
This example shows you how to plot the original gridpoint positions of the field.
[8]:
import earthkit.plots as ekp
chart = ekp.Map(size=(7,7))
chart.contourf(f, units="celsius", auto_style=True)
# plot the original grid points
chart.grid_points(f, c="black") #marker="+"
chart.title(f"gridType={f.get('geography.grid_type')}")
chart.coastlines()
chart.gridlines()
chart.legend()
chart.show()
The next plot shows a smaller area and displays the grid values at each grid point.
[9]:
import cartopy.crs as ccrs
chart = ekp.Map(domain="Europe")
chart.contourf(f, units="celsius", auto_style=True)
# plot the original grid points
chart.grid_points(f, c="black") #marker="+"
# generate grid values
lat, lon, vals = f.data(flatten=True)
labels = [f"{x:.1f}" for x in vals]
for i, lbs in enumerate(labels):
chart.ax.annotate(lbs, (lon[i], lat[i]), transform=ccrs.Geodetic(),
xytext=(0,5),
textcoords="offset pixels",
annotation_clip=True,
fontsize=6, horizontalalignment="center")
chart.title(f"gridType={f.metadata('gridType')}")
chart.coastlines()
chart.gridlines()
chart.legend()
chart.show()
4. Regridding¶
You can regrid data with earthkit.geo.regrid.regrid().
[10]:
import earthkit.geo as ekg
# the target grid is a global 10x10 degree regular latitude-longitude grid
grid = {"grid": [10,10]}
# perform interpolation for the field f
print(f)
ds_res = ekg.regrid(f, grid=grid, interpolation="linear")
Field(t, 2015-04-22 12:00:00, 2015-04-22 12:00:00, 0:00:00, 1000, pressure, None, regular_ll)
The next cell plots the original and interpolated fields over a subarea.
[11]:
figure = ekp.Figure(domain="North Atlantic", rows=2, columns=1)
# the original field
subplot = figure.add_map(0, 0)
subplot.contourf(f, units="celsius", auto_style=True)
subplot.grid_points(f, c="black")
subplot.title("Original field")
# the interpolated field
subplot = figure.add_map(1, 0)
subplot.contourf(ds_res, units="celsius", auto_style=True)
subplot.grid_points(ds_res, c="black")
subplot.title("Interpolated field")
figure.coastlines()
figure.gridlines()
figure.show()
5. Getting the nearest gridpoint¶
In this example you can see how to extract the nearest gridpoint value of a field using earthkit.geo.distance.nearest_point_haversine().
[12]:
# ref location (lat, lon)
p_ref = (51.45, -0.97)
# get latlon
lat, lon = f.geography.latlons()
# get nearest point index
idx, dist = ekg.distance.nearest_point_haversine(p_ref, (lat, lon))
idx
[12]:
array([576])
[13]:
# extract field value at given index
f.values[idx]
[13]:
array([283.45458984])