def create_timeseries_ecephys(self): """ create SpikeEventSeries, ElectricalSeries, Spectrum datatypes within nwbfile>processing>ecephys """ if self.no_probes == 0: return if not self.electrode_table_exist: self.create_electrode_table_ecephys() if 'ecephys' not in self.nwbfile.processing: mod = self.nwbfile.create_processing_module( 'ecephys', 'Processed electrophysiology data of IBL') else: mod = self.nwbfile.get_processing_module('ecephys') for neurodata_type_name, neurodata_type_args_list in self.nwb_metadata[ 'Ecephys']['Ecephys'].items(): data_retrieved_args_list = self._get_data( neurodata_type_args_list ) # list of dicts with keys as argument names for no, neurodata_type_args in enumerate(data_retrieved_args_list): ibl_dataset_name = neurodata_type_args_list[no]['data'] if 'ElectricalSeries' in neurodata_type_name: timestamps_names = self._one_data.data_attrs_dump[ '_iblqc_ephysTimeRms.timestamps'] data_names = self._one_data.data_attrs_dump[ '_iblqc_ephysTimeRms.rms'] for data_idx, data in enumerate( neurodata_type_args['data']): probe_no = [ j for j in range(self.no_probes) if self.nwb_metadata['Probes'][j]['name'] in data_names[data_idx] ][0] if data.shape[1] > self._one_data.data_attrs_dump[ 'electrode_table_length'][probe_no]: if 'channels.rawInd' in self._one_data.loaded_datasets: channel_idx = self._one_data.loaded_datasets[ 'channels.rawInd'][probe_no].data.astype( 'int') else: warnings.warn('could not find channels.rawInd') break else: channel_idx = slice(None) mod.add( ElectricalSeries( name=data_names[data_idx], description=neurodata_type_args['description'], timestamps=neurodata_type_args['timestamps'] [timestamps_names.index(data_names[data_idx])], data=data[:, channel_idx], electrodes=self.probe_dt_region[probe_no])) elif 'Spectrum' in neurodata_type_name: if ibl_dataset_name in '_iblqc_ephysSpectralDensity.power': freqs_names = self._one_data.data_attrs_dump[ '_iblqc_ephysSpectralDensity.freqs'] data_names = self._one_data.data_attrs_dump[ '_iblqc_ephysSpectralDensity.power'] for data_idx, data in enumerate( neurodata_type_args['data']): mod.add( Spectrum(name=data_names[data_idx], frequencies=neurodata_type_args[ 'frequencies'][freqs_names.index( data_names[data_idx])], power=data)) elif 'SpikeEventSeries' in neurodata_type_name: neurodata_type_args.update( dict(electrodes=self.probe_dt_region_all)) mod.add( pynwb.ecephys.SpikeEventSeries(**neurodata_type_args))
def copy_obj(obj_old, nwb_old, nwb_new): """ Creates a copy of obj_old. """ # ElectricalSeries -------------------------------------------------------- if type(obj_old) is ElectricalSeries: nChannels = obj_old.electrodes.table['x'].data.shape[0] elecs_region = nwb_new.electrodes.create_region( name='electrodes', region=np.arange(nChannels).tolist(), description='' ) return ElectricalSeries( name=obj_old.name, data=obj_old.data[:], electrodes=elecs_region, rate=obj_old.rate, description=obj_old.description ) # DynamicTable ------------------------------------------------------------ if type(obj_old) is DynamicTable: return DynamicTable( name=obj_old.name, description=obj_old.description, colnames=obj_old.colnames, columns=obj_old.columns, ) # LFP --------------------------------------------------------------------- if type(obj_old) is LFP: obj = LFP(name=obj_old.name) assert len(obj_old.electrical_series) == 1, ( 'Expected precisely one electrical series, got %i!' % len(obj_old.electrical_series)) els = list(obj_old.electrical_series.values())[0] nChannels = els.data.shape[1] #### # first check for a table among the new file's data_interfaces if els.electrodes.table.name in nwb_new.processing[ 'ecephys'].data_interfaces: LFP_dynamic_table = nwb_new.processing['ecephys'].data_interfaces[ els.electrodes.table.name] else: # othewise use the electrodes as the table LFP_dynamic_table = nwb_new.electrodes #### elecs_region = LFP_dynamic_table.create_region( name='electrodes', region=[i for i in range(nChannels)], description=els.electrodes.description ) obj_ts = obj.create_electrical_series( name=els.name, comments=els.comments, conversion=els.conversion, data=els.data[:], description=els.description, electrodes=elecs_region, rate=els.rate, resolution=els.resolution, starting_time=els.starting_time ) return obj # TimeSeries -------------------------------------------------------------- if type(obj_old) is TimeSeries: return TimeSeries( name=obj_old.name, description=obj_old.description, data=obj_old.data[:], rate=obj_old.rate, resolution=obj_old.resolution, conversion=obj_old.conversion, starting_time=obj_old.starting_time, unit=obj_old.unit ) # DecompositionSeries ----------------------------------------------------- if type(obj_old) is DecompositionSeries: list_columns = [] for item in obj_old.bands.columns: bp = VectorData( name=item.name, description=item.description, data=item.data[:] ) list_columns.append(bp) bandsTable = DynamicTable( name=obj_old.bands.name, description=obj_old.bands.description, columns=list_columns, colnames=obj_old.bands.colnames ) return DecompositionSeries( name=obj_old.name, data=obj_old.data[:], description=obj_old.description, metric=obj_old.metric, unit=obj_old.unit, rate=obj_old.rate, # source_timeseries=lfp, bands=bandsTable, ) # Spectrum ---------------------------------------------------------------- if type(obj_old) is Spectrum: file_elecs = nwb_new.electrodes nChannels = len(file_elecs['x'].data[:]) elecs_region = file_elecs.create_region( name='electrodes', region=np.arange(nChannels).tolist(), description='' ) return Spectrum( name=obj_old.name, frequencies=obj_old.frequencies[:], power=obj_old.power, electrodes=elecs_region )
from ndx_spectrum import Spectrum from datetime import datetime from pynwb import NWBFile, NWBHDF5IO nwb = NWBFile('session_description', 'identifier', datetime.now().astimezone()) spectrum = Spectrum('test_spectrum', frequencies=[1., 2., 3.], power=[1., 2., 3.], phase=[1., 2., 3.]) with NWBHDF5IO('test_spectrum.nwb', 'w') as io: io.write(nwb) with NWBHDF5IO('test_spectrum.nwb', 'r', load_namespaces=True) as io: io.read()
def psd_estimate(src_file, type): """ Estimates Power Spectral Density from signals. Parameters ---------- src_file : str or path Full path to the current NWB file. type : str ElectricalSeries source. 'raw' or 'preprocessed'. """ # Open file with NWBHDF5IO(src_file, mode='r+', load_namespaces=True) as io: nwb = io.read() # Source ElectricalSeries if type == 'raw': # Check if there is ElectricalSeries in acquisition group for i in list(nwb.acquisition.keys()): if isinstance(nwb.acquisition[i], ElectricalSeries): data_obj = nwb.acquisition[i] elif type == 'preprocessed': data_obj = nwb.processing['ecephys'].data_interfaces['LFP'].electrical_series['preprocessed'] nChannels = data_obj.data.shape[1] nSamples = data_obj.data.shape[0] fs = data_obj.rate # Welch - window length as power of 2 and keeps dF~0.05 Hz dF = .05 # Frequency bin size win_len_welch = 2**(np.ceil(np.log2(fs / dF)).astype('int')) # dF = fs/nfft # FFT - using a power of 2 number of samples improves performance nfft = int(2**(np.floor(np.log2(nSamples)).astype('int'))) fx_lim = 200. for ch in np.arange(nChannels): # Iterate over channels trace = data_obj.data[:, ch] fx_w, py_w = sgn.welch(trace, fs=fs, nperseg=win_len_welch) fx_f, py_f = sgn.periodogram(trace, fs=fs, nfft=nfft) # saves PSD up to 200 Hz py_w = py_w[fx_w < fx_lim] fx_w = fx_w[fx_w < fx_lim] py_f = py_f[fx_f < fx_lim] fx_f = fx_f[fx_f < fx_lim] if ch == 0: PY_welch = py_w.reshape(-1, 1) PY_fft = py_f.reshape(-1, 1) else: PY_welch = np.append(PY_welch, py_w.reshape(-1, 1), axis=1) PY_fft = np.append(PY_fft, py_f.reshape(-1, 1), axis=1) # vElectrodes elecs_region = nwb.electrodes.create_region(name='electrodes', region=np.arange(nChannels).tolist(), description='all electrodes') # vPSD shape: ('frequency', 'channel') spectrum_module_welch = Spectrum(name='Spectrum_welch_' + type, frequencies=fx_w, power=PY_welch, source_timeseries=data_obj, electrodes=elecs_region) spectrum_module_fft = Spectrum(name='Spectrum_fft_' + type, frequencies=fx_f, power=PY_fft, source_timeseries=data_obj, electrodes=elecs_region) # Processing module try: # if ecephys module already exists ecephys_module = nwb.processing['ecephys'] except: # creates ecephys ProcessingModule ecephys_module = ProcessingModule(name='ecephys', description='Extracellular electrophysiology data.') # Add module to NWB file nwb.add_processing_module(ecephys_module) print('Created ecephys') ecephys_module.add_data_interface(spectrum_module_welch) ecephys_module.add_data_interface(spectrum_module_fft) io.write(nwb) print('Spectrum_welch_' + type + ' added to file.') print('Spectrum_fft_' + type + ' added to file.')
def copy_obj(obj_old, nwb_old, nwb_new): """ Creates a copy of obj_old. """ obj = None obj_type = type(obj_old).__name__ #ElectricalSeries ---------------------------------------------------------- if obj_type == 'ElectricalSeries': nChannels = obj_old.electrodes.table['x'].data.shape[0] elecs_region = nwb_new.electrodes.create_region( name='electrodes', region=np.arange(nChannels).tolist(), description='') obj = ElectricalSeries(name=obj_old.name, data=obj_old.data[:], electrodes=elecs_region, rate=obj_old.rate, description=obj_old.description) #LFP ----------------------------------------------------------------------- if obj_type == 'LFP': obj = LFP(name=obj_old.name) els_name = list(obj_old.electrical_series.keys())[0] els = obj_old.electrical_series[els_name] nChannels = els.data.shape[1] elecs_region = nwb_new.electrodes.create_region( name='electrodes', region=np.arange(nChannels).tolist(), description='') obj_ts = obj.create_electrical_series(name=els.name, comments=els.comments, conversion=els.conversion, data=els.data[:], description=els.description, electrodes=elecs_region, rate=els.rate, resolution=els.resolution, starting_time=els.starting_time) #TimeSeries ---------------------------------------------------------------- elif obj_type == 'TimeSeries': obj = TimeSeries(name=obj_old.name, description=obj_old.description, data=obj_old.data[:], rate=obj_old.rate, resolution=obj_old.resolution, conversion=obj_old.conversion, starting_time=obj_old.starting_time, unit=obj_old.unit) #DecompositionSeries ------------------------------------------------------- elif obj_type == 'DecompositionSeries': list_columns = [] for item in obj_old.bands.columns: bp = VectorData(name=item.name, description=item.description, data=item.data[:]) list_columns.append(bp) bandsTable = DynamicTable(name=obj_old.bands.name, description=obj_old.bands.description, columns=list_columns, colnames=obj_old.bands.colnames) obj = DecompositionSeries( name=obj_old.name, data=obj_old.data[:], description=obj_old.description, metric=obj_old.metric, unit=obj_old.unit, rate=obj_old.rate, #source_timeseries=lfp, bands=bandsTable, ) #Spectrum ------------------------------------------------------------------ elif obj_type == 'Spectrum': file_elecs = nwb_new.electrodes nChannels = len(file_elecs['x'].data[:]) elecs_region = file_elecs.create_region( name='electrodes', region=np.arange(nChannels).tolist(), description='') obj = Spectrum(name=obj_old.name, frequencies=obj_old.frequencies[:], power=obj_old.power, electrodes=elecs_region) return obj
def copy_obj(obj_old, nwb_old, nwb_new): """ Creates a copy of obj_old. """ # ElectricalSeries -------------------------------------------------------- if type(obj_old) is ElectricalSeries: # If reference electrodes table is bipolar scheme if isinstance(obj_old.electrodes.table, BipolarSchemeTable): bst_old = obj_old.electrodes.table bst_old_df = bst_old.to_dataframe() bst_new = nwb_new.lab_meta_data['ecephys_ext'].bipolar_scheme_table for id, row in bst_old_df.iterrows(): index_anodes = row['anodes'].index.tolist() index_cathodes = row['cathodes'].index.tolist() bst_new.add_row(anodes=index_anodes, cathodes=index_cathodes) bst_new.anodes.table = nwb_new.electrodes bst_new.cathodes.table = nwb_new.electrodes # if there are custom columns new_cols = list(bst_old_df.columns) default_cols = ['anodes', 'cathodes'] [new_cols.remove(col) for col in default_cols] for col in new_cols: col_data = list(bst_old[col].data[:]) bst_new.add_column(name=str(col), description=str(bst_old[col].description), data=col_data) elecs_region = DynamicTableRegion(name='electrodes', data=bst_old_df.index.tolist(), description='desc', table=bst_new) else: region = np.array(obj_old.electrodes.table.id[:])[ obj_old.electrodes.data[:]].tolist() elecs_region = nwb_new.create_electrode_table_region( name='electrodes', region=region, description='') els = ElectricalSeries(name=obj_old.name, data=obj_old.data[:], electrodes=elecs_region, rate=obj_old.rate, description=obj_old.description) return els # DynamicTable ------------------------------------------------------------ if type(obj_old) is DynamicTable: return DynamicTable( name=obj_old.name, description=obj_old.description, colnames=obj_old.colnames, columns=obj_old.columns, ) # LFP --------------------------------------------------------------------- if type(obj_old) is LFP: obj = LFP(name=obj_old.name) assert len(obj_old.electrical_series) == 1, ( 'Expected precisely one electrical series, got %i!' % len(obj_old.electrical_series)) els = list(obj_old.electrical_series.values())[0] #### # first check for a table among the new file's data_interfaces if els.electrodes.table.name in nwb_new.processing[ 'ecephys'].data_interfaces: LFP_dynamic_table = nwb_new.processing['ecephys'].data_interfaces[ els.electrodes.table.name] else: # othewise use the electrodes as the table LFP_dynamic_table = nwb_new.electrodes #### region = np.array( els.electrodes.table.id[:])[els.electrodes.data[:]].tolist() elecs_region = LFP_dynamic_table.create_region( name='electrodes', region=region, description=els.electrodes.description) obj.create_electrical_series(name=els.name, comments=els.comments, conversion=els.conversion, data=els.data[:], description=els.description, electrodes=elecs_region, rate=els.rate, resolution=els.resolution, starting_time=els.starting_time) return obj # TimeSeries -------------------------------------------------------------- if type(obj_old) is TimeSeries: return TimeSeries(name=obj_old.name, description=obj_old.description, data=obj_old.data[:], rate=obj_old.rate, resolution=obj_old.resolution, conversion=obj_old.conversion, starting_time=obj_old.starting_time, unit=obj_old.unit) # DecompositionSeries ----------------------------------------------------- if type(obj_old) is DecompositionSeries: list_columns = [] for item in obj_old.bands.columns: bp = VectorData(name=item.name, description=item.description, data=item.data[:]) list_columns.append(bp) bandsTable = DynamicTable(name=obj_old.bands.name, description=obj_old.bands.description, columns=list_columns, colnames=obj_old.bands.colnames) return DecompositionSeries( name=obj_old.name, data=obj_old.data[:], description=obj_old.description, metric=obj_old.metric, unit=obj_old.unit, rate=obj_old.rate, # source_timeseries=lfp, bands=bandsTable, ) # Spectrum ---------------------------------------------------------------- if type(obj_old) is Spectrum: file_elecs = nwb_new.electrodes nChannels = len(file_elecs['x'].data[:]) elecs_region = file_elecs.create_region( name='electrodes', region=np.arange(nChannels).tolist(), description='') return Spectrum(name=obj_old.name, frequencies=obj_old.frequencies[:], power=obj_old.power, electrodes=elecs_region) # Survey tables ------------------------------------------------------------ if obj_old.neurodata_type == 'SurveyTable': if obj_old.name == 'nrs_survey_table': n_rows = len(obj_old['nrs_pain_intensity_rating'].data) for i in range(n_rows): nrs_survey_table.add_row( **{c: obj_old[c][i] for c in obj_old.colnames}) return nrs_survey_table elif obj_old.name == 'vas_survey_table': n_rows = len(obj_old['vas_pain_intensity_rating'].data) for i in range(n_rows): vas_survey_table.add_row( **{c: obj_old[c][i] for c in obj_old.colnames}) return vas_survey_table elif obj_old.name == 'mpq_survey_table': n_rows = len(obj_old['throbbing'].data) for i in range(n_rows): mpq_survey_table.add_row( **{c: obj_old[c][i] for c in obj_old.colnames}) return mpq_survey_table