예제 #1
0
    def test_append(self):
        proc_mod = self.nwbfile.create_processing_module(name='test_proc_mod',
                                                         description='')
        proc_inter = LFP(name='test_proc_dset')
        proc_mod.add(proc_inter)
        device = self.nwbfile.create_device(name='test_device')
        e_group = self.nwbfile.create_electrode_group(
            name='test_electrode_group',
            description='',
            location='',
            device=device)
        self.nwbfile.add_electrode(x=0.0,
                                   y=0.0,
                                   z=0.0,
                                   imp=np.nan,
                                   location='',
                                   filtering='',
                                   group=e_group)
        electrodes = self.nwbfile.create_electrode_table_region(region=[0],
                                                                description='')
        e_series = ElectricalSeries(
            name='test_es',
            electrodes=electrodes,
            data=np.ones(shape=(100, )),
            rate=10000.0,
        )
        proc_inter.add_electrical_series(e_series)

        with NWBHDF5IO(self.path, mode='w') as io:
            io.write(self.nwbfile, cache_spec=False)

        with NWBHDF5IO(self.path, mode='a') as io:
            nwb = io.read()
            link_electrodes = nwb.processing['test_proc_mod'][
                'LFP'].electrical_series['test_es'].electrodes
            ts2 = ElectricalSeries(name='timeseries2',
                                   data=[4., 5., 6.],
                                   rate=1.0,
                                   electrodes=link_electrodes)
            nwb.add_acquisition(ts2)
            io.write(nwb)  # also attempt to write same spec again
            self.assertIs(
                nwb.processing['test_proc_mod']
                ['LFP'].electrical_series['test_es'].electrodes,
                nwb.acquisition['timeseries2'].electrodes)

        with NWBHDF5IO(self.path, mode='r') as io:
            nwb = io.read()
            np.testing.assert_equal(nwb.acquisition['timeseries2'].data[:],
                                    ts2.data)
            self.assertIs(
                nwb.processing['test_proc_mod']
                ['LFP'].electrical_series['test_es'].electrodes,
                nwb.acquisition['timeseries2'].electrodes)
            errors = validate(io)
            for e in errors:
                print('ERROR', e)
예제 #2
0
 def test_add_electrical_series(self):
     lfp = LFP()
     table = make_electrode_table()
     region = DynamicTableRegion('electrodes', [0, 2],
                                 'the first and third electrodes', table)
     eS = ElectricalSeries('test_eS', [0, 1, 2, 3],
                           region,
                           timestamps=[0.1, 0.2, 0.3, 0.4])
     lfp.add_electrical_series(eS)
     self.assertEqual(lfp.electrical_series.get('test_eS'), eS)
예제 #3
0
    def test_append(self):

        FILENAME = 'test_append.nwb'

        nwb = NWBFile(session_description='hi',
                      identifier='hi',
                      session_start_time=datetime(1970,
                                                  1,
                                                  1,
                                                  12,
                                                  tzinfo=tzutc()))
        proc_mod = nwb.create_processing_module(name='test_proc_mod',
                                                description='')
        proc_inter = LFP(name='test_proc_dset')
        proc_mod.add_data_interface(proc_inter)
        device = nwb.create_device(name='test_device')
        e_group = nwb.create_electrode_group(name='test_electrode_group',
                                             description='',
                                             location='',
                                             device=device)
        nwb.add_electrode(x=0.0,
                          y=0.0,
                          z=0.0,
                          imp=np.nan,
                          location='',
                          filtering='',
                          group=e_group)
        electrodes = nwb.create_electrode_table_region(region=[0],
                                                       description='')
        e_series = ElectricalSeries(
            name='test_device',
            electrodes=electrodes,
            data=np.ones(shape=(100, )),
            rate=10000.0,
        )
        proc_inter.add_electrical_series(e_series)

        with NWBHDF5IO(FILENAME, mode='w') as io:
            io.write(nwb)

        with NWBHDF5IO(FILENAME, mode='a') as io:
            nwb = io.read()
            elec = nwb.modules['test_proc_mod']['LFP'].electrical_series[
                'test_device'].electrodes
            ts2 = ElectricalSeries(name='timeseries2',
                                   data=[4, 5, 6],
                                   rate=1.0,
                                   electrodes=elec)
            nwb.add_acquisition(ts2)
            io.write(nwb)

        with NWBHDF5IO(FILENAME, mode='r') as io:
            nwb = io.read()
            np.testing.assert_equal(nwb.acquisition['timeseries2'].data[:],
                                    ts2.data)
