A Streamlit component for NiiVue neuroimaging viewer
Project description
NiiVue Streamlit Component
A modern Streamlit component for visualizing neuroimaging data using NiiVue, built with TypeScript, Preact, and Vite.
๐ Quick Start
Simple Installation & Usage
-
Install the component:
pip install --index-url https://test.pypi.org/simple/ --no-deps niivue-streamlit
-
Use in your Streamlit app:
import streamlit as st from niivue_component import niivue_viewer uploaded_file = st.file_uploader("Choose a NIFTI file", type=["nii", "nii.gz"]) if uploaded_file is not None: result = niivue_viewer( nifti_data=uploaded_file.getvalue(), filename=uploaded_file.name, height=700 ) # Handle click events if result: st.write(f"Clicked voxel: {result['voxel']}, Value: {result['value']}")
โจ Features
- ๐จ Two Component Modes:
StyledViewer: Full-featured viewer with interactive menu and controlsUnstyledCanvas: Minimal canvas-only viewer for embedding
- ๐ Multiple View Modes:
- Axial, Coronal, Sagittal slices
- 3D render view
- Multiplanar view with render
- ๐ Advanced Capabilities:
- Multiple overlay images with custom colormaps
- Surface mesh rendering (FreeSurfer pial, white, inflated, GIfTI, STL, OBJ, etc.)
- Mesh overlays (curvature, thickness, annotations)
- Combined volume + mesh visualization
- Configurable display settings (crosshair, radiological convention, colorbar, interpolation)
- Bidirectional communication (click events from viewer to Python)
- DICOM support
๐ Advanced Usage
With Overlays
from niivue_component import niivue_viewer
result = niivue_viewer(
nifti_data=main_image_bytes,
filename="brain.nii.gz",
overlays=[
{
"data": overlay_bytes,
"name": "activation.nii.gz",
"colormap": "hot",
"opacity": 0.7
}
],
view_mode="multiplanar",
styled=True,
settings={
"crosshair": True,
"radiological": False,
"colorbar": True,
"interpolation": True
},
height=800
)
With Mesh Surfaces
from niivue_component import niivue_viewer
# Load a FreeSurfer surface mesh
mesh_data = open("lh.pial", "rb").read()
result = niivue_viewer(
meshes=[{
"data": mesh_data,
"name": "lh.pial",
}],
view_mode="3d",
height=700
)
Mesh with Overlays (Curvature, Thickness)
mesh_data = open("lh.pial", "rb").read()
thickness_data = open("lh.thickness", "rb").read()
result = niivue_viewer(
meshes=[{
"data": mesh_data,
"name": "lh.pial",
"overlays": [{
"data": thickness_data,
"name": "lh.thickness",
"colormap": "redyell",
"opacity": 0.7
}]
}],
view_mode="3d",
height=700
)
Volume with Mesh
# Display a volume image alongside a surface mesh
volume_data = open("brain.nii.gz", "rb").read()
mesh_data = open("lh.pial", "rb").read()
result = niivue_viewer(
nifti_data=volume_data,
filename="brain.nii.gz",
meshes=[{
"data": mesh_data,
"name": "lh.pial",
}],
view_mode="3d",
height=700
)
Minimal Viewer (No Menu)
# Perfect for embedding in complex layouts
result = niivue_viewer(
nifti_data=image_bytes,
filename="scan.nii",
styled=False, # Hide menu
view_mode="axial",
height=400
)
โก Performance
Because Streamlit re-runs the whole script whenever a component calls
Streamlit.setComponentValue, bidirectional click feedback from the viewer
can become a bottleneck: without care, every mouse event re-reads the file,
re-base64-encodes the NIfTI, and re-transmits it to the iframe. Three knobs
keep the viewer snappy:
@st.fragmentโ wrap the viewer plus the UI that consumes its return value in a fragment. Clicks re-run only the fragment, not the whole page. Seeapp_bidirectional.py.@st.cache_dataโ cachePath.read_bytes()so the same bytes aren't re-loaded on every re-run. The component wrapper also caches the base64 encoding internally, keyed on the bytes object's identity, so caching your loader transparently skips re-encoding too.update_interval_msโ controls the throttle on click events sent back to Python (default100ms). PassNoneto disable feedback entirely when the return value isn't used (e.g.app_simple.py,app_overlay.py,app_advanced.py).
Minimal template:
import streamlit as st
from niivue_component import niivue_viewer
from pathlib import Path
@st.cache_data
def load_nifti(path: str) -> bytes:
return Path(path).read_bytes()
image = load_nifti("brain.nii.gz")
@st.fragment
def viewer():
result = niivue_viewer(
nifti_data=image,
filename="brain.nii.gz",
key="viewer",
update_interval_ms=100, # or None to disable feedback
)
if result:
st.write(result)
viewer()
๐ API Reference
niivue_viewer()
Parameters:
nifti_data(bytes, optional): Raw NIFTI file datafilename(str): Displayed filenameoverlays(list[dict], optional): Overlay images listdata(bytes): Overlay dataname(str): Overlay namecolormap(str): Colormap (default: 'red')opacity(float): 0-1 (default: 0.5)
meshes(list[dict], optional): Mesh surfaces listdata(bytes): Mesh file dataname(str): Mesh filename (must include extension, e.g. 'lh.pial', 'brain.gii')overlays(list[dict], optional): Mesh overlays (curvature, thickness, etc.)data(bytes): Overlay dataname(str): Overlay filenamecolormap(str): Colormap (default: 'redyell')opacity(float): 0-1 (default: 0.7)
height(int): Height in pixels (default: 600)view_mode(str): 'axial', 'coronal', 'sagittal', '3d', 'multiplanar' (default)styled(bool): Show menu (default: True)settings(dict, optional):crosshair(bool): default Trueradiological(bool): default Falsecolorbar(bool): default Falseinterpolation(bool): default True
update_interval_ms(int or None): throttle for click events sent back to Python (default: 100 ms).Nonedisables feedback entirely โ use it when the return value isn't consumed to avoid any Python round-trip during mouse interaction.key(str, optional): Component key
Returns:
dict or None with click event data:
type: 'voxel_click'voxel: [x, y, z]mm: [x, y, z]value: floatfilename: str
๐ ๏ธ Development
Dev mode (live reload)
In dev mode, the Python package points to a local Vite dev server instead of built files.
Terminal 1 โ start the frontend dev server (port 3001):
pnpm dev
Terminal 2 โ run the example app with the dev flag:
NIIVUE_DEV=1 streamlit run app.py
The frontend hot-reloads on changes.
Production mode (built files)
Build the frontend first, then run Streamlit normally:
pnpm build
streamlit run app.py
_RELEASE = True (the default) serves from niivue_component/frontend/build/.
Running Examples
# Simple example
streamlit run app.py
# Advanced example with all features
streamlit run app_advanced.py
๐ Supported Formats
- Volume-based: NIFTI (.nii, .nii.gz), DICOM (.dcm), MINC (.mnc, .mnc.gz), MHA/MHD, NRRD, MGH/MGZ
- Mesh-based: GIfTI (.gii), FreeSurfer (pial, white, inflated), MZ3 (.mz3), STL (.stl), Wavefront OBJ (.obj), PLY (.ply), BrainSuite DFS (.dfs), Legacy VTK (.vtk)
- Mesh Overlays: GIfTI (.gii), CIfTI-2 (.nii), MZ3 (.mz3), FreeSurfer (CURV, ANNOT), SMP, STC
- Tractography: TCK (.tck), TRK (.trk), TRX (.trx), VTK (.vtk)
๐๏ธ Architecture
niivue_component/
โโโ __init__.py # Python API
โโโ frontend/
โ โโโ src/
โ โ โโโ components/
โ โ โ โโโ StyledViewer.tsx
โ โ โ โโโ UnstyledCanvas.tsx
โ โ โโโ types.ts
โ โ โโโ utils.ts
โ โโโ vite.config.ts
โ โโโ package.json
โโโ build/ # Compiled assets (generated, not in git)
๐ง Building for Distribution
Build files are not committed to git. To prepare the Python package for release:
pnpm build
python -m build
This compiles frontend assets into niivue_component/frontend/build/, which is then bundled into the Python package.
๐ License
BSD-2-Clause
๐ Credits
Built on top of:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file niivue_streamlit-0.0.0.dev36.tar.gz.
File metadata
- Download URL: niivue_streamlit-0.0.0.dev36.tar.gz
- Upload date:
- Size: 1.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6414fb6d18bbe76d443b22797b81196a502d331cd4c76d52731c32d50f0f3524
|
|
| MD5 |
b5221a45b9a41143cee1aadd80172c2c
|
|
| BLAKE2b-256 |
7e92e50a9d6395766bcac7baa961405b707f235cf9c09b39b24218dfb66e04fb
|
File details
Details for the file niivue_streamlit-0.0.0.dev36-py3-none-any.whl.
File metadata
- Download URL: niivue_streamlit-0.0.0.dev36-py3-none-any.whl
- Upload date:
- Size: 1.2 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d20d9c83abf56211391abb40145db909ef6ff4a6081888ee3e12b7cd67f0cfda
|
|
| MD5 |
cda678ed19eb3086ece027d8bb8935b2
|
|
| BLAKE2b-256 |
4b2e82361c0b6c0ee607143896a52d4ab1b71c8f8089d6887ba3736d8fd27f8e
|