Пример #1
0
    def setUp(self):
        xx_ele, yy_ele = utils.generate_electrodes(dim=2, res=9,
                                                   xlims=[0.05, 0.95],
                                                   ylims=[0.05, 0.95])
        self.ele_pos = np.vstack((xx_ele, yy_ele)).T
        self.csd_profile = utils.large_source_2D
        pots = CSD.generate_lfp(
            self.csd_profile,
            xx_ele,
            yy_ele,
            resolution=100)
        self.pots = np.reshape(pots, (-1, 1))
        self.test_method = 'KCSD2D'
        self.test_params = {'gdx': 0.25, 'gdy': 0.25, 'R_init': 0.08,
                            'h': 50., 'xmin': 0., 'xmax': 1.,
                            'ymin': 0., 'ymax': 1.}
        temp_signals = []
        for ii in range(len(self.pots)):
            temp_signals.append(self.pots[ii])
        self.an_sigs = neo.AnalogSignal(np.array(temp_signals).T * pq.mV,
                                        sampling_rate=1000 * pq.Hz)
        chidx = neo.ChannelIndex(range(len(self.pots)))
        chidx.analogsignals.append(self.an_sigs)
        chidx.coordinates = self.ele_pos * pq.mm

        chidx.create_relationship()
Пример #2
0
    def setUp(self):
        xx_ele, yy_ele, zz_ele = utils.generate_electrodes(dim=3, res=5,
                                                           xlims=[0.15, 0.85],
                                                           ylims=[0.15, 0.85],
                                                           zlims=[0.15, 0.85])
        self.ele_pos = np.vstack((xx_ele, yy_ele, zz_ele)).T
        self.csd_profile = utils.gauss_3d_dipole
        pots = CSD.generate_lfp(self.csd_profile, xx_ele, yy_ele, zz_ele)
        self.pots = np.reshape(pots, (-1, 1))
        self.test_method = 'KCSD3D'
        self.test_params = {'gdx': 0.05, 'gdy': 0.05, 'gdz': 0.05,
                            'lambd': 5.10896977451e-19, 'src_type': 'step',
                            'R_init': 0.31, 'xmin': 0., 'xmax': 1., 'ymin': 0.,
                            'ymax': 1., 'zmin': 0., 'zmax': 1.}

        temp_signals = []
        for ii in range(len(self.pots)):
            temp_signals.append(self.pots[ii])
        self.an_sigs = neo.AnalogSignal(np.array(temp_signals).T * pq.mV,
                                        sampling_rate=1000 * pq.Hz)
        chidx = neo.ChannelIndex(range(len(self.pots)))
        chidx.analogsignals.append(self.an_sigs)
        chidx.coordinates = self.ele_pos * pq.mm

        chidx.create_relationship()
Пример #3
0
    def _get_current_segment(self,
                             filter_ids=None,
                             variables='all',
                             clear=False):
        segment = neo.Segment(
            name="segment%03d" % self._simulator.state.segment_counter,
            description=self.population.describe(),
            rec_datetime=datetime.now()
        )  # would be nice to get the time at the start of the recording, not the end
        variables_to_include = set(self.recorded.keys())
        if variables is not 'all':
            variables_to_include = variables_to_include.intersection(
                set(variables))
        for variable in variables_to_include:
            if variable == 'spikes':
                t_stop = self._simulator.state.t * pq.ms  # must run on all MPI nodes
                sids = sorted(self.filter_recorded('spikes', filter_ids))
                data = self._get_spiketimes(sids)

                segment.spiketrains = [
                    neo.SpikeTrain(data.get(int(id), []),
                                   t_start=self._recording_start_time,
                                   t_stop=t_stop,
                                   units='ms',
                                   source_population=self.population.label,
                                   source_id=int(id),
                                   source_index=self.population.id_to_index(
                                       int(id))) for id in sids
                ]
            else:
                ids = sorted(self.filter_recorded(variable, filter_ids))
                signal_array = self._get_all_signals(variable,
                                                     ids,
                                                     clear=clear)
                t_start = self._recording_start_time
                sampling_period = self.sampling_interval * pq.ms
                current_time = self._simulator.state.t * pq.ms
                mpi_node = self._simulator.state.mpi_rank  # for debugging
                if signal_array.size > 0:  # may be empty if none of the recorded cells are on this MPI node
                    units = self.population.find_units(variable)
                    source_ids = numpy.fromiter(ids, dtype=int)
                    signal = neo.AnalogSignal(
                        signal_array,
                        units=units,
                        t_start=t_start,
                        sampling_period=sampling_period,
                        name=variable,
                        source_population=self.population.label,
                        source_ids=source_ids)
                    signal.channel_index = neo.ChannelIndex(
                        index=numpy.arange(source_ids.size),
                        channel_ids=numpy.array(
                            [self.population.id_to_index(id) for id in ids]))
                    segment.analogsignals.append(signal)
                    logger.debug("%d **** ids=%s, channels=%s", mpi_node,
                                 source_ids, signal.channel_index)
                    assert segment.analogsignals[
                        0].t_stop - current_time - 2 * sampling_period < 1e-10
                    # need to add `Unit` and `RecordingChannelGroup` objects
        return segment
 def get_weights(self):
     signal = neo.AnalogSignal(self._weights,
                               units='nA',
                               sampling_period=self.interval * ms,
                               name="weight")
     signal.channel_index = neo.ChannelIndex(
         numpy.arange(len(self._weights[0])))
     return signal
