Skip to content

Commit e27b157

Browse files
committed
LFP destripe CAR / sample shift on LF sampling rate
1 parent 1a0631c commit e27b157

File tree

2 files changed

+25
-21
lines changed

2 files changed

+25
-21
lines changed

ibllib/dsp/voltage.py

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,21 @@ def interpolate_bad_channels(data, channel_labels=None, h=None, p=1.3, kriging_d
223223
return data
224224

225225

226+
def _get_destripe_parameters(fs, butter_kwargs, k_kwargs, k_filter):
227+
"""gets the default params for destripe. This is used for both the destripe fcn on a
228+
numpy array and the function that actuates on a cbin file"""
229+
if butter_kwargs is None:
230+
butter_kwargs = {'N': 3, 'Wn': 300 / fs * 2, 'btype': 'highpass'}
231+
if k_kwargs is None:
232+
k_kwargs = {'ntr_pad': 60, 'ntr_tap': 0, 'lagc': 3000,
233+
'butter_kwargs': {'N': 3, 'Wn': 0.01, 'btype': 'highpass'}}
234+
if k_filter:
235+
spatial_fcn = lambda dat: kfilt(dat, **k_kwargs) # noqa
236+
else:
237+
spatial_fcn = lambda dat: car(dat, **k_kwargs) # noqa
238+
return butter_kwargs, k_kwargs, spatial_fcn
239+
240+
226241
def destripe(x, fs, neuropixel_version=1, butter_kwargs=None, k_kwargs=None, channel_labels=None, k_filter=True):
227242
"""Super Car (super slow also...) - far from being set in stone but a good workflow example
228243
:param x: demultiplexed array (nc, ns)
@@ -244,15 +259,7 @@ def destripe(x, fs, neuropixel_version=1, butter_kwargs=None, k_kwargs=None, cha
244259
:param k_filter (True): applies k-filter by default, otherwise, apply CAR.
245260
:return: x, filtered array
246261
"""
247-
if butter_kwargs is None:
248-
butter_kwargs = {'N': 3, 'Wn': 300 / fs * 2, 'btype': 'highpass'}
249-
if k_kwargs is None:
250-
k_kwargs = {'ntr_pad': 60, 'ntr_tap': 0, 'lagc': 3000,
251-
'butter_kwargs': {'N': 3, 'Wn': 0.01, 'btype': 'highpass'}}
252-
if k_filter:
253-
spatial_fcn = lambda dat: kfilt(dat, **k_kwargs) # noqa
254-
else:
255-
spatial_fcn = lambda dat: car(dat, **k_kwargs) # noqa
262+
butter_kwargs, k_kwargs, spatial_fcn = _get_destripe_parameters(fs, butter_kwargs, k_kwargs, k_filter)
256263
h = neuropixel.trace_header(version=neuropixel_version)
257264
if channel_labels is True:
258265
channel_labels, _ = detect_bad_channels(x, fs)
@@ -262,8 +269,7 @@ def destripe(x, fs, neuropixel_version=1, butter_kwargs=None, k_kwargs=None, cha
262269
# channel interpolation
263270
# apply ADC shift
264271
if neuropixel_version is not None:
265-
sample_shift = h['sample_shift'] if (30000 / fs) < 10 else h['sample_shift'] * fs / 30000
266-
x = fshift(x, sample_shift, axis=1)
272+
x = fshift(x, h['sample_shift'], axis=1)
267273
# apply spatial filter only on channels that are inside of the brain
268274
if channel_labels is not None:
269275
x = interpolate_bad_channels(x, channel_labels, h)
@@ -276,7 +282,7 @@ def destripe(x, fs, neuropixel_version=1, butter_kwargs=None, k_kwargs=None, cha
276282

277283
def decompress_destripe_cbin(sr_file, output_file=None, h=None, wrot=None, append=False, nc_out=None, butter_kwargs=None,
278284
dtype=np.int16, ns2add=0, nbatch=None, nprocesses=None, compute_rms=True, reject_channels=True,
279-
k_kwargs=None):
285+
k_kwargs=None, k_filter=True):
280286
"""
281287
From a spikeglx Reader object, decompresses and apply ADC.
282288
Saves output as a flat binary file in int16
@@ -296,7 +302,8 @@ def decompress_destripe_cbin(sr_file, output_file=None, h=None, wrot=None, appen
296302
interp 3:outside of brain and discard
297303
:param reject_channels: (True) detects noisy or bad channels and interpolate them. Channels outside of the brain are left
298304
untouched
299-
:param k_kwargs: (True) arguments for the kfilter function
305+
:param k_kwargs: (None) arguments for the kfilter function
306+
:param k_filter: (True) Performs a k-filter - if False will do median common average referencing
300307
:return:
301308
"""
302309
import pyfftw
@@ -308,11 +315,7 @@ def decompress_destripe_cbin(sr_file, output_file=None, h=None, wrot=None, appen
308315
if reject_channels: # get bad channels if option is on
309316
channel_labels = detect_bad_channels_cbin(sr)
310317
assert isinstance(sr_file, str) or isinstance(sr_file, Path)
311-
if butter_kwargs is None:
312-
butter_kwargs = butter_kwargs or {'N': 3, 'Wn': 300 / sr.fs * 2, 'btype': 'highpass'}
313-
if k_kwargs is None:
314-
k_kwargs = {'ntr_pad': 60, 'ntr_tap': 0, 'lagc': 3000,
315-
'butter_kwargs': {'N': 3, 'Wn': 0.01, 'btype': 'highpass'}}
318+
butter_kwargs, k_kwargs, spatial_fcn = _get_destripe_parameters(sr.fs, butter_kwargs, k_kwargs, k_filter)
316319
h = neuropixel.trace_header(version=1) if h is None else h
317320
ncv = h['sample_shift'].size # number of channels
318321
output_file = sr.file_bin.with_suffix('.bin') if output_file is None else output_file
@@ -416,9 +419,9 @@ def my_function(i_chunk, n_chunk):
416419
if reject_channels:
417420
chunk = interpolate_bad_channels(chunk, channel_labels, h=h)
418421
inside_brain = np.where(channel_labels != 3)[0]
419-
chunk[inside_brain, :] = kfilt(chunk[inside_brain, :], **k_kwargs) # apply the k-filter
422+
chunk[inside_brain, :] = spatial_fcn(chunk[inside_brain, :]) # apply the k-filter / CAR
420423
else:
421-
chunk = kfilt(chunk, **k_kwargs) # apply the k-filter
424+
chunk = spatial_fcn(chunk) # apply the k-filter / CAR
422425
# add back sync trace and save
423426
chunk = np.r_[chunk, _sr[first_s:last_s, ncv:].T].T
424427
intnorm = 1 / _sr.channel_conversion_sample2v['ap'] if dtype == np.int16 else 1.

ibllib/plots/figures.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ def _run(self, collection=None):
5353
if 'atlas_id' in channels.keys():
5454
plot_brain_regions(channels['atlas_id'], channel_depths=channels['axial_um'],
5555
brain_regions=None, display=True, ax=axs[1])
56-
title_str = f"{self.pid_label}, {collection}, {self.pid} \n {spikes.clusters.size:_} spikes, {clusters.depths.size:_} clusters"
56+
title_str = f"{self.pid_label}, {collection}, {self.pid} \n " \
57+
f"{spikes.clusters.size:_} spikes, {clusters.depths.size:_} clusters"
5758
logger.info(title_str.replace("\n", ""))
5859
axs[0].set(ylim=[0, 3800], title=title_str)
5960
run_label = str(Path(collection).relative_to(f'alf/{self.pname}'))

0 commit comments

Comments
 (0)