Hydrometeorclassification - PPI#

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.

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

  • PPI 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_20141007T0245_20141007T0250_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: 138MB
Dimensions:            (azimuth: 360, range: 1000)
Coordinates: (12/22)
  * azimuth            (azimuth) float64 3kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
    elevation          (azimuth) float64 3kB ...
    time               (azimuth) datetime64[ns] 3kB ...
  * range              (range) float32 4kB 50.0 150.0 ... 9.985e+04 9.995e+04
    x                  (azimuth, range) float64 3MB ...
    y                  (azimuth, range) float64 3MB ...
    ...                 ...
    crs_wkt            int64 8B ...
    band               int64 8B ...
    spatial_ref        int64 8B ...
    stdev              float64 8B ...
    NOISE_LEVEL        float64 8B ...
    alpha              float64 8B ...
Data variables: (12/55)
    KDP                (azimuth, range) float32 1MB ...
    PHIDP              (azimuth, range) float32 1MB ...
    DBZH               (azimuth, range) float32 1MB ...
    DBZV               (azimuth, range) float32 1MB ...
    RHOHV              (azimuth, range) float32 1MB ...
    DBTH               (azimuth, range) float32 1MB ...
    ...                 ...
    AH                 (azimuth, range) float64 3MB ...
    KDP_AH             (azimuth, range) float64 3MB ...
    PHIDP_CORR5        (azimuth, range) float64 3MB ...
    DBTH_CORR5         (azimuth, range) float64 3MB ...
    DBZH_CORR5         (azimuth, range) float64 3MB ...
    ZDR_CORR5          (azimuth, range) float64 3MB ...

Convective#

filename = "/radar/rp-data/workflow/tmp_20130701T1540_20130701T1545_workflow.nc"
with rp.rpol_data.open(filename) as f:
    filename = f.name
sweep_c = xr.open_dataset(filename)
display(sweep_c)
<xarray.Dataset> Size: 138MB
Dimensions:            (azimuth: 360, range: 1000)
Coordinates: (12/22)
  * azimuth            (azimuth) float64 3kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
    elevation          (azimuth) float64 3kB ...
    time               (azimuth) datetime64[ns] 3kB ...
  * range              (range) float32 4kB 50.0 150.0 ... 9.985e+04 9.995e+04
    x                  (azimuth, range) float64 3MB ...
    y                  (azimuth, range) float64 3MB ...
    ...                 ...
    crs_wkt            int64 8B ...
    band               int64 8B ...
    spatial_ref        int64 8B ...
    stdev              float64 8B ...
    NOISE_LEVEL        float64 8B ...
    alpha              float64 8B ...
Data variables: (12/55)
    KDP                (azimuth, range) float32 1MB ...
    PHIDP              (azimuth, range) float32 1MB ...
    DBZH               (azimuth, range) float32 1MB ...
    DBZV               (azimuth, range) float32 1MB ...
    RHOHV              (azimuth, range) float32 1MB ...
    DBTH               (azimuth, range) float32 1MB ...
    ...                 ...
    AH                 (azimuth, range) float64 3MB ...
    KDP_AH             (azimuth, range) float64 3MB ...
    PHIDP_CORR5        (azimuth, range) float64 3MB ...
    DBTH_CORR5         (azimuth, range) float64 3MB ...
    DBZH_CORR5         (azimuth, range) float64 3MB ...
    ZDR_CORR5          (azimuth, range) float64 3MB ...

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)
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)
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: 144MB
Dimensions:            (azimuth: 360, range: 1000)
Coordinates: (12/23)
  * azimuth            (azimuth) float64 3kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
    elevation          (azimuth) float64 3kB ...
    time               (azimuth) datetime64[ns] 3kB ...
  * range              (range) float32 4kB 50.0 150.0 ... 9.985e+04 9.995e+04
    x                  (azimuth, range) float64 3MB ...
    y                  (azimuth, range) float64 3MB ...
    ...                 ...
    crs_wkt            int64 8B ...
    band               int64 8B ...
    spatial_ref        int64 8B ...
    stdev              float64 8B ...
    NOISE_LEVEL        float64 8B ...
    alpha              float64 8B ...
Data variables: (12/56)
    KDP                (azimuth, range) float32 1MB ...
    PHIDP              (azimuth, range) float32 1MB ...
    DBZH               (azimuth, range) float32 1MB ...
    DBZV               (azimuth, range) float32 1MB ...
    RHOHV              (azimuth, range) float32 1MB ...
    DBTH               (azimuth, range) float32 1MB ...
    ...                 ...
    KDP_AH             (azimuth, range) float64 3MB ...
    PHIDP_CORR5        (azimuth, range) float64 3MB ...
    DBTH_CORR5         (azimuth, range) float64 3MB ...
    DBZH_CORR5         (azimuth, range) float64 3MB ...
    ZDR_CORR5          (azimuth, range) float64 3MB ...
    TEMP               (azimuth, range) float64 3MB 15.0 15.0 ... -10.29 -10.33
