eegdash 0.4.0.dev153__tar.gz → 0.4.0.dev171__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 (84) hide show
  1. {eegdash-0.4.0.dev153/eegdash.egg-info → eegdash-0.4.0.dev171}/PKG-INFO +1 -1
  2. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/api/api_core.rst +1 -1
  3. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/conf.py +6 -3
  4. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/dataset_summary/bubble.rst +2 -0
  5. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/dataset_summary/kde.rst +3 -1
  6. eegdash-0.4.0.dev171/docs/source/dataset_summary/sankey.rst +20 -0
  7. eegdash-0.4.0.dev171/docs/source/dataset_summary/table.rst +27 -0
  8. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/dataset_summary.rst +10 -6
  9. eegdash-0.4.0.dev171/docs/source/index.rst +86 -0
  10. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/__init__.py +1 -1
  11. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/api.py +180 -86
  12. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/bids_eeg_metadata.py +139 -39
  13. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/const.py +25 -0
  14. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/data_utils.py +239 -173
  15. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/dataset/dataset.py +35 -13
  16. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/dataset/dataset_summary.csv +255 -255
  17. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/dataset/registry.py +69 -4
  18. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/downloader.py +95 -9
  19. eegdash-0.4.0.dev171/eegdash/features/datasets.py +677 -0
  20. eegdash-0.4.0.dev171/eegdash/features/decorators.py +136 -0
  21. eegdash-0.4.0.dev171/eegdash/features/extractors.py +357 -0
  22. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/features/feature_bank/complexity.py +7 -3
  23. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/features/feature_bank/dimensionality.py +1 -1
  24. eegdash-0.4.0.dev171/eegdash/features/inspect.py +123 -0
  25. eegdash-0.4.0.dev171/eegdash/features/serialization.py +115 -0
  26. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/features/utils.py +75 -8
  27. eegdash-0.4.0.dev171/eegdash/hbn/preprocessing.py +105 -0
  28. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/hbn/windows.py +145 -32
  29. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/logging.py +19 -0
  30. eegdash-0.4.0.dev171/eegdash/mongodb.py +97 -0
  31. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/paths.py +14 -5
  32. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/utils.py +16 -1
  33. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171/eegdash.egg-info}/PKG-INFO +1 -1
  34. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash.egg-info/SOURCES.txt +2 -0
  35. eegdash-0.4.0.dev171/tests/test_features.py +67 -0
  36. eegdash-0.4.0.dev153/docs/source/dataset_summary/table.rst +0 -174
  37. eegdash-0.4.0.dev153/docs/source/index.rst +0 -60
  38. eegdash-0.4.0.dev153/eegdash/features/datasets.py +0 -493
  39. eegdash-0.4.0.dev153/eegdash/features/decorators.py +0 -51
  40. eegdash-0.4.0.dev153/eegdash/features/extractors.py +0 -209
  41. eegdash-0.4.0.dev153/eegdash/features/inspect.py +0 -48
  42. eegdash-0.4.0.dev153/eegdash/features/serialization.py +0 -87
  43. eegdash-0.4.0.dev153/eegdash/hbn/preprocessing.py +0 -72
  44. eegdash-0.4.0.dev153/eegdash/mongodb.py +0 -80
  45. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/LICENSE +0 -0
  46. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/MANIFEST.in +0 -0
  47. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/README.md +0 -0
  48. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/Makefile +0 -0
  49. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/_templates/autosummary/module.rst +0 -0
  50. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/api/api.rst +0 -0
  51. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/api/api_features.rst +0 -0
  52. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/install/install.rst +0 -0
  53. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/install/install_pip.rst +0 -0
  54. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/install/install_source.rst +0 -0
  55. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/sg_execution_times.rst +0 -0
  56. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/docs/source/user_guide.rst +0 -0
  57. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/dataset/__init__.py +0 -0
  58. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/features/__init__.py +0 -0
  59. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/features/feature_bank/__init__.py +0 -0
  60. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/features/feature_bank/connectivity.py +0 -0
  61. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/features/feature_bank/csp.py +0 -0
  62. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/features/feature_bank/signal.py +0 -0
  63. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/features/feature_bank/spectral.py +0 -0
  64. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/features/feature_bank/utils.py +0 -0
  65. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash/hbn/__init__.py +0 -0
  66. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash.egg-info/dependency_links.txt +0 -0
  67. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash.egg-info/requires.txt +0 -0
  68. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/eegdash.egg-info/top_level.txt +0 -0
  69. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/pyproject.toml +0 -0
  70. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/setup.cfg +0 -0
  71. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_api.py +0 -0
  72. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_bids_dependencies.py +0 -0
  73. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_cache_folder_suffix.py +0 -0
  74. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_challenge_kwargs.py +0 -0
  75. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_correctness.py +0 -0
  76. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_dataset.py +0 -0
  77. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_dataset_registration.py +0 -0
  78. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_downloader.py +0 -0
  79. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_eegdash.py +0 -0
  80. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_init.py +0 -0
  81. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_minirelease.py +0 -0
  82. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_mongo_connection.py +0 -0
  83. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_offline.py +0 -0
  84. {eegdash-0.4.0.dev153 → eegdash-0.4.0.dev171}/tests/test_query.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eegdash
