Metadata-Version: 2.4
Name: bidsval
Version: 0.0.4
Summary: A schema-driven, pydantic-typed, in-process BIDS validator.
Author: bidsval contributors
License: MIT
Project-URL: Homepage, https://github.com/karellopez/bidsval
Project-URL: Repository, https://github.com/karellopez/bidsval
Project-URL: Issues, https://github.com/karellopez/bidsval/issues
Keywords: BIDS,validation,neuroimaging,schema,pydantic
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering
Requires-Python: <3.15,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: bidsschematools<=1.2.2,>=1.0
Requires-Dist: pydantic<=2.13.4,>=2
Requires-Dist: nibabel<=5.4.2,>=5.0
Requires-Dist: pandas<3.0,>=2.0
Requires-Dist: mne<=1.12.1,>=1.6
Requires-Dist: pyyaml<=6.0.3,>=5.4
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: ruff>=0.1; extra == "dev"
Dynamic: license-file

# bidsval

Validate [BIDS](https://bids.neuroimaging.io) datasets in pure Python.

`bidsval` reads the official BIDS schema and checks datasets against the rules it
contains. It runs in-process with no external runtime, returns typed (pydantic)
results, and validates a whole dataset, a single subject, a single file, or a
single expression. Every published BIDS schema version ships inside the package,
so it works offline and you choose the version with one argument.

Because the schema drives everything, `bidsval` covers all of BIDS - anatomical,
functional, diffusion, fieldmaps, perfusion, EEG, MEG, iEEG, behavioural, PET,
microscopy, motion, NIRS, MRS - not a fixed set of modalities. Point it at a
newer schema and the newer rules apply with no code change.

> Verified against the reference Deno `bids-validator` across the full
> `bids-examples` corpus and real MRI/EEG/MEG/PET datasets, at a matched schema, with
> **zero false positives**. It covers filename and path legality, file integrity,
> sidecar field presence and value types, associated files, tabular columns (types,
> order, uniqueness), the inheritance principle, and dataset-level checks. The
> remaining gaps are HED and symlink validation; see the
> [comparison](https://github.com/karellopez/bidsval/blob/main/docs/comparison-vs-deno.md)
> and "Roadmap".

## Install

```shell
pip install bidsval
```

That is all you need: the bundled BIDS schemas and the content readers
(`nibabel`, `pandas`, `mne`) come with it, so it works offline. Python 3.10 to 3.14.

For development, from a clone:

```shell
git clone https://github.com/karellopez/bidsval
cd bidsval
pip install -e ".[dev]"   # editable install, plus the test and lint tooling
```

## Validate a dataset

From Python:

```python
import bidsval

report = bidsval.validate("/path/to/dataset")
report.is_valid            # False if there are any errors
report.counts              # {'error': 3, 'warning': 27, 'ignore': 0}
for verdict in report.files:
    for issue in verdict.issues:
        print(issue.severity.value, issue.code, verdict.path, issue.message)

# Narrower granularity:
bidsval.validate_subject("/path/to/dataset", "sub-01")
bidsval.validate_file("/path/to/dataset", "sub-01/anat/sub-01_T1w.nii.gz")
```

From the command line:

```shell
# Text summary to the terminal (exits non-zero on errors, so it drops into CI):
bidsval validate /path/to/dataset

# Validate one subject; also check NIfTI headers:
bidsval validate /path/to/dataset --subject sub-01 --headers

# Pick the output type (independent of where it goes):
bidsval validate /path/to/dataset --output-type json     # JSON to stdout
bidsval validate /path/to/dataset --output-type sarif    # SARIF to stdout (CI / IDE code scanning)

# Write report files: --out-dir holds report.<ext> for each selected type:
bidsval validate /path/to/dataset --output-type html --out-dir reports/   # reports/report.html
bidsval validate /path/to/dataset --output-type all  --out-dir reports/   # report.txt/.json/.sarif/.html

# Show only the severities you care about (does not change pass/fail):
bidsval validate /path/to/dataset --show error           # errors only
```

Flags: `--schema <version|url|path>`, `--subject sub-01`, `--headers`
(also check NIfTI headers, needs nibabel), `--output-type text|json|sarif|html|all`
(default `text`; one type prints to stdout, several need `--out-dir`),
`--out-dir DIR` (write `report.<ext>` per type), `--show error,warning,ignore,all`
(filter displayed findings; default `error,warning`).

## Choose a schema version

Every published BIDS schema is bundled, and any other version or a URL is fetched
and cached. One argument selects the schema; everything downstream is unchanged:

```python
bidsval.validate("/data", schema="1.10.0")               # a bundled version
bidsval.validate("/data", schema="latest")               # the development tip (fetched)
bidsval.validate("/data", schema="https://.../schema.json")  # any URL (fetched + cached)
bidsval.validate("/data", schema="/path/to/schema.json") # a local dereferenced schema.json
bidsval.validate("/data", schema="/path/to/src/schema")  # a YAML schema source directory
bidsval.available_versions()                             # bundled: ['1.8.0', ... '1.11.1']
```

```shell
bidsval validate /data --schema 1.9.0
bidsval validate /data --schema latest
bidsval validate /data --schema https://bids-specification.readthedocs.io/en/v1.10.0/schema.json
bidsval schema --schema 1.10.0      # show the versions a selector resolves to
```

## Evaluate a single expression

The expression engine is usable on its own - handy for understanding a rule or
checking one condition:

```python
from bidsval import evaluate_string

evaluate_string("suffix == 'T1w'", {"suffix": "T1w"})                       # True
evaluate_string("nifti_header.dim[0] == 3", {"nifti_header": {"dim": [4]}}) # False
```

```shell
bidsval eval "suffix == 'T1w'" --context '{"suffix": "T1w"}'
```

## How it works

- The schema is the engine. The BIDS schema expresses validation logic as
  expressions: selectors that decide when a rule applies (`suffix == 'T1w'`) and
  checks that must hold (`nifti_header.dim[0] == 3`). `bidsval` reads the schema's
  vocabulary (datatypes, entities, suffixes, extensions) and rules, builds a
  context for each file, and evaluates the rules against it. No BIDS terms are
  hardcoded.
- Parsing comes from `bidsschematools`; `bidsval` adds the evaluator that walks
  the syntax tree (no `eval`/`exec`), the file/context layers, and the rule loop.
- A finding is reported only when a rule produces a determinate failure. When the
  context cannot determine a rule (for example a check that needs a content layer
  not yet built), the rule is skipped rather than guessed, so the validator does
  not emit false errors.
- Results are pydantic models, ready to serialise to JSON or bind to a GUI.

## Layout

| Module | Responsibility |
|---|---|
| `bidsval.schema` | Resolve a selector to one schema object; read BIDS vocabulary from it. The only version-aware code. |
| `bidsval.files` | Index a dataset's files (`FileTree`). |
| `bidsval.context` | Build the per-file context: entities, datatype, inheritance-merged sidecar, associated files, loaded content. |
| `bidsval.expr` | Evaluate BIDS schema expressions against a context. |
| `bidsval.rules` | Apply the schema's checks, sidecar fields (presence + value type), and tabular-column rules; plus bespoke checks. |
| `bidsval.validate` | `validate` / `validate_subject` / `validate_file`. |
| `bidsval.render` | Render a report as text / JSON / SARIF / HTML. |
| `bidsval.issues` / `bidsval.report` | Typed findings and results. |
| `bidsval.cli` | The `bidsval` command. |

Done: the schema engine and the file/context/rule layers; dataset/subject/file
validation; filename and path legality (with `.bidsignore`); file-integrity checks;
sidecar field presence and full value-type checks; the associations layer
(events, bval/bvec, channels, ASL, coordsystem, atlas, ...); tabular checks (types,
order, uniqueness, additional columns); inheritance checks; dataset-level checks;
CITATION.cff; derivatives recursion; bundled + URL + `latest` schema selection;
text / JSON / SARIF / HTML output.

## Roadmap

Filename/path legality, file integrity, the cross-file and tabular checks (including
full value-type checking and type redefinition), inheritance checks, CITATION.cff,
derivatives recursion, and the coordsystems/atlas-description aggregates are all in
(see [comparison vs the Deno reference validator](https://github.com/karellopez/bidsval/blob/main/docs/comparison-vs-deno.md)
for full coverage). Remaining:

1. Deferred reference checks: HED (needs a HED validator dependency) and symlink checks
   (the annex-symlink tension). Only the gzip/ome/tiff content-header aggregates are
   still unbuilt.
2. The ahead-of-market features: requirement-level completeness per subject, reasoned
   waivers, explain mode, and one-click fixes (provenance and fix hints are already on
   every finding).

## Documentation

The docs live in [`docs/`](https://github.com/karellopez/bidsval/tree/main/docs) on GitHub:

- [usage](https://github.com/karellopez/bidsval/blob/main/docs/usage.md) - install, the CLI, the Python API.
- [CLI reference](https://github.com/karellopez/bidsval/blob/main/docs/cli-reference.md) - every command and option, with examples and exit codes.
- [schema selection](https://github.com/karellopez/bidsval/blob/main/docs/schema-selection.md) - the single `--schema` selector.
- [output formats](https://github.com/karellopez/bidsval/blob/main/docs/output-formats.md) - `--output-type`, `--out-dir`, `--show`.
- [how it works](https://github.com/karellopez/bidsval/blob/main/docs/internals.md) - the complete technical reference: design, dependencies, every layer, flowcharts, and a glossary.
- [comparison vs the Deno reference validator](https://github.com/karellopez/bidsval/blob/main/docs/comparison-vs-deno.md) - coverage, results, and the no-false-positives evidence.

## Develop

```shell
pytest                                  # unit suite, incl. the schema expression oracle
BIDSVAL_REAL_DATA=1 pytest tests/test_real_data.py   # real-data validation (if datasets present)
ruff check src tests
```

## License

MIT. See [LICENSE](https://github.com/karellopez/bidsval/blob/main/LICENSE).
