Beispiel #1
0
    def test_access_group_after_io(self):
        """
        Motivated by #739
        """
        nwbfile = NWBFile('a', 'b', datetime.now(tzlocal()))
        device = nwbfile.create_device('a')
        elecgrp = nwbfile.create_electrode_group('a', 'b', device=device, location='a')
        nwbfile.add_electrode(np.nan, np.nan, np.nan, np.nan, 'a', 'a', elecgrp, id=0)

        with NWBHDF5IO('electrodes_mwe.nwb', 'w') as io:
            io.write(nwbfile)

        with NWBHDF5IO('electrodes_mwe.nwb', 'a') as io:
            nwbfile_i = io.read()
            for aa, bb in zip(nwbfile_i.electrodes['group'][:], nwbfile.electrodes['group'][:]):
                self.assertEqual(aa.name, bb.name)

        for i in range(4):
            nwbfile.add_electrode(np.nan, np.nan, np.nan, np.nan, 'a', 'a', elecgrp, id=i + 1)

        with NWBHDF5IO('electrodes_mwe.nwb', 'w') as io:
            io.write(nwbfile)

        with NWBHDF5IO('electrodes_mwe.nwb', 'a') as io:
            nwbfile_i = io.read()
            for aa, bb in zip(nwbfile_i.electrodes['group'][:], nwbfile.electrodes['group'][:]):
                self.assertEqual(aa.name, bb.name)

        remove_test_file("electrodes_mwe.nwb")
Beispiel #2
0
 def test_create_electrode_group_invalid_index(self):
     """
     Test the case where the user creates an electrode table region with
     indexes that are out of range of the amount of electrodes added.
     """
     nwbfile = NWBFile('a', 'b', 'c', datetime.now())
     device = nwbfile.create_device('a', 'b')
     elecgrp = nwbfile.create_electrode_group('a',
                                              'b',
                                              'c',
                                              device=device,
                                              location='a')
     for i in range(4):
         nwbfile.add_electrode(i,
                               np.nan,
                               np.nan,
                               np.nan,
                               np.nan,
                               group=elecgrp,
                               location='a',
                               filtering='a',
                               description='a')
     with self.assertRaises(IndexError) as err:
         nwbfile.create_electrode_table_region(list(range(6)), 'test')
     self.assertTrue('out of range' in str(err.exception))
    def setUp(self):
        nwbfile = NWBFile(
            'my first synthetic recording',
            'EXAMPLE_ID',
            datetime.now(tzlocal()),
            experimenter='Dr. Matthew Douglass',
            lab='Vision Neuroscience Laboratory',
            institution='University of Middle Earth at the Shire',
            experiment_description=
            'We recorded from macaque monkeys during memory-guided saccade task',
            session_id='LONELYMTL')

        device = nwbfile.create_device(name='trodes_rig123')

        electrode_group = nwbfile.create_electrode_group(
            name='tetrode1',
            description='an example tetrode',
            location='somewhere in the hippocampus',
            device=device)

        for idx in [1, 2, 3, 4]:
            nwbfile.add_electrode(id=idx,
                                  x=1.0,
                                  y=2.0,
                                  z=3.0,
                                  imp=float(-idx),
                                  location='CA1',
                                  filtering='none',
                                  group=electrode_group)

        electrode_table_region = nwbfile.create_electrode_table_region(
            [0, 2], 'the first and third electrodes')

        self.electrodes = electrode_table_region
Beispiel #4
0
def test_io():
    nwbfile = NWBFile('description', 'id', datetime.now().astimezone())
    device = nwbfile.create_device('device_test')
    group = nwbfile.create_electrode_group(name='electrodes',
                                           description='label',
                                           device=device,
                                           location='brain')

    for i in range(4):
        nwbfile.add_electrode(x=float(i),
                              y=float(i),
                              z=float(i),
                              imp=np.nan,
                              location='',
                              filtering='',
                              group=group)

    bipolar_scheme_table = BipolarSchemeTable(name='bipolar_scheme_table',
                                              description='desc')

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

    bipolar_scheme_table.add_row(anodes=[0], cathodes=[1])
    bipolar_scheme_table.add_row(anodes=[0, 1], cathodes=[2, 3])

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

    st = StimTable(
        name='stimtable',
        description='stimulation parameters',
        # bipolar_table=bipolar_scheme_table
    )

    # calling this before `add_run` obviates bipolar_table=bipolar_scheme_table above.
    # You can add it to the NWBFile later, but you'll need to specify bipolar_table manually

    nwbfile.add_time_intervals(st)

    frequencies = [10., 10.]
    amplitudes = [5., 5.]
    pulse_widths = [2., 3.]

    for i in range(2):
        st.add_run(start_time=np.nan,
                   stop_time=np.nan,
                   frequency=frequencies[i],
                   amplitude=amplitudes[i],
                   pulse_width=pulse_widths[i],
                   bipolar_pair=i)

    with NWBHDF5IO('test_file.nwb', 'w') as io:
        io.write(nwbfile)

    # Make a 300 timepoint waveform time series for 2 electrodes (one
    # cathode, and one anode).
    current_data = np.random.randn(300, 2)
    def write_recording(recording, save_path, acquisition_name='ElectricalSeries'):
        assert HAVE_NWB, "To use the Nwb extractors, install pynwb: \n\n pip install pynwb\n\n"
        M = recording.get_num_channels()

        nwbfile = NWBFile(
            session_description='',
            identifier='',
            session_start_time=datetime.now(),
        )
        device = nwbfile.create_device(name='device_name')
        eg_name = 'electrode_group_name'
        eg_description = "electrode_group_description"
        eg_location = "electrode_group_location"

        electrode_group = nwbfile.create_electrode_group(
            name=eg_name,
            location=eg_location,
            device=device,
            description=eg_description
        )

        for m in range(M):
            location = recording.get_channel_property(m, 'location')
            impedence = -1.0
            while len(location) < 3:
                location = np.append(location, [0])
            nwbfile.add_electrode(
                id=m,
                x=float(location[0]), y=float(location[1]), z=float(location[2]),
                imp=impedence,
                location='electrode_location',
                filtering='none',
                group=electrode_group,
            )
        electrode_table_region = nwbfile.create_electrode_table_region(
            list(range(M)),
            'electrode_table_region'
        )

        rate = recording.get_sampling_frequency()
        ephys_data = recording.get_traces().T

        ephys_ts = ElectricalSeries(
            name=acquisition_name,
            data=ephys_data,
            electrodes=electrode_table_region,
            starting_time=recording.frame_to_time(0),
            rate=rate,
            resolution=1e-6,
            comments='Generated from SpikeInterface::NwbRecordingExtractor',
            description='acquisition_description'
        )
        nwbfile.add_acquisition(ephys_ts)

        if os.path.exists(save_path):
            os.remove(save_path)
        with NWBHDF5IO(save_path, 'w') as io:
            io.write(nwbfile)
Beispiel #6
0
    def setUp(self):
        nwbfile = NWBFile(
            "my first synthetic recording",
            "EXAMPLE_ID",
            datetime.now(tzlocal()),
            experimenter="Dr. Matthew Douglass",
            lab="Vision Neuroscience Laboratory",
            institution="University of Middle Earth at the Shire",
            experiment_description=
            "We recorded from macaque monkeys during memory-guided saccade task",
            session_id="LONELYMTL",
        )

        device = nwbfile.create_device(name="trodes_rig123")

        electrode_group = nwbfile.create_electrode_group(
            name="tetrode1",
            description="an example tetrode",
            location="somewhere in the hippocampus",
            device=device,
        )

        for idx in [1, 2, 3, 4]:
            nwbfile.add_electrode(
                id=idx,
                x=1.0,
                y=2.0,
                z=3.0,
                imp=float(-idx),
                location="CA1",
                filtering="none",
                group=electrode_group,
            )

        electrode_table_region = nwbfile.create_electrode_table_region(
            [0, 2], "the first and third electrodes")

        self.electrodes = electrode_table_region

        rate = 10.0
        np.random.seed(1234)
        data_len = 1000
        ephys_data = np.random.rand(data_len * 2).reshape((data_len, 2))
        ephys_timestamps = np.arange(data_len) / rate

        self.ephys_ts = ElectricalSeries(
            "test_ephys_data",
            ephys_data,
            self.electrodes,
            timestamps=ephys_timestamps,
            resolution=0.001,
            description="Random numbers generated with numpy.random.rand",
        )

        self.lfp = LFP(electrical_series=self.ephys_ts, name="LFP data")
Beispiel #7
0
def test_ext():
    nwbfile = NWBFile('description', 'id', datetime.now().astimezone())

    device = nwbfile.create_device('device_name')

    electrode_group = nwbfile.create_electrode_group('electrode_group',
                                                     'desc',
                                                     'loc',
                                                     device=device)

    for i in np.arange(20.):
        nwbfile.add_electrode(i, i, i, np.nan, 'loc', 'filt', electrode_group)

    bipolar_scheme = DynamicTable(name='bipolar_scheme', description='desc')
    bipolar_scheme.add_column(name='anode',
                              description='desc',
                              index=True,
                              table=nwbfile.electrodes)
    bipolar_scheme.add_column(name='cathode',
                              description='desc',
                              index=True,
                              table=nwbfile.electrodes)

    bipolar_scheme.add_row(anode=[0], cathode=[1])
    bipolar_scheme.add_row(anode=[0, 1], cathode=[2, 3])
    bipolar_scheme.add_row(anode=[0, 1], cathode=[2])

    ecephys_ext = EcephysExt(bipolar_scheme=bipolar_scheme)
    nwbfile.add_lab_meta_data(ecephys_ext)

    bipolar_scheme_region = DynamicTableRegion(
        name='electrodes',
        data=np.arange(0, 3),
        description='desc',
        table=nwbfile.lab_meta_data['extracellular_ephys_extensions'].
        bipolar_scheme)

    ec_series = ElectricalSeries(name='test_ec_series',
                                 description='desc',
                                 data=np.random.rand(100, 3),
                                 rate=1000.,
                                 electrodes=bipolar_scheme_region)

    nwbfile.add_acquisition(ec_series)

    with NWBHDF5IO('test_nwb.nwb', 'w') as io:
        io.write(nwbfile)

    with NWBHDF5IO('test_nwb.nwb', 'r', load_namespaces=True) as io:
        nwbfile = io.read()
        assert_array_equal(
            nwbfile.acquisition['test_ec_series'].electrodes.table['anode'][2]
            ['x'], [0., 1.])

    os.remove('test_nwb.nwb')
Beispiel #8
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)
Beispiel #9
0
    def create(cls, nwb_content: NWBFile, fl_electrode: FlElectrode):
        validate_parameters_not_none(__name__, fl_electrode.electrode_group,
                                     fl_electrode.electrode_id)

        nwb_content.add_electrode(x=0.0,
                                  y=0.0,
                                  z=0.0,
                                  imp=0.0,
                                  location='None',
                                  filtering='None',
                                  group=fl_electrode.electrode_group,
                                  id=fl_electrode.electrode_id)
Beispiel #10
0
 def test_create_electrode_group_invalid_index(self):
     """
     Test the case where the user creates an electrode table region with
     indexes that are out of range of the amount of electrodes added.
     """
     nwbfile = NWBFile('a', 'b', datetime.now(tzlocal()))
     device = nwbfile.create_device('a')
     elecgrp = nwbfile.create_electrode_group('a', 'b', device=device, location='a')
     for i in range(4):
         nwbfile.add_electrode(np.nan, np.nan, np.nan, np.nan, 'a', 'a', elecgrp, id=i)
     with self.assertRaises(IndexError):
         nwbfile.create_electrode_table_region(list(range(6)), 'test')
Beispiel #11
0
class TestAppend(TestCase):

    def setUp(self):
        self.nwbfile = NWBFile(session_description='hi',
                               identifier='hi',
                               session_start_time=datetime(1970, 1, 1, 12, tzinfo=tzutc()))
        self.path = "test_append.nwb"

    def tearDown(self):
        remove_test_file(self.path)

    def test_append(self):
        proc_mod = self.nwbfile.create_processing_module(name='test_proc_mod', description='')
        proc_inter = LFP(name='LFP')
        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)
Beispiel #12
0
class My_NWB_Writer:
    def __init__(self, filename, name, description, session_id='MyHome'):
        self.io = NWBHDF5IO(filename, 'w')

        self.nwbfile = NWBFile(name,
                               name.replace(' ', '_'),
                               datetime.now(tzlocal()),
                               experimenter='Francesco Cavarretta',
                               lab='Jaeger lab',
                               institution='Emory University',
                               experiment_description=description,
                               session_id=session_id)

        self.device = self.nwbfile.create_device(name='ThalamicRelayCell')

        self.electrode_group = self.nwbfile.create_electrode_group(
            'ThalamicRelayCell_000',
            description=
            "Thalamic Relay Cell somatic traces, Mouselight Morphologies",
            location="VM Thalamus",
            device=self.device)

        self.nwbfile.add_electrode(id=1,
                                   imp=-1.0,
                                   x=0.0,
                                   y=0.0,
                                   z=0.0,
                                   location="VM Thalamus",
                                   filtering='none',
                                   group=self.electrode_group)

        self.electrode_table_region = self.nwbfile.create_electrode_table_region(
            [0], 'an electrode')

    def write(self, name, t, v, description, comments=""):
        self.nwbfile.add_acquisition(
            ElectricalSeries(name,
                             v,
                             self.electrode_table_region,
                             timestamps=t,
                             resolution=0.001,
                             comments=comments,
                             description=description))

    def close(self):
        self.io.write(self.nwbfile)
        self.io.close()
Beispiel #13
0
    def setUp(self):
        nwbfile = NWBFile(
            "my first synthetic recording",
            "EXAMPLE_ID",
            datetime.now(tzlocal()),
            experimenter="Dr. Matthew Douglass",
            lab="Vision Neuroscience Laboratory",
            institution="University of Middle Earth at the Shire",
            experiment_description=
            "We recorded from macaque monkeys during memory-guided saccade task",
            session_id="LONELYMTL",
        )

        device = nwbfile.create_device(name="trodes_rig123")

        electrode_group = nwbfile.create_electrode_group(
            name="tetrode1",
            description="an example tetrode",
            location="somewhere in the hippocampus",
            device=device,
        )

        for idx in [1, 2, 3, 4]:
            nwbfile.add_electrode(
                id=idx,
                x=1.0,
                y=2.0,
                z=3.0,
                imp=float(-idx),
                location="CA1",
                filtering="none",
                group=electrode_group,
            )

        electrode_table_region = nwbfile.create_electrode_table_region(
            [0, 2], "the first and third electrodes")

        self.electrodes = electrode_table_region
Beispiel #14
0
def set_up_nwbfile():
    nwbfile = NWBFile(session_description='session_description',
                      identifier='identifier',
                      session_start_time=datetime.datetime.now(
                          datetime.timezone.utc))

    device = nwbfile.create_device(name='device_name')

    electrode_group = nwbfile.create_electrode_group(name='electrode_group',
                                                     description='description',
                                                     location='location',
                                                     device=device)

    for i in np.arange(10.):
        nwbfile.add_electrode(x=i,
                              y=i,
                              z=i,
                              imp=np.nan,
                              location='location',
                              filtering='filtering',
                              group=electrode_group)

    return nwbfile
Beispiel #15
0
def generate_nwbfile(nchannels=4):
    """Generate an `NWBFile` object that an `ElectricalSeries` can be added to.

    Returns
    -------
    nwbfile : NWBFile
        NWBFile object
    Device : Device
        Device for the ElectricalSeries
    electrode_group : ElectrodeGroup
        ElectrodeGroup for the ElectricalSeries
    electrodes : Electrodes
        Electrodes for the ElectricalSeries
    """
    start_time = datetime(2020, 12, 31, 11, 28, tzinfo=tzlocal())
    nwbfile = NWBFile(
        session_description='Demonstrate `process_nwb` on an NWBFile',
        identifier='NWB123',
        session_start_time=start_time)
    device = nwbfile.create_device(name='ECoG_grid')
    electrode_group = nwbfile.create_electrode_group('Grid',
                                                     description='Grid',
                                                     location='cortex',
                                                     device=device)
    for idx in range(nchannels):
        nwbfile.add_electrode(id=idx,
                              x=1.0,
                              y=2.0,
                              z=3.0,
                              imp=float(-idx),
                              location='cortex',
                              filtering='none',
                              group=electrode_group)
    electrodes = nwbfile.create_electrode_table_region(list(range(nchannels)),
                                                       'Electrodes')

    return nwbfile, device, electrode_group, electrodes
