KTLX rainfall and KDP case · Single-case demonstration
Ten KTLX Level-II volumes spanning 01:33:08–02:27:56 UTC on 29 April 2021 were processed for specific differential phase (KDP), reconstructed into storm-following vertical cross sections, and paired with MRMS surface rainfall at a fixed point near Norman, Oklahoma. This page reports what came out; the figures and the tables carry the detail.
Under the strict quality-control mask, the first KDP column reaching 1 ° km−1 within 5 km of the tracked core occurs at 01:50:19 UTC. MRMS rainfall at the fixed point begins at 02:02 UTC, and the peak 15-minute accumulation ends at 02:14 UTC. The three volumes before 01:50 extend radar coverage back to 01:33:08 — 28.9 minutes before rainfall onset — and contain no gate meeting the strict column threshold. Under the permissive mask, which admits lower ρHV gates, elevated KDP appears earlier.
Convection moved across the Norman, Oklahoma area late on 28 April into early 29 April 2021, producing a flood report at 20:05 CST (02:05 UTC). The event was warned operationally: NWS Norman issued Flash Flood Warning event 10 at 01:53 UTC for McClain and northwestern Cleveland Counties, valid to 05:00 UTC, naming Norman, Moore, Newcastle, Goldsby, and southern Oklahoma City. The archived product records it as radar-indicated and states that flash flooding was ongoing or expected shortly, with another 1–2 inches possible. The analysis window here, 01:48–02:28 UTC, came from an automated screening pass and was accepted after manual review of corrected radar quick looks.
| Time UTC | Event | Source |
|---|---|---|
| 01:33:08 | First antecedent radar volume | KTLX Level II |
| 01:50:19 | First strict-QC KDP column ≥ 1 ° km−1 | This analysis |
| 01:53 | NWS Norman Flash Flood Warning issued (radar-indicated) | NWS archive |
| 02:02 | MRMS rainfall onset at fixed target | MRMS |
| 02:06 | Instantaneous target rain rate reaches 150 mm h−1 | MRMS |
| 02:14 | Peak 15-minute accumulation ends (13.92 mm) | MRMS |
| 02:28 | Peak 30-minute accumulation ends (15.20 mm) | MRMS |
These are MRMS radar-derived totals at a single fixed pixel plus a 5-by-5-pixel neighbourhood. No return-period statistics were computed and no gauge comparison was made, so the totals stand on their own without a rarity or verification claim attached.
Vertical structure was reconstructed as KTLX pseudo-RHIs — vertical cross sections assembled from PPI volume scans, not true operational RHI scans. The panels below are radar-centered: zero range is KTLX and the dashed line marks the moving tracked core. This view keeps the changing range and azimuth visible: over the sequence the tracked core moves from 43.64 km to 6.39 km and back to 14.18 km, so the set of elevations sampled above it changes from volume to volume.
Metrics are computed within 5 km horizontally of the tracked core and below 12 km MSL. A missing threshold-top value means no valid selected gate met that threshold; it does not mean a zero-kilometre column.
| Time UTC | Strict KDP p95 (° km−1) | KDP ≥ 1 top | KDP ≥ 2 top | 40 dBZ top |
|---|---|---|---|---|
| 01:33 | 0.68 | none | none | 9.58 km |
| 01:38 | 0.73 | none | none | 9.58 km |
| 01:44 | 0.67 | none | none | 10.45 km |
| 01:50 | 1.19 | 6.54 km | 6.54 km | 9.36 km |
| 01:55 | 2.20 | 6.06 km | 6.00 km | 7.10 km |
| 02:02 | 4.58 | 3.59 km | 3.10 km | 4.93 km |
| 02:08 | 2.94 | 2.71 km | 2.05 km | 3.59 km |
| 02:14 | 4.56 | 3.18 km | 2.84 km | 3.01 km |
| 02:21 | 5.15 | 2.70 km | 2.70 km | 4.31 km |
| 02:28 | 3.31 | 5.32 km | 5.32 km | 7.02 km |
Radar is KTLX S-band WSR-88D Level II from the public unidata-nexrad-level2
S3 bucket. The full inventory covers 40 volumes from 00:00–04:00 UTC; the
demonstration sequence uses the 10 volumes from 01:33:08–02:27:56 UTC. Native fields
used are reflectivity, differential reflectivity, differential phase, and
cross-correlation ratio. KDP is calculated from native KTLX differential phase;
MRMS is never used as a KDP source.
Rainfall context comes from MRMS PrecipRate, RadarOnly_QPE_01H, and RadarQualityIndex
(public noaa-mrms-pds bucket) at 2-minute resolution, over
34.8–35.6 °N and 98.0–96.8 °W, with a fixed verification
point at 35.22 °N, 97.44 °W. Missing intervals are not filled with zero.
Rain rate is integrated by the trapezoidal rule only when both segment endpoints are
finite and the gap is no longer than 5 minutes. The accumulation map is masked where
temporal coverage falls below 90 %.
KTLX changed scan strategy within the window, with 16–23 sweeps per volume, so sweep indices are never copied between volumes. For each volume, every sweep is inspected for coverage of the four required fields; repeated elevations are grouped when fixed angles differ by no more than 0.1°; groups missing required dual-polarization fields are excluded; and within each repeated-elevation group the sweep maximizing the minimum valid fraction among required fields is selected.
Specific differential phase is one half of the range derivative of differential phase, KDP = ½ dΦDP/dr, reported in ° km−1. It responds to liquid-water content and drop-size distribution while being less affected by attenuation and calibration than reflectivity.
Retrieval uses Py-ART 2.3.0 pyart.retrieve.kdp_maesaka in native polar
coordinates, one selected sweep at a time, with Clpf=1.0,
first_guess=0.01, and finite_order="low". System phase is
estimated independently for each sweep with det_sys_phase_gf using the
permissive gate filter and first_gate=30. Returned KDP is
explicitly remasked after retrieval, because passing a Py-ART GateFilter does not
guarantee the returned Maesaka array retains every QC exclusion. Missing and excluded
gates stay masked; they are never converted to zero KDP.
| Mask | Reflectivity | ρHV | Finiteness |
|---|---|---|---|
| Strict (primary) | ≥ 20 dBZ | ≥ 0.95 | Z, ρHV, ΦDP all finite |
| Permissive (sensitivity) | ≥ 20 dBZ | ≥ 0.90 | Z, ρHV, ΦDP all finite |
| Value | Meaning |
|---|---|
| 1 | no data or nonfinite required input |
| 2 | reflectivity below 20 dBZ |
| 4 | ρHV below 0.90 |
| 8 | ρHV below 0.95 |
| 16 | possible mixed-phase or hail gate: reflectivity passes but ρHV is below 0.95 |
ρHV describes the correlation between horizontally and vertically polarized returns. Values near one generally indicate a more uniform scatterer population. Lower values can occur with hail, melting or mixed-phase particles, biological targets, low signal-to-noise ratio, sidelobes, or nonuniform beam filling. It is a quality indicator, not a unique hail detector.
The tracked object is a range-area-weighted reflectivity centroid computed on the lowest selected dual-polarization sweep: gates at or above 45 dBZ within 20 km of the previous target, each weighted by radar range multiplied by (reflectivity − 45 dBZ + 1) to reduce polar sampling-area bias.
The seven targets from 01:50–02:28 UTC were reviewed against reflectivity overlays and accepted. The 01:33, 01:38, and 01:44 UTC targets are an objective backward extension anchored to the accepted 01:50 target, with backward steps of 6.47–6.92 km, well within the 20 km search radius. The ten locations are therefore not all independently manually reviewed, and the three antecedent extensions should be read as such.
For each volume the azimuth from KTLX to the tracked centroid is computed; at every
dynamically selected elevation the nearest PPI ray to that azimuth is selected; the
section is rejected if any nearest-ray offset exceeds 1°; and the section is built
with pyart.util.cross_section_ppi, preserving native fields and masks in a
CF/Radial NetCDF output. The largest observed nearest-ray offset is 0.484°.
The storm-centered horizontal coordinate is xstorm = √(xradar² + yradar²) − Rtarget, so zero marks the tracked core. Height is geometric gate height plus radar altitude, shown in kilometres MSL. Sections span ±20 km around the target and up to 12 km MSL.
The 02:02 UTC lowest selected sweep (0.483°) was processed with the same strict mask using Maesaka, Vulpiani, and Schneebeli retrievals. All three use S-band settings; Vulpiani and Schneebeli additionally use Py-ART's ρHV-aware phase prefilter. Only gates valid in each method and in Maesaka are compared.
| Method | Correlation | Median |diff| (° km−1) | Notes |
|---|---|---|---|
| Vulpiani | 0.619 | 0.072 | Retains the enhancement but smoother and larger (p95 0.772 vs Maesaka 0.424); permits negative KDP. |
| Schneebeli (default) | 0.024 | 0.211 | 756 nonfinite unmasked gates and extreme outliers; not suitable here without tuning. |
Maesaka is the retrieval used everywhere else in this report; the other two were run only on this one sweep for comparison. The optional LP/Sobel phase product was also attempted and hit infeasible solver behaviour, so it produced no usable field here.
Three KDP fields are carried through the processing. All use the same Maesaka settings and differ only in which gates are admitted.
| Field | Gates admitted | Role |
|---|---|---|
| Strict | Z ≥ 20 dBZ, ρHV ≥ 0.95, all inputs finite | Every quoted number |
| Permissive | Z ≥ 20 dBZ, ρHV ≥ 0.90, all inputs finite | Sensitivity only |
| Unfiltered diagnostic | No Z or ρHV threshold; missing or nonfinite native ΦDP still excluded | Display only |
The permissive mask admits gates the strict mask rejects, and under it elevated KDP appears earlier in the sequence. Those extra gates have lower ρHV, which occurs with mixed-phase or melting particles, hail, low signal-to-noise, sidelobes, or nonuniform beam filling.
The unfiltered diagnostic field drops the thresholds entirely, so the blank areas of the strict field fill in. What appears there can include mixed-phase and hail returns, low-SNR gates, and unstable phase-gradient artefacts, so it is not rainfall-quality KDP and contributes to no column metric, lead time, or rainfall interpretation. It is shown beside the strict field so the extent and cause of the strict-field gaps are visible.
Where strict-mask KDP is NaN, the gate was missing or excluded by QC. A blank region can also mean nothing was sampled there: the top elevation in these volumes is 19.51°, so over a core at 6.4 km range no beam reaches above roughly 2.5 km MSL, whatever the masking.
Python 3.12.14 · Py-ART 2.3.0 · NumPy 2.5.3 · SciPy 1.18.1 ·
xarray 2026.7.0 · netCDF4 1.7.4 · pandas 3.0.6 · matplotlib 3.11.2
· PyGRIB 2.1.8 · pyproj 3.8.0. Full specification in
code/environment.yml; thresholds and paths in
code/config/config.yaml.
code/ktlx_case/radar.py — dual-pol sweep selectioncode/ktlx_case/kdp.py — QC flags and KDP retrievalcode/ktlx_case/radar_screening.py — target centroid and geometrycode/ktlx_case/sections.py — sampling checks and column metricscode/scripts/03_kdp_diagnostic.py — per-volume retrievalcode/scripts/04_refine_targets.py — accepted-window forward trackingcode/scripts/04_extend_early_targets.py — idempotent backward extensioncode/scripts/05_build_sections.py — pseudo-RHIs and section metricscode/scripts/06_compare_kdp_methods.py — algorithm sensitivitycode/scripts/07_plot_case_demonstration.py — main figure and timing evidencecode/scripts/08_animate_sections.py — reflectivity/KDP GIFThese accompany the full analysis bundle and are not redistributed with this page:
evidence/early_signal_case_demonstration.json — the timing numbers quoted aboveevidence/pseudo_rhi_metrics.csv — per-volume column metricsevidence/rainfall_summary.csv — fixed-pixel and domain accumulations with coverage fractionsevidence/refined_storm_targets.csv — tracked target positionsevidence/pseudo_rhi_sampling.json — per-elevation azimuth offsetsevidence/KTLX20210429_020204_method_comparison.json — retrieval comparison statisticsevidence/provenance.json — source-file provenanceMANIFEST.sha256 — checksums for every bundled fileevidence/official_warning_context.json — the NWS Flash Flood Warning
record (KOUN event 10, PIL FFWOUN, issued 202104290153), sourced from
the Iowa Environmental Mesonet VTEC archive
Radar-volume processing runs through Slurm on swat or swat_plus,
never on the login node. The completed workflow passed all 39 lightweight tests, all
expected products reported ready, and the GIF was verified to contain 10 nonblank,
varying frames. Slurm recipes are in code/sbatch/.
Forty low-level KTLX reflectivity quick looks spanning 00:04–03:55 UTC are in
figures/radar_quicklooks/; they were used for manual screening and
storm-target refinement.