eegdash 0.0.9__py3-none-any.whl → 0.2.0__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.

Potentially problematic release.


This version of eegdash might be problematic. Click here for more details.

@@ -1,10 +1,9 @@
1
- import numpy as np
2
1
  import numba as nb
2
+ import numpy as np
3
3
  from scipy import special
4
4
 
5
- from ..decorators import univariate_feature
6
- from .signal import signal_zero_crossings
7
-
5
+ from ..decorators import FeaturePredecessor, univariate_feature
6
+ from .signal import SIGNAL_PREDECESSORS, signal_zero_crossings
8
7
 
9
8
  __all__ = [
10
9
  "dimensionality_higuchi_fractal_dim",
@@ -15,6 +14,7 @@ __all__ = [
15
14
  ]
16
15
 
17
16
 
17
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
18
18
  @univariate_feature
19
19
  @nb.njit(cache=True, fastmath=True)
20
20
  def dimensionality_higuchi_fractal_dim(x, k_max=10, eps=1e-7):
@@ -33,6 +33,7 @@ def dimensionality_higuchi_fractal_dim(x, k_max=10, eps=1e-7):
33
33
  return hfd
34
34
 
35
35
 
36
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
36
37
  @univariate_feature
37
38
  def dimensionality_petrosian_fractal_dim(x):
38
39
  nd = signal_zero_crossings(np.diff(x, axis=-1))
@@ -40,6 +41,7 @@ def dimensionality_petrosian_fractal_dim(x):
40
41
  return log_n / (np.log(nd) + log_n)
41
42
 
42
43
 
44
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
43
45
  @univariate_feature
44
46
  def dimensionality_katz_fractal_dim(x):
45
47
  dists = np.abs(np.diff(x, axis=-1))
@@ -50,7 +52,6 @@ def dimensionality_katz_fractal_dim(x):
50
52
  return log_n / (np.log(d / L) + log_n)
51
53
 
52
54
 
53
- @univariate_feature
54
55
  @nb.njit(cache=True, fastmath=True)
55
56
  def _hurst_exp(x, ns, a, gamma_ratios, log_n):
56
57
  h = np.empty(x.shape[:-1])
@@ -76,6 +77,7 @@ def _hurst_exp(x, ns, a, gamma_ratios, log_n):
76
77
  return h
77
78
 
78
79
 
80
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
79
81
  @univariate_feature
80
82
  def dimensionality_hurst_exp(x):
81
83
  ns = np.unique(np.power(2, np.arange(2, np.log2(x.shape[-1]) - 1)).astype(int))
@@ -89,6 +91,7 @@ def dimensionality_hurst_exp(x):
89
91
  return _hurst_exp(x, ns, a, gamma_ratios, log_n)
90
92
 
91
93
 
94
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
92
95
  @univariate_feature
93
96
  @nb.njit(cache=True, fastmath=True)
94
97
  def dimensionality_detrended_fluctuation_analysis(x):
@@ -1,11 +1,13 @@
1
1
  import numbers
2
- import numpy as np
3
- from scipy import stats
4
2
 
5
- from ..decorators import univariate_feature
3
+ import numpy as np
4
+ from scipy import signal, stats
6
5
 
6
+ from ..decorators import FeaturePredecessor, univariate_feature
7
+ from ..extractors import FeatureExtractor
7
8
 
8
9
  __all__ = [
10
+ "HilbertFeatureExtractor",
9
11
  "signal_mean",
10
12
  "signal_variance",
11
13
  "signal_skewness",
@@ -23,51 +25,70 @@ __all__ = [
23
25
  ]
24
26
 
25
27
 
28
+ @FeaturePredecessor(FeatureExtractor)
29
+ class HilbertFeatureExtractor(FeatureExtractor):
30
+ def preprocess(self, x):
31
+ return np.abs(signal.hilbert(x - x.mean(axis=-1, keepdims=True), axis=-1))
32
+
33
+
34
+ SIGNAL_PREDECESSORS = [FeatureExtractor, HilbertFeatureExtractor]
35
+
36
+
37
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
26
38
  @univariate_feature
27
39
  def signal_mean(x):
28
40
  return x.mean(axis=-1)
29
41
 
30
42
 
43
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
31
44
  @univariate_feature
32
45
  def signal_variance(x, **kwargs):
33
46
  return x.var(axis=-1, **kwargs)
34
47
 
35
48
 
49
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
36
50
  @univariate_feature
37
51
  def signal_std(x, **kwargs):
38
52
  return x.std(axis=-1, **kwargs)
39
53
 
40
54
 
55
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
41
56
  @univariate_feature
42
57
  def signal_skewness(x, **kwargs):
43
58
  return stats.skew(x, axis=x.ndim - 1, **kwargs)
44
59
 
45
60
 
61
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
46
62
  @univariate_feature
47
63
  def signal_kurtosis(x, **kwargs):
48
64
  return stats.kurtosis(x, axis=x.ndim - 1, **kwargs)
49
65
 
50
66
 
67
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
51
68
  @univariate_feature
52
69
  def signal_root_mean_square(x):
53
70
  return np.sqrt(np.power(x, 2).mean(axis=-1))
54
71
 
55
72
 
73
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
56
74
  @univariate_feature
57
75
  def signal_peak_to_peak(x, **kwargs):
58
76
  return np.ptp(x, axis=-1, **kwargs)
59
77
 
60
78
 
79
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
61
80
  @univariate_feature
62
81
  def signal_quantile(x, q: numbers.Number = 0.5, **kwargs):
63
82
  return np.quantile(x, q=q, axis=-1, **kwargs)
64
83
 
65
84
 
85
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
66
86
  @univariate_feature
67
87
  def signal_line_length(x):
68
88
  return np.abs(np.diff(x, axis=-1)).mean(axis=-1)
69
89
 
70
90
 
91
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
71
92
  @univariate_feature
72
93
  def signal_zero_crossings(x, threshold=1e-15):
73
94
  zero_ind = np.logical_and(x > -threshold, x < threshold)
@@ -78,16 +99,21 @@ def signal_zero_crossings(x, threshold=1e-15):
78
99
  return zero_cross
79
100
 
80
101
 
102
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
81
103
  @univariate_feature
82
104
  def signal_hjorth_mobility(x):
83
105
  return np.diff(x, axis=-1).std(axis=-1) / x.std(axis=-1)
84
106
 
85
107
 
108
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
86
109
  @univariate_feature
87
110
  def signal_hjorth_complexity(x):
88
- return np.diff(x, 2, axis=-1).std(axis=-1) / x.std(axis=-1)
111
+ return (np.diff(x, 2, axis=-1).std(axis=-1) * x.std(axis=-1)) / np.diff(
112
+ x, axis=-1
113
+ ).var(axis=-1)
89
114
 
90
115
 
116
+ @FeaturePredecessor(*SIGNAL_PREDECESSORS)
91
117
  @univariate_feature
92
118
  def signal_decorrelation_time(x, fs=1):
93
119
  f = np.fft.fft(x - x.mean(axis=-1, keepdims=True), axis=-1)
@@ -1,10 +1,10 @@
1
- import numpy as np
2
1
  import numba as nb
2
+ import numpy as np
3
3
  from scipy.signal import welch
4
4
 
5
- from ..extractors import FeatureExtractor
6
5
  from ..decorators import FeaturePredecessor, univariate_feature
7
-
6
+ from ..extractors import FeatureExtractor
7
+ from . import utils
8
8
 
9
9
  __all__ = [
10
10
  "SpectralFeatureExtractor",
@@ -26,14 +26,13 @@ class SpectralFeatureExtractor(FeatureExtractor):
26
26
  def preprocess(self, x, **kwargs):
27
27
  f_min = kwargs.pop("f_min") if "f_min" in kwargs else None
28
28
  f_max = kwargs.pop("f_max") if "f_max" in kwargs else None
29
+ assert "fs" in kwargs
29
30
  kwargs["axis"] = -1
30
31
  f, p = welch(x, **kwargs)
31
- if f_min is not None or f_max is not None:
32
- f_min_idx = f > f_min if f_min is not None else True
33
- f_max_idx = f < f_max if f_max is not None else True
34
- idx = np.logical_and(f_min_idx, f_max_idx)
35
- f = f[idx]
36
- p = p[..., idx]
32
+ f_min, f_max = utils.get_valid_freq_band(
33
+ kwargs["fs"], x.shape[-1], f_min, f_max
34
+ )
35
+ f, p = utils.slice_freq_band(f, p, f_min=f_min, f_max=f_max)
37
36
  return f, p
38
37
 
39
38
 
@@ -113,22 +112,5 @@ def spectral_slope(f, p):
113
112
  DBSpectralFeatureExtractor,
114
113
  )
115
114
  @univariate_feature
116
- def spectral_bands_power(
117
- f,
118
- p,
119
- bands={
120
- "delta": (1, 4.5),
121
- "theta": (4.5, 8),
122
- "alpha": (8, 12),
123
- "beta": (12, 30),
124
- },
125
- ):
126
- bands_power = dict()
127
- for k, v in bands.items():
128
- assert isinstance(k, str)
129
- assert isinstance(v, tuple)
130
- assert len(v) == 2
131
- mask = np.logical_and(f > v[0], f < v[1])
132
- power = p[..., mask].sum(axis=-1)
133
- bands_power[k] = power
134
- return bands_power
115
+ def spectral_bands_power(f, p, bands=utils.DEFAULT_FREQ_BANDS):
116
+ return utils.reduce_freq_bands(f, p, bands, np.sum)
@@ -0,0 +1,48 @@
1
+ import numpy as np
2
+
3
+ DEFAULT_FREQ_BANDS = {
4
+ "delta": (1, 4.5),
5
+ "theta": (4.5, 8),
6
+ "alpha": (8, 12),
7
+ "beta": (12, 30),
8
+ }
9
+
10
+
11
+ def get_valid_freq_band(fs, n, f_min=None, f_max=None):
12
+ f0 = 2 * fs / n
13
+ f1 = fs / 2
14
+ if f_min is None:
15
+ f_min = f0
16
+ else:
17
+ assert f_min >= f0
18
+ if f_max is None:
19
+ f_max = f1
20
+ else:
21
+ assert f_max <= f1
22
+ return f_min, f_max
23
+
24
+
25
+ def slice_freq_band(f, *x, f_min=None, f_max=None):
26
+ if f_min is None and f_max is None:
27
+ return f, *x
28
+ else:
29
+ f_min_idx = f >= f_min if f_min is not None else True
30
+ f_max_idx = f <= f_max if f_max is not None else True
31
+ idx = np.logical_and(f_min_idx, f_max_idx)
32
+ f = f[idx]
33
+ xl = [*x]
34
+ for i, xi in enumerate(xl):
35
+ xl[i] = xi[..., idx]
36
+ return f, *xl
37
+
38
+
39
+ def reduce_freq_bands(f, x, bands, reduce_func=np.sum):
40
+ x_bands = dict()
41
+ for k, lims in bands.items():
42
+ assert isinstance(k, str)
43
+ assert len(lims) == 2 and lims[0] <= lims[1]
44
+ assert lims[0] >= f[0] and lims[1] <= f[-1]
45
+ mask = np.logical_and(f >= lims[0], f < lims[1])
46
+ xf = x[..., mask]
47
+ x_bands[k] = reduce_func(xf, axis=-1)
48
+ return x_bands
@@ -0,0 +1,48 @@
1
+ import inspect
2
+ from collections.abc import Callable
3
+
4
+ from . import extractors, feature_bank
5
+ from .extractors import FeatureExtractor, MultivariateFeature, _get_underlying_func
6
+
7
+
8
+ def get_feature_predecessors(feature_or_extractor: Callable):
9
+ current = _get_underlying_func(feature_or_extractor)
10
+ if current is FeatureExtractor:
11
+ return [current]
12
+ predecessor = getattr(current, "parent_extractor_type", [FeatureExtractor])
13
+ if len(predecessor) == 1:
14
+ return [current, *get_feature_predecessors(predecessor[0])]
15
+ else:
16
+ predecessors = [get_feature_predecessors(pred) for pred in predecessor]
17
+ for i in range(len(predecessors)):
18
+ if isinstance(predecessors[i], list) and len(predecessors[i]) == 1:
19
+ predecessors[i] = predecessors[i][0]
20
+ return [current, tuple(predecessors)]
21
+
22
+
23
+ def get_feature_kind(feature: Callable):
24
+ return _get_underlying_func(feature).feature_kind
25
+
26
+
27
+ def get_all_features():
28
+ def isfeature(x):
29
+ return hasattr(_get_underlying_func(x), "feature_kind")
30
+
31
+ return inspect.getmembers(feature_bank, isfeature)
32
+
33
+
34
+ def get_all_feature_extractors():
35
+ def isfeatureextractor(x):
36
+ return inspect.isclass(x) and issubclass(x, FeatureExtractor)
37
+
38
+ return [
39
+ ("FeatureExtractor", FeatureExtractor),
40
+ *inspect.getmembers(feature_bank, isfeatureextractor),
41
+ ]
42
+
43
+
44
+ def get_all_feature_kinds():
45
+ def isfeaturekind(x):
46
+ return inspect.isclass(x) and issubclass(x, MultivariateFeature)
47
+
48
+ return inspect.getmembers(extractors, isfeaturekind)
@@ -1,21 +1,19 @@
1
- """
2
- Convenience functions for storing and loading of features datasets.
1
+ """Convenience functions for storing and loading of features datasets.
3
2
 
4
3
  see also: https://github.com/braindecode/braindecode//blob/master/braindecode/datautil/serialization.py#L165-L229
5
4
  """
6
5
 
7
- import json
8
6
  from pathlib import Path
9
7
 
10
8
  import pandas as pd
11
9
  from joblib import Parallel, delayed
12
-
13
10
  from mne.io import read_info
11
+
14
12
  from braindecode.datautil.serialization import _load_kwargs_json
15
13
 
16
14
  from .datasets import (
17
- FeaturesDataset,
18
15
  FeaturesConcatDataset,
16
+ FeaturesDataset,
19
17
  )
20
18
 
21
19
 
@@ -34,6 +32,7 @@ def load_features_concat_dataset(path, ids_to_load=None, n_jobs=1):
34
32
  Returns
35
33
  -------
36
34
  concat_dataset: FeaturesConcatDataset of FeaturesDatasets
35
+
37
36
  """
38
37
  # Make sure we always work with a pathlib.Path
39
38
  path = Path(path)
eegdash/features/utils.py CHANGED
@@ -1,18 +1,20 @@
1
- from typing import Dict, List
2
- from collections.abc import Callable
3
1
  import copy
2
+ from collections.abc import Callable
3
+ from typing import Dict, List
4
+
4
5
  import numpy as np
5
6
  import pandas as pd
6
7
  from joblib import Parallel, delayed
7
- from tqdm import tqdm
8
8
  from torch.utils.data import DataLoader
9
+ from tqdm import tqdm
10
+
9
11
  from braindecode.datasets.base import (
12
+ BaseConcatDataset,
10
13
  EEGWindowsDataset,
11
14
  WindowsDataset,
12
- BaseConcatDataset,
13
15
  )
14
16
 
15
- from .datasets import FeaturesDataset, FeaturesConcatDataset
17
+ from .datasets import FeaturesConcatDataset, FeaturesDataset
16
18
  from .extractors import FeatureExtractor
17
19
 
18
20
 
@@ -53,7 +55,7 @@ def _extract_features_from_windowsdataset(
53
55
  metadata.reset_index(drop=True, inplace=True)
54
56
  metadata.drop("orig_index", axis=1, inplace=True)
55
57
 
56
- # FUTURE: truely support WindowsDataset objects
58
+ # FUTURE: truly support WindowsDataset objects
57
59
  return FeaturesDataset(
58
60
  features_df,
59
61
  metadata=metadata,
@@ -100,7 +102,7 @@ def fit_feature_extractors(
100
102
  features = dict(enumerate(features))
101
103
  if not isinstance(features, FeatureExtractor):
102
104
  features = FeatureExtractor(features)
103
- if not features._is_fitable:
105
+ if not features._is_trainable:
104
106
  return features
105
107
  features.clear()
106
108
  concat_dl = DataLoader(
@@ -0,0 +1,65 @@
1
+ import logging
2
+
3
+ import mne
4
+ import numpy as np
5
+
6
+ from braindecode.preprocessing import (
7
+ Preprocessor,
8
+ )
9
+
10
+ logger = logging.getLogger("eegdash")
11
+
12
+
13
+ class hbn_ec_ec_reannotation(Preprocessor):
14
+ """Preprocessor to reannotate the raw data for eyes open and eyes closed events.
15
+
16
+ This processor is designed for HBN datasets.
17
+
18
+ """
19
+
20
+ def __init__(self):
21
+ super().__init__(fn=self.transform, apply_on_array=False)
22
+
23
+ def transform(self, raw):
24
+ """Reannotate the raw data to create new events for eyes open and eyes closed
25
+
26
+ This function modifies the raw MNE object by creating new events based on
27
+ the existing annotations for "instructed_toCloseEyes" and "instructed_toOpenEyes".
28
+ It generates new events every 2 seconds within specified time ranges after
29
+ the original events, and replaces the existing annotations with these new events.
30
+
31
+ Parameters
32
+ ----------
33
+ raw : mne.io.Raw
34
+ The raw MNE object containing EEG data and annotations.
35
+
36
+ """
37
+ events, event_id = mne.events_from_annotations(raw)
38
+
39
+ logger.info("Original events found with ids: %s", event_id)
40
+
41
+ # Create new events array for 2-second segments
42
+ new_events = []
43
+ sfreq = raw.info["sfreq"]
44
+ for event in events[events[:, 2] == event_id["instructed_toCloseEyes"]]:
45
+ # For each original event, create events every 2 seconds from 15s to 29s after
46
+ start_times = event[0] + np.arange(15, 29, 2) * sfreq
47
+ new_events.extend([[int(t), 0, 1] for t in start_times])
48
+
49
+ for event in events[events[:, 2] == event_id["instructed_toOpenEyes"]]:
50
+ # For each original event, create events every 2 seconds from 5s to 19s after
51
+ start_times = event[0] + np.arange(5, 19, 2) * sfreq
52
+ new_events.extend([[int(t), 0, 2] for t in start_times])
53
+
54
+ # replace events in raw
55
+ new_events = np.array(new_events)
56
+
57
+ annot_from_events = mne.annotations_from_events(
58
+ events=new_events,
59
+ event_desc={1: "eyes_closed", 2: "eyes_open"},
60
+ sfreq=raw.info["sfreq"],
61
+ )
62
+
63
+ raw.set_annotations(annot_from_events)
64
+
65
+ return raw
eegdash/utils.py ADDED
@@ -0,0 +1,11 @@
1
+ def __init__mongo_client():
2
+ from mne.utils import get_config, set_config
3
+
4
+ if get_config("EEGDASH_DB_URI") is None:
5
+ # Set the default MongoDB URI for EEGDash
6
+ # This is a placeholder and should be replaced with your actual MongoDB URI
7
+
8
+ set_config(
9
+ "EEGDASH_DB_URI",
10
+ "mongodb+srv://eegdash-user:mdzoMjQcHWTVnKDq@cluster0.vz35p.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0",
11
+ )
@@ -1,14 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eegdash
3
- Version: 0.0.9
3
+ Version: 0.2.0
4
4
  Summary: EEG data for machine learning
5
- Author-email: Young Truong <dt.young112@gmail.com>, Arnaud Delorme <adelorme@gmail.com>
5
+ Author-email: Young Truong <dt.young112@gmail.com>, Arnaud Delorme <adelorme@gmail.com>, Bruno Aristimunha <b.aristimunha@gmail.com>
6
6
  License: GNU General Public License
7
7
 
8
8
  Copyright (C) 2024-2025
9
9
 
10
10
  Young Truong, UCSD, dt.young112@gmail.com
11
11
  Arnaud Delorme, UCSD, adelorme@ucsd.edu
12
+ Bruno Aristimunha, b.aristimunha@gmail.com
12
13
 
13
14
  This program is free software; you can redistribute it and/or modify
14
15
  it under the terms of the GNU General Public License as published by
@@ -24,35 +25,69 @@ License: GNU General Public License
24
25
  along with this program; if not, write to the Free Software
25
26
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1.07 USA
26
27
 
27
- Project-URL: Homepage, https://eegdash.org
28
- Project-URL: Issues, https://github.com/sccn/EEGDash/issues
29
- Classifier: Programming Language :: Python :: 3
28
+ Project-URL: Homepage, https://github.com/sccn/EEG-Dash-Data
29
+ Project-URL: Issues, https://github.com/sccn/EEG-Dash-Data/issues
30
30
  Classifier: License :: OSI Approved :: MIT License
31
31
  Classifier: Operating System :: OS Independent
32
- Requires-Python: >=3.8
32
+ Classifier: Intended Audience :: Science/Research
33
+ Classifier: Intended Audience :: Developers
34
+ Classifier: Programming Language :: Python
35
+ Classifier: Topic :: Software Development
36
+ Classifier: Topic :: Scientific/Engineering
37
+ Classifier: Development Status :: 3 - Alpha
38
+ Classifier: Operating System :: Microsoft :: Windows
39
+ Classifier: Operating System :: POSIX
40
+ Classifier: Operating System :: Unix
41
+ Classifier: Operating System :: MacOS
42
+ Classifier: Programming Language :: Python :: 3
43
+ Classifier: Programming Language :: Python :: 3.10
44
+ Classifier: Programming Language :: Python :: 3.11
45
+ Classifier: Programming Language :: Python :: 3.12
46
+ Requires-Python: >3.10
33
47
  Description-Content-Type: text/markdown
34
48
  License-File: LICENSE
35
- Requires-Dist: xarray
49
+ Requires-Dist: braindecode>=1.0
50
+ Requires-Dist: mne_bids>=0.16.0
51
+ Requires-Dist: numba
52
+ Requires-Dist: numpy
53
+ Requires-Dist: pandas
54
+ Requires-Dist: pybids
55
+ Requires-Dist: pymongo
36
56
  Requires-Dist: python-dotenv
37
57
  Requires-Dist: s3fs
38
- Requires-Dist: mne
39
- Requires-Dist: pynwb
40
- Requires-Dist: h5py
41
- Requires-Dist: pymongo
42
- Requires-Dist: joblib
43
- Requires-Dist: braindecode
44
- Requires-Dist: mne-bids
45
- Requires-Dist: pybids
46
- Requires-Dist: pymatreader
47
- Requires-Dist: pyarrow
58
+ Requires-Dist: scipy
48
59
  Requires-Dist: tqdm
49
- Requires-Dist: numba
60
+ Requires-Dist: xarray
61
+ Provides-Extra: tests
62
+ Requires-Dist: pytest; extra == "tests"
63
+ Requires-Dist: pytest-cov; extra == "tests"
64
+ Requires-Dist: codecov; extra == "tests"
65
+ Requires-Dist: pytest_cases; extra == "tests"
66
+ Provides-Extra: dev
67
+ Requires-Dist: pre-commit; extra == "dev"
68
+ Provides-Extra: docs
69
+ Requires-Dist: sphinx; extra == "docs"
70
+ Requires-Dist: sphinx_gallery; extra == "docs"
71
+ Requires-Dist: sphinx_rtd_theme; extra == "docs"
72
+ Requires-Dist: numpydoc; extra == "docs"
73
+ Provides-Extra: all
74
+ Requires-Dist: pytest; extra == "all"
75
+ Requires-Dist: pytest-cov; extra == "all"
76
+ Requires-Dist: codecov; extra == "all"
77
+ Requires-Dist: pytest_cases; extra == "all"
78
+ Requires-Dist: pre-commit; extra == "all"
79
+ Requires-Dist: sphinx; extra == "all"
80
+ Requires-Dist: sphinx_gallery; extra == "all"
81
+ Requires-Dist: sphinx_rtd_theme; extra == "all"
82
+ Requires-Dist: numpydoc; extra == "all"
50
83
  Dynamic: license-file
51
84
 
52
85
  # EEG-Dash
86
+
53
87
  To leverage recent and ongoing advancements in large-scale computational methods and to ensure the preservation of scientific data generated from publicly funded research, the EEG-DaSh data archive will create a data-sharing resource for MEEG (EEG, MEG) data contributed by collaborators for machine learning (ML) and deep learning (DL) applications.
54
88
 
55
89
  ## Data source
90
+
56
91
  The data in EEG-DaSh originates from a collaboration involving 25 laboratories, encompassing 27,053 participants. This extensive collection includes MEEG data, which is a combination of EEG and MEG signals. The data is sourced from various studies conducted by these labs, involving both healthy subjects and clinical populations with conditions such as ADHD, depression, schizophrenia, dementia, autism, and psychosis. Additionally, data spans different mental states like sleep, meditation, and cognitive tasks. In addition, EEG-DaSh will incorporate a subset of the data converted from NEMAR, which includes 330 MEEG BIDS-formatted datasets, further expanding the archive with well-curated, standardized neuroelectromagnetic data.
57
92
 
58
93
  ## Featured data
@@ -72,9 +107,11 @@ The following HBN datasets are currently featured on EEGDash. Documentation abou
72
107
  A total of [246 other datasets](datasets.md) are also available through EEGDash.
73
108
 
74
109
  ## Data format
110
+
75
111
  EEGDash queries return a **Pytorch Dataset** formatted to facilitate machine learning (ML) and deep learning (DL) applications. PyTorch Datasets are the best format for EEGDash queries because they provide an efficient, scalable, and flexible structure for machine learning (ML) and deep learning (DL) applications. They allow seamless integration with PyTorch’s DataLoader, enabling efficient batching, shuffling, and parallel data loading, which is essential for training deep learning models on large EEG datasets.
76
112
 
77
113
  ## Data preprocessing
114
+
78
115
  EEGDash datasets are processed using the popular [BrainDecode](https://braindecode.org/stable/index.html) library. In fact, EEGDash datasets are BrainDecode datasets, which are themselves PyTorch datasets. This means that any preprocessing possible on BrainDecode datasets is also possible on EEGDash datasets. Refer to [BrainDecode](https://braindecode.org/stable/index.html) tutorials for guidance on preprocessing EEG data.
79
116
 
80
117
  ## EEG-Dash usage
@@ -90,7 +127,10 @@ To use the data from a single subject, enter:
90
127
 
91
128
  ```python
92
129
  from eegdash import EEGDashDataset
93
- ds_NDARDB033FW5 = EEGDashDataset({'dataset': 'ds005514', 'task': 'RestingState', 'subject': 'NDARDB033FW5'})
130
+
131
+ ds_NDARDB033FW5 = EEGDashDataset(
132
+ {"dataset": "ds005514", "task": "RestingState", "subject": "NDARDB033FW5"}
133
+ )
94
134
  ```
95
135
 
96
136
  This will search and download the metadata for the task **RestingState** for subject **NDARDB033FW5** in BIDS dataset **ds005514**. The actual data will not be downloaded at this stage. Following standard practice, data is only downloaded once it is processed. The **ds_NDARDB033FW5** object is a fully functional BrainDecode dataset, which is itself a PyTorch dataset. This [tutorial](https://github.com/sccn/EEGDash/blob/develop/notebooks/tutorial_eoec.ipynb) shows how to preprocess the EEG data, extracting portions of the data containing eyes-open and eyes-closed segments, then perform eyes-open vs. eyes-closed classification using a (shallow) deep-learning model.
@@ -99,7 +139,10 @@ To use the data from multiple subjects, enter:
99
139
 
100
140
  ```python
101
141
  from eegdash import EEGDashDataset
102
- ds_ds005505rest = EEGDashDataset({'dataset': 'ds005505', 'task': 'RestingState'}, target_name='sex')
142
+
143
+ ds_ds005505rest = EEGDashDataset(
144
+ {"dataset": "ds005505", "task": "RestingState"}, target_name="sex"
145
+ )
103
146
  ```
104
147
 
105
148
  This will search and download the metadata for the task 'RestingState' for all subjects in BIDS dataset 'ds005505' (a total of 136). As above, the actual data will not be downloaded at this stage so this command is quick to execute. Also, the target class for each subject is assigned using the target_name parameter. This means that this object is ready to be directly fed to a deep learning model, although the [tutorial script](https://github.com/sccn/EEGDash/blob/develop/notebooks/tutorial_sex_classification.ipynb) performs minimal processing on it, prior to training a deep-learning model. Because 14 gigabytes of data are downloaded, this tutorial takes about 10 minutes to execute.
@@ -121,3 +164,7 @@ EEG-DaSh is a collaborative initiative between the United States and Israel, sup
121
164
 
122
165
 
123
166
 
167
+ python3 -m pip install --upgrade build
168
+ python3 -m build
169
+ python3 -m pip install --upgrade twine
170
+ python3 -m twine upload --repository eegdash dist/*
@@ -0,0 +1,27 @@
1
+ eegdash/__init__.py,sha256=nMBZrB4bJs79rl9TZ_x-IVPNTHYJS6V55Pus9fErB5E,232
2
+ eegdash/api.py,sha256=1mbufz6qgujrY_9V2GWUP4Eqel_q4ns9XVrmbGcSJG0,25776
3
+ eegdash/data_config.py,sha256=OS6ERO-jHrnEOfMJUehY7ieABdsRw_qWzOKJ4pzSfqw,1323
4
+ eegdash/data_utils.py,sha256=mR0TtERYIefakGQ98jwAeeRVKSNDU9eBlUoH1AY9tnc,23663
5
+ eegdash/dataset.py,sha256=qXcE4JxxYj89VQ84sKmq7kGcunZqt1pp5wz7a62j_OQ,2460
6
+ eegdash/preprocessing.py,sha256=wvqAO8UgDoQQz7xjVykrl4V8AawS4tpKR4Vrr_9BovY,2230
7
+ eegdash/utils.py,sha256=ZxVW4ll5MaSZ_ht1L5p7YJxOtYi3b0547oa5W_jbH4A,450
8
+ eegdash/features/__init__.py,sha256=484CLxpPifc8ZQfeM8jWZLvtVKljCxn3qqlUCaq-Yxk,1284
9
+ eegdash/features/datasets.py,sha256=kU1DO70ArSIy-LF1hHD2NN4iT-kJrI0mVpSkyV_OSeI,18301
10
+ eegdash/features/decorators.py,sha256=v0qaJz_dcX703p1fvFYbAIXmwK3d8naYGlq7fRVKn_w,1313
11
+ eegdash/features/extractors.py,sha256=H7h6tP3dKoRcjDJpWWAo0ppmokCq5QlhqMcehYwYV9s,6845
12
+ eegdash/features/inspect.py,sha256=PmbWhx5H_WqpnorUpWONUSkUtaIHkZblRa_Xyk7Szyc,1569
13
+ eegdash/features/serialization.py,sha256=pNsTz0EeRPPYE-A61XK7UoMShI9YBEHQqC5STbzUU6A,2861
14
+ eegdash/features/utils.py,sha256=eM6DdyOpdVfNh7dSPykJ0WaTDtaGvkCQWAmW0G8v60Y,3784
15
+ eegdash/features/feature_bank/__init__.py,sha256=BKrM3aaggXrfey1yEjEBYaxOV5e3UK-o8oGeB30epOg,149
16
+ eegdash/features/feature_bank/complexity.py,sha256=Ds1GAXZ0LGM32xB4EZC2jbMljUBv0yicf2SkuyLvN5I,3183
17
+ eegdash/features/feature_bank/connectivity.py,sha256=bQ6KlxWm5GNpCS9ypLqBUr2L171Yq7wpBQT2tRQKTZ4,2159
18
+ eegdash/features/feature_bank/csp.py,sha256=YOzieLnOcqjvfrcjvg8R3S4SWuC1BqK5J5WXVNCCTc0,3304
19
+ eegdash/features/feature_bank/dimensionality.py,sha256=j_Ds71Y1AbV2uLFQj8EuXQ4kzofLBlQtPV5snMkF7i4,3965
20
+ eegdash/features/feature_bank/signal.py,sha256=3Tb8z9gX7iZipxQJ9DSyy30JfdmW58kgvimSyZX74p8,3404
21
+ eegdash/features/feature_bank/spectral.py,sha256=bNB7skusePs1gX7NOU6yRlw_Gr4UOCkO_ylkCgybzug,3319
22
+ eegdash/features/feature_bank/utils.py,sha256=DGh-Q7-XFIittP7iBBxvsJaZrlVvuY5mw-G7q6C-PCI,1237
23
+ eegdash-0.2.0.dist-info/licenses/LICENSE,sha256=KykUD4H3kw3HLz5bZ0kxMWwZotnk8rhkfCCerGyX2sk,855
24
+ eegdash-0.2.0.dist-info/METADATA,sha256=GhxMc7p2HvTZo9lZFjBX1tJ70VeMlMnaYBhvpqw0iG8,10220
25
+ eegdash-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
+ eegdash-0.2.0.dist-info/top_level.txt,sha256=zavO69HQ6MyZM0aQMR2zUS6TAFc7bnN5GEpDpOpFZzU,8
27
+ eegdash-0.2.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -4,6 +4,7 @@ Copyright (C) 2024-2025
4
4
 
5
5
  Young Truong, UCSD, dt.young112@gmail.com
6
6
  Arnaud Delorme, UCSD, adelorme@ucsd.edu
7
+ Bruno Aristimunha, b.aristimunha@gmail.com
7
8
 
8
9
  This program is free software; you can redistribute it and/or modify
9
10
  it under the terms of the GNU General Public License as published by