Welcome to pyseries documentation!

_images/logo.jpg

Overwiev

pySeries is a package for statistical analysis of EEG data. Developed for neuro and cognitive science academics looking for a quick start into EEG data analysis with python.

Documentation

ReadData

Projects

Visually Evoked Potentials

import sys
sys.path.insert(0, '/Users/user/Desktop/repo_for_pyseries/pyseries')

import pyseries.LoadingData as loading
import pyseries.Preprocessing as prep
import pyseries.Analysis as analysis
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from scipy import stats

# Notebook settings (i.e. this thing settings)
%matplotlib inline
#%matplotlib notebook
#Change to %matplotlib notebook to be able to zoom, pan, etc the figures,
#inline is only used so the notebook can be exported to .rst format and hosted on readthedocs
%load_ext autoreload
%autoreload 2
def calc_corr(path):
    #Read single subject data - eeg, info about eeg and info from experimental app (unity)
    recording = loading.Read_edf.Combine_EDF_XML(path, 3, 70)
    #Display markers over the whole signal
    prep.Epochs.mark_events(recording,['EEG O1'], subject_name = path)

    #Define epochs for analysis
    epochs_info= {"Please Count": [0, 500*10], "Only Look": [0, 500 *10]}
    #Create them by slicing the signal
    epochs = prep.Epochs.Make_Epochs_for_Channels(recording, ['EEG O1','EEG O2','EEG P3', 'EEG P4'],epochs_info)
    #Re-reference, because only by subtracting P from O-electrodes ssvep response becomes visible
    new_ref = {}
    new_ref['Only Look'] = epochs ['EEG O2']['Only Look'] - epochs['EEG P4']['Only Look']
    new_ref['Please Count'] = epochs ['EEG O2']['Please Count'] - epochs ['EEG P4']['Please Count']
    new_epochs  = {"O-P":new_ref}

    #Get the accuracy in counting condition
    responses = recording['events'][recording['events']["code"] == "responded"]
    accuracy = responses['response'] / responses['expected']

    #Get the power spectra in two conditions
    power_density= analysis.Explore.PlotPowerSpectrum(new_epochs['O-P'], 498, mode = 'period', name = path, freq_min = 0, freq_max = 20)

    ssvep = analysis.Normalize.Z_score( power_density['Please Count'][1][:,49] )
    accuracy = analysis.Normalize.Z_score( accuracy )

    return ssvep, accuracy, power_density
def plot_slow_ssvep():
    #Slow is 5Hz flicker
    paths = ['/Users/user/Desktop/nagrania_eeg/ssvep/Blazej_13_06_16/',
            '/Users/user/Desktop/nagrania_eeg/ssvep/Ania_14_06_16/',
            '/Users/user/Desktop/nagrania_eeg/ssvep/Karen_14_06_16/',
            '/Users/user/Desktop/nagrania_eeg/ssvep/Agnieszka_03_06/',
            '/Users/user/Desktop/nagrania_eeg/ssvep/Kuba_14_06_16/',
            '/Users/user/Desktop/nagrania_eeg/ssvep/Rysiek_03_06/'
            ]

    all_ssvep = []
    all_acc = []

    saving = {}
    for p in paths:
        ssvep, acc, pxx = calc_corr(p)
        all_ssvep.extend(ssvep)
        all_acc.extend(acc)

        saving[p] = ssvep

    sns.jointplot(x = np.array(all_ssvep),y =  np.array(all_acc), kind="reg")
    return saving
def plot_fast_ssvep():
    #fast is 20 Hz flicker
    paths = ['/Users/user/Desktop/nagrania_eeg/ssvep_20hz/Agnieszka_03_06/',
             '/Users/user/Desktop/nagrania_eeg/ssvep_20hz/Rysiek_03_06/']

    for path in paths:

        #Read single subject data - eeg, info about eeg and info from experimental app (unity)
        recording = loading.Read_edf.Combine_EDF_XML(path, 0, 70)
        #Define epochs for analysis
        epochs_info= {"Only Look": [0, 500 *10]}
        #Create them by slicing the signal
        epochs = prep.Epochs.Make_Epochs_for_Channels(recording, ['EEG O1','EEG O2','EEG P3','EEG P4'],epochs_info)
        #Re-reference, because oonly then ssvep response becomes visible
        new_ref = {}
        new_ref['Only Look'] = epochs ['EEG O2']['Only Look'] - epochs['EEG P4']['Only Look']
        new_epochs  = {"O-P":new_ref}

        #Get the power spectra in two conditions
        power_density= analysis.Explore.PlotPowerSpectrum(new_epochs['O-P'], 498, mode = 'period', name = path, freq_min = 0, freq_max = 30)
