From 985c76f492ea6d27f1613f1fdc8626083ba63f3f Mon Sep 17 00:00:00 2001 From: mohit malpote Date: Sat, 22 Nov 2025 11:35:49 +0530 Subject: [PATCH 1/2] ENH: Add channel names to plot_alignment (#13502) --- doc/changes/dev/13502.newfeature.rst | 1 + mne/viz/_3d.py | 34 +++++++++++++++++++++++++++- mne/viz/tests/test_3d.py | 23 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 doc/changes/dev/13502.newfeature.rst diff --git a/doc/changes/dev/13502.newfeature.rst b/doc/changes/dev/13502.newfeature.rst new file mode 100644 index 00000000000..8ca57c6b4b0 --- /dev/null +++ b/doc/changes/dev/13502.newfeature.rst @@ -0,0 +1 @@ +Add ``show_names`` parameter to :func:`mne.viz.plot_alignment` to display channel names in the 3D scene. diff --git a/mne/viz/_3d.py b/mne/viz/_3d.py index cc660fe4986..0f48779bcb9 100644 --- a/mne/viz/_3d.py +++ b/mne/viz/_3d.py @@ -1,4 +1,4 @@ -"""Functions to make 3D plots with M/EEG data.""" +z"""Functions to make 3D plots with M/EEG data.""" # Authors: The MNE-Python contributors. # License: BSD-3-Clause @@ -554,6 +554,7 @@ def plot_alignment( sensor_colors=None, *, sensor_scales=None, + show_names=False, verbose=None, ): """Plot head, sensor, and source space alignment in 3D. @@ -621,6 +622,13 @@ def plot_alignment( %(seeg)s %(fnirs)s .. versionadded:: 0.20 + + show_names : bool + If True (default False), plot the name of each channel near its + location in the 3D scene. + + .. versionadded:: 1.x (The maintainer will finalize the version number) + show_axes : bool If True (default False), coordinate frame axis indicators will be shown: @@ -941,6 +949,30 @@ def plot_alignment( sensor_colors=sensor_colors, sensor_scales=sensor_scales, ) + + if show_names is True and info is not None: + for ch_type in ['mag', 'grad', 'eeg', 'ecog', 'seeg', 'dbs']: + picks = pick_types(info, **{ch_type: True, 'ref_meg': ch_type == 'meg'}) + + if len(picks) > 0: + ch_pos = np.array([info['chs'][k]['loc'][:3] for k in picks]) + ch_names = [info['ch_names'][k] for k in picks] + ch_coord_frame = info['chs'][picks[0]]['coord_frame'] + trans = to_cf_t[_frame_to_str[ch_coord_frame]] + + ch_pos = apply_trans(trans, ch_pos) + + scale = 0.003 + + for pos, name in zip(ch_pos, ch_names): + renderer.text3d( + x=pos[0], + y=pos[1], + z=pos[2], + text=name, + scale=scale, + color='gray' + ) if src is not None: atlas_ids, colors = read_freesurfer_lut() diff --git a/mne/viz/tests/test_3d.py b/mne/viz/tests/test_3d.py index ab24e6a70db..29592cbd463 100644 --- a/mne/viz/tests/test_3d.py +++ b/mne/viz/tests/test_3d.py @@ -439,6 +439,29 @@ def test_plot_alignment_ieeg( assert isinstance(fig, Figure3D) renderer.backend._close_all() +@testing.requires_testing_data +def test_plot_alignment_show_names(raw): + """Test that channel names are correctly added in plot_alignment (#13502).""" + info = raw.info + + fig = plot_alignment( + info, + eeg='sensors', + show_names=True, + show=False, + trans='fsaverage', + subject='fsaverage', + subjects_dir=testing.data_path() / "subjects" + ) + + n_text_actors = sum( + 1 for actor in fig.plotter.actors.values() if 'Label' in actor.name + ) + + # Assert presence of labels (e.g., more than 10) + assert n_text_actors > 10 + + fig.close() @pytest.mark.slowtest # Slow on Azure @testing.requires_testing_data # all use trans + head surf From cab4d8163bda8ec1bff1ed35c3df1da2e8c02056 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 22 Nov 2025 06:10:02 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mne/viz/tests/test_3d.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/mne/viz/tests/test_3d.py b/mne/viz/tests/test_3d.py index 29592cbd463..54a4c6fca90 100644 --- a/mne/viz/tests/test_3d.py +++ b/mne/viz/tests/test_3d.py @@ -439,30 +439,32 @@ def test_plot_alignment_ieeg( assert isinstance(fig, Figure3D) renderer.backend._close_all() + @testing.requires_testing_data def test_plot_alignment_show_names(raw): """Test that channel names are correctly added in plot_alignment (#13502).""" - info = raw.info - + info = raw.info + fig = plot_alignment( info, - eeg='sensors', - show_names=True, + eeg="sensors", + show_names=True, show=False, - trans='fsaverage', - subject='fsaverage', - subjects_dir=testing.data_path() / "subjects" + trans="fsaverage", + subject="fsaverage", + subjects_dir=testing.data_path() / "subjects", ) - + n_text_actors = sum( - 1 for actor in fig.plotter.actors.values() if 'Label' in actor.name + 1 for actor in fig.plotter.actors.values() if "Label" in actor.name ) - + # Assert presence of labels (e.g., more than 10) - assert n_text_actors > 10 - + assert n_text_actors > 10 + fig.close() + @pytest.mark.slowtest # Slow on Azure @testing.requires_testing_data # all use trans + head surf @pytest.mark.parametrize(