Skip to content

Python API

The entire public surface is importable directly from the top-level package:

from cp_anndata_validator import (
    validate,       # the one function that runs everything
    Report,         # what validate() returns
    Issue,          # a single structured finding
    Severity,       # error | warning | information
    Category,       # e.g. identifiers, matrix, provenance, ...
    ProfileLevel,   # single-cell | well | treatment
    LoadError,      # raised if the dataset can't be opened
    SchemaError,    # raised if the schema can't be loaded
)

validate()

def validate(
    path: str | Path,
    *,
    schema: str | Path = "generic-cell-painting",
    profile_level: ProfileLevel | str | None = None,
    backed: bool | None = None,
    sample_rows: int = 5000,
    strict: bool = False,
) -> Report: ...
from cp_anndata_validator import ProfileLevel, validate

report = validate(
    "experiment.h5ad",
    schema="jump-cp",
    profile_level=ProfileLevel.WELL,
)

# Equivalent — plain strings are coerced to ProfileLevel before checks run:
report = validate("experiment.h5ad", profile_level="well")

print(report.status)                 # "pass" or "fail"
print(report.counts.by_severity)     # {Severity.ERROR: 2, Severity.WARNING: 1}
for issue in report.issues:
    print(issue.code, issue.severity, issue.location, issue.message)

profile_level accepts either a ProfileLevel member or its string value ("single-cell", "well", "treatment"); a string is coerced to the enum before any check runs. Warnings alone do not fail a normal run; pass strict=True to treat warnings (including AGG001) as failures.

Raises ValueError if profile_level is not one of those values, cp_anndata_validator.LoadError if the file can't be safely opened, and cp_anndata_validator.SchemaError if the requested schema can't be loaded — all before any checks run.

Rendering a report

Renderers are pure functions, independent of validation logic — you can call them on any Report, including ones you constructed yourself (for example in a test):

from cp_anndata_validator.reporting import render_console, render_html, render_json

print(render_console(report))
Path("report.json").write_text(render_json(report))
Path("report.html").write_text(render_html(report))

Working with Issue and Report

Both are frozen Pydantic models (model_config = ConfigDict(frozen=True, extra="forbid")), so they serialize/deserialize losslessly:

payload = report.model_dump_json()
restored = Report.model_validate_json(payload)
assert restored == report

See Rule catalogue for the full field list on Issue, and src/cp_anndata_validator/models/report.py for Report's complete shape (profile_level, counts, checks, input_file, etc.).

Advanced: running the check registry directly

Most users only need validate(). If you need lower-level access (for example, to run a custom subset of checks), the building blocks are all independently importable:

from cp_anndata_validator.loading import load_anndata
from cp_anndata_validator.schema.loader import load_schema
from cp_anndata_validator.schema.resolve import resolve_schema
from cp_anndata_validator.profiles import detect_profile_level
from cp_anndata_validator.checks.registry import CheckContext
from cp_anndata_validator.orchestrator import run_checks, build_report
import cp_anndata_validator.checks  # registers all built-in checks

handle = load_anndata("experiment.h5ad")
schema = load_schema("generic-cell-painting")
resolved = resolve_schema(handle.adata.obs, handle.adata.var, schema)
profile = detect_profile_level(handle.adata.obs, resolved)

ctx = CheckContext(handle=handle, resolved_schema=resolved, profile=profile)
issues, checks = run_checks(ctx)

See Contributing for how to register a new check.

API reference

validate

validate(
    path: str | Path,
    *,
    schema: str | Path = "generic-cell-painting",
    profile_level: ProfileLevel | str | None = None,
    backed: bool | None = None,
    sample_rows: int = DEFAULT_SAMPLE_ROWS,
    strict: bool = False,
) -> Report

Validate one AnnData dataset and return a structured :class:Report.

Parameters:

Name Type Description Default
path str | Path

Path to an .h5ad file.

