diff --git a/doc/changes/latest.inc b/doc/changes/latest.inc index 0a46a969e1b..dcf028dfa78 100644 --- a/doc/changes/latest.inc +++ b/doc/changes/latest.inc @@ -55,6 +55,8 @@ Enhancements - Add :func:`mne.preprocessing.interpolate_bridged_electrodes` to use the spatially smeared signal to get a better interpolation rather than dropping those channels (:gh:`10587` by `Alex Rockhill`_) +- :func:`mne.viz.plot_evoked_topomap` and :meth:`mne.Evoked.plot_topomap` now display the time range the map was averaged over if ``average`` was passed (:gh:`10606` by `Richard Höchenberger`_) + Bugs ~~~~ - Make ``color`` parameter check in in :func:`mne.viz.plot_evoked_topo` consistent (:gh:`10217` by :newcontrib:`T. Wang` and `Stefan Appelhoff`_) diff --git a/mne/utils/docs.py b/mne/utils/docs.py index 017f02029b6..0331d28e3d2 100644 --- a/mne/utils/docs.py +++ b/mne/utils/docs.py @@ -235,10 +235,11 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75): docdict['average_topomap'] = """ average : float | None - The time window around a given time to be used for averaging (seconds). - For example, 0.01 would translate into window that starts 5 ms before - and ends 5 ms after a given time point. Defaults to None, which means - no averaging. + The time window (in seconds) around a given time point to be used for + averaging. For example, 0.2 would translate into a time window that starts + 0.1 s before and ends 0.1 s after the given time point. If the time window + exceeds the duration of the data, it will be clipped. If ``None`` + (default), no averaging will take place. """ docdict['axes_psd_topo'] = """ diff --git a/mne/viz/tests/test_topomap.py b/mne/viz/tests/test_topomap.py index 67392cc8733..46427934d33 100644 --- a/mne/viz/tests/test_topomap.py +++ b/mne/viz/tests/test_topomap.py @@ -333,6 +333,20 @@ def get_texts(p): assert_equal(texts[0], 'Custom') plt.close('all') + # Test averaging + averaging_times = [ev_bad.times[0], times[0], ev_bad.times[-1]] + p = plt_topomap(averaging_times, ch_type='eeg', average=0.01) + + expected_ax_titles = ( + '-0.200 – -0.195 s', # clipped on the left + '0.095 – 0.105 s', # full range + '0.494 – 0.499 s' # clipped on the right + ) + for idx, expected_title in enumerate(expected_ax_titles): + assert p.axes[idx].get_title() == expected_title + + del averaging_times, expected_ax_titles, expected_title + # delaunay triangulation warning plt_topomap(times, ch_type='mag') # projs have already been applied diff --git a/mne/viz/topomap.py b/mne/viz/topomap.py index 966d168c864..5c8d33e103d 100644 --- a/mne/viz/topomap.py +++ b/mne/viz/topomap.py @@ -1708,6 +1708,7 @@ def plot_evoked_topomap(evoked, times="auto", ch_type=None, for t in times] # do averaging if requested avg_err = '"average" must be `None` or a positive number of seconds' + averaged_times = [] if average is None: data = data[np.ix_(picks, time_idx)] elif not _is_numeric(average): @@ -1723,6 +1724,7 @@ def plot_evoked_topomap(evoked, times="auto", ch_type=None, iter_times + ave_time)): my_range = (tmin_ < evoked.times) & (evoked.times < tmax_) data_[:, ii] = data[picks][:, my_range].mean(-1) + averaged_times.append(evoked.times[my_range]) data = data_ # apply scalings and merge channels data *= scaling @@ -1767,7 +1769,16 @@ def plot_evoked_topomap(evoked, times="auto", ch_type=None, if cn is not None: contours_.append(cn) if time_format != '': - axes[ax_idx].set_title(time_format % (time * scaling_time)) + if average is None: + axes_title = time_format % (time * scaling_time) + else: + tmin_, tmax_ = averaged_times[idx][0], averaged_times[idx][-1] + from_time = time_format % (tmin_ * scaling_time) + from_time = from_time.split(' ')[0] # Remove unit + to_time = time_format % (tmax_ * scaling_time) + axes_title = f'{from_time} – {to_time}' + del from_time, to_time, tmin_, tmax_ + axes[ax_idx].set_title(axes_title) if interactive: axes.append(plt.subplot(gs[1, :-1]))