Source code for

#!/usr/bin/env python
# Copyright (c) 2021-2023, wradlib developers.
# Distributed under the MIT License. See LICENSE.txt for more info.

Xarray backends
Reading radar data into xarray Datasets using ``xarray.open_dataset``
and ``xarray.open_mfdataset``.

Former available backends have been ported to `xradar <>`__-package.

.. autosummary::
   :toctree: generated/

__all__ = [

__doc__ = __doc__.format("\n   ".join(__all__))

import io

import numpy as np
from xarray.backends.common import AbstractDataStore, BackendArray, BackendEntrypoint
from xarray.backends.file_manager import CachingFileManager, DummyFileManager
from xarray.backends.locks import SerializableLock, ensure_lock
from import StoreBackendEntrypoint
from xarray.core import indexing
from xarray.core.utils import Frozen, FrozenDict, close_on_error
from xarray.core.variable import Variable

from import _radolan_file

RADOLAN_LOCK = SerializableLock()

class RadolanArrayWrapper(BackendArray):
    """Wraps array of RADOLAN data."""

    def __init__(self, datastore, name, array):
        self.datastore = datastore = name
        self.shape = array.shape
        self.dtype = array.dtype

    def _getitem(self, key):

    def __getitem__(self, key):
        return indexing.explicit_indexing_adapter(

class RadolanDataStore(AbstractDataStore):
    """Implements ``xarray.AbstractDataStore`` read-only API for a RADOLAN files."""

    def __init__(
        self, filename_or_obj, lock=None, fillmissing=False, copy=False, ancillary=False
        if lock is None:
            lock = RADOLAN_LOCK
        self.lock = ensure_lock(lock)

        if isinstance(filename_or_obj, str):
            manager = CachingFileManager(
                    "fillmissing": fillmissing,
                    "copy": copy,
                    "ancillary": ancillary,
            if isinstance(filename_or_obj, bytes):
                filename_or_obj = io.BytesIO(filename_or_obj)
            dataset = _radolan_file(
                filename_or_obj, fillmissing=fillmissing, copy=copy, ancillary=ancillary
            manager = DummyFileManager(dataset)

        self._manager = manager
        self._filename = self.ds.filename

    def _acquire(self, needs_lock=True):
        with self._manager.acquire_context(needs_lock) as ds:
            return ds

    def ds(self):
        return self._acquire()

    def open_store_variable(self, name, var):
        encoding = {"source": self._filename}
        vdata =
        if isinstance(vdata, np.ndarray):
            data = vdata
            data = indexing.LazilyOuterIndexedArray(
                RadolanArrayWrapper(self, name, vdata)
        return Variable(var.dimensions, data, var.attributes, encoding)

    def get_variables(self):
        return FrozenDict(
            (k, self.open_store_variable(k, v)) for k, v in self.ds.variables.items()

    def get_attrs(self):
        return Frozen(self.ds.attributes)

    def get_dimensions(self):
        return Frozen(self.ds.dimensions)

    def get_encoding(self):
        dims = self.get_dimensions()
        encoding = {"unlimited_dims": {k for k, v in dims.items() if v is None}}
        return encoding

    def close(self, **kwargs):

[docs]class RadolanBackendEntrypoint(BackendEntrypoint): """Xarray BackendEntrypoint for RADOLAN data.""" description = "Open RADOLAN in Xarray" url = ""
[docs] def 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, fillmissing=False, copy=False, ancillary=False, ): store = RadolanDataStore( filename_or_obj, fillmissing=fillmissing, copy=copy, ancillary=ancillary, ) store_entrypoint = StoreBackendEntrypoint() with close_on_error(store): ds = store_entrypoint.open_dataset( store, mask_and_scale=mask_and_scale, decode_times=decode_times, concat_characters=concat_characters, decode_coords=decode_coords, drop_variables=drop_variables, use_cftime=use_cftime, decode_timedelta=decode_timedelta, ) return ds