def export_to_nwb(session_key, nwb_output_dir=default_nwb_output_dir, save=False, overwrite=True):

    this_session = (acquisition.Session & session_key).fetch1()

    # ===============================================================================
    # ============================== META INFORMATION ===============================
    # ===============================================================================

    # -- NWB file - a NWB2.0 file for each session
    experimenter = (acquisition.Session.Experimenter & session_key).fetch1('experimenter')
    nwbfile = NWBFile(identifier='_'.join(
        [this_session['subject'],
         this_session['session_time'].strftime('%Y-%m-%d %H:%M:%S')]),
        related_publications='https://www.nature.com/articles/s41586-018-0633-x',
        experiment_description='Extracelluar recording in ALM',
        session_description='',
        session_start_time=this_session['session_time'],
        file_create_date=datetime.now(tzlocal()),
        experimenter=experimenter,
        institution=institution,
        keywords=['motor planning', 'anterior lateral cortex',
                  'ALM', 'Extracellular recording', 'optogenetics'])
    # -- subject
    subj = (subject.Subject & session_key).fetch1()

    nwbfile.subject = pynwb.file.Subject(
        subject_id=str(this_session['subject']),
        genotype=' x '.join((subject.Zygosity &
                             subj).fetch('allele')) \
                 if len(subject.Zygosity & subj) else 'unknown',
        sex=subj['sex'],
        species=subj['species'],
        date_of_birth=datetime.combine(subj['date_of_birth'], zero_zero_time) if subj['date_of_birth'] else None)
    # -- virus
    nwbfile.virus = json.dumps([{k: str(v) for k, v in virus_injection.items() if k not in subj}
                                for virus_injection in action.VirusInjection * reference.Virus & session_key])

    # ===============================================================================
    # ======================== EXTRACELLULAR & CLUSTERING ===========================
    # ===============================================================================

    """
    In the event of multiple probe recording (i.e. multiple probe insertions), the clustering results
    (and the associated units) are associated with the corresponding probe.
    Each probe insertion is associated with one ElectrodeConfiguration (which may define multiple electrode groups)
    """

    dj_insert_location = ephys.ProbeInsertion

    for probe_insertion in ephys.ProbeInsertion & session_key:
        probe = (reference.Probe & probe_insertion).fetch1()
        electrode_group = nwbfile.create_electrode_group(
                name=probe['probe_type'] + '_g1',
                description='N/A',
                device=nwbfile.create_device(name=probe['probe_type']),
                location=json.dumps({k: str(v) for k, v in (dj_insert_location & session_key).fetch1().items()
                                     if k not in dj_insert_location.primary_key}))

        for chn in (reference.Probe.Channel & probe).fetch(as_dict=True):
            nwbfile.add_electrode(
                id=chn['channel_id']-1,
                group=electrode_group,
                filtering=hardware_filter,
                imp=-1.,
                x=np.nan,
                y=np.nan,
                z=np.nan,
                location=(dj_insert_location & session_key).fetch1('brain_location'))


        # --- unit spike times ---
        nwbfile.add_unit_column(name='cell_type', description='cell type (e.g. fast spiking or pyramidal)')
        nwbfile.add_unit_column(name='sampling_rate', description='sampling rate of the waveform, Hz')

        spk_times_all = np.hstack((ephys.UnitSpikeTimes & probe_insertion).fetch('spike_times'))

        obs_min = np.min(spk_times_all)
        obs_max = np.max(spk_times_all)

        for unit in (ephys.UnitSpikeTimes & probe_insertion).fetch(as_dict=True):
            nwbfile.add_unit(id=unit['unit_id'],
                             electrodes=[unit['channel']-1],
                             electrode_group=electrode_group,
                             cell_type=unit['unit_cell_type'],
                             spike_times=unit['spike_times'],
                             obs_intervals=np.array([[obs_min - 0.001, obs_max + 0.001]]),
                             waveform_mean=np.mean(unit['spike_waveform'], axis=0),
                             waveform_sd=np.std(unit['spike_waveform'], axis=0),
                             sampling_rate=20000)

    # ===============================================================================
    # ============================= PHOTO-STIMULATION ===============================
    # ===============================================================================
    stim_sites = {}
    for photostim in acquisition.PhotoStim * reference.BrainLocation & session_key:

        stim_device = (nwbfile.get_device(photostim['photo_stim_method'])
                       if photostim['photo_stim_method'] in nwbfile.devices
                       else nwbfile.create_device(name=photostim['photo_stim_method']))

        stim_site = pynwb.ogen.OptogeneticStimulusSite(
            name=photostim['brain_location'],
            device=stim_device,
            excitation_lambda=float(photostim['photo_stim_wavelength']),
            location=json.dumps({k: str(v) for k, v in photostim.items()
                                if k in acquisition.PhotoStim.heading.names and k not in acquisition.PhotoStim.primary_key + ['photo_stim_method', 'photo_stim_wavelength']}),
            description='')
        nwbfile.add_ogen_site(stim_site)

    # ===============================================================================
    # =============================== BEHAVIOR TRIALS ===============================
    # ===============================================================================

    # =============== TrialSet ====================
    # NWB 'trial' (of type dynamic table) by default comes with three mandatory attributes: 'start_time' and 'stop_time'
    # Other trial-related information needs to be added in to the trial-table as additional columns (with column name
    # and column description)

    dj_trial = acquisition.Session * behavior.TrialSet.Trial
    skip_adding_columns = acquisition.Session.primary_key + \
        ['trial_id', 'trial_start_idx', 'trial_end_idx', 'trial_start_time', 'session_note']

    if behavior.TrialSet.Trial & session_key:
        # Get trial descriptors from TrialSet.Trial and TrialStimInfo
        trial_columns = [{'name': tag.replace('trial_', ''),
                          'description': re.sub('\s+:|\s+', ' ', re.search(
                              f'(?<={tag})(.*)', str(dj_trial.heading)).group()).strip()}
                         for tag in dj_trial.heading.names
                         if tag not in skip_adding_columns]


        # Add new table columns to nwb trial-table for trial-label
        for c in trial_columns:
            nwbfile.add_trial_column(**c)

        # Add entry to the trial-table
        for trial in (dj_trial & session_key).fetch(as_dict=True):
            trial['start_time'] = float(trial['trial_start_time'])
            trial['stop_time'] = float(trial['trial_start_time']) + 5.0
            trial['trial_pole_in_time'] = trial['start_time'] + trial['trial_pole_in_time']
            trial['trial_pole_out_time'] = trial['start_time'] + trial['trial_pole_out_time']
            trial['trial_cue_time'] = trial['start_time'] + trial['trial_cue_time']
            [trial.pop(k) for k in skip_adding_columns]
            for k in trial.keys():
                if 'trial_' in k:
                    trial[k.replace('trial_', '')] = trial.pop(k)
            nwbfile.add_trial(**trial)


    # =============== Write NWB 2.0 file ===============
    if save:
        save_file_name = ''.join([nwbfile.identifier, '.nwb'])
        if not os.path.exists(nwb_output_dir):
            os.makedirs(nwb_output_dir)
        if not overwrite and os.path.exists(os.path.join(nwb_output_dir, save_file_name)):
            return nwbfile
        with NWBHDF5IO(os.path.join(nwb_output_dir, save_file_name), mode='w') as io:
            io.write(nwbfile)
            print(f'Write NWB 2.0 file: {save_file_name}')

    return nwbfile
Beispiel #17
0
def main():

    import os.path

    # prerequisites: start
    import numpy as np

    rate = 10.0
    np.random.seed(1234)
    data_len = 1000
    ephys_data = np.random.rand(data_len)
    ephys_timestamps = np.arange(data_len) / rate
    spatial_timestamps = ephys_timestamps[::10]
    spatial_data = np.cumsum(np.random.normal(size=(2,
                                                    len(spatial_timestamps))),
                             axis=-1).T
    # prerequisites: end

    # create-nwbfile: start
    from datetime import datetime
    from dateutil.tz import tzlocal
    from pynwb import NWBFile

    f = NWBFile(
        'the PyNWB tutorial',
        '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')
    # create-nwbfile: end

    # save-nwbfile: start
    from pynwb import NWBHDF5IO

    filename = "example.h5"
    io = NWBHDF5IO(filename, mode='w')
    io.write(f)
    io.close()
    # save-nwbfile: end

    os.remove(filename)

    # create-device: start
    device = f.create_device(name='trodes_rig123', source="a source")
    # create-device: end

    # create-electrode-groups: start
    electrode_name = 'tetrode1'
    source = "an hypothetical source"
    description = "an example tetrode"
    location = "somewhere in the hippocampus"

    electrode_group = f.create_electrode_group(electrode_name,
                                               source=source,
                                               description=description,
                                               location=location,
                                               device=device)

    # create-electrode-groups: end

    # create-electrode-table-region: start
    for idx in [1, 2, 3, 4]:
        f.add_electrode(idx,
                        x=1.0,
                        y=2.0,
                        z=3.0,
                        imp=float(-idx),
                        location='CA1',
                        filtering='none',
                        description='channel %s' % idx,
                        group=electrode_group)

    electrode_table_region = f.create_electrode_table_region(
        [0, 2], 'the first and third electrodes')
    # create-electrode-table-region: end

    # create-timeseries: start
    from pynwb.ecephys import ElectricalSeries
    from pynwb.behavior import SpatialSeries

    ephys_ts = ElectricalSeries(
        'test_ephys_data',
        'an hypothetical source',
        ephys_data,
        electrode_table_region,
        timestamps=ephys_timestamps,
        # Alternatively, could specify starting_time and rate as follows
        # starting_time=ephys_timestamps[0],
        # rate=rate,
        resolution=0.001,
        comments=
        "This data was randomly generated with numpy, using 1234 as the seed",
        description="Random numbers generated with numpy.random.rand")
    f.add_acquisition(ephys_ts)

    spatial_ts = SpatialSeries(
        'test_spatial_timeseries',
        'a stumbling rat',
        spatial_data,
        'origin on x,y-plane',
        timestamps=spatial_timestamps,
        resolution=0.1,
        comments="This data was generated with numpy, using 1234 as the seed",
        description="This 2D Brownian process generated with "
        "np.cumsum(np.random.normal(size=(2, len(spatial_timestamps))), axis=-1).T"
    )
    f.add_acquisition(spatial_ts)
    # create-timeseries: end

    # create-data-interface: start
    from pynwb.ecephys import LFP
    from pynwb.behavior import Position

    lfp = f.add_acquisition(LFP('a hypothetical source'))
    ephys_ts = lfp.create_electrical_series(
        'test_ephys_data',
        'an hypothetical source',
        ephys_data,
        electrode_table_region,
        timestamps=ephys_timestamps,
        resolution=0.001,
        comments=
        "This data was randomly generated with numpy, using 1234 as the seed",  # noqa: E501
        description="Random numbers generated with numpy.random.rand")

    pos = f.add_acquisition(Position('a hypothetical source'))
    spatial_ts = pos.create_spatial_series(
        'test_spatial_timeseries',
        'a stumbling rat',
        spatial_data,
        'origin on x,y-plane',
        timestamps=spatial_timestamps,
        resolution=0.1,
        comments="This data was generated with numpy, using 1234 as the seed",
        description="This 2D Brownian process generated with "
        "np.cumsum(np.random.normal(size=(2, len(spatial_timestamps))), axis=-1).T"
    )  # noqa: E501
    # create-data-interface: end

    # create-epochs: start
    epoch_tags = ('example_epoch', )

    f.add_epoch(name='epoch1',
                start_time=0.0,
                stop_time=1.0,
                tags=epoch_tags,
                description="the first test epoch",
                timeseries=[ephys_ts, spatial_ts])

    f.add_epoch(name='epoch2',
                start_time=0.0,
                stop_time=1.0,
                tags=epoch_tags,
                description="the second test epoch",
                timeseries=[ephys_ts, spatial_ts])
    # create-epochs: end

    # create-compressed-timeseries: start
    from pynwb.ecephys import ElectricalSeries
    from pynwb.behavior import SpatialSeries
    from pynwb.form.backends.hdf5 import H5DataIO

    ephys_ts = ElectricalSeries(
        'test_compressed_ephys_data',
        'an hypothetical source',
        H5DataIO(ephys_data, compress=True),
        electrode_table_region,
        timestamps=H5DataIO(ephys_timestamps, compress=True),
        resolution=0.001,
        comments=
        "This data was randomly generated with numpy, using 1234 as the seed",
        description="Random numbers generated with numpy.random.rand")
    f.add_acquisition(ephys_ts)

    spatial_ts = SpatialSeries(
        'test_compressed_spatial_timeseries',
        'a stumbling rat',
        H5DataIO(spatial_data, compress=True),
        'origin on x,y-plane',
        timestamps=H5DataIO(spatial_timestamps, compress=True),
        resolution=0.1,
        comments="This data was generated with numpy, using 1234 as the seed",
        description="This 2D Brownian process generated with "
        "np.cumsum(np.random.normal(size=(2, len(spatial_timestamps))), axis=-1).T"
    )
    f.add_acquisition(spatial_ts)
Beispiel #18
0
def write_multiple_nwb_files(root_dir='/tmp'):

    rec_datetime = date_parser.parse('03/22/2018 15:35:22')

    block = 'Site1'

    recording_name = '{}_{}'.format('bird', block)

    nwb_file = os.path.join(root_dir, '{}.nwb'.format(recording_name))

    session_desc = "A single recording session"

    exp_desc = "An experiment."

    nf = NWBFile(recording_name,
                 session_desc,
                 'bird',
                 rec_datetime,
                 experimenter='Experi Menter',
                 lab='The Lab',
                 institution='University of Shaz',
                 experiment_description=exp_desc,
                 session_id='bird')

    hemi = 'L'

    electrode_array_name = '16 electrode microwire array on {} hemisphere'.format(
        hemi)
    electrode_array = nf.create_device(name=electrode_array_name, source='')

    # create an electrode group
    egrp_desc = """ The (x,y) locations of the electrodes refer to the distance from region midline and distance
                    from L2A, respectively, in mm.            
                """

    electrode_group = nf.create_electrode_group(
        hemi,
        source=electrode_array_name,
        description=egrp_desc,
        location='{} Hemisphere, Field L, CM, NCM'.format(hemi),
        device=electrode_array)

    # add electrodes to electrode group
    electrode_start = 0
    if hemi == 'R':
        electrode_start = 16
    electrode_numbers = list(np.arange(electrode_start, electrode_start + 16))
    for electrode_number in electrode_numbers:

        nf.add_electrode(electrode_number - 1,
                         x=np.random.randn(),
                         y=np.random.randn(),
                         z=0.0,
                         imp=0.0,
                         location='cortex',
                         filtering='none',
                         description='An electrode',
                         group=electrode_group)

    # create an electrode table region
    etable = nf.create_electrode_table_region(
        electrode_numbers,
        'All electrodes in array for hemisphere {} with LFP'.format(hemi))

    lfp_data = np.random.randn(len(electrode_numbers), 1000)
    sr = 1000.
    t = np.arange(lfp_data.shape[1]) / sr

    # add the raw LFP
    lfp_series_name = 'Multi-electrode LFP on {} hemisphere from block {}'.format(
        hemi, block)
    lfp = ElectricalSeries(
        lfp_series_name,
        electrode_array_name,
        lfp_data,
        etable,
        timestamps=t,
        resolution=1e-12,
        comments='',
        description='Low-passed LFP recorded from microwire array')

    # add the spikes and their waveforms
    electrode_number = 0
    spike_times = [0.5, 1.5, 3.5]
    waveforms = np.random.randn(3, 18)
    sort_type = 'Multi-unit'

    full_unit_name = '{} on electrode {}'.format(sort_type, electrode_number)
    spikes = SpikeEventSeries(
        full_unit_name,
        lfp_series_name,
        waveforms,
        spike_times,
        etable,
        resolution=1e-12,
        conversion=1e6,
        comments='',
        description='',
    )

    print('\tAdding spikes acquisition: {} ({}), waveforms.shape={}'.format(
        full_unit_name, sort_type, str(waveforms.shape)))

    # adding the LFP is fine
    nf.add_acquisition(lfp)

    ########################################################
    # adding even a single spike event series causes the error
    ########################################################
    nf.add_acquisition(spikes)

    print('Writing to {}'.format(nwb_file))
    with NWBHDF5IO(nwb_file, mode='w') as io:
        io.write(nf)

    del nf
Beispiel #19
0
                                                 location=location,
                                                 device=device)

#######################
# After setting up electrode group metadata, you should add metadata about the individual electrodes comprising
# each electrode group. This is done with :py:func:`~pynwb.file.NWBFile.add_electrode`.
#
# The first argument to :py:class:`~pynwb.file.NWBFile.add_electrode` is a unique identifier that the user should
# assign. For details on the rest of the arguments, please see the
# :py:func:`API documentation <pynwb.file.NWBFile.add_electrode>`.


for idx in [1, 2, 3, 4]:
    nwbfile.add_electrode(idx,
                          x=1.0, y=2.0, z=3.0,
                          imp=float(-idx),
                          location='CA1', filtering='none',
                          description='channel %s' % idx, group=electrode_group)


#######################
# .. note: :py:class:`~pynwb.file.NWBFile.add_electrode` returns the index of the electrode you just added.
#    This can come in handy when creating with an :py:class:`~pynwb.ecephys.ElectrodeTableRegion`
#    :py:class:`~pynwb.file.NWBFile.create_electrode_table_region` (See :ref:`ec_recordings`).

