def add_corrected_fluorescence_traces(nwbfile, corrected_fluorescence_traces): corrected_fluorescence_traces = corrected_fluorescence_traces.reset_index( ).set_index('cell_roi_id')[['corrected_fluorescence']] # Create/Add corrected_fluorescence_traces modules and interfaces: assert corrected_fluorescence_traces.index.name == 'cell_roi_id' twop_module = nwbfile.modules['two_photon_imaging'] roi_table_region = nwbfile.modules['two_photon_imaging'].data_interfaces[ 'dff'].roi_response_series['traces'].rois ophys_timestamps = twop_module.get_data_interface( 'dff').roi_response_series['traces'].timestamps f_interface = Fluorescence(name='corrected_fluorescence') twop_module.add_data_interface(f_interface) f_interface.create_roi_response_series( name='traces', data=np.array([ corrected_fluorescence_traces.loc[cell_roi_id]. corrected_fluorescence for cell_roi_id in corrected_fluorescence_traces.index.values ]), unit='NA', rois=roi_table_region, timestamps=ophys_timestamps) return nwbfile
def to_nwb(self, nwbfile: NWBFile) -> NWBFile: corrected_fluorescence_traces = self.value['corrected_fluorescence'] # Convert from Series of lists to numpy array # of shape ROIs x timepoints traces = np.stack([x for x in corrected_fluorescence_traces]) # Create/Add corrected_fluorescence_traces modules and interfaces: ophys_module = nwbfile.processing['ophys'] roi_table_region = \ nwbfile.processing['ophys'].data_interfaces[ 'dff'].roi_response_series[ 'traces'].rois # noqa: E501 ophys_timestamps = ophys_module.get_data_interface( 'dff').roi_response_series['traces'].timestamps f_interface = Fluorescence(name='corrected_fluorescence') ophys_module.add_data_interface(f_interface) f_interface.create_roi_response_series( name='traces', data=traces.T, # Should be stored as timepoints x rois unit='NA', rois=roi_table_region, timestamps=ophys_timestamps) return nwbfile
def add_corrected_fluorescence_traces(nwbfile, corrected_fluorescence_traces): corrected_fluorescence_traces = \ corrected_fluorescence_traces.reset_index().set_index( 'cell_roi_id')[['corrected_fluorescence']] # Create/Add corrected_fluorescence_traces modules and interfaces: assert corrected_fluorescence_traces.index.name == 'cell_roi_id' ophys_module = nwbfile.processing['ophys'] # trace data in the form of rois x timepoints f_trace_data = np.array([ corrected_fluorescence_traces.loc[cell_roi_id].corrected_fluorescence for cell_roi_id in corrected_fluorescence_traces.index.values ]) roi_table_region = nwbfile.processing['ophys'].data_interfaces[ 'dff'].roi_response_series['traces'].rois # noqa: E501 ophys_timestamps = ophys_module.get_data_interface( 'dff').roi_response_series['traces'].timestamps f_interface = Fluorescence(name='corrected_fluorescence') ophys_module.add_data_interface(f_interface) f_interface.create_roi_response_series( name='traces', data=f_trace_data.T, # Should be stored as timepoints x rois unit='NA', rois=roi_table_region, timestamps=ophys_timestamps) return nwbfile
def add_ophys_processed(self): """Add Fluorescence data""" imaging_plane = self._get_imaging_plane() with h5py.File(self.source_paths['path_processed'], 'r') as f: # Stores segmented data ophys_module = self.nwbfile.create_processing_module( name='ophys', description='contains optical physiology processed data') meta_imgseg = self.metadata['Ophys']['ImageSegmentation'] img_seg = ImageSegmentation(name=meta_imgseg['name']) ophys_module.add(img_seg) meta_planeseg = meta_imgseg['plane_segmentations'][0] if meta_planeseg['reference_images'] in self.nwbfile.acquisition: reference_images = self.nwbfile.acquisition[ meta_planeseg['reference_images']] else: reference_images = None plane_segmentation = img_seg.create_plane_segmentation( name=meta_planeseg['name'], description=meta_planeseg['description'], imaging_plane=imaging_plane, reference_images=reference_images, ) # ROIs n_rows = int(f['linesPerFrame'][0]) n_cols = int(f['pixelsPerLine'][0][0]) pixel_mask = [] for pi in np.squeeze(f['pixel_list'][:]): row = int(pi // n_rows) col = int(pi % n_rows) pixel_mask.append([col, row, 1]) plane_segmentation.add_roi(pixel_mask=pixel_mask) # Fluorescene data meta_fluorescence = self.metadata['Ophys']['Fluorescence'] fl = Fluorescence(name=meta_fluorescence['name']) ophys_module.add(fl) with h5py.File(self.source_paths['path_calibration'], 'r') as fc: fluorescence_mean_trace = np.squeeze(fc['dff']) rt_region = plane_segmentation.create_roi_table_region( description='unique cell ROI', region=[0]) imaging_rate = 1 / np.array(fc['dto']) fl.create_roi_response_series( name=meta_fluorescence['roi_response_series'][0]['name'], data=fluorescence_mean_trace, rois=rt_region, rate=imaging_rate, starting_time=0., unit='no unit')
def add_signals(module, expt, rt_region): fs = 1 / expt.frame_period() fluor = Fluorescence() sigs = expt.imagingData(dFOverF=None) fluor.create_roi_response_series(name='Fluorescence', data=sigs.squeeze(), rate=fs, unit='NA', rois=rt_region) module.add_data_interface(fluor)
def add_fluorescence_traces(self, roi_ids=None, region_label=None): if roi_ids is None: roi_ids = list(range(len(self.ps))) region_label = 'all ROIs' rt_region = self.ps.create_roi_table_region(region_label, region=roi_ids) frame_rate = self.get_frame_rate() with File(self.from_path, 'r') as f: data = f['emAnalysisOutput/cellTraces'][:] fl = Fluorescence() self.ophys_mod.add_data_interface(fl) fl.create_roi_response_series('RoiResponseSeries', data, 'lumens', rt_region, rate=frame_rate)
#################### # Because this data stores information about specific ROIs, you will need to provide a reference to the ROIs # that you will be storing data for. This is done using a :py:class:`~pynwb.ophys.ROITableRegion`, which can be # created with :py:func:`~pynwb.ophys.PlaneSegmentation.create_roi_table_region`. rt_region = ps.create_roi_table_region('the first of two ROIs', region=[0]) #################### # Now that you have an :py:class:`~pynwb.ophys.ROITableRegion`, you can create your an # :py:class:`~pynwb.ophys.RoiResponseSeries`. data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] timestamps = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] rrs = fl.create_roi_response_series('my_rrs', data, 'lumens', rt_region, timestamps=timestamps) #################### # .. note:: You can also store more than one :py:class:`~pynwb.ophys.RoiResponseSeries` by calling # :py:func:`~pynwb.ophys.Fluorescence.create_roi_response_series` again. #################### # Once we have finished adding all of our data to our :py:class:`~pynwb.NWBFile`, make sure to write the file. # Writing (and reading) is carried out using :py:class:`~pynwb.NWBHDF5IO`. from pynwb import NWBHDF5IO with NWBHDF5IO('ophys_example.nwb', 'w') as io: io.write(nwbfile)
#################### # Alternatively, you can get create a region using the names of the ROIs you added by passing in # the ROI names with the *names* argument. We will create the same region we did above, but # by using the name of the ROI. rt_region = ps.create_roi_table_region('the first of two ROIs', names=['1234']) #################### # Now that you have an :py:class:`~pynwb.ophys.ROITableRegion`, you can create your an # :py:class:`~pynwb.ophys.RoiResponseSeries`. data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] timestamps = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] rrs = fl.create_roi_response_series('my_rrs', 'Ca2+ imaging example', data, 'lumens', rt_region, timestamps=timestamps) #################### # .. note:: You can also store more than one :py:class:`~pynwb.ophys.RoiResponseSeries` by calling # :py:func:`~pynwb.ophys.Fluorescence.create_roi_response_series` again. #################### # Once we have finished adding all of our data to our :py:class:`~pynwb.NWBFile`, make sure to write the file. # Writing (and reading) is carried out using :py:class:`~pynwb.NWBHDF5IO`. from pynwb import NWBHDF5IO with NWBHDF5IO('ophys_example.nwb', 'w') as io: io.write(nwbfile)
def write_segmentation( segext_obj: SegmentationExtractor, save_path: PathType = None, plane_num=0, metadata: dict = None, overwrite: bool = True, buffer_size: int = 10, nwbfile=None, ): assert ( save_path is None or nwbfile is None ), "Either pass a save_path location, or nwbfile object, but not both!" # parse metadata correctly: if isinstance(segext_obj, MultiSegmentationExtractor): segext_objs = segext_obj.segmentations if metadata is not None: assert isinstance(metadata, list), ( "For MultiSegmentationExtractor enter 'metadata' as a list of " "SegmentationExtractor metadata") assert len(metadata) == len(segext_objs), ( "The 'metadata' argument should be a list with the same " "number of elements as the segmentations in the " "MultiSegmentationExtractor") else: segext_objs = [segext_obj] if metadata is not None and not isinstance(metadata, list): metadata = [metadata] metadata_base_list = [ NwbSegmentationExtractor.get_nwb_metadata(sgobj) for sgobj in segext_objs ] print(f"writing nwb for {segext_obj.extractor_name}\n") # updating base metadata with new: for num, data in enumerate(metadata_base_list): metadata_input = metadata[num] if metadata else {} metadata_base_list[num] = dict_recursive_update( metadata_base_list[num], metadata_input) metadata_base_common = metadata_base_list[0] # build/retrieve nwbfile: if nwbfile is not None: assert isinstance( nwbfile, NWBFile), "'nwbfile' should be of type pynwb.NWBFile" write = False else: write = True save_path = Path(save_path) assert save_path.suffix == ".nwb" if save_path.is_file() and not overwrite: nwbfile_exist = True file_mode = "r+" else: if save_path.is_file(): os.remove(save_path) if not save_path.parent.is_dir(): save_path.parent.mkdir(parents=True) nwbfile_exist = False file_mode = "w" io = NWBHDF5IO(str(save_path), file_mode) if nwbfile_exist: nwbfile = io.read() else: nwbfile = NWBFile(**metadata_base_common["NWBFile"]) # Subject: if metadata_base_common.get("Subject") and nwbfile.subject is None: nwbfile.subject = Subject(**metadata_base_common["Subject"]) # Processing Module: if "ophys" not in nwbfile.processing: ophys = nwbfile.create_processing_module( "ophys", "contains optical physiology processed data") else: ophys = nwbfile.get_processing_module("ophys") for plane_no_loop, (segext_obj, metadata) in enumerate( zip(segext_objs, metadata_base_list)): # Device: if metadata["Ophys"]["Device"][0]["name"] not in nwbfile.devices: nwbfile.create_device(**metadata["Ophys"]["Device"][0]) # ImageSegmentation: image_segmentation_name = ( "ImageSegmentation" if plane_no_loop == 0 else f"ImageSegmentation_Plane{plane_no_loop}") if image_segmentation_name not in ophys.data_interfaces: image_segmentation = ImageSegmentation( name=image_segmentation_name) ophys.add(image_segmentation) else: image_segmentation = ophys.data_interfaces.get( image_segmentation_name) # OpticalChannel: optical_channels = [ OpticalChannel(**i) for i in metadata["Ophys"]["ImagingPlane"] [0]["optical_channel"] ] # ImagingPlane: image_plane_name = ("ImagingPlane" if plane_no_loop == 0 else f"ImagePlane_{plane_no_loop}") if image_plane_name not in nwbfile.imaging_planes.keys(): input_kwargs = dict( name=image_plane_name, device=nwbfile.get_device( metadata_base_common["Ophys"]["Device"][0]["name"]), ) metadata["Ophys"]["ImagingPlane"][0][ "optical_channel"] = optical_channels input_kwargs.update(**metadata["Ophys"]["ImagingPlane"][0]) if "imaging_rate" in input_kwargs: input_kwargs["imaging_rate"] = float( input_kwargs["imaging_rate"]) imaging_plane = nwbfile.create_imaging_plane(**input_kwargs) else: imaging_plane = nwbfile.imaging_planes[image_plane_name] # PlaneSegmentation: input_kwargs = dict( description="output from segmenting imaging plane", imaging_plane=imaging_plane, ) ps_metadata = metadata["Ophys"]["ImageSegmentation"][ "plane_segmentations"][0] if ps_metadata[ "name"] not in image_segmentation.plane_segmentations: ps_exist = False else: ps = image_segmentation.get_plane_segmentation( ps_metadata["name"]) ps_exist = True roi_ids = segext_obj.get_roi_ids() accepted_list = segext_obj.get_accepted_list() accepted_list = [] if accepted_list is None else accepted_list rejected_list = segext_obj.get_rejected_list() rejected_list = [] if rejected_list is None else rejected_list accepted_ids = [1 if k in accepted_list else 0 for k in roi_ids] rejected_ids = [1 if k in rejected_list else 0 for k in roi_ids] roi_locations = np.array(segext_obj.get_roi_locations()).T def image_mask_iterator(): for id in segext_obj.get_roi_ids(): img_msks = segext_obj.get_roi_image_masks( roi_ids=[id]).T.squeeze() yield img_msks if not ps_exist: input_kwargs.update( **ps_metadata, columns=[ VectorData( data=H5DataIO( DataChunkIterator(image_mask_iterator(), buffer_size=buffer_size), compression=True, compression_opts=9, ), name="image_mask", description="image masks", ), VectorData( data=roi_locations, name="RoiCentroid", description= "x,y location of centroid of the roi in image_mask", ), VectorData( data=accepted_ids, name="Accepted", description= "1 if ROi was accepted or 0 if rejected as a cell during segmentation operation", ), VectorData( data=rejected_ids, name="Rejected", description= "1 if ROi was rejected or 0 if accepted as a cell during segmentation operation", ), ], id=roi_ids, ) ps = image_segmentation.create_plane_segmentation( **input_kwargs) # Fluorescence Traces: if "Flourescence" not in ophys.data_interfaces: fluorescence = Fluorescence() ophys.add(fluorescence) else: fluorescence = ophys.data_interfaces["Fluorescence"] roi_response_dict = segext_obj.get_traces_dict() roi_table_region = ps.create_roi_table_region( description=f"region for Imaging plane{plane_no_loop}", region=list(range(segext_obj.get_num_rois())), ) rate = (np.float("NaN") if segext_obj.get_sampling_frequency() is None else segext_obj.get_sampling_frequency()) for i, j in roi_response_dict.items(): data = getattr(segext_obj, f"_roi_response_{i}") if data is not None: data = np.asarray(data) trace_name = "RoiResponseSeries" if i == "raw" else i.capitalize( ) trace_name = (trace_name if plane_no_loop == 0 else trace_name + f"_Plane{plane_no_loop}") input_kwargs = dict( name=trace_name, data=data.T, rois=roi_table_region, rate=rate, unit="n.a.", ) if trace_name not in fluorescence.roi_response_series: fluorescence.create_roi_response_series(**input_kwargs) # create Two Photon Series: if "TwoPhotonSeries" not in nwbfile.acquisition: warn( "could not find TwoPhotonSeries, using ImagingExtractor to create an nwbfile" ) # adding images: images_dict = segext_obj.get_images_dict() if any([image is not None for image in images_dict.values()]): images_name = ("SegmentationImages" if plane_no_loop == 0 else f"SegmentationImages_Plane{plane_no_loop}") if images_name not in ophys.data_interfaces: images = Images(images_name) for img_name, img_no in images_dict.items(): if img_no is not None: images.add_image( GrayscaleImage(name=img_name, data=img_no.T)) ophys.add(images) # saving NWB file: if write: io.write(nwbfile) io.close() # test read with NWBHDF5IO(str(save_path), "r") as io: io.read()
def setUp(self): start_time = datetime(2017, 4, 3, 11, 0, 0) create_date = datetime(2017, 4, 15, 12, 0, 0) # create your NWBFile object nwbfile = NWBFile('PyNWB Sample File', 'A simple NWB file', 'NWB_test', start_time, file_create_date=create_date) # create acquisition metadata optical_channel = OpticalChannel('test_optical_channel', 'optical channel source', 'optical channel description', 3.14) imaging_plane = nwbfile.create_imaging_plane('test_imaging_plane', 'ophys integration tests', optical_channel, 'imaging plane description', 'imaging_device_1', 6.28, '2.718', 'GFP', 'somewhere in the brain', (1, 2, 1, 2, 3), 4.0, 'manifold unit', 'A frame to refer to') # create acquisition data image_series = TwoPhotonSeries(name='test_iS', source='a hypothetical source', dimension=[2], external_file=['images.tiff'], imaging_plane=imaging_plane, starting_frame=[1, 2, 3], format='tiff', timestamps=list()) nwbfile.add_acquisition(image_series) mod = nwbfile.create_processing_module('img_seg_example', 'ophys demo', 'an example of writing Ca2+ imaging data') img_seg = ImageSegmentation('a toy image segmentation container') mod.add_data_interface(img_seg) ps = img_seg.create_plane_segmentation('integration test PlaneSegmentation', 'plane segmentation description', imaging_plane, 'test_plane_seg_name', image_series) # add two ROIs # - first argument is the pixel mask i.e. a list of pixels and their weights # - second argument is the image mask w, h = 3, 3 pix_mask1 = [(0, 0, 1.1), (1, 1, 1.2), (2, 2, 1.3)] img_mask1 = [[0.0 for x in range(w)] for y in range(h)] img_mask1[0][0] = 1.1 img_mask1[1][1] = 1.2 img_mask1[2][2] = 1.3 ps.add_roi('1234', pix_mask1, img_mask1) pix_mask2 = [(0, 0, 2.1), (1, 1, 2.2)] img_mask2 = [[0.0 for x in range(w)] for y in range(h)] img_mask2[0][0] = 2.1 img_mask2[1][1] = 2.2 ps.add_roi('5678', pix_mask2, img_mask2) # add a Fluorescence container fl = Fluorescence('a toy fluorescence container') mod.add_data_interface(fl) # get an ROI table region i.e. a subset of ROIs to create a RoiResponseSeries from rt_region = ps.create_roi_table_region('the first of two ROIs', region=[0]) # make some fake timeseries data data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] timestamps = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] rrs = fl.create_roi_response_series('test_roi_response_series', 'RoiResponseSeries integration test', data, 'lumens', rt_region, timestamps=timestamps) # write data nwb_path = './test_data/nwb_test_file.nwb' with NWBHDF5IO(nwb_path, 'w') as io: io.write(nwbfile)
def setUpClass(self): device = Device("imaging_device_1") optical_channel = OpticalChannel("my_optchan", "description", 500.0) self.imaging_plane = ImagingPlane( name="imgpln1", optical_channel=optical_channel, description="a fake ImagingPlane", device=device, excitation_lambda=600.0, imaging_rate=300.0, indicator="GFP", location="somewhere in the brain", reference_frame="unknown", origin_coords=[10, 20], origin_coords_unit="millimeters", grid_spacing=[0.001, 0.001], grid_spacing_unit="millimeters", ) self.image_series = TwoPhotonSeries( name="test_image_series", data=np.random.randn(100, 5, 5), imaging_plane=self.imaging_plane, starting_frame=[0], rate=1.0, unit="n.a", ) self.img_seg = ImageSegmentation() self.ps2 = self.img_seg.create_plane_segmentation( "output from segmenting my favorite imaging plane", self.imaging_plane, "2d_plane_seg", self.image_series, ) self.ps2.add_column("type", "desc") self.ps2.add_column("type2", "desc") w, h = 3, 3 img_mask1 = np.zeros((w, h)) img_mask1[0, 0] = 1.1 img_mask1[1, 1] = 1.2 img_mask1[2, 2] = 1.3 self.ps2.add_roi(image_mask=img_mask1, type=1, type2=0) img_mask2 = np.zeros((w, h)) img_mask2[0, 0] = 2.1 img_mask2[1, 1] = 2.2 self.ps2.add_roi(image_mask=img_mask2, type=1, type2=1) img_mask2 = np.zeros((w, h)) img_mask2[0, 0] = 9.1 img_mask2[1, 1] = 10.2 self.ps2.add_roi(image_mask=img_mask2, type=2, type2=0) img_mask2 = np.zeros((w, h)) img_mask2[0, 0] = 3.5 img_mask2[1, 1] = 5.6 self.ps2.add_roi(image_mask=img_mask2, type=2, type2=1) fl = Fluorescence() rt_region = self.ps2.create_roi_table_region("the first of two ROIs", region=[0, 1, 2, 3]) rois_shape = 5 data = np.arange(10 * rois_shape).reshape([10, -1], order='F') timestamps = np.array( [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]) rrs = fl.create_roi_response_series(name="my_rrs", data=data, rois=rt_region, unit="lumens", timestamps=timestamps) self.df_over_f = DfOverF(rrs)
def setUp(self): nwbfile = NWBFile( 'my first synthetic recording', 'EXAMPLE_ID', datetime.now(tzlocal()), experimenter='Dr. Bilbo Baggins', lab='Bag End Laboratory', institution='University of Middle Earth at the Shire', experiment_description=('I went on an adventure with thirteen ' 'dwarves to reclaim vast treasures.'), session_id='LONELYMTN') device = Device('imaging_device_1') nwbfile.add_device(device) optical_channel = OpticalChannel('my_optchan', 'description', 500.) imaging_plane = nwbfile.create_imaging_plane( 'my_imgpln', optical_channel, 'a very interesting part of the brain', device, 600., 300., 'GFP', 'my favorite brain location', np.ones((5, 5, 3)), 4.0, 'manifold unit', 'A frame to refer to') self.image_series = TwoPhotonSeries(name='test_iS', dimension=[2], data=np.random.rand(10, 5, 5, 3), external_file=['images.tiff'], imaging_plane=imaging_plane, starting_frame=[0], format='tiff', starting_time=0.0, rate=1.0) nwbfile.add_acquisition(self.image_series) mod = nwbfile.create_processing_module( 'ophys', 'contains optical physiology processed data') img_seg = ImageSegmentation() mod.add(img_seg) ps = img_seg.create_plane_segmentation( 'output from segmenting my favorite imaging plane', imaging_plane, 'my_planeseg', self.image_series) w, h = 3, 3 pix_mask1 = [(0, 0, 1.1), (1, 1, 1.2), (2, 2, 1.3)] vox_mask1 = [(0, 0, 0, 1.1), (1, 1, 1, 1.2), (2, 2, 2, 1.3)] img_mask1 = [[0.0 for x in range(w)] for y in range(h)] img_mask1[0][0] = 1.1 img_mask1[1][1] = 1.2 img_mask1[2][2] = 1.3 ps.add_roi(pixel_mask=pix_mask1, image_mask=img_mask1, voxel_mask=vox_mask1) pix_mask2 = [(0, 0, 2.1), (1, 1, 2.2)] vox_mask2 = [(0, 0, 0, 2.1), (1, 1, 1, 2.2)] img_mask2 = [[0.0 for x in range(w)] for y in range(h)] img_mask2[0][0] = 2.1 img_mask2[1][1] = 2.2 ps.add_roi(pixel_mask=pix_mask2, image_mask=img_mask2, voxel_mask=vox_mask2) fl = Fluorescence() mod.add(fl) rt_region = ps.create_roi_table_region('the first of two ROIs', region=[0]) data = np.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]).reshape(10, 1) timestamps = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] rrs = fl.create_roi_response_series('my_rrs', data, rt_region, unit='lumens', timestamps=timestamps) self.df_over_f = DfOverF(rrs)
def convert(self, **kwargs): """Convert the data and add to the nwb_file Args: **kwargs: arbitrary arguments """ super().convert(**kwargs) if "suite2p_dir" not in kwargs: raise Exception( f"'suite2p_dir' argument should be pass to convert " f"function in class {self.__class__.__name__}") suite2p_dir = kwargs["suite2p_dir"] # looking for the motion_corrected_ci_movie, return None if it doesn't exists # TODO: take in consideration the movie is not available # then don't construct image mask and don't build raw-traces, use F.npy is available image_series = self.nwb_file.acquisition.get( "motion_corrected_ci_movie") mod = self.nwb_file.create_processing_module( 'ophys', 'contains optical physiology processed data') img_seg = ImageSegmentation(name="segmentation_suite2p") mod.add_data_interface(img_seg) imaging_plane = self.nwb_file.get_imaging_plane("my_imgpln") # description, imaging_plane, name=None ps = img_seg.create_plane_segmentation( description='output from segmenting', imaging_plane=imaging_plane, name='my_plane_seg', reference_images=image_series) stat = np.load(os.path.join(suite2p_dir, "stat.npy"), allow_pickle=True) is_cell = np.load(os.path.join(suite2p_dir, "iscell.npy"), allow_pickle=True) # TODO: load f.npy for raw_traces if available if image_series.format == "tiff": dim_y, dim_x = image_series.data.shape[1:] n_frames = image_series.data.shape[0] print(f"dim_y, dim_x: {image_series.data.shape[1:]}") elif image_series.format == "external": im = PIL.Image.open(image_series.external_file[0]) n_frames = len(list(ImageSequence.Iterator(im))) dim_y, dim_x = np.array(im).shape print(f"dim_y, dim_x: {np.array(im).shape}") else: raise Exception( f"Format of calcium movie imaging {image_series.format} not yet implemented" ) n_cells = 0 # Add rois for cell in np.arange(len(stat)): if is_cell[cell][0] == 0: continue n_cells += 1 pix_mask = [(y, x, 1) for x, y in zip(stat[cell]["xpix"], stat[cell]["ypix"]) ] image_mask = np.zeros((dim_y, dim_x)) for pix in pix_mask: image_mask[pix[0], pix[1]] = pix[2] # we can id to identify the cell (int) otherwise it will be incremented at each step ps.add_roi(pixel_mask=pix_mask, image_mask=image_mask) fl = Fluorescence(name="fluorescence_suite2p") mod.add_data_interface(fl) rt_region = ps.create_roi_table_region('all cells', region=list(np.arange(n_cells))) if format == "external": if image_series.external_file[0].endswith(".tiff") or \ image_series.external_file[0].endswith(".tif"): # TODO: fix this bug, so far external loading, taking in consideration frames_to_add is not possible # either copy the code from ConvertCiMovieToNWB reconstructing frames_to_add from intervals # or find another solution. Another solution would be to put on the yaml as argument # frames_to_add but using the attribute from the ConvertMovie instance. s ci_movie = ConvertCiMovieToNWB.load_tiff_movie_in_memory( image_series.external_file[0]) else: raise Exception( f"Calcium imaging format not supported yet {image_series.external_file[0]}" ) else: ci_movie = image_series.data # TODO: if movie is external, see to load it if ci_movie: raw_traces = np.zeros((n_cells, ci_movie.shape[0])) for cell in np.arange(n_cells): img_mask = ps['image_mask'][cell] img_mask = img_mask.astype(bool) raw_traces[cell, :] = np.mean(ci_movie[:, img_mask], axis=1) rrs = fl.create_roi_response_series(name='raw_traces', data=raw_traces, unit='lumens', rois=rt_region, timestamps=np.arange(n_frames), description="raw traces")
def write_segmentation(segext_obj, save_path, plane_num=0, metadata=None, overwrite=True): save_path = Path(save_path) assert save_path.suffix == '.nwb' if save_path.is_file() and not overwrite: nwbfile_exist = True file_mode = 'r+' else: if save_path.is_file(): os.remove(save_path) if not save_path.parent.is_dir(): save_path.parent.mkdir(parents=True) nwbfile_exist = False file_mode = 'w' # parse metadata correctly: if isinstance(segext_obj, MultiSegmentationExtractor): segext_objs = segext_obj.segmentations if metadata is not None: assert isinstance(metadata, list), "For MultiSegmentationExtractor enter 'metadata' as a list of " \ "SegmentationExtractor metadata" assert len(metadata) == len(segext_objs), "The 'metadata' argument should be a list with the same " \ "number of elements as the segmentations in the " \ "MultiSegmentationExtractor" else: segext_objs = [segext_obj] if metadata is not None and not isinstance(metadata, list): metadata = [metadata] metadata_base_list = [ NwbSegmentationExtractor.get_nwb_metadata(sgobj) for sgobj in segext_objs ] print(f'writing nwb for {segext_obj.extractor_name}\n') # updating base metadata with new: for num, data in enumerate(metadata_base_list): metadata_input = metadata[num] if metadata else {} metadata_base_list[num] = dict_recursive_update( metadata_base_list[num], metadata_input) # loop for every plane: with NWBHDF5IO(str(save_path), file_mode) as io: metadata_base_common = metadata_base_list[0] if nwbfile_exist: nwbfile = io.read() else: nwbfile = NWBFile(**metadata_base_common['NWBFile']) # Subject: if metadata_base_common.get('Subject'): nwbfile.subject = Subject( **metadata_base_common['Subject']) # Processing Module: if 'ophys' not in nwbfile.processing: ophys = nwbfile.create_processing_module( 'ophys', 'contains optical physiology processed data') else: ophys = nwbfile.get_processing_module('ophys') for plane_no_loop, (segext_obj, metadata) in enumerate( zip(segext_objs, metadata_base_list)): # Device: if metadata['Ophys']['Device'][0][ 'name'] not in nwbfile.devices: nwbfile.create_device(**metadata['Ophys']['Device'][0]) # ImageSegmentation: image_segmentation_name = 'ImageSegmentation' if plane_no_loop == 0 else f'ImageSegmentation_Plane{plane_no_loop}' if image_segmentation_name not in ophys.data_interfaces: image_segmentation = ImageSegmentation( name=image_segmentation_name) ophys.add_data_interface(image_segmentation) else: image_segmentation = ophys.data_interfaces.get( image_segmentation_name) # OpticalChannel: optical_channels = [ OpticalChannel(**i) for i in metadata['Ophys'] ['ImagingPlane'][0]['optical_channel'] ] # ImagingPlane: image_plane_name = 'ImagingPlane' if plane_no_loop == 0 else f'ImagePlane_{plane_no_loop}' if image_plane_name not in nwbfile.imaging_planes.keys(): input_kwargs = dict( name=image_plane_name, device=nwbfile.get_device(metadata_base_common['Ophys'] ['Device'][0]['name']), ) metadata['Ophys']['ImagingPlane'][0][ 'optical_channel'] = optical_channels input_kwargs.update(**metadata['Ophys']['ImagingPlane'][0]) if 'imaging_rate' in input_kwargs: input_kwargs['imaging_rate'] = float( input_kwargs['imaging_rate']) imaging_plane = nwbfile.create_imaging_plane( **input_kwargs) else: imaging_plane = nwbfile.imaging_planes[image_plane_name] # PlaneSegmentation: input_kwargs = dict( description='output from segmenting imaging plane', imaging_plane=imaging_plane) ps_metadata = metadata['Ophys']['ImageSegmentation'][ 'plane_segmentations'][0] if ps_metadata[ 'name'] not in image_segmentation.plane_segmentations: input_kwargs.update(**ps_metadata) ps = image_segmentation.create_plane_segmentation( **input_kwargs) ps_exist = False else: ps = image_segmentation.get_plane_segmentation( ps_metadata['name']) ps_exist = True # ROI add: image_masks = segext_obj.get_roi_image_masks() roi_ids = segext_obj.get_roi_ids() accepted_list = segext_obj.get_accepted_list() accepted_list = [] if accepted_list is None else accepted_list rejected_list = segext_obj.get_rejected_list() rejected_list = [] if rejected_list is None else rejected_list accepted_ids = [ 1 if k in accepted_list else 0 for k in roi_ids ] rejected_ids = [ 1 if k in rejected_list else 0 for k in roi_ids ] roi_locations = np.array(segext_obj.get_roi_locations()).T if not ps_exist: ps.add_column( name='RoiCentroid', description= 'x,y location of centroid of the roi in image_mask') ps.add_column( name='Accepted', description= '1 if ROi was accepted or 0 if rejected as a cell during segmentation operation' ) ps.add_column( name='Rejected', description= '1 if ROi was rejected or 0 if accepted as a cell during segmentation operation' ) for num, row in enumerate(roi_ids): ps.add_roi(id=row, image_mask=image_masks[:, :, num], RoiCentroid=roi_locations[num, :], Accepted=accepted_ids[num], Rejected=rejected_ids[num]) # Fluorescence Traces: if 'Flourescence' not in ophys.data_interfaces: fluorescence = Fluorescence() ophys.add_data_interface(fluorescence) else: fluorescence = ophys.data_interfaces['Fluorescence'] roi_response_dict = segext_obj.get_traces_dict() roi_table_region = ps.create_roi_table_region( description=f'region for Imaging plane{plane_no_loop}', region=list(range(segext_obj.get_num_rois()))) rate = np.float('NaN') if segext_obj.get_sampling_frequency( ) is None else segext_obj.get_sampling_frequency() for i, j in roi_response_dict.items(): data = getattr(segext_obj, f'_roi_response_{i}') if data is not None: data = np.asarray(data) trace_name = 'RoiResponseSeries' if i == 'raw' else i.capitalize( ) trace_name = trace_name if plane_no_loop == 0 else trace_name + f'_Plane{plane_no_loop}' input_kwargs = dict(name=trace_name, data=data.T, rois=roi_table_region, rate=rate, unit='n.a.') if trace_name not in fluorescence.roi_response_series: fluorescence.create_roi_response_series( **input_kwargs) # create Two Photon Series: if 'TwoPhotonSeries' not in nwbfile.acquisition: warn( 'could not find TwoPhotonSeries, using ImagingExtractor to create an nwbfile' ) # adding images: images_dict = segext_obj.get_images_dict() if any([image is not None for image in images_dict.values()]): images_name = 'SegmentationImages' if plane_no_loop == 0 else f'SegmentationImages_Plane{plane_no_loop}' if images_name not in ophys.data_interfaces: images = Images(images_name) for img_name, img_no in images_dict.items(): if img_no is not None: images.add_image( GrayscaleImage(name=img_name, data=img_no)) ophys.add(images) # saving NWB file: io.write(nwbfile) # test read with NWBHDF5IO(str(save_path), 'r') as io: io.read()