Skip to content

Repository files navigation

PlateProof

CI Release Python 3.11+ MIT

Catch plate, row, column, edge, replicate, and missing-control risks in an existing microplate map before the experiment starts.

PlateProof is a small, fully offline CLI. Give it a long-form CSV and declare the categorical factors, replicate identifier, or roles you care about. It returns a terminal decision plus deterministic JSON, Markdown, and a self-contained HTML/SVG plate report. Your layout never leaves the machine.

PlateProof: REVIEW - 8 wells across 2 plates; 6 risk findings.
Reports: plateproof-report

Why and for whom

A valid CSV can still encode a risky experiment: every drug well may be on one plate, one cohort may sit in a single row, technical replicates may touch, or a plate may lack the requested positive control. These are easy to miss in a spreadsheet and costly to discover after wet-lab work.

PlateProof is for researchers, screening teams, and data stewards who already have a plate map and want a quick, reviewable preflight. It audits the supplied layout; it does not create or optimize one.

Install

PlateProof requires Python 3.11 or newer and has no runtime dependencies.

python -m pip install "https://github.com/KanadeK/plateproof/releases/download/v0.1.0/plateproof-0.1.0-py3-none-any.whl"
plateproof --version

The wheel, source distribution, and ready-to-open demo bundle are also on the v0.1.0 release.

60-second quick start

Download the demo bundle, unpack it with Python, and audit the intentionally risky layout:

curl -LO https://github.com/KanadeK/plateproof/releases/download/v0.1.0/plateproof-0.1.0-demo.zip
python -m zipfile -e plateproof-0.1.0-demo.zip .
cd plateproof-demo
plateproof audit examples/risky.csv \
  --factor treatment \
  --factor cohort \
  --replicate sample_id \
  --role-column role \
  --require-role positive_control \
  --out plateproof-report

Exit 1 is expected here: the audit completed and wrote reports, but found risks worth review. Open plateproof-report/report.html in any browser. The example finds all three v0.1.0 rule families:

  • factor_level_confined: treatment and cohort levels are each tied to one plate;
  • replicate_clustered: the two S1 wells are adjacent;
  • required_role_missing: plate P2 has no positive_control.

The report's plate-association evidence includes:

{
  "factor": "treatment",
  "dimension": "plate",
  "normalized_mutual_information": 1.0,
  "factor_levels": 2,
  "position_levels": 2
}

Normalized mutual information (NMI) is descriptive evidence, not a statistical significance test.

Input

PlateProof expects UTF-8 long-form CSV: one occupied well per row. The identity columns default to plate and well; each audited value must be non-empty.

plate,well,treatment,cohort,sample_id,role
P1,A1,drug,trial,S1,negative_control
P1,A2,drug,trial,S1,sample
P2,G11,control,reference,C1,negative_control

Well names are case-insensitive and normalized (a01 becomes A1). A (plate, well) pair must be unique and inside the declared geometry. The defaults are 8 rows by 12 columns; v0.1.0 supports up to 26 rows and 99 columns, with at most 100,000 occupied wells.

Use different identity column names when necessary:

plateproof audit layout.csv \
  --plate-column plate_id \
  --well-column position \
  --factor treatment \
  --out report

What the audit does

For every --factor, PlateProof computes counts and NMI against plate, row, column, and edge membership. A risk finding is emitted when a factor level with at least two wells is completely confined to one positional value while that position varies in the input.

--replicate COLUMN reports a group when all of its wells are on one plate and every member touches another group member orthogonally. --role-column plus repeatable --require-role checks the declared role on every plate.

The output directory must not already exist. A valid audit writes exactly:

File Use
report.json Versioned plateproof.report.v1 automation contract
report.md Portable review summary and actions
report.html Self-contained, escaped HTML with SVG plate maps

Reports contain the source filename, never its absolute path. HTML has no JavaScript, external font, tracker, or network request.

Success, boundary, and failure examples

From a repository checkout or the demo bundle:

# Balanced 96-well-style input: exit 0
plateproof audit examples/balanced.csv \
  --factor treatment --factor cohort \
  --role-column role \
  --require-role negative_control --require-role positive_control \
  --out balanced-report

# 384-well geometry and zero-padded well names: exit 0
plateproof audit examples/boundary_384.csv \
  --rows 16 --columns 24 \
  --factor condition \
  --out boundary-report

# Duplicate normalized well: exit 2, no report directory
plateproof audit examples/invalid_duplicate.csv \
  --factor treatment \
  --out invalid-report

The invalid example prints:

plateproof: error: row 3 has duplicate well P1/A1; each plate/well pair must be unique

Exit codes

Code Meaning What to do
0 Valid audit; no declared risk rule triggered Review the metrics and continue with domain judgment
1 Valid audit; one or more reports were written Open the report and review the stated evidence/action
2 Invalid arguments/input or report-write failure Fix the stderr message and rerun with a new output path

Troubleshooting

Message or behavior Cause Fix
missing required column: treatment A declared column is absent or spelled differently Correct the header or change the relevant CLI column option
duplicate well P1/A1 Case and zero padding normalize to the same well Keep one row or correct the plate/well identity
outside declared 8x12 geometry The map is larger than the defaults or the well is wrong Correct the well, or pass the actual --rows and --columns
output path already exists PlateProof never overwrites a report directory Choose a new --out path; remove old output yourself only if intended
Command exits 1 but reports exist This is a review result, not a crash Read report.html or consume report.json
cannot read CSV ... The file is missing, unreadable, malformed, or not UTF-8 Check the path/permissions and export UTF-8 CSV

Known limits

  • PlateProof only evaluates declared categorical columns and plate, row, column, and edge geometry.
  • NMI and the explicit rules are descriptive preflight signals. They are not hypothesis tests and do not prove bias, causality, or experimental validity.
  • The tool does not know dispensing order, chemistry, incubation, batch history, intentional gradients, or whether a scientific design choice is appropriate.
  • It does not generate/randomize layouts, create liquid-handler worklists, or analyze assay readings, images, OD values, or dose response.
  • Replicate adjacency is a transparent review heuristic, not proof that the layout is wrong.

These boundaries are deliberate. See the accepted specification and near-neighbor evidence for the product and novelty scope.

Development and release gate

git clone https://github.com/KanadeK/plateproof.git
cd plateproof
uv sync --locked --all-extras --dev
uv run python scripts/check.py

The single gate checks the lock file, formatting, lint, strict types, unit and integration tests with branch coverage, all four committed examples, local Markdown links and main README commands, dependency vulnerabilities, wheel and sdist contents, the demo bundle, clean-environment wheel installation, and a real run through the installed plateproof entry point. CI calls the same command on Linux/Python 3.11 and Windows/Python 3.14.

To reproduce the three release assets in a new dist directory:

uv run python scripts/release_assets.py dist

License

MIT © 2026 KanadeK.

About

Offline spatial-risk preflight for existing microplate layout CSVs

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages