BALTRAD PPC
|
The baltrad polarimetric processing chain quality algorithm is based on the work made by Gianfranco Vulpiani at SMHI in 2017. The original code was developed in Matlab and has been ported to work as a part of RAVE.
This documentation focus on the software and usage of the results so you will have to read the report for a more indepth knowledge about the original implementation and the physics behind it all.
The processing chain performs several different steps in order to produce an attenuation corrected result and is best described by the following picture.
The steps performed in the processing chain are:
When the above steps have been performed a number of different products will be added to the original radar data and then returned to the user of the process.
Some functions have been added to the public python APIs so that it's possible to run parts of the chain if needed. For example in tests or when evaluating the functions. There are 3 different modules that can be loaded.
The documentation for each module is obtained with the following command
>>> import module >>> print(module.__doc__)
The documentation for respective module is displayed below..
>>> import _pdpprocessor >>> print(_pdpprocessor.__doc__) This is the polarimetric processing chain module itself. The easiest way to get started is to use the process function which combines all functions into a chain but first you will have to create an instance of the _pdpprocessor which is done by: >>> import _pdpprocessor >>> processor = _pdpprocessor.new() After that you might have to modify the options that are used by the processor and these can be accessed with: >>> processor.options.... Next is to process the data in some way. The fastest way to get started is to use the process function which only takes a rave polar scan as in argument. >>> from _ppcradaroptions import P_TH_CORR,P_ZPHI_CORR,P_ATT_TH_CORR,P_ATT_DBZH_CORR,P_KDP_CORR >>> import _raveio >>> scan = _raveio.open(".../some.scan.h5").object >>> processor.requestedFields = P_TH_CORR | P_ZPHI_CORR | P_ATT_TH_CORR | P_ATT_DBZH_CORR | P_KDP_CORR >>> processor.meltingLayerBottomHeight = 1.0 # In KM >>> newscan = processor.process(scan) >>> param = newscan.getParameter("KDP_CORR") The functions are: scan := process(scan, clutterMap) Performs the polarimetric processing chain. - indata scan - a polar scan clutterMap - the statistical clutter map. - returns a scan of type PolarScanParam texture := texture(field) Creates a texture from the provided data field. - indata: field (RaveData2DCore) - An arbitary field - returns a texture of type RaveData2DCore degree := trap(field, a, b, s, t) Trapezoidal function where the field can be any variable and a,b,s,t identifies the trapezoid coordinates along the x-axis x1 = a-s, x2=a, x3=b, x4=b+t. - indata: field (RaveData2DCore) - An arbitary field a (float) - see above explanation of constant b (float) - see above explanation of constant s (float) - see above explanation of constant t (float) - see above explanation of constant - returns a RaveData2DCore field representing the membership degree (Z, Quality, ClutterMask) := clutterCorrection(Z, VRADH, texturePHIDP, RHOHV, textureZ, ClutterMap, nodataZ, nodataVRADH, qualityThreshold) Clutter correction function. - indata: Z (RaveData2DCore) - Reflectivity VRADH (RaveData2DCore) - Doppler velocity TexturePHIDP (RaveData2DCore) - Texture of PHIDP RHOHV (RaveData2DCore) - Correlation coefficient TextureZ (RaveData2DCore) - Texture of Z ClutterMap (RaveData2DCore) - Statistical clutter map nodataZ (float) - Nodata for Z nodataVRADH (float) - Nodata for VRADH qualityThreshold (float) - Threshold for the quality as generated. - returns a tuple (Z, Quality, ClutterMask) of type RaveData2DCore degree := clutterID(Z, VRADH, texturePHIDP, RHOHV, TextureZ, ClutterMap, nodataZ, nodataVRADH) Clutter identification function. That calculates a field containing a degree of membership of a target weather class. - indata: Z (RaveData2DCore) - Reflectivity VRADH (RaveData2DCore) - Doppler velocity texturePHIDP (PyRaveData2D) - The PHIDP texture RHOHV (RaveData2DCore) - Correlation coefficient TextureZ (RaveData2DCore) - Texture of Z ClutterMap (RaveData2DCore) - Statistical clutter map nodataZ (float) - Nodata for Z nodataVRADH (float) - Nodata for VRADH - returns a RaveData2DCore representing probability (degree) of weather class mask := medfilt(Z, threshZ, nodataZ, (filtXsize, filtYsize)) Median filter. threshZ, nodataZ, filtXsize and filtYsize are optional. filtXsize & filtYsize are specified as a tuple. - indata: Z (RaveData2DCore) - Reflectivity threshZ (float) - Z threshold nodataZ (float) - Z nodata value (filtXsize, filtYsize) (2*digit), - window size - returns a RaveData2DCore field with the mask calculated by the filter mask := residualClutterFilter(Z, threshZ, threshTexture, (filtXsize, filtYsize)) Residual clutter filter. Z is a RaveData2DCore field. threshZ, threshTexture are doubles and filtXsize, filtYsize are digits. All attributes are optional except Z. - indata: Z (RaveData2DCore) - Reflectivity threshZ (float) - Z threshold threshTexture (float) - Texture threshold (filtXsize, filtYsize) (2*digit), - window size - returns a RaveData2DCore field with the mask calculated by the filter (PHIDP, KDP) := pdpProcessing(PDP, res, window, nrIter) this function applies the Iterative Finite Difference scheme for the filtering of PHIDP and estimation of KDP - indata: PDP (RaveData2DCore) - Input differential phase to be processed res (float) - Radial resolution in km window (number) - Half of moving window size expressed in bins applied to the azimuthal rays. nrIter (number) - Number of iteration the procedure has to be applied to keep the excpected std dev of KDP under control - returns a tuple (PHIDP, KDP) of type RaveData2DCore (PHIDP, KDP) := pdpScript(PDP, dr, rWin1, &rWin2, nrIter) this function applies the Iterative Finite Difference scheme for the filtering of PHIDP and estimation of KDP - indata: PDP (RaveData2DCore) - Input differential phase to be processed dr (float) - Radial resolution in km rWin1 (float) - Half of moving window size expressed in km applied to the az-rays characterized by low to moderate total phase shift rWin2 (float) - Half of moving window size expressed in km applied to the az-rays characterized by moderate to high total phase shift nrIter (number) - Number of iteration the procedure has to be applied to keep the excpected std dev of KDP under control - returns a tuple (PHIDP, KDP) of type RaveData2DCore (Z, ZDR, PIA, DBZH) := attenuation(Z, ZDR, DBZH, PDP, mask, gamma_h, alpha, zundetect, dbzhundetect) This function applies the linear attenuation. - indata: Z (RaveData2DCore) - Reflectivity ZDR (RaveData2DCore) - Differential reflectivity DBZH (RaveData2DCore) - Reflectivity PDP (RaveData2DCore) - Filtered phase shift mask (RaveData2DCore) - Specifies the first and last range gates in rain to be considered for attenuation correction see source code for process for more information of type RaveData2DCore gamma_h (float) - Coefficient relating specific attenuation and specific differential phase. alpha (float) - Is the quota AH / ADP where AH is the specific attenuation and ADP is the specific differential attenuation. zundectect (float) - Z fields undetect value. dbzhundetect (float) - DBZH fields undetect value. - returns a tuple of attenuated fields (Z, ZDR, PIA, DBZH) of type RaveData2DCore (Zphi, AH) := zphi(Z, PDP, mask, dr, BB, gamma_h) This function applies the attenuation correction based on application of the analytical solution of differential equation. - indata: Z (RaveData2DCore) - Reflectivity PDP (RaveData2DCore) - Filtered phase shift mask (RaveData2DCore) - Specifies the first and last range gates in rain to be considered for attenuation correction see source code for process for more information dr (double) - Range resolution expressed in km. BB (double) - The exponent of the power law relating specific attenuation and Z. - returns a tuple of attenuated fields (Zphi, AH) of type RaveData2DCore where Zphi is attenuation corrected reflectivity and AH is estimated specific attenuation
>>> import _ppcoptions >>> print(_ppcoptions.__doc__) This is the ppc options loader. It is used to load ppc radar option configuration files written in xml-format. There are only a few member functions available here (getRadarOptions, exists and options) and currently there is no support for saving the configuration. The available functions are: - radaroptions := getRadarOptions(string) returns a PpcRadarOptionsCore instance if found - boolean := exists(string) returns if the specified option name exists or not - dictionary := options() returns a dictionary with all available option settings >>> import _ppcoptions >>> options = _ppcoptions.load(".../ppc_options.xml") >>> optionNames = options.options().keys() >>> print(optionNames) dict_keys(['default']) Assuming that we are loading a polar scan from sehud and want to use the options configured for that site one could implement the usage as follows: >>> sehudopt = options.getRadarOptions("default") >>> if options.exists("sehud"): >>> sehudopt = options.getRadarOptions("sehud") ....
>>> import _ppcradaroptions >>> print(_ppcradaroptions.__doc__) Keeps track of options used for the different radar sources when it comes to the polarimetric process chain processing. In this documentation section all the available options are listed for the different radars and a description of the values they assume. The following settings are available: parametersUZ - parameters for TH, 5 values separated by ',' Weight,X2,X3,Delta1,Delta2 and the derived values will be X1=X2-Delta1, X3=X4-Delta2 parametersVEL - parameters for VRADH, 5 values separated by ',' Weight,X2,X3,Delta1,Delta2 and the derived values will be X1=X2-Delta1, X3=X4-Delta2 parametersTextPHIDP - parameters for the PHIDP texture, 5 values separated by ',' Weight,X2,X3,Delta1,Delta2 and the derived values will be X1=X2-Delta1, X3=X4-Delta2 parametersRHV - parameters for RHOHV, 5 values separated by ',' Weight,X2,X3,Delta1,Delta2 and the derived values will be X1=X2-Delta1, X3=X4-Delta2 parametersTextUZ - parameters for the TH texture, 5 values separated by ',' Weight,X2,X3,Delta1,Delta2 and the derived values will be X1=X2-Delta1, X3=X4-Delta2 parametersClutterMap - parameters for the clutter map, 5 values separated by ',' Weight,X2,X3,Delta1,Delta2 and the derived values will be X1=X2-Delta1, X3=X4-Delta2 nodata - nodata to be used in most products minDBZ - min DBZ threshold in the clutter correction qualityThreshold - quality threshold in the clutter correction preprocessZThreshold - preprocessing Z threshold before starting actual processing residualMinZClutterThreshold - min z clutter threshold during residual clutter filtering residualThresholdZ - min Z threshold in the residual clutter filtering residualThresholdTexture - texture threshold in the residual clutter filtering residualClutterNodata - the nodata value to be used when creating the residual clutter image used for creating the mask residualClutterMaskNodata - Nodata value for the residual clutter mask residualClutterTextureFilteringMaxZ - Max Z value when creating the residual clutter mask, anything higher will be set to min value residualFilterBinSize - number of bins used in the window when creating the residual mask residualFilterRaySize - number of rays used in the window when creating the residual mask minZMedfilterThreshold - min z threshold used in the median filter that is used by the residual clutter filter processingTextureThreshold - threshold for the texture created in the pdp processing minWindow - min window size pdpRWin1 - pdp ray window 1 pdpRWin2 - pdp ray window 2 pdpNrIterations - number of iterations in pdp processing kdpUp - Maximum allowed value of Kdp kdpDown - Minimum allowed value of kdp kdpStdThreshold - Kdp STD threshold BB - BB value used in the zphi part of the pdp processing thresholdPhidp - threshold for PHIDP in the pdp processing minAttenuationMaskRHOHV - min RHOHV value for marking value as 1 in the attenuation mask minAttenuationMaskKDP - min KDP value for marking value as 1 in the attenuation mask minAttenuationMaskTH - min TH value for marking value as 1 in the attenuation mask attenuationGammaH - gamma h value used in the attenuation attenuationAlpha - alpha value used in the attenuation attenuationPIAminZ - min PIA Z value in attenuation process meltingLayerBottomHeight - The melting layer bottom height meltingLayerHourThreshold - The number of hours before default height should be used. invertPHIDP - if the PHIDP should be inverted (multiplied with -1) or not. Typically this can be needed if the RSP produces inverted values. requestedFields - '|' separated list of flags that defines what products should be added to the finished result. If the flag begins with a P, it means that the result is added as a parameter and the name of the parameter will be without the P_. If on the other hand the flag begins with a Q_ it means that the result is added as a quality field and in those cases the how/task name will be se.baltrad.ppc.<mask name without Q_ in lowercase> Available flags are: + P_TH_CORR + P_ATT_TH_CORR + P_DBZH_CORR + P_ATT_DBZH_CORR + P_KDP_CORR + P_RHOHV_CORR + P_PHIDP_CORR + P_ZDR_CORR + P_ZPHI_CORR + Q_RESIDUAL_CLUTTER_MASK + Q_ATTENUATION_MASK + Q_ATTENUATION
It is probably the rave plugin that will be used the most. The actual registration of the plugin is performed in the same way as other plugins are registered in rave. Either the file .../rave_pgf_quality_registry.xml file is modified manually or else a small python script containing the following is written.
from rave_pgf_quality_registry_mgr import rave_pgf_quality_registry_mgr a = rave_pgf_quality_registry_mgr("/etc/baltrad/rave/etc/rave_pgf_quality_registry.xml") a.remove_plugin("ppc") a.add_plugin("ppc", "ppc_quality_plugin", "ppc_quality_plugin") a.save("/etc/baltrad/rave/etc/rave_pgf_quality_registry.xml")
Next step is to configure the various settings for respective radar. This file /etc/baltrad/baltrad-ppc/config/ppc_options.xml is used to configure the various options for the different radars. In ppc_options.xml you will find a brief explanation of the different parameters that are configurable and also how you can reuse configuration for different radar sources.
The information described in the xml file will be roughly the same as explained when printing the doc for _ppcradaroptions. Some things to note though is that it is possible to build hierarchies of the properties. This means that you can differentiate configurations depending on the situation. To get this configuration you will be able to override configuration settings from a parent. This is achieved by inheriting the options by defining a default attribute in the radaroptions-tag.
As an example, let us say that seang & sekkr should use default values except for attenuationAlpha. selul should use the same attenuationAlpha as sekkr but it also needs to different attenuationGammaH set to 0.09. First you define an option group with the name default (<radaroptions name="default">). After that you define a subgroup called attenuationAlpha03 inheriting default setting from the previously created group. sekkr will just inherit attenuationAlpha03s options and selul will inherit sekkr with the modified attenuationGammaH. Obviously, it's possible to setup these options in several different ways all depending on needs.
<?xml version='1.0' encoding='UTF-8'?> <ppc-options> <radaroptions name="default"> <!-- Weight | X2 | X3 | Delta1 | Delta2 X1=X2-Delta1, X3=X4-Delta2--> <parametersUZ value="0.00,30.00,90.00,62.00,20.00" /> <parametersVEL value="0.30,-0.90,0.90,0.15,0.15" /> <parametersTextPHIDP value="0.80,15.00,40.00,5.00,40.00" /> <parametersRHV value="0.20,0.00,0.60,0.00,0.10" /> <parametersTextUZ value="0.30,20.00,60.00,5.00,10.00" /> <parametersClutterMap value="0.90,5.00,70.00,20.00,60.00" /> <minWindow value="11" /> <nodata value="-999.0" /> <minDBZ value="-32.0" /> <qualityThreshold value="0.75" /> <preprocessZThreshold value="-20.0" /> <residualMinZClutterThreshold value="-31.5" /> <residualThresholdZ value="-20.0" /> <residualThresholdTexture value="20.0" /> <residualClutterNodata value="-999.0" /> <residualClutterMaskNodata value="-1.0" /> <residualClutterTextureFilteringMaxZ value="70.0" /> <residualClutterNodata value="-31.5" /> <residualFilterBinSize value="1" /> <residualFilterRaySize value="1" /> <minZMedfilterThreshold value="-30.0" /> <processingTextureThreshold value="10.0" /> <pdpRWin1 value="3.5" /> <pdpRWin2 value="1.5" /> <pdpNrIterations value="2" /> <kdpUp value="20.0" /> <kdpDown value="-2.0" /> <kdpStdThreshold value="5.0" /> <BB value="0.7987" /> <thresholdPhidp value="40.0" /> <minAttenuationMaskRHOHV value="0.8" /> <minAttenuationMaskKDP value="0.001" /> <minAttenuationMaskTH value="-20.0" /> <attenuationGammaH value="0.08" /> <attenuationAlpha value="0.2" /> <attenuationPIAminZ value="-30" /> <meltingLayerBottomHeight value="2.463" /> <meltingLayerHourThreshold value="6" /> <invertPHIDP value="0" /> <requestedFields value="P_DBZH_CORR|P_ATT_DBZH_CORR|P_PHIDP_CORR|P_QUALITY_RESIDUAL_CLUTTER_MASK" /> </radaroptions> <radaroptions name="attenuationAlpha03" default="default" > <!-- Uses default above but with some modified values--> <attenuationAlpha value="0.3" /> </radaroptions> <radaroptions name="seang" default="attenuationAlpha03" > <!-- Attenuation alpha 0.3 --> </radaroptions> <radaroptions name="sekkr" default="attenuationAlpha03" > <!-- Attenuation alpha 0.3 --> </radaroptions> <radaroptions name="selul" default="sekkr" > <!-- Attenuation alpha 0.3 & attenuationGammaH 0.09 --> <attenuationGammaH value="0.09" /> </radaroptions> </ppc-options>