genome: --genomeType SuperTranscriptome - #161
Open
BenjaminDEMAILLE wants to merge 3 commits into
Open
Conversation
…x, sjdbInsertSave Four genome-side STAR parameters, each honest about what it does. `--genomeType` accepts `Full` and refuses `Transcriptome` and `SuperTranscriptome`. Those need a different index layout entirely; accepting them would build an ordinary genome under another name. `--genomeTransformOutput` accepts `None` and refuses `SAM` and `SJ`. Mapping alignments back to the original coordinate space is not implemented, and a silent no-op here is worse than a failure: it would report transformed coordinates as though they were original ones, and nothing downstream could tell. `--sjdbInsertSave` accepts `Basic` and `None`. The inserted-junction files are not retained either way. `--genomeSuffixLengthMax` is accepted and inert, with the reason recorded on the flag: the suffix-array builder exposes no comparison bound, and STAR uses this only to cap work on highly repetitive genomes. The index is identical either way, so ignoring it changes no output byte — which is the standard this codebase already applies to the other inert knobs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Condenses the genome to the union of its annotated exons, STAR's `GTF_superTranscript.cpp`. Overlapping exons merge, the merged intervals concatenate, overlapping transcripts group into superTranscripts, one per condensed chromosome. The index then covers only exonic sequence and introns cannot be crossed, because they are not there. The condensed genome comes back with its annotation already addressed to it — `st0`, one-based, plus strand — so the transcriptome tables, the junction extractor and the suffix array consume it unchanged. Nothing downstream needs to know the genome was condensed. `Genome::from_chromosomes` is split out of `from_fasta` for the same reason: these chromosomes are built, not read. Four files are written alongside the index, as STAR writes them: the superTranscript and transcript sequences, the collapsed junction table, and `fullGenome/conversionToFullGenome.tsv`, which is what makes condensed coordinates translatable back. D20, deliberately not reproduced. STAR condenses the sequence before it fills the reverse-complement half of its genome buffer, so every minus-strand exon reads the allocation's spacer bytes and minus-strand superTranscripts come out as uninitialised memory. Here that half is already filled, so a minus-strand exon yields its actual reverse complement. Reproducing STAR would mean writing code whose correct behaviour is to emit garbage, and a test that asserts it. The test asserts the hand-derived reverse complement instead, and that no 0x00 byte reaches the output. One behaviour worth stating because it looks like a missing feature: a transcript's own intron leaves no junction behind. With nothing else annotated between two exons, they end up contiguous in the condensed genome, and there is no gap left to record. A junction survives only when another transcript's exon separates them. Both cases have a test. Verified end to end: the 20 kb test genome with its two annotated 50 bp exons condenses to a single 100 bp `st0`; a read straddling the 200 bp intron aligns `50M` at position 26, and the conversion map names the two source intervals at 10000 and 10250.
CONTRIBUTING.md asks for one theme per PR and for the description to match the diff; the transform-output flag, its test and its changelog entry moved to their own PR, and the D20 divergence moved into the root DIVERGENCE.md.
This was referenced Jul 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
--genomeType SuperTranscriptome: condense the genome to the union of its annotated exons.What changed
Overlapping exons are merged, the merged intervals concatenated, and the transcripts that overlap grouped into superTranscripts — one per condensed chromosome (
st0,st1, ...). The index then covers only exonic sequence, and introns cannot be crossed because they are not there. Requires--sjdbGTFfile;--genomeType Transcriptomeis still refused.Four files are written alongside the index, as STAR writes them:
superTranscriptSequences.fasta,transcriptSequences.fasta,superTranscriptSJcollapsed.tsv, andfullGenome/conversionToFullGenome.tsv.The design decision that kept it small
condensereturns the annotation already rewritten into condensed coordinates —seqnameis the superTranscript, positions are 1-based within it, strand is+. The transcriptome tables, the junction extractor and the suffix-array builder then consume it unchanged; nothing downstream knows the genome was condensed.Genome::from_chromosomesis split out offrom_fastafor the same reason: these chromosomes are built rather than read.Divergence
DIVERGENCE.md§1.2, needing sign-off. STAR condenses the sequence before it fills the reverse-complement half of its genome buffer, so every minus-strand exon reads the allocation's spacer bytes and minus-strand superTranscripts come out as uninitialised memory. Here that half is already filled, so a minus-strand exon yields its actual reverse complement.This one is not a corner case: it affects any annotation with minus-strand transcripts. A superTranscript built here holds real sequence where STAR's holds spacer bytes, so for those transcripts the two indices differ and alignments against them are not comparable. Reproducing STAR would mean writing code whose correct behaviour is to emit garbage, and a test asserting it.
One behaviour that looks like a gap and is not
A transcript's own intron leaves no junction behind. With nothing else annotated between two exons they end up contiguous in the condensed genome, so there is no gap left to record. A junction survives only when another transcript's exon separates them. Both cases have a test.
Verification
End to end (
test_genome_type_supertranscriptome_condenses_to_exons): the 20 kb test genome with its two annotated 50 bp exons condenses to a single 100 bpst0; a read straddling the 200 bp intron aligns50Mat position 26;conversionToFullGenome.tsvnames the two source intervals at 10000 and 10250.Unit tests in
src/genome/supertranscript.rs:exons_are_concatenated_and_the_intron_disappearsthe_annotation_comes_back_in_condensed_coordinatesoverlapping_exons_are_merged_oncea_junction_is_recorded_when_another_exon_separates_the_twodisjoint_transcripts_become_separate_supertranscriptsminus_strand_supertranscript_is_reverse_complement_not_spacer— the divergencethe_conversion_map_has_one_block_per_merged_intervala_gtf_with_no_usable_exon_is_an_errorGate: 569 lib + 22 integration tests,
cargo clippy --all-targets -- -D warnings,cargo fmt --check, MSRV 1.89 — all green.Output-neutral for
--genomeType Full, which is the default and every existing run.Output neutrality, measured
10k yeast SE reads (CONTRIBUTING's dataset) through this branch and through
origin/main, both at default flags: the SAM records are byte-identical (9724 each; the two files differ only in the@PGCL:line, which records the binary path).Split out of #109 following the one-theme rule in CONTRIBUTING.md; #160 has the transform back-output and #109 keeps the libsais builder.