Clutter detection by using space-born cloud images#

import matplotlib.pyplot as plt
import numpy as np
import wradlib as wrl
import wradlib_data
import xarray as xr
import xradar as xd
from IPython.display import display
from osgeo import osr

Read the radar data into DataTree#

# read the radar volume scan
filename = "hdf5/20130429043000.rad.bewid.pvol.dbzh.scan1.hdf"
filename = wradlib_data.DATASETS.fetch(filename)
pvol = xd.io.open_odim_datatree(filename)
display(pvol)
Downloading file 'hdf5/20130429043000.rad.bewid.pvol.dbzh.scan1.hdf' from 'https://github.com/wradlib/wradlib-data/raw/main/data/hdf5/20130429043000.rad.bewid.pvol.dbzh.scan1.hdf' to '/home/docs/.cache/wradlib-data'.
<xarray.DataTree>
Group: /
β”‚   Dimensions:              (sweep: 5)
β”‚   Coordinates:
β”‚       latitude             float64 8B ...
β”‚       longitude            float64 8B ...
β”‚       altitude             float64 8B ...
β”‚   Dimensions without coordinates: sweep
β”‚   Data variables:
β”‚       volume_number        int64 8B 0
β”‚       platform_type        <U5 20B 'fixed'
β”‚       instrument_type      <U5 20B 'radar'
β”‚       time_coverage_start  <U20 80B '2013-04-29T04:30:00Z'
β”‚       time_coverage_end    <U20 80B '2013-04-29T04:31:39Z'
β”‚       sweep_fixed_angle    (sweep) float64 40B 0.3 0.9 1.8 3.3 6.0
β”‚       sweep_group_name     (sweep) int64 40B 0 1 2 3 4
β”‚   Attributes:
β”‚       Conventions:      ODIM_H5/V2_2
β”‚       instrument_name:  None
β”‚       version:          None
β”‚       title:            None
β”‚       institution:      None
β”‚       references:       None
β”‚       source:           None
β”‚       history:          None
β”‚       comment:          im/exported using xradar
β”œβ”€β”€ Group: /sweep_0
β”‚       Dimensions:            (azimuth: 360, range: 960)
β”‚       Coordinates:
β”‚         * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
β”‚           elevation          (azimuth) float64 3kB ...
β”‚           time               (azimuth) datetime64[ns] 3kB 2013-04-29T04:30:00.02777...
β”‚         * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
β”‚       Data variables:
β”‚           DBZH               (azimuth, range) float64 3MB ...
β”‚           sweep_mode         <U20 80B ...
β”‚           sweep_number       int64 8B ...
β”‚           prt_mode           <U7 28B ...
β”‚           follow_mode        <U7 28B ...
β”‚           sweep_fixed_angle  float64 8B ...
β”‚           nyquist_velocity   float64 8B ...
β”œβ”€β”€ Group: /sweep_1
β”‚       Dimensions:            (azimuth: 360, range: 960)
β”‚       Coordinates:
β”‚         * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
β”‚           elevation          (azimuth) float64 3kB ...
β”‚           time               (azimuth) datetime64[ns] 3kB 2013-04-29T04:30:20.02777...
β”‚         * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
β”‚       Data variables:
β”‚           DBZH               (azimuth, range) float64 3MB ...
β”‚           sweep_mode         <U20 80B ...
β”‚           sweep_number       int64 8B ...
β”‚           prt_mode           <U7 28B ...
β”‚           follow_mode        <U7 28B ...
β”‚           sweep_fixed_angle  float64 8B ...
β”‚           nyquist_velocity   float64 8B ...
β”œβ”€β”€ Group: /sweep_2
β”‚       Dimensions:            (azimuth: 360, range: 960)
β”‚       Coordinates:
β”‚         * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
β”‚           elevation          (azimuth) float64 3kB ...
β”‚           time               (azimuth) datetime64[ns] 3kB 2013-04-29T04:30:40.02777...
β”‚         * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
β”‚       Data variables:
β”‚           DBZH               (azimuth, range) float64 3MB ...
β”‚           sweep_mode         <U20 80B ...
β”‚           sweep_number       int64 8B ...
β”‚           prt_mode           <U7 28B ...
β”‚           follow_mode        <U7 28B ...
β”‚           sweep_fixed_angle  float64 8B ...
β”‚           nyquist_velocity   float64 8B ...
β”œβ”€β”€ Group: /sweep_3
β”‚       Dimensions:            (azimuth: 360, range: 960)
β”‚       Coordinates:
β”‚         * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
β”‚           elevation          (azimuth) float64 3kB ...
β”‚           time               (azimuth) datetime64[ns] 3kB 2013-04-29T04:31:00.02777...
β”‚         * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
β”‚       Data variables:
β”‚           DBZH               (azimuth, range) float64 3MB ...
β”‚           sweep_mode         <U20 80B ...
β”‚           sweep_number       int64 8B ...
β”‚           prt_mode           <U7 28B ...
β”‚           follow_mode        <U7 28B ...
β”‚           sweep_fixed_angle  float64 8B ...
β”‚           nyquist_velocity   float64 8B ...
└── Group: /sweep_4
        Dimensions:            (azimuth: 360, range: 960)
        Coordinates:
          * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
            elevation          (azimuth) float64 3kB ...
            time               (azimuth) datetime64[ns] 3kB 2013-04-29T04:31:20.02777...
          * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
        Data variables:
            DBZH               (azimuth, range) float64 3MB ...
            sweep_mode         <U20 80B ...
            sweep_number       int64 8B ...
            prt_mode           <U7 28B ...
            follow_mode        <U7 28B ...
            sweep_fixed_angle  float64 8B ...
            nyquist_velocity   float64 8B ...

