Skip to main content

PyPI version Python versions License CI

nifti-finder

Navigate neuroimaging datasets (and more) using flexible file explorers and filters. Optimized for typical neuroimaging research workflows, including BIDS-structured datasets.

Key features

  • Flexible file discovery with glob-based pattern matching for any dataset structure.
  • Rich set of composable filters for precise dataset querying (by file extension, prefix/suffix, regex, existence of related files, etc.).
  • Extensible design with modular, reusable interfaces for creating custom explorers and filters

Installation

pip install nifti-finder
# or from source
pip install -e .

Quickstart

Get all NIfTI files from any nested dataset

from nifti_finder import FileFinder

from your_package import preprocess

# Default: finds all .nii and .nii.gz files (flat recursive scan)
finder = FileFinder()

for path in finder.scan("/path/to/dataset"):
    preprocess(path)

Track subject-level progress in BIDS-style datasets

finder = FileFinder(
    levels={"subjects": "sub-*"},       # directory levels (progress tracks the first)
    patterns="**/anat/*T1w.nii*",        # file patterns at the final stage
)

for path in finder.scan("/path/to/dataset", progress=True, desc="Subjects"):
    preprocess(path)

Output:

Subjects:  50%|███████████████████▌               | 30/60 [00:15<00:15,  2.00 it/s]

Exclude subjects with missing data; e.g., a segmentation mask

from nifti_finder.filters import IncludeIfFileExists

finder = FileFinder(
    levels={"subjects": "sub-*"},
    patterns="**/anat/*T1w.nii*",
    filters=[
        IncludeIfFileExists(
            filename_pattern="*seg*", # require a segmentation mask
            search_in="/labels",      # in a parallel labels/ tree
            mirror_relative_to="/path/to/dataset",
        )
    ],
)

for path in finder.scan("/path/to/dataset"):
    preprocess(path)

API Overview

  • Recommended
    • FileFinder — nested or flat file discovery with levels, patterns, filters, and materialization helpers.
  • Primitives
    • RecursiveFileExplorer — flat recursive glob.
    • NestedFileExplorer — multi-level directory traversal with optional progress; uses patterns at the final stage.
  • Deprecated (removed in v2.2.0)
    • NeuroExplorer — legacy outer / inner two-stage API.
    • AllPurposeFileExplorer, BasicFileExplorer, TwoStageFileExplorer.
  • Filters
    • Include/Exclude: Extension, FilePrefix, FileSuffix, FileRegex, DirectoryPrefix/Suffix/Regex, IfFileExists
    • Filters can be combined with logical operators (AND/OR).
  • Mixins & Interfaces
    • MaterializeMixin — utilities to list, deduplicate, sort, batch, or count matches.
    • FilterableMixin — add, remove, and compose filters dynamically.

Extended Examples

Multi-level directory traversal

finder = FileFinder(
    levels={
        "datasets": "OpenNeuro-ds*",
        "subjects": "sub-*",
        "sessions": "ses-*",
        "anat": "anat",
    },
    patterns=["*_T1w.nii*", "*_FLAIR.nii*"],
)

for path in finder.scan("/path/to/datasets", progress=True, desc="Datasets"):
    preprocess(path)

Use with non-NIfTI files (e.g., JSON)

finder = FileFinder(
    levels={"subjects": "sub-*"},
    patterns="**/*.json",
)
for p in finder.scan("/path/to/bids", progress=True, desc="Subjects"):
    print(p)

Explorers support multiple patterns and filters, but will traverse once per pattern.

Materialize results

FileFinder provides convenience methods to turn the streaming output of scan() into concrete Python data structures.

This is useful when you want:

  • A list of paths (with optional sorting, deduplication, or limiting)
  • A single path (first match)
  • A quick boolean check
  • A count
  • Iteration in batches
finder = FileFinder(
    levels={"subjects": "sub-*"},
    patterns="**/anat/*T1w.nii*",
)
paths = finder.list("/path/to/dataset", sort=True, unique=True)

Chainable filtering

FileFinder allows include/exclude filters to refine results.

from nifti_finder.filters import IncludeExtension, ExcludeDirPrefix

finder = FileFinder(
    patterns="**/*.nii*",
    filters=[
        ExcludeFileSuffix("preprocessed"),              # drop already preprocessed files
        ExcludeDirPrefix("bad"),                        # drop 'bad' files
        IncludeIfFileExists(filename_pattern="*mask*"), # keep if a brain mask exists in same directory
    ],
    logic="AND",                                        # combination logic
)

for path in finder.scan("/path/to/dataset"):
    preprocess(path)

Filters can be dynamically adjusted.

finder.add_filters(ExcludeFileSuffix("mask"))
finder.remove_filters(ExcludeFileSuffix("mask"))
finder.clear_filters()

Filters can be composed together to get their own combination logic.

from nifti_finder.filters import ComposeFilter, ExcludeFilePrefix

suffix_filter = ComposeFilter(
    filters=[ExcludeFileSuffix("bet"), ExcludeFileSuffix("mask")],
    logic="OR"
)
prefix_filter = ComposeFilter(
    filters=[ExcludeFileSuffix("pet"), ExcludeFileSuffix("dwi")],
    logic="OR"
)
filename_filter = ComposeFilter(
    filters=[suffix_filter, prefix_filter],
    logic="AND"
)
finder.add_filters(filename_filter)

Migrating from v1.x

v1.x v2.0
NeuroExplorer() FileFinder() (flat scan; no progress bar)
NeuroExplorer(outer="sub-*", inner="**/*.nii*") FileFinder(levels={"subjects": "sub-*"}, patterns="**/*.nii*")
AllPurposeFileExplorer(pattern="*.json") FileFinder(patterns="*.json")
pattern= patterns=

Legacy shims (NeuroExplorer, AllPurposeFileExplorer, etc.) remain available until v2.2.0.

Development

# Setup
pip install -e .[test]

# Run tests
pytest -q

Metadata

Release files for nifti-finder 2.0.1

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

Source distribution (sdist)

Source distribution for nifti-finder 2.0.1
File Size Uploaded
nifti_finder-2.0.1.tar.gz 24.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nifti-finder 2.0.1
File Interpreter ABI Platform
nifti_finder-2.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 50.5 kB

Release files / nifti_finder-2.0.1.tar.gz

Download URL nifti_finder-2.0.1.tar.gz
Size 24.1 kB
Tags Source
SHA-256 checksum
How to use checksums
dc417ab8d4c36a9b7a6457134b7236e289cfd984c64f6c2ee3cb48b7bf173101
BLAKE2b-256 checksum
How to use checksums
ce9c987435034deb5fb40bab771771fd366091e18309f97666a6a9aae35094f8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.14

Release files / nifti_finder-2.0.1-py3-none-any.whl

Download URL nifti_finder-2.0.1-py3-none-any.whl
Size 26.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
abc65091ccd5cf40d176ec3a6e82d42ccbc1fe6601807ac0c3c8877c06a95092
BLAKE2b-256 checksum
How to use checksums
e6c71f28ff1077c76bb406951d75f60e9a22b8c4db31dcc1ba4194343cfba892
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

2.0.1 This release

2 release files

2.0.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.1.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