Read clutter map

Before we can use the fuzzy_echo_classification we have to prepare a clutter map (cmap). The clutter map is processed by summing up the reflectivities over a period of 3 months for each elevation angle. Here we plot a clutter map, which was generated with the clutter_chain. You can read a clutter map for selected time period and elevation angle with the function get_cmap. We have to import the following packages:

import wrainfo as wrf
[1]:
import wradlib as wrl
import datetime as dt
import warnings
warnings.filterwarnings('ignore')
[2]:
path_to_config_file="/tests/data/test_settings_wrainfo.json"

cmap_static=wrf.reader.get_cmap(starttime=dt.datetime(2022,11,6),
                                endtime=dt.datetime(2022,1,13),
                                path=path_to_config_file,
                                elev="0.5",
                                timestr='%Y%m%d')
display(cmap_static)
<xarray.Dataset>
Dimensions:          (azimuth: 720, range: 936)
Coordinates:
  * azimuth          (azimuth) float64 0.25 0.75 1.25 1.75 ... 358.8 359.2 359.8
  * range            (range) float32 37.5 112.5 187.5 ... 7.009e+04 7.016e+04
    elevation        (azimuth) float64 0.5 0.5 0.5 0.5 0.5 ... 0.5 0.5 0.5 0.5
    sweep_mode       <U20 'azimuth_surveillance'
    longitude        float64 13.24
    latitude         float64 53.55
    altitude         float64 38.0
    rtime            (azimuth) datetime64[ns] 2022-01-17T07:20:28.980652544 ....
Data variables:
    DBZH_sum_bool    (azimuth, range) bool ...
    DBZH_sum_values  (azimuth, range) float32 ...

Seealso

Get more information about the clutter_chain in the library reference section or in the process chain module.

The clutter map has two data variables. The first is a boolean data array and the second is a data array of absolute summarised values. We plot the boolean data array of the clutter map.

[3]:
# georeferenced cmap for the plot
cmap_static_georef = cmap_static.pipe(wrl.georef.georeference_dataset)

# plot cmap
cmap_static_georef.DBZH_sum_bool.plot(x="x", y="y")
[3]:
<matplotlib.collections.QuadMesh at 0x1454f82ec8e0>
../_images/jupyter_notebooks_clutter_detection_6_1.png

Fuzzy echo classification

The fuzzy echo classification and clutter identification are based on polarimetric moments and on a processed clutter map. The basic function is from \(\omega radlib\). The function contains a weights of all polarimetric moments and of the clutter map. For the weights the default values are used. If we use the function, then the dataset includes a new variable called “FUZZ”.

Seealso

You can find a detailed description of the function here.

At first, we have to read raw data.

[4]:
file_path="/tests/data/raw/2022/02/16/2006_20220216_134500.h5"

file_hdf5=xr.open_dataset(file_path,
                          engine="odim",
                          group="dataset1",
                          backend_kwargs=dict(reindex_angle=1.0))
display(file_hdf5)
<xarray.Dataset>
Dimensions:     (azimuth: 720, range: 936)
Coordinates:
  * azimuth     (azimuth) float64 0.25 0.75 1.25 1.75 ... 358.8 359.2 359.8
    elevation   (azimuth) float64 0.5 0.5 0.5 0.5 0.5 ... 0.5 0.5 0.5 0.5 0.5
    rtime       (azimuth) datetime64[ns] 2022-02-16T13:45:28.941817600 ... 20...
  * range       (range) float32 37.5 112.5 187.5 ... 7.009e+04 7.016e+04
    time        datetime64[ns] 2022-02-16T13:45:01
    sweep_mode  <U20 'azimuth_surveillance'
    longitude   float64 13.24
    latitude    float64 53.55
    altitude    float64 38.0