Пример #5
0
 def get_channel_idx(channel_id):
     if channel_id not in channel_idxs:
         channel_idxs[channel_id] = neo.ChannelIndex(
             name='Channel {}'.format(channel_id),
             index=None,
             channel_id=channel_id)
         block.channel_indexes.append(channel_idxs[channel_id])
     return channel_idxs[channel_id]
Пример #6
0
def _get_channel_index(ids, block):
    # Note this code is only called if not pynn8_syntax
    for channel_index in block.channel_indexes:
        if numpy.array_equal(channel_index.index, ids):
            return channel_index
    count = len(block.channel_indexes)
    channel_index = neo.ChannelIndex(name="Index {}".format(count), index=ids)
    block.channel_indexes.append(channel_index)
    return channel_index
Пример #7
0
 def __get_channel_index(ids, block):
     for channel_index in block.channel_indexes:
         if numpy.array_equal(channel_index.index, ids):
             return channel_index
     count = len(block.channel_indexes)
     channel_index = neo.ChannelIndex(name="Index {}".format(count),
                                      index=ids)
     block.channel_indexes.append(channel_index)
     return channel_index
Пример #8
0
def generate_block(n_segments=3,
                   n_channels=8,
                   n_units=3,
                   data_samples=1000,
                   feature_samples=100):
    """
    Generate a block with a single recording channel group and a number of
    segments, recording channels and units with associated analog signals
    and spike trains.
    """
    feature_len = feature_samples / data_samples

    # Create container and grouping objects
    segments = [neo.Segment(index=i) for i in range(n_segments)]

    chx = neo.ChannelIndex(index=1, name='T0')

    for i in range(n_channels):
        rc = neo.RecordingChannel(name='C%d' % i, index=i)
        rc.channelindexes = [chx]
        chx.recordingchannels.append(rc)

    units = [neo.Unit('U%d' % i) for i in range(n_units)]
    chx.units = units

    block = neo.Block()
    block.segments = segments
    block.channel_indexes = [chx]

    # Create synthetic data
    for seg in segments:
        feature_pos = np.random.randint(0, data_samples - feature_samples)

        # Analog signals: Noise with a single sinewave feature
        wave = 3 * np.sin(np.linspace(0, 2 * np.pi, feature_samples))
        for rc in chx.recordingchannels:
            sig = np.random.randn(data_samples)
            sig[feature_pos:feature_pos + feature_samples] += wave

            signal = neo.AnalogSignal(sig * pq.mV, sampling_rate=1 * pq.kHz)
            seg.analogsignals.append(signal)
            rc.analogsignals.append(signal)

        # Spike trains: Random spike times with elevated rate in short period
        feature_time = feature_pos / data_samples
        for u in units:
            random_spikes = np.random.rand(20)
            feature_spikes = np.random.rand(5) * feature_len + feature_time
            spikes = np.hstack([random_spikes, feature_spikes])

            train = neo.SpikeTrain(spikes * pq.s, 1 * pq.s)
            seg.spiketrains.append(train)
            u.spiketrains.append(train)

    block.create_many_to_one_relationship()
    return block
Пример #9
0
    def setUp(self):
        self.ele_pos = utils.generate_electrodes(dim=1).reshape(5, 1)
        self.csd_profile = utils.gauss_1d_dipole
        pots = CSD.generate_lfp(self.csd_profile, self.ele_pos)
        self.pots = np.reshape(pots, (-1, 1))
        self.test_method = 'KCSD1D'
        self.test_params = {'h': 50.}

        temp_signals = []
        for ii in range(len(self.pots)):
            temp_signals.append(self.pots[ii])
        self.an_sigs = neo.AnalogSignal(np.array(temp_signals).T * pq.mV,
                                        sampling_rate=1000 * pq.Hz)
        chidx = neo.ChannelIndex(range(len(self.pots)))
        chidx.analogsignals.append(self.an_sigs)
        chidx.coordinates = self.ele_pos * pq.mm

        chidx.create_relationship()
Пример #10
0
def ImageSequence2AnalogSignal(block):
    # ToDo: map potentially 2D array annotations to 1D and update
    for seg_count, segment in enumerate(block.segments):
        for imgseq in segment.imagesequences:
            dim_t, dim_x, dim_y = imgseq.as_array().shape
            # coords = np.zeros((dim_x, dim_y, 2), dtype=int)
            # for x, row in enumerate(coords):
            #     for y, cell in enumerate(row):
            #         coords[x][y][0] = x
            #         coords[x][y][1] = y
            # coords = coords.reshape((dim_x * dim_y, 2))
            coords = np.array(
                list(itertools.product(np.arange(dim_x), np.arange(dim_y))))

            imgseq_flat = imgseq.as_array().reshape((dim_t, dim_x * dim_y))

            asig = neo.AnalogSignal(signal=imgseq_flat,
                                    units=imgseq.units,
                                    sampling_rate=imgseq.sampling_rate,
                                    file_origin=imgseq.file_origin,
                                    description=imgseq.description,
                                    name=imgseq.name,
                                    array_annotations={
                                        'x_coords': coords[:, 0],
                                        'y_coords': coords[:, 1]
                                    },
                                    grid_size=(dim_x, dim_y),
                                    spatial_scale=imgseq.spatial_scale,
                                    **imgseq.annotations)

            chidx = neo.ChannelIndex(name=asig.name,
                                     channel_ids=np.arange(dim_x * dim_y),
                                     index=np.arange(dim_x * dim_y),
                                     coordinates=coords * imgseq.spatial_scale)

            chidx.annotations.update(asig.array_annotations)
            # asig.channel_index = chidx
            chidx.analogsignals = [asig] + chidx.analogsignals
            # block.channel_indexes.append(chidx)
            block.segments[seg_count].analogsignals.append(asig)
    return block
