Skip to content

Commit de1837b

Browse files
authored
Merge pull request #1028 from int-brain-lab/task_qc_fix
Task qc fix
2 parents e6c115f + 3406436 commit de1837b

File tree

11 files changed

+151
-81
lines changed

11 files changed

+151
-81
lines changed

ibllib/ephys/ephysqc.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,13 @@ def run(self, update: bool = False, overwrite: bool = True, stream: bool = None,
157157
sr = self.data['ap']
158158
nc = sr.nc - sr.nsync
159159

160-
# verify that the channel layout is correct according to IBL layout
161160
th = sr.geometry
162-
if sr.meta.get('NP2.4_shank', None) is not None:
163-
h = neuropixel.trace_header(sr.major_version, nshank=4)
164-
h = neuropixel.split_trace_header(h, shank=int(sr.meta.get('NP2.4_shank')))
165-
else:
161+
# Verify that the channel layout is correct according to IBL layout for version 1 probes
162+
if sr.major_version == 1:
166163
h = neuropixel.trace_header(sr.major_version, nshank=np.unique(th['shank']).size)
167-
168-
if not (np.all(h['x'] == th['x']) and np.all(h['y'] == th['y'])):
169-
_logger.critical("Channel geometry seems incorrect")
170-
# raise ValueError("Wrong Neuropixel channel mapping used - ABORT")
164+
if not (np.all(h['x'] == th['x']) and np.all(h['y'] == th['y'])):
165+
_logger.critical("Channel geometry seems incorrect")
166+
raise ValueError("Wrong Neuropixel channel mapping used - ABORT")
171167

172168
t0s = np.arange(TMIN, sr.rl - SAMPLE_LENGTH, BATCHES_SPACING)
173169
all_rms = np.zeros((2, nc, t0s.shape[0]))
@@ -179,7 +175,7 @@ def run(self, update: bool = False, overwrite: bool = True, stream: bool = None,
179175
sl = slice(int(t0 * sr.fs), int((t0 + SAMPLE_LENGTH) * sr.fs))
180176
raw = sr[sl, :-sr.nsync].T
181177
all_rms[0, :, i], all_rms[1, :, i], all_srs[:, i], channel_ok[:, i], psd =\
182-
self._compute_metrics_array(raw, sr.fs, h)
178+
self._compute_metrics_array(raw, sr.fs, th)
183179
psds += psd
184180
# Calculate the median RMS across all samples per channel
185181
results = {'rms': np.median(all_rms, axis=-1),
@@ -188,8 +184,12 @@ def run(self, update: bool = False, overwrite: bool = True, stream: bool = None,
188184
'ap_freqs': fourier.fscale(WELCH_WIN_LENGTH_SAMPLES, 1 / sr.fs, one_sided=True),
189185
'ap_power': psds.T / len(t0s), # shape: (nfreqs, nchannels)
190186
}
187+
unsort = np.argsort(sr.raw_channel_order)[:-sr.nsync]
191188
for k in files:
192-
np.save(files[k], results[k])
189+
if nc in results[k].shape:
190+
np.save(files[k], results[k][..., unsort])
191+
else:
192+
np.save(files[k], results[k])
193193
qc_files.extend([files[k] for k in files])
194194
for p in [10, 90]:
195195
self.metrics[f'apRms_p{p}_raw'] = np.format_float_scientific(
@@ -219,19 +219,19 @@ def rmsmap(sglx, spectra=True, nmod=1):
219219
# the window generator will generates window indices
220220
wingen = utils.WindowGenerator(ns=sglx.ns, nswin=rms_win_length_samples, overlap=0)
221221
nwin = np.ceil(wingen.nwin / nmod).astype(int)
222+
nc = sglx.nc - sglx.nsync
222223
# pre-allocate output dictionary of numpy arrays
223-
win = {'TRMS': np.zeros((nwin, sglx.nc)),
224+
win = {'TRMS': np.zeros((nwin, nc)),
224225
'nsamples': np.zeros((nwin,)),
225226
'fscale': fourier.fscale(WELCH_WIN_LENGTH_SAMPLES, 1 / sglx.fs, one_sided=True),
226227
'tscale': wingen.tscale(fs=sglx.fs)[::nmod]}
227-
win['spectral_density'] = np.zeros((len(win['fscale']), sglx.nc))
228+
win['spectral_density'] = np.zeros((len(win['fscale']), nc))
228229
# loop through the whole session
229230
with tqdm(total=wingen.nwin) as pbar:
230231
for iwindow, (first, last) in enumerate(wingen.firstlast):
231232
if np.mod(iwindow, nmod) != 0:
232233
continue
233-
234-
D = sglx.read_samples(first_sample=first, last_sample=last)[0].transpose()
234+
D = sglx[slice(first, last), :-sglx.nsync].T
235235
# remove low frequency noise below 1 Hz
236236
D = fourier.hp(D, 1 / sglx.fs, [0, 1])
237237
iw = np.floor(wingen.iw / nmod).astype(int)
@@ -283,12 +283,15 @@ def extract_rmsmap(sglx, out_folder=None, overwrite=False, spectra=True, nmod=1)
283283
# output ALF files, single precision with the optional label as suffix before extension
284284
if not out_folder.exists():
285285
out_folder.mkdir()
286+
unsort = np.argsort(sglx.raw_channel_order)[:-sglx.nsync]
286287
tdict = {'rms': rms['TRMS'].astype(np.single), 'timestamps': rms['tscale'].astype(np.single)}
288+
tdict['rms'] = tdict['rms'][:, unsort]
287289
out_time = alfio.save_object_npy(
288290
out_folder, object=alf_object_time, dico=tdict, namespace='iblqc')
289291
if spectra:
290292
fdict = {'power': rms['spectral_density'].astype(np.single),
291293
'freqs': rms['fscale'].astype(np.single)}
294+
fdict['power'] = fdict['power'][:, unsort]
292295
out_freq = alfio.save_object_npy(
293296
out_folder, object=alf_object_freq, dico=fdict, namespace='iblqc')
294297
return out_time + out_freq if spectra else out_time

ibllib/io/extractors/ephys_fpga.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -658,15 +658,16 @@ def _update_var_names(self, bpod_fields=None, bpod_rsync_fields=None):
658658
self.settings = self.bpod_extractor.settings # This is used by the TaskQC
659659
self.bpod_rsync_fields = bpod_rsync_fields
660660
if self.bpod_rsync_fields is None:
661-
self.bpod_rsync_fields = tuple(self._time_fields(self.bpod_extractor.var_names))
661+
self.bpod_rsync_fields = tuple([f for f in self._time_fields(self.bpod_extractor.var_names)
662+
if 'wheel' not in f])
662663
if 'table' in self.bpod_extractor.var_names:
663664
if not self.bpod_trials:
664665
self.bpod_trials = self.bpod_extractor.extract(save=False)
665666
table_keys = alfio.AlfBunch.from_df(self.bpod_trials['table']).keys()
666667
self.bpod_rsync_fields += tuple(self._time_fields(table_keys))
667668
elif bpod_rsync_fields:
668669
self.bpod_rsync_fields = bpod_rsync_fields
669-
excluded = (*self.bpod_rsync_fields, 'table')
670+
excluded = (*self.bpod_rsync_fields, 'table', *(f for f in self.bpod_extractor.var_names if 'wheel' in f))
670671
if bpod_fields:
671672
assert not set(self.bpod_fields).intersection(excluded), 'bpod_fields must not also be bpod_rsync_fields'
672673
self.bpod_fields = bpod_fields

0 commit comments

Comments
 (0)