This document is a practical reference for the public APIs most users need in
pycwr 1.0.9. It does not try to mirror every internal helper. The focus is:
- where to enter the package
- which object each API returns
- which arguments control behavior
- how aligned and native reflectivity workflows differ
For runnable examples grouped by feature, see ../test/README.md.
| Module | Main purpose | Recommended entry points |
|---|---|---|
pycwr.io |
Read and write radar base data | read_auto, read_WSR98D, read_SAB, read_CC, read_SC, read_PA |
pycwr.core |
Central volume object, geometry, export helpers | PRD, radar.summary(), radar.get_sweep_field() |
pycwr.draw |
Plotting and quick-look figures | plot_ppi, plot_ppi_map, plot_rhi, plot_section, plot_vvp, plot_wind_profile |
pycwr.qc |
Dual-pol quality control | apply_dualpol_qc, run_dualpol_qc |
pycwr.retrieve |
Hydrometeor and wind retrieval | classify_hydrometeors, retrieve_vad, retrieve_vvp, retrieve_vwp, retrieve_wind_volume_xy, retrieve_wind_volume_lonlat |
pycwr.interp |
Multi-radar compositing | run_radar_network_3d, radar_network_3d_to_netcdf |
pycwr.GraphicalInterface |
Local web viewer | create_app, launch |
- distance and height: meters
- internal trigonometric calculations: radians
- public azimuth, elevation, and fixed-angle values: degrees
- lon/lat input and output: degrees
Some historical plotting interfaces still accept kilometers because that was the historical public behavior.
Several APIs accept:
range_mode="aligned": historical aligned workflowrange_mode="native": native long-range reflectivity when available
Recommended rule:
- use
alignedfor backward-compatible plots and products - use
nativewhen low-level reflectivity coverage matters
Velocity fields usually remain aligned because their valid range is often shorter than reflectivity.
Base install covers:
- readers
PRD- geometry
- interpolation
- NetCDF-style export
Full install adds:
- plotting
- map plotting
- QC
- web viewer
- Py-ART and xradar interop
Install the full stack with:
pip install "pycwr[full]"read_auto(
filename,
station_lon=None,
station_lat=None,
station_alt=None,
effective_earth_radius=None,
)Purpose:
- detect the radar family automatically
- parse the file into a
PRD - preserve the package's compatible geometry and sweep layout
Arguments:
filename: radar file pathstation_lon,station_lat,station_alt: optional site override valueseffective_earth_radius: optional beam-geometry radius in meters
Returns:
pycwr.core.NRadar.PRD
Typical usage:
from pycwr.io import read_auto
radar = read_auto("your_radar_file.bin.bz2")
print(radar.summary())read_WSR98D(...)
read_SAB(...)
read_CC(...)
read_SC(...)
read_PA(...)Use these when you already know the file family.
They return the same PRD object type as read_auto.
Writer functions:
write_wsr98d(prd, filename, **kwargs)
write_nexrad_level2_msg31(prd, filename, **kwargs)
write_nexrad_level2_msg1(prd, filename, **kwargs)Preferred object-style export helpers:
radar.to_wsr98d(...)radar.to_nexrad_level2_msg31(...)radar.to_nexrad_level2_msg1(...)
The public readers target:
WSR98DSABCCSCPA- selected NEXRAD Level II workflows where enabled
If the input is not recognized, read_auto raises a format error instead of
silently guessing.
PRD is the central object in pycwr. Almost all user workflows start by
reading a file into a PRD.
fields: list of sweep-levelxarray.Datasetscan_info: volume metadata as anxarray.Datasetextended_fields: sidecar storage for native-range fieldsproduct: computed product datasetsitename: site namensweeps: number of sweepsnrays: number of rayseffective_earth_radius: geometry radius used by this volume
fields[sweep] is usually the best place to inspect one sweep.
Typical coordinates:
timerangeazimuthelevationx,y,zlon,lat
Typical variables:
dBZVWZDRCCPhiDPKDP- corrected fields such as
Zc,ZDRc,PhiDPc,KDPcwhen QC has run
radar.summary()
radar.available_fields(sweep=None, range_mode="aligned")
radar.sweep_summary()
radar.get_sweep_field(sweep, field_name, range_mode="aligned", sort_by_azimuth=False)
radar.get_native_sweep_field(sweep, field_name)
radar.has_extended_field(sweep, field_name)
radar.ordered_az(inplace=False)Returns a lightweight dict with:
- site information
- scan type
- number of sweeps and rays
- field list
- per-sweep summaries
Use this first when opening an unfamiliar file.
Returns:
- all visible field names for the full volume if
sweep is None - field names for one sweep if
sweepis specified
With range_mode="native", native sidecar fields are included when present.
Returns one summary row per sweep. Common keys include:
sweepfixed_angleraysaligned_fieldsnative_fieldsaligned_max_range_m
radar.get_sweep_field(
sweep,
field_name,
range_mode="aligned",
sort_by_azimuth=False,
)Returns one xarray.DataArray.
Use this when you want:
- one field only
- explicit
alignedornativecontrol - optional azimuth sorting
Returns the native-range field when an extended sidecar exists. If no native sidecar exists, it falls back to the aligned field.
Returns True or False.
Useful when you want to branch between aligned and native workflows explicitly.
Returns or applies an azimuth-sorted view.
inplace=False: return a sorted viewinplace=True: mutate the current object
For some low sweeps:
radar.fields[sweep]["dBZ"]is the aligned field on the shared range gridradar.get_native_sweep_field(sweep, "dBZ")is the native long-range field
Recommended rule:
- use aligned access for historical products and compatibility checks
- use native access when the actual low-level reflectivity range matters
Example:
aligned = radar.get_sweep_field(0, "dBZ", range_mode="aligned")
native = radar.get_sweep_field(0, "dBZ", range_mode="native")Public product builders on PRD include:
radar.add_product_CR_xy(XRange, YRange, range_mode="aligned")
radar.add_product_CAPPI_xy(XRange, YRange, level_height, range_mode="aligned")
radar.add_product_CAPPI_3d_xy(XRange, YRange, level_heights, range_mode="aligned")
radar.add_product_VIL_xy(XRange, YRange, level_heights, range_mode="aligned")
radar.add_product_ET_xy(XRange, YRange, level_heights, range_mode="aligned")
radar.add_product_CR_lonlat(XLon, YLat, range_mode="aligned")
radar.add_product_CAPPI_lonlat(XLon, YLat, level_height, range_mode="aligned")
radar.add_product_VIL_lonlat(XLon, YLat, level_heights, range_mode="aligned")
radar.add_product_ET_lonlat(XLon, YLat, level_heights, range_mode="aligned")
radar.add_product_VWP(sweeps=None, field_name=None, range_mode="aligned", **kwargs)Units:
- Cartesian grids: meters
- geographic grids: degrees
- heights: meters
Results are written into radar.product.
radar.extract_section(
start,
end,
field_name="dBZ",
point_units="km",
interpolation="linear",
range_mode="aligned",
sample_spacing=None,
)
radar.extract_section_lonlat(
start_lonlat,
end_lonlat,
field_name="dBZ",
interpolation="linear",
range_mode="aligned",
sample_spacing=None,
)
radar.get_RHI_data(...)
radar.get_vcs_data(...)Use these for vertical sections, lon/lat sections, and RHI-style extraction.
radar.retrieve_vad(sweeps=None, field_name=None, range_mode="aligned", **kwargs)
radar.retrieve_vvp(sweep, field_name=None, range_mode="aligned", **kwargs)
radar.retrieve_vwp(sweeps=None, field_name=None, range_mode="aligned", **kwargs)
radar.retrieve_wind_volume_xy(XRange, YRange, level_heights, sweeps=None, field_name=None, range_mode="aligned", **kwargs)
radar.retrieve_wind_volume_lonlat(XLon, YLat, level_heights, sweeps=None, field_name=None, range_mode="aligned", **kwargs)
radar.add_product_VWP(sweeps=None, field_name=None, range_mode="aligned", **kwargs)
radar.add_product_WIND_VOLUME_xy(XRange, YRange, level_heights, sweeps=None, field_name=None, range_mode="aligned", **kwargs)
radar.add_product_WIND_VOLUME_lonlat(XLon, YLat, level_heights, sweeps=None, field_name=None, range_mode="aligned", **kwargs)Behavior:
retrieve_vad(...): returns ring-wisexarray.Datasetresultsretrieve_vvp(...): returns local wind analysis on one sweepretrieve_vwp(...): returns a vertical wind profilexarray.Datasetretrieve_wind_volume_xy(...): returns a gridded Cartesianu/vwind volumeretrieve_wind_volume_lonlat(...): returns a gridded lon/latu/vwind volumeadd_product_VWP(...): stores the profile inradar.productasVWP_*add_product_WIND_VOLUME_xy(...): stores the Cartesian wind volume inradar.productadd_product_WIND_VOLUME_lonlat(...): stores the lon/lat wind volume inradar.product
Common object methods:
radar.to_pyart_radar(...)radar.to_xradar(...)radar.to_wsr98d(...)radar.to_nexrad_level2_msg31(...)radar.to_nexrad_level2_msg1(...)radar.to_cfgridded_netcdf(...)
These are the main public export paths for downstream interoperability.
Recommended public plotting APIs:
from pycwr.draw import (
plot,
plot_ppi,
plot_ppi_map,
plot_rhi,
plot_section,
plot_section_lonlat,
plot_vvp,
plot_wind_profile,
)The easy plotting functions return an EasyPlotResult with:
fig: matplotlib figureax: target axis or axesartist: main plotted artist
plot_ppi(radar, field="dBZ", sweep=0, ...)plot_ppi_map(radar, field="dBZ", sweep=0, ...)plot_rhi(radar, field="dBZ", azimuth=..., ...)plot_section(radar, start=..., end=..., field="dBZ", ...)plot_section_lonlat(radar, start_lonlat=..., end_lonlat=..., field="dBZ", ...)plot_vvp(radar, sweep=0, background_field="dBZ", ...)plot_wind_profile(profile_or_radar, ...)
Recommended usage:
- use
plot_ppifor quick Cartesian PPI inspection - use
plot_ppi_mapwhen geographic context matters - use
plot_sectionorplot_section_lonlatfor vertical analysis - use
plot_vvpfor vector-field output from wind retrieval - use
plot_wind_profileforVWPprofile products
from pycwr.qc import apply_dualpol_qc, run_dualpol_qcTypical usage:
qc_radar = apply_dualpol_qc(radar, inplace=False, clear_air_mode="mask")Purpose:
- despeckle or suppress non-meteorological signals
- generate corrected polarimetric fields
- emit mask fields used by later workflows
Typical output fields include:
ZcZDRcPhiDPcKDPcQC_MASKCLEAR_AIR_MASK
Use inplace=False when you want to preserve the raw input volume.
This module contains two public families of retrieval tools:
- hydrometeor classification
- single-radar wind retrieval
Public helpers:
from pycwr.retrieve import (
apply_hydrometeor_classification,
classify_hydrometeors,
interpolate_temperature_profile,
)Typical object workflow:
hcl_radar = radar.classify_hydrometeors(
inplace=False,
band="C",
profile_height=[0.0, 2000.0, 4000.0, 8000.0],
profile_temperature=[24.0, 12.0, 2.0, -16.0],
confidence_field="HCL_CONF",
)Use cases:
- classify hydrometeors directly from arrays
- interpolate a temperature profile to gate heights
- write
HCLand confidence fields back into aPRD
Public helpers:
from pycwr.retrieve import retrieve_vad, retrieve_vvp, retrieve_vwp, retrieve_wind_volume_xyThe main algorithms are:
VAD: harmonic fit on one or more sweepsVVP: local least-squares horizontal wind retrieval on one sweepVWP: robust vertical profile built from multiple VAD layersWIND_VOLUME: fixed-height gridded horizontal wind volume built from multiple VVP sweeps
Typical usage:
vad = radar.retrieve_vad(sweeps=[0, 1, 2], max_range_km=40.0, gate_step=4)
vvp = radar.retrieve_vvp(0, max_range_km=20.0, az_num=91, bin_num=5)
vwp = radar.retrieve_vwp(sweeps=[0, 1, 2], max_range_km=40.0, height_step=500.0)
wind = retrieve_wind_volume_xy(
radar,
XRange=np.arange(-20_000.0, 20_001.0, 10_000.0),
YRange=np.arange(-20_000.0, 20_001.0, 10_000.0),
level_heights=np.array([500.0, 1000.0, 1500.0]),
sweeps=[0, 1, 2],
max_range_km=30.0,
)Outputs are xarray.Dataset objects containing variables such as:
uvwind_speedwind_directionsource_sweep_countfit_rmse- coverage or sample-count metrics depending on the algorithm
Important behavior:
- velocity-field selection prefers
Vcwhen present, then falls back toV - retrievals are designed to tolerate missing data and partial azimuth coverage
attrsrecord the method, the actual velocity field used, and references
Method references included in the module:
- Browning and Wexler (1968), VAD
- Waldteufel and Corbin (1979), VVP
- Holleman (2003, 2005), operational radar wind-profile quality control and verification
Recommended high-level network entry points:
from pycwr.interp import (
parse_radar_time_from_filename,
discover_radar_files,
select_radar_files,
build_latlon_grid,
load_network_config,
run_radar_network_3d,
radar_network_3d_to_netcdf,
)Typical use:
- discover or select input radar files
- build a lon/lat grid
- run
run_radar_network_3d(...) - optionally write NetCDF
Outputs commonly include:
- network
CR - network
CAPPI - 3D reflectivity volumes
- per-radar metadata and range summaries
Public entry points:
from pycwr.GraphicalInterface import create_app, launchTypical use:
app = create_app()
launch()Or run the script:
python scripts/LaunchGUI.pyThe viewer is designed for local use:
- loopback-only binding
- token-guarded API
- restricted file access
from pycwr.io import read_auto
from pycwr.draw import plot_ppi
radar = read_auto("your_radar_file")
print(radar.summary())
plot_ppi(radar, field="dBZ", sweep=0, show=True)native_dBZ = radar.get_sweep_field(0, "dBZ", range_mode="native")qc_radar = radar.apply_dualpol_qc(inplace=False)
plot_ppi(qc_radar, field="Zc", sweep=0, show=True)from pycwr.draw import plot_wind_profile
profile = radar.retrieve_vwp(sweeps=[0, 1, 2], max_range_km=40.0, height_step=500.0)
plot_wind_profile(profile, show=True)from pycwr.interp import run_radar_network_3d
network = run_radar_network_3d(...)- ../README.md: project overview
- ../test/README.md: runnable examples
- radar_network_quickstart_en.md: beginner-friendly radar-network workflow
- draw_quickstart.md: plotting entry points
- Read the Docs: hosted documentation site
- Web viewer: launch it locally with
python scripts/LaunchGUI.py