Skip to content

Commit

Permalink
Fix lingering topomap api (#11371)
Browse files Browse the repository at this point in the history
  • Loading branch information
drammock committed Dec 17, 2022
1 parent 66fdc9f commit 715e979
Show file tree
Hide file tree
Showing 10 changed files with 387 additions and 294 deletions.
4 changes: 4 additions & 0 deletions doc/changes/latest.inc
Expand Up @@ -66,3 +66,7 @@ Bugs
API changes
~~~~~~~~~~~
- In :func:`mne.time_frequency.dpss_windows`, interpolating is deprecated (nowadays SciPy's computations are fast enough for large ``N`` without interpolation). This affects parameters ``interp_from`` and ``interp_kind``. Two new parameters of the underlying SciPy :func:`~scipy.signal.windows.dpss` function are also exposed: ``sym`` (for choosing symmetric vs. periodic windows) and ``norm`` (window normalization method). (:gh:`11293` by `Daniel McCloy`_)
- In :meth:`mne.decoding.CSP.plot_patterns`, :meth:`mne.decoding.CSP.plot_filters`, :meth:`mne.preprocessing.ICA.plot_components`, and :func:`mne.viz.plot_ica_components`, the parameters ``vmin`` and ``vmax`` are deprecated in favor of ``vlim``, for consistency with other topomap-plotting functions and methods (:gh:`11371` by `Daniel McCloy`_)
- In :meth:`mne.decoding.CSP.plot_patterns` and :meth:`mne.decoding.CSP.plot_filters` the ``title`` parameter is deprecated and will be removed in version 1.4 (:gh:`11371` by `Daniel McCloy`_)
- The APIs of :meth:`mne.preprocessing.ICA.plot_components` and :func:`mne.viz.plot_ica_components` gained new parameters ``show_names``, ``extrapolate``, ``border``, ``size``, ``cnorm``, ``cbar_fmt``, ``axes``, ``nrows``, ``ncols``, for consistency with other topomap-plotting functions and methods (:gh:`11371` by `Daniel McCloy`_)
- The APIs of :meth:`mne.decoding.CSP.plot_patterns` and :meth:`mne.decoding.CSP.plot_filters` gained new parameters ``extrapolate``, ``border``, ``cnorm``, ``axes``, ``nrows``, ``ncols``, for consistency with other topomap-plotting functions and methods (:gh:`11371` by `Daniel McCloy`_)
320 changes: 146 additions & 174 deletions mne/decoding/csp.py

Large diffs are not rendered by default.

39 changes: 20 additions & 19 deletions mne/preprocessing/ica.py
Expand Up @@ -2182,24 +2182,25 @@ def copy(self):
return deepcopy(self)

@copy_function_doc_to_method_doc(plot_ica_components)
def plot_components(self, picks=None, ch_type=None, res=64,
vmin=None, vmax=None, cmap='RdBu_r', sensors=True,
colorbar=False, title=None, show=True, outlines='head',
contours=6, image_interp=_INTERPOLATION_DEFAULT,
inst=None, plot_std=True,
topomap_args=None, image_args=None, psd_args=None,
reject='auto', sphere=None, verbose=None):
return plot_ica_components(self, picks=picks, ch_type=ch_type,
res=res, vmin=vmin,
vmax=vmax, cmap=cmap, sensors=sensors,
colorbar=colorbar, title=title, show=show,
outlines=outlines, contours=contours,
image_interp=image_interp,
inst=inst, plot_std=plot_std,
topomap_args=topomap_args,
image_args=image_args, psd_args=psd_args,
reject=reject, sphere=sphere,
verbose=verbose)
def plot_components(
self, picks=None, ch_type=None, *, inst=None, plot_std=True,
reject='auto', sensors=True, show_names=False, contours=6,
outlines='head', sphere=None, image_interp=_INTERPOLATION_DEFAULT,
extrapolate=_EXTRAPOLATE_DEFAULT, border=_BORDER_DEFAULT, res=64,
size=1, cmap='RdBu_r', vlim=(None, None), vmin=None, vmax=None,
cnorm=None, colorbar=False, cbar_fmt='%3.2f', axes=None,
title=None, nrows='auto', ncols='auto', show=True,
topomap_args=None, image_args=None, psd_args=None, verbose=None):
return plot_ica_components(
self, picks=picks, ch_type=ch_type, inst=inst, plot_std=plot_std,
reject=reject, sensors=sensors, show_names=show_names,
contours=contours, outlines=outlines, sphere=sphere,
image_interp=image_interp, extrapolate=extrapolate, border=border,
res=res, size=size, cmap=cmap, vlim=vlim, vmin=vmin, vmax=vmax,
cnorm=cnorm, colorbar=colorbar, cbar_fmt=cbar_fmt, axes=axes,
title=title, nrows=nrows, ncols=ncols, show=show,
topomap_args=topomap_args, image_args=image_args,
psd_args=psd_args, verbose=verbose)

@copy_function_doc_to_method_doc(plot_ica_properties)
def plot_properties(self, inst, picks=None, axes=None, dB=True,
Expand Down Expand Up @@ -2893,7 +2894,7 @@ def corrmap(icas, template, threshold="auto", label=None, ch_type="eeg", *,
template_fig = icas[template[0]].plot_components(
picks=template[1], ch_type=ch_type, title=ttl,
outlines=outlines, cmap=cmap, contours=contours,
show=show, topomap_args=dict(sphere=sphere))
show=show, sphere=sphere)
else: # plotting an array
template_fig = _plot_corrmap(
[template], [0], [0], ch_type, icas[0].copy(), "Template",
Expand Down
38 changes: 35 additions & 3 deletions mne/utils/docs.py
Expand Up @@ -219,6 +219,20 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75):
Freesurfer subject directory.
"""

docdict['average_plot_evoked_topomap'] = """
average : float | array-like of float, shape (n_times,) | None
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.
Different time windows (one per time point) can be provided by
passing an ``array-like`` object (e.g., ``[0.1, 0.2, 0.3]``). If
``None`` (default), no averaging will take place.
.. versionchanged:: 1.1
Support for ``array-like`` input.
"""

docdict['average_plot_psd'] = """\
average : bool
If False, the PSDs of all channels is displayed. No averaging
Expand Down Expand Up @@ -2241,6 +2255,24 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75):
a power-of-two size (can be much faster).
"""

docdict['nrows_ncols_ica_components'] = """
nrows, ncols : int | 'auto'
The number of rows and columns of topographies to plot. If both ``nrows``
and ``ncols`` are ``'auto'``, will plot up to 20 components in a 5×4 grid,
and return multiple figures if more than 20 components are requested.
If one is ``'auto'`` and the other a scalar, a single figure is generated.
If scalars are provided for both arguments, will plot up to ``nrows*ncols``
components in a grid and return multiple figures as needed. Default is
``nrows='auto', ncols='auto'``.
"""

docdict['nrows_ncols_topomap'] = """
nrows, ncols : int | 'auto'
The number of rows and columns of topographies to plot. If either ``nrows``
or ``ncols`` is ``'auto'``, the necessary number will be inferred. Defaults
to ``nrows=1, ncols='auto'``.
"""

# %%
# O

Expand Down Expand Up @@ -3769,9 +3801,9 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75):

_units = """
units : {}str | None
The units of the channel type; used for the colorbar label. Ignored if
``colorbar=False``. If ``None`` {}the label will be "AU" indicating
arbitrary units. Default is ``None``.
The units to use for the colorbar label. Ignored if ``colorbar=False``.
If ``None`` {}the label will be "AU" indicating arbitrary units.
Default is ``None``.
"""
docdict['units_topomap'] = _units.format('', '')
docdict['units_topomap_evoked'] = _units.format(
Expand Down
2 changes: 1 addition & 1 deletion mne/viz/tests/test_ica.py
Expand Up @@ -147,7 +147,7 @@ def test_plot_ica_properties():
assert 'extrapolation mode local to mean' in log, log
ica.plot_properties(epochs, picks=1, dB=False, plot_std=1.5, **topoargs)
fig = ica.plot_properties(epochs, picks=1, image_args={'sigma': 1.5},
topomap_args={'res': 4, 'colorbar': True},
topomap_args=dict(res=4, colorbar=True),
psd_args={'fmax': 65.}, plot_std=False,
log_scale=True, figsize=[4.5, 4.5],
reject=reject)[0]
Expand Down
25 changes: 24 additions & 1 deletion mne/viz/tests/test_topomap.py
Expand Up @@ -38,7 +38,6 @@
_fake_scroll)
from mne.utils import requires_sklearn, check_version


data_dir = testing.data_path(download=False)
subjects_dir = op.join(data_dir, 'subjects')
ecg_fname = op.join(data_dir, 'MEG', 'sample', 'sample_audvis_ecg-proj.fif')
Expand Down Expand Up @@ -229,6 +228,30 @@ def test_plot_evoked_topomap_errors(evoked, monkeypatch):
evoked.plot_topomap()


@pytest.mark.parametrize('units, scalings, expected_unit', [
(None, None, 'µV'),
('foo', None, 'foo'),
(None, 7., 'AU'), # non-default scaling → "AU"
])
def test_plot_evoked_topomap_units(evoked, units, scalings, expected_unit):
"""Test that colorbar units respect scalings correctly."""
evoked.pick(['EEG 001', 'EEG 002', 'EEG 003'])
fig = evoked.plot_topomap(times=0.1, res=8, contours=0, sensors=False,
units=units, scalings=scalings)
# ideally we'd do this:
# cbar = [ax for ax in fig.axes if hasattr(ax, '_colorbar')]
# assert len(cbar) == 1
# cbar = cbar[0]
# assert cbar.get_title() == expected_unit
# ...but not all matplotlib versions support it, and we can't use
# @requires_version because it's hard figure out exactly which MPL version
# is the cutoff since it relies on a private attribute. So for now we just
# do this:
for ax in fig.axes:
if hasattr(ax, '_colorbar'):
assert ax.get_title() == expected_unit


@pytest.mark.parametrize('extrapolate', ('box', 'local', 'head'))
def test_plot_evoked_topomap_extrapolation(evoked, extrapolate):
"""Test topomap extrapolation options."""
Expand Down

0 comments on commit 715e979

Please sign in to comment.