Source code for pyrad.proc.process_retrieve

"""
pyrad.proc.process_retrieve
===========================

Functions for retrieving new moments and products

.. autosummary::
    :toctree: generated/

    process_ccor
    process_signal_power
    process_rcs_pr
    process_rcs
    process_vol_refl
    process_refl_from_zdr
    process_snr
    process_radial_noise_hs
    process_radial_noise_ivic
    process_l
    process_cdr
    process_vpr
    process_rainrate
    process_rainfall_accumulation
    process_bird_density


"""

import datetime
from copy import deepcopy
from warnings import warn

import numpy as np

import pyart

from ..io.io_aux import get_datatype_fields, get_fieldname_pyart
from ..io.io_aux import get_file_list
from ..io.read_data_radar import interpol_field
from ..io.read_data_other import read_rhi_profile, read_vpr_theo_parameters

from ..util.radar_utils import time_avg_range


[docs] def process_ccor(procstatus, dscfg, radar_list=None): """ Computes the Clutter Correction Ratio, i.e. the ratio between the signal without Doppler filtering and the signal with Doppler filtering Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : list of string. Dataset keyword The input data types, must contain, "dBZ" or "dBZv", and, "dBuZ", or "dBuZV" radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "CCORh" or "CCORv" (if vertical reflectivities were provided) ind_rad : int radar index """ if procstatus != 1: return None, None for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("dBZ", "dBZv"): filt_field = get_fieldname_pyart(datatype) elif datatype in ("dBuZ", "dBuZv"): unfilt_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if filt_field not in radar.fields or unfilt_field not in radar.fields: warn("Unable to compute CCOR. Missing fields") return None, None ccor_field = "clutter_correction_ratio_hh" if "vv" in filt_field: ccor_field = "clutter_correction_ratio_vv" ccor = pyart.retrieve.compute_ccor( radar, filt_field=filt_field, unfilt_field=unfilt_field, ccor_field=ccor_field ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field(ccor_field, ccor) return new_dataset, ind_rad
[docs] def process_signal_power(procstatus, dscfg, radar_list=None): """ Computes the signal power in dBm Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : list of string. Dataset keyword The input data types, must contain, "dBZ" or "dBuZ" or "dBZc" or "dBuZc" or "dBZv" or "dBuZv" or "dBuZvc" mflossh, mflossv : float. Dataset keyword The matching filter losses of the horizontal (vertical) channel [dB]. If None it will be obtained from the attribute radar_calibration of the radar object. Defaults to 0 radconsth, radconstv : float. Dataset keyword The horizontal (vertical) channel radar constant. If None it will be obtained from the attribute radar_calibration of the radar object lrxh, lrxv : float. Global keyword The horizontal (vertical) receiver losses from the antenna feed to the reference point. [dB] positive value. Default 0 lradomeh, lradomev : float. Global keyword The 1-way dry radome horizontal (vertical) channel losses. [dB] positive value. Default 0. attg : float. Dataset keyword The gas attenuation [dB/km]. If none it will be obtained from the attribute radar_calibration of the radar object or assigned according to the radar frequency. Defaults to 0. radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "dBm" or "dBmv" (if vert. refl. was provided) ind_rad : int radar index """ if procstatus != 1: return None, None for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("dBZ", "dBuZ", "dBZc", "dBuZc", "dBZv", "dBuZv", "dBuZvc"): refl_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if refl_field not in radar.fields: warn("Unable to obtain signal power. Missing field " + refl_field) return None, None lrx = 0.0 lradome = 0.0 if refl_field.endswith("_vv"): pwr_field = "signal_power_vv" lmf = dscfg.get("mflossv", None) radconst = dscfg.get("radconstv", None) if "lrxv" in dscfg: lrx = dscfg["lrxv"][ind_rad] if "lradomev" in dscfg: lradome = dscfg["lradomev"][ind_rad] else: pwr_field = "signal_power_hh" lmf = dscfg.get("mflossh", None) radconst = dscfg.get("radconsth", None) if "lrxh" in dscfg: lrx = dscfg["lrxh"][ind_rad] if "lradomeh" in dscfg: lradome = dscfg["lradomeh"][ind_rad] attg = dscfg.get("attg", None) s_pwr = pyart.retrieve.compute_signal_power( radar, lmf=lmf, attg=attg, radconst=radconst, lrx=lrx, lradome=lradome, refl_field=refl_field, pwr_field=pwr_field, ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field(pwr_field, s_pwr) return new_dataset, ind_rad
[docs] def process_rcs_pr(procstatus, dscfg, radar_list=None): """ Computes the radar cross-section (assuming a point target) from radar reflectivity by first computing the received power and then the RCS from it. Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : list of string. Dataset keyword The input data types, must contain, "dBZ" or "dBuZ" or "dBZc" or "dBuZc" or "dBZv" or "dBuZv" or "dBuZvc" AntennaGainH, AntennaGainV : float. Dataset keyword The horizontal (vertical) polarization antenna gain [dB]. If None it will be obtained from the attribute instrument_parameters of the radar object txpwrh, txpwrv : float. Dataset keyword The transmitted power of the horizontal (vertical) channel [dBm]. If None it will be obtained from the attribute radar_calibration of the radar object mflossh, mflossv : float. Dataset keyword The matching filter losses of the horizontal (vertical) channel [dB]. If None it will be obtained from the attribute radar_calibration of the radar object. Defaults to 0 radconsth, radconstv : float. Dataset keyword The horizontal (vertical) channel radar constant. If None it will be obtained from the attribute radar_calibration of the radar object lrxh, lrxv : float. Global keyword The horizontal (vertical) receiver losses from the antenna feed to the reference point. [dB] positive value. Default 0 ltxh, ltxv : float. Global keyword The horizontal (vertical) transmitter losses from the output of the high power amplifier to the antenna feed. [dB] positive value. Default 0 lradomeh, lradomev : float. Global keyword The 1-way dry radome horizontal (vertical) channel losses. [dB] positive value. Default 0. attg : float. Dataset keyword The gas attenuation [dB/km]. If none it will be obtained from the attribute radar_calibration of the radar object or assigned according to the radar frequency. Defaults to 0. radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "rcs_h" or "rcs_v" (if vert. refl. were provided) ind_rad : int radar index """ if procstatus != 1: return None, None for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("dBZ", "dBuZ", "dBZc", "dBuZc", "dBZv", "dBuZv", "dBuZvc"): refl_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if refl_field not in radar.fields: warn("Unable to obtain RCS. Missing field " + refl_field) return None, None lrx = 0.0 lradome = 0.0 ltx = 0.0 if refl_field.endswith("_vv"): rcs_field = "radar_cross_section_vv" lmf = dscfg.get("mflossv", None) radconst = dscfg.get("radconstv", None) antenna_gain = dscfg.get("AntennaGainH", None) tx_pwr = dscfg.get("txpwrv", None) if "lrxv" in dscfg: lrx = dscfg["lrxv"][ind_rad] if "ltxv" in dscfg: ltx = dscfg["ltxv"][ind_rad] if "lradomev" in dscfg: lradome = dscfg["lradomev"][ind_rad] else: rcs_field = "radar_cross_section_hh" lmf = dscfg.get("mflossh", None) radconst = dscfg.get("radconsth", None) antenna_gain = dscfg.get("AntennaGainV", None) tx_pwr = dscfg.get("txpwrh", None) if "lrxh" in dscfg: lrx = dscfg["lrxh"][ind_rad] if "ltxh" in dscfg: ltx = dscfg["ltxh"][ind_rad] if "lradomeh" in dscfg: lradome = dscfg["lradomeh"][ind_rad] attg = dscfg.get("attg", None) rcs_dict = pyart.retrieve.compute_rcs_from_pr( radar, lmf=lmf, attg=attg, radconst=radconst, tx_pwr=tx_pwr, antenna_gain=antenna_gain, lrx=lrx, ltx=ltx, lradome=lradome, refl_field=refl_field, rcs_field=rcs_field, ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field(rcs_field, rcs_dict) return new_dataset, ind_rad
[docs] def process_rcs(procstatus, dscfg, radar_list=None): """ Computes the radar cross-section (assuming a point target) from radar reflectivity. Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : list of string. Dataset keyword The input data types, must contain, "dBZ" or "dBuZ" or "dBZc" or "dBuZc" or "dBZv" or "dBuZv" or "dBuZvc" kw2 : float. Dataset keyowrd The water constant pulse_width : float. Dataset keyowrd The pulse width [s] beamwidthv : float. Global keyword The vertical polarization antenna beamwidth [deg]. Used if input is vertical reflectivity beamwidthh : float. Global keyword The horizontal polarization antenna beamwidth [deg]. Used if input is horizontal reflectivity radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "rcs_h" or "rcs_v" (if vert. refl. were provided) ind_rad : int radar index """ if procstatus != 1: return None, None for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("dBZ", "dBuZ", "dBZc", "dBuZc", "dBZv", "dBuZv", "dBuZvc"): refl_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if refl_field not in radar.fields: warn("Unable to obtain RCS. Missing field " + refl_field) return None, None if refl_field.endswith("_vv"): rcs_field = "radar_cross_section_vv" beamwidth = dscfg.get("beamwidthv", None) else: rcs_field = "radar_cross_section_hh" beamwidth = dscfg.get("beamwidthh", None) pulse_width = dscfg.get("PulseWidth", None) kw2 = dscfg.get("kw2", 0.93) rcs_dict = pyart.retrieve.compute_rcs( radar, kw2=kw2, pulse_width=pulse_width, beamwidth=beamwidth, refl_field=refl_field, rcs_field=rcs_field, ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field(rcs_field, rcs_dict) return new_dataset, ind_rad
[docs] def process_vol_refl(procstatus, dscfg, radar_list=None): """ Computes the volumetric reflectivity eta in 10log10(cm^2 km^-3) Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : list of string. Dataset keyword The input data types, must contain, "dBZ", "dBuZ", "dBZc", "dBuZc", "dBZv", "dBZvc" "dBuZv", or "dBuZvc" freq : float. Dataset keyword The radar frequency kw : float. Dataset keyword The water constant radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "eta_h" or "eta_v" (if vert. refl. were provided) ind_rad : int radar index """ if procstatus != 1: return None, None for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ( "dBZ", "dBuZ", "dBZc", "dBuZc", "dBZv", "dBuZv", "dBZvc", "dBuZvc", ): refl_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if refl_field not in radar.fields: warn("Unable to obtain signal power. Missing field " + refl_field) return None, None if refl_field.endswith("_vv"): vol_refl_field = "volumetric_reflectivity_vv" else: vol_refl_field = "volumetric_reflectivity" freq = dscfg.get("freq", None) kw = dscfg.get("kw", None) vol_refl_dict = pyart.retrieve.compute_vol_refl( radar, kw=kw, freq=freq, refl_field=refl_field, vol_refl_field=vol_refl_field ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field(vol_refl_field, vol_refl_dict) return new_dataset, ind_rad
[docs] def process_refl_from_zdr(procstatus, dscfg, radar_list=None): """ Computes the vertical or horizontal reflectivity from ZDR and the reflectivity at the orthogonal polarization Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : list of string. Dataset keyword The input data types, must contain, "ZDR", or "ZDRc", or "ZDRu and "dBZ", "dBuZ", "dBZc", "dBuZc", "dBZv", "dBZvc" "dBuZv", or "dBuZvc" radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field: "dBZv" if "ZDR" and "dBZ" were provided "dBZ" if "ZDR" and "dBZv" were provided "dBZvc" if "ZDRc" and "dBZc" were provided "dBZv" if "ZDRc" and "dBZvc" were provided "dBuZ" if "ZDRu" and "dBuZ" were provided "dBuZv" if "ZDRu" and "dBuZv" were provided ind_rad : int radar index """ if procstatus != 1: return None, None for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ( "dBZ", "dBuZ", "dBZc", "dBuZc", "dBZv", "dBuZv", "dBZvc", "dBuZvc", ): refl_field = get_fieldname_pyart(datatype) if datatype in ("ZDR", "uZDR", "ZDRc"): zdr_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if refl_field not in radar.fields: warn("Unable to obtain reflectivity. Missing field " + refl_field) return None, None if zdr_field not in radar.fields: warn("Unable to obtain reflectivity. Missing field " + zdr_field) return None, None if refl_field.endswith("_vv"): ort_refl_field = "reflectivity" else: ort_refl_field = "reflectivity_vv" if "unfiltered" in zdr_field: ort_refl_field = "unfiltered" + ort_refl_field if "corrected" in zdr_field: ort_refl_field = "corrected_" + ort_refl_field ort_refl_dict = pyart.retrieve.compute_refl_from_zdr( radar, zdr_field=zdr_field, refl_field=refl_field, ort_refl_field=ort_refl_field ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field(ort_refl_field, ort_refl_dict) return new_dataset, ind_rad
[docs] def process_snr(procstatus, dscfg, radar_list=None): """ Computes SNR Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : string. Dataset keyword The input data type, must contain, "dBZ" or "dBuZ" or "dBZv" or "dBuZv", and, "Nh" or "Nv" output_type : string. Dataset keyword The output data type. Either SNRh or SNRv radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "SNRh" or "SNRv" (if vert. refl. were provided) ind_rad : int radar index """ if procstatus != 1: return None, None for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("dBZ", "dBuZ", "dBZv", "dBuZv"): refl = get_fieldname_pyart(datatype) elif datatype in ("Nh", "Nv"): noise = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if (refl not in radar.fields) or (noise not in radar.fields): warn("Unable to compute SNR. Missing data") return None, None output_type = dscfg.get("output_type", "SNRh") if output_type == "SNRh": snr_field = "signal_to_noise_ratio_hh" else: snr_field = "signal_to_noise_ratio_vv" snr = pyart.retrieve.compute_snr( radar, refl_field=refl, noise_field=noise, snr_field=snr_field ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field(snr_field, snr) return new_dataset, ind_rad
[docs] def process_radial_noise_hs(procstatus, dscfg, radar_list=None): """ Computes the radial noise from the signal power using the Hildebrand and Sekhon 1974 method Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : string. Dataset keyword The input data type, must contain, "dBm" or "dBmv" rmin : float. Dataset keyword The minimum range from which to start the computation nbins_min : int. Dataset keyword The minimum number of noisy gates to consider the estimation valid max_std_pwr : float. Dataset keyword The maximum standard deviation of the noise power to consider the estimation valid get_noise_pos : bool. Dataset keyword If True a field flagging the position of the noisy gets will be returned radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "NdBmh" and "noise_pos_h" or "NdBmh" and "noise_pos_v" (if vert. refl. were provided) ind_rad : int radar index """ if procstatus != 1: return None, None radarnr, _, datatype, _, _ = get_datatype_fields(dscfg["datatype"][0]) pwr_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if pwr_field not in radar.fields: warn("Unable to compute radial noise. Missing signal power") return None, None # user values rmin = dscfg.get("rmin", 10000.0) nbins_min = dscfg.get("nbins_min", 50) max_std_pwr = dscfg.get("max_std_pwr", 2.0) get_noise_pos = dscfg.get("get_noise_pos", False) if "hh" in pwr_field: noise_field = "noisedBm_hh" noise_pos_field = "noise_pos_h" else: noise_field = "noisedBm_vv" noise_pos_field = "noise_pos_v" ind_rmin = np.where(radar.range["data"] >= rmin)[0] if ind_rmin.size == 0: warn("No data at ranges further than rmin " + str(rmin) + " m.") return None, None ind_rmin = ind_rmin[0] noise, noise_pos = pyart.retrieve.compute_radial_noise_hs( radar, ind_rmin=ind_rmin, nbins_min=nbins_min, max_std_pwr=max_std_pwr, pwr_field=pwr_field, noise_field=noise_field, get_noise_pos=get_noise_pos, ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field(noise_field, noise) if noise_pos is not None: new_dataset["radar_out"].add_field(noise_pos_field, noise_pos) return new_dataset, ind_rad
[docs] def process_radial_noise_ivic(procstatus, dscfg, radar_list=None): """ Computes the radial noise from the signal power using the Ivic 2013 method Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : string. Dataset keyword The input data type, must contain, "dBm" or "dBmv" npulses_ray : int Default number of pulses used in the computation of the ray. If the number of pulses is not in radar.instrument_parameters this will be used instead. Default 30 ngates_min: int minimum number of gates with noise to consider the retrieval valid. Default 800 iterations: int number of iterations in step 7. Default 10. get_noise_pos : bool If true an additional field with gates containing noise according to the algorithm is produced radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "NdBmh" and "noise_pos_h" or "NdBmh" and "noise_pos_v" (if vert. refl. were provided) ind_rad : int radar index """ if procstatus != 1: return None, None radarnr, _, datatype, _, _ = get_datatype_fields(dscfg["datatype"][0]) pwr_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if pwr_field not in radar.fields: warn("Unable to compute radial noise. Missing signal power") return None, None # user values npulses_ray = dscfg.get("npulses_ray", 30) ngates_min = dscfg.get("ngates_min", 800) iterations = dscfg.get("iterations", 10) get_noise_pos = dscfg.get("get_noise_pos", False) if "hh" in pwr_field: noise_field = "noisedBm_hh" noise_pos_field = "noise_pos_h" else: noise_field = "noisedBm_vv" noise_pos_field = "noise_pos_v" noise, noise_pos = pyart.retrieve.compute_radial_noise_ivic( radar, npulses_ray=npulses_ray, ngates_min=ngates_min, iterations=iterations, pwr_field=pwr_field, noise_field=noise_field, get_noise_pos=get_noise_pos, ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field(noise_field, noise) if noise_pos is not None: new_dataset["radar_out"].add_field(noise_pos_field, noise_pos) return new_dataset, ind_rad
[docs] def process_l(procstatus, dscfg, radar_list=None): """ Computes L parameter (logarithmic cross-correlation ratio) Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : string. Dataset keyword The input data type, must contain, "RhoHV" or "RhoHVc" or "uRhoHV" radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "L" ind_rad : int radar index """ if procstatus != 1: return None, None radarnr, _, datatype, _, _ = get_datatype_fields(dscfg["datatype"]) rhohv = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if rhohv not in radar.fields: print("Unable to compute L. Missing RhoHV field") return None, None comp_l = pyart.retrieve.compute_l( radar, rhohv_field=rhohv, l_field="logarithmic_cross_correlation_ratio" ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field("logarithmic_cross_correlation_ratio", comp_l) return new_dataset, ind_rad
[docs] def process_cdr(procstatus, dscfg, radar_list=None): """ Computes approximation of Circular Depolarization Ratio Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : string. Dataset keyword The input data type, must contain, "RhoHV" or "uRhoHV" or "RhoHVu", and, "ZDR" or "ZDRc" radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "CDR" ind_rad : int radar index """ if procstatus != 1: return None, None for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("RhoHV", "uRhoHV", "RhoHVu"): rhohv = get_fieldname_pyart(datatype) elif datatype in ("ZDR", "ZDRc"): zdr = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if (rhohv not in radar.fields) or (zdr not in radar.fields): warn("Unable to compute CDR field. Missing data") return None, None cdr = pyart.retrieve.compute_cdr( radar, rhohv_field=rhohv, zdr_field=zdr, cdr_field="circular_depolarization_ratio", ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field("circular_depolarization_ratio", cdr) return new_dataset, ind_rad
[docs] def process_vpr(procstatus, dscfg, radar_list=None): """ Computes the vertical profile of reflectivity using the Meteo-France operational algorithm Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : string. Dataset keyword The input data type, must contain, "dBZ" or "dBZc", and, "H_ISO0" or "H_ISO0c" or "TEMP" or "TEMPc" nvalid_min : int Minimum number of rays with data to consider the azimuthal average valid. Default 20. angle_min, angle_max : float Minimum and maximum elevation angles used to compute the ratios of reflectivity. Default 0. and 4. ml_thickness_min, ml_thickness_max, ml_thickness_step : float Minimum, maximum and step of the melting layer thickness of the models to explore [m]. Default 200., 800. and 200. iso0_max : float maximum iso0 altitude of the profile. Default 5000. ml_top_diff_max, ml_top_step : float maximum difference +- between iso-0 and top of the melting layer [m] of the models to explore. Step. Default 200. and 200. ml_peak_min, ml_peak_max, ml_peak_step: float min, max and step of the value at the peak of the melting layer of the models to explore. Default 1., 6. and 1. dr_min, dr_max, dr_step : float min, max and step of the decreasing ratio above the melting layer. Default -6., -1.5 and 1.5 dr_default : float default decreasing ratio to use if a proper model could not be found. Default -4.5 dr_alt : float altitude above the melting layer top (m) where theoretical profile needs to be defined to be able to compute DR. If the theoretical profile is not defined up to the resulting altitude a default DR is used. Default 800. h_max : float maximum altitude [masl] where to compute the model profile. Default 6000. h_corr_max : float maximum altitude [masl] considered for the VPR correction h_res : float resolution of the model profile (m). Default 1. max_weight : float Maximum weight of the antenna pattern. Default 9. rmin_obs, rmax_obs : float minimum and maximum range (m) of the observations that are compared with the model. Default 5000. and 150000. use_ml : bool If True the retrieved ML will be used to select the range of variability the meltin layer top and thickness vpr_memory_max : float The maximum time range to average reflectivity (min) filter_vpr_memory_max : float The maximum time range where to look for previous VPR retrievals ml_datatype : str Melting layer data type descriptor z_datatype : str descriptor used get the linear reflectivity information vpr_theo_datatype : str descriptor used to get the retrieved theoretical VPR filter_params : bool If True the current theoretical VPR profile is averaged with the past VPR profile by averaging the 4 parameters that define the profile, otherwise the shape of the profiles is averaged. Default false. Used only in non-spatialised VPR correction weight_mem : float Weight given to past VPR when filtering the current VPR spatialized : bool If True the VPR correction is spatialized correct_iso0 : bool If True the iso0 field is corrected by a bias constant computed as the difference between the retrieved melting layer top and the average iso0 and areas with precipitation. Default True. Used only in the spatialised VPR correction radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output fields "dBZc" and "VPRcorr" ind_rad : int radar index """ if procstatus != 1: return None, None temp_ref = None temp_field = None iso0_field = None for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("dBZ", "dBZc"): refl_field = get_fieldname_pyart(datatype) elif datatype in ("H_ISO0", "H_ISO0c"): iso0_field = get_fieldname_pyart(datatype) elif datatype in ("TEMP", "TEMPc"): temp_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] # Check which should be the reference field for temperature if iso0_field is not None: if iso0_field not in radar.fields: warn("Unable to detect melting layer. " "Missing height over iso0 field") return None, None temp_ref = "height_over_iso0" if temp_field is not None: if temp_field not in radar.fields: warn("Unable to detect melting layer. " "Missing temperature field") return None, None temp_ref = "temperature" if temp_ref is None: warn("A valid temperature reference field has to be specified") return None, None if refl_field not in radar.fields: warn("ERROR: Unable to compute VPR. Missing data") return None, None # User defined variables nvalid_min = dscfg.get("nvalid_min", 20) angle_min = dscfg.get("angle_min", 0.0) angle_max = dscfg.get("angle_max", 4.0) ml_thickness_min = dscfg.get("ml_thickness_min", 200) ml_thickness_max = dscfg.get("ml_thickness_max", 800) ml_thickness_step = dscfg.get("ml_thickness_step", 200) iso0_max = dscfg.get("iso0_max", 5000.0) ml_top_diff_max = dscfg.get("ml_top_diff_max", 200) ml_top_step = dscfg.get("ml_top_step", 200) ml_peak_min = dscfg.get("ml_peak_min", 1.0) ml_peak_max = dscfg.get("ml_peak_max", 6.0) ml_peak_step = dscfg.get("ml_peak_step", 1.0) dr_min = dscfg.get("dr_min", -6.0) dr_max = dscfg.get("dr_max", -1.5) dr_step = dscfg.get("dr_step", 1.5) dr_default = dscfg.get("dr_default", -4.5) dr_alt = dscfg.get("dr_alt", 800.0) h_max = dscfg.get("h_max", 6000.0) h_corr_max = dscfg.get("h_corr_max", 15000.0) h_res = dscfg.get("h_res", 1.0) filter_params = dscfg.get("filter_params", False) max_weight = dscfg.get("max_weight", 9.0) rmin_obs = dscfg.get("rmin_obs", 5000.0) rmax_obs = dscfg.get("rmax_obs", 150000.0) use_ml = dscfg.get("use_ml", False) ml_datatypedescr = dscfg.get("ml_datatype", None) z_datatypedescr = dscfg.get("z_datatype", None) vpr_theo_datatypedescr = dscfg.get("vpr_theo_datatype", None) vpr_memory_max = dscfg.get("vpr_memory_max", 0.0) filter_vpr_memory_max = dscfg.get("filter_vpr_memory_max", 0.0) weight_mem = dscfg.get("weight_mem", 0.75) spatialised = dscfg.get("spatialised", False) correct_iso0 = dscfg.get("correct_iso0", True) iso0 = None if use_ml: if ( ml_datatypedescr is None or dscfg["loadbasepath"] is None or dscfg["loadname"] is None ): warn("unable to find files containing melting layer information") iso0 = None else: flist = get_file_list( ml_datatypedescr, [dscfg["timeinfo"]], [dscfg["timeinfo"]], dscfg ) if not flist: warn("unable to find files containing" " melting layer information") iso0 = None else: radar_ml = pyart.io.read_cfradial(flist[0]) if radar_ml is None: warn("Unable to use retrieved melting layer data") iso0 = None else: print(f"Using file {flist[0]} " f"with melting layer information") iso0 = np.ma.mean( radar_ml.fields["melting_layer_height"]["data"][:, 1] ) ml_bottom = np.ma.mean( radar_ml.fields["melting_layer_height"]["data"][:, 0] ) ml_thickness = iso0 - ml_bottom ml_thickness_min = ml_thickness - ml_thickness_step ml_thickness_max = ml_thickness + ml_thickness_step radar_mem_list = None if vpr_memory_max > 0: if ( z_datatypedescr is None or dscfg["loadbasepath"] is None or dscfg["loadname"] is None ): warn("unable to find files with azimuthal reflectivity average") else: # get previous reflectivity files but do not include current one flist = get_file_list( z_datatypedescr, [dscfg["timeinfo"] - datetime.timedelta(minutes=vpr_memory_max)], [dscfg["timeinfo"] - datetime.timedelta(seconds=1)], dscfg, ) if not flist: warn("unable to find files containing reflectivity") else: radar_mem_list = [] for fname in flist: radar_vpr = pyart.io.read_cfradial(fname) if radar_vpr is None: warn("Unable to use azimuthal reflectivity average") continue print(f"Using file {fname} with azimuthal averaged refl") radar_mem_list.append(radar_vpr) if not radar_mem_list: radar_mem_list = None vpr_theo_dict_mem = None if filter_vpr_memory_max > 0.0: if ( vpr_theo_datatypedescr is None or dscfg["loadbasepath"] is None or dscfg["loadname"] is None ): warn("unable to find files with theoretical VPR") else: # get previous VPR retrieved files but do not include current one flist = get_file_list( vpr_theo_datatypedescr, [dscfg["timeinfo"] - datetime.timedelta(minutes=filter_vpr_memory_max)], [dscfg["timeinfo"] - datetime.timedelta(seconds=1)], dscfg, ) if not flist: warn("unable to find files containing retrieved VPR") else: if spatialised or filter_params: # this function will read the stored VPR parameters from # the previous volume vpr_theo_dict_mem = read_vpr_theo_parameters(flist[-1]) else: height, _, vals = read_rhi_profile(flist[-1], labels=["Znorm"]) vpr_theo_dict_mem = {"value": vals[:, 0], "altitude": height} print(f"Using file {flist[-1]} with previously retrieved VPR") corr_refl_field = "corrected_reflectivity" corr_field = "vpr_correction" if spatialised: refl_corr, vpr_corr, vpr_theo_dict, radar_rhi, vpr_info = ( pyart.correct.correct_vpr_spatialised( radar, nvalid_min=nvalid_min, angle_min=angle_min, angle_max=angle_max, ml_thickness_min=ml_thickness_min, ml_thickness_max=ml_thickness_max, ml_thickness_step=ml_thickness_step, iso0_max=iso0_max, ml_top_diff_max=ml_top_diff_max, ml_top_step=ml_top_step, ml_peak_min=ml_peak_min, ml_peak_max=ml_peak_max, ml_peak_step=ml_peak_step, dr_min=dr_min, dr_max=dr_max, dr_step=dr_step, dr_default=dr_default, dr_alt=dr_alt, h_max=h_max, h_corr_max=h_corr_max, h_res=h_res, max_weight=max_weight, rmin_obs=rmin_obs, rmax_obs=rmax_obs, iso0=iso0, correct_iso0=correct_iso0, weight_mem=weight_mem, vpr_theo_dict_mem=vpr_theo_dict_mem, radar_mem_list=radar_mem_list, refl_field=refl_field, corr_refl_field=corr_refl_field, corr_field=corr_field, temp_field=temp_field, iso0_field=iso0_field, temp_ref=temp_ref, ) ) else: refl_corr, vpr_corr, vpr_theo_dict, radar_rhi, vpr_info = ( pyart.correct.correct_vpr( radar, nvalid_min=nvalid_min, angle_min=angle_min, angle_max=angle_max, ml_thickness_min=ml_thickness_min, ml_thickness_max=ml_thickness_max, ml_thickness_step=ml_thickness_step, iso0_max=iso0_max, ml_top_diff_max=ml_top_diff_max, ml_top_step=ml_top_step, ml_peak_min=ml_peak_min, ml_peak_max=ml_peak_max, ml_peak_step=ml_peak_step, dr_min=dr_min, dr_max=dr_max, dr_step=dr_step, dr_default=dr_default, dr_alt=dr_alt, h_max=h_max, h_corr_max=h_corr_max, h_res=h_res, max_weight=max_weight, rmin_obs=rmin_obs, rmax_obs=rmax_obs, iso0=iso0, filter_params=filter_params, weight_mem=weight_mem, vpr_theo_dict_mem=vpr_theo_dict_mem, radar_mem_list=radar_mem_list, refl_field=refl_field, corr_refl_field=corr_refl_field, corr_field=corr_field, temp_field=temp_field, iso0_field=iso0_field, temp_ref=temp_ref, ) ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field(corr_refl_field, refl_corr) new_dataset["radar_out"].add_field(corr_field, vpr_corr) new_dataset.update({"vpr_theo_dict": vpr_theo_dict}) new_dataset.update({"vpr_info": vpr_info}) new_dataset.update({"radar_rhi": radar_rhi}) return new_dataset, ind_rad
[docs] def process_rainrate(procstatus, dscfg, radar_list=None): """ Estimates rainfall rate from polarimetric moments Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : string. Dataset keyword The input data type, must contain, If RR_METHOD == "Z" or "ZPoly": "dBZ" or "dBZc" If RR_METHOD == "KDP": "KDP" or "KDPc" If RR_METHOD == "A": "Ah" or "Ahc" If RR_METHOD == "ZKDP": "dBZ" or "dBZc", and, "KDP" or "KDPc" IF RR_METHOD == "ZA": "dBZ" or "dBZc", and, "Ah" or "Ahc" IF RR_METHID == "hydro": "dBZ" or "dBZc", and, "Ah" or "Ahc", and, "hydro" RR_METHOD : string. Dataset keyword The rainfall rate estimation method. One of the following: Z, ZPoly, KDP, A, ZKDP, ZA, hydro alpha, beta : float factor and exponent of the R-Var power law R = alpha*Var^Beta. Default value depending on RR_METHOD. Z (0.0376, 0.6112), KDP (None, None), A (None, None) alphaz, betaz : float factor and exponent of the R-Z power law R = alpha*Z^Beta. Default value (0.0376, 0.6112) alphazr, betazr : float factor and exponent of the R-Z power law R = alpha*Z^Beta applied to rain in method hydro. Default value (0.0376, 0.6112) alphazs, betazs : float factor and exponent of the R-Z power law R = alpha*Z^Beta applied to solid precipitation in method hydro. Default value (0.1, 0.5) alphakdp, betakdp : float factor and exponent of the R-KDP power law R = alpha*KDP^Beta. Default value (None, None) alphaa, betaa : float factor and exponent of the R-Ah power law R = alpha*Ah^Beta. Default value (None, None) thresh : float In hybrid methods, Rainfall rate threshold at which the retrieval method used changes [mm/h]. Default value depending on RR_METHOD. ZKDP 10, ZA 10, hydro 10 mp_factor : float Factor by which the Z-R relation is multiplied in the melting layer in method hydro. Default 0.6 radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "RR" (rain rate) ind_rad : int radar index """ if procstatus != 1: return None, None if "RR_METHOD" not in dscfg: raise Exception( "ERROR: Undefined parameter 'RR_METHOD' for dataset '%s'" % dscfg["dsname"] ) if dscfg["RR_METHOD"] == "Z": radarnr, _, datatype, _, _ = get_datatype_fields(dscfg["datatype"][0]) refl_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if refl_field not in radar.fields: warn("ERROR: Unable to compute rainfall rate. Missing data") return None, None # user defined parameters alpha = dscfg.get("alpha", 0.0376) beta = dscfg.get("beta", 0.6112) rain = pyart.retrieve.est_rain_rate_z( radar, alpha=alpha, beta=beta, refl_field=refl_field, rr_field=None ) elif dscfg["RR_METHOD"] == "ZPoly": radarnr, _, datatype, _, _ = get_datatype_fields(dscfg["datatype"][0]) refl_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if refl_field not in radar.fields: warn("Unable to compute rainfall rate. Missing data") return None, None rain = pyart.retrieve.est_rain_rate_zpoly( radar, refl_field=refl_field, rr_field=None ) elif dscfg["RR_METHOD"] == "KDP": radarnr, _, datatype, _, _ = get_datatype_fields(dscfg["datatype"][0]) kdp_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if kdp_field not in radar.fields: warn("Unable to compute rainfall rate. Missing data") return None, None # user defined parameters alpha = dscfg.get("alpha", None) beta = dscfg.get("beta", None) rain = pyart.retrieve.est_rain_rate_kdp( radar, alpha=alpha, beta=beta, kdp_field=kdp_field, rr_field=None ) elif dscfg["RR_METHOD"] == "A": radarnr, _, datatype, _, _ = get_datatype_fields(dscfg["datatype"][0]) a_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if a_field not in radar.fields: warn("Unable to compute rainfall rate. Missing data") return None, None # user defined parameters alpha = dscfg.get("alpha", None) beta = dscfg.get("beta", None) rain = pyart.retrieve.est_rain_rate_a( radar, alpha=alpha, beta=beta, a_field=a_field, rr_field=None ) elif dscfg["RR_METHOD"] == "ZKDP": for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("dBZ", "dBZc"): refl_field = get_fieldname_pyart(datatype) elif datatype in ("KDP", "KDPc"): kdp_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if (refl_field not in radar.fields) or (kdp_field not in radar.fields): warn("Unable to compute rainfall rate. Missing data") return None, None # user defined parameters alphaz = dscfg.get("alphaz", 0.0376) betaz = dscfg.get("betaz", 0.6112) alphakdp = dscfg.get("alphakdp", None) betakdp = dscfg.get("betakdp", None) thresh = dscfg.get("thresh", 10.0) rain = pyart.retrieve.est_rain_rate_zkdp( radar, alphaz=alphaz, betaz=betaz, alphakdp=alphakdp, betakdp=betakdp, refl_field=refl_field, kdp_field=kdp_field, rr_field=None, main_field=refl_field, thresh=thresh, thresh_max=True, ) elif dscfg["RR_METHOD"] == "ZA": for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("dBZ", "dBZc"): refl_field = get_fieldname_pyart(datatype) elif datatype in ("Ah", "Ahc"): a_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if (refl_field not in radar.fields) or (a_field not in radar.fields): warn("Unable to compute rainfall rate. Missing data") return None, None # user defined parameters alphaz = dscfg.get("alphaz", 0.0376) betaz = dscfg.get("betaz", 0.6112) alphaa = dscfg.get("alphaa", None) betaa = dscfg.get("betaa", None) thresh = dscfg.get("thresh", 5.0) rain = pyart.retrieve.est_rain_rate_za( radar, alphaz=alphaz, betaz=betaz, alphaa=alphaa, betaa=betaa, refl_field=refl_field, a_field=a_field, rr_field=None, main_field=refl_field, thresh=thresh, thresh_max=True, ) elif dscfg["RR_METHOD"] == "hydro": for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("dBZ", "dBZc"): refl_field = get_fieldname_pyart(datatype) elif datatype in ("Ah", "Ahc"): a_field = get_fieldname_pyart(datatype) elif datatype == "hydro": hydro_field = "radar_echo_classification" ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] # user defined parameters alphazr = dscfg.get("alphazr", 0.0376) betazr = dscfg.get("betazr", 0.6112) alphazs = dscfg.get("alphazs", 0.1) betazs = dscfg.get("betazs", 0.5) alphaa = dscfg.get("alphaa", None) betaa = dscfg.get("betaa", None) thresh = dscfg.get("thresh", 5.0) mp_factor = dscfg.get("mp_factor", 0.6) if ( (refl_field in radar.fields) and (a_field in radar.fields) and (hydro_field in radar.fields) ): rain = pyart.retrieve.est_rain_rate_hydro( radar, alphazr=alphazr, betazr=betazr, alphazs=alphazs, betazs=betazs, alphaa=alphaa, betaa=betaa, mp_factor=mp_factor, refl_field=refl_field, a_field=a_field, hydro_field=hydro_field, rr_field=None, main_field=refl_field, thresh=thresh, thresh_max=True, ) elif refl_field in radar.fields: warn( "Unable to compute rainfall rate using hydrometeor " "classification. Missing data. " "A simple Z-R relation will be used instead" ) rain = pyart.retrieve.est_rain_rate_z( radar, alpha=alphazr, beta=betazr, refl_field=refl_field, rr_field=None ) else: warn( "Unable to compute rainfall rate using hydrometeor " "classification. Missing data." ) return None, None else: raise Exception( "ERROR: Unknown rainfall rate retrieval method " + dscfg["RR_METHOD"] ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field("radar_estimated_rain_rate", rain) return new_dataset, ind_rad
[docs] def process_rainfall_accumulation(procstatus, dscfg, radar_list=None): """ Computes rainfall accumulation fields Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : list of string. Dataset keyword The input data types, must contain, "RR" period : float. Dataset keyword the period to average [s]. If -1 the statistics are going to be performed over the entire data. Default 3600. start_average : float. Dataset keyword when to start the average [s from midnight UTC]. Default 0. use_nan : bool. Dataset keyword If true non valid data will be used nan_value : float. Dataset keyword The value of the non valid data. Default 0 radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "Raccu" ind_rad : int radar index """ if procstatus == 0: return None, None radarnr, _, datatype, _, _ = get_datatype_fields(dscfg["datatype"][0]) if datatype != "RR": warn( f"Unable to compute rainfall accumulation. " f"Data type: {datatype}. Expected RR" ) return None, None field_name = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 start_average = dscfg.get("start_average", 0.0) period = dscfg.get("period", 3600.0) use_nan = dscfg.get("use_nan", 0) nan_value = dscfg.get("nan_value", 0.0) rr_acu_name = "rainfall_accumulation" if procstatus == 1: if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if field_name not in radar.fields: warn("ERROR: Unable to compute rainfall accumulation. " "Missing data") return None, None # Prepare auxiliary radar field_data = deepcopy(radar.fields[field_name]["data"]) if use_nan: field_data = np.ma.asarray(field_data.filled(nan_value)) field_data *= dscfg["ScanPeriod"] * 60.0 / 3600.0 rr_acu_dict = pyart.config.get_metadata(rr_acu_name) rr_acu_dict["data"] = field_data radar_aux = deepcopy(radar) radar_aux.fields = dict() radar_aux.add_field(rr_acu_name, rr_acu_dict) # first volume: initialize start and end time of averaging if dscfg["initialized"] == 0: avg_par = dict() if period != -1: date_00 = dscfg["timeinfo"].replace( hour=0, minute=0, second=0, microsecond=0 ) avg_par.update( {"starttime": date_00 + datetime.timedelta(seconds=start_average)} ) avg_par.update( { "endtime": avg_par["starttime"] + datetime.timedelta(seconds=period) } ) else: avg_par.update({"starttime": dscfg["timeinfo"]}) avg_par.update({"endtime": dscfg["timeinfo"]}) avg_par.update({"timeinfo": dscfg["timeinfo"]}) dscfg["global_data"] = avg_par dscfg["initialized"] = 1 if dscfg["initialized"] == 0: return None, None dscfg["global_data"]["timeinfo"] = dscfg["timeinfo"] # no radar object in global data: create it if "radar_out" not in dscfg["global_data"]: if period != -1: # get start and stop times of new radar object (dscfg["global_data"]["starttime"], dscfg["global_data"]["endtime"]) = ( time_avg_range( dscfg["timeinfo"], dscfg["global_data"]["starttime"], dscfg["global_data"]["endtime"], period, ) ) # check if volume time older than starttime if dscfg["timeinfo"] > dscfg["global_data"]["starttime"]: dscfg["global_data"].update({"radar_out": radar_aux}) else: dscfg["global_data"].update({"radar_out": radar_aux}) return None, None # still accumulating: add field to global field if period == -1 or dscfg["timeinfo"] < dscfg["global_data"]["endtime"]: if period == -1: dscfg["global_data"]["endtime"] = dscfg["timeinfo"] field_interp = interpol_field( dscfg["global_data"]["radar_out"], radar_aux, rr_acu_name ) if use_nan: field_interp["data"] = np.ma.asarray( field_interp["data"].filled(nan_value) ) masked_sum = np.ma.getmaskarray( dscfg["global_data"]["radar_out"].fields[rr_acu_name]["data"] ) valid_sum = np.logical_and( np.logical_not(masked_sum), np.logical_not(np.ma.getmaskarray(field_interp["data"])), ) dscfg["global_data"]["radar_out"].fields[rr_acu_name]["data"][ masked_sum ] = field_interp["data"][masked_sum] dscfg["global_data"]["radar_out"].fields[rr_acu_name]["data"][ valid_sum ] += field_interp["data"][valid_sum] return None, None # we have reached the end of the accumulation period: start a new # object (only reachable if period != -1) new_dataset = { "radar_out": deepcopy(dscfg["global_data"]["radar_out"]), "timeinfo": dscfg["global_data"]["endtime"], } dscfg["global_data"]["starttime"] += datetime.timedelta(seconds=period) dscfg["global_data"]["endtime"] += datetime.timedelta(seconds=period) # remove old radar object from global_data dictionary dscfg["global_data"].pop("radar_out", None) # get start and stop times of new radar object dscfg["global_data"]["starttime"], dscfg["global_data"]["endtime"] = ( time_avg_range( dscfg["timeinfo"], dscfg["global_data"]["starttime"], dscfg["global_data"]["endtime"], period, ) ) # check if volume time older than starttime if dscfg["timeinfo"] > dscfg["global_data"]["starttime"]: dscfg["global_data"].update({"radar_out": radar_aux}) return new_dataset, ind_rad # no more files to process if there is global data pack it up if procstatus == 2: if dscfg["initialized"] == 0: return None, None if "radar_out" not in dscfg["global_data"]: return None, None new_dataset = { "radar_out": deepcopy(dscfg["global_data"]["radar_out"]), "timeinfo": dscfg["global_data"]["endtime"], } return new_dataset, ind_rad
[docs] def process_bird_density(procstatus, dscfg, radar_list=None): """ Computes the bird density from the volumetric reflectivity Parameters ---------- procstatus : int Processing status: 0 initializing, 1 processing volume, 2 post-processing dscfg : dictionary of dictionaries data set configuration. Accepted Configuration Keywords:: datatype : list of string. Dataset keyword The input data types, must contain, "eta_h" or "eta_v" (volumetric reflectivities) sigma_bird : float. Dataset keyword The bird radar cross section radar_list : list of Radar objects Optional. list of radar objects Returns ------- new_dataset : dict dictionary containing the output field "bird_density" ind_rad : int radar index """ if procstatus != 1: return None, None for datatypedescr in dscfg["datatype"]: radarnr, _, datatype, _, _ = get_datatype_fields(datatypedescr) if datatype in ("eta_h", "eta_v"): vol_refl_field = get_fieldname_pyart(datatype) ind_rad = int(radarnr[5:8]) - 1 if radar_list[ind_rad] is None: warn("No valid radar") return None, None radar = radar_list[ind_rad] if vol_refl_field not in radar.fields: warn(f"Unable to obtain bird density. Missing field {vol_refl_field}") return None, None sigma_bird = dscfg.get("sigma_bird", 11.0) bird_density_dict = pyart.retrieve.compute_bird_density( radar, sigma_bird=sigma_bird, vol_refl_field=vol_refl_field, bird_density_field="bird_density", ) # prepare for exit new_dataset = {"radar_out": deepcopy(radar)} new_dataset["radar_out"].fields = dict() new_dataset["radar_out"].add_field("bird_density", bird_density_dict) return new_dataset, ind_rad