Exemple #1
0
    def merge(self, other):
        '''
        Merge the another :class:`Epoch` into this one.

        The :class:`Epoch` objects are concatenated horizontally
        (column-wise), :func:`np.hstack`).

        If the attributes of the two :class:`Epoch` are not
        compatible, and Exception is raised.
        '''
        othertimes = other.times.rescale(self.times.units)
        otherdurations = other.durations.rescale(self.durations.units)
        times = np.hstack([self.times, othertimes]) * self.times.units
        durations = np.hstack([self.durations, otherdurations
                               ]) * self.durations.units
        labels = np.hstack([self.labels, other.labels])
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)

        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)
        return Epoch(times=times, durations=durations, labels=labels, **kwargs)
Exemple #2
0
    def test_merge_annotations__func__dict(self):
        ann1 = {'val0': 'val0', 'val1': 1, 'val2': 2.2, 'val3': 'test1',
                'val4': [.4], 'val5': {0: 0, 1: {0: 0}},
                'val6': np.array([0, 1, 2])}
        ann2 = {'val2': 2.2, 'val3': 'test2',
                'val4': [4, 4.4], 'val5': {1: {1: 1}, 2: 2},
                'val6': np.array([4, 5, 6]), 'val7': True}

        ann1c = ann1.copy()
        ann2c = ann2.copy()

        targ = {'val0': 'val0', 'val1': 1, 'val2': 2.2, 'val3': 'test1;test2',
                'val4': [.4, 4, 4.4], 'val5': {0: 0, 1: {0: 0, 1: 1}, 2: 2},
                'val7': True}

        res = merge_annotations(ann1, ann2)

        val6t = np.array([0, 1, 2, 4, 5, 6])
        val6r = res.pop('val6')
        val61 = ann1.pop('val6')
        val61c = ann1c.pop('val6')
        val62 = ann2.pop('val6')
        val62c = ann2c.pop('val6')

        self.assertEqual(ann1, ann1c)
        self.assertEqual(ann2, ann2c)
        self.assertEqual(res, targ)

        assert_arrays_equal(val6r, val6t)
        self.assertRaises(AssertionError, assert_arrays_equal, val61, val6t)
        assert_arrays_equal(val61, val61c)
        assert_arrays_equal(val62, val62c)
Exemple #3
0
 def test_merge_annotations__dict(self):
     value1 = {'val1': 1, 'val2': 2.2, 'val3': 'test1'}
     value2 = {'val2': 2.2, 'val3': 'test2', 'val4': [4, 4.4], 'val5': True}
     targ = {'val1': 1, 'val2': 2.2, 'val3': 'test1;test2',
             'val4': [4, 4.4], 'val5': True}
     res = merge_annotations(value1, value2)
     self.assertEqual(targ, res)
Exemple #4
0
    def merge(self, other):
        '''
        Merge the another :class:`Event` into this one.

        The :class:`Event` objects are concatenated horizontally
        (column-wise), :func:`np.hstack`).

        If the attributes of the two :class:`Event` are not
        compatible, and Exception is raised.
        '''
        othertimes = other.times.rescale(self.times.units)
        times = np.hstack([self.times, othertimes]) * self.times.units
        labels = np.hstack([self.labels, other.labels])
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge({}, {})".format(attr_self, attr_other)

        print('Event: merge annotations')
        merged_annotations = merge_annotations(self.annotations, other.annotations)

        kwargs.update(merged_annotations)

        kwargs['array_annotations'] = self._merge_array_annotations(other)

        evt = Event(times=times, labels=labels, **kwargs)

        return evt
Exemple #5
0
 def test_merge_annotations__dict(self):
     value1 = {'val1': 1, 'val2': 2.2, 'val3': 'test1'}
     value2 = {'val2': 2.2, 'val3': 'test2', 'val4': [4, 4.4], 'val5': True}
     targ = {'val1': 1, 'val2': 2.2, 'val3': 'test1;test2',
             'val4': [4, 4.4], 'val5': True}
     res = merge_annotations(value1, value2)
     self.assertEqual(targ, res)
