Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional parameters to OpticalSeries constructor #2023

Merged
merged 11 commits into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading