Skip to content

Commit 77e2f43

Browse files
Merge branch 'main' into jupyterlite-gh-actions
2 parents 2547160 + d2a7a69 commit 77e2f43

16 files changed

Lines changed: 426 additions & 106 deletions

File tree

doc/api/visualization.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Visualization
1414
:toctree: ../generated/
1515

1616
Brain
17+
LayeredMesh
1718
ClickableImage
1819
EvokedField
1920
Figure3D

doc/changes/dev/13680.other.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Document :attr:`~mne.Annotations.onset`, :attr:`~mne.Annotations.duration`, :attr:`~mne.Annotations.description`, and :attr:`~mne.Annotations.ch_names` attributes of :class:`mne.Annotations`, by `Famous077`_.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added public :class:`mne.viz.LayeredMesh` class (previously private ``_LayeredMesh``) with a ``smooth_mat`` attribute for efficient real-time source-space data streaming. Added ``Brain.layered_meshes`` attribute to access meshes after plotting, and a ``key`` parameter to :meth:`mne.viz.Brain.add_data` for named overlays, by :newcontrib:`Payam Sadeghi-Shabestari`.

doc/changes/names.inc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,10 @@
145145
.. _Jacob Woessner: https://github.com/withmywoessner
146146
.. _Jair Montoya Martinez: https://github.com/jmontoyam
147147
.. _Jan Ebert: https://www.jan-ebert.com/
148+
.. _Jan Mathijs Schoffelen: https://github.com/schoffelen
148149
.. _Jan Sedivy: https://github.com/honzaseda
149150
.. _Jan Sosulski: https://jan-sosulski.de
150151
.. _Jan Zerfowski: https://github.com/jzerfowski
151-
.. _Jan-Mathijs Schoeffelen: https://github.com/schoffelen
152152
.. _Jasper van den Bosch: https://github.com/ilogue
153153
.. _Jean-Baptiste Schiratti: https://github.com/jbschiratti
154154
.. _Jean-Rémi King: https://github.com/kingjr
@@ -267,6 +267,7 @@
267267
.. _Paul Roujansky: https://github.com/paulroujansky
268268
.. _Pavel Navratil: https://github.com/navrpa13
269269
.. _Pavel Popov: https://github.com/paavalipopov
270+
.. _Payam Sadeghi-Shabestari: https://github.com/payamsash
270271
.. _Peter Molfese: https://github.com/pmolfese
271272
.. _Phillip Alday: https://palday.bitbucket.io
272273
.. _Pierre Ablin: https://pierreablin.com

doc/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,8 @@
430430
"polars",
431431
"default",
432432
# unlinkable
433+
"_Renderer",
434+
"n_triangles",
433435
"CoregistrationUI",
434436
"mne_qt_browser.figure.MNEQtBrowser",
435437
# pooch, since its website is unreliable and users will rarely need the links

doc/credits/leaders.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Advisory Board
6767

6868
* `Alex Gramfort`_
6969
* `Bradley Voytek`_
70-
* `Jan-Mathijs Schoeffelen`_
70+
* `Jan Mathijs Schoffelen`_
7171
* `Liberty Hamilton`_
7272
* `Matti Hämäläinen`_
7373
* `Ole Jensen`_

examples/visualization/brain.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,48 @@
136136
fig.suptitle("Dipole Fits Scaled by Amplitude and Colored by GOF")
137137

138138

139+
# %%
140+
# Update overlays via ``Brain.layered_meshes``
141+
# --------------------------------------------
142+
#
143+
# After :meth:`~mne.viz.Brain.add_data` is called, each hemisphere's surface
144+
# is backed by a :class:`~mne.viz.LayeredMesh` stored in
145+
# ``brain.layered_meshes``. Calling
146+
# :meth:`~mne.viz.LayeredMesh.update_overlay` pushes new scalar data without
147+
# rebuilding the full rendering pipeline — the key operation for packages that
148+
# stream source-space data onto the brain in real time, such as
149+
# `MNE-RT <https://payamsash.github.io/mne-rt/>`_.
150+
#
151+
# Here we add an initial bottom-to-top gradient as the first data frame.
152+
153+
brain = mne.viz.Brain("sample", subjects_dir=subjects_dir, hemi="lh", **brain_kwargs)
154+
coords = brain.geo["lh"].coords
155+
data_t0 = coords[:, 2]
156+
data_t0 = (data_t0 - data_t0.min()) / (data_t0.max() - data_t0.min())
157+
brain.add_data(
158+
data_t0, hemi="lh", fmin=0, fmax=1, colormap="viridis", smoothing_steps=5
159+
)
160+
brain.show_view(azimuth=190, elevation=70, distance=350, focalpoint=(0, 0, 20))
161+
162+
# %%
163+
# Simulate a new data frame arriving: call
164+
# :meth:`~mne.viz.LayeredMesh.update_overlay` on the **same** brain to replace
165+
# the scalars in-place — no new mesh, no new actor, no pipeline rebuild.
166+
167+
# we create a new brain here for comparison purposes
168+
brain_update = mne.viz.Brain(
169+
"sample", subjects_dir=subjects_dir, hemi="lh", **brain_kwargs
170+
)
171+
brain_update.add_data(
172+
data_t0, hemi="lh", fmin=0, fmax=1, colormap="viridis", smoothing_steps=5
173+
)
174+
brain_update.show_view(azimuth=190, elevation=70, distance=350, focalpoint=(0, 0, 20))
175+
data_t1 = coords[:, 1]
176+
data_t1 = (data_t1 - data_t1.min()) / (data_t1.max() - data_t1.min())
177+
mesh = brain_update.layered_meshes["lh"]
178+
mesh.update_overlay(name="data", scalars=data_t1)
179+
mesh.update()
180+
139181
# %%
140182
# Use per-vertex opacity for distributed data
141183
# --------------------------------------------

0 commit comments

Comments
 (0)