示例#1
0
    def test_multi_sub_sorting_extractor(self):
        N = self.RX.get_num_frames()
        SX_multi = se.MultiSortingExtractor(
            sortings=[self.SX, self.SX, self.SX], )
        SX_multi.set_unit_property(unit_id=1, property_name='dummy', value=5)
        SX_sub = se.SubSortingExtractor(parent_sorting=SX_multi, start_frame=0)
        self._check_sortings_equal(SX_multi, SX_sub)
        self.assertEqual(SX_multi.get_unit_property(1, 'dummy'),
                         SX_sub.get_unit_property(1, 'dummy'))

        N = self.RX.get_num_frames()
        SX_multi = se.MultiSortingExtractor(sortings=[self.SX, self.SX2], )
        SX_sub1 = se.SubSortingExtractor(parent_sorting=SX_multi,
                                         start_frame=0,
                                         end_frame=N)
        self._check_sortings_equal(SX_multi, SX_sub1)
示例#2
0
    def get_result(self):
        sorting_list = self.get_result_list()
        if len(sorting_list) == 1:
            sorting = sorting_list[0]
        else:
            for i, sorting in enumerate(sorting_list):
                property_name = self.recording_list[i].get_channel_property(
                    self.recording_list[i].get_channel_ids()[0],
                    self.grouping_property)
                if sorting is not None:
                    for unit in sorting.get_unit_ids():
                        sorting.set_unit_property(unit, self.grouping_property,
                                                  property_name)

            # reassemble the sorting outputs
            sorting_list = [sort for sort in sorting_list if sort is not None]
            multi_sorting = se.MultiSortingExtractor(sortings=sorting_list)
            sorting = multi_sorting

        if self.delete_folders:
            for out in self.output_folders:
                if self.verbose:
                    print("Removing ", str(out))
                shutil.rmtree(str(out), ignore_errors=True)
        sorting.set_sampling_frequency(
            self.recording_list[0].get_sampling_frequency())
        return sorting
示例#3
0
def _spikeSortByProperty(recording, spikesorter, property, parallel, **kwargs):
    '''

    Parameters
    ----------
    recording
    sorter
    kwargs

    Returns
    -------

    '''
    recording_list = se.getSubExtractorsByProperty(recording, property)
    sorting_list = _parallelSpikeSorting(recording_list, spikesorter, parallel,
                                         **kwargs)
    # add group property
    for i, sorting in enumerate(sorting_list):
        group = recording_list[i].getChannelProperty(
            recording_list[i].getChannelIds()[0], 'group')
        for unit in sorting.getUnitIds():
            sorting.setUnitProperty(unit, 'group', group)
    # reassemble the sorting outputs
    multi_sorting = se.MultiSortingExtractor(sortings=sorting_list)
    return multi_sorting
示例#4
0
    def test_multi_sub_sorting_extractor(self):
        N = self.RX.get_num_frames()
        SX_multi = se.MultiSortingExtractor(
            sortings=[self.SX, self.SX, self.SX], start_frames=[0, N, 2 * N])
        SX_sub = se.SubSortingExtractor(parent_sorting=SX_multi,
                                        start_frame=N,
                                        end_frame=2 * N)
        self._check_sortings_equal(self.SX, SX_sub)
        self.assertEqual(SX_multi.get_sampling_frequency(),
                         self.SX.get_sampling_frequency())
        self.assertEqual(SX_sub.get_sampling_frequency(),
                         self.SX.get_sampling_frequency())

        N = self.RX.get_num_frames()
        SX_multi = se.MultiSortingExtractor(
            sortings=[self.SX, self.SX, self.SX], start_frames=[0, N, 2 * N])
        SX_sub = se.SubSortingExtractor(parent_sorting=SX_multi, start_frame=0)
        self._check_sortings_equal(SX_multi, SX_sub)

        N = self.RX.get_num_frames()
        SX_multi = se.MultiSortingExtractor(
            sortings=[self.SX, self.SX, self.SX], start_frames=[2 * N, 0, N])
        SX_sub = se.SubSortingExtractor(parent_sorting=SX_multi,
                                        start_frame=N,
                                        end_frame=2 * N)
        self._check_sortings_equal(self.SX, SX_sub)

        N = self.RX.get_num_frames()
        SX_multi = se.MultiSortingExtractor(
            sortings=[self.SX, self.SX, self.SX], start_frames=[0, 0, 0])
        SX_sub = se.SubSortingExtractor(parent_sorting=SX_multi, start_frame=0)
        self._check_sortings_equal(SX_multi, SX_sub)

        N = self.RX.get_num_frames()
        SX_multi = se.MultiSortingExtractor(sortings=[self.SX, self.SX2],
                                            start_frames=[0, 0])
        SX_sub1 = se.SubSortingExtractor(parent_sorting=SX_multi,
                                         start_frame=0,
                                         end_frame=N)
        self._check_sortings_equal(SX_multi, SX_sub1)
