rawbinarysignalio.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. # -*- coding: utf-8 -*-
  2. """
  3. Class for reading/writing data in a raw binary interleaved compact file.
  4. Sampling rate, units, number of channel and dtype must be externally known.
  5. This generic format is quite widely used in old acquisition systems and is quite universal
  6. for sharing data.
  7. Supported : Read/Write
  8. Author: sgarcia
  9. """
  10. import os
  11. import numpy as np
  12. import quantities as pq
  13. from neo.io.baseio import BaseIO
  14. from neo.core import Segment, AnalogSignal
  15. from neo.io.basefromrawio import BaseFromRaw
  16. from neo.rawio.rawbinarysignalrawio import RawBinarySignalRawIO
  17. class RawBinarySignalIO(RawBinarySignalRawIO, BaseFromRaw):
  18. """
  19. Class for reading/writing data in a raw binary interleaved compact file.
  20. **Important release note**
  21. Since the version neo 0.6.0 and the neo.rawio API,
  22. argmuents of the IO (dtype, nb_channel, sampling_rate) must be
  23. given at the __init__ and not at read_segment() because there is
  24. no read_segment() in neo.rawio classes.
  25. So now the usage is:
  26. >>>>r = io.RawBinarySignalIO(filename='file.raw', dtype='int16',
  27. nb_channel=16, sampling_rate=10000.)
  28. """
  29. _prefered_signal_group_mode = 'split-all'
  30. is_readable = True
  31. is_writable = True
  32. supported_objects = [Segment, AnalogSignal]
  33. readable_objects = [Segment]
  34. writeable_objects = [Segment]
  35. def __init__(self, filename, dtype='int16', sampling_rate=10000.,
  36. nb_channel=2, signal_gain=1., signal_offset=0., bytesoffset=0):
  37. RawBinarySignalRawIO.__init__(self, filename=filename, dtype=dtype,
  38. sampling_rate=sampling_rate, nb_channel=nb_channel,
  39. signal_gain=signal_gain,
  40. signal_offset=signal_offset, bytesoffset=bytesoffset)
  41. BaseFromRaw.__init__(self, filename)
  42. def write_segment(self, segment):
  43. """
  44. **Arguments**
  45. segment : the segment to write. Only analog signals will be written.
  46. Support only 2 cases:
  47. * segment.analogsignals have one 2D AnalogSignal
  48. * segment.analogsignals have several 1D AnalogSignal with
  49. same length/sampling_rate/dtype
  50. """
  51. if self.bytesoffset:
  52. raise NotImplementedError('bytesoffset values other than 0 ' +
  53. 'not supported')
  54. anasigs = segment.analogsignals
  55. assert len(anasigs) > 0, 'No AnalogSignal'
  56. anasig0 = anasigs[0]
  57. if len(anasigs) == 1 and anasig0.ndim == 2:
  58. numpy_sigs = anasig0.magnitude
  59. else:
  60. assert anasig0.ndim == 1 or (anasig0.ndim == 2 and anasig0.shape[1] == 1)
  61. # all AnaologSignal from Segment must have the same length/sampling_rate/dtype
  62. for anasig in anasigs[1:]:
  63. assert anasig.shape == anasig0.shape
  64. assert anasig.sampling_rate == anasig0.sampling_rate
  65. assert anasig.dtype == anasig0.dtype
  66. numpy_sigs = np.empty((anasig0.size, len(anasigs)))
  67. for i, anasig in enumerate(anasigs):
  68. numpy_sigs[:, i] = anasig.magnitude.flatten()
  69. numpy_sigs -= self.signal_offset
  70. numpy_sigs /= self.signal_gain
  71. numpy_sigs = numpy_sigs.astype(self.dtype)
  72. with open(self.filename, 'wb') as f:
  73. f.write(numpy_sigs.tobytes())