diff --git a/doc/changes/latest.inc b/doc/changes/latest.inc index 2d731c83364..dba8d159b15 100644 --- a/doc/changes/latest.inc +++ b/doc/changes/latest.inc @@ -64,6 +64,7 @@ Bugs - Fix :func:`mne.io.read_raw` for file names containing multiple dots (:gh:`11521` by `Clemens Brunner`_) - Fix bug in :func:`mne.export.export_raw` when exporting to EDF with a physical range set smaller than the data range (:gh:`11569` by `Mathieu Scheltienne`_) - Fix bug in :func:`mne.concatenate_raws` where two raws could not be merged if the order of the bad channel lists did not match (:gh:`11502` by `Moritz Gerster`_) +- Fix bug where :meth:`mne.Evoked.plot_topomap` opened an extra figure (:gh:`11607` by `Alex Rockhill`_) API changes diff --git a/mne/utils/__init__.py b/mne/utils/__init__.py index 0d04c882783..2ceef298cae 100644 --- a/mne/utils/__init__.py +++ b/mne/utils/__init__.py @@ -11,7 +11,7 @@ _check_pandas_index_arguments, _check_event_id, _check_ch_locs, _check_compensation_grade, _check_if_nan, _is_numeric, _ensure_int, _check_preload, - _validate_type, _check_info_inv, + _validate_type, _check_range, _check_info_inv, _check_channels_spatial_filter, _check_one_ch_type, _check_rank, _check_option, _check_depth, _check_combine, _path_like, _check_src_normal, _check_stc_units, diff --git a/mne/utils/check.py b/mne/utils/check.py index cb4459e9e26..780458264c9 100644 --- a/mne/utils/check.py +++ b/mne/utils/check.py @@ -551,6 +551,37 @@ def _validate_type(item, types=None, item_name=None, type_name=None, *, f"got {type(item)} instead.") +def _check_range(val, min_val, max_val, name, min_inclusive=True, + max_inclusive=True): + """Check that item is within range. + + Parameters + ---------- + val : int | float + The value to be checked. + min_val : int | float + The minimum value allowed. + max_val : int | float + The maximum value allowed. + name : str + The name of the value. + min_inclusive : bool + Whether ``val`` is allowed to be ``min_val``. + max_inclusive : bool + Whether ``val`` is allowed to be ``max_val``. + """ + below_min = val < min_val if min_inclusive else val <= min_val + above_max = val > max_val if max_inclusive else val >= max_val + if below_min or above_max: + error_str = f'The value of {name} must be between {min_val} ' + if min_inclusive: + error_str += 'inclusive ' + error_str += f'and {max_val}' + if max_inclusive: + error_str += 'inclusive ' + raise ValueError(error_str) + + def _path_like(item): """Validate that `item` is `path-like`. diff --git a/mne/utils/tests/test_check.py b/mne/utils/tests/test_check.py index 8f28ee7799a..44caa61ba10 100644 --- a/mne/utils/tests/test_check.py +++ b/mne/utils/tests/test_check.py @@ -18,7 +18,8 @@ from mne.utils import (check_random_state, _check_fname, check_fname, _suggest, _check_subject, _check_info_inv, _check_option, Bunch, check_version, _path_like, _validate_type, _on_missing, - _safe_input, _check_ch_locs, _check_sphere) + _safe_input, _check_ch_locs, _check_sphere, + _check_range) data_path = testing.data_path(download=False) base_dir = data_path / "MEG" / "sample" @@ -184,6 +185,15 @@ def test_validate_type(): _validate_type(False, 'int-like') +def test_check_range(): + """Test _check_range.""" + _check_range(10, 1, 100, 'value') + with pytest.raises(ValueError, match='must be between'): + _check_range(0, 1, 10, 'value') + with pytest.raises(ValueError, match='must be between'): + _check_range(1, 1, 10, 'value', False, False) + + @testing.requires_testing_data def test_suggest(): """Test suggestions.""" diff --git a/mne/viz/topomap.py b/mne/viz/topomap.py index be10dbe9502..0db592fe14c 100644 --- a/mne/viz/topomap.py +++ b/mne/viz/topomap.py @@ -908,7 +908,6 @@ def _plot_topomap( border=_BORDER_DEFAULT, res=64, cmap=None, vmin=None, vmax=None, cnorm=None, show=True, onselect=None): from matplotlib.colors import Normalize - import matplotlib.pyplot as plt from matplotlib.widgets import RectangleSelector data = np.asarray(data) logger.debug(f'Plotting topomap for {ch_type} data shape {data.shape}') @@ -1050,7 +1049,7 @@ def _plot_topomap( verticalalignment='center', size='x-small') if not axes.figure.get_constrained_layout(): - plt.subplots_adjust(top=.95) + axes.figure.subplots_adjust(top=.95) if onselect is not None: lim = axes.dataLim