Source code for wradlib.trafo

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Copyright (c) 2011-2023, wradlib developers.
# Distributed under the MIT License. See LICENSE.txt for more info.

"""
Data Transformation
^^^^^^^^^^^^^^^^^^^

Module <trafo> transforms data e.g. from RVP-units
to dBZ-values to Z-values and vice versa.

.. currentmodule:: wradlib.trafo

.. autosummary::
   :nosignatures:
   :toctree: generated/

   {}
"""
__all__ = [
    "rvp_to_dbz",
    "decibel",
    "idecibel",
    "r_to_depth",
    "kdp_to_r",
    "si_to_kmh",
    "si_to_mph",
    "si_to_kts",
    "kmh_to_si",
    "mph_to_si",
    "kts_to_si",
    "KuBandToS",
    "KuBandToX",
    "SBandToKu",
    "TrafoMethods",
]
__doc__ = __doc__.format("\n   ".join(__all__))

from dataclasses import dataclass

import numpy as np

from wradlib import util

# CONSTANTS
meters_per_mile = 1609.344
meters_per_nautical_mile = 1852.0


[docs]@dataclass(init=False, repr=False, eq=False) class SBandToKu: """Class to hold coefficients for Radar Reflectivity Conversion From S-band (2.8GHz) to Ku-band (13.8GHz) See :cite:`Liao2009` for reference. """ snow = np.array([0.185074, 1.01378, -0.00189212]) rain = np.array([-1.50393, 1.07274, 0.000165393])
[docs]@dataclass(init=False, repr=False, eq=False) class KuBandToS: """Class to hold coefficients for Radar Reflectivity Conversion From Ku-band (13.8 GHz) to S-band (2.8 GHz) See :cite:`Cao2013` for reference. """ # Rain 90% 80% 70% 60% 50% 40% 30% 20% 10% Snow snow = np.array( [ [ 4.78e-2, 4.12e-2, 8.12e-2, 1.59e-1, 2.87e-1, 4.93e-1, 8.16e-1, 1.31e0, 2.01e0, 2.82e0, 1.74e-1, ], [ 1.23e-2, 3.66e-3, 2.00e-3, 9.42e-4, 5.29e-4, 5.96e-4, 1.22e-3, 2.11e-3, 3.34e-3, 5.33e-3, 1.35e-2, ], [ -3.50e-4, 1.17e-3, 1.04e-3, 8.16e-4, 6.59e-4, 5.85e-4, 6.13e-4, 7.01e-4, 8.24e-4, 1.01e-3, -1.38e-3, ], [ -3.30e-5, -8.08e-5, -6.44e-5, -4.97e-5, -4.15e-5, -3.89e-5, -4.15e-5, -4.58e-5, -5.06e-5, -5.78e-5, 4.74e-5, ], [ 4.27e-7, 9.25e-7, 7.41e-7, 6.13e-7, 5.80e-7, 6.16e-7, 7.12e-7, 8.22e-7, 9.39e-7, 1.10e-6, 0.00e0, ], ] ) # Rain 90% 80% 70% 60% 50% 40% 30% 20% 10% Hail hail = np.array( [ [ 4.78e-2, 1.80e-1, 1.95e-1, 1.88e-1, 2.36e-1, 2.70e-1, 2.98e-1, 2.85e-1, 1.75e-1, 4.30e-2, 8.80e-2, ], [ 1.23e-2, -3.73e-2, -3.83e-2, -3.29e-2, -3.46e-2, -2.94e-2, -2.10e-2, -9.96e-3, -8.05e-3, -8.27e-3, 5.39e-2, ], [ -3.50e-4, 4.08e-3, 4.14e-3, 3.75e-3, 3.71e-3, 3.22e-3, 2.44e-3, 1.45e-3, 1.21e-3, 1.66e-3, -2.99e-4, ], [ -3.30e-5, -1.59e-4, -1.54e-4, -1.39e-4, -1.30e-4, -1.12e-4, -8.56e-5, -5.33e-5, -4.66e-5, -7.19e-5, 1.90e-5, ], [ 4.27e-7, 1.59e-6, 1.51e-6, 1.37e-6, 1.29e-6, 1.15e-6, 9.40e-7, 6.71e-7, 6.33e-7, 9.52e-7, 0.00e0, ], ] )
[docs]@dataclass(init=False, repr=False, eq=False) class KuBandToX: """Class to hold coefficients for Radar Reflectivity Conversion From Ku-band (13.8 GHz) to X-band (9.4 GHz) See :cite:`Pejcic2022` for reference. """ # Rain Snow snow = np.array( [ [ 1.91e-1, -1.2e-1, ], [ -7.83e-2, 6.8e-2, ], [ 1.12e-2, -4.55e-3, ], [ -6.17e-4, 1.18e-4, ], [ 1.25e-5, -6.6e-7, ], [ -8.43e-8, 0.0, ], ] ) # Rain Hail hail = np.array( [ [ 1.91e-1, 5.57e-2, ], [ -7.83e-2, 1.8e-2, ], [ 1.12e-2, 1.91e-3, ], [ -6.17e-4, -6.64e-5, ], [ 1.25e-5, 8.18e-7, ], [ -8.43e-8, 0.0, ], ] )
[docs]def rvp_to_dbz(x): """Calculates dBZ-values from DWD RVP6 values as given in DX-product files. Parameters ---------- x : float or :class:`numpy:numpy.ndarray` a number or an array Examples -------- >>> from wradlib.trafo import rvp_to_dbz >>> print(rvp_to_dbz(65.)) 0.0 """ return x * 0.5 - 32.5
[docs]def decibel(x): """Calculates the decibel representation of the input values :math:`dBZ=10 \\cdot \\log_{10} z` Parameters ---------- x : float or :class:`numpy:numpy.ndarray` (must not be <= 0.) Examples -------- >>> from wradlib.trafo import decibel >>> print(decibel(100.)) 20.0 """ return 10.0 * np.log10(x)
[docs]def idecibel(x): """Calculates the inverse of input decibel values :math:`z=10^{x \\over 10}` Parameters ---------- x : float or :class:`numpy:numpy.ndarray` Examples -------- >>> from wradlib.trafo import idecibel >>> print(idecibel(10.)) 10.0 """ return 10.0 ** (x / 10.0)
[docs]def r_to_depth(x, interval): """Computes rainfall depth (mm) from rainfall intensity (mm/h) Parameters ---------- x : float or :class:`numpy:numpy.ndarray` rainfall intensity in mm/h interval : float time interval (s) the values of `x` represent Returns ------- output : float or :class:`numpy:numpy.ndarray` rainfall depth (mm) """ return x * interval / 3600.0
[docs]def kdp_to_r(kdp, f, a=129.0, b=0.85): """Estimating rainfall intensity directly from specific differential phase. The general power law expression has been suggested by :cite:`Ryzhkov2005`. The default parameters have been set according to :cite:`Bringi2001`. Note ---- **Please note that this way, rainfall intensities can become negative.** This is an intended behaviour in order to account for noisy :math:`K_{DP}` values. Parameters ---------- kdp : float or :class:`numpy:numpy.ndarray` :math:`K_{DP}` as array of floats f : float radar frequency [GHz] - Standard frequencies in X-band range between 8.0 and 12.0 GHz, - Standard frequencies in C-band range between 4.0 and 8.0 GHz, - Standard frequencies in S-band range between 2.0 and 4.0 GHz. a : float linear coefficient of the power law b : float exponent of the power law Returns ------- output : :class:`numpy:numpy.ndarray` array of rainfall intensity """ return np.sign(kdp) * a * (np.abs(kdp) / f) ** b
[docs]def si_to_kmh(vals): """Conversion from SI wind speed units to km/hr. Note ---- Code was migrated from https://github.com/nguy/PyRadarMet. Parameters ---------- vals : float or :class:`numpy:numpy.ndarray` Speed in SI units (m/s) Returns ------- output: float or :class:`numpy:numpy.ndarray` Speed in km/hr Examples -------- >>> from wradlib.trafo import si_to_kmh >>> print(si_to_kmh(1.)) 3.6 """ return vals * 3600.0 / 1000.0
[docs]def si_to_mph(vals): """Conversion from SI wind speed units to miles/hr Note ---- Code was migrated from https://github.com/nguy/PyRadarMet. Parameters ---------- vals : float or :class:`numpy:numpy.ndarray` Speed in SI units (m/s) Returns ------- output: float or :class:`numpy:numpy.ndarray` Speed in miles per hour Examples -------- >>> from wradlib.trafo import si_to_mph >>> print(np.round(si_to_mph(1.), 3)) 2.237 """ return vals * 3600.0 / meters_per_mile
[docs]def si_to_kts(vals): """Conversion from SI wind speed units to knots Note ---- Code was migrated from https://github.com/nguy/PyRadarMet. Parameters ---------- vals : float or :class:`numpy:numpy.ndarray` Speed in SI units (m/s) Returns ------- output: float or :class:`numpy:numpy.ndarray` Speed in knots Examples -------- >>> from wradlib.trafo import si_to_kts >>> print(np.round(si_to_kts(1.), 3)) 1.944 """ return vals * 3600.0 / meters_per_nautical_mile
[docs]def kmh_to_si(vals): """Conversion from km/hr to SI wind speed units Note ---- Code was migrated from https://github.com/nguy/PyRadarMet. Parameters ---------- vals: float or :class:`numpy:numpy.ndarray` Wind speed in km/hr Returns ------- output: float or :class:`numpy:numpy.ndarray` Wind speed in SI units (m/s) Examples -------- >>> from wradlib.trafo import kmh_to_si >>> print(np.round(kmh_to_si(10.), 3)) 2.778 """ return vals * 1000.0 / 3600.0
[docs]def mph_to_si(vals): """Conversion from miles/hr to SI wind speed units Note ---- Code was migrated from https://github.com/nguy/PyRadarMet. Parameters ---------- vals: float or :class:`numpy:numpy.ndarray` Wind speed in miles per hour Returns ------- output: float or :class:`numpy:numpy.ndarray` Wind speed in SI units (m/s) Examples -------- >>> from wradlib.trafo import mph_to_si >>> print(np.round(mph_to_si(10.), 2)) 4.47 """ return vals * meters_per_mile / 3600.0
[docs]def kts_to_si(vals): """Conversion from knots to SI wind speed units Note ---- Code was migrated from https://github.com/nguy/PyRadarMet. Parameters ---------- vals: float or :class:`numpy:numpy.ndarray` Wind speed in knots Returns ------- output: float or :class:`numpy:numpy.ndarray` Wind speed in SI units (m/s) Examples -------- >>> from wradlib.trafo import kts_to_si >>> print(np.round(kts_to_si(1.), 3)) 0.514 """ return vals * meters_per_nautical_mile / 3600.0
[docs]class TrafoMethods(util.XarrayMethods): """wradlib xarray SubAccessor methods for DualPol."""
[docs] @util.docstring(decibel) def decibel(self): if not isinstance(self, TrafoMethods): return self.pipe(decibel) else: return self._obj.pipe(decibel)
[docs] @util.docstring(idecibel) def idecibel(self): if not isinstance(self, TrafoMethods): return self.pipe(idecibel) else: return self._obj.pipe(idecibel)
[docs] @util.docstring(r_to_depth) def r_to_depth(self, *args, **kwargs): if not isinstance(self, TrafoMethods): return self.pipe(r_to_depth, *args, **kwargs) else: return self._obj.pipe(r_to_depth, *args, **kwargs)
if __name__ == "__main__": print("wradlib: Calling module <trafo> as main...")