class TestAnalogSignalArrayMethods(unittest.TestCase): def setUp(self): self.data1 = np.arange(10.0) self.data1quant = self.data1 * pq.nA self.signal1 = AnalogSignal(self.data1quant, sampling_rate=1 * pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') self.signal1.segment = 1 self.signal1.channel_index = ChannelIndex(index=[0]) def test__compliant(self): assert_neo_object_is_compliant(self.signal1) def test__slice_should_return_AnalogSignalArray(self): # slice result = self.signal1[3:8, 0] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual( result.name, 'spam') # should slicing really preserve name and description? self.assertEqual( result.description, 'eggs') # perhaps these should be modified to indicate the slice? self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.size, 5) self.assertEqual(result.sampling_period, self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) self.assertEqual(result.t_start, self.signal1.t_start + 3 * result.sampling_period) self.assertEqual(result.t_stop, result.t_start + 5 * result.sampling_period) assert_array_equal(result.magnitude, self.data1[3:8].reshape(-1, 1)) # Test other attributes were copied over (in this case, defaults) self.assertEqual(result.file_origin, self.signal1.file_origin) self.assertEqual(result.name, self.signal1.name) self.assertEqual(result.description, self.signal1.description) self.assertEqual(result.annotations, self.signal1.annotations) def test__slice_should_let_access_to_parents_objects(self): result = self.signal1.time_slice(1 * pq.ms, 3 * pq.ms) self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) def test__slice_should_change_sampling_period(self): result1 = self.signal1[:2, 0] result2 = self.signal1[::2, 0] result3 = self.signal1[1:7:2, 0] self.assertIsInstance(result1, AnalogSignal) assert_neo_object_is_compliant(result1) self.assertEqual(result1.name, 'spam') self.assertEqual(result1.description, 'eggs') self.assertEqual(result1.file_origin, 'testfile.txt') self.assertEqual(result1.annotations, {'arg1': 'test'}) self.assertIsInstance(result2, AnalogSignal) assert_neo_object_is_compliant(result2) self.assertEqual(result2.name, 'spam') self.assertEqual(result2.description, 'eggs') self.assertEqual(result2.file_origin, 'testfile.txt') self.assertEqual(result2.annotations, {'arg1': 'test'}) self.assertIsInstance(result3, AnalogSignal) assert_neo_object_is_compliant(result3) self.assertEqual(result3.name, 'spam') self.assertEqual(result3.description, 'eggs') self.assertEqual(result3.file_origin, 'testfile.txt') self.assertEqual(result3.annotations, {'arg1': 'test'}) self.assertEqual(result1.sampling_period, self.signal1.sampling_period) self.assertEqual(result2.sampling_period, self.signal1.sampling_period * 2) self.assertEqual(result3.sampling_period, self.signal1.sampling_period * 2) assert_array_equal(result1.magnitude, self.data1[:2].reshape(-1, 1)) assert_array_equal(result2.magnitude, self.data1[::2].reshape(-1, 1)) assert_array_equal(result3.magnitude, self.data1[1:7:2].reshape(-1, 1)) def test__slice_should_modify_linked_channelindex(self): n = 8 # number of channels signal = AnalogSignal(np.arange(n * 100.0).reshape(100, n), sampling_rate=1 * pq.kHz, units="mV") self.assertEqual(signal.shape, (100, n)) signal.channel_index = ChannelIndex( index=np.arange(n, dtype=int), channel_names=["channel{0}".format(i) for i in range(n)]) odd_channels = signal[:, 1::2] self.assertEqual(odd_channels.shape, (100, n // 2)) assert_array_equal(odd_channels.channel_index.index, np.arange(n // 2, dtype=int)) assert_array_equal(odd_channels.channel_index.channel_names, ["channel{0}".format(i) for i in range(1, n, 2)]) assert_array_equal(signal.channel_index.channel_names, ["channel{0}".format(i) for i in range(n)]) def test__copy_should_let_access_to_parents_objects(self): ##copy result = self.signal1.copy() self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) ## deep copy (not fixed yet) #result = copy.deepcopy(self.signal1) #self.assertEqual(result.segment, self.signal1.segment) #self.assertEqual(result.channel_index, self.signal1.channel_index) def test__getitem_should_return_single_quantity(self): result1 = self.signal1[0, 0] result2 = self.signal1[9, 0] self.assertIsInstance(result1, pq.Quantity) self.assertFalse(hasattr(result1, 'name')) self.assertFalse(hasattr(result1, 'description')) self.assertFalse(hasattr(result1, 'file_origin')) self.assertFalse(hasattr(result1, 'annotations')) self.assertIsInstance(result2, pq.Quantity) self.assertFalse(hasattr(result2, 'name')) self.assertFalse(hasattr(result2, 'description')) self.assertFalse(hasattr(result2, 'file_origin')) self.assertFalse(hasattr(result2, 'annotations')) self.assertEqual(result1, 0 * pq.nA) self.assertEqual(result2, 9 * pq.nA) def test__getitem_out_of_bounds_IndexError(self): self.assertRaises(IndexError, self.signal1.__getitem__, (10, 0)) def test_comparison_operators(self): assert_array_equal( self.signal1 >= 5 * pq.nA, np.array([ False, False, False, False, False, True, True, True, True, True ]).reshape(-1, 1)) assert_array_equal( self.signal1 >= 5 * pq.pA, np.array( [False, True, True, True, True, True, True, True, True, True]).reshape(-1, 1)) def test__comparison_with_inconsistent_units_should_raise_Exception(self): self.assertRaises(ValueError, self.signal1.__gt__, 5 * pq.mV) def test__simple_statistics(self): self.assertEqual(self.signal1.max(), 9 * pq.nA) self.assertEqual(self.signal1.min(), 0 * pq.nA) self.assertEqual(self.signal1.mean(), 4.5 * pq.nA) def test__rescale_same(self): result = self.signal1.copy() result = result.rescale(pq.nA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1 * pq.nA) assert_array_equal(result.magnitude, self.data1.reshape(-1, 1)) assert_same_sub_schema(result, self.signal1) def test__rescale_new(self): result = self.signal1.copy() result = result.rescale(pq.pA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1 * pq.pA) assert_arrays_almost_equal(np.array(result), self.data1.reshape(-1, 1) * 1000., 1e-10) def test__rescale_new_incompatible_ValueError(self): self.assertRaises(ValueError, self.signal1.rescale, pq.mV) def test_as_array(self): sig_as_arr = self.signal1.as_array() self.assertIsInstance(sig_as_arr, np.ndarray) assert_array_equal(self.data1, sig_as_arr.flat) def test_as_quantity(self): sig_as_q = self.signal1.as_quantity() self.assertIsInstance(sig_as_q, pq.Quantity) assert_array_equal(self.data1, sig_as_q.magnitude.flat)
class TestAnalogSignalArrayMethods(unittest.TestCase): def setUp(self): self.data1 = np.arange(10.0) self.data1quant = self.data1 * pq.nA self.signal1 = AnalogSignal(self.data1quant, sampling_rate=1 * pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') def test__compliant(self): assert_neo_object_is_compliant(self.signal1) def test__slice_should_return_AnalogSignal(self): # slice result = self.signal1[3:8] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.size, 5) self.assertEqual(result.sampling_period, self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) self.assertEqual(result.t_start, self.signal1.t_start + 3 * result.sampling_period) self.assertEqual(result.t_stop, result.t_start + 5 * result.sampling_period) assert_arrays_equal(result, self.data1[3:8]) # Test other attributes were copied over (in this case, defaults) self.assertEqual(result.file_origin, self.signal1.file_origin) self.assertEqual(result.name, self.signal1.name) self.assertEqual(result.description, self.signal1.description) self.assertEqual(result.annotations, self.signal1.annotations) def test__slice_should_change_sampling_period(self): result1 = self.signal1[:2] result2 = self.signal1[::2] result3 = self.signal1[1:7:2] self.assertIsInstance(result1, AnalogSignal) assert_neo_object_is_compliant(result1) self.assertEqual(result1.name, 'spam') self.assertEqual(result1.description, 'eggs') self.assertEqual(result1.file_origin, 'testfile.txt') self.assertEqual(result1.annotations, {'arg1': 'test'}) self.assertIsInstance(result2, AnalogSignal) assert_neo_object_is_compliant(result2) self.assertEqual(result2.name, 'spam') self.assertEqual(result2.description, 'eggs') self.assertEqual(result2.file_origin, 'testfile.txt') self.assertEqual(result2.annotations, {'arg1': 'test'}) self.assertIsInstance(result3, AnalogSignal) assert_neo_object_is_compliant(result3) self.assertEqual(result3.name, 'spam') self.assertEqual(result3.description, 'eggs') self.assertEqual(result3.file_origin, 'testfile.txt') self.assertEqual(result3.annotations, {'arg1': 'test'}) self.assertEqual(result1.sampling_period, self.signal1.sampling_period) self.assertEqual(result2.sampling_period, self.signal1.sampling_period * 2) self.assertEqual(result3.sampling_period, self.signal1.sampling_period * 2) assert_arrays_equal(result1, self.data1[:2]) assert_arrays_equal(result2, self.data1[::2]) assert_arrays_equal(result3, self.data1[1:7:2]) def test__getitem_should_return_single_quantity(self): result1 = self.signal1[0] result2 = self.signal1[9] self.assertIsInstance(result1, pq.Quantity) self.assertFalse(hasattr(result1, 'name')) self.assertFalse(hasattr(result1, 'description')) self.assertFalse(hasattr(result1, 'file_origin')) self.assertFalse(hasattr(result1, 'annotations')) self.assertIsInstance(result2, pq.Quantity) self.assertFalse(hasattr(result2, 'name')) self.assertFalse(hasattr(result2, 'description')) self.assertFalse(hasattr(result2, 'file_origin')) self.assertFalse(hasattr(result2, 'annotations')) self.assertEqual(result1, 0 * pq.nA) self.assertEqual(result2, 9 * pq.nA) def test__getitem_out_of_bounds_IndexError(self): self.assertRaises(IndexError, self.signal1.__getitem__, 10) def test_comparison_operators(self): assert_arrays_equal( self.signal1 >= 5 * pq.nA, np.array([ False, False, False, False, False, True, True, True, True, True ])) assert_arrays_equal( self.signal1 >= 5 * pq.pA, np.array( [False, True, True, True, True, True, True, True, True, True])) def test__comparison_with_inconsistent_units_should_raise_Exception(self): self.assertRaises(ValueError, self.signal1.__gt__, 5 * pq.mV) def test__simple_statistics(self): self.assertEqual(self.signal1.max(), 9 * pq.nA) self.assertEqual(self.signal1.min(), 0 * pq.nA) self.assertEqual(self.signal1.mean(), 4.5 * pq.nA) def test__rescale_same(self): result = self.signal1.copy() result = result.rescale(pq.nA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1 * pq.nA) assert_arrays_equal(result, self.data1) assert_same_sub_schema(result, self.signal1) def test__rescale_new(self): result = self.signal1.copy() result = result.rescale(pq.pA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1 * pq.pA) assert_arrays_almost_equal(np.array(result), self.data1 * 1000., 1e-10) def test__rescale_new_incompatible_ValueError(self): self.assertRaises(ValueError, self.signal1.rescale, pq.mV)
class TestAnalogSignalArrayMethods(unittest.TestCase): def setUp(self): self.data1 = np.arange(10.0) self.data1quant = self.data1 * pq.nA self.signal1 = AnalogSignal(self.data1quant, sampling_rate=1*pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') self.signal1.segment = Segment() self.signal1.channel_index = ChannelIndex(index=[0]) def test__compliant(self): assert_neo_object_is_compliant(self.signal1) def test__slice_should_return_AnalogSignalArray(self): # slice for index in (0, np.int64(0)): result = self.signal1[3:8, index] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') # should slicing really preserve name and description? self.assertEqual(result.description, 'eggs') # perhaps these should be modified to indicate the slice? self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.size, 5) self.assertEqual(result.sampling_period, self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) self.assertEqual(result.t_start, self.signal1.t_start+3*result.sampling_period) self.assertEqual(result.t_stop, result.t_start + 5*result.sampling_period) assert_array_equal(result.magnitude, self.data1[3:8].reshape(-1, 1)) # Test other attributes were copied over (in this case, defaults) self.assertEqual(result.file_origin, self.signal1.file_origin) self.assertEqual(result.name, self.signal1.name) self.assertEqual(result.description, self.signal1.description) self.assertEqual(result.annotations, self.signal1.annotations) def test__slice_should_let_access_to_parents_objects(self): result = self.signal1.time_slice(1*pq.ms,3*pq.ms) self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) def test__slice_should_change_sampling_period(self): result1 = self.signal1[:2, 0] result2 = self.signal1[::2, 0] result3 = self.signal1[1:7:2, 0] self.assertIsInstance(result1, AnalogSignal) assert_neo_object_is_compliant(result1) self.assertEqual(result1.name, 'spam') self.assertEqual(result1.description, 'eggs') self.assertEqual(result1.file_origin, 'testfile.txt') self.assertEqual(result1.annotations, {'arg1': 'test'}) self.assertIsInstance(result2, AnalogSignal) assert_neo_object_is_compliant(result2) self.assertEqual(result2.name, 'spam') self.assertEqual(result2.description, 'eggs') self.assertEqual(result2.file_origin, 'testfile.txt') self.assertEqual(result2.annotations, {'arg1': 'test'}) self.assertIsInstance(result3, AnalogSignal) assert_neo_object_is_compliant(result3) self.assertEqual(result3.name, 'spam') self.assertEqual(result3.description, 'eggs') self.assertEqual(result3.file_origin, 'testfile.txt') self.assertEqual(result3.annotations, {'arg1': 'test'}) self.assertEqual(result1.sampling_period, self.signal1.sampling_period) self.assertEqual(result2.sampling_period, self.signal1.sampling_period * 2) self.assertEqual(result3.sampling_period, self.signal1.sampling_period * 2) assert_array_equal(result1.magnitude, self.data1[:2].reshape(-1, 1)) assert_array_equal(result2.magnitude, self.data1[::2].reshape(-1, 1)) assert_array_equal(result3.magnitude, self.data1[1:7:2].reshape(-1, 1)) def test__slice_should_modify_linked_channelindex(self): n = 8 # number of channels signal = AnalogSignal(np.arange(n * 100.0).reshape(100, n), sampling_rate=1*pq.kHz, units="mV", name="test") self.assertEqual(signal.shape, (100, n)) signal.channel_index = ChannelIndex(index=np.arange(n, dtype=int), channel_names=["channel{0}".format(i) for i in range(n)]) signal.channel_index.analogsignals.append(signal) odd_channels = signal[:, 1::2] self.assertEqual(odd_channels.shape, (100, n//2)) assert_array_equal(odd_channels.channel_index.index, np.arange(n//2, dtype=int)) assert_array_equal(odd_channels.channel_index.channel_names, ["channel{0}".format(i) for i in range(1, n, 2)]) assert_array_equal(signal.channel_index.channel_names, ["channel{0}".format(i) for i in range(n)]) self.assertEqual(odd_channels.channel_index.analogsignals[0].name, signal.name) def test__copy_should_let_access_to_parents_objects(self): result = self.signal1.copy() self.assertIs(result.segment, self.signal1.segment) self.assertIs(result.channel_index, self.signal1.channel_index) def test__deepcopy_should_let_access_to_parents_objects(self): result = copy.deepcopy(self.signal1) self.assertIsInstance(result.segment, Segment) self.assertIsInstance(result.channel_index, ChannelIndex) assert_same_sub_schema(result.segment, self.signal1.segment) assert_same_sub_schema(result.channel_index, self.signal1.channel_index) def test__getitem_should_return_single_quantity(self): result1 = self.signal1[0, 0] result2 = self.signal1[9, 0] self.assertIsInstance(result1, pq.Quantity) self.assertFalse(hasattr(result1, 'name')) self.assertFalse(hasattr(result1, 'description')) self.assertFalse(hasattr(result1, 'file_origin')) self.assertFalse(hasattr(result1, 'annotations')) self.assertIsInstance(result2, pq.Quantity) self.assertFalse(hasattr(result2, 'name')) self.assertFalse(hasattr(result2, 'description')) self.assertFalse(hasattr(result2, 'file_origin')) self.assertFalse(hasattr(result2, 'annotations')) self.assertEqual(result1, 0*pq.nA) self.assertEqual(result2, 9*pq.nA) def test__getitem_out_of_bounds_IndexError(self): self.assertRaises(IndexError, self.signal1.__getitem__, (10, 0)) def test_comparison_operators(self): assert_array_equal(self.signal1 >= 5*pq.nA, np.array([False, False, False, False, False, True, True, True, True, True]).reshape(-1, 1)) assert_array_equal(self.signal1 >= 5*pq.pA, np.array([False, True, True, True, True, True, True, True, True, True]).reshape(-1, 1)) def test__comparison_with_inconsistent_units_should_raise_Exception(self): self.assertRaises(ValueError, self.signal1.__gt__, 5*pq.mV) def test__simple_statistics(self): self.assertEqual(self.signal1.max(), 9*pq.nA) self.assertEqual(self.signal1.min(), 0*pq.nA) self.assertEqual(self.signal1.mean(), 4.5*pq.nA) def test__rescale_same(self): result = self.signal1.copy() result = result.rescale(pq.nA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1*pq.nA) assert_array_equal(result.magnitude, self.data1.reshape(-1, 1)) assert_same_sub_schema(result, self.signal1) self.assertIsInstance(result.channel_index, ChannelIndex) self.assertIsInstance(result.segment, Segment) self.assertIs(result.channel_index, self.signal1.channel_index) self.assertIs(result.segment, self.signal1.segment) def test__rescale_new(self): result = self.signal1.copy() result = result.rescale(pq.pA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1*pq.pA) assert_arrays_almost_equal(np.array(result), self.data1.reshape(-1, 1)*1000., 1e-10) self.assertIsInstance(result.channel_index, ChannelIndex) self.assertIsInstance(result.segment, Segment) self.assertIs(result.channel_index, self.signal1.channel_index) self.assertIs(result.segment, self.signal1.segment) def test__rescale_new_incompatible_ValueError(self): self.assertRaises(ValueError, self.signal1.rescale, pq.mV) def test_as_array(self): sig_as_arr = self.signal1.as_array() self.assertIsInstance(sig_as_arr, np.ndarray) assert_array_equal(self.data1, sig_as_arr.flat) def test_as_quantity(self): sig_as_q = self.signal1.as_quantity() self.assertIsInstance(sig_as_q, pq.Quantity) assert_array_equal(self.data1, sig_as_q.magnitude.flat) def test_splice_1channel_inplace(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=3*pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uA) result = self.signal1.splice(signal_for_splicing, copy=False) assert_array_equal(result.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 100.0, 100.0, 100.0, 6.0, 7.0, 8.0, 9.0])) assert_array_equal(self.signal1, result) # in-place self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) def test_splice_1channel_with_copy(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=3*pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uA) result = self.signal1.splice(signal_for_splicing, copy=True) assert_array_equal(result.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 100.0, 100.0, 100.0, 6.0, 7.0, 8.0, 9.0])) assert_array_equal(self.signal1.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])) self.assertIs(result.segment, None) self.assertIs(result.channel_index, None) def test_splice_2channels_inplace(self): signal = AnalogSignal(np.arange(20.0).reshape((10, 2)), sampling_rate=1 * pq.kHz, units="mV") signal_for_splicing = AnalogSignal(np.array([[0.1, 0.0], [0.2, 0.0], [0.3, 0.0]]), t_start=3*pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.V) result = signal.splice(signal_for_splicing, copy=False) assert_array_equal(result.magnitude, np.array([[0.0, 1.0], [2.0, 3.0], [4.0, 5.0], [100.0, 0.0], [200.0, 0.0], [300.0, 0.0], [12.0, 13.0], [14.0, 15.0], [16.0, 17.0], [18.0, 19.0]])) assert_array_equal(signal, result) # in-place def test_splice_1channel_invalid_t_start(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=12*pq.ms, # after the end of the signal sampling_rate=self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_t_stop(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=8 * pq.ms, # too close to the end of the signal sampling_rate=self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_sampling_rate(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=2 * self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_units(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uV) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False)
class TestAnalogSignalArrayArrayMethods(unittest.TestCase): def setUp(self): self.data1 = np.arange(55.0).reshape((11, 5)) self.data1quant = self.data1 * pq.nA self.signal1 = AnalogSignal(self.data1quant, sampling_rate=1 * pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') self.data2 = np.array([[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]).T self.data2quant = self.data2 * pq.mV self.signal2 = AnalogSignal(self.data2quant, sampling_rate=1.0 * pq.Hz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') def test__compliant(self): assert_neo_object_is_compliant(self.signal1) self.assertEqual(self.signal1.name, 'spam') self.assertEqual(self.signal1.description, 'eggs') self.assertEqual(self.signal1.file_origin, 'testfile.txt') self.assertEqual(self.signal1.annotations, {'arg1': 'test'}) assert_neo_object_is_compliant(self.signal2) self.assertEqual(self.signal2.name, 'spam') self.assertEqual(self.signal2.description, 'eggs') self.assertEqual(self.signal2.file_origin, 'testfile.txt') self.assertEqual(self.signal2.annotations, {'arg1': 'test'}) def test__index_dim1_should_return_single_channel_analogsignalarray(self): result = self.signal1[:, 0] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.t_stop, self.signal1.t_stop) self.assertEqual(result.t_start, self.signal1.t_start) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) assert_arrays_equal(result, self.data1[:, 0].reshape(-1, 1)) def test__index_dim1_and_slice_dim0_should_return_single_channel_analogsignalarray( self): result = self.signal1[2:7, 0] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.shape, (5, 1)) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual( result.t_start, self.signal1.t_start + 2 * self.signal1.sampling_period) self.assertEqual( result.t_stop, self.signal1.t_start + 7 * self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) assert_arrays_equal(result, self.data1[2:7, 0].reshape(-1, 1)) def test__index_dim0_should_return_quantity_array(self): # i.e. values from all signals for a single point in time result = self.signal1[3, :] self.assertIsInstance(result, pq.Quantity) self.assertFalse(hasattr(result, 'name')) self.assertFalse(hasattr(result, 'description')) self.assertFalse(hasattr(result, 'file_origin')) self.assertFalse(hasattr(result, 'annotations')) self.assertEqual(result.shape, (5, )) self.assertFalse(hasattr(result, "t_start")) self.assertEqual(result.units, pq.nA) assert_arrays_equal(result, self.data1[3, :]) def test__index_dim0_and_slice_dim1_should_return_quantity_array(self): # i.e. values from a subset of signals for a single point in time result = self.signal1[3, 2:5] self.assertIsInstance(result, pq.Quantity) self.assertFalse(hasattr(result, 'name')) self.assertFalse(hasattr(result, 'description')) self.assertFalse(hasattr(result, 'file_origin')) self.assertFalse(hasattr(result, 'annotations')) self.assertEqual(result.shape, (3, )) self.assertFalse(hasattr(result, "t_start")) self.assertEqual(result.units, pq.nA) assert_arrays_equal(result, self.data1[3, 2:5]) def test__index_as_string_IndexError(self): self.assertRaises(IndexError, self.signal1.__getitem__, 5.) def test__slice_both_dimensions_should_return_analogsignalarray(self): result = self.signal1[0:3, 0:3] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) targ = AnalogSignal([[0, 1, 2], [5, 6, 7], [10, 11, 12]], dtype=float, units="nA", sampling_rate=1 * pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') assert_neo_object_is_compliant(targ) self.assertEqual(result.t_stop, targ.t_stop) self.assertEqual(result.t_start, targ.t_start) self.assertEqual(result.sampling_rate, targ.sampling_rate) self.assertEqual(result.shape, targ.shape) assert_same_sub_schema(result, targ) assert_arrays_equal(result, self.data1[0:3, 0:3]) def test__slice_only_first_dimension_should_return_analogsignalarray(self): result = self.signal1[2:7] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.shape, (5, 5)) self.assertEqual( result.t_start, self.signal1.t_start + 2 * self.signal1.sampling_period) self.assertEqual( result.t_stop, self.signal1.t_start + 7 * self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) assert_arrays_equal(result, self.data1[2:7]) def test__getitem_should_return_single_quantity(self): # quantities drops the units in this case self.assertEqual(self.signal1[9, 3], 48000 * pq.pA) self.assertEqual(self.signal1[9][3], self.signal1[9, 3]) self.assertTrue(hasattr(self.signal1[9, 3], 'units')) self.assertRaises(IndexError, self.signal1.__getitem__, (99, 73)) def test_comparison_operators(self): assert_arrays_equal( self.signal1[0:3, 0:3] >= 5 * pq.nA, np.array([[False, False, False], [True, True, True], [True, True, True]])) assert_arrays_equal( self.signal1[0:3, 0:3] >= 5 * pq.pA, np.array([[False, True, True], [True, True, True], [True, True, True]])) def test__comparison_with_inconsistent_units_should_raise_Exception(self): self.assertRaises(ValueError, self.signal1.__gt__, 5 * pq.mV) def test__simple_statistics(self): self.assertEqual(self.signal1.max(), 54000 * pq.pA) self.assertEqual(self.signal1.min(), 0 * pq.nA) self.assertEqual(self.signal1.mean(), 27 * pq.nA) self.assertEqual(self.signal1.std(), self.signal1.magnitude.std() * pq.nA) self.assertEqual(self.signal1.var(), self.signal1.magnitude.var() * pq.nA**2) def test__rescale_same(self): result = self.signal1.copy() result = result.rescale(pq.nA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1 * pq.nA) assert_arrays_equal(result, self.data1) assert_same_sub_schema(result, self.signal1) def test__rescale_new(self): result = self.signal1.copy() result = result.rescale(pq.pA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1 * pq.pA) assert_arrays_almost_equal(np.array(result), self.data1 * 1000., 1e-10) def test__time_slice(self): t_start = 2 * pq.s t_stop = 4 * pq.s result = self.signal2.time_slice(t_start, t_stop) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) targ = AnalogSignal(np.array([[2., 3.], [2., 3.]]).T, sampling_rate=1.0 * pq.Hz, units='mV', t_start=t_start, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') assert_neo_object_is_compliant(result) self.assertEqual(result.t_stop, t_stop) self.assertEqual(result.t_start, t_start) self.assertEqual(result.sampling_rate, targ.sampling_rate) assert_array_equal(result, targ) assert_same_sub_schema(result, targ) def test__time_slice__out_of_bounds_ValueError(self): t_start_good = 2 * pq.s t_stop_good = 4 * pq.s t_start_bad = -2 * pq.s t_stop_bad = 40 * pq.s self.assertRaises(ValueError, self.signal2.time_slice, t_start_good, t_stop_bad) self.assertRaises(ValueError, self.signal2.time_slice, t_start_bad, t_stop_good) self.assertRaises(ValueError, self.signal2.time_slice, t_start_bad, t_stop_bad) def test__time_equal(self): t_start = 0 * pq.s t_stop = 6 * pq.s result = self.signal2.time_slice(t_start, t_stop) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.t_stop, t_stop) self.assertEqual(result.t_start, t_start) assert_array_equal(result, self.signal2) assert_same_sub_schema(result, self.signal2) def test__time_slice__offset(self): self.signal2.t_start = 10.0 * pq.s assert_neo_object_is_compliant(self.signal2) t_start = 12 * pq.s t_stop = 14 * pq.s result = self.signal2.time_slice(t_start, t_stop) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) targ = AnalogSignal(np.array([[2., 3.], [2., 3.]]).T, t_start=12.0 * pq.ms, sampling_rate=1.0 * pq.Hz, units='mV', name='spam', description='eggs', file_origin='testfile.txt', arg1='test') assert_neo_object_is_compliant(result) self.assertEqual(self.signal2.t_start, 10.0 * pq.s) self.assertEqual(result.t_stop, t_stop) self.assertEqual(result.t_start, t_start) self.assertEqual(result.sampling_rate, targ.sampling_rate) assert_arrays_equal(result, targ) assert_same_sub_schema(result, targ) def test__time_slice__different_units(self): self.signal2.t_start = 10.0 * pq.ms assert_neo_object_is_compliant(self.signal2) t_start = 2 * pq.s + 10.0 * pq.ms t_stop = 4 * pq.s + 10.0 * pq.ms result = self.signal2.time_slice(t_start, t_stop) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) targ = AnalogSignal(np.array([[2., 3.], [2., 3.]]).T, t_start=t_start.rescale(pq.ms), sampling_rate=1.0 * pq.Hz, units='mV', name='spam', description='eggs', file_origin='testfile.txt', arg1='test') assert_neo_object_is_compliant(result) assert_neo_object_is_compliant(self.signal2) self.assertEqual(self.signal2.t_start, 10.0 * pq.ms) self.assertAlmostEqual(result.t_stop, t_stop, delta=1e-12 * pq.ms) self.assertAlmostEqual(result.t_start, t_start, delta=1e-12 * pq.ms) assert_arrays_almost_equal(result.times, targ.times, 1e-12 * pq.ms) self.assertEqual(result.sampling_rate, targ.sampling_rate) assert_arrays_equal(result, targ) assert_same_sub_schema(result, targ) def test__time_slice__no_explicit_time(self): self.signal2.t_start = 10.0 * pq.ms assert_neo_object_is_compliant(self.signal2) t1 = 2 * pq.s + 10.0 * pq.ms t2 = 4 * pq.s + 10.0 * pq.ms for t_start, t_stop in [(t1, None), (None, None), (None, t2)]: t_start_targ = t1 if t_start != None else self.signal2.t_start t_stop_targ = t2 if t_stop != None else self.signal2.t_stop result = self.signal2.time_slice(t_start, t_stop) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) targ_ind = np.where((self.signal2.times >= t_start_targ) & (self.signal2.times < t_stop_targ)) targ_array = self.signal2.magnitude[targ_ind] targ = AnalogSignal(targ_array, t_start=t_start_targ.rescale(pq.ms), sampling_rate=1.0 * pq.Hz, units='mV', name='spam', description='eggs', file_origin='testfile.txt', arg1='test') assert_neo_object_is_compliant(result) assert_neo_object_is_compliant(self.signal2) self.assertEqual(self.signal2.t_start, 10.0 * pq.ms) self.assertAlmostEqual(result.t_stop, t_stop_targ, delta=1e-12 * pq.ms) self.assertAlmostEqual(result.t_start, t_start_targ, delta=1e-12 * pq.ms) assert_arrays_almost_equal(result.times, targ.times, 1e-12 * pq.ms) self.assertEqual(result.sampling_rate, targ.sampling_rate) assert_array_equal(result.magnitude, targ.magnitude) assert_same_sub_schema(result, targ)
class TestAnalogSignalArrayMethods(unittest.TestCase): def setUp(self): self.data1 = np.arange(10.0) self.data1quant = self.data1 * pq.nA self.signal1 = AnalogSignal(self.data1quant, sampling_rate=1*pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') def test__compliant(self): assert_neo_object_is_compliant(self.signal1) def test__slice_should_return_AnalogSignal(self): # slice result = self.signal1[3:8] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.size, 5) self.assertEqual(result.sampling_period, self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) self.assertEqual(result.t_start, self.signal1.t_start+3*result.sampling_period) self.assertEqual(result.t_stop, result.t_start + 5*result.sampling_period) assert_arrays_equal(result, self.data1[3:8]) # Test other attributes were copied over (in this case, defaults) self.assertEqual(result.file_origin, self.signal1.file_origin) self.assertEqual(result.name, self.signal1.name) self.assertEqual(result.description, self.signal1.description) self.assertEqual(result.annotations, self.signal1.annotations) def test__slice_should_change_sampling_period(self): result1 = self.signal1[:2] result2 = self.signal1[::2] result3 = self.signal1[1:7:2] self.assertIsInstance(result1, AnalogSignal) assert_neo_object_is_compliant(result1) self.assertEqual(result1.name, 'spam') self.assertEqual(result1.description, 'eggs') self.assertEqual(result1.file_origin, 'testfile.txt') self.assertEqual(result1.annotations, {'arg1': 'test'}) self.assertIsInstance(result2, AnalogSignal) assert_neo_object_is_compliant(result2) self.assertEqual(result2.name, 'spam') self.assertEqual(result2.description, 'eggs') self.assertEqual(result2.file_origin, 'testfile.txt') self.assertEqual(result2.annotations, {'arg1': 'test'}) self.assertIsInstance(result3, AnalogSignal) assert_neo_object_is_compliant(result3) self.assertEqual(result3.name, 'spam') self.assertEqual(result3.description, 'eggs') self.assertEqual(result3.file_origin, 'testfile.txt') self.assertEqual(result3.annotations, {'arg1': 'test'}) self.assertEqual(result1.sampling_period, self.signal1.sampling_period) self.assertEqual(result2.sampling_period, self.signal1.sampling_period * 2) self.assertEqual(result3.sampling_period, self.signal1.sampling_period * 2) assert_arrays_equal(result1, self.data1[:2]) assert_arrays_equal(result2, self.data1[::2]) assert_arrays_equal(result3, self.data1[1:7:2]) def test__getitem_should_return_single_quantity(self): result1 = self.signal1[0] result2 = self.signal1[9] self.assertIsInstance(result1, pq.Quantity) self.assertFalse(hasattr(result1, 'name')) self.assertFalse(hasattr(result1, 'description')) self.assertFalse(hasattr(result1, 'file_origin')) self.assertFalse(hasattr(result1, 'annotations')) self.assertIsInstance(result2, pq.Quantity) self.assertFalse(hasattr(result2, 'name')) self.assertFalse(hasattr(result2, 'description')) self.assertFalse(hasattr(result2, 'file_origin')) self.assertFalse(hasattr(result2, 'annotations')) self.assertEqual(result1, 0*pq.nA) self.assertEqual(result2, 9*pq.nA) def test__getitem_out_of_bounds_IndexError(self): self.assertRaises(IndexError, self.signal1.__getitem__, 10) def test_comparison_operators(self): assert_arrays_equal(self.signal1 >= 5*pq.nA, np.array([False, False, False, False, False, True, True, True, True, True])) assert_arrays_equal(self.signal1 >= 5*pq.pA, np.array([False, True, True, True, True, True, True, True, True, True])) def test__comparison_with_inconsistent_units_should_raise_Exception(self): self.assertRaises(ValueError, self.signal1.__gt__, 5*pq.mV) def test__simple_statistics(self): self.assertEqual(self.signal1.max(), 9*pq.nA) self.assertEqual(self.signal1.min(), 0*pq.nA) self.assertEqual(self.signal1.mean(), 4.5*pq.nA) def test__rescale_same(self): result = self.signal1.copy() result = result.rescale(pq.nA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1*pq.nA) assert_arrays_equal(result, self.data1) assert_same_sub_schema(result, self.signal1) def test__rescale_new(self): result = self.signal1.copy() result = result.rescale(pq.pA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1*pq.pA) assert_arrays_almost_equal(np.array(result), self.data1*1000., 1e-10) def test__rescale_new_incompatible_ValueError(self): self.assertRaises(ValueError, self.signal1.rescale, pq.mV)
class TestAnalogSignalArrayMethods(unittest.TestCase): def setUp(self): self.data1 = np.arange(10.0) self.data1quant = self.data1 * pq.nA self.signal1 = AnalogSignal(self.data1quant, sampling_rate=1 * pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') self.signal1.segment = Segment() self.signal1.channel_index = ChannelIndex(index=[0]) def test__compliant(self): assert_neo_object_is_compliant(self.signal1) def test__slice_should_return_AnalogSignalArray(self): # slice for index in (0, np.int64(0)): result = self.signal1[3:8, index] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) # should slicing really preserve name and description? self.assertEqual(result.name, 'spam') # perhaps these should be modified to indicate the slice? self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.size, 5) self.assertEqual(result.sampling_period, self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) self.assertEqual(result.t_start, self.signal1.t_start + 3 * result.sampling_period) self.assertEqual(result.t_stop, result.t_start + 5 * result.sampling_period) assert_array_equal(result.magnitude, self.data1[3:8].reshape(-1, 1)) # Test other attributes were copied over (in this case, defaults) self.assertEqual(result.file_origin, self.signal1.file_origin) self.assertEqual(result.name, self.signal1.name) self.assertEqual(result.description, self.signal1.description) self.assertEqual(result.annotations, self.signal1.annotations) def test__slice_should_let_access_to_parents_objects(self): result = self.signal1.time_slice(1 * pq.ms, 3 * pq.ms) self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) def test__slice_should_change_sampling_period(self): result1 = self.signal1[:2, 0] result2 = self.signal1[::2, 0] result3 = self.signal1[1:7:2, 0] self.assertIsInstance(result1, AnalogSignal) assert_neo_object_is_compliant(result1) self.assertEqual(result1.name, 'spam') self.assertEqual(result1.description, 'eggs') self.assertEqual(result1.file_origin, 'testfile.txt') self.assertEqual(result1.annotations, {'arg1': 'test'}) self.assertIsInstance(result2, AnalogSignal) assert_neo_object_is_compliant(result2) self.assertEqual(result2.name, 'spam') self.assertEqual(result2.description, 'eggs') self.assertEqual(result2.file_origin, 'testfile.txt') self.assertEqual(result2.annotations, {'arg1': 'test'}) self.assertIsInstance(result3, AnalogSignal) assert_neo_object_is_compliant(result3) self.assertEqual(result3.name, 'spam') self.assertEqual(result3.description, 'eggs') self.assertEqual(result3.file_origin, 'testfile.txt') self.assertEqual(result3.annotations, {'arg1': 'test'}) self.assertEqual(result1.sampling_period, self.signal1.sampling_period) self.assertEqual(result2.sampling_period, self.signal1.sampling_period * 2) self.assertEqual(result3.sampling_period, self.signal1.sampling_period * 2) assert_array_equal(result1.magnitude, self.data1[:2].reshape(-1, 1)) assert_array_equal(result2.magnitude, self.data1[::2].reshape(-1, 1)) assert_array_equal(result3.magnitude, self.data1[1:7:2].reshape(-1, 1)) def test__slice_should_modify_linked_channelindex(self): n = 8 # number of channels signal = AnalogSignal(np.arange(n * 100.0).reshape(100, n), sampling_rate=1 * pq.kHz, units="mV", name="test") self.assertEqual(signal.shape, (100, n)) signal.channel_index = ChannelIndex( index=np.arange(n, dtype=int), channel_names=["channel{0}".format(i) for i in range(n)]) signal.channel_index.analogsignals.append(signal) odd_channels = signal[:, 1::2] self.assertEqual(odd_channels.shape, (100, n // 2)) assert_array_equal(odd_channels.channel_index.index, np.arange(n // 2, dtype=int)) assert_array_equal(odd_channels.channel_index.channel_names, ["channel{0}".format(i) for i in range(1, n, 2)]) assert_array_equal(signal.channel_index.channel_names, ["channel{0}".format(i) for i in range(n)]) self.assertEqual(odd_channels.channel_index.analogsignals[0].name, signal.name) def test__copy_should_let_access_to_parents_objects(self): result = self.signal1.copy() self.assertIs(result.segment, self.signal1.segment) self.assertIs(result.channel_index, self.signal1.channel_index) def test__deepcopy_should_let_access_to_parents_objects(self): result = copy.deepcopy(self.signal1) self.assertIsInstance(result.segment, Segment) self.assertIsInstance(result.channel_index, ChannelIndex) assert_same_sub_schema(result.segment, self.signal1.segment) assert_same_sub_schema(result.channel_index, self.signal1.channel_index) def test__getitem_should_return_single_quantity(self): result1 = self.signal1[0, 0] result2 = self.signal1[9, 0] self.assertIsInstance(result1, pq.Quantity) self.assertFalse(hasattr(result1, 'name')) self.assertFalse(hasattr(result1, 'description')) self.assertFalse(hasattr(result1, 'file_origin')) self.assertFalse(hasattr(result1, 'annotations')) self.assertIsInstance(result2, pq.Quantity) self.assertFalse(hasattr(result2, 'name')) self.assertFalse(hasattr(result2, 'description')) self.assertFalse(hasattr(result2, 'file_origin')) self.assertFalse(hasattr(result2, 'annotations')) self.assertEqual(result1, 0 * pq.nA) self.assertEqual(result2, 9 * pq.nA) def test__getitem_out_of_bounds_IndexError(self): self.assertRaises(IndexError, self.signal1.__getitem__, (10, 0)) def test_comparison_operators(self): assert_array_equal( self.signal1 >= 5 * pq.nA, np.array([ False, False, False, False, False, True, True, True, True, True ]).reshape(-1, 1)) assert_array_equal( self.signal1 >= 5 * pq.pA, np.array( [False, True, True, True, True, True, True, True, True, True]).reshape(-1, 1)) def test__comparison_with_inconsistent_units_should_raise_Exception(self): self.assertRaises(ValueError, self.signal1.__gt__, 5 * pq.mV) def test__simple_statistics(self): self.assertEqual(self.signal1.max(), 9 * pq.nA) self.assertEqual(self.signal1.min(), 0 * pq.nA) self.assertEqual(self.signal1.mean(), 4.5 * pq.nA) def test__rescale_same(self): result = self.signal1.copy() result = result.rescale(pq.nA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1 * pq.nA) assert_array_equal(result.magnitude, self.data1.reshape(-1, 1)) assert_same_sub_schema(result, self.signal1) self.assertIsInstance(result.channel_index, ChannelIndex) self.assertIsInstance(result.segment, Segment) self.assertIs(result.channel_index, self.signal1.channel_index) self.assertIs(result.segment, self.signal1.segment) def test__rescale_new(self): result = self.signal1.copy() result = result.rescale(pq.pA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1 * pq.pA) assert_arrays_almost_equal(np.array(result), self.data1.reshape(-1, 1) * 1000., 1e-10) self.assertIsInstance(result.channel_index, ChannelIndex) self.assertIsInstance(result.segment, Segment) self.assertIs(result.channel_index, self.signal1.channel_index) self.assertIs(result.segment, self.signal1.segment) def test__rescale_new_incompatible_ValueError(self): self.assertRaises(ValueError, self.signal1.rescale, pq.mV) def test_as_array(self): sig_as_arr = self.signal1.as_array() self.assertIsInstance(sig_as_arr, np.ndarray) assert_array_equal(self.data1, sig_as_arr.flat) def test_as_quantity(self): sig_as_q = self.signal1.as_quantity() self.assertIsInstance(sig_as_q, pq.Quantity) assert_array_equal(self.data1, sig_as_q.magnitude.flat) def test_splice_1channel_inplace(self): signal_for_splicing = AnalogSignal( [0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uA) result = self.signal1.splice(signal_for_splicing, copy=False) assert_array_equal( result.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 100.0, 100.0, 100.0, 6.0, 7.0, 8.0, 9.0])) assert_array_equal(self.signal1, result) # in-place self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) def test_splice_1channel_with_copy(self): signal_for_splicing = AnalogSignal( [0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uA) result = self.signal1.splice(signal_for_splicing, copy=True) assert_array_equal( result.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 100.0, 100.0, 100.0, 6.0, 7.0, 8.0, 9.0])) assert_array_equal( self.signal1.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])) self.assertIs(result.segment, None) self.assertIs(result.channel_index, None) def test_splice_2channels_inplace(self): signal = AnalogSignal(np.arange(20.0).reshape((10, 2)), sampling_rate=1 * pq.kHz, units="mV") signal_for_splicing = AnalogSignal( np.array([[0.1, 0.0], [0.2, 0.0], [0.3, 0.0]]), t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.V) result = signal.splice(signal_for_splicing, copy=False) assert_array_equal( result.magnitude, np.array([[0.0, 1.0], [2.0, 3.0], [4.0, 5.0], [100.0, 0.0], [200.0, 0.0], [300.0, 0.0], [12.0, 13.0], [14.0, 15.0], [16.0, 17.0], [18.0, 19.0]])) assert_array_equal(signal, result) # in-place def test_splice_1channel_invalid_t_start(self): signal_for_splicing = AnalogSignal( [0.1, 0.1, 0.1], t_start=12 * pq.ms, # after the end of the signal sampling_rate=self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_t_stop(self): signal_for_splicing = AnalogSignal( [0.1, 0.1, 0.1], t_start=8 * pq.ms, # too close to the end of the signal sampling_rate=self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_sampling_rate(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=2 * self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_units(self): signal_for_splicing = AnalogSignal( [0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uV) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False)
class TestAnalogSignalArrayMethods(unittest.TestCase): def setUp(self): self.data1 = np.arange(10.0) self.data1quant = self.data1 * pq.nA self.arr_ann = {'anno1': [23], 'anno2': ['A']} self.signal1 = AnalogSignal(self.data1quant, sampling_rate=1 * pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test', array_annotations=self.arr_ann) self.signal1.segment = Segment() self.signal1.channel_index = ChannelIndex(index=[0]) def test__compliant(self): assert_neo_object_is_compliant(self.signal1) def test__slice_should_return_AnalogSignalArray(self): # slice for index in (0, np.int64(0)): result = self.signal1[3:8, index] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) # should slicing really preserve name and description? self.assertEqual(result.name, 'spam') # perhaps these should be modified to indicate the slice? self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) # Array annotations remain the same, because number of signals was not altered self.assertEqual(result.array_annotations, { 'anno1': [23], 'anno2': ['A'] }) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.size, 5) self.assertEqual(result.sampling_period, self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) self.assertEqual(result.t_start, self.signal1.t_start + 3 * result.sampling_period) self.assertEqual(result.t_stop, result.t_start + 5 * result.sampling_period) assert_array_equal(result.magnitude, self.data1[3:8].reshape(-1, 1)) # Test other attributes were copied over (in this case, defaults) self.assertEqual(result.file_origin, self.signal1.file_origin) self.assertEqual(result.name, self.signal1.name) self.assertEqual(result.description, self.signal1.description) self.assertEqual(result.annotations, self.signal1.annotations) def test__slice_should_let_access_to_parents_objects(self): result = self.signal1.time_slice(1 * pq.ms, 3 * pq.ms) self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) def test__slice_should_change_sampling_period(self): result1 = self.signal1[:2, 0] result2 = self.signal1[::2, 0] result3 = self.signal1[1:7:2, 0] self.assertIsInstance(result1, AnalogSignal) assert_neo_object_is_compliant(result1) self.assertEqual(result1.name, 'spam') self.assertEqual(result1.description, 'eggs') self.assertEqual(result1.file_origin, 'testfile.txt') self.assertEqual(result1.annotations, {'arg1': 'test'}) self.assertEqual(result1.array_annotations, { 'anno1': [23], 'anno2': ['A'] }) self.assertIsInstance(result1.array_annotations, ArrayDict) self.assertIsInstance(result2, AnalogSignal) assert_neo_object_is_compliant(result2) self.assertEqual(result2.name, 'spam') self.assertEqual(result2.description, 'eggs') self.assertEqual(result2.file_origin, 'testfile.txt') self.assertEqual(result2.annotations, {'arg1': 'test'}) self.assertEqual(result2.array_annotations, { 'anno1': [23], 'anno2': ['A'] }) self.assertIsInstance(result2.array_annotations, ArrayDict) self.assertIsInstance(result3, AnalogSignal) assert_neo_object_is_compliant(result3) self.assertEqual(result3.name, 'spam') self.assertEqual(result3.description, 'eggs') self.assertEqual(result3.file_origin, 'testfile.txt') self.assertEqual(result3.annotations, {'arg1': 'test'}) self.assertEqual(result3.array_annotations, { 'anno1': [23], 'anno2': ['A'] }) self.assertIsInstance(result3.array_annotations, ArrayDict) self.assertEqual(result1.sampling_period, self.signal1.sampling_period) self.assertEqual(result2.sampling_period, self.signal1.sampling_period * 2) self.assertEqual(result3.sampling_period, self.signal1.sampling_period * 2) assert_array_equal(result1.magnitude, self.data1[:2].reshape(-1, 1)) assert_array_equal(result2.magnitude, self.data1[::2].reshape(-1, 1)) assert_array_equal(result3.magnitude, self.data1[1:7:2].reshape(-1, 1)) def test__slice_should_modify_linked_channelindex(self): n = 8 # number of channels signal = AnalogSignal(np.arange(n * 100.0).reshape(100, n), sampling_rate=1 * pq.kHz, units="mV", name="test") self.assertEqual(signal.shape, (100, n)) signal.channel_index = ChannelIndex( index=np.arange(n, dtype=int), channel_names=["channel{0}".format(i) for i in range(n)]) signal.channel_index.analogsignals.append(signal) odd_channels = signal[:, 1::2] self.assertEqual(odd_channels.shape, (100, n // 2)) assert_array_equal(odd_channels.channel_index.index, np.arange(n // 2, dtype=int)) assert_array_equal(odd_channels.channel_index.channel_names, ["channel{0}".format(i) for i in range(1, n, 2)]) assert_array_equal(signal.channel_index.channel_names, ["channel{0}".format(i) for i in range(n)]) self.assertEqual(odd_channels.channel_index.analogsignals[0].name, signal.name) def test__copy_should_let_access_to_parents_objects(self): result = self.signal1.copy() self.assertIs(result.segment, self.signal1.segment) self.assertIs(result.channel_index, self.signal1.channel_index) def test__deepcopy_should_let_access_to_parents_objects(self): result = copy.deepcopy(self.signal1) self.assertIsInstance(result.segment, Segment) self.assertIsInstance(result.channel_index, ChannelIndex) assert_same_sub_schema(result.segment, self.signal1.segment) assert_same_sub_schema(result.channel_index, self.signal1.channel_index) def test__getitem_should_return_single_quantity(self): result1 = self.signal1[0, 0] result2 = self.signal1[9, 0] self.assertIsInstance(result1, pq.Quantity) self.assertFalse(hasattr(result1, 'name')) self.assertFalse(hasattr(result1, 'description')) self.assertFalse(hasattr(result1, 'file_origin')) self.assertFalse(hasattr(result1, 'annotations')) self.assertFalse(hasattr(result1, 'array_annotations')) self.assertIsInstance(result2, pq.Quantity) self.assertFalse(hasattr(result2, 'name')) self.assertFalse(hasattr(result2, 'description')) self.assertFalse(hasattr(result2, 'file_origin')) self.assertFalse(hasattr(result2, 'annotations')) self.assertFalse(hasattr(result2, 'array_annotations')) self.assertEqual(result1, 0 * pq.nA) self.assertEqual(result2, 9 * pq.nA) def test__getitem_out_of_bounds_IndexError(self): self.assertRaises(IndexError, self.signal1.__getitem__, (10, 0)) def test_comparison_operators(self): assert_array_equal( self.signal1 >= 5 * pq.nA, np.array([ False, False, False, False, False, True, True, True, True, True ]).reshape(-1, 1)) assert_array_equal( self.signal1 >= 5 * pq.pA, np.array( [False, True, True, True, True, True, True, True, True, True]).reshape(-1, 1)) assert_array_equal( self.signal1 == 5 * pq.nA, np.array([ False, False, False, False, False, True, False, False, False, False ]).reshape(-1, 1)) assert_array_equal( self.signal1 == self.signal1, np.array( [True, True, True, True, True, True, True, True, True, True]).reshape(-1, 1)) def test__comparison_as_indexing_single_trace(self): self.assertEqual(self.signal1[self.signal1 == 5], [5 * pq.mV]) def test__comparison_as_indexing_double_trace(self): signal = AnalogSignal(np.arange(20).reshape((-1, 2)) * pq.V, sampling_rate=1 * pq.Hz) assert_array_equal( signal[signal < 10], np.array([[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]]).T * pq.V) def test__indexing_keeps_order_across_channels(self): # AnalogSignals with 10 traces each having 5 samples (eg. data[0] = [0,10,20,30,40]) data = np.array([ range(10), range(10, 20), range(20, 30), range(30, 40), range(40, 50) ]) mask = np.full((5, 10), fill_value=False, dtype=bool) # selecting one entry per trace mask[[0, 1, 0, 3, 0, 2, 4, 3, 1, 4], range(10)] = True signal = AnalogSignal(np.array(data) * pq.V, sampling_rate=1 * pq.Hz) assert_array_equal( signal[mask], np.array([[0, 11, 2, 33, 4, 25, 46, 37, 18, 49]]) * pq.V) def test__indexing_keeps_order_across_time(self): # AnalogSignals with 10 traces each having 5 samples (eg. data[0] = [0,10,20,30,40]) data = np.array([ range(10), range(10, 20), range(20, 30), range(30, 40), range(40, 50) ]) mask = np.full((5, 10), fill_value=False, dtype=bool) # selecting two entries per trace temporal_ids = [0, 1, 0, 3, 1, 2, 4, 2, 1, 4 ] + [4, 3, 2, 1, 0, 1, 2, 3, 2, 1] mask[temporal_ids, list(range(10)) + list(range(10))] = True signal = AnalogSignal(np.array(data) * pq.V, sampling_rate=1 * pq.Hz) assert_array_equal( signal[mask], np.array([[0, 11, 2, 13, 4, 15, 26, 27, 18, 19], [40, 31, 22, 33, 14, 25, 46, 37, 28, 49]]) * pq.V) def test__comparison_with_inconsistent_units_should_raise_Exception(self): self.assertRaises(ValueError, self.signal1.__gt__, 5 * pq.mV) def test__simple_statistics(self): self.assertEqual(self.signal1.max(), 9 * pq.nA) self.assertEqual(self.signal1.min(), 0 * pq.nA) self.assertEqual(self.signal1.mean(), 4.5 * pq.nA) def test__rescale_same(self): result = self.signal1.copy() result = result.rescale(pq.nA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.array_annotations, { 'anno1': [23], 'anno2': ['A'] }) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.units, 1 * pq.nA) assert_array_equal(result.magnitude, self.data1.reshape(-1, 1)) assert_same_sub_schema(result, self.signal1) self.assertIsInstance(result.channel_index, ChannelIndex) self.assertIsInstance(result.segment, Segment) self.assertIs(result.channel_index, self.signal1.channel_index) self.assertIs(result.segment, self.signal1.segment) def test__rescale_new(self): result = self.signal1.copy() result = result.rescale(pq.pA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.array_annotations, { 'anno1': [23], 'anno2': ['A'] }) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.units, 1 * pq.pA) assert_arrays_almost_equal(np.array(result), self.data1.reshape(-1, 1) * 1000., 1e-10) self.assertIsInstance(result.channel_index, ChannelIndex) self.assertIsInstance(result.segment, Segment) self.assertIs(result.channel_index, self.signal1.channel_index) self.assertIs(result.segment, self.signal1.segment) def test__rescale_new_incompatible_ValueError(self): self.assertRaises(ValueError, self.signal1.rescale, pq.mV) def test_as_array(self): sig_as_arr = self.signal1.as_array() self.assertIsInstance(sig_as_arr, np.ndarray) assert_array_equal(self.data1, sig_as_arr.flat) def test_as_quantity(self): sig_as_q = self.signal1.as_quantity() self.assertIsInstance(sig_as_q, pq.Quantity) assert_array_equal(self.data1, sig_as_q.magnitude.flat) def test_splice_1channel_inplace(self): signal_for_splicing = AnalogSignal( [0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uA, array_annotations={ 'anno1': [0], 'anno2': ['C'] }) result = self.signal1.splice(signal_for_splicing, copy=False) assert_array_equal( result.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 100.0, 100.0, 100.0, 6.0, 7.0, 8.0, 9.0])) assert_array_equal(self.signal1, result) # in-place self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) assert_array_equal(result.array_annotations['anno1'], np.array([23])) assert_array_equal(result.array_annotations['anno2'], np.array(['A'])) self.assertIsInstance(result.array_annotations, ArrayDict) def test_splice_1channel_with_copy(self): signal_for_splicing = AnalogSignal( [0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uA, array_annotations={ 'anno1': [0], 'anno2': ['C'] }) result = self.signal1.splice(signal_for_splicing, copy=True) assert_array_equal( result.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 100.0, 100.0, 100.0, 6.0, 7.0, 8.0, 9.0])) assert_array_equal( self.signal1.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])) self.assertIs(result.segment, None) self.assertIs(result.channel_index, None) assert_array_equal(result.array_annotations['anno1'], np.array([23])) assert_array_equal(result.array_annotations['anno2'], np.array(['A'])) self.assertIsInstance(result.array_annotations, ArrayDict) def test_splice_2channels_inplace(self): arr_ann1 = {'index': np.arange(10, 12)} arr_ann2 = {'index': np.arange(2), 'test': ['a', 'b']} signal = AnalogSignal(np.arange(20.0).reshape((10, 2)), sampling_rate=1 * pq.kHz, units="mV", array_annotations=arr_ann1) signal_for_splicing = AnalogSignal( np.array([[0.1, 0.0], [0.2, 0.0], [0.3, 0.0]]), t_start=3 * pq.ms, array_annotations=arr_ann2, sampling_rate=self.signal1.sampling_rate, units=pq.V) result = signal.splice(signal_for_splicing, copy=False) assert_array_equal( result.magnitude, np.array([[0.0, 1.0], [2.0, 3.0], [4.0, 5.0], [100.0, 0.0], [200.0, 0.0], [300.0, 0.0], [12.0, 13.0], [14.0, 15.0], [16.0, 17.0], [18.0, 19.0]])) assert_array_equal(signal, result) # in-place # Array annotations are taken from the main signal assert_array_equal(result.array_annotations['index'], np.arange(10, 12)) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertNotIn('test', result.array_annotations) def test_splice_1channel_invalid_t_start(self): signal_for_splicing = AnalogSignal( [0.1, 0.1, 0.1], t_start=12 * pq.ms, # after the end of the signal sampling_rate=self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_t_stop(self): signal_for_splicing = AnalogSignal( [0.1, 0.1, 0.1], t_start=8 * pq.ms, # too close to the end of the signal sampling_rate=self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_sampling_rate(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=2 * self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_units(self): signal_for_splicing = AnalogSignal( [0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uV) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_array_annotations_getitem(self): data = np.arange(15).reshape(5, 3) * pq.mV arr_ann1 = [10, 15, 20] arr_ann2 = ['abc', 'def', 'ghi'] arr_anns = {'index': arr_ann1, 'label': arr_ann2} signal = AnalogSignal(data, sampling_rate=30000 * pq.Hz, array_annotations=arr_anns) # A time slice of all signals is selected, so all array annotations need to remain result1 = signal[0:2] assert_arrays_equal(result1.array_annotations['index'], np.array(arr_ann1)) assert_arrays_equal(result1.array_annotations['label'], np.array(arr_ann2)) self.assertIsInstance(result1.array_annotations, ArrayDict) # Only elements from signal with index 2 are selected, # so only those array_annotations should be returned result2 = signal[1:2, 2] assert_arrays_equal(result2.array_annotations['index'], np.array([20])) assert_arrays_equal(result2.array_annotations['label'], np.array(['ghi'])) self.assertIsInstance(result2.array_annotations, ArrayDict) # Because comparison of list with single element to scalar is possible, # we need to make sure that array_annotations remain arrays self.assertIsInstance(result2.array_annotations['index'], np.ndarray) self.assertIsInstance(result2.array_annotations['label'], np.ndarray) # Signals 0 and 1 are selected completely, # so their respective array_annotations should be returned result3 = signal[:, 0:2] assert_arrays_equal(result3.array_annotations['index'], np.array([10, 15])) assert_arrays_equal(result3.array_annotations['label'], np.array(['abc', 'def'])) self.assertIsInstance(result3.array_annotations, ArrayDict)
class TestAnalogSignalArrayMethods(unittest.TestCase): def setUp(self): self.data1 = np.arange(10.0) self.data1quant = self.data1 * pq.nA self.arr_ann = {'anno1': [23], 'anno2': ['A']} self.signal1 = AnalogSignal(self.data1quant, sampling_rate=1 * pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test', array_annotations=self.arr_ann) self.signal1.segment = Segment() self.signal1.channel_index = ChannelIndex(index=[0]) def test__compliant(self): assert_neo_object_is_compliant(self.signal1) def test__slice_should_return_AnalogSignalArray(self): # slice for index in (0, np.int64(0)): result = self.signal1[3:8, index] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) # should slicing really preserve name and description? self.assertEqual(result.name, 'spam') # perhaps these should be modified to indicate the slice? self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) # Array annotations remain the same, because number of signals was not altered self.assertEqual(result.array_annotations, {'anno1': [23], 'anno2': ['A']}) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.size, 5) self.assertEqual(result.sampling_period, self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) self.assertEqual(result.t_start, self.signal1.t_start + 3 * result.sampling_period) self.assertEqual(result.t_stop, result.t_start + 5 * result.sampling_period) assert_array_equal(result.magnitude, self.data1[3:8].reshape(-1, 1)) # Test other attributes were copied over (in this case, defaults) self.assertEqual(result.file_origin, self.signal1.file_origin) self.assertEqual(result.name, self.signal1.name) self.assertEqual(result.description, self.signal1.description) self.assertEqual(result.annotations, self.signal1.annotations) def test__slice_should_let_access_to_parents_objects(self): result = self.signal1.time_slice(1 * pq.ms, 3 * pq.ms) self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) def test__slice_should_change_sampling_period(self): result1 = self.signal1[:2, 0] result2 = self.signal1[::2, 0] result3 = self.signal1[1:7:2, 0] self.assertIsInstance(result1, AnalogSignal) assert_neo_object_is_compliant(result1) self.assertEqual(result1.name, 'spam') self.assertEqual(result1.description, 'eggs') self.assertEqual(result1.file_origin, 'testfile.txt') self.assertEqual(result1.annotations, {'arg1': 'test'}) self.assertEqual(result1.array_annotations, {'anno1': [23], 'anno2': ['A']}) self.assertIsInstance(result1.array_annotations, ArrayDict) self.assertIsInstance(result2, AnalogSignal) assert_neo_object_is_compliant(result2) self.assertEqual(result2.name, 'spam') self.assertEqual(result2.description, 'eggs') self.assertEqual(result2.file_origin, 'testfile.txt') self.assertEqual(result2.annotations, {'arg1': 'test'}) self.assertEqual(result2.array_annotations, {'anno1': [23], 'anno2': ['A']}) self.assertIsInstance(result2.array_annotations, ArrayDict) self.assertIsInstance(result3, AnalogSignal) assert_neo_object_is_compliant(result3) self.assertEqual(result3.name, 'spam') self.assertEqual(result3.description, 'eggs') self.assertEqual(result3.file_origin, 'testfile.txt') self.assertEqual(result3.annotations, {'arg1': 'test'}) self.assertEqual(result3.array_annotations, {'anno1': [23], 'anno2': ['A']}) self.assertIsInstance(result3.array_annotations, ArrayDict) self.assertEqual(result1.sampling_period, self.signal1.sampling_period) self.assertEqual(result2.sampling_period, self.signal1.sampling_period * 2) self.assertEqual(result3.sampling_period, self.signal1.sampling_period * 2) assert_array_equal(result1.magnitude, self.data1[:2].reshape(-1, 1)) assert_array_equal(result2.magnitude, self.data1[::2].reshape(-1, 1)) assert_array_equal(result3.magnitude, self.data1[1:7:2].reshape(-1, 1)) def test__slice_should_modify_linked_channelindex(self): n = 8 # number of channels signal = AnalogSignal(np.arange(n * 100.0).reshape(100, n), sampling_rate=1 * pq.kHz, units="mV", name="test") self.assertEqual(signal.shape, (100, n)) signal.channel_index = ChannelIndex(index=np.arange(n, dtype=int), channel_names=["channel{0}".format(i) for i in range(n)]) signal.channel_index.analogsignals.append(signal) odd_channels = signal[:, 1::2] self.assertEqual(odd_channels.shape, (100, n // 2)) assert_array_equal(odd_channels.channel_index.index, np.arange(n // 2, dtype=int)) assert_array_equal(odd_channels.channel_index.channel_names, ["channel{0}".format(i) for i in range(1, n, 2)]) assert_array_equal(signal.channel_index.channel_names, ["channel{0}".format(i) for i in range(n)]) self.assertEqual(odd_channels.channel_index.analogsignals[0].name, signal.name) def test__copy_should_let_access_to_parents_objects(self): result = self.signal1.copy() self.assertIs(result.segment, self.signal1.segment) self.assertIs(result.channel_index, self.signal1.channel_index) def test__deepcopy_should_let_access_to_parents_objects(self): result = copy.deepcopy(self.signal1) self.assertIsInstance(result.segment, Segment) self.assertIsInstance(result.channel_index, ChannelIndex) assert_same_sub_schema(result.segment, self.signal1.segment) assert_same_sub_schema(result.channel_index, self.signal1.channel_index) def test__getitem_should_return_single_quantity(self): result1 = self.signal1[0, 0] result2 = self.signal1[9, 0] self.assertIsInstance(result1, pq.Quantity) self.assertFalse(hasattr(result1, 'name')) self.assertFalse(hasattr(result1, 'description')) self.assertFalse(hasattr(result1, 'file_origin')) self.assertFalse(hasattr(result1, 'annotations')) self.assertFalse(hasattr(result1, 'array_annotations')) self.assertIsInstance(result2, pq.Quantity) self.assertFalse(hasattr(result2, 'name')) self.assertFalse(hasattr(result2, 'description')) self.assertFalse(hasattr(result2, 'file_origin')) self.assertFalse(hasattr(result2, 'annotations')) self.assertFalse(hasattr(result2, 'array_annotations')) self.assertEqual(result1, 0 * pq.nA) self.assertEqual(result2, 9 * pq.nA) def test__getitem_out_of_bounds_IndexError(self): self.assertRaises(IndexError, self.signal1.__getitem__, (10, 0)) def test_comparison_operators(self): assert_array_equal(self.signal1 >= 5 * pq.nA, np.array( [False, False, False, False, False, True, True, True, True, True]).reshape(-1, 1)) assert_array_equal(self.signal1 >= 5 * pq.pA, np.array( [False, True, True, True, True, True, True, True, True, True]).reshape(-1, 1)) assert_array_equal(self.signal1 == 5 * pq.nA, np.array( [False, False, False, False, False, True, False, False, False, False]).reshape(-1, 1)) assert_array_equal(self.signal1 == self.signal1, np.array( [True, True, True, True, True, True, True, True, True, True]).reshape(-1, 1)) def test__comparison_as_indexing_single_trace(self): self.assertEqual(self.signal1[self.signal1 == 5], [5 * pq.mV]) def test__comparison_as_indexing_double_trace(self): signal = AnalogSignal(np.arange(20).reshape((-1, 2)) * pq.V, sampling_rate=1 * pq.Hz) assert_array_equal(signal[signal < 10], np.array([[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]]).T * pq.V) def test__indexing_keeps_order_across_channels(self): # AnalogSignals with 10 traces each having 5 samples (eg. data[0] = [0,10,20,30,40]) data = np.array([range(10), range(10, 20), range(20, 30), range(30, 40), range(40, 50)]) mask = np.full((5, 10), fill_value=False, dtype=bool) # selecting one entry per trace mask[[0, 1, 0, 3, 0, 2, 4, 3, 1, 4], range(10)] = True signal = AnalogSignal(np.array(data) * pq.V, sampling_rate=1 * pq.Hz) assert_array_equal(signal[mask], np.array([[0, 11, 2, 33, 4, 25, 46, 37, 18, 49]]) * pq.V) def test__indexing_keeps_order_across_time(self): # AnalogSignals with 10 traces each having 5 samples (eg. data[0] = [0,10,20,30,40]) data = np.array([range(10), range(10, 20), range(20, 30), range(30, 40), range(40, 50)]) mask = np.full((5, 10), fill_value=False, dtype=bool) # selecting two entries per trace temporal_ids = [0, 1, 0, 3, 1, 2, 4, 2, 1, 4] + [4, 3, 2, 1, 0, 1, 2, 3, 2, 1] mask[temporal_ids, list(range(10)) + list(range(10))] = True signal = AnalogSignal(np.array(data) * pq.V, sampling_rate=1 * pq.Hz) assert_array_equal(signal[mask], np.array([[0, 11, 2, 13, 4, 15, 26, 27, 18, 19], [40, 31, 22, 33, 14, 25, 46, 37, 28, 49]]) * pq.V) def test__comparison_with_inconsistent_units_should_raise_Exception(self): self.assertRaises(ValueError, self.signal1.__gt__, 5 * pq.mV) def test__simple_statistics(self): self.assertEqual(self.signal1.max(), 9 * pq.nA) self.assertEqual(self.signal1.min(), 0 * pq.nA) self.assertEqual(self.signal1.mean(), 4.5 * pq.nA) def test__rescale_same(self): result = self.signal1.copy() result = result.rescale(pq.nA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.array_annotations, {'anno1': [23], 'anno2': ['A']}) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.units, 1 * pq.nA) assert_array_equal(result.magnitude, self.data1.reshape(-1, 1)) assert_same_sub_schema(result, self.signal1) self.assertIsInstance(result.channel_index, ChannelIndex) self.assertIsInstance(result.segment, Segment) self.assertIs(result.channel_index, self.signal1.channel_index) self.assertIs(result.segment, self.signal1.segment) def test__rescale_new(self): result = self.signal1.copy() result = result.rescale(pq.pA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.array_annotations, {'anno1': [23], 'anno2': ['A']}) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.units, 1 * pq.pA) assert_arrays_almost_equal(np.array(result), self.data1.reshape(-1, 1) * 1000., 1e-10) self.assertIsInstance(result.channel_index, ChannelIndex) self.assertIsInstance(result.segment, Segment) self.assertIs(result.channel_index, self.signal1.channel_index) self.assertIs(result.segment, self.signal1.segment) def test__rescale_new_incompatible_ValueError(self): self.assertRaises(ValueError, self.signal1.rescale, pq.mV) def test_as_array(self): sig_as_arr = self.signal1.as_array() self.assertIsInstance(sig_as_arr, np.ndarray) assert_array_equal(self.data1, sig_as_arr.flat) def test_as_quantity(self): sig_as_q = self.signal1.as_quantity() self.assertIsInstance(sig_as_q, pq.Quantity) assert_array_equal(self.data1, sig_as_q.magnitude.flat) def test_splice_1channel_inplace(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uA, array_annotations={'anno1': [0], 'anno2': ['C']}) result = self.signal1.splice(signal_for_splicing, copy=False) assert_array_equal(result.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 100.0, 100.0, 100.0, 6.0, 7.0, 8.0, 9.0])) assert_array_equal(self.signal1, result) # in-place self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) assert_array_equal(result.array_annotations['anno1'], np.array([23])) assert_array_equal(result.array_annotations['anno2'], np.array(['A'])) self.assertIsInstance(result.array_annotations, ArrayDict) def test_splice_1channel_with_copy(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uA, array_annotations={'anno1': [0], 'anno2': ['C']}) result = self.signal1.splice(signal_for_splicing, copy=True) assert_array_equal(result.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 100.0, 100.0, 100.0, 6.0, 7.0, 8.0, 9.0])) assert_array_equal(self.signal1.magnitude.flatten(), np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])) self.assertIs(result.segment, None) self.assertIs(result.channel_index, None) assert_array_equal(result.array_annotations['anno1'], np.array([23])) assert_array_equal(result.array_annotations['anno2'], np.array(['A'])) self.assertIsInstance(result.array_annotations, ArrayDict) def test_splice_2channels_inplace(self): arr_ann1 = {'index': np.arange(10, 12)} arr_ann2 = {'index': np.arange(2), 'test': ['a', 'b']} signal = AnalogSignal(np.arange(20.0).reshape((10, 2)), sampling_rate=1 * pq.kHz, units="mV", array_annotations=arr_ann1) signal_for_splicing = AnalogSignal(np.array([[0.1, 0.0], [0.2, 0.0], [0.3, 0.0]]), t_start=3 * pq.ms, array_annotations=arr_ann2, sampling_rate=self.signal1.sampling_rate, units=pq.V) result = signal.splice(signal_for_splicing, copy=False) assert_array_equal(result.magnitude, np.array( [[0.0, 1.0], [2.0, 3.0], [4.0, 5.0], [100.0, 0.0], [200.0, 0.0], [300.0, 0.0], [12.0, 13.0], [14.0, 15.0], [16.0, 17.0], [18.0, 19.0]])) assert_array_equal(signal, result) # in-place # Array annotations are taken from the main signal assert_array_equal(result.array_annotations['index'], np.arange(10, 12)) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertNotIn('test', result.array_annotations) def test_splice_1channel_invalid_t_start(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=12 * pq.ms, # after the end of the signal sampling_rate=self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_t_stop(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=8 * pq.ms, # too close to the end of the signal sampling_rate=self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_sampling_rate(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=2 * self.signal1.sampling_rate, units=pq.uA) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_splice_1channel_invalid_units(self): signal_for_splicing = AnalogSignal([0.1, 0.1, 0.1], t_start=3 * pq.ms, sampling_rate=self.signal1.sampling_rate, units=pq.uV) self.assertRaises(ValueError, self.signal1.splice, signal_for_splicing, copy=False) def test_array_annotations_getitem(self): data = np.arange(15).reshape(5, 3) * pq.mV arr_ann1 = [10, 15, 20] arr_ann2 = ['abc', 'def', 'ghi'] arr_anns = {'index': arr_ann1, 'label': arr_ann2} signal = AnalogSignal(data, sampling_rate=30000 * pq.Hz, array_annotations=arr_anns) # A time slice of all signals is selected, so all array annotations need to remain result1 = signal[0:2] assert_arrays_equal(result1.array_annotations['index'], np.array(arr_ann1)) assert_arrays_equal(result1.array_annotations['label'], np.array(arr_ann2)) self.assertIsInstance(result1.array_annotations, ArrayDict) # Only elements from signal with index 2 are selected, # so only those array_annotations should be returned result2 = signal[1:2, 2] assert_arrays_equal(result2.array_annotations['index'], np.array([20])) assert_arrays_equal(result2.array_annotations['label'], np.array(['ghi'])) self.assertIsInstance(result2.array_annotations, ArrayDict) # Because comparison of list with single element to scalar is possible, # we need to make sure that array_annotations remain arrays self.assertIsInstance(result2.array_annotations['index'], np.ndarray) self.assertIsInstance(result2.array_annotations['label'], np.ndarray) # Signals 0 and 1 are selected completely, # so their respective array_annotations should be returned result3 = signal[:, 0:2] assert_arrays_equal(result3.array_annotations['index'], np.array([10, 15])) assert_arrays_equal(result3.array_annotations['label'], np.array(['abc', 'def'])) self.assertIsInstance(result3.array_annotations, ArrayDict)
class TestAnalogSignalArrayArrayMethods(unittest.TestCase): def setUp(self): self.data1 = np.arange(55.0).reshape((11, 5)) self.data1quant = self.data1 * pq.nA self.arr_ann1 = {'anno1': np.arange(5), 'anno2': ['a', 'b', 'c', 'd', 'e']} self.signal1 = AnalogSignal(self.data1quant, sampling_rate=1 * pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', array_annotations=self.arr_ann1, arg1='test') self.data2 = np.array([[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]).T self.data2quant = self.data2 * pq.mV self.arr_ann2 = {'anno1': [10, 11], 'anno2': ['k', 'l']} self.signal2 = AnalogSignal(self.data2quant, sampling_rate=1.0 * pq.Hz, name='spam', description='eggs', file_origin='testfile.txt', array_annotations=self.arr_ann2, arg1='test') def test__compliant(self): assert_neo_object_is_compliant(self.signal1) self.assertEqual(self.signal1.name, 'spam') self.assertEqual(self.signal1.description, 'eggs') self.assertEqual(self.signal1.file_origin, 'testfile.txt') self.assertEqual(self.signal1.annotations, {'arg1': 'test'}) assert_arrays_equal(self.signal1.array_annotations['anno1'], np.arange(5)) assert_arrays_equal(self.signal1.array_annotations['anno2'], np.array(['a', 'b', 'c', 'd', 'e'])) self.assertIsInstance(self.signal1.array_annotations, ArrayDict) assert_neo_object_is_compliant(self.signal2) self.assertEqual(self.signal2.name, 'spam') self.assertEqual(self.signal2.description, 'eggs') self.assertEqual(self.signal2.file_origin, 'testfile.txt') self.assertEqual(self.signal2.annotations, {'arg1': 'test'}) assert_arrays_equal(self.signal2.array_annotations['anno1'], np.array([10, 11])) assert_arrays_equal(self.signal2.array_annotations['anno2'], np.array(['k', 'l'])) self.assertIsInstance(self.signal2.array_annotations, ArrayDict) def test__index_dim1_should_return_single_channel_analogsignalarray(self): result = self.signal1[:, 0] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.array([0])) assert_arrays_equal(result.array_annotations['anno2'], np.array(['a'])) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.t_stop, self.signal1.t_stop) self.assertEqual(result.t_start, self.signal1.t_start) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) assert_arrays_equal(result, self.data1[:, 0].reshape(-1, 1)) def test__index_dim1_and_slice_dim0_should_return_single_channel_analogsignalarray(self): result = self.signal1[2:7, 0] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.shape, (5, 1)) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.array([0])) assert_arrays_equal(result.array_annotations['anno2'], np.array(['a'])) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.t_start, self.signal1.t_start + 2 * self.signal1.sampling_period) self.assertEqual(result.t_stop, self.signal1.t_start + 7 * self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) assert_arrays_equal(result, self.data1[2:7, 0].reshape(-1, 1)) def test__index_dim0_should_return_quantity_array(self): # i.e. values from all signals for a single point in time result = self.signal1[3, :] self.assertIsInstance(result, pq.Quantity) self.assertFalse(hasattr(result, 'name')) self.assertFalse(hasattr(result, 'description')) self.assertFalse(hasattr(result, 'file_origin')) self.assertFalse(hasattr(result, 'annotations')) self.assertFalse(hasattr(result, 'array_annotations')) self.assertEqual(result.shape, (5,)) self.assertFalse(hasattr(result, "t_start")) self.assertEqual(result.units, pq.nA) assert_arrays_equal(result, self.data1[3, :]) def test__index_dim0_and_slice_dim1_should_return_quantity_array(self): # i.e. values from a subset of signals for a single point in time result = self.signal1[3, 2:5] self.assertIsInstance(result, pq.Quantity) self.assertFalse(hasattr(result, 'name')) self.assertFalse(hasattr(result, 'description')) self.assertFalse(hasattr(result, 'file_origin')) self.assertFalse(hasattr(result, 'annotations')) self.assertFalse(hasattr(result, 'array_annotations')) self.assertEqual(result.shape, (3,)) self.assertFalse(hasattr(result, "t_start")) self.assertEqual(result.units, pq.nA) assert_arrays_equal(result, self.data1[3, 2:5]) def test__index_as_string_IndexError(self): self.assertRaises(IndexError, self.signal1.__getitem__, 5.) def test__slice_both_dimensions_should_return_analogsignalarray(self): result = self.signal1[0:3, 0:3] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.array([0, 1, 2])) assert_arrays_equal(result.array_annotations['anno2'], np.array(['a', 'b', 'c'])) self.assertIsInstance(result.array_annotations, ArrayDict) targ = AnalogSignal([[0, 1, 2], [5, 6, 7], [10, 11, 12]], dtype=float, units="nA", sampling_rate=1 * pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') assert_neo_object_is_compliant(targ) self.assertEqual(result.t_stop, targ.t_stop) self.assertEqual(result.t_start, targ.t_start) self.assertEqual(result.sampling_rate, targ.sampling_rate) self.assertEqual(result.shape, targ.shape) assert_same_sub_schema(result, targ) assert_arrays_equal(result, self.data1[0:3, 0:3]) def test__slice_only_first_dimension_should_return_analogsignalarray(self): result = self.signal1[2:7] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.arange(5)) assert_arrays_equal(result.array_annotations['anno2'], np.array(['a', 'b', 'c', 'd', 'e'])) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.shape, (5, 5)) self.assertEqual(result.t_start, self.signal1.t_start + 2 * self.signal1.sampling_period) self.assertEqual(result.t_stop, self.signal1.t_start + 7 * self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) assert_arrays_equal(result, self.data1[2:7]) def test__getitem_should_return_single_quantity(self): # quantities drops the units in this case self.assertEqual(self.signal1[9, 3], 48000 * pq.pA) self.assertEqual(self.signal1[9][3], self.signal1[9, 3]) self.assertTrue(hasattr(self.signal1[9, 3], 'units')) self.assertRaises(IndexError, self.signal1.__getitem__, (99, 73)) def test_comparison_operators(self): assert_arrays_equal(self.signal1[0:3, 0:3] >= 5 * pq.nA, np.array( [[False, False, False], [True, True, True], [True, True, True]])) assert_arrays_equal(self.signal1[0:3, 0:3] >= 5 * pq.pA, np.array( [[False, True, True], [True, True, True], [True, True, True]])) assert_arrays_equal(self.signal1[0:3, 0:3] == 5 * pq.nA, np.array( [[False, False, False], [True, False, False], [False, False, False]])) assert_arrays_equal(self.signal1[0:3, 0:3] == self.signal1[0:3, 0:3], np.array([[True, True, True], [True, True, True], [True, True, True]])) def test__comparison_with_inconsistent_units_should_raise_Exception(self): self.assertRaises(ValueError, self.signal1.__gt__, 5 * pq.mV) def test__simple_statistics(self): self.assertEqual(self.signal1.max(), 54000 * pq.pA) self.assertEqual(self.signal1.min(), 0 * pq.nA) self.assertEqual(self.signal1.mean(), 27 * pq.nA) self.assertEqual(self.signal1.std(), self.signal1.magnitude.std() * pq.nA) self.assertEqual(self.signal1.var(), self.signal1.magnitude.var() * pq.nA ** 2) def test__rescale_same(self): result = self.signal1.copy() result = result.rescale(pq.nA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.arange(5)) assert_arrays_equal(result.array_annotations['anno2'], np.array(['a', 'b', 'c', 'd', 'e'])) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.units, 1 * pq.nA) assert_arrays_equal(result, self.data1) assert_same_sub_schema(result, self.signal1) def test__rescale_new(self): result = self.signal1.copy() result = result.rescale(pq.pA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.arange(5)) assert_arrays_equal(result.array_annotations['anno2'], np.array(['a', 'b', 'c', 'd', 'e'])) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.units, 1 * pq.pA) assert_arrays_almost_equal(np.array(result), self.data1 * 1000., 1e-10) def test__time_slice(self): t_start = 2 * pq.s t_stop = 4 * pq.s result = self.signal2.time_slice(t_start, t_stop) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.array([10, 11])) assert_arrays_equal(result.array_annotations['anno2'], np.array(['k', 'l'])) targ = AnalogSignal(np.array([[2., 3.], [2., 3.]]).T, sampling_rate=1.0 * pq.Hz, units='mV', t_start=t_start, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') assert_neo_object_is_compliant(result) self.assertEqual(result.t_stop, t_stop) self.assertEqual(result.t_start, t_start) self.assertEqual(result.sampling_rate, targ.sampling_rate) assert_array_equal(result, targ) assert_same_sub_schema(result, targ) def test__time_slice__out_of_bounds_ValueError(self): t_start_good = 2 * pq.s t_stop_good = 4 * pq.s t_start_bad = -2 * pq.s t_stop_bad = 40 * pq.s self.assertRaises(ValueError, self.signal2.time_slice, t_start_good, t_stop_bad) self.assertRaises(ValueError, self.signal2.time_slice, t_start_bad, t_stop_good) self.assertRaises(ValueError, self.signal2.time_slice, t_start_bad, t_stop_bad) def test__time_equal(self): t_start = 0 * pq.s t_stop = 6 * pq.s result = self.signal2.time_slice(t_start, t_stop) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.array([10, 11])) assert_arrays_equal(result.array_annotations['anno2'], np.array(['k', 'l'])) self.assertIsInstance(result.array_annotations, ArrayDict) self.assertEqual(result.t_stop, t_stop) self.assertEqual(result.t_start, t_start) assert_array_equal(result, self.signal2) assert_same_sub_schema(result, self.signal2) def test__time_slice__offset(self): self.signal2.t_start = 10.0 * pq.s assert_neo_object_is_compliant(self.signal2) t_start = 12 * pq.s t_stop = 14 * pq.s result = self.signal2.time_slice(t_start, t_stop) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.array([10, 11])) assert_arrays_equal(result.array_annotations['anno2'], np.array(['k', 'l'])) self.assertIsInstance(result.array_annotations, ArrayDict) targ = AnalogSignal(np.array([[2., 3.], [2., 3.]]).T, t_start=12.0 * pq.ms, sampling_rate=1.0 * pq.Hz, units='mV', name='spam', description='eggs', file_origin='testfile.txt', arg1='test') assert_neo_object_is_compliant(result) self.assertEqual(self.signal2.t_start, 10.0 * pq.s) self.assertEqual(result.t_stop, t_stop) self.assertEqual(result.t_start, t_start) self.assertEqual(result.sampling_rate, targ.sampling_rate) assert_arrays_equal(result, targ) assert_same_sub_schema(result, targ) def test__time_slice__different_units(self): self.signal2.t_start = 10.0 * pq.ms assert_neo_object_is_compliant(self.signal2) t_start = 2 * pq.s + 10.0 * pq.ms t_stop = 4 * pq.s + 10.0 * pq.ms result = self.signal2.time_slice(t_start, t_stop) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.array([10, 11])) assert_arrays_equal(result.array_annotations['anno2'], np.array(['k', 'l'])) self.assertIsInstance(result.array_annotations, ArrayDict) targ = AnalogSignal(np.array([[2., 3.], [2., 3.]]).T, t_start=t_start.rescale(pq.ms), sampling_rate=1.0 * pq.Hz, units='mV', name='spam', description='eggs', file_origin='testfile.txt', arg1='test') assert_neo_object_is_compliant(result) assert_neo_object_is_compliant(self.signal2) self.assertEqual(self.signal2.t_start, 10.0 * pq.ms) self.assertAlmostEqual(result.t_stop, t_stop, delta=1e-12 * pq.ms) self.assertAlmostEqual(result.t_start, t_start, delta=1e-12 * pq.ms) assert_arrays_almost_equal(result.times, targ.times, 1e-12 * pq.ms) self.assertEqual(result.sampling_rate, targ.sampling_rate) assert_arrays_equal(result, targ) assert_same_sub_schema(result, targ) def test__time_slice__no_explicit_time(self): self.signal2.t_start = 10.0 * pq.ms assert_neo_object_is_compliant(self.signal2) t1 = 2 * pq.s + 10.0 * pq.ms t2 = 4 * pq.s + 10.0 * pq.ms for t_start, t_stop in [(t1, None), (None, None), (None, t2)]: t_start_targ = t1 if t_start is not None else self.signal2.t_start t_stop_targ = t2 if t_stop is not None else self.signal2.t_stop result = self.signal2.time_slice(t_start, t_stop) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) assert_arrays_equal(result.array_annotations['anno1'], np.array([10, 11])) assert_arrays_equal(result.array_annotations['anno2'], np.array(['k', 'l'])) self.assertIsInstance(result.array_annotations, ArrayDict) targ_ind = np.where( (self.signal2.times >= t_start_targ) & (self.signal2.times < t_stop_targ)) targ_array = self.signal2.magnitude[targ_ind] targ = AnalogSignal(targ_array, t_start=t_start_targ.rescale(pq.ms), sampling_rate=1.0 * pq.Hz, units='mV', name='spam', description='eggs', file_origin='testfile.txt', arg1='test') assert_neo_object_is_compliant(result) assert_neo_object_is_compliant(self.signal2) self.assertEqual(self.signal2.t_start, 10.0 * pq.ms) self.assertAlmostEqual(result.t_stop, t_stop_targ, delta=1e-12 * pq.ms) self.assertAlmostEqual(result.t_start, t_start_targ, delta=1e-12 * pq.ms) assert_arrays_almost_equal(result.times, targ.times, 1e-12 * pq.ms) self.assertEqual(result.sampling_rate, targ.sampling_rate) assert_array_equal(result.magnitude, targ.magnitude) assert_same_sub_schema(result, targ)
class TestAnalogSignalArrayMethods(unittest.TestCase): def setUp(self): self.data1 = np.arange(10.0) self.data1quant = self.data1 * pq.nA self.signal1 = AnalogSignal(self.data1quant, sampling_rate=1*pq.kHz, name='spam', description='eggs', file_origin='testfile.txt', arg1='test') self.signal1.segment = 1 self.signal1.channel_index = ChannelIndex(index=[0]) def test__compliant(self): assert_neo_object_is_compliant(self.signal1) def test__slice_should_return_AnalogSignalArray(self): # slice result = self.signal1[3:8, 0] self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') # should slicing really preserve name and description? self.assertEqual(result.description, 'eggs') # perhaps these should be modified to indicate the slice? self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.size, 5) self.assertEqual(result.sampling_period, self.signal1.sampling_period) self.assertEqual(result.sampling_rate, self.signal1.sampling_rate) self.assertEqual(result.t_start, self.signal1.t_start+3*result.sampling_period) self.assertEqual(result.t_stop, result.t_start + 5*result.sampling_period) assert_array_equal(result.magnitude, self.data1[3:8].reshape(-1, 1)) # Test other attributes were copied over (in this case, defaults) self.assertEqual(result.file_origin, self.signal1.file_origin) self.assertEqual(result.name, self.signal1.name) self.assertEqual(result.description, self.signal1.description) self.assertEqual(result.annotations, self.signal1.annotations) def test__slice_should_let_access_to_parents_objects(self): result = self.signal1.time_slice(1*pq.ms,3*pq.ms) self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) def test__slice_should_change_sampling_period(self): result1 = self.signal1[:2, 0] result2 = self.signal1[::2, 0] result3 = self.signal1[1:7:2, 0] self.assertIsInstance(result1, AnalogSignal) assert_neo_object_is_compliant(result1) self.assertEqual(result1.name, 'spam') self.assertEqual(result1.description, 'eggs') self.assertEqual(result1.file_origin, 'testfile.txt') self.assertEqual(result1.annotations, {'arg1': 'test'}) self.assertIsInstance(result2, AnalogSignal) assert_neo_object_is_compliant(result2) self.assertEqual(result2.name, 'spam') self.assertEqual(result2.description, 'eggs') self.assertEqual(result2.file_origin, 'testfile.txt') self.assertEqual(result2.annotations, {'arg1': 'test'}) self.assertIsInstance(result3, AnalogSignal) assert_neo_object_is_compliant(result3) self.assertEqual(result3.name, 'spam') self.assertEqual(result3.description, 'eggs') self.assertEqual(result3.file_origin, 'testfile.txt') self.assertEqual(result3.annotations, {'arg1': 'test'}) self.assertEqual(result1.sampling_period, self.signal1.sampling_period) self.assertEqual(result2.sampling_period, self.signal1.sampling_period * 2) self.assertEqual(result3.sampling_period, self.signal1.sampling_period * 2) assert_array_equal(result1.magnitude, self.data1[:2].reshape(-1, 1)) assert_array_equal(result2.magnitude, self.data1[::2].reshape(-1, 1)) assert_array_equal(result3.magnitude, self.data1[1:7:2].reshape(-1, 1)) def test__slice_should_modify_linked_channelindex(self): n = 8 # number of channels signal = AnalogSignal(np.arange(n * 100.0).reshape(100, n), sampling_rate=1*pq.kHz, units="mV") self.assertEqual(signal.shape, (100, n)) signal.channel_index = ChannelIndex(index=np.arange(n, dtype=int), channel_names=["channel{0}".format(i) for i in range(n)]) odd_channels = signal[:, 1::2] self.assertEqual(odd_channels.shape, (100, n//2)) assert_array_equal(odd_channels.channel_index.index, np.arange(n//2, dtype=int)) assert_array_equal(odd_channels.channel_index.channel_names, ["channel{0}".format(i) for i in range(1, n, 2)]) assert_array_equal(signal.channel_index.channel_names, ["channel{0}".format(i) for i in range(n)]) def test__copy_should_let_access_to_parents_objects(self): ##copy result = self.signal1.copy() self.assertEqual(result.segment, self.signal1.segment) self.assertEqual(result.channel_index, self.signal1.channel_index) ## deep copy (not fixed yet) #result = copy.deepcopy(self.signal1) #self.assertEqual(result.segment, self.signal1.segment) #self.assertEqual(result.channel_index, self.signal1.channel_index) def test__getitem_should_return_single_quantity(self): result1 = self.signal1[0, 0] result2 = self.signal1[9, 0] self.assertIsInstance(result1, pq.Quantity) self.assertFalse(hasattr(result1, 'name')) self.assertFalse(hasattr(result1, 'description')) self.assertFalse(hasattr(result1, 'file_origin')) self.assertFalse(hasattr(result1, 'annotations')) self.assertIsInstance(result2, pq.Quantity) self.assertFalse(hasattr(result2, 'name')) self.assertFalse(hasattr(result2, 'description')) self.assertFalse(hasattr(result2, 'file_origin')) self.assertFalse(hasattr(result2, 'annotations')) self.assertEqual(result1, 0*pq.nA) self.assertEqual(result2, 9*pq.nA) def test__getitem_out_of_bounds_IndexError(self): self.assertRaises(IndexError, self.signal1.__getitem__, (10, 0)) def test_comparison_operators(self): assert_array_equal(self.signal1 >= 5*pq.nA, np.array([False, False, False, False, False, True, True, True, True, True]).reshape(-1, 1)) assert_array_equal(self.signal1 >= 5*pq.pA, np.array([False, True, True, True, True, True, True, True, True, True]).reshape(-1, 1)) def test__comparison_with_inconsistent_units_should_raise_Exception(self): self.assertRaises(ValueError, self.signal1.__gt__, 5*pq.mV) def test__simple_statistics(self): self.assertEqual(self.signal1.max(), 9*pq.nA) self.assertEqual(self.signal1.min(), 0*pq.nA) self.assertEqual(self.signal1.mean(), 4.5*pq.nA) def test__rescale_same(self): result = self.signal1.copy() result = result.rescale(pq.nA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1*pq.nA) assert_array_equal(result.magnitude, self.data1.reshape(-1, 1)) assert_same_sub_schema(result, self.signal1) def test__rescale_new(self): result = self.signal1.copy() result = result.rescale(pq.pA) self.assertIsInstance(result, AnalogSignal) assert_neo_object_is_compliant(result) self.assertEqual(result.name, 'spam') self.assertEqual(result.description, 'eggs') self.assertEqual(result.file_origin, 'testfile.txt') self.assertEqual(result.annotations, {'arg1': 'test'}) self.assertEqual(result.units, 1*pq.pA) assert_arrays_almost_equal(np.array(result), self.data1.reshape(-1, 1)*1000., 1e-10) def test__rescale_new_incompatible_ValueError(self): self.assertRaises(ValueError, self.signal1.rescale, pq.mV) def test_as_array(self): sig_as_arr = self.signal1.as_array() self.assertIsInstance(sig_as_arr, np.ndarray) assert_array_equal(self.data1, sig_as_arr.flat) def test_as_quantity(self): sig_as_q = self.signal1.as_quantity() self.assertIsInstance(sig_as_q, pq.Quantity) assert_array_equal(self.data1, sig_as_q.magnitude.flat)