Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

NiiVue Streamlit Component

A modern Streamlit component for visualizing neuroimaging data using NiiVue, built with TypeScript, Preact, and Vite.

🚀 Quick Start

Simple Installation & Usage

  1. Install the component:

    pip install niivue-streamlit
    
  2. 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 controls
    • UnstyledCanvas: 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
)

Scene Documents (NVDocument)

A NiiVue scene document (.nvd, or .nvd.json) restores images together with their display settings and the view. Pass it like an image; the file name tells the viewer it is a scene:

scene = Path("brain.nvd").read_bytes()
niivue_viewer(nifti_data=scene, filename="brain.nvd")

In the styled viewer, NVDocument saves the scene as a download, and NVDocument > Load opens a scene document from disk.

⚡ 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:

  1. @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. See app_bidirectional.py.
  2. @st.cache_data — cache Path.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.
  3. update_interval_ms — controls the throttle on click events sent back to Python (default 100 ms). Pass None to 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 file data of the main image (NIfTI or another supported format), or a scene document (.nvd, .nvd.json)
  • filename (str): Displayed filename; its extension selects the format
  • overlays (list[dict], optional): Overlay images list
    • data (bytes): Overlay data
    • name (str): Overlay name
    • colormap (str): Colormap (default: 'red')
    • opacity (float): 0-1 (default: 0.5)
  • meshes (list[dict], optional): Mesh surfaces list
    • data (bytes): Mesh file data
    • name (str): Mesh filename (must include extension, e.g. 'lh.pial', 'brain.gii')
    • overlays (list[dict], optional): Mesh overlays (curvature, thickness, etc.)
      • data (bytes): Overlay data
      • name (str): Overlay filename
      • colormap (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 True
    • radiological (bool): default False
    • colorbar (bool): default False
    • interpolation (bool): default True
  • update_interval_ms (int or None): throttle for click events sent back to Python (default: 100 ms). None disables 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: float
  • filename: 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

🏗️ 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.

📝 Citation

If you use this component in published work, please cite:

Eckstein K, Androulakis A, Dao TT, et al. Seamless neuroimaging visualization: The NiiVue wrapper ecosystem. Aperture Neuro. 2026;6. doi:10.52294/001c.167815

📄 License

BSD-2-Clause

🙏 Credits

Built on top of:

Release files for niivue-streamlit 0.4.0.dev161

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for niivue-streamlit 0.4.0.dev161
File Size Uploaded
niivue_streamlit-0.4.0.dev161.tar.gz 1.3 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for niivue-streamlit 0.4.0.dev161
File Interpreter ABI Platform
niivue_streamlit-0.4.0.dev161-py3-none-any.whl Python 3 none any Details

Total release size: 2.7 MB

Release files / niivue_streamlit-0.4.0.dev161.tar.gz

Download URL niivue_streamlit-0.4.0.dev161.tar.gz
Size 1.3 MB
Tags Source
SHA-256 checksum
How to use checksums
d49a479330998b0b256703f0a112a7eae80c97f547b9ed01379cf5d9c131fc27
BLAKE2b-256 checksum
How to use checksums
f5b5ca08378325b12db8b9e1557665a3ce8ec9cffd6ddca096cf756b259cd4e1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.16

Release files / niivue_streamlit-0.4.0.dev161-py3-none-any.whl

Download URL niivue_streamlit-0.4.0.dev161-py3-none-any.whl
Size 1.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
9bbad15796181902ab85c63d6fafb280ca32a07150e1394c56aaa0094caeb8f0
BLAKE2b-256 checksum
How to use checksums
2f82835edea509613fbf7ce566daffa76a7e5d7fd98ef9de8dfc706267acbb04
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.16

Release history Release notifications | RSS feed

This release

0.4.0.dev161 This release

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page