示例#5
0
    def test_multi_sub_sorting_extractor(self):
        N = self.RX.getNumFrames()
        SX_multi = se.MultiSortingExtractor(
            sortings=[self.SX, self.SX, self.SX], start_frames=[0, N, 2 * N])
        SX_sub = se.SubSortingExtractor(parent_sorting=SX_multi,
                                        start_frame=N,
                                        end_frame=2 * N)
        self._check_sortings_equal(self.SX, SX_sub)

        N = self.RX.getNumFrames()
        SX_multi = se.MultiSortingExtractor(
            sortings=[self.SX, self.SX, self.SX], start_frames=[0, N, 2 * N])
        SX_sub = se.SubSortingExtractor(parent_sorting=SX_multi, start_frame=0)
        self._check_sortings_equal(SX_multi, SX_sub)

        N = self.RX.getNumFrames()
        SX_multi = se.MultiSortingExtractor(
            sortings=[self.SX, self.SX, self.SX], start_frames=[2 * N, 0, N])
        SX_sub = se.SubSortingExtractor(parent_sorting=SX_multi,
                                        start_frame=N,
                                        end_frame=2 * N)
        self._check_sortings_equal(self.SX, SX_sub)

        N = self.RX.getNumFrames()
        SX_multi = se.MultiSortingExtractor(
            sortings=[self.SX, self.SX, self.SX], start_frames=[0, 0, 0])
        SX_sub = se.SubSortingExtractor(parent_sorting=SX_multi, start_frame=0)
        self._check_sortings_equal(SX_multi, SX_sub)

        N = self.RX.getNumFrames()
        SX_multi = se.MultiSortingExtractor(sortings=[self.SX, self.SX2],
                                            start_frames=[0, 0])
        SX_sub1 = se.SubSortingExtractor(parent_sorting=SX_multi,
                                         start_frame=0,
                                         end_frame=N)
        self._check_sortings_equal(SX_multi, SX_sub1)
    def test_dump_load_multi_sub_extractor(self):
        # generate dumpable formats
        path1 = self.test_dir + '/mda'
        path2 = path1 + '/firings_true.mda'
        se.MdaRecordingExtractor.write_recording(self.RX, path1)
        se.MdaSortingExtractor.write_sorting(self.SX, path2)
        RX_mda = se.MdaRecordingExtractor(path1)
        SX_mda = se.MdaSortingExtractor(path2)

        RX_multi_chan = se.MultiRecordingChannelExtractor(recordings=[RX_mda, RX_mda, RX_mda])
        check_dumping(RX_multi_chan)
        RX_multi_time = se.MultiRecordingTimeExtractor(recordings=[RX_mda, RX_mda, RX_mda], )
        check_dumping(RX_multi_time)
        RX_multi_chan = se.SubRecordingExtractor(RX_mda, channel_ids=[0, 1])
        check_dumping(RX_multi_chan)

        SX_sub = se.SubSortingExtractor(SX_mda, unit_ids=[1, 2])
        check_dumping(SX_sub)
        SX_multi = se.MultiSortingExtractor(sortings=[SX_mda, SX_mda, SX_mda])
        check_dumping(SX_multi)
