Examples¶
This section provides detailed examples of using the ndx-microscopy extension for various microscopy techniques and workflows.
Two-Photon Calcium Imaging¶
Complete example of two-photon calcium imaging with full optical path configuration:
from datetime import datetime
from uuid import uuid4
import matplotlib.pyplot as plt
import numpy as np
from pynwb import NWBFile, NWBHDF5IO
from ndx_microscopy import (
MicroscopeModel,
Microscope,
MicroscopyRig,
MicroscopyChannel,
PlanarImagingSpace,
PlanarMicroscopySeries,
PlanarSegmentation,
SummaryImage,
MicroscopyResponseSeries,
MicroscopyResponseSeriesContainer,
LineScan,
PlaneAcquisition,
RandomAccessScan,
)
from ndx_ophys_devices import (
ExcitationSourceModel,
PulsedExcitationSource,
BandOpticalFilterModel,
BandOpticalFilter,
DichroicMirrorModel,
DichroicMirror,
PhotodetectorModel,
Photodetector,
Indicator
)
# Create NWB file
nwbfile = NWBFile(
session_description='Two-photon calcium imaging session',
identifier=str(uuid4()),
session_start_time=datetime.now(),
lab='Neural Imaging Lab',
institution='University of Neuroscience',
experiment_description='GCaMP6f imaging in visual cortex'
)
# Set up microscope model
microscope_model = MicroscopeModel(
name='2p-model',
description='Two-photon microscope model for calcium imaging',
model_number='2p-001', # Example model number
manufacturer='ImagingTech'
)
nwbfile.add_device(microscope_model)
# Set up microscope with technique
microscope = Microscope(
name='2p-scope',
serial_number='2p-serial-001', # Example serial number
model=microscope_model,
technique='mirror scanning' # Specify the technique used
)
nwbfile.add_device(microscope)
# Set up optical components
excitation_source_model = ExcitationSourceModel(
name="excitation_source_model",
manufacturer="Laser Manufacturer",
model_number="ES-123",
description="Excitation source model for green indicator",
source_type="laser",
excitation_mode="two-photon",
wavelength_range_in_nm=[800.0, 1000.0]
)
nwbfile.add_device(excitation_source_model)
pulsed_excitation_source = PulsedExcitationSource(
name="pulsed_excitation_source",
description="Pulsed excitation source for red indicator",
serial_number="PES-SN-123456",
model=excitation_source_model,
peak_power_in_W=0.7,
peak_pulse_energy_in_J=0.7,
intensity_in_W_per_m2=0.005,
exposure_time_in_s=2.51e-13,
pulse_rate_in_Hz=2.0e6
)
nwbfile.add_device(pulsed_excitation_source)
excitation_filter_model = BandOpticalFilterModel(
name="excitation_filter_model",
filter_type="Bandpass",
manufacturer="Semrock",
model_number="FF01-920/80",
center_wavelength_in_nm=920.0,
bandwidth_in_nm=80.0
)
nwbfile.add_device(excitation_filter_model)
excitation_filter = BandOpticalFilter(
name="excitation_filter",
model=excitation_filter_model,
serial_number="EF-SN-123456"
)
nwbfile.add_device(excitation_filter)
dichroic_mirror_model = DichroicMirrorModel(
name="primary_dichroic_model",
manufacturer="Semrock",
model_number="FF757-Di01", # Common dichroic for GCaMP imaging
cut_on_wavelength_in_nm=757.0, # Transmits >757nm
cut_off_wavelength_in_nm=750.0, # Reflects <750nm
transmission_band_in_nm=[757.0, 1100.0], # Transmits NIR excitation light
reflection_band_in_nm=(400.0, 750.0), # Reflects emission light (including 510nm GCaMP6f emission)
angle_of_incidence_in_degrees=45.0 # Standard angle for dichroic mirrors in microscopes
)
nwbfile.add_device(dichroic_mirror_model)
dichroic_mirror = DichroicMirror(
name="dichroic_mirror",
description="Dichroic mirror for green indicator",
serial_number="DM-SN-123456",
model=dichroic_mirror_model
)
nwbfile.add_device(dichroic_mirror)
emission_filter_model = BandOpticalFilterModel(
name="emission_filter_model",
filter_type="Bandpass",
manufacturer="Semrock",
model_number="FF01-510/84",
center_wavelength_in_nm=510.0,
bandwidth_in_nm=84.0
)
nwbfile.add_device(emission_filter_model)
emission_filter = BandOpticalFilter(
name="emission_filter",
description="Band optical filter for green indicator",
serial_number="BOF-SN-123456",
model=emission_filter_model
)
nwbfile.add_device(emission_filter)
photodetector_model = PhotodetectorModel(
name="photodetector_model",
detector_type="PMT",
manufacturer="Hamamatsu",
model_number="R6357",
gain=1000000.0, # 10^6 typical PMT gain
gain_unit="V/A" # Voltage/Current
)
nwbfile.add_device(photodetector_model)
photodetector = Photodetector(
name="photodetector",
description="Photodetector for green emission",
serial_number="PD-SN-123456",
model=photodetector_model
)
nwbfile.add_device(photodetector)
# Create indicator
indicator = Indicator(
name="gcamp6f",
label="GCaMP6f",
description="Calcium indicator for two-photon imaging",
manufacturer="Addgene",
injection_brain_region="Visual cortex",
injection_coordinates_in_mm=[-2.5, 3.2, 0.5]
)
# Create microscopy rig
microscopy_rig = MicroscopyRig(
name='2p_rig',
description='Two-photon microscopy rig',
microscope=microscope,
excitation_source=pulsed_excitation_source,
excitation_filter=excitation_filter,
dichroic_mirror=dichroic_mirror,
photodetector=photodetector,
emission_filter=emission_filter
)
# Define illumination pattern
line_scan = LineScan(
name='line_scanning',
description='Line scanning two-photon microscopy',
scan_direction='horizontal',
line_rate_in_Hz=1000.0,
dwell_time_in_s=1.0e-6
)
# Create example imaging data
frames = 1000
height = 512
width = 512
data = np.random.rand(frames, height, width)
# Define imaging space with illumination pattern
imaging_space = PlanarImagingSpace(
name='cortex_plane1',
description='Layer 2/3 of visual cortex',
pixel_size_in_um=[1.0, 1.0],
dimensions_in_pixels=[height, width],
origin_coordinates=[-1.2, -0.6, -2.0],
location='Visual cortex, layer 2/3',
reference_frame='bregma',
orientation='RAS', # Right-Anterior-Superior
illumination_pattern=line_scan # Include the illumination pattern
)
# Create microscopy channel
microscopy_channel = MicroscopyChannel(
name='gcamp_channel',
description='GCaMP6f channel',
excitation_wavelength_in_nm=920.0,
emission_wavelength_in_nm=510.0,
indicator=indicator
)
# Create imaging series
imaging_series = PlanarMicroscopySeries(
name='imaging_data',
description='Two-photon calcium imaging',
microscopy_channel=microscopy_channel,
microscopy_rig=microscopy_rig,
planar_imaging_space=imaging_space,
data=data,
unit='a.u.',
rate=30.0,
starting_time=0.0
)
nwbfile.add_acquisition(imaging_series)
# Create ophys processing module
ophys_module = nwbfile.create_processing_module(
name='ophys',
description='Optical physiology processing module'
)
# Create summary images
mean_image = SummaryImage(
name='mean',
description='Mean intensity projection',
data=np.mean(data, axis=0)
)
max_image = SummaryImage(
name='max',
description='Maximum intensity projection',
data=np.max(data, axis=0)
)
# Create segmentation
segmentation = PlanarSegmentation(
name='rois',
description='Manual ROI segmentation',
planar_imaging_space=imaging_space,
summary_images=[mean_image, max_image]
)
# Add ROIs using image masks
roi_mask = np.zeros((height, width), dtype=bool)
roi_mask[256:266, 256:266] = True # 10x10 ROI
segmentation.add_roi(image_mask=roi_mask)
# OR Add ROIs using pixel masks
# pixel_mask = [
# [100, 100, 1.0], # x, y, weight
# [101, 100, 1.0],
# [102, 100, 1.0]
# ]
# segmentation.add_roi(pixel_mask=pixel_mask)
# Create ROI responses
roi_region = segmentation.create_roi_table_region(
description='All ROIs',
region=list(range(len(segmentation.id)))
)
# Extract responses (example calculation)
num_rois = len(segmentation.id)
responses = np.zeros((frames, num_rois))
for i, roi_mask in enumerate(segmentation.image_mask[:]):
roi_data = data[:, roi_mask]
responses[:, i] = np.mean(roi_data, axis=1)
# Create response series
response_series = MicroscopyResponseSeries(
name='roi_responses',
description='Fluorescence responses from ROIs',
data=responses,
rois=roi_region,
unit='n.a.',
rate=30.0,
starting_time=0.0
microscopy_series=imaging_series
)
# Create container for response series
response_container = MicroscopyResponseSeriesContainer(
name='responses',
microscopy_response_series=[response_series]
)
# Add segmentation and responses to ophys module
ophys_module.add(segmentation)
ophys_module.add(response_container)
# Save file
with NWBHDF5IO('calcium_imaging.nwb', 'w') as io:
io.write(nwbfile)
# Read file and access data
with NWBHDF5IO('calcium_imaging.nwb', 'r') as io:
nwbfile = io.read()
# Access imaging data
imaging = nwbfile.acquisition['imaging_data']
raw_data = imaging.data[:]
# Access ROI data
ophys = nwbfile.processing['ophys']
rois = ophys['rois']
roi_masks = rois.image_mask[:]
# Access responses
responses = ophys['responses']
roi_data = responses['roi_responses'].data[:]
Volumetric Imaging¶
Example of volumetric imaging with 3D ROI segmentation:
from datetime import datetime
from uuid import uuid4
import numpy as np
from pynwb import NWBFile, NWBHDF5IO
from ndx_microscopy import (
MicroscopeModel,
Microscope,
MicroscopyRig,
VolumetricImagingSpace,
VolumetricMicroscopySeries,
VolumetricSegmentation,
SummaryImage,
MicroscopyResponseSeries,
MicroscopyResponseSeriesContainer,
RandomAccessScan
)
from ndx_ophys_devices import (
ExcitationSourceModel,
ExcitationSource,
BandOpticalFilterModel,
BandOpticalFilter,
DichroicMirrorModel,
DichroicMirror,
PhotodetectorModel,
Photodetector,
Indicator
)
# Create NWB file
nwbfile = NWBFile(
session_description='Volumetric imaging session',
identifier=str(uuid4()),
session_start_time=datetime.now(),
lab='Neural Dynamics Lab',
institution='University of Neuroscience',
experiment_description='Volumetric imaging in cortex'
)
# Set up microscope model
microscope_model = MicroscopeModel(
name='volume-model',
description='Volumetric imaging microscope model',
model_number='volume-001',
manufacturer='ImagingTech'
)
nwbfile.add_device(microscope_model)
# Set up microscope with technique
microscope = Microscope(
name='volume-scope',
description='Custom volumetric imaging microscope',
serial_number='volume-serial-001',
model=microscope_model,
technique='acousto-optical deflectors' # Specify the technique used
)
nwbfile.add_device(microscope)
# Set up optical components
excitation_source_model = ExcitationSourceModel(
name="excitation_source_model",
manufacturer="Coherent",
model_number="Chameleon",
description="Excitation source model for volumetric imaging",
source_type="laser",
excitation_mode="two-photon",
wavelength_range_in_nm=[800.0, 1000.0]
)
nwbfile.add_device(excitation_source_model)
laser = ExcitationSource(
name='laser',
description="Excitation source for volumetric imaging",
serial_number="ES-SN-123456",
model=excitation_source_model,
intensity_in_W_per_m2=1000.0,
exposure_time_in_s=0.001
)
nwbfile.add_device(laser)
excitation_filter_model = BandOpticalFilterModel(
name="excitation_filter_model",
filter_type="Bandpass",
manufacturer="Semrock",
model_number="FF01-920/80",
center_wavelength_in_nm=920.0,
bandwidth_in_nm=80.0
)
nwbfile.add_device(excitation_filter_model)
excitation_filter = BandOpticalFilter(
name='excitation_filter',
description="Excitation filter for volumetric imaging",
serial_number="EF-SN-123456",
model=excitation_filter_model
)
nwbfile.add_device(excitation_filter)
dichroic_mirror_model = DichroicMirrorModel(
name="dichroic_mirror_model",
manufacturer="Semrock",
model_number="FF695-Di02",
cut_on_wavelength_in_nm=695.0
)
nwbfile.add_device(dichroic_mirror_model)
dichroic = DichroicMirror(
name='primary_dichroic',
description="Dichroic mirror for volumetric imaging",
serial_number="DM-SN-123456",
model=dichroic_mirror_model
)
nwbfile.add_device(dichroic)
emission_filter_model = BandOpticalFilterModel(
name="emission_filter_model",
filter_type="Bandpass",
manufacturer="Semrock",
model_number="FF01-510/84",
center_wavelength_in_nm=510.0,
bandwidth_in_nm=84.0
)
nwbfile.add_device(emission_filter_model)
emission_filter = BandOpticalFilter(
name='emission_filter',
description="Emission filter for volumetric imaging",
serial_number="EF-SN-123456",
model=emission_filter_model
)
nwbfile.add_device(emission_filter)
photodetector_model = PhotodetectorModel(
name="photodetector_model",
detector_type="PMT",
manufacturer="Hamamatsu",
model_number="R6357",
gain=70.0,
gain_unit="dB"
)
nwbfile.add_device(photodetector_model)
detector = Photodetector(
name='pmt',
description="Photodetector for volumetric imaging",
serial_number="PD-SN-123456",
model=photodetector_model
)
nwbfile.add_device(detector)
# Create indicator
indicator = Indicator(
name='gcamp6f',
label='GCaMP6f',
description='Calcium indicator for volumetric imaging',
manufacturer='Addgene',
injection_brain_region='Visual cortex',
injection_coordinates_in_mm=[-2.5, 3.2, 0.5]
)
# Create microscopy rig
microscopy_rig = MicroscopyRig(
name='volume_rig',
description='Volumetric microscopy rig',
microscope=microscope,
excitation_source=laser,
excitation_filter=excitation_filter,
dichroic_mirror=dichroic,
photodetector=detector,
emission_filter=emission_filter
)
# Define illumination pattern for volumetric imaging
random_access_scan = RandomAccessScan(
name='random_access',
description='Targeted imaging of specific neurons',
max_scan_points=1000,
dwell_time_in_s=1.0e-6,
scanning_pattern='spiral'
)
# Create example volumetric data
frames = 100
height = 512
width = 512
depths = 10
data = np.random.rand(frames, height, width, depths)
# Define volumetric imaging space with illumination pattern
volume_space = VolumetricImagingSpace(
name='cortex_volume',
description='Visual cortex volume',
voxel_size_in_um=[1.0, 1.0, 2.0], # Higher spacing in z
dimensions_in_voxels=[height, width, depths],
origin_coordinates=[-1.2, -0.6, -2.0],
location='Visual cortex',
reference_frame='bregma',
orientation='RAS', # Right-Anterior-Superior
illumination_pattern=random_access_scan # Include the illumination pattern
)
# Create microscopy channel
microscopy_channel = MicroscopyChannel(
name='gcamp_channel',
description='GCaMP6f channel',
excitation_wavelength_in_nm=920.0,
emission_wavelength_in_nm=510.0,
indicator=indicator
)
# Create volumetric series
volume_series = VolumetricMicroscopySeries(
name='volume_data',
description='Volumetric imaging series',
microscopy_channel=microscopy_channel,
microscopy_rig=microscopy_rig,
volumetric_imaging_space=volume_space,
data=data,
unit='a.u.',
rate=5.0, # Lower rate for volumetric imaging
starting_time=0.0
)
nwbfile.add_acquisition(volume_series)
# Create ophys processing module
ophys_module = nwbfile.create_processing_module(
name='ophys',
description='Optical physiology processing module'
)
# Create 3D summary images
mean_image = SummaryImage(
name='mean',
description='Mean intensity projection',
data=np.mean(data, axis=0)
)
max_image = SummaryImage(
name='max',
description='Maximum intensity projection',
data=np.max(data, axis=0)
)
# Create 3D segmentation
segmentation = VolumetricSegmentation(
name='volume_rois',
description='3D ROI segmentation',
volumetric_imaging_space=volume_space,
summary_images=[mean_image, max_image]
)
# Add 3D ROIs using image masks
roi_mask = np.zeros((height, width, depths), dtype=bool)
roi_mask[256:266, 256:266, 4:6] = True # 10x10x2 ROI
segmentation.add_roi(volume_mask=roi_mask)
# Add ROIs using voxel masks
voxel_mask = [
[100, 100, 5, 1.0], # x, y, z, weight
[101, 100, 5, 1.0],
[102, 100, 5, 1.0]
]
segmentation.add_roi(voxel_mask=voxel_mask)
# Create ROI responses
roi_region = segmentation.create_roi_table_region(
description='All 3D ROIs',
region=list(range(len(segmentation.id)))
)
# Extract responses (example calculation)
num_rois = len(segmentation.id)
responses = np.zeros((frames, num_rois))
for i, roi_mask in enumerate(segmentation.volume_mask[:]):
roi_data = data[:, roi_mask]
responses[:, i] = np.mean(roi_data, axis=1)
# Create response series
response_series = MicroscopyResponseSeries(
name='volume_responses',
description='Fluorescence responses from 3D ROIs',
data=responses,
rois=roi_region,
unit='n.a.',
rate=5.0,
starting_time=0.0
microscopy_series=volume_series
)
# Create container for response series
response_container = MicroscopyResponseSeriesContainer(
name='volume_responses',
microscopy_response_series=[response_series]
)
# Add segmentation and responses to ophys module
ophys_module.add(segmentation)
ophys_module.add(response_container)
# Save file
with NWBHDF5IO('volumetric_imaging.nwb', 'w') as io:
io.write(nwbfile)
# Read file and access data
with NWBHDF5IO('volumetric_imaging.nwb', 'r') as io:
nwbfile = io.read()
# Access volumetric data
imaging = nwbfile.acquisition['volume_data']
volume_data = imaging.data[:]
# Access ROI data
ophys = nwbfile.processing['ophys']
rois = ophys['volume_rois']
roi_masks = rois.volume_mask[:]
# Access responses
responses = ophys['volume_responses']
roi_data = responses['volume_responses'].data[:]
Multi-Plane Imaging¶
Example of multi-plane imaging with an electrically tunable lens:
from datetime import datetime
from uuid import uuid4
import numpy as np
from pynwb import NWBFile, NWBHDF5IO
from ndx_microscopy import (
MicroscopeModel,
Microscope,
MicroscopyRig,
MicroscopyChannel,
PlanarImagingSpace,
PlanarMicroscopySeries,
MultiPlaneMicroscopyContainer,
PlanarSegmentation,
SummaryImage,
MicroscopyResponseSeries,
MicroscopyResponseSeriesContainer,
SegmentationContainer,
PlaneAcquisition
)
from ndx_ophys_devices import (
ExcitationSourceModel,
ExcitationSource,
BandOpticalFilterModel,
BandOpticalFilter,
DichroicMirrorModel,
DichroicMirror,
PhotodetectorModel,
Photodetector,
Indicator
)
# Create NWB file
nwbfile = NWBFile(
session_description='Multi-plane imaging session',
identifier=str(uuid4()),
session_start_time=datetime.now(),
lab='Neural Circuits Lab',
institution='University of Neuroscience',
experiment_description='Multi-plane imaging with ETL'
)
# Set up microscope model
microscope_model = MicroscopeModel(
name='etl-model',
description='Two-photon microscope model with electrically tunable lens',
model_number='etl-001', # Example model number
manufacturer='ImagingTech'
)
nwbfile.add_device(microscope_model)
# Set up microscope with ETL and technique
microscope = Microscope(
name='etl-scope',
description='Two-photon microscope with electrically tunable lens',
serial_number='etl-serial-001', # Example serial number
model=microscope_model,
technique='electrically tunable lens' # Specify the technique used
)
nwbfile.add_device(microscope)
# Set up optical components
excitation_source_model = ExcitationSourceModel(
name="excitation_source_model",
manufacturer="Coherent",
model_number="Chameleon",
description="Excitation source model for multi-plane imaging",
source_type="laser",
excitation_mode="two-photon",
wavelength_range_in_nm=[800.0, 1000.0]
)
nwbfile.add_device(excitation_source_model)
laser = ExcitationSource(
name='laser',
description="Excitation source for multi-plane imaging",
serial_number="ES-SN-123456",
model=excitation_source_model,
intensity_in_W_per_m2=1000.0,
exposure_time_in_s=0.001
)
nwbfile.add_device(laser)
excitation_filter_model = BandOpticalFilterModel(
name="excitation_filter_model",
filter_type="Bandpass",
manufacturer="Semrock",
model_number="FF01-920/80",
center_wavelength_in_nm=920.0,
bandwidth_in_nm=80.0
)
nwbfile.add_device(excitation_filter_model)
excitation_filter = BandOpticalFilter(
name='excitation_filter',
description="Excitation filter for multi-plane imaging",
serial_number="EF-SN-123456",
model=excitation_filter_model
)
nwbfile.add_device(excitation_filter)
dichroic_mirror_model = DichroicMirrorModel(
name="dichroic_mirror_model",
manufacturer="Semrock",
model_number="FF695-Di02",
cut_on_wavelength_in_nm=695.0
)
nwbfile.add_device(dichroic_mirror_model)
dichroic = DichroicMirror(
name='primary_dichroic',
description="Dichroic mirror for multi-plane imaging",
serial_number="DM-SN-123456",
model=dichroic_mirror_model
)
nwbfile.add_device(dichroic)
emission_filter_model = BandOpticalFilterModel(
name="emission_filter_model",
filter_type="Bandpass",
manufacturer="Semrock",
model_number="FF01-510/84",
center_wavelength_in_nm=510.0,
bandwidth_in_nm=84.0
)
nwbfile.add_device(emission_filter_model)
emission_filter = BandOpticalFilter(
name='emission_filter',
description="Emission filter for multi-plane imaging",
serial_number="EF-SN-123456",
model=emission_filter_model
)
nwbfile.add_device(emission_filter)
photodetector_model = PhotodetectorModel(
name="photodetector_model",
detector_type="PMT",
manufacturer="Hamamatsu",
model_number="R6357",
gain=70.0,
gain_unit="dB"
)
nwbfile.add_device(photodetector_model)
detector = Photodetector(
name='pmt',
description="Photodetector for multi-plane imaging",
serial_number="PD-SN-123456",
model=photodetector_model
)
nwbfile.add_device(detector)
# Create indicator
indicator = Indicator(
name='gcamp6f',
label='GCaMP6f',
description='Calcium indicator for multi-plane imaging',
manufacturer='Addgene',
injection_brain_region='Visual cortex',
injection_coordinates_in_mm=[-2.5, 3.2, 0.5]
)
# Create microscopy rig
microscopy_rig = MicroscopyRig(
name='etl_rig',
description='Multi-plane microscopy rig with ETL',
microscope=microscope,
excitation_source=laser,
excitation_filter=excitation_filter,
dichroic_mirror=dichroic,
photodetector=detector,
emission_filter=emission_filter
)
# Create ophys processing module
ophys_module = nwbfile.create_processing_module(
name='ophys',
description='Optical physiology processing module'
)
# Create multiple imaging planes
planar_series_list = []
segmentation_list = []
response_series_list = []
depths = [-100, -50, 0, 50, 100] # Depths in µm
# Create illumination pattern
plane_acquisition = PlaneAcquisition(
name=f'plane_acquisition',
description=f'Plane acquisition',
point_spread_function_in_um="32 um ± 1.6 um"
)
for depth in depths:
# Create example data for this plane
frames = 1000
height = 512
width = 512
data = np.random.rand(frames, height, width)
# Create imaging space for this depth with illumination pattern
plane_space = PlanarImagingSpace(
name=f'plane_depth_{depth}',
description=f'Imaging plane at {depth} µm depth',
pixel_size_in_um=[1.0, 1.0],
dimensions_in_pixels=[height, width],
origin_coordinates=[-1.2, -0.6, depth/1000], # Convert to mm
location='Visual cortex',
reference_frame='bregma',
orientation='RAS',
illumination_pattern=plane_acquisition # Include the illumination pattern
)
# Create microscopy channel for this plane
microscopy_channel = MicroscopyChannel(
name=f'gcamp_channel_{depth}',
description=f'GCaMP6f channel at {depth} µm depth',
excitation_wavelength_in_nm=920.0,
emission_wavelength_in_nm=510.0,
indicator=indicator
)
# Create imaging series for this plane
plane_series = PlanarMicroscopySeries(
name=f'imaging_depth_{depth}',
description=f'Imaging data at {depth} µm depth',
microscopy_channel=microscopy_channel,
microscopy_rig=microscopy_rig,
planar_imaging_space=plane_space,
data=data,
unit='a.u.',
conversion=1.0,
offset=0.0,
rate=30.0,
starting_time=0.0
)
planar_series_list.append(plane_series)
# Create summary images for this plane
mean_image = SummaryImage(
name=f'mean_{depth}',
description=f'Mean intensity projection at {depth} µm',
data=np.mean(data, axis=0)
)
max_image = SummaryImage(
name=f'max_{depth}',
description=f'Maximum intensity projection at {depth} µm',
data=np.max(data, axis=0)
)
# Create segmentation for this plane
segmentation = PlanarSegmentation(
name=f'rois_{depth}',
description=f'ROI segmentation at {depth} µm',
planar_imaging_space=plane_space,
summary_images=[mean_image, max_image]
)
# Add ROIs
roi_mask = np.zeros((height, width), dtype=bool)
roi_mask[256:266, 256:266] = True
segmentation.add_roi(image_mask=roi_mask)
segmentation_list.append(segmentation)
# Create ROI responses
roi_region = segmentation.create_roi_table_region(
description=f'ROIs at {depth} µm',
region=list(range(len(segmentation.id)))
)
# Extract responses
num_rois = len(segmentation.id)
responses = np.zeros((frames, num_rois))
for i, roi_mask in enumerate(segmentation.image_mask[:]):
roi_data = data[:, roi_mask]
responses[:, i] = np.mean(roi_data, axis=1)
# Create response series
response_series = MicroscopyResponseSeries(
name=f'responses_{depth}',
description=f'Fluorescence responses at {depth} µm',
data=responses,
rois=roi_region,
unit='n.a.',
rate=30.0,
starting_time=0.0
microscopy_series=plane_series
)
response_series_list.append(response_series)
# Create containers
multi_plane_container = MultiPlaneMicroscopyContainer(
name='multi_plane_data',
planar_microscopy_series=planar_series_list
)
nwbfile.add_acquisition(multi_plane_container)
segmentation_container = SegmentationContainer(
name='plane_segmentations',
segmentations=segmentation_list
)
ophys_module.add(segmentation_container)
response_container = MicroscopyResponseSeriesContainer(
name='plane_responses',
microscopy_response_series=response_series_list
)
ophys_module.add(response_container)
# Save file
with NWBHDF5IO('multi_plane_imaging.nwb', 'w') as io:
io.write(nwbfile)
# Read file and access data
with NWBHDF5IO('multi_plane_imaging.nwb', 'r') as io:
nwbfile = io.read()
# Access multi-plane data
multi_plane = nwbfile.acquisition['multi_plane_data']
# Access specific plane data
plane_0 = multi_plane.planar_microscopy_series['imaging_depth_0']
plane_data = plane_0.data[:]
# Access ROI data
ophys = nwbfile.processing['ophys']
segmentations = ophys['plane_segmentations']
rois_0 = segmentations['rois_0']
roi_masks = rois_0.image_mask[:]
# Access responses
responses = ophys['plane_responses']
responses_0 = responses['responses_0']
roi_data = responses_0.data[:]