#######################
# .. _ec_recordings:
#
# Extracellular recordings
# ^^^^^^^^^^^^^^^^^^^^^^^^
#
Beispiel #20
0
class Alyx2NWBConverter:
    def __init__(self,
                 saveloc=None,
                 nwb_metadata_file=None,
                 metadata_obj: Alyx2NWBMetadata = None,
                 one_object: ONE = None,
                 save_raw=False,
                 save_camera_raw=False,
                 complevel=4,
                 shuffle=False,
                 buffer_size=1):
        """
        Retrieve all Alyx session, subject metadata, raw data for eid using the one apis load method
        Map that to nwb supported datatypes and create an nwb file.
        Parameters
        ----------
        saveloc: str, Path
            save location of nwbfile
        nwb_metadata_file: [dict, str]
            output of Alyx2NWBMetadata as a dict/json location str
        metadata_obj: Alyx2NWBMetadata
        one_object: ONE()
        save_raw: bool
            will load and save large raw files: ecephys.raw.ap/lf.cbin to nwb
        save_camera_raw: bool
            will load and save mice camera movie .mp4: _iblrig_Camera.raw
        complevel: int
            level of compression to apply to raw datasets
            (0-9)>(low,high). https://docs.h5py.org/en/latest/high/dataset.html
        shuffle: bool
            Enable shuffle I/O filter. http://docs.h5py.org/en/latest/high/dataset.html#dataset-shuffle
        """
        self.buffer_size = buffer_size
        self.complevel = complevel
        self.shuffle = shuffle
        if nwb_metadata_file is not None:
            if isinstance(nwb_metadata_file, dict):
                self.nwb_metadata = nwb_metadata_file
            elif isinstance(nwb_metadata_file, str):
                with open(nwb_metadata_file, 'r') as f:
                    self.nwb_metadata = json.load(f)
        elif metadata_obj is not None:
            self.nwb_metadata = metadata_obj.complete_metadata
        else:
            raise Exception(
                'required one of argument: nwb_metadata_file OR metadata_obj')
        if one_object is not None:
            self.one_object = one_object
        elif metadata_obj is not None:
            self.one_object = metadata_obj.one_obj
        else:
            Warning('creating a ONE object and continuing')
            self.one_object = ONE()
        if saveloc is None:
            Warning('saving nwb file in current working directory')
            self.saveloc = str(Path.cwd())
        else:
            self.saveloc = str(saveloc)
        self.eid = self.nwb_metadata["eid"]
        if not isinstance(self.nwb_metadata['NWBFile']['session_start_time'],
                          datetime):
            self.nwb_metadata['NWBFile']['session_start_time'] = \
                datetime.strptime(self.nwb_metadata['NWBFile']['session_start_time'], '%Y-%m-%dT%X').replace(
                    tzinfo=pytz.utc)
            self.nwb_metadata['IBLSubject']['date_of_birth'] = \
                datetime.strptime(self.nwb_metadata['IBLSubject']['date_of_birth'], '%Y-%m-%dT%X').replace(
                    tzinfo=pytz.utc)
        # create nwbfile:
        self.initialize_nwbfile()
        self.no_probes = len(self.nwb_metadata['Probes'])
        if self.no_probes == 0:
            warnings.warn(
                'could not find probe information, will create trials, behavior, acquisition'
            )
        self.electrode_table_exist = False
        self._one_data = _OneData(self.one_object,
                                  self.eid,
                                  self.no_probes,
                                  self.nwb_metadata,
                                  save_raw=save_raw,
                                  save_camera_raw=save_camera_raw)

    def initialize_nwbfile(self):
        """
        Creates self.nwbfile, devices and electrode group of nwb file.
        """
        nwbfile_args = dict(identifier=str(uuid.uuid4()), )
        nwbfile_args.update(**self.nwb_metadata['NWBFile'])
        self.nwbfile = NWBFile(**nwbfile_args)
        # create devices
        [
            self.nwbfile.create_device(**idevice_meta)
            for idevice_meta in self.nwb_metadata['Ecephys']['Device']
        ]
        if 'ElectrodeGroup' in self.nwb_metadata['Ecephys']:
            self.create_electrode_groups(self.nwb_metadata['Ecephys'])

    def create_electrode_groups(self, metadata_ecephys):
        """
        This method is called at __init__.
        Use metadata to create ElectrodeGroup object(s) in the NWBFile

        Parameters
        ----------
        metadata_ecephys : dict
            Dict with key:value pairs for defining the Ecephys group from where this
            ElectrodeGroup belongs. This should contain keys for required groups
            such as 'Device', 'ElectrodeGroup', etc.
        """
        for metadata_elec_group in metadata_ecephys['ElectrodeGroup']:
            eg_name = metadata_elec_group['name']
            # Tests if ElectrodeGroup already exists
            aux = [i.name == eg_name for i in self.nwbfile.children]
            if any(aux):
                print(eg_name + ' already exists in current NWBFile.')
            else:
                device_name = metadata_elec_group['device']
                if device_name in self.nwbfile.devices:
                    device = self.nwbfile.devices[device_name]
                else:
                    print('Device ', device_name, ' for ElectrodeGroup ',
                          eg_name, ' does not exist.')
                    print('Make sure ', device_name,
                          ' is defined in metadata.')

                eg_description = metadata_elec_group['description']
                eg_location = metadata_elec_group['location']
                self.nwbfile.create_electrode_group(name=eg_name,
                                                    location=eg_location,
                                                    device=device,
                                                    description=eg_description)

    def check_module(self, name, description=None):
        """
        Check if processing module exists. If not, create it. Then return module

        Parameters
        ----------
        name: str
        description: str | None (optional)

        Returns
        -------
        pynwb.module

        """

        if name in self.nwbfile.processing:
            return self.nwbfile.processing[name]
        else:
            if description is None:
                description = name
            return self.nwbfile.create_processing_module(name, description)

    def create_stimulus(self):
        """
        Creates stimulus data in nwbfile
        """
        stimulus_list = self._get_data(
            self.nwb_metadata['Stimulus'].get('time_series'))
        for i in stimulus_list:
            self.nwbfile.add_stimulus(pynwb.TimeSeries(**i))

    def create_units(self):
        """
        Units table in nwbfile
        """
        if self.no_probes == 0:
            return
        if not self.electrode_table_exist:
            self.create_electrode_table_ecephys()
        unit_table_list = self._get_data(self.nwb_metadata['Units'])
        # no required arguments for units table. Below are default columns in the table.
        default_args = [
            'id', 'waveform_mean', 'electrodes', 'electrode_group',
            'spike_times', 'obs_intervals'
        ]
        default_ids = _get_default_column_ids(
            default_args, [i['name'] for i in unit_table_list])
        if len(default_ids) != len(default_args):
            warnings.warn(f'could not find all of {default_args} clusters')
        non_default_ids = list(
            set(range(len(unit_table_list))).difference(set(default_ids)))
        default_dict = {
            unit_table_list[id]['name']: unit_table_list[id]['data']
            for id in default_ids
        }
        for cluster_no in range(len(unit_table_list[0]['data'])):
            add_dict = dict()
            for ibl_dataset_name in default_dict:
                if ibl_dataset_name == 'electrodes':
                    add_dict.update({
                        ibl_dataset_name:
                        [default_dict[ibl_dataset_name][cluster_no]]
                    })
                if ibl_dataset_name == 'spike_times':
                    add_dict.update({
                        ibl_dataset_name:
                        default_dict[ibl_dataset_name][cluster_no]
                    })
                elif ibl_dataset_name == 'obs_intervals':  # common across all clusters
                    add_dict.update(
                        {ibl_dataset_name: default_dict[ibl_dataset_name]})
                elif ibl_dataset_name == 'electrode_group':
                    add_dict.update({
                        ibl_dataset_name:
                        self.nwbfile.electrode_groups[self.nwb_metadata[
                            'Probes'][default_dict[ibl_dataset_name]
                                      [cluster_no]]['name']]
                    })
                elif ibl_dataset_name == 'id':
                    if cluster_no >= self._one_data.data_attrs_dump[
                            'unit_table_length'][0]:
                        add_dict.update({
                            ibl_dataset_name:
                            default_dict[ibl_dataset_name][cluster_no] +
                            self._one_data.data_attrs_dump['unit_table_length']
                            [0]
                        })
                    else:
                        add_dict.update({
                            ibl_dataset_name:
                            default_dict[ibl_dataset_name][cluster_no]
                        })
                elif ibl_dataset_name == 'waveform_mean':
                    add_dict.update({
                        ibl_dataset_name:
                        np.mean(default_dict[ibl_dataset_name][cluster_no],
                                axis=1)
                    })  # finding the mean along all the channels of the sluter
            self.nwbfile.add_unit(**add_dict)

        for id in non_default_ids:
            if isinstance(unit_table_list[id]['data'], object):
                unit_table_list[id]['data'] = unit_table_list[id][
                    'data'].tolist()  # convert string numpy
            self.nwbfile.add_unit_column(
                name=unit_table_list[id]['name'],
                description=unit_table_list[id]['description'],
                data=unit_table_list[id]['data'])

    def create_electrode_table_ecephys(self):
        """
        Creates electrode table
        """
        if self.no_probes == 0:
            return
        if self.electrode_table_exist:
            pass
        electrode_table_list = self._get_data(
            self.nwb_metadata['ElectrodeTable'])
        # electrode table has required arguments:
        required_args = ['group', 'x', 'y']
        default_ids = _get_default_column_ids(
            required_args, [i['name'] for i in electrode_table_list])
        non_default_ids = list(
            set(range(len(electrode_table_list))).difference(set(default_ids)))
        default_dict = {
            electrode_table_list[id]['name']: electrode_table_list[id]['data']
            for id in default_ids
        }
        if 'group' in default_dict:
            group_labels = default_dict['group']
        else:  # else fill with probe zero data.
            group_labels = np.concatenate([
                np.ones(self._one_data.
                        data_attrs_dump['electrode_table_length'][i],
                        dtype=int) * i for i in range(self.no_probes)
            ])
        for electrode_no in range(len(electrode_table_list[0]['data'])):
            if 'x' in default_dict:
                x = default_dict['x'][electrode_no][0]
                y = default_dict['y'][electrode_no][1]
            else:
                x = float('NaN')
                y = float('NaN')
            group_data = self.nwbfile.electrode_groups[self.nwb_metadata[
                'Probes'][group_labels[electrode_no]]['name']]
            self.nwbfile.add_electrode(x=x,
                                       y=y,
                                       z=float('NaN'),
                                       imp=float('NaN'),
                                       location='None',
                                       group=group_data,
                                       filtering='none')
        for id in non_default_ids:
            self.nwbfile.add_electrode_column(
                name=electrode_table_list[id]['name'],
                description=electrode_table_list[id]['description'],
                data=electrode_table_list[id]['data'])
        # create probes specific DynamicTableRegion:
        self.probe_dt_region = [
            self.nwbfile.create_electrode_table_region(region=list(
                range(self._one_data.data_attrs_dump['electrode_table_length']
                      [j])),
                                                       description=i['name'])
            for j, i in enumerate(self.nwb_metadata['Probes'])
        ]
        self.probe_dt_region_all = self.nwbfile.create_electrode_table_region(
            region=list(
                range(
                    sum(self._one_data.
                        data_attrs_dump['electrode_table_length']))),
            description='AllProbes')
        self.electrode_table_exist = True

    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 create_behavior(self):
        """
        Create behavior processing module
        """
        self.check_module('behavior')
        for behavior_datatype in self.nwb_metadata['Behavior']:
            if behavior_datatype == 'Position':
                position_cont = pynwb.behavior.Position()
                time_series_list_details = self._get_data(
                    self.nwb_metadata['Behavior'][behavior_datatype]
                    ['spatial_series'])
                if len(time_series_list_details) == 0:
                    continue
                # rate_list = [150.0,60.0,60.0] # based on the google doc for _iblrig_body/left/rightCamera.raw,
                dataname_list = self._one_data.data_attrs_dump['camera.dlc']
                data_list = time_series_list_details[0]['data']
                timestamps_list = time_series_list_details[0]['timestamps']
                for dataname, data, timestamps in zip(dataname_list, data_list,
                                                      timestamps_list):
                    colnames = data.columns
                    data_np = data.to_numpy()
                    x_column_ids = [
                        n for n, k in enumerate(colnames) if 'x' in k
                    ]
                    for x_column_id in x_column_ids:
                        data_loop = data_np[:, x_column_id:x_column_id + 2]
                        position_cont.create_spatial_series(
                            name=dataname + colnames[x_column_id][:-2],
                            data=data_loop,
                            reference_frame='none',
                            timestamps=timestamps,
                            conversion=1e-3)
                self.nwbfile.processing['behavior'].add(position_cont)
            elif not (behavior_datatype == 'BehavioralEpochs'):
                time_series_func = pynwb.TimeSeries
                time_series_list_details = self._get_data(
                    self.nwb_metadata['Behavior'][behavior_datatype]
                    ['time_series'])
                if len(time_series_list_details) == 0:
                    continue
                time_series_list_obj = []
                for i in time_series_list_details:
                    unit = 'radians/sec' if 'velocity' in i[
                        'name'] else 'radians'
                    time_series_list_obj.append(
                        time_series_func(**i, unit=unit))
                func = getattr(pynwb.behavior, behavior_datatype)
                self.nwbfile.processing['behavior'].add(
                    func(time_series=time_series_list_obj))
            else:
                time_series_func = pynwb.epoch.TimeIntervals
                time_series_list_details = self._get_data(
                    self.nwb_metadata['Behavior'][behavior_datatype]
                    ['time_intervals'])
                if len(time_series_list_details) == 0:
                    continue
                for k in time_series_list_details:
                    time_intervals = time_series_func('BehavioralEpochs')
                    for time_interval in k['timestamps']:
                        time_intervals.add_interval(
                            start_time=time_interval[0],
                            stop_time=time_interval[1])
                    time_intervals.add_column(k['name'],
                                              k['description'],
                                              data=k['data'])
                    self.nwbfile.processing['behavior'].add(time_intervals)

    def create_acquisition(self):
        """
        Acquisition data like audiospectrogram(raw beh data), nidq(raw ephys data), raw camera data.
        These are independent of probe type.
        """
        for neurodata_type_name, neurodata_type_args_list in self.nwb_metadata[
                'Acquisition'].items():
            data_retrieved_args_list = self._get_data(neurodata_type_args_list)
            for neurodata_type_args in data_retrieved_args_list:
                if neurodata_type_name == 'ImageSeries':
                    for types, times in zip(neurodata_type_args['data'],
                                            neurodata_type_args['timestamps']):
                        customargs = dict(name='camera_raw',
                                          external_file=[str(types)],
                                          format='external',
                                          timestamps=times,
                                          unit='n.a.')
                        self.nwbfile.add_acquisition(ImageSeries(**customargs))
                elif neurodata_type_name == 'DecompositionSeries':
                    neurodata_type_args['bands'] = np.squeeze(
                        neurodata_type_args['bands'])
                    freqs = DynamicTable(
                        'bands',
                        'spectogram frequencies',
                        id=np.arange(neurodata_type_args['bands'].shape[0]))
                    freqs.add_column('freq',
                                     'frequency value',
                                     data=neurodata_type_args['bands'])
                    neurodata_type_args.update(dict(bands=freqs))
                    temp = neurodata_type_args['data'][:, :, np.newaxis]
                    neurodata_type_args['data'] = np.moveaxis(
                        temp, [0, 1, 2], [0, 2, 1])
                    ts = neurodata_type_args.pop('timestamps')
                    starting_time = ts[0][0] if isinstance(
                        ts[0], np.ndarray) else ts[0]
                    neurodata_type_args.update(
                        dict(starting_time=np.float64(starting_time),
                             rate=1 / np.mean(np.diff(ts.squeeze())),
                             unit='sec'))
                    self.nwbfile.add_acquisition(
                        DecompositionSeries(**neurodata_type_args))
                elif neurodata_type_name == 'ElectricalSeries':
                    if not self.electrode_table_exist:
                        self.create_electrode_table_ecephys()
                    if neurodata_type_args['name'] in ['raw.lf', 'raw.ap']:
                        for probe_no in range(self.no_probes):
                            if neurodata_type_args['data'][probe_no].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)
                            self.nwbfile.add_acquisition(
                                ElectricalSeries(
                                    name=neurodata_type_args['name'] + '_' +
                                    self.nwb_metadata['Probes'][probe_no]
                                    ['name'],
                                    starting_time=np.abs(
                                        np.round(
                                            neurodata_type_args['timestamps']
                                            [probe_no][0, 1], 2)
                                    ),  # round starting times of the order of 1e-5
                                    rate=neurodata_type_args['data']
                                    [probe_no].fs,
                                    data=H5DataIO(
                                        DataChunkIterator(
                                            _iter_datasetview(
                                                neurodata_type_args['data']
                                                [probe_no],
                                                channel_ids=channel_idx),
                                            buffer_size=self.buffer_size),
                                        compression=True,
                                        shuffle=self.shuffle,
                                        compression_opts=self.complevel),
                                    electrodes=self.probe_dt_region[probe_no],
                                    channel_conversion=neurodata_type_args[
                                        'data']
                                    [probe_no].channel_conversion_sample2v[
                                        neurodata_type_args['data']
                                        [probe_no].type][channel_idx]))
                    elif neurodata_type_args['name'] in ['raw.nidq']:
                        self.nwbfile.add_acquisition(
                            ElectricalSeries(**neurodata_type_args))

    def create_probes(self):
        """
        Fills in all the probes metadata into the custom NeuroPixels extension.
        """
        for i in self.nwb_metadata['Probes']:
            self.nwbfile.add_device(IblProbes(**i))

    def create_iblsubject(self):
        """
        Populates the custom subject extension for IBL mice daata
        """
        self.nwbfile.subject = IblSubject(**self.nwb_metadata['IBLSubject'])

    def create_lab_meta_data(self):
        """
        Populates the custom lab_meta_data extension for IBL sessions data
        """
        self.nwbfile.add_lab_meta_data(
            IblSessionData(**self.nwb_metadata['IBLSessionsData']))

    def create_trials(self):
        table_data = self._get_data(self.nwb_metadata['Trials'])
        required_fields = ['start_time', 'stop_time']
        required_data = [i for i in table_data if i['name'] in required_fields]
        optional_data = [
            i for i in table_data if i['name'] not in required_fields
        ]
        if len(required_fields) != len(required_data):
            warnings.warn(
                'could not find required datasets: trials.start_time, trials.stop_time, '
                'skipping trials table')
            return
        for start_time, stop_time in zip(required_data[0]['data'][:, 0],
                                         required_data[1]['data'][:, 1]):
            self.nwbfile.add_trial(start_time=start_time, stop_time=stop_time)
        for op_data in optional_data:
            if op_data['data'].shape[0] == required_data[0]['data'].shape[0]:
                self.nwbfile.add_trial_column(
                    name=op_data['name'],
                    description=op_data['description'],
                    data=op_data['data'])
            else:
                warnings.warn(
                    f'shape of trials.{op_data["name"]} does not match other trials.* datasets'
                )

    def _get_data(self, sub_metadata):
        """
        Uses OneData class to query ONE datasets on server and download them locally
        Parameters
        ----------
        sub_metadata: [list, dict]
            list of metadata dicts containing a data key with a dataset type string as value to retrieve data from(npy, tsv etc)

        Returns
        -------
        out_dict: dict
            dictionary with actual data loaded in the data field
        """
        include_idx = []
        out_dict_trim = []
        alt_datatypes = ['bands', 'power', 'frequencies', 'timestamps']
        if isinstance(sub_metadata, list):
            out_dict = deepcopy(sub_metadata)
        elif isinstance(sub_metadata, dict):
            out_dict = deepcopy(list(sub_metadata))
        else:
            return []
        req_datatypes = ['data']
        for count, neurodata_type_args in enumerate(out_dict):
            for alt_names in alt_datatypes:
                if neurodata_type_args.get(
                        alt_names
                ):  # in case of Decomposotion series, Spectrum
                    neurodata_type_args[
                        alt_names] = self._one_data.download_dataset(
                            neurodata_type_args[alt_names],
                            neurodata_type_args['name'])
                    req_datatypes.append(alt_names)
            if neurodata_type_args[
                    'name'] == 'id':  # valid in case of units table.
                neurodata_type_args['data'] = self._one_data.download_dataset(
                    neurodata_type_args['data'], 'cluster_id')
            else:
                out_dict[count]['data'] = self._one_data.download_dataset(
                    neurodata_type_args['data'], neurodata_type_args['name'])
            if all([out_dict[count][i] is not None for i in req_datatypes]):
                include_idx.extend([count])
        out_dict_trim.extend([out_dict[j0] for j0 in include_idx])
        return out_dict_trim

    def run_conversion(self):
        """
        Single method to create all datasets and metadata in nwbfile in one go
        Returns
        -------

        """
        execute_list = [
            self.create_stimulus, self.create_trials,
            self.create_electrode_table_ecephys,
            self.create_timeseries_ecephys, self.create_units,
            self.create_behavior, self.create_probes, self.create_iblsubject,
            self.create_lab_meta_data, self.create_acquisition
        ]
        t = tqdm(execute_list)
        for i in t:
            t.set_postfix(current=f'creating nwb ' + i.__name__.split('_')[-1])
            i()
        print('done converting')

    def write_nwb(self, read_check=True):
        """
        After run_conversion(), write nwbfile to disk with the loaded nwbfile
        Parameters
        ----------
        read_check: bool
            Round trip verification
        """
        print('Saving to file, please wait...')
        with NWBHDF5IO(self.saveloc, 'w') as io:
            io.write(self.nwbfile)
            print('File successfully saved at: ', str(self.saveloc))

        if read_check:
            with NWBHDF5IO(self.saveloc, 'r') as io:
                io.read()
                print('Read check: OK')
Beispiel #21
0
                                                 location=location,
                                                 device=device)

#######################
# After setting up electrode group metadata, you should add metadata about the individual electrodes comprising
# each electrode group. This is done with :py:func:`~pynwb.file.NWBFile.add_electrode`.
#
# The first argument to :py:class:`~pynwb.file.NWBFile.add_electrode` is a unique identifier that the user should
# assign. For details on the rest of the arguments, please see the
# :py:func:`API documentation <pynwb.file.NWBFile.add_electrode>`.

for idx in [1, 2, 3, 4]:
    nwbfile.add_electrode(id=idx,
                          x=1.0,
                          y=2.0,
                          z=3.0,
                          imp=float(-idx),
                          location='CA1',
                          filtering='none',
                          group=electrode_group)

#######################
# .. note: :py:class:`~pynwb.file.NWBFile.add_electrode` returns the index of the electrode you just added.
#    This can come in handy when creating with an :py:class:`~pynwb.core.DynamicTableRegion`
#    :py:class:`~pynwb.file.NWBFile.create_electrode_table_region` (See :ref:`ec_recordings`).

