Figure-ready 3D brain viewer. Pick a transparent template shell, pick an atlas, pick the regions you want highlighted, style them, save the scene for later, and export a high-DPI PNG or a rotating GIF.
![]() Paired subcortical structures under a glass shell (oblique). |
![]() Cortical landmarks with in-scene labels (left lateral). |
![]() 360° rotating GIF exported from the same scene. |
All three are produced by scripts/demo.py.
uv venv --python 3.10 .venv
uv pip install --python .venv/bin/python -e ".[dev]"Or with vanilla pip:
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"Inside the repo:
.venv/bin/python -m ezbvOr from anywhere (once per machine, after pip install -e):
ln -sf "$(pwd)/.venv/bin/ezbv" ~/.local/bin/ezbv
ezbv- Template section: switch between MNI152 and the three fsaverage variants; adjust opacity; hide/show the shell; toggle back-face culling.
- Atlas section: pick an atlas, filter regions, multi-select and click Add (or double-click a region). Use the + button to register a custom NIfTI + labels pair.
- Layers section: each row has a visibility checkbox, color picker, opacity slider, label toggle, and remove (✕). Hidden layers are greyed out and excluded from exports.
- View section: six cardinal view presets plus an oblique.
- File → Open scene… / Save scene… (Ctrl+O / Ctrl+S): persist the full editable scene (active shells, layers, colors, opacities, label toggles, visibility, camera, back-face toggle) as a
*.ezbv.jsonfile and reopen it later. Missing atlases or templates on load produce warnings; everything else restores. - File → Export figure… (or Ctrl+E): choose format (PNG still or animated GIF), width (px), DPI, transparent background. GIF adds rotation axis (vertical / horizontal / roll), total sweep, frame count, and cycle duration.
.venv/bin/python scripts/demo.pyWrites assets/demo_subcortex.png, assets/demo_cortex.png, and assets/demo_rotation.gif — the same images shown in the Examples section above.
.venv/bin/python -m pytest -vThe dropdown ships ~40 built-in atlases grouped by anatomy (Cortex / Subcortex / Cerebellum / Thalamus / White matter / Whole brain / Networks). First-time loads download through nilearn or a pinned external URL; subsequent loads hit the on-disk cache under ~/.cache/ezbv/atlases/.
| id | Source | Regions |
|---|---|---|
harvard_oxford_cort |
nilearn fetch_atlas_harvard_oxford('cort-maxprob-thr25-2mm') |
48 |
destrieux |
nilearn fetch_atlas_destrieux_2009() |
148 gyri/sulci |
juelich |
nilearn fetch_atlas_juelich('maxprob-thr25-2mm') |
62 cytoarchitectonic |
schaefer_{100,200,400,600,1000}_7 |
nilearn fetch_atlas_schaefer_2018 |
100–1000 parcels, 7 nets |
yeo_7, yeo_17 |
nilearn fetch_atlas_yeo_2011 |
7 / 17 networks |
talairach_lobe, talairach_gyrus, talairach_ba |
nilearn fetch_atlas_talairach |
12 / 55 / 48 |
allen_2011_rsn |
nilearn fetch_atlas_allen_2011 |
28 RSNs |
glasser_hcp_mmp1_auto |
figshare 3501911 → HCP-MMP1_on_MNI152_ICBM2009a_nlin.nii.gz |
179 (left hemisphere only) |
glasser_hcp_mmp1 |
manual install (see below) | 360 (bilateral) |
| id | Source | Regions |
|---|---|---|
harvard_oxford_sub |
nilearn fetch_atlas_harvard_oxford('sub-…-thr25-2mm') |
21 |
pauli_2017_det, pauli_2017_prob |
nilearn fetch_atlas_pauli_2017 |
12 / 16 |
melbourne_sub_s{1,2,3,4} |
nitrc Tian 2020 MSA zip | 16 / 32 / 50 / 54 |
| id | Source | Regions |
|---|---|---|
suit_anatom |
github DiedrichsenLab/cerebellar_atlases | 34 lobules (SUIT) |
buckner_cerebellar_7, buckner_cerebellar_17 |
same repo | 7 / 17 networks |
mdtb_10 |
same repo (King 2019) | 10 task domains |
| id | Source | Regions |
|---|---|---|
najdenovska_thalamus |
Zenodo 1405484 (max-prob) | 14 (7 per hemi) |
najdenovska_thalamus_prob |
Zenodo 1405484 (4D probabilistic) | 14 |
| id | Source | Regions |
|---|---|---|
jhu_wm_labels |
NeuroVault 264 — JHU ICBM labels | 48 tracts |
| id | Source | Regions |
|---|---|---|
aal |
nilearn fetch_atlas_aal('SPM12') |
~116 |
basc_{64,122,444}_sym |
nilearn fetch_atlas_basc_multiscale_2015 |
64 / 122 / 444 |
difumo_{64,256,1024} |
nilearn fetch_atlas_difumo |
64 / 256 / 1024 (probabilistic) |
craddock_2012 |
nilearn fetch_atlas_craddock_2012 |
~43 (scorr_mean) |
brainnetome_246 |
github mirror of Fan 2016 BN_Atlas (official LUT) | 246 (210 cortical + 36 subcortical, incl. 6 insular subregions/hemi) |
msdl |
nilearn fetch_atlas_msdl |
39 probabilistic |
smith_2009_rsn_{10,70} |
nilearn fetch_atlas_smith_2009 |
10 / 70 ICA networks |
- AAL and Talairach gyrus/BA and Craddock 2012 upstream hosts (
www.gin.cnrs.fr,www.talairach.org,cluster_roi.projects.nitrc.org) have had intermittent TLS certificate problems. If these fail to download withSSLCertVerificationError, updating your systemca-certificatesusually fixes it. - Glasser auto-download is left-hemisphere only (179 regions). For full bilateral 360-region Glasser, use the manual-install path below.
These require registration, have ambiguous redistribution terms, or aren't in MNI152 volume form — use the + button in the Atlas section to paste a URL or local file after downloading:
- AICHA (384 regions) — Joliot lab / Lead-DBS
- Iglesias hippocampal subfields — FreeSurfer license; tied to FreeSurfer install
- Gordon 2016 (333 cortical parcels) — BALSA (CIFTI surface-only by default)
- Morel thalamus — Zenodo (search "Morel atlas")
- CIT168 (14 subcortical ROIs) — https://osf.io/r2hvk
- Glasser bilateral (360 regions) — place at
~/.cache/ezbv/atlases/glasser/HCP-MMP1_on_MNI152.nii.gzwith aHCP-MMP1_labels.csvalongside (seeglasser_hcp_mmp1entry).
To add your own parcellation (e.g. a more detailed insula atlas), click + next to the atlas dropdown:
- Display name — how it appears in the dropdown (prefixed
Custom: …). - Volume — a local NIfTI path (
.nii/.nii.gz) or an HTTP(S) URL. Must be in MNI152 space to align with the template shells. 4D volumes are auto-detected as probabilistic (one channel per region, thresholded at 0.25 by default for mesh extraction). - Labels (optional) — a CSV/TSV with
index+namecolumns, a JSON dict ({"1": "Insula_anterior", ...}), or a plain text file withindex namelines (FSL LUT style). If omitted, regions are auto-namedLabel Nfrom unique integer values in the volume.
The dialog downloads or copies the files into ~/.cache/ezbv/atlases/custom/<id>/ and writes a small index.json, so your custom atlases persist across sessions. The ✕ button next to the dropdown removes the currently-selected custom atlas (cache files and all).
The Glasser atlas is not bundled with nilearn because of licensing. To enable it:
- Download an MNI152-projected volume version (CC-BY), e.g. from figshare (search "HCP-MMP1 MNI").
- Place the files at:
The CSV must have
~/.cache/ezbv/atlases/glasser/HCP-MMP1_on_MNI152.nii.gz ~/.cache/ezbv/atlases/glasser/HCP-MMP1_labels.csvindex,namecolumns (one row per parcel, integer index matching the volume value). - Restart ezbv. "Glasser HCP-MMP1.0" will then load like any other atlas.
Each template is a glass shell mesh rendered semi-transparent. ROI solids always sit in MNI152 world coords regardless of which template is active — switching templates only changes the enclosing shell, not where the regions are.
| id | Source | Notes |
|---|---|---|
mni152_detailed |
iso-surface of load_mni152_gm_template(resolution=1) at 0.5 |
Default. Detailed cortical gyri visible. Includes subcortical GM so subcortical ROIs still fit inside. |
mni152_brain |
load_mni152_brain_mask() → marching_cubes → smooth |
Simplified brain envelope. Chunkier, no gyri, but fully watertight around every voxel of the brain mask. |
fsaverage_pial |
fetch_surf_fsaverage('fsaverage6').pial_{left,right} |
FreeSurfer pial surface. |
fsaverage_white |
same, white_* |
Grey/white boundary surface. |
fsaverage_inflated |
same, infl_* |
Stylized inflated cortex. LH/RH separated along X with a 20 mm midline gap so the two hemispheres don't overlap. |
Alignment caveat: fsaverage lives in FreeSurfer's MNI305-ish space — ROIs in MNI152 volume space will have mm-scale drift relative to fsaverage shells, mostly visible at the cortical surface. For precise overlay, use mni152_detailed. fsaverage is best for cortical-only figures where stylized aesthetics matter more than mm-level anatomical precision.
Template meshes are cached at ~/.cache/ezbv/templates/{id}_v{N}.vtp — delete to force a rebuild.
File → Save scene… writes an *.ezbv.json file describing everything the user can edit in the GUI:
- Active template shells (id, opacity, visibility)
- Layers (atlas id, label index + display name, color RGB, opacity, label toggle, visibility)
- Back-face culling toggle
- Camera (position, focal point, view-up)
File → Open scene… clears the current scene, re-fetches the referenced atlases & templates, rebuilds meshes from the on-disk cache, restores all state, and syncs the left-panel rows. Missing items (e.g. a custom atlas that was deleted, or a renamed template id) are reported as warnings and the rest of the scene still loads.
The file is plain indented JSON — it's fine to hand-edit colors, opacities, or visibility flags outside the GUI.
Legacy ez_brain_viewer.scene format strings from pre-rename scene files are still accepted on load.
File → Export figure… opens a dialog with two formats:
PNG (still image)
- Width (px) — output pixel width. The off-screen plotter renders at a fixed 1600×1200 base then scales up; Pillow resizes to exactly your target width.
- DPI — metadata only (PNG
pHYschunk). VTK has no concept of DPI; this is what LaTeX / Inkscape / MS Word read to decide physical print size. - Transparent background — on by default; alpha channel is preserved.
Animated GIF (rotating)
- Width (px) — defaults to 1200 px because GIFs balloon in file size with dimensions × frames.
- Axis —
vertical(azimuth spin around the up axis; classic rotating brain),horizontal(elevation pitch), orroll(line-of-sight roll). - Total rotation — sweep angle across the whole clip. 360° gives a seamless loop.
- Frames — number of captured frames. More = smoother motion, larger file.
- Cycle duration — total playback time (seconds) for one full sweep. Per-frame duration =
1000 × duration / framesms. - Loop indefinitely — standard GIF looping flag.
- Background — always solid white. GIF supports only 1-bit palette transparency, which bleeds through any semi-transparent shell; for alpha-correct output, export PNG.
The live viewer window is never resized during export.
- Atlas downloads:
~/.cache/ezbv/atlases/ - Template meshes (pre-computed
.vtp):~/.cache/ezbv/templates/ - ROI meshes (per atlas label,
.vtp):~/.cache/ezbv/meshes/
Safe to delete any of these to force a rebuild.
If you are upgrading from the previous brain_viewer / ez_brain_viewer names, migrate your existing downloads in one command:
mv ~/.cache/ez_brain_viewer ~/.cache/ezbv # or ~/.cache/brain_viewer if you never went through the intermediate nameMIT.



