def test_EventProxy(self): proxy_event = EventProxy(rawio=self.reader, event_channel_index=0, block_index=0, seg_index=0) assert proxy_event.name == 'Some events' assert proxy_event.shape == (6, ) # full load full_event = proxy_event.load(time_slice=None) assert isinstance(full_event, Event) assert_same_attributes(proxy_event, full_event, exclude=('times', 'labels')) assert full_event.shape == proxy_event.shape # slice time event = proxy_event.load(time_slice=(1 * pq.s, 2 * pq.s)) assert event.shape == (2, ) assert event.labels.shape == (2, ) assert_same_attributes(proxy_event.time_slice(1 * pq.s, 2 * pq.s), event) # buggy time slice with self.assertRaises(AssertionError): event = proxy_event.load(time_slice=(2 * pq.s, 15 * pq.s)) event = proxy_event.load(time_slice=(2 * pq.s, 15 * pq.s), strict_slicing=False)
def test__add_epoch(self): proxy_event = EventProxy(rawio=self.reader, event_channel_index=0, block_index=0, seg_index=0) loaded_event = proxy_event.load() regular_event = Event(times=loaded_event.times - 1 * loaded_event.units) loaded_event.annotate(nix_name='neo.event.0') regular_event.annotate(nix_name='neo.event.1') seg = Segment() seg.events = [regular_event, proxy_event] # test cutting with two events one of which is a proxy epoch = add_epoch(seg, regular_event, proxy_event) assert_neo_object_is_compliant(epoch) exp_annos = { k: v for k, v in regular_event.annotations.items() if k != 'nix_name' } self.assertDictEqual(epoch.annotations, exp_annos) assert_arrays_almost_equal(epoch.times, regular_event.times, 1e-12) assert_arrays_almost_equal( epoch.durations, np.ones(regular_event.shape) * loaded_event.units, 1e-12)
def test_EventProxy(self): proxy_event = EventProxy(rawio=self.reader, event_channel_index=0, block_index=0, seg_index=0) assert proxy_event.name == 'Some events' assert proxy_event.shape == (6,) # full load full_event = proxy_event.load(time_slice=None) assert isinstance(full_event, Event) assert_same_attributes(proxy_event, full_event, exclude=('times', 'labels')) assert full_event.shape == proxy_event.shape # slice time event = proxy_event.load(time_slice=(1 * pq.s, 2 * pq.s)) assert event.shape == (2,) assert event.labels.shape == (2,) # buggy time slice with self.assertRaises(AssertionError): event = proxy_event.load(time_slice=(2 * pq.s, 15 * pq.s)) event = proxy_event.load(time_slice=(2 * pq.s, 15 * pq.s), strict_slicing=False)
def test__match_events(self): proxy_event = EventProxy(rawio=self.reader, event_channel_index=0, block_index=0, seg_index=0) loaded_event = proxy_event.load() regular_event = Event(times=loaded_event.times - 1 * loaded_event.units, labels=np.array(['trigger_a', 'trigger_b'] * 3, dtype='U12')) seg = Segment() seg.events = [regular_event, proxy_event] # test matching two events one of which is a proxy matched_regular, matched_proxy = match_events(regular_event, proxy_event) assert_same_attributes(matched_regular, regular_event) assert_same_attributes(matched_proxy, loaded_event)
def test__add_epoch(self): proxy_event = EventProxy(rawio=self.reader, event_channel_index=0, block_index=0, seg_index=0) loaded_event = proxy_event.load() regular_event = Event(times=loaded_event.times - 1 * loaded_event.units) seg = Segment() seg.events = [regular_event, proxy_event] # test cutting with two events one of which is a proxy epoch = add_epoch(seg, regular_event, proxy_event) assert_neo_object_is_compliant(epoch) assert_same_annotations(epoch, regular_event) assert_arrays_almost_equal(epoch.times, regular_event.times, 1e-12) assert_arrays_almost_equal(epoch.durations, np.ones(regular_event.shape) * loaded_event.units, 1e-12)
def read_segment(self, block_index=0, seg_index=0, lazy=False, signal_group_mode=None, load_waveforms=False, time_slice=None, strict_slicing=True): """ :param block_index: int default 0. In case of several block block_index can be specified. :param seg_index: int default 0. Index of segment. :param lazy: False by default. :param signal_group_mode: 'split-all' or 'group-by-same-units' (default depend IO): This control behavior for grouping channels in AnalogSignal. * 'split-all': each channel will give an AnalogSignal * 'group-by-same-units' all channel sharing the same quantity units ar grouped in a 2D AnalogSignal :param load_waveforms: False by default. Control SpikeTrains.waveforms is None or not. :param time_slice: None by default means no limit. A time slice is (t_start, t_stop) both are quantities. All object AnalogSignal, SpikeTrain, Event, Epoch will load only in the slice. :param strict_slicing: True by default. Control if an error is raise or not when one of time_slice member (t_start or t_stop) is outside the real time range of the segment. """ if lazy: assert time_slice is None, 'For lazy=true you must specify time_slice when loading' if signal_group_mode is None: signal_group_mode = self._prefered_signal_group_mode # annotations seg_annotations = dict( self.raw_annotations['blocks'][block_index]['segments'][seg_index]) for k in ('signals', 'units', 'events'): seg_annotations.pop(k) seg_annotations = check_annotations(seg_annotations) seg = Segment(index=seg_index, **seg_annotations) # AnalogSignal signal_channels = self.header['signal_channels'] if signal_channels.size > 0: channel_indexes_list = self.get_group_channel_indexes() for channel_indexes in channel_indexes_list: for i, (ind_within, ind_abs) in self._make_signal_channel_subgroups( channel_indexes, signal_group_mode=signal_group_mode).items(): # make a proxy... anasig = AnalogSignalProxy(rawio=self, global_channel_indexes=ind_abs, block_index=block_index, seg_index=seg_index) if not lazy: # ... and get the real AnalogSIgnal if not lazy anasig = anasig.load(time_slice=time_slice, strict_slicing=strict_slicing) # TODO magnitude_mode='rescaled'/'raw' anasig.segment = seg seg.analogsignals.append(anasig) # SpikeTrain and waveforms (optional) unit_channels = self.header['unit_channels'] for unit_index in range(len(unit_channels)): # make a proxy... sptr = SpikeTrainProxy(rawio=self, unit_index=unit_index, block_index=block_index, seg_index=seg_index) if not lazy: # ... and get the real SpikeTrain if not lazy sptr = sptr.load(time_slice=time_slice, strict_slicing=strict_slicing, load_waveforms=load_waveforms) # TODO magnitude_mode='rescaled'/'raw' sptr.segment = seg seg.spiketrains.append(sptr) # Events/Epoch event_channels = self.header['event_channels'] for chan_ind in range(len(event_channels)): if event_channels['type'][chan_ind] == b'event': e = EventProxy(rawio=self, event_channel_index=chan_ind, block_index=block_index, seg_index=seg_index) if not lazy: e = e.load(time_slice=time_slice, strict_slicing=strict_slicing) e.segment = seg seg.events.append(e) elif event_channels['type'][chan_ind] == b'epoch': e = EpochProxy(rawio=self, event_channel_index=chan_ind, block_index=block_index, seg_index=seg_index) if not lazy: e = e.load(time_slice=time_slice, strict_slicing=strict_slicing) e.segment = seg seg.epochs.append(e) seg.create_many_to_one_relationship() return seg
def test__cut_block_by_epochs(self): seg = Segment() proxy_anasig = AnalogSignalProxy(rawio=self.reader, global_channel_indexes=None, block_index=0, seg_index=0) seg.analogsignals.append(proxy_anasig) proxy_st = SpikeTrainProxy(rawio=self.reader, unit_index=0, block_index=0, seg_index=0) seg.spiketrains.append(proxy_st) proxy_event = EventProxy(rawio=self.reader, event_channel_index=0, block_index=0, seg_index=0) seg.events.append(proxy_event) proxy_epoch = EpochProxy(rawio=self.reader, event_channel_index=1, block_index=0, seg_index=0) proxy_epoch.annotate(pick='me') seg.epochs.append(proxy_epoch) loaded_epoch = proxy_epoch.load() loaded_event = proxy_event.load() loaded_st = proxy_st.load() loaded_anasig = proxy_anasig.load() block = Block() block.segments = [seg] block.create_many_to_one_relationship() cut_block_by_epochs(block, properties={'pick': 'me'}) assert_neo_object_is_compliant(block) self.assertEqual(len(block.segments), proxy_epoch.shape[0]) for epoch_idx in range(len(loaded_epoch)): sliced_event = loaded_event.time_slice( t_start=loaded_epoch.times[epoch_idx], t_stop=loaded_epoch.times[epoch_idx] + loaded_epoch.durations[epoch_idx]) has_event = len(sliced_event) > 0 sliced_anasig = loaded_anasig.time_slice( t_start=loaded_epoch.times[epoch_idx], t_stop=loaded_epoch.times[epoch_idx] + loaded_epoch.durations[epoch_idx]) sliced_st = loaded_st.time_slice( t_start=loaded_epoch.times[epoch_idx], t_stop=loaded_epoch.times[epoch_idx] + loaded_epoch.durations[epoch_idx]) self.assertEqual(len(block.segments[epoch_idx].events), int(has_event)) self.assertEqual(len(block.segments[epoch_idx].spiketrains), 1) self.assertEqual(len(block.segments[epoch_idx].analogsignals), 1) self.assertTrue( isinstance(block.segments[epoch_idx].spiketrains[0], SpikeTrain)) assert_same_attributes(block.segments[epoch_idx].spiketrains[0], sliced_st) self.assertTrue( isinstance(block.segments[epoch_idx].analogsignals[0], AnalogSignal)) assert_same_attributes(block.segments[epoch_idx].analogsignals[0], sliced_anasig) if has_event: self.assertTrue( isinstance(block.segments[epoch_idx].events[0], Event)) assert_same_attributes(block.segments[epoch_idx].events[0], sliced_event) block2 = Block() seg2 = Segment() epoch = Epoch(np.arange(10) * pq.s, durations=np.ones((10)) * pq.s) epoch.annotate(pick='me instead') seg2.epochs = [proxy_epoch, epoch] block2.segments = [seg2] block2.create_many_to_one_relationship() # test correct loading and slicing of EpochProxy objects # (not tested above since we used the EpochProxy to cut the block) cut_block_by_epochs(block2, properties={'pick': 'me instead'}) for epoch_idx in range(len(epoch)): sliced_epoch = loaded_epoch.time_slice( t_start=epoch.times[epoch_idx], t_stop=epoch.times[epoch_idx] + epoch.durations[epoch_idx]) has_epoch = len(sliced_epoch) > 0 if has_epoch: self.assertTrue( isinstance(block2.segments[epoch_idx].epochs[0], Epoch)) assert_same_attributes(block2.segments[epoch_idx].epochs[0], sliced_epoch)
def test__time_slice(self): time_slice = [.5, 5.6] * pq.s epoch2 = Epoch([0.6, 9.5, 16.8, 34.1] * pq.s, durations=[4.5, 4.8, 5.0, 5.0] * pq.s, t_start=.1 * pq.s) epoch2.annotate(epoch_type='b') epoch2.array_annotate(trial_id=[1, 2, 3, 4]) event = Event(times=[0.5, 10.0, 25.2] * pq.s, t_start=.1 * pq.s) event.annotate(event_type='trial start') event.array_annotate(trial_id=[1, 2, 3]) anasig = AnalogSignal(np.arange(50.0) * pq.mV, t_start=.1 * pq.s, sampling_rate=1.0 * pq.Hz) irrsig = IrregularlySampledSignal(signal=np.arange(50.0) * pq.mV, times=anasig.times, t_start=.1 * pq.s) st = SpikeTrain( np.arange(0.5, 50, 7) * pq.s, t_start=.1 * pq.s, t_stop=50.0 * pq.s, waveforms=np.array( [[[0., 1.], [0.1, 1.1]], [[2., 3.], [2.1, 3.1]], [[4., 5.], [4.1, 5.1]], [[6., 7.], [6.1, 7.1]], [[8., 9.], [8.1, 9.1]], [[12., 13.], [12.1, 13.1]], [[14., 15.], [14.1, 15.1]], [[16., 17.], [16.1, 17.1]]]) * pq.mV, array_annotations={'spikenum': np.arange(1, 9)}) seg = Segment() seg.epochs = [epoch2] seg.events = [event] seg.analogsignals = [anasig] seg.irregularlysampledsignals = [irrsig] seg.spiketrains = [st] block = Block() block.segments = [seg] block.create_many_to_one_relationship() # test without resetting the time sliced = seg.time_slice(time_slice[0], time_slice[1]) assert_neo_object_is_compliant(sliced) self.assertEqual(len(sliced.events), 1) self.assertEqual(len(sliced.spiketrains), 1) self.assertEqual(len(sliced.analogsignals), 1) self.assertEqual(len(sliced.irregularlysampledsignals), 1) self.assertEqual(len(sliced.epochs), 1) assert_same_attributes( sliced.spiketrains[0], st.time_slice(t_start=time_slice[0], t_stop=time_slice[1])) assert_same_attributes( sliced.analogsignals[0], anasig.time_slice(t_start=time_slice[0], t_stop=time_slice[1])) assert_same_attributes( sliced.irregularlysampledsignals[0], irrsig.time_slice(t_start=time_slice[0], t_stop=time_slice[1])) assert_same_attributes( sliced.events[0], event.time_slice(t_start=time_slice[0], t_stop=time_slice[1])) assert_same_attributes( sliced.epochs[0], epoch2.time_slice(t_start=time_slice[0], t_stop=time_slice[1])) seg = Segment() seg.epochs = [epoch2] seg.events = [event] seg.analogsignals = [anasig] seg.irregularlysampledsignals = [irrsig] seg.spiketrains = [st] block = Block() block.segments = [seg] block.create_many_to_one_relationship() # test with resetting the time sliced = seg.time_slice(time_slice[0], time_slice[1], reset_time=True) assert_neo_object_is_compliant(sliced) self.assertEqual(len(sliced.events), 1) self.assertEqual(len(sliced.spiketrains), 1) self.assertEqual(len(sliced.analogsignals), 1) self.assertEqual(len(sliced.irregularlysampledsignals), 1) self.assertEqual(len(sliced.epochs), 1) assert_same_attributes( sliced.spiketrains[0], st.time_shift(-time_slice[0]).time_slice(t_start=0 * pq.s, t_stop=time_slice[1] - time_slice[0])) anasig_target = anasig.copy() anasig_target = anasig_target.time_shift(-time_slice[0]).time_slice( t_start=0 * pq.s, t_stop=time_slice[1] - time_slice[0]) assert_same_attributes(sliced.analogsignals[0], anasig_target) irrsig_target = irrsig.copy() irrsig_target = irrsig_target.time_shift(-time_slice[0]).time_slice( t_start=0 * pq.s, t_stop=time_slice[1] - time_slice[0]) assert_same_attributes(sliced.irregularlysampledsignals[0], irrsig_target) assert_same_attributes( sliced.events[0], event.time_shift(-time_slice[0]).time_slice(t_start=0 * pq.s, t_stop=time_slice[1] - time_slice[0])) assert_same_attributes( sliced.epochs[0], epoch2.time_shift(-time_slice[0]).time_slice(t_start=0 * pq.s, t_stop=time_slice[1] - time_slice[0])) seg = Segment() reader = ExampleRawIO(filename='my_filename.fake') reader.parse_header() proxy_anasig = AnalogSignalProxy(rawio=reader, stream_index=0, inner_stream_channels=None, block_index=0, seg_index=0) seg.analogsignals.append(proxy_anasig) proxy_st = SpikeTrainProxy(rawio=reader, spike_channel_index=0, block_index=0, seg_index=0) seg.spiketrains.append(proxy_st) proxy_event = EventProxy(rawio=reader, event_channel_index=0, block_index=0, seg_index=0) seg.events.append(proxy_event) proxy_epoch = EpochProxy(rawio=reader, event_channel_index=1, block_index=0, seg_index=0) proxy_epoch.annotate(pick='me') seg.epochs.append(proxy_epoch) loaded_epoch = proxy_epoch.load() loaded_event = proxy_event.load() loaded_st = proxy_st.load() loaded_anasig = proxy_anasig.load() block = Block() block.segments = [seg] block.create_many_to_one_relationship() # test with proxy objects sliced = seg.time_slice(time_slice[0], time_slice[1]) assert_neo_object_is_compliant(sliced) sliced_event = loaded_event.time_slice(t_start=time_slice[0], t_stop=time_slice[1]) has_event = len(sliced_event) > 0 sliced_anasig = loaded_anasig.time_slice(t_start=time_slice[0], t_stop=time_slice[1]) sliced_st = loaded_st.time_slice(t_start=time_slice[0], t_stop=time_slice[1]) self.assertEqual(len(sliced.events), int(has_event)) self.assertEqual(len(sliced.spiketrains), 1) self.assertEqual(len(sliced.analogsignals), 1) self.assertTrue(isinstance(sliced.spiketrains[0], SpikeTrain)) assert_same_attributes(sliced.spiketrains[0], sliced_st) self.assertTrue(isinstance(sliced.analogsignals[0], AnalogSignal)) assert_same_attributes(sliced.analogsignals[0], sliced_anasig) if has_event: self.assertTrue(isinstance(sliced.events[0], Event)) assert_same_attributes(sliced.events[0], sliced_event)
def read_segment(self, block_index=0, seg_index=0, lazy=False, signal_group_mode=None, load_waveforms=False, time_slice=None, strict_slicing=True): """ :param block_index: int default 0. In case of several block block_index can be specified. :param seg_index: int default 0. Index of segment. :param lazy: False by default. :param signal_group_mode: 'split-all' or 'group-by-same-units' (default depend IO): This control behavior for grouping channels in AnalogSignal. * 'split-all': each channel will give an AnalogSignal * 'group-by-same-units' all channel sharing the same quantity units ar grouped in a 2D AnalogSignal :param load_waveforms: False by default. Control SpikeTrains.waveforms is None or not. :param time_slice: None by default means no limit. A time slice is (t_start, t_stop) both are quantities. All object AnalogSignal, SpikeTrain, Event, Epoch will load only in the slice. :param strict_slicing: True by default. Control if an error is raise or not when one of time_slice member (t_start or t_stop) is outside the real time range of the segment. """ if lazy: assert time_slice is None, 'For lazy=true you must specify time_slice when loading' if signal_group_mode is None: signal_group_mode = self._prefered_signal_group_mode # annotations seg_annotations = dict(self.raw_annotations['blocks'][block_index]['segments'][seg_index]) for k in ('signals', 'units', 'events'): seg_annotations.pop(k) seg_annotations = check_annotations(seg_annotations) seg = Segment(index=seg_index, **seg_annotations) # AnalogSignal signal_channels = self.header['signal_channels'] if signal_channels.size > 0: channel_indexes_list = self.get_group_channel_indexes() for channel_indexes in channel_indexes_list: for i, (ind_within, ind_abs) in self._make_signal_channel_subgroups( channel_indexes, signal_group_mode=signal_group_mode).items(): # make a proxy... anasig = AnalogSignalProxy(rawio=self, global_channel_indexes=ind_abs, block_index=block_index, seg_index=seg_index) if not lazy: # ... and get the real AnalogSIgnal if not lazy anasig = anasig.load(time_slice=time_slice, strict_slicing=strict_slicing) # TODO magnitude_mode='rescaled'/'raw' anasig.segment = seg seg.analogsignals.append(anasig) # SpikeTrain and waveforms (optional) unit_channels = self.header['unit_channels'] for unit_index in range(len(unit_channels)): # make a proxy... sptr = SpikeTrainProxy(rawio=self, unit_index=unit_index, block_index=block_index, seg_index=seg_index) if not lazy: # ... and get the real SpikeTrain if not lazy sptr = sptr.load(time_slice=time_slice, strict_slicing=strict_slicing, load_waveforms=load_waveforms) # TODO magnitude_mode='rescaled'/'raw' sptr.segment = seg seg.spiketrains.append(sptr) # Events/Epoch event_channels = self.header['event_channels'] for chan_ind in range(len(event_channels)): if event_channels['type'][chan_ind] == b'event': e = EventProxy(rawio=self, event_channel_index=chan_ind, block_index=block_index, seg_index=seg_index) if not lazy: e = e.load(time_slice=time_slice, strict_slicing=strict_slicing) e.segment = seg seg.events.append(e) elif event_channels['type'][chan_ind] == b'epoch': e = EpochProxy(rawio=self, event_channel_index=chan_ind, block_index=block_index, seg_index=seg_index) if not lazy: e = e.load(time_slice=time_slice, strict_slicing=strict_slicing) e.segment = seg seg.epochs.append(e) seg.create_many_to_one_relationship() return seg