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.])
plot lfp data

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()
plot lfp data

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

Gallery generated by Sphinx-Gallery