eegdash 0.3.0.dev172943270__tar.gz → 0.3.1.dev50__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.

Potentially problematic release.


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

Files changed (38) hide show
  1. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/LICENSE +2 -0
  2. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/PKG-INFO +4 -2
  3. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/__init__.py +1 -1
  4. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/data_utils.py +33 -6
  5. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/dataset.py +17 -17
  6. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/feature_bank/complexity.py +3 -1
  7. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/feature_bank/csp.py +1 -1
  8. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash.egg-info/PKG-INFO +4 -2
  9. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/pyproject.toml +2 -0
  10. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/tests/test_dataset.py +8 -2
  11. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/README.md +0 -0
  12. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/api.py +0 -0
  13. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/data_config.py +0 -0
  14. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/__init__.py +0 -0
  15. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/datasets.py +0 -0
  16. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/decorators.py +0 -0
  17. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/extractors.py +0 -0
  18. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/feature_bank/__init__.py +0 -0
  19. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/feature_bank/connectivity.py +0 -0
  20. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/feature_bank/dimensionality.py +0 -0
  21. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/feature_bank/signal.py +0 -0
  22. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/feature_bank/spectral.py +0 -0
  23. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/feature_bank/utils.py +0 -0
  24. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/inspect.py +0 -0
  25. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/serialization.py +0 -0
  26. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/features/utils.py +0 -0
  27. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/mongodb.py +0 -0
  28. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/preprocessing.py +0 -0
  29. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash/utils.py +0 -0
  30. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash.egg-info/SOURCES.txt +0 -0
  31. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash.egg-info/dependency_links.txt +0 -0
  32. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash.egg-info/requires.txt +0 -0
  33. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/eegdash.egg-info/top_level.txt +0 -0
  34. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/setup.cfg +0 -0
  35. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/tests/test_correctness.py +0 -0
  36. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/tests/test_eegdash.py +0 -0
  37. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/tests/test_init.py +0 -0
  38. {eegdash-0.3.0.dev172943270 → eegdash-0.3.1.dev50}/tests/test_mongo_connection.py +0 -0
@@ -4,6 +4,8 @@ Copyright (C) 2024-2025
4
4
 
5
5
  Young Truong, UCSD, dt.young112@gmail.com
6
6
  Arnaud Delorme, UCSD, adelorme@ucsd.edu
7
+ Aviv Dotan, BGU, avivdot@bgu.post.ac.il
8
+ Oren Shriki, BGU, shrikio@bgu.ac.il
7
9
  Bruno Aristimunha, b.aristimunha@gmail.com
8
10
 
9
11
  This program is free software; you can redistribute it and/or modify
@@ -1,14 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eegdash
3
- Version: 0.3.0.dev172943270
3
+ Version: 0.3.1.dev50
4
4
  Summary: EEG data for machine learning
5
- Author-email: Young Truong <dt.young112@gmail.com>, Arnaud Delorme <adelorme@gmail.com>, Bruno Aristimunha <b.aristimunha@gmail.com>
5
+ Author-email: Young Truong <dt.young112@gmail.com>, Arnaud Delorme <adelorme@gmail.com>, Aviv Dotan <avivd220@gmail.com>, Oren Shriki <oren70@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
+ Aviv Dotan, BGU, avivdot@bgu.post.ac.il
13
+ Oren Shriki, BGU, shrikio@bgu.ac.il
12
14
  Bruno Aristimunha, b.aristimunha@gmail.com
13
15
 
14
16
  This program is free software; you can redistribute it and/or modify
@@ -5,4 +5,4 @@ from .utils import __init__mongo_client
5
5
  __init__mongo_client()
6
6
 
7
7
  __all__ = ["EEGDash", "EEGDashDataset", "EEGChallengeDataset"]
8
- __version__ = "0.3.0.dev172943270"
8
+ __version__ = "0.3.1.dev50"
@@ -55,16 +55,33 @@ class EEGDashBaseDataset(BaseDataset):
55
55
  self.cache_dir = Path(cache_dir)
56
56
  bids_kwargs = self.get_raw_bids_args()
57
57
 
58
+ if s3_bucket:
59
+ self.s3_bucket = s3_bucket
60
+ self.s3_open_neuro = False
61
+ bids_root = self.cache_dir
62
+ self.filecache = self.cache_dir / record["bidspath"]
63
+ else:
64
+ self.s3_bucket = self._AWS_BUCKET
65
+ self.s3_open_neuro = True
66
+ bids_root = self.cache_dir / record["dataset"]
67
+ self.filecache = self.cache_dir / record["bidspath"]
68
+
58
69
  self.bidspath = BIDSPath(
59
- root=self.cache_dir / record["dataset"],
70
+ root=bids_root,
60
71
  datatype="eeg",
61
72
  suffix="eeg",
62
73
  **bids_kwargs,
63
74
  )
