.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/asr/plot_14_rms_distribution.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_14_rms_distribution.py: ============================================= Quantifying Dataset Noise with RMS Statistics ============================================= This example demonstrates how to use ASR's robust mathematical estimators independently of the full ASR pipeline to quantify the baseline noisiness of a dataset. We use the ``fit_rms_distribution`` function. This function takes a distribution of window-RMS values, ignores the extreme artifact tails, and fits a Generalized Gaussian curve to the clean data. This allows researchers to calculate robust location (mu) and scale (sigma) statistics to standardize or compare subjects. .. GENERATED FROM PYTHON SOURCE LINES 17-19 Imports ------- .. GENERATED FROM PYTHON SOURCE LINES 19-25 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from mne_denoise.asr import fit_rms_distribution .. GENERATED FROM PYTHON SOURCE LINES 26-32 Part 1: Synthetic Data ---------------------- Let's generate a synthetic distribution of RMS values. Real EEG/MEG RMS values often follow a Generalized Gaussian distribution, but are heavily contaminated by large, positive "tails" caused by artifacts like eye blinks or movement. .. GENERATED FROM PYTHON SOURCE LINES 32-47 .. code-block:: Python rng = np.random.default_rng(42) # Simulate clean brain RMS data (mean=10.0, std=2.0) clean_rms = np.abs(rng.normal(loc=10.0, scale=2.0, size=5000)) # Simulate massive artifact RMS data (mean=30.0, std=10.0) artifact_rms = np.abs(rng.normal(loc=30.0, scale=10.0, size=500)) # Combine them into a single contaminated dataset contaminated_rms = np.concatenate([clean_rms, artifact_rms]) np.random.shuffle(contaminated_rms) print(f"Total simulated windows: {len(contaminated_rms)}") .. rst-class:: sphx-glr-script-out .. code-block:: none Total simulated windows: 5500 .. GENERATED FROM PYTHON SOURCE LINES 48-54 Fitting the Distribution ------------------------ If we used standard mean and standard deviation on this dataset, the massive artifacts would severely distort the results. Instead, we use ``fit_rms_distribution`` to ignore the artifact tails and fit the true clean core. .. GENERATED FROM PYTHON SOURCE LINES 54-73 .. code-block:: Python standard_mean = np.mean(contaminated_rms) standard_std = np.std(contaminated_rms) # We set return_info=True to get the exact fitted shape parameter (beta) mu, sigma, info = fit_rms_distribution(contaminated_rms, return_info=True) print("\n--- Standard Statistics ---") print(f"Mean: {standard_mean:.2f}") print(f"Std: {standard_std:.2f}") print("\n--- Robust RMS Statistics ---") print(f"Mu (Clean Center): {mu:.2f}") print(f"Sigma (Clean Spread): {sigma:.2f}") print(f"Beta (Curve Shape): {info['beta']:.2f}") # Notice how `mu` perfectly locked onto the true clean mean (10.0), while # the standard mean was artificially dragged up by the artifacts. .. rst-class:: sphx-glr-script-out .. code-block:: none --- Standard Statistics --- Mean: 11.81 Std: 6.84 --- Robust RMS Statistics --- Mu (Clean Center): 10.04 Sigma (Clean Spread): 2.01 Beta (Curve Shape): 2.00 .. GENERATED FROM PYTHON SOURCE LINES 74-78 Visualizing the Fit ------------------- We can visualize the distribution to see exactly what the algorithm did. The algorithm found the main peak and ignored the long right tail. .. GENERATED FROM PYTHON SOURCE LINES 78-109 .. code-block:: Python fig, ax = plt.subplots(figsize=(10, 6)) # Plot the raw histogram counts, bins, _ = ax.hist( contaminated_rms, bins=100, density=True, alpha=0.6, color="steelblue", label="Contaminated RMS Data", ) # Plot the robust center ax.axvline(mu, color="red", linestyle="--", linewidth=2, label=f"Robust Mu ({mu:.1f})") ax.axvline( standard_mean, color="black", linestyle=":", linewidth=2, label=f"Standard Mean ({standard_mean:.1f})", ) ax.set_title("RMS Distribution with Robust Fit") ax.set_xlabel("RMS Value") ax.set_ylabel("Density") ax.set_xlim(0, 50) ax.legend() plt.tight_layout() plt.show(block=False) .. image-sg:: /auto_examples/asr/images/sphx_glr_plot_14_rms_distribution_001.png :alt: RMS Distribution with Robust Fit :srcset: /auto_examples/asr/images/sphx_glr_plot_14_rms_distribution_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 110-118 Part 2: Real Data ----------------- In practice, you would calculate these RMS values yourself directly from your continuous data by sliding a window across it and calculating the RMS of the variance for each window. This allows you to quantify "how noisy is this subject compared to the cohort?" or to Z-score your data robustly prior to downstream machine learning. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.257 seconds) .. _sphx_glr_download_auto_examples_asr_plot_14_rms_distribution.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_14_rms_distribution.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_14_rms_distribution.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_14_rms_distribution.zip `