Skip to content

STAR & Salmon

After quality control and trimming, the next step is to figure out where each read came from and how many reads map to each gene. There are two fundamentally different approaches.

Genome alignment maps each read to a position on the reference genome. This produces a BAM file containing the genomic coordinates of every aligned read. You then count how many reads fall within each gene’s boundaries.

Pseudo-alignment skips the genome entirely. It maps reads directly to a set of known transcripts. This is much faster because it avoids the computational cost of full genomic alignment. It produces transcript-level abundance estimates directly.

STAR performs genome alignment. Salmon can work in two modes: standalone pseudo-alignment to the transcriptome, or quantification from an existing BAM file. The nf-core/rnaseq pipeline uses both tools together by default. STAR aligns reads to the genome. Then Salmon quantifies from the STAR-aligned BAM, applying its bias correction models for accurate counts.

STAR stands for Spliced Transcripts Alignment to a Reference. It was designed specifically for RNA-seq data. The key challenge with aligning RNA-seq reads to a genome is that mRNA does not contain introns. A single read can span an exon-exon junction, meaning part of the read maps to one exon and part maps to another exon that is thousands or millions of bases away in the genome.

General-purpose DNA aligners like BWA cannot handle this. They expect reads to map contiguously. STAR solves this by performing splice-aware alignment. It identifies where reads cross exon boundaries and aligns the two portions to the correct exons.

STAR uses a two-step strategy called seed searching and clustering.

First, it finds the longest substring of the read that maps exactly to the genome. This is the first seed. Then it searches for additional seeds from the unmapped portions of the read. If a read spans a splice junction, the first seed will map to one exon and the second seed will map to the adjacent exon.

STAR then clusters these seeds, identifies the splice junctions they imply, and produces a full alignment that accounts for intron-spanning reads.

STAR supports a two-pass alignment mode that improves splice junction detection.

In the first pass, STAR aligns all reads and discovers novel splice junctions that are not in the gene annotation. In the second pass, these newly discovered junctions are added to the genome index, and all reads are re-aligned using the expanded junction set.

Two-pass mode is especially useful for detecting rare or novel splice events. The nf-core/rnaseq pipeline uses two-pass mode by default.

Before alignment, STAR needs a genome index. This pre-processed version of the reference genome allows fast lookup during alignment. Building the index requires the genome FASTA file and a gene annotation GTF file.

Terminal window
STAR --runMode genomeGenerate \
--genomeDir star_index \
--genomeFastaFiles GRCh38.primary_assembly.fa \
--sjdbGTFfile gencode.v44.annotation.gtf \
--sjdbOverhang 99 \
--runThreadN 8

The --sjdbOverhang parameter should be set to your read length minus 1. For 100bp reads, use 99. For 150bp reads, use 149.

Building a human genome index requires approximately 30 GB of RAM and takes 30 to 60 minutes. The resulting index is around 25 GB on disk. This is a one-time cost. You reuse the same index for all samples.

When using nf-core/rnaseq, you do not need to build the index manually. The pipeline handles it automatically if you specify a reference genome with --genome.

Terminal window
STAR --runMode alignReads \
--genomeDir star_index \
--readFilesIn sample_R1.fastq.gz sample_R2.fastq.gz \
--readFilesCommand zcat \
--outSAMtype BAM SortedByCoordinate \
--twopassMode Basic \
--outFileNamePrefix sample_ \
--runThreadN 8

STAR produces a sorted BAM file containing the aligned reads. This file records the genomic position of each read, whether it mapped to a splice junction, and the alignment quality.

The BAM file is the primary output of STAR. It is a compressed binary file that stores the alignment position of every read. You can use BAM files for:

  • Visualization in genome browsers like IGV to inspect read coverage and splice junctions at specific loci.
  • Counting with tools like featureCounts to produce gene-level count matrices.
  • Variant calling to identify RNA editing events or expressed genetic variants.
  • Quality assessment to check for alignment biases, strand specificity, and gene body coverage.

Salmon takes a fundamentally different approach. Instead of aligning reads to the genome, it maps reads to the transcriptome. This is a set of all known transcript sequences. Salmon does not need to know where those transcripts fall on the genome.

Salmon uses a technique called selective alignment. It builds a lightweight index of the transcriptome and quickly determines which transcript each read most likely came from. This is not a full base-by-base alignment. Instead, Salmon identifies which transcripts are compatible with each read and uses a statistical model to estimate abundance.