3
- Version: 0.4.0.dev153
3
+ Version: 0.4.0.dev171
4
4
  Summary: EEG data for machine learning
5
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-Expression: GPL-3.0-only
@@ -76,4 +76,4 @@ API Reference
76
76
  hbn
77
77
  mongodb
78
78
  paths
79
- utils
79
+ utils
@@ -12,13 +12,15 @@ from sphinx.util import logging
12
12
  from sphinx_gallery.sorting import ExplicitOrder, FileNameSortKey
13
13
  from tabulate import tabulate
14
14
 
15
+ sys.path.insert(0, os.path.abspath(".."))
16
+
15
17
  import eegdash
16
18
 
17
19
  # -- Project information -----------------------------------------------------
18
20
 
19
21
  project = "EEG Dash"
20
22
  copyright = f"2025–{datetime.now(tz=timezone.utc).year}, {project} Developers"
21
- author = "Arnaud Delorme"
23
+ author = "Bruno Aristimunha and Arnaud Delorme"
22
24
  release = eegdash.__version__
23
25
  version = ".".join(release.split(".")[:2])
24
26
 
@@ -44,6 +46,7 @@ extensions = [
44
46
  "sphinx_sitemap",
45
47
  "sphinx_copybutton",
46
48
  "sphinx.ext.graphviz",
49
+ "sphinx_time_estimation",
47
50
  ]
48
51
 
49
52
  templates_path = ["_templates"]
