lair.utils.geo#
Geo-spatial utilities.
Functions
|
Add an extent map to the figure. |
|
Add latitude ticks to the map. |
|
Add latitude and longitude ticks to the map. |
|
Add longitude ticks to the map. |
|
Bounding box to extent. |
|
|
|
Clip the data to the given bounds. |
|
Calculate cosine weights from latitude. |
|
Degree-minute-second to decimal degree |
|
Calculate radius of Earth assuming oblate spheroid defined by WGS84 |
|
Extent to bounding box. |
|
Generate a regular grid. |
|
Calculate the area of each grid cell in a grid. |
|
Calculate the area of each grid cell in a lat-lon grid. |
|
|
|
Plot a grid. |
|
Regrid data to a new grid. |
|
Resample the data to a new resolution. |
|
Round latitude and longitude values to a specified number of decimal places. |
|
Transform the longitude values to be within the closed interval [base, base + period]. |
|
Write the CRS and coordinate system to the rioxarray accessor. |
Classes
|
Base class for working with gridded data. |
|
Coordinate Reference System (CRS) class. |
- lair.utils.geo.bbox2extent(bbox: list[float]) list[float] [source]#
Bounding box to extent.
- Parameters:
- bboxlist[minx, miny, maxx, maxy]
Bounding box
- Returns:
- list[minx, maxx, miny, maxy]
Extent
- lair.utils.geo.extent2bbox(extent: list[float] | tuple[float, float, float, float]) list[float] [source]#
Extent to bounding box.
- Parameters:
- extentlist[minx, maxx, miny, maxy]
Extent
- Returns:
- list[minx, miny, maxx, maxy]
Bounding box
- class lair.utils.geo.CRS(crs: Any)[source]#
Coordinate Reference System (CRS) class.
This class is a wrapper around the pyproj.CRS class, with additional methods for converting to other CRS classes.
See https://pyproj4.github.io/pyproj/stable/crs_compatibility.html#cartopy for more information.
Note
osgeo, fiona, and pycrs conversions have not been implemented.
Attributes
Get the EPSG code of the CRS.
Get the PROJ4 string of the CRS.
Get the WKT string of the CRS.
crs
(pyproj.CRS) Pyproj CRS object
- lair.utils.geo.dms2dd(d: float = 0.0, m: float = 0.0, s: float = 0.0) float [source]#
Degree-minute-second to decimal degree
- Parameters:
- dfloat, optional
Degrees, by default 0.0
- mfloat, optional
Minutes, by default 0.0
- sfloat, optional
Seconds, by default 0.0
- Returns:
- float
Decimal degrees
- Raises:
- ValueError
If any of the inputs are not floats
- lair.utils.geo.wrap_lons(longitudes: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], base: float = -180.0, period: float | None = 360.0) ndarray [source]#
Transform the longitude values to be within the closed interval [base, base + period].
- Parameters:
- longitudesArrayLike
One or more longitude values (degrees) to be wrapped.
- basefloat, default=-180.0
The start limit (degrees) of the closed interval.
- periodfloat, default=360.0
The end limit (degrees) of the closed interval expressed as a length from the base.
- Returns:
- ndarray
The transformed longitude values.
Notes
- lair.utils.geo.add_lat_ticks(ax: Axes, ylims: list[float], labelsize: int | None = None, more_ticks: int = 0) None [source]#
Add latitude ticks to the map.
- Parameters:
- axplt.Axes
Axes object
- ylimslist[float]
Latitude limits
- labelsizeint, optional
Font size of the labels, by default None
- more_ticksint, optional
Number of additional ticks, by default 0
- Returns:
- None
- lair.utils.geo.add_lon_ticks(ax: Axes, xlims: list[float], rotation: int = 0, labelsize: int | None = None, more_ticks: int = 0) None [source]#
Add longitude ticks to the map.
- Parameters:
- axplt.Axes
Axes object
- xlimslist[float]
Longitude limits
- rotationint, optional
Rotation of the labels, by default 0
- labelsizeint, optional
Font size of the labels, by default None
- more_ticksint, optional
Number of additional ticks, by default 0
- Returns:
- None
- lair.utils.geo.add_latlon_ticks(ax: Axes, extent: list[float], x_rotation: int = 0, labelsize: int | None = None, more_lon_ticks: int = 0, more_lat_ticks: int = 0) None [source]#
Add latitude and longitude ticks to the map.
- Parameters:
- axplt.Axes
Axes object
- extentlist[float]
Extent of the map. [minx, maxx, miny, maxy]
- x_rotationint, optional
Rotation of the longitude labels, by default 0
- labelsizeint, optional
Font size of the labels, by default None
- more_lon_ticksint, optional
Number of additional longitude ticks, by default 0
- more_lat_ticksint, optional
Number of additional latitude ticks, by default 0
- Returns:
- None
- lair.utils.geo.add_extent_map(fig: matplotlib.figure.Figure, main_extent: list[float], main_extent_crs: CRS, extent_map_rect: list[float], extent_map_extent: list[float], extent_map_crs: CRS, color: str, linewidth: int, zorder: int | None = None) Axes [source]#
Add an extent map to the figure.
TODO This needs better naming and documentation.
- Parameters:
- figmatplotlib.figure.Figure
Figure object
- main_extentlist[float]
Extent of the main map
- main_extent_crsccrs.CRS
CRS of the main extent
- extent_map_rectlist[float]
Rectangle of the extent map
- extent_map_extentlist[float]
Extent of the extent map
- extent_map_crsccrs.CRS
CRS of the extent map
- colorstr
Color of the extent map
- linewidthint
Line width of the extent map
- zorderint, optional
Zorder of the extent map, by default None
- Returns:
- plt.Axes
Axes object of the extent map
- class lair.utils.geo.BaseGrid(data, crs, **kwargs)[source]#
Base class for working with gridded data.
This class is a wrapper around xarray DataArray and Dataset objects, with additional methods for clipping, regridding, resampling, and reprojection. All operations are performed inplace, but return the grid object for chaining.
- property gridcell_area: DataArray#
Calculate the grid cell area in km^2.
- Returns:
- xr.DataArray
The grid cell area.
- clip(bbox: tuple[float, float, float, float] | None = None, extent: tuple[float, float, float, float] | None = None, geom: Polygon | None = None, crs: Any = None, **kwargs: Any) Self [source]#
Clip the data to the given bounds. Mopdifies the data in place. .. note:
The result can be slightly different between supplying a geom and a bbox/extent. Clipping with a geom seems to be exclusive of the bounds, while clipping with a bbox/extent seems to be inclusive of the bounds.
- Parameters:
- bboxtuple[minx, miny, maxx, maxy]
The bounding box to clip the data to.
- extenttuple[minx, maxx, miny, maxy]
The extent to clip the data to.
- geomshapely.Polygon
The geometry to clip the data to.
- crsAny
The CRS of the input geometries. If not provided, the CRS of the data is used.
- inplacebool, optional
Whether to modify the data in place, by default False.
- kwargsAny
Additional keyword arguments to pass to the rioxarray clip method.
- Returns:
- BaseGrid
The clipped grid
- regrid(out_grid: Dataset, method: Literal['bilinear', 'conservative', 'conservative_normed', 'nearest_s2d', 'nearest_d2s', 'patch'] = 'bilinear') Self [source]#
Regrid the data to a new grid. Uses xesmf for regridding. Modifies the data in place.
Note
At present, xesmf only supports regridding lat-lon grids. self.data must be on a lat-lon grid. Possibly could use xesmf.frontend.BaseRegridder to regrid to a generic grid.
Warning
xarray.Dataset.cf.add_bounds is known to have issues, including near the 180th meridian. Care should be taken when using this method, especially with global datasets.
- Parameters:
- out_gridxr.DataArray
The new grid to resample to. Must be a lat-lon grid.
- methodstr, optional
The regridding method, by default ‘bilinear’.
- Returns:
- BaseGrid
The regridded grid
- resample(resolution: float | tuple[float, float], regrid_method: Literal['bilinear', 'conservative', 'conservative_normed', 'nearest_s2d', 'nearest_d2s', 'patch'] = 'bilinear') Self [source]#
Resample the data to a new resolution. Modifies the data in place.
- Parameters:
- resolutionfloat | tuple[x_res, y_res]
The new resolution in degrees. If a single value is provided, the resolution is assumed to be the same in both dimensions.
- regrid_methodstr, optional
The regridding method, by default ‘bilinear’.
- Returns:
- BaseGrid
The resampled grid
- reproject(resolution: float | tuple[float, float], regrid_method: Literal['bilinear', 'conservative', 'conservative_normed', 'nearest_s2d', 'nearest_d2s', 'patch'] = 'bilinear') Self [source]#
Reproject the data to a lat lon rectilinear grid.
- Parameters:
- resolutionfloat | tuple[x_res, y_res]
The new resolution in degrees. If a single value is provided, the resolution is assumed to be the same in both dimensions.
- regrid_methodstr, optional
The regridding method, by default ‘bilinear’.
- Returns:
- BaseGrid
The reprojected grid
- lair.utils.geo.clip(data: DataArray | Dataset, bbox: list[float] | tuple[float, float, float, float] | None = None, extent: list[float] | tuple[float, float, float, float] | None = None, geom: Polygon | list[Polygon] | None = None, crs: Any = 'EPSG:4326', **kwargs: Any) DataArray | Dataset [source]#
Clip the data to the given bounds.
Note
The result can be slightly different between supplying a geom and a bbox/extent. Clipping with a geom seems to be exclusive of the outer bounds, while clipping with a bbox/extent seems to be inclusive of the outer bounds.
- Parameters:
- dataxr.DataArray | xr.Dataset
The data to clip.
- bboxtuple[minx, miny, maxx, maxy]
The bounding box to clip the data to.
- extenttuple[minx, maxx, miny, maxy]
The extent to clip the data to.
- geomshapely.Polygon
The geometry or geometries to clip the data to.
- crsAny, optional
The CRS of the input geometries. Default is ‘EPSG:4326’.
- kwargsAny
Additional keyword arguments to pass to the rioxarray clip method.
- Returns:
- xr.DataArray | xr.Dataset
The clipped data.
- lair.utils.geo.gridcell_area(grid: DataArray | Dataset, R: float | Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] | None = None) DataArray [source]#
Calculate the area of each grid cell in a grid.
Note
For lat-lon grids, xesmf.utils.grid_area is used to calculate the area, which requires the radius of the earth in kilometers. If the radius of the earth is not provided, it will be calculated based on the latitude.
- Parameters:
- gridxr.DataArray | xr.Dataset
Grid data. rioxarray coords must be set.
- Rfloat, optional
Radius of earth in kilometers, by default calculated based on the latitude.
- Returns:
- np.ndarray | xr.DataArray
grid-cell area in square-kilometers
- lair.utils.geo.plot_grid(grid: DataArray | Dataset, lw: float = 1, ax: Axes | None = None, extent: list[float] | None = None, crs: CRS | None = None, **kwargs: Any) Axes [source]#
Plot a grid.
- Parameters:
- gridxr.DataArray | xr.Dataset
The grid to plot.
- axplt.Axes, optional
Axes object to plot to, by default None.
- extentlist[minx, maxx, miny, maxy], optional
Extent of the plot, by default None.
- crsccrs.CRS, optional
CRS of the plot, by default None.
- kwargsAny
Additional keyword arguments to pass to the pcol or pcolormesh method.
- Returns:
- plt.Axes
Axes object
- lair.utils.geo.generate_regular_grid(xmin: float, xmax: float, dx: float, ymin: float, ymax: float, dy: float, x_label='x', y_label='y', chunks: dict | None = None) DataArray [source]#
Generate a regular grid. Grid points are cell centers.
- Parameters:
- xminfloat
x value of the left edge of the grid
- xmaxfloat
x value of the right edge of the grid
- dxfloat
x resolution
- yminfloat
y value of the bottom edge of the grid
- ymaxfloat
y value of the top edge of the grid
- dyfloat
y resolution
- x_labelstr, optional
Name of the x coordinate, by default ‘x’
- y_labelstr, optional
Name of the y coordinate, by default ‘y’
- Returns:
- xr.DataArray
The generated grid
- lair.utils.geo.regrid(data: DataArray | Dataset, out_grid: Dataset, method: Literal['bilinear', 'conservative', 'conservative_normed', 'nearest_s2d', 'nearest_d2s', 'patch'] = 'bilinear') DataArray | Dataset [source]#
Regrid data to a new grid. Uses xesmf for regridding.
Note
At present, xesmf only supports regridding lat-lon grids. self.data must be on a lat-lon grid. Possibly could use xesmf.frontend.BaseRegridder to regrid to a generic grid.
Warning
xarray.Dataset.cf.add_bounds is known to have issues, including near the 180th meridian. Care should be taken when using this method, especially with global datasets.
- Parameters:
- dataxr.DataArray | xr.Dataset
The data to regrid.
- out_gridxr.DataArray
The new grid to resample to. Must be a lat-lon grid.
- methodstr, optional
The regridding method, by default ‘bilinear’.
- Returns:
- xr.DataArray | xr.Dataset
The regridded data.
- lair.utils.geo.resample(data: DataArray | Dataset, resolution: float | tuple[float, float], regrid_method: Literal['bilinear', 'conservative', 'conservative_normed', 'nearest_s2d', 'nearest_d2s', 'patch'] = 'bilinear') DataArray | Dataset [source]#
Resample the data to a new resolution. Modifies the data in place.
- Parameters:
- dataxr.DataArray | xr.Dataset
The data to resample.
- resolutionfloat | tuple[x_res, y_res]
The new resolution in degrees. If a single value is provided, the resolution is assumed to be the same in both dimensions.
- regrid_methodstr, optional
The regridding method, by default ‘bilinear’.
- Returns:
- xr.DataArray | xr.Dataset
The resampled data.
- lair.utils.geo.round_latlon(data: DataArray | Dataset, lat_deci: int, lon_deci: int, lat_dim: str = 'lat', lon_dim: str = 'lon') Dataset [source]#
Round latitude and longitude values to a specified number of decimal places.
- Parameters:
- dataxr.DataArray | xr.Dataset
The data with lat/lon coordinates to round.
- lat_deciint
Number of decimal places to round latitude values to.
- lon_deciint
Number of decimal places to round longitude values to.
- lat_dimstr, optional
Name of the latitude dimension, by default ‘lat’.
- lon_dimstr, optional
Name of the longitude dimension, by default ‘lon’.
- Returns:
- xr.DataArray | xr.Dataset
The data with rounded lat/lon coordinates.
- lair.utils.geo.write_rio_crs(data: DataArray | Dataset, crs: Any) DataArray | Dataset [source]#
Write the CRS and coordinate system to the rioxarray accessor.
- Parameters:
- dataDataArray | Dataset
The data to write the CRS to.
- crsAny
The CRS to write to the data.
- Returns:
- DataArray | Dataset
The data with the CRS written to the rioxarray accessor.
- lair.utils.geo.cosine_weights(lats: ndarray) ndarray [source]#
Calculate cosine weights from latitude.
- Parameters:
- latsnp.ndarray
Latitude values
- Returns:
- np.ndarray
Cosine weighting
Examples
>>> ds: xr.Dataset >>> weights = cosine_weighting(ds.lat) >>> ds_weighted = ds.weighted(weights)
- lair.utils.geo.earth_radius(lat: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] [source]#
Calculate radius of Earth assuming oblate spheroid defined by WGS84
- Parameters:
- latarray-like
latitudes in degrees
- Returns:
- array-like
vector of radius in kilometers
Notes
- lair.utils.geo.gridcell_area_from_latlon(lat: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], lon: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], R: float | None = None) ndarray [source]#
Calculate the area of each grid cell in a lat-lon grid.
- Parameters:
- latArrayLike
Latitude array
- lonArrayLike
Longitude array
- Returns:
- np.ndarray
Grid-cell area in square-kilometers