예제 #4
0
 def test_add_electrical_series(self):
     lfp = LFP()  # noqa: F405
     dev1 = Device('dev1')  # noqa: F405
     group = ElectrodeGroup(  # noqa: F405, F841
         'tetrode1', 'tetrode description', 'tetrode location', dev1)
     table = make_electrode_table()
     region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table)
     eS = ElectricalSeries(  # noqa: F405
         'test_eS', [0, 1, 2, 3], region, timestamps=[0.1, 0.2, 0.3, 0.4])
     lfp.add_electrical_series(eS)
     self.assertEqual(lfp.electrical_series.get('test_eS'), eS)
     self.assertEqual(lfp['test_eS'], lfp.electrical_series.get('test_eS'))
예제 #5
0
def chang2nwb(blockpath, out_file_path=None, save_to_file=False, htk_config=None):
    """
    Parameters
    ----------
    blockpath: str
    out_file_path: None | str
        if None, output = [blockpath]/[blockname].nwb
    save_to_file : bool
        If True, saves to file. If False, just returns nwbfile object
    htk_config : dict
        Dictionary cotaining HTK conversion paths and options. Example:
        {
            ecephys_path: 'path_to/ecephys_htk_files',
            ecephys_type: 'raw', 'preprocessed' or 'high_gamma',
            analog_path: 'path_to/analog_htk_files',
            anin1: {present: True, name: 'microphone', type: 'acquisition'},
            anin2: {present: True, name: 'speaker1', type: 'stimulus'},
            anin3: {present: False, name: 'speaker2', type: 'stimulus'},
            anin4: {present: False, name: 'custom', type: 'acquisition'},
            metadata: metadata,
            electrodes_file: electrodes_file,
            bipolar_file: bipolar_file
        }

    Returns
    -------
    """

    metadata = {}

    if htk_config is None:
        blockpath = Path(blockpath)
    else:
        blockpath = Path(htk_config['ecephys_path'])
        metadata = htk_config['metadata']
    blockname = blockpath.parent.name
    subject_id = blockpath.parent.parent.name[2:]

    if out_file_path is None:
        out_file_path = blockpath.resolve().parent / ''.join(['EC', subject_id, '_', blockname, '.nwb'])

    # file paths
    ecog_path = blockpath
    anin_path = htk_config['analog_path']
    bad_time_file = path.join(blockpath, 'Artifacts', 'badTimeSegments.mat')

    # Create the NWB file object
    nwbfile_dict = {
        'session_description': blockname,
        'identifier': blockname,
        'session_start_time': datetime.now().astimezone(),
        'institution': 'University of California, San Francisco',
        'lab': 'Chang Lab'
    }
    if 'NWBFile' in metadata:
        nwbfile_dict.update(metadata['NWBFile'])
    nwbfile = NWBFile(**nwbfile_dict)

    # Read electrophysiology data from HTK files
    print('reading htk acquisition...', flush=True)
    ecog_rate, data = readhtks(ecog_path)
    data = data.squeeze()
    print('done', flush=True)

    # Get electrodes info from mat file
    if htk_config['electrodes_file'] is not None:
        nwbfile = elecs_to_electrode_table(
            nwbfile=nwbfile,
            elecspath=htk_config['electrodes_file'],
        )
        n_electrodes = nwbfile.electrodes[:].shape[0]
        all_elecs = list(range(n_electrodes))
        elecs_region = nwbfile.create_electrode_table_region(
            region=all_elecs,
            description='ECoG electrodes on brain'
        )
    else:
        ecephys_dict = {
            'Device': [{'name': 'auto_device'}],
            'ElectricalSeries': [{'name': 'ECoG', 'description': 'description'}],
            'ElectrodeGroup': [{'name': 'auto_group', 'description': 'auto_group',
                                'location': 'location', 'device': 'auto_device'}]
        }
        if 'Ecephys' in metadata:
            ecephys_dict.update(metadata['Ecephys'])

        # Create devices
        for dev in ecephys_dict['Device']:
            device = nwbfile.create_device(dev['name'])

        # Electrode groups
        for el_grp in ecephys_dict['ElectrodeGroup']:
            device = nwbfile.devices[el_grp['device']]
            electrode_group = nwbfile.create_electrode_group(
                name=el_grp['name'],
                description=el_grp['description'],
                location=el_grp['location'],
                device=device
            )

        # Electrodes table
        n_electrodes = data.shape[1]
        nwbfile.add_electrode_column('label', 'label of electrode')
        nwbfile.add_electrode_column('bad', 'electrode identified as too noisy')
        nwbfile.add_electrode_column('x_warped', 'x warped onto cvs_avg35_inMNI152')
        nwbfile.add_electrode_column('y_warped', 'y warped onto cvs_avg35_inMNI152')
        nwbfile.add_electrode_column('z_warped', 'z warped onto cvs_avg35_inMNI152')
        nwbfile.add_electrode_column('null', 'if not connected to real electrode')
        bad_elecs_inds = get_bad_elecs(blockpath)
        for elec_counter in range(n_electrodes):
            bad = elec_counter in bad_elecs_inds
            nwbfile.add_electrode(
                id=elec_counter,
                x=np.nan,
                y=np.nan,
                z=np.nan,
                imp=np.nan,
                x_warped=np.nan,
                y_warped=np.nan,
                z_warped=np.nan,
                location='',
                filtering='none',
                group=electrode_group,
                label='',
                bad=bad,
                null=False,
            )

        all_elecs = list(range(n_electrodes))
        elecs_region = nwbfile.create_electrode_table_region(
            region=all_elecs,
            description='ECoG electrodes on brain'
        )

    # Get Bipolar table from file
    if htk_config['bipolar_file'] is not None:
        df = pd.read_csv(htk_config['bipolar_file'], index_col='id', sep='\t')

        # Create bipolar scheme table
        bipolar_scheme_table = BipolarSchemeTable(
            name='bipolar_scheme_table',
            description='desc'
        )

        # Columns for bipolar scheme - all anodes and cathodes within the same
        # bipolar row are considered to have the same group and location
        bipolar_scheme_table.add_column(
            name='group_name',
            description='electrode group name'
        )
        bipolar_scheme_table.add_column(
            name='location',
            description='electrode location'
        )

        # Iterate over anode / cathode rows
        for i, r in df.iterrows():
            if isinstance(r['anodes'], str):
                anodes = [int(a) for a in r['anodes'].split(',')]
            else:
                anodes = [int(r['anodes'])]
            if isinstance(r['cathodes'], str):
                cathodes = [int(a) for a in r['cathodes'].split(',')]
            else:
                cathodes = [int(r['cathodes'])]
            bipolar_scheme_table.add_row(
                anodes=anodes,
                cathodes=cathodes,
                group_name=nwbfile.electrodes['group_name'][anodes[0]],
                location=nwbfile.electrodes['location'][anodes[0]]
            )

        bipolar_scheme_table.anodes.table = nwbfile.electrodes
        bipolar_scheme_table.cathodes.table = nwbfile.electrodes

        # Creates bipolar table region
        elecs_region = DynamicTableRegion(
            name='electrodes',
            data=np.arange(0, df.shape[0]),
            description='desc',
            table=bipolar_scheme_table
        )

        ecephys_ext = EcephysExt(name='ecephys_ext')
        ecephys_ext.bipolar_scheme_table = bipolar_scheme_table
        nwbfile.add_lab_meta_data(ecephys_ext)

    # Stores HTK electrophysiology data as raw, preprocessed or high gamma
    if htk_config['ecephys_type'] == 'raw':
        ecog_es = ElectricalSeries(name='ECoG',
                                   data=H5DataIO(data[:, 0:n_electrodes], compression='gzip'),
                                   electrodes=elecs_region,
                                   rate=ecog_rate,
                                   description='all Wav data')
        nwbfile.add_acquisition(ecog_es)
    elif htk_config['ecephys_type'] == 'preprocessed':
        lfp = LFP()
        ecog_es = ElectricalSeries(name='preprocessed',
                                   data=H5DataIO(data[:, 0:n_electrodes], compression='gzip'),
                                   electrodes=elecs_region,
                                   rate=ecog_rate,
                                   description='all Wav data')
        lfp.add_electrical_series(ecog_es)
        # Creates the ecephys processing module
        ecephys_module = nwbfile.create_processing_module(
            name='ecephys',
            description='preprocessed electrophysiology data'
        )
        ecephys_module.add_data_interface(lfp)
    elif htk_config['ecephys_type'] == 'high_gamma':
        ecog_es = ElectricalSeries(name='high_gamma',
                                   data=H5DataIO(data[:, 0:n_electrodes], compression='gzip'),
                                   electrodes=elecs_region,
                                   rate=ecog_rate,
                                   description='all Wav data')
        # Creates the ecephys processing module
        ecephys_module = nwbfile.create_processing_module(
            name='ecephys',
            description='preprocessed electrophysiology data'
        )
        ecephys_module.add_data_interface(ecog_es)

    # Add ANIN 1
    if htk_config['anin1']['present']:
        fs, data = get_analog(anin_path, 1)
        ts = TimeSeries(
            name=htk_config['anin1']['name'],
            data=data,
            unit='NA',
            rate=fs,
        )
        if htk_config['anin1']['type'] == 'acquisition':
            nwbfile.add_acquisition(ts)
        else:
            nwbfile.add_stimulus(ts)
        print('ANIN1 saved with name "', htk_config['anin1']['name'], '" in ',
              htk_config['anin1']['type'])

    # Add ANIN 2
    if htk_config['anin2']['present']:
        fs, data = get_analog(anin_path, 2)
        ts = TimeSeries(
            name=htk_config['anin2']['name'],
            data=data,
            unit='NA',
            rate=fs,
        )
        if htk_config['anin2']['type'] == 'acquisition':
            nwbfile.add_acquisition(ts)
        else:
            nwbfile.add_stimulus(ts)
        print('ANIN2 saved with name "', htk_config['anin2']['name'], '" in ',
              htk_config['anin2']['type'])

    # Add ANIN 3
    if htk_config['anin3']['present']:
        fs, data = get_analog(anin_path, 3)
        ts = TimeSeries(
            name=htk_config['anin3']['name'],
            data=data,
            unit='NA',
            rate=fs,
        )
        if htk_config['anin3']['type'] == 'acquisition':
            nwbfile.add_acquisition(ts)
        else:
            nwbfile.add_stimulus(ts)
        print('ANIN3 saved with name "', htk_config['anin3']['name'], '" in ',
              htk_config['anin3']['type'])

    # Add ANIN 4
    if htk_config['anin4']['present']:
        fs, data = get_analog(anin_path, 4)
        ts = TimeSeries(
            name=htk_config['anin4']['name'],
            data=data,
            unit='NA',
            rate=fs,
        )
        if htk_config['anin4']['type'] == 'acquisition':
            nwbfile.add_acquisition(ts)
        else:
            nwbfile.add_stimulus(ts)
        print('ANIN4 saved with name "', htk_config['anin4']['name'], '" in ',
              htk_config['anin4']['type'])

    # Add bad time segments
    if os.path.exists(bad_time_file) and os.stat(bad_time_file).st_size:
        bad_time = sio.loadmat(bad_time_file)['badTimeSegments']
        for row in bad_time:
            nwbfile.add_invalid_time_interval(start_time=row[0],
                                              stop_time=row[1],
                                              tags=('ECoG artifact',),
                                              timeseries=ecog_es)

    # Subject
    subject_dict = {'subject_id': subject_id}
    if 'Subject' in metadata:
        subject_dict.update(metadata['Subject'])
    subject = ECoGSubject(**subject_dict)
    nwbfile.subject = subject

    if save_to_file:
        print('Saving HTK content to NWB file...')
        # Export the NWB file
        with NWBHDF5IO(str(out_file_path), manager=manager, mode='w') as io:
            io.write(nwbfile)

        # read check
        with NWBHDF5IO(str(out_file_path), manager=manager, mode='r') as io:
            io.read()
        print('NWB file saved: ', str(out_file_path))

    return nwbfile, out_file_path, subject_id, blockname
