Skip to content

Commit

Permalink
fix: add args and kwargs to all __array__ methods
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmueller committed Jul 2, 2024
1 parent 1cf5de0 commit e77b6d1
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
0.60.3
- fix: add args and kwargs to all __array__ methods
0.60.2
- enh: add [experiment]:timestamp (unix time) to configuration
0.60.1
Expand Down
5 changes: 3 additions & 2 deletions dclab/rtdc_dataset/feat_basin.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,13 +405,14 @@ def __init__(self, feat_obj, basinmap):
self._cache = None
self.is_scalar = bool(len(self.feat_obj.shape) == 1)

def __array__(self):
def __array__(self, dtype=None, *args, **kwargs):
if self._cache is None and self.is_scalar:
self._cache = self.feat_obj[:][self.basinmap]
else:
# This is dangerous territory in terms of memory usage
out_arr = np.empty((len(self.basinmap),) + self.feat_obj.shape[1:],
dtype=self.feat_obj.dtype)
dtype=dtype or self.feat_obj.dtype,
*args, **kwargs)
for ii, idx in enumerate(self.basinmap):
out_arr[ii] = self.feat_obj[idx]
return out_arr
Expand Down
8 changes: 4 additions & 4 deletions dclab/rtdc_dataset/fmt_hdf5/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,15 @@ def __init__(self, h5dataset):
self.identifier = (self.h5dataset.file.filename, self.h5dataset.name)
self.dtype = np.dtype(bool)

def __array__(self, dtype=np.bool_):
def __array__(self, dtype=np.bool_, *args, **kwargs):
if dtype is not np.uint8:
warnings.warn("Please avoid calling the `__array__` method of the "
"`H5MaskEvent`. It may consume a lot of memory.",
UserWarning)
# One of the reasons why we implement __array__ is such that
# the data exporter knows this object is sliceable
# (see yield_filtered_array_stacks).
return self.h5dataset.__array__(dtype=dtype)
return self.h5dataset.__array__(dtype=dtype, *args, **kwargs)

def __getitem__(self, idx):
return np.asarray(self.h5dataset[idx], dtype=bool)
Expand Down Expand Up @@ -180,9 +180,9 @@ def __init__(self, h5ds):
# attrs
self._ufunc_attrs = dict(self.h5ds.attrs)

def __array__(self, dtype=None):
def __array__(self, *args, **kwargs):
if self._array is None:
self._array = np.asarray(self.h5ds, dtype=dtype)
self._array = np.asarray(self.h5ds, *args, **kwargs)
return self._array

def __getitem__(self, idx):
Expand Down
12 changes: 6 additions & 6 deletions dclab/rtdc_dataset/fmt_hierarchy/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ def __init__(self, child, feat):
super(ChildNDArray, self).__init__(child)
self.feat = feat

def __array__(self):
def __array__(self, *args, **kwargs):
warnings.warn("Please avoid calling the `__array__` method of the "
"`ChildNDArray`. It may consume a lot of memory. "
"Consider using a generator instead.",
UserWarning)
return self[:]
return np.asarray(self[:], *args, **kwargs)

def __getitem__(self, idx):
pidx = map_indices_child2parent(child=self.child,
Expand All @@ -69,12 +69,12 @@ def __init__(self, child, feat):
self._ufunc_attrs = {}
self.ndim = 1 # matplotlib might expect this from an array

def __array__(self, dtype=None):
def __array__(self, *args, **kwargs):
if self._array is None:
hparent = self.child.hparent
filt_arr = hparent.filter.all
self._array = hparent[self.feat][filt_arr]
return self._array
return np.asarray(self._array, *args, **kwargs)

def __getitem__(self, idx):
return self.__array__()[idx]
Expand Down Expand Up @@ -121,12 +121,12 @@ def __init__(self, child, flname):
super(ChildTraceItem, self).__init__(child)
self.flname = flname

def __array__(self):
def __array__(self, *args, **kwargs):
warnings.warn("Please avoid calling the `__array__` method of the "
"`ChildTraceItem`. It may consume a lot of memory. "
"Consider using a generator instead.",
UserWarning)
return self[:]
return np.asarray(self[:], *args, **kwargs)

def __getitem__(self, idx):
pidx = map_indices_child2parent(child=self.child,
Expand Down
33 changes: 33 additions & 0 deletions tests/test_rtdc_feat_basin.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,39 @@ def test_basin_cyclic_dependency_found_2():
_ = ds["userdef1"]


@pytest.mark.filterwarnings(
"ignore::dclab.rtdc_dataset.config.WrongConfigurationTypeWarning")
@pytest.mark.filterwarnings(
"ignore::UserWarning")
def test_basin_feature_image_export_from_basin_with_hierarchy(tmp_path):
h5path = retrieve_data("fmt-hdf5_fl_wide-channel_2023.zip")
epath = tmp_path / "exported.rtdc"
epath2 = tmp_path / "exported2.rtdc"
# Create a basins-only dataset using the export functionality
with dclab.new_dataset(h5path) as ds:
assert "image" in ds
ds.export.hdf5(path=epath,
features=[],
basins=True,
filtered=False,
)
# Attempt to export image data from the exported dataset
with dclab.new_dataset(epath) as ds:
ds2 = dclab.new_dataset(ds)
assert "image" in ds2
assert "image" not in ds2.features_innate
ds2.export.hdf5(path=epath2,
features=["mask", "image"],
basins=False,
filtered=False,
)

# Open the exported dataset and attempt to access the image feature
with dclab.new_dataset(epath2) as ds:
assert "mask" in ds
assert np.any(ds["mask"][0])


@pytest.mark.filterwarnings(
"ignore::dclab.rtdc_dataset.config.WrongConfigurationTypeWarning")
@pytest.mark.skipif(not DCOR_AVAILABLE, reason="DCOR is not available")
Expand Down
2 changes: 2 additions & 0 deletions tests/test_rtdc_feat_basin_mapped.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ def test_basin_mapped(basinmap):
[1, 3, 4], # very simple case
[1, 1, 1, 2], # not trivial, not realizable with hierarchy children
])
@pytest.mark.filterwarnings(
"ignore::UserWarning")
def test_basin_mapped_export(basinmap):
path = retrieve_data("fmt-hdf5_image-mask-blood_2021.zip")
with h5py.File(path, "a") as h5:
Expand Down

0 comments on commit e77b6d1

Please sign in to comment.