<xarray.Dataset> Size: 144MB
Dimensions:            (azimuth: 360, range: 1000)
Coordinates: (12/23)
  * azimuth            (azimuth) float64 3kB 0.5 1.5 2.5 ... 357.5 358.5 359.5
    elevation          (azimuth) float64 3kB ...
    time               (azimuth) datetime64[ns] 3kB ...
  * range              (range) float32 4kB 50.0 150.0 ... 9.985e+04 9.995e+04
    x                  (azimuth, range) float64 3MB ...
    y                  (azimuth, range) float64 3MB ...
    ...                 ...
    crs_wkt            int64 8B ...
    band               int64 8B ...
    spatial_ref        int64 8B ...
    stdev              float64 8B ...
    NOISE_LEVEL        float64 8B ...
    alpha              float64 8B ...
Data variables: (12/56)
    KDP                (azimuth, range) float32 1MB ...
    PHIDP              (azimuth, range) float32 1MB ...
    DBZH               (azimuth, range) float32 1MB ...
    DBZV               (azimuth, range) float32 1MB ...
    RHOHV              (azimuth, range) float32 1MB ...
    DBTH               (azimuth, range) float32 1MB ...
    ...                 ...
    KDP_AH             (azimuth, range) float64 3MB ...
    PHIDP_CORR5        (azimuth, range) float64 3MB ...
    DBTH_CORR5         (azimuth, range) float64 3MB ...
    DBZH_CORR5         (azimuth, range) float64 3MB ...
    ZDR_CORR5          (azimuth, range) float64 3MB ...
    TEMP               (azimuth, range) float64 3MB 17.4 17.4 ... -12.64 -12.67

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, azimuth: 360,
                                     range: 1000, trapezoid: 4)> Size: 634MB
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, 360, 1000, 4))
Coordinates: (12/25)
  * hmc          (hmc) <U2 88B 'LR' 'MR' 'HR' 'LD' 'HL' ... 'DS' 'WS' 'HC' 'VC'
  * obs          (obs) object 40B 'ZH' 'ZDR' 'RHO' 'KDP' 'TEMP'
  * azimuth      (azimuth) float64 3kB 0.5 1.5 2.5 3.5 ... 357.5 358.5 359.5
    elevation    (azimuth) float64 3kB 2.395 2.395 2.395 ... 2.395 2.395 2.395
    time         (azimuth) datetime64[ns] 3kB 2013-07-01T15:43:26 ... 2013-07...
  * range        (range) float32 4kB 50.0 150.0 250.0 ... 9.985e+04 9.995e+04
    ...           ...
    crs_wkt      int64 8B 0
    band         int64 8B 1
    spatial_ref  int64 8B 0
    stdev        float64 8B 0.00471
    NOISE_LEVEL  float64 8B -27.0
    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 137 ms, sys: 162 ms, total: 299 ms
Wall time: 298 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, azimuth: 360, range: 1000)> Size: 158MB
dask.array<xarray-<this-array>, shape=(11, 5, 360, 1000), dtype=float64, chunksize=(1, 5, 360, 1000), chunktype=numpy.ndarray>
Coordinates: (12/25)
  * hmc          (hmc) <U2 88B 'LR' 'MR' 'HR' 'LD' 'HL' ... 'DS' 'WS' 'HC' 'VC'
  * obs          (obs) object 40B 'ZH' 'ZDR' 'RHO' 'KDP' 'TEMP'
  * azimuth      (azimuth) float64 3kB 0.5 1.5 2.5 3.5 ... 357.5 358.5 359.5
    elevation    (azimuth) float64 3kB dask.array<chunksize=(360,), meta=np.ndarray>
    time         (azimuth) datetime64[ns] 3kB dask.array<chunksize=(360,), meta=np.ndarray>
  * range        (range) float32 4kB 50.0 150.0 250.0 ... 9.985e+04 9.995e+04
    ...           ...
    crs_wkt      int64 8B 0
    band         int64 8B 1
    spatial_ref  int64 8B 0
    stdev        float64 8B 0.00471
    NOISE_LEVEL  float64 8B -27.0
    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, azimuth: 360, range: 1000)> Size: 32MB
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, 360, 1000))
Coordinates: (12/24)
  * hmc          (hmc) <U2 88B 'LR' 'MR' 'HR' 'LD' 'HL' ... 'DS' 'WS' 'HC' 'VC'
  * azimuth      (azimuth) float64 3kB 0.5 1.5 2.5 3.5 ... 357.5 358.5 359.5
    elevation    (azimuth) float64 3kB 2.395 2.395 2.395 ... 2.395 2.395 2.395
    time         (azimuth) datetime64[ns] 3kB 2013-07-01T15:43:26 ... 2013-07...
  * range        (range) float32 4kB 50.0 150.0 250.0 ... 9.985e+04 9.995e+04
    x            (azimuth, range) float64 3MB 0.4359 1.308 ... -870.1 -871.0
    ...           ...
    crs_wkt      int64 8B 0
    band         int64 8B 1
    spatial_ref  int64 8B 0
    stdev        float64 8B 0.00471
    NOISE_LEVEL  float64 8B -27.0
    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, azimuth: 360, range: 1000)> Size: 35MB
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, 360, 1000))
Coordinates: (12/24)
  * hmc          (hmc) <U2 96B 'LR' 'MR' 'HR' 'LD' 'HL' ... 'WS' 'HC' 'VC' 'NP'
  * azimuth      (azimuth) float64 3kB 0.5 1.5 2.5 3.5 ... 357.5 358.5 359.5
    elevation    (azimuth) float64 3kB 2.395 2.395 2.395 ... 2.395 2.395 2.395
    time         (azimuth) datetime64[ns] 3kB 2013-07-01T15:43:26 ... 2013-07...
  * range        (range) float32 4kB 50.0 150.0 250.0 ... 9.985e+04 9.995e+04
    x            (azimuth, range) float64 3MB 0.4359 1.308 ... -870.1 -871.0
    ...           ...
    crs_wkt      int64 8B 0
    band         int64 8B 1
    spatial_ref  int64 8B 0
    stdev        float64 8B 0.00471
    NOISE_LEVEL  float64 8B -27.0
    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.assign_coords(hmc=np.array(list(pr_types.values())).T[1][:11])
