test_analogsignalarray.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. # -*- coding: utf-8 -*-
  2. """
  3. Tests of the neo.core.analogsignalarray.AnalogSignalArrayArray class
  4. """
  5. import os
  6. import pickle
  7. try:
  8. import unittest2 as unittest
  9. except ImportError:
  10. import unittest
  11. import numpy as np
  12. import quantities as pq
  13. try:
  14. from IPython.lib.pretty import pretty
  15. except ImportError as err:
  16. HAVE_IPYTHON = False
  17. else:
  18. HAVE_IPYTHON = True
  19. from numpy.testing import assert_array_equal
  20. from neo.core.analogsignal import AnalogSignal
  21. from neo.core import Segment, ChannelIndex
  22. from neo.test.tools import (assert_arrays_almost_equal, assert_arrays_equal,
  23. assert_neo_object_is_compliant,
  24. assert_same_sub_schema)
  25. from neo.test.generate_datasets import (get_fake_value, get_fake_values,
  26. fake_neo, TEST_ANNOTATIONS)
  27. class Test__generate_datasets(unittest.TestCase):
  28. def setUp(self):
  29. np.random.seed(0)
  30. self.annotations = dict([(str(x), TEST_ANNOTATIONS[x]) for x in
  31. range(len(TEST_ANNOTATIONS))])
  32. def test__get_fake_values(self):
  33. self.annotations['seed'] = 0
  34. signal = get_fake_value('signal', pq.Quantity, seed=0, dim=2)
  35. sampling_rate = get_fake_value('sampling_rate', pq.Quantity,
  36. seed=1, dim=0)
  37. t_start = get_fake_value('t_start', pq.Quantity, seed=2, dim=0)
  38. name = get_fake_value('name', str, seed=3, obj=AnalogSignal)
  39. description = get_fake_value('description', str, seed=4,
  40. obj='AnalogSignal')
  41. file_origin = get_fake_value('file_origin', str)
  42. attrs1 = {'name': name,
  43. 'description': description,
  44. 'file_origin': file_origin}
  45. attrs2 = attrs1.copy()
  46. attrs2.update(self.annotations)
  47. res11 = get_fake_values(AnalogSignal, annotate=False, seed=0)
  48. res12 = get_fake_values('AnalogSignal', annotate=False, seed=0)
  49. res21 = get_fake_values(AnalogSignal, annotate=True, seed=0)
  50. res22 = get_fake_values('AnalogSignal', annotate=True, seed=0)
  51. assert_arrays_equal(res11.pop('signal'), signal)
  52. assert_arrays_equal(res12.pop('signal'), signal)
  53. assert_arrays_equal(res21.pop('signal'), signal)
  54. assert_arrays_equal(res22.pop('signal'), signal)
  55. assert_arrays_equal(res11.pop('sampling_rate'), sampling_rate)
  56. assert_arrays_equal(res12.pop('sampling_rate'), sampling_rate)
  57. assert_arrays_equal(res21.pop('sampling_rate'), sampling_rate)
  58. assert_arrays_equal(res22.pop('sampling_rate'), sampling_rate)
  59. assert_arrays_equal(res11.pop('t_start'), t_start)
  60. assert_arrays_equal(res12.pop('t_start'), t_start)
  61. assert_arrays_equal(res21.pop('t_start'), t_start)
  62. assert_arrays_equal(res22.pop('t_start'), t_start)
  63. self.assertEqual(res11, attrs1)
  64. self.assertEqual(res12, attrs1)
  65. self.assertEqual(res21, attrs2)
  66. self.assertEqual(res22, attrs2)
  67. def test__fake_neo__cascade(self):
  68. self.annotations['seed'] = None
  69. obj_type = 'AnalogSignal'
  70. cascade = True
  71. res = fake_neo(obj_type=obj_type, cascade=cascade)
  72. self.assertTrue(isinstance(res, AnalogSignal))
  73. assert_neo_object_is_compliant(res)
  74. self.assertEqual(res.annotations, self.annotations)
  75. def test__fake_neo__nocascade(self):
  76. self.annotations['seed'] = None
  77. obj_type = AnalogSignal
  78. cascade = False
  79. res = fake_neo(obj_type=obj_type, cascade=cascade)
  80. self.assertTrue(isinstance(res, AnalogSignal))
  81. assert_neo_object_is_compliant(res)
  82. self.assertEqual(res.annotations, self.annotations)
  83. class TestAnalogSignalArrayConstructor(unittest.TestCase):
  84. def test__create_from_list(self):
  85. data = [(i, i, i) for i in range(10)] # 3 signals each with 10 samples
  86. rate = 1000*pq.Hz
  87. signal = AnalogSignal(data, sampling_rate=rate, units="mV")
  88. assert_neo_object_is_compliant(signal)
  89. self.assertEqual(signal.shape, (10, 3))
  90. self.assertEqual(signal.t_start, 0*pq.ms)
  91. self.assertEqual(signal.t_stop, len(data)/rate)
  92. self.assertEqual(signal[9, 0], 9000*pq.uV)
  93. def test__create_from_numpy_array(self):
  94. data = np.arange(20.0).reshape((10, 2))
  95. rate = 1*pq.kHz
  96. signal = AnalogSignal(data, sampling_rate=rate, units="uV")
  97. assert_neo_object_is_compliant(signal)
  98. self.assertEqual(signal.t_start, 0*pq.ms)
  99. self.assertEqual(signal.t_stop, data.shape[0]/rate)
  100. self.assertEqual(signal[9, 0], 0.018*pq.mV)
  101. self.assertEqual(signal[9, 1], 19*pq.uV)
  102. def test__create_from_quantities_array(self):
  103. data = np.arange(20.0).reshape((10, 2)) * pq.mV
  104. rate = 5000*pq.Hz
  105. signal = AnalogSignal(data, sampling_rate=rate)
  106. assert_neo_object_is_compliant(signal)
  107. self.assertEqual(signal.t_start, 0*pq.ms)
  108. self.assertEqual(signal.t_stop, data.shape[0]/rate)
  109. self.assertEqual(signal[9, 0], 18000*pq.uV)
  110. def test__create_from_quantities_with_inconsistent_units_ValueError(self):
  111. data = np.arange(20.0).reshape((10, 2)) * pq.mV
  112. self.assertRaises(ValueError, AnalogSignal, data,
  113. sampling_rate=1*pq.kHz, units="nA")
  114. def test__create_with_copy_true_should_return_copy(self):
  115. data = np.arange(20.0).reshape((10, 2)) * pq.mV
  116. rate = 5000*pq.Hz
  117. signal = AnalogSignal(data, copy=True, sampling_rate=rate)
  118. assert_neo_object_is_compliant(signal)
  119. data[3, 0] = 0.099*pq.V
  120. self.assertNotEqual(signal[3, 0], 99*pq.mV)
  121. def test__create_with_copy_false_should_return_view(self):
  122. data = np.arange(20.0).reshape((10, 2)) * pq.mV
  123. rate = 5000*pq.Hz
  124. signal = AnalogSignal(data, copy=False, sampling_rate=rate)
  125. assert_neo_object_is_compliant(signal)
  126. data[3, 0] = 99*pq.mV
  127. self.assertEqual(signal[3, 0], 99000*pq.uV)
  128. # signal must not be 1D - should raise Exception if 1D
  129. class TestAnalogSignalArrayProperties(unittest.TestCase):
  130. def setUp(self):
  131. self.t_start = [0.0*pq.ms, 100*pq.ms, -200*pq.ms]
  132. self.rates = [1*pq.kHz, 420*pq.Hz, 999*pq.Hz]
  133. self.data = [np.arange(10.0).reshape((5, 2))*pq.nA,
  134. np.arange(-100.0, 100.0, 10.0).reshape((4, 5))*pq.mV,
  135. np.random.uniform(size=(100, 4))*pq.uV]
  136. self.signals = [AnalogSignal(D, sampling_rate=r, t_start=t)
  137. for r, D, t in zip(self.rates,
  138. self.data,
  139. self.t_start)]
  140. def test__compliant(self):
  141. for signal in self.signals:
  142. assert_neo_object_is_compliant(signal)
  143. def test__t_stop(self):
  144. for i, signal in enumerate(self.signals):
  145. targ = self.t_start[i] + self.data[i].shape[0]/self.rates[i]
  146. self.assertEqual(signal.t_stop, targ)
  147. def test__duration(self):
  148. for signal in self.signals:
  149. self.assertAlmostEqual(signal.duration,
  150. signal.t_stop - signal.t_start,
  151. delta=1e-15)
  152. def test__sampling_period(self):
  153. for signal, rate in zip(self.signals, self.rates):
  154. self.assertEqual(signal.sampling_period, 1/rate)
  155. def test__times(self):
  156. for i, signal in enumerate(self.signals):
  157. targ = np.arange(self.data[i].shape[0])
  158. targ = targ/self.rates[i] + self.t_start[i]
  159. assert_arrays_almost_equal(signal.times, targ, 1e-12*pq.ms)
  160. def test__children(self):
  161. signal = self.signals[0]
  162. segment = Segment(name='seg1')
  163. segment.analogsignals = [signal]
  164. segment.create_many_to_one_relationship()
  165. chx = ChannelIndex(name='chx1', index=np.arange(signal.shape[1]))
  166. chx.analogsignals = [signal]
  167. chx.create_many_to_one_relationship()
  168. self.assertEqual(signal._single_parent_objects,
  169. ('Segment', 'ChannelIndex'))
  170. self.assertEqual(signal._multi_parent_objects, ())
  171. self.assertEqual(signal._single_parent_containers,
  172. ('segment', 'channel_index'))
  173. self.assertEqual(signal._multi_parent_containers, ())
  174. self.assertEqual(signal._parent_objects,
  175. ('Segment', 'ChannelIndex'))
  176. self.assertEqual(signal._parent_containers,
  177. ('segment', 'channel_index'))
  178. self.assertEqual(len(signal.parents), 2)
  179. self.assertEqual(signal.parents[0].name, 'seg1')
  180. self.assertEqual(signal.parents[1].name, 'chx1')
  181. assert_neo_object_is_compliant(signal)
  182. def test__repr(self):
  183. for i, signal in enumerate(self.signals):
  184. prepr = repr(signal)
  185. targ = '<AnalogSignal(%s, [%s, %s], sampling rate: %s)>' % \
  186. (repr(self.data[i]),
  187. self.t_start[i],
  188. self.t_start[i] + len(self.data[i])/self.rates[i],
  189. self.rates[i])
  190. self.assertEqual(prepr, targ)
  191. class TestAnalogSignalArrayArrayMethods(unittest.TestCase):
  192. def setUp(self):
  193. self.data1 = np.arange(55.0).reshape((11, 5))
  194. self.data1quant = self.data1 * pq.nA
  195. self.signal1 = AnalogSignal(self.data1quant,
  196. sampling_rate=1*pq.kHz,
  197. name='spam', description='eggs',
  198. file_origin='testfile.txt',
  199. arg1='test')
  200. self.data2 = np.array([[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]).T
  201. self.data2quant = self.data2 * pq.mV
  202. self.signal2 = AnalogSignal(self.data2quant,
  203. sampling_rate=1.0*pq.Hz,
  204. name='spam', description='eggs',
  205. file_origin='testfile.txt',
  206. arg1='test')
  207. def test__compliant(self):
  208. assert_neo_object_is_compliant(self.signal1)
  209. self.assertEqual(self.signal1.name, 'spam')
  210. self.assertEqual(self.signal1.description, 'eggs')
  211. self.assertEqual(self.signal1.file_origin, 'testfile.txt')
  212. self.assertEqual(self.signal1.annotations, {'arg1': 'test'})
  213. assert_neo_object_is_compliant(self.signal2)
  214. self.assertEqual(self.signal2.name, 'spam')
  215. self.assertEqual(self.signal2.description, 'eggs')
  216. self.assertEqual(self.signal2.file_origin, 'testfile.txt')
  217. self.assertEqual(self.signal2.annotations, {'arg1': 'test'})
  218. def test__index_dim1_should_return_single_channel_analogsignalarray(self):
  219. result = self.signal1[:, 0]
  220. self.assertIsInstance(result, AnalogSignal)
  221. assert_neo_object_is_compliant(result)
  222. self.assertEqual(result.name, 'spam')
  223. self.assertEqual(result.description, 'eggs')
  224. self.assertEqual(result.file_origin, 'testfile.txt')
  225. self.assertEqual(result.annotations, {'arg1': 'test'})
  226. self.assertEqual(result.t_stop, self.signal1.t_stop)
  227. self.assertEqual(result.t_start, self.signal1.t_start)
  228. self.assertEqual(result.sampling_rate,
  229. self.signal1.sampling_rate)
  230. assert_arrays_equal(result, self.data1[:, 0].reshape(-1, 1))
  231. def test__index_dim1_and_slice_dim0_should_return_single_channel_analogsignalarray(self):
  232. result = self.signal1[2:7, 0]
  233. self.assertIsInstance(result, AnalogSignal)
  234. assert_neo_object_is_compliant(result)
  235. self.assertEqual(result.shape, (5, 1))
  236. self.assertEqual(result.name, 'spam')
  237. self.assertEqual(result.description, 'eggs')
  238. self.assertEqual(result.file_origin, 'testfile.txt')
  239. self.assertEqual(result.annotations, {'arg1': 'test'})
  240. self.assertEqual(result.t_start,
  241. self.signal1.t_start+2*self.signal1.sampling_period)
  242. self.assertEqual(result.t_stop,
  243. self.signal1.t_start+7*self.signal1.sampling_period)
  244. self.assertEqual(result.sampling_rate,
  245. self.signal1.sampling_rate)
  246. assert_arrays_equal(result, self.data1[2:7, 0].reshape(-1, 1))
  247. def test__index_dim0_should_return_quantity_array(self):
  248. # i.e. values from all signals for a single point in time
  249. result = self.signal1[3, :]
  250. self.assertIsInstance(result, pq.Quantity)
  251. self.assertFalse(hasattr(result, 'name'))
  252. self.assertFalse(hasattr(result, 'description'))
  253. self.assertFalse(hasattr(result, 'file_origin'))
  254. self.assertFalse(hasattr(result, 'annotations'))
  255. self.assertEqual(result.shape, (5,))
  256. self.assertFalse(hasattr(result, "t_start"))
  257. self.assertEqual(result.units, pq.nA)
  258. assert_arrays_equal(result, self.data1[3, :])
  259. def test__index_dim0_and_slice_dim1_should_return_quantity_array(self):
  260. # i.e. values from a subset of signals for a single point in time
  261. result = self.signal1[3, 2:5]
  262. self.assertIsInstance(result, pq.Quantity)
  263. self.assertFalse(hasattr(result, 'name'))
  264. self.assertFalse(hasattr(result, 'description'))
  265. self.assertFalse(hasattr(result, 'file_origin'))
  266. self.assertFalse(hasattr(result, 'annotations'))
  267. self.assertEqual(result.shape, (3,))
  268. self.assertFalse(hasattr(result, "t_start"))
  269. self.assertEqual(result.units, pq.nA)
  270. assert_arrays_equal(result, self.data1[3, 2:5])
  271. def test__index_as_string_IndexError(self):
  272. self.assertRaises(IndexError, self.signal1.__getitem__, 5.)
  273. def test__slice_both_dimensions_should_return_analogsignalarray(self):
  274. result = self.signal1[0:3, 0:3]
  275. self.assertIsInstance(result, AnalogSignal)
  276. assert_neo_object_is_compliant(result)
  277. self.assertEqual(result.name, 'spam')
  278. self.assertEqual(result.description, 'eggs')
  279. self.assertEqual(result.file_origin, 'testfile.txt')
  280. self.assertEqual(result.annotations, {'arg1': 'test'})
  281. targ = AnalogSignal([[0, 1, 2], [5, 6, 7], [10, 11, 12]],
  282. dtype=float, units="nA",
  283. sampling_rate=1*pq.kHz,
  284. name='spam', description='eggs',
  285. file_origin='testfile.txt', arg1='test')
  286. assert_neo_object_is_compliant(targ)
  287. self.assertEqual(result.t_stop, targ.t_stop)
  288. self.assertEqual(result.t_start, targ.t_start)
  289. self.assertEqual(result.sampling_rate, targ.sampling_rate)
  290. self.assertEqual(result.shape, targ.shape)
  291. assert_same_sub_schema(result, targ)
  292. assert_arrays_equal(result, self.data1[0:3, 0:3])
  293. def test__slice_only_first_dimension_should_return_analogsignalarray(self):
  294. result = self.signal1[2:7]
  295. self.assertIsInstance(result, AnalogSignal)
  296. assert_neo_object_is_compliant(result)
  297. self.assertEqual(result.name, 'spam')
  298. self.assertEqual(result.description, 'eggs')
  299. self.assertEqual(result.file_origin, 'testfile.txt')
  300. self.assertEqual(result.annotations, {'arg1': 'test'})
  301. self.assertEqual(result.shape, (5, 5))
  302. self.assertEqual(result.t_start,
  303. self.signal1.t_start+2*self.signal1.sampling_period)
  304. self.assertEqual(result.t_stop,
  305. self.signal1.t_start+7*self.signal1.sampling_period)
  306. self.assertEqual(result.sampling_rate, self.signal1.sampling_rate)
  307. assert_arrays_equal(result, self.data1[2:7])
  308. def test__getitem_should_return_single_quantity(self):
  309. # quantities drops the units in this case
  310. self.assertEqual(self.signal1[9, 3], 48000*pq.pA)
  311. self.assertEqual(self.signal1[9][3], self.signal1[9, 3])
  312. self.assertTrue(hasattr(self.signal1[9, 3], 'units'))
  313. self.assertRaises(IndexError, self.signal1.__getitem__, (99, 73))
  314. def test_comparison_operators(self):
  315. assert_arrays_equal(self.signal1[0:3, 0:3] >= 5*pq.nA,
  316. np.array([[False, False, False],
  317. [True, True, True],
  318. [True, True, True]]))
  319. assert_arrays_equal(self.signal1[0:3, 0:3] >= 5*pq.pA,
  320. np.array([[False, True, True],
  321. [True, True, True],
  322. [True, True, True]]))
  323. def test__comparison_with_inconsistent_units_should_raise_Exception(self):
  324. self.assertRaises(ValueError, self.signal1.__gt__, 5*pq.mV)
  325. def test__simple_statistics(self):
  326. self.assertEqual(self.signal1.max(), 54000*pq.pA)
  327. self.assertEqual(self.signal1.min(), 0*pq.nA)
  328. self.assertEqual(self.signal1.mean(), 27*pq.nA)
  329. self.assertEqual(self.signal1.std(), self.signal1.magnitude.std()*pq.nA)
  330. self.assertEqual(self.signal1.var(), self.signal1.magnitude.var()*pq.nA**2)
  331. def test__rescale_same(self):
  332. result = self.signal1.copy()
  333. result = result.rescale(pq.nA)
  334. self.assertIsInstance(result, AnalogSignal)
  335. assert_neo_object_is_compliant(result)
  336. self.assertEqual(result.name, 'spam')
  337. self.assertEqual(result.description, 'eggs')
  338. self.assertEqual(result.file_origin, 'testfile.txt')
  339. self.assertEqual(result.annotations, {'arg1': 'test'})
  340. self.assertEqual(result.units, 1*pq.nA)
  341. assert_arrays_equal(result, self.data1)
  342. assert_same_sub_schema(result, self.signal1)
  343. def test__rescale_new(self):
  344. result = self.signal1.copy()
  345. result = result.rescale(pq.pA)
  346. self.assertIsInstance(result, AnalogSignal)
  347. assert_neo_object_is_compliant(result)
  348. self.assertEqual(result.name, 'spam')
  349. self.assertEqual(result.description, 'eggs')
  350. self.assertEqual(result.file_origin, 'testfile.txt')
  351. self.assertEqual(result.annotations, {'arg1': 'test'})
  352. self.assertEqual(result.units, 1*pq.pA)
  353. assert_arrays_almost_equal(np.array(result), self.data1*1000., 1e-10)
  354. def test__time_slice(self):
  355. t_start = 2 * pq.s
  356. t_stop = 4 * pq.s
  357. result = self.signal2.time_slice(t_start, t_stop)
  358. self.assertIsInstance(result, AnalogSignal)
  359. assert_neo_object_is_compliant(result)
  360. self.assertEqual(result.name, 'spam')
  361. self.assertEqual(result.description, 'eggs')
  362. self.assertEqual(result.file_origin, 'testfile.txt')
  363. self.assertEqual(result.annotations, {'arg1': 'test'})
  364. targ = AnalogSignal(np.array([[2., 3.], [2., 3.]]).T,
  365. sampling_rate=1.0*pq.Hz, units='mV',
  366. t_start=t_start,
  367. name='spam', description='eggs',
  368. file_origin='testfile.txt', arg1='test')
  369. assert_neo_object_is_compliant(result)
  370. self.assertEqual(result.t_stop, t_stop)
  371. self.assertEqual(result.t_start, t_start)
  372. self.assertEqual(result.sampling_rate, targ.sampling_rate)
  373. assert_array_equal(result, targ)
  374. assert_same_sub_schema(result, targ)
  375. def test__time_slice__out_of_bounds_ValueError(self):
  376. t_start_good = 2 * pq.s
  377. t_stop_good = 4 * pq.s
  378. t_start_bad = -2 * pq.s
  379. t_stop_bad = 40 * pq.s
  380. self.assertRaises(ValueError, self.signal2.time_slice,
  381. t_start_good, t_stop_bad)
  382. self.assertRaises(ValueError, self.signal2.time_slice,
  383. t_start_bad, t_stop_good)
  384. self.assertRaises(ValueError, self.signal2.time_slice,
  385. t_start_bad, t_stop_bad)
  386. def test__time_equal(self):
  387. t_start = 0 * pq.s
  388. t_stop = 6 * pq.s
  389. result = self.signal2.time_slice(t_start, t_stop)
  390. self.assertIsInstance(result, AnalogSignal)
  391. assert_neo_object_is_compliant(result)
  392. self.assertEqual(result.name, 'spam')
  393. self.assertEqual(result.description, 'eggs')
  394. self.assertEqual(result.file_origin, 'testfile.txt')
  395. self.assertEqual(result.annotations, {'arg1': 'test'})
  396. self.assertEqual(result.t_stop, t_stop)
  397. self.assertEqual(result.t_start, t_start)
  398. assert_array_equal(result, self.signal2)
  399. assert_same_sub_schema(result, self.signal2)
  400. def test__time_slice__offset(self):
  401. self.signal2.t_start = 10.0 * pq.s
  402. assert_neo_object_is_compliant(self.signal2)
  403. t_start = 12 * pq.s
  404. t_stop = 14 * pq.s
  405. result = self.signal2.time_slice(t_start, t_stop)
  406. self.assertIsInstance(result, AnalogSignal)
  407. assert_neo_object_is_compliant(result)
  408. self.assertEqual(result.name, 'spam')
  409. self.assertEqual(result.description, 'eggs')
  410. self.assertEqual(result.file_origin, 'testfile.txt')
  411. self.assertEqual(result.annotations, {'arg1': 'test'})
  412. targ = AnalogSignal(np.array([[2., 3.], [2., 3.]]).T,
  413. t_start=12.0*pq.ms,
  414. sampling_rate=1.0*pq.Hz, units='mV',
  415. name='spam', description='eggs',
  416. file_origin='testfile.txt', arg1='test')
  417. assert_neo_object_is_compliant(result)
  418. self.assertEqual(self.signal2.t_start, 10.0 * pq.s)
  419. self.assertEqual(result.t_stop, t_stop)
  420. self.assertEqual(result.t_start, t_start)
  421. self.assertEqual(result.sampling_rate, targ.sampling_rate)
  422. assert_arrays_equal(result, targ)
  423. assert_same_sub_schema(result, targ)
  424. def test__time_slice__different_units(self):
  425. self.signal2.t_start = 10.0 * pq.ms
  426. assert_neo_object_is_compliant(self.signal2)
  427. t_start = 2 * pq.s + 10.0 * pq.ms
  428. t_stop = 4 * pq.s + 10.0 * pq.ms
  429. result = self.signal2.time_slice(t_start, t_stop)
  430. self.assertIsInstance(result, AnalogSignal)
  431. assert_neo_object_is_compliant(result)
  432. self.assertEqual(result.name, 'spam')
  433. self.assertEqual(result.description, 'eggs')
  434. self.assertEqual(result.file_origin, 'testfile.txt')
  435. self.assertEqual(result.annotations, {'arg1': 'test'})
  436. targ = AnalogSignal(np.array([[2., 3.], [2., 3.]]).T,
  437. t_start=t_start.rescale(pq.ms),
  438. sampling_rate=1.0*pq.Hz, units='mV',
  439. name='spam', description='eggs',
  440. file_origin='testfile.txt', arg1='test')
  441. assert_neo_object_is_compliant(result)
  442. assert_neo_object_is_compliant(self.signal2)
  443. self.assertEqual(self.signal2.t_start, 10.0 * pq.ms)
  444. self.assertAlmostEqual(result.t_stop, t_stop, delta=1e-12*pq.ms)
  445. self.assertAlmostEqual(result.t_start, t_start, delta=1e-12*pq.ms)
  446. assert_arrays_almost_equal(result.times, targ.times, 1e-12*pq.ms)
  447. self.assertEqual(result.sampling_rate, targ.sampling_rate)
  448. assert_arrays_equal(result, targ)
  449. assert_same_sub_schema(result, targ)
  450. def test__time_slice__no_explicit_time(self):
  451. self.signal2.t_start = 10.0 * pq.ms
  452. assert_neo_object_is_compliant(self.signal2)
  453. t1 = 2 * pq.s + 10.0 * pq.ms
  454. t2 = 4 * pq.s + 10.0 * pq.ms
  455. for t_start,t_stop in [(t1,None),(None,None),(None,t2)]:
  456. t_start_targ = t1 if t_start!=None else self.signal2.t_start
  457. t_stop_targ = t2 if t_stop!=None else self.signal2.t_stop
  458. result = self.signal2.time_slice(t_start, t_stop)
  459. self.assertIsInstance(result, AnalogSignal)
  460. assert_neo_object_is_compliant(result)
  461. self.assertEqual(result.name, 'spam')
  462. self.assertEqual(result.description, 'eggs')
  463. self.assertEqual(result.file_origin, 'testfile.txt')
  464. self.assertEqual(result.annotations, {'arg1': 'test'})
  465. targ_ind = np.where((self.signal2.times >= t_start_targ) &
  466. (self.signal2.times < t_stop_targ))
  467. targ_array = self.signal2.magnitude[targ_ind]
  468. targ = AnalogSignal(targ_array,
  469. t_start=t_start_targ.rescale(pq.ms),
  470. sampling_rate=1.0*pq.Hz, units='mV',
  471. name='spam', description='eggs',
  472. file_origin='testfile.txt', arg1='test')
  473. assert_neo_object_is_compliant(result)
  474. assert_neo_object_is_compliant(self.signal2)
  475. self.assertEqual(self.signal2.t_start, 10.0 * pq.ms)
  476. self.assertAlmostEqual(result.t_stop, t_stop_targ, delta=1e-12*pq.ms)
  477. self.assertAlmostEqual(result.t_start, t_start_targ, delta=1e-12*pq.ms)
  478. assert_arrays_almost_equal(result.times, targ.times, 1e-12*pq.ms)
  479. self.assertEqual(result.sampling_rate, targ.sampling_rate)
  480. assert_array_equal(result.magnitude, targ.magnitude)
  481. assert_same_sub_schema(result, targ)
  482. class TestAnalogSignalArrayEquality(unittest.TestCase):
  483. def test__signals_with_different_data_complement_should_be_not_equal(self):
  484. signal1 = AnalogSignal(np.arange(55.0).reshape((11, 5)),
  485. units="mV", sampling_rate=1*pq.kHz)
  486. signal2 = AnalogSignal(np.arange(55.0).reshape((11, 5)),
  487. units="mV", sampling_rate=2*pq.kHz)
  488. self.assertNotEqual(signal1, signal2)
  489. assert_neo_object_is_compliant(signal1)
  490. assert_neo_object_is_compliant(signal2)
  491. class TestAnalogSignalArrayCombination(unittest.TestCase):
  492. def setUp(self):
  493. self.data1 = np.arange(55.0).reshape((11, 5))
  494. self.data1quant = self.data1 * pq.mV
  495. self.signal1 = AnalogSignal(self.data1quant,
  496. sampling_rate=1*pq.kHz,
  497. name='spam', description='eggs',
  498. file_origin='testfile.txt',
  499. arg1='test')
  500. self.data2 = np.arange(100.0, 155.0).reshape((11, 5))
  501. self.data2quant = self.data2 * pq.mV
  502. self.signal2 = AnalogSignal(self.data2quant,
  503. sampling_rate=1*pq.kHz,
  504. name='spam', description='eggs',
  505. file_origin='testfile.txt',
  506. arg1='test')
  507. def test__compliant(self):
  508. assert_neo_object_is_compliant(self.signal1)
  509. self.assertEqual(self.signal1.name, 'spam')
  510. self.assertEqual(self.signal1.description, 'eggs')
  511. self.assertEqual(self.signal1.file_origin, 'testfile.txt')
  512. self.assertEqual(self.signal1.annotations, {'arg1': 'test'})
  513. assert_neo_object_is_compliant(self.signal2)
  514. self.assertEqual(self.signal2.name, 'spam')
  515. self.assertEqual(self.signal2.description, 'eggs')
  516. self.assertEqual(self.signal2.file_origin, 'testfile.txt')
  517. self.assertEqual(self.signal2.annotations, {'arg1': 'test'})
  518. def test__add_const_quantity_should_preserve_data_complement(self):
  519. result = self.signal1 + 0.065*pq.V
  520. self.assertIsInstance(result, AnalogSignal)
  521. assert_neo_object_is_compliant(result)
  522. self.assertEqual(result.name, 'spam')
  523. self.assertEqual(result.description, 'eggs')
  524. self.assertEqual(result.file_origin, 'testfile.txt')
  525. self.assertEqual(result.annotations, {'arg1': 'test'})
  526. # time zero, signal index 4
  527. assert_arrays_equal(result, self.data1 + 65)
  528. self.assertEqual(self.signal1[0, 4], 4*pq.mV)
  529. self.assertEqual(result[0, 4], 69000*pq.uV)
  530. self.assertEqual(self.signal1.t_start, result.t_start)
  531. self.assertEqual(self.signal1.sampling_rate, result.sampling_rate)
  532. def test__add_two_consistent_signals_should_preserve_data_complement(self):
  533. result = self.signal1 + self.signal2
  534. self.assertIsInstance(result, AnalogSignal)
  535. assert_neo_object_is_compliant(result)
  536. self.assertEqual(result.name, 'spam')
  537. self.assertEqual(result.description, 'eggs')
  538. self.assertEqual(result.file_origin, 'testfile.txt')
  539. self.assertEqual(result.annotations, {'arg1': 'test'})
  540. targdata = np.arange(100.0, 210.0, 2.0).reshape((11, 5))
  541. targ = AnalogSignal(targdata, units="mV",
  542. sampling_rate=1*pq.kHz,
  543. name='spam', description='eggs',
  544. file_origin='testfile.txt', arg1='test')
  545. assert_neo_object_is_compliant(targ)
  546. assert_arrays_equal(result, targdata)
  547. assert_same_sub_schema(result, targ)
  548. def test__add_signals_with_inconsistent_data_complement_ValueError(self):
  549. self.signal2.sampling_rate = 0.5*pq.kHz
  550. assert_neo_object_is_compliant(self.signal2)
  551. self.assertRaises(ValueError, self.signal1.__add__, self.signal2)
  552. def test__subtract_const_should_preserve_data_complement(self):
  553. result = self.signal1 - 65*pq.mV
  554. self.assertIsInstance(result, AnalogSignal)
  555. assert_neo_object_is_compliant(result)
  556. self.assertEqual(result.name, 'spam')
  557. self.assertEqual(result.description, 'eggs')
  558. self.assertEqual(result.file_origin, 'testfile.txt')
  559. self.assertEqual(result.annotations, {'arg1': 'test'})
  560. self.assertEqual(np.array(self.signal1[1, 4]), 9)
  561. self.assertEqual(np.array(result[1, 4]), -56)
  562. assert_arrays_equal(result, self.data1 - 65)
  563. self.assertEqual(self.signal1.sampling_rate, result.sampling_rate)
  564. def test__subtract_from_const_should_return_signal(self):
  565. result = 10*pq.mV - self.signal1
  566. self.assertIsInstance(result, AnalogSignal)
  567. assert_neo_object_is_compliant(result)
  568. self.assertEqual(result.name, 'spam')
  569. self.assertEqual(result.description, 'eggs')
  570. self.assertEqual(result.file_origin, 'testfile.txt')
  571. self.assertEqual(result.annotations, {'arg1': 'test'})
  572. self.assertEqual(np.array(self.signal1[1, 4]), 9)
  573. self.assertEqual(np.array(result[1, 4]), 1)
  574. assert_arrays_equal(result, 10 - self.data1)
  575. self.assertEqual(self.signal1.sampling_rate, result.sampling_rate)
  576. def test__mult_by_const_float_should_preserve_data_complement(self):
  577. result = self.signal1*2
  578. self.assertIsInstance(result, AnalogSignal)
  579. assert_neo_object_is_compliant(result)
  580. self.assertEqual(result.name, 'spam')
  581. self.assertEqual(result.description, 'eggs')
  582. self.assertEqual(result.file_origin, 'testfile.txt')
  583. self.assertEqual(result.annotations, {'arg1': 'test'})
  584. self.assertEqual(np.array(self.signal1[1, 4]), 9)
  585. self.assertEqual(np.array(result[1, 4]), 18)
  586. assert_arrays_equal(result, self.data1*2)
  587. self.assertEqual(self.signal1.sampling_rate, result.sampling_rate)
  588. def test__divide_by_const_should_preserve_data_complement(self):
  589. result = self.signal1/0.5
  590. self.assertIsInstance(result, AnalogSignal)
  591. assert_neo_object_is_compliant(result)
  592. self.assertEqual(result.name, 'spam')
  593. self.assertEqual(result.description, 'eggs')
  594. self.assertEqual(result.file_origin, 'testfile.txt')
  595. self.assertEqual(result.annotations, {'arg1': 'test'})
  596. self.assertEqual(np.array(self.signal1[1, 4]), 9)
  597. self.assertEqual(np.array(result[1, 4]), 18)
  598. assert_arrays_equal(result, self.data1/0.5)
  599. self.assertEqual(self.signal1.sampling_rate, result.sampling_rate)
  600. def test__merge(self):
  601. self.signal1.description = None
  602. self.signal1.file_origin = None
  603. assert_neo_object_is_compliant(self.signal1)
  604. data3 = np.arange(1000.0, 1066.0).reshape((11, 6)) * pq.uV
  605. data3scale = data3.rescale(self.data1quant.units)
  606. signal2 = AnalogSignal(self.data1quant,
  607. sampling_rate=1*pq.kHz,
  608. name='signal2',
  609. description='test signal',
  610. file_origin='testfile.txt')
  611. signal3 = AnalogSignal(data3,
  612. units="uV", sampling_rate=1*pq.kHz,
  613. name='signal3',
  614. description='test signal',
  615. file_origin='testfile.txt')
  616. signal4 = AnalogSignal(data3,
  617. units="uV", sampling_rate=1*pq.kHz,
  618. name='signal4',
  619. description='test signal',
  620. file_origin='testfile.txt')
  621. merged13 = self.signal1.merge(signal3)
  622. merged23 = signal2.merge(signal3)
  623. merged24 = signal2.merge(signal4)
  624. mergeddata13 = np.array(merged13)
  625. mergeddata23 = np.array(merged23)
  626. mergeddata24 = np.array(merged24)
  627. targdata13 = np.hstack([self.data1quant, data3scale])
  628. targdata23 = np.hstack([self.data1quant, data3scale])
  629. targdata24 = np.hstack([self.data1quant, data3scale])
  630. assert_neo_object_is_compliant(signal2)
  631. assert_neo_object_is_compliant(signal3)
  632. assert_neo_object_is_compliant(merged13)
  633. assert_neo_object_is_compliant(merged23)
  634. assert_neo_object_is_compliant(merged24)
  635. self.assertEqual(merged13[0, 4], 4*pq.mV)
  636. self.assertEqual(merged23[0, 4], 4*pq.mV)
  637. self.assertEqual(merged13[0, 5], 1*pq.mV)
  638. self.assertEqual(merged23[0, 5], 1*pq.mV)
  639. self.assertEqual(merged13[10, 10], 1.065*pq.mV)
  640. self.assertEqual(merged23[10, 10], 1.065*pq.mV)
  641. self.assertEqual(merged13.t_stop, self.signal1.t_stop)
  642. self.assertEqual(merged23.t_stop, self.signal1.t_stop)
  643. self.assertEqual(merged13.name, 'merge(spam, signal3)')
  644. self.assertEqual(merged23.name, 'merge(signal2, signal3)')
  645. self.assertEqual(merged13.description, 'merge(None, test signal)')
  646. self.assertEqual(merged23.description, 'test signal')
  647. self.assertEqual(merged13.file_origin, 'merge(None, testfile.txt)')
  648. self.assertEqual(merged23.file_origin, 'testfile.txt')
  649. assert_arrays_equal(mergeddata13, targdata13)
  650. assert_arrays_equal(mergeddata23, targdata23)
  651. assert_arrays_equal(mergeddata24, targdata24)
  652. class TestAnalogSignalArrayFunctions(unittest.TestCase):
  653. def test__pickle(self):
  654. signal1 = AnalogSignal(np.arange(55.0).reshape((11, 5)),
  655. units="mV", sampling_rate=1*pq.kHz)
  656. fobj = open('./pickle', 'wb')
  657. pickle.dump(signal1, fobj)
  658. fobj.close()
  659. fobj = open('./pickle', 'rb')
  660. try:
  661. signal2 = pickle.load(fobj)
  662. except ValueError:
  663. signal2 = None
  664. assert_array_equal(signal1, signal2)
  665. assert_neo_object_is_compliant(signal1)
  666. assert_neo_object_is_compliant(signal2)
  667. fobj.close()
  668. os.remove('./pickle')
  669. if __name__ == "__main__":
  670. unittest.main()