plot_slow_ssvep()
Channels:
EEG F3
EEG F4
EEG P3
EEG P4
EEG O1
EEG O2
EEG T6
EEG A2
EEG Pz
(497.971446705165,)
/Users/user/Desktop/nagrania_eeg/ssvep/Blazej_13_06_16/
Channels:
EEG Fp1
EEG F3
EEG F4
EEG C3
EEG C4
EEG P3
EEG P4
EEG O1
EEG O2
EEG T5
EEG T6
EEG Pz
S1
S2
(497.971446705165,)
/Users/user/Desktop/nagrania_eeg/ssvep/Ania_14_06_16/
Channels:
EEG Fp1
EEG F3
EEG F4
EEG C3
EEG C4
EEG P3
EEG P4
EEG O1
EEG O2
EEG T3
EEG T4
EEG Pz
S1
S2
(497.971446705165,)
/Users/user/Desktop/nagrania_eeg/ssvep/Karen_14_06_16/
Channels:
EEG F3
EEG F4
EEG C3
EEG C4
EEG P3
EEG P4
EEG O1
EEG O2
EEG A2
EEG Cz
(497.971446705165,)
/Users/user/Desktop/nagrania_eeg/ssvep/Agnieszka_03_06/
Channels:
EEG Fp2
EEG F3
EEG F4
EEG C3
EEG C4
EEG P3
EEG P4
EEG O1
EEG O2
EEG T3
EEG Fz
EEG Cz
S1
S2
S3
S4
(497.971446705165,)
/Users/user/Desktop/nagrania_eeg/ssvep/Kuba_14_06_16/
Channels:
EEG F3
EEG F4
EEG C3
EEG C4
EEG P3
EEG P4
EEG O1
EEG O2
EEG A2
EEG Cz
(497.971446705165,)
/Users/user/Desktop/nagrania_eeg/ssvep/Rysiek_03_06/
/Users/user/anaconda/lib/python3.5/site-packages/statsmodels/nonparametric/kdetools.py:20: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
  y = X[:m/2+1] + np.r_[0,X[m/2+1:],0]*1j
{'/Users/user/Desktop/nagrania_eeg/ssvep/Agnieszka_03_06/': array([ 1.62312664, -0.64587493, -1.07742191, -0.57539491,  0.6755651 ]),
 '/Users/user/Desktop/nagrania_eeg/ssvep/Ania_14_06_16/': array([-1.88734758,  0.41555267,  1.08925904,  0.2441026 ,  0.13843327]),
 '/Users/user/Desktop/nagrania_eeg/ssvep/Blazej_13_06_16/': array([-1.51988438,  1.45266728, -0.50483657,  0.56995163,  0.00210205]),
 '/Users/user/Desktop/nagrania_eeg/ssvep/Karen_14_06_16/': array([-0.52336364, -0.10604935,  1.53643037,  0.53210927, -1.43912664]),
 '/Users/user/Desktop/nagrania_eeg/ssvep/Kuba_14_06_16/': array([-1.1445404 , -0.02263413, -1.07913341,  1.15506314,  1.09124479]),
 '/Users/user/Desktop/nagrania_eeg/ssvep/Rysiek_03_06/': array([ 0.57460658,  1.19457484, -1.48773301,  0.56278917, -0.84423758])}
_images/output_4_31.png _images/output_4_41.png _images/output_4_51.png _images/output_4_61.png _images/output_4_71.png _images/output_4_81.png _images/output_4_91.png _images/output_4_10.png _images/output_4_11.png _images/output_4_12.png _images/output_4_13.png _images/output_4_14.png _images/output_4_15.png
plot_fast_ssvep()
Channels:
EEG F3
EEG F4
EEG C3
EEG C4
EEG P3
EEG P4
EEG O1
EEG O2
EEG A2
EEG Cz
(497.971446705165,)
/Users/user/Desktop/nagrania_eeg/ssvep_20hz/Agnieszka_03_06/
Channels:
EEG F3
EEG F4
EEG C3
EEG C4
EEG P3
EEG P4
EEG O1
EEG O2
EEG A2
EEG Cz
(497.971446705165,)
/Users/user/Desktop/nagrania_eeg/ssvep_20hz/Rysiek_03_06/
_images/output_5_1.png _images/output_5_2.png

