Hydrometeorclassification - RHI#

The hydrometeorclassification code is based on the paper by Zrnic et.al 2001 utilizing 2D trapezoidal membership functions based on the paper by Straka et. al 2000 adapted by Evaristo et. al 2013 for X-Band.

  • RHI Stratiform (2014-10-07 02:45)

  • RHI Convective (2013-07-01 15:40)

import datetime as dt

import matplotlib.pyplot as plt
import numpy as np
import wradlib as wrl
import xarray as xr

Utility Functions#

import radarpolarimetry as rp

Precipitation Types#

pr_types = dict(wrl.classify.pr_types.values())
for k, v in enumerate(pr_types.items()):
    print(f"{k:02} {' - '.join(v)}")
00 LR - Light Rain
01 MR - Moderate Rain
02 HR - Heavy Rain
03 LD - Large Drops
04 HL - Hail
05 RH - Rain/Hail
06 GH - Graupel/Hail
07 DS - Dry Snow
08 WS - Wet Snow
09 HC - H Crystals
10 VC - V Crystals
11 NP - No Precip

Load 2D Membership Functions#

filename = "/radar/wradlib-data/misc/msf_xband_v1.nc"
with rp.rpol_data.open(filename) as f:
    filename = f.name
msf = xr.open_dataset(filename)
display(msf)
<xarray.Dataset> Size: 97kB
Dimensions:  (hmc: 11, idp: 55, trapezoid: 4)
Coordinates:
  * hmc      (hmc) <U2 88B 'LR' 'MR' 'HR' 'LD' 'HL' ... 'GH' 'DS' 'WS' 'HC' 'VC'
  * idp      (idp) float64 440B -10.0 -8.0 -6.0 -4.0 ... 92.0 94.0 96.0 98.0
Dimensions without coordinates: trapezoid
Data variables:
    ZH       (hmc, idp, trapezoid) float64 19kB ...
    ZDR      (hmc, idp, trapezoid) float64 19kB ...
    RHO      (hmc, idp, trapezoid) float64 19kB ...
    KDP      (hmc, idp, trapezoid) float64 19kB ...
    TEMP     (hmc, idp, trapezoid) float64 19kB ...
Attributes:
    version:      1
    title:        2D Membershipfunctions Hydrometeorclassification for XBand
    institution:  Institute of Geosciences, Meteorology Section, University o...
    history:      created by Raquel Evaristo, adapted to netCDF by Kai Mühlbauer
    comment:      created with wradlib

Stratiform#

filename = "/radar/rp-data/workflow/tmp_20141007T0120_20141007T0125_workflow.nc"
with rp.rpol_data.open(filename) as f:
    filename = f.name
sweep_s = xr.open_dataset(filename)
display(sweep_s)
<xarray.Dataset> Size: 101MB
Dimensions:            (elevation: 450, range: 667)
Coordinates: (12/18)
  * elevation          (elevation) float64 4kB 0.1 0.3 0.5 ... 89.5 89.7 89.9
    azimuth            (elevation) float64 4kB ...
    time               (elevation) datetime64[ns] 4kB ...
  * range              (range) float32 3kB 37.5 112.5 ... 4.991e+04 4.999e+04
    x                  (elevation, range) float64 2MB ...
    y                  (elevation, range) float64 2MB ...
    ...                 ...
    latitude           float64 8B ...
    altitude           float64 8B ...
    crs_wkt            int64 8B ...
    stdev              float64 8B ...
    NOISE_LEVEL        float64 8B ...
    alpha              float64 8B ...
Data variables: (12/51)
    KDP                (elevation, range) float32 1MB ...
    PHIDP              (elevation, range) float32 1MB ...
    DBZH               (elevation, range) float32 1MB ...
    DBZV               (elevation, range) float32 1MB ...
    RHOHV              (elevation, range) float32 1MB ...
    DBTH               (elevation, range) float32 1MB ...
    ...                 ...
    AH                 (elevation, range) float64 2MB ...
    KDP_AH             (elevation, range) float64 2MB ...
    PHIDP_CORR5        (elevation, range) float64 2MB ...
    DBTH_CORR5         (elevation, range) float64 2MB ...
    DBZH_CORR5         (elevation, range) float64 2MB ...
    ZDR_CORR5          (elevation, range) float64 2MB ...

