From a1f488b75c6b6dc44b68735e8e95155bf09093d5 Mon Sep 17 00:00:00 2001 From: Virginie van Wassenhove Date: Mon, 24 Aug 2026 15:02:36 +0200 Subject: [PATCH 01/12] Implementation of the meanlogration proposed by Kinley et al (2026) for TFR baselining --- doc/references.bib | 9 ++++++ mne/baseline.py | 29 ++++++++---------- mne/minimum_norm/time_frequency.py | 34 ++------------------- mne/time_frequency/tfr.py | 30 ++++++++----------- mne/utils/docs.py | 47 +++++++++++++++++++----------- mne/viz/topomap.py | 15 +--------- 6 files changed, 67 insertions(+), 97 deletions(-) diff --git a/doc/references.bib b/doc/references.bib index 668e204543d..4a9a0b89f02 100644 --- a/doc/references.bib +++ b/doc/references.bib @@ -1025,6 +1025,15 @@ @unpublished{KingEtAl2018 note = {hal-01848442} } +@article{KinleyEtAl2026, + author={Kinley, Isaac and Roberts, Reece P and Meltzer, Jed A and Addis, Donna Rose}, + title={Spectral change or Jensen gap? Log-ratio baseline correction for time-frequency M/EEG is negatively biased}, + journal={Journal of Neuroscience Methods}, + pages={110826}, + year={2026}, + publisher={Elsevier} +} + @article{KnuutilaEtAl1993, author = {Knuutila, Jukka E. T. and Ahonen, Antti I. and Hämäläinen, Matti S. and Kajola, Matti J. and Laine, P. P. and Lounasmaa, Olli V. and Parkkonen, Lauri T. and Simola, Juha T. A. and Tesche, Claudia D.}, doi = {10.1109/20.281163}, diff --git a/mne/baseline.py b/mne/baseline.py index 4e73ed0ce95..a1d294df32c 100644 --- a/mne/baseline.py +++ b/mne/baseline.py @@ -15,7 +15,7 @@ def _log_rescale(baseline, mode="mean"): _check_option( "mode", mode, - ["logratio", "ratio", "zscore", "mean", "percent", "zlogratio"], + ["logratio", "ratio", "zscore", "mean", "percent", "zlogratio", "meanlogratio"], ) msg = f"Applying baseline correction (mode: {mode})" else: @@ -35,21 +35,9 @@ def rescale(data, times, baseline, mode="mean", copy=True, picks=None, verbose=N times : 1D array Time instants is seconds. %(baseline_rescale)s - mode : 'mean' | 'ratio' | 'logratio' | 'percent' | 'zscore' | 'zlogratio' - Perform baseline correction by - - - subtracting the mean of baseline values ('mean') - - dividing by the mean of baseline values ('ratio') - - dividing by the mean of baseline values and taking the log - ('logratio') - - subtracting the mean of baseline values followed by dividing by - the mean of baseline values ('percent') - - subtracting the mean of baseline values and dividing by the - standard deviation of baseline values ('zscore') - - dividing by the mean of baseline values, taking the log, and - dividing by the standard deviation of log baseline values - ('zlogratio') - + %(baseline_mode)s + %(verbose)s + copy : bool Whether to return a new instance or modify in place. picks : list of int | None @@ -113,7 +101,14 @@ def fun(d, m): def fun(d, m): d /= m np.log10(d, out=d) - + + elif mode == "meanlogratio": + + def fun(d, m): + d /= m + np.log10(d, out=d) + d -= np.mean(d[..., imin:imax], axis=-1, keepdims=True) + elif mode == "percent": def fun(d, m): diff --git a/mne/minimum_norm/time_frequency.py b/mne/minimum_norm/time_frequency.py index 00cc4d6fa79..d3c38998ad7 100644 --- a/mne/minimum_norm/time_frequency.py +++ b/mne/minimum_norm/time_frequency.py @@ -219,22 +219,8 @@ def source_band_induced_power( it. If baseline is (a, b) the interval is between "a (s)" and "b (s)". If a is None the beginning of the data is used and if b is None then b is set to the end of the interval. If baseline is equal to (None, None) - all the time interval is used. - baseline_mode : 'mean' | 'ratio' | 'logratio' | 'percent' | 'zscore' | 'zlogratio' - Perform baseline correction by - - - subtracting the mean of baseline values ('mean') - - dividing by the mean of baseline values ('ratio') - - dividing by the mean of baseline values and taking the log - ('logratio') - - subtracting the mean of baseline values followed by dividing by - the mean of baseline values ('percent') - - subtracting the mean of baseline values and dividing by the - standard deviation of baseline values ('zscore') - - dividing by the mean of baseline values, taking the log, and - dividing by the standard deviation of log baseline values - ('zlogratio') - + all the time interval is used. + %(mn_baseline_mode)s pca : bool If True, the true dimension of data is estimated before running the time-frequency transforms. It reduces the computation times @@ -648,21 +634,7 @@ def source_induced_power( and if b is None then b is set to the end of the interval. If baseline is equal to (None, None) all the time interval is used. - baseline_mode : 'mean' | 'ratio' | 'logratio' | 'percent' | 'zscore' | 'zlogratio' - Perform baseline correction by - - - subtracting the mean of baseline values ('mean') - - dividing by the mean of baseline values ('ratio') - - dividing by the mean of baseline values and taking the log - ('logratio') - - subtracting the mean of baseline values followed by dividing by - the mean of baseline values ('percent') - - subtracting the mean of baseline values and dividing by the - standard deviation of baseline values ('zscore') - - dividing by the mean of baseline values, taking the log, and - dividing by the standard deviation of log baseline values - ('zlogratio') - + %(mn_baseline_mode)s pca : bool If True, the true dimension of data is estimated before running the time-frequency transforms. It reduces the computation times diff --git a/mne/time_frequency/tfr.py b/mne/time_frequency/tfr.py index 16c6d0fc85c..8fc87b9463d 100644 --- a/mne/time_frequency/tfr.py +++ b/mne/time_frequency/tfr.py @@ -1792,28 +1792,22 @@ def apply_baseline(self, baseline, mode="mean", verbose=None): ---------- %(baseline_rescale)s - How baseline is computed is determined by the ``mode`` parameter. - mode : 'mean' | 'ratio' | 'logratio' | 'percent' | 'zscore' | 'zlogratio' - Perform baseline correction by - - - subtracting the mean of baseline values ('mean') - - dividing by the mean of baseline values ('ratio') - - dividing by the mean of baseline values and taking the log - ('logratio') - - subtracting the mean of baseline values followed by dividing by - the mean of baseline values ('percent') - - subtracting the mean of baseline values and dividing by the - standard deviation of baseline values ('zscore') - - dividing by the mean of baseline values, taking the log, and - dividing by the standard deviation of log baseline values - ('zlogratio') + How baseline is computed is determined by the ``mode`` parameter. + %(baseline_mode)s + %(verbose)s Returns ------- %(inst_tfr)s The modified instance. + + References + ---------- + .. footbibliography:: + """ + self._baseline = _check_baseline(baseline, times=self.times, sfreq=self.sfreq) rescale(self.data, self.times, self.baseline, mode, copy=False, verbose=verbose) return self @@ -1950,7 +1944,7 @@ def plot( %(baseline_rescale)s How baseline is computed is determined by the ``mode`` parameter. - %(mode_tfr_plot)s + %(baseline_mode)s %(dB_tfr_plot)s %(combine_tfr_plot)s @@ -2216,7 +2210,7 @@ def plot_joint( %(baseline_rescale)s How baseline is computed is determined by the ``mode`` parameter. - %(mode_tfr_plot)s + %(baseline_mode)s %(dB_tfr_plot)s %(yscale_tfr_plot)s %(vlim_tfr_plot_joint)s @@ -2514,7 +2508,7 @@ def plot_topo( %(baseline_rescale)s How baseline is computed is determined by the ``mode`` parameter. - %(mode_tfr_plot)s + %(baseline_mode)s %(tmin_tmax_psd)s %(fmin_fmax_tfr)s %(vmin_vmax_tfr_plot_topo)s diff --git a/mne/utils/docs.py b/mne/utils/docs.py index e9a87d0cd47..b57ccec1d2d 100644 --- a/mne/utils/docs.py +++ b/mne/utils/docs.py @@ -516,6 +516,36 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75): 2. Subtract this mean from the **entire** ``Evoked``. """ +_baseline_mode_desc = """\ + + Perform baseline correction by: + - subtracting the mean of baseline values ('mean') + - dividing by the mean of baseline values ('ratio') + - dividing by the mean of baseline values and taking the log + ('logratio') + - dividing by the mean of baseline values, taking the log and the, + substract the mean (:footcite:`KinleyEtAl2026`) + + .. note:: this baseline mode has not been tested at the source-level! + + - subtracting the mean of baseline values followed by dividing by + the mean of baseline values ('percent') + - subtracting the mean of baseline values and dividing by the + standard deviation of baseline values ('zscore') + - dividing by the mean of baseline values, taking the log, and + dividing by the standard deviation of log baseline values + ('zlogratio') +""" + +docdict["baseline_mode"] = """ + mode : 'mean' | 'ratio' | 'logratio' | 'meanlogratio' | 'percent' | 'zscore' | 'zlogratio' + {_baseline_mode_desc} + +""" +docdict["mn_baseline_mode"] = f""" + baseline_mode : 'mean' | 'ratio' | 'logratio' | 'meanlogratio' | 'percent' | 'zscore' | 'zlogratio' + {_baseline_mode_desc} +""" docdict["baseline_report"] = f"""{_baseline_rescale_base} Correction is applied in the following way **to each channel:** @@ -2817,23 +2847,6 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75): * 'sum' : Sum of PSFs/CTFs across vertices. """ -docdict["mode_tfr_plot"] = """ -mode : 'mean' | 'ratio' | 'logratio' | 'percent' | 'zscore' | 'zlogratio' - Perform baseline correction by - - - subtracting the mean of baseline values ('mean') (default) - - dividing by the mean of baseline values ('ratio') - - dividing by the mean of baseline values and taking the log - ('logratio') - - subtracting the mean of baseline values followed by dividing by - the mean of baseline values ('percent') - - subtracting the mean of baseline values and dividing by the - standard deviation of baseline values ('zscore') - - dividing by the mean of baseline values, taking the log, and - dividing by the standard deviation of log baseline values - ('zlogratio') -""" - docdict["montage"] = """ montage : None | str | DigMontage A montage containing channel positions. If a string or diff --git a/mne/viz/topomap.py b/mne/viz/topomap.py index 75ca4371cb6..c360c3d2e57 100644 --- a/mne/viz/topomap.py +++ b/mne/viz/topomap.py @@ -2065,20 +2065,7 @@ def plot_tfr_topomap( "b (s)". If a is None the beginning of the data is used and if b is None then b is set to the end of the interval. If baseline is equal to (None, None) the whole time interval is used. - mode : 'mean' | 'ratio' | 'logratio' | 'percent' | 'zscore' | 'zlogratio' | None - Perform baseline correction by - - - subtracting the mean baseline power ('mean') - - dividing by the mean baseline power ('ratio') - - dividing by the mean baseline power and taking the log ('logratio') - - subtracting the mean baseline power followed by dividing by the - mean baseline power ('percent') - - subtracting the mean baseline power and dividing by the standard - deviation of the baseline power ('zscore') - - dividing by the mean baseline power, taking the log, and dividing - by the standard deviation of the baseline power ('zlogratio') - - If None no baseline correction is applied. + %(baseline_mode)s %(sensors_topomap)s %(show_names_topomap)s %(mask_evoked_topomap)s From 2cbf1b0e70f6082a254a002bee1db7d04c2f5830 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 14:14:22 +0000 Subject: [PATCH 02/12] [autofix.ci] apply automated fixes --- mne/baseline.py | 18 +++++++++++++----- mne/minimum_norm/time_frequency.py | 4 ++-- mne/time_frequency/tfr.py | 9 ++++----- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/mne/baseline.py b/mne/baseline.py index a1d294df32c..060a6cb88fd 100644 --- a/mne/baseline.py +++ b/mne/baseline.py @@ -15,7 +15,15 @@ def _log_rescale(baseline, mode="mean"): _check_option( "mode", mode, - ["logratio", "ratio", "zscore", "mean", "percent", "zlogratio", "meanlogratio"], + [ + "logratio", + "ratio", + "zscore", + "mean", + "percent", + "zlogratio", + "meanlogratio", + ], ) msg = f"Applying baseline correction (mode: {mode})" else: @@ -37,7 +45,7 @@ def rescale(data, times, baseline, mode="mean", copy=True, picks=None, verbose=N %(baseline_rescale)s %(baseline_mode)s %(verbose)s - + copy : bool Whether to return a new instance or modify in place. picks : list of int | None @@ -101,14 +109,14 @@ def fun(d, m): def fun(d, m): d /= m np.log10(d, out=d) - + elif mode == "meanlogratio": - + def fun(d, m): d /= m np.log10(d, out=d) d -= np.mean(d[..., imin:imax], axis=-1, keepdims=True) - + elif mode == "percent": def fun(d, m): diff --git a/mne/minimum_norm/time_frequency.py b/mne/minimum_norm/time_frequency.py index d3c38998ad7..063d72dc5d9 100644 --- a/mne/minimum_norm/time_frequency.py +++ b/mne/minimum_norm/time_frequency.py @@ -219,8 +219,8 @@ def source_band_induced_power( it. If baseline is (a, b) the interval is between "a (s)" and "b (s)". If a is None the beginning of the data is used and if b is None then b is set to the end of the interval. If baseline is equal to (None, None) - all the time interval is used. - %(mn_baseline_mode)s + all the time interval is used. + %(mn_baseline_mode)s pca : bool If True, the true dimension of data is estimated before running the time-frequency transforms. It reduces the computation times diff --git a/mne/time_frequency/tfr.py b/mne/time_frequency/tfr.py index 8fc87b9463d..98c90a5d9cb 100644 --- a/mne/time_frequency/tfr.py +++ b/mne/time_frequency/tfr.py @@ -1794,20 +1794,19 @@ def apply_baseline(self, baseline, mode="mean", verbose=None): How baseline is computed is determined by the ``mode`` parameter. %(baseline_mode)s - + %(verbose)s Returns ------- %(inst_tfr)s The modified instance. - - References + + References ---------- .. footbibliography:: - + """ - self._baseline = _check_baseline(baseline, times=self.times, sfreq=self.sfreq) rescale(self.data, self.times, self.baseline, mode, copy=False, verbose=verbose) return self From d495a1f5efc3360d0df798bf9d74e5621b695f7f Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Mon, 24 Aug 2026 10:57:07 -0400 Subject: [PATCH 03/12] Apply suggestions from code review Co-authored-by: Eric Larson --- mne/time_frequency/tfr.py | 3 +-- mne/utils/docs.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/mne/time_frequency/tfr.py b/mne/time_frequency/tfr.py index 98c90a5d9cb..2addc381f24 100644 --- a/mne/time_frequency/tfr.py +++ b/mne/time_frequency/tfr.py @@ -1792,7 +1792,7 @@ def apply_baseline(self, baseline, mode="mean", verbose=None): ---------- %(baseline_rescale)s - How baseline is computed is determined by the ``mode`` parameter. + How baseline is computed is determined by the ``mode`` parameter. %(baseline_mode)s %(verbose)s @@ -1805,7 +1805,6 @@ def apply_baseline(self, baseline, mode="mean", verbose=None): References ---------- .. footbibliography:: - """ self._baseline = _check_baseline(baseline, times=self.times, sfreq=self.sfreq) rescale(self.data, self.times, self.baseline, mode, copy=False, verbose=verbose) diff --git a/mne/utils/docs.py b/mne/utils/docs.py index b57ccec1d2d..629541537dc 100644 --- a/mne/utils/docs.py +++ b/mne/utils/docs.py @@ -537,10 +537,9 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75): ('zlogratio') """ -docdict["baseline_mode"] = """ +docdict["baseline_mode"] = f""" mode : 'mean' | 'ratio' | 'logratio' | 'meanlogratio' | 'percent' | 'zscore' | 'zlogratio' {_baseline_mode_desc} - """ docdict["mn_baseline_mode"] = f""" baseline_mode : 'mean' | 'ratio' | 'logratio' | 'meanlogratio' | 'percent' | 'zscore' | 'zlogratio' From 9c473b407568520f70de851d8bdeadac3271aad7 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Mon, 24 Aug 2026 11:01:24 -0400 Subject: [PATCH 04/12] Add meanlogratio baselining mode to apply_baseline Introduced a new baselining mode for EpochsTFR. --- doc/changes/dev/14205.newfeature.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changes/dev/14205.newfeature.rst diff --git a/doc/changes/dev/14205.newfeature.rst b/doc/changes/dev/14205.newfeature.rst new file mode 100644 index 00000000000..74f78033c36 --- /dev/null +++ b/doc/changes/dev/14205.newfeature.rst @@ -0,0 +1 @@ +Added ``meanlogratio`` baselining mode to :meth:`mne.time_frequency.EpochsTFR.apply_baseline` and related functions, by :newcontrib:`Virginie van Wassenhove`. From 4293d174fca91ac118403f1d20e1b6d43f17f9dc Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Mon, 24 Aug 2026 11:01:54 -0400 Subject: [PATCH 05/12] Add Virginie van Wassenhove to names list --- doc/changes/names.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/changes/names.inc b/doc/changes/names.inc index 1fac2d421d2..b2ca48bc775 100644 --- a/doc/changes/names.inc +++ b/doc/changes/names.inc @@ -474,6 +474,7 @@ .. _Victor Férat: https://github.com/vferat .. _Victoria Peterson: https://github.com/vpeterson .. _Vincent Gao: https://github.com/gaoflow +.. _Virginie van Wassenhove: https://brainthemind.com/virginie-van-wassenhove .. _Wei Xu: https://github.com/psyxw .. _Will Turner: https://bootstrapbill.github.io .. _Wouter Kroot: https://github.com/WouterKroot From 31d37296103158776e9536580c2f8f0f1bdd77b1 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Mon, 24 Aug 2026 11:04:30 -0400 Subject: [PATCH 06/12] Add noqa comment for E501 in docs.py Added noqa comment to docstring for line length compliance. --- mne/utils/docs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mne/utils/docs.py b/mne/utils/docs.py index 629541537dc..8aff1375ce1 100644 --- a/mne/utils/docs.py +++ b/mne/utils/docs.py @@ -540,11 +540,11 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75): docdict["baseline_mode"] = f""" mode : 'mean' | 'ratio' | 'logratio' | 'meanlogratio' | 'percent' | 'zscore' | 'zlogratio' {_baseline_mode_desc} -""" +""" # noqa: E501 docdict["mn_baseline_mode"] = f""" baseline_mode : 'mean' | 'ratio' | 'logratio' | 'meanlogratio' | 'percent' | 'zscore' | 'zlogratio' {_baseline_mode_desc} -""" +""" # noqa: E501 docdict["baseline_report"] = f"""{_baseline_rescale_base} Correction is applied in the following way **to each channel:** From b2c599e007d5b1089392f10e167b7fcbcd16ebba Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Mon, 24 Aug 2026 11:06:11 -0400 Subject: [PATCH 07/12] Fix formatting and wording in baseline correction description --- mne/utils/docs.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mne/utils/docs.py b/mne/utils/docs.py index 8aff1375ce1..9ffa0671b0b 100644 --- a/mne/utils/docs.py +++ b/mne/utils/docs.py @@ -517,17 +517,16 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75): """ _baseline_mode_desc = """\ - - Perform baseline correction by: + Perform baseline correction by: + - subtracting the mean of baseline values ('mean') - dividing by the mean of baseline values ('ratio') - dividing by the mean of baseline values and taking the log ('logratio') - - dividing by the mean of baseline values, taking the log and the, - substract the mean (:footcite:`KinleyEtAl2026`) - - .. note:: this baseline mode has not been tested at the source-level! - + - dividing by the mean of baseline values, taking the log and then + subtracting the mean (:footcite:`KinleyEtAl2026`) + + .. note:: this baseline mode has not been tested at the source-level! - subtracting the mean of baseline values followed by dividing by the mean of baseline values ('percent') - subtracting the mean of baseline values and dividing by the From fa0bcb7e6dd1a633983e881915aac44bfb3fd34b Mon Sep 17 00:00:00 2001 From: Virginie van Wassenhove Date: Mon, 24 Aug 2026 17:29:53 +0200 Subject: [PATCH 08/12] added meanlogratio to unit test --- mne/time_frequency/tests/test_tfr.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mne/time_frequency/tests/test_tfr.py b/mne/time_frequency/tests/test_tfr.py index 02e256313eb..b8a10aba8ef 100644 --- a/mne/time_frequency/tests/test_tfr.py +++ b/mne/time_frequency/tests/test_tfr.py @@ -1723,7 +1723,8 @@ def test_tfr_copy(average_tfr): @pytest.mark.parametrize( - "mode", ("mean", "ratio", "logratio", "percent", "zscore", "zlogratio") + "mode", + ("mean", "ratio", "logratio", "meanlogratio", "percent", "zscore", "zlogratio") ) def test_tfr_apply_baseline(average_tfr, mode): """Test TFR baselining.""" From e7b473c8a11e314334b1faef55eafea9028be206 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 15:32:22 +0000 Subject: [PATCH 09/12] [autofix.ci] apply automated fixes --- mne/time_frequency/tests/test_tfr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mne/time_frequency/tests/test_tfr.py b/mne/time_frequency/tests/test_tfr.py index b8a10aba8ef..217a8403e35 100644 --- a/mne/time_frequency/tests/test_tfr.py +++ b/mne/time_frequency/tests/test_tfr.py @@ -1724,7 +1724,7 @@ def test_tfr_copy(average_tfr): @pytest.mark.parametrize( "mode", - ("mean", "ratio", "logratio", "meanlogratio", "percent", "zscore", "zlogratio") + ("mean", "ratio", "logratio", "meanlogratio", "percent", "zscore", "zlogratio"), ) def test_tfr_apply_baseline(average_tfr, mode): """Test TFR baselining.""" From 101dc9fd30cc0d3b55157974b1caabbc4c13429b Mon Sep 17 00:00:00 2001 From: Virginie van Wassenhove Date: Mon, 24 Aug 2026 22:22:59 +0200 Subject: [PATCH 10/12] added baseline modes description --- .../time-freq/20_sensors_time_frequency.py | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tutorials/time-freq/20_sensors_time_frequency.py b/tutorials/time-freq/20_sensors_time_frequency.py index 9175e700041..e2c03d892bd 100644 --- a/tutorials/time-freq/20_sensors_time_frequency.py +++ b/tutorials/time-freq/20_sensors_time_frequency.py @@ -242,6 +242,69 @@ # commented:: # # # power.apply_baseline(baseline=(-0.5, 0), mode='logratio') +# +# +# .. note:: +# Applying a baseline correction to time-frequency results can help +# express post-stimulus oscillatory activity relative to a reference period. +# It facilitates interpreting brain activity evoked or induced by stimuli, and +# reduce the influence of baseline power (e.g. the 1/f temporal structure). +# However, baseline correction is not a noise removal procedure and its +# interpretation depends on assumptions about how baseline (~resting-state) +# activity combines with post-stimulus activity (e.g. additively or multiplicatively). +# Thus, your choice of baseline should be theory- and experiment-driven. +# The baseline should be free of systematic anticipatory, preparatory, or +# sequential effects if it is intended to represent a neutral reference. +# Temporal leakage from the time–frequency transform must also be considered: +# activity after stimulus onset can contaminate estimates immediately +# preceding the stimulus, so the baseline should end sufficiently early. +# +# commented:: +# # MNE-Python provides seven baseline modes: "mean", "ratio", "logratio", +# # "meanlogratio", "percent", "zscore", "zlogratio" +# +# “mean”: subtracts the mean baseline power. It is simple and remains in +# the original power units, making it appropriate when an additive change +# from baseline is of interest. However, values remain frequency- and +# sensor-dependent, so magnitudes are not directly comparable across +# frequencies or sensor types. +# +# “ratio”: expresses power relative to baseline. It is intuitive because values +# indicate relative power (e.g., 1.2 means 20% above baseline), but the resulting +# distribution is typically positively skewed, which can be problematic for +# parametric statistical analyses (Grandchamp & Delorme 2011). +# +# “logratio”: expresses relative power on a log scale (dB). The log transformation +# reduces skewness and make the increase or decrease more symmetric, while providing +# a conveneient scale for comparing relative changes. However, Kinley et al. (2026) +# show that this conventional approach introduces a negative bias, which can make +# unchanged power appear to decrease and understimate genuine increases. Note that +# single-trial correction (on ``EpochsTFR``) is more affected by the logratio bias +# than correction of trial-averaged data (``AverageTFR``), because the bias scales +# with the variance of the quantity being corrected. +# +# #meanlogratio”: provides a logarithmic (dB) interpretation but avoids its negative +# bias by averaging the log-transformed baseline rather than first averaging baseline power. +# It retains the reduced skewness of the logarithmic transformation and ensures that +# the baseline is zero on average. It is therefore preferable to logratio when a +# multiplicative model and a logarithmic representation are desired (Kinley et al. 2026). +# +# "percent”: expresses the percentage change from baseline, making the magnitude +# of relative changes readily interpretable. Like ratio, it is asymmetric and +# typically positively skewed; this can be particularly problematic when normalization +# is performed at the single-trial level. +# +# “zscore”: expresses changes relative to the variability of the baseline, in +# units of baseline standard deviations. This can facilitate comparison across +# frequencies or sensors with different baseline variability, but the resulting +# values depend on the baseline variance and therefore do not directly represent +# absolute or proportional power changes. +# +# “zlogratio”: combines the logarithmic relative-power transformation with +# normalization by baseline variability. It is useful when the question concerns +# how large a relative power change is with respect to baseline variability, but +# shares the interpretational dependence on baseline variance of zscore. + # # Exercise # -------- From ccbf7501507109ba6e0c85ddfed77c2dc5cce8dc Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 20:33:20 +0000 Subject: [PATCH 11/12] [autofix.ci] apply automated fixes --- .../time-freq/20_sensors_time_frequency.py | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/tutorials/time-freq/20_sensors_time_frequency.py b/tutorials/time-freq/20_sensors_time_frequency.py index e2c03d892bd..116b024aa64 100644 --- a/tutorials/time-freq/20_sensors_time_frequency.py +++ b/tutorials/time-freq/20_sensors_time_frequency.py @@ -245,64 +245,64 @@ # # # .. note:: -# Applying a baseline correction to time-frequency results can help -# express post-stimulus oscillatory activity relative to a reference period. -# It facilitates interpreting brain activity evoked or induced by stimuli, and -# reduce the influence of baseline power (e.g. the 1/f temporal structure). -# However, baseline correction is not a noise removal procedure and its -# interpretation depends on assumptions about how baseline (~resting-state) -# activity combines with post-stimulus activity (e.g. additively or multiplicatively). -# Thus, your choice of baseline should be theory- and experiment-driven. -# The baseline should be free of systematic anticipatory, preparatory, or -# sequential effects if it is intended to represent a neutral reference. -# Temporal leakage from the time–frequency transform must also be considered: -# activity after stimulus onset can contaminate estimates immediately -# preceding the stimulus, so the baseline should end sufficiently early. +# Applying a baseline correction to time-frequency results can help +# express post-stimulus oscillatory activity relative to a reference period. +# It facilitates interpreting brain activity evoked or induced by stimuli, and +# reduce the influence of baseline power (e.g. the 1/f temporal structure). +# However, baseline correction is not a noise removal procedure and its +# interpretation depends on assumptions about how baseline (~resting-state) +# activity combines with post-stimulus activity (e.g. additively or multiplicatively). +# Thus, your choice of baseline should be theory- and experiment-driven. +# The baseline should be free of systematic anticipatory, preparatory, or +# sequential effects if it is intended to represent a neutral reference. +# Temporal leakage from the time–frequency transform must also be considered: +# activity after stimulus onset can contaminate estimates immediately +# preceding the stimulus, so the baseline should end sufficiently early. # # commented:: -# # MNE-Python provides seven baseline modes: "mean", "ratio", "logratio", +# # MNE-Python provides seven baseline modes: "mean", "ratio", "logratio", # # "meanlogratio", "percent", "zscore", "zlogratio" # -# “mean”: subtracts the mean baseline power. It is simple and remains in -# the original power units, making it appropriate when an additive change -# from baseline is of interest. However, values remain frequency- and -# sensor-dependent, so magnitudes are not directly comparable across +# “mean”: subtracts the mean baseline power. It is simple and remains in +# the original power units, making it appropriate when an additive change +# from baseline is of interest. However, values remain frequency- and +# sensor-dependent, so magnitudes are not directly comparable across # frequencies or sensor types. # -# “ratio”: expresses power relative to baseline. It is intuitive because values +# “ratio”: expresses power relative to baseline. It is intuitive because values # indicate relative power (e.g., 1.2 means 20% above baseline), but the resulting -# distribution is typically positively skewed, which can be problematic for +# distribution is typically positively skewed, which can be problematic for # parametric statistical analyses (Grandchamp & Delorme 2011). -# +# # “logratio”: expresses relative power on a log scale (dB). The log transformation # reduces skewness and make the increase or decrease more symmetric, while providing # a conveneient scale for comparing relative changes. However, Kinley et al. (2026) -# show that this conventional approach introduces a negative bias, which can make -# unchanged power appear to decrease and understimate genuine increases. Note that -# single-trial correction (on ``EpochsTFR``) is more affected by the logratio bias +# show that this conventional approach introduces a negative bias, which can make +# unchanged power appear to decrease and understimate genuine increases. Note that +# single-trial correction (on ``EpochsTFR``) is more affected by the logratio bias # than correction of trial-averaged data (``AverageTFR``), because the bias scales -# with the variance of the quantity being corrected. +# with the variance of the quantity being corrected. # -# #meanlogratio”: provides a logarithmic (dB) interpretation but avoids its negative -# bias by averaging the log-transformed baseline rather than first averaging baseline power. -# It retains the reduced skewness of the logarithmic transformation and ensures that -# the baseline is zero on average. It is therefore preferable to logratio when a +# #meanlogratio”: provides a logarithmic (dB) interpretation but avoids its negative +# bias by averaging the log-transformed baseline rather than first averaging baseline power. +# It retains the reduced skewness of the logarithmic transformation and ensures that +# the baseline is zero on average. It is therefore preferable to logratio when a # multiplicative model and a logarithmic representation are desired (Kinley et al. 2026). # -# "percent”: expresses the percentage change from baseline, making the magnitude -# of relative changes readily interpretable. Like ratio, it is asymmetric and +# "percent”: expresses the percentage change from baseline, making the magnitude +# of relative changes readily interpretable. Like ratio, it is asymmetric and # typically positively skewed; this can be particularly problematic when normalization # is performed at the single-trial level. # # “zscore”: expresses changes relative to the variability of the baseline, in -# units of baseline standard deviations. This can facilitate comparison across -# frequencies or sensors with different baseline variability, but the resulting -# values depend on the baseline variance and therefore do not directly represent +# units of baseline standard deviations. This can facilitate comparison across +# frequencies or sensors with different baseline variability, but the resulting +# values depend on the baseline variance and therefore do not directly represent # absolute or proportional power changes. # -# “zlogratio”: combines the logarithmic relative-power transformation with -# normalization by baseline variability. It is useful when the question concerns -# how large a relative power change is with respect to baseline variability, but +# “zlogratio”: combines the logarithmic relative-power transformation with +# normalization by baseline variability. It is useful when the question concerns +# how large a relative power change is with respect to baseline variability, but # shares the interpretational dependence on baseline variance of zscore. # From d2c894506727b2906d34a11e397507f1a25bdd03 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Tue, 25 Aug 2026 16:42:03 +0200 Subject: [PATCH 12/12] FIX: Fix reST --- mne/baseline.py | 6 +- mne/minimum_norm/time_frequency.py | 12 +- mne/time_frequency/tfr.py | 1 - mne/utils/docs.py | 57 +++++---- mne/viz/topomap.py | 4 + .../time-freq/20_sensors_time_frequency.py | 116 ++++++++++-------- 6 files changed, 111 insertions(+), 85 deletions(-) diff --git a/mne/baseline.py b/mne/baseline.py index 060a6cb88fd..ec22bafe923 100644 --- a/mne/baseline.py +++ b/mne/baseline.py @@ -44,8 +44,6 @@ def rescale(data, times, baseline, mode="mean", copy=True, picks=None, verbose=N Time instants is seconds. %(baseline_rescale)s %(baseline_mode)s - %(verbose)s - copy : bool Whether to return a new instance or modify in place. picks : list of int | None @@ -56,6 +54,10 @@ def rescale(data, times, baseline, mode="mean", copy=True, picks=None, verbose=N ------- data_scaled: array Array of same shape as data after rescaling. + + References + ---------- + .. footbibliography:: """ if copy: data = data.copy() diff --git a/mne/minimum_norm/time_frequency.py b/mne/minimum_norm/time_frequency.py index 063d72dc5d9..6cf26f6a71e 100644 --- a/mne/minimum_norm/time_frequency.py +++ b/mne/minimum_norm/time_frequency.py @@ -220,7 +220,7 @@ def source_band_induced_power( If a is None the beginning of the data is used and if b is None then b is set to the end of the interval. If baseline is equal to (None, None) all the time interval is used. - %(mn_baseline_mode)s + %(baseline_mode_mn)s pca : bool If True, the true dimension of data is estimated before running the time-frequency transforms. It reduces the computation times @@ -244,6 +244,10 @@ def source_band_induced_power( (n_vertices, n_frequencies, n_samples) if label=None or label=label. For lists of one or more labels, the induced power estimate has shape (n_labels, n_frequencies, n_samples). + + References + ---------- + .. footbibliography:: """ # noqa: E501 _check_option("method", method, INVERSE_METHODS) @@ -634,7 +638,7 @@ def source_induced_power( and if b is None then b is set to the end of the interval. If baseline is equal to (None, None) all the time interval is used. - %(mn_baseline_mode)s + %(baseline_mode_mn)s pca : bool If True, the true dimension of data is estimated before running the time-frequency transforms. It reduces the computation times @@ -664,6 +668,10 @@ def source_induced_power( plv : array The phase-locking value array with shape (n_sources, n_freqs, n_samples). Only returned if ``return_plv=True``. + + References + ---------- + .. footbibliography:: """ # noqa: E501 _check_option("method", method, INVERSE_METHODS) _check_ori(pick_ori, inverse_operator["source_ori"], inverse_operator["src"]) diff --git a/mne/time_frequency/tfr.py b/mne/time_frequency/tfr.py index da5276d3dc9..98e7940c256 100644 --- a/mne/time_frequency/tfr.py +++ b/mne/time_frequency/tfr.py @@ -1794,7 +1794,6 @@ def apply_baseline(self, baseline, mode="mean", verbose=None): How baseline is computed is determined by the ``mode`` parameter. %(baseline_mode)s - %(verbose)s Returns diff --git a/mne/utils/docs.py b/mne/utils/docs.py index 4a2ee8d52fc..6808fa62771 100644 --- a/mne/utils/docs.py +++ b/mne/utils/docs.py @@ -512,33 +512,36 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75): """ _baseline_mode_desc = """\ - Perform baseline correction by: - - - subtracting the mean of baseline values ('mean') - - dividing by the mean of baseline values ('ratio') - - dividing by the mean of baseline values and taking the log - ('logratio') - - dividing by the mean of baseline values, taking the log and then - subtracting the mean (:footcite:`KinleyEtAl2026`) - - .. note:: this baseline mode has not been tested at the source-level! - - subtracting the mean of baseline values followed by dividing by - the mean of baseline values ('percent') - - subtracting the mean of baseline values and dividing by the - standard deviation of baseline values ('zscore') - - dividing by the mean of baseline values, taking the log, and - dividing by the standard deviation of log baseline values - ('zlogratio') -""" - -docdict["baseline_mode"] = f""" - mode : 'mean' | 'ratio' | 'logratio' | 'meanlogratio' | 'percent' | 'zscore' | 'zlogratio' - {_baseline_mode_desc} -""" # noqa: E501 -docdict["mn_baseline_mode"] = f""" - baseline_mode : 'mean' | 'ratio' | 'logratio' | 'meanlogratio' | 'percent' | 'zscore' | 'zlogratio' - {_baseline_mode_desc} -""" # noqa: E501 + Perform baseline correction by: + + ``"mean"`` + Subtracting the mean of baseline values + ``"ratio"`` + Dividing by the mean of baseline values + ``"logratio"`` + Dividing by the mean of baseline values and taking the log + ``"meanlogratio"`` + Dividing by the mean of baseline values, taking the log and then + subtracting the mean (:footcite:`KinleyEtAl2026`) + + .. note:: this baseline mode has not been tested at the source-level! + ``"percent"`` + Subtracting the mean of baseline values followed by dividing by + the mean of baseline values + ``"zscore"`` + Subtracting the mean of baseline values and dividing by the + standard deviation of baseline values + ``"zlogratio"`` + Dividing by the mean of baseline values, taking the log, and + dividing by the standard deviation of log baseline values +""" + +docdict["baseline_mode"] = f"""\ +mode : 'mean' | 'ratio' | 'logratio' | 'meanlogratio' | 'percent' | 'zscore' | 'zlogratio' +{_baseline_mode_desc}""" # noqa: E501 +docdict["baseline_mode_mn"] = f"""\ +baseline_mode : 'mean' | 'ratio' | 'logratio' | 'meanlogratio' | 'percent' | 'zscore' | 'zlogratio' +{_baseline_mode_desc}""" # noqa: E501 docdict["baseline_report"] = f"""{_baseline_rescale_base} Correction is applied in the following way **to each channel:** diff --git a/mne/viz/topomap.py b/mne/viz/topomap.py index c360c3d2e57..e4db37d7231 100644 --- a/mne/viz/topomap.py +++ b/mne/viz/topomap.py @@ -2106,6 +2106,10 @@ def plot_tfr_topomap( ------- fig : matplotlib.figure.Figure The figure containing the topography. + + References + ---------- + .. footbibliography:: """ # noqa: E501 import matplotlib.pyplot as plt diff --git a/tutorials/time-freq/20_sensors_time_frequency.py b/tutorials/time-freq/20_sensors_time_frequency.py index 116b024aa64..f64b92d7dbd 100644 --- a/tutorials/time-freq/20_sensors_time_frequency.py +++ b/tutorials/time-freq/20_sensors_time_frequency.py @@ -244,70 +244,80 @@ # # power.apply_baseline(baseline=(-0.5, 0), mode='logratio') # # -# .. note:: -# Applying a baseline correction to time-frequency results can help -# express post-stimulus oscillatory activity relative to a reference period. -# It facilitates interpreting brain activity evoked or induced by stimuli, and -# reduce the influence of baseline power (e.g. the 1/f temporal structure). -# However, baseline correction is not a noise removal procedure and its -# interpretation depends on assumptions about how baseline (~resting-state) -# activity combines with post-stimulus activity (e.g. additively or multiplicatively). -# Thus, your choice of baseline should be theory- and experiment-driven. -# The baseline should be free of systematic anticipatory, preparatory, or -# sequential effects if it is intended to represent a neutral reference. -# Temporal leakage from the time–frequency transform must also be considered: -# activity after stimulus onset can contaminate estimates immediately -# preceding the stimulus, so the baseline should end sufficiently early. +# Baseline correction considerations +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# Applying a baseline correction to time-frequency results can help +# express post-stimulus oscillatory activity relative to a reference period. +# It facilitates interpreting brain activity evoked or induced by stimuli, and +# reduce the influence of baseline power (e.g. the 1/f temporal structure). +# However, baseline correction is not a noise removal procedure and its +# interpretation depends on assumptions about how baseline (~resting-state) +# activity combines with post-stimulus activity (e.g. additively or multiplicatively). +# Thus, your choice of baseline should be theory- and experiment-driven. +# The baseline should be free of systematic anticipatory, preparatory, or +# sequential effects if it is intended to represent a neutral reference. +# Temporal leakage from the time–frequency transform must also be considered: +# activity after stimulus onset can contaminate estimates immediately +# preceding the stimulus, so the baseline should end sufficiently early. # -# commented:: -# # MNE-Python provides seven baseline modes: "mean", "ratio", "logratio", -# # "meanlogratio", "percent", "zscore", "zlogratio" +# MNE-Python provides multiple baseline modes # -# “mean”: subtracts the mean baseline power. It is simple and remains in -# the original power units, making it appropriate when an additive change -# from baseline is of interest. However, values remain frequency- and -# sensor-dependent, so magnitudes are not directly comparable across -# frequencies or sensor types. +# ``“mean”`` +# Subtracts the mean baseline power. It is simple and remains in +# the original power units, making it appropriate when an additive change +# from baseline is of interest. However, values remain frequency- and +# sensor-dependent, so magnitudes are not directly comparable across +# frequencies or sensor types. # -# “ratio”: expresses power relative to baseline. It is intuitive because values -# indicate relative power (e.g., 1.2 means 20% above baseline), but the resulting -# distribution is typically positively skewed, which can be problematic for -# parametric statistical analyses (Grandchamp & Delorme 2011). +# ``“ratio”`` +# Expresses power relative to baseline. It is intuitive because values +# indicate relative power (e.g., 1.2 means 20% above baseline), but the resulting +# distribution is typically positively skewed, which can be problematic for +# parametric statistical analyses (Grandchamp & Delorme 2011). # -# “logratio”: expresses relative power on a log scale (dB). The log transformation -# reduces skewness and make the increase or decrease more symmetric, while providing -# a conveneient scale for comparing relative changes. However, Kinley et al. (2026) -# show that this conventional approach introduces a negative bias, which can make -# unchanged power appear to decrease and understimate genuine increases. Note that -# single-trial correction (on ``EpochsTFR``) is more affected by the logratio bias -# than correction of trial-averaged data (``AverageTFR``), because the bias scales -# with the variance of the quantity being corrected. +# ``“logratio”`` +# Expresses relative power on a log scale (dB). The log transformation +# reduces skewness and make the increase or decrease more symmetric, while providing +# a conveneient scale for comparing relative changes. However, +# Kinley et al. (2006; :footcite:`KinleyEtAl2026`) +# show that this conventional approach introduces a negative bias, which can make +# unchanged power appear to decrease and understimate genuine increases. Note that +# single-trial correction (on ``EpochsTFR``) is more affected by the logratio bias +# than correction of trial-averaged data (``AverageTFR``), because the bias scales +# with the variance of the quantity being corrected. # -# #meanlogratio”: provides a logarithmic (dB) interpretation but avoids its negative -# bias by averaging the log-transformed baseline rather than first averaging baseline power. -# It retains the reduced skewness of the logarithmic transformation and ensures that -# the baseline is zero on average. It is therefore preferable to logratio when a -# multiplicative model and a logarithmic representation are desired (Kinley et al. 2026). +# ``"meanlogratio”`` +# Provides a logarithmic (dB) interpretation but avoids its negative bias by averaging +# the log-transformed baseline rather than first averaging baseline power. It retains +# the reduced skewness of the logarithmic transformation and ensures that the baseline +# is zero on average. It is therefore preferable to logratio when a multiplicative +# model and a logarithmic representation are desired (Kinley et al. 2026). # -# "percent”: expresses the percentage change from baseline, making the magnitude -# of relative changes readily interpretable. Like ratio, it is asymmetric and -# typically positively skewed; this can be particularly problematic when normalization -# is performed at the single-trial level. +# ``"percent”`` +# Expresses the percentage change from baseline, making the magnitude +# of relative changes readily interpretable. Like ratio, it is asymmetric and +# typically positively skewed; this can be particularly problematic when normalization +# is performed at the single-trial level. # -# “zscore”: expresses changes relative to the variability of the baseline, in -# units of baseline standard deviations. This can facilitate comparison across -# frequencies or sensors with different baseline variability, but the resulting -# values depend on the baseline variance and therefore do not directly represent -# absolute or proportional power changes. +# ``"zscore”`` +# Expresses changes relative to the variability of the baseline, in +# units of baseline standard deviations. This can facilitate comparison across +# frequencies or sensors with different baseline variability, but the resulting +# values depend on the baseline variance and therefore do not directly represent +# absolute or proportional power changes. # -# “zlogratio”: combines the logarithmic relative-power transformation with -# normalization by baseline variability. It is useful when the question concerns -# how large a relative power change is with respect to baseline variability, but -# shares the interpretational dependence on baseline variance of zscore. - +# ``"zlogratio”`` +# Combines the logarithmic relative-power transformation with +# normalization by baseline variability. It is useful when the question concerns +# how large a relative power change is with respect to baseline variability, but +# shares the interpretational dependence on baseline variance of zscore. # # Exercise # -------- # # - Visualize the inter-trial coherence values as topomaps as done with # power. +# +# References +# ---------- +# .. footbibliography::