Пример #11
0
def test_load_save():
    n_channels = 5
    n_samples = 20
    n_spikes = 50
    fname = '/tmp/test_phy.exdir'
    if os.path.exists(fname):
        shutil.rmtree(fname)
    wf = np.random.random((n_spikes, n_channels, n_samples))
    ts = np.sort(np.random.random(n_spikes))
    t_stop = np.ceil(ts[-1])
    sptr = neo.SpikeTrain(times=ts, units='s', waveforms=wf * pq.V,
                          t_stop=t_stop, **{'group_id': 0})
    blk = neo.Block()
    seg = neo.Segment()
    seg.duration = t_stop
    blk.segments.append(seg)
    chx = neo.ChannelIndex(index=range(n_channels), **{'group_id': 0})
    blk.channel_indexes.append(chx)
    sptr.channel_index = chx
    unit = neo.Unit()
    unit.spiketrains.append(sptr)
    chx.units.append(unit)
    seg.spiketrains.append(sptr)
    epo = neo.Epoch()
    if os.path.exists(fname):
        shutil.rmtree(fname)
    io = neo.ExdirIO(fname)
    io.write_block(blk)
    wfswap = wf.swapaxes(1, 2)
    m = NeoModel(fname, overwrite=True)
    assert np.array_equal(m.spike_times, ts)
    assert np.array_equal(m.waveforms, wfswap)
    m.save()
    m2 = NeoModel(fname, overwrite=True)
    assert np.array_equal(m2.spike_times, ts)
    assert np.array_equal(m2.waveforms, wfswap)
    assert np.array_equal(m2.features, m.features)
    assert np.array_equal(m2.amplitudes, m.amplitudes)
    assert np.array_equal(m2.spike_clusters, m.spike_clusters)