score = score.where(score > 0)
score.plot(
    x="x",
    y="y",
    col="hmc",
    col_wrap=4,
    cmap="HomeyerRainbow",
    cbar_kwargs=dict(label="Score"),
    subplot_kws=dict(xlim=(-100e3, 100e3), ylim=(-100e3, 100e3), xlabel="Range (m)"),
)
<xarray.plot.facetgrid.FacetGrid at 0x7f4102c782f0>
../../_images/0c7e57ed4494bab0ca664efaf960f28ed0deff482995c666140024c2ad0a992e.png

Plot maximum score#

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

fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111)
cl_res.max("hmc").plot(
    x="x", y="y", cmap="HomeyerRainbow", ax=ax, cbar_kwargs=dict(label="Score")
)
ax.set_xlabel("Range [m]")
ax.set_ylabel("Range [m]")
ax.set_xlim(-100e3, 100e3)
ax.set_ylim(-100e3, 100e3)
t = ax.set_title("Hydrometeorclassification")

t.set_y(1.1)
../../_images/1d01096515c6b1100c2d0447f961dfdf098a665beaba1ac19aa4d35aee525a69.png

Plot classification result#

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

display(hydro)
<xarray.DataArray (azimuth: 360, range: 1000)> Size: 3MB
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=(360, 1000))
Coordinates: (12/23)
  * azimuth      (azimuth) float64 3kB 0.5 1.5 2.5 3.5 ... 357.5 358.5 359.5
    elevation    (azimuth) float64 3kB 2.395 2.395 2.395 ... 2.395 2.395 2.395
    time         (azimuth) datetime64[ns] 3kB 2013-07-01T15:43:26 ... 2013-07...
  * range        (range) float32 4kB 50.0 150.0 250.0 ... 9.985e+04 9.995e+04
    x            (azimuth, range) float64 3MB 0.4359 1.308 ... -870.1 -871.0
    y            (azimuth, range) float64 3MB 49.95 149.9 ... 9.97e+04 9.98e+04
    ...           ...
    crs_wkt      int64 8B 0
    band         int64 8B 1
    spatial_ref  int64 8B 0
    stdev        float64 8B 0.00471
    NOISE_LEVEL  float64 8B -27.0
    alpha        float64 8B 0.28
Attributes:
    long_name:  Hydrometeorclassification
hmc = rp.visdict14["HMC"]
cmap = hmc["cmap"]
norm = hmc["norm"]
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111)

# prepare colorbar
cbar_kwargs = dict(ticks=hmc["ticks"], norm=norm, extend="neither")
im = hydro.plot(
    x="x",
    y="y",
    ax=ax,
    levels=hmc["ticks"],
    cmap=hmc["cmap"],
    norm=norm,
    cbar_kwargs=cbar_kwargs,
    xlim=(-100e3, 100e3),
    ylim=(-100e3, 100e3),
)
# override colorbar ticklabels
labels = pr_types.values()  # [i][1] for i, _ in enumerate(pr_types)]
labels = im.colorbar.ax.set_yticklabels(labels)
../../_images/cc23aba5e049af0f2d97a801fe03032d598aa6ccf7629e213247a3492e6feb0e.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="x", y="y", xlim=(-100e3, 100e3), ylim=(-100e3, 100e3), cmap="HomeyerRainbow"
)

fig = plt.figure(figsize=(16, 20))
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/d984142d63c1948c7aa31efbcbfc787c620c5b281dff22a47f46681bde8ae814.png