Reading Data: xradar and Py-ART#
This page answers the question new users ask first: which IO path do I use, and what works on the object it gives me?
Reading data in Py-ART today#
The recommended path for reading radar data is xradar-first: open the
file with xradar
into an xarray DataTree, then attach Py-ART’s pyart accessor to get
a pyart.xradar.Xradar object that behaves like a
pyart.core.Radar for the purposes of running Py-ART algorithms,
correction routines, and displays.
import xradar as xd
import pyart
# Access sample cfradial1 data from Py-ART and read using xradar
filename = pyart.testing.get_test_data("swx_20120520_0641.nc")
tree = xd.io.open_cfradial1_datatree(filename)
# Attach the Py-ART accessor -- ``radar`` now exposes Radar-like
# attributes/methods (fields, azimuth, elevation, get_elevation, ...)
radar = tree.pyart.to_radar()
xradar ships open_*_datatree readers for CfRadial1, CfRadial2/FM301,
ODIM_H5, Furuno, Iris/Sigmet, NEXRAD Level 2, and others – see the
xradar documentation
for the full list. Any algorithm in Py-ART that accepts a radar
argument can be handed the resulting pyart.xradar.Xradar object
directly, in place of a pyart.core.Radar. Code that needs to
accept either interchangeably (for example, a helper function) can
normalize the input with pyart.xradar.to_pyart_radar(), which
returns a Radar or Xradar
unchanged and wraps a bare xarray.DataTree for you:
import pyart
radar = pyart.xradar.to_pyart_radar(tree) # Radar, Xradar, or DataTree in
When to use pyart.io.read instead#
Py-ART’s built-in readers (pyart.io.read() and friends, e.g.
pyart.io.read_cfradial(), pyart.io.read_nexrad_archive()) remain
available and return a classic pyart.core.Radar. Reach for them
when:
You need a format xradar does not (yet) read, or a Py-ART-specific reader such as MDV, UF, CHL, or RSL-backed files (see
pyart.ioandpyart.aux_io).You depend on behavior specific to
pyart.core.Radarthat is not (yet) mirrored onpyart.xradar.Xradar– check the supported-API table below first.You are maintaining existing code and are not ready to migrate.
import pyart
radar = pyart.io.read(filename) # returns a pyart.core.Radar
Reader migration: the roadmap direction#
New radar-format IO support is expected to land in xradar going
forward rather than as new readers in pyart.io. Py-ART’s own legacy
readers will be deprecated over time as xradar’s format coverage grows,
matching “Moderate #1” of the rc3.0 roadmap
(roadmaps/pyart-roadmap-rc3.0.pdf). No legacy reader is being removed
today – this is a direction to plan for, not an immediate break.
Supported-API table#
pyart.xradar.Xradar wraps an xradar DataTree and duck-types
pyart.core.Radar: most attributes and methods used by Py-ART’s
correction, retrieval, mapping, and graphing subpackages work unchanged.
The table below lists what has been verified to work, sourced from
pyart/xradar/accessor.py and the test suite in tests/xradar/
(notably tests/xradar/test_compat_matrix.py, which runs the same
algorithm against a Radar and the equivalent
Xradar and asserts numerically equal results).
Xradar (radar-level)#
Member |
Notes |
|---|---|
|
|
|
Standard Radar-style |
|
Populated from the DataTree root |
|
Derived from the combined per-sweep data |
|
Lazily derived from the sweep start/end indices |
|
Computed the same way as on |
|
Per-sweep elevation slice |
|
Per-sweep azimuth slice |
|
Per-gate area, same formula as |
|
Per-sweep gate locations, computed via |
|
From |
|
Same three levels as |
|
Mutates both |
|
Returns a new |
|
Populated from a |
|
Populated from a |
|
|
|
|
Xgrid (grid-level)#
Member |
Notes |
|---|---|
|
Same shape and layout as |
|
Same as |
|
|
|
Writes the grid via |
Known caveats#
Fields are masked, not filled.
Xradar.fields[name]["data"]is anumpy.ma.MaskedArray; any NaN in the source variable (xarray’s decoded_FillValue) is masked, mirroring howpyart.core.Radarmasks missing gates.RHI sweeps are supported by passing
scan_type="rhi"totree.pyart.to_radar(); internally rays are combined per-sweep on elevation (which varies per ray in an RHI) instead of azimuth (which is ~constant across an RHI sweep).``radar_calibration`` is populated only when the source DataTree has a
radar_calibrationchild group (mirroring howinstrument_parametersis sourced from aradar_parameterssubgroup); otherwise it isNone, matchingRadar’s handling of files that lack this information.Comparing a file read both ways is not bit-for-bit.
pyart.io.readand xradar’sopen_*_datatreereaders can disagree on ray bookkeeping for messy real-world files (e.g. which ray straddling the 0/360 azimuth wrap belongs to which sweep); this is a property of two independent parsers, not anXradaraccessor defect. Seetests/xradar/test_compat_matrix.pyfor how the compatibility test suite works around this to get an apples-to-apples numerical comparison.
Worked example#
import xradar as xd
import pyart
filename = pyart.testing.get_test_data("swx_20120520_0641.nc")
tree = xd.io.open_cfradial1_datatree(filename)
radar = tree.pyart.to_radar()
# Grid using 11 vertical levels, and 101 horizontal grid cells at a
# resolution of 1 km -- pyart.map works directly on the Xradar object
grid = pyart.map.grid_from_radars(
(radar,),
grid_shape=(11, 101, 101),
grid_limits=(
(0.0, 10_000),
(-50_000.0, 50_000.0),
(-50_000, 50_000.0),
),
)
More end-to-end examples are in the example gallery:
See also Py-ART 2.0 for the rest of the Py-ART 2.0 API changes, and
Why Py-ART? for how the Radar/xradar data models compare.