eegprep 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eegprep/ICL_feature_extractor.py +90 -0
- eegprep/ICL_feature_extractor_compare_helper.py +19 -0
- eegprep/__init__.py +1 -0
- eegprep/eeg_autocorr.py +61 -0
- eegprep/eeg_autocorr_compare_helper.py +13 -0
- eegprep/eeg_autocorr_fftw.py +68 -0
- eegprep/eeg_autocorr_fftw_compare_helper.py +20 -0
- eegprep/eeg_autocorr_welch.py +61 -0
- eegprep/eeg_autocorr_welch_compare_helper.py +13 -0
- eegprep/eeg_checkset.py +110 -0
- eegprep/eeg_eeglab2mne.py +39 -0
- eegprep/eeg_mne2eeglab.py +46 -0
- eegprep/eeg_mne2eeglab_epochs.py +187 -0
- eegprep/eeg_rpsd.py +65 -0
- eegprep/eeg_rpsd_compare_helper.py +17 -0
- eegprep/eeglabcompat.py +117 -0
- eegprep/iclabel.py +51 -0
- eegprep/iclabel_helper.py +26 -0
- eegprep/iclabel_net.py +136 -0
- eegprep/iclabel_net_load_py_measures.py +137 -0
- eegprep/pop_loadset.py +97 -0
- eegprep/pop_reref.py +44 -0
- eegprep/pop_reref_compare_helper.py +31 -0
- eegprep/pop_reref_helper.py +22 -0
- eegprep/pop_resample.py +42 -0
- eegprep/pop_saveset.py +201 -0
- eegprep/save_struct_as_hdf5.py +50 -0
- eegprep/topoplot.py +194 -0
- eegprep/topoplot_compare_helper.py +29 -0
- eegprep-0.0.2.dist-info/LICENSE +20 -0
- eegprep-0.0.2.dist-info/METADATA +56 -0
- eegprep-0.0.2.dist-info/RECORD +34 -0
- eegprep-0.0.2.dist-info/WHEEL +5 -0
- eegprep-0.0.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from .topoplot import topoplot
|
|
3
|
+
from .eeg_rpsd import eeg_rpsd
|
|
4
|
+
from .eeg_autocorr_welch import eeg_autocorr_welch
|
|
5
|
+
from .eeg_autocorr import eeg_autocorr
|
|
6
|
+
from .eeg_autocorr_fftw import eeg_autocorr_fftw
|
|
7
|
+
from .pop_reref import pop_reref
|
|
8
|
+
|
|
9
|
+
def ICL_feature_extractor(EEG, flag_autocorr=False):
|
|
10
|
+
|
|
11
|
+
# Check inputs
|
|
12
|
+
ncomp = EEG['icawinv'].shape[1]
|
|
13
|
+
|
|
14
|
+
# Check for ICA key and if it is not empty
|
|
15
|
+
if not 'icawinv' in EEG.keys() or EEG['icawinv'].size == 0:
|
|
16
|
+
raise ValueError('You must have an ICA decomposition to use ICLabel')
|
|
17
|
+
|
|
18
|
+
# Assuming chanlocs are correct
|
|
19
|
+
if EEG['ref'] != 'average' and EEG['ref'] != 'averef':
|
|
20
|
+
EEG = pop_reref(EEG, []) #, exclude=list(set(range(EEG.nbchan)) - set(EEG.icachansind)))
|
|
21
|
+
# raise ValueError('Data must be rereferenced to average to use ICLabel')
|
|
22
|
+
# EEG = pop_reref(EEG, [], exclude=list(set(range(EEG.nbchan)) - set(EEG.icachansind)))
|
|
23
|
+
|
|
24
|
+
# Calculate ICA activations if missing and cast to double
|
|
25
|
+
if EEG['icaact'] is None:
|
|
26
|
+
raise ValueError('You must have ICA activations to use ICLabel')
|
|
27
|
+
# EEG['icaact'] = eeg_getica(EEG)
|
|
28
|
+
|
|
29
|
+
EEG['icaact'] = EEG['icaact'].astype(float)
|
|
30
|
+
|
|
31
|
+
# Check ICA is real
|
|
32
|
+
assert np.isreal(EEG['icaact']).all(), 'Your ICA decomposition must be real to use ICLabel'
|
|
33
|
+
|
|
34
|
+
# Calculate topo
|
|
35
|
+
topo = np.zeros((32, 32, 1, ncomp))
|
|
36
|
+
for it in range(ncomp):
|
|
37
|
+
_, temp_topo, _, _, _ = topoplot(EEG['icawinv'][:, it], EEG['chanlocs'][EEG['icachansind']], noplot='on')
|
|
38
|
+
temp_topo[np.isnan(temp_topo)] = 0
|
|
39
|
+
topo[:, :, 0, it] = temp_topo / np.max(np.abs(temp_topo))
|
|
40
|
+
|
|
41
|
+
# Cast
|
|
42
|
+
topo = topo.astype(np.float32)
|
|
43
|
+
|
|
44
|
+
# Calculate PSD
|
|
45
|
+
psd = eeg_rpsd(EEG, 100)
|
|
46
|
+
|
|
47
|
+
# Extrapolate or prune as needed
|
|
48
|
+
nfreq = psd.shape[1]
|
|
49
|
+
if nfreq < 100:
|
|
50
|
+
psd = np.hstack((psd, np.tile(psd[:, -1][:, np.newaxis], (1, 100 - nfreq))))
|
|
51
|
+
|
|
52
|
+
# Undo notch filter
|
|
53
|
+
for linenoise_ind in [50, 60]:
|
|
54
|
+
linenoise_around = [linenoise_ind - 1, linenoise_ind + 1]
|
|
55
|
+
difference = psd[:, linenoise_around] - psd[:, linenoise_ind][:, np.newaxis]
|
|
56
|
+
notch_ind = np.all(difference > 5, axis=1)
|
|
57
|
+
if np.any(notch_ind):
|
|
58
|
+
psd[notch_ind, linenoise_ind] = np.mean(psd[notch_ind][:, linenoise_around], axis=1)
|
|
59
|
+
|
|
60
|
+
# Normalize
|
|
61
|
+
psd = psd / np.max(np.abs(psd), axis=1)[:, np.newaxis]
|
|
62
|
+
|
|
63
|
+
psd = np.transpose(np.expand_dims(np.expand_dims(psd, axis=-1), axis=-1), (2, 1, 3, 0)).astype(np.float32)
|
|
64
|
+
|
|
65
|
+
# Calculate autocorrelation
|
|
66
|
+
if flag_autocorr:
|
|
67
|
+
if EEG['trials'] == 1:
|
|
68
|
+
if EEG['pnts'] / EEG['srate'] > 5:
|
|
69
|
+
autocorr = eeg_autocorr_welch(EEG)
|
|
70
|
+
else:
|
|
71
|
+
autocorr = eeg_autocorr(EEG)
|
|
72
|
+
else:
|
|
73
|
+
autocorr = eeg_autocorr_fftw(EEG)
|
|
74
|
+
|
|
75
|
+
# Reshape and cast
|
|
76
|
+
autocorr = np.transpose(np.expand_dims(np.expand_dims(autocorr, axis=-1), axis=-1), (2, 1, 3, 0)).astype(np.float32)
|
|
77
|
+
|
|
78
|
+
# Format outputs
|
|
79
|
+
if flag_autocorr:
|
|
80
|
+
features = [0.99 * topo, 0.99 * psd, 0.99 * autocorr]
|
|
81
|
+
else:
|
|
82
|
+
features = [0.99 * topo, 0.99 * psd]
|
|
83
|
+
|
|
84
|
+
return features
|
|
85
|
+
|
|
86
|
+
def test_ICL_feature_extractor():
|
|
87
|
+
flag_autocorr = True
|
|
88
|
+
EEG = EEG2
|
|
89
|
+
EEG['ref'] = 'averef'
|
|
90
|
+
EEG['chanlocs'] = np.random.randn(32, 3)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from ICL_feature_extractor import ICL_feature_extractor
|
|
2
|
+
from pop_loadset import pop_loadset
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
# check if a parameter is present and if it is assign eeglab_file_path to it
|
|
6
|
+
if len(sys.argv) > 1:
|
|
7
|
+
eeglab_file_path = sys.argv[1]
|
|
8
|
+
else:
|
|
9
|
+
eeglab_file_path = './eeglab_data_with_ica_tmp.set'
|
|
10
|
+
eeglab_file_path = '/Users/arno/Downloads/STUDYstern/S01/Memorize.set'
|
|
11
|
+
EEG = pop_loadset(eeglab_file_path)
|
|
12
|
+
|
|
13
|
+
# Print the loaded data
|
|
14
|
+
res = ICL_feature_extractor(EEG, True)
|
|
15
|
+
|
|
16
|
+
# save in a matlab file
|
|
17
|
+
import scipy.io
|
|
18
|
+
scipy.io.savemat('python_temp.mat', {'grid': res})
|
|
19
|
+
print('Saved python_temp.mat')
|
eegprep/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .iclabel import iclabel
|
eegprep/eeg_autocorr.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy.signal import resample_poly
|
|
3
|
+
from numpy.fft import fft, ifft
|
|
4
|
+
|
|
5
|
+
def eeg_autocorr(EEG, pct_data=None):
|
|
6
|
+
if pct_data is None:
|
|
7
|
+
pct_data = 100
|
|
8
|
+
|
|
9
|
+
# convert EEG['icaact'] to single precision
|
|
10
|
+
EEG['icaact'] = EEG['icaact'].astype(np.float32)
|
|
11
|
+
|
|
12
|
+
ncomp = EEG['icaact'].shape[0]
|
|
13
|
+
nfft = 2**np.ceil(np.log2(2 * EEG['pnts'] - 1)).astype(int)
|
|
14
|
+
|
|
15
|
+
# Calculate autocorrelation
|
|
16
|
+
c = np.zeros((ncomp, nfft))
|
|
17
|
+
for it in range(ncomp):
|
|
18
|
+
comp = EEG['icaact'][it,:].reshape(-1)
|
|
19
|
+
Xtmp = fft(comp, nfft)
|
|
20
|
+
Xtmp = Xtmp.astype(np.complex64) # matches MATLAB's single precision since python convert to double precision by default
|
|
21
|
+
X = np.abs(Xtmp)**2
|
|
22
|
+
c[it, :] = np.real(ifft(X))
|
|
23
|
+
|
|
24
|
+
# Adjust the size of the autocorrelation to match sampling rate
|
|
25
|
+
if EEG['pnts'] < EEG['srate']:
|
|
26
|
+
ac = np.hstack([c[:, :EEG['pnts']], np.zeros((ncomp, EEG['srate'] - EEG['pnts'] + 1))])
|
|
27
|
+
else:
|
|
28
|
+
ac = c[:, :EEG['srate'] + 1]
|
|
29
|
+
|
|
30
|
+
# Normalize by the 0-tap of the autocorrelation
|
|
31
|
+
ac /= ac[:, [0]]
|
|
32
|
+
|
|
33
|
+
# Resample to 1 second at 100 samples/sec
|
|
34
|
+
|
|
35
|
+
# print the size of the second dim of ac
|
|
36
|
+
ac = resample_poly(ac.T, up=100, down=EEG['srate']).T
|
|
37
|
+
ac = ac[:, 1:]
|
|
38
|
+
|
|
39
|
+
return ac
|
|
40
|
+
|
|
41
|
+
def test_eeg_autocorr():
|
|
42
|
+
EEG = {
|
|
43
|
+
'srate': 256,
|
|
44
|
+
'icaweights': np.random.randn(10, 256),
|
|
45
|
+
'pnts': 1000,
|
|
46
|
+
'trials': 5,
|
|
47
|
+
'icaact': np.random.randn(10, 1000, 5)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
psdmed = eeg_autocorr(EEG, 100)
|
|
51
|
+
|
|
52
|
+
# print information about psdmed
|
|
53
|
+
print(psdmed.shape)
|
|
54
|
+
|
|
55
|
+
#print(psdmed)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
#assert psdmed.shape == (10, 100)
|
|
59
|
+
#assert np.all(np.isfinite(psdmed))
|
|
60
|
+
|
|
61
|
+
test_eeg_autocorr()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from eeg_autocorr import eeg_autocorr
|
|
2
|
+
from pop_loadset import pop_loadset
|
|
3
|
+
|
|
4
|
+
eeglab_file_path = './eeglab_data_with_ica_tmp.set'
|
|
5
|
+
EEG = pop_loadset(eeglab_file_path)
|
|
6
|
+
|
|
7
|
+
# Print the loaded data
|
|
8
|
+
res = eeg_autocorr(EEG, 100)
|
|
9
|
+
|
|
10
|
+
# save in a matlab file
|
|
11
|
+
import scipy.io
|
|
12
|
+
scipy.io.savemat('eeg_autocorr_data.mat', {'grid': res})
|
|
13
|
+
print('Saved eeg_autocorr_data.mat')
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy import signal
|
|
3
|
+
from scipy.fft import fft, ifft, next_fast_len
|
|
4
|
+
from scipy.signal import resample_poly
|
|
5
|
+
from .pop_loadset import pop_loadset
|
|
6
|
+
from .pop_reref import pop_reref
|
|
7
|
+
|
|
8
|
+
def eeg_autocorr_fftw(EEG, pct_data=100):
|
|
9
|
+
|
|
10
|
+
# FFT length
|
|
11
|
+
nfft = next_fast_len(2 * EEG['pnts'] - 1)
|
|
12
|
+
|
|
13
|
+
# Initialize autocorrelation array
|
|
14
|
+
ncomp = EEG['icaact'].shape[0]
|
|
15
|
+
ac = np.zeros((ncomp, nfft))
|
|
16
|
+
|
|
17
|
+
# Calculate autocorrelation using FFT
|
|
18
|
+
for it in range(EEG['icaact'].shape[0]):
|
|
19
|
+
# Apply FFT
|
|
20
|
+
X = fft(EEG['icaact'][it, :, :], n=nfft, axis=0)
|
|
21
|
+
# Compute the mean of the power spectrum
|
|
22
|
+
ac[it, :] = np.mean(np.abs(X)**2, axis=1)
|
|
23
|
+
|
|
24
|
+
# Inverse FFT to get autocorrelation
|
|
25
|
+
ac = ifft(ac, axis=1)
|
|
26
|
+
|
|
27
|
+
# make sure the data is in real
|
|
28
|
+
ac = np.real(ac)
|
|
29
|
+
|
|
30
|
+
# Adjust the size of autocorrelation array
|
|
31
|
+
if EEG['pnts'] < EEG['srate']:
|
|
32
|
+
# ac = np.hstack( [ac[:, :EEG['pnts']], np.zeros((ncomp , EEG['srate'] - EEG['pnts'] + 1))])
|
|
33
|
+
ac = np.concatenate((ac[:, :EEG['pnts']], np.zeros((ac.shape[0], EEG['srate'] - EEG['pnts'] + 1))), axis=1)
|
|
34
|
+
else:
|
|
35
|
+
ac = ac[:, :EEG['srate'] + 1]
|
|
36
|
+
|
|
37
|
+
# Normalize by 0-lag autocorrelation
|
|
38
|
+
ac = ac / ac[:, 0][:, np.newaxis]
|
|
39
|
+
|
|
40
|
+
# resample to 1 second at 100 samples/sec
|
|
41
|
+
ac = resample_poly(ac.T, up=100, down=EEG['srate']).T
|
|
42
|
+
ac = ac[:, 1:101]
|
|
43
|
+
|
|
44
|
+
return ac
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_eeg_autocorr_fftw():
|
|
48
|
+
EEG = {
|
|
49
|
+
'srate': 256,
|
|
50
|
+
'icaweights': np.random.randn(10, 256),
|
|
51
|
+
'pnts': 1000,
|
|
52
|
+
'trials': 5,
|
|
53
|
+
'icaact': np.random.randn(10, 1000, 5)
|
|
54
|
+
}
|
|
55
|
+
EEG = pop_loadset('/System/Volumes/Data/data/data/STUDIES/STERN/S01/Memorize.set')
|
|
56
|
+
|
|
57
|
+
# reshape the last two dimensions of EEG['icaact']
|
|
58
|
+
# EEG['icaact'] = EEG['icaact'].reshape(EEG['icaact'].shape[0], -1)
|
|
59
|
+
|
|
60
|
+
# convert EEG['icaact'] to double precision
|
|
61
|
+
|
|
62
|
+
psdmed = eeg_autocorr_fftw(EEG, 100)
|
|
63
|
+
|
|
64
|
+
# print information about psdmed
|
|
65
|
+
print(psdmed.shape)
|
|
66
|
+
print(psdmed)
|
|
67
|
+
|
|
68
|
+
# test_eeg_autocorr_fftw()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from eeg_autocorr_fftw import eeg_autocorr_fftw
|
|
2
|
+
from pop_loadset import pop_loadset
|
|
3
|
+
from pop_reref import pop_reref
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
# check if a parameter is present and if it is assign eeglab_file_path to it
|
|
7
|
+
if len(sys.argv) > 1:
|
|
8
|
+
eeglab_file_path = sys.argv[1]
|
|
9
|
+
else:
|
|
10
|
+
eeglab_file_path = './eeglab_data_with_ica_tmp.set'
|
|
11
|
+
EEG = pop_loadset(eeglab_file_path)
|
|
12
|
+
EEG = pop_reref(EEG, [])
|
|
13
|
+
|
|
14
|
+
# Print the loaded data
|
|
15
|
+
res = eeg_autocorr_fftw(EEG, 100)
|
|
16
|
+
|
|
17
|
+
# save in a matlab file
|
|
18
|
+
import scipy.io
|
|
19
|
+
scipy.io.savemat('eeg_autocorr_data.mat', {'grid': res})
|
|
20
|
+
print('Saved eeg_autocorr_data.mat')
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy.signal import resample_poly
|
|
3
|
+
import random
|
|
4
|
+
from .pop_loadset import pop_loadset
|
|
5
|
+
import numpy as np
|
|
6
|
+
from numpy.fft import fft, ifft
|
|
7
|
+
|
|
8
|
+
def eeg_autocorr_welch(EEG, pct_data=100):
|
|
9
|
+
# clean input cutoff freq
|
|
10
|
+
if pct_data is None or pct_data == 0:
|
|
11
|
+
pct_data = 100
|
|
12
|
+
|
|
13
|
+
# setup constants
|
|
14
|
+
ncomp = EEG['icaweights'].shape[0]
|
|
15
|
+
n_points = min(EEG['pnts'], EEG['srate'] * 3)
|
|
16
|
+
nfft = 2**(int(np.log2(n_points * 2 - 1)) + 1)
|
|
17
|
+
cutoff = (EEG['pnts'] // n_points) * n_points
|
|
18
|
+
index = np.add.outer(np.ceil(np.arange(0, cutoff - n_points + 1, n_points // 2)).astype(int), np.arange(n_points)).astype(int)
|
|
19
|
+
index = index.T
|
|
20
|
+
|
|
21
|
+
# separate data segments
|
|
22
|
+
if pct_data != 100:
|
|
23
|
+
random.seed(0)
|
|
24
|
+
n_seg = index.shape[0] * EEG['trials']
|
|
25
|
+
subset = random.sample(range(n_seg), int(np.ceil(n_seg * pct_data / 100)))
|
|
26
|
+
random.seed() # restore normal random behavior
|
|
27
|
+
temp = np.reshape(EEG['icaact'][:, index, :], (ncomp, *index.shape, EEG['trials']))
|
|
28
|
+
segments = temp[:, :, subset]
|
|
29
|
+
else:
|
|
30
|
+
segments = np.reshape(EEG['icaact'][:, index, :], (ncomp, *index.shape, EEG['trials']))
|
|
31
|
+
|
|
32
|
+
# calc autocorrelation
|
|
33
|
+
ac = np.zeros((ncomp, nfft))
|
|
34
|
+
for it in range(ncomp):
|
|
35
|
+
fftpow = np.mean(np.abs(fft(segments[it, :, :], nfft, axis=0))**2, axis=1)
|
|
36
|
+
ac[it, :] = np.real(ifft(fftpow, axis=0)).T
|
|
37
|
+
|
|
38
|
+
# normalizefft
|
|
39
|
+
if EEG['pnts'] < EEG['srate']:
|
|
40
|
+
ac = np.concatenate([ac[:, :EEG['pnts']] / (ac[:, 0][:, np.newaxis] * np.arange(n_points, 0, -1) / n_points),
|
|
41
|
+
np.zeros((ncomp, EEG['srate'] - n_points + 1))], axis=1)
|
|
42
|
+
else:
|
|
43
|
+
ac = ac[:, :EEG['srate'] + 1] / (ac[:, 0][:, np.newaxis] * np.concatenate((np.arange(n_points, n_points - EEG['srate'], -1), np.array([max(1, n_points - EEG['srate'])]))) / n_points)
|
|
44
|
+
|
|
45
|
+
# resample to 1 second at 100 samples/sec
|
|
46
|
+
ac = resample_poly(ac.T, up=100, down=EEG['srate']).T
|
|
47
|
+
ac = ac[:, 1:101]
|
|
48
|
+
|
|
49
|
+
return ac
|
|
50
|
+
|
|
51
|
+
def test_eeg_autocorr_welch():
|
|
52
|
+
eeglab_file_path = './eeglab_data_with_ica_tmp.set'
|
|
53
|
+
EEG = pop_loadset(eeglab_file_path)
|
|
54
|
+
|
|
55
|
+
psdmed = eeg_autocorr_welch(EEG, 100)
|
|
56
|
+
|
|
57
|
+
# print information about psdmed
|
|
58
|
+
print(psdmed.shape)
|
|
59
|
+
print(psdmed)
|
|
60
|
+
|
|
61
|
+
# test_eeg_autocorr_welch()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from eeg_autocorr_welch import eeg_autocorr_welch
|
|
2
|
+
from pop_loadset import pop_loadset
|
|
3
|
+
|
|
4
|
+
eeglab_file_path = './eeglab_data_with_ica_tmp.set'
|
|
5
|
+
EEG = pop_loadset(eeglab_file_path)
|
|
6
|
+
|
|
7
|
+
# Print the loaded data
|
|
8
|
+
res = eeg_autocorr_welch(EEG, 100)
|
|
9
|
+
|
|
10
|
+
# save in a matlab file
|
|
11
|
+
import scipy.io
|
|
12
|
+
scipy.io.savemat('eeg_autocorr_welch_data.mat', {'grid': res})
|
|
13
|
+
print('Saved eeg_autocorr_welch_data.mat')
|
eegprep/eeg_checkset.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import os
|
|
3
|
+
from pop_loadset import pop_loadset
|
|
4
|
+
|
|
5
|
+
def eeg_checkset(EEG):
|
|
6
|
+
|
|
7
|
+
# Define the expected types
|
|
8
|
+
expected_types = {
|
|
9
|
+
'setname': str,
|
|
10
|
+
'filename': str,
|
|
11
|
+
'filepath': str,
|
|
12
|
+
'subject': str,
|
|
13
|
+
'group': str,
|
|
14
|
+
'condition': str,
|
|
15
|
+
'session': (str, int),
|
|
16
|
+
'comments': np.ndarray,
|
|
17
|
+
'nbchan': int,
|
|
18
|
+
'trials': int,
|
|
19
|
+
'pnts': int,
|
|
20
|
+
'srate': (float,int),
|
|
21
|
+
'xmin': float,
|
|
22
|
+
'xmax': float,
|
|
23
|
+
'times': np.ndarray, # Expecting a float numpy array
|
|
24
|
+
'data': np.ndarray, # Expecting a float numpy array
|
|
25
|
+
'icaact': np.ndarray, # Expecting a float numpy array
|
|
26
|
+
'icawinv': np.ndarray,# Expecting a float numpy array
|
|
27
|
+
'icasphere': np.ndarray, # Expecting a float numpy array
|
|
28
|
+
'icaweights': np.ndarray, # Expecting a float numpy array
|
|
29
|
+
'icachansind': np.ndarray, # Expecting an integer numpy array
|
|
30
|
+
'chanlocs': np.ndarray, # Expecting numpy array of dictionaries
|
|
31
|
+
'urchanlocs': np.ndarray, # Expecting numpy array of dictionaries
|
|
32
|
+
'chaninfo': dict,
|
|
33
|
+
'ref': str,
|
|
34
|
+
'event': np.ndarray, # Expecting numpy array of dictionaries
|
|
35
|
+
'urevent': np.ndarray, # Expecting numpy array of dictionaries
|
|
36
|
+
'eventdescription': np.ndarray, # Expecting numpy array of strings
|
|
37
|
+
'epoch': np.ndarray, # Expecting numpy array of dictionaries
|
|
38
|
+
'epochdescription': np.ndarray, # Expecting numpy array of strings
|
|
39
|
+
'reject': dict,
|
|
40
|
+
'stats': dict,
|
|
41
|
+
'specdata': dict,
|
|
42
|
+
'specicaact': dict,
|
|
43
|
+
'splinefile': str,
|
|
44
|
+
'icasplinefile': str,
|
|
45
|
+
'dipfit': dict,
|
|
46
|
+
'history': str,
|
|
47
|
+
'saved': str,
|
|
48
|
+
'etc': dict,
|
|
49
|
+
'datfile': str,
|
|
50
|
+
'run': (str, int),
|
|
51
|
+
'roi': dict,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Iterate through expected types and check input dictionary
|
|
55
|
+
for field, expected_type in expected_types.items():
|
|
56
|
+
if field not in EEG:
|
|
57
|
+
print(f"Field '{field}' is missing from the EEG dictionnary, adding it.")
|
|
58
|
+
|
|
59
|
+
# add default values
|
|
60
|
+
if expected_type == str:
|
|
61
|
+
EEG[field] = ''
|
|
62
|
+
elif expected_type == int:
|
|
63
|
+
EEG[field] = np.array([], dtype=int)
|
|
64
|
+
elif expected_type == float:
|
|
65
|
+
EEG[field] = np.array([], dtype=float)
|
|
66
|
+
elif expected_type == dict:
|
|
67
|
+
EEG[field] = {}
|
|
68
|
+
elif expected_type == np.ndarray:
|
|
69
|
+
EEG[field] = np.array([])
|
|
70
|
+
else:
|
|
71
|
+
EEG[field] = np.array([])
|
|
72
|
+
continue
|
|
73
|
+
|
|
74
|
+
value = EEG[field]
|
|
75
|
+
|
|
76
|
+
# Special cases for numpy arrays with specific content types
|
|
77
|
+
if isinstance(expected_type, type) and expected_type == np.ndarray:
|
|
78
|
+
if not isinstance(value, np.ndarray):
|
|
79
|
+
print(f"Field '{field}' is expected to be a numpy array but is of type {type(value).__name__}.")
|
|
80
|
+
continue
|
|
81
|
+
# Further checks for numpy array content types
|
|
82
|
+
if field in ['times', 'data', 'icaact', 'icawinv', 'icasphere', 'icaweights']:
|
|
83
|
+
if not np.issubdtype(value.dtype, np.floating):
|
|
84
|
+
print(f"Field '{field}' is expected to be a numpy array of floats but has dtype {value.dtype}.")
|
|
85
|
+
elif field in ['icachansind']:
|
|
86
|
+
if not np.issubdtype(value.dtype, np.integer):
|
|
87
|
+
print(f"Field '{field}' is expected to be a numpy array of integers but has dtype {value.dtype}.")
|
|
88
|
+
elif field in ['chanlocs', 'urchanlocs', 'event', 'urevent', 'epoch']:
|
|
89
|
+
if not all(isinstance(item, dict) for item in value):
|
|
90
|
+
print(f"Field '{field}' is expected to be a numpy array of dictionaries but contains other types.")
|
|
91
|
+
# elif field in ['eventdescription', 'epochdescription']:
|
|
92
|
+
# if not all(isinstance(item, str) for item in value):
|
|
93
|
+
# print(f"Field '{field}' is expected to be a numpy array of strings but contains other types.")
|
|
94
|
+
else:
|
|
95
|
+
# General type check
|
|
96
|
+
if not isinstance(value, expected_type):
|
|
97
|
+
# check for empty Ndarray
|
|
98
|
+
if isinstance(value, np.ndarray) and value.size == 0:
|
|
99
|
+
continue
|
|
100
|
+
print(f"Field '{field}' is expected to be of type {expected_type} but is of type {type(value).__name__}.")
|
|
101
|
+
|
|
102
|
+
return EEG
|
|
103
|
+
|
|
104
|
+
def test_eeg_checkset():
|
|
105
|
+
eeglab_file_path = './eeglab_data_with_ica_tmp.set'
|
|
106
|
+
EEG = pop_loadset(eeglab_file_path)
|
|
107
|
+
EEG = eeg_checkset(EEG)
|
|
108
|
+
print('Checkset done')
|
|
109
|
+
|
|
110
|
+
test_eeg_checkset()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from eeg_autocorr import eeg_autocorr
|
|
2
|
+
from pop_loadset import pop_loadset
|
|
3
|
+
import mne
|
|
4
|
+
import tempfile
|
|
5
|
+
import os
|
|
6
|
+
from mne.export import export_raw
|
|
7
|
+
from pop_saveset import pop_saveset # in development
|
|
8
|
+
|
|
9
|
+
# write a funtion that converts a MNE raw object to an EEGLAB set file
|
|
10
|
+
def eeg_eeglab2mne(EEG):
|
|
11
|
+
|
|
12
|
+
# Generate a temporary file name
|
|
13
|
+
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
|
|
14
|
+
temp_file_path = temp_file.name
|
|
15
|
+
|
|
16
|
+
base, _ = os.path.splitext(temp_file_path)
|
|
17
|
+
new_temp_file_path = base + ".set"
|
|
18
|
+
|
|
19
|
+
# save the raw file as a new EEGLAB .set file using MNE EEGLAB writer
|
|
20
|
+
pop_saveset(EEG, new_temp_file_path)
|
|
21
|
+
|
|
22
|
+
# load the EEGLAB set file
|
|
23
|
+
if EEG['trials'] > 1:
|
|
24
|
+
raw = mne.io.read_epochs_eeglab(new_temp_file_path)
|
|
25
|
+
else:
|
|
26
|
+
raw = mne.io.read_raw_eeglab(new_temp_file_path, preload=True)
|
|
27
|
+
|
|
28
|
+
return raw
|
|
29
|
+
|
|
30
|
+
def test_eeg_eeglab2mne():
|
|
31
|
+
eeglab_file_path = './eeglab_data_with_ica_tmp.set'
|
|
32
|
+
eeglab_file_path = '/System/Volumes/Data/data/matlab/eeglab/sample_data/eeglab_data_epochs_ica.set'
|
|
33
|
+
EEG = pop_loadset(eeglab_file_path)
|
|
34
|
+
raw = eeg_eeglab2mne(EEG)
|
|
35
|
+
|
|
36
|
+
# print the keys of the EEG dictionary
|
|
37
|
+
print(raw.info)
|
|
38
|
+
|
|
39
|
+
# test_eeg_eeglab2mne()
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from eeg_autocorr import eeg_autocorr
|
|
2
|
+
from pop_loadset import pop_loadset
|
|
3
|
+
import mne
|
|
4
|
+
import tempfile
|
|
5
|
+
import os
|
|
6
|
+
from mne.export import export_raw
|
|
7
|
+
import eeglabio
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
# write a funtion that converts a MNE raw object to an EEGLAB set file
|
|
11
|
+
def eeg_mne2eeglab(raw):
|
|
12
|
+
# Generate a temporary file name
|
|
13
|
+
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
|
|
14
|
+
temp_file_path = temp_file.name
|
|
15
|
+
|
|
16
|
+
base, _ = os.path.splitext(temp_file_path)
|
|
17
|
+
new_temp_file_path = base + ".set"
|
|
18
|
+
|
|
19
|
+
# save the raw file as a new EEGLAB .set file using MNE EEGLAB writer
|
|
20
|
+
export_raw(new_temp_file_path, raw, fmt='eeglab')
|
|
21
|
+
|
|
22
|
+
# load the EEGLAB set file
|
|
23
|
+
EEG = pop_loadset(new_temp_file_path)
|
|
24
|
+
|
|
25
|
+
return EEG
|
|
26
|
+
|
|
27
|
+
def test_eeg_mne2eeglab():
|
|
28
|
+
eeglab_file_path = './eeglab_data_with_ica_tmp.set'
|
|
29
|
+
eeglab_file_path = '/System/Volumes/Data/data/matlab/eeglab/sample_data/eeglab_data_epochs_ica.set'
|
|
30
|
+
EEG = pop_loadset(eeglab_file_path)
|
|
31
|
+
|
|
32
|
+
# create MNE info structure
|
|
33
|
+
info = mne.create_info(ch_names=[ x['labels'] for x in EEG['chanlocs']], sfreq=EEG['srate'], ch_types='eeg')
|
|
34
|
+
if EEG['trials'] > 1:
|
|
35
|
+
events = np.array([[i, 0, 1] for i in range(EEG['trials'])]) # NOT CORRECT CONVERTION JUST FOR TESTING
|
|
36
|
+
event_id = dict(dummy=1)
|
|
37
|
+
raw = mne.EpochsArray(EEG['data'].transpose(2,0,1), info, events, tmin=0, event_id=event_id)
|
|
38
|
+
else:
|
|
39
|
+
raw = mne.io.RawArray(EEG['data'], info)
|
|
40
|
+
|
|
41
|
+
EEG2 = eeg_mne2eeglab(raw)
|
|
42
|
+
|
|
43
|
+
# print the keys of the EEG dictionary
|
|
44
|
+
print(EEG2.keys())
|
|
45
|
+
|
|
46
|
+
# test_eeg_mne2eeglab()
|