Exemple #6
0
    def merge(self, other):
        '''
        Merge the another :class:`Epoch` into this one.

        The :class:`Epoch` objects are concatenated horizontally
        (column-wise), :func:`np.hstack`).

        If the attributes of the two :class:`Epoch` are not
        compatible, and Exception is raised.
        '''
        othertimes = other.times.rescale(self.times.units)
        times = np.hstack([self.times, othertimes]) * self.times.units
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)

        merged_annotations = merge_annotations(self.annotations, other.annotations)
        kwargs.update(merged_annotations)

        kwargs['array_annotations'] = self._merge_array_annotations(other)
        labels = kwargs['array_annotations']['labels']
        durations = kwargs['array_annotations']['durations']

        return Epoch(times=times, durations=durations, labels=labels, **kwargs)
    def merge(self, other):
        '''
        Merge the another :class:`AnalogSignal` into this one.

        The :class:`AnalogSignal` objects are concatenated horizontally
        (column-wise, :func:`np.hstack`).

        If the attributes of the two :class:`AnalogSignal` are not
        compatible, and Exception is raised.
        '''
        assert self.sampling_rate == other.sampling_rate
        assert self.t_start == other.t_start
        if other.units != self.units:
            other = other.rescale(self.units)
        stack = np.hstack(map(np.array, (self, other)))
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)
        return AnalogSignal(stack, units=self.units, dtype=self.dtype,
                                 copy=False, t_start=self.t_start,
                                 sampling_rate=self.sampling_rate,
                                 **kwargs)
Exemple #8
0
    def test_merge_annotations__func__dict(self):
        ann1 = {'val0': 'val0', 'val1': 1, 'val2': 2.2, 'val3': 'test1',
                'val4': [.4], 'val5': {0: 0, 1: {0: 0}},
                'val6': np.array([0, 1, 2])}
        ann2 = {'val2': 2.2, 'val3': 'test2',
                'val4': [4, 4.4], 'val5': {1: {1: 1}, 2: 2},
                'val6': np.array([4, 5, 6]), 'val7': True}

        ann1c = ann1.copy()
        ann2c = ann2.copy()

        targ = {'val0': 'val0', 'val1': 1, 'val2': 2.2, 'val3': 'test1;test2',
                'val4': [.4, 4, 4.4], 'val5': {0: 0, 1: {0: 0, 1: 1}, 2: 2},
                'val7': True}

        res = merge_annotations(ann1, ann2)

        val6t = np.array([0, 1, 2, 4, 5, 6])
        val6r = res.pop('val6')
        val61 = ann1.pop('val6')
        val61c = ann1c.pop('val6')
        val62 = ann2.pop('val6')
        val62c = ann2c.pop('val6')

        self.assertEqual(ann1, ann1c)
        self.assertEqual(ann2, ann2c)
        self.assertEqual(res, targ)

        assert_arrays_equal(val6r, val6t)
        self.assertRaises(AssertionError, assert_arrays_equal, val61, val6t)
        assert_arrays_equal(val61, val61c)
        assert_arrays_equal(val62, val62c)
    def merge(self, other):
        '''
        Merge another signal into this one.

        The signal objects are concatenated horizontally
        (column-wise, :func:`np.hstack`).

        If the attributes of the two signals are not
        compatible, an Exception is raised.

        Required attributes of the signal are used.
        '''

        if not np.array_equal(self.times, other.times):
            raise MergeError(
                "Cannot merge these two signals as the sample times differ.")

        if self.segment != other.segment:
            raise MergeError(
                "Cannot merge these two signals as they belong to different segments."
            )
        if hasattr(self, "lazy_shape"):
            if hasattr(other, "lazy_shape"):
                if self.lazy_shape[0] != other.lazy_shape[0]:
                    raise MergeError(
                        "Cannot merge signals of different length.")
                merged_lazy_shape = (self.lazy_shape[0],
                                     self.lazy_shape[1] + other.lazy_shape[1])
            else:
                raise MergeError(
                    "Cannot merge a lazy object with a real object.")
        if other.units != self.units:
            other = other.rescale(self.units)
        stack = np.hstack((self.magnitude, other.magnitude))
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge({}, {})".format(attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)

        signal = self.__class__(self.times,
                                stack,
                                units=self.units,
                                dtype=self.dtype,
                                copy=False,
                                **kwargs)
        signal.segment = self.segment
        signal.array_annotate(**self._merge_array_annotations(other))

        if hasattr(self, "lazy_shape"):
            signal.lazy_shape = merged_lazy_shape

        return signal
    def merge(self, other):
        '''
        Merge another :class:`AnalogSignal` into this one.

        The :class:`AnalogSignal` objects are concatenated horizontally
        (column-wise, :func:`np.hstack`).

        If the attributes of the two :class:`AnalogSignal` are not
        compatible, an Exception is raised.
        '''
        if self.sampling_rate != other.sampling_rate:
            raise MergeError("Cannot merge, different sampling rates")
        if self.t_start != other.t_start:
            raise MergeError("Cannot merge, different t_start")
        if self.segment != other.segment:
            raise MergeError("Cannot merge these two signals as they belong to different segments.")
        if hasattr(self, "lazy_shape"):
            if hasattr(other, "lazy_shape"):
                if self.lazy_shape[0] != other.lazy_shape[0]:
                    raise MergeError("Cannot merge signals of different length.")
                merged_lazy_shape = (self.lazy_shape[0], self.lazy_shape[1] + other.lazy_shape[1])
            else:
                raise MergeError("Cannot merge a lazy object with a real object.")
        if other.units != self.units:
            other = other.rescale(self.units)
        stack = np.hstack(map(np.array, (self, other)))
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)
        signal = AnalogSignal(stack, units=self.units, dtype=self.dtype,
                              copy=False, t_start=self.t_start,
                              sampling_rate=self.sampling_rate,
                              **kwargs)
        signal.segment = self.segment
        # merge channel_index (move to ChannelIndex.merge()?)
        if self.channel_index and other.channel_index:
            signal.channel_index = ChannelIndex(
                    index=np.arange(signal.shape[1]),
                    channel_ids=np.hstack([self.channel_index.channel_ids,
                                           other.channel_index.channel_ids]),
                    channel_names=np.hstack([self.channel_index.channel_names,
                                             other.channel_index.channel_names]))
        else:
            signal.channel_index = ChannelIndex(index=np.arange(signal.shape[1]))

        if hasattr(self, "lazy_shape"):
            signal.lazy_shape = merged_lazy_shape
        return signal