#######################
# .. _ec_recordings:
#
# Extracellular recordings
# ^^^^^^^^^^^^^^^^^^^^^^^^
#
Beispiel #22
0
def nwb_copy_file(old_file, new_file, cp_objs={}):
    """
    Copy fields defined in 'obj', from existing NWB file to new NWB file.

    Parameters
    ----------
    old_file : str, path
        String such as '/path/to/old_file.nwb'.
    new_file : str, path
        String such as '/path/to/new_file.nwb'.
    cp_objs : dict
        Name:Value pairs (Group:Children) listing the groups and respective
        children from the current NWB file to be copied. Children can be:
        - Boolean, indicating an attribute (e.g. for institution, lab)
        - List of strings, containing several children names
        Example:
        {'institution':True,
         'lab':True,
         'acquisition':['microphone'],
         'ecephys':['LFP','DecompositionSeries']}
    """

    manager = get_manager()

    # Open original signal file
    with NWBHDF5IO(old_file, 'r', manager=manager,
                   load_namespaces=True) as io1:
        nwb_old = io1.read()

        # Creates new file
        nwb_new = NWBFile(session_description=str(nwb_old.session_description),
                          identifier='',
                          session_start_time=datetime.now(tzlocal()))
        with NWBHDF5IO(new_file, mode='w', manager=manager,
                       load_namespaces=False) as io2:
            # Institution name ------------------------------------------------
            if 'institution' in cp_objs:
                nwb_new.institution = str(nwb_old.institution)

            # Lab name --------------------------------------------------------
            if 'lab' in cp_objs:
                nwb_new.lab = str(nwb_old.lab)

            # Session id ------------------------------------------------------
            if 'session' in cp_objs:
                nwb_new.session_id = nwb_old.session_id

            # Devices ---------------------------------------------------------
            if 'devices' in cp_objs:
                for aux in list(nwb_old.devices.keys()):
                    dev = Device(nwb_old.devices[aux].name)
                    nwb_new.add_device(dev)

            # Electrode groups ------------------------------------------------
            if 'electrode_groups' in cp_objs:
                for aux in list(nwb_old.electrode_groups.keys()):
                    nwb_new.create_electrode_group(
                        name=str(nwb_old.electrode_groups[aux].name),
                        description=str(nwb_old.electrode_groups[
                            aux].description),
                        location=str(nwb_old.electrode_groups[aux].location),
                        device=nwb_new.get_device(
                            nwb_old.electrode_groups[aux].device.name)
                    )

            # Electrodes ------------------------------------------------------
            if 'electrodes' in cp_objs:
                nElec = len(nwb_old.electrodes['x'].data[:])
                for aux in np.arange(nElec):
                    nwb_new.add_electrode(
                        x=nwb_old.electrodes['x'][aux],
                        y=nwb_old.electrodes['y'][aux],
                        z=nwb_old.electrodes['z'][aux],
                        imp=nwb_old.electrodes['imp'][aux],
                        location=str(nwb_old.electrodes['location'][aux]),
                        filtering=str(nwb_old.electrodes['filtering'][aux]),
                        group=nwb_new.get_electrode_group(
                            nwb_old.electrodes['group'][aux].name),
                        group_name=str(nwb_old.electrodes['group_name'][aux])
                    )
                # if there are custom variables
                new_vars = list(nwb_old.electrodes.colnames)
                default_vars = ['x', 'y', 'z', 'imp', 'location', 'filtering',
                                'group', 'group_name']
                [new_vars.remove(var) for var in default_vars]
                for var in new_vars:

                    if var == 'label':
                        var_data = [str(elem) for elem in nwb_old.electrodes[
                                                          var].data[:]]
                    else:
                        var_data = np.array(nwb_old.electrodes[var].data[:])

                    nwb_new.add_electrode_column(name=str(var),
                                                 description=
                                                 str(nwb_old.electrodes[
                                                     var].description),
                                                 data=var_data)

            # Epochs ----------------------------------------------------------
            if 'epochs' in cp_objs:
                nEpochs = len(nwb_old.epochs['start_time'].data[:])
                for i in np.arange(nEpochs):
                    nwb_new.add_epoch(
                        start_time=nwb_old.epochs['start_time'].data[i],
                        stop_time=nwb_old.epochs['stop_time'].data[i])
                # if there are custom variables
                new_vars = list(nwb_old.epochs.colnames)
                default_vars = ['start_time', 'stop_time', 'tags',
                                'timeseries']
                [new_vars.remove(var) for var in default_vars if
                 var in new_vars]
                for var in new_vars:
                    nwb_new.add_epoch_column(name=var,
                                             description=nwb_old.epochs[
                                                 var].description,
                                             data=nwb_old.epochs[var].data[:])

            # Invalid times ---------------------------------------------------
            if 'invalid_times' in cp_objs:
                nInvalid = len(nwb_old.invalid_times['start_time'][:])
                for aux in np.arange(nInvalid):
                    nwb_new.add_invalid_time_interval(
                        start_time=nwb_old.invalid_times['start_time'][aux],
                        stop_time=nwb_old.invalid_times['stop_time'][aux])

            # Trials ----------------------------------------------------------
            if 'trials' in cp_objs:
                nTrials = len(nwb_old.trials['start_time'])
                for aux in np.arange(nTrials):
                    nwb_new.add_trial(
                        start_time=nwb_old.trials['start_time'][aux],
                        stop_time=nwb_old.trials['stop_time'][aux])
                # if there are custom variables
                new_vars = list(nwb_old.trials.colnames)
                default_vars = ['start_time', 'stop_time']
                [new_vars.remove(var) for var in default_vars]
                for var in new_vars:
                    nwb_new.add_trial_column(name=var,
                                             description=nwb_old.trials[
                                                 var].description,
                                             data=nwb_old.trials[var].data[:])

            # Intervals -------------------------------------------------------
            if 'intervals' in cp_objs:
                all_objs_names = list(nwb_old.intervals.keys())
                for obj_name in all_objs_names:
                    obj_old = nwb_old.intervals[obj_name]
                    # create and add TimeIntervals
                    obj = TimeIntervals(name=obj_old.name,
                                        description=obj_old.description)
                    nInt = len(obj_old['start_time'])
                    for ind in np.arange(nInt):
                        obj.add_interval(start_time=obj_old['start_time'][ind],
                                         stop_time=obj_old['stop_time'][ind])
                    # Add to file
                    nwb_new.add_time_intervals(obj)

            # Stimulus --------------------------------------------------------
            if 'stimulus' in cp_objs:
                all_objs_names = list(nwb_old.stimulus.keys())
                for obj_name in all_objs_names:
                    obj_old = nwb_old.stimulus[obj_name]
                    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)
                    nwb_new.add_stimulus(obj)

            # Processing modules ----------------------------------------------
            if 'ecephys' in cp_objs:
                if cp_objs['ecephys'] is True:
                    interfaces = nwb_old.processing[
                        'ecephys'].data_interfaces.keys()
                else:  # list of items
                    interfaces = [
                        nwb_old.processing['ecephys'].data_interfaces[key]
                        for key in cp_objs['ecephys']
                    ]
                # Add ecephys module to NWB file
                ecephys_module = ProcessingModule(
                    name='ecephys',
                    description='Extracellular electrophysiology data.'
                )
                nwb_new.add_processing_module(ecephys_module)
                for interface_old in interfaces:
                    obj = copy_obj(interface_old, nwb_old, nwb_new)
                    if obj is not None:
                        ecephys_module.add_data_interface(obj)

            # Acquisition -----------------------------------------------------
            if 'acquisition' in cp_objs:
                if cp_objs['acquisition'] is True:
                    all_acq_names = list(nwb_old.acquisition.keys())
                else:  # list of items
                    all_acq_names = cp_objs['acquisition']
                for acq_name in all_acq_names:
                    obj_old = nwb_old.acquisition[acq_name]
                    obj = copy_obj(obj_old, nwb_old, nwb_new)
                    if obj is not None:
                        nwb_new.add_acquisition(obj)

            # Subject ---------------------------------------------------------
            if 'subject' in cp_objs:
                try:
                    cortical_surfaces = CorticalSurfaces()
                    surfaces = nwb_old.subject.cortical_surfaces.surfaces
                    for sfc in list(surfaces.keys()):
                        cortical_surfaces.create_surface(
                            name=surfaces[sfc].name,
                            faces=surfaces[sfc].faces,
                            vertices=surfaces[sfc].vertices)
                    nwb_new.subject = ECoGSubject(
                        cortical_surfaces=cortical_surfaces,
                        subject_id=nwb_old.subject.subject_id,
                        age=nwb_old.subject.age,
                        description=nwb_old.subject.description,
                        genotype=nwb_old.subject.genotype,
                        sex=nwb_old.subject.sex,
                        species=nwb_old.subject.species,
                        weight=nwb_old.subject.weight,
                        date_of_birth=nwb_old.subject.date_of_birth)
                except:
                    nwb_new.subject = Subject(age=nwb_old.subject.age,
                                              description=nwb_old.subject.description,
                                              genotype=nwb_old.subject.genotype,
                                              sex=nwb_old.subject.sex,
                                              species=nwb_old.subject.species,
                                              subject_id=nwb_old.subject.subject_id,
                                              weight=nwb_old.subject.weight,
                                              date_of_birth=nwb_old.subject.date_of_birth)

            # Write new file with copied fields
            io2.write(nwb_new, link_data=False)
Beispiel #23
0
def no2nwb(NOData, session_use, subjects_ini, path_to_data):
    '''
       Purpose:
           Import the data and associated meta-data from the new/old recognition dataset into an
           NWB file. Each of the features of the dataset, such as the events (i.e., TTLs) or mean waveform, are
           compartmentalized to the appropriate component of the NWB file.


    '''

    # Time scaling (covert uS -----> S for NWB file)
    TIME_SCALING = 10**6

    # Prepare the NO data that will be coverted to the NWB format

    session = NOData.sessions[session_use]
    events = NOData._get_event_data(session_use, experiment_type='All')
    cell_ids = NOData.ls_cells(session_use)
    experiment_id_learn = session['experiment_id_learn']
    experiment_id_recog = session['experiment_id_recog']
    task_descr = session['task_descr']

    # Get the metadata for the subject
    # ============ Read Config File ()
    # load config file (subjects == config file)

    #  Check config file path
    filename = subjects_ini
    if not os.path.exists(filename):
        print('This file does not exist: {}'.format(filename))
        print("Check filename/and or directory")

    # Read the config file
    try:
        # initialze the ConfigParser() class
        config = configparser.ConfigParser()
        # read .ini file
        config.read(filename)
    except:
        print('Failed to read the config file..')
        print('Does this file exist: {}'.format(os.path.exists(filename)))

    #  Read Meta-data from INI file.
    for section in config.sections():
        if session_use == int(section):
            session_id = int(section)  #  The New/Old ID for the session
            #Get the session ID
            for value in config[section]:
                if value.lower() == 'nosessions.age':
                    age = int(config[section][value])
                if value.lower() == 'nosessions.diagnosiscode':
                    epilepsyDxCode = config[section][value]
                    epilepsyDx = getEpilepsyDx(int(epilepsyDxCode))
                if value.lower() == 'nosessions.sex':
                    sex = config[section][value].strip("'")
                if value.lower() == 'nosessions.id':
                    ID = config[section][value].strip("'")
                if value.lower() == 'nosessions.session':
                    pt_session = config[section][value].strip("'")
                if value.lower() == 'nosessions.date':
                    unformattedDate = config[section][value].strip("'")
                    date = datetime.strptime(unformattedDate, '%Y-%m-%d')
                    finaldate = date.replace(hour=0, minute=0)
                if value.lower() == 'nosessions.institution':
                    institution = config[section][value].strip("'")
                if value.lower() == 'nosessions.la':
                    LA = config[section][value].strip("'").split(',')
                    if LA[0] == 'NaN':
                        LA_x = np.nan
                        LA_y = np.nan
                        LA_z = np.nan
                    else:
                        LA_x = float(LA[0])
                        LA_y = float(LA[1])
                        LA_z = float(LA[2])
                if value.lower() == 'nosessions.ra':
                    RA = config[section][value].strip("'").split(',')
                    if RA[0] == 'NaN':
                        RA_x = np.nan
                        RA_y = np.nan
                        RA_z = np.nan
                    else:
                        RA_x = float(RA[0])
                        RA_y = float(RA[1])
                        RA_z = float(RA[2])
                if value.lower() == 'nosessions.lh':
                    LH = config[section][value].strip("'").split(',')
                    if LH[0] == 'NaN':
                        LH_x = np.nan
                        LH_y = np.nan
                        LH_z = np.nan
                    else:
                        LH_x = float(LH[0])
                        LH_y = float(LH[1])
                        LH_z = float(LH[2])
                if value.lower() == 'nosessions.rh':
                    RH = config[section][value].strip("'").split(',')
                    if RH[0] == 'NaN':
                        RH_x = np.nan
                        RH_y = np.nan
                        RH_z = np.nan
                    else:
                        RH_x = float(RH[0])
                        RH_y = float(RH[1])
                        RH_z = float(RH[2])
                if value.lower() == 'nosessions.system':
                    signalSystem = config[section][value].strip("'")

    # =================================================================

    print(
        '======================================================================='
    )
    print('session use: {}'.format(session_id))
    print('age: {}'.format(age))
    print('epilepsy_diagnosis: {}'.format(epilepsyDx))

    nwb_subject = Subject(age=str(age),
                          description=epilepsyDx,
                          sex=sex,
                          species='Human',
                          subject_id=pt_session[:pt_session.find('_')])

    # Create the NWB file
    nwbfile = NWBFile(
        #source='https://datadryad.org/bitstream/handle/10255/dryad.163179/RecogMemory_MTL_release_v2.zip',
        session_description='New/Old recognition task for ID: {}. '.format(
            session_id),
        identifier='{}_{}'.format(ID, session_use),
        session_start_time=finaldate,  #default session start time
        file_create_date=datetime.now(),
        experiment_description=
        'The data contained within this file describes a new/old recogntion task performed in '
        'patients with intractable epilepsy implanted with depth electrodes and Behnke-Fried '
        'microwires in the human Medical Temporal Lobe (MTL).',
        institution=institution,
        keywords=[
            'Intracranial Recordings', 'Intractable Epilepsy',
            'Single-Unit Recordings', 'Cognitive Neuroscience', 'Learning',
            'Memory', 'Neurosurgery'
        ],
        related_publications=
        'Faraut et al. 2018, Scientific Data; Rutishauser et al. 2015, Nat Neurosci;',
        lab='Rutishauser',
        subject=nwb_subject,
        data_collection='learning: {}, recognition: {}'.format(
            session['experiment_id_learn'], session['experiment_id_recog']))

    # Add events and experiment_id acquisition
    events_description = (
        """ The events coorespond to the TTL markers for each trial. For the learning trials, the TTL markers 
            are the following: 55 = start of the experiment, 1 = stimulus ON, 2 = stimulus OFF, 3 = Question Screen Onset [“Is this an animal?”], 
            20 = Yes (21 = NO) during learning, 6 = End of Delay after Response, 66 = End of Experiment. For the recognition trials, 
            the TTL markers are the following: 55 = start of experiment, 1 = stimulus ON, 2 = stimulus OFF, 3 = Question Screen Onset [“Have you seen this image before?”], 
            31:36 = Confidence (Yes vs. No) response [31 (new, confident), 32 (new, probably), 33 (new, guess), 34 (old, guess), 
            35 (old, probably), 36 (old, confident)], 66 = End of Experiment"""
    )

    event_ts = AnnotationSeries(name='events',
                                data=np.asarray(events[1].values).astype(str),
                                timestamps=np.asarray(events[0].values) /
                                TIME_SCALING,
                                description=events_description)

    experiment_ids_description = (
        """The experiment_ids coorespond to the encoding (i.e., learning) or recogniton trials. The learning trials are demarcated by: {}. The recognition trials are demarcated by: {}. """
        .format(experiment_id_learn, experiment_id_recog))

    experiment_ids = TimeSeries(name='experiment_ids',
                                unit='NA',
                                data=np.asarray(events[2]),
                                timestamps=np.asarray(events[0].values) /
                                TIME_SCALING,
                                description=experiment_ids_description)

    nwbfile.add_acquisition(event_ts)
    nwbfile.add_acquisition(experiment_ids)

    # Add stimuli to the NWB file
    # Get the first cell from the cell list
    cell = NOData.pop_cell(session_use,
                           NOData.ls_cells(session_use)[0], path_to_data)
    trials = cell.trials
    stimuli_recog_path = [trial.file_path_recog for trial in trials]
    stimuli_learn_path = [trial.file_path_learn for trial in trials]

    # Add epochs and trials: storing start and end times for a stimulus

    # First extract the category ids and names that we need
    # The metadata for each trials will be store in a trial table

    cat_id_recog = [trial.category_recog for trial in trials]
    cat_name_recog = [trial.category_name_recog for trial in trials]
    cat_id_learn = [trial.category_learn for trial in trials]
    cat_name_learn = [trial.category_name_learn for trial in trials]

    # Extract the event timestamps
    events_learn_stim_on = events[(events[2] == experiment_id_learn) &
                                  (events[1] == NOData.markers['stimulus_on'])]
    events_learn_stim_off = events[(events[2] == experiment_id_learn) & (
        events[1] == NOData.markers['stimulus_off'])]
    events_learn_delay1_off = events[(events[2] == experiment_id_learn) & (
        events[1] == NOData.markers['delay1_off'])]
    events_learn_delay2_off = events[(events[2] == experiment_id_learn) & (
        events[1] == NOData.markers['delay2_off'])]
    events_learn = events[(events[2] == experiment_id_learn)]
    events_learn_response = []
    events_learn_response_time = []
    for i in range(len(events_learn[0])):
        if (events_learn.iloc[i, 1]
                == NOData.markers['response_learning_animal']) or (
                    events_learn.iloc[i, 1]
                    == NOData.markers['response_learning_non_animal']):
            events_learn_response.append(events_learn.iloc[i, 1] - 20)
            events_learn_response_time.append(events_learn.iloc[i, 0])

    events_recog_stim_on = events[(events[2] == experiment_id_recog) &
                                  (events[1] == NOData.markers['stimulus_on'])]
    events_recog_stim_off = events[(events[2] == experiment_id_recog) & (
        events[1] == NOData.markers['stimulus_off'])]
    events_recog_delay1_off = events[(events[2] == experiment_id_recog) & (
        events[1] == NOData.markers['delay1_off'])]
    events_recog_delay2_off = events[(events[2] == experiment_id_recog) & (
        events[1] == NOData.markers['delay2_off'])]
    events_recog = events[(events[2] == experiment_id_recog)]
    events_recog_response = []
    events_recog_response_time = []
    for i in range(len(events_recog[0])):
        if ((events_recog.iloc[i, 1] == NOData.markers['response_1'])
                or (events_recog.iloc[i, 1] == NOData.markers['response_2'])
                or (events_recog.iloc[i, 1] == NOData.markers['response_3'])
                or (events_recog.iloc[i, 1] == NOData.markers['response_4'])
                or (events_recog.iloc[i, 1] == NOData.markers['response_5'])
                or (events_recog.iloc[i, 1] == NOData.markers['response_6'])):
            events_recog_response.append(events_recog.iloc[i, 1])
            events_recog_response_time.append(events_recog.iloc[i, 0])

    # Extract new_old label
    new_old_recog = [trial.new_old_recog for trial in trials]
    # Create the trial tables

    nwbfile.add_trial_column('stim_on_time',
                             'The Time when the Stimulus is Shown')
    nwbfile.add_trial_column('stim_off_time',
                             'The Time when the Stimulus is Off')
    nwbfile.add_trial_column('delay1_time', 'The Time when Delay1 is Off')
    nwbfile.add_trial_column('delay2_time', 'The Time when Delay2 is Off')
    nwbfile.add_trial_column('stim_phase',
                             'Learning/Recognition Phase During the Trial')
    nwbfile.add_trial_column('stimCategory', 'The Category ID of the Stimulus')
    nwbfile.add_trial_column('category_name',
                             'The Category Name of the Stimulus')
    nwbfile.add_trial_column('external_image_file',
                             'The File Path to the Stimulus')
    nwbfile.add_trial_column(
        'new_old_labels_recog',
        '''The Ground truth Labels for New or Old Stimulus. 0 == Old Stimuli 
                            (presented during the learning phase), 1 = New Stimuli (not seen )'during learning phase'''
    )
    nwbfile.add_trial_column('response_value',
                             'The Response for Each Stimulus')
    nwbfile.add_trial_column('response_time',
                             'The Response Time for each Stimulus')

    range_recog = np.amin([
        len(events_recog_stim_on),
        len(events_recog_stim_off),
        len(events_recog_delay1_off),
        len(events_recog_delay2_off)
    ])
    range_learn = np.amin([
        len(events_learn_stim_on),
        len(events_learn_stim_off),
        len(events_learn_delay1_off),
        len(events_learn_delay2_off)
    ])

    # Iterate the event list and add information into each epoch and trial table
    for i in range(range_learn):

        nwbfile.add_trial(
            start_time=(events_learn_stim_on.iloc[i][0]) / (TIME_SCALING),
            stop_time=(events_learn_delay2_off.iloc[i][0]) / (TIME_SCALING),
            stim_on_time=(events_learn_stim_on.iloc[i][0]) / (TIME_SCALING),
            stim_off_time=(events_learn_stim_off.iloc[i][0]) / (TIME_SCALING),
            delay1_time=(events_learn_delay1_off.iloc[i][0]) / (TIME_SCALING),
            delay2_time=(events_learn_delay2_off.iloc[i][0]) / (TIME_SCALING),
            stim_phase='learn',
            stimCategory=cat_id_learn[i],
            category_name=cat_name_learn[i],
            external_image_file=stimuli_learn_path[i],
            new_old_labels_recog='NA',
            response_value=events_learn_response[i],
            response_time=(events_learn_response_time[i]) / (TIME_SCALING))

    for i in range(range_recog):

        nwbfile.add_trial(
            start_time=events_recog_stim_on.iloc[i][0] / (TIME_SCALING),
            stop_time=events_recog_delay2_off.iloc[i][0] / (TIME_SCALING),
            stim_on_time=events_recog_stim_on.iloc[i][0] / (TIME_SCALING),
            stim_off_time=events_recog_stim_off.iloc[i][0] / (TIME_SCALING),
            delay1_time=events_recog_delay1_off.iloc[i][0] / (TIME_SCALING),
            delay2_time=events_recog_delay2_off.iloc[i][0] / (TIME_SCALING),
            stim_phase='recog',
            stimCategory=cat_id_recog[i],
            category_name=cat_name_recog[i],
            external_image_file=stimuli_recog_path[i],
            new_old_labels_recog=new_old_recog[i],
            response_value=events_recog_response[i],
            response_time=events_recog_response_time[i] / (TIME_SCALING))

    # Add the waveform clustering and the spike data.
    # Get the unique channel id that we will be iterate over
    channel_ids = np.unique([cell_id[0] for cell_id in cell_ids])

    # unique unit id
    unit_id = 0

    # Create unit columns
    nwbfile.add_unit_column('origClusterID', 'The original cluster id')
    nwbfile.add_unit_column('waveform_mean_encoding',
                            'The mean waveform for encoding phase.')
    nwbfile.add_unit_column('waveform_mean_recognition',
                            'The mean waveform for the recognition phase.')
    nwbfile.add_unit_column('IsolationDist', 'IsolDist')
    nwbfile.add_unit_column('SNR', 'SNR')
    nwbfile.add_unit_column('waveform_mean_sampling_rate',
                            'The Sampling Rate of Waveform')

    #Add Stimuli
    stimuli_presentation = []

    # Add stimuli learn
    counter = 1
    for path in stimuli_learn_path:
        if path == 'NA':
            continue
        folders = path.split('\\')

        path = os.path.join(path_to_data, 'Stimuli', folders[0], folders[1],
                            folders[2])
        img = cv2.imread(path)
        resized_image = cv2.resize(img, (300, 400))
        stimuli_presentation.append(resized_image)

    # Add stimuli recog
    counter = 1
    for path in stimuli_recog_path:
        folders = path.split('\\')
        path = os.path.join(path_to_data, 'Stimuli', folders[0], folders[1],
                            folders[2])
        img = cv2.imread(path)
        resized_image = cv2.resize(img, (300, 400))
        stimuli_presentation.append(resized_image)
        name = 'stimuli_recog_' + str(counter)

    # Add stimuli to OpticalSeries
    stimulus_presentation_on_time = []

    for n in range(0, len(events_learn_stim_on)):
        stimulus_presentation_on_time.append(events_learn_stim_on.iloc[n][0] /
                                             (TIME_SCALING))

    for n in range(0, len(events_recog_stim_on)):
        stimulus_presentation_on_time.append(events_recog_stim_on.iloc[n][0] /
                                             (TIME_SCALING))

    name = 'StimulusPresentation'
    stimulus = OpticalSeries(name=name,
                             data=stimuli_presentation,
                             timestamps=stimulus_presentation_on_time[:],
                             orientation='lower left',
                             format='raw',
                             unit='meters',
                             field_of_view=[.2, .3, .7],
                             distance=0.7,
                             dimension=[300, 400, 3])

    nwbfile.add_stimulus(stimulus)

    # Get Unit data
    all_spike_cluster_ids = []
    all_selected_time_stamps = []
    all_IsolDist = []
    all_SNR = []
    all_selected_mean_waveform_learn = []
    all_selected_mean_waveform_recog = []
    all_mean_waveform = []
    all_channel_id = []
    all_oriClusterIDs = []
    all_channel_numbers = []
    all_brain_area = []
    # Iterate the channel list

    # load brain area file
    brain_area_file_path = os.path.join(path_to_data, 'Data', 'events',
                                        session['session'], task_descr,
                                        'brainArea.mat')

    try:
        brain_area_mat = loadmat(brain_area_file_path)
    except FileNotFoundError:
        print("brain_area_mat file not found")

    for channel_id in channel_ids:
        cell_name = 'A' + str(channel_id) + '_cells.mat'
        cell_file_path = os.path.join(path_to_data, 'Data', 'sorted',
                                      session['session'], task_descr,
                                      cell_name)

        try:
            cell_mat = loadmat(cell_file_path)
        except FileNotFoundError:
            print("cell mat file not found")
            continue

        spikes = cell_mat['spikes']
        meanWaveform_recog = cell_mat['meanWaveform_recog']
        meanWaveform_learn = cell_mat['meanWaveform_learn']
        IsolDist_SNR = cell_mat['IsolDist_SNR']

        spike_cluster_id = np.asarray([spike[1] for spike in spikes
                                       ])  # Each Cluster ID of the spike
        spike_timestamps = (np.asarray([spike[2] for spike in spikes])) / (
            TIME_SCALING)  # Timestamps of spikes for each ClusterID
        unique_cluster_ids = np.unique(spike_cluster_id)

        # If there are more than one cluster.
        for id in unique_cluster_ids:

            # Grab brain area
            brain_area = extra_brain_area(brain_area_mat, channel_id)

            selected_spike_timestamps = spike_timestamps[spike_cluster_id ==
                                                         id]
            IsolDist, SNR = extract_IsolDist_SNR_by_cluster_id(
                IsolDist_SNR, id)
            selected_mean_waveform_learn = extra_mean_waveform(
                meanWaveform_learn, id)
            selected_mean_waveform_recog = extra_mean_waveform(
                meanWaveform_recog, id)

            # If the mean waveform does not have 256 elements, we set the mean wave form to all 0
            if len(selected_mean_waveform_learn) != 256:
                selected_mean_waveform_learn = np.zeros(256)
            if len(selected_mean_waveform_recog) != 256:
                selected_mean_waveform_recog = np.zeros(256)

            mean_waveform = np.hstack(
                [selected_mean_waveform_learn, selected_mean_waveform_recog])

            # Append unit data
            all_spike_cluster_ids.append(id)
            all_selected_time_stamps.append(selected_spike_timestamps)
            all_IsolDist.append(IsolDist)
            all_SNR.append(SNR)
            all_selected_mean_waveform_learn.append(
                selected_mean_waveform_learn)
            all_selected_mean_waveform_recog.append(
                selected_mean_waveform_recog)
            all_mean_waveform.append(mean_waveform)
            all_channel_id.append(channel_id)
            all_oriClusterIDs.append(int(id))
            all_channel_numbers.append(channel_id)
            all_brain_area.append(brain_area)

            unit_id += 1

    nwbfile.add_electrode_column(
        name='origChannel',
        description='The original channel ID for the channel')

    #Add Device
    device = nwbfile.create_device(name=signalSystem)

    # Add Electrodes (brain Area Locations, MNI coordinates for microwires)
    length_all_spike_cluster_ids = len(all_spike_cluster_ids)
    for electrodeNumber in range(0, len(channel_ids)):

        brainArea_location = extra_brain_area(brain_area_mat,
                                              channel_ids[electrodeNumber])

        if brainArea_location == 'RH':  #  Right Hippocampus
            full_brainArea_Location = 'Right Hippocampus'

            electrode_name = '{}-microwires-{}'.format(
                signalSystem, channel_ids[electrodeNumber])
            description = "Behnke Fried/Micro Inner Wire Bundle (Behnke-Fried BF08R-SP05X-000 and WB09R-SP00X-0B6; Ad-Tech Medical)"
            location = full_brainArea_Location

            # Add electrode group
            electrode_group = nwbfile.create_electrode_group(
                electrode_name,
                description=description,
                location=location,
                device=device)

            #Add Electrode
            nwbfile.add_electrode([channel_ids[electrodeNumber]],
                                  x=RH_x,
                                  y=RH_y,
                                  z=RH_z,
                                  imp=np.nan,
                                  location=full_brainArea_Location,
                                  filtering='300-3000Hz',
                                  group=electrode_group,
                                  origChannel=channel_ids[electrodeNumber])

        if brainArea_location == 'LH':
            full_brainArea_Location = 'Left Hippocampus'

            electrode_name = '{}-microwires-{}'.format(
                signalSystem, channel_ids[electrodeNumber])
            description = "Behnke Fried/Micro Inner Wire Bundle (Behnke-Fried BF08R-SP05X-000 and WB09R-SP00X-0B6; Ad-Tech Medical)"
            location = full_brainArea_Location

            # Add electrode group
            electrode_group = nwbfile.create_electrode_group(
                electrode_name,
                description=description,
                location=location,
                device=device)

            nwbfile.add_electrode([all_channel_id[electrodeNumber]],
                                  x=LH_x,
                                  y=LH_y,
                                  z=LH_z,
                                  imp=np.nan,
                                  location=full_brainArea_Location,
                                  filtering='300-3000Hz',
                                  group=electrode_group,
                                  origChannel=channel_ids[electrodeNumber])
        if brainArea_location == 'RA':
            full_brainArea_Location = 'Right Amygdala'

            electrode_name = '{}-microwires-{}'.format(
                signalSystem, channel_ids[electrodeNumber])
            description = "Behnke Fried/Micro Inner Wire Bundle (Behnke-Fried BF08R-SP05X-000 and WB09R-SP00X-0B6; Ad-Tech Medical)"
            location = full_brainArea_Location

            # Add electrode group
            electrode_group = nwbfile.create_electrode_group(
                electrode_name,
                description=description,
                location=location,
                device=device)

            nwbfile.add_electrode([all_channel_id[electrodeNumber]],
                                  x=RA_x,
                                  y=RA_y,
                                  z=RA_z,
                                  imp=np.nan,
                                  location=full_brainArea_Location,
                                  filtering='300-3000Hz',
                                  group=electrode_group,
                                  origChannel=channel_ids[electrodeNumber])
        if brainArea_location == 'LA':
            full_brainArea_Location = 'Left Amygdala'

            electrode_name = '{}-microwires-{}'.format(
                signalSystem, channel_ids[electrodeNumber])
            description = "Behnke Fried/Micro Inner Wire Bundle (Behnke-Fried BF08R-SP05X-000 and WB09R-SP00X-0B6; Ad-Tech Medical)"
            location = full_brainArea_Location

            # Add electrode group
            electrode_group = nwbfile.create_electrode_group(
                electrode_name,
                description=description,
                location=location,
                device=device)

            nwbfile.add_electrode([all_channel_id[electrodeNumber]],
                                  x=LA_x,
                                  y=LA_y,
                                  z=LA_z,
                                  imp=np.nan,
                                  location=full_brainArea_Location,
                                  filtering='300-3000Hz',
                                  group=electrode_group,
                                  origChannel=channel_ids[electrodeNumber])

    # Create Channel list index
    channel_list = list(range(0, length_all_spike_cluster_ids))
    unique_channel_ids = np.unique(all_channel_id)
    length_ChannelIds = len(np.unique(all_channel_id))
    for yy in range(0, length_ChannelIds):
        a = np.array(np.where(unique_channel_ids[yy] == all_channel_id))
        b = a[0]
        c = b.tolist()
        for i in c:
            channel_list[i] = yy

    #Add WAVEFORM Sampling RATE
    waveform_mean_sampling_rate = [98.4 * 10**3]
    waveform_mean_sampling_rate_matrix = [waveform_mean_sampling_rate
                                          ] * (length_all_spike_cluster_ids)

    # Add Units to NWB file
    for index_id in range(0, length_all_spike_cluster_ids):
        nwbfile.add_unit(
            id=index_id,
            spike_times=all_selected_time_stamps[index_id],
            origClusterID=all_oriClusterIDs[index_id],
            IsolationDist=all_IsolDist[index_id],
            SNR=all_SNR[index_id],
            waveform_mean_encoding=all_selected_mean_waveform_learn[index_id],
            waveform_mean_recognition=all_selected_mean_waveform_recog[
                index_id],
            electrodes=[channel_list[index_id]],
            waveform_mean_sampling_rate=waveform_mean_sampling_rate_matrix[
                index_id])

    return nwbfile
