Skip to content

Commit 1f0a70c

Browse files
committed
[DataView] allows to be created as invalid, ...
no exceptions are thrown upon creation, DataView is invalid though and reading the data will return an empty array Adds a "debug_message" to troubleshoot why the DV might be empty Adapts the tests
1 parent 1d9bf80 commit 1f0a70c

File tree

2 files changed

+56
-18
lines changed

2 files changed

+56
-18
lines changed

nixio/data_view.py

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,66 @@
1111
from collections.abc import Iterable
1212
except ImportError:
1313
from collections import Iterable
14+
import numpy as np
1415
from .data_set import DataSet
15-
from .exceptions import OutOfBounds, IncompatibleDimensions
16+
from .exceptions import OutOfBounds, InvalidSlice
1617

1718

1819
class DataView(DataSet):
1920

2021
def __init__(self, da, slices):
21-
if len(slices) != len(da.shape):
22+
self._valid = slices is not None and all(slices)
23+
self._slices = slices
24+
if not self.valid:
25+
self._error_message = (
26+
"InvalidSlice error!"
27+
"Given slice {} is invalid! At least one slice along one dimension"
28+
"does not contain data.".format(slices)
29+
)
30+
else:
31+
self._error_message = ""
32+
33+
if self.valid and len(slices) != len(da.shape):
2234
# This is always checked by the calling function, but we repeat
2335
# the check here for future bug catching
24-
raise IncompatibleDimensions(
36+
self._valid = False
37+
self._error_message = (
38+
"IncompatibleDimensions error."
2539
"Number of dimensions for DataView does not match underlying "
2640
"data object: {} != {}".format(len(slices), len(da.shape)),
27-
"DataView"
2841
)
2942

30-
if any(s.stop > e for s, e in zip(slices, da.data_extent)):
31-
raise OutOfBounds(
32-
"Trying to create DataView which is out of bounds of the "
33-
"underlying DataArray"
43+
if self.valid and any(s.stop > e for s, e in zip(slices, da.data_extent)):
44+
self._valid = False
45+
self._error_message = (
46+
"OutOfBounds error!"
47+
"Trying to create DataView with slices {} which are out of bounds of the "
48+
"underlying DataArray {}".format(self._slices, da.shape)
3449
)
3550

3651
# Simplify all slices
37-
slices = tuple(slice(*sl.indices(dimlen))
38-
for sl, dimlen in zip(slices, da.shape))
52+
if self.valid:
53+
slices = tuple(slice(*sl.indices(dimlen))
54+
for sl, dimlen in zip(slices, da.shape))
55+
self._slices = slices
3956

4057
self.array = da
4158
self._h5group = self.array._h5group
42-
self._slices = slices
59+
60+
@property
61+
def valid(self):
62+
return self._valid
63+
64+
@property
65+
def debug_message(self):
66+
return self._error_message
4367

4468
@property
4569
def data_extent(self):
46-
return tuple(s.stop - s.start for s in self._slices)
70+
if self.valid:
71+
return tuple(s.stop - s.start for s in self._slices)
72+
else:
73+
return None
4774

4875
@data_extent.setter
4976
def data_extent(self, v):
@@ -54,12 +81,19 @@ def data_type(self):
5481
return self.array.data_type
5582

5683
def _write_data(self, data, sl=None):
84+
if not self.valid:
85+
raise InvalidSlice(
86+
"Write Data failed due to an invalid slice."
87+
"Reason is: {}".format(self._error_message)
88+
)
5789
tsl = self._slices
5890
if sl:
5991
tsl = self._transform_coordinates(sl)
6092
super(DataView, self)._write_data(data, tsl)
6193

6294
def _read_data(self, sl=None):
95+
if not self.valid:
96+
return np.array([])
6397
tsl = self._slices
6498
if sl is not None:
6599
tsl = self._transform_coordinates(sl)
@@ -90,7 +124,7 @@ def transform_slice(uslice, dvslice):
90124
ustart, ustop, ustep = uslice.indices(dimlen)
91125
if ustop < 0: # special case for None stop
92126
ustop = dimlen + ustop
93-
tslice = slice(dvslice.start+ustart, dvslice.start+ustop, ustep)
127+
tslice = slice(dvslice.start + ustart, dvslice.start + ustop, ustep)
94128
if tslice.stop > dvslice.stop:
95129
raise oob
96130

@@ -141,7 +175,7 @@ def _expand_user_slices(self, user_slices):
141175
expidx = user_slices.index(Ellipsis)
142176
npad = len(self.data_extent) - len(user_slices) + 1
143177
padding = (slice(None),) * npad
144-
return user_slices[:expidx] + padding + user_slices[expidx+1:]
178+
return user_slices[:expidx] + padding + user_slices[expidx + 1:]
145179

146180
# expand slices at the end
147181
npad = len(self.data_extent) - len(user_slices)

nixio/test/test_data_view.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,21 @@ def test_data_view_write_index(self):
123123

124124
def test_data_view_oob(self):
125125
da = self.file.blocks[0].data_arrays[0]
126+
from IPython import embed
126127

127-
with self.assertRaises(nix.exceptions.OutOfBounds):
128-
da.get_slice((41, 81), extents=(1, 1))
128+
dv = da.get_slice((41, 81), extents=(1, 1))
129+
assert not dv.valid
130+
assert "OutOfBounds error" in dv.debug_message
129131

130-
with self.assertRaises(nix.exceptions.OutOfBounds):
131-
da.get_slice((0, 0), extents=(100, 5))
132+
dv = da.get_slice((0, 0), extents=(100, 5))
133+
assert not dv.valid
134+
assert "OutOfBounds error" in dv.debug_message
132135

133136
with self.assertRaises(nix.exceptions.IncompatibleDimensions):
134137
da.get_slice((0, 0, 0), extents=(5, 5, 5))
135138

136139
dv = da.get_slice((5, 8), extents=(10, 20))
140+
assert dv.valid
137141

138142
with self.assertRaises(nix.exceptions.OutOfBounds):
139143
_ = dv[12, :]

0 commit comments

Comments
 (0)