Skip to main content

bids_layout/
lib.rs

1#![deny(unsafe_code)]
2//! BIDS dataset layout indexing and querying.
3//!
4//! This is the central crate for interacting with BIDS datasets on disk. It
5//! provides [`BidsLayout`], the main entry point that indexes a dataset directory
6//! into a SQLite database and exposes a fluent query API for finding files.
7//!
8//! Corresponds to PyBIDS' `BIDSLayout` class.
9//!
10//! # Indexing
11//!
12//! When a `BidsLayout` is created, the dataset directory is walked recursively.
13//! Each file's path is matched against entity regex patterns from the configuration
14//! to extract BIDS entities (subject, session, task, run, suffix, extension, etc.).
15//! Files and their entity tags are stored in a SQLite database — either in-memory
16//! for fast one-off use, or on disk for persistent caching of large datasets.
17//!
18//! JSON sidecar metadata is also indexed following the BIDS inheritance principle,
19//! and file associations (IntendedFor, events↔bold, bvec/bval↔DWI) are recorded.
20//!
21//! # Querying
22//!
23//! The [`GetBuilder`] provides a fluent API for filtering files:
24//!
25//! ```no_run
26//! # use bids_layout::BidsLayout;
27//! # let layout = BidsLayout::new("/path/to/dataset").unwrap();
28//! let files = layout.get()
29//!     .subject("01")
30//!     .task("rest")
31//!     .suffix("bold")
32//!     .extension(".nii.gz")
33//!     .collect()
34//!     .unwrap();
35//! ```
36//!
37//! Queries support exact matching, multi-value matching (`.filter_any()`),
38//! regex matching (`.filter_regex()`), existence checks (`.query_any()`,
39//! `.query_none()`), and scope-aware searching across derivatives.
40//!
41//! # Derivatives
42//!
43//! Derivative datasets (e.g., fMRIPrep output) can be added via
44//! `layout.add_derivatives()`. Queries can then be scoped to raw data only,
45//! derivatives only, a specific pipeline, or all datasets.
46//!
47//! # Persistent Database
48//!
49//! For large datasets, create a persistent index to avoid re-scanning:
50//!
51//! ```no_run
52//! # use bids_layout::BidsLayout;
53//! let layout = BidsLayout::builder("/path/to/dataset")
54//!     .database_path("/path/to/index.sqlite")
55//!     .build()
56//!     .unwrap();
57//! ```
58//!
59//! Subsequent calls with the same database path will load the existing index
60//! instead of re-walking the filesystem.
61
62pub mod db;
63pub mod get_builder;
64pub mod indexer;
65pub mod layout;
66pub mod query;
67
68pub use get_builder::{GetBuilder, InvalidFilters};
69pub use layout::BidsLayout;
70pub use query::{Query, QueryFilter, Scope};