Beispiel #24
0
elec_inds = []
for i, (elec_id, elec_label) in tqdm(enumerate(elecs)):
    if elec_label[:4] == 'ainp':
        electrode_group = ainp_electrode_group
    else:
        electrode_group = elec_electrode_group
        elecs_data = nev_file.getdata([elec_id])
        spikes = (np.array(elecs_data['spike_events']['TimeStamps'][0]) /
                  30000).tolist()
        elec_inds.append(i)
        ut.add_spike_times(elec_id, spikes)
    nwbfile.add_electrode(
        elec_id,
        np.nan,
        np.nan,
        np.nan,  # position?
        imp=np.nan,
        location='unknown',
        filtering='unknown',
        description='description',
        group=electrode_group)

all_table_region = nwbfile.create_electrode_table_region(
    elec_inds, 'all_electrodes')
print('done.')

# lfp
print('reading LFPs...', end='', flush=True)

print('done.')

print('making ElectricalSeries objects for LFP...', end='', flush=True)
Beispiel #25
0
class ProcessingDataTestCase(unittest.TestCase):

    def setUp(self):
        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 = self.nwbfile.create_device(name='trodes_rig123')

        electrode_name = 'tetrode1'
        description = "an example tetrode"
        location = "somewhere in the hippocampus"

        electrode_group = self.nwbfile.create_electrode_group(
            electrode_name,
            description=description,
            location=location,
            device=device
        )

        for idx in [1, 2, 3, 4]:
            self.nwbfile.add_electrode(
                id=idx,
                x=1.0, y=2.0, z=3.0,
                imp=float(-idx),
                location='CA1', filtering='none',
                group=electrode_group
            )

        electrode_table_region = self.nwbfile.create_electrode_table_region([0, 2], 'the first and third electrodes')

        rate = 5.0
        np.random.seed(1234)
        data_len = 50
        ephys_data = np.array([[0.76711663, 0.70811536],
                               [0.79686718, 0.55776083],
                               [0.96583653, 0.1471569],
                               [0.029647, 0.59389349],
                               [0.1140657, 0.95080985],
                               [0.32570741, 0.19361869],
                               [0.45781165, 0.92040257],
                               [0.87906916, 0.25261576],
                               [0.34800879, 0.18258873],
                               [0.90179605, 0.70652816],
                               [0.72665846, 0.90008784],
                               [0.7791638, 0.59915478],
                               [0.29112524, 0.15139526],
                               [0.33517466, 0.65755178],
                               [0.07334254, 0.0550064],
                               [0.32319481, 0.5904818],
                               [0.85389857, 0.28706243],
                               [0.17306723, 0.13402121],
                               [0.99465383, 0.17949787],
                               [0.31754682, 0.5682914],
                               [0.00934857, 0.90064862],
                               [0.97724143, 0.55689468],
                               [0.08477384, 0.33300247],
                               [0.72842868, 0.14243537],
                               [0.55246894, 0.27304326],
                               [0.97449514, 0.66778691],
                               [0.25565329, 0.10831149],
                               [0.77618072, 0.78247799],
                               [0.76160391, 0.91440311],
                               [0.65862278, 0.56836758],
                               [0.20175569, 0.69829638],
                               [0.95219541, 0.88996329],
                               [0.99356736, 0.81870351],
                               [0.54512217, 0.45125405],
                               [0.89055719, 0.97326479],
                               [0.59341133, 0.3660745],
                               [0.32309469, 0.87142326],
                               [0.21563406, 0.73494519],
                               [0.36561909, 0.8016026],
                               [0.78273559, 0.70135538],
                               [0.62277659, 0.49368265],
                               [0.8405377, 0.71209699],
                               [0.44390898, 0.03103486],
                               [0.36323976, 0.73072179],
                               [0.47556657, 0.34441697],
                               [0.64088043, 0.12620532],
                               [0.17146526, 0.73708649],
                               [0.12702939, 0.36964987],
                               [0.604334, 0.10310444],
                               [0.80237418, 0.94555324]])
        ephys_timestamps = np.arange(data_len) / rate

        ephys_ts = ElectricalSeries('preprocessed',
                                    ephys_data,
                                    electrode_table_region,
                                    starting_time=ephys_timestamps[0],
                                    rate=rate,
                                    resolution=0.001,
                                    comments="This data was randomly generated with numpy, using 1234 as the seed",
                                    description="Random numbers generated with numpy.random.rand")

        lfp = LFP(ephys_ts)

        self.nwbfile.create_processing_module(
            name='ecephys',
            description='preprocessed ecephys data'
        )

        self.nwbfile.processing['ecephys'].add(lfp)

        self.nwbfile_new = 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'
        )

    def test_high_gamma_estimation(self):
        with NWBHDF5IO('ecephys_exmpl_gamma.nwb', 'w') as io:
            io.write(self.nwbfile)

        bands_vals = np.random.rand(2, 10) * 80 + 70
        high_gamma_estimation('ecephys_exmpl_gamma.nwb', bands_vals)

        io = NWBHDF5IO('ecephys_exmpl_gamma.nwb', 'r')
        nwbfile_in = io.read()

        high_gamma_data = nwbfile_in.processing['ecephys'].data_interfaces['high_gamma'].data[:]
        high_gamma_data_expected = np.array([[114432.12734375, 106926.36953125],
                                             [104311.51640625, 81010.54921875],
                                             [158632.765625, 29015.66972656],
                                             [87235.18125, 109977.53828125],
                                             [40694.96054688, 143791.29375],
                                             [39189.63359375, 24476.98222656],
                                             [99898.77265625, 131793.8921875],
                                             [116746.00546875, 82916.5953125],
                                             [56977.66171875, 55775.99765625],
                                             [122025.39375, 100550.2734375],
                                             [110798.99609375, 128243.16484375],
                                             [110201.42265625, 118032.4765625],
                                             [73953.45234375, 22560.153125],
                                             [41865.0109375, 95126.09453125],
                                             [23743.01894531, 19107.33242187],
                                             [85232.5453125, 83586.396875],
                                             [127444.34921875, 60134.734375],
                                             [17301.87333984, 21913.7796875],
                                             [153644.3453125, 44228.69492188],
                                             [108004.7703125, 107790.89140625],
                                             [92584.2421875, 128566.275],
                                             [130929.23828125, 82646.0515625],
                                             [22233.11679688, 52573.65625],
                                             [106470.29765625, 17475.74941406],
                                             [89623.346875, 73826.7125],
                                             [129937.9359375, 93547.39375],
                                             [44125.3484375, 34720.43320313],
                                             [115818.246875, 149635.4359375],
                                             [114519.30625, 130255.1828125],
                                             [87249.54921875, 79923.99765625],
                                             [35482.24257812, 102406.0171875],
                                             [149241.865625, 126403.61484375],
                                             [155159.1921875, 123572.7953125],
                                             [68665.5015625, 63900.49492187],
                                             [133760.8578125, 139165.9765625],
                                             [97677.2953125, 51414.00859375],
                                             [64852.78320312, 129346.84296875],
                                             [24607.39375, 106858.39453125],
                                             [72500.85078125, 114212.22421875],
                                             [103932.5, 117112.81796875],
                                             [93862.08828125, 70807.0515625],
                                             [112166.11640625, 120027.41953125],
                                             [86554.1046875, 19128.88339844],
                                             [43686.26601562, 101883.1171875],
                                             [73509.96875, 82221.49609375],
                                             [85105.04296875, 32386.06582031],
                                             [52379.96210938, 107256.77421875],
                                             [49256.02304688, 69351.2296875],
                                             [106910.11328125, 53854.99570313],
                                             [108948.4109375, 138653.6015625]])

        np.testing.assert_almost_equal(high_gamma_data, high_gamma_data_expected)

        # Remove test nwb files
        io.close()
        os.remove('ecephys_exmpl_gamma.nwb')

    def test_spectral_decomposition(self):
        with NWBHDF5IO('ecephys_exmpl_decomp.nwb', 'w') as io:
            io.write(self.nwbfile)

        bands_vals = np.random.rand(2, 10) * 80 + 70
        spectral_decomposition('ecephys_exmpl_decomp.nwb', bands_vals)

        io = NWBHDF5IO('ecephys_exmpl_decomp.nwb', 'r')
        nwbfile_in = io.read()

        decomposition_data = nwbfile_in.processing['ecephys'].data_interfaces['DecompositionSeries'].data[:]
        decomposition_data_expected = np.array([[[114617.296875  , 114486.0078125 , 114848.0546875 ,
                                             114675.953125  , 114086.171875  , 114826.0546875 ,
                                             114754.0390625 , 112567.6015625 , 114651.6171875 ,
                                             114808.4765625 ],
                                            [107103.5859375 , 106978.0390625 , 107322.3828125 ,
                                             107158.4609375 , 106597.3828125 , 107301.71875   ,
                                             107233.3046875 , 105149.265625  , 107135.1796875 ,
                                             107284.375     ]],

                                           [[104542.0625    , 104378.6796875 , 104826.75      ,
                                             104613.4453125 , 103883.40625   , 104799.859375  ,
                                             104710.84375   , 101999.6953125 , 104583.140625  ,
                                             104777.28125   ],
                                            [ 81147.546875  ,  81050.4140625 ,  81318.34375   ,
                                              81190.9921875 ,  80754.515625  ,  81302.0625    ,
                                              81248.7578125 ,  79630.8046875 ,  81172.984375  ,
                                              81289.0703125 ]],

                                           [[158760.78125   , 158670.578125  , 158918.875     ,
                                             158800.859375  , 158395.78125   , 158903.84375   ,
                                             158854.5       , 157346.59375   , 158784.15625   ,
                                             158891.6875    ],
                                            [ 29102.65429688,  29037.88867188,  29218.96875   ,
                                              29132.79296875,  28841.1015625 ,  29207.6640625 ,
                                              29171.3984375 ,  28124.09765625,  29120.74609375,
                                              29199.38476562]],

                                           [[ 87250.3984375 ,  87238.7890625 ,  87270.2734375 ,
                                              87255.125     ,  87204.71875   ,  87268.4453125 ,
                                              87262.1640625 ,  87082.296875  ,  87252.953125  ,
                                              87266.6484375 ],
                                            [110059.9453125 , 110001.0390625 , 110163.3046875 ,
                                             110086.0859375 , 109822.2578125 , 110153.4765625 ,
                                             110121.1796875 , 109147.4453125 , 110075.15625   ,
                                             110145.4921875 ]],

                                           [[ 40677.609375  ,  40688.921875  ,  40660.45703125,
                                              40674.203125  ,  40721.69921875,  40661.8203125 ,
                                              40667.31640625,  40857.2578125 ,  40676.30078125,
                                              40664.01953125],
                                            [143883.140625  , 143818.203125  , 143998.140625  ,
                                             143912.75      , 143619.421875  , 143987.09375   ,
                                             143951.265625  , 142863.53125   , 143900.71875   ,
                                             143978.671875  ]],

                                           [[ 39313.33984375,  39225.09765625,  39468.546875  ,
                                              39352.76171875,  38956.734375  ,  39453.74609375,
                                              39405.29296875,  37942.51171875,  39336.39453125,
                                              39441.91015625],
                                            [ 24713.640625  ,  24545.43945312,  25007.27539062,
                                              24787.41992188,  24035.4765625 ,  24979.49609375,
                                              24887.69726562,  22100.8046875 ,  24756.22070312,
                                              24956.3515625 ]],

                                           [[100002.8828125 ,  99928.78125   , 100133.0078125 ,
                                             100035.8671875 ,  99703.484375  , 100120.6171875 ,
                                             100079.984375  ,  98850.34375   , 100022.125     ,
                                             100110.6328125 ],
                                            [131870.265625  , 131816.25      , 131966.625     ,
                                             131895.34375   , 131650.25      , 131957.296875  ,
                                             131927.3125    , 131019.75      , 131885.34375   ,
                                             131950.484375  ]],

                                           [[116872.1015625 , 116782.671875  , 117029.625     ,
                                             116912.2734375 , 116510.015625  , 117014.5703125 ,
                                             116965.4296875 , 115474.9765625 , 116895.6953125 ,
                                             117002.6953125 ],
                                            [ 82944.453125  ,  82923.578125  ,  82981.71875   ,
                                              82954.        ,  82860.5       ,  82978.125     ,
                                              82966.4765625 ,  82631.6171875 ,  82950.109375  ,
                                              82975.375     ]],

                                           [[ 57186.56640625,  57038.0390625 ,  57446.73828125,
                                              57252.28515625,  56586.92578125,  57422.03125   ,
                                              57340.75390625,  54876.6953125 ,  57224.73828125,
                                              57401.84375   ],
                                            [ 55797.07421875,  55780.6328125 ,  55827.8203125 ,
                                              55805.421875  ,  55730.19921875,  55824.71875   ,
                                              55815.1796875 ,  55553.68359375,  55802.35546875,
                                              55822.890625  ]],

                                           [[122179.578125  , 122070.3828125 , 122371.640625  ,
                                             122228.4609375 , 121737.5859375 , 122353.3125    ,
                                             122293.3828125 , 120472.625     , 122208.2265625 ,
                                             122338.7421875 ],
                                            [100709.890625  , 100597.0078125 , 100906.890625  ,
                                             100759.4375    , 100254.3125    , 100888.25      ,
                                             100826.6875    ,  98948.984375  , 100738.515625  ,
                                             100872.7578125 ]],

                                           [[111004.203125  , 110858.9453125 , 111257.671875  ,
                                             111067.921875  , 110418.1171875 , 111233.6953125 ,
                                             111154.46875   , 108740.2109375 , 111040.9921875 ,
                                             111213.734375  ],
                                            [128413.328125  , 128293.0390625 , 128622.9921875 ,
                                             128465.96875   , 127928.0546875 , 128603.1796875 ,
                                             128537.640625  , 126537.171875  , 128443.6640625 ,
                                             128586.609375  ]],

                                           [[110364.5078125 , 110249.078125  , 110566.71875   ,
                                             110415.6640625 , 109898.        , 110547.5078125 ,
                                             110484.359375  , 108562.234375  , 110394.2734375 ,
                                             110531.8828125 ],
                                            [118127.28125   , 118059.953125  , 118246.0234375 ,
                                             118157.609375  , 117854.6171875 , 118234.6640625 ,
                                             118197.625     , 117076.1171875 , 118145.125     ,
                                             118225.75      ]],

                                           [[ 74073.4375    ,  73988.0078125 ,  74223.2578125 ,
                                              74111.3359375 ,  73728.4921875 ,  74209.015625  ,
                                              74162.21875   ,  72745.828125  ,  74095.4921875 ,
                                              74197.4375    ],
                                            [ 22709.97460938,  22600.88867188,  22901.94335938,
                                              22758.49414062,  22270.98046875,  22883.65429688,
                                              22823.63867188,  21044.90234375,  22738.22460938,
                                              22868.83007812]],

                                           [[ 41966.58984375,  41894.28125   ,  42094.3046875 ,
                                              41999.265625  ,  41673.734375  ,  42082.0703125 ,
                                              42042.2421875 ,  40839.22265625,  41985.859375  ,
                                              42072.5390625 ],
                                            [ 95182.1796875 ,  95142.4609375 ,  95253.84375   ,
                                              95201.140625  ,  95019.671875  ,  95246.8203125 ,
                                              95224.578125  ,  94554.421875  ,  95193.7890625 ,
                                              95242.0390625 ]],

                                           [[ 23771.328125  ,  23749.13085938,  23813.07421875,
                                              23782.74023438,  23680.88867188,  23808.84179688,
                                              23795.90429688,  23443.24414062,  23778.60351562,
                                              23806.43359375],
                                            [ 19185.515625  ,  19125.25195312,  19292.16796875,
                                              19212.27539062,  18945.38671875,  19281.98632812,
                                              19248.54492188,  18307.54296875,  19201.01953125,
                                              19273.6328125 ]],

                                           [[ 85284.265625  ,  85247.        ,  85349.34375   ,
                                              85300.5625    ,  85134.46875   ,  85343.1953125 ,
                                              85322.828125  ,  84712.125     ,  85293.640625  ,
                                              85338.0234375 ],
                                            [ 83637.5546875 ,  83601.1953125 ,  83702.796875  ,
                                              83654.65625   ,  83489.2578125 ,  83696.4453125 ,
                                              83676.171875  ,  83066.0234375 ,  83647.921875  ,
                                              83691.9453125 ]],

                                           [[127513.3359375 , 127464.5703125 , 127600.4453125 ,
                                             127536.0546875 , 127314.578125  , 127591.9921875 ,
                                             127564.9140625 , 126744.6875    , 127527.03125   ,
                                             127585.8828125 ],
                                            [ 60189.546875  ,  60150.15625   ,  60258.734375  ,
                                              60207.04296875,  60030.73046875,  60252.1484375 ,
                                              60230.53125   ,  59581.91796875,  60199.73046875,
                                              60246.8046875 ]],

                                           [[ 17533.41601562,  17367.984375  ,  17821.8203125 ,
                                              17605.61914062,  16867.51171875,  17794.5859375 ,
                                              17704.36328125,  14976.88574219,  17574.91601562,
                                              17771.63085938],
                                            [ 21968.08984375,  21928.48046875,  22039.79296875,
                                              21987.00195312,  21806.87304688,  22032.7578125 ,
                                              22010.47265625,  21356.734375  ,  21979.65234375,
                                              22027.94140625]],

                                           [[153698.0625    , 153660.21875   , 153766.09375   ,
                                             153715.984375  , 153543.28125   , 153759.453125  ,
                                             153738.328125  , 153098.21875   , 153708.984375  ,
                                             153754.828125  ],
                                            [ 44348.2734375 ,  44263.34765625,  44496.57421875,
                                              44385.5625    ,  44005.76953125,  44482.5390625 ,
                                              44436.18359375,  43028.01171875,  44369.8125    ,
                                              44470.875     ]],

                                           [[107953.4140625 , 107989.0078125 , 107892.7265625 ,
                                             107938.625     , 108096.3984375 , 107898.328125  ,
                                             107917.359375  , 108513.078125  , 107945.21875   ,
                                             107903.546875  ],
                                            [107917.4453125 , 107827.84375   , 108073.8515625 ,
                                             107956.78125   , 107555.8828125 , 108059.0546875 ,
                                             108010.171875  , 106520.953125  , 107940.171875  ,
                                             108046.7578125 ]],

                                           [[ 92517.5078125 ,  92563.8515625 ,  92438.5234375 ,
                                              92498.2890625 ,  92703.546875  ,  92445.8125    ,
                                              92470.5859375 ,  93244.8046875 ,  92506.875     ,
                                              92452.625     ],
                                            [128713.953125  , 128609.6796875 , 128895.9609375 ,
                                             128759.765625  , 128292.9296875 , 128878.734375  ,
                                             128821.859375  , 127084.9765625 , 128740.4375    ,
                                             128864.453125  ]],

                                           [[130982.6796875 , 130944.7890625 , 131050.984375  ,
                                             131000.7265625 , 130827.75      , 131044.296875  ,
                                             131023.09375   , 130384.6328125 , 130993.7109375 ,
                                             131039.71875   ],
                                            [ 82797.28125   ,  82690.0703125 ,  82984.3359375 ,
                                              82844.2734375 ,  82364.875     ,  82966.6484375 ,
                                              82908.171875  ,  81128.578125  ,  82824.390625  ,
                                              82951.890625  ]],

                                           [[ 22414.328125  ,  22282.98828125,  22645.05664062,
                                              22472.5625    ,  21885.6171875 ,  22623.109375  ,
                                              22550.97460938,  20403.16015625,  22448.16601562,
                                              22605.20507812],
                                            [ 52676.65234375,  52603.47265625,  52805.58984375,
                                              52709.52734375,  52380.4453125 ,  52793.26953125,
                                              52753.04296875,  51535.05859375,  52695.9609375 ,
                                              52783.54296875]],

                                           [[106585.1015625 , 106503.6953125 , 106729.59375   ,
                                             106622.390625  , 106254.421875  , 106715.6796875 ,
                                             106670.6796875 , 105308.921875  , 106607.3125    ,
                                             106705.1796875 ],
                                            [ 17574.67382812,  17503.72851562,  17700.84960938,
                                              17607.23046875,  17286.98242188,  17688.6796875 ,
                                              17649.3671875 ,  16472.38476562,  17594.07421875,
                                              17679.5234375 ]],

                                           [[ 89841.609375  ,  89687.        ,  90110.859375  ,
                                              89909.0625    ,  89218.390625  ,  90085.453125  ,
                                              90001.2578125 ,  87435.40625   ,  89880.390625  ,
                                              90064.0390625 ],
                                            [ 73912.234375  ,  73851.3359375 ,  74018.96875   ,
                                              73939.203125  ,  73666.40625   ,  74008.828125  ,
                                              73975.484375  ,  72966.203125  ,  73927.90625   ,
                                              74000.5546875 ]],

                                           [[130067.0703125 , 129975.640625  , 130228.828125  ,
                                             130108.625     , 129696.0546875 , 130213.296875  ,
                                             130162.890625  , 128633.890625  , 130091.6875    ,
                                             130201.375     ],
                                            [ 93639.2421875 ,  93574.015625  ,  93754.9921875 ,
                                              93669.09375   ,  93374.3984375 ,  93743.8515625 ,
                                              93707.796875  ,  92618.125     ,  93657.        ,
                                              93735.421875  ]],

                                           [[ 44317.23046875,  44179.5078125 ,  44558.93359375,
                                              44378.296875  ,  43761.9453125 ,  44535.953125  ,
                                              44460.421875  ,  42191.2265625 ,  44352.734375  ,
                                              44517.234375  ],
                                            [ 34893.8828125 ,  34768.875     ,  35112.75      ,
                                              34948.90234375,  34390.81640625,  35092.        ,
                                              35023.546875  ,  32973.06640625,  34925.6875    ,
                                              35074.8046875 ]],

                                           [[115943.078125  , 115854.3359375 , 116100.1015625 ,
                                             115983.3828125 , 115583.28125   , 116085.03125   ,
                                             116036.0859375 , 114556.8125    , 115966.9296875 ,
                                             116073.4296875 ],
                                            [149762.703125  , 149672.703125  , 149920.90625   ,
                                             149802.953125  , 149398.375     , 149905.828125  ,
                                             149856.453125  , 148354.34375   , 149786.28125   ,
                                             149893.8125    ]],

                                           [[114704.3125    , 114573.2890625 , 114933.1640625 ,
                                             114761.9296875 , 114175.5       , 114911.4921875 ,
                                             114839.9765625 , 112662.2109375 , 114737.6328125 ,
                                             114893.5546875 ],
                                            [130433.8984375 , 130307.078125  , 130655.90625   ,
                                             130489.953125  , 129921.8046875 , 130634.8359375 ,
                                             130565.484375  , 128458.859375  , 130466.4296875 ,
                                             130617.578125  ]],

                                           [[ 87400.578125  ,  87293.3515625 ,  87589.6875    ,
                                              87448.890625  ,  86966.3125    ,  87571.6015625 ,
                                              87512.6171875 ,  85726.0234375 ,  87429.015625  ,
                                              87557.4140625 ],
                                            [ 80134.59375   ,  79984.9296875 ,  80397.6875    ,
                                              80201.4296875 ,  79529.4140625 ,  80372.609375  ,
                                              80290.484375  ,  77802.6015625 ,  80173.6875    ,
                                              80352.5390625 ]],

                                           [[ 35690.89453125,  35542.4765625 ,  35951.64453125,
                                              35757.0625    ,  35091.03125   ,  35926.8046875 ,
                                              35845.39453125,  33380.73046875,  35729.5390625 ,
                                              35906.84765625],
                                            [102604.6484375 , 102463.7421875 , 102852.3125    ,
                                             102667.59375   , 102034.6796875 , 102828.7109375 ,
                                             102751.40625   , 100405.78125   , 102641.46875   ,
                                             102809.828125  ]],

                                           [[149377.171875  , 149281.203125  , 149545.625     ,
                                             149419.890625  , 148989.1875    , 149529.59375   ,
                                             149477.        , 147880.203125  , 149402.109375  ,
                                             149516.671875  ],
                                            [126608.765625  , 126463.4140625 , 126863.078125  ,
                                             126672.953125  , 126021.7578125 , 126838.9609375 ,
                                             126759.5078125 , 124342.5390625 , 126646.0078125 ,
                                             126819.1640625 ]],

                                           [[155320.53125   , 155206.171875  , 155521.375     ,
                                             155371.515625  , 154858.015625  , 155502.25      ,
                                             155439.546875  , 153535.328125  , 155350.3125    ,
                                             155486.875     ],
                                            [123725.328125  , 123616.875     , 123916.859375  ,
                                             123774.3359375 , 123285.9921875 , 123898.515625  ,
                                             123838.78125   , 122032.8046875 , 123754.234375  ,
                                             123884.2265625 ]],

                                           [[ 68918.1328125 ,  68738.6953125 ,  69232.140625  ,
                                              68997.3515625 ,  68193.828125  ,  69202.359375  ,
                                              69104.25      ,  66126.2890625 ,  68964.0703125 ,
                                              69177.8984375 ],
                                            [ 64116.609375  ,  63962.26171875,  64387.06640625,
                                              64184.87109375,  63494.01953125,  64361.3828125 ,
                                              64276.8671875 ,  61725.27734375,  64156.234375  ,
                                              64340.359375  ]],

                                           [[133915.78125   , 133806.109375  , 134108.9375    ,
                                             133965.0625    , 133471.5625    , 134090.484375  ,
                                             134030.234375  , 132199.734375  , 133944.734375  ,
                                             134075.9375    ],
                                            [139290.890625  , 139202.421875  , 139448.03125   ,
                                             139331.515625  , 138931.3125    , 139432.875     ,
                                             139383.953125  , 137902.109375  , 139315.125     ,
                                             139421.53125   ]],

                                           [[ 97851.0859375 ,  97727.8515625 ,  98066.171875  ,
                                              97905.1484375 ,  97354.0078125 ,  98045.828125  ,
                                              97978.59375   ,  95933.09375   ,  97882.2890625 ,
                                              98028.8828125 ],
                                            [ 51638.5703125 ,  51478.11328125,  51919.62109375,
                                              51709.453125  ,  50991.50390625,  51892.9453125 ,
                                              51805.109375  ,  49154.03515625,  51679.6796875 ,
                                              51871.0546875 ]],

                                           [[ 64976.17578125,  64888.53125   ,  65130.69921875,
                                              65015.62109375,  64621.30078125,  65115.921875  ,
                                              65067.71875   ,  63608.1796875 ,  64999.375     ,
                                              65104.30859375],
                                            [129480.15625   , 129385.4375    , 129648.0390625 ,
                                             129523.3671875 , 129095.8125    , 129631.8984375 ,
                                             129579.5859375 , 127998.71875   , 129505.8125    ,
                                             129619.6015625 ]],

                                           [[ 24721.80273438,  24639.79296875,  24867.24804688,
                                              24759.17382812,  24389.60351562,  24853.25976562,
                                              24807.91601562,  23448.61328125,  24743.96484375,
                                              24842.5625    ],
                                            [107061.8515625 , 106917.234375  , 107315.234375  ,
                                             107125.8828125 , 106477.8984375 , 107291.171875  ,
                                             107212.0234375 , 104812.0546875 , 107099.0625    ,
                                             107271.53125   ]],

                                           [[ 72607.0625    ,  72531.4296875 ,  72740.0078125 ,
                                              72640.8125    ,  72301.3828125 ,  72727.3359375 ,
                                              72685.828125  ,  71430.6796875 ,  72626.7890625 ,
                                              72717.1796875 ],
                                            [114398.0078125 , 114266.        , 114629.921875  ,
                                             114456.875     , 113864.3359375 , 114607.828125  ,
                                             114535.4296875 , 112341.3515625 , 114432.3984375 ,
                                             114590.09375   ]],

                                           [[104087.21875   , 103977.6953125 , 104279.203125  ,
                                             104135.8359375 , 103644.46875   , 104260.953125  ,
                                             104201.0078125 , 102376.9296875 , 104115.53125   ,
                                             104246.15625   ],
                                            [117260.9921875 , 117155.6328125 , 117446.8359375 ,
                                             117308.4453125 , 116834.40625   , 117429.0546875 ,
                                             117371.0859375 , 115617.7109375 , 117288.9140625 ,
                                             117415.1015625 ]],

                                           [[ 94057.4609375 ,  93919.03125   ,  94299.5625    ,
                                              94118.53125   ,  93498.515625  ,  94276.609375  ,
                                              94200.96875   ,  91899.6015625 ,  94092.8671875 ,
                                              94257.734375  ],
                                            [ 71002.0078125 ,  70863.09375   ,  71245.2421875 ,
                                              71063.375     ,  70441.546875  ,  71222.1640625 ,
                                              71146.15625   ,  68846.09375   ,  71037.609375  ,
                                              71203.2265625 ]],

                                           [[112330.8515625 , 112214.2421875 , 112535.1953125 ,
                                             112382.5703125 , 111859.5234375 , 112515.7734375 ,
                                             112451.96875   , 110510.0703125 , 112360.9609375 ,
                                             112500.0078125 ],
                                            [120118.9453125 , 120054.171875  , 120234.0859375 ,
                                             120148.75      , 119855.546875  , 120222.9765625 ,
                                             120187.1328125 , 119101.140625  , 120136.75      ,
                                             120214.6953125 ]],

                                           [[ 86687.7578125 ,  86592.7578125 ,  86854.5859375 ,
                                              86730.0703125 ,  86303.8046875 ,  86838.703125  ,
                                              86786.609375  ,  85208.390625  ,  86712.453125  ,
                                              86825.9140625 ],
                                            [ 19218.1953125 ,  19147.984375  ,  19342.8671875 ,
                                              19249.48046875,  18939.14648438,  19330.9375    ,
                                              19291.82226562,  18210.8515625 ,  19236.34765625,
                                              19321.20117188]],

                                           [[ 43832.3671875 ,  43728.375     ,  44015.71875   ,
                                              43879.14453125,  43411.4921875 ,  43998.1875    ,
                                              43940.984375  ,  42212.13671875,  43859.8671875 ,
                                              43984.38671875],
                                            [101950.578125  , 101902.671875  , 102035.890625  ,
                                             101972.703125  , 101755.78125   , 102027.6484375 ,
                                             102001.09375   , 101199.4296875 , 101963.828125  ,
                                             102021.546875  ]],

                                           [[ 73639.2578125 ,  73547.5625    ,  73800.359375  ,
                                              73680.1796875 ,  73268.3984375 ,  73785.0078125 ,
                                              73734.7265625 ,  72208.3046875 ,  73663.1796875 ,
                                              73772.7109375 ],
                                            [ 82278.609375  ,  82237.65625   ,  82350.9765625 ,
                                              82297.09375   ,  82112.9921875 ,  82344.0390625 ,
                                              82321.4609375 ,  81644.0078125 ,  82289.5       ,
                                              82338.625     ]],

                                           [[ 85226.90625   ,  85140.6953125 ,  85377.8125    ,
                                              85265.0390625 ,  84878.5546875 ,  85363.4921875 ,
                                              85316.359375  ,  83880.734375  ,  85249.0546875 ,
                                              85351.78125   ],
                                            [ 32416.81445312,  32392.0703125 ,  32461.36914062,
                                              32428.15625   ,  32318.44140625,  32457.04882812,
                                              32443.0859375 ,  32066.41992188,  32423.52148438,
                                              32453.73046875]],

                                           [[ 52421.3828125 ,  52391.21484375,  52475.328125  ,
                                              52435.3515625 ,  52299.20703125,  52470.1015625 ,
                                              52453.29296875,  51957.75      ,  52429.75      ,
                                              52466.2421875 ],
                                            [107343.4375    , 107282.2890625 , 107450.890625  ,
                                             107370.78125   , 107095.8046875 , 107440.6484375 ,
                                             107407.1171875 , 106384.828125  , 107359.453125  ,
                                             107432.4921875 ]],

                                           [[ 49289.08984375,  49264.3203125 ,  49332.95703125,
                                              49300.1875    ,  49189.8125    ,  49328.7578125 ,
                                              49315.02734375,  48919.109375  ,  49295.57421875,
                                              49325.39453125],
                                            [ 69407.6171875 ,  69366.828125  ,  69479.984375  ,
                                              69426.171875  ,  69242.7109375 ,  69473.03125   ,
                                              69450.453125  ,  68779.2265625 ,  69418.59375   ,
                                              69467.6796875 ]],

                                           [[107046.53125   , 106950.0546875 , 107215.546875  ,
                                             107089.3046875 , 106656.546875  , 107199.484375  ,
                                             107146.7109375 , 105539.09375   , 107071.421875  ,
                                             107186.4375    ],
                                            [ 53900.2734375 ,  53866.16796875,  53960.3125    ,
                                              53915.29296875,  53764.0859375 ,  53954.60546875,
                                              53935.78515625,  53394.6484375 ,  53908.93359375,
                                              53949.8515625 ]],

                                           [[109147.5546875 , 109006.59375   , 109393.609375  ,
                                             109209.453125  , 108578.7109375 , 109370.328125  ,
                                             109293.4296875 , 106950.125     , 109183.3125    ,
                                             109350.9921875 ],
                                            [138774.28125   , 138689.15625   , 138923.515625  ,
                                             138812.109375  , 138429.875     , 138909.3125    ,
                                             138862.734375  , 137440.828125  , 138796.34375   ,
                                             138897.859375  ]]])

        np.testing.assert_almost_equal(decomposition_data, decomposition_data_expected)

        # Remove test nwb files
        io.close()
        os.remove('ecephys_exmpl_decomp.nwb')

    def test_preprocess_raw_data(self):
        with NWBHDF5IO('ecephys_exmpl_raw.nwb', 'w') as io:
            io.write(self.nwbfile)

        config = {'CAR': 16, 'Notch': 60, 'Downsample': 400}
        preprocess_raw_data('ecephys_exmpl_raw.nwb', config)

        io = NWBHDF5IO('ecephys_exmpl_raw.nwb', 'r')
        nwbfile_in = io.read()

        raw_data = nwbfile_in.processing['ecephys'].data_interfaces['LFP'].electrical_series['preprocessed'].data[:]
        raw_data_expected = np.array([[0.76711663, 0.70811536],
                                      [0.79686718, 0.55776083],
                                      [0.96583653, 0.1471569],
                                      [0.029647, 0.59389349],
                                      [0.1140657, 0.95080985],
                                      [0.32570741, 0.19361869],
                                      [0.45781165, 0.92040257],
                                      [0.87906916, 0.25261576],
                                      [0.34800879, 0.18258873],
                                      [0.90179605, 0.70652816],
                                      [0.72665846, 0.90008784],
                                      [0.7791638, 0.59915478],
                                      [0.29112524, 0.15139526],
                                      [0.33517466, 0.65755178],
                                      [0.07334254, 0.0550064],
                                      [0.32319481, 0.5904818],
                                      [0.85389857, 0.28706243],
                                      [0.17306723, 0.13402121],
                                      [0.99465383, 0.17949787],
                                      [0.31754682, 0.5682914],
                                      [0.00934857, 0.90064862],
                                      [0.97724143, 0.55689468],
                                      [0.08477384, 0.33300247],
                                      [0.72842868, 0.14243537],
                                      [0.55246894, 0.27304326],
                                      [0.97449514, 0.66778691],
                                      [0.25565329, 0.10831149],
                                      [0.77618072, 0.78247799],
                                      [0.76160391, 0.91440311],
                                      [0.65862278, 0.56836758],
                                      [0.20175569, 0.69829638],
                                      [0.95219541, 0.88996329],
                                      [0.99356736, 0.81870351],
                                      [0.54512217, 0.45125405],
                                      [0.89055719, 0.97326479],
                                      [0.59341133, 0.3660745],
                                      [0.32309469, 0.87142326],
                                      [0.21563406, 0.73494519],
                                      [0.36561909, 0.8016026],
                                      [0.78273559, 0.70135538],
                                      [0.62277659, 0.49368265],
                                      [0.8405377, 0.71209699],
                                      [0.44390898, 0.03103486],
                                      [0.36323976, 0.73072179],
                                      [0.47556657, 0.34441697],
                                      [0.64088043, 0.12620532],
                                      [0.17146526, 0.73708649],
                                      [0.12702939, 0.36964987],
                                      [0.604334, 0.10310444],
                                      [0.80237418, 0.94555324]])
        np.testing.assert_almost_equal(raw_data, raw_data_expected)

        # Remove test nwb files
        io.close()
        os.remove('ecephys_exmpl_raw.nwb')

    def test_make_new_nwb(self):
        with NWBHDF5IO('ecephys_exmpl_make.nwb', 'w') as io:
            io.write(self.nwbfile)

        with NWBHDF5IO('new_ecephys_example.nwb', 'w') as io:
            io.write(self.nwbfile_new)

        cp_objs = {
            'institution': True,
            'lab': True,
            'session': True,
            'devices': True,
            'electrode_groups': True,
            'electrodes': True,
            'intervals': True,
            'stimulus': True,
            'acquisition': 'default',
            'ecephys': 'default'
        }
        make_new_nwb('ecephys_exmpl_make.nwb', 'new_ecephys_example.nwb', cp_objs=cp_objs)

        io1 = NWBHDF5IO('ecephys_exmpl_make.nwb', 'r')
        nwbfile_in = io1.read()

        io2 = NWBHDF5IO('new_ecephys_example.nwb', 'r')
        new_nwbfile_in = io2.read()

        assert (set(cp_objs.keys()) & set(new_nwbfile_in.fields.keys())).issubset(set(nwbfile_in.fields.keys()))

        # Remove test nwb files
        io1.close()
        io2.close()
        os.remove('ecephys_exmpl_make.nwb')
        os.remove('new_ecephys_example.nwb')
