Skip to content

Fix Lenaig2026 data_path layout + Schrag2026Pediatric zero-annotation run crash - #1225

Merged
bruAristimunha merged 3 commits into
NeuroTechX:developfrom
bruAristimunha:fix/lenaig-schrag-convert
Oct 5, 2026
Merged

bruAristimunha merged 3 commits into
NeuroTechX:developfrom
bruAristimunha:fix/lenaig-schrag-convert

Conversation

@bruAristimunha

Copy link
Copy Markdown
Collaborator

Problem

Both bugs were found re-running the Voyager convert pipeline on real downloads (not caught by synthetic tests, since neither reproduces the real archive layout / real-subject trial-CSV drift). See .pr-audits/w41/V6B-REPORT.md for the original evidence.

1. Lenaig2026

data_path() hard-coded an EEG_24Chan_AudioStim/ wrapper directory for the extracted RAR. The current Zenodo v2 archive (record 21156618) extracts EXP1//EXP2/ directly at the extraction root, so every subject's data_path() raised FileNotFoundError: Some data files are missing. before ever reading a file.

Fix: locate each run's file with a recursive glob (base_path.glob(f"**/{rel}")) that matches both the wrapped and flat layouts, instead of a single hard-coded relative path. Events/labels are unchanged.

2. Schrag2026Pediatric

_load_game_run's documented policy drops all trial labels when a game run's Trial Started marker count drifts more than 10% from its movements-CSV row count. Subject 1's personalized-stimulus game run (task-T3_acq-C3S1_M2) has 15% drift, so that run ends up with zero annotations. _get_single_subject_data returned it anyway, and bids_interface._write_file hard-requires every Raw to carry annotations, so the whole convert crashed with ValueError: Raw object must have annotations to be saved in BIDS format.

Fix: _get_single_subject_data now skips a run that ends up with zero events instead of returning it, logging a warning that names the subject and run. The class and _load_game_run docstrings document this. The high-drift policy itself (why labels are dropped) is unchanged — this only changes what happens to a run with zero resulting labels.

Tests

Two new regression tests in moabb/tests/test_dataset_fixes.py:

  • test_lenaig2026_data_path_accepts_wrapped_and_flat_layouts: a synthetic tmp tree in each layout, asserting data_path() finds the right files either way.
  • test_schrag2026_skips_run_with_zero_annotations_after_high_drift: mocks _load_game_run to return one zero-annotation and one labelled run, asserts the zero-annotation run is skipped and a warning names the subject/run.

Both pass locally (pytest -k "lenaig2026 or schrag2026"), plus the rest of test_dataset_fixes.py (15/15 passed).

Not in scope

Does not touch the Lenaig2026 CC-BY-NC-ND-4.0 licence question (held for a separate confirmation) or attempt any upload/publish.

… run crash

- Lenaig2026.data_path(): accept both the wrapped (EEG_24Chan_AudioStim/)
  and flat (EXP*/ at root) extracted-RAR layouts via a recursive glob,
  instead of hard-coding the wrapper the current Zenodo v2 archive
  (record 21156618) does not ship. Events/labels unchanged.
- Schrag2026Pediatric._get_single_subject_data(): skip a game run that
  ends up with zero annotations after the loader's own >10% Trial/CSV
  drift policy drops all labels, with a warning naming the subject and
  run, instead of returning it and crashing bids_interface's writer
  ('Raw object must have annotations to be saved in BIDS format').
- TDD regression tests for both (moabb/tests/test_dataset_fixes.py).
- whats_new Bugs entries.
@bruAristimunha
bruAristimunha force-pushed the fix/lenaig-schrag-convert branch from f466420 to a9ed24e Compare October 5, 2026 12:24
Caught by a real end-to-end convert on Voyager: METADATA.experiment.
trials_per_class was a bare int (10), violating the schema's declared
Dict[str, int] type; bids_interface._build_readme's _format_dict()
crashes on a non-dict with AttributeError: 'int' object has no
attribute 'items'. Now {"Stimulus": 10, "Silence": 10}, matching the
documented 10 repetitions per condition.
@bruAristimunha

Copy link
Copy Markdown
Collaborator Author

Pushed a third fix (52a5e6e): Lenaig2026.METADATA.experiment.trials_per_class was a bare int (10), not the Dict[str, int] the schema declares. Found during the real Voyager end-to-end convert this PR enables (the layout fix got past data_path(), then convert_to_bids() crashed in bids_interface._build_readme with AttributeError: 'int' object has no attribute 'items'). Fixed to {"Stimulus": 10, "Silence": 10}, matching the documented 10 repetitions per condition. Regression test + whats_new entry added.

…otFoundError

Caught on a real end-to-end convert of Schrag2026Pediatric: subject 16's
only game recording's only run was dropped by the >10% drift policy,
leaving zero usable runs, so _get_single_subject_data correctly raised
FileNotFoundError for that one subject. convert_to_bids's per-subject
loop had no try/except, so that single subject's exception aborted the
whole multi-subject convert, silently losing every later subject too.
Now the loop catches FileNotFoundError, logs a warning naming the
subject, and continues converting the rest.
@bruAristimunha

Copy link
Copy Markdown
Collaborator Author

Pushed a fourth fix (5e98acd): convert_to_bids's per-subject loop had no try/except around self.get_data(). Found on the real Voyager convert of Schrag2026Pediatric: subject 16's only game recording has a single run, and that run is dropped entirely by the >10% drift policy (same mechanism as subject 1, fixed earlier in this PR), so _get_single_subject_data correctly raises FileNotFoundError for that one subject -- but with no per-subject exception handling, that aborted conversion of every subject after 16 too (would have silently lost subjects 17-47). Now caught, logged with a warning naming the subject, and the loop continues. Regression test + whats_new entry added; full re-convert of both datasets on Voyager now running end-to-end.

@bruAristimunha
bruAristimunha merged commit a2180fa into NeuroTechX:develop Oct 5, 2026
14 checks passed
@bruAristimunha
bruAristimunha deleted the fix/lenaig-schrag-convert branch October 6, 2026 10:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant