def setUp(self): # create a random noise signal with 50 epochs, 100 samples, and # 2 sources # even epochs and source 0: *= 5 # odd epochs and source 1: *= 5 self.s = np.random.randn(self.EPOCHS, self.SAMPLES, self.SOURCES) self.s[::2, :, 0] *= 5 self.s[1::2, :, 1] *= 5 # the mixmatrix which converts our sources to channels # X = As + noise self.A = np.random.randn(self.CHANNELS, self.SOURCES) # our 'signal' which 50 epochs, 100 samples and 10 channels self.X = np.empty((self.EPOCHS, self.SAMPLES, self.CHANNELS)) for i in range(self.EPOCHS): self.X[i] = np.dot(self.A, self.s[i].T).T noise = np.random.randn(self.EPOCHS, self.SAMPLES, self.CHANNELS) * 0.01 self.X += noise a = np.array([1 for i in range(self.X.shape[0])]) a[0::2] = 0 axes = [a, np.arange(self.X.shape[1]), np.arange(self.X.shape[2])] self.epo = Data(self.X, axes=axes, names=['class', 'time', 'channel'], units=['#', 'ms', '#']) self.epo.class_names = ['foo', 'bar'] self.filter = np.random.random((self.CHANNELS, self.CHANNELS))
def setUp(self): # generate sources with independent variance modulations, the # first source will be the target source z = np.abs(np.random.randn(self.EPOCHS, self.SOURCES)) for i in range(self.SOURCES): z[:, i] /= z[:, i].std() self.s = np.random.randn(self.EPOCHS, self.SAMPLES, self.SOURCES) for i in range(self.SOURCES): for j in range(self.EPOCHS): self.s[j, :, i] *= z[j, i] # the mixmatrix which converts our sources to channels # X = As + noise self.A = np.random.randn(self.CHANNELS, self.SOURCES) # our 'signal' which 50 epochs, 100 samples and 10 channels self.X = np.empty((self.EPOCHS, self.SAMPLES, self.CHANNELS)) for i in range(self.EPOCHS): self.X[i] = np.dot(self.A, self.s[i].T).T noise = np.random.randn(self.EPOCHS, self.SAMPLES, self.CHANNELS) * 0.01 self.X += noise # convert to epo axes = [ z[:, 0], np.arange(self.X.shape[1]), np.arange(self.X.shape[2]) ] self.epo = Data(self.X, axes=axes, names=['target_variable', 'time', 'channel'], units=['#', 'ms', '#'])
def setUp(self): data = np.random.randn(SAMPLES, CHANS) data[:, 1] += 0.5 * data[:, 0] data[:, 2] -= 0.5 * data[:, 0] t = np.arange(SAMPLES) chans = ['chan{i}'.format(i=i) for i in range(CHANS)] self.cnt = Data(data, [t, chans], ['time', 'channels'], ['ms', '#'])
def test_eq_and_ne(self): """Check if __ne__ is properly implemented.""" d1 = Data(self.data, self.axes, self.names, self.units) d2 = d1.copy() # if __eq__ is implemented and __ne__ is not, this evaluates to # True! self.assertFalse(d1 == d2 and d1 != d2)
def test_correct_classlabels(self): """lda_train must throw an error if the class labels are not exactly [0, 1].""" data = np.random.random((50, 100)) labels = np.zeros(50) # only 0s -> fail fv = Data(data=data, axes=[labels, np.arange(100)], units=['x', 'y'], names=['foo', 'bar']) with self.assertRaises(ValueError): lda_train(fv) # 0s and 1s -> ok labels[1] = 1 fv = Data(data=data, axes=[labels, np.arange(100)], units=['x', 'y'], names=['foo', 'bar']) try: lda_train(fv) except ValueError: self.fail() # 0s, 1s, and 2s -> fail labels[2] = 2 fv = Data(data=data, axes=[labels, np.arange(100)], units=['x', 'y'], names=['foo', 'bar']) with self.assertRaises(ValueError): lda_train(fv)
def convert_mushu_data(data, markers, fs, channels): """Convert mushu data into wyrm's ``Data`` format. This convenience method creates a continuous ``Data`` object from the parameters given. The timeaxis always starts from zero and its values are calculated from the sampling frequency ``fs`` and the length of ``data``. The ``names`` and ``units`` attributes are filled with default vaules. Parameters ---------- data : 2d array an 2 dimensional numpy array with the axes: (time, channel) markers : list of tuples: (float, str) a list of markers. Each element is a tuple of timestamp and string. The timestamp is the time in ms relative to the onset of the block of data. Note that negative values are *allowed* as well as values bigger than the length of the block of data returned. That is to be interpreted as a marker from the last block and a marker for a future block respectively. fs : float the sampling frequency, this number is used to calculate the timeaxis for the data channels : list or 1d array of strings the channel names Returns ------- cnt : continuous ``Data`` object Examples -------- Assuming that ``amp`` is an Amplifier instance from ``libmushu``, already configured but not started yet: >>> amp_fs = amp.get_sampling_frequency() >>> amp_channels = amp.get_channels() >>> amp.start() >>> while True: ... data, markers = amp.get_data() ... cnt = convert_mushu_data(data, markers, amp_fs, amp_channels) ... # some more code >>> amp.stop() References ---------- https://github.com/bbci/mushu """ time_axis = np.linspace(0, 1000 * data.shape[0] / fs, data.shape[0], endpoint=False) chan_axis = channels[:] axes = [time_axis, chan_axis] names = ['time', 'channel'] units = ['uV', '#'] cnt = Data(data=data.copy(), axes=axes, names=names, units=units) cnt.markers = markers[:] cnt.fs = fs return cnt
class TestClearMarkers(unittest.TestCase): def setUp(self): ones = np.ones((10, 5)) # cnt with 1, 2, 3 cnt = np.append(ones, ones * 2, axis=0) cnt = np.append(cnt, ones * 3, axis=0) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(-1000, 2000, 30, endpoint=False) self.good_markers = [[-1000, 'a'], [-999, 'b'], [0, 'c'], [1999.9999999, 'd']] bad_markers = [[-1001, 'x'], [2000, 'x']] markers = self.good_markers[:] markers.extend(bad_markers) classes = [0, 1, 2, 1] # four cnts: 1s, -1s, and 0s data = np.array([cnt * 0, cnt * 1, cnt * 2, cnt * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#']) self.dat.markers = markers self.dat.fs = 10 def test_clear_markers(self): """Clear markers.""" dat = clear_markers(self.dat) self.assertEqual(dat.markers, self.good_markers) def test_clear_emtpy_markers(self): """Clearing emtpy markers has no effect.""" dat = self.dat.copy() dat.markers = [] dat2 = clear_markers(dat) self.assertEqual(dat, dat2) def test_clear_nonexisting_markers(self): """Clearing emtpy markers has no effect.""" dat = self.dat.copy() del dat.markers dat2 = clear_markers(dat) self.assertEqual(dat, dat2) def test_clear_markers_w_empty_data(self): """Clearing emtpy dat should remove all markers.""" dat = self.dat.copy() dat.data = np.array([]) dat2 = clear_markers(dat) self.assertEqual(dat2.markers, []) def test_clear_markes_swapaxes(self): """clear_markers must work with nonstandard timeaxis.""" dat = clear_markers(swapaxes(self.dat, 1, 2), timeaxis=2) dat = swapaxes(dat, 1, 2) dat2 = clear_markers(self.dat) self.assertEqual(dat, dat2) def test_clear_markers_copy(self): """clear_markers must not modify argument.""" cpy = self.dat.copy() clear_markers(self.dat) self.assertEqual(self.dat, cpy)
class TestClearMarkers(unittest.TestCase): def setUp(self): ones = np.ones((10, 5)) # cnt with 1, 2, 3 cnt = np.append(ones, ones*2, axis=0) cnt = np.append(cnt, ones*3, axis=0) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(-1000, 2000, 30, endpoint=False) self.good_markers = [[-1000, 'a'], [-999, 'b'], [0, 'c'], [1999.9999999, 'd']] bad_markers = [[-1001, 'x'], [2000, 'x']] markers = self.good_markers[:] markers.extend(bad_markers) classes = [0, 1, 2, 1] # four cnts: 1s, -1s, and 0s data = np.array([cnt * 0, cnt * 1, cnt * 2, cnt * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#']) self.dat.markers = markers self.dat.fs = 10 def test_clear_markers(self): """Clear markers.""" dat = clear_markers(self.dat) self.assertEqual(dat.markers, self.good_markers) def test_clear_emtpy_markers(self): """Clearing emtpy markers has no effect.""" dat = self.dat.copy() dat.markers = [] dat2 = clear_markers(dat) self.assertEqual(dat, dat2) def test_clear_nonexisting_markers(self): """Clearing emtpy markers has no effect.""" dat = self.dat.copy() del dat.markers dat2 = clear_markers(dat) self.assertEqual(dat, dat2) def test_clear_markers_w_empty_data(self): """Clearing emtpy dat should remove all markers.""" dat = self.dat.copy() dat.data = np.array([]) dat2 = clear_markers(dat) self.assertEqual(dat2.markers, []) def test_clear_markes_swapaxes(self): """clear_markers must work with nonstandard timeaxis.""" dat = clear_markers(swapaxes(self.dat, 1, 2), timeaxis=2) dat = swapaxes(dat, 1, 2) dat2 = clear_markers(self.dat) self.assertEqual(dat, dat2) def test_clear_markers_copy(self): """clear_markers must not modify argument.""" cpy = self.dat.copy() clear_markers(self.dat) self.assertEqual(self.dat, cpy)
def setUp(self): ones = np.ones((10, 5)) # epo with 0, 1, 2 data = np.array([0 * ones, ones, 2 * ones]) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 1000, 10, endpoint=False) classes = [0, 1, 2] self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#'])
def setUp(self): self.empty_dat = Data(np.array([]), [], [], []) self.dat_1 = Data( np.array([0, 0])[np.newaxis, :], [np.array([0]), np.array(['ch1', 'ch2'])], ['time', 'channel'], ['ms', '#']) self.dat_1.fs = 1000 self.dat_1.markers = [[0, 'x']] self.dat_5 = reduce(append_cnt, [self.dat_1 for i in range(5)])
def setUp(self): ones = np.ones((10, 5)) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(-1000, 0, 10, endpoint=False) classes = [0, 0, 0] # three cnts: 1s, -1s, and 0s data = np.array([ones, ones * -1, ones * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#']) self.dat.fs = 10
def setUp(self): ones = np.ones((10, 5)) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 1000, 10, endpoint=False) classes = [0, 1, 2, 1] class_names = ['zeros', 'ones', 'twoes'] # four cnts: 0s, 1s, -1s, and 0s data = np.array([ones * 0, ones * 1, ones * 2, ones * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#']) self.dat.class_names = class_names
def setUp(self): ones = np.ones((10, 5)) # three blocks: 1s, -1s, and 0s cnt_data = np.concatenate([ones, -ones, 0 * ones], axis=0) classes = [0, 0, 0] channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(-1000, 2000, 30, endpoint=False) epo_data = np.array([cnt_data, cnt_data, cnt_data]) self.dat = Data(epo_data, [classes, time, channels], ['class', 'time', 'channels'], ['#', 'ms', '#'])
def setUp(self): raw = np.arange(2000).reshape(-1, 5) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 4000, 400, endpoint=False) fs = 100 marker = [[100, 'foo'], [200, 'bar']] self.dat = Data(raw, [time, channels], ['time', 'channels'], ['ms', '#']) self.dat.fs = fs self.dat.markers = marker
def test_copy(self): """Copy must work.""" d1 = Data(self.data, self.axes, self.names, self.units) d2 = d1.copy() self.assertEqual(d1, d2) # we can't really check of all references to be different in # depth recursively, so we only check on the first level for k in d1.__dict__: self.assertNotEqual(id(getattr(d1, k)), id(getattr(d2, k))) d2 = d1.copy(foo='bar') self.assertEqual(d2.foo, 'bar')
def setUp(self): ones = np.ones((10, 5)) # cnt with 1, 2, 3 cnt = np.append(ones, ones * 2, axis=0) cnt = np.append(cnt, ones * 3, axis=0) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 3000, 30, endpoint=False) self.dat = Data(cnt, [time, channels], ['time', 'channel'], ['ms', '#']) self.dat.markers = [[0, 'a'], [1, 'b']] self.dat.fs = 10
def setUp(self): # create epoched data with only 0s in class0, 1s in class1 and # 2s in class2 cnt = np.ones((10, 3)) epo = np.array([0 * cnt, 1 * cnt, 2 * cnt]) time = np.arange(10) channels = np.array(['ch1', 'ch2', 'ch3']) classes = np.arange(3) axes = ['class', 'time', 'channel'] units = ['#', 'ms', '#'] self.dat = Data(epo, [classes, time, channels], axes, units)
def setUp(self): # create 100 samples and tree channels data ones = np.ones((100, 3)) data = np.array([ones, ones * 2, ones * 3]).reshape(-1, 3) time = np.linspace(0, 3000, 300, endpoint=False) channels = ['a', 'b', 'c'] markers = [[500, 'M1'], [1500, 'M2'], [2500, 'M3']] self.dat = Data(data, [time, channels], ['time', 'channels'], ['ms', '#']) self.dat.markers = markers self.dat.fs = 100 self.mrk_def = {'class 1': ['M1'], 'class 2': ['M2', 'M3']}
def setUp(self): ones = np.ones((10, 2)) twoes = ones * 2 # 7 epochs data = np.array([ones, ones, twoes, twoes, ones, twoes, twoes]) channels = ['c1', 'c2'] time = np.linspace(0, 1000, 10) classes = [0, 0, 1, 1, 0, 1, 1] class_names = ['ones', 'twoes'] self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#']) self.dat.class_names = class_names
def setUp(self): ones = np.ones((10, 5)) # cnt with 1, 2, 3 cnt = np.append(ones, ones*2, axis=0) cnt = np.append(cnt, ones*3, axis=0) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 3000, 30, endpoint=False) classes = [0, 1, 2, 1] # four cnts: 1s, -1s, and 0s data = np.array([cnt * 0, cnt * 1, cnt * 2, cnt * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#']) self.dat.class_names = ['zero', 'one', 'two']
class TestAppendEpo(unittest.TestCase): def setUp(self): ones = np.ones((10, 5)) # cnt with 1, 2, 3 cnt = np.append(ones, ones*2, axis=0) cnt = np.append(cnt, ones*3, axis=0) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 3000, 30, endpoint=False) classes = [0, 1, 2, 1] # four cnts: 1s, -1s, and 0s data = np.array([cnt * 0, cnt * 1, cnt * 2, cnt * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#']) self.dat.class_names = ['zero', 'one', 'two'] def test_append_epo(self): """append_epo.""" dat = append_epo(self.dat, self.dat) self.assertEqual(dat.data.shape[0], 2*self.dat.data.shape[0]) self.assertEqual(len(dat.axes[0]), 2*len(self.dat.axes[0])) np.testing.assert_array_equal(dat.data, np.concatenate([self.dat.data, self.dat.data], axis=0)) np.testing.assert_array_equal(dat.axes[0], np.concatenate([self.dat.axes[0], self.dat.axes[0]])) self.assertEqual(dat.class_names, self.dat.class_names) def test_append_epo_with_extra(self): """append_epo with extra must work with list and ndarrays.""" self.dat.a = list(range(10)) self.dat.b = np.arange(10) dat = append_epo(self.dat, self.dat, extra=['a', 'b']) self.assertEqual(dat.a, list(range(10)) + list(range(10))) np.testing.assert_array_equal(dat.b, np.concatenate([np.arange(10), np.arange(10)])) def test_append_epo_with_different_class_names(self): """test_append must raise a ValueError if class_names are different.""" a = self.dat.copy() a.class_names = a.class_names[:-1] with self.assertRaises(ValueError): append_epo(a, self.dat) append_epo(self.dat, a) def test_append_epo_swapaxes(self): """append_epo must work with nonstandard timeaxis.""" dat = append_epo(swapaxes(self.dat, 0, 2), swapaxes(self.dat, 0, 2), classaxis=2) dat = swapaxes(dat, 0, 2) dat2 = append_epo(self.dat, self.dat) self.assertEqual(dat, dat2) def test_append_epo_copy(self): """append_epo means must not modify argument.""" cpy = self.dat.copy() append_epo(self.dat, self.dat) self.assertEqual(self.dat, cpy)
def load_mushu_data(meta): """Load saved EEG data in Mushu's format. This method loads saved data in Mushu's format and returns a continuous ``Data`` object. Parameters ---------- meta : str Path to `.meta` file. A Mushu recording consists of three different files: `.eeg`, `.marker`, and `.meta`. Returns ------- dat : Data Continuous Data object Examples -------- >>> dat = load_mushu_data('testrecording.meta') """ # reverse and replace and reverse again to replace only the last # (occurrence of .meta) datafile = meta[::-1].replace('atem.', 'gee.', 1)[::-1] markerfile = meta[::-1].replace('atem.', 'rekram.', 1)[::-1] assert path.exists(meta) and path.exists(datafile) and path.exists( markerfile) # load meta data with open(meta) as fh: metadata = json.load(fh) fs = metadata['Sampling Frequency'] channels = np.array(metadata['Channels']) # load eeg data data = np.fromfile(datafile, np.float32) data = data.reshape((-1, len(channels))) # load markers markers = [] with open(markerfile) as fh: for line in fh: ts, m = line.split(' ', 1) markers.append([float(ts), str(m).strip()]) # construct Data duration = len(data) * 1000 / fs axes = [np.linspace(0, duration, len(data), endpoint=False), channels] names = ['time', 'channels'] units = ['ms', '#'] dat = Data(data=data, axes=axes, names=names, units=units) dat.fs = fs dat.markers = markers return dat
def setUp(self): # create some data fs = 100 dt = 5 self.freqs = [2, 7, 15] amps = [30, 10, 2] t = np.linspace(0, dt, fs*dt) data = np.sum([a * np.sin(2*np.pi*t*f) for a, f in zip(amps, self.freqs)], axis=0) data = data[:, np.newaxis] data = np.concatenate([data, data], axis=1) channel = np.array(['ch1', 'ch2']) self.dat = Data(data, [t, channel], ['time', 'channel'], ['s', '#']) self.dat.fs = fs
def setUp(self): self.sorted_channels = np.array([name for name, pos in CHANNEL_10_20]) channels = self.sorted_channels.copy() random.shuffle(channels) raw = np.random.random((5, 10, len(channels))) time = np.linspace(0, 1000, 10, endpoint=False) epochs = np.array([0, 1, 0, 1, 0]) fs = 100 marker = [[100, 'foo'], [200, 'bar']] self.dat = Data(raw, [epochs, time, channels], ['class', 'time', 'channels'], ['#', 'ms', '#']) self.dat.fs = fs self.dat.markers = marker
def setUp(self): dat = np.zeros((SAMPLES, CHANS)) # [-10, -9, ... 20) dat[:, 0] = np.arange(SAMPLES) - SAMPLES / 2 channels = ['chan{i}'.format(i=i) for i in range(CHANS)] time = np.arange(SAMPLES) self.cnt = Data(dat, [time, channels], ['time', 'channels'], ['ms', '#']) # construct epo epo_dat = np.array([dat + i for i in range(EPOS)]) classes = ['class{i}'.format(i=i) for i in range(EPOS)] self.epo = Data(epo_dat, [classes, time, channels], ['class', 'time', 'channels'], ['#', 'ms', '#'])
class TestCorrectForBaseline(unittest.TestCase): def setUp(self): ones = np.ones((10, 5)) classes = [0, 0, 0] channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(-1000, 0, 10, endpoint=False) # three cnts: 1s, -1s, and 0s data = np.array([ones, ones * -1, ones * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channels'], ['#', 'ms', '#']) def test_correct_for_baseline_epo(self): """Test baselineing w/ epo like.""" # normal case dat = correct_for_baseline(self.dat, [-500, 0]) np.testing.assert_array_equal(np.zeros((3, 10, 5)), dat.data) # the full dat interval dat = correct_for_baseline(self.dat, [dat.axes[-2][0], dat.axes[-2][-1]]) np.testing.assert_array_equal(np.zeros((3, 10, 5)), dat.data) def test_correct_for_baseline_cnt(self): """Test baselineing w/ cnt like.""" data = self.dat.data.reshape(30, 5) axes = [np.linspace(-1000, 2000, 30, endpoint=False), self.dat.axes[-1]] units = self.dat.units[1:] names = self.dat.names[1:] dat = self.dat.copy(data=data, axes=axes, names=names, units=units) dat2 = correct_for_baseline(dat, [-1000, 0]) np.testing.assert_array_equal(dat2.data, dat.data - 1) def test_ival_checks(self): """Test for malformed ival parameter.""" with self.assertRaises(AssertionError): correct_for_baseline(self.dat, [0, -1]) with self.assertRaises(AssertionError): correct_for_baseline(self.dat, [self.dat.axes[-2][0]-1, 0]) with self.assertRaises(AssertionError): correct_for_baseline(self.dat, [0, self.dat.axes[-2][1]+1]) def test_correct_for_baseline_copy(self): """Correct for baseline must not modify dat argument.""" cpy = self.dat.copy() correct_for_baseline(self.dat, [-1000, 0]) self.assertEqual(cpy, self.dat) def test_correct_for_baseline_swapaxes(self): """Correct for baseline must work with nonstandard timeaxis.""" dat = correct_for_baseline(swapaxes(self.dat, 0, 1), [-1000, 0], timeaxis=0) dat = swapaxes(dat, 0, 1) dat2 = correct_for_baseline(self.dat, [-1000, 0]) self.assertEqual(dat, dat2)
def load_mushu_data(meta): """Load saved EEG data in Mushu's format. This method loads saved data in Mushu's format and returns a continuous ``Data`` object. Parameters ---------- meta : str Path to `.meta` file. A Mushu recording consists of three different files: `.eeg`, `.marker`, and `.meta`. Returns ------- dat : Data Continuous Data object Examples -------- >>> dat = load_mushu_data('testrecording.meta') """ # reverse and replace and reverse again to replace only the last # (occurrence of .meta) datafile = meta[::-1].replace('atem.', 'gee.', 1)[::-1] markerfile = meta[::-1].replace('atem.', 'rekram.', 1)[::-1] assert path.exists(meta) and path.exists(datafile) and path.exists(markerfile) # load meta data with open(meta, 'r') as fh: metadata = json.load(fh) fs = metadata['Sampling Frequency'] channels = np.array(metadata['Channels']) # load eeg data data = np.fromfile(datafile, np.float32) data = data.reshape((-1, len(channels))) # load markers markers = [] with open(markerfile, 'r') as fh: for line in fh: ts, m = line.split(' ', 1) markers.append([float(ts), str(m).strip()]) # construct Data duration = len(data) * 1000 / fs axes = [np.linspace(0, duration, len(data), endpoint=False), channels] names = ['time', 'channels'] units = ['ms', '#'] dat = Data(data=data, axes=axes, names=names, units=units) dat.fs = fs dat.markers = markers return dat
def test_segment_dat_with_restriction_to_new_data_ival_pos_pos(self): """Online Segmentation with ival +something..+something must work correctly.""" data = np.ones((9, 3)) time = np.linspace(0, 900, 9, endpoint=False) channels = 'a', 'b', 'c' markers = [[100, 'x'], [200, 'x'], [300, 'x']] dat = Data(data, [time, channels], ['time', 'channels'], ['ms', '#']) dat.fs = 10 dat.markers = markers mrk_def = {'class 1': ['x']} # each tuple has (number of new samples, expected epocs) samples_epos = [(0, 0), (1, 0), (2, 1), (3, 2), (4, 3), (5, 3)] for s, e in samples_epos: epo = segment_dat(dat, mrk_def, [100, 500], newsamples=s) self.assertEqual(epo.data.shape[0], e)
def setUp(self): data = np.random.randn(SAMPLES, CHANS) data[:, 1] += 0.5 * data[:, 0] data[:, 2] -= 0.5 * data[:, 0] t = np.arange(SAMPLES) chans = ['chan{i}'.format(i=i) for i in range(CHANS)] self.cnt = Data(data, [t, chans], ['time', 'channels'], ['ms', '#']) # construct epo epo_dat = np.array([data for i in range(EPOS)]) classes = ['class{i}'.format(i=i) for i in range(EPOS)] self.epo = Data(epo_dat, [classes, t, chans], ['class', 'time', 'channels'], ['#', 'ms', '#']) # my little spatial filter self.w = np.array([[0, 0.5, 1], [-1, 0.5, 0], [1, 0.5, 0]])
class TestSwapaxes(unittest.TestCase): def setUp(self): raw = np.arange(2000).reshape(-1, 5) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 4000, 400, endpoint=False) fs = 100 marker = [[100, 'foo'], [200, 'bar']] self.dat = Data(raw, [time, channels], ['time', 'channels'], ['ms', '#']) self.dat.fs = fs self.dat.markers = marker def test_swapaxes(self): """Swapping axes.""" new = swapaxes(self.dat, 0, 1) self.assertTrue((new.axes[0] == self.dat.axes[1]).all()) self.assertTrue((new.axes[1] == self.dat.axes[0]).all()) self.assertEqual(new.names[0], self.dat.names[1]) self.assertEqual(new.names[1], self.dat.names[0]) self.assertEqual(new.units[0], self.dat.units[1]) self.assertEqual(new.units[1], self.dat.units[0]) self.assertEqual(new.data.shape[::-1], self.dat.data.shape) np.testing.assert_array_equal(new.data.swapaxes(0, 1), self.dat.data) def test_swapaxes_copy(self): """Swapaxes must not modify argument.""" cpy = self.dat.copy() swapaxes(self.dat, 0, 1) self.assertEqual(cpy, self.dat) def test_swapaxes_twice(self): """Swapping the same axes twice must result in original.""" dat = swapaxes(self.dat, 0, 1) dat = swapaxes(dat, 0, 1) self.assertEqual(dat, self.dat)
def setUp(self): # X is a random mixture matrix of random variables Sx = randn(self.SAMPLES, self.CHANNELS_X) Ax = randn(self.CHANNELS_X, self.CHANNELS_X) self.X = np.dot(Sx, Ax) # Y is a random mixture matrix of random variables except the # first component Sy = randn(self.SAMPLES, self.CHANNELS_Y) Sy[:, 0] = Sx[:, 0] + self.NOISE_LEVEL * randn(self.SAMPLES) Ay = randn(self.CHANNELS_Y, self.CHANNELS_Y) self.Y = np.dot(Sy, Ay) # generate Data object axes_x = [np.arange(self.X.shape[0]), np.arange(self.X.shape[1])] axes_y = [np.arange(self.Y.shape[0]), np.arange(self.Y.shape[1])] self.dat_x = Data(self.X, axes=axes_x, names=['time', 'channel'], units=['ms', '#']) self.dat_y = Data(self.Y, axes=axes_y, names=['time', 'channel'], units=['ms', '#'])
class TestSelectChannels(unittest.TestCase): def setUp(self): raw = np.arange(20).reshape(4, 5) channels = ["ca1", "ca2", "cb1", "cb2", "cc1"] time = np.arange(4) self.dat = Data(raw, [time, channels], ["time", "channels"], ["ms", "#"]) def test_select_channels(self): """Selecting channels with an array of regexes.""" channels = self.dat.data.copy() self.dat = select_channels(self.dat, ["ca.*", "cc1"]) np.testing.assert_array_equal(self.dat.axes[-1], np.array(["ca1", "ca2", "cc1"])) np.testing.assert_array_equal(self.dat.data, channels[:, np.array([0, 1, -1])]) def test_select_channels_inverse(self): """Removing channels with an array of regexes.""" channels = self.dat.data.copy() self.dat = select_channels(self.dat, ["ca.*", "cc1"], invert=True) np.testing.assert_array_equal(self.dat.axes[-1], np.array(["cb1", "cb2"])) np.testing.assert_array_equal(self.dat.data, channels[:, np.array([2, 3])]) def test_select_channels_copy(self): """Select channels must not change the original parameter.""" cpy = self.dat.copy() select_channels(self.dat, ["ca.*"]) self.assertEqual(cpy, self.dat) def test_select_channels_swapaxis(self): """Select channels works with non default chanaxis.""" dat1 = select_channels(swapaxes(self.dat, 0, 1), ["ca.*"], chanaxis=0) dat1 = swapaxes(dat1, 0, 1) dat2 = select_channels(self.dat, ["ca.*"]) self.assertEqual(dat1, dat2)
def setUp(self): # generate sources with independent variance modulations, the # first source will be the target source z = np.abs(np.random.randn(self.EPOCHS, self.SOURCES)) for i in range(self.SOURCES): z[:, i] /= z[:, i].std() self.s = np.random.randn(self.EPOCHS, self.SAMPLES, self.SOURCES) for i in range(self.SOURCES): for j in range(self.EPOCHS): self.s[j, :, i] *= z[j, i] # the mixmatrix which converts our sources to channels # X = As + noise self.A = np.random.randn(self.CHANNELS, self.SOURCES) # our 'signal' which 50 epochs, 100 samples and 10 channels self.X = np.empty((self.EPOCHS, self.SAMPLES, self.CHANNELS)) for i in range(self.EPOCHS): self.X[i] = np.dot(self.A, self.s[i].T).T noise = np.random.randn(self.EPOCHS, self.SAMPLES, self.CHANNELS) * 0.01 self.X += noise # convert to epo axes = [z[:, 0], np.arange(self.X.shape[1]), np.arange(self.X.shape[2])] self.epo = Data(self.X, axes=axes, names=['target_variable', 'time', 'channel'], units=['#', 'ms', '#'])
def setUp(self): # X is a random mixture matrix of random variables Sx = randn(self.SAMPLES, self.CHANNELS_X) Ax = randn(self.CHANNELS_X, self.CHANNELS_X) X = np.dot(Sx, Ax) # Y is a random mixture matrix of random variables except the # first component Sy = randn(self.SAMPLES, self.CHANNELS_Y) Sy[:, 0] = Sx[:, 0] + self.NOISE_LEVEL * randn(self.SAMPLES) Ay = randn(self.CHANNELS_Y, self.CHANNELS_Y) Y = np.dot(Sy, Ay) # generate Data object axes_x = [np.arange(X.shape[0]), np.arange(X.shape[1])] axes_y = [np.arange(Y.shape[0]), np.arange(Y.shape[1])] self.dat_x = Data(X, axes=axes_x, names=['time', 'channel'], units=['ms', '#']) self.dat_y = Data(Y, axes=axes_y, names=['time', 'channel'], units=['ms', '#'])
def setUp(self): # create a random noise signal with 50 epochs, 100 samples, and # 2 sources # even epochs and source 0: *= 5 # odd epochs and source 1: *= 5 self.s = np.random.randn(self.EPOCHS, self.SAMPLES, self.SOURCES) self.s[ ::2, :, 0] *= 5 self.s[1::2, :, 1] *= 5 # the mixmatrix which converts our sources to channels # X = As + noise self.A = np.random.randn(self.CHANNELS, self.SOURCES) # our 'signal' which 50 epochs, 100 samples and 10 channels self.X = np.empty((self.EPOCHS, self.SAMPLES, self.CHANNELS)) for i in range(self.EPOCHS): self.X[i] = np.dot(self.A, self.s[i].T).T noise = np.random.randn(self.EPOCHS, self.SAMPLES, self.CHANNELS) * 0.01 self.X += noise a = np.array([1 for i in range(self.X.shape[0])]) a[0::2] = 0 axes = [a, np.arange(self.X.shape[1]), np.arange(self.X.shape[2])] self.epo = Data(self.X, axes=axes, names=['class', 'time', 'channel'], units=['#', 'ms', '#']) self.epo.class_names = ['foo', 'bar'] self.filter = np.random.random((self.CHANNELS, self.CHANNELS))
def setUp(self): data = np.arange(10).reshape(5, 2) axes = [np.arange(5), np.array(['ch1', 'ch2'])] names = ['time', 'channel'] units = ['ms', '#'] fs = 1000 self.dat = Data(data, axes, names, units) self.dat.fs = fs
def setUp(self): ones = np.ones((10, 5)) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(-1000, 0, 10, endpoint=False) classes = [0, 0, 0] # three cnts: 1s, -1s, and 0s data = np.array([ones, ones * -1, ones * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#'])
def test_init_with_inconsistent_values(self): """Test init with inconsistent values.""" data = self.data[np.newaxis, :] with self.assertRaises(AssertionError): Data(data, self.axes, self.names, self.units) axes = self.axes[:] axes[0] = np.arange(100) with self.assertRaises(AssertionError): Data(self.data, axes, self.names, self.units) names = self.names[:] names.append('baz') with self.assertRaises(AssertionError): Data(self.data, self.axes, names, self.units) units = self.units[:] units.append('u3') with self.assertRaises(AssertionError): Data(self.data, self.axes, self.names, units)
def test_raise_error_with_non_continuous_data(self): """Raise error if ``dat_x`` is not continuous Data object.""" dat = Data(randn(2, self.SAMPLES, self.CHANNELS_X), axes=[[0, 1], self.dat_x.axes[0], self.dat_x.axes[1]], names=['class', 'time', 'channel'], units=['#', 'ms', '#']) with self.assertRaises(AssertionError): calculate_cca(dat, self.dat_x)
def setUp(self): ones = np.ones((10, 5)) # epo with 0, 1, 2 data = np.array([0*ones, ones, 2*ones]) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 1000, 10, endpoint=False) classes = [0, 1, 2] self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#'])
class TestSelectEpochs(unittest.TestCase): def setUp(self): ones = np.ones((10, 5)) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 1000, 10, endpoint=False) classes = [0, 1, 2, 1] class_names = ['zeros', 'ones', 'twoes'] # four cnts: 0s, 1s, -1s, and 0s data = np.array([ones * 0, ones * 1, ones * 2, ones * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#']) self.dat.class_names = class_names def test_select_epochs(self): """Selecting Epochs.""" # normal case dat = select_epochs(self.dat, [0]) self.assertEqual(dat.data.shape[0], 1) np.testing.assert_array_equal(dat.data, self.dat.data[[0]]) np.testing.assert_array_equal(dat.axes[0], self.dat.axes[0][0]) # normal every second dat = select_epochs(self.dat, [0, 2]) self.assertEqual(dat.data.shape[0], 2) np.testing.assert_array_equal(dat.data, self.dat.data[::2]) np.testing.assert_array_equal(dat.axes[0], self.dat.axes[0][::2]) # the full epo dat = select_epochs(self.dat, list(range(self.dat.data.shape[0]))) np.testing.assert_array_equal(dat.data, self.dat.data) np.testing.assert_array_equal(dat.axes[0], self.dat.axes[0]) # remove one dat = select_epochs(self.dat, [0], invert=True) self.assertEqual(dat.data.shape[0], 3) np.testing.assert_array_equal(dat.data, self.dat.data[1:]) np.testing.assert_array_equal(dat.axes[0], self.dat.axes[0][1:]) # remove every second dat = select_epochs(self.dat, [0, 2], invert=True) self.assertEqual(dat.data.shape[0], 2) np.testing.assert_array_equal(dat.data, self.dat.data[1::2]) np.testing.assert_array_equal(dat.axes[0], self.dat.axes[0][1::2]) def test_select_epochs_with_cnt(self): """Select epochs must raise an exception if called with cnt argument.""" del(self.dat.class_names) with self.assertRaises(AssertionError): select_epochs(self.dat, [0, 1]) def test_select_epochs_swapaxes(self): """Select epochs must work with nonstandard classaxis.""" dat = select_epochs(swapaxes(self.dat, 0, 2), [0, 1], classaxis=2) dat = swapaxes(dat, 0, 2) dat2 = select_epochs(self.dat, [0, 1]) self.assertEqual(dat, dat2) def test_select_epochs_copy(self): """Select Epochs must not modify argument.""" cpy = self.dat.copy() select_epochs(self.dat, [0, 1]) self.assertEqual(self.dat, cpy)
def setUp(self): ones = np.ones((10, 5)) # cnt with 1, 2, 3 cnt = np.append(ones, ones*2, axis=0) cnt = np.append(cnt, ones*3, axis=0) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 3000, 30, endpoint=False) self.dat = Data(cnt, [time, channels], ['time', 'channel'], ['ms', '#']) self.dat.markers = [[0, 'a'], [1, 'b']]
def data_factory(data, axes=None, names=None, units=None, markers=None): """Helper method to create Data objects.""" if len(data) == 0: axes = names = units = [] else: if axes is None: axes = [] for i in range(data.ndim): a = [i * 10 for i in range(data.shape[i])] axes.append(a) if names is None: names = ['name %i' % i for i in range(data.ndim)] if units is None: units = ['unit %i' % i for i in range(data.ndim)] d = Data(data=data, axes=axes, names=names, units=units) d.markers = markers if markers is not None else [] d.fs = 100 return d
class TestRereference(unittest.TestCase): def setUp(self): dat = np.zeros((SAMPLES, CHANS)) # [-10, -9, ... 20) dat[:, 0] = np.arange(SAMPLES) - SAMPLES/2 channels = ['chan{i}'.format(i=i) for i in range(CHANS)] time = np.arange(SAMPLES) self.cnt = Data(dat, [time, channels], ['time', 'channels'], ['ms', '#']) # construct epo epo_dat = np.array([dat + i for i in range(EPOS)]) classes = ['class{i}'.format(i=i) for i in range(EPOS)] self.epo = Data(epo_dat, [classes, time, channels], ['class', 'time', 'channels'], ['#', 'ms', '#']) def test_rereference_cnt(self): """Rereference channels (cnt).""" cnt_r = rereference(self.cnt, 'chan0') dat_r = np.linspace(SAMPLES/2, -SAMPLES/2, SAMPLES, endpoint=False) dat_r = [dat_r for i in range(CHANS)] dat_r = np.array(dat_r).T dat_r[:, 0] = 0 np.testing.assert_array_equal(cnt_r.data, dat_r) def test_rereference_epo(self): """Rereference channels (epo).""" epo_r = rereference(self.epo, 'chan0') dat_r = np.linspace(SAMPLES/2, -SAMPLES/2, SAMPLES, endpoint=False) dat_r = [dat_r for i in range(CHANS)] dat_r = np.array(dat_r).T dat_r[:, 0] = 0 dat_r = np.array([dat_r for i in range(EPOS)]) np.testing.assert_array_equal(epo_r.data, dat_r) def test_raise_value_error(self): """Raise ValueError if channel not found.""" with self.assertRaises(ValueError): rereference(self.cnt, 'foo') def test_case_insensitivity(self): """rereference should not care about case.""" try: rereference(self.cnt, 'ChAN0') except ValueError: self.fail() def test_rereference_copy(self): """rereference must not modify arguments.""" cpy = self.cnt.copy() rereference(self.cnt, 'chan0') self.assertEqual(self.cnt, cpy) def test_rereference_swapaxes(self): """rereference must work with nonstandard chanaxis.""" dat = rereference(swapaxes(self.epo, 1, 2), 'chan0', chanaxis=1) dat = swapaxes(dat, 1, 2) dat2 = rereference(self.epo, 'chan0') self.assertEqual(dat, dat2)
class TestVariance(unittest.TestCase): def setUp(self): ones = np.ones((10, 5)) # epo with 0, 1, 2 data = np.array([0*ones, ones, 2*ones]) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 1000, 10, endpoint=False) classes = [0, 1, 2] self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#']) def test_variance(self): """Variance.""" dat = variance(self.dat) # test the resulting dat has one axis less (the middle one) self.assertEqual(dat.data.shape, self.dat.data.shape[::2]) # each epoch should have a variance of zero, test if the var of # all epochs is 0 self.assertEqual(dat.data.var(), 0) self.assertEqual(len(dat.axes), len(self.dat.axes)-1) def test_variance_with_cnt(self): """variance must work with cnt argument.""" data = self.dat.data[1] axes = self.dat.axes[1:] names = self.dat.names[1:] units = self.dat.units[1:] dat = self.dat.copy(data=data, axes=axes, names=names, units=units) dat = variance(dat) self.assertEqual(dat.data.var(), 0) self.assertEqual(len(dat.axes), len(self.dat.axes)-2) def test_variance_swapaxes(self): """variance must work with nonstandard timeaxis.""" dat = variance(swapaxes(self.dat, 1, 2), timeaxis=2) # we don't swap back here as variance removes the timeaxis dat2 = variance(self.dat) self.assertEqual(dat, dat2) def test_variance_copy(self): """variance must not modify argument.""" cpy = self.dat.copy() variance(self.dat) self.assertEqual(self.dat, cpy)
class TestRectifytChannels(unittest.TestCase): def setUp(self): raw = np.arange(20).reshape(4, 5) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.arange(4) self.dat = Data(raw, [time, channels], ['time', 'channels'], ['ms', '#']) def test_rectify_channels(self): """Rectify channels of positive and negative data must be equal.""" dat = rectify_channels(self.dat.copy(data=-self.dat.data)) dat2 = rectify_channels(self.dat) self.assertEqual(dat, dat2) def test_rectify_channels_copy(self): """Rectify channels must not change the original parameter.""" cpy = self.dat.copy() rectify_channels(self.dat) self.assertEqual(cpy, self.dat)
def setUp(self): ones = np.ones((10, 5)) channels = ["ca1", "ca2", "cb1", "cb2", "cc1"] time = np.linspace(0, 1000, 10, endpoint=False) classes = [0, 1, 2, 1] class_names = ["zeros", "ones", "twoes"] # four cnts: 0s, 1s, -1s, and 0s data = np.array([ones * 0, ones * 1, ones * 2, ones * 0]) self.dat = Data(data, [classes, time, channels], ["class", "time", "channel"], ["#", "ms", "#"]) self.dat.class_names = class_names
class TestSelectIval(unittest.TestCase): def setUp(self): ones = np.ones((10, 5)) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(-1000, 0, 10, endpoint=False) classes = [0, 0, 0] # three cnts: 1s, -1s, and 0s data = np.array([ones, ones * -1, ones * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#']) self.dat.fs = 10 def test_select_ival(self): """Selecting Intervals.""" # normal case dat = select_ival(self.dat, [-500, 0]) self.assertEqual(dat.axes[1][0], -500) self.assertEqual(dat.axes[1][-1],-100) # the full dat interval dat = select_ival(self.dat, [self.dat.axes[1][0], self.dat.axes[1][-1] + 1]) self.assertEqual(dat.axes[1][0], self.dat.axes[1][0]) self.assertEqual(dat.axes[1][-1], self.dat.axes[1][-1]) np.testing.assert_array_equal(dat.data, self.dat.data) def test_select_ival_with_markers(self): """Selecting Intervals with markers.""" # normal case good_markers = [[-499,99, 'x'], [-500, 'x'], [-0.0001, 'x']] bad_markers = [[501, 'y'], [0, 'y'], [1, 'y']] self.dat.markers = good_markers[:] self.dat.markers.extend(bad_markers) dat = select_ival(self.dat, [-500, 0]) self.assertEqual(dat.markers, good_markers) def test_ival_checks(self): """Test for malformed ival parameter.""" with self.assertRaises(AssertionError): select_ival(self.dat, [0, -1]) with self.assertRaises(AssertionError): select_ival(self.dat, [self.dat.axes[1][0]-1, 0]) with self.assertRaises(AssertionError): select_ival(self.dat, [0, self.dat.axes[1][-1]+1]) def test_select_ival_copy(self): """Select_ival must not modify the argument.""" cpy = self.dat.copy() select_ival(cpy, [-500, 0]) self.assertEqual(cpy, self.dat) def test_select_ival_swapaxes(self): """select_ival must work with nonstandard timeaxis.""" dat = select_ival(swapaxes(self.dat, 0, 1), [-500, 0], timeaxis=0) dat = swapaxes(dat, 0, 1) dat2 = select_ival(self.dat, [-500, 0]) self.assertEqual(dat, dat2)
def setUp(self): ones = np.ones((10, 5)) # cnt with 1, 2, 3 cnt = np.append(ones, ones*2, axis=0) cnt = np.append(cnt, ones*3, axis=0) channels = ['ca1', 'ca2', 'cb1', 'cb2', 'cc1'] time = np.linspace(0, 3000, 30, endpoint=False) classes = [0, 1, 2, 1] # four cnts: 1s, -1s, and 0s data = np.array([cnt * 0, cnt * 1, cnt * 2, cnt * 0]) self.dat = Data(data, [classes, time, channels], ['class', 'time', 'channel'], ['#', 'ms', '#'])
def setUp(self): # create 100 samples and tree channels data ones = np.ones((100, 3)) data = np.array([ones, ones * 2, ones * 3]).reshape(-1, 3) time = np.linspace(0, 3000, 300, endpoint=False) channels = ["a", "b", "c"] markers = [[500, "M1"], [1500, "M2"], [2500, "M3"]] self.dat = Data(data, [time, channels], ["time", "channels"], ["ms", "#"]) self.dat.markers = markers self.dat.fs = 100 self.mrk_def = {"class 1": ["M1"], "class 2": ["M2", "M3"]}
def setUp(self): dat = np.zeros((SAMPLES, CHANS)) # [-10, -9, ... 20) dat[:, 0] = np.arange(SAMPLES) - SAMPLES/2 channels = ['chan{i}'.format(i=i) for i in range(CHANS)] time = np.arange(SAMPLES) self.cnt = Data(dat, [time, channels], ['time', 'channels'], ['ms', '#']) # construct epo epo_dat = np.array([dat + i for i in range(EPOS)]) classes = ['class{i}'.format(i=i) for i in range(EPOS)] self.epo = Data(epo_dat, [classes, time, channels], ['class', 'time', 'channels'], ['#', 'ms', '#'])