64
- self.s3_bucket = s3_bucket if s3_bucket else self._AWS_BUCKET
75
+
65
76
  self.s3file = self.get_s3path(record["bidspath"])
66
- self.filecache = self.cache_dir / record["bidspath"]
67
77
  self.bids_dependencies = record["bidsdependencies"]
78
+ # Temporary fix for BIDS dependencies path
79
+ # just to release to the competition
80
+ if not self.s3_open_neuro:
81
+ self.bids_dependencies = [
82
+ dep.split("/", 1)[1] for dep in self.bids_dependencies
83
+ ]
84
+
68
85
  self._raw = None
69
86
 
70
87
  def get_s3path(self, filepath: str) -> str:
@@ -72,11 +89,18 @@ class EEGDashBaseDataset(BaseDataset):
72
89
  return f"{self.s3_bucket}/{filepath}"
73
90
 
74
91
  def _download_s3(self) -> None:
75
- """Fetch the given data from its S3 location and cache it locally."""
76
- self.filecache.parent.mkdir(parents=True, exist_ok=True)
92
+ """Download function that gets the raw EEG data from S3."""
77
93
  filesystem = s3fs.S3FileSystem(
78
94
  anon=True, client_kwargs={"region_name": "us-east-2"}
79
95
  )
96
+ if not self.s3_open_neuro:
97
+ self.s3file = re.sub(r"(^|/)ds\d{6}/", r"\1", self.s3file, count=1)
98
+ self.filecache = re.sub(
99
+ r"(^|/)ds\d{6}/", r"\1", str(self.filecache), count=1
100
+ )
101
+ self.filecache = Path(self.filecache)
102
+
103
+ self.filecache.parent.mkdir(parents=True, exist_ok=True)
80
104
  filesystem.download(self.s3file, self.filecache)
81
105
  self.filenames = [self.filecache]
82
106
 
@@ -90,6 +114,8 @@ class EEGDashBaseDataset(BaseDataset):
90
114
  for dep in self.bids_dependencies:
91
115
  s3path = self.get_s3path(dep)
92
116
  filepath = self.cache_dir / dep
117
+ # here, we download the dependency and it is fine
118
+ # in the case of the competition.
93
119
  if not filepath.exists():
94
120
  filepath.parent.mkdir(parents=True, exist_ok=True)
95
121
  filesystem.download(s3path, filepath)
@@ -108,7 +134,7 @@ class EEGDashBaseDataset(BaseDataset):
108
134
  self._download_dependencies()
109
135
  self._download_s3()
110
136
  if self._raw is None:
111
- self._raw = mne.io.read_raw(self.bidspath, verbose=False)
137
+ self._raw = mne.io.read_raw(fname=self.bidspath, verbose=False)
112
138
 
113
139
  # === BaseDataset and PyTorch Dataset interface ===
114
140
 
@@ -215,6 +241,7 @@ class EEGDashBaseRaw(BaseRaw):
215
241
  )
216
242
 
217
243
  def get_s3path(self, filepath):
244
+ print(f"Getting S3 path for {filepath}")
218
245
  return f"{self._AWS_BUCKET}/{filepath}"
219
246
 
220
247
  def _download_s3(self):
@@ -1,5 +1,19 @@
1
1
  from .api import EEGDashDataset
2
2
 
3
+ RELEASE_TO_OPENNEURO_DATASET_MAP = {
4
+ "R11": "ds005516",
5
+ "R10": "ds005515",
6
+ "R9": "ds005514",
7
+ "R8": "ds005512",
8
+ "R7": "ds005511",
9
+ "R6": "ds005510",
10
+ "R4": "ds005508",
11
+ "R5": "ds005509",
12
+ "R3": "ds005507",
13
+ "R2": "ds005506",
14
+ "R1": "ds005505",
15
+ }
16
+
3
17
 
4
18
  class EEGChallengeDataset(EEGDashDataset):
5
19
  def __init__(
@@ -7,7 +21,7 @@ class EEGChallengeDataset(EEGDashDataset):
7
21
  release: str = "R5",
8
22
  query: dict | None = None,
9
23
  cache_dir: str = ".eegdash_cache",
10
- s3_bucket: str | None = "s3://nmdatasets/NeurIPS25/",
24
+ s3_bucket: str | None = "s3://nmdatasets/NeurIPS25",
11
25
  **kwargs,
12
26
  ):
13
27
  """Create a new EEGDashDataset from a given query or local BIDS dataset directory
@@ -32,25 +46,11 @@ class EEGChallengeDataset(EEGDashDataset):
32
46
  constructor.
33
47
 
34
48
  """
35
- dsnumber_release_map = {
36
- "R11": "ds005516",
37
- "R10": "ds005515",
38
- "R9": "ds005514",
39
- "R8": "ds005512",
40
- "R7": "ds005511",
41
- "R6": "ds005510",
42
- "R4": "ds005508",
43
- "R5": "ds005509",
44
- "R3": "ds005507",
45
- "R2": "ds005506",
46
- "R1": "ds005505",
47
- }
48
-
49
49
  self.release = release
