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/14126.newfeature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add ``source_id`` as an optional parameter in :class:`mne.viz.ui_events.VertexSelect`, by `Lifeng Qiu Lin`_.
22 changes: 16 additions & 6 deletions mne/viz/_brain/_brain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1182,8 +1182,10 @@ def _configure_vertex_time_course(self):
ind = np.unravel_index(
np.argmax(np.abs(use_data), axis=None), use_data.shape
)
vertex_id = vertices[ind[0]]
publish(self, VertexSelect(hemi=hemi, vertex_id=vertex_id))
publish(
self,
VertexSelect(hemi=hemi, vertex_id=vertices[ind[0]], source_id=ind[0]),
)
Comment thread
Gnefil marked this conversation as resolved.

def _configure_picking(self):
# get data for each hemi
Expand Down Expand Up @@ -1457,6 +1459,7 @@ def _on_pick(self, vtk_picker, event):
# shift = np.array(grid.GetOrigin()) + spacing / 2.
# ijk = np.round((pos - shift) / spacing).astype(int)
# vertex_id = np.ravel_multi_index(ijk, shape, order='F')
source_id = idx

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why rename idx -> source_id here and not starting from line 1446?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My intention here is to unify the variable name, is it worth it?

else:
vtk_cell = mesh.GetCell(cell_id)
cell = [
Expand All @@ -1466,7 +1469,12 @@ def _on_pick(self, vtk_picker, event):
vert_pos = mesh.points[cell]
vertex_id = cell[np.argmin(np.linalg.norm(vert_pos - pos, axis=1))]

publish(self, VertexSelect(hemi=hemi, vertex_id=vertex_id))
# retrieve the nearest source_id from the smooth_mat
smooth_mat = self.act_data_smooth[hemi][1]
row = smooth_mat[vertex_id]
source_id = smooth_mat[vertex_id].argmax() if row.nnz else None

publish(self, VertexSelect(hemi=hemi, vertex_id=vertex_id, source_id=source_id))

def _on_time_change(self, event):
"""Respond to a time change UI event."""
Expand Down Expand Up @@ -4050,9 +4058,11 @@ def _update_current_time_idx(self, time_idx):
mesh = self.layered_meshes[hemi]
mesh.smooth_mat = hemi_data.get("smooth_mat")
key_rng = [
-key_data["fmax"]
if key_data["center"] is not None
else key_data["fmin"],
(
-key_data["fmax"]
if key_data["center"] is not None
else key_data["fmin"]
),
key_data["fmax"],
]
if data_key in mesh._overlays:
Expand Down
29 changes: 29 additions & 0 deletions mne/viz/_brain/tests/test_brain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,35 @@ def test_brain_ui_events(renderer_interactive_pyvistaqt, brain_gc):
# Should remain unchanged.
assert_array_equal(brain._data["ctable"][:3, 3], [0, 2, 4])

# Test effect of vertex selection publishing.
events = list()
ui_events.subscribe(brain, "vertex_select", lambda event: events.append(event))

mesh = brain.layered_meshes["lh"]._polydata
faces = brain.geo["lh"].faces
vertices = brain._data["lh"]["vertices"]
smooth_mat = brain.act_data_smooth["lh"][1]

# each for existing and missing source vertex cases
for is_source in (True, False):
mask = np.isin(faces[:, 0], vertices)
# select first vertex satisfying the condition
cell_id = np.where(mask if is_source else ~mask)[0][0]
vertex_id = faces[cell_id, 0]
# make the selection
n_events = len(events)
brain._on_pick(TstVTKPicker(mesh, cell_id, "lh", brain), None)
assert len(events) == n_events + 1
event = events[-1]
assert event.vertex_id == vertex_id
row = smooth_mat[vertex_id, :]
if is_source:
assert event.source_id == row.argmax()
assert vertices[event.source_id] == event.vertex_id
else:
assert row.sum() == 0
assert event.source_id is None

brain.close()


Expand Down
7 changes: 7 additions & 0 deletions mne/viz/ui_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ class VertexSelect(UIEvent):
Can be ``"lh"``, ``"rh"``, or ``"vol"``.
vertex_id : int
The vertex number (in the high resolution mesh) that was selected.
source_id : int | None
The index number of the closest source point to the vertex.
Only set if the publishing figure contains a source estimate.

Attributes
----------
Expand All @@ -176,10 +179,14 @@ class VertexSelect(UIEvent):
Can be ``"lh"``, ``"rh"``, or ``"vol"``.
vertex_id : int
The vertex number (in the high resolution mesh) that was selected.
source_id : int | None
The index number of the closest source point to the vertex.
Only set if the publishing figure contains a source estimate.
"""

hemi: str
vertex_id: int
source_id: int = None


@dataclass
Expand Down
Loading