44
55https://spikegadgets.com/spike-products/
66
7+
8+ The file ".rec" have :
9+ * a fist part in text with xml informations
10+ * a second part for the binary buffer
11+
712Author: Samuel Garcia
813"""
914from .baserawio import (BaseRawIO , _signal_channel_dtype , _unit_channel_dtype ,
1015 _event_channel_dtype )
1116
1217import numpy as np
1318
19+ from xml .etree import ElementTree
1420
1521class SpikeGadgetsRawIO (BaseRawIO ):
1622 extensions = ['rec' ]
@@ -25,8 +31,42 @@ def _source_name(self):
2531
2632 def _parse_header (self ):
2733
34+ # parse file until "</Configuration>"
35+ header_size = None
36+ with open (self .filename , mode = 'rb' ) as f :
37+ while True :
38+ line = f .readline ()
39+ if b"</Configuration>" in line :
40+ header_size = f .tell ()
41+ break
42+ if header_size is None :
43+ ValueError ("SpikeGadgets : the xml header do not contain </Configuration>" )
44+ print (header_size )
45+ f .seek (0 )
46+ header_txt = f .read (header_size ).decode ('utf8' )
47+
48+ # explore xml header
49+ root = ElementTree .fromstring (header_txt )
50+
51+ gconf = sr = root .find ('GlobalConfiguration' )
52+ hconf = root .find ('HardwareConfiguration' )
53+ self ._sampling_rate = float (hconf .attrib ['samplingRate' ])
54+
2855 signal_channels = []
29- signal_channels = np .array (sig_channels , dtype = _signal_channel_dtype )
56+ for chan_ind , child in enumerate (hconf .find ('Device' )):
57+ name = child .attrib ['id' ]
58+ chan_id = chan_ind #TODO change this to str with new rawio refactoring
59+ dtype = 'int16' # TODO check this
60+ units = 'uV' # TODO check where is the info
61+ gain = 1. # TODO check where is the info
62+ offset = 0. # TODO check where is the info
63+ group_id = 0
64+ signal_channels .append ((name , chan_id , self ._sampling_rate , 'int16' ,
65+ units , gain , offset , group_id ))
66+ signal_channels = np .array (signal_channels , dtype = _signal_channel_dtype )
67+
68+ self ._raw_memmap = np .memmap (self .filename , mode = 'r' , offset = header_size , dtype = 'int16' )
69+ self ._raw_memmap = self ._raw_memmap .reshape (- 1 , signal_channels .size )
3070
3171 # No events
3272 event_channels = []
@@ -39,8 +79,8 @@ def _parse_header(self):
3979 # fille into header dict
4080 self .header = {}
4181 self .header ['nb_block' ] = 1
42- self .header ['nb_segment' ] = [nb_segment ]
43- self .header ['signal_channels' ] = sig_channels
82+ self .header ['nb_segment' ] = [1 ]
83+ self .header ['signal_channels' ] = signal_channels
4484 self .header ['unit_channels' ] = unit_channels
4585 self .header ['event_channels' ] = event_channels
4686
@@ -50,16 +90,20 @@ def _segment_t_start(self, block_index, seg_index):
5090 return 0.
5191
5292 def _segment_t_stop (self , block_index , seg_index ):
93+ size = self ._raw_memmap .shape [0 ]
94+ t_stop = size / self ._sampling_rate
5395 return t_stop
5496
5597 def _get_signal_size (self , block_index , seg_index , channel_indexes ):
56- sie = 0
98+ size = self . _raw_memmap . shape [ 0 ]
5799 return size
58100
59101 def _get_signal_t_start (self , block_index , seg_index , channel_indexes ):
60102 return 0.
61103
62104 def _get_analogsignal_chunk (self , block_index , seg_index , i_start , i_stop , channel_indexes ):
63- raw_signals = None
105+ if channel_indexes is None :
106+ channel_indexes = slice (None )
107+ raw_signals = self ._raw_memmap [slice (i_start , i_stop ), :][:, channel_indexes ]
64108 return raw_signals
65109
0 commit comments