def process_epoch(seg, trials, event, duration, epochname, mask=None): if not isinstance(trials, np.ndarray): warnings.warn("not a valid trials!") return if mask is None: mask = [True] * len(trials) subtrial = trials[mask] subtrial = subtrial[subtrial['eventname'] == event] seg.epochs.append(Epoch( times=subtrial['time'] * duration[0].units + duration[0], durations=[duration[1] - duration[0]] * len(subtrial), name=epochname ))
def load(self, time_slice=None, strict_slicing=True): ''' *Args*: :time_slice: None or tuple of the time slice expressed with quantities. None is the entire signal. :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. ''' t_start, t_stop = consolidate_time_slice(time_slice, self.t_start, self.t_stop, strict_slicing) _t_start, _t_stop = prepare_time_slice(time_slice) timestamp, durations, labels = self._rawio.get_event_timestamps( block_index=self._block_index, seg_index=self._seg_index, event_channel_index=self._event_channel_index, t_start=_t_start, t_stop=_t_stop) dtype = 'float64' times = self._rawio.rescale_event_timestamp(timestamp, dtype=dtype) units = 's' if durations is not None: durations = self._rawio.rescale_epoch_duration(durations, dtype=dtype) * pq.s # this should be remove when labesl will be unicode labels = labels.astype('S') h = self._rawio.header['event_channels'][self._event_channel_index] if h['type'] == b'event': ret = Event(times=times, labels=labels, units='s', name=self.name, file_origin=self.file_origin, description=self.description, **self.annotations) elif h['type'] == b'epoch': ret = Epoch(times=times, durations=durations, labels=labels, units='s', name=self.name, file_origin=self.file_origin, description=self.description, **self.annotations) return ret
def test_epoch_write(self): block = Block() seg = Segment() block.segments.append(seg) epoch = Epoch(times=[1, 1, 10, 3] * pq.ms, durations=[3, 3, 3, 1] * pq.ms, labels=np.array(["one", "two", "three", "four"]), name="test epoch", description="an epoch for testing") seg.epochs.append(epoch) self.write_and_compare([block])
def _get_stim(self, channel): epo = Epoch() ttls = self._kwe['event_types']['TTL']['events']['time_samples'].value event_channels = self._kwe['event_types']['TTL']['events'][ 'user_data']['event_channels'].value event_id = self._kwe['event_types']['TTL']['events']['user_data'][ 'eventID'].value epo.times = (ttls[(event_channels == channel) & (event_id == 1)] / self._attrs['kwe']['sample_rate']) * pq.s off_times = (ttls[(event_channels == channel) & (event_id == 0)] / self._attrs['kwe']['sample_rate']) * pq.s epo.durations = off_times - epo.times # TODO check length match epo.name = 'StimulusTTL' return epo
def read_epoch(self, lazy=False, channel_index=0, t_start=0., segment_duration=0.): """function to read digital timestamps. this function reads the event onset and offset and outputs onset and duration. to get only onsets use the event array function""" assert not lazy, 'Do not support lazy' # create temporary empty lists to store data tempNames = list() tempTimeStamp = list() durations = list() # get entity from file digEntity = self.fd.get_entity(channel_index) # transform t_start into index (reading will start from this index) startat = digEntity.get_index_by_time( t_start, 0) # zero means closest index to value # get the last index to read, using segment duration and t_start # -1 means last index before time endat = digEntity.get_index_by_time(float(segment_duration + t_start), -1) # run through entity using only odd "i"s for i in range(startat, endat + 1, 1): if i % 2 == 1: # get in which digital bit was the trigger detected tempNames.append(digEntity.label[-8:]) # get the time stamps of even events tempData, onOrOff = digEntity.get_data(i - 1) # if this was an onset event, save it to the list # on triggered recordings it seems that only onset events are # recorded. On continuous recordings both onset(==1) # and offset(==255) seem to be recorded # if onOrOff == 1: # append the time stamp to them empty list tempTimeStamp.append(tempData) # get time stamps of odd events tempData1, onOrOff = digEntity.get_data(i) # if onOrOff == 255: # pass durations.append(tempData1 - tempData) epa = Epoch(file_origin=self.filename, times=np.array(tempTimeStamp) * pq.s, durations=np.array(durations) * pq.s, labels=np.array(tempNames, dtype="U"), description="digital events with duration") return epa
def setUp(self): self.segment = Segment() self.epoch = Epoch(name='my epoch') self.segment.epochs.append(self.epoch) self.signal = AnalogSignal(np.random.randn(1000, 1), units='V', sampling_rate=1 * pq.Hz, name='my signal') self.segment.analogsignals.append(self.signal) self.trials = pd.DataFrame() self.trials.name = 'trials' self.segment2 = Segment() self.segment2.epochs.append(self.epoch) self.segment2.analogsignals.append(self.signal) self.segment2.dataframes = [self.trials]
def random_epoch(): size = random.randint(1, 7) times = np.cumsum(np.random.uniform(5, 10, size=size)) durations = np.random.uniform(1, 3, size=size) labels = [random_string() for i in range(size)] obj = Epoch( times=times, durations=durations, labels=labels, units="ms", name=random_string(), array_annotations=None, # todo **random_annotations(3) ) return obj
def test_make_stimulus_off_epoch(): from neo.core import Epoch from exana.stimulus.tools import (make_stimulus_off_epoch) times = np.linspace(0, 10, 11) * pq.s durations = np.ones(len(times)) * pq.s labels = np.ones(len(times)) stim_epoch = Epoch(labels=labels, durations=durations, times=times) stim_off_epoch = make_stimulus_off_epoch(stim_epoch) assert (stim_off_epoch.times == np.linspace(1, 10, 10)).all() assert (stim_off_epoch.durations == np.zeros(10)).all() assert (stim_off_epoch.labels == [None] * 10) stim_off_epoch = make_stimulus_off_epoch(stim_epoch, include_boundary=True) assert (stim_off_epoch.times == np.linspace(0, 10, 11)).all() assert (stim_off_epoch.durations == np.zeros(11)).all() assert (stim_off_epoch.labels == [None] * 11) times = np.arange(0.5, 11, 0.5)[::2] * pq.s durations = np.ones(len(times)) * 0.5 * pq.s labels = np.ones(len(times)) stim_epoch = Epoch(labels=labels, durations=durations, times=times) stim_off_epoch = make_stimulus_off_epoch(stim_epoch) assert (stim_off_epoch.times == np.arange(1, 11, 1)).all() assert (stim_off_epoch.durations == np.ones(10) * 0.5).all() assert (stim_off_epoch.labels == [None] * 10) stim_off_epoch = make_stimulus_off_epoch(stim_epoch, include_boundary=True) assert (stim_off_epoch.times == np.arange(0, 11, 1)).all() assert (stim_off_epoch.durations == np.ones(11) * 0.5).all() assert (stim_off_epoch.labels == [None] * 11)
def _read_epocharray(self, node, parent): attributes = self._get_standard_attributes(node) times = self._get_quantity(node["times"]) durations = self._get_quantity(node["durations"]) if self._lazy: labels = np.array((), dtype=node["labels"].dtype) else: labels = node["labels"].value epoch = Epoch(times=times, durations=durations, labels=labels, **attributes) epoch.segment = parent if self._lazy: epoch.lazy_shape = node["times"].shape return epoch
def test_anonymous_objects_write(self): nblocks = 2 nsegs = 2 nanasig = 4 nirrseg = 2 nepochs = 3 nevents = 4 nspiketrains = 3 nchx = 5 nunits = 10 times = self.rquant(1, pq.s) signal = self.rquant(1, pq.V) blocks = [] for blkidx in range(nblocks): blk = Block() blocks.append(blk) for segidx in range(nsegs): seg = Segment() blk.segments.append(seg) for anaidx in range(nanasig): seg.analogsignals.append(AnalogSignal(signal=signal, sampling_rate=pq.Hz)) for irridx in range(nirrseg): seg.irregularlysampledsignals.append( IrregularlySampledSignal(times=times, signal=signal, time_units=pq.s) ) for epidx in range(nepochs): seg.epochs.append(Epoch(times=times, durations=times)) for evidx in range(nevents): seg.events.append(Event(times=times)) for stidx in range(nspiketrains): seg.spiketrains.append(SpikeTrain(times=times, t_stop=times[-1]+pq.s, units=pq.s)) for chidx in range(nchx): chx = ChannelIndex(name="chx{}".format(chidx), index=[1, 2], channel_ids=[11, 22]) blk.channel_indexes.append(chx) for unidx in range(nunits): unit = Unit() chx.units.append(unit) self.writer.write_all_blocks(blocks) self.compare_blocks(blocks, self.reader.blocks)
def create_all_annotated(cls): times = cls.rquant(1, pq.s) signal = cls.rquant(1, pq.V) blk = Block() blk.annotate(**cls.rdict(3)) cls.populate_dates(blk) seg = Segment() seg.annotate(**cls.rdict(4)) cls.populate_dates(seg) blk.segments.append(seg) asig = AnalogSignal(signal=signal, sampling_rate=pq.Hz) asig.annotate(**cls.rdict(2)) seg.analogsignals.append(asig) isig = IrregularlySampledSignal(times=times, signal=signal, time_units=pq.s) isig.annotate(**cls.rdict(2)) seg.irregularlysampledsignals.append(isig) epoch = Epoch(times=times, durations=times) epoch.annotate(**cls.rdict(4)) seg.epochs.append(epoch) event = Event(times=times) event.annotate(**cls.rdict(4)) seg.events.append(event) spiketrain = SpikeTrain(times=times, t_stop=pq.s, units=pq.s) d = cls.rdict(6) d["quantity"] = pq.Quantity(10, "mV") d["qarray"] = pq.Quantity(range(10), "mA") spiketrain.annotate(**d) seg.spiketrains.append(spiketrain) chx = ChannelIndex(name="achx", index=[1, 2], channel_ids=[0, 10]) chx.annotate(**cls.rdict(5)) blk.channel_indexes.append(chx) unit = Unit() unit.annotate(**cls.rdict(2)) chx.units.append(unit) return blk
def test_multiref_write(self): blk = Block("blk1") signal = AnalogSignal(name="sig1", signal=[0, 1, 2], units="mV", sampling_period=pq.Quantity(1, "ms")) othersignal = IrregularlySampledSignal(name="i1", signal=[0, 0, 0], units="mV", times=[1, 2, 3], time_units="ms") event = Event(name="Evee", times=[0.3, 0.42], units="year") epoch = Epoch(name="epoche", times=[0.1, 0.2] * pq.min, durations=[0.5, 0.5] * pq.min) st = SpikeTrain(name="the train of spikes", times=[0.1, 0.2, 10.3], t_stop=11, units="us") for idx in range(3): segname = "seg" + str(idx) seg = Segment(segname) blk.segments.append(seg) seg.analogsignals.append(signal) seg.irregularlysampledsignals.append(othersignal) seg.events.append(event) seg.epochs.append(epoch) seg.spiketrains.append(st) chidx = ChannelIndex([10, 20, 29]) seg = blk.segments[0] st = SpikeTrain(name="choochoo", times=[10, 11, 80], t_stop=1000, units="s") seg.spiketrains.append(st) blk.channel_indexes.append(chidx) for idx in range(6): unit = Unit("unit" + str(idx)) chidx.units.append(unit) unit.spiketrains.append(st) self.writer.write_block(blk) self.compare_blocks([blk], self.reader.blocks)
def to_epoch(self, durations=None): from neo.core import Epoch, Event, Segment if durations is None: # times = self.times[:] # durations = np.diff(self.times)[:] # labels = self.labels[:] times = self.times[:-1] durations = np.diff(self.times) # labels = self.labels[:-1] labels = np.array([ "{}-{}".format(a, b) for a, b in zip(self.labels[:-1], self.labels[1:]) ]) else: times = self.times labels = self.labels return Epoch(time=times, durations=durations, labels=labels)
def _create_extra_stimuli_channel(from_channel: Event, time_threshold: Quantity) -> Epoch: stimuli: List[Tuple[int, int]] = _group_stimuli(from_channel, time_threshold) #data_points: List[Quantity] = [from_channel.times[start:stop] for start, stop in stimuli] # the label of each timespan is the label of the first event labels = np.array([from_channel.labels[start] for start, _ in stimuli]) # the timestamp of each timespan is the timestamp of the first event times: Quantity = np.array([from_channel.times[start] for start, _ in stimuli]) * from_channel.units # the duration is the time difference between the first and last event durations: Quantity = np.array([from_channel.times[stop-1] - from_channel.times[start] for start, stop in stimuli]) * from_channel.units frequencies: Quantity = None # with this deactivate the divide by 0 warning from NP # it just returns infinity with np.errstate(divide="ignore"): # the frequency is the number of pulses by the duration. # FIXME: shouldn't it be the number -1 as the last one marks exactly the end, so we only count the ones in the middle? frequencies = np.array([(stop - start) / durations[i] for i, (start, stop) in enumerate(stimuli)]) / from_channel.units frequencies.units = Hz epoch = Epoch(times=times, durations=durations, labels=labels, units=from_channel.units) epoch.array_annotate(frequencies=frequencies) return epoch
def load(self, time_slice=None, strict_slicing=True): """ Load EpochProxy args: :param time_slice: None or tuple of the time slice expressed with quantities. None is all of the intervals. :param strict_slicing: True by default. Control if an error is raised or not when one of the time_slice members (t_start or t_stop) is outside the real time range of the segment. """ if time_slice: raise NotImplementedError("todo") else: start_times = self._time_intervals.start_time[self._index] stop_times = self._time_intervals.stop_time[self._index] durations = stop_times - start_times labels = self._time_intervals.tags[self._index] return Epoch(times=start_times * pq.s, durations=durations * pq.s, labels=labels, name=self.name)
def read_epoch(fh, block_id, array_id): nix_block = fh.handle.blocks[block_id] nix_da = nix_block.data_arrays[array_id] params = { 'times': nix_da[0], # TODO think about lazy data loading 'durations': nix_da[1], # TODO think about lazy data loading 'labels': [x.encode('UTF-8') for x in nix_da.dimensions[0].labels] } name = Reader.Help.get_obj_neo_name(nix_da) if name: params['name'] = name epoch = Epoch(**params) for key, value in Reader.Help.read_attributes(nix_da.metadata, 'epoch').items(): setattr(epoch, key, value) epoch.annotations = Reader.Help.read_annotations(nix_da.metadata, 'epoch') return epoch
def read_epoch(self, path, cascade=True, lazy=False): group = self._exdir_directory[path] if lazy: times = [] else: times = pq.Quantity(group['timestamps'].data, group['timestamps'].attrs['unit']) if "durations" in group and not lazy: durations = pq.Quantity(group['durations'].data, group['durations'].attrs['unit']) elif "durations" in group and lazy: durations = [] else: durations = None if 'data' in group and not lazy: if 'unit' not in group['data'].attrs: labels = group['data'].data else: labels = pq.Quantity(group['data'].data, group['data'].attrs['unit']) elif 'data' in group and lazy: labels = [] else: labels = None annotations = {'exdir_path': path} annotations.update(group.attrs.to_dict()) if lazy: lazy_shape = (group.attrs['num_samples'], ) else: lazy_shape = None epo = Epoch(times=times, durations=durations, labels=labels, lazy_shape=lazy_shape, **annotations) return epo
def fake_epoch(seed=None, n=1): """ Create a fake Epoch. We use this separate function because the attributes of Epoch are not independent (must all have the same size) """ kwargs = get_annotations() if seed is not None: np.random.seed(seed) size = np.random.randint(5, 15) for i, attr in enumerate(Epoch._necessary_attrs + Epoch._recommended_attrs): if seed is not None: iseed = seed + i else: iseed = None if attr[0] in ('times', 'durations', 'labels'): kwargs[attr[0]] = get_fake_value(*attr, seed=iseed, obj=Epoch, shape=size) else: kwargs[attr[0]] = get_fake_value(*attr, seed=iseed, obj=Epoch, n=n) kwargs['seed'] = seed obj = Epoch(**kwargs) return obj
def test__issue_285(self): train = SpikeTrain([3, 4, 5] * pq.s, t_stop=10.0) unit = Unit() train.unit = unit unit.spiketrains.append(train) epoch = Epoch([0, 10, 20], [2, 2, 2], ["a", "b", "c"], units="ms") blk = Block() seg = Segment() seg.spiketrains.append(train) seg.epochs.append(epoch) epoch.segment = seg blk.segments.append(seg) reader = PickleIO(filename="blk.pkl") reader.write(blk) reader = PickleIO(filename="blk.pkl") r_blk = reader.read_block() r_seg = r_blk.segments[0] self.assertIsInstance(r_seg.spiketrains[0].unit, Unit) self.assertIsInstance(r_seg.epochs[0], Epoch)
def generate_one_simple_segment(seg_name='segment 0', supported_objects=[], nb_analogsignal=4, t_start=0. * pq.s, sampling_rate=10 * pq.kHz, duration=6. * pq.s, nb_spiketrain=6, spikerate_range=[.5 * pq.Hz, 12 * pq.Hz], event_types={'stim': ['a', 'b', 'c', 'd'], 'enter_zone': ['one', 'two'], 'color': ['black', 'yellow', 'green'], }, event_size_range=[5, 20], epoch_types={'animal state': ['Sleep', 'Freeze', 'Escape'], 'light': ['dark', 'lighted']}, epoch_duration_range=[.5, 3.], # this should be multiplied by pq.s, no? array_annotations={'valid': np.array([True, False]), 'number': np.array(range(5))} ): if supported_objects and Segment not in supported_objects: raise ValueError('Segment must be in supported_objects') seg = Segment(name=seg_name) if AnalogSignal in supported_objects: for a in range(nb_analogsignal): anasig = AnalogSignal(rand(int((sampling_rate * duration).simplified)), sampling_rate=sampling_rate, t_start=t_start, units=pq.mV, channel_index=a, name='sig %d for segment %s' % (a, seg.name)) seg.analogsignals.append(anasig) if SpikeTrain in supported_objects: for s in range(nb_spiketrain): spikerate = rand() * np.diff(spikerate_range) spikerate += spikerate_range[0].magnitude # spikedata = rand(int((spikerate*duration).simplified))*duration # sptr = SpikeTrain(spikedata, # t_start=t_start, t_stop=t_start+duration) # #, name = 'spiketrain %d'%s) spikes = rand(int((spikerate * duration).simplified)) spikes.sort() # spikes are supposed to be an ascending sequence sptr = SpikeTrain(spikes * duration, t_start=t_start, t_stop=t_start + duration) sptr.annotations['channel_index'] = s # Randomly generate array_annotations from given options arr_ann = {key: value[(rand(len(spikes)) * len(value)).astype('i')] for (key, value) in array_annotations.items()} sptr.array_annotate(**arr_ann) seg.spiketrains.append(sptr) if Event in supported_objects: for name, labels in event_types.items(): evt_size = rand() * np.diff(event_size_range) evt_size += event_size_range[0] evt_size = int(evt_size) labels = np.array(labels, dtype='S') labels = labels[(rand(evt_size) * len(labels)).astype('i')] evt = Event(times=rand(evt_size) * duration, labels=labels) # Randomly generate array_annotations from given options arr_ann = {key: value[(rand(evt_size) * len(value)).astype('i')] for (key, value) in array_annotations.items()} evt.array_annotate(**arr_ann) seg.events.append(evt) if Epoch in supported_objects: for name, labels in epoch_types.items(): t = 0 times = [] durations = [] while t < duration: times.append(t) dur = rand() * (epoch_duration_range[1] - epoch_duration_range[0]) dur += epoch_duration_range[0] durations.append(dur) t = t + dur labels = np.array(labels, dtype='S') labels = labels[(rand(len(times)) * len(labels)).astype('i')] assert len(times) == len(durations) assert len(times) == len(labels) epc = Epoch(times=pq.Quantity(times, units=pq.s), durations=pq.Quantity(durations, units=pq.s), labels=labels,) assert epc.times.dtype == 'float' # Randomly generate array_annotations from given options arr_ann = {key: value[(rand(len(times)) * len(value)).astype('i')] for (key, value) in array_annotations.items()} epc.array_annotate(**arr_ann) seg.epochs.append(epc) # TODO : Spike, Event seg.create_many_to_one_relationship() return seg
def test_roundtrip(self): annotations = {"session_start_time": datetime.now()} # Define Neo blocks bl0 = Block(name='First block', **annotations) bl1 = Block(name='Second block', **annotations) bl2 = Block(name='Third block', **annotations) original_blocks = [bl0, bl1, bl2] num_seg = 4 # number of segments num_chan = 3 # number of channels for blk in original_blocks: for ind in range(num_seg): # number of Segments seg = Segment(index=ind) seg.block = blk blk.segments.append(seg) for seg in blk.segments: # AnalogSignal objects # 3 Neo AnalogSignals a = AnalogSignal(np.random.randn(44, num_chan) * pq.nA, sampling_rate=10 * pq.kHz, t_start=50 * pq.ms) b = AnalogSignal(np.random.randn(64, num_chan) * pq.mV, sampling_rate=8 * pq.kHz, t_start=40 * pq.ms) c = AnalogSignal(np.random.randn(33, num_chan) * pq.uA, sampling_rate=10 * pq.kHz, t_start=120 * pq.ms) # 2 Neo IrregularlySampledSignals d = IrregularlySampledSignal( np.arange(7.0) * pq.ms, np.random.randn(7, num_chan) * pq.mV) # 2 Neo SpikeTrains train = SpikeTrain(times=[1, 2, 3] * pq.s, t_start=1.0, t_stop=10.0) train2 = SpikeTrain(times=[4, 5, 6] * pq.s, t_stop=10.0) # todo: add waveforms # 1 Neo Event evt = Event(times=np.arange(0, 30, 10) * pq.ms, labels=np.array(['ev0', 'ev1', 'ev2'])) # 2 Neo Epochs epc = Epoch(times=np.arange(0, 30, 10) * pq.s, durations=[10, 5, 7] * pq.ms, labels=np.array(['btn0', 'btn1', 'btn2'])) epc2 = Epoch(times=np.arange(10, 40, 10) * pq.s, durations=[9, 3, 8] * pq.ms, labels=np.array(['btn3', 'btn4', 'btn5'])) seg.spiketrains.append(train) seg.spiketrains.append(train2) seg.epochs.append(epc) seg.epochs.append(epc2) seg.analogsignals.append(a) seg.analogsignals.append(b) seg.analogsignals.append(c) seg.irregularlysampledsignals.append(d) seg.events.append(evt) a.segment = seg b.segment = seg c.segment = seg d.segment = seg evt.segment = seg train.segment = seg train2.segment = seg epc.segment = seg epc2.segment = seg # write to file test_file_name = "test_round_trip.nwb" iow = NWBIO(filename=test_file_name, mode='w') iow.write_all_blocks(original_blocks) ior = NWBIO(filename=test_file_name, mode='r') retrieved_blocks = ior.read_all_blocks() self.assertEqual(len(retrieved_blocks), 3) self.assertEqual(len(retrieved_blocks[2].segments), num_seg) original_signal_22b = original_blocks[2].segments[2].analogsignals[1] retrieved_signal_22b = retrieved_blocks[2].segments[2].analogsignals[1] for attr_name in ("name", "units", "sampling_rate", "t_start"): retrieved_attribute = getattr(retrieved_signal_22b, attr_name) original_attribute = getattr(original_signal_22b, attr_name) self.assertEqual(retrieved_attribute, original_attribute) assert_array_equal(retrieved_signal_22b.magnitude, original_signal_22b.magnitude) original_issignal_22d = original_blocks[2].segments[ 2].irregularlysampledsignals[0] retrieved_issignal_22d = retrieved_blocks[2].segments[ 2].irregularlysampledsignals[0] for attr_name in ("name", "units", "t_start"): retrieved_attribute = getattr(retrieved_issignal_22d, attr_name) original_attribute = getattr(original_issignal_22d, attr_name) self.assertEqual(retrieved_attribute, original_attribute) assert_array_equal( retrieved_issignal_22d.times.rescale('ms').magnitude, original_issignal_22d.times.rescale('ms').magnitude) assert_array_equal(retrieved_issignal_22d.magnitude, original_issignal_22d.magnitude) original_event_11 = original_blocks[1].segments[1].events[0] retrieved_event_11 = retrieved_blocks[1].segments[1].events[0] for attr_name in ("name", ): retrieved_attribute = getattr(retrieved_event_11, attr_name) original_attribute = getattr(original_event_11, attr_name) self.assertEqual(retrieved_attribute, original_attribute) assert_array_equal( retrieved_event_11.rescale('ms').magnitude, original_event_11.rescale('ms').magnitude) assert_array_equal(retrieved_event_11.labels, original_event_11.labels) original_spiketrain_131 = original_blocks[1].segments[1].spiketrains[1] retrieved_spiketrain_131 = retrieved_blocks[1].segments[1].spiketrains[ 1] for attr_name in ("name", "t_start", "t_stop"): retrieved_attribute = getattr(retrieved_spiketrain_131, attr_name) original_attribute = getattr(original_spiketrain_131, attr_name) self.assertEqual(retrieved_attribute, original_attribute) assert_array_equal( retrieved_spiketrain_131.times.rescale('ms').magnitude, original_spiketrain_131.times.rescale('ms').magnitude) original_epoch_11 = original_blocks[1].segments[1].epochs[0] retrieved_epoch_11 = retrieved_blocks[1].segments[1].epochs[0] for attr_name in ("name", ): retrieved_attribute = getattr(retrieved_epoch_11, attr_name) original_attribute = getattr(original_epoch_11, attr_name) self.assertEqual(retrieved_attribute, original_attribute) assert_array_equal( retrieved_epoch_11.rescale('ms').magnitude, original_epoch_11.rescale('ms').magnitude) assert_allclose( retrieved_epoch_11.durations.rescale('ms').magnitude, original_epoch_11.durations.rescale('ms').magnitude) assert_array_equal(retrieved_epoch_11.labels, original_epoch_11.labels) os.remove(test_file_name)
def test__get_epochs(self): a_1 = Epoch([0.5, 10.0, 25.2] * pq.s, durations=[5.1, 4.8, 5.0] * pq.s) a_1.annotate(epoch_type='a', pick='me') a_1.array_annotate(trial_id=[1, 2, 3]) b_1 = Epoch([5.5, 14.9, 30.1] * pq.s, durations=[4.7, 4.9, 5.2] * pq.s) b_1.annotate(epoch_type='b') b_1.array_annotate(trial_id=[1, 2, 3]) a_2 = Epoch([33.2, 41.7, 52.4] * pq.s, durations=[5.3, 5.0, 5.1] * pq.s) a_2.annotate(epoch_type='a') a_2.array_annotate(trial_id=[4, 5, 6]) b_2 = Epoch([37.6, 46.1, 57.0] * pq.s, durations=[4.9, 5.2, 5.1] * pq.s) b_2.annotate(epoch_type='b') b_2.array_annotate(trial_id=[4, 5, 6]) seg = Segment() seg2 = Segment() seg.epochs = [a_1, b_1] seg2.epochs = [a_2, b_2] block = Block() block.segments = [seg, seg2] # test getting one whole event via annotation extracted_a_1 = get_epochs(seg, epoch_type='a') extracted_a_1b = get_epochs(block, pick='me') self.assertEqual(len(extracted_a_1), 1) self.assertEqual(len(extracted_a_1b), 1) extracted_a_1 = extracted_a_1[0] extracted_a_1b = extracted_a_1b[0] assert_same_attributes(extracted_a_1, a_1) assert_same_attributes(extracted_a_1b, a_1) # test getting an empty list by searching for a non-existent property empty1 = get_epochs(seg, foo='bar') self.assertEqual(len(empty1), 0) # test getting an empty list by searching for a non-existent property value empty2 = get_epochs(seg, epoch_type='undefined') self.assertEqual(len(empty2), 0) # test getting only one event time of one event trial_2 = get_epochs(block, trial_id=2, epoch_type='a') self.assertEqual(len(trial_2), 1) trial_2 = trial_2[0] self.assertEqual(a_1.name, trial_2.name) self.assertEqual(a_1.description, trial_2.description) self.assertEqual(a_1.file_origin, trial_2.file_origin) self.assertEqual(a_1.annotations['epoch_type'], trial_2.annotations['epoch_type']) assert_arrays_equal(trial_2.array_annotations['trial_id'], np.array([2])) self.assertIsInstance(trial_2.array_annotations, ArrayDict) # test getting only one event time of more than one event trial_2b = get_epochs(block, trial_id=2) self.assertEqual(len(trial_2b), 2) a_idx = np.where( np.array([ev.annotations['epoch_type'] for ev in trial_2b]) == 'a')[0][0] trial_2b_a = trial_2b[a_idx] trial_2b_b = trial_2b[a_idx - 1] assert_same_attributes(trial_2b_a, trial_2) self.assertEqual(b_1.name, trial_2b_b.name) self.assertEqual(b_1.description, trial_2b_b.description) self.assertEqual(b_1.file_origin, trial_2b_b.file_origin) self.assertEqual(b_1.annotations['epoch_type'], trial_2b_b.annotations['epoch_type']) assert_arrays_equal(trial_2b_b.array_annotations['trial_id'], np.array([2])) self.assertIsInstance(trial_2b_b.array_annotations, ArrayDict) # test getting more than one event time of one event trials_1_2 = get_epochs(block, trial_id=[1, 2], epoch_type='a') self.assertEqual(len(trials_1_2), 1) trials_1_2 = trials_1_2[0] self.assertEqual(a_1.name, trials_1_2.name) self.assertEqual(a_1.description, trials_1_2.description) self.assertEqual(a_1.file_origin, trials_1_2.file_origin) self.assertEqual(a_1.annotations['epoch_type'], trials_1_2.annotations['epoch_type']) assert_arrays_equal(trials_1_2.array_annotations['trial_id'], np.array([1, 2])) self.assertIsInstance(trials_1_2.array_annotations, ArrayDict) # test getting more than one event time of more than one event trials_1_2b = get_epochs(block, trial_id=[1, 2]) self.assertEqual(len(trials_1_2b), 2) a_idx = np.where( np.array([ev.annotations['epoch_type'] for ev in trials_1_2b]) == 'a')[0][0] trials_1_2b_a = trials_1_2b[a_idx] trials_1_2b_b = trials_1_2b[a_idx - 1] assert_same_attributes(trials_1_2b_a, trials_1_2) self.assertEqual(b_1.name, trials_1_2b_b.name) self.assertEqual(b_1.description, trials_1_2b_b.description) self.assertEqual(b_1.file_origin, trials_1_2b_b.file_origin) self.assertEqual(b_1.annotations['epoch_type'], trials_1_2b_b.annotations['epoch_type']) assert_arrays_equal(trials_1_2b_b.array_annotations['trial_id'], np.array([1, 2])) self.assertIsInstance(trials_1_2b_b.array_annotations, ArrayDict)
def plot_segment(seg, analist=(), spklist=(), epchlist=(), showevent=None, embedpeaks=True, recenter=None): anas = [x for x in seg.analogsignals if x.name in analist] spks = [x for x in seg.spiketrains if x.name in spklist] evts = next((e for e in seg.events if e.name == 'Events'), None) if not evts: warnings.warn("No Events presented in data. Turning showevent off.") showevent = False if (not anas) and (not spks): print("Empty data lists. Nothing plotted") return if not epchlist: if spks: tunit = spks[0].t_start.units tstart = np.min([s.t_start for s in spks]) tstop = np.max([s.t_stop for s in spks]) elif anas: tunit = anas[0].t_start.units tstart = np.min([a.t_start for a in anas]) tstop = np.max([np.max(a.times) for a in anas]) else: tunit = pq.s tstart = 0 tstop = 0 epchlist = [ Epoch(name='all', times=[tstart] * tunit, durations=[tstop - tstart] * tunit) ] else: epchlist = [ep for ep in seg.epochs if ep.name in epchlist] nrow = len(analist) + len(spklist) ncol = len(epchlist) fig = plt.figure(figsize=(ncol * 18, nrow * 6)) fig.suptitle(seg.name) gs = grdspc.GridSpec(nrow, ncol) for epid, epch in enumerate(epchlist): row = 0 cur_anas = [slice_signals(a, epch, recenter) for a in anas] cur_spks = [slice_signals(s, epch, recenter) for s in spks] if showevent: cur_evts = slice_signals(evts, epch, recenter) for ana in cur_anas: ax = fig.add_subplot(gs[row, epid]) for aid, a in enumerate(ana): ax.plot(a.times, a, linewidth=0.3, alpha=0.5, color='darkgrey') if embedpeaks: arrlen = (np.max(a) - np.min(a)) / 10 peaks = next( (spk[aid] for spk in cur_spks if spk[aid].name == a.name), []) for p in peaks: pidx = np.argmin(np.abs(a.times - p)) pidx = int(pidx) ax.annotate('', xy=(p, a[pidx]), xytext=(p, a[pidx] + arrlen), arrowprops={'arrowstyle': "->"}) if showevent: for et in cur_evts[aid].times: ax.add_patch( pch.Rectangle((et - showevent, np.min(a)), showevent * 2, np.max(a) - np.min(a), alpha=0.2, edgecolor='none')) ana_mean = np.mean(trim_signals(ana), axis=0) ax.plot(ana[0].times, ana_mean) ax.set_xlabel("time (s)") ax.set_ylabel("signal") # ax.set_ylim(0, 1) ax.set_title("Signal: " + ana[0].name + "\n" + epch.name) row += 1 for spk in cur_spks: ax = fig.add_subplot(gs[row, epid]) for sid, s in enumerate(spk): if s.times.size: ax.vlines(s.times, sid, sid + 1) if showevent: for et in cur_evts[sid].times: ax.add_patch( pch.Rectangle((et - showevent, sid), showevent * 2, 1, alpha=0.2, edgecolor='none')) ax.set_title("Signal: " + spk[0].name + "\n" + epch.name) ax.set_xlabel("time (s)") ax.set_ylabel("spike ID") row += 1 return fig
def test__cut_block_by_epochs(self): epoch = Epoch([0.5, 10.0, 25.2] * pq.s, durations=[5.1, 4.8, 5.0] * pq.s, t_start=.1 * pq.s) epoch.annotate(epoch_type='a', pick='me') epoch.array_annotate(trial_id=[1, 2, 3]) 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() seg2 = Segment(name='NoCut') seg.epochs = [epoch, epoch2] seg.events = [event] seg.analogsignals = [anasig] seg.irregularlysampledsignals = [irrsig] seg.spiketrains = [st] block = Block() block.segments = [seg, seg2] block.create_many_to_one_relationship() # test without resetting the time cut_block_by_epochs(block, properties={'pick': 'me'}) assert_neo_object_is_compliant(block) self.assertEqual(len(block.segments), 3) for epoch_idx in range(len(epoch)): self.assertEqual(len(block.segments[epoch_idx].events), 1) self.assertEqual(len(block.segments[epoch_idx].spiketrains), 1) self.assertEqual(len(block.segments[epoch_idx].analogsignals), 1) self.assertEqual( len(block.segments[epoch_idx].irregularlysampledsignals), 1) if epoch_idx != 0: self.assertEqual(len(block.segments[epoch_idx].epochs), 1) else: self.assertEqual(len(block.segments[epoch_idx].epochs), 2) assert_same_attributes( block.segments[epoch_idx].spiketrains[0], st.time_slice(t_start=epoch.times[epoch_idx], t_stop=epoch.times[epoch_idx] + epoch.durations[epoch_idx])) assert_same_attributes( block.segments[epoch_idx].analogsignals[0], anasig.time_slice(t_start=epoch.times[epoch_idx], t_stop=epoch.times[epoch_idx] + epoch.durations[epoch_idx])) assert_same_attributes( block.segments[epoch_idx].irregularlysampledsignals[0], irrsig.time_slice(t_start=epoch.times[epoch_idx], t_stop=epoch.times[epoch_idx] + epoch.durations[epoch_idx])) assert_same_attributes( block.segments[epoch_idx].events[0], event.time_slice(t_start=epoch.times[epoch_idx], t_stop=epoch.times[epoch_idx] + epoch.durations[epoch_idx])) assert_same_attributes( block.segments[0].epochs[0], epoch.time_slice(t_start=epoch.times[0], t_stop=epoch.times[0] + epoch.durations[0])) assert_same_attributes( block.segments[0].epochs[1], epoch2.time_slice(t_start=epoch.times[0], t_stop=epoch.times[0] + epoch.durations[0])) seg = Segment() seg2 = Segment(name='NoCut') seg.epochs = [epoch, epoch2] seg.events = [event] seg.analogsignals = [anasig] seg.irregularlysampledsignals = [irrsig] seg.spiketrains = [st] block = Block() block.segments = [seg, seg2] block.create_many_to_one_relationship() # test with resetting the time cut_block_by_epochs(block, properties={'pick': 'me'}, reset_time=True) assert_neo_object_is_compliant(block) self.assertEqual(len(block.segments), 3) for epoch_idx in range(len(epoch)): self.assertEqual(len(block.segments[epoch_idx].events), 1) self.assertEqual(len(block.segments[epoch_idx].spiketrains), 1) self.assertEqual(len(block.segments[epoch_idx].analogsignals), 1) self.assertEqual( len(block.segments[epoch_idx].irregularlysampledsignals), 1) if epoch_idx != 0: self.assertEqual(len(block.segments[epoch_idx].epochs), 1) else: self.assertEqual(len(block.segments[epoch_idx].epochs), 2) assert_same_attributes( block.segments[epoch_idx].spiketrains[0], st.time_shift(-epoch.times[epoch_idx]).time_slice( t_start=0 * pq.s, t_stop=epoch.durations[epoch_idx])) anasig_target = anasig.time_shift(-epoch.times[epoch_idx]) anasig_target = anasig_target.time_slice( t_start=0 * pq.s, t_stop=epoch.durations[epoch_idx]) assert_same_attributes(block.segments[epoch_idx].analogsignals[0], anasig_target) irrsig_target = irrsig.time_shift(-epoch.times[epoch_idx]) irrsig_target = irrsig_target.time_slice( t_start=0 * pq.s, t_stop=epoch.durations[epoch_idx]) assert_same_attributes( block.segments[epoch_idx].irregularlysampledsignals[0], irrsig_target) assert_same_attributes( block.segments[epoch_idx].events[0], event.time_shift(-epoch.times[epoch_idx]).time_slice( t_start=0 * pq.s, t_stop=epoch.durations[epoch_idx])) assert_same_attributes( block.segments[0].epochs[0], epoch.time_shift(-epoch.times[0]).time_slice( t_start=0 * pq.s, t_stop=epoch.durations[0])) assert_same_attributes( block.segments[0].epochs[1], epoch2.time_shift(-epoch.times[0]).time_slice( t_start=0 * pq.s, t_stop=epoch.durations[0]))
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 read_segment(self, lazy=False, cascade=True): fid = open(self.filename, 'rb') global_header = HeaderReader(fid, GlobalHeader).read_f(offset=0) # ~ print globalHeader #~ print 'version' , globalHeader['version'] seg = Segment() seg.file_origin = os.path.basename(self.filename) seg.annotate(neuroexplorer_version=global_header['version']) seg.annotate(comment=global_header['comment']) if not cascade: return seg offset = 544 for i in range(global_header['nvar']): entity_header = HeaderReader( fid, EntityHeader).read_f(offset=offset + i * 208) entity_header['name'] = entity_header['name'].replace('\x00', '') #print 'i',i, entityHeader['type'] if entity_header['type'] == 0: # neuron if lazy: spike_times = [] * pq.s else: spike_times = np.memmap(self.filename, np.dtype('i4'), 'r', shape=(entity_header['n']), offset=entity_header['offset']) spike_times = spike_times.astype( 'f8') / global_header['freq'] * pq.s sptr = SpikeTrain(times=spike_times, t_start=global_header['tbeg'] / global_header['freq'] * pq.s, t_stop=global_header['tend'] / global_header['freq'] * pq.s, name=entity_header['name']) if lazy: sptr.lazy_shape = entity_header['n'] sptr.annotate(channel_index=entity_header['WireNumber']) seg.spiketrains.append(sptr) if entity_header['type'] == 1: # event if lazy: event_times = [] * pq.s else: event_times = np.memmap(self.filename, np.dtype('i4'), 'r', shape=(entity_header['n']), offset=entity_header['offset']) event_times = event_times.astype( 'f8') / global_header['freq'] * pq.s labels = np.array([''] * event_times.size, dtype='S') evar = Event(times=event_times, labels=labels, channel_name=entity_header['name']) if lazy: evar.lazy_shape = entity_header['n'] seg.events.append(evar) if entity_header['type'] == 2: # interval if lazy: start_times = [] * pq.s stop_times = [] * pq.s else: start_times = np.memmap(self.filename, np.dtype('i4'), 'r', shape=(entity_header['n']), offset=entity_header['offset']) start_times = start_times.astype( 'f8') / global_header['freq'] * pq.s stop_times = np.memmap(self.filename, np.dtype('i4'), 'r', shape=(entity_header['n']), offset=entity_header['offset'] + entity_header['n'] * 4) stop_times = stop_times.astype( 'f') / global_header['freq'] * pq.s epar = Epoch(times=start_times, durations=stop_times - start_times, labels=np.array([''] * start_times.size, dtype='S'), channel_name=entity_header['name']) if lazy: epar.lazy_shape = entity_header['n'] seg.epochs.append(epar) if entity_header['type'] == 3: # spiketrain and wavefoms if lazy: spike_times = [] * pq.s waveforms = None else: spike_times = np.memmap(self.filename, np.dtype('i4'), 'r', shape=(entity_header['n']), offset=entity_header['offset']) spike_times = spike_times.astype( 'f8') / global_header['freq'] * pq.s waveforms = np.memmap(self.filename, np.dtype('i2'), 'r', shape=(entity_header['n'], 1, entity_header['NPointsWave']), offset=entity_header['offset'] + entity_header['n'] * 4) waveforms = ( waveforms.astype('f') * entity_header['ADtoMV'] + entity_header['MVOffset']) * pq.mV t_stop = global_header['tend'] / global_header['freq'] * pq.s if spike_times.size > 0: t_stop = max(t_stop, max(spike_times)) sptr = SpikeTrain( times=spike_times, t_start=global_header['tbeg'] / global_header['freq'] * pq.s, #~ t_stop = max(globalHeader['tend']/ #~ globalHeader['freq']*pq.s,max(spike_times)), t_stop=t_stop, name=entity_header['name'], waveforms=waveforms, sampling_rate=entity_header['WFrequency'] * pq.Hz, left_sweep=0 * pq.ms) if lazy: sptr.lazy_shape = entity_header['n'] sptr.annotate(channel_index=entity_header['WireNumber']) seg.spiketrains.append(sptr) if entity_header['type'] == 4: # popvectors pass if entity_header['type'] == 5: # analog timestamps = np.memmap(self.filename, np.dtype('i4'), 'r', shape=(entity_header['n']), offset=entity_header['offset']) timestamps = timestamps.astype('f8') / global_header['freq'] fragment_starts_offset = entity_header[ 'offset'] + entity_header['n'] * 4 fragment_starts = np.memmap(self.filename, np.dtype('i4'), 'r', shape=(entity_header['n']), offset=fragment_starts_offset) fragment_starts = fragment_starts.astype( 'f8') / global_header['freq'] t_start = timestamps[0] - fragment_starts[0] / float( entity_header['WFrequency']) del timestamps, fragment_starts if lazy: signal = [] * pq.mV else: signal_offset = fragment_starts_offset + entity_header[ 'n'] * 4 signal = np.memmap(self.filename, np.dtype('i2'), 'r', shape=(entity_header['NPointsWave']), offset=signal_offset) signal = signal.astype('f') signal *= entity_header['ADtoMV'] signal += entity_header['MVOffset'] signal = signal * pq.mV ana_sig = AnalogSignal( signal=signal, t_start=t_start * pq.s, sampling_rate=entity_header['WFrequency'] * pq.Hz, name=entity_header['name'], channel_index=entity_header['WireNumber']) if lazy: ana_sig.lazy_shape = entity_header['NPointsWave'] seg.analogsignals.append(ana_sig) if entity_header['type'] == 6: # markers : TO TEST if lazy: times = [] * pq.s labels = np.array([], dtype='S') markertype = None else: times = np.memmap(self.filename, np.dtype('i4'), 'r', shape=(entity_header['n']), offset=entity_header['offset']) times = times.astype('f8') / global_header['freq'] * pq.s fid.seek(entity_header['offset'] + entity_header['n'] * 4) markertype = fid.read(64).replace('\x00', '') labels = np.memmap( self.filename, np.dtype('S' + str(entity_header['MarkerLength'])), 'r', shape=(entity_header['n']), offset=entity_header['offset'] + entity_header['n'] * 4 + 64) ea = Event(times=times, labels=labels.view(np.ndarray), name=entity_header['name'], channel_index=entity_header['WireNumber'], marker_type=markertype) if lazy: ea.lazy_shape = entity_header['n'] seg.events.append(ea) seg.create_many_to_one_relationship() return seg
def _handle_timeseries(self, name, timeseries): # todo: check timeseries.attrs.get('schema_id') # todo: handle timeseries.attrs.get('source') subtype = timeseries.attrs['ancestry'][-1] data_group = timeseries.get('data') dtype = data_group.dtype if self._lazy: data = np.array((), dtype=dtype) lazy_shape = data_group.value.shape # inefficient to load the data to get the shape else: data = data_group.value if dtype.type is np.string_: if self._lazy: times = np.array(()) else: times = timeseries.get('timestamps') durations = timeseries.get('durations') if durations: # Epoch if self._lazy: durations = np.array(()) obj = Epoch(times=times, durations=durations, labels=data, units='second') else: # Event obj = Event(times=times, labels=data, units='second') else: units = get_units(data_group) if 'starting_time' in timeseries: # AnalogSignal sampling_metadata = timeseries.get('starting_time') t_start = sampling_metadata.value * pq.s sampling_rate = sampling_metadata.attrs.get('rate') * pq.Hz assert sampling_metadata.attrs.get('unit') == 'Seconds' # todo: handle data.attrs['resolution'] obj = AnalogSignal(data, units=units, sampling_rate=sampling_rate, t_start=t_start, name=name) elif 'timestamps' in timeseries: # IrregularlySampledSignal if self._lazy: time_data = np.array(()) else: time_data = timeseries.get('timestamps') assert time_data.attrs.get('unit') == 'Seconds' obj = IrregularlySampledSignal(time_data.value, data, units=units, time_units=pq.second) else: raise Exception("Timeseries group does not contain sufficient time information") if self._lazy: obj.lazy_shape = lazy_shape return obj
def _mtag_eest_to_neo(self, nix_mtag, lazy): neo_attrs = self._nix_attr_to_neo(nix_mtag) neo_type = nix_mtag.type time_unit = nix_mtag.positions.unit if lazy: times = pq.Quantity(np.empty(0), time_unit) lazy_shape = np.shape(nix_mtag.positions) else: times = pq.Quantity(nix_mtag.positions, time_unit) lazy_shape = None if neo_type == "neo.epoch": if lazy: durations = pq.Quantity(np.empty(0), nix_mtag.extents.unit) labels = np.empty(0, dtype='S') else: durations = pq.Quantity(nix_mtag.extents, nix_mtag.extents.unit) labels = np.array(nix_mtag.positions.dimensions[0].labels, dtype="S") eest = Epoch(times=times, durations=durations, labels=labels, **neo_attrs) elif neo_type == "neo.event": if lazy: labels = np.empty(0, dtype='S') else: labels = np.array(nix_mtag.positions.dimensions[0].labels, dtype="S") eest = Event(times=times, labels=labels, **neo_attrs) elif neo_type == "neo.spiketrain": if "t_start" in neo_attrs: if "t_start.units" in neo_attrs: t_start_units = neo_attrs["t_start.units"] del neo_attrs["t_start.units"] else: t_start_units = time_unit t_start = pq.Quantity(neo_attrs["t_start"], t_start_units) del neo_attrs["t_start"] else: t_start = None if "t_stop" in neo_attrs: if "t_stop.units" in neo_attrs: t_stop_units = neo_attrs["t_stop.units"] del neo_attrs["t_stop.units"] else: t_stop_units = time_unit t_stop = pq.Quantity(neo_attrs["t_stop"], t_stop_units) del neo_attrs["t_stop"] else: t_stop = None if "sampling_interval.units" in neo_attrs: interval_units = neo_attrs["sampling_interval.units"] del neo_attrs["sampling_interval.units"] else: interval_units = None if "left_sweep.units" in neo_attrs: left_sweep_units = neo_attrs["left_sweep.units"] del neo_attrs["left_sweep.units"] else: left_sweep_units = None eest = SpikeTrain(times=times, t_start=t_start, t_stop=t_stop, **neo_attrs) if len(nix_mtag.features): wfda = nix_mtag.features[0].data wftime = self._get_time_dimension(wfda) if lazy: eest.waveforms = pq.Quantity(np.empty((0, 0, 0)), wfda.unit) eest.sampling_period = pq.Quantity(1, wftime.unit) eest.left_sweep = pq.Quantity(0, wftime.unit) else: eest.waveforms = pq.Quantity(wfda, wfda.unit) if interval_units is None: interval_units = wftime.unit eest.sampling_period = pq.Quantity( wftime.sampling_interval, interval_units) if left_sweep_units is None: left_sweep_units = wftime.unit if "left_sweep" in wfda.metadata: eest.left_sweep = pq.Quantity( wfda.metadata["left_sweep"], left_sweep_units) else: return None self._object_map[nix_mtag.id] = eest if lazy_shape: eest.lazy_shape = lazy_shape return eest
def test__issue_285(self): # Spiketrain train = SpikeTrain([3, 4, 5] * pq.s, t_stop=10.0) unit = Unit() train.unit = unit unit.spiketrains.append(train) epoch = Epoch(np.array([0, 10, 20]), np.array([2, 2, 2]), np.array(["a", "b", "c"]), units="ms") blk = Block() seg = Segment() seg.spiketrains.append(train) seg.epochs.append(epoch) epoch.segment = seg blk.segments.append(seg) reader = PickleIO(filename="blk.pkl") reader.write(blk) reader = PickleIO(filename="blk.pkl") r_blk = reader.read_block() r_seg = r_blk.segments[0] self.assertIsInstance(r_seg.spiketrains[0].unit, Unit) self.assertIsInstance(r_seg.epochs[0], Epoch) os.remove('blk.pkl') # Epoch epoch = Epoch(times=np.arange(0, 30, 10) * pq.s, durations=[10, 5, 7] * pq.ms, labels=np.array(['btn0', 'btn1', 'btn2'], dtype='U')) epoch.segment = Segment() blk = Block() seg = Segment() seg.epochs.append(epoch) blk.segments.append(seg) reader = PickleIO(filename="blk.pkl") reader.write(blk) reader = PickleIO(filename="blk.pkl") r_blk = reader.read_block() r_seg = r_blk.segments[0] self.assertIsInstance(r_seg.epochs[0].segment, Segment) os.remove('blk.pkl') # Event event = Event(np.arange(0, 30, 10) * pq.s, labels=np.array(['trig0', 'trig1', 'trig2'], dtype='U')) event.segment = Segment() blk = Block() seg = Segment() seg.events.append(event) blk.segments.append(seg) reader = PickleIO(filename="blk.pkl") reader.write(blk) reader = PickleIO(filename="blk.pkl") r_blk = reader.read_block() r_seg = r_blk.segments[0] self.assertIsInstance(r_seg.events[0].segment, Segment) os.remove('blk.pkl') # IrregularlySampledSignal signal = IrregularlySampledSignal([0.0, 1.23, 6.78], [1, 2, 3], units='mV', time_units='ms') signal.segment = Segment() blk = Block() seg = Segment() seg.irregularlysampledsignals.append(signal) blk.segments.append(seg) blk.segments[0].block = blk reader = PickleIO(filename="blk.pkl") reader.write(blk) reader = PickleIO(filename="blk.pkl") r_blk = reader.read_block() r_seg = r_blk.segments[0] self.assertIsInstance(r_seg.irregularlysampledsignals[0].segment, Segment) os.remove('blk.pkl')
def read_segment( self, cascade=True, lazy=False, ): """ Arguments: """ f = StructFile(open(self.filename, 'rb')) # Name f.seek(64, 0) surname = f.read(22).decode('ascii') while surname[-1] == ' ': if len(surname) == 0: break surname = surname[:-1] firstname = f.read(20).decode('ascii') while firstname[-1] == ' ': if len(firstname) == 0: break firstname = firstname[:-1] #Date f.seek(128, 0) day, month, year, hour, minute, sec = f.read_f('bbbbbb') rec_datetime = datetime.datetime(year + 1900, month, day, hour, minute, sec) f.seek(138, 0) Data_Start_Offset, Num_Chan, Multiplexer, Rate_Min, Bytes = f.read_f( 'IHHHH') #~ print Num_Chan, Bytes #header version f.seek(175, 0) header_version, = f.read_f('b') assert header_version == 4 seg = Segment(name=str(firstname + ' ' + surname), file_origin=os.path.basename(self.filename)) seg.annotate(surname=surname) seg.annotate(firstname=firstname) seg.annotate(rec_datetime=rec_datetime) if not cascade: f.close() return seg # area f.seek(176, 0) zone_names = [ 'ORDER', 'LABCOD', 'NOTE', 'FLAGS', 'TRONCA', 'IMPED_B', 'IMPED_E', 'MONTAGE', 'COMPRESS', 'AVERAGE', 'HISTORY', 'DVIDEO', 'EVENT A', 'EVENT B', 'TRIGGER' ] zones = {} for zname in zone_names: zname2, pos, length = f.read_f('8sII') zones[zname] = zname2, pos, length #~ print zname2, pos, length # reading raw data if not lazy: f.seek(Data_Start_Offset, 0) rawdata = np.fromstring(f.read(), dtype='u' + str(Bytes)) rawdata = rawdata.reshape((-1, Num_Chan)) # Reading Code Info zname2, pos, length = zones['ORDER'] f.seek(pos, 0) code = np.fromstring(f.read(Num_Chan * 2), dtype='u2', count=Num_Chan) units = { -1: pq.nano * pq.V, 0: pq.uV, 1: pq.mV, 2: 1, 100: pq.percent, 101: pq.dimensionless, 102: pq.dimensionless } for c in range(Num_Chan): zname2, pos, length = zones['LABCOD'] f.seek(pos + code[c] * 128 + 2, 0) label = f.read(6).strip(b"\x00").decode('ascii') ground = f.read(6).strip(b"\x00").decode('ascii') (logical_min, logical_max, logical_ground, physical_min, physical_max) = f.read_f('iiiii') k, = f.read_f('h') if k in units.keys(): unit = units[k] else: unit = pq.uV f.seek(8, 1) sampling_rate, = f.read_f('H') * pq.Hz sampling_rate *= Rate_Min if lazy: signal = [] * unit else: factor = float(physical_max - physical_min) / float(logical_max - logical_min + 1) signal = (rawdata[:, c].astype('f') - logical_ground) * factor * unit ana_sig = AnalogSignal(signal, sampling_rate=sampling_rate, name=str(label), channel_index=c) if lazy: ana_sig.lazy_shape = None ana_sig.annotate(ground=ground) seg.analogsignals.append(ana_sig) sampling_rate = np.mean( [ana_sig.sampling_rate for ana_sig in seg.analogsignals]) * pq.Hz # Read trigger and notes for zname, label_dtype in [('TRIGGER', 'u2'), ('NOTE', 'S40')]: zname2, pos, length = zones[zname] f.seek(pos, 0) triggers = np.fromstring(f.read(length), dtype=[('pos', 'u4'), ('label', label_dtype)]) if not lazy: keep = (triggers['pos'] >= triggers['pos'][0]) & ( triggers['pos'] < rawdata.shape[0]) & (triggers['pos'] != 0) triggers = triggers[keep] ea = Event(name=zname[0] + zname[1:].lower(), labels=triggers['label'].astype('S'), times=(triggers['pos'] / sampling_rate).rescale('s')) else: ea = Event(name=zname[0] + zname[1:].lower()) ea.lazy_shape = triggers.size seg.events.append(ea) # Read Event A and B # Not so well tested for zname in ['EVENT A', 'EVENT B']: zname2, pos, length = zones[zname] f.seek(pos, 0) epochs = np.fromstring(f.read(length), dtype=[ ('label', 'u4'), ('start', 'u4'), ('stop', 'u4'), ]) ep = Epoch(name=zname[0] + zname[1:].lower()) if not lazy: keep = (epochs['start'] > 0) & ( epochs['start'] < rawdata.shape[0]) & (epochs['stop'] < rawdata.shape[0]) epochs = epochs[keep] ep = Epoch(name=zname[0] + zname[1:].lower(), labels=epochs['label'].astype('S'), times=(epochs['start'] / sampling_rate).rescale('s'), durations=((epochs['stop'] - epochs['start']) / sampling_rate).rescale('s')) else: ep = Epoch(name=zname[0] + zname[1:].lower()) ep.lazy_shape = triggers.size seg.epochs.append(ep) seg.create_many_to_one_relationship() f.close() return seg