From fc00d484dee1e5931ab030f57a0788fec4bfa898 Mon Sep 17 00:00:00 2001 From: Ryan Ly Date: Wed, 18 May 2022 16:05:40 -0700 Subject: [PATCH 1/4] Warn instead of raise error if spatialseries has more than 3 columns --- src/pynwb/behavior.py | 25 +++++++++++++++++++++---- tests/unit/test_behavior.py | 9 ++------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/pynwb/behavior.py b/src/pynwb/behavior.py index 8638d1f25..026b62606 100644 --- a/src/pynwb/behavior.py +++ b/src/pynwb/behavior.py @@ -1,4 +1,6 @@ -from hdmf.utils import docval, popargs, get_docval +import warnings + +from hdmf.utils import docval, popargs, get_docval, get_data_shape from . import register_class, CORE_NAMESPACE from .core import MultiContainerInterface @@ -21,9 +23,7 @@ class SpatialSeries(TimeSeries): __nwbfields__ = ('reference_frame',) @docval(*get_docval(TimeSeries.__init__, 'name'), # required - {'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': ( - (None, ), (None, 1), (None, 2), (None, 3) - ), # required + {'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': ((None, ), (None, None)), # required 'doc': ('The data values. Can be 1D or 2D. The first dimension must be time. If 2D, there can be 1, 2, ' 'or 3 columns, which represent x, y, and z.')}, {'name': 'reference_frame', 'type': str, # required @@ -38,8 +38,25 @@ def __init__(self, **kwargs): """ name, data, reference_frame, unit = popargs('name', 'data', 'reference_frame', 'unit', kwargs) super(SpatialSeries, self).__init__(name, data, unit, **kwargs) + + # NWB 2.5 restricts length of second dimension to be <= 3 + allowed_data_shapes = ((None, ), (None, 1), (None, 2), (None, 3)) + data_shape = get_data_shape(data) + if not any(self._validate_data_shape(data_shape, a) for a in allowed_data_shapes): + warnings.warn("SpatialSeries '%s' has data shape %s which is not compliant with NWB 2.5 and greater." % + (name, str(data_shape))) + self.reference_frame = reference_frame + @staticmethod + def _validate_data_shape(valshape, argshape): + if not len(valshape) == len(argshape): + return False + for a, b in zip(valshape, argshape): + if b not in (a, None): + return False + return True + @register_class('BehavioralEpochs', CORE_NAMESPACE) class BehavioralEpochs(MultiContainerInterface): diff --git a/tests/unit/test_behavior.py b/tests/unit/test_behavior.py index 9ba75e128..432088695 100644 --- a/tests/unit/test_behavior.py +++ b/tests/unit/test_behavior.py @@ -20,15 +20,10 @@ def test_set_unit(self): self.assertEqual(sS.unit, 'degrees') def test_gt_3_cols(self): - with self.assertRaises(ValueError) as error: + msg = "SpatialSeries 'test_sS' has data shape (5, 4) which is not compliant with NWB 2.5 and greater." + with self.assertWarnsWith(UserWarning, msg): SpatialSeries("test_sS", np.ones((5, 4)), "reference_frame", "meters", rate=30.) - self.assertEqual( - "SpatialSeries.__init__: incorrect shape for 'data' (got '(5, 4)', expected " - "'((None,), (None, 1), (None, 2), (None, 3))')", - str(error.exception) - ) - class BehavioralEpochsConstructor(TestCase): def test_init(self): From 8bc3eb7340732c2a9979e2984112a266cdf7d3b1 Mon Sep 17 00:00:00 2001 From: Ryan Ly Date: Wed, 18 May 2022 16:07:13 -0700 Subject: [PATCH 2/4] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39213a72d..4832ab303 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## PyNWB 2.1.0 (Upcoming) ### Breaking changes: -- Restrict `SpatialSeries.data` to have no more than 3 columns (#1455) +- Raise a warning if `SpatialSeries.data` has more than 3 columns (#1455, #1480) - Updated ``TimeIntervals`` to use the new ``TimeSeriesReferenceVectorData`` type. This does not alter the overall structure of ``TimeIntervals`` in a major way aside from changing the value of the ``neurodata_type`` attribute of the ``TimeIntervals.timeseries`` column from ``VectorData`` to ``TimeSeriesReferenceVectorData``. This change facilitates From 1f8378867ab2ed6fa0ce217f2a9bfc67a34695ac Mon Sep 17 00:00:00 2001 From: Ryan Ly Date: Wed, 18 May 2022 16:37:56 -0700 Subject: [PATCH 3/4] Make warning message clearer --- src/pynwb/behavior.py | 3 ++- tests/unit/test_behavior.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pynwb/behavior.py b/src/pynwb/behavior.py index 026b62606..cd981c76f 100644 --- a/src/pynwb/behavior.py +++ b/src/pynwb/behavior.py @@ -43,7 +43,8 @@ def __init__(self, **kwargs): allowed_data_shapes = ((None, ), (None, 1), (None, 2), (None, 3)) data_shape = get_data_shape(data) if not any(self._validate_data_shape(data_shape, a) for a in allowed_data_shapes): - warnings.warn("SpatialSeries '%s' has data shape %s which is not compliant with NWB 2.5 and greater." % + warnings.warn("SpatialSeries '%s' has data shape %s which is not compliant with NWB 2.5 and greater. " + "The second dimension should have length <= 3 to represent at most x, y, z." % (name, str(data_shape))) self.reference_frame = reference_frame diff --git a/tests/unit/test_behavior.py b/tests/unit/test_behavior.py index 432088695..fdbeaf280 100644 --- a/tests/unit/test_behavior.py +++ b/tests/unit/test_behavior.py @@ -20,7 +20,8 @@ def test_set_unit(self): self.assertEqual(sS.unit, 'degrees') def test_gt_3_cols(self): - msg = "SpatialSeries 'test_sS' has data shape (5, 4) which is not compliant with NWB 2.5 and greater." + msg = ("SpatialSeries 'test_sS' has data shape (5, 4) which is not compliant with NWB 2.5 and greater." + "The second dimension should have length <= 3 to represent at most x, y, z.") with self.assertWarnsWith(UserWarning, msg): SpatialSeries("test_sS", np.ones((5, 4)), "reference_frame", "meters", rate=30.) From de6b4f7bce46fcf2acd1e0603ca7ff70375fa7c4 Mon Sep 17 00:00:00 2001 From: Ryan Ly Date: Wed, 18 May 2022 23:19:43 -0700 Subject: [PATCH 4/4] Update test_behavior.py --- tests/unit/test_behavior.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_behavior.py b/tests/unit/test_behavior.py index fdbeaf280..664365070 100644 --- a/tests/unit/test_behavior.py +++ b/tests/unit/test_behavior.py @@ -20,7 +20,7 @@ def test_set_unit(self): self.assertEqual(sS.unit, 'degrees') def test_gt_3_cols(self): - msg = ("SpatialSeries 'test_sS' has data shape (5, 4) which is not compliant with NWB 2.5 and greater." + msg = ("SpatialSeries 'test_sS' has data shape (5, 4) which is not compliant with NWB 2.5 and greater. " "The second dimension should have length <= 3 to represent at most x, y, z.") with self.assertWarnsWith(UserWarning, msg): SpatialSeries("test_sS", np.ones((5, 4)), "reference_frame", "meters", rate=30.)