예제 #6
0
파일: nwb.py 프로젝트: elijahc/emu
def nlx_to_nwb(nev_fp,
               ncs_paths,
               desc='',
               trim_buffer=60 * 10,
               practice_incl=False,
               electrode_locations=None):
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        ncs = nlx.load_ncs(ncs_paths.pop(0), load_time=False)
        nev = nlx.load_nev(nev_fp)

    uuid = nev['header']['SessionUUID']
    start_time = pd.to_datetime(ncs['timestamp'][0], unit='us',
                                utc=True).to_pydatetime()
    start_time_sec = start_time.timestamp()
    nwbfile = NWBFile(session_description=desc,
                      identifier=uuid,
                      session_start_time=start_time)

    dev = nwbfile.create_device(name='Neuralynx')
    # ts = ncs_to_timeseries(ncs)

    if electrode_locations is not None:
        add_electrodes(nwbfile, electrode_locations, dev)

    ev = pd.DataFrame.from_records(nev_as_records(nev), index='TimeStamp')

    ev['EventString'] = [str(v, 'utf-8') for v in ev.EventString.values]
    ev['time'] = pd.to_datetime(ev.index.values, unit='us', utc=True)
    ev = ev[ev.ttl == 1]
    label_blockstart(ev)
    n_blocks = int(len(ev[ev.label == 'block_start']) / 2)
    n_ttls = int(n_blocks * 17)
    if practice_incl:
        n_ttls -= 5

    # ev['TimeStamp'] = ev.index.values/10**6 - start_time.timestamp()
    ev_ts = np.array([t.timestamp() for t in ev.time]) - start_time.timestamp()
    #     start_stop = ev[ev.EventString.isin(['Starting Recording','Stopping Recording'])]

    events = AnnotationSeries(name='ttl',
                              data=ev.label.values[:n_ttls],
                              timestamps=ev_ts[:n_ttls])
    data_time_len = events.timestamps[-1] + trim_buffer

    nwbfile.add_acquisition(events)

    lfp = LFP(name='LFP')
    nwbfile.add_acquisition(ncs_to_timeseries(ncs, data_time_len))

    for ch, ts_kwargs in iter_ncs_to_timeseries(ncs_paths, data_time_len):
        if electrode_locations is not None:
            # ts_kwargs['electrodes']=electrode_table_region
            try:
                electrode_table_region = nwbfile.create_electrode_table_region(
                    [ch], 'Channel')
                row = electrode_locations.where(
                    electrode_locations.chan_num == ch + 1).dropna().iloc[0]
                ts_kwargs['name'] = 'wire_{}_electrode_{}'.format(
                    int(row.wire_num), int(row.electrode))
                ts_kwargs['electrodes'] = electrode_table_region
                ts = ElectricalSeries(**ts_kwargs)
                if ts.name not in lfp.electrical_series.keys():
                    lfp.add_electrical_series(ts)
            except IndexError:
                pass
        else:
            ts = TimeSeries(**ts_kwargs)
            if ts.name not in nwbfile.acquisition.keys():
                nwbfile.add_acquisition(ts)

            else:
                print('Failed to load: ', ts.name)

        ecephys_module = ProcessingModule(
            name='ecephys',
            description='preprocessed extracellular electrophysiology')
        nwbfile.create_processing_module(
            name='ecephys',
            description='preprocessed extracellular electrophysiology')
        nwbfile.processing['ecephys'].add(lfp)

    return nwbfile
