combinr reimplements only the evidence-combining algorithms from
PASA and
EVidenceModeler as a
single self-contained Rust binary. This reimplementation was made to be agnostic
to input source, and also accepts a wide variety of input file types,
specifically GTF, GFF3, or BAM.
- Combine multiple transcript-alignment sources into one non-redundant
assembly set (
assemble). A faithful port of PASA's C++ assembler and its orientation wrapper. - Model alternative splicing between the resulting isoforms
(
assemble --alt-splice: retained intron, alternate donor/acceptor, transcription-start / polyA within an intron, exon skipping, alternate terminal exons);assemble --gene-pred --genomeadditionally reconciles an external gene-prediction CDS onto the isoforms to derive CDS + 5'/3' UTRs. - Build consensus gene models (
consensus) by integrating weighted heterogeneous evidence (ab-initio gene predictions, protein alignments, transcript alignments) into one best-scoring coding gene structure per locus, via a frame-aware gene-structure dynamic program. A reimplementation of EVidenceModeler's core algorithm.
The two families are complementary, named by what they consolidate: assemble
merges compatible alignments and keeps alternatives (transcript-level isoforms);
consensus weighs competing evidence and selects one model (a gene-level
coding structure).
- No canonical splice-site bias. combinr deliberately omits PASA's
sequence-based splice validation, which matches intron dinucleotides against
GT‑AG/GC‑AG/AT‑AC to infer strand and drop "non-consensus" alignments. Splice
junctions are defined purely by exon position, and strand is taken verbatim
from the input. Whatever introns and strand your upstream tools produce are
honored as-is. This extends to
consensus: EVM normally scans the genome for canonical GT‑AG splice sites and ATG/stop codons to gate candidate exons whereas combinr does not. The candidate splice/start/stop sites are evidence-derived (the union of intron boundaries and CDS bounds seen across the inputs), and in-frame stops are detected with the configurable genetic code, never a hard-coded table. - The genome FASTA is only needed for the ORF/UTR step. Assembly and alt-splice classification are purely coordinate-based.
- ORFs come from an external gene prediction, not from translating the transcripts. Given a gene-prediction GFF3 with already-mapped CDS, an isoform that matches the prediction inherits the CDS verbatim; a divergent isoform is projected from the same start codon and translated along its own exon structure to the first in-frame stop (a premature stop becomes that isoform's ORF stop). Multiple coding models per locus are supported.
- Genetic code. Divergent-isoform stop detection uses the standard code
(NCBI table 1) by default; pass
--genetic-code/-g <id>to theassemblereconcile step orconsensusfor a non-standard table. Every assigned NCBI table is supported:1-6,9-16,21-33(ids 7, 8, and 17–20 were never assigned and are rejected). Codes are grouped by stop-codon set, since only stop assignments affect ORF bounds; matching isoforms inherit the predicted CDS and are unaffected by the code. The context-dependent tables (27/28/31, whose codons are dual sense/stop) use NCBI's declared stop set. Translation halts at the first such codon, the conservative choice for CDS bounds. - Consensus never blanks a locus (
consensus). EVM eliminates a gene whose coding/noncoding score ratio falls below a threshold, which can leave a locus empty. combinr computes the same metric but flags low-support genes (low_support=true) and keeps them by default. A false negative is treated as worse than a false positive. Pass--strictfor EVM's drop-it behavior. (combinr also fixes EVM's bug where an eliminated gene's span still blocked the re-search for nested/adjacent genes.) - Both strands, independently.
consensusruns the trellis on each strand by reverse-complementing the locus, so the two strands are explored fully everywhere; an antisense locus can yield genes on both strands rather than EVM's single best-strand pick. The genome FASTA is required here (for the across-junction stop check and CDS projection) but, per the note above, never gates which sites are allowed.
combinr is a single self-contained binary with no system dependencies: no
Perl, no database, and no htslib (BAM reading comes from the pure-Rust
noodles crate). It runs on Linux and
macOS. Install a prebuilt binary (no toolchain required), or build from source.
The quickest option, and it needs no Rust toolchain. This downloads a prebuilt,
statically-linked binary for your platform, verifies its checksum, installs it,
and updates your PATH:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/BFL-lab/combinr/releases/latest/download/combinr-installer.sh | shreleases/latest/download/… always resolves to the newest release; pin a
specific version by using its tag instead:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/BFL-lab/combinr/releases/download/v0.1.1/combinr-installer.sh | shPrefer to do it by hand (or on Windows)? Grab the tarball for your target — or the
.zip on Windows — from the Releases page,
check it against the bundled .sha256, and put combinr on your PATH.
Building needs a Rust toolchain, 1.85 or newer (the crate uses the 2024 edition). The easiest way to get one is rustup:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # then: rustc --versionThen clone and build:
git clone https://github.com/BFL-lab/combinr
cd combinr
cargo build --release
# optimized binary lands at: target/release/combinr
./target/release/combinr --helpThe first build compiles all dependencies and takes a few minutes; later builds
are incremental. Drop --release for a faster-compiling debug build under
target/debug/. To install it onto your PATH (into ~/.cargo/bin):
cargo install --path . # from a local checkout
cargo install --git https://github.com/BFL-lab/combinr # or straight from git
combinr --versionThe suite is self-contained. It checks combinr against committed golden references, so no PASA or EVidenceModeler installation is required:
cargo test# 1) Combine sources into a non-redundant GFF3 (multiple -i, GTF/GFF3/BAM, mixed)
combinr assemble -i sampleA.gtf -i sampleB.gff3 -i reads.bam > assemblies.gff3
# 2) Also classify alternative splicing (isoform GFF3 to stdout, events to a TSV)
combinr assemble -i sampleA.gtf -i sampleB.gff3 --alt-splice --events events.tsv > isoforms.gff3
# 3) Reconcile an external CDS into CDS/UTR (add --genetic-code/-g for a non-standard table)
combinr assemble -i samples.gtf --gene-pred p.gff3 --genome genome.fa --events events.tsv > out.gff3
# 4) Consensus gene models from weighted evidence (EvidenceModeler-style)
combinr consensus --weights weights.txt --genome genome.fa \
--gene-predictions abinitio.gff3 \
--protein-alignments proteins.gff3 \
--transcript-alignments transcripts.gff3 > consensus.gff3consensus options: --strict (drop low-support genes instead of flagging),
--genetic-code/-g, --flank <bp> (per-locus DP-window padding, default 10000.
Only widens the window for UTR/end placement, never merges loci), and the
off-by-default EVM heuristics --research-intergenic <bp> (re-search intergenic gaps
for missed genes), --search-long-introns <bp> (find nested genes in long introns),
--extend-terminal-stop (extend protein/transcript 3' ends to a stop to complete genes),
--peak-augment (boost intergenic scores near start/stop evidence peaks),
--promote-transcript-orfs (at loci with only transcript evidence and no consensus CDS,
find the longest ORF in the transcripts and emit it, tagged support=transcript_orf),
--alt-splice (also emit each consensus locus's alternative transcript isoforms as extra
mRNAs, with CDS derived from the consensus (inherited if matching, re-projected from the
consensus start if divergent) and write a region-tagged alt-splice events TSV to
--events), plus --repeats <gff3> (mask repeats from scoring).
assemble tuning: --fuzzlength <bp> (default 20) and the quality filters
--min-avg-per-id and --min-intron (off by default) plus --max-intron
(defaults to 100000 bp, matching PASA's MAX_INTRON_LENGTH, to drop spurious
long-range junctions; pass --max-intron 0 to disable the cap).
Shared options, given after the subcommand name (e.g. combinr consensus --threads 4 ...): --output/-o <file> (write models to a file instead of stdout,
the default), --format gff3|gtf, --threads <n> (default 4; 0 = all cores),
and --verbose. The > out.gff3 redirections above are interchangeable with
-o out.gff3.
- Transcript files (
-i, repeatable; GTF, GFF3, and/or BAM, mixed allowed). GFF3 is accepted ascDNA_match+Targetalignment rows or as plaingene/mRNA/exonmodels; GTF asexonrows grouped bytranscript_id. Each file's basename is recorded as provenance. - BAM (auto-detected by the
.bamextension): a cDNA/transcript-to-genome alignment from a splice-aware mapper (segemehl,minimap2 -ax splice, STAR, HISAT2, …). One primary mapped record becomes one transcript; exon blocks come from the CIGAR (aNskip is an intron;D/Istay within an exon); the transcribed strand is read from theXS:Atag (else left undetermined and resolved during assembly). CRAM and plain-text SAM are not supported. - Gene-prediction GFF3 (
--gene-pred, theassemblereconcile step only):CDSrows grouped by mRNAParent. - Genome FASTA (
--genome, theassemblereconcile step andconsensus). - Consensus evidence (
consensus): a--weightsfile (three whitespace columnsCLASS TYPE WEIGHT, whereCLASSisPROTEIN/TRANSCRIPT/ABINITIO_PREDICTION/OTHER_PREDICTIONandTYPEmatches the GFF column-2 source) plus the evidence GFF3s:--gene-predictions(read asCDSrows grouped byParent),--protein-alignmentsand--transcript-alignments(read as match chains carryingTarget=). All repeatable.
- Transcript models to stdout as GFF3 (
gene/mRNA/exon, plusCDS/five_prime_UTR/three_prime_UTRwhen the ORF step runs) or GTF (--format gtf). Each transcript carriessources=(provenance) andcontains=(contributing accessions). - Alt-splice event report as a TSV (
--events) with the event type, coords, the two isoforms, and after the ORF step, the region (5'UTR / CDS / 3'UTR). - Consensus gene models (
consensus) to stdout as GFF3gene/mRNA/exon/CDSwith CDS phases (the exon structure is the coding structure). Each mRNA carriesscore,score_ratio,coding_length,low_support, andpartial5/partial3.
combinr is validated against the original PASA, using committed golden
references so the test suite is self-contained, no PASA code runs at test
time. Just cargo test.
- Assembly (Algorithm 1): the original C++ PASA binary's output on every
pasa_cpp_sample_input*is committed undertests/data/assembler/.tests/golden_assembler.rsruns three combinr code paths (raw assembler, orientation wrapper, full GFF3 pipeline) and asserts each reproduces the golden assembly set. - Alternative splicing (Algorithm 2): PASA's real
CDNA::Alternative_splice_comparerwas run on combinr's emitted isoforms and its events committed undertests/data/altsplice/(thestringtie.gtffixture alone exercises all seven event types).tests/golden_altsplice.rsasserts combinr's classification reproduces them exactly. - Consensus: because
consensusdeliberately diverges from EVM (non-canonical sites + two independent per-strand trellises), there is no byte-for-byte EVM parity to assert. Insteadtests/golden_consensus.rsis a self-golden: it runsconsensuson EVidenceModeler'stesting/data set (vendored undertests/data/consensus/) and asserts the GFF3 matches a committed frozen snapshot, and that the output is deterministic. This guards against regressions in combinr's own algorithm.
The PASA goldens are a frozen snapshot, generated once from a PASA checkout; the
one-off generation tooling is preserved in git history. combinr has also been run on the full
sample_data (a 6.5 MB cDNA_match GFF3 → 1334 assemblies; with the bundled gene
annotations + genome → CDS/UTR-annotated isoforms; alt-splice cross-check: 371/371
events identical to PASA).