Source code for wradlib.georef.xarray
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Copyright (c) 2011-2023, wradlib developers.
# Distributed under the MIT License. See LICENSE.txt for more info.
"""
Xarray Functions
^^^^^^^^^^^^^^^^
.. autosummary::
:nosignatures:
:toctree: generated/
{}
"""
__all__ = ["as_xarray_dataarray", "create_xarray_dataarray"]
__doc__ = __doc__.format("\n ".join(__all__))
import collections
import numpy as np
import xarray as xr
from wradlib.util import import_optional
osr = import_optional("osgeo.osr")
[docs]def as_xarray_dataarray(data, dims, coords):
"""Create Xarray DataArray from NumPy Array
.. versionadded:: 1.3
Parameters
----------
data : :class:`numpy:numpy.ndarray`
data array
dims : dict
dictionary describing xarray dimensions
coords : dict
dictionary describing xarray coordinates
Returns
-------
dataset : :py:class:`xarray:xarray.DataArray`
DataArray
"""
da = xr.DataArray(data, coords=dims.values(), dims=dims.keys())
da = da.assign_coords(**coords)
return da
[docs]def create_xarray_dataarray(
data,
*,
r=None,
phi=None,
theta=None,
site=None,
sweep_mode="azimuth_surveillance",
rf=1.0,
**kwargs,
):
"""Create Xarray DataArray from Polar Radar Data
.. versionadded:: 1.3
Parameters
----------
data : :class:`numpy:numpy.ndarray`
The data array. It is assumed that the first dimension is over
the azimuth angles, while the second dimension is over the range bins
r : :class:`numpy:numpy.ndarray`
The ranges. Units may be chosen arbitrarily, m preferred.
phi : :class:`numpy:numpy.ndarray`
The azimuth angles in degrees.
theta : :class:`numpy:numpy.ndarray`
The elevation angles in degrees.
site : tuple
Coordinates of the radar site.
sweep_mode : str
Defaults to 'azimuth_surveillance'.
rf : float
factor to scale range, defaults to 1. (no scale)
Keyword Arguments
-----------------
re : float
effective earth radius
ke : float
adjustment factor to account for the refractivity gradient that
affects radar beam propagation. Defaults to 4/3.
dim0 : str
Name of the first dimension. Defaults to 'azimuth'.
dim1 : str
Name of the second dimension. Defaults to 'range'.
Returns
-------
dataset : :py:class:`xarray:xarray.DataArray`
DataArray
"""
# check coordinate tuple
if site and len(site) < 3:
raise ValueError(
"`site` need to be a sequence of coordinates "
"`longitude`, `latitude`, `altitude`."
)
if phi is None:
if sweep_mode == "azimuth_surveillance":
phi = np.arange(data.shape[0], dtype=np.float_)
phi += (phi[1] - phi[0]) / 2.0
else:
phi = 0.0
if r is None:
r = np.arange(data.shape[1], dtype=np.float_)
r += (r[1] - r[0]) / 2.0
if theta is None:
if sweep_mode == "rhi":
theta = np.arange(data.shape[0], dtype=np.float_)
theta += (theta[1] - theta[0]) / 2.0
else:
theta = 0.0
if np.isscalar(theta):
theta = np.ones_like(phi) * theta
if np.isscalar(phi):
phi = np.ones_like(theta) * phi
r = r.copy()
phi = phi.copy()
theta = theta.copy()
if site is None:
site = (0.0, 0.0, 0.0)
dims = collections.OrderedDict()
dim0 = kwargs.pop("dim0", "azimuth")
dim1 = kwargs.pop("dim1", "range")
ang = theta if sweep_mode == "rhi" else phi
dims[dim0] = np.arange(ang.shape[0])
dims[dim1] = r / rf
coords = {
"azimuth": ([dim0], phi),
"elevation": ([dim0], theta),
"longitude": (site[0]),
"latitude": (site[1]),
"altitude": (site[2]),
"sweep_mode": sweep_mode,
}
# create xarray dataarray
da = as_xarray_dataarray(data, dims=dims, coords=coords)
return da