Skip to content

Commit

Permalink
Add optional parameters to OpticalSeries constructor (#2023)
Browse files Browse the repository at this point in the history
Co-authored-by: Steph Prince <[email protected]>
Co-authored-by: Ryan Ly <[email protected]>
  • Loading branch information
3 people authored Feb 20, 2025
1 parent f3b3306 commit 5564f82
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
### Enhancements and minor changes
- Added `__all__` to modules. @bendichter [#2021](https://github.com/NeurodataWithoutBorders/pynwb/pull/2021)
- Added `pynwb.read_nwb` convenience method to simplify reading an NWBFile written with any backend @h-mayorquin [#1994](https://github.com/NeurodataWithoutBorders/pynwb/pull/1994)

### Bug fixes
- Made distance, orientation, and field_of_view optional in OpticalSeries to match schema @bendichter [#2023](https://github.com/NeurodataWithoutBorders/pynwb/pull/2023)
- Added support for NWB schema 2.8.0. @rly [#2001](https://github.com/NeurodataWithoutBorders/pynwb/pull/2001)
- Removed `SpatialSeries.bounds` field that was not functional. This will be fixed in a future release. @rly [#1907](https://github.com/NeurodataWithoutBorders/pynwb/pull/1907), [#1996](https://github.com/NeurodataWithoutBorders/pynwb/pull/1996)
- Added support for `NWBFile.was_generated_by` field. @stephprince [#1924](https://github.com/NeurodataWithoutBorders/pynwb/pull/1924)
Expand Down
26 changes: 20 additions & 6 deletions src/pynwb/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,12 +331,26 @@ class OpticalSeries(ImageSeries):
'orientation')

@docval(*get_docval(ImageSeries.__init__, 'name'), # required
{'name': 'distance', 'type': float, 'doc': 'Distance from camera/monitor to target/eye.'}, # required
{'name': 'field_of_view', 'type': ('array_data', 'data', 'TimeSeries'), 'shape': ((2, ), (3, )), # required
'doc': 'Width, height and depth of image, or imaged area (meters).'},
{'name': 'orientation', 'type': str, # required
'doc': 'Description of image relative to some reference frame (e.g., which way is up). '
'Must also specify frame of reference.'},
{
"name": "distance",
"type": float,
"doc": "Distance from camera/monitor to target/eye.",
"default": None,
},
{
"name": "field_of_view",
"type": ("array_data", "data", "TimeSeries"),
"shape": ((2,), (3,)),
"doc": "Width, height and depth of image, or imaged area (meters).",
"default": None,
},
{
"name": "orientation",
"type": str,
"doc": "Description of image relative to some reference frame (e.g., which way is up). "
"Must also specify frame of reference.",
"default": None,
},
{'name': 'data', 'type': ('array_data', 'data'), 'shape': ([None] * 3, [None, None, None, 3]),
'doc': ('Images presented to subject, either grayscale or RGB. May be 3D or 4D. The first dimension must '
'be time (frame). The second and third dimensions represent x and y. The optional fourth '
Expand Down
32 changes: 32 additions & 0 deletions tests/integration/hdf5/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,35 @@ def addContainer(self, nwbfile):
def getContainer(self, nwbfile):
""" Return the test OpticalSeries from the given NWBFile """
return nwbfile.stimulus['OpticalSeries']


class TestOpticalSeriesOptionalFieldsIO(NWBH5IOMixin, TestCase):
"""Test reading/writing OpticalSeries with optional fields omitted"""

def setUpContainer(self):
""" Return a test OpticalSeries with optional fields set to None """
self.dev1 = Device('dev1')
self.optical_series = OpticalSeries(
name='OpticalSeries',
data=np.ones((10, 3, 3)),
unit='m',
format='raw',
timestamps=np.arange(10.),
device=self.dev1,
)
return self.optical_series

def addContainer(self, nwbfile):
""" Add the test OpticalSeries to the given NWBFile """
nwbfile.add_device(self.dev1)
nwbfile.add_stimulus(self.optical_series)

def getContainer(self, nwbfile):
""" Return the test OpticalSeries from the given NWBFile """
return nwbfile.stimulus['OpticalSeries']

def test_optional_fields(self):
"""Test that optional fields are None when omitted"""
self.assertIsNone(self.optical_series.distance)
self.assertIsNone(self.optical_series.field_of_view)
self.assertIsNone(self.optical_series.orientation)
14 changes: 14 additions & 0 deletions tests/unit/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,20 @@ def test_init(self):
self.assertEqual(ts.format, 'external')


def test_init_all_optional_fields_none(self):
"""Test that OpticalSeries can be created with all optional fields set to None."""
ts = OpticalSeries(
name="test_ts",
unit="unit",
external_file=["external_file"],
starting_frame=[0],
format="external",
timestamps=[1.0, 2.0],
)
self.assertIsNone(ts.distance)
self.assertIsNone(ts.field_of_view)
self.assertIsNone(ts.orientation)

class TestImageSubtypes(TestCase):

def test_grayscale_image(self):
Expand Down

0 comments on commit 5564f82

Please sign in to comment.