From 6f7003bd35ab0543daa1cd7c55d547c88b79bab6 Mon Sep 17 00:00:00 2001 From: Alessandra Trapani Date: Sat, 25 May 2024 17:41:20 +0200 Subject: [PATCH 1/9] integrate devices from ndx-ophys-devices --- spec/ndx-microscopy.extensions.yaml | 478 ++++++++++--------- src/pynwb/ndx_microscopy/__init__.py | 26 +- src/pynwb/ndx_microscopy/testing/__init__.py | 6 +- src/pynwb/ndx_microscopy/testing/_mock.py | 99 +--- src/pynwb/tests/test_constructors.py | 68 +-- src/pynwb/tests/test_ndx_microscopy.py | 29 +- 6 files changed, 340 insertions(+), 366 deletions(-) diff --git a/spec/ndx-microscopy.extensions.yaml b/spec/ndx-microscopy.extensions.yaml index e936d43..5f87b77 100644 --- a/spec/ndx-microscopy.extensions.yaml +++ b/spec/ndx-microscopy.extensions.yaml @@ -1,258 +1,306 @@ groups: - - - neurodata_type_def: Microscope - neurodata_type_inc: Device - doc: A microscope used to acquire imaging data. - attributes: - - name: model - dtype: text - doc: Model identifier of the light source device. - required: false - - - neurodata_type_def: LightSource - neurodata_type_inc: Device - doc: Light source used to illuminate an imaging space. - attributes: - - name: model + - neurodata_type_def: MicroscopyTable + neurodata_type_inc: DynamicTable + doc: Extends DynamicTable to hold metadata on the Microscopy system. + datasets: + - name: location + neurodata_type_inc: VectorData dtype: text - doc: Model identifier of the light source device. - required: false - - name: filter_description + shape: + - null + doc: Imaged location. + - name: coordinates + neurodata_type_inc: VectorData + dtype: float + shape: + - null + - 3 + doc: If a GRIN lens is used, the GRIN lens placement in stereotactic coordinates (AP, ML, DV) mm relative to Bregma. + quantity: "?" + attributes: + - name: unit + dtype: text + value: millimeters + doc: coordinates unit + - name: indicator + neurodata_type_inc: VectorData + dtype: + target_type: Indicator + reftype: object + shape: + - null + doc: Link to the indicator object. + - name: notes + neurodata_type_inc: VectorData dtype: text - doc: Filter used to obtain the excitation wavelength of light, e.g. 'Short pass at 1040 nm'. - required: false - - name: excitation_wavelength_in_nm - dtype: numeric - doc: Excitation wavelength of light, in nanometers. - required: false - - name: peak_power_in_W - dtype: numeric - doc: Incident power of stimulation device (in Watts). - required: false - - name: peak_pulse_energy_in_J - dtype: numeric - doc: If device is pulsed light source, pulse energy (in Joules). - required: false - - name: intensity_in_W_per_m2 - dtype: numeric - doc: Intensity of the excitation in W/m^2, if known. - required: false - - name: exposure_time_in_s - dtype: numeric - doc: Exposure time of the sample (in sec). - required: false - - name: pulse_rate_in_Hz - dtype: numeric - doc: If device is pulsed light source, pulse rate (in Hz) used for stimulation. - required: false - - # Microscopy is added on to this only to differentiate from the OpticalChannel in the core namespace - # It would be removed when this structure is merged to core - - neurodata_type_def: MicroscopyOpticalChannel - neurodata_type_inc: NWBContainer - doc: An optical channel used to filter light emission from an imaging space. - datasets: - - name: description - doc: Description or other notes about the channel. - dtype: text - attributes: - - name: indicator - doc: Identifier for the indicator pertaining to this optical channel. - dtype: text - - name: filter_description - doc: Metadata information about the filter used by this optical channel. - dtype: text - required: false - - name: emission_wavelength_in_nm - doc: Emission wavelength for this optical channel, in nanometers. - dtype: numeric - required: false + shape: + - null + doc: Description of system. + quantity: "?" + - name: microscope + neurodata_type_inc: VectorData + dtype: + target_type: Microscope + reftype: object + shape: + - null + doc: Link to the optical fiber device. + - name: excitation_source + neurodata_type_inc: VectorData + dtype: + target_type: ExcitationSource + reftype: object + shape: + - null + doc: Link to the excitation source device. + - name: commanded_voltage_series + neurodata_type_inc: VectorData + dtype: + target_type: TimeSeries + reftype: object + shape: + - - null + - - null + - null + doc: Link to the commanded voltage series. + quantity: "?" + - name: photodetector + neurodata_type_inc: VectorData + dtype: + target_type: Photodetector + reftype: object + shape: + - null + doc: Link to the photodetector device. + - name: dichroic_mirror + neurodata_type_inc: VectorData + dtype: + target_type: DichroicMirror + reftype: object + shape: + - null + doc: Link to the dichroic mirror device. + - name: emission_filter + neurodata_type_inc: VectorData + dtype: + target_type: Device + reftype: object + shape: + - null + doc: Link to the emission filter device. + quantity: "?" + - name: excitation_filter + neurodata_type_inc: VectorData + dtype: + target_type: Device + reftype: object + shape: + - null + doc: Link to the excitation filter device. + quantity: "?" + - name: objective_lens + neurodata_type_inc: VectorData + dtype: + target_type: ObjectiveLens + reftype: object + shape: + - null + doc: Link to the objective lens device. + quantity: "?" + + - neurodata_type_def: Microscopy + neurodata_type_inc: LabMetaData + doc: Extends LabMetaData to hold all Microscopy metadata. + groups: + - neurodata_type_inc: MicroscopyTable + doc: The table containing the metadata on the Microscopy system. - neurodata_type_def: ImagingSpace neurodata_type_inc: NWBContainer doc: Metadata about the region of physical space that imaging data was recorded from. datasets: - - name: description - dtype: text - doc: Description of the imaging space. - - name: origin_coordinates - dtype: float64 - dims: - - - x, y, z - shape: - - - 3 - doc: Physical location in stereotactic coordinates for the first element of the grid. - See reference_frame to determine what the coordinates are relative to (e.g., bregma). - quantity: '?' - attributes: - - name: unit - dtype: text - default_value: micrometers - doc: Measurement units for origin coordinates. The default value is 'micrometers'. + - name: description + dtype: text + doc: Description of the imaging space. + - name: origin_coordinates + dtype: float64 + dims: + - - x, y, z + shape: + - - 3 + doc: + Physical location in stereotactic coordinates for the first element of the grid. + See reference_frame to determine what the coordinates are relative to (e.g., bregma). + quantity: "?" + attributes: + - name: unit + dtype: text + default_value: micrometers + doc: Measurement units for origin coordinates. The default value is 'micrometers'. attributes: - - name: location - dtype: text - doc: General estimate of location in the brain being subset by this space. - Specify the area, layer, etc. - Use standard atlas names for anatomical regions when possible. - Specify 'whole-brain' if the entire brain is strictly contained within the space. - required: false - links: - - name: microscope - target_type: Microscope - doc: Link to Microscope object which contains metadata about the device which imaged this space. + - name: location + dtype: text + doc: + General estimate of location in the brain being subset by this space. + Specify the area, layer, etc. + Use standard atlas names for anatomical regions when possible. + Specify 'whole-brain' if the entire brain is strictly contained within the space. + required: false - neurodata_type_def: PlanarImagingSpace neurodata_type_inc: ImagingSpace doc: Metadata about the 2-dimensional slice of physical space that imaging data was recorded from. datasets: - - name: grid_spacing - dtype: float64 - dims: - - - x, y - shape: - - - 2 - doc: Amount of space between pixels in the specified unit. - Specify 'z' only when imaging volume is a regular grid; otherwise only specify 'x' and 'y'. - See origin_coordinates to determine where the grid begins. - quantity: '?' - attributes: - - name: unit - dtype: text - default_value: micrometers - doc: Measurement units for grid spacing. The default value is 'micrometers'. + - name: grid_spacing + dtype: float64 + dims: + - - x, y + shape: + - - 2 + doc: Amount of space between pixels in the specified unit. + Specify 'z' only when imaging volume is a regular grid; otherwise only specify 'x' and 'y'. + See origin_coordinates to determine where the grid begins. + quantity: "?" + attributes: + - name: unit + dtype: text + default_value: micrometers + doc: Measurement units for grid spacing. The default value is 'micrometers'. attributes: - - name: reference_frame - dtype: text - doc: Describes the reference frame of origin_coordinates and grid_spacing. - For example, this can be a text description of the anatomical location and orientation of the grid - defined by origin_coords and grid_spacing or the vectors needed to transform or rotate the grid to - a common anatomical axis (e.g., AP/DV/ML). - This field is necessary to interpret origin_coords and grid_spacing. - If origin_coords and grid_spacing are not present, then this field is not required. - For example, if the microscope returns 10 x 10 images, where the first value of the data matrix - (index (0, 0)) corresponds to (-1.2, -0.6, -2) mm relative to bregma, the spacing between pixels is 0.2 mm in - x, 0.2 mm in y and 0.5 mm in z, and larger numbers in x means more anterior, larger numbers in y means more - rightward, and larger numbers in z means more ventral, then enter the following -- - origin_coords = (-1.2, -0.6, -2) - grid_spacing = (0.2, 0.2) - reference_frame = "Origin coordinates are relative to bregma. First dimension corresponds to anterior-posterior - axis (larger index = more anterior). Second dimension corresponds to medial-lateral axis (larger index = more - rightward). Third dimension corresponds to dorsal-ventral axis (larger index = more ventral)." - required: false + - name: reference_frame + dtype: text + doc: + Describes the reference frame of origin_coordinates and grid_spacing. + For example, this can be a text description of the anatomical location and orientation of the grid + defined by origin_coords and grid_spacing or the vectors needed to transform or rotate the grid to + a common anatomical axis (e.g., AP/DV/ML). + This field is necessary to interpret origin_coords and grid_spacing. + If origin_coords and grid_spacing are not present, then this field is not required. + For example, if the microscope returns 10 x 10 images, where the first value of the data matrix + (index (0, 0)) corresponds to (-1.2, -0.6, -2) mm relative to bregma, the spacing between pixels is 0.2 mm in + x, 0.2 mm in y and 0.5 mm in z, and larger numbers in x means more anterior, larger numbers in y means more + rightward, and larger numbers in z means more ventral, then enter the following -- + origin_coords = (-1.2, -0.6, -2) + grid_spacing = (0.2, 0.2) + reference_frame = "Origin coordinates are relative to bregma. First dimension corresponds to anterior-posterior + axis (larger index = more anterior). Second dimension corresponds to medial-lateral axis (larger index = more + rightward). Third dimension corresponds to dorsal-ventral axis (larger index = more ventral)." + required: false - neurodata_type_def: VolumetricImagingSpace neurodata_type_inc: ImagingSpace doc: Metadata about the 3-dimensional region of physical space that imaging data was recorded from. datasets: - - name: grid_spacing - doc: Amount of space between pixels in (x, y) or voxels in (x, y, z), in the specified unit. - Specify 'z' only when imaging volume is a regular grid; otherwise only specify 'x' and 'y'. - See origin_coordinates to determine where the grid begins. - dtype: float64 - dims: - - - x, y, z - shape: - - - 3 - quantity: '?' - attributes: - - name: unit - doc: Measurement units for grid spacing. The default value is 'micrometers'. - dtype: text - default_value: micrometers + - name: grid_spacing + doc: + Amount of space between pixels in (x, y) or voxels in (x, y, z), in the specified unit. + Specify 'z' only when imaging volume is a regular grid; otherwise only specify 'x' and 'y'. + See origin_coordinates to determine where the grid begins. + dtype: float64 + dims: + - - x, y, z + shape: + - - 3 + quantity: "?" + attributes: + - name: unit + doc: Measurement units for grid spacing. The default value is 'micrometers'. + dtype: text + default_value: micrometers attributes: - - name: reference_frame - doc: Describes the reference frame of origin_coordinates and grid_spacing. - For example, this can be a text description of the anatomical location and orientation of the grid - defined by origin_coords and grid_spacing or the vectors needed to transform or rotate the grid to - a common anatomical axis (e.g., AP/DV/ML). - This field is necessary to interpret origin_coords and grid_spacing. - If origin_coords and grid_spacing are not present, then this field is not required. - For example, if the microscope returns 10 x 10 x 2 images, where the first value of the data matrix - (index (0, 0, 0)) corresponds to (-1.2, -0.6, -2) mm relative to bregma, the spacing between pixels is 0.2 mm in - x, 0.2 mm in y and 0.5 mm in z, and larger numbers in x means more anterior, larger numbers in y means more - rightward, and larger numbers in z means more ventral, then enter the following -- - origin_coords = (-1.2, -0.6, -2) - grid_spacing = (0.2, 0.2, 0.5) - reference_frame = "Origin coordinates are relative to bregma. First dimension corresponds to anterior-posterior - axis (larger index = more anterior). Second dimension corresponds to medial-lateral axis (larger index = more - rightward). Third dimension corresponds to dorsal-ventral axis (larger index = more ventral)." - dtype: text - required: false + - name: reference_frame + doc: + Describes the reference frame of origin_coordinates and grid_spacing. + For example, this can be a text description of the anatomical location and orientation of the grid + defined by origin_coords and grid_spacing or the vectors needed to transform or rotate the grid to + a common anatomical axis (e.g., AP/DV/ML). + This field is necessary to interpret origin_coords and grid_spacing. + If origin_coords and grid_spacing are not present, then this field is not required. + For example, if the microscope returns 10 x 10 x 2 images, where the first value of the data matrix + (index (0, 0, 0)) corresponds to (-1.2, -0.6, -2) mm relative to bregma, the spacing between pixels is 0.2 mm in + x, 0.2 mm in y and 0.5 mm in z, and larger numbers in x means more anterior, larger numbers in y means more + rightward, and larger numbers in z means more ventral, then enter the following -- + origin_coords = (-1.2, -0.6, -2) + grid_spacing = (0.2, 0.2, 0.5) + reference_frame = "Origin coordinates are relative to bregma. First dimension corresponds to anterior-posterior + axis (larger index = more anterior). Second dimension corresponds to medial-lateral axis (larger index = more + rightward). Third dimension corresponds to dorsal-ventral axis (larger index = more ventral)." + dtype: text + required: false - neurodata_type_def: MicroscopySeries neurodata_type_inc: TimeSeries - doc: Imaging data acquired over time from an optical channel in a microscope while a light source illuminates the + doc: + Imaging data acquired over time from an optical channel in a microscope while a light source illuminates the imaging space. - links: - - name: microscope - doc: Link to a Microscope object containing metadata about the device used to acquire this imaging data. - target_type: Microscope - - name: light_source - doc: Link to a LightSource object containing metadata about the device used to illuminate the imaging space. - target_type: LightSource - - name: optical_channel - doc: Link to a MicroscopyOpticalChannel object containing metadata about the indicator and filters used to collect - this data. - target_type: MicroscopyOpticalChannel + datasets: + - name: microscopy_table_region + neurodata_type_inc: DynamicTableRegion + doc: References row of MicroscopyTable. + quantity: '?' - neurodata_type_def: PlanarMicroscopySeries neurodata_type_inc: MicroscopySeries - doc: Imaging data acquired over time from an optical channel in a microscope while a light source illuminates a + doc: + Imaging data acquired over time 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 (number of frames, frame height, frame width). - dtype: numeric - dims: - - frames - - height - - width - shape: - - null - - null - - null + - name: data + doc: Recorded imaging data, shaped by (number of frames, frame height, frame width). + dtype: numeric + dims: + - frames + - height + - width + shape: + - null + - null + - null links: - - name: imaging_space - doc: Link to PlanarImagingSpace object containing metadata about the region of physical space this imaging data - was recorded from. - target_type: PlanarImagingSpace + - name: imaging_space + doc: + Link to PlanarImagingSpace object containing metadata about the region of physical space this imaging data + was recorded from. + target_type: PlanarImagingSpace - neurodata_type_def: VariableDepthMicroscopySeries neurodata_type_inc: PlanarMicroscopySeries - doc: Volumetric imaging data acquired over an irregular number and amount of depths; for instance, when using an + doc: + Volumetric imaging data acquired over an irregular number and amount of depths; for instance, when using an electrically tunable lens. datasets: - - name: depth_per_frame_in_mm - doc: Depth of each frame in the data array. - These values offset the 'z' value of the origin_coordinates of the linked imaging_space object. - dtype: numeric - dims: - - frames - shape: - - null + - name: depth_per_frame_in_mm + doc: Depth of each frame in the data array. + These values offset the 'z' value of the origin_coordinates of the linked imaging_space object. + dtype: numeric + dims: + - frames + shape: + - null - neurodata_type_def: VolumetricMicroscopySeries neurodata_type_inc: MicroscopySeries - doc: Volumetric imaging data acquired over time from an optical channel in a microscope while a light source + doc: + Volumetric imaging data acquired over time 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 (number of frames, frame height, frame width, number of depth planes). - dtype: numeric - dims: - - frames - - height - - width - - depth - shape: - - null - - null - - null - - null + - name: data + doc: Recorded imaging data, shaped by (number of frames, frame height, frame width, number of depth planes). + dtype: numeric + dims: + - frames + - height + - width + - depth + shape: + - null + - null + - null + - null links: - - name: imaging_space - doc: Link to VolumetricImagingSpace object containing metadata about the region of physical space this imaging data - was recorded from. - target_type: VolumetricImagingSpace + - name: imaging_space + doc: + Link to VolumetricImagingSpace object containing metadata about the region of physical space this imaging data + was recorded from. + target_type: VolumetricImagingSpace diff --git a/src/pynwb/ndx_microscopy/__init__.py b/src/pynwb/ndx_microscopy/__init__.py index a8cf19a..abe2175 100644 --- a/src/pynwb/ndx_microscopy/__init__.py +++ b/src/pynwb/ndx_microscopy/__init__.py @@ -20,9 +20,18 @@ load_namespaces(str(__spec_path)) -Microscope = get_class("Microscope", extension_name) -LightSource = get_class("LightSource", extension_name) -MicroscopyOpticalChannel = get_class("MicroscopyOpticalChannel", extension_name) +from ndx_ophys_devices import ( + Indicator, + ExcitationSource, + Photodetector, + DichroicMirror, + BandOpticalFilter, + EdgeOpticalFilter, + ObjectiveLens, + Microscope, +) +Microscopy = get_class("Microscopy", extension_name) +MicroscopyTable = get_class("MicroscopyTable", extension_name) ImagingSpace = get_class("ImagingSpace", extension_name) PlanarImagingSpace = get_class("PlanarImagingSpace", extension_name) VolumetricImagingSpace = get_class("VolumetricImagingSpace", extension_name) @@ -32,9 +41,16 @@ VolumetricMicroscopySeries = get_class("VolumetricMicroscopySeries", extension_name) __all__ = [ + "Indicator", + "ExcitationSource", + "Photodetector", + "DichroicMirror", + "BandOpticalFilter", + "EdgeOpticalFilter", + "ObjectiveLens", "Microscope", - "LightSource", - "MicroscopyOpticalChannel", + "MicroscopyTable", + "Microscopy", "ImagingSpace", "PlanarImagingSpace", "VolumetricImagingSpace", diff --git a/src/pynwb/ndx_microscopy/testing/__init__.py b/src/pynwb/ndx_microscopy/testing/__init__.py index adad764..11cedf0 100644 --- a/src/pynwb/ndx_microscopy/testing/__init__.py +++ b/src/pynwb/ndx_microscopy/testing/__init__.py @@ -1,7 +1,6 @@ from ._mock import ( - mock_LightSource, + mock_ExcitationSource, mock_Microscope, - mock_MicroscopyOpticalChannel, mock_PlanarImagingSpace, mock_PlanarMicroscopySeries, mock_VariableDepthMicroscopySeries, @@ -11,8 +10,7 @@ __all__ = [ "mock_Microscope", - "mock_LightSource", - "mock_MicroscopyOpticalChannel", + "mock_ExcitationSource", "mock_PlanarImagingSpace", "mock_VolumetricImagingSpace", "mock_PlanarMicroscopySeries", diff --git a/src/pynwb/ndx_microscopy/testing/_mock.py b/src/pynwb/ndx_microscopy/testing/_mock.py index 7eebeb5..fd24185 100644 --- a/src/pynwb/ndx_microscopy/testing/_mock.py +++ b/src/pynwb/ndx_microscopy/testing/_mock.py @@ -7,73 +7,32 @@ import ndx_microscopy -def mock_Microscope( +def mock_Microscopy( *, name: Optional[str] = None, - description: str = "This is a mock instance of a Microscope type to be used for rapid testing.", - manufacturer: str = "A fake manufacturer of the mock microscope.", - model: str = "A fake model of the mock microscope.", -) -> ndx_microscopy.Microscope: - microscope = ndx_microscopy.Microscope( - name=name or name_generator("Microscope"), + description: str = "This is a mock instance of a Microscopy type to be used for rapid testing.", +) -> ndx_microscopy.Microscopy: + microscopy = ndx_microscopy.Microscopy( + name=name or name_generator("Microscopy"), description=description, - manufacturer=manufacturer, - model=model, ) - return microscope + return microscopy -def mock_LightSource( +def mock_MicroscopyTable( *, name: Optional[str] = None, - description: str = "This is a mock instance of a LightSource type to be used for rapid testing.", - manufacturer: str = "A fake manufacturer of the mock light source.", - model: str = "A fake model of the mock light source.", - filter_description: str = "A description about the fake filter used by the mock light source.", - excitation_wavelength_in_nm: float = 500.0, - peak_power_in_W: float = 0.7, - peak_pulse_energy_in_J: float = 0.7, - intensity_in_W_per_m2: float = 0.005, - exposure_time_in_s: float = 2.51e-13, - pulse_rate_in_Hz: float = 2.0e6, -) -> ndx_microscopy.LightSource: - light_source = ndx_microscopy.LightSource( - name=name or name_generator("LightSource"), + description: str = "This is a mock instance of a Microscopy Table type to be used for rapid testing.", +) -> ndx_microscopy.MicroscopyTable: + microscopy_table = ndx_microscopy.MicroscopyTable( + name=name or name_generator("MicroscopyTable"), description=description, - manufacturer=manufacturer, - model=model, - filter_description=filter_description, - excitation_wavelength_in_nm=excitation_wavelength_in_nm, - peak_power_in_W=peak_power_in_W, - peak_pulse_energy_in_J=peak_pulse_energy_in_J, - intensity_in_W_per_m2=intensity_in_W_per_m2, - exposure_time_in_s=exposure_time_in_s, - pulse_rate_in_Hz=pulse_rate_in_Hz, ) - return light_source - - -def mock_MicroscopyOpticalChannel( - *, - name: Optional[str] = None, - description: str = "This is a mock instance of a MicroscopyOpticalChannel type to be used for rapid testing.", - indicator: str = "The indicator targeted by the mock optical channel.", - filter_description: str = "A description about the fake filter used by the mock optical channel.", - emission_wavelength_in_nm: float = 450.0, -) -> ndx_microscopy.MicroscopyOpticalChannel: - optical_channel = ndx_microscopy.MicroscopyOpticalChannel( - name=name or name_generator("MicroscopyOpticalChannel"), - description=description, - indicator=indicator, - filter_description=filter_description, - emission_wavelength_in_nm=emission_wavelength_in_nm, - ) - return optical_channel + return microscopy_table def mock_PlanarImagingSpace( *, - microscope: ndx_microscopy.Microscope, name: Optional[str] = None, description: str = "This is a mock instance of a PlanarImagingSpace type to be used for rapid testing.", origin_coordinates: Tuple[float, float, float] = (-1.2, -0.6, -2), @@ -84,7 +43,6 @@ def mock_PlanarImagingSpace( planar_imaging_space = ndx_microscopy.PlanarImagingSpace( name=name or name_generator("PlanarImagingSpace"), description=description, - microscope=microscope, origin_coordinates=origin_coordinates, grid_spacing=grid_spacing, location=location, @@ -95,7 +53,6 @@ def mock_PlanarImagingSpace( def mock_VolumetricImagingSpace( *, - microscope: ndx_microscopy.Microscope, name: Optional[str] = None, description: str = "This is a mock instance of a VolumetricImagingSpace type to be used for rapid testing.", origin_coordinates: Tuple[float, float, float] = (-1.2, -0.6, -2), @@ -106,7 +63,6 @@ def mock_VolumetricImagingSpace( volumetric_imaging_space = ndx_microscopy.VolumetricImagingSpace( name=name or name_generator("VolumetricImagingSpace"), description=description, - microscope=microscope, origin_coordinates=origin_coordinates, grid_spacing=grid_spacing, location=location, @@ -117,12 +73,9 @@ def mock_VolumetricImagingSpace( def mock_PlanarMicroscopySeries( *, - microscope: ndx_microscopy.Microscope, - light_source: ndx_microscopy.LightSource, - imaging_space: ndx_microscopy.PlanarImagingSpace, - optical_channel: ndx_microscopy.MicroscopyOpticalChannel, name: Optional[str] = None, description: str = "This is a mock instance of a PlanarMicroscopySeries type to be used for rapid testing.", + microscopy_table_region: list = [0], data: Optional[np.ndarray] = None, unit: str = "a.u.", conversion: float = 1.0, @@ -133,7 +86,6 @@ def mock_PlanarMicroscopySeries( ) -> ndx_microscopy.PlanarMicroscopySeries: series_name = name or name_generator("PlanarMicroscopySeries") series_data = data if data is not None else np.ones(shape=(15, 5, 5)) - if timestamps is None: series_starting_time = starting_time or 0.0 series_rate = rate or 10.0 @@ -155,10 +107,7 @@ def mock_PlanarMicroscopySeries( planar_microscopy_series = ndx_microscopy.PlanarMicroscopySeries( name=series_name, description=description, - microscope=microscope, - light_source=light_source, - imaging_space=imaging_space, - optical_channel=optical_channel, + microscopy_table_region = microscopy_table_region, data=series_data, unit=unit, conversion=conversion, @@ -172,12 +121,9 @@ def mock_PlanarMicroscopySeries( def mock_VariableDepthMicroscopySeries( *, - microscope: ndx_microscopy.Microscope, - light_source: ndx_microscopy.LightSource, - imaging_space: ndx_microscopy.PlanarImagingSpace, - optical_channel: ndx_microscopy.MicroscopyOpticalChannel, name: Optional[str] = None, description: str = "This is a mock instance of a PlanarMicroscopySeries type to be used for rapid testing.", + microscopy_table_region: list = [0], data: Optional[np.ndarray] = None, depth_per_frame_in_mm: Optional[np.ndarray] = None, unit: str = "a.u.", @@ -217,10 +163,7 @@ def mock_VariableDepthMicroscopySeries( variable_depth_microscopy_series = ndx_microscopy.VariableDepthMicroscopySeries( name=series_name, description=description, - microscope=microscope, - light_source=light_source, - imaging_space=imaging_space, - optical_channel=optical_channel, + microscopy_table_region = microscopy_table_region, data=series_data, depth_per_frame_in_mm=series_depth_per_frame_in_mm, unit=unit, @@ -235,12 +178,9 @@ def mock_VariableDepthMicroscopySeries( def mock_VolumetricMicroscopySeries( *, - microscope: ndx_microscopy.Microscope, - light_source: ndx_microscopy.LightSource, - imaging_space: ndx_microscopy.VolumetricImagingSpace, - optical_channel: ndx_microscopy.MicroscopyOpticalChannel, name: Optional[str] = None, description: str = "This is a mock instance of a VolumetricMicroscopySeries type to be used for rapid testing.", + microscopy_table_region: list = [0], data: Optional[np.ndarray] = None, unit: str = "a.u.", conversion: float = 1.0, @@ -273,10 +213,7 @@ def mock_VolumetricMicroscopySeries( volumetric_microscopy_series = ndx_microscopy.VolumetricMicroscopySeries( name=series_name, description=description, - microscope=microscope, - light_source=light_source, - imaging_space=imaging_space, - optical_channel=optical_channel, + microscopy_table_region = microscopy_table_region, data=series_data, unit=unit, conversion=conversion, diff --git a/src/pynwb/tests/test_constructors.py b/src/pynwb/tests/test_constructors.py index bdad7b9..4356417 100644 --- a/src/pynwb/tests/test_constructors.py +++ b/src/pynwb/tests/test_constructors.py @@ -2,73 +2,57 @@ import pytest -from ndx_microscopy.testing import ( - mock_LightSource, +from ndx_ophys_devices.testing import ( + mock_Indicator, + mock_Photodetector, + mock_DichroicMirror, + mock_BandOpticalFilter, + mock_EdgeOpticalFilter, + mock_ObjectiveLens, + mock_ExcitationSource, mock_Microscope, - mock_MicroscopyOpticalChannel, +) + +from ndx_microscopy.testing import ( + mock_Microscopy, + mock_MicroscopyTable, mock_PlanarImagingSpace, mock_PlanarMicroscopySeries, mock_VariableDepthMicroscopySeries, mock_VolumetricImagingSpace, mock_VolumetricMicroscopySeries, ) +def test_constructor_microscopy(): + mock_Microscopy() -def test_constructor_microscope(): - mock_Microscope() - - -def test_constructor_light_source(): - mock_LightSource() - - -def test_constructor_microscopy_optical_channel(): - mock_MicroscopyOpticalChannel() +def test_constructor_microscopy_table(): + mock_MicroscopyTable() def test_constructor_planar_image_space(): - microscope = mock_Microscope() - - mock_PlanarImagingSpace(microscope=microscope) + mock_PlanarImagingSpace() def test_constructor_volumetric_image_space(): - microscope = mock_Microscope() - - mock_VolumetricImagingSpace(microscope=microscope) + mock_VolumetricImagingSpace() def test_constructor_planar_microscopy_series(): - microscope = mock_Microscope() - light_source = mock_LightSource() - imaging_space = mock_PlanarImagingSpace(microscope=microscope) - optical_channel = mock_MicroscopyOpticalChannel() - - mock_PlanarMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space, optical_channel=optical_channel - ) + imaging_space = mock_PlanarImagingSpace() + mock_PlanarMicroscopySeries(imaging_space=imaging_space) def test_constructor_variable_depth_microscopy_series(): - microscope = mock_Microscope() - light_source = mock_LightSource() - imaging_space = mock_PlanarImagingSpace(microscope=microscope) - optical_channel = mock_MicroscopyOpticalChannel() + imaging_space = mock_PlanarImagingSpace() - mock_VariableDepthMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space, optical_channel=optical_channel - ) + mock_VariableDepthMicroscopySeries(imaging_space=imaging_space ) def test_constructor_volumetric_microscopy_series(): - microscope = mock_Microscope() - light_source = mock_LightSource() - imaging_space = mock_VolumetricImagingSpace(microscope=microscope) - optical_channel = mock_MicroscopyOpticalChannel() - - mock_VolumetricMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space, optical_channel=optical_channel - ) + imaging_space = mock_VolumetricImagingSpace() + + mock_VolumetricMicroscopySeries(imaging_space=imaging_space) if __name__ == "__main__": diff --git a/src/pynwb/tests/test_ndx_microscopy.py b/src/pynwb/tests/test_ndx_microscopy.py index a91c45e..a60854e 100644 --- a/src/pynwb/tests/test_ndx_microscopy.py +++ b/src/pynwb/tests/test_ndx_microscopy.py @@ -8,9 +8,8 @@ import pynwb from ndx_microscopy.testing import ( - mock_LightSource, + mock_ExcitationSource, mock_Microscope, - mock_MicroscopyOpticalChannel, mock_PlanarImagingSpace, mock_PlanarMicroscopySeries, mock_VariableDepthMicroscopySeries, @@ -25,11 +24,7 @@ def test_constructor_microscope(): def test_constructor_light_source(): - mock_LightSource() - - -def test_constructor_microscopy_optical_channel(): - mock_MicroscopyOpticalChannel() + mock_ExcitationSource() def test_constructor_planar_image_space(): @@ -46,34 +41,31 @@ def test_constructor_volumetric_image_space(): def test_constructor_planar_microscopy_series(): microscope = mock_Microscope() - light_source = mock_LightSource() + light_source = mock_ExcitationSource() imaging_space = mock_PlanarImagingSpace(microscope=microscope) - optical_channel = mock_MicroscopyOpticalChannel() mock_PlanarMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space, optical_channel=optical_channel + microscope=microscope, light_source=light_source, imaging_space=imaging_space ) def test_constructor_variable_depth_microscopy_series(): microscope = mock_Microscope() - light_source = mock_LightSource() + light_source = mock_ExcitationSource() imaging_space = mock_PlanarImagingSpace(microscope=microscope) - optical_channel = mock_MicroscopyOpticalChannel() mock_VariableDepthMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space, optical_channel=optical_channel + microscope=microscope, light_source=light_source, imaging_space=imaging_space ) def test_constructor_volumetric_microscopy_series(): microscope = mock_Microscope() - light_source = mock_LightSource() + light_source = mock_ExcitationSource() imaging_space = mock_PlanarImagingSpace(microscope=microscope) - optical_channel = mock_MicroscopyOpticalChannel() mock_VolumetricMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space, optical_channel=optical_channel + microscope=microscope, light_source=light_source, imaging_space=imaging_space ) @@ -82,12 +74,11 @@ def nwbfile_with_microscopy(): nwbfile = pynwb.testing.mock.mock_NWBFile() microscope = mock_Microscope() - light_source = mock_LightSource() + light_source = mock_ExcitationSource() imaging_space = mock_PlanarImagingSpace(microscope=microscope) - optical_channel = mock_MicroscopyOpticalChannel() mock_PlanarMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space, optical_channel=optical_channel + microscope=microscope, light_source=light_source, imaging_space=imaging_space ) return nwbfile From 3eb60466aa0e96fd565bbe6cbe368d3caebca966 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 25 May 2024 15:42:46 +0000 Subject: [PATCH 2/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- spec/ndx-microscopy.extensions.yaml | 2 +- src/pynwb/ndx_microscopy/__init__.py | 11 ++++++----- src/pynwb/ndx_microscopy/testing/_mock.py | 6 +++--- src/pynwb/tests/test_constructors.py | 13 +++++++------ src/pynwb/tests/test_ndx_microscopy.py | 16 ++++------------ 5 files changed, 21 insertions(+), 27 deletions(-) diff --git a/spec/ndx-microscopy.extensions.yaml b/spec/ndx-microscopy.extensions.yaml index 5f87b77..b0fcf96 100644 --- a/spec/ndx-microscopy.extensions.yaml +++ b/spec/ndx-microscopy.extensions.yaml @@ -107,7 +107,7 @@ groups: - null doc: Link to the objective lens device. quantity: "?" - + - neurodata_type_def: Microscopy neurodata_type_inc: LabMetaData doc: Extends LabMetaData to hold all Microscopy metadata. diff --git a/src/pynwb/ndx_microscopy/__init__.py b/src/pynwb/ndx_microscopy/__init__.py index abe2175..522a268 100644 --- a/src/pynwb/ndx_microscopy/__init__.py +++ b/src/pynwb/ndx_microscopy/__init__.py @@ -21,15 +21,16 @@ load_namespaces(str(__spec_path)) from ndx_ophys_devices import ( - Indicator, - ExcitationSource, - Photodetector, - DichroicMirror, BandOpticalFilter, + DichroicMirror, EdgeOpticalFilter, - ObjectiveLens, + ExcitationSource, + Indicator, Microscope, + ObjectiveLens, + Photodetector, ) + Microscopy = get_class("Microscopy", extension_name) MicroscopyTable = get_class("MicroscopyTable", extension_name) ImagingSpace = get_class("ImagingSpace", extension_name) diff --git a/src/pynwb/ndx_microscopy/testing/_mock.py b/src/pynwb/ndx_microscopy/testing/_mock.py index fd24185..84848cd 100644 --- a/src/pynwb/ndx_microscopy/testing/_mock.py +++ b/src/pynwb/ndx_microscopy/testing/_mock.py @@ -107,7 +107,7 @@ def mock_PlanarMicroscopySeries( planar_microscopy_series = ndx_microscopy.PlanarMicroscopySeries( name=series_name, description=description, - microscopy_table_region = microscopy_table_region, + microscopy_table_region=microscopy_table_region, data=series_data, unit=unit, conversion=conversion, @@ -163,7 +163,7 @@ def mock_VariableDepthMicroscopySeries( variable_depth_microscopy_series = ndx_microscopy.VariableDepthMicroscopySeries( name=series_name, description=description, - microscopy_table_region = microscopy_table_region, + microscopy_table_region=microscopy_table_region, data=series_data, depth_per_frame_in_mm=series_depth_per_frame_in_mm, unit=unit, @@ -213,7 +213,7 @@ def mock_VolumetricMicroscopySeries( volumetric_microscopy_series = ndx_microscopy.VolumetricMicroscopySeries( name=series_name, description=description, - microscopy_table_region = microscopy_table_region, + microscopy_table_region=microscopy_table_region, data=series_data, unit=unit, conversion=conversion, diff --git a/src/pynwb/tests/test_constructors.py b/src/pynwb/tests/test_constructors.py index 4356417..9d78539 100644 --- a/src/pynwb/tests/test_constructors.py +++ b/src/pynwb/tests/test_constructors.py @@ -1,16 +1,15 @@ """Test in-memory Python API constructors for ndx-microscopy extension.""" import pytest - from ndx_ophys_devices.testing import ( - mock_Indicator, - mock_Photodetector, - mock_DichroicMirror, mock_BandOpticalFilter, + mock_DichroicMirror, mock_EdgeOpticalFilter, - mock_ObjectiveLens, mock_ExcitationSource, + mock_Indicator, mock_Microscope, + mock_ObjectiveLens, + mock_Photodetector, ) from ndx_microscopy.testing import ( @@ -22,6 +21,8 @@ mock_VolumetricImagingSpace, mock_VolumetricMicroscopySeries, ) + + def test_constructor_microscopy(): mock_Microscopy() @@ -46,7 +47,7 @@ def test_constructor_planar_microscopy_series(): def test_constructor_variable_depth_microscopy_series(): imaging_space = mock_PlanarImagingSpace() - mock_VariableDepthMicroscopySeries(imaging_space=imaging_space ) + mock_VariableDepthMicroscopySeries(imaging_space=imaging_space) def test_constructor_volumetric_microscopy_series(): diff --git a/src/pynwb/tests/test_ndx_microscopy.py b/src/pynwb/tests/test_ndx_microscopy.py index a60854e..c056f09 100644 --- a/src/pynwb/tests/test_ndx_microscopy.py +++ b/src/pynwb/tests/test_ndx_microscopy.py @@ -44,9 +44,7 @@ def test_constructor_planar_microscopy_series(): light_source = mock_ExcitationSource() imaging_space = mock_PlanarImagingSpace(microscope=microscope) - mock_PlanarMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space - ) + mock_PlanarMicroscopySeries(microscope=microscope, light_source=light_source, imaging_space=imaging_space) def test_constructor_variable_depth_microscopy_series(): @@ -54,9 +52,7 @@ def test_constructor_variable_depth_microscopy_series(): light_source = mock_ExcitationSource() imaging_space = mock_PlanarImagingSpace(microscope=microscope) - mock_VariableDepthMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space - ) + mock_VariableDepthMicroscopySeries(microscope=microscope, light_source=light_source, imaging_space=imaging_space) def test_constructor_volumetric_microscopy_series(): @@ -64,9 +60,7 @@ def test_constructor_volumetric_microscopy_series(): light_source = mock_ExcitationSource() imaging_space = mock_PlanarImagingSpace(microscope=microscope) - mock_VolumetricMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space - ) + mock_VolumetricMicroscopySeries(microscope=microscope, light_source=light_source, imaging_space=imaging_space) @pytest.fixture(scope="module") @@ -77,9 +71,7 @@ def nwbfile_with_microscopy(): light_source = mock_ExcitationSource() imaging_space = mock_PlanarImagingSpace(microscope=microscope) - mock_PlanarMicroscopySeries( - microscope=microscope, light_source=light_source, imaging_space=imaging_space - ) + mock_PlanarMicroscopySeries(microscope=microscope, light_source=light_source, imaging_space=imaging_space) return nwbfile From 0729028cc511d42854892c6ba4568bb56dc087ad Mon Sep 17 00:00:00 2001 From: Cody Baker <51133164+CodyCBakerPhD@users.noreply.github.com> Date: Sat, 25 May 2024 12:39:14 -0400 Subject: [PATCH 3/9] add other extension to namespace --- spec/ndx-microscopy.namespace.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/ndx-microscopy.namespace.yaml b/spec/ndx-microscopy.namespace.yaml index 8399608..c4f3d98 100644 --- a/spec/ndx-microscopy.namespace.yaml +++ b/spec/ndx-microscopy.namespace.yaml @@ -8,6 +8,8 @@ namespaces: - cody.baker@catalystneuro.com - alessandra.trapani@catalystneuro.com schema: - - namespace: core + - namespace: + - core + - ndx-ophys-devices - source: ndx-microscopy.extensions.yaml version: 0.1.0 From 8d945f78552f8fb8b7331e57fb25403d56b1f74d Mon Sep 17 00:00:00 2001 From: Alessandra Trapani Date: Mon, 27 May 2024 14:41:12 +0200 Subject: [PATCH 4/9] add create_microscopy_table_region --- spec/ndx-microscopy.extensions.yaml | 5 +++-- src/pynwb/ndx_microscopy/__init__.py | 2 +- src/pynwb/ndx_microscopy/microscopy.py | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 src/pynwb/ndx_microscopy/microscopy.py diff --git a/spec/ndx-microscopy.extensions.yaml b/spec/ndx-microscopy.extensions.yaml index b0fcf96..c328769 100644 --- a/spec/ndx-microscopy.extensions.yaml +++ b/spec/ndx-microscopy.extensions.yaml @@ -80,10 +80,11 @@ groups: shape: - null doc: Link to the dichroic mirror device. + quantity: "?" - name: emission_filter neurodata_type_inc: VectorData dtype: - target_type: Device + target_type: OpticalFilter reftype: object shape: - null @@ -92,7 +93,7 @@ groups: - name: excitation_filter neurodata_type_inc: VectorData dtype: - target_type: Device + target_type: OpticalFilter reftype: object shape: - null diff --git a/src/pynwb/ndx_microscopy/__init__.py b/src/pynwb/ndx_microscopy/__init__.py index 522a268..1df6043 100644 --- a/src/pynwb/ndx_microscopy/__init__.py +++ b/src/pynwb/ndx_microscopy/__init__.py @@ -32,7 +32,7 @@ ) Microscopy = get_class("Microscopy", extension_name) -MicroscopyTable = get_class("MicroscopyTable", extension_name) +from .microscopy import MicroscopyTable ImagingSpace = get_class("ImagingSpace", extension_name) PlanarImagingSpace = get_class("PlanarImagingSpace", extension_name) VolumetricImagingSpace = get_class("VolumetricImagingSpace", extension_name) diff --git a/src/pynwb/ndx_microscopy/microscopy.py b/src/pynwb/ndx_microscopy/microscopy.py new file mode 100644 index 0000000..da249bd --- /dev/null +++ b/src/pynwb/ndx_microscopy/microscopy.py @@ -0,0 +1,15 @@ +from hdmf.utils import docval, popargs +from pynwb import get_class + +MicroscopyTable = get_class("MicroscopyTable", "ndx-microscopy") + +@docval( + {'name': 'region', 'type': list, 'doc': 'the indices of the MicroscopyTable'}, + {'name': 'description', 'type': str, 'doc': 'a brief description of what these table entries represent'}, +) +def create_microscopy_table_region(self, **kwargs): + region, description = popargs('region', 'description', kwargs) + name = 'microscopy_table_region' + return super(MicroscopyTable, self).create_region(name=name, region=region, description=description) + +MicroscopyTable.create_microscopy_table_region = create_microscopy_table_region \ No newline at end of file From 92f10d52dcdc9899391e4adce010a77c564cac06 Mon Sep 17 00:00:00 2001 From: Alessandra Trapani Date: Mon, 27 May 2024 15:19:46 +0200 Subject: [PATCH 5/9] write mock fun for Microscopy and MicroscopyTable --- src/pynwb/ndx_microscopy/testing/__init__.py | 8 ++-- src/pynwb/ndx_microscopy/testing/_mock.py | 35 +++++++++++++++ src/pynwb/tests/test_constructors.py | 10 ----- src/pynwb/tests/test_ndx_microscopy.py | 46 +++++++------------- 4 files changed, 55 insertions(+), 44 deletions(-) diff --git a/src/pynwb/ndx_microscopy/testing/__init__.py b/src/pynwb/ndx_microscopy/testing/__init__.py index 11cedf0..48c2353 100644 --- a/src/pynwb/ndx_microscopy/testing/__init__.py +++ b/src/pynwb/ndx_microscopy/testing/__init__.py @@ -1,6 +1,6 @@ from ._mock import ( - mock_ExcitationSource, - mock_Microscope, + mock_MicroscopyTable, + mock_Microscopy, mock_PlanarImagingSpace, mock_PlanarMicroscopySeries, mock_VariableDepthMicroscopySeries, @@ -9,8 +9,8 @@ ) __all__ = [ - "mock_Microscope", - "mock_ExcitationSource", + "mock_MicroscopyTable", + "mock_Microscopy", "mock_PlanarImagingSpace", "mock_VolumetricImagingSpace", "mock_PlanarMicroscopySeries", diff --git a/src/pynwb/ndx_microscopy/testing/_mock.py b/src/pynwb/ndx_microscopy/testing/_mock.py index 84848cd..0270f4d 100644 --- a/src/pynwb/ndx_microscopy/testing/_mock.py +++ b/src/pynwb/ndx_microscopy/testing/_mock.py @@ -5,16 +5,28 @@ from pynwb.testing.mock.utils import name_generator import ndx_microscopy +from ndx_ophys_devices.testing import ( + mock_Indicator, + mock_ExcitationSource, + mock_Photodetector, + mock_DichroicMirror, + mock_BandOpticalFilter, + mock_EdgeOpticalFilter, + mock_Microscope, + mock_ObjectiveLens, +) def mock_Microscopy( *, + microscopy_table: ndx_microscopy.MicroscopyTable, name: Optional[str] = None, description: str = "This is a mock instance of a Microscopy type to be used for rapid testing.", ) -> ndx_microscopy.Microscopy: microscopy = ndx_microscopy.Microscopy( name=name or name_generator("Microscopy"), description=description, + microscopy_table=microscopy_table, ) return microscopy @@ -23,11 +35,25 @@ def mock_MicroscopyTable( *, name: Optional[str] = None, description: str = "This is a mock instance of a Microscopy Table type to be used for rapid testing.", + number_of_rows: int = 2, ) -> ndx_microscopy.MicroscopyTable: microscopy_table = ndx_microscopy.MicroscopyTable( name=name or name_generator("MicroscopyTable"), description=description, ) + for row in range(number_of_rows): + microscopy_table.add_row( + location=f"The location targeted of row number {row}", + notes=f"The notes for row number {row}", + indicator=mock_Indicator(name=f"indicator_{row}"), + excitation_source=mock_ExcitationSource(name=f"excitation_source_{row}"), + photodetector=mock_Photodetector(name=f"photodetector_{row}"), + dichroic_mirror=mock_DichroicMirror(name=f"dichroic_mirror_{row}"), + emission_filter=mock_BandOpticalFilter(name=f"emission_filter_{row}"), + excitation_filter=mock_EdgeOpticalFilter(name=f"excitation_filter_{row}"), + objective_lens=mock_ObjectiveLens(name=f"objective_lens_{row}"), + microscope=mock_Microscope(name=f"microscope_{row}"), + ) return microscopy_table @@ -104,6 +130,9 @@ def mock_PlanarMicroscopySeries( series_rate = None series_timestamps = timestamps + microscopy_table = mock_MicroscopyTable() + microscopy_table_region = microscopy_table.create_microscopy_table_region(region=microscopy_table_region) + planar_microscopy_series = ndx_microscopy.PlanarMicroscopySeries( name=series_name, description=description, @@ -160,6 +189,9 @@ def mock_VariableDepthMicroscopySeries( series_rate = None series_timestamps = timestamps + microscopy_table = mock_MicroscopyTable() + microscopy_table_region = microscopy_table.create_microscopy_table_region(region=microscopy_table_region) + variable_depth_microscopy_series = ndx_microscopy.VariableDepthMicroscopySeries( name=series_name, description=description, @@ -210,6 +242,9 @@ def mock_VolumetricMicroscopySeries( series_rate = None series_timestamps = timestamps + microscopy_table = mock_MicroscopyTable() + microscopy_table_region = microscopy_table.create_microscopy_table_region(region=microscopy_table_region) + volumetric_microscopy_series = ndx_microscopy.VolumetricMicroscopySeries( name=series_name, description=description, diff --git a/src/pynwb/tests/test_constructors.py b/src/pynwb/tests/test_constructors.py index 9d78539..2e97866 100644 --- a/src/pynwb/tests/test_constructors.py +++ b/src/pynwb/tests/test_constructors.py @@ -1,16 +1,6 @@ """Test in-memory Python API constructors for ndx-microscopy extension.""" import pytest -from ndx_ophys_devices.testing import ( - mock_BandOpticalFilter, - mock_DichroicMirror, - mock_EdgeOpticalFilter, - mock_ExcitationSource, - mock_Indicator, - mock_Microscope, - mock_ObjectiveLens, - mock_Photodetector, -) from ndx_microscopy.testing import ( mock_Microscopy, diff --git a/src/pynwb/tests/test_ndx_microscopy.py b/src/pynwb/tests/test_ndx_microscopy.py index c056f09..d2c89b4 100644 --- a/src/pynwb/tests/test_ndx_microscopy.py +++ b/src/pynwb/tests/test_ndx_microscopy.py @@ -8,8 +8,8 @@ import pynwb from ndx_microscopy.testing import ( - mock_ExcitationSource, - mock_Microscope, + mock_Microscopy, + mock_MicroscopyTable, mock_PlanarImagingSpace, mock_PlanarMicroscopySeries, mock_VariableDepthMicroscopySeries, @@ -19,59 +19,45 @@ from pynwb import NWBHDF5IO, NWBFile -def test_constructor_microscope(): - mock_Microscope() +def test_constructor_microscopy(): + mock_Microscopy() -def test_constructor_light_source(): - mock_ExcitationSource() +def test_constructor_microscopy_table(): + mock_MicroscopyTable() def test_constructor_planar_image_space(): - microscope = mock_Microscope() - - mock_PlanarImagingSpace(microscope=microscope) + mock_PlanarImagingSpace() def test_constructor_volumetric_image_space(): - microscope = mock_Microscope() - - mock_VolumetricImagingSpace(microscope=microscope) + mock_VolumetricImagingSpace() def test_constructor_planar_microscopy_series(): - microscope = mock_Microscope() - light_source = mock_ExcitationSource() - imaging_space = mock_PlanarImagingSpace(microscope=microscope) - - mock_PlanarMicroscopySeries(microscope=microscope, light_source=light_source, imaging_space=imaging_space) + imaging_space = mock_PlanarImagingSpace() + mock_PlanarMicroscopySeries(imaging_space=imaging_space) def test_constructor_variable_depth_microscopy_series(): - microscope = mock_Microscope() - light_source = mock_ExcitationSource() - imaging_space = mock_PlanarImagingSpace(microscope=microscope) + imaging_space = mock_PlanarImagingSpace() - mock_VariableDepthMicroscopySeries(microscope=microscope, light_source=light_source, imaging_space=imaging_space) + mock_VariableDepthMicroscopySeries(imaging_space=imaging_space) def test_constructor_volumetric_microscopy_series(): - microscope = mock_Microscope() - light_source = mock_ExcitationSource() - imaging_space = mock_PlanarImagingSpace(microscope=microscope) + imaging_space = mock_VolumetricImagingSpace() - mock_VolumetricMicroscopySeries(microscope=microscope, light_source=light_source, imaging_space=imaging_space) + mock_VolumetricMicroscopySeries(imaging_space=imaging_space) @pytest.fixture(scope="module") def nwbfile_with_microscopy(): nwbfile = pynwb.testing.mock.mock_NWBFile() - microscope = mock_Microscope() - light_source = mock_ExcitationSource() - imaging_space = mock_PlanarImagingSpace(microscope=microscope) - - mock_PlanarMicroscopySeries(microscope=microscope, light_source=light_source, imaging_space=imaging_space) + imaging_space = mock_PlanarImagingSpace() + mock_PlanarMicroscopySeries(imaging_space=imaging_space) return nwbfile From 152656acce74e63403cc8c1f14cbca8184c3a03e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 13:21:46 +0000 Subject: [PATCH 6/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/pynwb/ndx_microscopy/__init__.py | 1 + src/pynwb/ndx_microscopy/microscopy.py | 13 ++++++++----- src/pynwb/ndx_microscopy/testing/__init__.py | 2 +- src/pynwb/ndx_microscopy/testing/_mock.py | 14 +++++++------- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/pynwb/ndx_microscopy/__init__.py b/src/pynwb/ndx_microscopy/__init__.py index 1df6043..e0332bd 100644 --- a/src/pynwb/ndx_microscopy/__init__.py +++ b/src/pynwb/ndx_microscopy/__init__.py @@ -33,6 +33,7 @@ Microscopy = get_class("Microscopy", extension_name) from .microscopy import MicroscopyTable + ImagingSpace = get_class("ImagingSpace", extension_name) PlanarImagingSpace = get_class("PlanarImagingSpace", extension_name) VolumetricImagingSpace = get_class("VolumetricImagingSpace", extension_name) diff --git a/src/pynwb/ndx_microscopy/microscopy.py b/src/pynwb/ndx_microscopy/microscopy.py index da249bd..caee133 100644 --- a/src/pynwb/ndx_microscopy/microscopy.py +++ b/src/pynwb/ndx_microscopy/microscopy.py @@ -1,15 +1,18 @@ from hdmf.utils import docval, popargs + from pynwb import get_class MicroscopyTable = get_class("MicroscopyTable", "ndx-microscopy") + @docval( - {'name': 'region', 'type': list, 'doc': 'the indices of the MicroscopyTable'}, - {'name': 'description', 'type': str, 'doc': 'a brief description of what these table entries represent'}, + {"name": "region", "type": list, "doc": "the indices of the MicroscopyTable"}, + {"name": "description", "type": str, "doc": "a brief description of what these table entries represent"}, ) def create_microscopy_table_region(self, **kwargs): - region, description = popargs('region', 'description', kwargs) - name = 'microscopy_table_region' + region, description = popargs("region", "description", kwargs) + name = "microscopy_table_region" return super(MicroscopyTable, self).create_region(name=name, region=region, description=description) -MicroscopyTable.create_microscopy_table_region = create_microscopy_table_region \ No newline at end of file + +MicroscopyTable.create_microscopy_table_region = create_microscopy_table_region diff --git a/src/pynwb/ndx_microscopy/testing/__init__.py b/src/pynwb/ndx_microscopy/testing/__init__.py index 48c2353..e2141d5 100644 --- a/src/pynwb/ndx_microscopy/testing/__init__.py +++ b/src/pynwb/ndx_microscopy/testing/__init__.py @@ -1,6 +1,6 @@ from ._mock import ( - mock_MicroscopyTable, mock_Microscopy, + mock_MicroscopyTable, mock_PlanarImagingSpace, mock_PlanarMicroscopySeries, mock_VariableDepthMicroscopySeries, diff --git a/src/pynwb/ndx_microscopy/testing/_mock.py b/src/pynwb/ndx_microscopy/testing/_mock.py index 0270f4d..15cb948 100644 --- a/src/pynwb/ndx_microscopy/testing/_mock.py +++ b/src/pynwb/ndx_microscopy/testing/_mock.py @@ -2,19 +2,19 @@ from typing import Optional, Tuple import numpy as np -from pynwb.testing.mock.utils import name_generator - -import ndx_microscopy from ndx_ophys_devices.testing import ( - mock_Indicator, - mock_ExcitationSource, - mock_Photodetector, - mock_DichroicMirror, mock_BandOpticalFilter, + mock_DichroicMirror, mock_EdgeOpticalFilter, + mock_ExcitationSource, + mock_Indicator, mock_Microscope, mock_ObjectiveLens, + mock_Photodetector, ) +from pynwb.testing.mock.utils import name_generator + +import ndx_microscopy def mock_Microscopy( From 413654d5e6c2ec3461c040b4eabe10586dc3a436 Mon Sep 17 00:00:00 2001 From: Alessandra Trapani Date: Mon, 27 May 2024 15:46:09 +0200 Subject: [PATCH 7/9] fix schema namespace --- spec/ndx-microscopy.namespace.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spec/ndx-microscopy.namespace.yaml b/spec/ndx-microscopy.namespace.yaml index c4f3d98..75bf1c6 100644 --- a/spec/ndx-microscopy.namespace.yaml +++ b/spec/ndx-microscopy.namespace.yaml @@ -8,8 +8,7 @@ namespaces: - cody.baker@catalystneuro.com - alessandra.trapani@catalystneuro.com schema: - - namespace: - - core - - ndx-ophys-devices + - namespace: core + - namespace: ndx-ophys-devices - source: ndx-microscopy.extensions.yaml version: 0.1.0 From 7fbf74ef0fcb3607628affd526ee5c0dd081bc3f Mon Sep 17 00:00:00 2001 From: Alessandra Trapani Date: Mon, 27 May 2024 15:46:30 +0200 Subject: [PATCH 8/9] remove commanded_voltages_series for now --- spec/ndx-microscopy.extensions.yaml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/spec/ndx-microscopy.extensions.yaml b/spec/ndx-microscopy.extensions.yaml index c328769..efe2dab 100644 --- a/spec/ndx-microscopy.extensions.yaml +++ b/spec/ndx-microscopy.extensions.yaml @@ -9,6 +9,7 @@ groups: shape: - null doc: Imaged location. + quantity: "?" - name: coordinates neurodata_type_inc: VectorData dtype: float @@ -44,7 +45,7 @@ groups: reftype: object shape: - null - doc: Link to the optical fiber device. + doc: Link to the microscope device. - name: excitation_source neurodata_type_inc: VectorData dtype: @@ -53,17 +54,6 @@ groups: shape: - null doc: Link to the excitation source device. - - name: commanded_voltage_series - neurodata_type_inc: VectorData - dtype: - target_type: TimeSeries - reftype: object - shape: - - - null - - - null - - null - doc: Link to the commanded voltage series. - quantity: "?" - name: photodetector neurodata_type_inc: VectorData dtype: From 7d06dc4776161681319c17b068d581fc25dbab2f Mon Sep 17 00:00:00 2001 From: Alessandra Trapani Date: Mon, 27 May 2024 15:46:49 +0200 Subject: [PATCH 9/9] update diagram --- README.md | 60 +++++++++++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 6116b3e..fbc81bf 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,9 @@ classDiagram <> -------------------------------------- - links + datasets -------------------------------------- - microscope : Microscope - light_source : LightSource - optical_channel : MicroscopyOpticalChannel + microscopy_table_region : DynamicTableRegion } class PlanarMicroscopySeries { @@ -133,45 +131,34 @@ classDiagram reference_frame : text, optional } - class MicroscopyOpticalChannel{ - <> + class MicroscopyTable{ + <> -------------------------------------- datasets -------------------------------------- - description : text - - -------------------------------------- - attributes - -------------------------------------- - indicator : text - filter_description : text, optional - emission_wavelength_in_nm : numeric, optional - } - - class LightSource{ - <> - - -------------------------------------- - attributes - -------------------------------------- - model : text, optional - filter_description : text, optional - excitation_wavelength_in_nm : numeric, optional - peak_power_in_W : numeric, optional - peak_pulse_energy_in_J : numeric, optional - intensity_in_W_per_m2 : numeric, optional - exposure_time_in_s : numeric, optional - pulse_rate_in_Hz : numeric, optional + VectorData : + - location : text, optional + - coordinates : numeric, length 2, optional + --> unit : text, default="micrometers" + - indicator : Indicator + - notes : text, optional + - microscope : Microscope + - excitation_source : ExcitationSource + - photodetector : Photodetector + - dichroic_mirror : DichroicMirror + - emission_filter : OpticalFilter + - excitation_filter : OpticalFilter + - objective_lens : ObjectiveLens } - class Microscope{ - <> + class Microscopy{ + <> -------------------------------------- - attributes + groups -------------------------------------- - model : text, optional + microscopy_table : MicroscopyTable } PlanarMicroscopySeries *-- MicroscopySeries : extends @@ -182,9 +169,8 @@ classDiagram VolumetricMicroscopySeries -- VolumetricImagingSpace : links PlanarImagingSpace *-- ImagingSpace : extends VolumetricImagingSpace *-- ImagingSpace : extends - MicroscopySeries ..> Microscope : links - MicroscopySeries ..> LightSource : links - MicroscopySeries ..> MicroscopyOpticalChannel : links + MicroscopySeries ..> MicroscopyTable : reference rows + Microscopy ..> MicroscopyTable : links ``` ---