Пример #12
0
def build_block(data_file):
    """(plaintextfile_path) -> neo.core.block.Block
    Thie function reads a plain text file (data_file) with the data exported (per waveform) from Plexon Offline Sorter after sorting and returns a neo.Block with spiketrains ordered in any number of 10 minute segments.

    For practicality and Plexon management of channels names, units and channels have been ignored in the block structure."""

    raw_data = pd.read_csv(data_file, sep=',', header=0, usecols=[0, 1, 2])
    ord_times = raw_data.groupby(['Channel Name', 'Unit'])['Timestamp']
    new_block = neo.Block()
    chx = neo.ChannelIndex(index=None, name='MEA_60')
    new_block.channel_indexes.append(chx)
    # Next line will not work properly if last spike happens
    # exactly at the end of the recording
    num_segments = range(int(raw_data['Timestamp'].max() // 600 + 1))
    for ind in num_segments:
        seg = neo.Segment(name='segment {}'.format(ind), index=ind)
        new_block.segments.append(seg)

    for name, group in ord_times:
        time_stamps = ord_times.get_group(name).values
        inter = 600  # Number of seconds in 10 minutes
        first_seg = neo.SpikeTrain(
            time_stamps[time_stamps < inter], units='sec', t_start=0,  t_stop=inter)
        new_block.segments[0].spiketrains.append(first_seg)
        new_unit = neo.Unit(name=name)
        sptrs = [first_seg]
        for seg in num_segments[1:-1]:
            seg_train = neo.SpikeTrain(time_stamps[(time_stamps > seg * inter) & (time_stamps < ((seg + 1) * inter))],
                                       units='sec', t_start=(seg * inter), t_stop=((seg + 1) * inter))
            new_block.segments[seg].spiketrains.append(seg_train)
            sptrs.append(seg_train)
        last_seg = neo.SpikeTrain(time_stamps[time_stamps > (num_segments[-1] * inter)], units='sec',
                                  t_start=(num_segments[-1]) * inter, t_stop=((num_segments[-1] + 1) * inter))
        new_block.segments[num_segments[-1]].spiketrains.append(last_seg)
        sptrs.append(last_seg)
        new_unit.spiketrains = sptrs
        chx.units.append(new_unit)
    return new_block
Пример #13
0
def generate_spike_trains(exdir_path, openephys_rec, source='klusta'):
    import neo
    if source == 'klusta':  # TODO acquire features and masks
        print('Generating spike trains from KWIK file')
        exdir_file = exdir.File(exdir_path)
        acquisition = exdir_file["acquisition"]
        openephys_session = acquisition.attrs["openephys_session"]
        klusta_directory = op.join(str(acquisition.directory),
                                   openephys_session, 'klusta')
        n = 0
        for root, dirs, files in os.walk(klusta_directory):
            for f in files:
                if not f.endswith('_klusta.kwik'):
                    continue
                n += 1
                kwikfile = op.join(root, f)
                kwikio = neo.io.KwikIO(filename=kwikfile, )
                blk = kwikio.read_block(raw_data_units='uV')
                seg = blk.segments[0]
                try:
                    exdirio = neo.io.ExdirIO(exdir_path)
                    exdirio.write_block(blk)
                except Exception:
                    print('WARNING: unable to convert\n', kwikfile)
        if n == 0:
            raise IOError('.kwik file cannot be found in ' + klusta_directory)
    elif source == 'openephys':
        exdirio = neo.io.ExdirIO(exdir_path)
        for oe_group in openephys_rec.channel_groups:
            channel_ids = [ch.id for ch in oe_group.channels]
            channel_index = [ch.index for ch in oe_group.channels]
            chx = neo.ChannelIndex(name='channel group {}'.format(oe_group.id),
                                   channel_ids=channel_ids,
                                   index=channel_index,
                                   group_id=oe_group.id)
            for sptr in oe_group.spiketrains:
                unit = neo.Unit(cluster_group='unsorted',
                                cluster_id=sptr.attrs['cluster_id'],
                                name=sptr.attrs['name'])
                unit.spiketrains.append(
                    neo.SpikeTrain(times=sptr.times,
                                   waveforms=sptr.waveforms,
                                   sampling_rate=sptr.sample_rate,
                                   t_stop=sptr.t_stop,
                                   **sptr.attrs))
                chx.units.append(unit)
            exdirio.write_channelindex(chx,
                                       start_time=0 * pq.s,
                                       stop_time=openephys_rec.duration)
    elif source == 'kilosort':
        print('Generating spike trains from KiloSort')
        exdirio = neo.io.ExdirIO(exdir_path)
        exdir_file = exdir.File(exdir_path)
        openephys_directory = op.join(
            str(exdir_file["acquisition"].directory),
            exdir_file["acquisition"].attrs["openephys_session"])
        # iterate over channel groups. As there are no channel associated with
        # any spiking unit (TO BE IMPLEMENTED), everything is written to
        # channel_group 0
        for oe_group in openephys_rec.channel_groups:
            channel_ids = [ch.id for ch in oe_group.channels]
            channel_index = [ch.index for ch in oe_group.channels]
            chx = neo.ChannelIndex(name='channel group {}'.format(oe_group.id),
                                   channel_ids=channel_ids,
                                   index=channel_index,
                                   group_id=oe_group.id)
            # load output
            spt = np.load(op.join(openephys_directory,
                                  'spike_times.npy')).flatten()
            spc = np.load(op.join(openephys_directory,
                                  'spike_clusters.npy')).flatten()
            try:
                cgroup = np.loadtxt(op.join(openephys_directory,
                                            'cluster_group.tsv'),
                                    dtype=[('cluster_id', 'i4'),
                                           ('group', 'U8')],
                                    skiprows=1)
                if cgroup.shape == (0, ):
                    raise FileNotFoundError
            except FileNotFoundError:
                # manual corrections didn't happen;
                cgroup = np.array(list(
                    zip(np.unique(spc), ['unsorted'] * np.unique(spc).size)),
                                  dtype=[('cluster_id', 'i4'),
                                         ('group', 'U8')])
            for id, grp in cgroup:
                unit = neo.Unit(cluster_group=str(grp), cluster_id=id, name=id)
                unit.spiketrains.append(
                    neo.SpikeTrain(
                        times=(spt[spc == id].astype(float) /
                               openephys_rec.sample_rate).simplified,
                        t_stop=openephys_rec.duration,
                    ))
                chx.units.append(unit)
            exdirio.write_channelindex(chx,
                                       start_time=0 * pq.s,
                                       stop_time=openephys_rec.duration)
            break
    else:
        raise ValueError(source + ' not supported')
Пример #14
0
import neo
import quantities as pq
import numpy as np
import nixio as nix
from neo.io import NixIO

block = neo.Block()
chn_index = neo.ChannelIndex([0, 1, 2],
                             channel_names=["a", "b", "c"],
                             channel_ids=[1, 2, 3])
block.channel_indexes.append(chn_index)
unit = neo.Unit(name="x", description="contain1st")
chn_index.units.append(unit)

seg = neo.Segment()
asig = neo.AnalogSignal(name="signal",
                        signal=[1.1, 1.2, 1.5],
                        units="mV",
                        sampling_rate=1 * pq.Hz)
seg.analogsignals.append(asig)
asig2 = neo.AnalogSignal(name="signal2",
                         signal=[1.1, 1.2, 2.5],
                         units="mV",
                         sampling_rate=1 * pq.Hz)
seg.analogsignals.append(asig2)
irasig = neo.IrregularlySampledSignal(name="irsignal",
                                      signal=np.random.random((100, 2)),
                                      units="mV",
                                      times=np.cumsum(
                                          np.random.random(100) * pq.s))
seg.irregularlysampledsignals.append(irasig)
if options.plot_figure:
    from pyNN.utility.plotting import Figure, Panel
    #figure_filename = normalized_filename("Results", "stochastic_comparison",
    #                                      "png", options.simulator)
    figure_filename = "Results/stochastic_comparison_{}.png".format(
        options.simulator)

    data = {}
    for label in synapse_types:
        data[label] = populations[label].get_data().segments[0]
        if 'stochastic' in label:
            gsyn = data[label].filter(name='gsyn_inh')[0]
            gsyn_mean = neo.AnalogSignal(gsyn.mean(axis=1).reshape(-1, 1),
                                         sampling_rate=gsyn.sampling_rate)
            gsyn_mean.channel_index = neo.ChannelIndex(np.array([0]))
            gsyn_mean.name = 'gsyn_inh_mean'
            data[label].analogsignals.append(gsyn_mean)

    def make_panel(population, label):
        return Panel(
            population.get_data().segments[0].filter(name='gsyn_inh')[0],
            data_labels=[label],
            yticks=True)

    panels = [
        Panel(data['depressing, deterministic'].filter(name='gsyn_inh')[0][:,
                                                                           0],
              data_labels=['depressing, deterministic'],
              yticks=True,
              ylim=[0, 0.008]),
Пример #16
0
    def save(self, spike_clusters=None, groups=None, *labels):
        if spike_clusters is None:
            spike_clusters = self.spike_clusters
        assert spike_clusters.shape == self.spike_clusters.shape
        # assert spike_clusters.dtype == self.spike_clusters.dtype # TODO check if this is necessary
        self.spike_clusters = spike_clusters
        blk = neo.Block()
        seg = neo.Segment(name='Segment_{}'.format(self.segment_num),
                          index=self.segment_num)
        # seg.duration = self.duration
        blk.segments.append(seg)
        metadata = self.chx.annotations
        if labels:
            metadata.update({name: values for name, values in labels})
        chx = neo.ChannelIndex(index=self.chx.index,
                               name=self.chx.name,
                               **metadata)
        blk.channel_indexes.append(chx)
        try:
            wf_units = self.sptrs[0].waveforms.units
        except AttributeError:
            wf_units = pq.dimensionless
        clusters = np.unique(spike_clusters)
        self.cluster_groups = groups or self.cluster_groups
        for sc in clusters:
            mask = self.spike_clusters == sc
            waveforms = np.swapaxes(self.waveforms[mask], 1, 2) * wf_units
            sptr = neo.SpikeTrain(times=self.spike_times[mask] * pq.s,
                                  waveforms=waveforms,
                                  sampling_rate=self.sample_rate * pq.Hz,
                                  name='cluster #%i' % sc,
                                  t_stop=self.duration,
                                  t_start=self.start_time,
                                  **{'cluster_id': sc,
                                     'cluster_group': self.cluster_groups[sc].lower(),
                                     'kk2_metadata': self.kk2_metadata})
            sptr.channel_index = chx
            unt = neo.Unit(name='Unit #{}'.format(sc),
                           **{'cluster_id': sc,
                              'cluster_group': self.cluster_groups[sc].lower()})
            unt.spiketrains.append(sptr)
            chx.units.append(unt)
            seg.spiketrains.append(sptr)

        # save block to file
        try:
            io = neo.get_io(self.save_path, mode=self.mode)
        except Exception:
            io = neo.get_io(self.save_path)
        io.write_block(blk)
        if hasattr(io, 'close'):
            io.close()
        if self.output_ext == '.exdir':
            # save features and masks
            group = exdir.File(directory=self.save_path)
            self._exdir_save_group = self._find_exdir_channel_group(
                group["processing"]['electrophysiology']) # TODO not use elphys name
            if self._exdir_save_group is None:
                raise IOError('Can not find a dirctory corresponding to ' +
                              'channel_group {}'.format(self.channel_group))
            self.save_features_masks(spike_clusters)
Пример #17
0
    def load_data(self, channel_group=None, segment_num=None):
        io = neo.get_io(self.data_path)
        print(self.data_path)
        assert io.is_readable
        self.channel_group = channel_group or self.channel_group
        self.segment_num = segment_num or self.segment_num
        if self.segment_num is None:
            self.segment_num = 0  # TODO find the right seg num
        if neo.Block in io.readable_objects:
            logger.info('Loading block')
            blk = io.read_block()  # TODO params to select what to read
            try:
                io.close()
            except:
                pass

            if not all(['group_id' in chx.annotations
                        for chx in blk.channel_indexes]):
                logger.warn('"group_id" is not in channel_index.annotations ' +
                            'counts channel_group as appended to ' +
                            'Block.channel_indexes')
                self._chxs = {i: chx for i, chx in
                              enumerate(blk.channel_indexes)}
            else:
                self._chxs = {int(chx.annotations['group_id']): chx
                              for chx in blk.channel_indexes}
            self.channel_groups = list(self._chxs.keys())

            self.seg = blk.segments[self.segment_num]
            if self.channel_group is None:
                self.channel_group = self.channel_groups[0]
            if self.channel_group not in self.channel_groups:
                raise ValueError('channel group not available,' +
                                 ' see available channel groups in neo-describe')
            self.chx = self._chxs[self.channel_group]
            self.sptrs = [st for st in self.seg.spiketrains
                          if st.channel_index == self.chx]
        elif neo.Segment in io.readable_objects:
            logger.info('Loading segment')
            self.seg = io.read_segment()
            self.segment_num = 0
            self.sptrs = self.seg.spiketrains
            self.chx = neo.ChannelIndex(
                index=[range(self.sptrs[0].waveforms.shape[1])],
                **{'group_id': 0}
            )

        self.duration = self.seg.t_stop - self.seg.t_start
        self.start_time = self.seg.t_start

        self.channel_ids = self.chx.index
        self.n_chans = len(self.chx.index)

        self.sample_rate = self.sptrs[0].sampling_rate.rescale('Hz').magnitude

        self.spike_times = self._load_spike_times()
        sorted_idxs = np.argsort(self.spike_times)
        self.spike_times = self.spike_times[sorted_idxs]
        ns, = self.n_spikes, = self.spike_times.shape

        self.spike_clusters = self._load_spike_clusters()[sorted_idxs]
        assert self.spike_clusters.shape == (ns,)

        self.cluster_groups = self._load_cluster_groups()

        self.waveforms = self._load_waveforms()[sorted_idxs, :, :]
        assert self.waveforms.shape[::2] == (ns, self.n_chans), '{} != {}'.format(self.waveforms.shape[::2], (ns, self.n_chans))

        self.features, self.masks = self._load_features_masks() # loads from waveforms which is already sorted

        self.amplitudes = self._load_amplitudes()
        assert self.amplitudes.shape == (ns, self.n_chans)

        # TODO load positino from params
        ch_pos = np.zeros((self.n_chans, 2))
        ch_pos[:, 1] = np.arange(self.n_chans)
        self.channel_positions = ch_pos
Пример #18
0
def generate_lfp(csd_profile,
                 x_positions,
                 y_positions=None,
                 z_positions=None,
                 x_limits=[0., 1.],
                 y_limits=[0., 1.],
                 z_limits=[0., 1.],
                 resolution=50):
    """
    Forward modelling for getting the potentials for testing Current Source
    Density (CSD).

    Parameters
    ----------
    csd_profile : callable
        A function that computes true CSD profile.
        Available options are (see ./csd/utility_functions.py)
        1D : gauss_1d_dipole
        2D : large_source_2D and small_source_2D
        3D : gauss_3d_dipole
    x_positions : np.ndarray
        Positions of the x coordinates of the electrodes
    y_positions : np.ndarray, optional
        Positions of the y coordinates of the electrodes
        Defaults to None, use in 2D or 3D cases only
    z_positions : np.ndarray, optional
        Positions of the z coordinates of the electrodes
        Defaults to None, use in 3D case only
    x_limits : list, optional
        A list of [start, end].
        The starting spatial coordinate and the ending for integration
        Defaults to [0.,1.]
    y_limits : list, optional
        A list of [start, end].
        The starting spatial coordinate and the ending for integration
        Defaults to [0.,1.], use only in 2D and 3D case
    z_limits : list, optional
        A list of [start, end].
        The starting spatial coordinate and the ending for integration
        Defaults to [0.,1.], use only in 3D case
    resolution : int, optional
        The resolution of the integration
        Defaults to 50

    Returns
    -------
    LFP : neo.AnalogSignal
       The potentials created by the csd profile at the electrode positions.
       The electrode positions are attached as RecordingChannel's coordinate.
    """
    def integrate_1D(x0, csd_x, csd, h):
        m = np.sqrt((csd_x - x0)**2 + h**2) - abs(csd_x - x0)
        y = csd * m
        I = simps(y, csd_x)
        return I

    def integrate_2D(x, y, xlin, ylin, csd, h, X, Y):
        x = np.reshape(x, (1, 1, len(x)))
        y = np.reshape(y, (1, 1, len(y)))
        X = np.expand_dims(X, axis=2)
        Y = np.expand_dims(Y, axis=2)
        csd = np.expand_dims(csd, axis=2)
        m = np.sqrt((x - X)**2 + (y - Y)**2)
        np.clip(m, a_min=0.0000001, a_max=None, out=m)
        y = np.arcsinh(2 * h / m) * csd
        I = simps(y.T, ylin)
        F = simps(I, xlin)
        return F

    def integrate_3D(x, y, z, csd, xlin, ylin, zlin, X, Y, Z):
        m = np.sqrt((x - X)**2 + (y - Y)**2 + (z - Z)**2)
        np.clip(m, a_min=0.0000001, a_max=None, out=m)
        z = csd / m
        Iy = simps(np.transpose(z, (1, 0, 2)), zlin)
        Iy = simps(Iy, ylin)
        F = simps(Iy, xlin)
        return F

    dim = 1
    if z_positions is not None:
        dim = 3
    elif y_positions is not None:
        dim = 2

    x = np.linspace(x_limits[0], x_limits[1], resolution)
    sigma = 1.0
    h = 50.
    if dim == 1:
        chrg_x = x
        csd = csd_profile(chrg_x)
        pots = integrate_1D(x_positions, chrg_x, csd, h)
        pots /= 2. * sigma  # eq.: 26 from Potworowski et al
        ele_pos = x_positions
    elif dim == 2:
        y = np.linspace(y_limits[0], y_limits[1], resolution)
        chrg_x = np.expand_dims(x, axis=1)
        chrg_y = np.expand_dims(y, axis=0)
        csd = csd_profile(chrg_x, chrg_y)
        pots = integrate_2D(x_positions, y_positions, x, y, csd, h, chrg_x,
                            chrg_y)
        pots /= 2 * np.pi * sigma
        ele_pos = np.vstack((x_positions, y_positions)).T
    elif dim == 3:
        y = np.linspace(y_limits[0], y_limits[1], resolution)
        z = np.linspace(z_limits[0], z_limits[1], resolution)
        chrg_x, chrg_y, chrg_z = np.mgrid[
            x_limits[0]:x_limits[1]:np.complex(0, resolution),
            y_limits[0]:y_limits[1]:np.complex(0, resolution),
            z_limits[0]:z_limits[1]:np.complex(0, resolution)]

        csd = csd_profile(chrg_x, chrg_y, chrg_z)

        pots = np.zeros(len(x_positions))
        for ii in range(len(x_positions)):
            pots[ii] = integrate_3D(x_positions[ii], y_positions[ii],
                                    z_positions[ii], csd, x, y, z, chrg_x,
                                    chrg_y, chrg_z)
        pots /= 4 * np.pi * sigma
        ele_pos = np.vstack((x_positions, y_positions, z_positions)).T
    ele_pos = ele_pos * pq.mm
    ch = neo.ChannelIndex(index=range(len(pots)))
    asig = neo.AnalogSignal(np.expand_dims(pots, axis=0),
                            sampling_rate=pq.kHz,
                            units='mV')
    ch.coordinates = ele_pos
    ch.analogsignals.append(asig)
    ch.create_relationship()
    return asig
Пример #19
0
def save_spikesorting(sorting_file,
                      block,
                      sorting_hash=None,
                      parameter_dict=None):
    """
    :param savedir:
    :param block:
    :return:
    """

    if parameter_dict is None and sorting_hash is None:
        raise ValueError('Please provide either a parameter dictionary or a '
                         'sorting hash to specify the sorting you want to '
                         'load.')
    elif parameter_dict is not None:
        sorting_hash = elephant.spike_sorting.SpikeSorter.get_sorting_hash(
            parameter_dict)

    filename = sorting_file + '_spikesorting.hdf5'
    print('Saving sorted spikes (sorting hash {}) at {}'
          ''.format(sorting_hash, filename))

    sorting_chidx = [
        i for i in block.channel_indexes
        if ('sorting_hash' in i.annotations
            and i.annotations['sorting_hash'] == sorting_hash)
    ]

    if len(sorting_chidx) == 0:
        warnings.warn('No channel_index selected for saving spikesorting with '
                      'hash "{}". Not saving anything.'.format(sorting_hash))
        return

    elif len(sorting_chidx) > 1:
        warnings.warn('Multiple channels with sorting hash "{}" exist. Not '
                      'saving anything.'.format(sorting_hash))
        return
    sorting_chidx = sorting_chidx[0]

    with neo.nixio.NixIO(filename, 'rw') as nix_file:
        # check if there is already a block with the same channel_index annotation
        nix_blocks = nix_file.read_all_blocks()
        new_block = False
        if len(nix_blocks) is 0:
            new_block = True
            nix_blocks = [neo.Block(name='spike sorting block')]
            nix_blocks[0].segments.append(
                neo.Segment(name='spike sorting '
                            'segment'))

        assert len(nix_blocks[0].segments) == 1
        nix_block = nix_blocks[0]
        seg = nix_blocks[0].segments[0]

        # check if channel_index for this sorting already exists
        chidx = None
        for chidx_i in nix_block.channel_indexes:
            if chidx_i.annotations['sorting_hash'] == sorting_hash:
                chidx = chidx_i
                break
        if chidx is None:
            chidx = neo.ChannelIndex([-1],
                                     name='spike sorting',
                                     sorting_hash=sorting_hash)
            for anno in ['sorter', 'sorting_parameters']:
                if anno in sorting_chidx.annotations:
                    chidx.annotations[anno] = sorting_chidx.annotations[anno]

            chidx.block = nix_block
            nix_block.channel_indexes.append(chidx)

        duplicated_units = [copy.deepcopy(u) for u in sorting_chidx.units]
        for uid, unit in enumerate(duplicated_units):
            chidx.units.append(unit)
            unit.channel_index = chidx
            # spiketrain is automatically duplicated when rescaled
            original_sts = sorting_chidx.units[uid].spiketrains
            unit.spiketrains = []
            for o_st in original_sts:
                # TODO: Remove this rescaling quickfix once nixpy is fixed
                # but duplicate spiketrain instead
                duplicated_st = o_st.rescale('s')
                unit.spiketrains.append(duplicated_st)

            # duplicating and decoupling of spiketrains from original neo structure
            for st in unit.spiketrains:
                ######################
                # # TODO: Remove this quickfix once nixpy is fixed
                # # Quickfix
                # st_new = st.rescale('s')
                # unit.spiketrains.remove(st)
                # unit.spiketrains.append(st_new)
                # st_new.segment = seg

                # TODO: Remove this quickfix once neo nixio is fixed
                if st.left_sweep:
                    st.left_sweep = [st.left_sweep.rescale('s').magnitude
                                     ] * pq.s
                st.sampling_rate = st.sampling_rate.rescale('Hz')
                if ('invalid_waveforms' in st.annotations
                        and st.annotations['invalid_waveforms'] == []):
                    st.annotations['invalid_waveforms'] = 0
                ########################

                st.unit = unit
                st.segment = seg

            seg.spiketrains.extend(unit.spiketrains)

        nix_block.create_relationship()
        nix_file.write_block(nix_block)
Пример #20
0
def generate_lfp(csd_profile,
                 ele_xx,
                 ele_yy=None,
                 ele_zz=None,
                 xlims=[0., 1.],
                 ylims=[0., 1.],
                 zlims=[0., 1.],
                 res=50):
    """Forward modelling for the getting the potentials for testing CSD

        Parameters
        ----------
        csd_profile : fuction that computes True CSD profile
            Available options are (see ./csd/utility_functions.py)
            1D : gauss_1d_dipole
            2D : large_source_2D and small_source_2D
            3D : gauss_3d_dipole
        ele_xx : np.array
            Positions of the x coordinates of the electrodes
        ele_yy : np.array
            Positions of the y coordinates of the electrodes
            Defaults ot None, use in 2D or 3D cases only
        ele_zz : np.array
            Positions of the z coordinates of the electrodes
            Defaults ot None, use in 3D case only
        x_lims : [start, end]
            The starting spatial coordinate and the ending for integration
            Defaults to [0.,1.]
        y_lims : [start, end]
            The starting spatial coordinate and the ending for integration
            Defaults to [0.,1.], use only in 2D and 3D case
        z_lims : [start, end]
            The starting spatial coordinate and the ending for integration
            Defaults to [0.,1.], use only in 3D case
        res : int
            The resolution of the integration
            Defaults to 50

        Returns
        -------
        LFP : neo.AnalogSignal object
           The potentials created by the csd profile at the electrode positions
           The electrode postions are attached as RecordingChannel's coordinate
    """
    def integrate_1D(x0, csd_x, csd, h):
        m = np.sqrt((csd_x - x0)**2 + h**2) - abs(csd_x - x0)
        y = csd * m
        I = simps(y, csd_x)
        return I

    def integrate_2D(x, y, xlin, ylin, csd, h, X, Y):
        Ny = ylin.shape[0]
        m = np.sqrt((x - X)**2 + (y - Y)**2)
        m[m < 0.0000001] = 0.0000001
        y = np.arcsinh(2 * h / m) * csd
        I = np.zeros(Ny)
        for i in range(Ny):
            I[i] = simps(y[:, i], ylin)
        F = simps(I, xlin)
        return F

    def integrate_3D(x, y, z, xlim, ylim, zlim, csd, xlin, ylin, zlin, X, Y,
                     Z):
        Nz = zlin.shape[0]
        Ny = ylin.shape[0]
        m = np.sqrt((x - X)**2 + (y - Y)**2 + (z - Z)**2)
        m[m < 0.0000001] = 0.0000001
        z = csd / m
        Iy = np.zeros(Ny)
        for j in range(Ny):
            Iz = np.zeros(Nz)
            for i in range(Nz):
                Iz[i] = simps(z[:, j, i], zlin)
            Iy[j] = simps(Iz, ylin)
        F = simps(Iy, xlin)
        return F

    dim = 1
    if ele_zz is not None:
        dim = 3
    elif ele_yy is not None:
        dim = 2
    x = np.linspace(xlims[0], xlims[1], res)
    if dim >= 2:
        y = np.linspace(ylims[0], ylims[1], res)
    if dim == 3:
        z = np.linspace(zlims[0], zlims[1], res)
    sigma = 1.0
    h = 50.
    pots = np.zeros(len(ele_xx))
    if dim == 1:
        chrg_x = np.linspace(xlims[0], xlims[1], res)
        csd = csd_profile(chrg_x)
        for ii in range(len(ele_xx)):
            pots[ii] = integrate_1D(ele_xx[ii], chrg_x, csd, h)
        pots /= 2. * sigma  # eq.: 26 from Potworowski et al
        ele_pos = ele_xx
    elif dim == 2:
        chrg_x, chrg_y = np.mgrid[xlims[0]:xlims[1]:np.complex(0, res),
                                  ylims[0]:ylims[1]:np.complex(0, res)]
        csd = csd_profile(chrg_x, chrg_y)
        for ii in range(len(ele_xx)):
            pots[ii] = integrate_2D(ele_xx[ii], ele_yy[ii], x, y, csd, h,
                                    chrg_x, chrg_y)
        pots /= 2 * np.pi * sigma
        ele_pos = np.vstack((ele_xx, ele_yy)).T
    elif dim == 3:
        chrg_x, chrg_y, chrg_z = np.mgrid[xlims[0]:xlims[1]:np.complex(0, res),
                                          ylims[0]:ylims[1]:np.complex(0, res),
                                          zlims[0]:zlims[1]:np.complex(0, res)]
        csd = csd_profile(chrg_x, chrg_y, chrg_z)
        xlin = chrg_x[:, 0, 0]
        ylin = chrg_y[0, :, 0]
        zlin = chrg_z[0, 0, :]
        for ii in range(len(ele_xx)):
            pots[ii] = integrate_3D(ele_xx[ii], ele_yy[ii], ele_zz[ii], xlims,
                                    ylims, zlims, csd, xlin, ylin, zlin,
                                    chrg_x, chrg_y, chrg_z)
        pots /= 4 * np.pi * sigma
        ele_pos = np.vstack((ele_xx, ele_yy, ele_zz)).T
    pots = np.reshape(pots, (-1, 1)) * pq.mV
    ele_pos = ele_pos * pq.mm
    lfp = []
    ch = neo.ChannelIndex(index=range(len(pots)))
    for ii in range(len(pots)):
        lfp.append(pots[ii])
    asig = neo.AnalogSignal(np.array(lfp).T, sampling_rate=pq.kHz, units='mV')
    ch.coordinates = ele_pos
    ch.analogsignals.append(asig)
    ch.create_relationship()
    return asig
Пример #21
0
        ][0])
    asig.array_annotations.update(electrode_location=locations)

    colors = [
        kwargs['ELECTRODE_COLOR'][loc]
        for loc in asig.array_annotations['electrode_location']
    ]
    asig.array_annotations.update(electrode_color=colors)

    asig.annotations.update(parse_string2dict(args.annotations))
    asig.annotations.update(spatial_scale=args.spatial_scale * pq.mm)

    dim_t, channel_num = asig.as_array().shape

    chidx = neo.ChannelIndex(name=asig.name,
                             channel_ids=np.arange(channel_num),
                             index=np.arange(channel_num),
                             coordinates=coords * args.spatial_scale * pq.mm)
    chidx.annotations.update(asig.array_annotations)

    # Save data
    block.name = args.data_name
    block.segments[0].name = 'Segment 1'
    block.segments[0].description = 'Loaded with neo.Spike2IO (neo version {})'\
                                    .format(neo.__version__)
    if asig.description is None:
        asig.description = ''
    asig.description += 'ECoG signal. '

    # Save data
    if len(block.segments[0].analogsignals) > 1:
        raise Warning('Additional AnalogSignal found. The pipeline can yet \