Beispiel #26
0
class Intan2NWB(NWBConverter):
    def __init__(self, nwbfile=None, metadata=None, source_paths=None):
        """
        Reads data from Intantech .rhd files, using an adapted version of the
        rhd reader scripts: http://intantech.com/downloads.html?tabSelect=Software

        Parameters
        ----------
        nwbfile: pynwb.NWBFile
        metadata: dict
        """
        super().__init__(nwbfile=nwbfile,
                         metadata=metadata,
                         source_paths=source_paths)

    def create_nwbfile(self, metadata_nwbfile):
        """
        Overriding method to get session_start_time form rhd files.
        """
        nwbfile_args = dict(identifier=str(uuid.uuid4()), )
        nwbfile_args.update(**metadata_nwbfile)
        session_start_time = self.get_session_start_time(
            self.source_paths['dir_ecephys_rhd']['path'])
        nwbfile_args.update(**session_start_time)
        self.nwbfile = NWBFile(**nwbfile_args)

    def get_session_start_time(self, dir_ecephys_rhd):
        """
        Gets session_start_time from first rhd file in dir_ecephys_rhd.

        Parameters
        ----------
        dir_ecephys_rhd: string or Path

        Returns
        -------
        dict
        """
        dir_ecephys_rhd = Path(dir_ecephys_rhd)
        all_files_rhd = list(dir_ecephys_rhd.glob('*.rhd'))
        all_files_rhd.sort()
        # Gets data/time info from first file name
        date_string = Path(all_files_rhd[0]).name.split('.')[0].split('_')[1]
        time_string = Path(all_files_rhd[0]).name.split('.')[0].split('_')[2]
        date_time_string = date_string + ' ' + time_string
        date_time_obj = datetime.strptime(date_time_string, '%y%m%d %H%M%S')
        return {'session_start_time': date_time_obj}

    def run_conversion(self):
        """
        Reads extracellular electrophysiology data from .rhd files and adds data to nwbfile.
        """
        dir_ecephys_rhd = Path(self.source_paths['dir_ecephys_rhd']['path'])
        if 'file_electrodes' in self.source_paths:
            electrodes_file = Path(
                self.source_paths['file_electrodes']['path'])
        else:
            electrodes_file = None

        def data_gen(source_dir):
            all_files_rhd = list(dir_ecephys_rhd.glob('*.rhd'))
            n_files = len(all_files_rhd)
            # Iterates over all files within the directory
            for ii, fname in enumerate(all_files_rhd):
                print("Converting ecephys rhd data: {}%".format(100 * ii /
                                                                n_files))
                file_data = load_intan.read_data(filename=fname)
                # Gets only valid timestamps
                valid_ts = file_data['board_dig_in_data'][0]
                analog_data = file_data['amplifier_data'][:, valid_ts]
                n_samples = analog_data.shape[1]
                for sample in range(n_samples):
                    yield analog_data[:, sample]

        # Gets header data from first file
        all_files_rhd = list(dir_ecephys_rhd.glob('*.rhd'))
        all_files_rhd.sort()
        fid = open(all_files_rhd[0], 'rb')
        header = read_header.read_header(fid)
        sampling_rate = header['sample_rate']

        self.create_electrodes_ecephys(all_files_rhd=all_files_rhd,
                                       electrodes_file=electrodes_file)

        # Gets electrodes info from first rhd file
        file_data = load_intan.read_data(filename=all_files_rhd[0])
        electrodes_info = file_data['amplifier_channels']
        n_electrodes = len(electrodes_info)
        electrode_table_region = self.nwbfile.create_electrode_table_region(
            region=list(np.arange(n_electrodes)), description='no description')

        # Create iterator
        data_iter = DataChunkIterator(
            data=data_gen(source_dir=dir_ecephys_rhd),
            iter_axis=0,
            buffer_size=10000,
            maxshape=(None, n_electrodes))

        # Electrical Series
        metadata_ecephys = self.metadata['Ecephys']
        # Gets electricalseries conversion factor
        es_conversion_factor = file_data['amplifier_data_conversion_factor']
        ephys_ts = ElectricalSeries(
            name=metadata_ecephys['ElectricalSeries'][0]['name'],
            description=metadata_ecephys['ElectricalSeries'][0]['description'],
            data=data_iter,
            electrodes=electrode_table_region,
            rate=sampling_rate,
            starting_time=0.0,
            conversion=es_conversion_factor)
        self.nwbfile.add_acquisition(ephys_ts)

    def create_electrodes_ecephys(self, all_files_rhd, electrodes_file):
        """
        Parameters
        ----------
        all_files_rhd: list
            List of paths to rhd files
        electrodes_file : str
            Path to CSV file containing extra electrodes information
        """
        # Gets electrodes info from first rhd file
        file_data = load_intan.read_data(filename=all_files_rhd[0])
        electrodes_info = file_data['amplifier_channels']
        n_electrodes = len(electrodes_info)

        # Electrodes
        if electrodes_file is not None:  # if an electrodes info file was provided
            df_electrodes = pd.read_csv(electrodes_file,
                                        index_col='Channel Number')
            for idx, elec in enumerate(electrodes_info):
                elec_name = elec['native_channel_name']
                elec_group = df_electrodes.loc[elec_name]['electrode_group']
                elec_imp = df_electrodes.loc[elec_name][
                    'Impedance Magnitude at 1000 Hz (ohms)']
                self.nwbfile.add_electrode(
                    id=idx,
                    x=np.nan,
                    y=np.nan,
                    z=np.nan,
                    imp=float(elec_imp),
                    location='location',
                    filtering='none',
                    group=self.nwbfile.electrode_groups[elec_group])
        else:  # if no electrodes file info was provided
            first_el_grp = list(self.nwbfile.electrode_groups.keys())[0]
            electrode_group = self.nwbfile.electrode_groups[first_el_grp]
            for idx in range(n_electrodes):
                self.nwbfile.add_electrode(id=idx,
                                           x=np.nan,
                                           y=np.nan,
                                           z=np.nan,
                                           imp=np.nan,
                                           location='location',
                                           filtering='none',
                                           group=electrode_group)
