.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/asr/plot_15_guided_asr.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_asr_plot_15_guided_asr.py: Guided ASR: preserving neural activity that ASR would over-clean. ================================================================= Standard ASR decides purely on variance, so a strong, spatially structured **neural** burst (here a transient 10 Hz oscillation) looks just as "abnormal" as an artifact and gets reconstructed away. ``GuidedASR`` keeps ASR's abnormality detection but adds DSS-style **bias operators** that recognise the neural direction and a continuous reconstruction weight that rescues it, while still removing a genuine artifact. This example builds a substrate with a known 10 Hz neural target and a known broadband artifact, cleans it with standard ASR and with GuidedASR, and shows that GuidedASR preserves the neural projection that standard ASR removes. .. warning:: GuidedASR is an unpublished, unvalidated experimental research prototype. This synthetic demonstration is not evidence of validity on real EEG. Check neural-signal preservation, artifact attenuation, and downstream endpoints independently before scientific use. .. GENERATED FROM PYTHON SOURCE LINES 25-27 Imports ------- .. GENERATED FROM PYTHON SOURCE LINES 27-34 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from mne_denoise.asr import ASR, GuidedASR from mne_denoise.dss.denoisers import BandpassBias, PeakFilterBias from mne_denoise.viz import plot_guided_asr_weights .. GENERATED FROM PYTHON SOURCE LINES 35-40 Synthetic substrate ------------------- A quiet 1/f-ish background (the calibration baseline), plus a transient 10 Hz neural target (fixed spatial pattern, second half) we want to PRESERVE, plus a high-amplitude broadband artifact (different pattern) we want to REMOVE. .. GENERATED FROM PYTHON SOURCE LINES 40-66 .. code-block:: Python sfreq = 250.0 rng = np.random.default_rng(7) n_ch, n = 16, 15000 t = np.arange(n) / sfreq background = 0.15 * rng.standard_normal((n_ch, n)) for f in (3.0, 6.0, 11.0, 23.0): for c in range(n_ch): background[c] += (1.0 / f) * np.sin(2 * np.pi * f * t + rng.uniform(0, 6.28)) p_neural = rng.standard_normal(n_ch) p_neural /= np.linalg.norm(p_neural) neural_ts = np.zeros(n) neural_ts[n // 2 :] = 4.0 * np.sin(2 * np.pi * 10.0 * t[n // 2 :]) clean = background + np.outer(p_neural, neural_ts) # ground truth p_art = rng.standard_normal(n_ch) p_art /= np.linalg.norm(p_art) artifact = np.zeros((n_ch, n)) for start in (int(0.15 * n), int(0.30 * n)): seg = slice(start, start + int(0.4 * sfreq)) artifact[:, seg] += 7.0 * np.outer(p_art, rng.standard_normal(seg.stop - seg.start)) contaminated = clean + artifact calib = background[:, : int(8.0 * sfreq)] # quiet baseline (no events, no artifact) .. GENERATED FROM PYTHON SOURCE LINES 67-71 Clean with standard ASR and with Guided ASR ------------------------------------------- Both calibrate on the quiet baseline. GuidedASR is told the brain subspace (a 10 Hz peak filter) and the artifact subspace (a broadband band). .. GENERATED FROM PYTHON SOURCE LINES 71-92 .. code-block:: Python common = { "sfreq": sfreq, "cutoff": 8.0, "calibration": "manual", "picks": None, "verbose": False, } asr = ASR(method="riemannian_windowed", **common).fit(calib) cleaned_asr = np.asarray(asr.transform(contaminated)) guided = GuidedASR( reconstruction="soft", experimental=True, guidance_strength=1.0, preserve_biases=[PeakFilterBias(10.0, sfreq)], artifact_biases=[BandpassBias((30.0, 80.0), sfreq)], **common, ).fit(contaminated, calibration=calib) cleaned_guided = np.asarray(guided.transform(contaminated)) .. GENERATED FROM PYTHON SOURCE LINES 93-97 Soft weights ------------ Green = kept (w -> 1), red = suppressed (w -> 0). Standard ASR would show only 0/1; the graded values are where Guided ASR preserves structure. .. GENERATED FROM PYTHON SOURCE LINES 97-99 .. code-block:: Python plot_guided_asr_weights(guided, show=False) .. image-sg:: /auto_examples/asr/images/sphx_glr_plot_15_guided_asr_001.png :alt: GuidedASR soft weights (mean = 0.996) :srcset: /auto_examples/asr/images/sphx_glr_plot_15_guided_asr_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none (
, ) .. GENERATED FROM PYTHON SOURCE LINES 100-103 Neural projection: preserved vs over-cleaned -------------------------------------------- Project each signal onto the neural spatial pattern over the event region. .. GENERATED FROM PYTHON SOURCE LINES 103-128 .. code-block:: Python ev = slice(n // 2, n) proj_clean = (p_neural @ clean)[ev] proj_asr = (p_neural @ cleaned_asr)[ev] proj_guided = (p_neural @ cleaned_guided)[ev] tt = t[ev] fig, ax = plt.subplots(figsize=(11, 3.6)) ax.plot(tt, proj_clean, color="0.6", lw=1.4, label="ground truth (neural)") ax.plot(tt, proj_asr, color="C3", lw=0.9, alpha=0.8, label="standard ASR (removed)") ax.plot(tt, proj_guided, color="C0", lw=1.0, label="GuidedASR (preserved)") ax.set_xlabel("Time (s)") ax.set_ylabel("Neural-pattern projection") ax.set_title("GuidedASR preserves the 10 Hz neural target ASR over-cleans") ax.legend(loc="upper right", fontsize=8) fig.tight_layout() def _corr(a, b): return float(np.corrcoef(a, b)[0, 1]) print(f"neural preservation standard ASR: {_corr(proj_asr, proj_clean):+.3f}") print(f"neural preservation GuidedASR : {_corr(proj_guided, proj_clean):+.3f}") plt.show() .. image-sg:: /auto_examples/asr/images/sphx_glr_plot_15_guided_asr_002.png :alt: GuidedASR preserves the 10 Hz neural target ASR over-cleans :srcset: /auto_examples/asr/images/sphx_glr_plot_15_guided_asr_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none neural preservation standard ASR: -0.734 neural preservation GuidedASR : +1.000 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.505 seconds) .. _sphx_glr_download_auto_examples_asr_plot_15_guided_asr.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_15_guided_asr.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_15_guided_asr.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_15_guided_asr.zip `