def nwbfile(): _nwbfile = pynwb.NWBFile( session_description="test session", identifier='test session', session_start_time=datetime.now() ) dev = pynwb.device.Device(name="my_device") _nwbfile.add_device(dev) ice = pynwb.icephys.IntracellularElectrode( name="my_electrode", device=dev, description="" ) _nwbfile.add_ic_electrode(ice) series = pynwb.icephys.CurrentClampSeries( name="a current clamp", data=[1, 2, 3], starting_time=0.0, rate=1.0, gain=1.0, electrode=ice, sweep_number=12 ) _nwbfile.add_acquisition(series) _nwbfile.subject = pynwb.file.Subject() return _nwbfile
def test_add_partial_metadata(test_partial_metadata, roundtrip, roundtripper, cell_specimen_table, metadata_fixture, partial_metadata_fixture): if test_partial_metadata: meta = partial_metadata_fixture else: meta = metadata_fixture nwbfile = pynwb.NWBFile( session_description='asession', identifier='afile', session_start_time=meta['date_of_acquisition'] ) nwb.add_metadata(nwbfile, meta, behavior_only=False) if not test_partial_metadata: nwb.add_cell_specimen_table(nwbfile, cell_specimen_table, meta) if roundtrip: obt = roundtripper(nwbfile, BehaviorOphysNwbApi) else: obt = BehaviorOphysNwbApi.from_nwbfile(nwbfile) if not test_partial_metadata: metadata_obt = obt.get_metadata() else: with warnings.catch_warnings(record=True) as record: metadata_obt = obt.get_metadata() exp_warn_msg = "Could not locate 'ophys' module in NWB" print(record) assert record[0].message.args[0].startswith(exp_warn_msg) assert len(metadata_obt) == len(meta) for key, val in meta.items(): assert val == metadata_obt[key]
def create_nwb_file(): ''' acquisition.t1 acquisition.t2 modules.mod.t3 modules.mod.t4 :return: ''' start_time = datetime(2019, 1, 1, 11, tzinfo=tzlocal()) create_date = datetime.now(tz=tzlocal()) # FIXME: this attr breaks nwb-explorer # date_of_birth=create_date sub = pynwb.file.Subject(age='33', description='Nothing too personal.', genotype='AA', sex='M', species='H**o erectus', subject_id='001', weight="199 lb") nwbfile = pynwb.NWBFile('Example structured data', 'TSD', start_time, file_create_date=create_date, notes='Example NWB file', experimenter='Filippo Ledda', experiment_description='Add example data', institution='UCL', subject=sub) sample_num = 100 timestamps = np.arange(0, sample_num, 1) data = timestamps * 2 nwbfile.add_acquisition( pynwb.TimeSeries(name='t1', data=data, unit='UA', timestamps=timestamps)) nwbfile.add_acquisition( pynwb.TimeSeries(name='t2', data=data, unit='pA', rate=1.0)) mod = nwbfile.create_processing_module('mod', 'Mod') interface = mod.add( pynwb.TimeSeries(name='t3', data=data, unit='pA', timestamps=timestamps)) mod.add( pynwb.TimeSeries(name='t4', data=data, unit='UA', timestamps=timestamps)) nwbfile.add_acquisition( create_image('internal_storaged_image', nwbfile, False)) nwbfile.add_acquisition( create_image('external_storaged_image', nwbfile, True)) return nwbfile
def setup_method(self, method): self.meta = self._get_meta() self.nwbfile = pynwb.NWBFile( session_description='asession', identifier=str(self.meta.ophys_metadata.ophys_experiment_id), session_start_time=datetime.datetime.now() )
def make_nwb_file(filename, *args, cache_spec=False, **kwargs): """A little helper to produce an .nwb file in the path using NWBFile Note: it doesn't cache_spec by default """ nwbfile = pynwb.NWBFile(*args, **kwargs) with pynwb.NWBHDF5IO(filename, "w") as io: io.write(nwbfile, cache_spec=cache_spec) return filename
def test_roundtrip_basic_metadata(roundtripper): dt = datetime.now(timezone.utc) nwbfile = pynwb.NWBFile(session_description='EcephysSession', identifier='{}'.format(12345), session_start_time=dt) api = roundtripper(nwbfile, EcephysNwbSessionApi) assert 12345 == api.get_ecephys_session_id() assert dt == api.get_session_start_time()
def setup_method(self, method): self.nwbfile = pynwb.NWBFile(session_description='asession', identifier='1234', session_start_time=datetime.now()) # Need to write stimulus timestamps first bsf = StimulusFile(filepath=self.test_data_dir / 'behavior_stimulus_file.pkl') ts = StimulusTimestamps.from_stimulus_file(stimulus_file=bsf) ts.to_nwb(nwbfile=self.nwbfile)
def setup_method(self, method): self.nwbfile = pynwb.NWBFile(session_description='asession', identifier='1234', session_start_time=datetime.now()) dir = Path(__file__).parent.resolve() self.test_data_dir = dir / 'test_data' with open(self.test_data_dir / 'task_parameters.json') as f: tp = json.load(f) self.task_parameters = TaskParameters(**tp)
def get_probe_lfp_data(self, probe_id): path = os.path.join(shared_tmpdir, f"probe_{probe_id}.nwb") nwbfile = pynwb.NWBFile(session_description='EcephysProbe', identifier=f"{probe_id}", session_start_time=datetime.now()) with pynwb.NWBHDF5IO(path, "w") as io: io.write(nwbfile) return open(path, 'rb')
def newfile(params): f = pynwb.NWBFile(params['title'], params['session_description'], params['identifier'], params['session_start_time'], experimenter=params['experimenter'], lab=params['lab'], institution=params['institution'], experiment_description=params['experiment_description'], session_id=params['session_id']) return f
def _old_method_for_creating_test_file(): nwb_content = pynwb.NWBFile( session_description='test-session-description', experimenter='test-experimenter-name', lab='test-lab', institution='test-institution', session_start_time=datetime.now(), timestamps_reference_time=datetime.fromtimestamp(0, pytz.utc), identifier=str(uuid.uuid1()), session_id='test-session-id', notes='test-notes', experiment_description='test-experiment-description', subject=pynwb.file.Subject( description='test-subject-description', genotype='test-subject-genotype', sex='female', species='test-subject-species', subject_id='test-subject-id', weight='2 lbs' ), ) nwb_content.add_epoch( start_time=float(0), # start time in seconds stop_time=float(100), # end time in seconds tags='epoch1' ) nwb_content.create_device( name='test-device' ) nwb_content.create_electrode_group( name='test-electrode-group', location='test-electrode-group-location', device=nwb_content.devices['test-device'], description='test-electrode-group-description' ) num_channels = 8 for m in range(num_channels): location = [0, m] grp = nwb_content.electrode_groups['test-electrode-group'] impedance = -1.0 nwb_content.add_electrode( id=m, x=float(location[0]), y=float(location[1]), z=float(0), imp=impedance, location='test-electrode-group-location', filtering='none', group=grp ) nwb_fname = os.environ['NWB_DATAJOINT_BASE_DIR'] + '/test.nwb' with pynwb.NWBHDF5IO(path=nwb_fname, mode='w') as io: io.write(nwb_content) io.close()
def new_nwbfile_raw_file_name(tmp_path): nwbfile = pynwb.NWBFile( session_description='session_description', identifier='identifier', session_start_time=datetime.datetime.now(datetime.timezone.utc), ) device = nwbfile.create_device('dev1') group = nwbfile.create_electrode_group('tetrode1', 'tetrode description', 'tetrode location', device) nwbfile.add_electrode(id=1, x=1.0, y=2.0, z=3.0, imp=-1.0, location='CA1', filtering='none', group=group, group_name='tetrode1') region = nwbfile.create_electrode_table_region(region=[0], description='electrode 1') es = pynwb.ecephys.ElectricalSeries( name='test_ts', data=[1, 2, 3], timestamps=[1., 2., 3.], electrodes=region, ) nwbfile.add_acquisition(es) nwb_datajoint_base_dir = tmp_path / 'nwb-data' os.environ['NWB_DATAJOINT_BASE_DIR'] = str(nwb_datajoint_base_dir) os.mkdir(os.environ['NWB_DATAJOINT_BASE_DIR']) raw_dir = nwb_datajoint_base_dir / 'raw' os.mkdir(raw_dir) dj.config['stores'] = { 'raw': { 'protocol': 'file', 'location': str(raw_dir), 'stage': str(raw_dir) }, } file_name = 'raw.nwb' file_path = raw_dir / file_name with pynwb.NWBHDF5IO(str(file_path), mode='w') as io: io.write(nwbfile) return file_name
def setup_method(self, method): self.nwbfile = pynwb.NWBFile(session_description='asession', identifier='1234', session_start_time=datetime.now()) tj = TestJson() tj.setup_class() self.dict_repr = tj.dict_repr # Write metadata, since csp requires other metdata tbom = TestBOM() tbom.setup_class() bom = tbom.meta bom.to_nwb(nwbfile=self.nwbfile)
def init_nwb_file(file_name, source_script, experimenter, session_start_time): subject_id, date, session_id = file_name.split("_") nwb_file = pynwb.NWBFile( session_description='reaching without borders', # required identifier=file_name, # required session_start_time=session_start_time, # required experimenter=experimenter, session_id=session_id, file_create_date=datetime.now(tzlocal()), source_script=source_script) subject = pynwb.file.Subject( subject_id=subject_id) # consider adding more metadata nwb_file.subject = subject return nwb_file
def make_skeleton_nwb2_file(nwb2_file_name): nwbfile = pynwb.NWBFile(session_description='test icephys', identifier='session_uuid', session_start_time=datetime.datetime.now(), file_create_date=datetime.datetime.now()) device = nwbfile.create_device(name='electrode_0') electrode = nwbfile.create_ic_electrode( name="elec0", description='intracellular electrode', device=device) io = pynwb.NWBHDF5IO(nwb2_file_name, 'w') io.write(nwbfile) io.close()
def get_session_data(self, session_id, **kwargs): path = os.path.join(shared_tmpdir, 'tmp.nwb') nwbfile = pynwb.NWBFile(session_description='EcephysSession', identifier=f"{session_id}", session_start_time=datetime.now()) write_nwb.add_probe_to_nwbfile(nwbfile, 11, sampling_rate=1.0, lfp_sampling_rate=2.0, has_lfp_data=True) with pynwb.NWBHDF5IO(path, "w") as io: io.write(nwbfile) return open(path, 'rb')
def test_add_behavior_only_metadata(roundtrip, roundtripper, behavior_only_metadata_fixture): metadata = behavior_only_metadata_fixture nwbfile = pynwb.NWBFile(session_description='asession', identifier='afile', session_start_time=metadata['date_of_acquisition']) nwb.add_metadata(nwbfile, metadata, behavior_only=True) if roundtrip: obt = roundtripper(nwbfile, BehaviorNwbApi) else: obt = BehaviorNwbApi.from_nwbfile(nwbfile) metadata_obt = obt.get_metadata() assert len(metadata_obt) == len(metadata) for key, val in metadata.items(): assert val == metadata_obt[key]
def simple_nwb(base_path): in_nwb_path = os.path.join(base_path, "input.nwb") out_nwb_path = os.path.join(base_path, "meta.nwb") nwbfile = pynwb.NWBFile( session_description="test session", identifier='test session', session_start_time=datetime.now() ) nwbfile.add_acquisition( pynwb.TimeSeries( name="a timeseries", data=[1, 2, 3], starting_time=0.0, rate=1.0 ) ) with pynwb.NWBHDF5IO(path=in_nwb_path, mode="w") as writer: writer.write(nwbfile) return in_nwb_path, out_nwb_path
def write_data(self): filename = '%s-%i.nwb' % (self.STIM['label'][self.iEp % len( self.STIM['label'])], int(self.iEp / len(self.STIM['label'])) + 1) nwbfile = pynwb.NWBFile( 'Intrinsic Imaging data following bar stimulation', 'intrinsic', datetime.datetime.utcnow(), file_create_date=datetime.datetime.utcnow()) # Create our time series angles = pynwb.TimeSeries( name='angle_timeseries', data=self.STIM[self.STIM['label'][self.iEp % len(self.STIM['label'])] + '-angle'], unit='Rd', timestamps=self.STIM[self.STIM['label'][self.iEp % len(self.STIM['label'])] + '-times']) nwbfile.add_acquisition(angles) images = pynwb.image.ImageSeries( name='image_timeseries', data=np.array(self.FRAMES, dtype=np.float64), unit='a.u.', timestamps=self.STIM[self.STIM['label'][self.iEp % len(self.STIM['label'])] + '-times']) nwbfile.add_acquisition(images) # Write the data to file io = pynwb.NWBHDF5IO(os.path.join(self.datafolder, filename), 'w') print('writing:', filename) io.write(nwbfile) io.close() print(filename, ' saved !')
def main(): '''Main entry point''' parser = argparse.ArgumentParser(description='nwb2nix') parser.add_argument('-v', '--version', action='store_true', default=False) parser.add_argument('FILE', type=str) args = parser.parse_args() if args.version: print(f"NIX: {nix.__version__}") print(f"NWB: {nwb.__version__}") sys.exit(0) p = Path(args.FILE).resolve() print(f"Loading {p}", file=sys.stderr) nfd = nix.File.open(str(p), nix.FileMode.ReadOnly) for b in nfd.blocks: md = b.metadata recording = md['Recording'] name = recording['Name'] dt = make_recoding_time(recording) print(dt) # now to nwb out = nwb.NWBFile(identifier=name, session_description=name, #TODO session_start_time=dt) for data in b.data_arrays: dims = data.dimensions if len(dims) == 1 and dims[0].dimension_type == nix.DimensionType.Sample: convert_1d_sampled(out, data, md) print(f'writing {name}.nwb', file=sys.stderr) with nwb.NWBHDF5IO(f'{name}.nwb', 'w') as w: w.write(out) print("all done", file=sys.stderr)
def nwbfile_to_test(): """ Create a simple nwbfile for testing Returns ------- nwbfile """ nwbfile = pynwb.NWBFile(session_description="test nwb data", identifier='test session', session_start_time=datetime.datetime.now(), file_create_date=datetime.datetime.now()) device = nwbfile.create_device(name='electrode_0') electrode = nwbfile.create_icephys_electrode(name="electrode 0", description='fancy electrode', device=device) stimulus_data = [0, 3, 3, 3, 0] stimulus_meta_data = { "name": "stimulus", "sweep_number": 4, "unit": "A", "gain": 32.0, "resolution": 1.0, "conversion": 1.0E-3, "starting_time": 1.5, "rate": 7000.0, "stimulus_description": "STIMULUS_CODE" } stimulus_series = CurrentClampStimulusSeries(data=stimulus_data, electrode=electrode, **stimulus_meta_data) nwbfile.add_stimulus(stimulus_series) response_data = [1, 2, 3, 4, 5] response_meta_data = { "name": "acquisition", "sweep_number": 4, "unit": "V", "gain": 32.0, "resolution": 1.0, "conversion": 1.0E-3, "bridge_balance": 500.0, "bias_current": 100.0, "starting_time": 1.5, "rate": 7000.0, "stimulus_description": "STIMULUS_CODE" } acquisition_series = CurrentClampSeries(data=response_data, electrode=electrode, **response_meta_data) nwbfile.add_acquisition(acquisition_series) return nwbfile
def write_probe_lfp_file(session_id, session_metadata, session_start_time, log_level, probe): """ Writes LFP data (and associated channel information) for one probe to a standalone nwb file """ logging.getLogger('').setLevel(log_level) logging.info(f"writing lfp file for probe {probe['id']}") nwbfile = pynwb.NWBFile( session_description= 'LFP data and associated channel info for a single Ecephys probe', identifier=f"{probe['id']}", session_id=f"{session_id}", session_start_time=session_start_time, institution="Allen Institute for Brain Science") if session_metadata is not None: nwbfile = add_metadata_to_nwbfile(nwbfile, session_metadata) if probe.get("temporal_subsampling_factor", None) is not None: probe["lfp_sampling_rate"] = probe["lfp_sampling_rate"] / probe[ "temporal_subsampling_factor"] nwbfile, probe_nwb_device, probe_nwb_electrode_group = add_probe_to_nwbfile( nwbfile, probe_id=probe["id"], name=probe["name"], sampling_rate=probe["sampling_rate"], lfp_sampling_rate=probe["lfp_sampling_rate"], has_lfp_data=probe["lfp"] is not None) lfp_channels = np.load(probe['lfp']['input_channels_path'], allow_pickle=False) add_ecephys_electrodes(nwbfile, probe["channels"], probe_nwb_electrode_group, local_index_whitelist=lfp_channels) electrode_table_region = nwbfile.create_electrode_table_region( region=np.arange(len( nwbfile.electrodes)).tolist(), # must use raw indices here name='electrodes', description=f"lfp channels on probe {probe['id']}") lfp_data, lfp_timestamps = ContinuousFile( data_path=probe['lfp']['input_data_path'], timestamps_path=probe['lfp']['input_timestamps_path'], total_num_channels=len(nwbfile.electrodes)).load(memmap=False) lfp_data = lfp_data.astype(np.float32) lfp_data = lfp_data * probe["amplitude_scale_factor"] lfp = pynwb.ecephys.LFP(name=f"probe_{probe['id']}_lfp") nwbfile.add_acquisition( lfp.create_electrical_series(name=f"probe_{probe['id']}_lfp_data", data=H5DataIO(data=lfp_data, compression='gzip', compression_opts=9), timestamps=H5DataIO(data=lfp_timestamps, compression='gzip', compression_opts=9), electrodes=electrode_table_region)) nwbfile.add_acquisition(lfp) csd, csd_times, csd_locs = read_csd_data_from_h5(probe["csd_path"]) nwbfile = add_csd_to_nwbfile(nwbfile, csd, csd_times, csd_locs) with pynwb.NWBHDF5IO(probe['lfp']['output_path'], 'w') as lfp_writer: logging.info( f"writing probe lfp file to {probe['lfp']['output_path']}") lfp_writer.write(nwbfile, cache_spec=True) return {"id": probe["id"], "nwb_path": probe["lfp"]["output_path"]}
def create(self): yield ("core", "simple1.nwb", pynwb.NWBFile(**metadata))
def build_summary_episodes( FILES, roi_prefix=10000, # to have unique roi per session, session X has roi IDs: X*roi_prefix+i_ROI prestim_duration=2, modalities=['pupil', 'facemotion', 'running-speed'], dt_sampling=20, # ms Nmax=100000): """ """ protocols, subjects, sessions, sessions_per_subject, filename, STIM = find_protocol_details( FILES) FULL_EPISODE_ARRAY, QUANT = [], { 'subject': [], 'session_per_subject': [], 'session': [], 'roi': [], 'pupil': [], 'running-speed': [], 'facemotion': [] } print('- building "%s" by concatenating episodes from n=%i files [...]' % (filename, len(FILES))) for session, f in enumerate(FILES): print(' -> session #%i: %s' % (session + 1, f)) data = Data(f) for ip, p in enumerate(protocols): if len(protocols) > 1: duration = data.metadata['Protocol-%i-presentation-duration' % (ip + 1)] else: duration = data.metadata['presentation-duration'] # build episodes of other modalities (running, ...) if ('Pupil' in data.nwbfile.processing) and ('pupil' in modalities): Pupil_episodes = EpisodeResponse( data, protocol_id=ip, prestim_duration=prestim_duration, dt_sampling=dt_sampling, # ms quantity='Pupil') t_pupil_cond = (Pupil_episodes.t > 0) & (Pupil_episodes.t < duration) else: Pupil_episodes = None if ('Running-Speed' in data.nwbfile.acquisition) and ('running-speed' in modalities): Running_episodes = EpisodeResponse( data, protocol_id=ip, prestim_duration=prestim_duration, dt_sampling=dt_sampling, # ms quantity='Running-Speed') t_running_cond = (Running_episodes.t > 0) & (Running_episodes.t < duration) else: Running_episodes = None if ('FaceMotion' in data.nwbfile.processing) and ('facemotion' in modalities): FaceMotion_episodes = EpisodeResponse( data, protocol_id=ip, prestim_duration=prestim_duration, dt_sampling=dt_sampling, # ms quantity='FaceMotion') t_facemotion_cond = (FaceMotion_episodes.t > 0) & (FaceMotion_episodes.t < duration) else: FaceMotion_episodes = None for roi in range(np.sum(data.iscell))[:Nmax]: roiID = roi_prefix * session + roi EPISODES = EpisodeResponse( data, protocol_id=ip, quantity='CaImaging', subquantity='dF/F', dt_sampling=dt_sampling, # ms roiIndex=roi, prestim_duration=prestim_duration) for iEp in range(EPISODES.resp.shape[0]): FULL_EPISODE_ARRAY.append(EPISODES.resp[iEp, :]) for key in data.nwbfile.stimulus.keys(): STIM[key].append(data.nwbfile.stimulus[key].data[iEp]) QUANT['roi'].append(roiID) QUANT['session'].append(session) QUANT['subject'].append(data.metadata['subject_ID']) QUANT['session_per_subject'].append( sessions_per_subject[session]) if Running_episodes is not None: QUANT['running-speed'].append( Running_episodes.resp[iEp, :][t_running_cond]) else: QUANT['running-speed'].append(666.) # flag for None if Pupil_episodes is not None: QUANT['pupil'].append( Pupil_episodes.resp[iEp, :][t_pupil_cond]) else: QUANT['pupil'].append(666.) # flag for None if FaceMotion_episodes is not None: QUANT['facemotion'].append(FaceMotion_episodes.resp[ iEp, :][t_facemotion_cond]) else: QUANT['facemotion'].append(666.) # flag for None # set up the NWBFile description = 'Summary data concatenating episodes from the datafiles:\n' for f in FILES: description += '- %s\n' % f nwbfile = pynwb.NWBFile( session_description=description, identifier=filename, session_start_time=datetime.datetime.now().astimezone()) episode_waveforms = pynwb.TimeSeries(name='episode_waveforms', data=np.array(FULL_EPISODE_ARRAY), unit='dF/F', timestamps=EPISODES.t) nwbfile.add_acquisition(episode_waveforms) for key in STIM: stim = pynwb.TimeSeries(name=key, data=np.array(STIM[key]), unit='None', rate=1.) nwbfile.add_stimulus(stim) for key in QUANT: stim = pynwb.TimeSeries(name=key, data=np.array(QUANT[key]), unit='None', rate=1.) nwbfile.add_acquisition(stim) io = pynwb.NWBHDF5IO(filename, mode='w') io.write(nwbfile) io.close()
def create_nwb_file(session, nwb_file_path): logging.info('Staring session {}'.format(session.session_id)) nwbfile = pynwb.NWBFile( session_description=session.description, session_id=str(session.session_id), identifier=str(session.experiment_metadata['experiment_id']), session_start_time=session.start_time, # experiment_description=str(session.experiment_metadata['experiment_id']) ) ### Build the stimulus table ### stim_table_df = session.stimulus_table nwbfile = add_stimulus_timestamps(nwbfile, stim_table_df['start_time'].values) nwbfile = add_stimulus_presentations(nwbfile, stim_table_df) ### Image Segmentation ### optical_channel = pynwb.ophys.OpticalChannel( name='optical_channel', description='description', emission_lambda=session.emission_wavelength) # device = pynwb.device.Device(name='Allen Institute two-photon pipeline: {}'.format(session.session_metadata['rig'])) device = pynwb.device.Device( name='{}'.format(session.session_metadata['rig'])) nwbfile.add_device(device) imaging_plane = nwbfile.create_imaging_plane( name=session.imaging_plane_name, optical_channel=optical_channel, description=session.imaging_plane_name, device=device, excitation_lambda=session.excitation_lambda, imaging_rate=session.imaging_rate, indicator=session.calcium_indicator, location='area: {},depth: {}'.format( session.experiment_metadata["area"], str(session.experiment_metadata["depth"])), unit="Fluorescence (au)", reference_frame="Intrinsic imaging home", ) ophys_module = nwbfile.create_processing_module( session.ophys_module_name, 'contains optical physiology processed data') max_projection = pynwb.ophys.TwoPhotonSeries( name='max_project', data=[session.max_projection], imaging_plane=imaging_plane, dimension=[session.image_width, session.image_height], rate=30.0) # nwbfile.add_acquisition(max_projection) ophys_module.add_data_interface(max_projection) img_seg = pynwb.ophys.ImageSegmentation( name=session.image_segmentation_name) ophys_module.add_data_interface(img_seg) ps = img_seg.create_plane_segmentation( name=session.plane_segmentation_name, description= "Segmentation for imaging plane (de Vries et al., 2019, Nat Neurosci)", imaging_plane=imaging_plane, ) for cell_id, roi_mask in session.roi_masks.items(): ps.add_roi(id=cell_id, image_mask=roi_mask) rt_region = ps.create_roi_table_region( description="segmented cells with cell_specimen_ids") ### Fluorescence traces ### fluorescence = pynwb.ophys.Fluorescence() ophys_module.add_data_interface(fluorescence) timestamps = session.twop_timestamps raw_traces = session.raw_traces assert (raw_traces.shape[1] <= timestamps.shape[0]) fluorescence.create_roi_response_series( name='raw_traces', data=raw_traces, rois=rt_region, unit='lumens', timestamps=timestamps[:raw_traces.shape[1]]) neuropil_traces = session.neuropil_traces assert (neuropil_traces.shape[1] <= timestamps.shape[0]) fluorescence.create_roi_response_series( name='neuropil_traces', data=neuropil_traces, rois=rt_region, unit='lumens', timestamps=timestamps[:neuropil_traces.shape[1]]) demixed_traces = session.demixed_traces assert (demixed_traces.shape[1] <= timestamps.shape[0]) fluorescence.create_roi_response_series( name='demixed_traces', data=demixed_traces, rois=rt_region, unit='lumens', timestamps=timestamps[:demixed_traces.shape[1]]) dff_traces = session.dff_traces assert (dff_traces.shape[1] <= timestamps.shape[0]) fluorescence.create_roi_response_series( name='DfOverF', data=session.dff_traces, rois=rt_region, unit='lumens', timestamps=timestamps[:dff_traces.shape[1]]) ### Running Speed ### running_velocity = pynwb.base.TimeSeries( name="running_speed", data=session.running_velocity[:len(session.stimulus_timestamps)], timestamps=session.stimulus_timestamps, unit="cm/s", description="Speed of the mouse on a rotating wheel", ) behavior_module = pynwb.behavior.BehavioralTimeSeries() behavior_module.add_timeseries(running_velocity) ophys_module.add_data_interface(behavior_module) ### Motion Correction ### # NOTE: Older versions of pynwb had a schema bug in ophys.CorrectedImageStack class that prevents it from being # acccessed. Unfortunately currently allensdk has frozen pynwb at version 1.0.2. To fix we need to add the # x/y corrections as a time series rather than using CorrectImageStack. # add_motion_correction_cis(session, ophys_module, nwbfile) add_motion_correction_pm(session, ophys_module, nwbfile) ### Subject and lab metadata ### sex_lu = {'F': 'female', 'M': 'male'} subject_metadata = pynwb.file.Subject( age=session.session_metadata['age'][1:], genotype=session.session_metadata['full_genotype'], sex=sex_lu.get(session.session_metadata['sex'], 'unknown'), species='Mus musculus', subject_id=str(session.session_metadata['specimen_id']), description=session.session_metadata['name']) nwbfile.subject = subject_metadata ### Events ### # add_events_discrete(session=session, ophys_module=ophys_module, nwbfile=nwbfile) add_events_contiguous(session=session, ophys_module=ophys_module, nwbfile=nwbfile, roi_table=rt_region) # pd.set_option('display.max_columns', None) # nwbfile.units = pynwb.misc.Units.from_dataframe(session.units, name='units') # # events_indices = session.event_indices # nwbfile.units.add_column( # name='event_times', # data=session.event_times, # index=session.event_indices, # description='times (s) of detected L0 events' # ) # # nwbfile.units.add_column( # name='event_amplitudes', # data=session.event_amps, # index=session.event_indices, # description='amplitudes (s) of detected L0 events' # ) ### Eye Tracking ### eye_dlc_path = session.eye_dlc_screen_mapping if eye_dlc_path is not None: eye_gazing_data = read_eye_gaze_mappings(eye_dlc_path) add_eye_gaze_mapping_data_to_nwbfile(nwbfile, eye_gazing_data) with pynwb.NWBHDF5IO(str(nwb_file_path), mode="w") as io: io.write(nwbfile)
def setup_method(self, method): self.nwbfile = pynwb.NWBFile(session_description='asession', identifier='1234', session_start_time=datetime.now())
def create_random_nwbfile(add_processing=True, add_high_gamma=True): """ Creates a NWB file with fields used by the Chang lab, with random fake data. Parameters ---------- add_processing : boolean Whether to add processing (LFP) data or not. add_high_gamma : boolean Whether to add high_gamma data or not. Returns ------- nwbfile : nwbfile object """ # Create NWBFile start_time = datetime(2017, 4, 3, 11, tzinfo=tzlocal()) nwbfile = pynwb.NWBFile(session_description='fake data', identifier='NWB123', session_start_time=start_time) # Basic fields nwbfile.institution = 'My institution' nwbfile.lab = 'My lab' nwbfile.subject = pynwb.file.Subject(age='5 months', description='description') # Add device and electrodes device = nwbfile.create_device(name='device') electrode_group = nwbfile.create_electrode_group( name='electrode_group0', description="an electrode group", location="somewhere in the hippocampus", device=device) n_electrodes = 4 for idx in np.arange(n_electrodes): nwbfile.add_electrode(id=idx, x=1.0, y=2.0, z=3.0, imp=float(-idx), location='CA1', filtering='none', group=electrode_group) # Add noise signal as raw data electrode_table_region = nwbfile.create_electrode_table_region( list(np.arange(n_electrodes)), 'electrodes_table_region') raw_len = 100000 ephys_data = np.random.rand(raw_len * 4).reshape((raw_len, 4)) ephys_ts = pynwb.ecephys.ElectricalSeries( name='raw_data', data=ephys_data, electrodes=electrode_table_region, starting_time=0., rate=100.) nwbfile.add_acquisition(ephys_ts) # Add noise signal as processing data if add_processing: ecephys_module = nwbfile.create_processing_module( name='ecephys', description='preprocessed data') lfp_len = 10000 lfp_data = np.random.rand(lfp_len * 4).reshape((lfp_len, 4)) lfp = pynwb.ecephys.LFP(name='LFP') lfp.create_electrical_series(name='processed_electrical_series', data=lfp_data, electrodes=electrode_table_region, rate=10., starting_time=0.) ecephys_module.add_data_interface(lfp) # Add noise signal as high gamma if add_processing and add_high_gamma: hg_data = np.random.rand(lfp_len * 4).reshape((lfp_len, 4)) hg = pynwb.ecephys.ElectricalSeries(name='high_gamma', data=hg_data, electrodes=electrode_table_region, rate=10., description='') ecephys_module.add_data_interface(hg) # Add noise signals as speaker stimuli and mic recording acquisition stim1 = pynwb.TimeSeries(name='stim1', data=np.random.rand(raw_len), starting_time=0.0, rate=100., unit='') stim2 = pynwb.TimeSeries(name='stim2', data=np.random.rand(raw_len), starting_time=0.0, rate=100., unit='') nwbfile.add_stimulus(stim1) nwbfile.add_stimulus(stim2) mic = pynwb.TimeSeries(name='mic', data=np.random.rand(raw_len), starting_time=0.0, rate=100., unit='') nwbfile.add_acquisition(mic) return nwbfile
def nwbfile(): return pynwb.NWBFile(session_description='asession', identifier='afile', session_start_time=datetime.now())
def build_NWB(args, Ca_Imaging_options={ 'Suite2P-binary-filename': 'data.bin', 'plane': 0 }): if args.verbose: print('Initializing NWB file for "%s" [...]' % args.datafolder) ################################################# #### BASIC metadata ####### ################################################# metadata = np.load(os.path.join(args.datafolder, 'metadata.npy'), allow_pickle=True).item() # replace by day and time in metadata !! if os.path.sep in args.datafolder: sep = os.path.sep else: sep = '/' # a weird behavior on Windows day = metadata['filename'].split('\\')[-2].split('_') Time = metadata['filename'].split('\\')[-1].split('-') identifier = metadata['filename'].split( '\\')[-2] + '-' + metadata['filename'].split('\\')[-1] start_time = datetime.datetime(int(day[0]), int(day[1]), int(day[2]), int(Time[0]), int(Time[1]), int(Time[2]), tzinfo=tzlocal()) # subject info if 'subject_props' in metadata and (metadata['subject_props'] is not None): subject_props = metadata['subject_props'] dob = subject_props['date_of_birth'].split('_') else: subject_props = {} print('subject properties not in metadata ...') dob = ['1988', '4', '24'] # NIdaq tstart if os.path.isfile(os.path.join(args.datafolder, 'NIdaq.start.npy')): metadata['NIdaq_Tstart'] = np.load( os.path.join(args.datafolder, 'NIdaq.start.npy'))[0] subject = pynwb.file.Subject( description=(subject_props['description'] if ('description' in subject_props) else 'Unknown'), sex=(subject_props['sex'] if ('sex' in subject_props) else 'Unknown'), genotype=(subject_props['genotype'] if ('genotype' in subject_props) else 'Unknown'), species=(subject_props['species'] if ('species' in subject_props) else 'Unknown'), subject_id=(subject_props['subject_id'] if ('subject_id' in subject_props) else 'Unknown'), weight=(subject_props['weight'] if ('weight' in subject_props) else 'Unknown'), date_of_birth=datetime.datetime(int(dob[0]), int(dob[1]), int(dob[2]), tzinfo=tzlocal())) nwbfile = pynwb.NWBFile( identifier=identifier, session_description=str(metadata), experiment_description=metadata['protocol'], experimenter=(metadata['experimenter'] if ('experimenter' in metadata) else 'Unknown'), lab=(metadata['lab'] if ('lab' in metadata) else 'Unknown'), institution=(metadata['institution'] if ('institution' in metadata) else 'Unknown'), notes=(metadata['notes'] if ('notes' in metadata) else 'Unknown'), virus=(subject_props['virus'] if ('virus' in subject_props) else 'Unknown'), surgery=(subject_props['surgery'] if ('surgery' in subject_props) else 'Unknown'), session_start_time=start_time, subject=subject, source_script=str(pathlib.Path(__file__).resolve()), source_script_file_name=str(pathlib.Path(__file__).resolve()), file_create_date=datetime.datetime.utcnow().replace(tzinfo=tzlocal())) filename = os.path.join( pathlib.Path(args.datafolder).parent, '%s.nwb' % identifier) manager = pynwb.get_manager( ) # we need a manager to link raw and processed data ################################################# #### IMPORTING NI-DAQ data ####### ################################################# if args.verbose: print('- Loading NIdaq data for "%s" [...]' % args.datafolder) try: NIdaq_data = np.load(os.path.join(args.datafolder, 'NIdaq.npy'), allow_pickle=True).item() NIdaq_Tstart = np.load(os.path.join(args.datafolder, 'NIdaq.start.npy'))[0] except FileNotFoundError: print(' /!\ No NI-DAQ data found /!\ ') print(' -----> Not able to build NWB file for "%s"' % args.datafolder) raise BaseException true_tstart0 = np.load(os.path.join(args.datafolder, 'NIdaq.start.npy'))[0] st = datetime.datetime.fromtimestamp(true_tstart0).strftime('%H:%M:%S.%f') true_tstart = StartTime_to_day_seconds(st) # ################################################# # #### Locomotion ####### # ################################################# if metadata['Locomotion'] and ('Locomotion' in args.modalities): # compute running speed from binary NI-daq signal if args.verbose: print('- Computing and storing running-speed for "%s" [...]' % args.datafolder) speed = compute_locomotion_speed( NIdaq_data['digital'][0], acq_freq=float(metadata['NIdaq-acquisition-frequency']), radius_position_on_disk=float( metadata['rotating-disk']['radius-position-on-disk-cm']), rotoencoder_value_per_rotation=float( metadata['rotating-disk']['roto-encoder-value-per-rotation'])) _, speed = resample_signal( speed, original_freq=float(metadata['NIdaq-acquisition-frequency']), new_freq=args.running_sampling, pre_smoothing=2. / args.running_sampling) running = pynwb.TimeSeries(name='Running-Speed', data=speed, starting_time=0., unit='cm/s', rate=args.running_sampling) nwbfile.add_acquisition(running) # ################################################# # #### Visual Stimulation ####### # ################################################# if (metadata['VisualStim'] and ('VisualStim' in args.modalities)) and os.path.isfile( os.path.join(args.datafolder, 'visual-stim.npy')): # preprocessing photodiode signal _, Psignal = resample_signal( NIdaq_data['analog'][0], original_freq=float(metadata['NIdaq-acquisition-frequency']), pre_smoothing=2. / float(metadata['NIdaq-acquisition-frequency']), new_freq=args.photodiode_sampling) VisualStim = np.load(os.path.join(args.datafolder, 'visual-stim.npy'), allow_pickle=True).item() # using the photodiod signal for the realignement if args.verbose: print( '=> Performing realignement from photodiode for "%s" [...] ' % args.datafolder) if 'time_duration' not in VisualStim: VisualStim['time_duration'] = np.array( VisualStim['time_stop']) - np.array(VisualStim['time_start']) for key in ['time_start', 'time_stop', 'time_duration']: metadata[key] = VisualStim[key] success, metadata = realign_from_photodiode( Psignal, metadata, sampling_rate=(args.photodiode_sampling if args.photodiode_sampling > 0 else None), verbose=args.verbose) if success: timestamps = metadata['time_start_realigned'] for key in ['time_start_realigned', 'time_stop_realigned']: VisualStimProp = pynwb.TimeSeries(name=key, data=metadata[key], unit='seconds', timestamps=timestamps) nwbfile.add_stimulus(VisualStimProp) for key in VisualStim: None_cond = (VisualStim[key] == None) if key in ['protocol_id', 'index']: array = np.array(VisualStim[key]) elif (type(VisualStim[key]) in [list, np.ndarray, np.array ]) and np.sum(None_cond) > 0: # need to remove the None elements VisualStim[key][ None_cond] = 0 * VisualStim[key][~None_cond][0] array = np.array(VisualStim[key], dtype=type( VisualStim[key][~None_cond][0])) else: array = VisualStim[key] VisualStimProp = pynwb.TimeSeries(name=key, data=array, unit='NA', timestamps=timestamps) nwbfile.add_stimulus(VisualStimProp) else: print(' /!\ No VisualStim metadata found /!\ ') # print(' -----> Not able to build NWB file for "%s" ' % args.datafolder) # TEMPORARY FOR TROUBLESHOOTING !! metadata['time_start_realigned'] = metadata['time_start'] metadata['time_stop_realigned'] = metadata['time_stop'] print(' /!\ Realignement unsuccessful /!\ ') print( ' --> using the default time_start / time_stop values ') if args.verbose: print('=> Storing the photodiode signal for "%s" [...]' % args.datafolder) photodiode = pynwb.TimeSeries(name='Photodiode-Signal', data=Psignal, starting_time=0., unit='[current]', rate=args.photodiode_sampling) nwbfile.add_acquisition(photodiode) ################################################# #### FaceCamera Recording ####### ################################################# if metadata['FaceCamera']: if args.verbose: print('=> Storing FaceCamera acquisition for "%s" [...]' % args.datafolder) if ('raw_FaceCamera' in args.modalities): try: FC_times, FC_FILES, _, _, _ = load_FaceCamera_data( os.path.join(args.datafolder, 'FaceCamera-imgs'), t0=NIdaq_Tstart, verbose=True) img = np.load( os.path.join(args.datafolder, 'FaceCamera-imgs', FC_FILES[0])) FC_SUBSAMPLING = build_subsampling_from_freq( args.FaceCamera_frame_sampling, 1. / np.mean(np.diff(FC_times)), len(FC_FILES), Nmin=3) def FaceCamera_frame_generator(): for i in FC_SUBSAMPLING: yield np.load( os.path.join(args.datafolder, 'FaceCamera-imgs', FC_FILES[i])).astype(np.uint8) FC_dataI = DataChunkIterator(data=FaceCamera_frame_generator(), maxshape=(None, img.shape[0], img.shape[1]), dtype=np.dtype(np.uint8)) FaceCamera_frames = pynwb.image.ImageSeries( name='FaceCamera', data=FC_dataI, unit='NA', timestamps=FC_times[FC_SUBSAMPLING]) nwbfile.add_acquisition(FaceCamera_frames) except BaseException as be: print(be) FC_FILES = None print(' /!\ Problems with FaceCamera data for "%s" /!\ ' % args.datafolder) ################################################# #### Pupil from FaceCamera ####### ################################################# if 'Pupil' in args.modalities: # add_pupil_data(nwbfile, FC_FILES, args) if os.path.isfile(os.path.join(args.datafolder, 'pupil.npy')): if args.verbose: print('=> Adding processed pupil data for "%s" [...]' % args.datafolder) dataP = np.load(os.path.join(args.datafolder, 'pupil.npy'), allow_pickle=True).item() if 'cm_to_pix' in dataP: # SCALE FROM THE PUPIL GUI pix_to_mm = 10. / float( dataP['cm_to_pix']) # IN MILLIMETERS FROM HERE else: pix_to_mm = 1 pupil_module = nwbfile.create_processing_module( name='Pupil', description= 'processed quantities of Pupil dynamics, pix_to_mm=%.3f' % pix_to_mm) for key, scale in zip(['cx', 'cy', 'sx', 'sy', 'blinking'], [pix_to_mm for i in range(4)] + [1]): if type(dataP[key]) is np.ndarray: PupilProp = pynwb.TimeSeries(name=key, data=dataP[key] * scale, unit='seconds', timestamps=FC_times) pupil_module.add(PupilProp) # then add the frames subsampled if FC_FILES is not None: img = np.load( os.path.join(args.datafolder, 'FaceCamera-imgs', FC_FILES[0])) x, y = np.meshgrid(np.arange(0, img.shape[0]), np.arange(0, img.shape[1]), indexing='ij') cond = (x >= dataP['xmin']) & (x <= dataP['xmax']) & ( y >= dataP['ymin']) & (y <= dataP['ymax']) PUPIL_SUBSAMPLING = build_subsampling_from_freq( args.Pupil_frame_sampling, 1. / np.mean(np.diff(FC_times)), len(FC_FILES), Nmin=3) def Pupil_frame_generator(): for i in PUPIL_SUBSAMPLING: yield np.load(os.path.join(args.datafolder, 'FaceCamera-imgs', FC_FILES[i])).astype(np.uint8)[cond].reshape(\ dataP['xmax']-dataP['xmin']+1, dataP['ymax']-dataP['ymin']+1) PUC_dataI = DataChunkIterator( data=Pupil_frame_generator(), maxshape=(None, dataP['xmax'] - dataP['xmin'] + 1, dataP['ymax'] - dataP['ymin'] + 1), dtype=np.dtype(np.uint8)) Pupil_frames = pynwb.image.ImageSeries( name='Pupil', data=PUC_dataI, unit='NA', timestamps=FC_times[PUPIL_SUBSAMPLING]) nwbfile.add_acquisition(Pupil_frames) else: print(' /!\ No processed pupil data found for "%s" /!\ ' % args.datafolder) ################################################# #### Facemotion from FaceCamera ####### ################################################# if 'Facemotion' in args.modalities: if os.path.isfile(os.path.join(args.datafolder, 'facemotion.npy')): if args.verbose: print( '=> Adding processed facemotion data for "%s" [...]' % args.datafolder) dataF = np.load(os.path.join(args.datafolder, 'facemotion.npy'), allow_pickle=True).item() faceMotion_module = nwbfile.create_processing_module( name='face-motion', description='face motion dynamics') FaceMotionProp = pynwb.TimeSeries( name='face motion time series', data=dataF['motion'], unit='seconds', timestamps=FC_times[dataF['frame']]) faceMotion_module.add(FaceMotionProp) # then add the motion frames subsampled if FC_FILES is not None: FACEMOTION_SUBSAMPLING = build_subsampling_from_freq( args.FaceMotion_frame_sampling, 1. / np.mean(np.diff(FC_times)), len(FC_FILES), Nmin=3) img = np.load( os.path.join(args.datafolder, 'FaceCamera-imgs', FC_FILES[0])) x, y = np.meshgrid(np.arange(0, img.shape[0]), np.arange(0, img.shape[1]), indexing='ij') condF = (x>=dataF['ROI'][0]) & (x<=(dataF['ROI'][0]+dataF['ROI'][2])) &\ (y>=dataF['ROI'][1]) & (y<=(dataF['ROI'][1]+dataF['ROI'][3])) def Facemotion_frame_generator(): for i in FACEMOTION_SUBSAMPLING: i0 = np.min([i, len(FC_FILES) - 2]) img1 = np.load( os.path.join(args.datafolder, 'FaceCamera-imgs', FC_FILES[i0])).astype( np.uint8)[condF].reshape( dataF['ROI'][2] + 1, dataF['ROI'][3] + 1) img2 = np.load( os.path.join(args.datafolder, 'FaceCamera-imgs', FC_FILES[i0 + 1])).astype( np.uint8)[condF].reshape( dataF['ROI'][2] + 1, dataF['ROI'][3] + 1) yield img2 - img1 FMCI_dataI = DataChunkIterator( data=Facemotion_frame_generator(), maxshape=(None, dataF['ROI'][2] + 1, dataF['ROI'][3] + 1), dtype=np.dtype(np.uint8)) FaceMotion_frames = pynwb.image.ImageSeries( name='Face-Motion', data=FMCI_dataI, unit='NA', timestamps=FC_times[FACEMOTION_SUBSAMPLING]) nwbfile.add_acquisition(FaceMotion_frames) else: print(' /!\ No processed facemotion data found for "%s" /!\ ' % args.datafolder) ################################################# #### Electrophysiological Recording ####### ################################################# if metadata['Electrophy'] and ('Electrophy' in args.modalities): if args.verbose: print('=> Storing electrophysiological signal for "%s" [...]' % args.datafolder) electrophy = pynwb.TimeSeries( name='Electrophysiological-Signal', data=NIdaq_data['analog'][1], starting_time=0., unit='[voltage]', rate=float(metadata['NIdaq-acquisition-frequency'])) nwbfile.add_acquisition(electrophy) ################################################# #### Calcium Imaging ####### ################################################# # see: add_ophys.py script Ca_data = None if metadata['CaImaging']: if args.verbose: print('=> Storing Calcium Imaging signal for "%s" [...]' % args.datafolder) if not hasattr(args, 'CaImaging_folder') or (args.CaImaging_folder == ''): try: args.CaImaging_folder = get_TSeries_folders(args.datafolder) Ca_data = add_ophys( nwbfile, args, metadata=metadata, with_raw_CaImaging=('raw_CaImaging' in args.modalities), with_processed_CaImaging=('processed_CaImaging' in args.modalities), Ca_Imaging_options=Ca_Imaging_options) except BaseException as be: print(be) print(' /!\ No Ca-Imaging data found, /!\ ') print(' -> add them later with "add_ophys.py" \n') ################################################# #### Writing NWB file ####### ################################################# if os.path.isfile(filename): temp = str(tempfile.NamedTemporaryFile().name) + '.nwb' print(""" "%s" already exists ---> moving the file to the temporary file directory as: "%s" [...] """ % (filename, temp)) shutil.move(filename, temp) print('---> done !') io = pynwb.NWBHDF5IO(filename, mode='w', manager=manager) print(""" ---> Creating the NWB file: "%s" """ % filename) io.write(nwbfile, link_data=False) io.close() print('---> done !') if Ca_data is not None: Ca_data.close() # can be closed only after having written return filename
def write_ecephys_nwb(output_path, session_id, session_start_time, stimulus_table_path, invalid_epochs, probes, running_speed_path, session_sync_path, eye_tracking_rig_geometry, eye_dlc_ellipses_path, eye_gaze_mapping_path, pool_size, optotagging_table_path=None, session_metadata=None, **kwargs): nwbfile = pynwb.NWBFile( session_description='Data and metadata for an Ecephys session', identifier=f"{session_id}", session_id=f"{session_id}", session_start_time=session_start_time, institution="Allen Institute for Brain Science") if session_metadata is not None: nwbfile = add_metadata_to_nwbfile(nwbfile, session_metadata) stimulus_columns_to_drop = [ "colorSpace", "depth", "interpolate", "pos", "rgbPedestal", "tex", "texRes", "flipHoriz", "flipVert", "rgb", "signalDots" ] stimulus_table = read_stimulus_table( stimulus_table_path, columns_to_drop=stimulus_columns_to_drop) nwbfile = add_stimulus_timestamps( nwbfile, stimulus_table['start_time'].values ) # TODO: patch until full timestamps are output by stim table module nwbfile = add_stimulus_presentations(nwbfile, stimulus_table) nwbfile = add_invalid_times(nwbfile, invalid_epochs) if optotagging_table_path is not None: optotagging_table = pd.read_csv(optotagging_table_path) nwbfile = add_optotagging_table_to_nwbfile(nwbfile, optotagging_table) nwbfile = add_probewise_data_to_nwbfile(nwbfile, probes) running_speed, raw_running_data = read_running_speed(running_speed_path) add_running_speed_to_nwbfile(nwbfile, running_speed) add_raw_running_data_to_nwbfile(nwbfile, raw_running_data) add_eye_tracking_rig_geometry_data_to_nwbfile(nwbfile, eye_tracking_rig_geometry) # Collect eye tracking/gaze mapping data from files eye_tracking_frame_times = su.get_synchronized_frame_times( session_sync_file=session_sync_path, sync_line_label_keys=Dataset.EYE_TRACKING_KEYS) eye_dlc_tracking_data = read_eye_dlc_tracking_ellipses( Path(eye_dlc_ellipses_path)) if eye_gaze_mapping_path: eye_gaze_data = read_eye_gaze_mappings(Path(eye_gaze_mapping_path)) else: eye_gaze_data = None add_eye_tracking_data_to_nwbfile(nwbfile, eye_tracking_frame_times, eye_dlc_tracking_data, eye_gaze_data) Manifest.safe_make_parent_dirs(output_path) with pynwb.NWBHDF5IO(output_path, mode='w') as io: logging.info(f"writing session nwb file to {output_path}") io.write(nwbfile, cache_spec=True) probes_with_lfp = [p for p in probes if p["lfp"] is not None] probe_outputs = write_probewise_lfp_files(probes_with_lfp, session_id, session_metadata, session_start_time, pool_size=pool_size) return {'nwb_path': output_path, "probe_outputs": probe_outputs}