Beispiel #27
0
device_name = 'LFP device'
device = nwbfile.create_device(device_name, source=source)
electrode_group = nwbfile.create_electrode_group(name=device_name +
                                                 '_electrodes',
                                                 source=lfp_xml_fpath,
                                                 description=device_name,
                                                 device=device,
                                                 location='unknown')

for channel in channel_groups[0]:
    nwbfile.add_electrode(
        channel,
        np.nan,
        np.nan,
        np.nan,  # position?
        imp=np.nan,
        location='unknown',
        filtering='unknown',
        description='lfp electrode {}'.format(channel),
        group=electrode_group)

lfp_table_region = nwbfile.create_electrode_table_region(
    list(range(4)), 'lfp electrodes')

lfp_elec_series = ElectricalSeries('lfp',
                                   'lfp',
                                   gzip(lfp_signal),
                                   lfp_table_region,
                                   conversion=np.nan,
                                   starting_time=0.0,
                                   rate=lfp_fs,
Beispiel #28
0
class NWBFileTest(TestCase):
    def setUp(self):
        self.start = datetime(2017, 5, 1, 12, 0, 0, tzinfo=tzlocal())
        self.ref_time = datetime(1979, 1, 1, 0, tzinfo=tzutc())
        self.create = [
            datetime(2017, 5, 1, 12, tzinfo=tzlocal()),
            datetime(2017, 5, 2, 13, 0, 0, 1, tzinfo=tzutc()),
            datetime(2017, 5, 2, 14, tzinfo=tzutc())
        ]
        self.path = 'nwbfile_test.h5'
        self.nwbfile = NWBFile(
            'a test session description for a test NWBFile',
            'FILE123',
            self.start,
            file_create_date=self.create,
            timestamps_reference_time=self.ref_time,
            experimenter='A test experimenter',
            lab='a test lab',
            institution='a test institution',
            experiment_description='a test experiment description',
            session_id='test1',
            notes='my notes',
            pharmacology='drugs',
            protocol='protocol',
            related_publications='my pubs',
            slices='my slices',
            surgery='surgery',
            virus='a virus',
            source_script='noscript',
            source_script_file_name='nofilename',
            stimulus_notes='test stimulus notes',
            data_collection='test data collection notes',
            keywords=('these', 'are', 'keywords'))

    def test_constructor(self):
        self.assertEqual(self.nwbfile.session_description,
                         'a test session description for a test NWBFile')
        self.assertEqual(self.nwbfile.identifier, 'FILE123')
        self.assertEqual(self.nwbfile.session_start_time, self.start)
        self.assertEqual(self.nwbfile.file_create_date, self.create)
        self.assertEqual(self.nwbfile.lab, 'a test lab')
        self.assertEqual(self.nwbfile.experimenter, ('A test experimenter', ))
        self.assertEqual(self.nwbfile.institution, 'a test institution')
        self.assertEqual(self.nwbfile.experiment_description,
                         'a test experiment description')
        self.assertEqual(self.nwbfile.session_id, 'test1')
        self.assertEqual(self.nwbfile.stimulus_notes, 'test stimulus notes')
        self.assertEqual(self.nwbfile.data_collection,
                         'test data collection notes')
        self.assertEqual(self.nwbfile.related_publications, ('my pubs', ))
        self.assertEqual(self.nwbfile.source_script, 'noscript')
        self.assertEqual(self.nwbfile.source_script_file_name, 'nofilename')
        self.assertEqual(self.nwbfile.keywords, ('these', 'are', 'keywords'))
        self.assertEqual(self.nwbfile.timestamps_reference_time, self.ref_time)

    def test_create_electrode_group(self):
        name = 'example_electrode_group'
        desc = 'An example electrode'
        loc = 'an example location'
        d = self.nwbfile.create_device('a fake device')
        elecgrp = self.nwbfile.create_electrode_group(name, desc, loc, d)
        self.assertEqual(elecgrp.description, desc)
        self.assertEqual(elecgrp.location, loc)
        self.assertIs(elecgrp.device, d)

    def test_create_custom_intervals(self):
        df_words = pd.DataFrame({
            'start_time': [.1, 2.],
            'stop_time': [.8, 2.3],
            'label': ['hello', 'there']
        })
        words = TimeIntervals.from_dataframe(df_words, name='words')
        self.nwbfile.add_time_intervals(words)
        self.assertEqual(self.nwbfile.intervals['words'], words)

    def test_create_electrode_group_invalid_index(self):
        """
        Test the case where the user creates an electrode table region with
        indexes that are out of range of the amount of electrodes added.
        """
        nwbfile = NWBFile('a', 'b', datetime.now(tzlocal()))
        device = nwbfile.create_device('a')
        elecgrp = nwbfile.create_electrode_group('a',
                                                 'b',
                                                 device=device,
                                                 location='a')
        for i in range(4):
            nwbfile.add_electrode(np.nan,
                                  np.nan,
                                  np.nan,
                                  np.nan,
                                  'a',
                                  'a',
                                  elecgrp,
                                  id=i)
        with self.assertRaises(IndexError):
            nwbfile.create_electrode_table_region(list(range(6)), 'test')

    def test_access_group_after_io(self):
        """
        Motivated by #739
        """
        nwbfile = NWBFile('a', 'b', datetime.now(tzlocal()))
        device = nwbfile.create_device('a')
        elecgrp = nwbfile.create_electrode_group('a',
                                                 'b',
                                                 device=device,
                                                 location='a')
        nwbfile.add_electrode(np.nan,
                              np.nan,
                              np.nan,
                              np.nan,
                              'a',
                              'a',
                              elecgrp,
                              id=0)

        with NWBHDF5IO('electrodes_mwe.nwb', 'w') as io:
            io.write(nwbfile)

        with NWBHDF5IO('electrodes_mwe.nwb', 'a') as io:
            nwbfile_i = io.read()
            for aa, bb in zip(nwbfile_i.electrodes['group'][:],
                              nwbfile.electrodes['group'][:]):
                self.assertEqual(aa.name, bb.name)

        for i in range(4):
            nwbfile.add_electrode(np.nan,
                                  np.nan,
                                  np.nan,
                                  np.nan,
                                  'a',
                                  'a',
                                  elecgrp,
                                  id=i + 1)

        with NWBHDF5IO('electrodes_mwe.nwb', 'w') as io:
            io.write(nwbfile)

        with NWBHDF5IO('electrodes_mwe.nwb', 'a') as io:
            nwbfile_i = io.read()
            for aa, bb in zip(nwbfile_i.electrodes['group'][:],
                              nwbfile.electrodes['group'][:]):
                self.assertEqual(aa.name, bb.name)

        remove_test_file("electrodes_mwe.nwb")

    def test_access_processing(self):
        self.nwbfile.create_processing_module('test_mod', 'test_description')
        # test deprecate .modules
        with self.assertWarnsWith(DeprecationWarning,
                                  'replaced by NWBFile.processing'):
            modules = self.nwbfile.modules['test_mod']
        self.assertIs(self.nwbfile.processing['test_mod'], modules)

    def test_epoch_tags(self):
        tags1 = ['t1', 't2']
        tags2 = ['t3', 't4']
        tstamps = np.arange(1.0, 100.0, 0.1, dtype=np.float)
        ts = TimeSeries("test_ts",
                        list(range(len(tstamps))),
                        'unit',
                        timestamps=tstamps)
        expected_tags = tags1 + tags2
        self.nwbfile.add_epoch(0.0, 1.0, tags1, ts)
        self.nwbfile.add_epoch(0.0, 1.0, tags2, ts)
        tags = self.nwbfile.epoch_tags
        self.assertEqual(set(expected_tags), set(tags))

    def test_add_acquisition(self):
        self.nwbfile.add_acquisition(
            TimeSeries('test_ts', [0, 1, 2, 3, 4, 5],
                       'grams',
                       timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]))
        self.assertEqual(len(self.nwbfile.acquisition), 1)

    def test_add_stimulus(self):
        self.nwbfile.add_stimulus(
            TimeSeries('test_ts', [0, 1, 2, 3, 4, 5],
                       'grams',
                       timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]))
        self.assertEqual(len(self.nwbfile.stimulus), 1)

    def test_add_stimulus_template(self):
        self.nwbfile.add_stimulus_template(
            TimeSeries('test_ts', [0, 1, 2, 3, 4, 5],
                       'grams',
                       timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]))
        self.assertEqual(len(self.nwbfile.stimulus_template), 1)

    def test_add_analysis(self):
        self.nwbfile.add_analysis(
            TimeSeries('test_ts', [0, 1, 2, 3, 4, 5],
                       'grams',
                       timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]))
        self.assertEqual(len(self.nwbfile.analysis), 1)

    def test_add_acquisition_check_dups(self):
        self.nwbfile.add_acquisition(
            TimeSeries('test_ts', [0, 1, 2, 3, 4, 5],
                       'grams',
                       timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]))
        with self.assertRaises(ValueError):
            self.nwbfile.add_acquisition(
                TimeSeries('test_ts', [0, 1, 2, 3, 4, 5],
                           'grams',
                           timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]))

    def test_get_acquisition_empty(self):
        with self.assertRaisesWith(ValueError,
                                   "acquisition of NWBFile 'root' is empty"):
            self.nwbfile.get_acquisition()

    def test_get_acquisition_multiple_elements(self):
        self.nwbfile.add_acquisition(
            TimeSeries('test_ts1', [0, 1, 2, 3, 4, 5],
                       'grams',
                       timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]))
        self.nwbfile.add_acquisition(
            TimeSeries('test_ts2', [0, 1, 2, 3, 4, 5],
                       'grams',
                       timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]))
        msg = "more than one element in acquisition of NWBFile 'root' -- must specify a name"
        with self.assertRaisesWith(ValueError, msg):
            self.nwbfile.get_acquisition()

    def test_add_acquisition_invalid_name(self):
        self.nwbfile.add_acquisition(
            TimeSeries('test_ts', [0, 1, 2, 3, 4, 5],
                       'grams',
                       timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]))
        msg = "\"'TEST_TS' not found in acquisition of NWBFile 'root'\""
        with self.assertRaisesWith(KeyError, msg):
            self.nwbfile.get_acquisition("TEST_TS")

    def test_set_electrode_table(self):
        table = ElectrodeTable()
        dev1 = self.nwbfile.create_device('dev1')
        group = self.nwbfile.create_electrode_group('tetrode1',
                                                    'tetrode description',
                                                    'tetrode location', dev1)
        table.add_row(x=1.0,
                      y=2.0,
                      z=3.0,
                      imp=-1.0,
                      location='CA1',
                      filtering='none',
                      group=group,
                      group_name='tetrode1')
        table.add_row(x=1.0,
                      y=2.0,
                      z=3.0,
                      imp=-2.0,
                      location='CA1',
                      filtering='none',
                      group=group,
                      group_name='tetrode1')
        table.add_row(x=1.0,
                      y=2.0,
                      z=3.0,
                      imp=-3.0,
                      location='CA1',
                      filtering='none',
                      group=group,
                      group_name='tetrode1')
        table.add_row(x=1.0,
                      y=2.0,
                      z=3.0,
                      imp=-4.0,
                      location='CA1',
                      filtering='none',
                      group=group,
                      group_name='tetrode1')
        self.nwbfile.set_electrode_table(table)

        self.assertIs(self.nwbfile.electrodes, table)
        self.assertIs(table.parent, self.nwbfile)

    def test_add_unit_column(self):
        self.nwbfile.add_unit_column('unit_type', 'the type of unit')
        self.assertEqual(self.nwbfile.units.colnames, ('unit_type', ))

    def test_add_unit(self):
        self.nwbfile.add_unit(id=1)
        self.assertEqual(len(self.nwbfile.units), 1)
        self.nwbfile.add_unit(id=2)
        self.nwbfile.add_unit(id=3)
        self.assertEqual(len(self.nwbfile.units), 3)

    def test_add_trial_column(self):
        self.nwbfile.add_trial_column('trial_type', 'the type of trial')
        self.assertEqual(self.nwbfile.trials.colnames,
                         ('start_time', 'stop_time', 'trial_type'))

    def test_add_trial(self):
        self.nwbfile.add_trial(start_time=10.0, stop_time=20.0)
        self.assertEqual(len(self.nwbfile.trials), 1)
        self.nwbfile.add_trial(start_time=30.0, stop_time=40.0)
        self.nwbfile.add_trial(start_time=50.0, stop_time=70.0)
        self.assertEqual(len(self.nwbfile.trials), 3)

    def test_add_invalid_times_column(self):
        self.nwbfile.add_invalid_times_column(
            'comments', 'description of reason for omitting time')
        self.assertEqual(self.nwbfile.invalid_times.colnames,
                         ('start_time', 'stop_time', 'comments'))

    def test_add_invalid_time_interval(self):

        self.nwbfile.add_invalid_time_interval(start_time=0.0, stop_time=12.0)
        self.assertEqual(len(self.nwbfile.invalid_times), 1)
        self.nwbfile.add_invalid_time_interval(start_time=15.0, stop_time=16.0)
        self.nwbfile.add_invalid_time_interval(start_time=17.0, stop_time=20.5)
        self.assertEqual(len(self.nwbfile.invalid_times), 3)

    def test_add_invalid_time_w_ts(self):
        ts = TimeSeries(name='name', data=[1.2], rate=1.0, unit='na')
        self.nwbfile.add_invalid_time_interval(start_time=18.0,
                                               stop_time=20.6,
                                               timeseries=ts,
                                               tags=('hi', 'there'))

    def test_add_electrode(self):
        dev1 = self.nwbfile.create_device('dev1')
        group = self.nwbfile.create_electrode_group('tetrode1',
                                                    'tetrode description',
                                                    'tetrode location', dev1)
        self.nwbfile.add_electrode(1.0,
                                   2.0,
                                   3.0,
                                   -1.0,
                                   'CA1',
                                   'none',
                                   group=group,
                                   id=1)
        elec = self.nwbfile.electrodes[0]
        self.assertEqual(elec.index[0], 1)
        self.assertEqual(elec.iloc[0]['x'], 1.0)
        self.assertEqual(elec.iloc[0]['y'], 2.0)
        self.assertEqual(elec.iloc[0]['z'], 3.0)
        self.assertEqual(elec.iloc[0]['location'], 'CA1')
        self.assertEqual(elec.iloc[0]['filtering'], 'none')
        self.assertEqual(elec.iloc[0]['group'], group)

    def test_all_children(self):
        ts1 = TimeSeries('test_ts1', [0, 1, 2, 3, 4, 5],
                         'grams',
                         timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])
        ts2 = TimeSeries('test_ts2', [0, 1, 2, 3, 4, 5],
                         'grams',
                         timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])
        self.nwbfile.add_acquisition(ts1)
        self.nwbfile.add_acquisition(ts2)
        name = 'example_electrode_group'
        desc = 'An example electrode'
        loc = 'an example location'
        device = self.nwbfile.create_device('a fake device')
        elecgrp = self.nwbfile.create_electrode_group(name, desc, loc, device)
        children = self.nwbfile.all_children()
        self.assertIn(ts1, children)
        self.assertIn(ts2, children)
        self.assertIn(device, children)
        self.assertIn(elecgrp, children)

    def test_fail_if_source_script_file_name_without_source_script(self):
        with self.assertRaises(ValueError):
            # <-- source_script_file_name without source_script is not allowed
            NWBFile('a test session description for a test NWBFile',
                    'FILE123',
                    self.start,
                    source_script=None,
                    source_script_file_name='nofilename')

    def test_get_neurodata_type(self):
        ts1 = TimeSeries('test_ts1', [0, 1, 2, 3, 4, 5],
                         'grams',
                         timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])
        ts2 = TimeSeries('test_ts2', [0, 1, 2, 3, 4, 5],
                         'grams',
                         timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])
        self.nwbfile.add_acquisition(ts1)
        self.nwbfile.add_acquisition(ts2)
        p1 = ts1.get_ancestor(neurodata_type='NWBFile')
        self.assertIs(p1, self.nwbfile)
        p2 = ts2.get_ancestor(neurodata_type='NWBFile')
        self.assertIs(p2, self.nwbfile)

    def test_print_units(self):
        self.nwbfile.add_unit(spike_times=[1., 2., 3.])
        expected = """units pynwb.misc.Units at 0x%d
Fields:
  colnames: ['spike_times']
  columns: (
    spike_times_index <class 'hdmf.common.table.VectorIndex'>,
    spike_times <class 'hdmf.common.table.VectorData'>
  )
  description: Autogenerated by NWBFile
  id: id <class 'hdmf.common.table.ElementIdentifiers'>
"""
        expected = expected % id(self.nwbfile.units)
        self.assertEqual(str(self.nwbfile.units), expected)

    def test_copy(self):
        self.nwbfile.add_unit(spike_times=[1., 2., 3.])
        device = self.nwbfile.create_device('a')
        elecgrp = self.nwbfile.create_electrode_group('a',
                                                      'b',
                                                      device=device,
                                                      location='a')
        self.nwbfile.add_electrode(np.nan,
                                   np.nan,
                                   np.nan,
                                   np.nan,
                                   'a',
                                   'a',
                                   elecgrp,
                                   id=0)
        self.nwbfile.add_electrode(np.nan, np.nan, np.nan, np.nan, 'b', 'b',
                                   elecgrp)
        elec_region = self.nwbfile.create_electrode_table_region([1], 'name')

        ts1 = TimeSeries('test_ts1', [0, 1, 2, 3, 4, 5],
                         'grams',
                         timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])
        ts2 = ElectricalSeries('test_ts2', [0, 1, 2, 3, 4, 5],
                               electrodes=elec_region,
                               timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])
        self.nwbfile.add_acquisition(ts1)
        self.nwbfile.add_acquisition(ts2)
        self.nwbfile.add_trial(start_time=50.0, stop_time=70.0)
        self.nwbfile.add_invalid_times_column(
            'comments', 'description of reason for omitting time')
        self.nwbfile.create_processing_module('test_mod', 'test_description')
        self.nwbfile.create_time_intervals('custom_interval',
                                           'a custom time interval')
        self.nwbfile.intervals['custom_interval'].add_interval(start_time=10.,
                                                               stop_time=20.)
        newfile = self.nwbfile.copy()

        # test dictionaries
        self.assertIs(self.nwbfile.devices['a'], newfile.devices['a'])
        self.assertIs(self.nwbfile.acquisition['test_ts1'],
                      newfile.acquisition['test_ts1'])
        self.assertIs(self.nwbfile.acquisition['test_ts2'],
                      newfile.acquisition['test_ts2'])
        self.assertIs(self.nwbfile.processing['test_mod'],
                      newfile.processing['test_mod'])

        # test dynamic tables
        self.assertIsNot(self.nwbfile.electrodes, newfile.electrodes)
        self.assertIs(self.nwbfile.electrodes['x'], newfile.electrodes['x'])
        self.assertIsNot(self.nwbfile.units, newfile.units)
        self.assertIs(self.nwbfile.units['spike_times'],
                      newfile.units['spike_times'])
        self.assertIsNot(self.nwbfile.trials, newfile.trials)
        self.assertIsNot(self.nwbfile.trials.parent, newfile.trials.parent)
        self.assertIs(self.nwbfile.trials.id, newfile.trials.id)
        self.assertIs(self.nwbfile.trials['start_time'],
                      newfile.trials['start_time'])
        self.assertIs(self.nwbfile.trials['stop_time'],
                      newfile.trials['stop_time'])
        self.assertIsNot(self.nwbfile.invalid_times, newfile.invalid_times)
        self.assertTupleEqual(self.nwbfile.invalid_times.colnames,
                              newfile.invalid_times.colnames)
        self.assertIsNot(self.nwbfile.intervals['custom_interval'],
                         newfile.intervals['custom_interval'])
        self.assertTupleEqual(
            self.nwbfile.intervals['custom_interval'].colnames,
            newfile.intervals['custom_interval'].colnames)
        self.assertIs(self.nwbfile.intervals['custom_interval']['start_time'],
                      newfile.intervals['custom_interval']['start_time'])
        self.assertIs(self.nwbfile.intervals['custom_interval']['stop_time'],
                      newfile.intervals['custom_interval']['stop_time'])

    def test_multi_experimenters(self):
        self.nwbfile = NWBFile('a test session description for a test NWBFile',
                               'FILE123',
                               self.start,
                               experimenter=('experimenter1', 'experimenter2'))
        self.assertTupleEqual(self.nwbfile.experimenter,
                              ('experimenter1', 'experimenter2'))

    def test_multi_publications(self):
        self.nwbfile = NWBFile('a test session description for a test NWBFile',
                               'FILE123',
                               self.start,
                               related_publications=('pub1', 'pub2'))
        self.assertTupleEqual(self.nwbfile.related_publications,
                              ('pub1', 'pub2'))
