baseio.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. """
  2. baseio
  3. ======
  4. Classes
  5. -------
  6. BaseIO - abstract class which should be overridden, managing how a
  7. file will load/write its data
  8. If you want a model for developing a new IO start from exampleIO.
  9. """
  10. try:
  11. from collections.abc import Sequence
  12. except ImportError:
  13. from collections import Sequence
  14. import logging
  15. from neo import logging_handler
  16. from neo.core import (AnalogSignal, Block,
  17. Epoch, Event, Group,
  18. IrregularlySampledSignal,
  19. ChannelIndex, ChannelView,
  20. Segment, SpikeTrain, Unit, ImageSequence,
  21. RectangularRegionOfInterest, CircularRegionOfInterest,
  22. PolygonRegionOfInterest)
  23. read_error = "This type is not supported by this file format for reading"
  24. write_error = "This type is not supported by this file format for writing"
  25. class BaseIO:
  26. """
  27. Generic class to handle all the file read/write methods for the key objects
  28. of the core class. This template is file-reading/writing oriented but it
  29. can also handle data read from/written to a database such as TDT sytem
  30. tanks or SQLite files.
  31. This is an abstract class that will be subclassed for each format
  32. The key methods of the class are:
  33. - ``read()`` - Read the whole object structure, return a list of Block
  34. objects
  35. - ``read_block(lazy=True, **params)`` - Read Block object
  36. from file with some parameters
  37. - ``read_segment(lazy=True, **params)`` - Read Segment
  38. object from file with some parameters
  39. - ``read_spiketrainlist(lazy=True, **params)`` - Read
  40. SpikeTrainList object from file with some parameters
  41. - ``write()`` - Write the whole object structure
  42. - ``write_block(**params)`` - Write Block object to file with some
  43. parameters
  44. - ``write_segment(**params)`` - Write Segment object to file with
  45. some parameters
  46. - ``write_spiketrainlist(**params)`` - Write SpikeTrainList object to
  47. file with some parameters
  48. The class can also implement these methods:
  49. - ``read_XXX(lazy=True, **params)``
  50. - ``write_XXX(**params)``
  51. where XXX could be one of the objects supported by the IO
  52. Each class is able to declare what can be accessed or written directly
  53. discribed by **readable_objects** and **readable_objects**.
  54. The object types can be one of the classes defined in neo.core
  55. (Block, Segment, AnalogSignal, ...)
  56. Each class does not necessary support all the whole neo hierarchy but part
  57. of it.
  58. This is described with **supported_objects**.
  59. All IOs must support at least Block with a read_block()
  60. ** start a new IO **
  61. If you want to implement your own file format, you should create a class
  62. that will inherit from this BaseFile class and implement the previous
  63. methods.
  64. See ExampleIO in exampleio.py
  65. """
  66. is_readable = False
  67. is_writable = False
  68. supported_objects = []
  69. readable_objects = []
  70. writeable_objects = []
  71. support_lazy = False
  72. read_params = {}
  73. write_params = {}
  74. name = 'BaseIO'
  75. description = ''
  76. extensions = []
  77. mode = 'file' # or 'fake' or 'dir' or 'database'
  78. def __init__(self, filename=None, **kargs):
  79. self.filename = filename
  80. # create a logger for the IO class
  81. fullname = self.__class__.__module__ + '.' + self.__class__.__name__
  82. self.logger = logging.getLogger(fullname)
  83. # create a logger for 'neo' and add a handler to it if it doesn't
  84. # have one already.
  85. # (it will also not add one if the root logger has a handler)
  86. corename = self.__class__.__module__.split('.')[0]
  87. corelogger = logging.getLogger(corename)
  88. rootlogger = logging.getLogger()
  89. if not corelogger.handlers and not rootlogger.handlers:
  90. corelogger.addHandler(logging_handler)
  91. ######## General read/write methods #######################
  92. def read(self, lazy=False, **kargs):
  93. """
  94. Return all data from the file as a list of Blocks
  95. """
  96. if lazy and not self.support_lazy:
  97. raise ValueError("This IO module does not support lazy loading")
  98. if Block in self.readable_objects:
  99. if (hasattr(self, 'read_all_blocks') and
  100. callable(getattr(self, 'read_all_blocks'))):
  101. return self.read_all_blocks(lazy=lazy, **kargs)
  102. return [self.read_block(lazy=lazy, **kargs)]
  103. elif Segment in self.readable_objects:
  104. bl = Block(name='One segment only')
  105. seg = self.read_segment(lazy=lazy, **kargs)
  106. bl.segments.append(seg)
  107. bl.create_many_to_one_relationship()
  108. return [bl]
  109. else:
  110. raise NotImplementedError
  111. def write(self, bl, **kargs):
  112. if Block in self.writeable_objects:
  113. if isinstance(bl, Sequence):
  114. assert hasattr(self, 'write_all_blocks'), \
  115. '%s does not offer to store a sequence of blocks' % \
  116. self.__class__.__name__
  117. self.write_all_blocks(bl, **kargs)
  118. else:
  119. self.write_block(bl, **kargs)
  120. elif Segment in self.writeable_objects:
  121. assert len(bl.segments) == 1, \
  122. '%s is based on segment so if you try to write a block it ' + \
  123. 'must contain only one Segment' % self.__class__.__name__
  124. self.write_segment(bl.segments[0], **kargs)
  125. else:
  126. raise NotImplementedError
  127. ######## All individual read methods #######################
  128. def read_block(self, **kargs):
  129. assert (Block in self.readable_objects), read_error
  130. def read_segment(self, **kargs):
  131. assert (Segment in self.readable_objects), read_error
  132. def read_unit(self, **kargs):
  133. assert (Unit in self.readable_objects), read_error
  134. def read_spiketrain(self, **kargs):
  135. assert (SpikeTrain in self.readable_objects), read_error
  136. def read_analogsignal(self, **kargs):
  137. assert (AnalogSignal in self.readable_objects), read_error
  138. def read_imagesequence(self, **kargs):
  139. assert (ImageSequence in self.readable_objects), read_error
  140. def read_rectangularregionofinterest(self, **kargs):
  141. assert (RectangularRegionOfInterest in self.readable_objects), read_error
  142. def read_circularregionofinterest(self, **kargs):
  143. assert (CircularRegionOfInterest in self.readable_objects), read_error
  144. def read_polygonregionofinterest(self, **kargs):
  145. assert (PolygonRegionOfInterest in self.readable_objects), read_error
  146. def read_irregularlysampledsignal(self, **kargs):
  147. assert (IrregularlySampledSignal in self.readable_objects), read_error
  148. def read_channelindex(self, **kargs):
  149. assert (ChannelIndex in self.readable_objects), read_error
  150. def read_channelview(self, **kargs):
  151. assert (ChannelView in self.readable_objects), read_error
  152. def read_event(self, **kargs):
  153. assert (Event in self.readable_objects), read_error
  154. def read_epoch(self, **kargs):
  155. assert (Epoch in self.readable_objects), read_error
  156. def read_group(self, **kargs):
  157. assert (Group in self.readable_objects), read_error
  158. ######## All individual write methods #######################
  159. def write_block(self, bl, **kargs):
  160. assert (Block in self.writeable_objects), write_error
  161. def write_segment(self, seg, **kargs):
  162. assert (Segment in self.writeable_objects), write_error
  163. def write_unit(self, ut, **kargs):
  164. assert (Unit in self.writeable_objects), write_error
  165. def write_spiketrain(self, sptr, **kargs):
  166. assert (SpikeTrain in self.writeable_objects), write_error
  167. def write_analogsignal(self, anasig, **kargs):
  168. assert (AnalogSignal in self.writeable_objects), write_error
  169. def write_imagesequence(self, imseq, **kargs):
  170. assert (ImageSequence in self.writeable_objects), write_error
  171. def write_rectangularregionofinterest(self, rectroi, **kargs):
  172. assert (RectangularRegionOfInterest in self.writeable_objects), read_error
  173. def write_circularregionofinterest(self, circroi, **kargs):
  174. assert (CircularRegionOfInterest in self.writeable_objects), read_error
  175. def write_polygonregionofinterest(self, polyroi, **kargs):
  176. assert (PolygonRegionOfInterest in self.writeable_objects), read_error
  177. def write_irregularlysampledsignal(self, irsig, **kargs):
  178. assert (IrregularlySampledSignal in self.writeable_objects), write_error
  179. def write_channelindex(self, chx, **kargs):
  180. assert (ChannelIndex in self.writeable_objects), write_error
  181. def write_channelview(self, chv, **kargs):
  182. assert (ChannelView in self.writeable_objects), write_error
  183. def write_event(self, ev, **kargs):
  184. assert (Event in self.writeable_objects), write_error
  185. def write_epoch(self, ep, **kargs):
  186. assert (Epoch in self.writeable_objects), write_error
  187. def write_group(self, group, **kargs):
  188. assert (Group in self.writeable_objects), write_error