Skip to content

Instantly share code, notes, and snippets.

@larsoner
Last active February 11, 2026 17:01
Show Gist options
  • Select an option

  • Save larsoner/8a9377d62bd54eed4988bbc3052e400d to your computer and use it in GitHub Desktop.

Select an option

Save larsoner/8a9377d62bd54eed4988bbc3052e400d to your computer and use it in GitHub Desktop.
MagicGUI
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "1b694c73-3e57-412c-a0e8-f6226065943b",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "78adecf45a874866a6aa308d080eec04",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"AppLayout(children=(VBox(children=(Label(value='Time', layout=Layout(width='190px')), FloatSlider(value=0.1, l…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import mne\n",
"mne.viz.set_3d_backend(\"notebook\")\n",
"from magic import *"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a584aa29-5c92-4c46-b13d-6e4ea4892e3c",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "28d22d70-deb8-4d94-9c87-c7e0bfce4986",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
from magicgui import widgets, use_app
import numpy as np
import re
import mne
from matplotlib.figure import Figure
import pyvista
import pyvista.plotting
# native stuff
backend = mne.viz.get_3d_backend()
assert backend in ("pyvistaqt", "notebook"), backend
if backend == "notebook":
use_app("ipynb")
columns = [widgets.Container(layout="vertical", labels=False) for _ in range(2)]
columns[0].extend([
widgets.Label(value="Time"),
widgets.FloatSlider(min=-0.2, max=0.5, value=0.1, step=0.01),
widgets.ComboBox(choices=["lateral", "medial"]),
widgets.Label(value="fmin/fmid/fmax"),
widgets.FloatSlider(min=1, max=3, value=1, step=0.01),
widgets.FloatSlider(min=1, max=3, value=2, step=0.01),
widgets.FloatSlider(min=1, max=3, value=3, step=0.01),
widgets.Container(
widgets=[
widgets.PushButton(text="↺"),
widgets.PushButton(text="+"),
widgets.PushButton(text="-"),
],
layout="horizontal",
labels=False,
),
widgets.Label(value="Annotation"),
widgets.ComboBox(choices=["None", "aparc"]),
widgets.Label(value="Extract mode"),
widgets.ComboBox(choices=["mean", "max"]),
])
# %% Create main window
if backend == "pyvistaqt":
window = widgets.MainWindow(widgets=columns, layout="horizontal")
else:
from ipywidgets import AppLayout
window = AppLayout(
left_sidebar=columns[0].native,
center=columns[1].native,
)
for col in columns:
col.native.layout.height = "100%"
columns[0].native.layout.width = "200px"
for widget in columns[0]:
widget.native.layout.width = "190px"
window.layout.align_items = "center"
window.layout.display = "flex"
window.layout.width = "810px" # 10px buffer
window.layout.height = "610px" # 10px buffer
window.layout.flex_flow = "stretch"
window.layout.border = "1px solid black"
# columns[0].native.layout.border = "1px solid black"
# columns[1].native.layout.border = "1px solid red"
# native stuff
backend = mne.viz.get_3d_backend()
assert backend in ("pyvistaqt", "notebook"), backend
if backend == "pyvistaqt":
columns[0].native.layout().addStretch(1)
# %% PyVista renderer
if backend == "pyvistaqt":
from pyvistaqt import QtInteractor
from qtpy.QtWidgets import QSizePolicy
plotter = QtInteractor(parent=window.native, auto_update=False)
plotter.resize(600, 400)
plotter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
columns[1].native.layout().addWidget(plotter, stretch=2)
else:
plotter = pyvista.plotting.Plotter(
off_screen=True,
notebook=True,
window_size=(600, 400),
)
from pyvista.trame import show_trame
viewer = show_trame(
plotter,
add_menu=False,
# width="100%",
# height="100%",
)
viewer.value = re.sub(
r" style=[\"'](.+)[\"']></iframe>",
# value taken from matplotlib's widget
r" style='\1; border: none;' scrolling='no'></iframe>", # noqa: E501
viewer.value,
)
viewer.layout.height = "400px"
viewer.layout.min_height = "400px"
viewer.layout.width = "600px"
viewer.layout.min_width = "600px"
columns[1].native.children += (viewer,)
grid = pyvista.ImageData(dimensions=(5, 5, 5), origin=(-2, -2, -2)).explode(0.2)
plotter.add_mesh(grid)
# %% matplotlib
dpi = 92
fig = Figure(figsize=(600 / dpi, dpi / 80), dpi=dpi, constrained_layout=True)
ax = fig.subplots()
ax.plot(np.random.RandomState(0).randn(1000))
if backend == "pyvistaqt":
from matplotlib.backends.backend_qt5agg import FigureCanvas
canvas = FigureCanvas(fig)
columns[1].native.layout().addWidget(canvas, stretch=1)
window.show()
else:
import ipympl.backend_nbagg
canvas = ipympl.backend_nbagg.Canvas(fig)
manager = ipympl.backend_nbagg.FigureManager(canvas, 0)
canvas.toolbar_visible = False
canvas.header_visible = False
canvas.footer_visible = False
canvas.layout.height = "200px"
canvas.layout.min_height = "200px"
fig.set_figheight(200 / dpi) # shouldn't be necessary but whatever
fig.set_figwidth(200 / dpi) # shouldn't be necessary but whatever
canvas.layout.min_width = "600px"
canvas.layout.width = "600px"
canvas.resizable = False
columns[1].native.children += (canvas,)
for widget in (window, columns[0].native, columns[1].native, viewer, canvas):
widget.layout.padding = "0 0 0 0px"
widget.layout.margin = "0 0 0 0px"
display(window)
plotter.camera.up = (0., 0., 1.)
plotter.camera.position = (0., -15, 0)
plotter.camera.focal_point = (0., 0., 0.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment