Note
Click here to download the full example code
CSC to learn LFP spiking atoms¶
Here, we show how CSC can be used to learn spiking atoms from Local Field Potential (LFP) data [1].
- [1] Hitziger, Sebastian, et al.
Adaptive Waveform Learning: A Framework for Modeling Variability in Neurophysiological Signals. IEEE Transactions on Signal Processing (2017).
First, let us fetch the data (~14 MB)
import os
from mne.utils import _fetch_file
url = ('https://github.com/hitziger/AWL/raw/master/Experiments/data/'
'LFP_data_contiguous_1250_Hz.mat')
fname = './LFP_data_contiguous_1250_Hz.mat'
if not os.path.exists(fname):
_fetch_file(url, fname)
It is a mat file, so we use scipy to load it
from scipy import io
data = io.loadmat(fname)
X, sfreq = data['X'].T, float(data['sfreq'])
And now let us look at the data
import numpy as np
import matplotlib.pyplot as plt
start, stop = 11000, 15000
times = np.arange(start, stop) / sfreq
plt.plot(times, X[0, start:stop], color='b')
plt.xlabel('Time (s)')
plt.ylabel(r'$\mu$ V')
plt.xlim([9., 12.])

Out:
(9.0, 12.0)
and filter it using a convenient function from MNE. This will remove low frequency drifts, but we keep the high frequencies
from mne.filter import filter_data
X = filter_data(
X.astype(np.float64), sfreq, l_freq=1, h_freq=None, fir_design='firwin')
Out:
Setting up high-pass filter at 1 Hz
FIR filter parameters
---------------------
Designing a one-pass, zero-phase, non-causal highpass filter:
- Windowed time-domain design (firwin) method
- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation
- Lower passband edge: 1.00
- Lower transition bandwidth: 1.00 Hz (-6 dB cutoff frequency: 0.50 Hz)
- Filter length: 4125 samples (3.300 sec)
Now, we define the parameters of our model.
reg = 6.0
n_times = 2500
n_times_atom = 350
n_trials = 100
n_atoms = 3
n_iter = 60
Let’s stick to one random state for now, but if you want to learn how to select the random state, consult this example.
random_state = 10
Now, we epoch the trials
overlap = 0
starts = np.arange(0, X.shape[1] - n_times, n_times - overlap)
stops = np.arange(n_times, X.shape[1], n_times - overlap)
X_new = []
for idx, (start, stop) in enumerate(zip(starts, stops)):
if idx >= n_trials:
break
X_new.append(X[0, start:stop])
X_new = np.vstack(X_new)
del X
We remove the mean and scale to unit variance.
X_new -= np.mean(X_new)
X_new /= np.std(X_new)
The convolutions can result in edge artifacts at the edges of the trials. Therefore, we discount the contributions from the edges by windowing the trials.
from numpy import hamming
X_new *= hamming(n_times)[None, :]
Of course, in a data-limited setting we want to use as much of the data as possible. If this is the case, you can set overlap to non-zero (for example half the epoch length).
Now, we run regular CSC since the trials are not too noisy
from alphacsc import learn_d_z
pobj, times, d_hat, z_hat, reg = learn_d_z(X_new, n_atoms, n_times_atom,
reg=reg, n_iter=n_iter,
random_state=random_state, n_jobs=1)
Out:
Coordinate descent loop 0 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 51134.32096508
Using method dual for projection
[seed 10] Objective (d) 45299.80903125
Coordinate descent loop 1 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 26399.47853871
Using method dual for projection
[seed 10] Objective (d) 25948.80915409
Coordinate descent loop 2 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 23777.89064427
Using method dual for projection
[seed 10] Objective (d) 23704.90593344
Coordinate descent loop 3 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 22233.60227587
Using method dual for projection
[seed 10] Objective (d) 22221.01870097
Coordinate descent loop 4 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 21202.43876006
Using method dual for projection
[seed 10] Objective (d) 21169.49202496
Coordinate descent loop 5 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 20579.63611160
Using method dual for projection
[seed 10] Objective (d) 20618.98107838
Coordinate descent loop 6 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 20283.55110757
Using method dual for projection
[seed 10] Objective (d) 20210.75292119
Coordinate descent loop 7 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 19971.53116238
Using method dual for projection
[seed 10] Objective (d) 19970.52325693
Coordinate descent loop 8 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 19708.44554814
Using method dual for projection
[seed 10] Objective (d) 19691.20196937
Coordinate descent loop 9 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 19462.43966049
Using method dual for projection
[seed 10] Objective (d) 19467.01239142
Coordinate descent loop 10 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 19233.45092821
Using method dual for projection
[seed 10] Objective (d) 19214.12766228
Coordinate descent loop 11 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 19085.64469638
Using method dual for projection
[seed 10] Objective (d) 19084.13170902
Coordinate descent loop 12 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18945.61954180
Using method dual for projection
[seed 10] Objective (d) 18980.31578130
Coordinate descent loop 13 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18876.43985522
Using method dual for projection
[seed 10] Objective (d) 18836.38353365
Coordinate descent loop 14 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18720.74584344
Using method dual for projection
[seed 10] Objective (d) 18721.54845149
Coordinate descent loop 15 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18623.64002131
Using method dual for projection
[seed 10] Objective (d) 18621.18904483
Coordinate descent loop 16 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18547.81611677
Using method dual for projection
[seed 10] Objective (d) 18545.24281149
Coordinate descent loop 17 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18471.88752075
Using method dual for projection
[seed 10] Objective (d) 18470.42055102
Coordinate descent loop 18 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18393.84202336
Using method dual for projection
[seed 10] Objective (d) 18391.78226334
Coordinate descent loop 19 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18331.73169085
Using method dual for projection
[seed 10] Objective (d) 18328.84451728
Coordinate descent loop 20 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18274.15271778
Using method dual for projection
[seed 10] Objective (d) 18297.40702009
Coordinate descent loop 21 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18257.44912764
Using method dual for projection
[seed 10] Objective (d) 18276.17808971
Coordinate descent loop 22 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18243.49274430
Using method dual for projection
[seed 10] Objective (d) 18261.00618801
Coordinate descent loop 23 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18234.36110409
Using method dual for projection
[seed 10] Objective (d) 18208.94505651
Coordinate descent loop 24 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18179.04646085
Using method dual for projection
[seed 10] Objective (d) 18179.60670455
Coordinate descent loop 25 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18156.84098656
Using method dual for projection
[seed 10] Objective (d) 18166.58627553
Coordinate descent loop 26 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18145.85002352
Using method dual for projection
[seed 10] Objective (d) 18152.93057126
Coordinate descent loop 27 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18131.29820960
Using method dual for projection
[seed 10] Objective (d) 18131.16931585
Coordinate descent loop 28 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18119.63495620
Using method dual for projection
[seed 10] Objective (d) 18111.53150228
Coordinate descent loop 29 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18095.94336612
Using method dual for projection
[seed 10] Objective (d) 18106.50704367
Coordinate descent loop 30 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18098.05237181
Using method dual for projection
[seed 10] Objective (d) 18097.82986883
Coordinate descent loop 31 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18084.15728411
Using method dual for projection
[seed 10] Objective (d) 18025.10056832
Coordinate descent loop 32 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18015.48732514
Using method dual for projection
[seed 10] Objective (d) 18015.15575809
Coordinate descent loop 33 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18009.09807293
Using method dual for projection
[seed 10] Objective (d) 18010.63887509
Coordinate descent loop 34 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18004.88799043
Using method dual for projection
[seed 10] Objective (d) 18058.43293868
Coordinate descent loop 35 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18049.18810207
Using method dual for projection
[seed 10] Objective (d) 17997.43383372
Coordinate descent loop 36 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17990.54845545
Using method dual for projection
[seed 10] Objective (d) 17990.87720429
Coordinate descent loop 37 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17985.96104611
Using method dual for projection
[seed 10] Objective (d) 17988.72477275
Coordinate descent loop 38 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17984.75060685
Using method dual for projection
[seed 10] Objective (d) 18049.42031595
Coordinate descent loop 39 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 18046.54427422
Using method dual for projection
[seed 10] Objective (d) 17984.35843227
Coordinate descent loop 40 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17980.96852119
Using method dual for projection
[seed 10] Objective (d) 17980.80637993
Coordinate descent loop 41 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17972.69145764
Using method dual for projection
[seed 10] Objective (d) 17972.03875516
Coordinate descent loop 42 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17966.98348874
Using method dual for projection
[seed 10] Objective (d) 17966.82851203
Coordinate descent loop 43 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17962.43651755
Using method dual for projection
[seed 10] Objective (d) 17977.52908027
Coordinate descent loop 44 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17975.02834571
Using method dual for projection
[seed 10] Objective (d) 17966.23337802
Coordinate descent loop 45 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17963.82252957
Using method dual for projection
[seed 10] Objective (d) 17978.80967677
Coordinate descent loop 46 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17976.66483297
Using method dual for projection
[seed 10] Objective (d) 17972.18480338
Coordinate descent loop 47 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17970.12420962
Using method dual for projection
[seed 10] Objective (d) 17972.48288898
Coordinate descent loop 48 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17969.94996022
Using method dual for projection
[seed 10] Objective (d) 17965.23270533
Coordinate descent loop 49 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17963.55205711
Using method dual for projection
[seed 10] Objective (d) 17969.37962537
Coordinate descent loop 50 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17965.54664778
Using method dual for projection
[seed 10] Objective (d) 17961.28071921
Coordinate descent loop 51 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17958.73277309
Using method dual for projection
[seed 10] Objective (d) 17958.21375077
Coordinate descent loop 52 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17956.75580565
Using method dual for projection
[seed 10] Objective (d) 17958.71603218
Coordinate descent loop 53 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17957.61409011
Using method dual for projection
[seed 10] Objective (d) 17960.55118043
Coordinate descent loop 54 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17959.37464115
Using method dual for projection
[seed 10] Objective (d) 17956.79042742
Coordinate descent loop 55 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17955.76752140
Using method dual for projection
[seed 10] Objective (d) 17955.63489044
Coordinate descent loop 56 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17954.87025576
Using method dual for projection
[seed 10] Objective (d) 17955.93825285
Coordinate descent loop 57 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17954.98377639
Using method dual for projection
[seed 10] Objective (d) 17950.93343036
Coordinate descent loop 58 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17950.03062819
Using method dual for projection
[seed 10] Objective (d) 17956.16185689
Coordinate descent loop 59 / 60 [n_jobs=1]
[seed 10] Objective (z_hat) : 17954.83421551
Using method dual for projection
[seed 10] Objective (d) 17957.42392000
Let’s look at the atoms now.
plt.figure()
plt.plot(d_hat.T)
plt.show()

Total running time of the script: ( 2 minutes 20.967 seconds)