Exemple #11
0
    def merge(self, other):
        '''
        Merge another :class:`AnalogSignal` into this one.

        The :class:`AnalogSignal` objects are concatenated horizontally
        (column-wise, :func:`np.hstack`).

        If the attributes of the two :class:`AnalogSignal` are not
        compatible, an Exception is raised.
        '''
        if self.sampling_rate != other.sampling_rate:
            raise MergeError("Cannot merge, different sampling rates")
        if self.t_start != other.t_start:
            raise MergeError("Cannot merge, different t_start")
        if self.segment != other.segment:
            raise MergeError("Cannot merge these two signals as they belong to different segments.")
        if hasattr(self, "lazy_shape"):
            if hasattr(other, "lazy_shape"):
                if self.lazy_shape[0] != other.lazy_shape[0]:
                    raise MergeError("Cannot merge signals of different length.")
                merged_lazy_shape = (self.lazy_shape[0], self.lazy_shape[1] + other.lazy_shape[1])
            else:
                raise MergeError("Cannot merge a lazy object with a real object.")
        if other.units != self.units:
            other = other.rescale(self.units)
        stack = np.hstack(map(np.array, (self, other)))
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)
        signal = AnalogSignal(stack, units=self.units, dtype=self.dtype,
                              copy=False, t_start=self.t_start,
                              sampling_rate=self.sampling_rate,
                              **kwargs)
        signal.segment = self.segment
        # merge channel_index (move to ChannelIndex.merge()?)
        if self.channel_index and other.channel_index:
            signal.channel_index = ChannelIndex(
                    index=np.arange(signal.shape[1]),
                    channel_ids=np.hstack([self.channel_index.channel_ids,
                                           other.channel_index.channel_ids]),
                    channel_names=np.hstack([self.channel_index.channel_names,
                                             other.channel_index.channel_names]))
        else:
            signal.channel_index = ChannelIndex(index=np.arange(signal.shape[1]))

        if hasattr(self, "lazy_shape"):
            signal.lazy_shape = merged_lazy_shape
        return signal