示例#7
0
    def get_result_from_folder(output_folder):

        output_folder = Path(output_folder)
        sortings = []
        recording_folders = [
            f for f in os.listdir(output_folder)
            if (os.path.isdir(os.path.join(output_folder, f))
                and f.startswith('recording'))
        ]

        for rf in recording_folders:
            result_fname = str(output_folder / rf)
            sorting = se.CombinatoSortingExtractor(datapath=result_fname)
            for u in sorting.get_unit_ids():
                sorting.set_unit_property(unit_id=u,
                                          property_name='channel_id',
                                          value=int(rf[9:]))
            sortings.append(sorting)

        return se.MultiSortingExtractor(sortings)
示例#8
0
    def test_neuroscope_extractors(self):
        # NeuroscopeRecordingExtractor tests
        nscope_dir = Path(self.test_dir) / 'neuroscope_rec0'
        dat_file = nscope_dir / 'neuroscope_rec0.dat'
        se.NeuroscopeRecordingExtractor.write_recording(self.RX, nscope_dir)
        RX_ns = se.NeuroscopeRecordingExtractor(dat_file)

        check_recording_return_types(RX_ns)
        check_recordings_equal(self.RX, RX_ns, force_dtype='int32')
        check_dumping(RX_ns)

        check_recording_return_types(RX_ns)
        check_recordings_equal(self.RX, RX_ns, force_dtype='int32')
        check_dumping(RX_ns)

        del RX_ns
        # overwrite
        nscope_dir = Path(self.test_dir) / 'neuroscope_rec1'
        dat_file = nscope_dir / 'neuroscope_rec1.dat'
        se.NeuroscopeRecordingExtractor.write_recording(recording=self.RX,
                                                        save_path=nscope_dir)
        RX_ns = se.NeuroscopeRecordingExtractor(dat_file)
        check_recording_return_types(RX_ns)
        check_recordings_equal(self.RX, RX_ns)
        check_dumping(RX_ns)

        # NeuroscopeSortingExtractor tests
        nscope_dir = Path(self.test_dir) / 'neuroscope_sort0'
        sort_name = 'neuroscope_sort0'
        initial_sorting_resfile = Path(
            self.test_dir) / sort_name / f'{sort_name}.res'
        initial_sorting_clufile = Path(
            self.test_dir) / sort_name / f'{sort_name}.clu'
        se.NeuroscopeSortingExtractor.write_sorting(self.SX, nscope_dir)
        SX_neuroscope = se.NeuroscopeSortingExtractor(
            resfile_path=initial_sorting_resfile,
            clufile_path=initial_sorting_clufile)
        check_sorting_return_types(SX_neuroscope)
        check_sortings_equal(self.SX, SX_neuroscope)
        check_dumping(SX_neuroscope)
        SX_neuroscope_no_mua = se.NeuroscopeSortingExtractor(
            resfile_path=initial_sorting_resfile,
            clufile_path=initial_sorting_clufile,
            keep_mua_units=False)
        check_sorting_return_types(SX_neuroscope_no_mua)
        check_dumping(SX_neuroscope_no_mua)

        # Test for extra argument 'keep_mua_units' resulted in the right output
        SX_neuroscope_no_mua = se.NeuroscopeSortingExtractor(
            resfile_path=initial_sorting_resfile,
            clufile_path=initial_sorting_clufile,
            keep_mua_units=False)
        check_sorting_return_types(SX_neuroscope_no_mua)
        check_dumping(SX_neuroscope_no_mua)

        num_original_units = len(SX_neuroscope.get_unit_ids())
        self.assertEqual(list(SX_neuroscope.get_unit_ids()),
                         list(range(1, num_original_units + 1)))
        self.assertEqual(list(SX_neuroscope_no_mua.get_unit_ids()),
                         list(range(1, num_original_units)))

        # Tests for the auto-detection of format for NeuroscopeSortingExtractor
        SX_neuroscope_from_fp = se.NeuroscopeSortingExtractor(
            folder_path=nscope_dir)
        check_sorting_return_types(SX_neuroscope_from_fp)
        check_sortings_equal(self.SX, SX_neuroscope_from_fp)
        check_dumping(SX_neuroscope_from_fp)

        # Tests for the NeuroscopeMultiSortingExtractor
        nscope_dir = Path(self.test_dir) / 'neuroscope_sort1'
        SX_multisorting = se.MultiSortingExtractor(
            sortings=[self.SX, self.SX])  # re-using same SX for simplicity
        se.NeuroscopeMultiSortingExtractor.write_sorting(
            SX_multisorting, nscope_dir)
        SX_neuroscope_mse = se.NeuroscopeMultiSortingExtractor(nscope_dir)
        check_sorting_return_types(SX_neuroscope_mse)
        check_sortings_equal(SX_multisorting, SX_neuroscope_mse)
        check_dumping(SX_neuroscope_mse)
