Release Highlights for spkit 0.0.9.7

Release Highlights for spkit 0.0.9.7

We are pleased to announce the release of spkit 0.0.9.7, which comes with many fixed bug, more organised documentation and new features! For an exhaustive list of all the changes, please refer to the release notes.

Topographic Map correction: 10-20 System

A widely used EEG system is 10-20 system, although there are many libraries that can plot topographic map from EEG data, their layouts are a little different than standards.

Notice the 10-20 Standard described in following

In above examples, Cz is the center point and horizontal line crossing is straight line. In Spkit we tried to correct this mapping style, however, keeping the conventional style as option. See following examples.

#sp.eeg.topomap
import numpy as np
import matplotlib.pyplot as plt
import spkit as sp
X,fs, ch_names = sp.data.eeg_sample_14ch()
X = sp.filterDC_sGolay(X, window_length=fs//3+1)
Px,Pm,Pd = sp.eeg.rhythmic_powers(X=X,fs=fs,fBands=[[4],[8,14]],Sum=True,Mean=True,SD =True)
Px = 20*np.log10(Px)
pos1, ch = sp.eeg.s1020_get_epos2d(ch_names,style='eeglab-mne')
pos2, ch = sp.eeg.s1020_get_epos2d(ch_names,style='spkit')
fig, ax = plt.subplots(1,2,figsize=(10,4))
Z1i,im1 = sp.eeg.topomap(pos=pos1,data=Px[1],axes=ax[0],return_im=True)
Z2i,im2 = sp.eeg.topomap(pos=pos2,data=Px[1],axes=ax[1],return_im=True)
ax[0].set_title(r'Conventional style')
ax[1].set_title(r'SpKit style')
plt.colorbar(im1, ax=ax[0],label='dB')
plt.colorbar(im2, ax=ax[1],label='dB')
plt.suptitle('Topographical maps')
plt.show()
Topographical maps, Conventional style, SpKit style

Location of all the eletrodes

Location of all the electrodes are shown here.

import numpy as np
import matplotlib.pyplot as plt
import spkit as sp

ch_names_emotiv = ['AF3','F7','F3','FC5','T7','P7','O1','O2','P8','T8','FC6','F4','F8','AF4']
pos1, ch1 = sp.eeg.s1020_get_epos2d(ch_names_emotiv)
pos2, ch2 = sp.eeg.s1020_get_epos2d(ch_names_emotiv,style='spkit')

ch_names_all = sp.eeg.presets.standard_1020_ch
pos3, ch3 = sp.eeg.s1020_get_epos2d(ch_names_all)

ch_names_spkit_all = sp.eeg.presets.standard_1020_spkit_ch
pos4, ch4 = sp.eeg.s1020_get_epos2d(ch_names_spkit_all,style='spkit')

plt.figure(figsize=(10,5))
plt.subplot(121)
plt.plot(pos1[:,0],pos1[:,1],'.',alpha=0.5)
for i,ch in enumerate(ch_names_emotiv):
    plt.text(pos1[i,0],pos1[i,1],ch,va='center',ha='center')
plt.title('Emotiv: 14 channels: mne-eeglab-style')
plt.axvline(0,lw=0.5,color='k',ls='--')
plt.axhline(0,lw=0.5,color='k',ls='--')
plt.subplot(122)
plt.plot(pos3[:,0],pos3[:,1],'.',alpha=0.5)
for i,ch in enumerate(ch_names_all):
    plt.text(pos3[i,0],pos3[i,1],ch,va='center',ha='center')
plt.title(f'All 10-20 Channels: (n={len(ch_names_all)})')
plt.axvline(0,lw=0.5,color='k',ls='--')
plt.axhline(0,lw=0.5,color='k',ls='--')
plt.suptitle('MNE-EEGLab style topographic map')
plt.tight_layout()
plt.show()

plt.figure(figsize=(10,5))
plt.subplot(121)
plt.plot(pos2[:,0],pos2[:,1],'.',alpha=0.5)
for i,ch in enumerate(ch_names_emotiv):
    plt.text(pos2[i,0],pos2[i,1],ch,va='center',ha='center')
plt.title('Emotiv: 14 channels')
plt.axvline(0,lw=0.5,color='k',ls='--')
plt.axhline(0,lw=0.5,color='k',ls='--')
plt.subplot(122)
plt.plot(pos4[:,0],pos4[:,1],'.',alpha=0.5)
for i,ch in enumerate(ch_names_spkit_all):
    plt.text(pos4[i,0],pos4[i,1],ch,va='center',ha='center')
plt.title(f'All 10-20 Channels: (n={len(ch_names_spkit_all)})')
plt.suptitle('SPKIT-style topographic map')
plt.axvline(0,lw=0.5,color='k',ls='--')
plt.axhline(0,lw=0.5,color='k',ls='--')
plt.tight_layout()
plt.show()
  • MNE-EEGLab style topographic map, Emotiv: 14 channels: mne-eeglab-style, All 10-20 Channels: (n=97)
  • SPKIT-style topographic map, Emotiv: 14 channels, All 10-20 Channels: (n=75)

Topographic Map 10-10 System

import numpy as np
import matplotlib.pyplot as plt
import spkit as sp

ch_names = ['AF3','F7','F3','FC5','T7','P7','O1','O2','P8','T8','FC6','F4','F8','AF4']
pos, ch = sp.eeg.s1010_get_epos2d(ch_names)

plt.figure(figsize=(12,5))

plt.subplot(121)
plt.plot(pos[:,0],pos[:,1],'.',alpha=0.5)
for i,ch in enumerate(ch_names):
    plt.text(pos[i,0],pos[i,1],ch,va='center',ha='center')
plt.title('Emotiv: 14 channels')

ch_names = sp.eeg.presets.standard_1010_ch
pos, ch = sp.eeg.s1010_get_epos2d(ch_names)

plt.subplot(122)
plt.plot(pos[:,0],pos[:,1],'.',alpha=0.5)
for i,ch in enumerate(ch_names):
    plt.text(pos[i,0],pos[i,1],ch,va='center',ha='center')
plt.title(f'All 10-10 Channels: (n={len(ch_names)})')
plt.show()
Emotiv: 14 channels, All 10-10 Channels: (n=132)

Topographic Map 10-05 System

import numpy as np
import matplotlib.pyplot as plt
import spkit as sp

ch_names = ['AF3','F7','F3','FC5','T7','P7','O1','O2','P8','T8','FC6','F4','F8','AF4']
pos, ch = sp.eeg.s1005_get_epos2d(ch_names)

plt.figure(figsize=(12,5))

plt.subplot(121)
plt.plot(pos[:,0],pos[:,1],'.',alpha=0.5)
for i,ch in enumerate(ch_names):
    plt.text(pos[i,0],pos[i,1],ch,va='center',ha='center')
plt.title('Emotiv: 14 channels')

ch_names = sp.eeg.presets.standard_1005_ch
pos, ch = sp.eeg.s1005_get_epos2d(ch_names)

plt.subplot(122)
plt.plot(pos[:,0],pos[:,1],'.',alpha=0.5)
for i,ch in enumerate(ch_names):
    plt.text(pos[i,0],pos[i,1],ch,va='center',ha='center')
plt.title(f'All 10-05 Channels: (n{len(ch_names)})')
plt.show()
Emotiv: 14 channels, All 10-05 Channels: (n346)

Convolution with missing values (NaNs)

1D

sp.conv1d_nan

import numpy as np
import matplotlib.pyplot as plt
import scipy
import spkit as sp
seed = 4
x = (sp.create_signal_1d(n=100,seed=seed,sg_winlen=5)*10).round(0)
t = np.arange(len(x))/100
np.random.seed(seed)
r = np.random.rand(*x.shape)
x[r<0.05] = np.nan
kernel = np.ones(7)/7
np.random.seed(None)
x_scipy = scipy.signal.convolve(x.copy(), kernel,mode='same')
x_spkit = sp.conv1d_nan(x.copy(), kernel)
plt.figure(figsize=(8,7))
plt.subplot(311)
plt.plot(t,x,color='C0')
plt.vlines(t[np.isnan(x)],ymin=np.nanmin(x),ymax=np.nanmax(x),color='r',alpha=0.2,lw=8,label='missing: NaN')
plt.xlim([t[0],t[-1]])
plt.ylim([np.nanmin(x),np.nanmax(x)])
plt.legend(bbox_to_anchor=(1,1.2))
plt.grid()
plt.title('Signal with NaNs')
plt.subplot(312)
plt.plot(t,x_scipy)
plt.vlines(t[np.isnan(x_scipy)],ymin=np.nanmin(x),ymax=np.nanmax(x),color='r',alpha=0.2,lw=5.5)
plt.xlim([t[0],t[-1]])
plt.ylim([np.nanmin(x),np.nanmax(x)])
plt.grid()
plt.title('Convolution uisng Scipy (scipy.signal.convolution)')
plt.subplot(313)
plt.plot(t,x_spkit)
plt.xlim([t[0],t[-1]])
plt.ylim([np.nanmin(x),np.nanmax(x)])
plt.grid()
plt.title('Convolution uisng Spkit (sp.conv1d_nan)')
plt.tight_layout()
plt.show()
Signal with NaNs, Convolution uisng Scipy (scipy.signal.convolution), Convolution uisng Spkit (sp.conv1d_nan)
2D

sp.conv2d_nan

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scipy
import spkit as sp
seed = 2
I = (sp.create_signal_2d(n=10,seed=seed,sg_winlen=3)*10).round(0)
np.random.seed(seed)
r = np.random.rand(*I.shape)
np.random.seed(None)
I[r<0.05] = np.nan
kernel = np.ones([3,3])/9
I_scipy = scipy.signal.convolve2d(I.copy(), kernel,mode='same', boundary='fill',fillvalue=0)
I_spkit = sp.conv2d_nan(I.copy(), kernel, boundary='fill',fillvalue=0)
plt.figure(figsize=(12,4))
plt.subplot(131)
sns.heatmap(I, annot=True,cbar=False,xticklabels='', yticklabels='')
plt.title('Image with NaNs')
plt.subplot(132)
sns.heatmap(I_scipy, annot=True,cbar=False,xticklabels='', yticklabels='')
plt.title('Convolution uisng Scipy \n (scipy.signal.convolve2d)')
plt.subplot(133)
sns.heatmap(I_spkit, annot=True,cbar=False,xticklabels='', yticklabels='')
plt.title('Convolution uisng Spkit \n (sp.conv2d_nan)')
plt.tight_layout()
plt.show()
Image with NaNs, Convolution uisng Scipy   (scipy.signal.convolve2d), Convolution uisng Spkit   (sp.conv2d_nan)

Filling Missing values with inter/exterpolation

# 1D
# ~~~~~
#sp.fill_nans_1d
import numpy as np
import spkit as sp
x = np.array([1,1,np.nan, 3,4,9,3, np.nan])
y = sp.fill_nans_1d(x)
print(x)
print(y)
[ 1.  1. nan  3.  4.  9.  3. nan]
[ 1.  1.  2.  3.  4.  9.  3. -3.]
2D

sp.fill_nans_2d

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scipy
import spkit as sp
seed = 2
I = (sp.create_signal_2d(n=10,seed=seed,sg_winlen=3)*10).round(0)
np.random.seed(seed)
r = np.random.rand(*I.shape)
I[r<0.05] = np.nan
np.random.seed(None)
kernel = np.ones([2,2])/4
I_spkit = sp.conv2d_nan(I.copy(), kernel, boundary='reflect',fillvalue=0)
I_fill, I_sm  = sp.fill_nans_2d(I.copy())
plt.figure(figsize=(12,4))
plt.subplot(131)
sns.heatmap(I, annot=True,cbar=False,xticklabels='', yticklabels='')
plt.title('Matrix with NaNs')
plt.subplot(132)
sns.heatmap(I_fill, annot=True,cbar=False,xticklabels='', yticklabels='')
plt.title('Filling NaNs with \n (sp.fill_nans_2d)')
plt.subplot(133)
sns.heatmap(I_spkit, annot=True,cbar=False,xticklabels='', yticklabels='')
plt.title('Smoothing with \n (sp.conv2d_nan)')
plt.tight_layout()
plt.show()
Matrix with NaNs, Filling NaNs with   (sp.fill_nans_2d), Smoothing with   (sp.conv2d_nan)

Wavelet Decomped Signals

  1. Wavelet Transform

  2. Wavelet Packet Decompositon

# Example 1: Wavelet Transform
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# sp.wavelet_decomposed_signals
import numpy as np
import matplotlib.pyplot as plt
import spkit as sp
x,fs,lead_names = sp.data.ecg_sample_12leads(sample=2)
x = x[:int(fs*5),5]
x = sp.filterDC_sGolay(x, window_length=fs//3+1)
t = np.arange(len(x))/fs
XR = sp.wavelet_decomposed_signals(x,wv='db3',L=3,plot_each=False,WPD=False)
plt.show()
Decomposed using Wavelet Transform (L=3)

Example 2: Wavelet Packet Decomposition

import numpy as np
import matplotlib.pyplot as plt
import spkit as sp
x,fs,lead_names = sp.data.ecg_sample_12leads(sample=2)
x = x[:int(fs*5),5]
x = sp.filterDC_sGolay(x, window_length=fs//3+1)
t = np.arange(len(x))/fs
XR = sp.wavelet_decomposed_signals(x,wv='db3',L=3,plot_each=False,WPD=True)
plt.show()
Decomposed using Wavelet Packet Decomposition(L=3)

MEA: Multi-Electrode Array Processing

A full Documentation of MEA Processing Library is added.

MEA: Multi-Electrode Array Processing

https://raw.githubusercontent.com/spkit/spkit.github.io/master/assets/images/docs_fig/mea_proce_2.png https://raw.githubusercontent.com/spkit/spkit.github.io/master/assets/images/docs_fig/mea_proce_3.png

Check Examples of MEA

Total running time of the script: (0 minutes 1.395 seconds)

Related examples

EEG Topographic Map

EEG Topographic Map

Release Highlights for spkit 0.0.9.6

Release Highlights for spkit 0.0.9.6

EEG Data from EDF File

EEG Data from EDF File

Wavelet Filtering

Wavelet Filtering

Sinusoidal Model: Analysis and Synthesis

Sinusoidal Model: Analysis and Synthesis

Gallery generated by Sphinx-Gallery