Exemple #12
0
    def merge(self, other):
        '''
        Merge another :class:`IrregularlySampledSignal` with this one, and return the
        merged signal.

        The :class:`IrregularlySampledSignal` objects are concatenated horizontally
        (column-wise, :func:`np.hstack`).

        If the attributes of the two :class:`IrregularlySampledSignal` are not
        compatible, a :class:`MergeError` is raised.
        '''
        if not np.array_equal(self.times, other.times):
            raise MergeError(
                "Cannot merge these two signals as the sample times differ.")
        if self.segment != other.segment:
            raise MergeError(
                "Cannot merge these two signals as they belong to different segments."
            )
        if hasattr(self, "lazy_shape"):
            if hasattr(other, "lazy_shape"):
                if self.lazy_shape[0] != other.lazy_shape[0]:
                    raise MergeError(
                        "Cannot merge signals of different length.")
                merged_lazy_shape = (self.lazy_shape[0],
                                     self.lazy_shape[1] + other.lazy_shape[1])
            else:
                raise MergeError(
                    "Cannot merge a lazy object with a real object.")
        if other.units != self.units:
            other = other.rescale(self.units)
        stack = np.hstack(map(np.array, (self, other)))
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)
        signal = IrregularlySampledSignal(self.times,
                                          stack,
                                          units=self.units,
                                          dtype=self.dtype,
                                          copy=False,
                                          **kwargs)
        signal.segment = self.segment
        if hasattr(self, "lazy_shape"):
            signal.lazy_shape = merged_lazy_shape
        return signal
    def merge(self, other):
        '''
        Merge another :class:`IrregularlySampledSignal` with this one, and return the
        merged signal.

        The :class:`IrregularlySampledSignal` objects are concatenated horizontally
        (column-wise, :func:`np.hstack`).

        If the attributes of the two :class:`IrregularlySampledSignal` are not
        compatible, a :class:`MergeError` is raised.
        '''
        if not np.array_equal(self.times, other.times):
            raise MergeError("Cannot merge these two signals as the sample times differ.")
        if self.segment != other.segment:
            raise MergeError("Cannot merge these two signals as they belong to different segments.")
        if hasattr(self, "lazy_shape"):
            if hasattr(other, "lazy_shape"):
                if self.lazy_shape[0] != other.lazy_shape[0]:
                    raise MergeError("Cannot merge signals of different length.")
                merged_lazy_shape = (self.lazy_shape[0], self.lazy_shape[1] + other.lazy_shape[1])
            else:
                raise MergeError("Cannot merge a lazy object with a real object.")
        if other.units != self.units:
            other = other.rescale(self.units)
        stack = np.hstack(map(np.array, (self, other)))
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)
        signal = IrregularlySampledSignal(self.times, stack, units=self.units,
                                         dtype=self.dtype, copy=False,
                                         **kwargs)
        signal.segment = self.segment
        if hasattr(self, "lazy_shape"):
            signal.lazy_shape = merged_lazy_shape
        return signal
    def merge(self, other):
        '''
        Merge the another :class:`AnalogSignalArray` into this one.

        The :class:`AnalogSignalArray` objects are concatenated horizontally
        (column-wise, :func:`np.hstack`).

        If the attributes of the two :class:`AnalogSignalArray` are not
        compatible, and Exception is raised.
        '''
        assert self.sampling_rate == other.sampling_rate
        assert self.t_start == other.t_start
        other.units = self.units
        stack = np.hstack(map(np.array, (self, other)))
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)
        if self.channel_index is None:
            channel_index = other.channel_index
        elif other.channel_index is None:
            channel_index = self.channel_index
        else:
            channel_index = np.append(self.channel_index, other.channel_index)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)
        return AnalogSignalArray(stack,
                                 units=self.units,
                                 dtype=self.dtype,
                                 copy=False,
                                 t_start=self.t_start,
                                 sampling_rate=self.sampling_rate,
                                 channel_index=channel_index,
                                 **kwargs)
    def merge(self, other):
        '''
        Merge another :class:`SpikeTrain` into this one.

        The times of the :class:`SpikeTrain` objects combined in one array
        and sorted.

        If the attributes of the two :class:`SpikeTrain` are not
        compatible, an Exception is raised.
        '''
        if self.sampling_rate != other.sampling_rate:
            raise MergeError("Cannot merge, different sampling rates")
        if self.t_start != other.t_start:
            raise MergeError("Cannot merge, different t_start")
        if self.t_stop != other.t_stop:
            raise MemoryError("Cannot merge, different t_stop")
        if self.left_sweep != other.left_sweep:
            raise MemoryError("Cannot merge, different left_sweep")
        if self.segment != other.segment:
            raise MergeError("Cannot merge these two signals as they belong to"
                             " different segments.")
        if hasattr(self, "lazy_shape"):
            if hasattr(other, "lazy_shape"):
                merged_lazy_shape = (self.lazy_shape[0] + other.lazy_shape[0])
            else:
                raise MergeError("Cannot merge a lazy object with a real"
                                 " object.")
        if other.units != self.units:
            other = other.rescale(self.units)
        wfs = [self.waveforms is not None, other.waveforms is not None]
        if any(wfs) and not all(wfs):
            raise MergeError("Cannot merge signal with waveform and signal "
                             "without waveform.")
        stack = np.concatenate((np.asarray(self), np.asarray(other)))
        sorting = np.argsort(stack)
        stack = stack[sorting]
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)
        train = SpikeTrain(stack, units=self.units, dtype=self.dtype,
                           copy=False, t_start=self.t_start,
                           t_stop=self.t_stop,
                           sampling_rate=self.sampling_rate,
                           left_sweep=self.left_sweep, **kwargs)
        if all(wfs):
            wfs_stack = np.vstack((self.waveforms, other.waveforms))
            wfs_stack = wfs_stack[sorting]
            train.waveforms = wfs_stack
        train.segment = self.segment
        if train.segment is not None:
            self.segment.spiketrains.append(train)

        if hasattr(self, "lazy_shape"):
            train.lazy_shape = merged_lazy_shape
        return train
Exemple #16
0
    def merge(self, other):
        '''
        Merge another signal into this one.

        The signal objects are concatenated horizontally
        (column-wise, :func:`np.hstack`).

        If the attributes of the two signal are not
        compatible, an Exception is raised.

        Required attributes of the signal are used.
        '''

        for attr in self._necessary_attrs:
            if 'signal' != attr[0]:
                if getattr(self, attr[0], None) != getattr(other, attr[0], None):
                    raise MergeError("Cannot merge these two signals as the %s differ." % attr[0])

        if self.segment != other.segment:
            raise MergeError(
                "Cannot merge these two signals as they belong to different segments.")
        if hasattr(self, "lazy_shape"):
            if hasattr(other, "lazy_shape"):
                if self.lazy_shape[0] != other.lazy_shape[0]:
                    raise MergeError("Cannot merge signals of different length.")
                merged_lazy_shape = (self.lazy_shape[0], self.lazy_shape[1] + other.lazy_shape[1])
            else:
                raise MergeError("Cannot merge a lazy object with a real object.")
        if other.units != self.units:
            other = other.rescale(self.units)
        stack = np.hstack((self.magnitude, other.magnitude))
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations, other.annotations)
        kwargs.update(merged_annotations)

        kwargs['array_annotations'] = self._merge_array_annotations(other)

        signal = self.__class__(stack, units=self.units, dtype=self.dtype, copy=False,
                                t_start=self.t_start, sampling_rate=self.sampling_rate, **kwargs)
        signal.segment = self.segment

        if hasattr(self, "lazy_shape"):
            signal.lazy_shape = merged_lazy_shape

        # merge channel_index (move to ChannelIndex.merge()?)
        if self.channel_index and other.channel_index:
            signal.channel_index = ChannelIndex(index=np.arange(signal.shape[1]),
                channel_ids=np.hstack(
                    [self.channel_index.channel_ids, other.channel_index.channel_ids]),
                channel_names=np.hstack(
                    [self.channel_index.channel_names, other.channel_index.channel_names]))
        else:
            signal.channel_index = ChannelIndex(index=np.arange(signal.shape[1]))

        return signal