Georeference sweeps#

pvol1 = pvol.match("sweep*")
display(pvol1)
vol = []
for sweep in pvol1:
    vol.append(pvol[sweep].to_dataset(inherit="all_coords").pipe(wrl.georef.georeference))
vol = xr.concat(vol, dim="tilt")
vol = vol.assign_coords(sweep_mode=vol.sweep_mode)
display(vol)
<xarray.DataTree>
Group: /
β”œβ”€β”€ Group: /sweep_0
β”‚       Dimensions:            (azimuth: 360, range: 960)
β”‚       Coordinates:
β”‚         * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
β”‚           elevation          (azimuth) float64 3kB ...
β”‚           time               (azimuth) datetime64[ns] 3kB 2013-04-29T04:30:00.02777...
β”‚         * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
β”‚       Data variables:
β”‚           DBZH               (azimuth, range) float64 3MB ...
β”‚           sweep_mode         <U20 80B ...
β”‚           sweep_number       int64 8B ...
β”‚           prt_mode           <U7 28B ...
β”‚           follow_mode        <U7 28B ...
β”‚           sweep_fixed_angle  float64 8B ...
β”‚           nyquist_velocity   float64 8B ...
β”œβ”€β”€ Group: /sweep_1
β”‚       Dimensions:            (azimuth: 360, range: 960)
β”‚       Coordinates:
β”‚         * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
β”‚           elevation          (azimuth) float64 3kB ...
β”‚           time               (azimuth) datetime64[ns] 3kB 2013-04-29T04:30:20.02777...
β”‚         * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
β”‚       Data variables:
β”‚           DBZH               (azimuth, range) float64 3MB ...
β”‚           sweep_mode         <U20 80B ...
β”‚           sweep_number       int64 8B ...
β”‚           prt_mode           <U7 28B ...
β”‚           follow_mode        <U7 28B ...
β”‚           sweep_fixed_angle  float64 8B ...
β”‚           nyquist_velocity   float64 8B ...
β”œβ”€β”€ Group: /sweep_2
β”‚       Dimensions:            (azimuth: 360, range: 960)
β”‚       Coordinates:
β”‚         * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
β”‚           elevation          (azimuth) float64 3kB ...
β”‚           time               (azimuth) datetime64[ns] 3kB 2013-04-29T04:30:40.02777...
β”‚         * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
β”‚       Data variables:
β”‚           DBZH               (azimuth, range) float64 3MB ...
β”‚           sweep_mode         <U20 80B ...
β”‚           sweep_number       int64 8B ...
β”‚           prt_mode           <U7 28B ...
β”‚           follow_mode        <U7 28B ...
β”‚           sweep_fixed_angle  float64 8B ...
β”‚           nyquist_velocity   float64 8B ...
β”œβ”€β”€ Group: /sweep_3
β”‚       Dimensions:            (azimuth: 360, range: 960)
β”‚       Coordinates:
β”‚         * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
β”‚           elevation          (azimuth) float64 3kB ...
β”‚           time               (azimuth) datetime64[ns] 3kB 2013-04-29T04:31:00.02777...
β”‚         * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
β”‚       Data variables:
β”‚           DBZH               (azimuth, range) float64 3MB ...
β”‚           sweep_mode         <U20 80B ...
β”‚           sweep_number       int64 8B ...
β”‚           prt_mode           <U7 28B ...
β”‚           follow_mode        <U7 28B ...
β”‚           sweep_fixed_angle  float64 8B ...
β”‚           nyquist_velocity   float64 8B ...
└── Group: /sweep_4
        Dimensions:            (azimuth: 360, range: 960)
        Coordinates:
          * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
            elevation          (azimuth) float64 3kB ...
            time               (azimuth) datetime64[ns] 3kB 2013-04-29T04:31:20.02777...
          * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
        Data variables:
            DBZH               (azimuth, range) float64 3MB ...
            sweep_mode         <U20 80B ...
            sweep_number       int64 8B ...
            prt_mode           <U7 28B ...
            follow_mode        <U7 28B ...
            sweep_fixed_angle  float64 8B ...
            nyquist_velocity   float64 8B ...
