diff --git a/doc/changes/dev/13447.other.rst b/doc/changes/dev/13447.other.rst new file mode 100644 index 00000000000..50c47167211 --- /dev/null +++ b/doc/changes/dev/13447.other.rst @@ -0,0 +1 @@ +Improve the error message raised by :func:`mne.viz.plot_topomap` when mixed 10–20 EEG electrode naming conventions are detected, by :newcontrib:`Aasma Gupta`. \ No newline at end of file diff --git a/doc/changes/names.inc b/doc/changes/names.inc index b684d067a1d..33df89820ae 100644 --- a/doc/changes/names.inc +++ b/doc/changes/names.inc @@ -1,4 +1,5 @@ .. _Aaron Earle-Richardson: https://github.com/Aaronearlerichardson +.. _Aasma Gupta: https://github.com/AasmaGupta .. _Abram Hindle: https://softwareprocess.es .. _Adam Li: https://github.com/adam2392 .. _Adeline Fecker: https://github.com/adelinefecker diff --git a/mne/channels/layout.py b/mne/channels/layout.py index 85b7913c1c6..0d5f614f60a 100644 --- a/mne/channels/layout.py +++ b/mne/channels/layout.py @@ -971,11 +971,28 @@ def _auto_topomap_coords(info, picks, ignore_overlap, to_sphere, sphere): for elec_i in squareform(dist < 1e-10).any(axis=0).nonzero()[0] ] - raise ValueError( - "The following electrodes have overlapping positions," - " which causes problems during visualization:\n" - + ", ".join(problematic_electrodes) - ) + # Check for duplicate 10-20 channels that are aliases for the same position + LEGACY_TO_MODERN_1020 = {"T3": "T7", "T4": "T8", "T5": "P7", "T6": "P8"} + names = set(problematic_electrodes) + conflicts = { + old: new + for old, new in LEGACY_TO_MODERN_1020.items() + if old in names and new in names + } + if conflicts: + overlap_info = ", ".join(f"{old}/{new}" for old, new in conflicts.items()) + drop_list = ", ".join(repr(old) for old in conflicts) + raise ValueError( + "The following electrodes are aliases for the same physical location " + f"(10-20 vs 10-10): {overlap_info}\n. To fix this call " + f"`.drop_channels([{drop_list}])` on your Raw/Epochs/Evoked object." + ) + + else: + raise ValueError( + "The following electrodes have overlapping positions, which causes " + "problems during visualization:\n" + ", ".join(problematic_electrodes) + ) if to_sphere: # translate to sphere origin, transform/flatten Z, translate back diff --git a/mne/channels/tests/test_layout.py b/mne/channels/tests/test_layout.py index ad44a6873a4..7c818f63762 100644 --- a/mne/channels/tests/test_layout.py +++ b/mne/channels/tests/test_layout.py @@ -15,6 +15,7 @@ assert_equal, ) +import mne from mne import pick_info, pick_types from mne._fiff.constants import FIFF from mne._fiff.meas_info import _empty_info @@ -186,6 +187,24 @@ def test_find_topomap_coords(): _find_topomap_coords(info, picks, **kwargs) +def test_duplicate_1020_electrode_names_error(): + """Ensure mixed 10–20 EEG naming conventions raise a clear error.""" + montage = mne.channels.make_standard_montage("standard_1020") + data = np.random.randn(len(montage.ch_names)) + info = mne.create_info( + ch_names=montage.ch_names, + sfreq=1000, + ch_types="eeg", + ) + info.set_montage(montage) + + with pytest.raises( + ValueError, + match="aliases for the same physical location", + ): + mne.viz.plot_topomap(data, pos=info) + + def test_make_eeg_layout(tmp_path): """Test creation of EEG layout.""" lout_orig = read_layout(fname=lout_path / "test_raw.lout")