diff --git a/doc/source/authors.rst b/doc/source/authors.rst index 035fdfbe7..81fb794ab 100644 --- a/doc/source/authors.rst +++ b/doc/source/authors.rst @@ -106,6 +106,7 @@ and may not be the current affiliation of a contributor. * Aditya Singh (github) * Stanley C. * Axel Coiffard-Donaty +* Anton Soloviev 1. Centre de Recherche en Neuroscience de Lyon, CNRS UMR5292 - INSERM U1028 - Université Claude Bernard Lyon 1 2. Unité de Neuroscience, Information et Complexité, CNRS UPR 3293, Gif-sur-Yvette, France diff --git a/neo/core/analogsignal.py b/neo/core/analogsignal.py index 252224f16..aaaf32146 100644 --- a/neo/core/analogsignal.py +++ b/neo/core/analogsignal.py @@ -311,10 +311,9 @@ def __getitem__(self, i): obj = pq.Quantity(obj.magnitude, units=obj.units) else: if isinstance(j, slice): - if j.start: - obj.t_start = self.t_start + j.start * self.sampling_period - if j.step: - obj.sampling_period *= j.step + start, _, step = j.indices(len(self)) + obj.t_start = self.t_start + start * self.sampling_period + obj.sampling_period = self.sampling_period * step elif isinstance(j, np.ndarray): raise NotImplementedError("Arrays not yet supported") # in the general case, would need to return # IrregularlySampledSignal(Array) @@ -329,8 +328,9 @@ def __getitem__(self, i): obj.array_annotate(**deepcopy(self.array_annotations_at_index(k))) elif isinstance(i, slice): obj = super().__getitem__(i) - if i.start: - obj.t_start = self.t_start + i.start * self.sampling_period + start, _, step = i.indices(len(self)) + obj.t_start = self.t_start + start * self.sampling_period + obj.sampling_period = self.sampling_period * step obj.array_annotations = deepcopy(self.array_annotations) elif isinstance(i, np.ndarray): # Indexing of an AnalogSignal is only consistent if the resulting number of diff --git a/neo/test/coretest/test_analogsignal.py b/neo/test/coretest/test_analogsignal.py index b79c17f32..f0ece3ced 100644 --- a/neo/test/coretest/test_analogsignal.py +++ b/neo/test/coretest/test_analogsignal.py @@ -600,6 +600,41 @@ def test__slice_should_change_sampling_period(self): assert_array_equal(result2.magnitude, self.data1[::2, :1]) assert_array_equal(result3.magnitude, self.data1[1:7:2, :1]) + def test__slice_timestamps_match_selected_samples(self): + signal = AnalogSignal(np.arange(40).reshape(20, 2), units="uV", sampling_rate=4 * pq.Hz, t_start=2 * pq.s) + original_times = signal.times.copy() + original_period = signal.sampling_period.copy() + slices = ( + slice(None, None, 2), + slice(3, 17, 3), + slice(-5, None), + slice(-12, -2, 2), + slice(-100, None, 3), + slice(None, None, -1), + slice(17, 2, -3), + slice(100, None, -2), + ) + for time_slice in slices: + for channel_slice in (None, slice(None), 1): + with self.subTest(time_slice=time_slice, channel_slice=channel_slice): + if channel_slice is None: + result = signal[time_slice] + expected_data = signal.magnitude[time_slice] + else: + result = signal[time_slice, channel_slice] + expected_data = signal.magnitude[time_slice, channel_slice].reshape(result.shape) + assert_array_equal(result.magnitude, expected_data) + assert_array_equal(result.times, original_times[time_slice]) + self.assertEqual(result.sampling_period, original_period * (time_slice.step or 1)) + assert_array_equal(signal.times, original_times) + self.assertEqual(signal.sampling_period, original_period) + + def test__nested_slices_preserve_sample_times(self): + signal = AnalogSignal(np.arange(20), units="mV", sampling_rate=4 * pq.Hz, t_start=2 * pq.s) + result = signal[1::2][-3:] + assert_array_equal(result.magnitude, signal.magnitude[1::2][-3:]) + assert_array_equal(result.times, signal.times[1::2][-3:]) + def test__index_dim1_and_slice_dim0_should_return_single_channel_analogsignal(self): result = self.signal1[2:7, 0] self.assertIsInstance(result, AnalogSignal)