Scheduled service maintenance on November 22


On Friday, November 22, 2024, between 06:00 CET and 18:00 CET, GIN services will undergo planned maintenance. Extended service interruptions should be expected. We will try to keep downtimes to a minimum, but recommend that users avoid critical tasks, large data uploads, or DOI requests during this time.

We apologize for any inconvenience.

io.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. ******
  2. Neo IO
  3. ******
  4. .. currentmodule:: neo
  5. Preamble
  6. ========
  7. The Neo :mod:`io` module aims to provide an exhaustive way of loading and saving several widely used data formats in electrophysiology.
  8. The more these heterogeneous formats are supported, the easier it will be to manipulate them as Neo objects in a similar way.
  9. Therefore the IO set of classes propose a simple and flexible IO API that fits many format specifications.
  10. It is not only file-oriented, it can also read/write objects from a database.
  11. At the moment, there are 3 families of IO modules:
  12. 1. for reading closed manufacturers' formats (Spike2, Plexon, AlphaOmega, BlackRock, Axon, ...)
  13. 2. for reading(/writing) formats from open source tools (KlustaKwik, Elan, WinEdr, WinWcp, ...)
  14. 3. for reading/writing Neo structure in neutral formats (HDF5, .mat, ...) but with Neo structure inside (NeoHDF5, NeoMatlab, ...)
  15. Combining **1** for reading and **3** for writing is a good example of use: converting your datasets
  16. to a more standard format when you want to share/collaborate.
  17. Introduction
  18. ============
  19. There is an intrinsic structure in the different Neo objects, that could be seen as a hierachy with cross-links. See :doc:`core`.
  20. The highest level object is the :class:`Block` object, which is the high level container able to encapsulate all the others.
  21. A :class:`Block` has therefore a list of :class:`Segment` objects, that can, in some file formats, be accessed individually.
  22. Depending on the file format, i.e. if it is streamable or not, the whole :class:`Block` may need to be loaded, but sometimes
  23. particular :class:`Segment` objects can be accessed individually.
  24. Within a :class:`Segment`, the same hierarchical organisation applies.
  25. A :class:`Segment` embeds several objects, such as :class:`SpikeTrain`,
  26. :class:`AnalogSignal`, :class:`IrregularlySampledSignal`, :class:`Epoch`, :class:`Event`
  27. (basically, all the different Neo objects).
  28. Depending on the file format, these objects can sometimes be loaded separately, without the need to load the whole file.
  29. If possible, a file IO therefore provides distinct methods allowing to load only particular objects that may be present in the file.
  30. The basic idea of each IO file format is to have, as much as possible, read/write methods for the individual encapsulated objects,
  31. and otherwise to provide a read/write method that will return the object at the highest level of hierarchy
  32. (by default, a :class:`Block` or a :class:`Segment`).
  33. The :mod:`neo.io` API is a balance between full flexibility for the user (all :meth:`read_XXX` methods are enabled)
  34. and simple, clean and understandable code for the developer (few :meth:`read_XXX` methods are enabled).
  35. This means that not all IOs offer the full flexibility for partial reading of data files.
  36. One format = one class
  37. ======================
  38. The basic syntax is as follows. If you want to load a file format that is implemented in a generic :class:`MyFormatIO` class::
  39. >>> from neo.io import MyFormatIO
  40. >>> reader = MyFormatIO(filename="myfile.dat")
  41. you can replace :class:`MyFormatIO` by any implemented class, see :ref:`list_of_io`
  42. Modes
  43. ======
  44. IO can be based on a single file, a directory containing files, or a database.
  45. This is described in the :attr:`mode` attribute of the IO class.
  46. >>> from neo.io import MyFormatIO
  47. >>> print MyFormatIO.mode
  48. 'file'
  49. For *file* mode the *filename* keyword argument is necessary.
  50. For *directory* mode the *dirname* keyword argument is necessary.
  51. Ex:
  52. >>> reader = io.PlexonIO(filename='File_plexon_1.plx')
  53. >>> reader = io.TdtIO(dirname='aep_05')
  54. Supported objects/readable objects
  55. ==================================
  56. To know what types of object are supported by a given IO interface::
  57. >>> MyFormatIO.supported_objects
  58. [Segment , AnalogSignal , SpikeTrain, Event, Spike]
  59. Supported objects does not mean objects that you can read directly. For instance, many formats support :class:`AnalogSignal`
  60. but don't allow them to be loaded directly, rather to access the :class:`AnalogSignal` objects, you must read a :class:`Segment`::
  61. >>> seg = reader.read_segment()
  62. >>> print(seg.analogsignals)
  63. >>> print(seg.analogsignals[0])
  64. To get a list of directly readable objects ::
  65. >>> MyFormatIO.readable_objects
  66. [Segment]
  67. The first element of the previous list is the highest level for reading the file. This mean that the IO has a :meth:`read_segment` method::
  68. >>> seg = reader.read_segment()
  69. >>> type(seg)
  70. neo.core.Segment
  71. All IOs have a read() method that returns a list of :class:`Block` objects (representing the whole content of the file)::
  72. >>> bl = reader.read()
  73. >>> print bl[0].segments[0]
  74. neo.core.Segment
  75. Lazy option (deprecated)
  76. ========================
  77. In some cases you may not want to load everything in memory because it could be too big.
  78. For this scenario, some IOs implement ``lazy=True/False``. With ``lazy=True`` all arrays will have a size of zero,
  79. but all the metadata will be loaded. The *lazy_shape* attribute is added to all array-like objects
  80. (AnalogSignal, IrregularlySampledSignal, SpikeTrain, Epoch, Event).
  81. In this case, *lazy_shape* is a tuple that has the same value as *shape* with ``lazy=False``.
  82. To know if a class supports lazy mode use ``ClassIO.support_lazy``.
  83. By default (if not specified), ``lazy=False``, i.e. all data is loaded.
  84. The lazy option will be removed in future Neo versions. Similar functionality will be
  85. implemented using proxy objects.
  86. Example of lazy loading::
  87. >>> seg = reader.read_segment(lazy=False)
  88. >>> print(seg.analogsignals[0].shape) # this is (N, M)
  89. >>> seg = reader.read_segment(lazy=True)
  90. >>> print(seg.analogsignals[0].shape) # this is 0, the AnalogSignal is empty
  91. >>> print(seg.analogsignals[0].lazy_shape) # this is (N, M)
  92. .. _neo_io_API:
  93. Details of API
  94. ==============
  95. The :mod:`neo.io` API is designed to be simple and intuitive:
  96. - each file format has an IO class (for example for Spike2 files you have a :class:`Spike2IO` class).
  97. - each IO class inherits from the :class:`BaseIO` class.
  98. - each IO class can read or write directly one or several Neo objects (for example :class:`Segment`, :class:`Block`, ...): see the :attr:`readable_objects` and :attr:`writable_objects` attributes of the IO class.
  99. - each IO class supports part of the :mod:`neo.core` hierachy, though not necessarily all of it (see :attr:`supported_objects`).
  100. - each IO class has a :meth:`read()` method that returns a list of :class:`Block` objects. If the IO only supports :class:`Segment` reading, the list will contain one block with all segments from the file.
  101. - each IO class that supports writing has a :meth:`write()` method that takes as a parameter a list of blocks, a single block or a single segment, depending on the IO's :attr:`writable_objects`.
  102. - each IO is able to do a *lazy* load: all metadata (e.g. :attr:`sampling_rate`) are read, but not the actual numerical data. lazy_shape attribute is added to provide information on real size.
  103. - each IO is able to save and load all required attributes (metadata) of the objects it supports.
  104. - each IO can freely add user-defined or manufacturer-defined metadata to the :attr:`annotations` attribute of an object.
  105. If you want to develop your own IO
  106. ==================================
  107. See :doc:`io_developers_guide` for information on how to implement a new IO.
  108. .. _list_of_io:
  109. List of implemented formats
  110. ===========================
  111. .. automodule:: neo.io
  112. Logging
  113. =======
  114. :mod:`neo` uses the standard Python :mod:`logging` module for logging.
  115. All :mod:`neo.io` classes have logging set up by default, although not all classes produce log messages.
  116. The logger name is the same as the full qualified class name, e.g. :class:`neo.io.hdf5io.NeoHdf5IO`.
  117. By default, only log messages that are critically important for users are displayed, so users should not disable log messages unless they are sure they know what they are doing.
  118. However, if you wish to disable the messages, you can do so::
  119. >>> import logging
  120. >>>
  121. >>> logger = logging.getLogger('neo')
  122. >>> logger.setLevel(100)
  123. Some io classes provide additional information that might be interesting to advanced users.
  124. To enable these messages, do the following::
  125. >>> import logging
  126. >>>
  127. >>> logger = logging.getLogger('neo')
  128. >>> logger.setLevel(logging.INFO)
  129. It is also possible to log to a file in addition to the terminal::
  130. >>> import logging
  131. >>>
  132. >>> logger = logging.getLogger('neo')
  133. >>> handler = logging.FileHandler('filename.log')
  134. >>> logger.addHandler(handler)
  135. To only log to the terminal::
  136. >>> import logging
  137. >>> from neo import logging_handler
  138. >>>
  139. >>> logger = logging.getLogger('neo')
  140. >>> handler = logging.FileHandler('filename.log')
  141. >>> logger.addHandler(handler)
  142. >>>
  143. >>> logging_handler.setLevel(100)
  144. This can also be done for individual IO classes::
  145. >>> import logging
  146. >>>
  147. >>> logger = logging.getLogger('neo.io.hdf5io.NeoHdf5IO')
  148. >>> handler = logging.FileHandler('filename.log')
  149. >>> logger.addHandler(handler)
  150. Individual IO classes can have their loggers disabled as well::
  151. >>> import logging
  152. >>>
  153. >>> logger = logging.getLogger('neo.io.hdf5io.NeoHdf5IO')
  154. >>> logger.setLevel(100)
  155. And more detailed logging messages can be enabled for individual IO classes::
  156. >>> import logging
  157. >>>
  158. >>> logger = logging.getLogger('neo.io.hdf5io.NeoHdf5IO')
  159. >>> logger.setLevel(logging.INFO)
  160. The default handler, which is used to print logs to the command line, is stored in :attr:`neo.logging_handler`.
  161. This example changes how the log text is displayed::
  162. >>> import logging
  163. >>> from neo import logging_handler
  164. >>>
  165. >>> formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  166. >>> logging_handler.setFormatter(formatter)
  167. For more complex logging, please see the documentation for the logging_ module.
  168. .. note:: If you wish to implement more advanced logging as describe in the documentation for the logging_ module or elsewhere on the internet, please do so before calling any :mod:`neo` functions or initializing any :mod:`neo` classes.
  169. This is because the default handler is created when :mod:`neo` is imported, but it is not attached to the :mod:`neo` logger until a class that uses logging is initialized or a function that uses logging is called.
  170. Further, the handler is only attached if there are no handlers already attached to the root logger or the :mod:`neo` logger, so adding your own logger will override the default one.
  171. Additional functions and/or classes may get logging during bugfix releases, so code relying on particular modules not having logging may break at any time without warning.
  172. .. _`logging`: http://docs.python.org/library/logging.html