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.
Files changed (130) hide show
  1. {eegprep-0.1.0/src/eegprep.egg-info → eegprep-0.2.3}/PKG-INFO +14 -8
  2. {eegprep-0.1.0 → eegprep-0.2.3}/README.md +9 -7
  3. {eegprep-0.1.0 → eegprep-0.2.3}/pyproject.toml +9 -3
  4. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/ICL_feature_extractor.py +2 -1
  5. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_artifacts.py +19 -19
  6. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_asr.py +10 -10
  7. eegprep-0.2.3/src/eegprep/netICL.mat +0 -0
  8. {eegprep-0.1.0 → eegprep-0.2.3/src/eegprep.egg-info}/PKG-INFO +14 -8
  9. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep.egg-info/SOURCES.txt +1 -0
  10. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep.egg-info/requires.txt +5 -0
  11. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_artifacts.py +5 -5
  12. {eegprep-0.1.0 → eegprep-0.2.3}/LICENSE +0 -0
  13. {eegprep-0.1.0 → eegprep-0.2.3}/setup.cfg +0 -0
  14. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/__init__.py +0 -0
  15. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/bids_list_eeg_files.py +0 -0
  16. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/bids_preproc.py +0 -0
  17. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_channels.py +0 -0
  18. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_channels_nolocs.py +0 -0
  19. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_drifts.py +0 -0
  20. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_flatlines.py +0 -0
  21. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/clean_windows.py +0 -0
  22. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_autocorr.py +0 -0
  23. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_autocorr_fftw.py +0 -0
  24. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_autocorr_welch.py +0 -0
  25. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_checkset.py +0 -0
  26. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_compare.py +0 -0
  27. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_decodechan.py +0 -0
  28. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_eeg2mne.py +0 -0
  29. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_eegrej.py +0 -0
  30. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_findboundaries.py +0 -0
  31. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_interp.py +0 -0
  32. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_lat2point.py +0 -0
  33. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_mne2eeg.py +0 -0
  34. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_mne2eeg_epochs.py +0 -0
  35. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_options.py +0 -0
  36. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_picard.py +0 -0
  37. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_point2lat.py +0 -0
  38. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeg_rpsd.py +0 -0
  39. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eeglabcompat.py +0 -0
  40. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eegobj.py +0 -0
  41. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/eegrej.py +0 -0
  42. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/epoch.py +0 -0
  43. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/iclabel.py +0 -0
  44. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/iclabel_net.py +0 -0
  45. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/iclabel_net_load_py_measures.py +0 -0
  46. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pinv.py +0 -0
  47. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_epoch.py +0 -0
  48. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_load_frombids.py +0 -0
  49. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_loadset.py +0 -0
  50. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_loadset_h5.py +0 -0
  51. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_reref.py +0 -0
  52. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_reref_helper.py +0 -0
  53. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_resample.py +0 -0
  54. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_rmbase.py +0 -0
  55. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_saveset.py +0 -0
  56. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pop_select.py +0 -0
  57. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/pymat.py +0 -0
  58. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/redefine_functions.py +0 -0
  59. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/eeg_options_64bit.m +0 -0
  60. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/README.md +0 -0
  61. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/biosemi-128.locs +0 -0
  62. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/biosemi-sccn-128v1.locs +0 -0
  63. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/biosemi-sccn-128v2.locs +0 -0
  64. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/biosemi-sccn-256v1.locs +0 -0
  65. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/egi-gsn-hydrocell-129.locs +0 -0
  66. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/egi-gsn-hydrocell-257.locs +0 -0
  67. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/resources/montages/standard-10-5-342ch.locs +0 -0
  68. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/save_struct_as_hdf5.py +0 -0
  69. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/topoplot.py +0 -0
  70. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/__init__.py +0 -0
  71. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/asr.py +0 -0
  72. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/bids.py +0 -0
  73. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/coords.py +0 -0
  74. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/covariance.py +0 -0
  75. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/git.py +0 -0
  76. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/logs.py +0 -0
  77. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/misc.py +0 -0
  78. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/ransac.py +0 -0
  79. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/sigproc.py +0 -0
  80. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/spatial.py +0 -0
  81. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/stats.py +0 -0
  82. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep/utils/testing.py +0 -0
  83. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep.egg-info/dependency_links.txt +0 -0
  84. {eegprep-0.1.0 → eegprep-0.2.3}/src/eegprep.egg-info/top_level.txt +0 -0
  85. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_ICL_feature_extractor.py +0 -0
  86. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_bids_preproc.py +0 -0
  87. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_bids_preproc_old.py +0 -0
  88. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_asr.py +0 -0
  89. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_drifts.py +0 -0
  90. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_flatlines.py +0 -0
  91. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_rawdata.py +0 -0
  92. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_clean_windows.py +0 -0
  93. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_autocorr.py +0 -0
  94. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_autocorr_fftw.py +0 -0
  95. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_autocorr_welch.py +0 -0
  96. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_compare.py +0 -0
  97. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_decodechan.py +0 -0
  98. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_eeg2mne.py +0 -0
  99. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_eegrej.py +0 -0
  100. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_interp.py +0 -0
  101. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_lat2point.py +0 -0
  102. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_mne2eeg.py +0 -0
  103. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_mne2eeg_epochs.py +0 -0
  104. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_picard.py +0 -0
  105. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeg_point2lat.py +0 -0
  106. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eegfindboundaries.py +0 -0
  107. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eeglabcompat.py +0 -0
  108. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eegobj.py +0 -0
  109. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_eegrej.py +0 -0
  110. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_epoch.py +0 -0
  111. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_fixtures.py +0 -0
  112. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_iclabel.py +0 -0
  113. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_import_edf.py +0 -0
  114. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_logs.py +0 -0
  115. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pinv.py +0 -0
  116. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pipeline.py +0 -0
  117. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_epoch.py +0 -0
  118. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_loadset_h5.py +0 -0
  119. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_reref.py +0 -0
  120. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_resample.py +0 -0
  121. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_rmbase.py +0 -0
  122. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_saveset.py +0 -0
  123. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pop_select.py +0 -0
  124. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_pymat.py +0 -0
  125. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_spatial.py +0 -0
  126. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_topoplot.py +0 -0
  127. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_utils_asr.py +0 -0
  128. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_utils_covariance.py +0 -0
  129. {eegprep-0.1.0 → eegprep-0.2.3}/tests/test_utils_ransac.py +0 -0
  130. {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.1.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
- docker run --rm -it -v $(pwd):/usr/src/project dtyoung/eegprep /bin/bash
101
- docker run -u root --rm -it -v $(pwd):/usr/src/project dtyoung/eegprep /bin/bash
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 rmi dtyoung/eegprep
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
- docker run --rm -it -v $(pwd):/usr/src/project dtyoung/eegprep /bin/bash
38
- docker run -u root --rm -it -v $(pwd):/usr/src/project dtyoung/eegprep /bin/bash
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 rmi dtyoung/eegprep
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.1.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 = false
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
- _, temp_topo, _, _, _ = topoplot(EEG['icawinv'][:, it], EEG['chanlocs'][EEG['icachansind']], noplot='on')
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[str, Tuple[float, float]] = (0.25, 0.75),
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: str = 'off',
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 != 'off':
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 != 'off':
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 != 'off' or LineNoiseCriterion != 'off':
199
- chancorr_crit = 0.0 if ChannelCriterion == 'off' else float(ChannelCriterion)
200
- line_crit = 100.0 if LineNoiseCriterion == 'off' else float(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 != 'off':
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.lower() == 'on':
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 != 'off' and WindowCriterionTolerances != 'off':
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 'off').")
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 'off').")
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 'off').")
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.1.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
- docker run --rm -it -v $(pwd):/usr/src/project dtyoung/eegprep /bin/bash
101
- docker run -u root --rm -it -v $(pwd):/usr/src/project dtyoung/eegprep /bin/bash
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 rmi dtyoung/eegprep
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
@@ -36,6 +36,7 @@ src/eegprep/epoch.py
36
36
  src/eegprep/iclabel.py
37
37
  src/eegprep/iclabel_net.py
38
38
  src/eegprep/iclabel_net_load_py_measures.py
39
+ src/eegprep/netICL.mat
39
40
  src/eegprep/pinv.py
40
41
  src/eegprep/pop_epoch.py
41
42
  src/eegprep/pop_load_frombids.py
@@ -12,9 +12,14 @@ python-picard<0.9,>=0.8
12
12
  scipy>=1.7.0
13
13
  sympy>=1.14.0
14
14
  threadpoolctl>=3.6.0
15
+ torch
15
16
 
16
17
  [all]
17
18
  torch>=1.10.0
19
+ eeglabio>=0.1.2
20
+
21
+ [eeglabio]
22
+ eeglabio>=0.1.2
18
23
 
19
24
  [torch]
20
25
  torch>=1.10.0
@@ -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