Beispiel #29
0
ns.write_electrode_table(nwbfile, fpath)
# shank electrodes
device = nwbfile.create_device('implant', fname + '.xml')
electrode_counter = 0
for shankn, channels in enumerate(shank_channels):
    electrode_group = nwbfile.create_electrode_group(
        name='shank{}'.format(shankn),
        description=fname,
        device=device,
        location='unknown')
    for channel in channels:
        nwbfile.add_electrode(
            np.nan,
            np.nan,
            np.nan,  # position?
            imp=np.nan,
            location='unknown',
            filtering='unknown',
            description='electrode {} of shank {}, channel {}'.format(
                electrode_counter, shankn, channel),
            group=electrode_group)

        if channel == lfp_channel:
            lfp_table_region = nwbfile.create_electrode_table_region(
                [electrode_counter], 'lfp electrode')

        electrode_counter += 1

all_table_region = nwbfile.create_electrode_table_region(
    list(range(electrode_counter)), 'all electrodes')
print('done.')
Beispiel #30
0
    def writeRecording(recording, save_path, acquisition_name):
        try:
            from pynwb import NWBHDF5IO
            from pynwb import NWBFile
            from pynwb.ecephys import ElectricalSeries
        except ModuleNotFoundError:
            raise ModuleNotFoundError(
                "To use the Nwb extractors, install pynwb: \n\n"
                "pip install pynwb\n\n")
        M = recording.getNumChannels()
        N = recording.getNumFrames()

        nwbfile = NWBFile(source='SpikeInterface::NwbRecordingExtractor',
                          session_description='',
                          identifier='',
                          session_start_time=datetime.now(),
                          experimenter='',
                          lab='',
                          institution='',
                          experiment_description='',
                          session_id='')
        device = nwbfile.create_device(name='device_name',
                                       source="device_source")
        eg_name = 'electrode_group_name'
        eg_source = "electrode_group_source"
        eg_description = "electrode_group_description"
        eg_location = "electrode_group_location"

        electrode_group = nwbfile.create_electrode_group(
            name=eg_name,
            source=eg_source,
            location=eg_location,
            device=device,
            description=eg_description)

        for m in range(M):
            id = m
            location = recording.getChannelProperty(m, 'location')
            impedence = -1.0
            while len(location) < 3:
                location = np.append(location, [0])
            nwbfile.add_electrode(id,
                                  x=float(location[0]),
                                  y=float(location[1]),
                                  z=float(location[2]),
                                  imp=impedence,
                                  location='electrode_location',
                                  filtering='none',
                                  group=electrode_group,
                                  description='electrode_description')
        electrode_table_region = nwbfile.create_electrode_table_region(
            list(range(M)), 'electrode_table_region')

        rate = recording.getSamplingFrequency() / 1000
        ephys_data = recording.getTraces().T

        ephys_ts = ElectricalSeries(
            name=acquisition_name,
            source='acquisition_source',
            data=ephys_data,
            electrodes=electrode_table_region,
            starting_time=recording.frameToTime(0),
            rate=rate,
            resolution=1e-6,
            comments='Generated from SpikeInterface::NwbRecordingExtractor',
            description='acquisition_description')
        nwbfile.add_acquisition(ephys_ts)
        if os.path.exists(save_path):
            os.remove(save_path)
        with NWBHDF5IO(save_path, 'w') as io:
            io.write(nwbfile)