Exemple #17
0
    def merge(self, other):
        '''
        Merge another :class:`SpikeTrain` into this one.

        The times of the :class:`SpikeTrain` objects combined in one array
        and sorted.

        If the attributes of the two :class:`SpikeTrain` are not
        compatible, an Exception is raised.
        '''
        if self.sampling_rate != other.sampling_rate:
            raise MergeError("Cannot merge, different sampling rates")
        if self.t_start != other.t_start:
            raise MergeError("Cannot merge, different t_start")
        if self.t_stop != other.t_stop:
            raise MemoryError("Cannot merge, different t_stop")
        if self.left_sweep != other.left_sweep:
            raise MemoryError("Cannot merge, different left_sweep")
        if self.segment != other.segment:
            raise MergeError("Cannot merge these two signals as they belong to"
                             " different segments.")
        if hasattr(self, "lazy_shape"):
            if hasattr(other, "lazy_shape"):
                merged_lazy_shape = (self.lazy_shape[0] + other.lazy_shape[0])
            else:
                raise MergeError("Cannot merge a lazy object with a real"
                                 " object.")
        if other.units != self.units:
            other = other.rescale(self.units)
        wfs = [self.waveforms is not None, other.waveforms is not None]
        if any(wfs) and not all(wfs):
            raise MergeError("Cannot merge signal with waveform and signal "
                             "without waveform.")
        stack = np.concatenate((np.asarray(self), np.asarray(other)))
        sorting = np.argsort(stack)
        stack = stack[sorting]
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge(%s, %s)" % (attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)
        train = SpikeTrain(stack,
                           units=self.units,
                           dtype=self.dtype,
                           copy=False,
                           t_start=self.t_start,
                           t_stop=self.t_stop,
                           sampling_rate=self.sampling_rate,
                           left_sweep=self.left_sweep,
                           **kwargs)
        if all(wfs):
            wfs_stack = np.vstack((self.waveforms, other.waveforms))
            wfs_stack = wfs_stack[sorting]
            train.waveforms = wfs_stack
        train.segment = self.segment
        if train.segment is not None:
            self.segment.spiketrains.append(train)

        if hasattr(self, "lazy_shape"):
            train.lazy_shape = merged_lazy_shape
        return train
Exemple #18
0
    def merge(self, other):
        '''
        Merge another signal into this one.

        The signal objects are concatenated horizontally
        (column-wise, :func:`np.hstack`).

        If the attributes of the two signal are not
        compatible, an Exception is raised.

        Required attributes of the signal are used.
        '''

        for attr in self._necessary_attrs:
            if 'signal' != attr[0]:
                if getattr(self, attr[0], None) != getattr(
                        other, attr[0], None):
                    raise MergeError(
                        "Cannot merge these two signals as the %s differ." %
                        attr[0])

        if self.segment != other.segment:
            raise MergeError(
                "Cannot merge these two signals as they belong to different segments."
            )
        if hasattr(self, "lazy_shape"):
            if hasattr(other, "lazy_shape"):
                if self.lazy_shape[0] != other.lazy_shape[0]:
                    raise MergeError(
                        "Cannot merge signals of different length.")
                merged_lazy_shape = (self.lazy_shape[0],
                                     self.lazy_shape[1] + other.lazy_shape[1])
            else:
                raise MergeError(
                    "Cannot merge a lazy object with a real object.")
        if other.units != self.units:
            other = other.rescale(self.units)
        stack = np.hstack((self.magnitude, other.magnitude))
        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge({}, {})".format(attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)

        kwargs['array_annotations'] = self._merge_array_annotations(other)

        signal = self.__class__(stack,
                                units=self.units,
                                dtype=self.dtype,
                                copy=False,
                                t_start=self.t_start,
                                sampling_rate=self.sampling_rate,
                                **kwargs)
        signal.segment = self.segment

        if hasattr(self, "lazy_shape"):
            signal.lazy_shape = merged_lazy_shape

        # merge channel_index (move to ChannelIndex.merge()?)
        if self.channel_index and other.channel_index:
            signal.channel_index = ChannelIndex(
                index=np.arange(signal.shape[1]),
                channel_ids=np.hstack([
                    self.channel_index.channel_ids,
                    other.channel_index.channel_ids
                ]),
                channel_names=np.hstack([
                    self.channel_index.channel_names,
                    other.channel_index.channel_names
                ]))
        else:
            signal.channel_index = ChannelIndex(
                index=np.arange(signal.shape[1]))

        return signal
