McsCMOS.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. """
  2. McsCMOS
  3. ~~~~~~~
  4. Wrapper and Helper to access MCS CMOS Data within H5 Files
  5. :copyright: (c) 2015 by Multi Channel Systems MCS GmbH
  6. :license: see LICENSE for more details
  7. """
  8. import h5py
  9. import numpy
  10. class CMOSData(h5py.File):
  11. """
  12. Wrapper for a HDF5 File containing CMOS Data
  13. """
  14. def __init__(self, path):
  15. """
  16. Creates a CMOSData file and links it to a H5 File
  17. :param path: Path to a H5 File containing CMOS Data
  18. :type path: string
  19. """
  20. super(CMOSData, self).__init__(path, mode='r')
  21. # -- map raw data --
  22. self.raw_data= self['/Data/Recording_0/FrameStream/Stream_0/FrameDataEntity_0/FrameData']
  23. self.conv_factors= self['/Data/Recording_0/FrameStream/Stream_0/FrameDataEntity_0/ConversionFactors']
  24. # - map proxy data -
  25. self.conv_data = CMOSConvProxy(self)
  26. # -- map meta --
  27. self.meta={}
  28. # - from InfoFrame
  29. info_frame= self['/Data/Recording_0/FrameStream/Stream_0/InfoFrame']
  30. for key in info_frame.dtype.names:
  31. self.meta[key]=info_frame[key][0]
  32. if("Tick" in self.meta):
  33. self.meta["FrameRate"] = 10.0**6/self.meta["Tick"]
  34. # - from File
  35. for key, value in self.attrs.items():
  36. self.meta[key]= value
  37. # - from Data Group
  38. for key, value in self['/Data'].attrs.items():
  39. self.meta[key]= value
  40. # -- map events --
  41. if("EventStream" in self["Data/Recording_0/"].keys()):
  42. event_group = self["Data/Recording_0/EventStream/Stream_0/"]
  43. event_info = self["Data/Recording_0/EventStream/Stream_0/InfoEvent"]
  44. self.events={}
  45. self.event_frames={}
  46. for key in event_group.keys():
  47. if "EventEntity" in key:
  48. info = event_info["Label"][event_info["EventID"]==int(key.split("_")[1])][0]
  49. self.events[info] = event_group[key][0, 0]
  50. self.event_frames[info] = event_group[key][0, 0]/self.meta["Tick"]
  51. class CMOSConvProxy:
  52. """
  53. Private Class, should be embedded within a CMOSData Object.
  54. A proxy that transparently converts raw data to calibrated data.
  55. """
  56. def __init__(self, parent):
  57. """
  58. Creates a new CMOSConvProxy
  59. :param parent: Object that can provide raw_data and conv_factors
  60. :type parent: CMOSData
  61. """
  62. self._parent = parent
  63. self.dtype = numpy.int32
  64. def __getitem__(self, slices):
  65. """
  66. Sliced access to converted data
  67. :param slices: Data-slices to retrieve
  68. :returns: converted data
  69. """
  70. raw_data = self._parent.raw_data.__getitem__(slices)
  71. conv_fasctors = self._parent.conv_factors.__getitem__((slices[0], slices[1]))
  72. return (raw_data*conv_fasctors).astype(self.dtype)
  73. @property
  74. def shape(self):
  75. """
  76. Shape of the data
  77. """
  78. return self._parent.raw_data.shape
  79. class CMOSSpikes(h5py.File):
  80. """
  81. Wrapper for a HDF5 File containing CMOS Spike Data.
  82. Spike Information is accessible through the .spike Member,
  83. Waveform Information (if available) through the .waveforms Member.
  84. """
  85. def __init__(self, path):
  86. super(CMOSSpikeFile, self).__init__(path)
  87. # -- Check for right structure --
  88. if("data" in self.keys() and "spikes" in self['data'].keys()):
  89. # -- Map Spike-Data to RecordArray
  90. self.spikes = np.core.records.fromarrays(self['data/spikes'][:,:],
  91. names='time, col, row',
  92. formats = 'int64, int64, int64')
  93. # -- Map Waveforms to Array
  94. if("waveforms" in self['data'].keys()):
  95. self.waveforms = self['data/waveforms'][:,:].transpose()
  96. else:
  97. raise IOError(path+ " has no valid CMOSSpikeFile Structure")