<xarray.Dataset> Size: 72MB
Dimensions:            (tilt: 5, azimuth: 360, range: 960)
Coordinates: (12/15)
    sweep_mode         (tilt) <U20 400B 'azimuth_surveillance' ... 'azimuth_s...
  * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
    elevation          (tilt, azimuth) float64 14kB 0.3 0.3 0.3 ... 6.0 6.0 6.0
    time               (tilt, azimuth) datetime64[ns] 14kB 2013-04-29T04:30:0...
  * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
    x                  (tilt, azimuth, range) float64 14MB 1.091 ... -2.075e+03
    ...                 ...
    rays               (azimuth, range) float32 1MB 0.5 0.5 0.5 ... 359.5 359.5
    bins               (azimuth, range) float32 1MB 125.0 375.0 ... 2.399e+05
    latitude           float64 8B 49.91
    longitude          float64 8B 5.506
    altitude           float64 8B 592.0
    crs_wkt            int64 8B 0
Dimensions without coordinates: tilt
Data variables:
    DBZH               (tilt, azimuth, range) float64 14MB -32.0 -32.0 ... -32.0
    sweep_number       (tilt) int64 40B 0 1 2 3 4
    prt_mode           (tilt) <U7 140B 'not_set' 'not_set' ... 'not_set'
    follow_mode        (tilt) <U7 140B 'not_set' 'not_set' ... 'not_set'
    sweep_fixed_angle  (tilt) float64 40B 0.3 0.9 1.8 3.3 6.0
    nyquist_velocity   (tilt) float64 40B 7.98 7.98 7.98 7.98 7.98

Construct collocated satellite data#