Exemple #19
0
    def concatenate(self, other, allow_overlap=False):
        '''
        Combine this and another signal along the time axis.

        The signal objects are concatenated vertically
        (row-wise, :func:`np.vstack`). Patching can be
        used to combine signals across segments.
        Note: Only array annotations common to
        both signals are attached to the concatenated signal.

        If the attributes of the two signal are not
        compatible, an Exception is raised.

        Required attributes of the signal are used.

        Parameters
        ----------
        other : neo.BaseSignal
            The object that is merged into this one.
        allow_overlap : bool
            If false, overlapping samples between the two
            signals are not permitted and an ValueError is raised.
            If true, no check for overlapping samples is
            performed and all samples are combined.

        Returns
        -------
        signal : neo.IrregularlySampledSignal
            Signal containing all non-overlapping samples of
            both source signals.

        Raises
        ------
        MergeError
            If `other` object has incompatible attributes.
        '''

        for attr in self._necessary_attrs:
            if not (attr[0]
                    in ['signal', 'times', 't_start', 't_stop', 'times']):
                if getattr(self, attr[0], None) != getattr(
                        other, attr[0], None):
                    raise MergeError(
                        "Cannot concatenate these two signals as the %s differ."
                        % attr[0])

        if hasattr(self, "lazy_shape"):
            if hasattr(other, "lazy_shape"):
                if self.lazy_shape[-1] != other.lazy_shape[-1]:
                    raise MergeError(
                        "Cannot concatenate signals as they contain"
                        " different numbers of traces.")
                merged_lazy_shape = (self.lazy_shape[0] + other.lazy_shape[0],
                                     self.lazy_shape[-1])
            else:
                raise MergeError(
                    "Cannot concatenate a lazy object with a real object.")
        if other.units != self.units:
            other = other.rescale(self.units)

        new_times = np.hstack((self.times, other.times))
        sorting = np.argsort(new_times)
        new_samples = np.vstack((self.magnitude, other.magnitude))

        kwargs = {}
        for name in ("name", "description", "file_origin"):
            attr_self = getattr(self, name)
            attr_other = getattr(other, name)
            if attr_self == attr_other:
                kwargs[name] = attr_self
            else:
                kwargs[name] = "merge({}, {})".format(attr_self, attr_other)
        merged_annotations = merge_annotations(self.annotations,
                                               other.annotations)
        kwargs.update(merged_annotations)

        kwargs['array_annotations'] = intersect_annotations(
            self.array_annotations, other.array_annotations)

        if not allow_overlap:
            if max(self.t_start, other.t_start) <= min(self.t_stop,
                                                       other.t_stop):
                raise ValueError(
                    'Can not combine signals that overlap in time. Allow for '
                    'overlapping samples using the "no_overlap" parameter.')

        t_start = min(self.t_start, other.t_start)
        t_stop = max(self.t_start, other.t_start)

        signal = IrregularlySampledSignal(signal=new_samples[sorting],
                                          times=new_times[sorting],
                                          units=self.units,
                                          dtype=self.dtype,
                                          copy=False,
                                          t_start=t_start,
                                          t_stop=t_stop,
                                          **kwargs)
        signal.segment = None
        signal.channel_index = None

        if hasattr(self, "lazy_shape"):
            signal.lazy_shape = merged_lazy_shape

        return signal
    def merge(self, *others):
        '''
        Merge other :class:`SpikeTrain` objects into this one.

        The times of the :class:`SpikeTrain` objects combined in one array
        and sorted.

        If the attributes of the :class:`SpikeTrain` objects are not
        compatible, an Exception is raised.
        '''
        for other in others:
            if isinstance(other, neo.io.proxyobjects.SpikeTrainProxy):
                raise MergeError("Cannot merge, SpikeTrainProxy objects cannot be merged"
                                 "into regular SpikeTrain objects, please load them first.")
            elif not isinstance(other, SpikeTrain):
                raise MergeError("Cannot merge, only SpikeTrain"
                                 "can be merged into a SpikeTrain.")
            if self.sampling_rate != other.sampling_rate:
                raise MergeError("Cannot merge, different sampling rates")
            if self.t_start != other.t_start:
                raise MergeError("Cannot merge, different t_start")
            if self.t_stop != other.t_stop:
                raise MergeError("Cannot merge, different t_stop")
            if self.left_sweep != other.left_sweep:
                raise MergeError("Cannot merge, different left_sweep")
            if self.segment != other.segment:
                raise MergeError("Cannot merge these signals as they belong to"
                                 " different segments.")

        all_spiketrains = [self]
        all_spiketrains.extend([st.rescale(self.units) for st in others])

        wfs = [st.waveforms is not None for st in all_spiketrains]
        if any(wfs) and not all(wfs):
            raise MergeError("Cannot merge signal with waveform and signal "
                             "without waveform.")
        stack = np.concatenate([np.asarray(st) for st in all_spiketrains])
        sorting = np.argsort(stack)
        stack = stack[sorting]

        kwargs = {}

        kwargs['array_annotations'] = self._merge_array_annotations(others, sorting=sorting)

        for name in ("name", "description", "file_origin"):
            attr = getattr(self, name)

            # check if self is already a merged spiketrain
            # if it is, get rid of the bracket at the end to append more attributes
            if attr is not None:
                if attr.startswith('merge(') and attr.endswith(')'):
                    attr = attr[:-1]

            for other in others:
                attr_other = getattr(other, name)

                # both attributes are None --> nothing to do
                if attr is None and attr_other is None:
                    continue

                # one of the attributes is None --> convert to string in order to merge them
                elif attr is None or attr_other is None:
                    attr = str(attr)
                    attr_other = str(attr_other)

                # check if the other spiketrain is already a merged spiketrain
                # if it is, append all of its merged attributes that aren't already in attr
                if attr_other.startswith('merge(') and attr_other.endswith(')'):
                    for subattr in attr_other[6:-1].split('; '):
                        if subattr not in attr:
                            attr += '; ' + subattr
                            if not attr.startswith('merge('):
                                attr = 'merge(' + attr

                # if the other attribute is not in the list --> append
                # if attr doesn't already start with merge add merge( in the beginning
                elif attr_other not in attr:
                    attr += '; ' + attr_other
                    if not attr.startswith('merge('):
                        attr = 'merge(' + attr

            # close the bracket of merge(...) if necessary
            if attr is not None:
                if attr.startswith('merge('):
                    attr += ')'

            # write attr into kwargs dict
            kwargs[name] = attr

        merged_annotations = merge_annotations(*(st.annotations for st in
                                                 all_spiketrains))
        kwargs.update(merged_annotations)

        train = SpikeTrain(stack, units=self.units, dtype=self.dtype, copy=False,
                           t_start=self.t_start, t_stop=self.t_stop,
                           sampling_rate=self.sampling_rate, left_sweep=self.left_sweep, **kwargs)
        if all(wfs):
            wfs_stack = np.vstack([st.waveforms.rescale(self.waveforms.units)
                                   for st in all_spiketrains])
            wfs_stack = wfs_stack[sorting] * self.waveforms.units
            train.waveforms = wfs_stack
        train.segment = self.segment
        if train.segment is not None:
            self.segment.spiketrains.append(train)

        return train