poa-consensus
A pure-Rust banded Partial Order Alignment (POA) library for building consensus sequences from a set of reads.
POA aligns reads into a directed acyclic graph (DAG) using affine-gap dynamic programming and extracts consensus by following the heaviest (most-supported) path. Insertions and deletions create branches resolved by read support.
Target use cases: short tandem repeat (STR) loci, amplicon consensus, structural variants, per-locus nanopore or HiFi read sets (50 bp to ~20 kb with banded DP). Can be paired with bedpull for building a consensus of extracted sequences.
The nearest alternative on crates.io is
poasta(Broad Institute, pure Rust, gap-affine A* alignment), which excels at larger graphs such as bacterial genes and HLA loci. For STR reads where graphs stay small and throughput across many loci matters, banded DP is faster. Both crates are pure Rust with no C dependencies.
Usage
[]
= "0.1"
Functional API
use ;
let reads: = vec!;
// Single-allele consensus; seed_idx seeds the graph with reads[seed_idx].
let result = consensus?;
println!;
// Multi-allele: returns one Consensus per detected allele.
let alleles = consensus_multi?;
// Adaptive two-pass: inspects graph statistics after pass 1 and automatically
// chooses multi-allele split, noise tightening, or semi-global switch for pass 2.
// Always returns a Vec<Consensus> (one element for single-allele outcomes).
let alleles = consensus_adaptive?;
Stateful API
use ;
let reads: & = &;
let mut graph = new?;
for read in &reads
let consensus = graph.consensus?;
let stats = graph.stats;
println!;
The stateful API lets you inspect graph state between reads and reuse pre-allocated buffers across calls, which is important for high-throughput per-locus pipelines.
Seed selection
use ;
// Automatically find the shortest fully-spanning read using terminal k-mer anchors.
// Falls back to longest read when no cluster structure is detected.
// Returns Err(NoSpanningReads) when reads split into two non-overlapping groups.
let seed_idx = select_seed?;
let result = consensus?;
Orientation utilities
use ;
// Orient all reads to match the strand of reads[seed_idx] before POA.
let oriented = auto_orient;
Diagnostics
use ;
let result = consensus?;
let warnings = diagnose;
if !warnings.is_clean
diagnose checks four independent signals: read depth, coverage gaps, near-zero interior support, and structural competing alleles. All signals are also available as structured fields on ConsensusWarnings for programmatic handling.
CLI
cargo install poa-consensus --features cli
poa-consensus reads.fa # FASTA or FASTQ, auto-detected
poa-consensus reads.fa --multi # multi-allele mode
poa-consensus reads.fa --adaptive-band # recommended for reads > 1 kb
poa-consensus reads.fa --quiet # suppress warnings; errors always printed
Feature flags
| Flag | Adds |
|---|---|
cli |
Binary target; pulls in clap + noodles |
plot |
SVG visualisation helpers via kuva |
Default build: library only, zero external dependencies.
AI disclosure
This library was developed with AI assistance (Claude). Architecture decisions, testing, validation, and algorithm designs, are the author's own. AI tooling served as an accelerator over existing skill. The library originated from prototyping a POA implementation inside bladerunner, a nanopore STR detector and genotyper, and was spun out as a standalone crate when existing POA crates did not meet the throughput and API requirements of that use case.
License
MIT - James Ferguson 2026