required
schema str | Path

A built-in schema name (for example "jump-cp") or a path to a custom schema YAML file.

'generic-cell-painting'
profile_level ProfileLevel | str | None

Declare the profile level explicitly, overriding auto-detection (the report still records what was detected). Accepts a :class:ProfileLevel member or its string value (for example "well").

None
backed bool | None

Force backed (True) or in-memory (False) loading; None (default) auto-selects based on file size.

None
sample_rows int

Maximum number of rows sampled for numeric validity and AI-readiness checks.

DEFAULT_SAMPLE_ROWS
strict bool

Treat warnings as failures when computing the report status.

False

Raises:

Type Description
ValueError

If profile_level is not a supported profile level.

LoadError

If the dataset cannot be safely opened.

SchemaError

If the requested schema cannot be loaded.

Source code in src/cp_anndata_validator/api.py
def validate(
    path: str | Path,
    *,
    schema: str | Path = "generic-cell-painting",
    profile_level: ProfileLevel | str | None = None,
    backed: bool | None = None,
    sample_rows: int = DEFAULT_SAMPLE_ROWS,
    strict: bool = False,
) -> Report:
    """Validate one AnnData dataset and return a structured :class:`Report`.

    Parameters:
        path: Path to an ``.h5ad`` file.
        schema: A built-in schema name (for example ``"jump-cp"``) or a path
            to a custom schema YAML file.
        profile_level: Declare the profile level explicitly, overriding
            auto-detection (the report still records what was detected).
            Accepts a :class:`ProfileLevel` member or its string value (for
            example ``"well"``).
        backed: Force backed (``True``) or in-memory (``False``) loading;
            ``None`` (default) auto-selects based on file size.
        sample_rows: Maximum number of rows sampled for numeric validity and
            AI-readiness checks.
        strict: Treat warnings as failures when computing the report status.

    Raises:
        ValueError: If ``profile_level`` is not a supported profile level.
        LoadError: If the dataset cannot be safely opened.
        SchemaError: If the requested schema cannot be loaded.
    """
    declared_level = _coerce_profile_level(profile_level)

    handle = load_anndata(path, backed=backed)
    try:
        obs = cast(pd.DataFrame, handle.adata.obs)
        var = cast(pd.DataFrame, handle.adata.var)
        schema_definition = load_schema(schema)
        resolved = resolve_schema(obs, var, schema_definition)
        detection = detect_profile_level(obs, resolved)
        profile = (
            detection.model_copy(update={"declared": declared_level})
            if declared_level is not None
            else detection
        )

        ctx = CheckContext(
            handle=handle, resolved_schema=resolved, profile=profile, sample_rows=sample_rows
        )
        issues, checks = run_checks(ctx)

        input_file = InputFileInfo(
            path=str(handle.path),
            size_bytes=handle.size_bytes,
            format="h5ad",
            backed=handle.backed,
        )
        return build_report(
            schema_id=schema_definition.schema_id,
            schema_version=schema_definition.schema_version,
            input_file=input_file,
            profile_level=profile,
            issues=issues,
            checks=checks,
            strict=strict,
        )
    finally:
        handle.close()

Report

Bases: BaseModel

The complete, structured result of validating one AnnData dataset.

Issue

Bases: BaseModel

A single, structured validation finding.

code is a stable rule code (for example "IDENT003") that must never be renumbered or reused once shipped. location should point at an AnnData path such as "obs.plate_id", "var.index" or "uns.provenance".

Severity

Bases: StrEnum

How serious a validation issue is.

Category

Bases: StrEnum

The validation category an issue (or check) belongs to.

ProfileLevel

Bases: StrEnum

The granularity at which observations in an AnnData object are profiled.

LoadError

Bases: Exception

Raised when an AnnData file cannot be opened safely for validation.

SchemaError

Bases: Exception

Raised when a schema (built-in or custom) cannot be loaded or is invalid.