phred-consensus
A dependency-free Python library and CLI for Phred-aware Bayesian consensus calling from aligned, same-length reads. It combines observations in log space, reports posterior-derived consensus qualities, and offers an explicit unweighted majority baseline.
Install
Python 3.11 or newer is required.
python -m pip install phred-consensus
For development and verification:
python -m pip install -e '.[dev]'
ruff check .
pytest --cov=phred_consensus --cov-branch --cov-fail-under=100
Quickstart
FASTQ records are grouped by the portion of each record ID before --delimiter (default /). Groups must be contiguous and all reads within a group must be aligned and the same length.
phred-consensus reads.fastq --output-format jsonl
phred-consensus reads.fastq --delimiter ':' --min-posterior 0.99 -o consensus.fastq
The TSV format is headerless: group, sequence, and Phred+33 quality string.
family1 ACGT IIII
family1 ACGA III$
phred-consensus reads.tsv --input-format tsv --output-format fastq
Use a nonuniform prior with all four positive weights:
phred-consensus reads.tsv --input-format tsv --prior A=2,C=1,G=1,T=2
Library use:
from phred_consensus import call_consensus
result = call_consensus(
["ACGT", "ACGA"],
[[40, 40, 40, 40], [40, 40, 40, 3]],
min_posterior=0.95,
)
print(result.sequence, result.qualities, result.posteriors)
Algorithm
flowchart LR; F[FASTQ/TSV reads] --> G[group by ID prefix]; G --> L[per-position log-likelihoods<br/>e = 10^-Q/10]; P[prior, log-sum-exp] --> L; L --> W[posterior per base]; W --> O[consensus + Phred qualities]
For an observed base $b$ with Phred score $Q$, the error probability is $e=10^{-Q/10}$. The likelihood is $1-e$ when a candidate equals $b$, and $e/3$ for each of the other three bases. For candidate $x$ at a position, the implementation computes
$$ \log P(x \mid \text{reads}) = C + \log P(x) + \sum_i \log P(b_i \mid x,Q_i) $$
and normalizes the four candidate scores with a log-sum-exp calculation. Ties resolve deterministically in A,C,G,T order. The winning posterior $p$ becomes consensus quality $\min(60,\operatorname{round}(-10\log_{10}(1-p)))$. If $p$ is below --min-posterior, the emitted base is N, while the posterior-derived quality is retained.
Reproducible capability evidence
The repository includes a deterministic synthetic benchmark with 2,000 truth bases and five reads per base: three low-quality Q3 reads and two high-quality Q30 reads. Errors are sampled according to the same Phred model, with incorrect bases chosen uniformly. On seed 2026, the Bayesian caller has 1 mismatch (0.05%), while unweighted majority vote has 128 mismatches (6.4%).
Reproduce the exact result:
phred-consensus --benchmark --seed 2026 --bases 2000
The benchmark test asserts determinism and that the Bayesian mismatch count is lower; it does not treat this synthetic scenario as a claim about every biological dataset.
Input validation
The caller rejects empty groups, unequal sequence/quality lengths, unequal aligned-read lengths, symbols outside A/C/G/T, quality values outside 0–93, malformed FASTQ structure, non-Phred+33 text, blank or malformed TSV rows, invalid priors, invalid posterior thresholds, and noncontiguous repeated groups. Errors are reported on stderr with a nonzero status.
Verification
Mutation testing
The deterministic suite generated 764 mutants and killed 729 (95.42%). The 35 survivors were individually reviewed and are behavior-equivalent under the validated public contract, not missed mutants; there were zero suspicious results and zero timeouts. Mutation testing also exposed duplicate prior keys being silently overwritten; the parser now rejects them.
| Reviewed equivalent rationale | Count |
|---|---|
Validated equal-length inputs make strict/non-strict zip behavior identical |
15 |
Parser delimiter, maxsplit, separator, and sentinel identities |
12 |
| Additive log-prior normalization constants cancel from posterior ratios | 3 |
| The posterior-quality floor is hidden by integer rounding and the quality-60 cap | 1 |
| The infinity guard differs only for unreachable validated states | 1 |
| UTF-8/type-only/default identities and benchmark PRNG equality | 3 |
| Total reviewed equivalents | 35 |
Reproduce the campaign from the repository root:
source .venv/bin/activate
mutmut run
mutmut results
Limitations
- Reads must already be aligned, ungapped, and equal length within a group.
- Only canonical
A/C/G/Tobservations are accepted; ambiguity symbols and gaps are deliberately rejected. - FASTQ qualities use Sanger Phred+33 and are limited to the representable range 0–93.
- Under the stated substitution model, Q0 means
P(correct)=0: the observed symbol is anti-evidence rather than an uninformative observation. Datasets that use Q0 as a missing-quality sentinel must filter or recode those observations before calling consensus. - The model assumes conditionally independent read errors and uniform substitution among the three incorrect bases; it does not model indels, strand bias, context effects, correlated PCR errors, or platform-specific confusion matrices.
- Input is processed without network access. Completed groups are yielded incrementally; memory is bounded by the largest group plus the set of prior group names used to reject noncontiguous repeats.
- The 60 cap prevents misleadingly extreme output qualities and means very strong posterior distinctions are intentionally compressed.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file phred_consensus-1.0.0.tar.gz.
File metadata
- Download URL: phred_consensus-1.0.0.tar.gz
- Upload date:
- Size: 17.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
84d0bc80af6ec099861b8cd1cc73e4a32fea9335dbfff2e6a59f23718ffda741
|
|
| MD5 |
516f66beea418a658800fb98e8b349f1
|
|
| BLAKE2b-256 |
59822c9f5fc27db1e970420c78bd0bb3e834dd7151b823ceb281da52e53b8eba
|
Provenance
The following attestation bundles were made for phred_consensus-1.0.0.tar.gz:
Publisher:
publish.yml on bmouler/phred-consensus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
phred_consensus-1.0.0.tar.gz -
Subject digest:
84d0bc80af6ec099861b8cd1cc73e4a32fea9335dbfff2e6a59f23718ffda741 - Sigstore transparency entry: 2443165226
- Sigstore integration time:
-
Permalink:
bmouler/phred-consensus@4bc06076cc50ee26880df1a909e47406dc5eb155 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/bmouler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4bc06076cc50ee26880df1a909e47406dc5eb155 -
Trigger Event:
release
-
Statement type:
File details
Details for the file phred_consensus-1.0.0-py3-none-any.whl.
File metadata
- Download URL: phred_consensus-1.0.0-py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c1cd8ddbd1fa05c6cc309fac8344e741fe16819964f1dc171c402f6891d0566
|
|
| MD5 |
9d5c6a3a4aff4f81eeaee2ba2a5c38db
|
|
| BLAKE2b-256 |
b188171279cf647b18c46d6f72dbe028b059a1d6a80f93914f6e5cb5bd48888a
|
Provenance
The following attestation bundles were made for phred_consensus-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on bmouler/phred-consensus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
phred_consensus-1.0.0-py3-none-any.whl -
Subject digest:
7c1cd8ddbd1fa05c6cc309fac8344e741fe16819964f1dc171c402f6891d0566 - Sigstore transparency entry: 2443165285
- Sigstore integration time:
-
Permalink:
bmouler/phred-consensus@4bc06076cc50ee26880df1a909e47406dc5eb155 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/bmouler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4bc06076cc50ee26880df1a909e47406dc5eb155 -
Trigger Event:
release
-
Statement type: