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>]
../_images/05b4799fd85a0ebf8d20448810694f61d4b8189dd01f1b68c6c08b9dfbf3d8c9.png

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>
../_images/be857b264fd27f58d0a4f77dc25b1fe31a35e71dd5c3a0a07f95ec506dfee557.png

Plot Range vs. Azimuth#

ds.DBZH.plot()
<matplotlib.collections.QuadMesh at 0x779209e81f90>
../_images/690a048308d2174937fbfd7494ed96193f52a5f136a765645947f7ad21e745ec.png

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>
../_images/1962ea585923f3dcd80c286c36a7c0e849c9945113c950d6480a92c372c5822b.png

Plot Sweep Range vs. Azimuth#

dtree["sweep_0"].ds.DBZH.plot()
<matplotlib.collections.QuadMesh at 0x77920a1d0190>
../_images/2c5eb7cdaec42494465c20af732dcb302f447eaab8cbd2f0bbedc8c71238a17a.png
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 ...