Skip to content

Ben consolidation 1 - #134

Merged
Psy-Fer merged 16 commits into
mainfrom
ben-consolidation
Jul 25, 2026
Merged

Ben consolidation 1#134
Psy-Fer merged 16 commits into
mainfrom
ben-consolidation

Conversation

@Psy-Fer

@Psy-Fer Psy-Fer commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

This PR consolidates a number of PRs from @BenjaminDEMAILLE

Each was tested, and fixed where there were issues.

It closes #106 #115 #117 #120 #121 #126 #127 #128

BenjaminDEMAILLE and others added 16 commits July 23, 2026 20:00
CI's clippy advanced to 1.97 (new lints fail the `-D warnings` gate) and rustsec
flagged several advisories in the dependency tree. Both block all PRs.

Clippy:
- src/index/suffix_array.rs: assert!(x == 0) -> assert_eq! (manual_assert_eq)
- src/io/sam.rs, tests/alignment_features.rs: byte-slice literals -> byte
  strings, e.g. [b'S', b'M'] -> *b"SM" (byte_char_slices)
- src/quant/transcriptome.rs: if-let/else-return-None -> `?` (question_mark)

Security audit (Cargo.lock only, no manifest change):
- memmap2 0.9.10 -> 0.9.11 (RUSTSEC-2026-0186, out-of-bounds pointer offset)
- crossbeam-epoch 0.9.18 -> 0.9.20 (RUSTSEC-2026-0204, invalid pointer deref)
- anyhow 1.0.102 -> 1.0.104 (RUSTSEC-2026-0190, unsound downcast_mut)

No behavioural change. Unblocks CI for open and future PRs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add LICENSES/STAR_RS_LICENSE (STAR-rs MIT notice, Copyright (c) 2026 Benjamin
Demaille) and note it in LICENSES/README.md, for attribution of modules ported
from STAR-rs. STAR-rs is dual MIT-OR-Apache; ported code is taken under its MIT
option, compatible with this repo's MIT license.

Add docs-old/dev/porting-from-star-rs.md documenting the STAR-rs to
rustar-aligner type/module mapping, the licensing and cellranger reference-only
caveat, the determinism decision (adopt STAR-rs's thread-invariant, no-rand
model), and how to validate ports against native STAR via the existing test/
harness with DIVERGENCES.md as the acceptance spec.

This is the base of a series of themed, dependency-stacked PRs bringing the
STAR-rs feature surface (WASP, clipping, signal tracks, genome transforms,
STARlong, STARsolo, ...) into rustar-aligner.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oid)

Port STAR-rs's genomeGenerate-time genome transform from STAR-rs
`crates/star-index/src/transform.rs` (itself a port of STAR's
`Genome_transformGenome.cpp`): substitute a VCF's alleles into the reference
genome before the suffix array is built, so reads carrying the alternate
allele map with fewer mismatches.