Data variables:
    RATE        (azimuth, range) float32 ...
    DBZH        (azimuth, range) float32 ...
    VRAD        (azimuth, range) float32 ...
    ZDR         (azimuth, range) float32 ...
    KDP         (azimuth, range) float32 ...
    PHIDP       (azimuth, range) float32 ...
    RHOHV       (azimuth, range) float32 ...
    WRAD        (azimuth, range) float32 ...
    QC_INFO     (azimuth, range) float32 ...
Attributes:
    fixed_angle:  0.5

We extracted the boolean data array from the clutter map.

[5]:
cmap_static_bool = cmap_static.DBZH_sum_bool

Now we can use the function fuzzy_echo_classification.

[6]:
ds_fuzz=wrf.clutter.fuzzy_echo_classification(ds=file_hdf5,
                                              cmap=cmap_static_bool,
                                              dims=["azimuth", "range"])
display(ds_fuzz)
<xarray.Dataset>
Dimensions:     (azimuth: 720, range: 936)
Coordinates:
  * azimuth     (azimuth) float64 0.25 0.75 1.25 1.75 ... 358.8 359.2 359.8
    elevation   (azimuth) float64 0.5 0.5 0.5 0.5 0.5 ... 0.5 0.5 0.5 0.5 0.5
    rtime       (azimuth) datetime64[ns] 2022-02-16T13:45:28.941817600 ... 20...
  * range       (range) float32 37.5 112.5 187.5 ... 7.009e+04 7.016e+04
    time        datetime64[ns] 2022-02-16T13:45:01
    sweep_mode  <U20 'azimuth_surveillance'
    longitude   float64 13.24
    latitude    float64 53.55
    altitude    float64 38.0
Data variables:
    RATE        (azimuth, range) float32 ...
    DBZH        (azimuth, range) float32 nan nan nan 23.0 ... -32.0 -32.0 -32.0
    VRAD        (azimuth, range) float32 nan nan nan 0.0 ... -35.0 nan nan nan
    ZDR         (azimuth, range) float32 nan nan nan ... 0.587 0.4894 -0.2914
    KDP         (azimuth, range) float32 ...
    PHIDP       (azimuth, range) float32 nan nan nan 9.844 ... 18.28 40.78 9.844
    RHOHV       (azimuth, range) float32 nan nan nan ... 0.1494 0.2291 0.4382
    WRAD        (azimuth, range) float32 ...
    QC_INFO     (azimuth, range) float32 ...
    FUZZ        (azimuth, range) bool False False False ... False False False
Attributes:
    fixed_angle:  0.5

Note

The function works also for a xarray dataset which is linking over the time and for SCN/SCNX files. Before you can use the function with SCN/SCNX files, you have to rename a variable.

Now we plot the static clutter map on the left and the “FUZZ” clutter map on the right.

[7]:
import matplotlib.pyplot as plt

# georefenced dataset for plot
ds_fuzz_georef=ds_fuzz.pipe(wrl.georef.georeference_dataset)

# plot
fig = plt.figure(figsize=(14, 5))

# first subplot
ax1 = fig.add_subplot(121)
cmap_static_georef.DBZH_sum_bool.plot(x="x", y="y", ax=ax1)
t = plt.title(r'Static clutter map')
t.set_y(1.1)

# second subplot
ax2 = fig.add_subplot(122)
ds_fuzz_georef.FUZZ.plot(x="x", y="y", ax=ax2)
t = plt.title(r'FUZZY clutter map')
t.set_y(1.1)
../_images/jupyter_notebooks_clutter_detection_18_0.png

Remove clutter

Now we want to remove the clutter in the raw reflectivity. Therefore, we use the function dbzh_no_clutter. This function set as clutter identified pixels (in the above plot the yellow points) to NaN values. So we exclude clutter pixels from further processing steps. If we use the function, then the dataset includes a new variable called “DBZH_no_clutter”.

[8]:
ds_no_clutter=wrf.clutter.dbzh_no_clutter(ds=ds_fuzz,
                                          dims=['azimuth', 'range'])