proj_radar = osr.SpatialReference()
proj_radar.ImportFromWkt(vol.crs_wkt.attrs["crs_wkt"])
0
filename = "hdf5/SAFNWC_MSG3_CT___201304290415_BEL_________.h5"
filename = wradlib_data.DATASETS.fetch(filename)
Downloading file 'hdf5/SAFNWC_MSG3_CT___201304290415_BEL_________.h5' from 'https://github.com/wradlib/wradlib-data/raw/main/data/hdf5/SAFNWC_MSG3_CT___201304290415_BEL_________.h5' to '/home/docs/.cache/wradlib-data'.
sat_gdal = wrl.io.read_safnwc(filename)
val_sat = wrl.georef.read_gdal_values(sat_gdal)
coord_sat = wrl.georef.read_gdal_coordinates(sat_gdal)
proj_sat = wrl.georef.read_gdal_projection(sat_gdal)
coord_sat = wrl.georef.reproject(coord_sat, src_crs=proj_sat, trg_crs=proj_radar)
coord_radar = np.stack((vol.x, vol.y), axis=-1)
coord_sat[..., 0:2].reshape(-1, 2).shape, coord_radar[..., 0:2].reshape(-1, 2).shape
((180000, 2), (1728000, 2))
interp = wrl.ipol.Nearest(
    coord_sat[..., 0:2].reshape(-1, 2), coord_radar[..., 0:2].reshape(-1, 2)
)
val_sat = interp(val_sat.ravel()).reshape(coord_radar.shape[:-1])

Estimate localisation errors#

timelag = 9 * 60
wind = 10
error = np.absolute(timelag) * wind

Identify clutter based on collocated cloudtype#

rscale = vol.range.diff("range").median().values
clutter = wrl.classify.filter_cloudtype(
    vol.DBZH, val_sat, scale=rscale, smoothing=error
)

Assign to vol#

vol = vol.assign(sat=(["tilt", "azimuth", "range"], val_sat))
vol = vol.assign(clutter=(["tilt", "azimuth", "range"], clutter.values))
display(vol)
<xarray.Dataset> Size: 75MB
Dimensions:            (tilt: 5, azimuth: 360, range: 960)
Coordinates: (12/15)
    sweep_mode         (tilt) <U20 400B 'azimuth_surveillance' ... 'azimuth_s...
  * azimuth            (azimuth) float32 1kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
    elevation          (tilt, azimuth) float64 14kB 0.3 0.3 0.3 ... 6.0 6.0 6.0
    time               (tilt, azimuth) datetime64[ns] 14kB 2013-04-29T04:30:0...
  * range              (range) float32 4kB 125.0 375.0 ... 2.396e+05 2.399e+05
    x                  (tilt, azimuth, range) float64 14MB 1.091 ... -2.075e+03
    ...                 ...
    rays               (azimuth, range) float32 1MB 0.5 0.5 0.5 ... 359.5 359.5
    bins               (azimuth, range) float32 1MB 125.0 375.0 ... 2.399e+05
    latitude           float64 8B 49.91
    longitude          float64 8B 5.506
    altitude           float64 8B 592.0
    crs_wkt            int64 8B 0
Dimensions without coordinates: tilt
Data variables:
    DBZH               (tilt, azimuth, range) float64 14MB -32.0 -32.0 ... -32.0
    sweep_number       (tilt) int64 40B 0 1 2 3 4
    prt_mode           (tilt) <U7 140B 'not_set' 'not_set' ... 'not_set'
    follow_mode        (tilt) <U7 140B 'not_set' 'not_set' ... 'not_set'
    sweep_fixed_angle  (tilt) float64 40B 0.3 0.9 1.8 3.3 6.0
    nyquist_velocity   (tilt) float64 40B 7.98 7.98 7.98 7.98 7.98
    sat                (tilt, azimuth, range) uint8 2MB 6 6 6 6 ... 10 10 10 10
    clutter            (tilt, azimuth, range) bool 2MB False False ... False

Plot the results#

fig = plt.figure(figsize=(16, 8))

tilt = 0

ax = fig.add_subplot(131)
pm = vol.DBZH[tilt].wrl.vis.plot(ax=ax)
# plt.colorbar(pm, shrink=0.5)
plt.title("Radar reflectivity")

ax = fig.add_subplot(132)
pm = vol.sat[tilt].wrl.vis.plot(ax=ax)
# plt.colorbar(pm, shrink=0.5)
plt.title("Satellite cloud classification")

ax = fig.add_subplot(133)
pm = vol.clutter[tilt].wrl.vis.plot(ax=ax)
# plt.colorbar(pm, shrink=0.5)
plt.title("Detected clutter")

fig.tight_layout()
../../_images/8592be1e8171ad8b9e035f0bbd668f477a37e8333227c8e99f237ac59e7af099.png