Scoped to Haploid only (Diploid — duplicating the genome into `_h1`/`_h2`
haplotypes — is a follow-up), and to genomeGenerate only: with the only
supported `--genomeTransformOutput` (`None`, STAR's own default), the aligner
reports transformed-genome coordinates directly, so align-time back-transform
isn't needed and isn't implemented. `Parameters::validate` loudly rejects
Diploid, an unknown transform type, a missing VCF, or combining a transform
with a GTF (STAR itself doesn't support that combination either).

- src/genome/transform.rs: parse_vcf_haploid (first ALT allele per record, no
  genotype filtering, STAR's overlap filter), transform_one_chromosome
  (per-chromosome allele substitution in chromosome-local coordinates; indels
  shift length and split the block map), transform_chromosomes (globalizes
  blocks using compute_chr_starts run once over original lengths and once over
  transformed lengths), blocks_to_tsv (transformGenomeBlocks.tsv, STAR's
  reverse-conversion format).
- src/genome/mod.rs: extract compute_chr_starts (STAR's bin-padding formula)
  out of Genome::from_fasta as a shared helper; hook the transform in
  from_fasta right after FASTA parsing (indel-resized chromosomes flow
  unchanged through the existing padding/RC-buffer logic below); add
  Genome::transform_blocks, written to transformGenomeBlocks.tsv by
  write_index_files when present.
- src/lib.rs: genome_generate() also writes the untransformed index to
  `<genomeDir>/OriginalGenome/` (STAR's own layout) by re-running
  generate_streaming with the transform disabled and the output directory
  redirected.
- src/params/mod.rs: --genomeTransformType (None/Haploid), --genomeTransformVCF.

Adding the `transform_blocks` field to `Genome` required threading `None`
through ~28 existing test-only struct literals across align/chimeric/io/
junction/quant/signal (mechanical, no behavior change).

Verified end-to-end on a tiny fixture beyond the unit tests: genomeGenerate
with --genomeTransformType Haploid produces a transformed Genome file with the
VCF allele substituted at the right offset, an untouched OriginalGenome/, and
a transformGenomeBlocks.tsv with the correct identity block; the three
validation rejections (missing VCF, Diploid, unknown type) all fire correctly.

Gate green: cargo build --all-targets, clippy -D warnings, fmt, 478 tests (4
new transform unit tests). Byte-level validation against native STAR via the
test/ harness is a separate step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oid)

Genotype-aware transform ported from STAR-rs: parse_vcf_diploid reads the
sample GT field per haplotype, transform_genome_diploid runs the Haploid
substitution once per haplotype and concatenates chr_h1/chr_h2 with new_start
offset by hap0's padded genome length. Rejects Diploid at validate() time no
longer; both Haploid and Diploid now share the same genomeGenerate path,
writing one OriginalGenome/ for both haplotypes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Parses chr/start/end/[strand] TSV files (1-based intron first/last
base) into the same raw junction shape produced by GTF parsing, and
unions them with any --sjdbGTFfile junctions before sjdb insertion
into the genome/SA. Works standalone (no GTF): junction_db and the
sjdb files are built whenever the union is non-empty; only the
transcriptome index requires a GTF.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Makes the GTF attribute keys for gene name/biotype configurable
(multi-candidate, last-match-in-list wins, matching STAR's
find_attr_list), and fixes a latent gap where the hardcoded lookup
only ever checked gene_biotype: GENCODE-style GTFs using gene_type
fell back to the literal "MissingGeneType" even though STAR's
default candidate list (gene_type, gene_biotype) would have picked
it up.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ports STAR's bamRemoveDuplicates (STAR-rs star-io/bam.rs): marks PCR
duplicates in a coordinate-sorted BAM by grouping reads into maximal
overlapping clusters, pairing unique mappers by name, and keeping
only the highest-AS pair per (start, flag, S-extended CIGAR) key.
NH/AS tags are required. Writes <prefix>Processed.out.bam.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…d records)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Threads a configurable HI-tag start value through all SAM/BAM record
writers (SE multimapper, PE mate records, transcriptome projection,
half-mapped fallback): default 1 matches STAR; 0 matches the
CellRanger convention. The secondary FLAG bit stays rank-based and
is unaffected by the shift.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds the missing RunMode::LiftOver variant (a prior stub referenced
it without defining it, so this run mode never compiled) and ports
STAR's Chain::chainLoad / Chain::liftOverGTF (STAR-rs chain.rs) to
lift --sjdbGTFfile coordinates through the first --genomeChainFiles
chain file. Writes <prefix>GTFliftOver_1.gtf plus a .unlifted
sidecar for features that fall in an unaligned gap.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@Psy-Fer Psy-Fer self-assigned this Jul 25, 2026
@Psy-Fer
Psy-Fer enabled auto-merge (squash) July 25, 2026 07:31
@Psy-Fer
Psy-Fer merged commit b38ce58 into main Jul 25, 2026
10 checks passed
@Psy-Fer
Psy-Fer deleted the ben-consolidation branch July 25, 2026 07:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants