123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- # -*- coding: utf-8 -*-
- """
- Tools for IO coder:
- * Creating RecordingChannel and making links with AnalogSignals and
- SPikeTrains
- """
- import collections
- import numpy as np
- from neo.core import (AnalogSignal, Block,
- Epoch, Event,
- IrregularlySampledSignal,
- ChannelIndex,
- Segment, SpikeTrain, Unit)
- #def finalize_block(block):
- # populate_RecordingChannel(block)
- # block.create_many_to_one_relationship()
- # Special case this tricky many-to-many relationship
- # we still need links from recordingchannel to analogsignal
- # for chx in block.channel_indexes:
- # for rc in chx.recordingchannels:
- # rc.create_many_to_one_relationship()
- # def populate_RecordingChannel(bl, remove_from_annotation=True):
- # """
- # When a Block is
- # Block>Segment>AnalogSIgnal
- # this function auto create all RecordingChannel following these rules:
- # * when 'channel_index ' is in AnalogSIgnal the corresponding
- # RecordingChannel is created.
- # * 'channel_index ' is then set to None if remove_from_annotation
- # * only one ChannelIndex is created
- #
- # It is a utility at the end of creating a Block for IO.
- #
- # Usage:
- # >>> populate_RecordingChannel(a_block)
- # """
- # recordingchannels = {}
- # for seg in bl.segments:
- # for anasig in seg.analogsignals:
- # if getattr(anasig, 'channel_index', None) is not None:
- # ind = int(anasig.channel_index)
- # if ind not in recordingchannels:
- # recordingchannels[ind] = RecordingChannel(index=ind)
- # if 'channel_name' in anasig.annotations:
- # channel_name = anasig.annotations['channel_name']
- # recordingchannels[ind].name = channel_name
- # if remove_from_annotation:
- # anasig.annotations.pop('channel_name')
- # recordingchannels[ind].analogsignals.append(anasig)
- # anasig.recordingchannel = recordingchannels[ind]
- # if remove_from_annotation:
- # anasig.channel_index = None
- #
- # indexes = np.sort(list(recordingchannels.keys())).astype('i')
- # names = np.array([recordingchannels[idx].name for idx in indexes],
- # dtype='S')
- # chx = ChannelIndex(name='all channels',
- # index=indexes,
- # channel_names=names)
- # bl.channel_indexes.append(chx)
- # for ind in indexes:
- # # many to many relationship
- # chx.recordingchannels.append(recordingchannels[ind])
- # recordingchannels[ind].channel_indexes.append(chx)
- def iteritems(D):
- try:
- return D.iteritems() # Python 2
- except AttributeError:
- return D.items() # Python 3
- class LazyList(collections.MutableSequence):
- """ An enhanced list that can load its members on demand. Behaves exactly
- like a regular list for members that are Neo objects. Each item should
- contain the information that ``load_lazy_cascade`` needs to load the
- respective object.
- """
- _container_objects = set(
- [Block, Segment, ChannelIndex, Unit])
- _neo_objects = _container_objects.union(
- [AnalogSignal, Epoch, Event,
- IrregularlySampledSignal, SpikeTrain])
- def __init__(self, io, lazy, items=None):
- """
- :param io: IO instance that can load items.
- :param lazy: Lazy parameter with which the container object
- using the list was loaded.
- :param items: Optional, initial list of items.
- """
- if items is None:
- self._data = []
- else:
- self._data = items
- self._lazy = lazy
- self._io = io
- def __getitem__(self, index):
- item = self._data.__getitem__(index)
- if isinstance(index, slice):
- return LazyList(self._io, item)
- if type(item) in self._neo_objects:
- return item
- loaded = self._io.load_lazy_cascade(item, self._lazy)
- self._data[index] = loaded
- return loaded
- def __delitem__(self, index):
- self._data.__delitem__(index)
- def __len__(self):
- return self._data.__len__()
- def __setitem__(self, index, value):
- self._data.__setitem__(index, value)
- def insert(self, index, value):
- self._data.insert(index, value)
- def append(self, value):
- self._data.append(value)
- def reverse(self):
- self._data.reverse()
- def extend(self, values):
- self._data.extend(values)
- def remove(self, value):
- self._data.remove(value)
- def __str__(self):
- return '<' + self.__class__.__name__ + '>' + self._data.__str__()
- def __repr__(self):
- return '<' + self.__class__.__name__ + '>' + self._data.__repr__()
|