diff --git a/h5rdmtoolbox/wrapper/core.py b/h5rdmtoolbox/wrapper/core.py index 437f5a90..80f0401d 100644 --- a/h5rdmtoolbox/wrapper/core.py +++ b/h5rdmtoolbox/wrapper/core.py @@ -1668,12 +1668,18 @@ def __setitem__(self, key, value): super().__setitem__(key, value) @dataset_value_decoder - def __getitem__(self, args, new_dtype=None, nparray=False) -> Union[xr.DataArray, np.ndarray]: + def __getitem__(self, args, new_dtype=None, nparray=False, links_as_strings:bool=False) -> Union[xr.DataArray, np.ndarray]: """Return sliced HDF dataset. If global setting `return_xarray` is set to True, a `xr.DataArray` is returned, otherwise the default behaviour of the h5p-package is used and a np.ndarray is returned. Note, that even if `return_xarray` is True, there is another way to - receive numpy array. This is by calling .values[:] on the dataset.""" + receive numpy array. This is by calling .values[:] on the dataset. + + Parameters + ---------- + links_as_strings: bool + Attributes, that are links to other datasets or groups are returned as strings. + """ args = args if isinstance(args, tuple) else (args,) @@ -1691,7 +1697,16 @@ def __getitem__(self, args, new_dtype=None, nparray=False) -> Union[xr.DataArray args = tuple(args) arr = super().__getitem__(args, new_dtype=new_dtype) - ds_attrs = self.attrs + + if links_as_strings: + attrs = dict(self.attrs) + for k, v in attrs.copy().items(): + if isinstance(v, (h5py.Group, h5py.Dataset)): + attrs[k] = v.name + ds_attrs = attrs + else: + ds_attrs = self.attrs + attrs = pop_hdf_attributes(ds_attrs) if 'DIMENSION_LIST' in ds_attrs: diff --git a/h5rdmtoolbox/wrapper/ds_decoder.py b/h5rdmtoolbox/wrapper/ds_decoder.py index 5a1c149e..6cf1d374 100644 --- a/h5rdmtoolbox/wrapper/ds_decoder.py +++ b/h5rdmtoolbox/wrapper/ds_decoder.py @@ -68,6 +68,7 @@ def wrapper(*args, **kwargs): """wrapper that decodes the xarray.DataArray object""" ds = args[0] assert isinstance(ds, h5py.Dataset) + kwargs.update(links_as_strings=True) xarr = func(*args, **kwargs) parent_slice = args[1] diff --git a/tests/wrapper/test_core.py b/tests/wrapper/test_core.py index e03cc438..2ff7131d 100644 --- a/tests/wrapper/test_core.py +++ b/tests/wrapper/test_core.py @@ -1,12 +1,13 @@ import datetime -import h5py import json -import numpy as np -import pandas as pd import pathlib import unittest -import xarray as xr from datetime import datetime, timedelta + +import h5py +import numpy as np +import pandas as pd +import xarray as xr from numpy import linspace as ls import h5rdmtoolbox as h5tbx @@ -28,7 +29,8 @@ def test_lower(self): self.assertEqual(h5tbx.Lower('Hello'), 'hello') self.assertIsInstance(h5tbx.lower('Hello'), h5tbx.Lower) - def tearDownClass(): + @classmethod + def tearDownClass(cls) -> None: h5tbx.set_config(auto_create_h5tbx_version=False) def test_File(self): @@ -771,3 +773,17 @@ def test_multidim_time_ds(self): self.assertIsInstance(t, xr.DataArray) self.assertEqual(t.shape, (2, 3)) self.assertIsInstance(t[0, 0].values, np.datetime64) + + def test_attr_group_link_and_xarray(self): + with h5tbx.File() as h5: + grp = h5.create_group('my_grp') + ds = h5.create_dataset(name='ds', data=4) + + ds.attrs['link to grp'] = grp + + self.assertIsInstance(ds.attrs['link to grp'], h5py.Group) + + da = ds[()] + self.assertIsInstance(da, xr.DataArray) + self.assertIsInstance(da.attrs['link to grp'], str) + print(da)