@@ -23,39 +23,67 @@ def __init__(self, root_dir):
23
23
name & associated meta - no interpretation of g0_t0.imec, etc is
24
24
performed at this layer.
25
25
'''
26
+ self ._apmeta , self ._apdata = None , None
27
+ self ._lfmeta , self ._lfdata = None , None
26
28
27
- self .root_dir = root_dir
29
+ self .root_dir = pathlib . Path ( root_dir )
28
30
29
31
meta_filepath = next (pathlib .Path (root_dir ).glob ('*.ap.meta' ))
30
- self .npx_meta = SpikeGLXMeta (meta_filepath )
31
-
32
32
self .root_name = meta_filepath .name .replace ('.ap.meta' , '' )
33
- self ._apdata = None
34
- self ._lfdata , self ._lfmeta = None , None
33
+
34
+ @property
35
+ def apmeta (self ):
36
+ if self ._apmeta is None :
37
+ self ._apmeta = SpikeGLXMeta (self .root_dir / (self .root_name + '.ap.meta' ))
38
+ return self ._apmeta
35
39
36
40
@property
37
41
def apdata (self ):
38
- if self ._apdata is not None :
39
- return self ._apdata
40
- else :
41
- return self ._read_bin ( self . root_dir / ( self . root_name + '.ap.bin' ))
42
+ if self ._apdata is None :
43
+ self ._apdata = self . _read_bin ( self . root_dir / ( self . root_name + '.ap.bin' ))
44
+ self . _apdata = self . _apdata * self . get_channel_bit_volts ( 'ap' )
45
+ return self ._apdata
42
46
43
47
@property
44
48
def lfmeta (self ):
45
- if self ._lfmeta is not None :
46
- return self ._lfmeta
47
- else :
48
- return _read_meta (self .root_dir / (self .root_name + '.lf.meta' ))
49
+ if self ._lfmeta is None :
50
+ self ._lfmeta = SpikeGLXMeta (self .root_dir / (self .root_name + '.lf.meta' ))
51
+ return self ._lfmeta
49
52
50
53
@property
51
54
def lfdata (self ):
52
- if self ._lfdata is not None :
53
- return self ._lfdata
55
+ if self ._lfdata is None :
56
+ self ._lfdata = self ._read_bin (self .root_dir / (self .root_name + '.lf.bin' ))
57
+ self ._lfdata = self ._lfdata * self .get_channel_bit_volts ('lf' )
58
+ return self ._lfdata
59
+
60
+ def get_channel_bit_volts (self , band = 'ap' ):
61
+ """
62
+ Extract the AP and LF channels' int16 to microvolts
63
+ Following the steps specified in: https://billkarsh.github.io/SpikeGLX/Support/SpikeGLX_Datafile_Tools.zip
64
+ dataVolts = dataInt * fI2V / gain
65
+ """
66
+ fI2V = float (self .apmeta .meta ['imAiRangeMax' ]) / 512
67
+
68
+ if band == 'ap' :
69
+ imroTbl_data = self .apmeta .imroTbl ['data' ]
70
+ imroTbl_idx = 3
71
+ elif band == 'lf' :
72
+ imroTbl_data = self .lfmeta .imroTbl ['data' ]
73
+ imroTbl_idx = 4
74
+
75
+ # extract channels' gains
76
+ if 'imDatPrb_dock' in self .apmeta .meta :
77
+ # NP 2.0; APGain = 80 for all AP (LF is computed from AP)
78
+ chn_gains = [80 ] * len (imroTbl_data )
54
79
else :
55
- return self ._read_bin (self .root_dir / (self .root_name + '.lf.bin' ))
80
+ # 3A, 3B1, 3B2 (NP 1.0)
81
+ chn_gains = [c [imroTbl_idx ] for c in imroTbl_data ]
82
+
83
+ return fI2V / np .array (chn_gains ) * 1e6
56
84
57
85
def _read_bin (self , fname ):
58
- nchan = self .npx_meta .meta ['nSavedChans' ]
86
+ nchan = self .apmeta .meta ['nSavedChans' ]
59
87
dtype = np .dtype ((np .int16 , nchan ))
60
88
return np .memmap (fname , dtype , 'r' )
61
89
@@ -70,9 +98,9 @@ def extract_spike_waveforms(self, spikes, channel, n_wf=500, wf_win=(-32, 32), b
70
98
"""
71
99
72
100
data = self .apdata
73
- channel_idx = [np .where (self .npx_meta .recording_channels == chn )[0 ][0 ] for chn in channel ]
101
+ channel_idx = [np .where (self .apmeta .recording_channels == chn )[0 ][0 ] for chn in channel ]
74
102
75
- spikes = np .round (spikes * self .npx_meta .meta ['imSampRate' ]).astype (int ) # convert to sample
103
+ spikes = np .round (spikes * self .apmeta .meta ['imSampRate' ]).astype (int ) # convert to sample
76
104
# ignore spikes at the beginning or end of raw data
77
105
spikes = spikes [np .logical_and (spikes > - wf_win [0 ], spikes < data .shape [0 ] - wf_win [- 1 ])]
78
106
@@ -125,6 +153,8 @@ def __init__(self, meta_filepath):
125
153
126
154
self .recording_channels = [c [0 ] for c in self .imroTbl ['data' ]] if self .imroTbl else None
127
155
156
+ self ._chan_gains = None
157
+
128
158
@staticmethod
129
159
def _parse_chanmap (raw ):
130
160
'''
0 commit comments