The statistical model accounts for several biases that affect RNA-seq data:

  • GC content bias. Fragments with extreme GC content are less likely to be sequenced. Salmon corrects for this.
  • Sequence-specific bias. Certain nucleotide sequences near fragment ends are over-represented or under-represented due to enzymatic preferences during library preparation.
  • Positional bias. In some protocols, fragments from the 3-prime end of transcripts are over-represented.

By modeling these biases, Salmon produces more accurate abundance estimates than simple read counting.

First, build a Salmon index from the transcriptome:

Terminal window
salmon index \
-t gencode.v44.transcripts.fa \
-i salmon_index \
--threads 8

Then quantify:

Terminal window
salmon quant \
-i salmon_index \
-l A \
-1 sample_R1.fastq.gz \
-2 sample_R2.fastq.gz \
-o salmon_output \
--threads 8 \
--validateMappings

The -l A flag tells Salmon to automatically detect the library type. The --validateMappings flag enables selective alignment mode for improved accuracy.

Salmon produces a quant.sf file with transcript-level abundance estimates:

Name Length EffectiveLength TPM NumReads
ENST00000456328 1657 1463.000 0.000000 0.000
ENST00000450305 632 438.000 0.000000 0.000
ENST00000488147 1351 1157.000 28.526713 112.000

Salmon in alignment-based mode (nf-core default)

Section titled “Salmon in alignment-based mode (nf-core default)”

When used inside the nf-core/rnaseq star_salmon workflow, Salmon does not perform pseudo-alignment. Instead, it reads the BAM file produced by STAR and quantifies transcripts from those alignments. This is called alignment-based mode.

Terminal window
salmon quant \
--alignments sample_Aligned.toTranscriptome.out.bam \
-t transcriptome.fa \
-l A \
-o salmon_output \
--threads 8

The --alignments flag tells Salmon to quantify from a BAM file instead of performing its own mapping. This mode still applies Salmon’s GC bias correction, positional bias correction, and expectation-maximization model. You get the accuracy of Salmon’s statistical model combined with STAR’s splice-aware alignment.

Salmon in pseudo-alignment mode is dramatically faster than STAR. A typical human RNA-seq sample with 30 million reads takes 20 to 30 minutes with STAR but only 3 to 5 minutes with Salmon. This speed difference matters when processing dozens or hundreds of samples.

STAR alignment followed by featureCounts produces gene-level counts. Each gene gets a single count representing the total number of reads that fall within any of its exons. This is straightforward but loses information about which specific transcript isoforms are expressed.

Salmon produces transcript-level counts. Each individual transcript gets its own count. This preserves isoform-level information but introduces a challenge: many reads are compatible with multiple transcripts from the same gene. Salmon uses a statistical model called expectation-maximization to assign these ambiguous reads probabilistically.

For differential expression analysis, gene-level counts are usually sufficient. Tools like DESeq2 and limma-voom work with gene-level count matrices. You can aggregate Salmon transcript counts to the gene level using the tximeta or tximport R packages.

Use STAR when you need BAM files. If you want to visualize alignments in a genome browser, call variants from RNA-seq data, or analyze read coverage across specific genomic regions, you need BAM files. Only genome alignment produces them.

Use Salmon when speed matters and you only need counts. If your goal is differential expression analysis and you do not need BAM files, Salmon is faster and produces accurate gene-level estimates when aggregated with tximeta.

Use both (nf-core default). The nf-core/rnaseq pipeline uses the star_salmon aligner by default. In this mode, STAR performs the genome alignment and produces BAM files. Salmon then quantifies transcript abundance from the STAR-aligned BAM, not via pseudo-alignment. Salmon reads the BAM file and applies its bias correction models to produce accurate transcript-level estimates. This combines STAR’s splice-aware alignment with Salmon’s statistical quantification. You get BAM files for visualization and accurate counts for differential expression in one run.

If you use STAR for alignment and want gene-level counts directly from the BAM file, featureCounts is the standard tool. It counts how many reads overlap with each gene’s exonic regions as defined by a GTF annotation file.

Terminal window
featureCounts \
-a gencode.v44.annotation.gtf \
-o counts.txt \
-T 8 \
-p --countReadPairs \
-s 2 \
sample_Aligned.sortedByCoord.out.bam

The -p --countReadPairs flags tell featureCounts to count read pairs rather than individual reads for paired-end data. The -s 2 flag specifies reverse-stranded library preparation, which is the most common protocol.

featureCounts produces a tab-separated file with one row per gene and one column per sample. This matrix can be loaded directly into DESeq2 or limma-voom for differential expression analysis.

Now that you understand how reads are aligned and quantified, the next page covers QC & Filtering of the count matrix.