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

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
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 @@ -4,6 +4,9 @@

### Enhancements and minor changes
- 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 @@ -325,12 +325,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
50 changes: 49 additions & 1 deletion tests/unit/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import numpy as np

from pynwb import TimeSeries
from pynwb import TimeSeries, NWBHDF5IO
from pynwb.base import Image, Images, ImageReferences
from pynwb.device import Device
from pynwb.image import (
Expand Down Expand Up @@ -396,6 +396,54 @@ 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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a roundtrip test to make sure read/write is ok?

self.assertIsNone(ts.field_of_view)
self.assertIsNone(ts.orientation)

def test_roundtrip_optional_fields(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move this test to tests/integration/hdf5/test_image.py with the other roundtrip image tests?

This test is currently failing in Windows due to a file access issue. The NWBH5IOMixin could also be used to simplify the file setup for read/write testing.

"""Test that OpticalSeries with optional fields set to None can be written to and read from file."""
from datetime import datetime
import tempfile
from pynwb import NWBFile

nwbfile = NWBFile(
session_description='test session',
identifier='TEST123',
session_start_time=datetime.now().astimezone()
)

# Create OpticalSeries without providing the optional fields
ts = OpticalSeries(
name="test_ts",
unit="unit",
external_file=["external_file"],
starting_frame=[0],
format="external",
timestamps=[1.0, 2.0]
)

nwbfile.add_acquisition(ts)

with tempfile.NamedTemporaryFile(suffix='.nwb') as temp:
with NWBHDF5IO(temp.name, mode='w') as io:
io.write(nwbfile)
with NWBHDF5IO(temp.name, mode='r', load_namespaces=True) as io:
nwbfile_read = io.read()
ts_read = nwbfile_read.acquisition['test_ts']
self.assertIsNone(ts_read.distance)
self.assertIsNone(ts_read.field_of_view)
self.assertIsNone(ts_read.orientation)

class TestImageSubtypes(TestCase):

def test_grayscale_image(self):
Expand Down
Loading