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.98Construct 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 ... FalsePlot 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()