Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changes/dev/13502.newfeature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add ``show_names`` parameter to :func:`mne.viz.plot_alignment` to display channel names in the 3D scene.
34 changes: 33 additions & 1 deletion mne/viz/_3d.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Functions to make 3D plots with M/EEG data."""
z"""Functions to make 3D plots with M/EEG data."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
z"""Functions to make 3D plots with M/EEG data."""
"""Functions to make 3D plots with M/EEG data."""


# Authors: The MNE-Python contributors.
# License: BSD-3-Clause
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -621,6 +622,13 @@ def plot_alignment(
%(seeg)s
%(fnirs)s
.. versionadded:: 0.20

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

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)

Comment on lines +630 to +631
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.. versionadded:: 1.x (The maintainer will finalize the version number)
.. versionadded:: 1.12.0

show_axes : bool
If True (default False), coordinate frame axis indicators will be
shown:
Expand Down Expand Up @@ -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()
Expand Down
25 changes: 25 additions & 0 deletions mne/viz/tests/test_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,31 @@ def test_plot_alignment_ieeg(
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
@pytest.mark.parametrize(
Expand Down
Loading