Source code for autoclean.functions.preprocessing.referencing

"""Referencing functions for EEG data.

This module provides standalone functions for applying different referencing
schemes to EEG data, including average reference, specific channel reference,
and REST (Reference Electrode Standardization Technique).
"""

from typing import List, Optional, Union

import mne


[docs] def rereference_data( data: Union[mne.io.BaseRaw, mne.Epochs], ref_channels: Union[str, List[str]] = "average", projection: bool = False, ch_type: str = "auto", forward: Optional[mne.Forward] = None, verbose: Optional[bool] = None, ) -> Union[mne.io.BaseRaw, mne.Epochs]: """Apply referencing scheme to EEG data. This function applies various referencing schemes to continuous (Raw) or epoched EEG data. Referencing is a crucial preprocessing step that determines the voltage reference point for all EEG measurements, significantly affecting signal interpretation and analysis results. The function supports common referencing schemes including average reference, single-channel reference, multi-channel reference, and REST (Reference Electrode Standardization Technique) when appropriate forward model is provided. Parameters ---------- data : mne.io.BaseRaw or mne.Epochs The EEG data to rereference. Can be any MNE Raw object (e.g., RawFIF, RawEEGLAB, etc.) or Epochs object. ref_channels : str or list of str, default 'average' Reference channel(s) to use. Options: - 'average': Compute average reference across all EEG channels - 'REST': Apply Reference Electrode Standardization Technique (requires forward model) - str: Name of single channel to use as reference (e.g., 'Cz', 'TP9') - list of str: Names of multiple channels to average for reference - []: Empty list creates an artificial reference channel projection : bool, default False Whether to apply referencing as a projection. If True, referencing is applied as a reversible projection operator. If False, data is modified directly (recommended for most use cases). ch_type : str, default 'auto' Channel type to apply referencing to. 'auto' automatically selects EEG channels. Can also specify 'eeg', 'ecog', 'seeg', or 'dbs'. forward : mne.Forward or None, default None Forward model for REST referencing. Required only when ref_channels='REST'. Should be computed for the same electrode montage as the data. verbose : bool or None, default None Control verbosity of output. If None, uses MNE default. Returns ------- rereferenced_data : mne.io.BaseRaw or mne.Epochs The rereferenced data object, same type as input. Contains identical structure and metadata but with modified voltage references. Notes ----- Common referencing schemes: average reference, single channel, linked mastoids, or REST. Examples -------- >>> avg_ref_data = rereference_data(raw, ref_channels='average') >>> mastoid_ref_data = rereference_data(raw, ref_channels='TP9') >>> rest_ref_data = rereference_data(raw, ref_channels='REST', forward=forward_model) See Also -------- mne.io.Raw.set_eeg_reference : MNE's raw data referencing method mne.Epochs.set_eeg_reference : MNE's epochs referencing method mne.set_eeg_reference : General referencing function mne.make_forward_solution : For creating forward models for REST """ # Input validation if not isinstance(data, (mne.io.BaseRaw, mne.Epochs)): raise TypeError( f"Data must be an MNE Raw or Epochs object, got {type(data).__name__}" ) # Validate reference channels parameter if isinstance(ref_channels, str): if ( ref_channels not in ["average", "REST"] and ref_channels not in data.ch_names ): if ref_channels != "average" and ref_channels != "REST": raise ValueError( f"Reference channel '{ref_channels}' not found in data. " f"Available channels: {data.ch_names}" ) elif isinstance(ref_channels, (list, tuple)): if ref_channels: # Non-empty list missing_channels = [ch for ch in ref_channels if ch not in data.ch_names] if missing_channels: raise ValueError( f"Reference channels {missing_channels} not found in data. " f"Available channels: {data.ch_names}" ) else: raise TypeError( f"ref_channels must be str, list, or tuple, got {type(ref_channels).__name__}" ) # Validate REST requirements if ref_channels == "REST" and forward is None: raise ValueError("Forward model is required for REST referencing") # Create a copy to avoid modifying the original rereferenced_data = data.copy() try: # Apply referencing using MNE's built-in method if ref_channels == "average": # Special handling for average reference rereferenced_data.set_eeg_reference( ref_channels="average", projection=projection, ch_type=ch_type, verbose=verbose, ) elif ref_channels == "REST": # REST referencing with forward model rereferenced_data.set_eeg_reference( ref_channels="REST", projection=projection, ch_type=ch_type, forward=forward, verbose=verbose, ) else: # Single channel or multi-channel reference rereferenced_data.set_eeg_reference( ref_channels=ref_channels, projection=projection, ch_type=ch_type, verbose=verbose, ) return rereferenced_data except Exception as e: ref_str = ( str(ref_channels) if not isinstance(ref_channels, list) else f"[{', '.join(ref_channels)}]" ) raise RuntimeError(f"Failed to apply {ref_str} reference: {str(e)}") from e