示例#9
0
def yuta2nwb(
        session_path='D:/BuzsakiData/SenzaiY/YutaMouse41/YutaMouse41-150903',
        # '/Users/bendichter/Desktop/Buzsaki/SenzaiBuzsaki2017/YutaMouse41/YutaMouse41-150903',
        subject_xls=None,
        include_spike_waveforms=True,
        stub=True,
        cache_spec=True):

    subject_path, session_id = os.path.split(session_path)
    fpath_base = os.path.split(subject_path)[0]
    identifier = session_id
    mouse_number = session_id[9:11]
    if '-' in session_id:
        subject_id, date_text = session_id.split('-')
        b = False
    else:
        subject_id, date_text = session_id.split('b')
        b = True

    if subject_xls is None:
        subject_xls = os.path.join(subject_path,
                                   'YM' + mouse_number + ' exp_sheet.xlsx')
    else:
        if not subject_xls[-4:] == 'xlsx':
            subject_xls = os.path.join(subject_xls,
                                       'YM' + mouse_number + ' exp_sheet.xlsx')

    session_start_time = dateparse(date_text, yearfirst=True)

    df = pd.read_excel(subject_xls)

    subject_data = {}
    for key in [
            'genotype', 'DOB', 'implantation', 'Probe', 'Surgery',
            'virus injection', 'mouseID'
    ]:
        names = df.iloc[:, 0]
        if key in names.values:
            subject_data[key] = df.iloc[np.argmax(names == key), 1]

    if isinstance(subject_data['DOB'], datetime):
        age = session_start_time - subject_data['DOB']
    else:
        age = None

    subject = Subject(subject_id=subject_id,
                      age=str(age),
                      genotype=subject_data['genotype'],
                      species='mouse')

    nwbfile = NWBFile(
        session_description='mouse in open exploration and theta maze',
        identifier=identifier,
        session_start_time=session_start_time.astimezone(),
        file_create_date=datetime.now().astimezone(),
        experimenter='Yuta Senzai',
        session_id=session_id,
        institution='NYU',
        lab='Buzsaki',
        subject=subject,
        related_publications='DOI:10.1016/j.neuron.2016.12.011')

    print('reading and writing raw position data...', end='', flush=True)
    ns.add_position_data(nwbfile, session_path)

    shank_channels = ns.get_shank_channels(session_path)[:8]
    nshanks = len(shank_channels)
    all_shank_channels = np.concatenate(shank_channels)

    print('setting up electrodes...', end='', flush=True)
    hilus_csv_path = os.path.join(fpath_base, 'early_session_hilus_chans.csv')
    lfp_channel = get_reference_elec(subject_xls,
                                     hilus_csv_path,
                                     session_start_time,
                                     session_id,
                                     b=b)

    custom_column = [{
        'name': 'theta_reference',
        'description':
        'this electrode was used to calculate LFP canonical bands',
        'data': all_shank_channels == lfp_channel
    }]
    ns.write_electrode_table(nwbfile,
                             session_path,
                             custom_columns=custom_column,
                             max_shanks=max_shanks)

    print('reading raw electrode data...', end='', flush=True)
    if stub:
        # example recording extractor for fast testing
        xml_filepath = os.path.join(session_path, session_id + '.xml')
        xml_root = et.parse(xml_filepath).getroot()
        acq_sampling_frequency = float(
            xml_root.find('acquisitionSystem').find('samplingRate').text)
        num_channels = 4
        num_frames = 10000
        X = np.random.normal(0, 1, (num_channels, num_frames))
        geom = np.random.normal(0, 1, (num_channels, 2))
        X = (X * 100).astype(int)
        sre = se.NumpyRecordingExtractor(
            timeseries=X, sampling_frequency=acq_sampling_frequency, geom=geom)
    else:
        nre = se.NeuroscopeRecordingExtractor('{}/{}.dat'.format(
            session_path, session_id))
        sre = se.SubRecordingExtractor(nre, channel_ids=all_shank_channels)

    print('writing raw electrode data...', end='', flush=True)
    se.NwbRecordingExtractor.add_electrical_series(sre, nwbfile)
    print('done.')

    print('reading spiking units...', end='', flush=True)
    if stub:
        spike_times = [200, 300, 400]
        num_frames = 10000
        allshanks = []
        for k in range(nshanks):
            SX = se.NumpySortingExtractor()
            for j in range(len(spike_times)):
                SX.add_unit(unit_id=j + 1,
                            times=np.sort(
                                np.random.uniform(0, num_frames,
                                                  spike_times[j])))
            allshanks.append(SX)
        se_allshanks = se.MultiSortingExtractor(allshanks)
        se_allshanks.set_sampling_frequency(acq_sampling_frequency)
    else:
        se_allshanks = se.NeuroscopeMultiSortingExtractor(session_path,
                                                          keep_mua_units=False)

    electrode_group = []
    for shankn in np.arange(1, nshanks + 1, dtype=int):
        for id in se_allshanks.sortings[shankn - 1].get_unit_ids():
            electrode_group.append(nwbfile.electrode_groups['shank' +
                                                            str(shankn)])

    df_unit_features = get_UnitFeatureCell_features(fpath_base, session_id,
                                                    session_path)

    celltype_names = []
    for celltype_id, region_id in zip(df_unit_features['fineCellType'].values,
                                      df_unit_features['region'].values):
        if celltype_id == 1:
            if region_id == 3:
                celltype_names.append('pyramidal cell')
            elif region_id == 4:
                celltype_names.append('granule cell')
            else:
                raise Exception('unknown type')
        elif not np.isfinite(celltype_id):
            celltype_names.append('missing')
        else:
            celltype_names.append(celltype_dict[celltype_id])

    # Add custom column data into the SortingExtractor so it can be written by the converter
    # Note there is currently a hidden assumption that the way in which the NeuroscopeSortingExtractor
    # merges the cluster IDs matches one-to-one with the get_UnitFeatureCell_features extraction
    property_descriptions = {
        'cell_type': 'name of cell type',
        'global_id': 'global id for cell for entire experiment',
        'shank_id': '0-indexed id of cluster of shank',
        'electrode_group': 'the electrode group that each spike unit came from'
    }
    property_values = {
        'cell_type': celltype_names,
        'global_id': df_unit_features['unitID'].values,
        'shank_id': [x - 2 for x in df_unit_features['unitIDshank'].values],
        # - 2 b/c the get_UnitFeatureCell_features removes 0 and 1 IDs from each shank
        'electrode_group': electrode_group
    }
    for unit_id in se_allshanks.get_unit_ids():
        for property_name in property_descriptions.keys():
            se_allshanks.set_unit_property(
                unit_id, property_name,
                property_values[property_name][unit_id])

    se.NwbSortingExtractor.write_sorting(
        se_allshanks,
        nwbfile=nwbfile,
        property_descriptions=property_descriptions)
    print('done.')

    # Read and write LFP's
    print('reading LFPs...', end='', flush=True)
    lfp_fs, all_channels_lfp_data = ns.read_lfp(session_path, stub=stub)

    lfp_data = all_channels_lfp_data[:, all_shank_channels]
    print('writing LFPs...', flush=True)
    # lfp_data[:int(len(lfp_data)/4)]
    lfp_ts = ns.write_lfp(nwbfile,
                          lfp_data,
                          lfp_fs,
                          name='lfp',
                          description='lfp signal for all shank electrodes')

    # Read and add special environmental electrodes
    for name, channel in special_electrode_dict.items():
        ts = TimeSeries(
            name=name,
            description=
            'environmental electrode recorded inline with neural data',
            data=all_channels_lfp_data[:, channel],
            rate=lfp_fs,
            unit='V',
            #conversion=np.nan,
            resolution=np.nan)
        nwbfile.add_acquisition(ts)

    # compute filtered LFP
    print('filtering LFP...', end='', flush=True)
    all_lfp_phases = []
    for passband in ('theta', 'gamma'):
        lfp_fft = filter_lfp(
            lfp_data[:, all_shank_channels == lfp_channel].ravel(),
            lfp_fs,
            passband=passband)
        lfp_phase, _ = hilbert_lfp(lfp_fft)
        all_lfp_phases.append(lfp_phase[:, np.newaxis])
    data = np.dstack(all_lfp_phases)
    print('done.', flush=True)

    if include_spike_waveforms:
        print('writing waveforms...', end='', flush=True)
        nshanks = min((max_shanks, len(ns.get_shank_channels(session_path))))

        for shankn in np.arange(nshanks, dtype=int) + 1:
            # Get spike activty from .spk file on a per-shank and per-sample basis
            ns.write_spike_waveforms(nwbfile, session_path, shankn, stub=stub)
        print('done.', flush=True)

    # Get the LFP Decomposition Series
    decomp_series = DecompositionSeries(
        name='LFPDecompositionSeries',
        description='Theta and Gamma phase for reference LFP',
        data=data,
        rate=lfp_fs,
        source_timeseries=lfp_ts,
        metric='phase',
        unit='radians')
    decomp_series.add_band(band_name='theta', band_limits=(4, 10))
    decomp_series.add_band(band_name='gamma', band_limits=(30, 80))

    check_module(nwbfile, 'ecephys',
                 'contains processed extracellular electrophysiology data'
                 ).add_data_interface(decomp_series)

    [nwbfile.add_stimulus(x) for x in ns.get_events(session_path)]

    # create epochs corresponding to experiments/environments for the mouse

    sleep_state_fpath = os.path.join(session_path,
                                     '{}--StatePeriod.mat'.format(session_id))

    exist_pos_data = any(
        os.path.isfile(
            os.path.join(session_path, '{}__{}.mat'.format(
                session_id, task_type['name']))) for task_type in task_types)

    if exist_pos_data:
        nwbfile.add_epoch_column('label', 'name of epoch')

    for task_type in task_types:
        label = task_type['name']

        file = os.path.join(session_path, session_id + '__' + label + '.mat')
        if os.path.isfile(file):
            print('loading position for ' + label + '...', end='', flush=True)

            pos_obj = Position(name=label + '_position')

            matin = loadmat(file)
            tt = matin['twhl_norm'][:, 0]
            exp_times = find_discontinuities(tt)

            if 'conversion' in task_type:
                conversion = task_type['conversion']
            else:
                conversion = np.nan

            for pos_type in ('twhl_norm', 'twhl_linearized'):
                if pos_type in matin:
                    pos_data_norm = matin[pos_type][:, 1:]

                    spatial_series_object = SpatialSeries(
                        name=label + '_{}_spatial_series'.format(pos_type),
                        data=H5DataIO(pos_data_norm, compression='gzip'),
                        reference_frame='unknown',
                        conversion=conversion,
                        resolution=np.nan,
                        timestamps=H5DataIO(tt, compression='gzip'))
                    pos_obj.add_spatial_series(spatial_series_object)

            check_module(
                nwbfile, 'behavior',
                'contains processed behavioral data').add_data_interface(
                    pos_obj)
            for i, window in enumerate(exp_times):
                nwbfile.add_epoch(start_time=window[0],
                                  stop_time=window[1],
                                  label=label + '_' + str(i))
            print('done.')

    # there are occasional mismatches between the matlab struct and the neuroscope files
    # regions: 3: 'CA3', 4: 'DG'

    trialdata_path = os.path.join(session_path,
                                  session_id + '__EightMazeRun.mat')
    if os.path.isfile(trialdata_path):
        trials_data = loadmat(trialdata_path)['EightMazeRun']

        trialdatainfo_path = os.path.join(fpath_base, 'EightMazeRunInfo.mat')
        trialdatainfo = [
            x[0] for x in loadmat(trialdatainfo_path)['EightMazeRunInfo'][0]
        ]

        features = trialdatainfo[:7]
        features[:2] = 'start_time', 'stop_time',
        [
            nwbfile.add_trial_column(x, 'description')
            for x in features[4:] + ['condition']
        ]

        for trial_data in trials_data:
            if trial_data[3]:
                cond = 'run_left'
            else:
                cond = 'run_right'
            nwbfile.add_trial(start_time=trial_data[0],
                              stop_time=trial_data[1],
                              condition=cond,
                              error_run=trial_data[4],
                              stim_run=trial_data[5],
                              both_visit=trial_data[6])
    """
    mono_syn_fpath = os.path.join(session_path, session_id+'-MonoSynConvClick.mat')

    matin = loadmat(mono_syn_fpath)
    exc = matin['FinalExcMonoSynID']
    inh = matin['FinalInhMonoSynID']

    #exc_obj = CatCellInfo(name='excitatory_connections',
    #                      indices_values=[], cell_index=exc[:, 0] - 1, indices=exc[:, 1] - 1)
    #module_cellular.add_container(exc_obj)
    #inh_obj = CatCellInfo(name='inhibitory_connections',
    #                      indices_values=[], cell_index=inh[:, 0] - 1, indices=inh[:, 1] - 1)
    #module_cellular.add_container(inh_obj)
    """

    if os.path.isfile(sleep_state_fpath):
        matin = loadmat(sleep_state_fpath)['StatePeriod']

        table = TimeIntervals(name='states',
                              description='sleep states of animal')
        table.add_column(name='label', description='sleep state')

        data = []
        for name in matin.dtype.names:
            for row in matin[name][0][0]:
                data.append({
                    'start_time': row[0],
                    'stop_time': row[1],
                    'label': name
                })
        [
            table.add_row(**row)
            for row in sorted(data, key=lambda x: x['start_time'])
        ]

        check_module(nwbfile, 'behavior',
                     'contains behavioral data').add_data_interface(table)

    print('writing NWB file...', end='', flush=True)
    if stub:
        out_fname = session_path + '_stub.nwb'
    else:
        out_fname = session_path + '.nwb'

    with NWBHDF5IO(out_fname, mode='w') as io:
        io.write(nwbfile, cache_spec=cache_spec)
    print('done.')

    print('testing read...', end='', flush=True)
    # test read
    with NWBHDF5IO(out_fname, mode='r') as io:
        io.read()
    print('done.')