@@ -103,8 +106,8 @@ html_theme_options = {
103
106
  "navbar_end": ["theme-switcher", "navbar-icon-links"],
104
107
  "footer_start": ["copyright"],
105
108
  "logo": {
106
- "image_light": "_static/eegdash_long.png",
107
- "image_dark": "_static/eegdash_long.png",
109
+ "image_light": "_static/eegdash_long_white.svg",
110
+ "image_dark": "_static/eegdash_long_dark.svg",
108
111
  "alt_text": "EEG Dash Logo",
109
112
  },
110
113
  "external_links": [
@@ -1,3 +1,5 @@
1
+ .. title:: Dataset landscape
2
+
1
3
  .. rubric:: Dataset landscape
2
4
 
3
5
  .. raw:: html
@@ -1,4 +1,6 @@
1
- .. rubric:: Participant Distribution by Modality
1
+ .. title:: Participant Distribution by Modality
2
+
3
+ .. rubric:: Distribution of Sample Sizes Varies by Experimental Modality
2
4
 
3
5
  .. raw:: html
4
6
 
@@ -0,0 +1,20 @@
1
+ .. title:: Dataset flow
2
+
3
+ .. rubric:: Sankey diagrams of EEGDash Datasets by Population, Modality, and Cognitive Domain
4
+
5
+ .. raw:: html
6
+
7
+ <figure class="eegdash-figure" style="margin: 0 0 1.25rem 0;">
8
+
9
+ .. raw:: html
10
+ :file: ../_static/dataset_generated/dataset_sankey.html
11
+
12
+ .. raw:: html
13
+
14
+ <figcaption class="eegdash-caption">
15
+ Figure: Dataset flow across population, modality, and cognitive domain.
16
+ Link thickness is proportional to the total number of subjects, and the tooltip
17
+ reports both subject and dataset counts. Hover and click legend entries to
18
+ explore specific segments.
19
+ </figcaption>
20
+ </figure>
@@ -0,0 +1,27 @@
1
+ .. title:: EEG Datasets Table
2
+
3
+ .. rubric:: EEG Datasets Table
4
+
5
+ The data in EEG-DaSh originates from a collaboration involving 25 laboratories, encompassing 27,053 participants. This extensive collection includes M-EEG data, which is a combination of EEG and MEG signals. The data is sourced from various studies conducted by these labs,
6
+ 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.
7
+
8
+ In addition, EEG-DaSh will incorporate a subset of the data converted from `NEMAR <https://nemar.org/>`__, which includes 330 MEEG BIDS-formatted datasets, further expanding the archive with well-curated, standardized neuroelectromagnetic data.
9
+
10
+ .. raw:: html
11
+
12
+ <figure class="eegdash-figure" style="margin: 0 0 1.25rem 0;">
13
+
14
+ .. raw:: html
15
+ :file: ../_static/dataset_generated/dataset_summary_table.html
16
+
17
+ .. raw:: html
18
+
19
+ <figcaption class="eegdash-caption">
20
+ Table: Sortable catalogue of EEG‑DaSh datasets. Use the “Filters” button to open column filters;
21
+ click a column header to jump directly to a filter pane. The Total row is pinned at the bottom.
22
+ * means that we use the median value across multiple recordings in the dataset, and empty cells
23
+ when the metainformation is not extracted yet.
24
+ </figcaption>
25
+ </figure>
26
+
27
+ Pathology, modality, and dataset type now surface as consistent color-coded tags so you can scan the table at a glance.
@@ -10,13 +10,11 @@
10
10
 
11
11
  .. rst-class:: dataset-summary-article
12
12
 
13
- Datasets
14
- =========
13
+ Datasets Catalog
14
+ ================
15
15
 
16
16
  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.
17
17
 
18
- The archive is currently still in :bdg-danger:`beta testing` mode, so be kind.
19
-
20
18
  .. raw:: html
21
19
 
22
20
  <script src="https://cdn.plot.ly/plotly-3.1.0.min.js"></script>
@@ -27,10 +25,16 @@ The archive is currently still in :bdg-danger:`beta testing` mode, so be kind.
27
25
 
28
26
  .. include:: dataset_summary/table.rst
29
27
 
30
- .. tab-item:: Participant KDE
28
+ .. tab-item:: Participant Distribution
31
29
 
32
30
  .. include:: dataset_summary/kde.rst
33
31
 
34
- .. tab-item:: Landscape
32
+ .. tab-item:: Dataset Flow
33
+
34
+ .. include:: dataset_summary/sankey.rst
35
+
36
+ .. tab-item:: Scatter of Sample Size vs. Recording Duration
35
37
 
36
38
  .. include:: dataset_summary/bubble.rst
39
+
40
+ The archive is currently still in :bdg-danger:`beta testing` mode, so be kind.
@@ -0,0 +1,86 @@
1
+ :html_theme.sidebar_secondary.remove: true
2
+
3
+ EEGDASH Homepage
4
+ =================
5
+
6
+ .. title:: EEG Dash
7
+
8
+
9
+ EEG Dash Homepage
10
+ ==================
11
+
12
+ .. raw:: html
13
+
14
+ <style type="text/css">h1 {display:none;}</style>
15
+
16
+ .. raw:: html
17
+
18
+ <h1 class="eegdash-hero__title">EEG Dash</h1>
19
+
20
+
21
+ .. image:: _static/logos/eegdash.svg
22
+ :alt: EEG Dash Logo
23
+ :class: logo mainlogo only-dark
24
+ :align: center
25
+ :scale: 50%
26
+
27
+ .. image:: _static/logos/eegdash.svg
28
+ :alt: EEG Dash Logo
29
+ :class: logo mainlogo only-light
30
+ :align: center
31
+ :scale: 50%
32
+
33
+ .. rst-class:: h4 text-center font-weight-light my-4
34
+
35
+ The EEG-DaSh data archive is a data-sharing resource for MEEG (EEG, MEG) data, enabling
36
+ large-scale computational advancements to preserve and share scientific data from publicly funded
37
+ research for machine learning and deep learning applications.
38
+
39
+ .. rst-class:: text-center
40
+
41
+ The "DaSh" in EEG-DaSh stands for **Data Share**.
42
+
43
+ The EEG-DaSh data archive is a collaborative effort led by the University of California, San Diego (UCSD) and Ben-Gurion University of the Negev (BGU) and partially funded by the National Science Foundation (NSF). All are welcome to contribute to the https://github.com/sccn/EEGDash project.
44
+
45
+ The archive is currently still in :bdg-danger:`beta testing` mode, so be kind.
46
+
47
+ .. raw:: html
48
+
49
+ <h2 style="text-align: center;">Institutions</h2>
50
+
51
+
52
+ .. image:: _static/logos/ucsd_white.svg
53
+ :alt: UCSD
54
+ :class: logo mainlogo only-dark flex-logo
55
+ :width: 45%
56
+ :align: left
57
+
58
+
59
+ .. image:: _static/logos/ucsd_dark.svg
60
+ :alt: UCSD
61
+ :class: logo mainlogo only-light flex-logo
62
+ :align: left
63
+ :width: 45%
64
+
65
+
66
+ .. image:: _static/logos/bgu_dark.svg
67
+ :alt: Ben-Gurion University of the Negev (BGU)
68
+ :class: logo mainlogo only-dark flex-logo
69
+ :align: right
70
+ :width: 40%
71
+
72
+ .. image:: _static/logos/bgu_white.svg
73
+ :alt: Ben-Gurion University of the Negev (BGU)
74
+ :class: logo mainlogo only-light flex-logo
75
+ :align: right
76
+ :width: 40%
77
+
78
+
79
+ .. toctree::
80
+ :hidden:
81
+
82
+ Installing <install/install>
83
+ User Guide <user_guide>
84
+ API <api/api>
85
+ Dataset Catalog <dataset_summary>
86
+ Examples <generated/auto_examples/index>
@@ -18,4 +18,4 @@ _init_mongo_client()
18
18
 
19
19
  __all__ = ["EEGDash", "EEGDashDataset", "EEGChallengeDataset", "preprocessing"]
20
20
 
21
- __version__ = "0.4.0.dev153"
21
+ __version__ = "0.4.0.dev171"
@@ -212,17 +212,22 @@ class EEGDash:
212
212
  return doc is not None
213
213
 
214
214
  def _validate_input(self, record: dict[str, Any]) -> dict[str, Any]:
215
- """Internal method to validate the input record against the expected schema.
215
+ """Validate the input record against the expected schema.
216
216
 
217
217
  Parameters
218
218
  ----------
219
- record: dict
219
+ record : dict
220
220
  A dictionary representing the EEG data record to be validated.
221
221
 
222
222
  Returns
223
223
  -------
224
- dict:
225
- Returns the record itself on success, or raises a ValueError if the record is invalid.
224
+ dict
225
+ The record itself on success.
226
+
227
+ Raises
228
+ ------
229
+ ValueError
230
+ If the record is missing required keys or has values of the wrong type.
226
231
 
227
232
  """
228
233
  input_types = {
@@ -252,20 +257,44 @@ class EEGDash:
252
257
  return record
253
258
 
254
259
  def _build_query_from_kwargs(self, **kwargs) -> dict[str, Any]:
255
- """Internal helper to build a validated MongoDB query from keyword args.
260
+ """Build a validated MongoDB query from keyword arguments.
261
+
262
+ This delegates to the module-level builder used across the package.
263
+
264
+ Parameters
265
+ ----------
266
+ **kwargs
267
+ Keyword arguments to convert into a MongoDB query.
268
+
269
+ Returns
270
+ -------
271
+ dict
272
+ A MongoDB query dictionary.
256
273
 
257
- This delegates to the module-level builder used across the package and
258
- is exposed here for testing and convenience.
259
274
  """
260
275
  return build_query_from_kwargs(**kwargs)
261
276
 
262
- # --- Query merging and conflict detection helpers ---
263
- def _extract_simple_constraint(self, query: dict[str, Any], key: str):
277
+ def _extract_simple_constraint(
278
+ self, query: dict[str, Any], key: str
279
+ ) -> tuple[str, Any] | None:
264
280
  """Extract a simple constraint for a given key from a query dict.
265
281
 
266
- Supports only top-level equality (key: value) and $in (key: {"$in": [...]})
267
- constraints. Returns a tuple (kind, value) where kind is "eq" or "in". If the
268
- key is not present or uses other operators, returns None.
282
+ Supports top-level equality (e.g., ``{'subject': '01'}``) and ``$in``
283
+ (e.g., ``{'subject': {'$in': ['01', '02']}}``) constraints.
284
+
285
+ Parameters
286
+ ----------
287
+ query : dict
288
+ The MongoDB query dictionary.
289
+ key : str
290
+ The key for which to extract the constraint.
291
+
292
+ Returns
293
+ -------
294
+ tuple or None
295
+ A tuple of (kind, value) where kind is "eq" or "in", or None if the
296
+ constraint is not present or unsupported.
297
+
269
298
  """
270
299
  if not isinstance(query, dict) or key not in query:
271
300
  return None
@@ -275,16 +304,28 @@ class EEGDash:
275
304
  return ("in", list(val["$in"]))
276
305
  return None # unsupported operator shape for conflict checking
277
306
  else:
278
- return ("eq", val)
307
+ return "eq", val
279
308
 
280
309
  def _raise_if_conflicting_constraints(
281
310
  self, raw_query: dict[str, Any], kwargs_query: dict[str, Any]
282
311
  ) -> None:
283
- """Raise ValueError if both query sources define incompatible constraints.
312
+ """Raise ValueError if query sources have incompatible constraints.
313
+
314
+ Checks for mutually exclusive constraints on the same field to avoid
315
+ silent empty results.
316
+
317
+ Parameters
318
+ ----------
319
+ raw_query : dict
320
+ The raw MongoDB query dictionary.
321
+ kwargs_query : dict
322
+ The query dictionary built from keyword arguments.
323
+
324
+ Raises
325
+ ------
326
+ ValueError
327
+ If conflicting constraints are found.
284
328
 
285
- We conservatively check only top-level fields with simple equality or $in
286
- constraints. If a field appears in both queries and constraints are mutually
287
- exclusive, raise an explicit error to avoid silent empty result sets.
288
329
  """
289
330
  if not raw_query or not kwargs_query:
290
331
  return
@@ -388,12 +429,31 @@ class EEGDash:
388
429
  logger.info("Upserted: %s", result.upserted_count)
389
430
  logger.info("Errors: %s ", result.bulk_api_result.get("writeErrors", []))
390
431
 
391
- def _add_request(self, record: dict):
392
- """Internal helper method to create a MongoDB insertion request for a record."""
432
+ def _add_request(self, record: dict) -> InsertOne:
433
+ """Create a MongoDB insertion request for a record.
434
+
435
+ Parameters
436
+ ----------
437
+ record : dict
438
+ The record to insert.
439
+
440
+ Returns
441
+ -------
442
+ InsertOne
443
+ A PyMongo ``InsertOne`` object.
444
+
445
+ """
393
446
  return InsertOne(record)
394
447
 
395
- def add(self, record: dict):
396
- """Add a single record to the MongoDB collection."""
448
+ def add(self, record: dict) -> None:
449
+ """Add a single record to the MongoDB collection.
450
+
451
+ Parameters
452
+ ----------
453
+ record : dict
454
+ The record to add.
455
+
456
+ """
397
457
  try:
398
458
  self.__collection.insert_one(record)
399
459
  except ValueError as e:
@@ -405,11 +465,23 @@ class EEGDash:
405
465
  )
406
466
  logger.debug("Add operation failed", exc_info=exc)
407
467
 
408
- def _update_request(self, record: dict):
409
- """Internal helper method to create a MongoDB update request for a record."""
468
+ def _update_request(self, record: dict) -> UpdateOne:
469
+ """Create a MongoDB update request for a record.
470
+
471
+ Parameters
472
+ ----------
473
+ record : dict
474
+ The record to update.
475
+
476
+ Returns
477
+ -------
478
+ UpdateOne
479
+ A PyMongo ``UpdateOne`` object.
480
+
481
+ """
410
482
  return UpdateOne({"data_name": record["data_name"]}, {"$set": record})
411
483
 
412
- def update(self, record: dict):
484
+ def update(self, record: dict) -> None:
413
485
  """Update a single record in the MongoDB collection.
414
486
 
415
487
  Parameters
@@ -429,58 +501,81 @@ class EEGDash:
429
501
  logger.debug("Update operation failed", exc_info=exc)
430
502
 
431
503
  def exists(self, query: dict[str, Any]) -> bool:
432
- """Alias for :meth:`exist` provided for API clarity."""
504
+ """Check if at least one record matches the query.
505
+
506
+ This is an alias for :meth:`exist`.
507
+
508
+ Parameters
509
+ ----------
510
+ query : dict
511
+ MongoDB query to check for existence.
512
+
513
+ Returns
514
+ -------
515
+ bool
516
+ True if a matching record exists, False otherwise.
517
+
518
+ """
433
519
  return self.exist(query)
434
520
 
435
- def remove_field(self, record, field):
436
- """Remove a specific field from a record in the MongoDB collection.
521
+ def remove_field(self, record: dict, field: str) -> None:
522
+ """Remove a field from a specific record in the MongoDB collection.
437
523
 
438
524
  Parameters
439
525
  ----------
440
526
  record : dict
441
- Record identifying object with ``data_name``.
527
+ Record-identifying object with a ``data_name`` key.
442
528
  field : str
443
- Field name to remove.
529
+ The name of the field to remove.
444
530
 
445
531
  """
446
532
  self.__collection.update_one(
447
533
  {"data_name": record["data_name"]}, {"$unset": {field: 1}}
448
534
  )
449
535
 
450
- def remove_field_from_db(self, field):
451
- """Remove a field from all records (destructive).
536
+ def remove_field_from_db(self, field: str) -> None:
537
+ """Remove a field from all records in the database.
538
+
539
+ .. warning::
540
+ This is a destructive operation and cannot be undone.
452
541
 
453
542
  Parameters
454
543
  ----------
455
544
  field : str
456
- Field name to remove from every document.
545
+ The name of the field to remove from all documents.
457
546
 
458
547
  """
459
548
  self.__collection.update_many({}, {"$unset": {field: 1}})
460
549
 
461
550
  @property
462
551
  def collection(self):
463
- """Return the MongoDB collection object."""
464
- return self.__collection
552
+ """The underlying PyMongo ``Collection`` object.
465
553
 
466
- def close(self):
467
- """Backward-compatibility no-op; connections are managed globally.
554
+ Returns
555
+ -------
556
+ pymongo.collection.Collection
557
+ The collection object used for database interactions.
468
558
 
469
- Notes
470
- -----
471
- Connections are managed by :class:`MongoConnectionManager`. Use
472
- :meth:`close_all_connections` to explicitly close all clients.
559
+ """
560
+ return self.__collection
473
561
 
562
+ def close(self) -> None:
563
+ """Close the MongoDB connection.
564
+
565
+ .. deprecated:: 0.1
566
+ Connections are now managed globally by :class:`MongoConnectionManager`.
567
+ This method is a no-op and will be removed in a future version.
568
+ Use :meth:`EEGDash.close_all_connections` to close all clients.
474
569
  """
475
570
  # Individual instances no longer close the shared client
476
571
  pass
477
572
 
478
573
  @classmethod
479
- def close_all_connections(cls):
480
- """Close all MongoDB client connections managed by the singleton."""
574
+ def close_all_connections(cls) -> None:
575
+ """Close all MongoDB client connections managed by the singleton manager."""
481
576
  MongoConnectionManager.close_all()
482
577
 
483
- def __del__(self):
578
+ def __del__(self) -> None:
484
579
  """Destructor; no explicit action needed due to global connection manager."""
485
580
  # No longer needed since we're using singleton pattern
486
581
  pass
@@ -775,45 +870,30 @@ class EEGDashDataset(BaseConcatDataset, metaclass=NumpyDocstringInheritanceInitM
775
870
  ) -> list[dict]:
776
871
  """Discover local BIDS EEG files and build minimal records.
777
872
 
778
- This helper enumerates EEG recordings under ``dataset_root`` via
779
- ``mne_bids.find_matching_paths`` and applies entity filters to produce a
780
- list of records suitable for ``EEGDashBaseDataset``. No network access
781
- is performed and files are not read.
873
+ Enumerates EEG recordings under ``dataset_root`` using
874
+ ``mne_bids.find_matching_paths`` and applies entity filters to produce
875
+ records suitable for :class:`EEGDashBaseDataset`. No network access is
876
+ performed, and files are not read.
782
877
 
783
878
  Parameters
784
879
  ----------
785
880
  dataset_root : Path
786
- Local dataset directory. May be the plain dataset folder (e.g.,
787
- ``ds005509``) or a suffixed cache variant (e.g.,
788
- ``ds005509-bdf-mini``).
789
- filters : dict of {str, Any}
790
- Query filters. Must include ``'dataset'`` with the dataset id (without
791
- local suffixes). May include BIDS entities ``'subject'``,
792
- ``'session'``, ``'task'``, and ``'run'``. Each value can be a scalar
793
- or a sequence of scalars.
881
+ Local dataset directory (e.g., ``/path/to/cache/ds005509``).
882
+ filters : dict
883
+ Query filters. Must include ``'dataset'`` and may include BIDS
884
+ entities like ``'subject'``, ``'session'``, etc.
794
885
 
795
886
  Returns
796
887
  -------
797
- records : list of dict
798
- One record per matched EEG file with at least:
799
-
800
- - ``'data_name'``
801
- - ``'dataset'`` (dataset id, without suffixes)
802
- - ``'bidspath'`` (normalized to start with the dataset id)
803
- - ``'subject'``, ``'session'``, ``'task'``, ``'run'`` (may be None)
804
- - ``'bidsdependencies'`` (empty list)
805
- - ``'modality'`` (``"eeg"``)
806
- - ``'sampling_frequency'``, ``'nchans'``, ``'ntimes'`` (minimal
807
- defaults for offline usage)
888
+ list of dict
889
+ A list of records, one for each matched EEG file. Each record
890
+ contains BIDS entities, paths, and minimal metadata for offline use.
808
891
 
809
892
  Notes
810
893
  -----
811
- - Matching uses ``datatypes=['eeg']`` and ``suffixes=['eeg']``.
812
- - ``bidspath`` is constructed as
813
- ``<dataset_id> / <relative_path_from_dataset_root>`` to ensure the
814
- first path component is the dataset id (without local cache suffixes).
815
- - Minimal defaults are set for ``sampling_frequency``, ``nchans``, and
816
- ``ntimes`` to satisfy dataset length requirements offline.
894
+ Matching is performed for ``datatypes=['eeg']`` and ``suffixes=['eeg']``.
895
+ The ``bidspath`` is normalized to ensure it starts with the dataset ID,
896
+ even for suffixed cache directories.
817
897
 
818
898
  """
819
899
  dataset_id = filters["dataset"]
@@ -875,10 +955,22 @@ class EEGDashDataset(BaseConcatDataset, metaclass=NumpyDocstringInheritanceInitM
875
955
  return records_out
876
956
 
877
957
  def _find_key_in_nested_dict(self, data: Any, target_key: str) -> Any:
878
- """Recursively search for target_key in nested dicts/lists with normalized matching.
958
+ """Recursively search for a key in nested dicts/lists.
959
+
960
+ Performs a case-insensitive and underscore/hyphen-agnostic search.
961
+
962
+ Parameters
963
+ ----------
964
+ data : Any
965
+ The nested data structure (dicts, lists) to search.
966
+ target_key : str
967
+ The key to search for.
968
+
969
+ Returns
970
+ -------
971
+ Any
972
+ The value of the first matching key, or None if not found.
879
973
 
880
- This makes lookups tolerant to naming differences like "p-factor" vs "p_factor".
881
- Returns the first match or None.
882
974
  """
883
975
  norm_target = normalize_key(target_key)
884
976
  if isinstance(data, dict):
@@ -901,23 +993,25 @@ class EEGDashDataset(BaseConcatDataset, metaclass=NumpyDocstringInheritanceInitM
901
993
  description_fields: list[str],
902
994
  base_dataset_kwargs: dict,
903
995
  ) -> list[EEGDashBaseDataset]:
904
- """Helper method to find datasets in the MongoDB collection that satisfy the
905
- given query and return them as a list of EEGDashBaseDataset objects.
996
+ """Find and construct datasets from a MongoDB query.
997
+
998
+ Queries the database, then creates a list of
999
+ :class:`EEGDashBaseDataset` objects from the results.
906
1000
 
907
1001
  Parameters
908
1002
  ----------
909
- query : dict
910
- The query object, as in EEGDash.find().
911
- description_fields : list[str]
912
- A list of fields to be extracted from the dataset records and included in
913
- the returned dataset description(s).
914
- kwargs: additional keyword arguments to be passed to the EEGDashBaseDataset
915
- constructor.
1003
+ query : dict, optional
1004
+ The MongoDB query to execute.
1005
+ description_fields : list of str
1006
+ Fields to extract from each record for the dataset description.
1007
+ base_dataset_kwargs : dict
1008
+ Additional keyword arguments to pass to the
1009
+ :class:`EEGDashBaseDataset` constructor.
916
1010
 
917
1011
  Returns
918
1012
  -------
919
- list :
920
- A list of EEGDashBaseDataset objects that match the query.
1013
+ list of EEGDashBaseDataset
1014
+ A list of dataset objects matching the query.
921
1015
 
922
1016
  """
923
1017
  datasets: list[EEGDashBaseDataset] = []