Skip to content

NeuroVault I/O

Open in molab

Run this tutorial

This page is rendered from the marimo notebook docs/tutorials/data-operations/04_neurovault.py. Click the badge to run it in the cloud (free, no install), or locally: download 04_neurovault.py and run uvx marimo edit --sandbox 04_neurovault.py. The outputs below were produced when this page was built.

NeuroVault is a public repository of unthresholded statistical maps. nltools can pull a whole collection, a single image by URL, and push your own maps back up.

Download a collection

fetch_neurovault_collection takes a collection ID and returns the image metadata and the local file paths. Files land in nilearn's data directory unless you pass data_dir, and are reused on later calls.

from nltools.datasets import fetch_neurovault_collection

metadata, files = fetch_neurovault_collection(2099, verbose=0)
print(f"{len(files)} images")
metadata.select("id", "name", "map_type", "modality").head()
3 images
shape: (3, 4)
idnamemap_typemodality
i64strstrstr
39709"Neurosynth Parcellation_0.nii.…"parcellation""Other"
39710"Neurosynth Parcellation_1.nii.…"parcellation""Other"
39711"Neurosynth Parcellation_2.nii.…"parcellation""Other"

Hand both to BrainData and the metadata rides along on .X, one row per image:

from nltools.data import BrainData

collection = BrainData(files, X=metadata)
collection
nltools.data.braindata.BrainData(data=(3, 238955), resolution=2.0mm, space=mni, mask=2mm-MNI152-2009fsl-mask.nii.gz)

Collection 2099 is a three-image parcellation set, so all three fit under plot's default limit of 3:

collection.plot(limit=len(collection))
[<Figure size 950x350 with 6 Axes>, <Figure size 950x350 with 6 Axes>, <Figure size 950x350 with 6 Axes>]
2026-09-13T00:39:14.721121 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ L R L R 0 12 25 38 50 image 0
2026-09-13T00:39:14.876092 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ L R L R 0 25 50 75 1e+02 image 1
2026-09-13T00:39:15.033049 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ L R L R 0 50 1e+02 1.5e+02 2e+02 image 2

Download a single image

download_nifti fetches one image by URL and returns the path it wrote. Without data_dir it writes to the working directory, so give it a location you control. BrainData also accepts a URL directly, which saves a line but drops the file in a temporary directory your system will eventually clear — use download_nifti when you want to keep it.

import tempfile

from nltools.datasets import download_nifti

_url = "https://neurovault.org/media/images/2099/Neurosynth%20Parcellation_0.nii.gz"
parcellation_path = download_nifti(_url, data_dir=tempfile.mkdtemp())
parcellation = BrainData(parcellation_path)
parcellation
nltools.data.braindata.BrainData(data=(238955,), resolution=2.0mm, space=mni, mask=2mm-MNI152-2009fsl-mask.nii.gz)

From there it is an ordinary BrainData, so any nilearn plot works:

from nilearn.plotting import plot_glass_brain

_glass = plot_glass_brain(parcellation.to_nifti())
2026-09-13T00:39:15.513124 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ L R L R 0 12 25 38 50

Upload to NeuroVault

upload_neurovault pushes a BrainData object to a new or existing collection. It needs an access token, which you generate under your NeuroVault account settings. collection_name creates a new collection; collection_id adds to one you already have. img_type and img_modality are required, and anything else you pass is forwarded as image metadata — as are the columns of .X, with the row index used as each image's name.

The cell below is not run when these docs are built, because it would write to a live public repository.

parcellation.upload_neurovault(
    access_token="your_neurovault_api_key",
    collection_name="Neurosynth Parcellation",
    img_type="Pa",
    img_modality="Other",
    analysis_level="M",
)