Skip to main content

masstrust

Calibrated trust and abstention for MS/MS molecular annotations.

CI License

日本語 | 中文


What masstrust does

masstrust is a Rust toolkit for selective prediction in MS/MS molecular annotation.

It takes candidate rankings from external annotation or retrieval tools and decides whether the top-ranked molecular annotation should be trusted or abstained under a user-specified error-rate target.

The core idea:

Trust confident annotations. Abstain when uncertainty is too high.

What masstrust does NOT do

  • Does not perform MS/MS database search or spectral matching
  • Does not generate molecular structures
  • Does not perform retrosynthesis
  • Does not replace SIRIUS, CSI:FingerID, MassSpecGym, or similar tools
  • Does not guarantee clinical correctness

masstrust is a post-hoc trust layer for annotation pipelines. It sits after your annotation tool of choice and controls the risk of accepting incorrect annotations.


Installation

Rust CLI (from source)

git clone https://github.com/kent-tokyo/masstrust
cd masstrust
cargo install --path crates/masstrust-cli

Python wheel (requires maturin)

maturin build --features extension-module
pip install target/wheels/masstrust-*.whl

Quick start — CLI

Step 1. Compute the risk-coverage curve from labeled candidates:

masstrust curve examples/labeled_candidates.csv \
  --score score-gap \
  --out risk_coverage.csv \
  --verbose

Step 2. Calibrate a threshold at 5% error rate:

masstrust calibrate examples/labeled_candidates.csv \
  --score score-gap \
  --error-rate 0.05 \
  --method empirical \
  --out policy.json

Step 3. Apply the policy to new (unlabeled) candidates:

masstrust apply examples/candidates.csv \
  --policy policy.json \
  --out trusted_annotations.csv \
  --abstained abstained.csv

Batch mode — apply one policy to many files:

