Skip to article frontmatterSkip to article content

Attenuation correction comparison with wradlib

Comparison between BALTRAD and wradlib attenuation correction

Retrieve data from s3 bucket

import os
import urllib.request
from pathlib import Path

# Set the URL for the cloud
URL = "https://js2.jetstream-cloud.org:8001/"
path = "pythia/radar/erad2024/baltrad/baltrad2wradlib/"
!mkdir -p data
!mkdir -p shp
files = [
    "data/201405190715_SUR.h5",
    "shp/europe_countries.dbf",
    "shp/europe_countries.prj",
    "shp/europe_countries.sbn",
    "shp/europe_countries.sbx",
    "shp/europe_countries.shp",
    "shp/europe_countries.shx",
]
for file in files:
    file0 = os.path.join(path, Path(file).name)
    if not os.path.exists(file):
        print(f"downloading, {file}")
        x = urllib.request.urlretrieve(f"{URL}{file0}", file)

Prepare your environment

%matplotlib inline
import gc

import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import numpy as np
import shapefile
import wradlib
import xradar as xd
from matplotlib.collections import PatchCollection
from matplotlib.patches import Polygon

Run BALTRAD’s odc_toolbox

First, you will process a scan from Suergavere (Estland) by using BALTRAD’s odc_toolbox.

From your VM’s vagrant directory, navigate to the folder /baltrad2wradlib.

Execute the following command:

$ odc_toolbox -i data -o out -q ropo,radvol-att

Check whether a file was created in the folder /out.

BALTRAD will not create output files if these already exist. You can check that via !ls out.

!odc_toolbox --help
!odc_toolbox -i data -o out -q ropo,radvol-att
!ls out

Read and inspect data from Suergavere (Estonia) before and after QC with odc_toolbox

# Before QC
inp = xd.io.open_odim_datatree("data/201405190715_SUR.h5")
# After QC
out = xd.io.open_odim_datatree("out/201405190715_SUR.h5")

Georeference

inp = inp.xradar.georeference()
out = out.xradar.georeference()
swp_inp = inp["sweep_0"].ds.set_coords("sweep_mode")
swp_out = out["sweep_0"].ds.set_coords("sweep_mode")
display(swp_inp)
display(swp_out)

Design a plot we will use for all PPIs in this exercise

import cartopy.crs as ccrs
import wradlib as wrl
from cartopy.io.shapereader import Reader

map_proj = ccrs.AzimuthalEquidistant(
    central_latitude=swp_inp.latitude.values, central_longitude=swp_inp.longitude.values
)
osr_proj = wrl.georef.create_osr(
    "aeqd", lat_0=swp_inp.latitude.values, lon_0=swp_inp.longitude.values
)

geometries = list(Reader("shp/europe_countries.shp").geometries())


def plot_ppi_to_ax(ppi, ax, title="", geometries=None, **kwargs):
    pm = ppi.wrl.vis.plot(crs=map_proj, ax=ax, **kwargs)
    ax.set_title(title)
    if geometries is not None:
        ax.add_geometries(
            geometries,
            ccrs.PlateCarree(),
            facecolor="lightgrey",
            edgecolor="k",
            linewidths=1,
            zorder=-1,
        )
    wrl.vis.plot_ppi_crosshair(
        site=(ppi.longitude.values, ppi.latitude.values, ppi.altitude.values),
        ranges=[50000, 100000, 150000, 200000, ppi.range.max().values],
        angles=[0, 90, 180, 270],
        line=dict(color="white"),
        circle={"edgecolor": "white"},
        ax=ax,
        crs=osr_proj,
    )
    return pm

Plot the selected fields into one figure

fig = plt.figure(figsize=(12, 10))

ax = plt.subplot(221, projection=map_proj)
pm = plot_ppi_to_ax(
    swp_inp.DBZH.where(swp_inp.DBZH >= -10),
    ax=ax,
    geometries=geometries,
    title="Before QC",
    add_colorbar=False,
    vmin=-10,
    vmax=65,
)

ax = plt.subplot(222, projection=map_proj)
pm = plot_ppi_to_ax(
    swp_out.DBZH.where(swp_out.DBZH >= -10),
    ax=ax,
    geometries=geometries,
    title="After QC",
    add_colorbar=False,
    vmin=-10,
    vmax=65,
)

ax = plt.subplot(223, projection=map_proj)
qm = plot_ppi_to_ax(
    swp_out.quality1,
    ax=ax,
    geometries=geometries,
    add_colorbar=False,
    title="Quality 1",
)

ax = plt.subplot(224, projection=map_proj)
qm = plot_ppi_to_ax(
    swp_out.QIND, ax=ax, geometries=geometries, add_colorbar=False, title="Quality 2"
)

plt.tight_layout()

# Add colorbars
fig.subplots_adjust(right=0.9)
cax = fig.add_axes((0.9, 0.6, 0.03, 0.3))
cbar = plt.colorbar(pm, cax=cax)
cbar.set_label("Horizontal reflectivity (dBZ)", fontsize="large")

cax = fig.add_axes((0.9, 0.1, 0.03, 0.3))
cbar = plt.colorbar(qm, cax=cax)
cbar.set_label("Quality index", fontsize="large")

Collect and plot the polarimetric moments from the original ODIM_H5 dataset

fig = plt.figure(figsize=(12, 12))

ax = plt.subplot(221, projection=map_proj)
pm = plot_ppi_to_ax(swp_inp.RHOHV, ax=ax, title="RhoHV", geometries=geometries)

ax = plt.subplot(222, projection=map_proj)
pm = plot_ppi_to_ax(swp_inp.PHIDP, ax=ax, title="PhiDP", geometries=geometries)

ax = plt.subplot(223, projection=map_proj)
pm = plot_ppi_to_ax(
    swp_inp.ZDR, ax=ax, title="Differential reflectivity", geometries=geometries
)

ax = plt.subplot(224, projection=map_proj)
pm = plot_ppi_to_ax(
    swp_inp.VRAD, ax=ax, title="Doppler velocity", geometries=geometries
)

plt.tight_layout()

Try some filtering and attenuation correction

# Set ZH to a very low value where we do not expect valid data
zh = swp_inp.DBZH.fillna(-32.0)
# Retrieve PIA by using some constraints (see https://docs.wradlib.org/en/latest/notebooks/attenuation/attenuation.html for help)
pia = zh.wrl.atten.correct_attenuation_constrained(
    constraints=[wradlib.atten.constraint_dbz, wradlib.atten.constraint_pia],
    constraint_args=[[64.0], [20.0]],
)

# Correct reflectivity by PIA
zh_corrected = swp_inp.DBZH + pia

Compare results against QC from odc_toolbox

fig = plt.figure(figsize=(18, 10))

ax = plt.subplot(131, projection=map_proj)
pm = plot_ppi_to_ax(
    swp_inp.DBZH.where(swp_out.DBZH >= -10),
    ax=ax,
    geometries=geometries,
    title="Before QC",
)

ax = plt.subplot(132, projection=map_proj)
pm = plot_ppi_to_ax(
    swp_out.DBZH.where(swp_out.DBZH >= -10),
    ax=ax,
    geometries=geometries,
    title="After QC using BALTRAD Toolbox",
)

ax = plt.subplot(133, projection=map_proj)
pm = plot_ppi_to_ax(
    zh_corrected.where(zh_corrected >= -10),
    ax=ax,
    geometries=geometries,
    title="After QC using wradlib",
)