Source code for bemobil_mne.io.bids_export

"""BIDS export utilities for bemobil_mne.

Thin wrappers around :mod:`mne_bids` that apply project conventions and
optionally record export parameters in the raw object's provenance descriptor.

Requires the ``mne_bids`` package (already a declared dependency of
``BeMoBIL-MNE``).
"""

# %% Imports

from __future__ import annotations

import logging
from pathlib import Path

import mne_bids

# %% Settings & Constants

LOGGER = logging.getLogger(__name__)

# %% Functions


[docs] def export_to_bids( raw, bids_root, subject, session=None, task="task", run=None, acquisition=None, events=None, event_id=None, line_freq=50.0, overwrite=False, verbose=True, extra_params=None, ): """Export an MNE Raw object to a BIDS-compatible directory tree. Wraps :func:`mne_bids.write_raw_bids` with sensible defaults for EEG data and records the BIDS path in the raw object's provenance descriptor (when one exists). Parameters ---------- raw : mne.io.BaseRaw Raw EEG recording. Must have a montage set and ``info['sfreq']`` populated. bids_root : str | Path Root of the BIDS dataset (will be created if it does not exist). subject : str BIDS subject label (without the ``sub-`` prefix, e.g. ``"01"``). session : str | None BIDS session label (without ``ses-``). ``None`` omits the session directory level. task : str BIDS task label. Defaults to ``"task"``. run : str | None BIDS run label (without ``run-``). ``None`` when there is a single run. acquisition : str | None BIDS acquisition label (without ``acq-``). events : ndarray, shape (n_events, 3) | None MNE-style event array (sample, prev_id, event_id). When ``None``, events are derived from ``raw.annotations`` automatically by :func:`mne_bids.write_raw_bids`. event_id : dict | None Mapping of event descriptions to integer codes, e.g. ``{"left_hand": 1, "right_hand": 2}``. line_freq : float Power-line frequency (Hz). Used to populate the ``PowerLineFrequency`` BIDS field. Defaults to 50 Hz (Europe / most of Asia). overwrite : bool Whether to overwrite existing BIDS files for this entity. verbose : bool | str | int Verbosity level forwarded to :func:`mne_bids.write_raw_bids`. extra_params : dict | None Extra keyword arguments forwarded verbatim to :func:`mne_bids.write_raw_bids`. Returns ------- bids_path : mne_bids.BIDSPath The :class:`mne_bids.BIDSPath` object describing the written file. """ bids_root = Path(bids_root) bids_path = mne_bids.BIDSPath( subject=str(subject), session=str(session) if session is not None else None, task=str(task), run=str(run) if run is not None else None, acquisition=str(acquisition) if acquisition is not None else None, root=bids_root, datatype="eeg", ) # Set power-line frequency in info (required by BIDS validator) raw = raw.copy() raw.info["line_freq"] = float(line_freq) write_kwargs: dict = dict( raw=raw, bids_path=bids_path, overwrite=overwrite, verbose=verbose, ) if events is not None: write_kwargs["events"] = events if event_id is not None: write_kwargs["event_id"] = event_id if extra_params: write_kwargs.update(extra_params) # mne_bids requires explicit permission when raw is preloaded in memory # (not backed by a file on disk) - default to BrainVision format. if raw.preload and "allow_preload" not in write_kwargs: write_kwargs["allow_preload"] = True write_kwargs.setdefault("format", "BrainVision") bids_path_out = mne_bids.write_raw_bids(**write_kwargs) LOGGER.info(f"BIDS export complete: {bids_path_out.fpath}") # Record in provenance if descriptor exists try: from bemobil_mne.preproc.utils import append_desc, get_descriptor if get_descriptor(raw) is not None: append_desc( raw, name="bids_export", bids_path=str(bids_path_out.fpath), subject=subject, session=session, task=task, run=run, ) except Exception: pass # provenance recording is best-effort return bids_path_out
[docs] def make_bids_dataset_description( bids_root, name, authors=None, data_license=None, acknowledgements=None, funding=None, doi=None, ): """Write a minimal BIDS ``dataset_description.json``. Calls :func:`mne_bids.make_dataset_description`. Idempotent: safe to call multiple times. Parameters ---------- bids_root : str | Path Root of the BIDS dataset. name : str Human-readable dataset name. authors : list of str | None Author names. data_license : str | None SPDX license identifier or free-text (maps to ``data_license`` in BIDS ``dataset_description.json``). acknowledgements : str | None Acknowledgements text. funding : list of str | None Funding source strings. doi : str | None Dataset DOI. """ mne_bids.make_dataset_description( path=str(bids_root), name=name, authors=authors or [], data_license=data_license or "", acknowledgements=acknowledgements or "", funding=funding or [], doi=doi or "", overwrite=True, ) LOGGER.info(f"BIDS dataset_description.json written at {bids_root}")
[docs] def batch_export_to_bids( subject_runs, bids_root, task="task", line_freq=50.0, overwrite=False, verbose=False, ): """Export multiple subjects / runs to BIDS in a single call. Parameters ---------- subject_runs : list of dict Each dict must contain at least ``{"raw": <raw>, "subject": "01"}``. Optional keys: ``session``, ``run``, ``acquisition``, ``events``, ``event_id``. bids_root : str | Path BIDS root directory. task : str Task label shared across all runs. line_freq : float Power-line frequency. overwrite : bool Overwrite existing BIDS files. verbose : bool | str | int Verbosity for :func:`mne_bids.write_raw_bids`. Returns ------- bids_paths : list of mne_bids.BIDSPath One path per successfully written run. """ results = [] for entry in subject_runs: raw = entry["raw"] subject = str(entry["subject"]) session = entry.get("session") run = entry.get("run") acquisition = entry.get("acquisition") events = entry.get("events") event_id = entry.get("event_id") try: bp = export_to_bids( raw=raw, bids_root=bids_root, subject=subject, session=session, task=task, run=run, acquisition=acquisition, events=events, event_id=event_id, line_freq=line_freq, overwrite=overwrite, verbose=verbose, ) results.append(bp) except Exception as exc: LOGGER.error(f"BIDS export failed for sub-{subject}: {exc}") return results