eegprep 0.1.0__tar.gz → 0.2.3__tar.gz
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-0.1.0/src/eegprep.egg-info → eegprep-0.2.3}/PKG-INFO +14 -8
- {eegprep-0.1.0 → eegprep-0.2.3}/README.md +9 -7
- {eegprep-0.1.0 → eegprep-0.2.3}/pyproject.toml +9 -3
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/ICL_feature_extractor.py +2 -1
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_artifacts.py +19 -19
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_asr.py +10 -10
- eegprep-0.2.3/src/eegprep/netICL.mat +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3/src/eegprep.egg-info}/PKG-INFO +14 -8
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep.egg-info/SOURCES.txt +1 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep.egg-info/requires.txt +5 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_artifacts.py +5 -5
- {eegprep-0.1.0 → eegprep-0.2.3}/LICENSE +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/setup.cfg +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/__init__.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/bids_list_eeg_files.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/bids_preproc.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_channels.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_channels_nolocs.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_drifts.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_flatlines.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_windows.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_autocorr.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_autocorr_fftw.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_autocorr_welch.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_checkset.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_compare.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_decodechan.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_eeg2mne.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_eegrej.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_findboundaries.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_interp.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_lat2point.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_mne2eeg.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_mne2eeg_epochs.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_options.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_picard.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_point2lat.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_rpsd.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeglabcompat.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eegobj.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eegrej.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/epoch.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/iclabel.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/iclabel_net.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/iclabel_net_load_py_measures.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pinv.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_epoch.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_load_frombids.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_loadset.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_loadset_h5.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_reref.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_reref_helper.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_resample.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_rmbase.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_saveset.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_select.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pymat.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/redefine_functions.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/eeg_options_64bit.m +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/README.md +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/biosemi-128.locs +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/biosemi-sccn-128v1.locs +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/biosemi-sccn-128v2.locs +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/biosemi-sccn-256v1.locs +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/egi-gsn-hydrocell-129.locs +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/egi-gsn-hydrocell-257.locs +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/standard-10-5-342ch.locs +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/save_struct_as_hdf5.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/topoplot.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/__init__.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/asr.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/bids.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/coords.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/covariance.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/git.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/logs.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/misc.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/ransac.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/sigproc.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/spatial.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/stats.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/testing.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep.egg-info/dependency_links.txt +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep.egg-info/top_level.txt +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_ICL_feature_extractor.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_bids_preproc.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_bids_preproc_old.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_asr.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_drifts.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_flatlines.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_rawdata.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_windows.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_autocorr.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_autocorr_fftw.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_autocorr_welch.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_compare.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_decodechan.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_eeg2mne.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_eegrej.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_interp.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_lat2point.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_mne2eeg.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_mne2eeg_epochs.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_picard.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_point2lat.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eegfindboundaries.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeglabcompat.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eegobj.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eegrej.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_epoch.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_fixtures.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_iclabel.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_import_edf.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_logs.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pinv.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pipeline.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_epoch.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_loadset_h5.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_reref.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_resample.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_rmbase.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_saveset.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_select.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pymat.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_spatial.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_topoplot.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_utils_asr.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_utils_covariance.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_utils_ransac.py +0 -0
- {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_utils_testing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eegprep
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: EEG preprocessing pipeline on Python
|
|
5
5
|
Author-email: Arnaud Delorme <adelorme@gmail.com>, Young Truong <dt.young112@gmail.com>
|
|
6
6
|
License: BSD 2-Clause License
|
|
@@ -55,10 +55,14 @@ Requires-Dist: python-picard<0.9,>=0.8
|
|
|
55
55
|
Requires-Dist: scipy>=1.7.0
|
|
56
56
|
Requires-Dist: sympy>=1.14.0
|
|
57
57
|
Requires-Dist: threadpoolctl>=3.6.0
|
|
58
|
+
Requires-Dist: torch
|
|
58
59
|
Provides-Extra: torch
|
|
59
60
|
Requires-Dist: torch>=1.10.0; extra == "torch"
|
|
61
|
+
Provides-Extra: eeglabio
|
|
62
|
+
Requires-Dist: eeglabio>=0.1.2; extra == "eeglabio"
|
|
60
63
|
Provides-Extra: all
|
|
61
64
|
Requires-Dist: torch>=1.10.0; extra == "all"
|
|
65
|
+
Requires-Dist: eeglabio>=0.1.2; extra == "all"
|
|
62
66
|
Dynamic: license-file
|
|
63
67
|
|
|
64
68
|
# EEGPrep
|
|
@@ -96,15 +100,17 @@ The MATLAB and Python implementations were compared using the first two subjects
|
|
|
96
100
|
|
|
97
101
|
## Build Docker
|
|
98
102
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
## Remove Docker
|
|
103
|
+
### versioning
|
|
104
|
+
- pyproject version (change version inside file)
|
|
105
|
+
- main version (change version inside file)
|
|
106
|
+
- git tag
|
|
107
|
+
- docker version when building (see below)
|
|
105
108
|
|
|
109
|
+
### building
|
|
106
110
|
```
|
|
107
|
-
docker
|
|
111
|
+
docker build -t eegprep:0.2.3 -f DOCKERFILE .
|
|
112
|
+
docker tag eegprep:0.2.1 arnodelorme/eegprep:0.2.3
|
|
113
|
+
docker push arnodelorme/eegprep:0.2.3
|
|
108
114
|
```
|
|
109
115
|
|
|
110
116
|
Mounted folder in /usr/src/project
|
|
@@ -33,15 +33,17 @@ The MATLAB and Python implementations were compared using the first two subjects
|
|
|
33
33
|
|
|
34
34
|
## Build Docker
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
## Remove Docker
|
|
36
|
+
### versioning
|
|
37
|
+
- pyproject version (change version inside file)
|
|
38
|
+
- main version (change version inside file)
|
|
39
|
+
- git tag
|
|
40
|
+
- docker version when building (see below)
|
|
42
41
|
|
|
42
|
+
### building
|
|
43
43
|
```
|
|
44
|
-
docker
|
|
44
|
+
docker build -t eegprep:0.2.3 -f DOCKERFILE .
|
|
45
|
+
docker tag eegprep:0.2.1 arnodelorme/eegprep:0.2.3
|
|
46
|
+
docker push arnodelorme/eegprep:0.2.3
|
|
45
47
|
```
|
|
46
48
|
|
|
47
49
|
Mounted folder in /usr/src/project
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "eegprep"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Arnaud Delorme", email="adelorme@gmail.com" },
|
|
10
10
|
{ name="Young Truong", email="dt.young112@gmail.com" },
|
|
@@ -37,18 +37,23 @@ dependencies = [
|
|
|
37
37
|
"scipy>=1.7.0",
|
|
38
38
|
"sympy>=1.14.0",
|
|
39
39
|
"threadpoolctl>=3.6.0",
|
|
40
|
+
"torch"
|
|
40
41
|
]
|
|
41
42
|
|
|
42
43
|
[project.optional-dependencies]
|
|
43
44
|
torch = [
|
|
44
45
|
"torch>=1.10.0",
|
|
45
46
|
]
|
|
47
|
+
eeglabio = [
|
|
48
|
+
"eeglabio>=0.1.2",
|
|
49
|
+
]
|
|
46
50
|
all = [
|
|
47
51
|
"torch>=1.10.0",
|
|
52
|
+
"eeglabio>=0.1.2",
|
|
48
53
|
]
|
|
49
54
|
|
|
50
55
|
[tool.setuptools]
|
|
51
|
-
include-package-data =
|
|
56
|
+
include-package-data = true
|
|
52
57
|
|
|
53
58
|
[tool.setuptools.packages.find]
|
|
54
59
|
where = ["src"]
|
|
@@ -58,7 +63,8 @@ exclude = ["eegprep.eeglab*"]
|
|
|
58
63
|
"eegprep" = [
|
|
59
64
|
"resources/montages/*.locs",
|
|
60
65
|
"resources/montages/README.md",
|
|
61
|
-
"resources/*.m"
|
|
66
|
+
"resources/*.m",
|
|
67
|
+
"netICL.mat"
|
|
62
68
|
]
|
|
63
69
|
|
|
64
70
|
[tool.setuptools.exclude-package-data]
|
|
@@ -36,7 +36,8 @@ def ICL_feature_extractor(EEG, flag_autocorr=False):
|
|
|
36
36
|
# Calculate topo
|
|
37
37
|
topo = np.zeros((32, 32, 1, ncomp))
|
|
38
38
|
for it in range(ncomp):
|
|
39
|
-
|
|
39
|
+
tmp_chanlocs = [EEG['chanlocs'][i] for i in EEG['icachansind']]
|
|
40
|
+
_, temp_topo, _, _, _ = topoplot(EEG['icawinv'][:, it], tmp_chanlocs, noplot='on')
|
|
40
41
|
temp_topo[np.isnan(temp_topo)] = 0
|
|
41
42
|
topo[:, :, 0, it] = temp_topo / np.max(np.abs(temp_topo))
|
|
42
43
|
|
|
@@ -23,18 +23,18 @@ logger = logging.getLogger(__name__)
|
|
|
23
23
|
def clean_artifacts(
|
|
24
24
|
EEG: Dict[str, Any],
|
|
25
25
|
# Core parameters
|
|
26
|
-
ChannelCriterion: Union[float, str] = 0.8,
|
|
27
|
-
LineNoiseCriterion: Union[float, str] = 4.0,
|
|
28
|
-
BurstCriterion: Union[float, str] = 5.0,
|
|
29
|
-
WindowCriterion: Union[float, str] = 0.25,
|
|
30
|
-
Highpass: Union[
|
|
26
|
+
ChannelCriterion: Union[float, str, None] = 0.8,
|
|
27
|
+
LineNoiseCriterion: Union[float, str, None] = 4.0,
|
|
28
|
+
BurstCriterion: Union[float, str, None] = 5.0,
|
|
29
|
+
WindowCriterion: Union[float, str, None] = 0.25,
|
|
30
|
+
Highpass: Union[Tuple[float, float], str, None] = (0.25, 0.75),
|
|
31
31
|
# Detail parameters
|
|
32
32
|
ChannelCriterionMaxBadTime: float = 0.5,
|
|
33
|
-
BurstCriterionRefMaxBadChns: Union[float, str] = 0.075,
|
|
34
|
-
BurstCriterionRefTolerances: Union[Tuple[float, float], str] = (-np.inf, 5.5),
|
|
35
|
-
BurstRejection:
|
|
36
|
-
WindowCriterionTolerances: Union[Tuple[float, float], str] = (-np.inf, 7),
|
|
37
|
-
FlatlineCriterion: Union[float, str] = 5.0,
|
|
33
|
+
BurstCriterionRefMaxBadChns: Union[float, str, None] = 0.075,
|
|
34
|
+
BurstCriterionRefTolerances: Union[Tuple[float, float], str, None] = (-np.inf, 5.5),
|
|
35
|
+
BurstRejection: bool = False,
|
|
36
|
+
WindowCriterionTolerances: Union[Tuple[float, float], str, None] = (-np.inf, 7),
|
|
37
|
+
FlatlineCriterion: Union[float, str, None] = 5.0,
|
|
38
38
|
NumSamples: int = 50,
|
|
39
39
|
SubsetSize: float = 0.25,
|
|
40
40
|
NoLocsChannelCriterion: float = 0.45,
|
|
@@ -176,16 +176,16 @@ def clean_artifacts(
|
|
|
176
176
|
# ------------------------------------------------------------------
|
|
177
177
|
# 1) Flat‑line channel removal
|
|
178
178
|
# ------------------------------------------------------------------
|
|
179
|
-
if FlatlineCriterion
|
|
179
|
+
if FlatlineCriterion not in (None, 'off'):
|
|
180
180
|
logger.info('Detecting flat line channels...')
|
|
181
181
|
EEG = clean_flatlines(EEG, max_flatline_duration=float(FlatlineCriterion))
|
|
182
182
|
|
|
183
183
|
# ------------------------------------------------------------------
|
|
184
184
|
# 2) High‑pass filtering
|
|
185
185
|
# ------------------------------------------------------------------
|
|
186
|
-
if Highpass
|
|
186
|
+
if Highpass not in (None, 'off'):
|
|
187
187
|
if not isinstance(Highpass, (tuple, list)) or len(Highpass) != 2:
|
|
188
|
-
raise ValueError('Highpass must be a (low, high) tuple or "off".')
|
|
188
|
+
raise ValueError('Highpass must be a (low, high) tuple or None/"off".')
|
|
189
189
|
logger.info('Applying high‑pass filter...')
|
|
190
190
|
EEG = clean_drifts(EEG, tuple(Highpass))
|
|
191
191
|
# Keep a copy after HP for optional return
|
|
@@ -195,9 +195,9 @@ def clean_artifacts(
|
|
|
195
195
|
# 3) Channel cleaning (noisy / disconnected)
|
|
196
196
|
# ------------------------------------------------------------------
|
|
197
197
|
removed_channels = np.zeros(EEG['nbchan'], dtype=bool)
|
|
198
|
-
if ChannelCriterion
|
|
199
|
-
chancorr_crit = 0.0 if ChannelCriterion
|
|
200
|
-
line_crit = 100.0 if LineNoiseCriterion
|
|
198
|
+
if ChannelCriterion not in (None, 'off') or LineNoiseCriterion not in (None, 'off'):
|
|
199
|
+
chancorr_crit = 0.0 if ChannelCriterion in (None, 'off') else float(ChannelCriterion)
|
|
200
|
+
line_crit = 100.0 if LineNoiseCriterion in (None, 'off') else float(LineNoiseCriterion)
|
|
201
201
|
try:
|
|
202
202
|
EEG = clean_channels(
|
|
203
203
|
EEG,
|
|
@@ -226,7 +226,7 @@ def clean_artifacts(
|
|
|
226
226
|
# 4) Burst repair via ASR
|
|
227
227
|
# ------------------------------------------------------------------
|
|
228
228
|
BUR = EEG # default in case ASR is skipped
|
|
229
|
-
if BurstCriterion
|
|
229
|
+
if BurstCriterion not in (None, 'off'):
|
|
230
230
|
logger.info('Applying ASR burst repair...')
|
|
231
231
|
try:
|
|
232
232
|
BUR = clean_asr(
|
|
@@ -250,7 +250,7 @@ def clean_artifacts(
|
|
|
250
250
|
maxmem=int(MaxMem),
|
|
251
251
|
)
|
|
252
252
|
|
|
253
|
-
if BurstRejection
|
|
253
|
+
if BurstRejection:
|
|
254
254
|
# Determine unchanged samples after ASR repair
|
|
255
255
|
sample_mask = np.sum(np.abs(EEG['data'] - BUR['data']), axis=0) < 1e-8
|
|
256
256
|
# Convert to intervals (start,end) inclusive
|
|
@@ -290,7 +290,7 @@ def clean_artifacts(
|
|
|
290
290
|
# ------------------------------------------------------------------
|
|
291
291
|
# 5) Post‑clean windows stage
|
|
292
292
|
# ------------------------------------------------------------------
|
|
293
|
-
if WindowCriterion
|
|
293
|
+
if WindowCriterion not in (None, 'off') and WindowCriterionTolerances not in (None, 'off'):
|
|
294
294
|
logger.info('Final post‑processing – removing irrecoverable windows...')
|
|
295
295
|
EEG, _ = clean_windows(
|
|
296
296
|
EEG,
|
|
@@ -19,9 +19,9 @@ def clean_asr(
|
|
|
19
19
|
window_len: Optional[float] = None,
|
|
20
20
|
step_size: Optional[int] = None,
|
|
21
21
|
max_dims: float = 0.66,
|
|
22
|
-
ref_maxbadchannels: Union[float, str, np.ndarray] = 0.075,
|
|
23
|
-
ref_tolerances: Union[Tuple[float, float], str] = (-3.5, 5.5),
|
|
24
|
-
ref_wndlen: Union[float, str] = 1.0,
|
|
22
|
+
ref_maxbadchannels: Union[float, str, None, np.ndarray] = 0.075,
|
|
23
|
+
ref_tolerances: Union[Tuple[float, float], str, None] = (-3.5, 5.5),
|
|
24
|
+
ref_wndlen: Union[float, str, None] = 1.0,
|
|
25
25
|
use_gpu: bool = False,
|
|
26
26
|
useriemannian: Optional[str] = None,
|
|
27
27
|
maxmem: Optional[int] = 64
|
|
@@ -110,14 +110,14 @@ def clean_asr(
|
|
|
110
110
|
logger.error(f"An error occurred during clean_windows: {e}")
|
|
111
111
|
logger.warning("Could not automatically identify clean calibration data. Falling back to using the entire data for calibration.")
|
|
112
112
|
ref_section_data = data
|
|
113
|
-
elif isinstance(ref_maxbadchannels, str) and ref_maxbadchannels.lower() == 'off':
|
|
114
|
-
logger.info("Using the entire data for calibration ('ref_maxbadchannels' set to
|
|
113
|
+
elif (isinstance(ref_maxbadchannels, str) and ref_maxbadchannels.lower() == 'off') or ref_maxbadchannels is None:
|
|
114
|
+
logger.info(f"Using the entire data for calibration ('ref_maxbadchannels' set to {ref_maxbadchannels!r}).")
|
|
115
115
|
ref_section_data = data
|
|
116
|
-
elif isinstance(ref_tolerances, str) and ref_tolerances.lower() == 'off':
|
|
117
|
-
logger.info("Using the entire data for calibration ('ref_tolerances' set to
|
|
116
|
+
elif (isinstance(ref_tolerances, str) and ref_tolerances.lower() == 'off') or ref_tolerances is None:
|
|
117
|
+
logger.info(f"Using the entire data for calibration ('ref_tolerances' set to {ref_tolerances!r}).")
|
|
118
118
|
ref_section_data = data
|
|
119
|
-
elif isinstance(ref_wndlen, str) and ref_wndlen.lower() == 'off':
|
|
120
|
-
logger.info("Using the entire data for calibration ('ref_wndlen' set to
|
|
119
|
+
elif (isinstance(ref_wndlen, str) and ref_wndlen.lower() == 'off') or ref_wndlen is None:
|
|
120
|
+
logger.info(f"Using the entire data for calibration ('ref_wndlen' set to {ref_wndlen!r}).")
|
|
121
121
|
ref_section_data = data
|
|
122
122
|
elif isinstance(ref_maxbadchannels, np.ndarray):
|
|
123
123
|
logger.info("Using user-supplied data array for calibration.")
|
|
@@ -125,7 +125,7 @@ def clean_asr(
|
|
|
125
125
|
if ref_section_data.ndim != 2 or ref_section_data.shape[0] != C:
|
|
126
126
|
raise ValueError(f"User-supplied calibration data must be a 2D array with shape ({C}, n_samples).")
|
|
127
127
|
else:
|
|
128
|
-
raise ValueError(f"Unsupported value or type for 'ref_maxbadchannels': {ref_maxbadchannels}. Must be float, 'off', or numpy array.")
|
|
128
|
+
raise ValueError(f"Unsupported value or type for 'ref_maxbadchannels': {ref_maxbadchannels}. Must be float, None/'off', or numpy array.")
|
|
129
129
|
|
|
130
130
|
# --- Calibrate ASR ---
|
|
131
131
|
logger.info('Estimating ASR calibration statistics...')
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eegprep
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: EEG preprocessing pipeline on Python
|
|
5
5
|
Author-email: Arnaud Delorme <adelorme@gmail.com>, Young Truong <dt.young112@gmail.com>
|
|
6
6
|
License: BSD 2-Clause License
|
|
@@ -55,10 +55,14 @@ Requires-Dist: python-picard<0.9,>=0.8
|
|
|
55
55
|
Requires-Dist: scipy>=1.7.0
|
|
56
56
|
Requires-Dist: sympy>=1.14.0
|
|
57
57
|
Requires-Dist: threadpoolctl>=3.6.0
|
|
58
|
+
Requires-Dist: torch
|
|
58
59
|
Provides-Extra: torch
|
|
59
60
|
Requires-Dist: torch>=1.10.0; extra == "torch"
|
|
61
|
+
Provides-Extra: eeglabio
|
|
62
|
+
Requires-Dist: eeglabio>=0.1.2; extra == "eeglabio"
|
|
60
63
|
Provides-Extra: all
|
|
61
64
|
Requires-Dist: torch>=1.10.0; extra == "all"
|
|
65
|
+
Requires-Dist: eeglabio>=0.1.2; extra == "all"
|
|
62
66
|
Dynamic: license-file
|
|
63
67
|
|
|
64
68
|
# EEGPrep
|
|
@@ -96,15 +100,17 @@ The MATLAB and Python implementations were compared using the first two subjects
|
|
|
96
100
|
|
|
97
101
|
## Build Docker
|
|
98
102
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
## Remove Docker
|
|
103
|
+
### versioning
|
|
104
|
+
- pyproject version (change version inside file)
|
|
105
|
+
- main version (change version inside file)
|
|
106
|
+
- git tag
|
|
107
|
+
- docker version when building (see below)
|
|
105
108
|
|
|
109
|
+
### building
|
|
106
110
|
```
|
|
107
|
-
docker
|
|
111
|
+
docker build -t eegprep:0.2.3 -f DOCKERFILE .
|
|
112
|
+
docker tag eegprep:0.2.1 arnodelorme/eegprep:0.2.3
|
|
113
|
+
docker push arnodelorme/eegprep:0.2.3
|
|
108
114
|
```
|
|
109
115
|
|
|
110
116
|
Mounted folder in /usr/src/project
|
|
@@ -122,31 +122,31 @@ class TestCleanArtifactsBasic(DebuggableTestCase):
|
|
|
122
122
|
"""Test clean_artifacts with invalid highpass string parameter."""
|
|
123
123
|
with self.assertRaises(ValueError) as cm:
|
|
124
124
|
clean_artifacts(self.test_eeg, Highpass='invalid')
|
|
125
|
-
self.assertIn('Highpass must be a (low, high) tuple or "off"', str(cm.exception))
|
|
125
|
+
self.assertIn('Highpass must be a (low, high) tuple or None/"off"', str(cm.exception))
|
|
126
126
|
|
|
127
127
|
def test_clean_artifacts_invalid_highpass_single_value(self):
|
|
128
128
|
"""Test clean_artifacts with single value instead of tuple."""
|
|
129
129
|
with self.assertRaises(ValueError) as cm:
|
|
130
130
|
clean_artifacts(self.test_eeg, Highpass=0.5)
|
|
131
|
-
self.assertIn('Highpass must be a (low, high) tuple or "off"', str(cm.exception))
|
|
131
|
+
self.assertIn('Highpass must be a (low, high) tuple or None/"off"', str(cm.exception))
|
|
132
132
|
|
|
133
133
|
def test_clean_artifacts_invalid_highpass_too_many_values(self):
|
|
134
134
|
"""Test clean_artifacts with too many values in highpass tuple."""
|
|
135
135
|
with self.assertRaises(ValueError) as cm:
|
|
136
136
|
clean_artifacts(self.test_eeg, Highpass=(0.1, 0.5, 1.0))
|
|
137
|
-
self.assertIn('Highpass must be a (low, high) tuple or "off"', str(cm.exception))
|
|
137
|
+
self.assertIn('Highpass must be a (low, high) tuple or None/"off"', str(cm.exception))
|
|
138
138
|
|
|
139
139
|
def test_clean_artifacts_invalid_highpass_empty_tuple(self):
|
|
140
140
|
"""Test clean_artifacts with empty highpass tuple."""
|
|
141
141
|
with self.assertRaises(ValueError) as cm:
|
|
142
142
|
clean_artifacts(self.test_eeg, Highpass=())
|
|
143
|
-
self.assertIn('Highpass must be a (low, high) tuple or "off"', str(cm.exception))
|
|
143
|
+
self.assertIn('Highpass must be a (low, high) tuple or None/"off"', str(cm.exception))
|
|
144
144
|
|
|
145
145
|
def test_clean_artifacts_invalid_highpass_list_single(self):
|
|
146
146
|
"""Test clean_artifacts with single-element list."""
|
|
147
147
|
with self.assertRaises(ValueError) as cm:
|
|
148
148
|
clean_artifacts(self.test_eeg, Highpass=[0.5])
|
|
149
|
-
self.assertIn('Highpass must be a (low, high) tuple or "off"', str(cm.exception))
|
|
149
|
+
self.assertIn('Highpass must be a (low, high) tuple or None/"off"', str(cm.exception))
|
|
150
150
|
|
|
151
151
|
def test_clean_artifacts_valid_highpass_list(self):
|
|
152
152
|
"""Test clean_artifacts with valid highpass list (should work like tuple)."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|