display(ds_no_clutter)
<xarray.Dataset>
Dimensions:          (azimuth: 720, range: 936)
Coordinates: (12/15)
  * azimuth          (azimuth) float64 0.25 0.75 1.25 1.75 ... 358.8 359.2 359.8
    elevation        (azimuth) float64 0.5 0.5 0.5 0.5 0.5 ... 0.5 0.5 0.5 0.5
    rtime            (azimuth) datetime64[ns] 2022-02-16T13:45:28.941817600 ....
  * range            (range) float32 37.5 112.5 187.5 ... 7.009e+04 7.016e+04
    time             datetime64[ns] 2022-02-16T13:45:01
    sweep_mode       <U20 'azimuth_surveillance'
    ...               ...
    x                (azimuth, range) float64 0.1636 0.4909 ... -305.8 -306.1
    y                (azimuth, range) float64 37.5 112.5 ... 7.008e+04 7.015e+04
    z                (azimuth, range) float64 38.3 38.95 39.61 ... 939.2 940.3
    gr               (azimuth, range) float64 37.5 112.5 ... 7.008e+04 7.015e+04
    rays             (azimuth, range) float64 0.25 0.25 0.25 ... 359.8 359.8
    bins             (azimuth, range) float32 37.5 112.5 ... 7.009e+04 7.016e+04
Data variables:
    RATE             (azimuth, range) float32 ...
    DBZH             (azimuth, range) float32 nan nan nan ... -32.0 -32.0 -32.0
    VRAD             (azimuth, range) float32 nan nan nan 0.0 ... nan nan nan
    ZDR              (azimuth, range) float32 nan nan nan ... 0.4894 -0.2914
    KDP              (azimuth, range) float32 ...
    PHIDP            (azimuth, range) float32 nan nan nan ... 18.28 40.78 9.844
    RHOHV            (azimuth, range) float32 nan nan nan ... 0.2291 0.4382
    WRAD             (azimuth, range) float32 ...
    QC_INFO          (azimuth, range) float32 ...
    FUZZ             (azimuth, range) bool False False False ... False False
    DBZH_no_clutter  (azimuth, range) float32 nan nan nan ... -32.0 -32.0 -32.0
Attributes:
    fixed_angle:  0.5

Note

The function works also for a xarray dataset which is linking over the time and for SCN/SCNX files.

Here we plot the reflecivity before and after clutter correction.

[9]:
import matplotlib.pyplot as plt

# georefenced dataset for plot
ds_no_clutter_georef=ds_no_clutter.pipe(wrl.georef.georeference_dataset)

# plot
fig = plt.figure(figsize=(14, 5))

# first subplot
ax1 = fig.add_subplot(121)
ds_no_clutter_georef.DBZH.plot(x="x", y="y", ax=ax1)
t = plt.title(r'Raw reflectivity')
t.set_y(1.1)

# second subplot
ax2 = fig.add_subplot(122)
ds_no_clutter_georef.DBZH_no_clutter.plot(x="x", y="y", ax=ax2)
t = plt.title(r'Clutter corrected reflectivity')
t.set_y(1.1)
../_images/jupyter_notebooks_clutter_detection_24_0.png

The result shows that we still have noise in the reflectivity. We can remove the noise with the variable RHOHV, which is a good indicator of noise. Is RHOHV < 0.9 then it is no rain but noise.

[10]:
ds_no_clutter=ds_no_clutter.where(ds_no_clutter.RHOHV>0.9)
[11]:
import matplotlib.pyplot as plt

# georefenced dataset for plot
ds_no_clutter_georef=ds_no_clutter.pipe(wrl.georef.georeference_dataset)

ds_no_clutter_georef.DBZH.plot(x="x", y="y")
t = plt.title(r'Clutter and RHOHV corrected reflectivity')
t.set_y(1.1)
../_images/jupyter_notebooks_clutter_detection_27_0.png

Library Reference

Seealso

Get more information about the clutter module in the library reference section.