Source code for shoot.grid
#!/usr/bin/env python3
"""
Grid utilities for computing spatial resolutions and window sizes
"""
import numpy as np
import xarray as xr
from . import geo as sgeo
from . import meta as smeta
[docs]
def get_dx_dy(da, dx=None, dy=None):
"""Compute local grid resolution in meters
Parameters
----------
da : xarray.DataArray
Data array with longitude and latitude coordinates.
dx : xarray.DataArray, optional
X resolution in meters. Computed if not provided.
dy : xarray.DataArray, optional
Y resolution in meters. Computed if not provided.
Returns
-------
dx : xarray.DataArray
Resolution along X in meters.
dy : xarray.DataArray
Resolution along Y in meters.
"""
if dx is not None and dy is not None:
return dx, dy
lon = smeta.get_lon(da)
lat = smeta.get_lat(da)
lat2d, lon2d = xr.broadcast(lat, lon)
dlonx = np.gradient(lon2d.values, axis=-1)
dlony = np.gradient(lon2d.values, axis=-2)
dlatx = np.gradient(lat2d.values, axis=-1)
dlaty = np.gradient(lat2d.values, axis=-2)
# cf = smeta.get_cf_specs()
if dx is None:
dx = sgeo.deg2m(dlonx, lat2d.values) ** 2
dx += sgeo.deg2m(dlatx) ** 2
dx = np.sqrt(dx)
dx = xr.DataArray(dx, dims=lon2d.dims, coords=lon2d.coords, name="dx", attrs={"units": "m"})
if dy is None:
dy = sgeo.deg2m(dlony, lat2d.values) ** 2
dy += sgeo.deg2m(dlaty) ** 2
dy = np.sqrt(dy)
dy = xr.DataArray(dy, dims=lon2d.dims, coords=lon2d.coords, name="dy", attrs={"units": "m"})
return dx, dy
[docs]
def get_wx_wy(window, dx, dy):
"""Convert window size from km to grid points
Parameters
----------
window : float
Window size in kilometers.
dx : float or xarray.DataArray
Grid resolution along X in meters.
dy : float or xarray.DataArray
Grid resolution along Y in meters.
Returns
-------
wx : int
Window width in grid points (odd number).
wy : int
Window height in grid points (odd number).
"""
dx = np.nanmean(dx)
dy = np.nanmean(dy)
wx = 2 * (int(np.ceil(window * 1e3 / dx)) // 2) + 1
wy = 2 * (int(np.ceil(window * 1e3 / dy)) // 2) + 1
return wx, wy