Neuroviewer
A freeview-like neuroimaging viewer written in pure Python.
PySide6 interface, vedo/VTK rendering, nibabel reading. Native desktop app, no browser, no server.
Install
pip install neuroviewer # core viewer
pip install "neuroviewer[open3d]" # + Open3D point-cloud tools
Then:
neuroviewer # empty window
neuroviewer T1.mgz aseg.mgz lh.pial # open files at start
python -m neuroviewer # same thing
neuroviewer --install-desktop # Linux: add a menu entry with icon
Requirements: Python 3.9+, an OpenGL-capable display. On Linux, Qt 6.5+
needs libxcb-cursor0 (sudo apt install libxcb-cursor0). A self-contained
Linux AppImage is attached to each GitHub release.
What it does
- Files (left): folder tree filtered to neuroimaging files, plus a
recursive search under the root folder (name filter such as
aseg,*T1*.nii.gz; blank = everything). Double click opens a file. - Views (centre): one main view and three side views (layout
1+3,2x2or1x1). Click a panel title, a toolbar button orCtrl+1..4to put 3D / sagittal / coronal / axial in the main position. - Layers (right): one entry per volume, top of the list drawn on top. Colormap, window min/max, opacity, "transparent below min", frame (4D).
- 3D scene (right, second tab): slices / bounding box / volume rendering toggles, the Tools menu and the list of 3D objects (surfaces, streamlines, isosurfaces, point clouds) with visibility, colour, opacity.
- Time course (bottom): signal of the active 4D layer at the cursor.
- Status bar: cursor in RAS mm, voxel index and value of every visible layer (with the FreeSurfer label name for label maps).
Mouse and keys
| where | action |
|---|---|
| 2D | left click / drag: move cursor; shift+left or middle drag: pan; right drag or wheel: zoom |
| 2D | Up / PageUp, Down / PageDown: next / previous slice; r: fit slice |
| 3D | left drag: rotate; middle: pan; right / wheel: zoom; double click on a slice or surface: move cursor; r: reset camera |
Formats
- Volumes:
.nii,.nii.gz,.mgz,.mgh, Analyze.img/.hdr, MINC.mnc, PAR/REC. - Surfaces: FreeSurfer
lh.pial,rh.white, ... (shifted to scanner RAS withc_ras) and GIfTI.surf.gii. - Streamlines:
.trk,.tck(direction-coloured, subsampled toTRACT_MAX_STREAMLINES).
Coordinates
Everything is kept in world coordinates (scanner RAS, mm). Volumes are
reoriented to RAS+ voxel order on load (FreeSurfer conformed .mgz is LIA on
disk) and keep their full affine. The first loaded volume defines the display
grid; every other layer is sampled onto it through its own affine, so layers
with different resolutions or fields of view overlay correctly. Oblique
volumes are resampled for display.
Label maps are detected by file name (aseg, aparc, ribbon, ...) plus
integer values. Their colours come from $FREESURFER_HOME/FreeSurferColorLUT.txt
(or FREESURFER_LUT_PATH in the config), with generated colours as fallback.
Configuration
The packaged defaults live in neuroviewer/config.py. Do not edit that copy;
create your own once and edit it:
neuroviewer --write-config # writes ~/.config/neuroviewer/config.py (Linux/macOS)
neuroviewer --config-path # shows where it is (%APPDATA%\neuroviewer on Windows)
It is plain Python with the same names (radiological convention, colours,
layout, label hints, point-cloud size, Open3D parameters, screenshot scale,
...). Keep only the lines you change. Set NEUROVIEWER_CONFIG to use another
file. An existing file is never overwritten unless you pass --force.
Tools (extension point)
neuroviewer/tools.py holds a registry. A tool is one function that receives
a context (layers, active layer, cursor, grid, dialogs) and returns 3D objects:
from neuroviewer.tools import register_tool
@register_tool("My tool", "What it does.")
def my_tool(ctx):
layer = ctx.require_active()
arr, origin, spacing = ctx.aligned(layer)
...
return [("result name", vedo_object, "mesh")]
Built-in tools: isosurface, label surfaces (e.g. 17 53), cortex point cloud
from FreeSurfer labels, threshold point cloud, point cloud from the last
surface, Open3D voxel downsampling and Open3D Poisson reconstruction. Open3D
is optional; it is used as a compute engine and the result is shown in vedo.
Troubleshooting
Could not find the Qt platform plugin "xcb": another Qt install is exporting its own plugin path (Spyder/PyQt5, opencv-python, conda qt). Neuroviewer resets it to the PySide6 plugins and prints the folder it used ([qt] ...). Start it from a terminal, not from the Spyder/IPython console. If it still fails, runQT_DEBUG_PLUGINS=1 neuroviewer.- Black views on Wayland:
QT_QPA_PLATFORM=xcb neuroviewer. - Missing
libxcb-cursor0(Qt 6.5+ on Linux): install it with your package manager.
Development
git clone https://github.com/rdneuro/neuroviewer.git
cd neuroviewer
pip install -e ".[dev]"
pytest
See RELEASING.md for the PyPI and AppImage release steps.
License
MIT. See LICENSE. Neuroviewer depends on PySide6 (LGPLv3), VTK (BSD), vedo (MIT), nibabel (MIT) and matplotlib (PSF-based); the AppImage redistributes them under their own licenses.
Metadata
Release files for neuroviewer 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| neuroviewer-0.1.0.tar.gz | 73.4 kB | With provenance | Details for neuroviewer-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| neuroviewer-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for neuroviewer-0.1.0-py3-none-any.whl |
Total release size: 143.1 kB
Release files / neuroviewer-0.1.0.tar.gz
| Download URL | neuroviewer-0.1.0.tar.gz |
|---|---|
| Size | 73.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6d810a1ac81a82f2b51e7710450193807a3598085e0613024d7df569e6677468
|
|
BLAKE2b-256 checksum How to use checksums |
89517b1cb807a59a623fa82d16b073a08e214789dc3fc06c28a5599b7d85ed59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logRelease files / neuroviewer-0.1.0-py3-none-any.whl
| Download URL | neuroviewer-0.1.0-py3-none-any.whl |
|---|---|
| Size | 69.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9226630ce00be49c27c46ac0919dafba3442cc5b44ff2a74b6506ef5f9c7e854
|
|
BLAKE2b-256 checksum How to use checksums |
97b28e334224b4022c0dc4a5d871195828a24513c13006f442f5aea7a02d54ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logSecurity for neuroviewer 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for neuroviewer-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.