Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3a1e325
update to pynwb new Device class (old DeviceInstance)
alessandratrapani Dec 1, 2025
be0eabb
Rename OpticalLens to ObjectiveLens in extensions and namespace files
alessandratrapani Dec 1, 2025
b637226
Add MicroscopyExperimentMetadata
alessandratrapani Dec 1, 2025
27476b5
update documentation
alessandratrapani Dec 1, 2025
b126a1d
Eliminate the reference to one ImagingSpace in the `SegmentationConta…
alessandratrapani Dec 2, 2025
47bc9fa
update doc
alessandratrapani Dec 2, 2025
340cf8d
add TODO
alessandratrapani Dec 2, 2025
3d41923
ruff fixes
alessandratrapani Dec 2, 2025
f6feac2
Merge branch 'v0.4.x' into NWBEP0004_reviews
alessandratrapani Dec 2, 2025
9cd37a8
Fix import for DynamicTableRegion in mock.py and update type hint in …
alessandratrapani Dec 2, 2025
a2b5c17
add static images representation
alessandratrapani Dec 2, 2025
73a4097
Add MicroscopyStaticImageContainer and related mock functions
alessandratrapani Dec 3, 2025
2b8cb45
update CHANGELOG
alessandratrapani Dec 3, 2025
102ef08
remove MicroscopyStaticImageContainer
alessandratrapani Dec 3, 2025
d07043e
update tests
alessandratrapani Dec 3, 2025
71e8562
Merge branch 'NWBEP0004_reviews_2' of https://github.com/catalystneur…
alessandratrapani Dec 3, 2025
340bfe1
Remove MicroscopyStaticImageContainer definition and references
alessandratrapani Dec 3, 2025
db2fd99
fixes
alessandratrapani Dec 3, 2025
7c7a52c
Merge branch 'NWBEP0004_reviews' into NWBEP0004_reviews_2
alessandratrapani Dec 3, 2025
f7ec69e
Merge branch 'v0.4.x' into NWBEP0004_reviews_2
alessandratrapani Mar 25, 2026
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
- **Breaking Change**: `OpticalLens`changed in `ObjectiveLens`
- **Breaking Change**: `MicroscopyChannel.indicator` changed from a nested group to a link reference
- **Breaking Change**: `MicroscopySeries.microscopy_rig` changed from a nested group to a link reference
- Updated `ndx-ophys-devices` dependency from v0.2.0 to v0.4.0
- Updated `ndx-ophys-devices` dependency from v0.2.0 to < v0.5.0

## Features
- Added static image support for microscopy experiments:
- `MicroscopyStaticImage`: Base class for static images
- `PlanarMicroscopyStaticImage`: For 2D static images
- `VolumetricMicroscopyStaticImage`: For 3D static images
- Added `MicroscopyExperimentMetadata` (extends `LabMetaData`) as a centralized container for experiment metadata, including:
- `MicroscopyRig` objects
- `ViralVector` objects (from ndx-ophys-devices)
Expand Down
18 changes: 13 additions & 5 deletions docs/source/format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,16 @@ Container for multiple PlanarMicroscopySeries.
- neurodata_type_def: MultiPlaneMicroscopyContainer
neurodata_type_inc: NWBDataInterface
default_name: MultiPlaneMicroscopyContainer
doc: Imaging data acquired over several depths, regularly or irregularly spaced; for instance, when using an
electrically tunable lens. Each depth scan is stored in a separate PlanarMicroscopySeries object.
doc:
Imaging data acquired over several depths, regularly or irregularly spaced; for instance, when using an
electrically tunable lens. Each depth scan is stored in a separate PlanarMicroscopySeries or PlanarMicroscopyStaticImage object.
groups:
- neurodata_type_inc: PlanarMicroscopySeries
doc: PlanarMicroscopySeries object(s) containing imaging data for a single depth scan.
quantity: "+"
quantity: "*"
- neurodata_type_inc: PlanarMicroscopyStaticImage
doc: PlanarMicroscopyStaticImage object(s) containing imaging data for a single depth scan.
quantity: "*"

MultiChannelMicroscopyContainer
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -242,11 +246,15 @@ Container for multiple PlanerMicroscopySeries or VolumetricMicroscopySeries acqu
default_name: MultiChannelMicroscopyContainer
doc:
Imaging data acquired over several channels; for instance, when using multiple excitation wavelengths
or multiple indicators. Each channel is stored in a separate PlanarMicroscopySeries or VolumetricMicroscopySeries object.
or multiple indicators. Each channel is stored in a separate PlanarMicroscopySeries, VolumetricMicroscopySeries,
PlanarMicroscopyStaticImage or VolumetricMicroscopyStaticImage.
groups:
- neurodata_type_inc: MicroscopySeries
doc: MicroscopySeries object containing imaging data for a single channel scan.
quantity: "+"
quantity: "*"
- neurodata_type_inc: MicroscopyStaticImage
doc: MicroscopyStaticImage object containing imaging data for a single channel scan.
quantity: "*"

Illumination Pattern Components
--------------------------
Expand Down
78 changes: 75 additions & 3 deletions spec/ndx-microscopy.extensions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,72 @@ groups:
- - 3
quantity: "?"

- neurodata_type_def: MicroscopyStaticImage
neurodata_type_inc: NWBDataInterface
doc:
Abstract class to contain static imaging data acquired from an optical channel in a microscope while a light source illuminates the
imaging space.
attributes:
- name: name
dtype: text
doc: Name of the static image.
- name: description
dtype: text
doc: Description of the static image.
links:
- name: microscopy_rig
doc: Link to a MicroscopyRig object containing metadata about the microscopy rig used to acquire this imaging data.
target_type: MicroscopyRig
groups:
- neurodata_type_inc: MicroscopyChannel
doc: MicroscopyChannel object containing metadata about the channel used to acquire this imaging data.
quantity: 1

- neurodata_type_def: PlanarMicroscopyStaticImage
neurodata_type_inc: MicroscopyStaticImage
doc:
Static imaging data acquired from an optical channel in a microscope while a light source illuminates a
planar imaging space.
datasets:
- name: data
doc: Recorded imaging data, shaped by (frame height, frame width).
dtype: numeric
dims:
- height
- width
shape:
- null
- null
groups:
- neurodata_type_inc: PlanarImagingSpace
doc:
PlanarImagingSpace object containing metadata about the region of physical space this imaging data
was recorded from.

- neurodata_type_def: VolumetricMicroscopyStaticImage
neurodata_type_inc: MicroscopyStaticImage
doc:
Static volumetric imaging data acquired from an optical channel in a microscope while a light source
illuminates a volumetric imaging space.
Assumes the number of depth scans used to construct the volume is regular.
datasets:
- name: data
doc: Recorded imaging data, shaped by (frame height, frame width, number of depth planes).
dtype: numeric
dims:
- height
- width
- depths
shape:
- null
- null
- null
groups:
- neurodata_type_inc: VolumetricImagingSpace
doc:
VolumetricImagingSpace object containing metadata about the region of physical space this imaging data
was recorded from.

- neurodata_type_def: MicroscopySeries
neurodata_type_inc: TimeSeries
doc:
Expand Down Expand Up @@ -316,18 +382,24 @@ groups:
groups:
- neurodata_type_inc: PlanarMicroscopySeries
doc: PlanarMicroscopySeries object(s) containing imaging data for a single depth scan.
quantity: "+"
quantity: "*"
- neurodata_type_inc: PlanarMicroscopyStaticImage
doc: PlanarMicroscopyStaticImage object(s) containing imaging data for a single depth scan.
quantity: "*"

- neurodata_type_def: MultiChannelMicroscopyContainer
neurodata_type_inc: NWBDataInterface
default_name: MultiChannelMicroscopyContainer
doc:
Imaging data acquired over several channels; for instance, when using multiple excitation wavelengths
or multiple indicators. Each channel is stored in a separate PlanarMicroscopySeries or VolumetricMicroscopySeries object.
or multiple indicators. Each channel is stored in a separate PlanarMicroscopySeries or VolumetricMicroscopySeries.
groups:
- neurodata_type_inc: MicroscopySeries
doc: MicroscopySeries object containing imaging data for a single channel scan.
quantity: "+"
quantity: "*"
- neurodata_type_inc: MicroscopyStaticImage
doc: MicroscopyStaticImage object containing imaging data for a single channel scan.
quantity: "*"

- neurodata_type_def: SegmentationContainer
neurodata_type_inc: NWBDataInterface
Expand Down
2 changes: 2 additions & 0 deletions spec/ndx-microscopy.namespace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ namespaces:
neurodata_types:
- ExcitationSource
- Indicator
- ViralVectorInjection
- ViralVector
- OpticalFilter
- Photodetector
- DichroicMirror
Expand Down
6 changes: 6 additions & 0 deletions src/pynwb/ndx_microscopy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
PlanarImagingSpace = get_class("PlanarImagingSpace", extension_name)
VolumetricImagingSpace = get_class("VolumetricImagingSpace", extension_name)

MicroscopyStaticImage = get_class("MicroscopyStaticImage", extension_name)
PlanarMicroscopyStaticImage = get_class("PlanarMicroscopyStaticImage", extension_name)
VolumetricMicroscopyStaticImage = get_class("VolumetricMicroscopyStaticImage", extension_name)
MicroscopySeries = get_class("MicroscopySeries", extension_name)
PlanarMicroscopySeries = get_class("PlanarMicroscopySeries", extension_name)
VolumetricMicroscopySeries = get_class("VolumetricMicroscopySeries", extension_name)
Expand Down Expand Up @@ -91,6 +94,9 @@
"MicroscopySeries",
"PlanarMicroscopySeries",
"VolumetricMicroscopySeries",
"MicroscopyStaticImage",
"PlanarMicroscopyStaticImage",
"VolumetricMicroscopyStaticImage",
"MultiPlaneMicroscopyContainer",
"MultiChannelMicroscopyContainer",
"MicroscopyResponseSeries",
Expand Down
4 changes: 4 additions & 0 deletions src/pynwb/ndx_microscopy/testing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
mock_MicroscopyResponseSeriesContainer,
mock_PlanarImagingSpace,
mock_PlanarMicroscopySeries,
mock_PlanarMicroscopyStaticImage,
mock_MultiPlaneMicroscopyContainer,
mock_MultiChannelMicroscopyContainer,
mock_VolumetricImagingSpace,
mock_VolumetricMicroscopySeries,
mock_VolumetricMicroscopyStaticImage,
mock_IlluminationPattern,
mock_LineScan,
mock_PlaneAcquisition,
Expand All @@ -33,9 +35,11 @@
"mock_SegmentationContainer",
"mock_Segmentation",
"mock_PlanarMicroscopySeries",
"mock_PlanarMicroscopyStaticImage",
"mock_MultiPlaneMicroscopyContainer",
"mock_MultiChannelMicroscopyContainer",
"mock_VolumetricMicroscopySeries",
"mock_VolumetricMicroscopyStaticImage",
"mock_MicroscopyResponseSeries",
"mock_MicroscopyResponseSeriesContainer",
"mock_IlluminationPattern",
Expand Down
62 changes: 56 additions & 6 deletions src/pynwb/ndx_microscopy/testing/_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,31 +395,58 @@ def mock_PlanarMicroscopySeries(
return planar_microscopy_series


def mock_PlanarMicroscopyStaticImage(
*,
microscopy_rig: ndx_microscopy.MicroscopyRig,
planar_imaging_space: ndx_microscopy.PlanarImagingSpace,
microscopy_channel: ndx_microscopy.MicroscopyChannel,
name: Optional[str] = None,
description: str = "A mock instance of a PlanarMicroscopyStaticImage type to be used for rapid testing.",
data: Optional[np.ndarray] = None,
) -> ndx_microscopy.PlanarMicroscopyStaticImage:
image_name = name or name_generator("PlanarMicroscopyStaticImage")
image_data = data if data is not None else np.ones(shape=(5, 5))

planar_microscopy_static_image = ndx_microscopy.PlanarMicroscopyStaticImage(
name=image_name,
description=description,
microscopy_rig=microscopy_rig,
microscopy_channel=microscopy_channel,
planar_imaging_space=planar_imaging_space,
data=image_data,
)
return planar_microscopy_static_image


def mock_MultiPlaneMicroscopyContainer(
*,
planar_microscopy_series: List[ndx_microscopy.PlanarMicroscopySeries],
planar_microscopy_static_images: Optional[List[ndx_microscopy.PlanarMicroscopyStaticImage]] = None,
planar_microscopy_series: Optional[List[ndx_microscopy.PlanarMicroscopySeries]] = None,
name: Optional[str] = None,
) -> ndx_microscopy.MultiPlaneMicroscopyContainer:
container_name = name or name_generator("MultiPlaneMicroscopyContainer")

multi_plane_microscopy_container = ndx_microscopy.MultiPlaneMicroscopyContainer(
name=container_name, planar_microscopy_series=planar_microscopy_series
name=container_name,
planar_microscopy_static_images=planar_microscopy_static_images,
planar_microscopy_series=planar_microscopy_series,
)

return multi_plane_microscopy_container


def mock_MultiChannelMicroscopyContainer(
*,
microscopy_series: List[ndx_microscopy.MicroscopySeries],
microscopy_static_images: Optional[List[ndx_microscopy.MicroscopyStaticImage]] = None,
microscopy_series: Optional[List[ndx_microscopy.MicroscopySeries]] = None,
name: Optional[str] = None,
) -> ndx_microscopy.MultiChannelMicroscopyContainer:
container_name = name or name_generator("MultiChannelMicroscopyContainer")

multi_channel_microscopy_container = ndx_microscopy.MultiChannelMicroscopyContainer(
name=container_name, microscopy_series=microscopy_series
name=container_name,
microscopy_static_images=microscopy_static_images,
microscopy_series=microscopy_series,
)

return multi_channel_microscopy_container


Expand Down Expand Up @@ -476,6 +503,29 @@ def mock_VolumetricMicroscopySeries(
return volumetric_microscopy_series


def mock_VolumetricMicroscopyStaticImage(
*,
microscopy_rig: ndx_microscopy.MicroscopyRig,
volumetric_imaging_space: ndx_microscopy.VolumetricImagingSpace,
microscopy_channel: ndx_microscopy.MicroscopyChannel,
name: Optional[str] = None,
description: str = "A mock instance of a VolumetricMicroscopyStaticImage type to be used for rapid testing.",
data: Optional[np.ndarray] = None,
) -> ndx_microscopy.VolumetricMicroscopyStaticImage:
image_name = name or name_generator("VolumetricMicroscopyStaticImage")
image_data = data if data is not None else np.ones(shape=(5, 5, 5))

volumetric_microscopy_static_image = ndx_microscopy.VolumetricMicroscopyStaticImage(
name=image_name,
description=description,
microscopy_rig=microscopy_rig,
microscopy_channel=microscopy_channel,
volumetric_imaging_space=volumetric_imaging_space,
data=image_data,
)
return volumetric_microscopy_static_image


def mock_MicroscopyResponseSeries(
*,
rois: DynamicTableRegion,
Expand Down
Loading
Loading