Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,23 @@ Sections commonly used: Features, Bug fixes, Other changes.
glibc's malloc and per-thread heaps that return whole segments to
the OS when abandoned, so allocator cache size stays bounded.

- **`--genomeType SuperTranscriptome`** condenses the genome to the union
of its annotated exons: overlapping exons are merged, the merged
intervals concatenated, and overlapping transcripts 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 present. Requires `--sjdbGTFfile`.
Writes `superTranscriptSequences.fasta`, `transcriptSequences.fasta`,
`superTranscriptSJcollapsed.tsv` and
`fullGenome/conversionToFullGenome.tsv` alongside the index.

Diverges from STAR on minus-strand exons, deliberately. STAR condenses
the sequence before filling the reverse-complement half of its genome
buffer, so minus-strand superTranscripts read uninitialised memory;
here they hold the actual reverse complement. Recorded in
`docs-old/dev/divergences.md` and locked by a test asserting the
hand-derived sequence.

### Bug fixes

- **STARsolo `Gene` assignment now requires exon concordance**, matching
Expand Down
12 changes: 12 additions & 0 deletions DIVERGENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ This is the reason faithfulness is reported **tie-adjusted**. On the 10k yeast b

**Source.** `src/rng.rs`, `src/align/read_align.rs` (`per_read_seed`, `shuffle_tied_prefix`), `src/params/mod.rs` (`MultimapperOrder`). STAR: `ReadAlign_multMapSelect.cpp`, `ReadAlignChunk` RNG seeding.

### 1.2 `--genomeType SuperTranscriptome` minus-strand sequence

**What STAR does.** `GTF::superTranscript` builds the condensed sequence by reading the doubled genome buffer `G`, reflecting minus-strand exons into its second half. That half is not filled until roughly twenty-five lines later in `Genome_genomeGenerate.cpp`. Every minus-strand exon therefore reads the allocation's spacer bytes, and a minus-strand superTranscript comes out as uninitialised memory rather than sequence.

**What rustar-aligner does.** The reverse-complement half is already filled when condensing runs, so a minus-strand exon yields its actual reverse complement.

**Why.** STAR's output on this path is not a rule; it is a read of memory that has not been written. Reproducing it would mean writing code whose correct behaviour is to emit garbage, and a test asserting that garbage.

**Impact.** Any annotation containing minus-strand transcripts — which is essentially all of them. A superTranscript built here holds real sequence where STAR's holds spacer bytes, so the two indices differ for those transcripts and the alignments against them are not comparable.

**Source.** `src/genome/supertranscript.rs`, locked by `minus_strand_supertranscript_is_reverse_complement_not_spacer`, which asserts the hand-derived reverse complement of a non-palindromic exon and that no `0x00` byte reaches the output. STAR: `GTF_superTranscript.cpp`, `Genome_genomeGenerate.cpp`.

---

## 2. Cases where rustar-aligner outperforms STAR
Expand Down
20 changes: 18 additions & 2 deletions src/genome/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
pub mod fasta;
pub mod supertranscript;
pub mod transform;

use std::path::Path;

use crate::error::Error;
use crate::params::Parameters;

use fasta::parse_fasta_files;
use fasta::{Chromosome, parse_fasta_files};

/// STAR's genome spacing character (used for inter-chromosome padding).
const GENOME_SPACING_CHAR: u8 = 5;
Expand Down Expand Up @@ -213,10 +214,25 @@ impl Genome {
None
};

Self::from_chromosomes(&chromosomes, bin_nbits, transform_blocks)
}

/// Lay out a genome from chromosome sequences already in base codes:
/// pad each to a `2^chr_bin_nbits` boundary, then fill the
/// reverse-complement half.
///
/// [`from_fasta`](Self::from_fasta) is this plus FASTA parsing and the
/// VCF transform. `--genomeType SuperTranscriptome` uses it directly,
/// since its chromosomes are built rather than read.
pub fn from_chromosomes(
chromosomes: &[Chromosome],
bin_nbits: u32,
transform_blocks: Option<Vec<[u64; 3]>>,
) -> Result<Self, Error> {
// First pass: chromosome names/lengths, validating non-zero length.
let mut chr_name = Vec::new();
let mut chr_length = Vec::new();
for chrom in &chromosomes {
for chrom in chromosomes {
let len = chrom.sequence.len() as u64;
if len == 0 {
return Err(Error::Fasta(format!(
Expand Down
Loading
Loading