2020Author: Samuel Garcia
2121"""
2222
23+ import numpy as np
24+
25+ from xml .etree import ElementTree
26+
2327from .baserawio import (
2428 BaseRawIO ,
2529 _signal_channel_dtype ,
2630 _signal_stream_dtype ,
2731 _spike_channel_dtype ,
2832 _event_channel_dtype ,
2933)
30-
31- import numpy as np
32-
33- from xml .etree import ElementTree
34+ from neo .core import NeoReadWriteError
3435
3536
3637class SpikeGadgetsRawIO (BaseRawIO ):
@@ -79,6 +80,24 @@ def __init__(self, filename="", selected_streams=None):
7980 def _source_name (self ):
8081 return self .filename
8182
83+ def _produce_ephys_channel_ids (self , n_total_channels , n_channels_per_chip ):
84+ """Compute the channel ID labels
85+ The ephys channels in the .rec file are stored in the following order:
86+ hwChan ID of channel 0 of first chip, hwChan ID of channel 0 of second chip, ..., hwChan ID of channel 0 of Nth chip,
87+ hwChan ID of channel 1 of first chip, hwChan ID of channel 1 of second chip, ..., hwChan ID of channel 1 of Nth chip,
88+ ...
89+ So if there are 32 channels per chip and 128 channels (4 chips), then the channel IDs are:
90+ 0, 32, 64, 96, 1, 33, 65, 97, ..., 128
91+ See also: https://github.com/NeuralEnsemble/python-neo/issues/1215
92+ """
93+ ephys_channel_ids_list = []
94+ for hw_channel in range (n_channels_per_chip ):
95+ hw_channel_list = [
96+ hw_channel + chip * n_channels_per_chip for chip in range (int (n_total_channels / n_channels_per_chip ))
97+ ]
98+ ephys_channel_ids_list .append (hw_channel_list )
99+ return [channel for channel_list in ephys_channel_ids_list for channel in channel_list ]
100+
82101 def _parse_header (self ):
83102 # parse file until "</Configuration>"
84103 header_size = None
@@ -104,6 +123,20 @@ def _parse_header(self):
104123 self ._sampling_rate = float (hconf .attrib ["samplingRate" ])
105124 num_ephy_channels = int (hconf .attrib ["numChannels" ])
106125
126+ # check for agreement with number of channels in xml
127+ sconf_channels = np .sum ([len (x ) for x in sconf ])
128+ if sconf_channels < num_ephy_channels :
129+ num_ephy_channels = sconf_channels
130+ if sconf_channels > num_ephy_channels :
131+ raise NeoReadWriteError (
132+ "SpikeGadgets: the number of channels in the spike configuration is larger than the number of channels in the hardware configuration"
133+ )
134+
135+ try :
136+ num_chan_per_chip = int (sconf .attrib ["chanPerChip" ])
137+ except KeyError :
138+ num_chan_per_chip = 32 # default value for Intan chips
139+
107140 # explore sub stream and count packet size
108141 # first bytes is 0x55
109142 packet_size = 1
@@ -174,6 +207,7 @@ def _parse_header(self):
174207 signal_streams .append ((stream_name , stream_id ))
175208 self ._mask_channels_bytes [stream_id ] = []
176209
210+ channel_ids = self ._produce_ephys_channel_ids (num_ephy_channels , num_chan_per_chip )
177211 chan_ind = 0
178212 self .is_scaleable = "spikeScalingToUv" in sconf [0 ].attrib
179213 if not self .is_scaleable :
@@ -190,8 +224,8 @@ def _parse_header(self):
190224 units = ""
191225
192226 for schan in trode :
193- name = "trode" + trode . attrib [ "id" ] + "chan" + schan . attrib [ "hwChan" ]
194- chan_id = schan . attrib [ "hwChan" ]
227+ chan_id = str ( channel_ids [ chan_ind ])
228+ name = "hwChan" + chan_id
195229
196230 offset = 0.0
197231 signal_channels .append (
0 commit comments