예제 #7
0
def ncs_to_nwb(
    ncs_paths,
    desc='',
    nev_path=None,
    electrode_locations=None,
    lab='Thompson Lab',
    institution='University of Colorado Anschutz',
    trim_buffer=60 * 10,
):
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        first_ncs = ncs_paths.pop(0)
        ncs = nlx.load_ncs(first_ncs, load_time=False)

    uuid = ncs['header']['SessionUUID']
    start_time = pd.to_datetime(ncs['timestamp'][0], unit='us',
                                utc=True).to_pydatetime()
    # start_time = ncs['header']['TimeCreated_dt']
    start_time_sec = start_time.timestamp()
    nwbfile = NWBFile(session_description=desc,
                      identifier=uuid,
                      session_id=uuid,
                      lab=lab,
                      institution=institution,
                      session_start_time=start_time)

    dev = nwbfile.create_device(name='Neuralynx')
    # ts = ncs_to_timeseries(ncs)

    if electrode_locations is not None:
        add_electrodes(nwbfile, electrode_locations, dev)

    if nev_path is not None:
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            nev = load_nev(nev_path)
            if len(nev['events']) > 0:
                ev = pd.DataFrame.from_records(nev_as_records(nev),
                                               index='TimeStamp')

                ev['EventString'] = [
                    str(v, 'utf-8') for v in ev.EventString.values
                ]
                ev['time'] = pd.to_datetime(ev.index.values,
                                            unit='us',
                                            utc=True)
                ev = ev[ev.ttl == 1]
                ev_ts = np.array([t.timestamp()
                                  for t in ev.time]) - start_time.timestamp()
                data_time_len = ev_ts[-1] + trim_buffer
    else:
        data_time_len = len(ncs['data']) / int(ncs['sampling_rate'])

    ncs_paths.append(first_ncs)
    lfp = LFP(name='LFP')

    for ch, ts_kwargs in iter_ncs_to_timeseries(ncs_paths, data_time_len):
        if electrode_locations is not None:
            # ts_kwargs['electrodes']=electrode_table_region
            try:
                electrode_table_region = nwbfile.create_electrode_table_region(
                    [ch], 'Channel')
                row = electrode_locations.where(
                    electrode_locations.chan_num == ch + 1).dropna().iloc[0]
                ts_kwargs['name'] = 'wire_{}_electrode_{}'.format(
                    int(row.wire_num), int(row.electrode))
                ts_kwargs['electrodes'] = electrode_table_region
                ts = ElectricalSeries(**ts_kwargs)
                if ts.name not in lfp.electrical_series.keys():
                    lfp.add_electrical_series(ts)
                else:
                    print('Failed to load: ', ts.name)
            except IndexError:
                pass
        else:
            ts = TimeSeries(**ts_kwargs)
            if ts.name not in nwbfile.acquisition.keys():
                nwbfile.add_acquisition(ts)
            else:
                print('Failed to load: ', ts.name)

    nwbfile.create_processing_module(
        name='ecephys',
        description='preprocessed extracellular electrophysiology')
    nwbfile.processing['ecephys'].add(lfp)

    return nwbfile