Skip to content

Commit 56f8fdc

Browse files
author
Thinh Nguyen
committed
bugfix: Imax per probe type
1 parent 6d5ee8b commit 56f8fdc

File tree

1 file changed

+31
-12
lines changed

1 file changed

+31
-12
lines changed

elements_ephys/readers/spikeglx.py

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44
from .utils import convert_to_number
55

66

7+
AP_GAIN = 80 # For NP 2.0 probes; APGain = 80 for all AP (LF is computed from AP)
8+
9+
# Imax values for different probe types - see metaguides (http://billkarsh.github.io/SpikeGLX/#metadata-guides)
10+
IMAX = {'neuropixels 1.0 - 3A': 512,
11+
'neuropixels 1.0 - 3B': 512,
12+
'neuropixels 2.0 - SS': 8192,
13+
'neuropixels 2.0 - MS': 8192}
14+
15+
716
class SpikeGLX:
817

918
def __init__(self, root_dir):
@@ -69,26 +78,31 @@ def get_channel_bit_volts(self, band='ap'):
6978
"""
7079
Extract the AP and LF channels' int16 to microvolts
7180
Following the steps specified in: https://billkarsh.github.io/SpikeGLX/Support/SpikeGLX_Datafile_Tools.zip
72-
dataVolts = dataInt * fI2V / gain
81+
dataVolts = dataInt * Vmax / Imax / gain
7382
"""
74-
fI2V = float(self.apmeta.meta['imAiRangeMax']) / 512
83+
vmax = float(self.apmeta.meta['imAiRangeMax'])
7584

7685
if band == 'ap':
86+
imax = IMAX[self.apmeta.probe_model]
7787
imroTbl_data = self.apmeta.imroTbl['data']
7888
imroTbl_idx = 3
89+
7990
elif band == 'lf':
91+
imax = IMAX[self.lfmeta.probe_model]
8092
imroTbl_data = self.lfmeta.imroTbl['data']
8193
imroTbl_idx = 4
94+
else:
95+
raise ValueError(f'Unsupported band: {band} - Must be "ap" or "lf"')
8296

8397
# extract channels' gains
8498
if 'imDatPrb_dock' in self.apmeta.meta:
8599
# NP 2.0; APGain = 80 for all AP (LF is computed from AP)
86-
chn_gains = [80] * len(imroTbl_data)
100+
chn_gains = [AP_GAIN] * len(imroTbl_data)
87101
else:
88102
# 3A, 3B1, 3B2 (NP 1.0)
89103
chn_gains = [c[imroTbl_idx] for c in imroTbl_data]
90104

91-
return fI2V / np.array(chn_gains) * 1e6 # convert to uV as well
105+
return vmax / imax / np.array(chn_gains) * 1e6 # convert to uV as well
92106

93107
def _read_bin(self, fname):
94108
nchan = self.apmeta.meta['nSavedChans']
@@ -245,23 +259,28 @@ def _parse_imrotbl(raw):
245259

246260
@property
247261
def recording_channels(self):
262+
"""
263+
Because you can selectively save channels, the
264+
ith channel in the file isn't necessarily the ith acquired channel.
265+
Use this function to convert from ith stored to original index.
266+
267+
Credit to https://billkarsh.github.io/SpikeGLX/Support/SpikeGLX_Datafile_Tools.zip
268+
OriginalChans() function
269+
"""
248270
if self._recording_channels is None:
249271
if self.meta['snsSaveChanSubset'] == 'all':
250272
# output = int32, 0 to nSavedChans - 1
251273
self._recording_channels = np.arange(0, int(self.meta['nSavedChans']))
252274
else:
253275
# parse the snsSaveChanSubset string
254276
# split at commas
255-
chStrList = self.meta['snsSaveChanSubset'].split(sep = ',')
277+
chStrList = self.meta['snsSaveChanSubset'].split(sep=',')
256278
self._recording_channels = np.arange(0, 0) # creates an empty array of int32
257279
for sL in chStrList:
258-
currList = sL.split(sep = ':')
259-
if len(currList) > 1:
260-
# each set of contiguous channels specified by
261-
# chan1:chan2 inclusive
262-
newChans = np.arange(int(currList[0]), int(currList[1]) + 1)
263-
else:
264-
newChans = np.arange(int(currList[0]), int(currList[0]) + 1)
280+
currList = sL.split(sep=':')
281+
# each set of continuous channels specified by chan1:chan2 inclusive
282+
newChans = np.arange(int(currList[0]), int(currList[min(1, len(currList))]) + 1)
283+
265284
self._recording_channels = np.append(self._recording_channels, newChans)
266285
return self._recording_channels
267286

0 commit comments

Comments
 (0)