Rainbow#
import xarray as xr
from open_radar_data import DATASETS
import xradar as xd
Download#
Fetching Rainbow radar data file from open-radar-data repository.
filename = DATASETS.fetch("2013051000000600dBZ.vol")
xr.open_dataset#
Making use of the xarray rainbow backend. We also need to provide the group. Note, that we are using CfRadial2 group access pattern.
ds = xr.open_dataset(filename, group="sweep_0", engine="rainbow")
display(ds)
<xarray.Dataset> Size: 1MB
Dimensions: (azimuth: 361, range: 400)
Coordinates:
* azimuth (azimuth) float64 3kB 0.5055 1.549 2.505 ... 358.5 359.5
elevation (azimuth) float64 3kB ...
time (azimuth) datetime64[ns] 3kB ...
* range (range) float32 2kB 125.0 375.0 ... 9.962e+04 9.988e+04
longitude float64 8B ...
latitude float64 8B ...
altitude float64 8B ...
Data variables:
DBZH (azimuth, range) float64 1MB ...
sweep_mode <U20 80B ...
sweep_number int64 8B ...
prt_mode <U7 28B ...
follow_mode <U7 28B ...
sweep_fixed_angle float64 8B ...Plot Time vs. Azimuth#
We need to sort by time and specify the coordinate.
ds.azimuth.sortby("time").plot(x="time")
[<matplotlib.lines.Line2D at 0x779212a0a5d0>]
Plot Range vs. Time#
We need to sort by time and specify the coordinate.
ds.DBZH.sortby("time").plot(y="time")
<matplotlib.collections.QuadMesh at 0x77921289de80>
Plot Range vs. Azimuth#
ds.DBZH.plot()
<matplotlib.collections.QuadMesh at 0x779209e81f90>
backend_kwargs#
Beside first_dim there are several additional backend_kwargs for the rainbow backend, which handle different aspects of angle alignment. This comes into play, when azimuth and/or elevation arrays are not evenly spacend and other issues.
help(xd.io.RainbowBackendEntrypoint)
Help on class RainbowBackendEntrypoint in module xradar.io.backends.rainbow:
class RainbowBackendEntrypoint(xarray.backends.common.BackendEntrypoint)
| Xarray BackendEntrypoint for Rainbow5 data.
|
| Method resolution order:
| RainbowBackendEntrypoint
| xarray.backends.common.BackendEntrypoint
| builtins.object
|
| Methods defined here:
|
| guess_can_open(self, filename_or_obj)
| Rainbow5 file (XML header starting with ``<volume``).
|
| open_dataset(
| self,
| filename_or_obj,
| *,
| mask_and_scale=True,
| decode_times=True,
| concat_characters=True,
| decode_coords=True,
| drop_variables=None,
| use_cftime=None,
| decode_timedelta=None,
| group=None,
| reindex_coord=None,
| reindex_angle=False,
| first_dim='auto',
| site_as_coords=True
| )
| Backend open_dataset method used by Xarray in :py:func:`~xarray.open_dataset`.
|
| open_datatree(self, filename_or_obj, **kwargs)
| Open a Rainbow5 file as :py:class:`xarray.DataTree`. See :meth:`open_groups_as_dict` for keyword arguments.
|
| open_groups_as_dict(
| self,
| filename_or_obj,
| *,
| mask_and_scale=True,
| decode_times=True,
| concat_characters=True,
| decode_coords=True,
| drop_variables=None,
| use_cftime=None,
| decode_timedelta=None,
| first_dim='auto',
| reindex_coord=None,
| reindex_angle=False,
| site_coords=True,
| sweep=None,
| optional=True,
| optional_groups=False
| )
| Open a Rainbow5 file as a CfRadial2-shaped dict of group datasets.
|
| Parameters
| ----------
| filename_or_obj : str, Path, or file-like
| Path or file-like object understood by the underlying reader.
| mask_and_scale : bool or dict-like, optional
| Replace fill values with NA and apply ``scale_factor``/``add_offset``
| decoding. See :py:func:`xarray.open_dataset`. Defaults to ``True``.
| decode_times : bool or dict-like, optional
| Decode CF time variables (calendar, units) into ``np.datetime64``.
| Defaults to ``True``.
| concat_characters : bool or dict-like, optional
| Concatenate character arrays into strings along their trailing
| dimension. Defaults to ``True``.
| decode_coords : bool or {"coordinates", "all"}, optional
| Decode the CF ``coordinates`` attribute. Defaults to ``True``
| (equivalent to ``"coordinates"``).
| drop_variables : str or iterable of str, optional
| Names of variables to drop before processing.
| use_cftime : bool, optional
| Force ``cftime`` decoding for time variables (instead of
| ``np.datetime64``). Defaults to ``None`` (auto).
| decode_timedelta : bool, optional
| Decode CF timedelta variables. Default mirrors ``decode_times``
| unless the backend overrides it (cfradial1, cfradial2, and imd
| default to ``False``).
| sweep : int, str, or list of int/str, optional
| Sweep selection. ``None`` (default) returns all sweeps. An ``int``
| or ``"sweep_N"`` string returns one sweep; a list returns the
| named subset.
| first_dim : {"auto", "time"}, optional
| Leading dimension of each sweep dataset. ``"auto"`` picks
| ``azimuth`` (PPI) or ``elevation`` (RHI); ``"time"`` keeps the
| raw time axis. Default ``"auto"`` (``"time"`` for cfradial2).
| optional : bool, optional
| Include optional root variables when available. Defaults to ``True``.
| optional_groups : bool, optional
| Include the ``/radar_parameters``, ``/georeferencing_correction``,
| and ``/radar_calibration`` metadata subgroups under the root.
| Defaults to ``False``.
| reindex_coord : dict, optional
| Nested dict with optional keys ``angle`` and ``range`` holding the
| kwargs for :func:`xradar.util.reindex_angle` and
| :func:`xradar.util.reindex_range`, e.g. ``dict(angle=dict(start_angle=0,
| stop_angle=360, angle_res=1.0, direction=1))``. Only invoked when
| ``decode_coords=True``. Defaults to ``None`` (no reindexing).
| reindex_angle : dict, optional
| Deprecated, use ``reindex_coord=dict(angle=...)`` instead.
| site_coords : bool, optional
| Attach ``latitude``/``longitude``/``altitude`` as coordinates on
| the root dataset (and on per-sweep datasets where the backend
| supports it). Defaults to ``True``.
|
| Returns
| -------
| dict[str, xarray.Dataset]
| CfRadial2 group paths (``/``, ``/sweep_N``, optional
| ``/radar_parameters`` etc.) mapped to their datasets,
| ready for :py:meth:`xarray.DataTree.from_dict`.
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __annotations__ = {}
|
| description = 'Open Rainbow5 files in Xarray'
|
| open_dataset_parameters = ('filename_or_obj', 'mask_and_scale', 'decod...
|
| supports_groups = True
|
| url = 'https://xradar.rtfd.io/latest/io.html#rainbow-data-i-o'
|
| ----------------------------------------------------------------------
| Methods inherited from xarray.backends.common.BackendEntrypoint:
|
| __repr__(self) -> 'str'
| Return repr(self).
|
| ----------------------------------------------------------------------
| Data descriptors inherited from xarray.backends.common.BackendEntrypoint:
|
| __dict__
| dictionary for instance variables
|
| __weakref__
| list of weak references to the object
ds = xr.open_dataset(filename, group="sweep_1", engine="rainbow", first_dim="time")
display(ds)
<xarray.Dataset> Size: 1MB
Dimensions: (time: 361, range: 400)
Coordinates:
* time (time) datetime64[ns] 3kB 2013-05-10T00:00:19.01515150...
azimuth (time) float64 3kB ...
elevation (time) float64 3kB ...
* range (range) float32 2kB 125.0 375.0 ... 9.962e+04 9.988e+04
longitude float64 8B ...
latitude float64 8B ...
altitude float64 8B ...
Data variables:
DBZH (time, range) float64 1MB ...
sweep_mode <U20 80B ...
sweep_number int64 8B ...
prt_mode <U7 28B ...
follow_mode <U7 28B ...
sweep_fixed_angle float64 8B ...open_odim_datatree#
The same works analoguous with the datatree loader. But additionally we can provide a sweep string, number or list.
help(xd.open_datatree)
Help on function open_datatree in module xradar.io:
open_datatree(filename_or_obj, *, engine=None, **kwargs)
Open a radar file as :py:class:`xarray.DataTree`.
The engine is the given ``engine`` or, without it, the one found by
:func:`xradar.io.discover_engine`. This works for all radar formats,
including the netCDF/HDF5 based ones (ODIM_H5, GAMIC, CfRadial) which
:py:func:`xarray.open_datatree` without ``engine`` hands to xarray's own
netCDF/HDF5 backends.
A list of files is stacked into one volume (see
:func:`xradar.util.create_volume`): this is for formats which write one
sweep per file, e.g. IMD or IRIS/Sigmet files of single sweeps. All files
need the same engine, the sweeps of all files are sorted by time and
numbered in this order. The keyword arguments ``time_coverage_start``,
``time_coverage_end``, ``min_angle``, ``max_angle`` and ``volume_number``
of :func:`xradar.util.create_volume` select and label the sweeps, all other
arguments are used for each file.
Parameters
----------
filename_or_obj : str, Path, file-like or list of str or Path
Path to the radar file, or the paths of files with one sweep each.
engine : str, optional
Backend engine name (e.g., ``"odim"``, ``"cfradial1"``, ``"nexradlevel2"``).
Default is to discover the engine from the file with
:func:`xradar.io.discover_engine` (raises ``ValueError`` if no xradar
engine can open it).
**kwargs
Keyword arguments for :py:func:`xarray.open_datatree`: xarray options
such as ``chunks`` or ``cache``, and the backend options documented on
the engine's ``open_groups_as_dict`` (``sweep``, ``first_dim``, ...).
Returns
-------
dtree : xarray.DataTree
DataTree with CfRadial2 group structure.
Examples
--------
>>> import xradar as xd
>>> dtree = xd.open_datatree("file.h5", engine="odim")
>>> dtree = xd.open_datatree("file.h5") # engine discovered
>>> volume = xd.open_datatree(["sweep_1.nc", "sweep_2.nc"]) # stacked sweeps
dtree = xd.open_datatree(filename, engine="rainbow", sweep="sweep_8")
display(dtree)
<xarray.DataTree>
Group: /
│ Dimensions: (sweep: 1)
│ Coordinates:
│ longitude float64 8B ...
│ altitude float64 8B ...
│ latitude float64 8B ...
│ Dimensions without coordinates: sweep
│ Data variables:
│ volume_number int64 8B ...
│ platform_type <U5 20B ...
│ instrument_type <U5 20B ...
│ time_coverage_start <U20 80B ...
│ time_coverage_end <U20 80B ...
│ sweep_group_name (sweep) int64 8B ...
│ sweep_fixed_angle (sweep) float64 8B ...
│ Attributes:
│ Conventions: None
│ instrument_name: None
│ version: None
│ title: None
│ institution: None
│ references: None
│ source: None
│ history: None
│ comment: im/exported using xradar
└── Group: /sweep_0
Dimensions: (azimuth: 361, range: 400)
Coordinates:
* azimuth (azimuth) float64 3kB 0.5 1.544 2.51 ... 358.5 359.5
elevation (azimuth) float64 3kB ...
time (azimuth) datetime64[ns] 3kB ...
* range (range) float32 2kB 125.0 375.0 ... 9.962e+04 9.988e+04
Data variables:
DBZH (azimuth, range) float64 1MB ...
sweep_mode <U20 80B ...
sweep_number int64 8B ...
prt_mode <U7 28B ...
follow_mode <U7 28B ...
sweep_fixed_angle float64 8B ...Plot Sweep Range vs. Time#
dtree["sweep_0"].ds.DBZH.sortby("time").plot(y="time")
<matplotlib.collections.QuadMesh at 0x77920a2de850>
Plot Sweep Range vs. Azimuth#
dtree["sweep_0"].ds.DBZH.plot()
<matplotlib.collections.QuadMesh at 0x77920a1d0190>
dtree = xd.open_datatree(filename, engine="rainbow", sweep="sweep_8")
display(dtree)
<xarray.DataTree>
Group: /
│ Dimensions: (sweep: 1)
│ Coordinates:
│ longitude float64 8B ...
│ altitude float64 8B ...
│ latitude float64 8B ...
│ Dimensions without coordinates: sweep
│ Data variables:
│ volume_number int64 8B ...
│ platform_type <U5 20B ...
│ instrument_type <U5 20B ...
│ time_coverage_start <U20 80B ...
│ time_coverage_end <U20 80B ...
│ sweep_group_name (sweep) int64 8B ...
│ sweep_fixed_angle (sweep) float64 8B ...
│ Attributes:
│ Conventions: None
│ instrument_name: None
│ version: None
│ title: None
│ institution: None
│ references: None
│ source: None
│ history: None
│ comment: im/exported using xradar
└── Group: /sweep_0
Dimensions: (azimuth: 361, range: 400)
Coordinates:
* azimuth (azimuth) float64 3kB 0.5 1.544 2.51 ... 358.5 359.5
elevation (azimuth) float64 3kB ...
time (azimuth) datetime64[ns] 3kB ...
* range (range) float32 2kB 125.0 375.0 ... 9.962e+04 9.988e+04
Data variables:
DBZH (azimuth, range) float64 1MB ...
sweep_mode <U20 80B ...
sweep_number int64 8B ...
prt_mode <U7 28B ...
follow_mode <U7 28B ...
sweep_fixed_angle float64 8B ...dtree = xd.open_datatree(filename, engine="rainbow", sweep=[0, 1, 8])
display(dtree)
<xarray.DataTree>
Group: /
│ Dimensions: (sweep: 3)
│ Coordinates:
│ longitude float64 8B ...
│ altitude float64 8B ...
│ latitude float64 8B ...
│ Dimensions without coordinates: sweep
│ Data variables:
│ volume_number int64 8B ...
│ platform_type <U5 20B ...
│ instrument_type <U5 20B ...
│ time_coverage_start <U20 80B ...
│ time_coverage_end <U20 80B ...
│ sweep_group_name (sweep) int64 24B ...
│ sweep_fixed_angle (sweep) float64 24B ...
│ Attributes:
│ Conventions: None
│ instrument_name: None
│ version: None
│ title: None
│ institution: None
│ references: None
│ source: None
│ history: None
│ comment: im/exported using xradar
├── Group: /sweep_0
│ Dimensions: (azimuth: 361, range: 400)
│ Coordinates:
│ * azimuth (azimuth) float64 3kB 0.5055 1.549 2.505 ... 358.5 359.5
│ elevation (azimuth) float64 3kB ...
│ time (azimuth) datetime64[ns] 3kB ...
│ * range (range) float32 2kB 125.0 375.0 ... 9.962e+04 9.988e+04
│ Data variables:
│ DBZH (azimuth, range) float64 1MB ...
│ sweep_mode <U20 80B ...
│ sweep_number int64 8B ...
│ prt_mode <U7 28B ...
│ follow_mode <U7 28B ...
│ sweep_fixed_angle float64 8B ...
├── Group: /sweep_1
│ Dimensions: (azimuth: 361, range: 400)
│ Coordinates:
│ * azimuth (azimuth) float64 3kB 0.5055 1.549 2.516 ... 358.5 359.5
│ elevation (azimuth) float64 3kB ...
│ time (azimuth) datetime64[ns] 3kB ...
│ * range (range) float32 2kB 125.0 375.0 ... 9.962e+04 9.988e+04
│ Data variables:
│ DBZH (azimuth, range) float64 1MB ...
│ sweep_mode <U20 80B ...
│ sweep_number int64 8B ...
│ prt_mode <U7 28B ...
│ follow_mode <U7 28B ...
│ sweep_fixed_angle float64 8B ...
└── Group: /sweep_2
Dimensions: (azimuth: 361, range: 400)
Coordinates:
* azimuth (azimuth) float64 3kB 0.5 1.544 2.51 ... 358.5 359.5
elevation (azimuth) float64 3kB ...
time (azimuth) datetime64[ns] 3kB ...
* range (range) float32 2kB 125.0 375.0 ... 9.962e+04 9.988e+04
Data variables:
DBZH (azimuth, range) float64 1MB ...
sweep_mode <U20 80B ...
sweep_number int64 8B ...
prt_mode <U7 28B ...
follow_mode <U7 28B ...
sweep_fixed_angle float64 8B ...dtree = xd.open_datatree(filename, engine="rainbow", sweep=["sweep_1", "sweep_2", "sweep_8"])
display(dtree)
<xarray.DataTree>
Group: /
│ Dimensions: (sweep: 3)
│ Coordinates:
│ longitude float64 8B ...
│ altitude float64 8B ...
│ latitude float64 8B ...
│ Dimensions without coordinates: sweep
│ Data variables:
│ volume_number int64 8B ...
│ platform_type <U5 20B ...
│ instrument_type <U5 20B ...
│ time_coverage_start <U20 80B ...
│ time_coverage_end <U20 80B ...
│ sweep_group_name (sweep) int64 24B ...
│ sweep_fixed_angle (sweep) float64 24B ...
│ Attributes:
│ Conventions: None
│ instrument_name: None
│ version: None
│ title: None
│ institution: None
│ references: None
│ source: None
│ history: None
│ comment: im/exported using xradar
├── Group: /sweep_0
│ Dimensions: (azimuth: 361, range: 400)
│ Coordinates:
│ * azimuth (azimuth) float64 3kB 0.5055 1.549 2.516 ... 358.5 359.5
│ elevation (azimuth) float64 3kB ...
│ time (azimuth) datetime64[ns] 3kB ...
│ * range (range) float32 2kB 125.0 375.0 ... 9.962e+04 9.988e+04
│ Data variables:
│ DBZH (azimuth, range) float64 1MB ...
│ sweep_mode <U20 80B ...
│ sweep_number int64 8B ...
│ prt_mode <U7 28B ...
│ follow_mode <U7 28B ...
│ sweep_fixed_angle float64 8B ...
├── Group: /sweep_1
│ Dimensions: (azimuth: 361, range: 400)
│ Coordinates:
│ * azimuth (azimuth) float64 3kB 0.511 1.505 2.505 ... 358.5 359.5
│ elevation (azimuth) float64 3kB ...
│ time (azimuth) datetime64[ns] 3kB ...
│ * range (range) float32 2kB 125.0 375.0 ... 9.962e+04 9.988e+04
│ Data variables:
│ DBZH (azimuth, range) float64 1MB ...
│ sweep_mode <U20 80B ...
│ sweep_number int64 8B ...
│ prt_mode <U7 28B ...
│ follow_mode <U7 28B ...
│ sweep_fixed_angle float64 8B ...
└── Group: /sweep_2
Dimensions: (azimuth: 361, range: 400)
Coordinates:
* azimuth (azimuth) float64 3kB 0.5 1.544 2.51 ... 358.5 359.5
elevation (azimuth) float64 3kB ...
time (azimuth) datetime64[ns] 3kB ...
* range (range) float32 2kB 125.0 375.0 ... 9.962e+04 9.988e+04
Data variables:
DBZH (azimuth, range) float64 1MB ...
sweep_mode <U20 80B ...
sweep_number int64 8B ...
prt_mode <U7 28B ...
follow_mode <U7 28B ...
sweep_fixed_angle float64 8B ...