neuroscoperawio.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. """
  2. Reading from neuroscope format files.
  3. Ref: http://neuroscope.sourceforge.net/
  4. It is an old format from Buzsaki's lab
  5. Some old open datasets from spike sorting
  6. are still using this format.
  7. This only the signals.
  8. This should be done (but maybe never will):
  9. * SpikeTrain file '.clu' '.res'
  10. * Event '.ext.evt' or '.evt.ext'
  11. Author: Samuel Garcia
  12. """
  13. from .baserawio import (BaseRawIO, _signal_channel_dtype, _unit_channel_dtype,
  14. _event_channel_dtype)
  15. import numpy as np
  16. from xml.etree import ElementTree
  17. class NeuroScopeRawIO(BaseRawIO):
  18. extensions = ['xml', 'dat']
  19. rawmode = 'one-file'
  20. def __init__(self, filename=''):
  21. BaseRawIO.__init__(self)
  22. self.filename = filename
  23. def _source_name(self):
  24. return self.filename.replace('.xml', '').replace('.dat', '')
  25. def _parse_header(self):
  26. filename = self.filename.replace('.xml', '').replace('.dat', '')
  27. tree = ElementTree.parse(filename + '.xml')
  28. root = tree.getroot()
  29. acq = root.find('acquisitionSystem')
  30. nbits = int(acq.find('nBits').text)
  31. nb_channel = int(acq.find('nChannels').text)
  32. self._sampling_rate = float(acq.find('samplingRate').text)
  33. voltage_range = float(acq.find('voltageRange').text)
  34. # offset = int(acq.find('offset').text)
  35. amplification = float(acq.find('amplification').text)
  36. # find groups for channels
  37. channel_group = {}
  38. for grp_index, xml_chx in enumerate(
  39. root.find('anatomicalDescription').find('channelGroups').findall('group')):
  40. for xml_rc in xml_chx:
  41. channel_group[int(xml_rc.text)] = grp_index
  42. if nbits == 16:
  43. sig_dtype = 'int16'
  44. gain = voltage_range / (2 ** 16) / amplification / 1000.
  45. # ~ elif nbits==32:
  46. # Not sure if it is int or float
  47. # ~ dt = 'int32'
  48. # ~ gain = voltage_range/2**32/amplification
  49. else:
  50. raise (NotImplementedError)
  51. self._raw_signals = np.memmap(filename + '.dat', dtype=sig_dtype,
  52. mode='r', offset=0).reshape(-1, nb_channel)
  53. # signals
  54. sig_channels = []
  55. for c in range(nb_channel):
  56. name = 'ch{}grp{}'.format(c, channel_group[c])
  57. chan_id = c
  58. units = 'mV'
  59. offset = 0.
  60. group_id = 0
  61. sig_channels.append((name, chan_id, self._sampling_rate,
  62. sig_dtype, units, gain, offset, group_id))
  63. sig_channels = np.array(sig_channels, dtype=_signal_channel_dtype)
  64. # No events
  65. event_channels = []
  66. event_channels = np.array(event_channels, dtype=_event_channel_dtype)
  67. # No spikes
  68. unit_channels = []
  69. unit_channels = np.array(unit_channels, dtype=_unit_channel_dtype)
  70. # fille into header dict
  71. self.header = {}
  72. self.header['nb_block'] = 1
  73. self.header['nb_segment'] = [1]
  74. self.header['signal_channels'] = sig_channels
  75. self.header['unit_channels'] = unit_channels
  76. self.header['event_channels'] = event_channels
  77. self._generate_minimal_annotations()
  78. def _segment_t_start(self, block_index, seg_index):
  79. return 0.
  80. def _segment_t_stop(self, block_index, seg_index):
  81. t_stop = self._raw_signals.shape[0] / self._sampling_rate
  82. return t_stop
  83. def _get_signal_size(self, block_index, seg_index, channel_indexes):
  84. return self._raw_signals.shape[0]
  85. def _get_signal_t_start(self, block_index, seg_index, channel_indexes):
  86. return 0.
  87. def _get_analogsignal_chunk(self, block_index, seg_index, i_start, i_stop, channel_indexes):
  88. if channel_indexes is None:
  89. channel_indexes = slice(None)
  90. raw_signals = self._raw_signals[slice(i_start, i_stop), channel_indexes]
  91. return raw_signals