masstrust batch data/*.csv \
  --policy policy.json \
  --out-dir ./results/

Compare multiple scoring methods on one labeled dataset:

masstrust compare examples/labeled_candidates.csv \
  --scores score-gap,score-ratio,topk-gap,candidate-count \
  --error-rate 0.05 --method empirical \
  --bootstrap 1000 \
  --out compare.csv

Evaluate a policy on separate held-out data — calibrate on one set (e.g. validation), evaluate on another (e.g. test) without recalibrating:

masstrust calibrate val.csv --score score-gap --error-rate 0.05 --method empirical --out policy.json
masstrust evaluate test.csv --policy policy.json --out eval_report.json

Detect confidence drift between calibration and new data:

masstrust drift --calibration examples/labeled_candidates.csv --new examples/candidates.csv \
  --score score-gap --out drift_report.json

Guard against calibration/test leakage (query_id/inchikey/formula overlap):

masstrust validate-split --calibration val.csv --test test.csv

Sample output

$ masstrust calibrate examples/massspecgym_candidates.csv \
    --score score-gap --error-rate 0.05 --method empirical --out policy.json

Calibration result (ScoreGap, empirical):
  target error rate: 0.0500
  global threshold:  0.120000
  coverage:          0.5000  (4/8 queries accepted, 50.0%)
  observed risk:     0.0000  (0/4 errors)
  AURC:              0.151488
  E-AURC:            -0.001938

$ masstrust apply examples/candidates.csv --policy policy.json \
    --out trusted.csv --abstained abstained.csv

Accepted: 1  Abstained: 1  (wrote trusted.csv and abstained.csv)

SVG plots (requires --features plot):

cargo build --features plot
masstrust curve examples/labeled_candidates.csv \
  --score score-gap --out risk.csv \
  --plot risk.svg --histogram hist.svg

Quick start — Python

import masstrust

# 1. Compute risk-coverage curve
curve = masstrust.compute_curve(
    "examples/labeled_candidates.csv",
    score="score-gap",
)
print(f"AURC: {masstrust.aurc(curve):.4f}")

# 2. Calibrate
policy = masstrust.calibrate(
    "examples/labeled_candidates.csv",
    score="score-gap",
    error_rate=0.05,
    method="empirical",
)
print(f"Threshold: {policy['threshold']:.4f}")

# 3. Apply to new data
decisions = masstrust.apply_policy("examples/candidates.csv", policy)
accepted  = [d for d in decisions if d["accepted"]]
print(f"Accepted: {len(accepted)}/{len(decisions)}")

# Save / load policy
masstrust.save_policy("policy.json", policy)
policy = masstrust.load_policy("policy.json")

Input CSV format

query_id,candidate_id,rank,score,probability,is_correct
q1,cand_a,1,0.92,0.71,true
q1,cand_b,2,0.81,0.21,false
q2,cand_c,1,0.88,0.46,false
q2,cand_d,2,0.86,0.43,true
Column Required Description
query_id ✓ Spectrum identifier
candidate_id ✓ Candidate structure identifier
rank ✓ Rank among candidates for this query (1 = best)
score ✓ Raw annotation score (higher is better)
probability — Posterior probability (required for max-prob, margin, entropy)
is_correct — Ground-truth label; required for calibrate and curve

Parquet input is supported with --features parquet (auto-detected by .parquet extension).

Add --bootstrap 1000 to curve or compare for a bootstrap 95% confidence interval on AURC.


Confidence scoring methods

Method Formula Requires
score-gap score(rank-1) − score(rank-2) ≥2 candidates
score-ratio score(rank-1) / score(rank-2) ≥2 candidates, score(rank-2) > 0
topk-gap score(rank-1) − mean(score(rank-2..min(5,n))) ≥2 candidates
candidate-count 1 / n_candidates none — always scoreable
max-prob probability(rank-1) probability column
margin probability(rank-1) − probability(rank-2) probability, ≥2 candidates
entropy 1 − H_normalized over all candidate probabilities probability for all candidates
effective-k exp(−H) over all candidate probabilities probability for all candidates

Calibration methods

Method Behaviour Notes
empirical Maximum coverage where observed risk ≤ target No statistical guarantee beyond validation set
binomial Maximum coverage where one-sided Wilson upper bound ≤ target Conservative; add --confidence-level 0.95
crc (experimental) Empirical target tightened by 1/(n+1) CRC-style correction; see caveats below
# Empirical
masstrust calibrate labeled.csv --score score-gap --error-rate 0.05 --method empirical --out policy.json

# Binomial (conservative)
masstrust calibrate labeled.csv --score score-gap --error-rate 0.05 --method binomial --confidence-level 0.95 --out policy.json

# CRC-style (experimental)
masstrust calibrate labeled.csv --score score-gap --error-rate 0.05 --method crc --out policy.json

Batch selective-deployment certification (risksieve, optional)

masstrust certify-batch is a feature-gated (--features risksieve), independent workflow, built on the risksieve crate's SCoRE-SDR controller (Bai and Jin, 2026, arXiv:2603.24704). It is not exposed at all in a default build.

This is not a reusable threshold policy. Unlike calibrate/apply, it computes a fresh selection for one specific calibration set + test batch pair every time you run it — the default construction's e-values depend on the whole test batch's composition, so the same calibration data can select a different subset of a different test batch. See docs/risksieve-integration.md for why this is a separate command rather than a new CalibrationMethod, and exactly what GuaranteeKind::SelectiveDeploymentRisk does and does not claim.

masstrust certify-batch \
  --calibration val.csv \
  --test test.csv \
  --score score-gap \
  --alpha 0.05 \
  --gamma 0.05 \
  --construction coupled \
  --accepted accepted.csv \
  --abstained abstained.csv \
  --certificate certificate.json \
  --report report.md
  • The risk guarantee is conditional on stated assumptions (exchangeability of calibration and the entire test batch jointly, a [0, 1]-bounded loss, and so on) — certificate.json and report.md both record them in full; read them before trusting a number.
  • Zero selections is a normal, valid certificate, not an error — SCoRE-SDR's bound holds trivially on an empty selected set.
  • If test.csv happens to carry is_correct labels, the report also prints a realized selective risk — a post-hoc descriptive statistic computed from this one batch's actual outcomes. It is kept clearly separate from the theorem-backed certificate above it and never described as validating (or invalidating) that certificate.

Graded chemical loss (--loss-column)

By default the certified/realized loss is binary top-1 correctness (is_correct: 0.0 if correct, 1.0 otherwise). --loss-column <name> certifies against any [0, 1]-bounded precomputed loss instead — e.g. Tanimoto dissimilarity or scaffold mismatch, computed upstream (masstrust never computes chemistry itself; see docs/graded-loss-integration.md):

masstrust certify-batch \
  --calibration val.csv \
  --test test.csv \
  --score score-gap \
  --alpha 0.05 \
  --gamma 0.05 \
  --loss-column tanimoto_loss \
  --accepted accepted.csv \
  --abstained abstained.csv \
  --certificate certificate.json \
  --report report.md
  • Required on every scoreable calibration query (hard error if the column is absent, or a value is missing/malformed/outside [0, 1]/non-finite). Genuinely optional on --test — an unlabeled test set (no such column at all) still certifies successfully; it just can't produce a realized-risk number.
  • certificate.json/report.md record loss_kind/loss_label/loss_column/loss_domain so a --loss-column certificate can never be misread as certifying exact-match risk.
  • Realized risk is always resolved against the same loss the certificate itself used — asking for it under a different --loss-column (or under binary correctness, for a graded-loss certificate) is a hard error, not a silently mismatched number.

masstrust's existing calibration methods (empirical/binomial/crc) are untouched by this feature — see the scientific caveats below, which apply to certify-batch too.


Understanding risk and coverage

The risk-coverage curve summarises the accept/abstain tradeoff:

  • Coverage = fraction of queries where a prediction is accepted
  • Risk = fraction of accepted predictions that are incorrect

At any threshold, higher coverage comes at higher risk. masstrust finds the threshold that maximises coverage while keeping risk within the specified target.

risk
1.0 ┤                          ╭──
    │                     ╭────╯
    │                ╭────╯
0.05┤ ─ ─ ─ ─ ─ ─ ─╱── target
    │           ╭───╯
0.0 ┤───────────╯
    └──────────────────────────── coverage
    0                             1.0

The threshold is chosen as the rightmost point on the curve that stays at or below the target risk line.


Policy JSON

A calibrated policy is saved as a reproducible JSON file:

{
  "version": "0.1.0",
  "scoring_method": "score_gap",
  "threshold": 0.18,
  "target_error_rate": 0.05,
  "calibration_method": "empirical",
  "confidence_level": null,
  "created_by": "masstrust"
}

Benchmarking on MassSpecGym

benchmarks/massspecgym/ is a self-contained pipeline (kept out of the Rust workspace — it depends on massspecgym/torch/rdkit) that trains the official Fingerprint FFN retrieval baseline, exports its predictions in masstrust's schema, and reports masstrust's own scoring methods' AURC/E-AURC/coverage-at-risk on real MassSpecGym data. This establishes a real, reproducible benchmark before any competitor comparison — none is claimed yet.

The harness has been validated end to end against real data via a small-scale preflight run (download → train → checkpoint → predictions → report), which found and fixed several real integration bugs along the way. The full benchmark run is not complete yet — no results are published. See benchmarks/massspecgym/README.md for the full protocol and current status.


Scientific caveats

  • masstrust controls observed or bounded risk under the chosen calibration procedure on the provided validation data. It does not guarantee correctness on out-of-distribution spectra.
  • Risk control is calibrated on the validation set provided. If the test distribution differs (different instrument, adduct type, compound class), guarantees may not transfer.
  • The experimental crc method assumes i.i.d. calibration data and binary 0/1 annotation loss. Verify these assumptions hold for your dataset before relying on the stated guarantee.
  • Small calibration sets (< ~20 queries) may produce very conservative thresholds or no valid threshold at all (reported as threshold = +inf, i.e. abstain on everything).
  • masstrust does not claim clinical validity or regulatory compliance.

References

  • Angelopoulos, A. N., Bates, S., Fisch, A., Lei, L., & Schuster, R. (2022). Conformal Risk Control. arXiv:2208.02814. — basis for the crc calibration method.
  • Geifman, Y., & El-Yaniv, R. (2017). Selective classification for deep neural networks. NeurIPS. — foundational selective prediction framework.

License

Licensed under either of:

at your option.

Metadata

Release files for masstrust 0.3.0

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

Source distribution (sdist)

Source distribution for masstrust 0.3.0
File Size Uploaded
masstrust-0.3.0.tar.gz 70.8 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for masstrust 0.3.0
File Interpreter ABI Platform
masstrust-0.3.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl CPython 3.14 CPython 3.14 macOS 10.12+ x86-64, macOS 10.12+ universal2 (ARM64, x86-64), macOS 11.0+ ARM64 Details
masstrust-0.3.0-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
masstrust-0.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.9 CPython 3.9 Linux glibc 2.17+ x86-64 Details

Total release size: 1.5 MB

Release files / masstrust-0.3.0.tar.gz

Download URL masstrust-0.3.0.tar.gz
Size 70.8 kB
Tags Source
SHA-256 checksum
How to use checksums
87cbe8bb71778890c958d80ae8c198779c031e0935c3b071b7bf49c7eeb0d77f
BLAKE2b-256 checksum
How to use checksums
bff1f2ee802e7dd0530f082701a14d997bf69c48382e8ac3531136ce6e5230a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 13, 2026.

Transparency log

Release files / masstrust-0.3.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl

Download URL masstrust-0.3.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Size 725.6 kB
Tags CPython 3.14 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
43552544b8d094678396695eb073de3cdb45d0afb688d806a1b845627a02a20f
BLAKE2b-256 checksum
How to use checksums
329e926cb8b745e406502ef3a6b0bbba965f2123006fe0239b5d7ea56bab9e1f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 13, 2026.

Transparency log

Release files / masstrust-0.3.0-cp312-cp312-win_amd64.whl

Download URL masstrust-0.3.0-cp312-cp312-win_amd64.whl
Size 276.4 kB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
a870d9c939bc1673a0002046c4705a218b2f9745a49a4d8e491464286f8e8cfc
BLAKE2b-256 checksum
How to use checksums
3d70940cc123fa07ebcd14b3a92be3e365f6830b81fcc091d03c1a326baec05b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 13, 2026.

Transparency log

Release files / masstrust-0.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL masstrust-0.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 424.5 kB
Tags CPython 3.9 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
9e4aa2b884a8ce57fc397ab308c086b5e5f1e66f1ddaf5cc6b3b9c58465760b8
BLAKE2b-256 checksum
How to use checksums
e647b8ec2aa667601565b6700a3a65c23fcb6b39d1a61081eac10a5b7dea5882
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

4 release files

0.2.0

4 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