Tutorials

PCA filtering

Filter signals using PCA decomposition (sklearn.decomposition.PCA()) of their fast-fourier transform

  1. Identify outliers in fft-transformed signal with PrepareData.MD_removeOutliers()
  2. Identify clusters in ft-transformed signal with PrepareData.Cluster()
import LoadingData.ReadData as rd
import Preprocessing.PrepareData as pd
in_path = '/Users/ryszardcetnarski/Desktop/Nencki/Badanie_NFB/Dane/fft_treningi/'
filter_list = ['P3_trening_','P4_trening_', 'F3_trening_', 'F4_trening_']
#load averaged fft from trainings
signals_dict = rd.LoadAvg(in_path, filter_list, freq_lim = [15,40])
#label the outliers
labels, signals_colum_major = pd.FilterIndividualAndGroup(signals_dict, plot_on = True, log = True)
#Plot'em
pd.MarkOutliers(labels[labels['mask'] ==1], rd.LoadAvg(in_path, filter_list, freq_lim = [0,50]))
N outliers inside individual: 338, 0.039348 %

For n_clusters = 2 The average silhouette_score is : 0.735854433865

N outliers across group: 539, 0.065317 %
_images/output_1_2.png _images/output_1_3.png _images/output_1_4.png _images/output_1_5.png _images/output_1_6.png _images/output_1_7.png _images/output_1_8.png _images/output_1_9.png _images/output_1_10.png _images/output_1_11.png _images/output_1_12.png _images/output_1_13.png _images/output_1_14.png _images/output_1_15.png _images/output_1_16.png _images/output_1_17.png _images/output_1_18.png _images/output_1_19.png _images/output_1_20.png _images/output_1_21.png _images/output_1_22.png _images/output_1_23.png _images/output_1_24.png _images/output_1_25.png _images/output_1_26.png _images/output_1_27.png _images/output_1_28.png _images/output_1_29.png _images/output_1_30.png _images/output_1_31.png _images/output_1_32.png _images/output_1_33.png _images/output_1_34.png _images/output_1_35.png _images/output_1_36.png _images/output_1_37.png _images/output_1_38.png _images/output_1_39.png _images/output_1_40.png _images/output_1_41.png _images/output_1_42.png _images/output_1_43.png _images/output_1_44.png _images/output_1_45.png _images/output_1_46.png _images/output_1_47.png _images/output_1_48.png _images/output_1_49.png _images/output_1_50.png _images/output_1_51.png _images/output_1_52.png _images/output_1_53.png _images/output_1_54.png

ANOVA

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
import Analysis.Anova as anova


%matplotlib inline
%load_ext autoreload
%autoreload 2
groups = []
for mean in [1, 1.5, 1.5, 1]:
    groups.append(np.random.normal(mean, 0.5, 100))

groups = pd.DataFrame(groups).T
ax = sns.boxplot(groups)
_images/output_1_1.png
anova.one_way(groups)
+-----------+-------------+--------------+-------------+-------------+------------+
|   F-value |     p-value |   effect sss |   effect df |   error sss |   error df |
+===========+=============+==============+=============+=============+============+
|   35.4803 | 1.11022e-16 |      24.6688 |           3 |     91.7773 |        396 |
+-----------+-------------+--------------+-------------+-------------+------------+
(27.174986167650943, 5.5511151231257827e-16, 3, 396)
#Conduct anova on one population which was exposed to different levels of two treatments

factorByfactor = np.array([[np.random.normal(1, 0.5, 100), np.random.normal(1.5, 0.5, 100), np.random.normal(1, 0.5, 100)],
                          [np.random.normal(1, 0.5, 100), np.random.normal(1.5, 0.5, 100), np.random.normal(1, 0.5, 100)]]
                         ).swapaxes(0,2).swapaxes(1,2)

anova.two_way(factorByfactor, 'seed', 'fertilizer')
+-------------+---------------+------+------------+-------------+
| Source      |   Mean square |   df |   F-values |    p-values |
+=============+===============+======+============+=============+
| seed        |      0.750668 |    1 |    3.24798 | 0.0720186   |
+-------------+---------------+------+------------+-------------+
| fertilizer  |     20.3989   |    2 |   88.2614  | 1.11022e-16 |
+-------------+---------------+------+------------+-------------+
| Interaction |      0.234242 |    2 |    1.01351 | 0.363568    |
+-------------+---------------+------+------------+-------------+