Convective#

filename = "/radar/rp-data/workflow/tmp_20130701T1530_20130701T1600_workflow.nc"
with rp.rpol_data.open(filename) as f:
    filename = f.name
sweep_c = xr.open_dataset(
    filename,
    chunks=dict(time2=1),
).isel(time2=2)
display(sweep_c)
<xarray.Dataset> Size: 94MB
Dimensions:            (elevation: 450, range: 667)
Coordinates: (12/19)
  * elevation          (elevation) float64 4kB 0.1 0.3 0.5 ... 89.5 89.7 89.9
    azimuth            (elevation) float64 4kB dask.array<chunksize=(450,), meta=np.ndarray>
    time               (elevation) datetime64[ns] 4kB dask.array<chunksize=(450,), meta=np.ndarray>
  * range              (range) float32 3kB 37.5 112.5 ... 4.991e+04 4.999e+04
    x                  (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    y                  (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    ...                 ...
    latitude           float64 8B ...
    altitude           float64 8B ...
    crs_wkt            int64 8B ...
    stdev              float64 8B ...
    NOISE_LEVEL        float64 8B ...
    alpha              float64 8B ...
Data variables: (12/51)
    KDP                (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    PHIDP              (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    DBZH               (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    DBZV               (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    RHOHV              (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    DBTH               (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    ...                 ...
    AH                 (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    KDP_AH             (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    PHIDP_CORR5        (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    DBTH_CORR5         (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    DBZH_CORR5         (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    ZDR_CORR5          (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>

Load Sounding Data#

# http://weather.uwyo.edu/upperair/sounding.html
rs_time_s = dt.datetime(2014, 10, 7, 2, 0)
rs_time_c = dt.datetime(2013, 7, 1, 12, 0)
print(rs_time_s)
date = rs_time_s
year = date.strftime("%Y")
month = date.strftime("%m")
day = date.strftime("%d")
hour = date.strftime("%H")
print(year, month, day, hour)
import urllib

try:
    rs_data_s, rs_meta_s = wrl.io.get_radiosonde(10410, rs_time_s, cols=(0, 1, 2))
    rs_data_c, rs_meta_c = wrl.io.get_radiosonde(10410, rs_time_c, cols=(0, 1, 2))
    print("downloaded from UWYO")
except urllib.error.HTTPError:
    raise
print(rs_meta_s, rs_meta_c)
2014-10-07 02:00:00
2014 10 07 02
downloaded from UWYO
{'Station identifier': 'EDZE', 'Station number': 10410, 'Observation time': datetime.datetime(2014, 10, 7, 0, 0), 'Station latitude': 51.4, 'Station longitude': 6.97, 'Station elevation': 147.0, 'Showalter index': 7.79, 'Lifted index': 4.55, 'LIFT computed using virtual temperature': 4.63, 'SWEAT index': 204.28, 'K index': 22.9, 'Cross totals index': 14.7, 'Vertical totals index': 24.7, 'Totals totals index': 39.4, 'Convective Available Potential Energy': 28.92, 'CAPE using virtual temperature': 36.38, 'Convective Inhibition': -70.37, 'CINS using virtual temperature': -11.48, 'Equilibrum Level': 689.06, 'Equilibrum Level using virtual temperature': 688.7, 'Level of Free Convection': 766.58, 'LFCT using virtual temperature': 881.01, 'Bulk Richardson Number': 1.33, 'Bulk Richardson Number using CAPV': 1.68, 'Temp [K] of the Lifted Condensation Level': 282.6, 'Pres [hPa] of the Lifted Condensation Level': 913.15, 'Equivalent potential temp [K] of the LCL': 313.42, 'Mean mixed layer potential temperature': 290.05, 'Mean mixed layer mixing ratio': 8.2, '1000 hPa to 500 hPa thickness': 5547.0, 'Precipitable water [mm] for entire sounding': 24.77, 'quantity': {'PRES': 'hPa', 'HGHT': 'm', 'TEMP': 'C'}} {'Station identifier': 'EDZE', 'Station number': 10410, 'Observation time': datetime.datetime(2013, 7, 1, 12, 0), 'Station latitude': 51.4, 'Station longitude': 6.97, 'Station elevation': 147.0, 'Showalter index': 6.1, 'Lifted index': 0.57, 'LIFT computed using virtual temperature': 0.51, 'SWEAT index': 77.7, 'K index': 11.7, 'Cross totals index': 13.7, 'Vertical totals index': 28.7, 'Totals totals index': 42.4, 'Convective Available Potential Energy': 7.03, 'CAPE using virtual temperature': 18.0, 'Convective Inhibition': 0.0, 'CINS using virtual temperature': 0.0, 'Equilibrum Level': 597.47, 'Equilibrum Level using virtual temperature': 589.23, 'Level of Free Convection': 931.56, 'LFCT using virtual temperature': 934.17, 'Bulk Richardson Number': 0.24, 'Bulk Richardson Number using CAPV': 0.62, 'Temp [K] of the Lifted Condensation Level': 284.17, 'Pres [hPa] of the Lifted Condensation Level': 934.17, 'Equivalent potential temp [K] of the LCL': 315.07, 'Mean mixed layer potential temperature': 289.76, 'Mean mixed layer mixing ratio': 8.92, '1000 hPa to 500 hPa thickness': 5543.0, 'Precipitable water [mm] for entire sounding': 19.02, 'quantity': {'PRES': 'hPa', 'HGHT': 'm', 'TEMP': 'C'}}

Extract Temperature Profile#

itemp_s = rp.get_temperature_profile(rs_data_s)
itemp_c = rp.get_temperature_profile(rs_data_c)

Plot Temperature Profile#

fig = plt.figure(figsize=(2.5, 5))
ax = fig.add_subplot(111)
itemp_s.plot(y="height", ax=ax, zorder=0, label="stratiform")
itemp_c.plot(y="height", ax=ax, zorder=0, label="convective")
plt.legend()
ax.grid(True)
../../_images/d7500ea3ef918a80281bbe15f055bd2b75b13bd3cc9377deaf592c791969a010.png

Merge Temperature Profile#

hmc_s = sweep_s.pipe(rp.merge_radar_profile, itemp_s)
hmc_c = sweep_c.pipe(rp.merge_radar_profile, itemp_c)
display(hmc_s)
display(hmc_c)
<xarray.Dataset> Size: 106MB
Dimensions:            (elevation: 450, range: 667)
Coordinates: (12/19)
  * elevation          (elevation) float64 4kB 0.1 0.3 0.5 ... 89.5 89.7 89.9
    azimuth            (elevation) float64 4kB ...
    time               (elevation) datetime64[ns] 4kB ...
  * range              (range) float32 3kB 37.5 112.5 ... 4.991e+04 4.999e+04
    x                  (elevation, range) float64 2MB ...
    y                  (elevation, range) float64 2MB ...
    ...                 ...
    latitude           float64 8B ...
    altitude           float64 8B ...
    crs_wkt            int64 8B ...
    stdev              float64 8B ...
    NOISE_LEVEL        float64 8B ...
    alpha              float64 8B ...
Data variables: (12/52)
    KDP                (elevation, range) float32 1MB ...
    PHIDP              (elevation, range) float32 1MB ...
    DBZH               (elevation, range) float32 1MB ...
    DBZV               (elevation, range) float32 1MB ...
    RHOHV              (elevation, range) float32 1MB ...
    DBTH               (elevation, range) float32 1MB ...
    ...                 ...
    KDP_AH             (elevation, range) float64 2MB ...
    PHIDP_CORR5        (elevation, range) float64 2MB ...
    DBTH_CORR5         (elevation, range) float64 2MB ...
    DBZH_CORR5         (elevation, range) float64 2MB ...
    ZDR_CORR5          (elevation, range) float64 2MB ...
    TEMP               (elevation, range) float64 2MB 15.0 15.0 15.0 ... nan nan
<xarray.Dataset> Size: 98MB
Dimensions:            (elevation: 450, range: 667)
Coordinates: (12/20)
  * elevation          (elevation) float64 4kB 0.1 0.3 0.5 ... 89.5 89.7 89.9
    azimuth            (elevation) float64 4kB dask.array<chunksize=(450,), meta=np.ndarray>
    time               (elevation) datetime64[ns] 4kB dask.array<chunksize=(450,), meta=np.ndarray>
  * range              (range) float32 3kB 37.5 112.5 ... 4.991e+04 4.999e+04
    x                  (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    y                  (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    ...                 ...
    latitude           float64 8B ...
    altitude           float64 8B ...
    crs_wkt            int64 8B ...
    stdev              float64 8B ...
    NOISE_LEVEL        float64 8B ...
    alpha              float64 8B ...
Data variables: (12/52)
    KDP                (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    PHIDP              (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    DBZH               (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    DBZV               (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    RHOHV              (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    DBTH               (elevation, range) float32 1MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    ...                 ...
    KDP_AH             (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    PHIDP_CORR5        (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    DBTH_CORR5         (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    DBZH_CORR5         (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    ZDR_CORR5          (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>
    TEMP               (elevation, range) float64 2MB dask.array<chunksize=(450, 667), meta=np.ndarray>

HMC Workflow#

switch between stratiform and convective processing here

hmc_ds = hmc_s.copy()
# hmc_ds = hmc_c.copy()
# unify masks
hmc_ds = hmc_ds.where(
    ~np.isnan(hmc_ds.DBZH_CORR1)
    & ~np.isnan(hmc_ds.ZDR_CORR1)
    & ~np.isnan(hmc_ds.RHOHV_NC)
    & ~np.isnan(hmc_ds.KDP_VULP)
    & ~np.isnan(hmc_ds.TEMP)
)

Setup Independent Observable \(Z_H\)#

Retrieve membership function values based on independent observable

%%time
msf_val = msf.wrl.classify.msf_index_indep(hmc_ds.DBZH_CORR1)
display(msf_val)
<xarray.DataArray 'msf_index_indep' (hmc: 11, obs: 5, elevation: 450,
                                     range: 667, trapezoid: 4)> Size: 528MB
array([[[[[0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          ...,
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.]],

         [[0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          ...,
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.]],

         [[0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          ...,
...
          ...,
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.]],

         [[0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          ...,
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.]],

         [[0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          ...,
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.]]]]], shape=(11, 5, 450, 667, 4))
Coordinates: (12/21)
  * hmc          (hmc) <U2 88B 'LR' 'MR' 'HR' 'LD' 'HL' ... 'DS' 'WS' 'HC' 'VC'
  * obs          (obs) object 40B 'ZH' 'ZDR' 'RHO' 'KDP' 'TEMP'
  * elevation    (elevation) float64 4kB 0.1 0.3 0.5 0.7 ... 89.3 89.5 89.7 89.9
    azimuth      (elevation) float64 4kB 225.0 225.0 225.0 ... 225.0 225.0 225.0
    time         (elevation) datetime64[ns] 4kB 2014-10-07T01:20:02 ... 2014-...
  * range        (range) float32 3kB 37.5 112.5 187.5 ... 4.991e+04 4.999e+04
    ...           ...
    latitude     float64 8B 50.73
    altitude     float64 8B 99.5
    crs_wkt      int64 8B 0
    stdev        float64 8B 0.003062
    NOISE_LEVEL  float64 8B -19.6
    alpha        float64 8B 0.28
Dimensions without coordinates: trapezoid
Attributes:
    version:      1
    title:        2D Membershipfunctions Hydrometeorclassification for XBand
    institution:  Institute of Geosciences, Meteorology Section, University o...
    history:      created by Raquel Evaristo, adapted to netCDF by Kai Mühlbauer
    comment:      created with wradlib
CPU times: user 191 ms, sys: 133 ms, total: 323 ms
Wall time: 323 ms

Fuzzyfication#

fu = msf_val.wrl.classify.fuzzyfi(
    hmc_ds,
    dict(ZH="DBZH_CORR1", ZDR="ZDR_CORR1", RHO="RHOHV_NC", KDP="KDP_VULP", TEMP="TEMP"),
)
fu = fu.chunk({"hmc": 1})
display(fu)
<xarray.DataArray 'fuzzyfi' (hmc: 11, obs: 5, elevation: 450, range: 667)> Size: 132MB
dask.array<xarray-<this-array>, shape=(11, 5, 450, 667), dtype=float64, chunksize=(1, 5, 450, 667), chunktype=numpy.ndarray>
Coordinates: (12/21)
  * hmc          (hmc) <U2 88B 'LR' 'MR' 'HR' 'LD' 'HL' ... 'DS' 'WS' 'HC' 'VC'
  * obs          (obs) object 40B 'ZH' 'ZDR' 'RHO' 'KDP' 'TEMP'
  * elevation    (elevation) float64 4kB 0.1 0.3 0.5 0.7 ... 89.3 89.5 89.7 89.9
    azimuth      (elevation) float64 4kB dask.array<chunksize=(450,), meta=np.ndarray>
    time         (elevation) datetime64[ns] 4kB dask.array<chunksize=(450,), meta=np.ndarray>
  * range        (range) float32 3kB 37.5 112.5 187.5 ... 4.991e+04 4.999e+04
    ...           ...
    latitude     float64 8B 50.73
    altitude     float64 8B 99.5
    crs_wkt      int64 8B 0
    stdev        float64 8B 0.003062
    NOISE_LEVEL  float64 8B -19.6
    alpha        float64 8B 0.28
Attributes:
    version:      1
    title:        2D Membershipfunctions Hydrometeorclassification for XBand
    institution:  Institute of Geosciences, Meteorology Section, University o...
    history:      created by Raquel Evaristo, adapted to netCDF by Kai Mühlbauer
    comment:      created with wradlib

Score#

# weights dataset
w = xr.Dataset(dict(ZH=2.0, ZDR=1.0, RHO=1.0, KDP=1.0, TEMP=1.0))
display(w)
<xarray.Dataset> Size: 40B
Dimensions:  ()
Data variables:
    ZH       float64 8B 2.0
    ZDR      float64 8B 1.0
    RHO      float64 8B 1.0
    KDP      float64 8B 1.0
    TEMP     float64 8B 1.0
score = fu.wrl.classify.probability(w).compute()
display(score)
<xarray.DataArray (hmc: 11, elevation: 450, range: 667)> Size: 26MB
array([[[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]],

       [[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]],

       [[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
...
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]],

       [[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]],

       [[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]]], shape=(11, 450, 667))
Coordinates: (12/20)
  * hmc          (hmc) <U2 88B 'LR' 'MR' 'HR' 'LD' 'HL' ... 'DS' 'WS' 'HC' 'VC'
  * elevation    (elevation) float64 4kB 0.1 0.3 0.5 0.7 ... 89.3 89.5 89.7 89.9
    azimuth      (elevation) float64 4kB 225.0 225.0 225.0 ... 225.0 225.0 225.0
    time         (elevation) datetime64[ns] 4kB 2014-10-07T01:20:02 ... 2014-...
  * range        (range) float32 3kB 37.5 112.5 187.5 ... 4.991e+04 4.999e+04
    x            (elevation, range) float64 2MB -26.52 -79.55 ... -61.24 -61.33
    ...           ...
    latitude     float64 8B 50.73
    altitude     float64 8B 99.5
    crs_wkt      int64 8B 0
    stdev        float64 8B 0.003062
    NOISE_LEVEL  float64 8B -19.6
    alpha        float64 8B 0.28
Attributes:
    version:      1
    title:        2D Membershipfunctions Hydrometeorclassification for XBand
    institution:  Institute of Geosciences, Meteorology Section, University o...
    history:      created by Raquel Evaristo, adapted to netCDF by Kai Mühlbauer
    comment:      created with wradlib

Classification#

cl_res = score.wrl.classify.classify(threshold=0.0)
display(cl_res)
<xarray.DataArray (hmc: 12, elevation: 450, range: 667)> Size: 29MB
array([[[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]],

       [[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]],

       [[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
...
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]],

       [[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]],

       [[1., 1., 1., ..., 1., 1., 1.],
        [1., 1., 1., ..., 1., 1., 1.],
        [1., 1., 1., ..., 1., 1., 1.],
        ...,
        [1., 1., 1., ..., 1., 1., 1.],
        [1., 1., 1., ..., 1., 1., 1.],
        [1., 1., 1., ..., 1., 1., 1.]]], shape=(12, 450, 667))
Coordinates: (12/20)
  * hmc          (hmc) <U2 96B 'LR' 'MR' 'HR' 'LD' 'HL' ... 'WS' 'HC' 'VC' 'NP'
  * elevation    (elevation) float64 4kB 0.1 0.3 0.5 0.7 ... 89.3 89.5 89.7 89.9
    azimuth      (elevation) float64 4kB 225.0 225.0 225.0 ... 225.0 225.0 225.0
    time         (elevation) datetime64[ns] 4kB 2014-10-07T01:20:02 ... 2014-...
  * range        (range) float32 3kB 37.5 112.5 187.5 ... 4.991e+04 4.999e+04
    x            (elevation, range) float64 2MB -26.52 -79.55 ... -61.24 -61.33
    ...           ...
    latitude     float64 8B 50.73
    altitude     float64 8B 99.5
    crs_wkt      int64 8B 0
    stdev        float64 8B 0.003062
    NOISE_LEVEL  float64 8B -19.6
    alpha        float64 8B 0.28
Attributes:
    version:      1
    title:        2D Membershipfunctions Hydrometeorclassification for XBand
    institution:  Institute of Geosciences, Meteorology Section, University o...
    history:      created by Raquel Evaristo, adapted to netCDF by Kai Mühlbauer
    comment:      created with wradlib

Plot HMC Results#

Plot Score of HMC Types#

score = score.where(score > 0)
score.plot(
    x="gr",
    y="z",
    col="hmc",
    col_wrap=4,
    cmap="HomeyerRainbow",
    cbar_kwargs=dict(label="Score"),
    subplot_kws=dict(ylim=(0, 8000), xlabel="Range (m)"),
)
<xarray.plot.facetgrid.FacetGrid at 0x7fcfc1d97b60>
../../_images/6c7f1d918060dfde531553c48159dfc050c55c263df0ade20bcade164168c52f.png

Plot maximum score#

sort score and calculate difference between the winner and the other classes!

fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111)
cl_res.max("hmc").plot(
    x="gr", y="z", cmap="HomeyerRainbow", ax=ax, cbar_kwargs=dict(label="Score")
)
ax.set_xlabel("Range [m]")
ax.set_ylabel("Range [m]")
ax.set_xlim(0, 20000)
ax.set_ylim(0, 10000)
t = ax.set_title("Hydrometeorclassification")

t.set_y(1.1)
../../_images/0df4b9437a55f61acc9a88e61e577038e457bfd9caa661d86b09111cbd17b879.png

Plot classification result#

hydro = cl_res.argmax("hmc")
hydro.attrs = dict(long_name="Hydrometeorclassification")

display(hydro)
<xarray.DataArray (elevation: 450, range: 667)> Size: 2MB
array([[11, 11, 11, ..., 11, 11, 11],
       [11, 11, 11, ..., 11, 11, 11],
       [11, 11, 11, ..., 11, 11, 11],
       ...,
       [11, 11, 11, ..., 11, 11, 11],
       [11, 11, 11, ..., 11, 11, 11],
       [11, 11, 11, ..., 11, 11, 11]], shape=(450, 667))
Coordinates: (12/19)
  * elevation    (elevation) float64 4kB 0.1 0.3 0.5 0.7 ... 89.3 89.5 89.7 89.9
    azimuth      (elevation) float64 4kB 225.0 225.0 225.0 ... 225.0 225.0 225.0
    time         (elevation) datetime64[ns] 4kB 2014-10-07T01:20:02 ... 2014-...
  * range        (range) float32 3kB 37.5 112.5 187.5 ... 4.991e+04 4.999e+04
    x            (elevation, range) float64 2MB -26.52 -79.55 ... -61.24 -61.33
    y            (elevation, range) float64 2MB -26.52 -79.55 ... -61.24 -61.33
    ...           ...
    latitude     float64 8B 50.73
    altitude     float64 8B 99.5
    crs_wkt      int64 8B 0
    stdev        float64 8B 0.003062
    NOISE_LEVEL  float64 8B -19.6
    alpha        float64 8B 0.28
Attributes:
    long_name:  Hydrometeorclassification
hmc = rp.visdict14["HMC"]
# ticks_hmc = hmc["ticks"]
cmap = hmc["cmap"]
norm = hmc["norm"]
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111)

# prepare colorbar
cbar_kwargs = dict(ticks=hmc["ticks"], norm=norm, extend="neither")
im = hydro.plot(
    x="gr",
    y="z",
    ax=ax,
    levels=hmc["ticks"],
    cmap=hmc["cmap"],
    norm=norm,
    cbar_kwargs=cbar_kwargs,  # xlim=(-80e3, 80e3), ylim=(-80e3, 80e3),
)
# override colorbar ticklabels
labels = pr_types.values()  # ][i][1] for i, _ in enumerate(pr_types)]
labels = im.colorbar.ax.set_yticklabels(labels)
ax.set_xlim(0, 20000)
ax.set_ylim(0, 10000)
(0.0, 10000.0)
../../_images/1d53b0249f3d9c3f4e9baf54765fedb87b3d10aa4520d337b67f54dade06ca21.png
zlevels = rp.visdict14["ZH"]["ticks"]
zdrlevels = rp.visdict14["ZDR"]["ticks"]
rholevels = rp.visdict14["RHO"]["ticks"]
kdplevels = rp.visdict14["KDP"]["ticks"]
philevels = rp.visdict14["PHI"]["ticks"]
hmclevels = rp.visdict14["HMC"]["ticks"]
levels = lambda x: dict(levels=x, cbar_kwargs=dict(ticks=x))
_kwargs = dict(x="gr", y="z", xlim=(0, 25000), ylim=(0, 8000), cmap="HomeyerRainbow")

fig = plt.figure(figsize=(16, 8))
ax1 = fig.add_subplot(321)
kwargs = _kwargs | levels(zlevels) | dict(ax=ax1)
hmc_ds.DBZH_CORR1.plot.contourf(**kwargs)
ax1.set_title(hmc_ds.DBZH_CORR1.attrs["long_name"])
ax2 = fig.add_subplot(322)
zdrlevels2 = np.arange(0, 5, 0.2)
kwargs = _kwargs | levels(zdrlevels2) | dict(ax=ax2)
hmc_ds.ZDR_CORR1.plot.contourf(**kwargs)
ax2.set_title(hmc_ds.ZDR_CORR1.attrs["long_name"])
ax3 = fig.add_subplot(323)
kwargs = _kwargs | levels(rholevels) | dict(ax=ax3)
hmc_ds.RHOHV_NC.plot.contourf(**kwargs)
ax3.set_title(hmc_ds.RHOHV_NC.attrs["long_name"])
ax4 = fig.add_subplot(324)
# philevels2 = np.arange(0, 15, 1)
# kwargs = _kwargs | levels(philevels2) | dict(ax=ax4)
# hmc_ds.PHIDP_CORR1.plot.contourf(**kwargs)
# ax4.set_title(hmc_ds.PHIDP_CORR2.attrs["long_name"])
kwargs = _kwargs | levels(kdplevels) | dict(ax=ax4)
hmc_ds.KDP_VULP.plot(**kwargs)
ax4.set_title(hmc_ds.KDP_VULP.attrs["long_name"])

ax5 = fig.add_subplot(325)
templevels = None
kwargs = _kwargs | levels(templevels) | dict(ax=ax5) | dict(cmap="seismic")
hmc_ds.TEMP.plot(**kwargs)
ax5.set_title(hmc_ds.TEMP.attrs["long_name"])

ax6 = fig.add_subplot(326)
cbar_kwargs = dict(ticks=hmc["ticks"], norm=hmc["norm"], extend="neither")
kwargs = (
    _kwargs
    | levels(hmclevels)
    | dict(ax=ax6)
    | dict(norm=hmc["norm"], cmap=hmc["cmap"])
)
im = hydro.plot(**kwargs)
ax6.set_title(hydro.attrs["long_name"])
# override colorbar ticklabels
labels = pr_types.values()  # [i][1] for i, _ in enumerate(pr_types)]
labels = im.colorbar.ax.set_yticklabels(labels)

fig.tight_layout()
../../_images/434fe65bb8aeec7877685d5b027990713cb08a45e511ebd285191984b3a6e371.png