50
- if release not in dsnumber_release_map:
50
+ if release not in RELEASE_TO_OPENNEURO_DATASET_MAP:
51
51
  raise ValueError(f"Unknown release: {release}")
52
52
 
53
- dataset = dsnumber_release_map[release]
53
+ dataset = RELEASE_TO_OPENNEURO_DATASET_MAP[release]
54
54
  if query is None:
55
55
  query = {"dataset": dataset}
56
56
  elif "dataset" not in query:
@@ -71,7 +71,7 @@ def complexity_svd_entropy(x, m=10, tau=1):
71
71
  @FeaturePredecessor(*SIGNAL_PREDECESSORS)
72
72
  @univariate_feature
73
73
  @nb.njit(cache=True, fastmath=True)
74
- def complexity_lempel_ziv(x, threshold=None):
74
+ def complexity_lempel_ziv(x, threshold=None, normalize=True):
75
75
  lzc = np.empty(x.shape[:-1])
76
76
  for i in np.ndindex(x.shape[:-1]):
77
77
  t = np.median(x[i]) if threshold is None else threshold
@@ -97,4 +97,6 @@ def complexity_lempel_ziv(x, threshold=None):
97
97
  j, k, k_max = 0, 1, 1
98
98
  else:
99
99
  k = 1
100
+ if normalize:
101
+ lzc[i] *= np.log2(n) / n
100
102
  return lzc
@@ -97,5 +97,5 @@ class CommonSpatialPattern(TrainableFeature):
97
97
  + "all weights were filtered out."
98
98
  )
99
99
  proj = (self.transform_input(x) - self._mean) @ w
100
- proj = proj.reshape(x.shape[0], x.shape[2], -1).mean(axis=1)
100
+ proj = proj.reshape(x.shape[0], x.shape[2], -1).var(axis=1)
101
101
  return {f"{i}": proj[:, i] for i in range(proj.shape[-1])}
@@ -1,14 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eegdash
3
- Version: 0.3.0.dev172943270
3
+ Version: 0.3.1.dev50
4
4
  Summary: EEG data for machine learning
5
- Author-email: Young Truong <dt.young112@gmail.com>, Arnaud Delorme <adelorme@gmail.com>, Bruno Aristimunha <b.aristimunha@gmail.com>
5
+ Author-email: Young Truong <dt.young112@gmail.com>, Arnaud Delorme <adelorme@gmail.com>, Aviv Dotan <avivd220@gmail.com>, Oren Shriki <oren70@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
+ Aviv Dotan, BGU, avivdot@bgu.post.ac.il
13
+ Oren Shriki, BGU, shrikio@bgu.ac.il
12
14
  Bruno Aristimunha, b.aristimunha@gmail.com
13
15
 
14
16
  This program is free software; you can redistribute it and/or modify
@@ -8,6 +8,8 @@ name = "eegdash"
8
8
  authors = [
9
9
  { name = "Young Truong", email = "dt.young112@gmail.com" },
10
10
  { name = "Arnaud Delorme", email = "adelorme@gmail.com" },
11
+ { name = "Aviv Dotan", email = "avivd220@gmail.com" },
12
+ { name = "Oren Shriki", email = "oren70@gmail.com" },
11
13
  { name = "Bruno Aristimunha", email = "b.aristimunha@gmail.com"}
12
14
  ]
13
15
  description = "EEG data for machine learning"
@@ -30,7 +30,7 @@ def test_eeg_challenge_dataset_initialization():
30
30
  dataset = EEGChallengeDataset(release="R5")
31
31
 
32
32
  release = "R5"
33
- expected_bucket_prefix = f"s3://nmdatasets/NeurIPS25//{release}_L100"
33
+ expected_bucket_prefix = f"s3://nmdatasets/NeurIPS25/{release}_L100"
34
34
  assert dataset.s3_bucket == expected_bucket_prefix, (
35
35
  f"Unexpected s3_bucket: {dataset.s3_bucket} (expected {expected_bucket_prefix})"
36
36
  )
@@ -79,4 +79,10 @@ def test_mongodb_load_under_slo(release):
79
79
  start_time = time.perf_counter()
80
80
  _ = EEGChallengeDataset(release=release)
81
81
  duration = time.perf_counter() - start_time
82
- assert duration < 10, f"{release} took {duration:.2f}s"
82
+ assert duration < 30, f"{release} took {duration:.2f}s"
83
+
84
+
85
+ def test_consuming_data_r5():
86
+ dataset_obj = EEGChallengeDataset(release="R5", query=dict(task="RestingState"))
87
+ raw = dataset_obj.datasets[0].raw
88
+ assert raw is not None