Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADD: function to rescale reflectivity to a precipitation rate #1486

Merged
merged 11 commits into from
Nov 9, 2023
1 change: 1 addition & 0 deletions pyart/retrieve/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .qpe import est_rain_rate_za # noqa
from .qpe import est_rain_rate_zkdp # noqa
from .qpe import est_rain_rate_zpoly # noqa
from .qpe import ZtoR # noqa
from .qvp import quasi_vertical_profile # noqa
from .simple_moment_calculations import calculate_snr_from_reflectivity # noqa
from .simple_moment_calculations import calculate_velocity_texture # noqa
Expand Down
55 changes: 55 additions & 0 deletions pyart/retrieve/qpe.py
Original file line number Diff line number Diff line change
Expand Up @@ -684,3 +684,58 @@ def _coeff_ra_table():
coeff_ra_dict.update({"X": (45.5, 0.83)})

return coeff_ra_dict


def ZtoR(radar, ref_field="reflectivity", a=300, b=1.4, save_name="NWS_primary_prate"):
"""
Convert reflectivity (dBZ) to precipitation rate (mm/hr)

Author: Laura Tomkins

Parameters
----------
radar : Radar
Radar object used.
ref_field : str
Reflectivity field name to use to look up reflectivity data. In the
radar object. Default field name is 'reflectivity'. Units are expected
to be dBZ.
a : float
a value (coefficient) in the Z-R relationship
b: float
b value (exponent) in the Z-R relationship

Returns
-------
radar : Radar
The radar object containing the precipitation rate field

References
----------
American Meteorological Society, 2022: "Z-R relation". Glossary of Meteorology,
https://glossary.ametsoc.org/wiki/Z-r_relation

"""

# get reflectivity data
ref_data = radar.fields[ref_field]["data"]
ref_data = np.ma.masked_invalid(ref_data)

# convert to linear reflectivity
ref_linear = 10 ** (ref_data / 10)
precip_rate = (ref_linear / a) ** (1 / b)

# create dictionary
prate_dict = {
"data": precip_rate,
"standard_name": save_name,
"long_name": f"{save_name} rescaled from linear reflectivity",
"units": "mm/hr",
"valid_min": 0,
"valid_max": 10000,
}

# add field to radar object
radar.add_field(save_name, prate_dict, replace_existing=True)

return radar
16 changes: 16 additions & 0 deletions tests/retrieve/test_qpe.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,19 @@ def test_get_coeff_rkdp():

coeff_rkdp_use_x = pyart.retrieve.qpe._get_coeff_rkdp(13e9)
assert coeff_rkdp_use_x == (15.81, 0.7992)


def test_precip_rate():
grid = pyart.testing.make_storm_grid()
grid = pyart.retrieve.ZtoR(grid)

# check that field is in grid object
assert "NWS_primary_prate" in grid.fields.keys()

# Calculate the estimated value
correct = (
(10 ** (grid.fields["reflectivity"]["data"][0, 10, 10] / 10.0)) / 300.0
) ** (1 / 1.4)

# Check for correctness
assert_allclose(grid.fields["NWS_primary_prate"]["data"][0, 10, 10], correct)
Loading