Aligns RNA-seq reads to a genome with HISAT2, the splice-aware aligner whose hierarchical graph FM-index runs at roughly a quarter of STAR's memory (~7 GB for human), whose SNP/haplotype graph index reduces reference bias in the index itself, and whose MAPQ is GATK-friendly (60 for unique, no 255 problem). Use when RNA alignment must fit a memory-constrained machine, when feeding StringTie/Cufflinks transcript assembly via --dta, or when a SNP-aware graph index is wanted for allele-robust map...
Scanned 9/5/2026
Install to Claude Code
npx -y skills add FridrichMethod/awesome-skills --skill hisat2-alignment --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Hisat2 Alignment?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/fridrichmethod-hisat2-alignment)More formats (shields.io, HTML) on the badges page.
---
name: bio-read-alignment-hisat2-alignment
description: Aligns RNA-seq reads to a genome with HISAT2, the splice-aware aligner whose hierarchical graph FM-index runs at roughly a quarter of STAR's memory (~7 GB for human), whose SNP/haplotype graph index reduces reference bias in the index itself, and whose MAPQ is GATK-friendly (60 for unique, no 255 problem). Use when RNA alignment must fit a memory-constrained machine, when feeding StringTie/Cufflinks transcript assembly via --dta, or when a SNP-aware graph index is wanted for allele-robust mapping. Feature-rich/high-RAM RNA alignment and fusion detection are star-alignment; DE on known transcripts only should skip alignment for rna-quantification/alignment-free-quant; the QC gate and contig-naming reconciliation are alignment-files; counting is rna-quantification.
tool_type: cli
primary_tool: HISAT2
---
## Version Compatibility
Reference examples tested with: hisat2 2.2+, samtools 1.19+
Before using code patterns, verify installed versions match. If versions differ:
- CLI: `<tool> --version` then `<tool> --help` to confirm flags
If code throws ImportError, AttributeError, or TypeError, introspect the installed
package and adapt the example to match the actual API rather than retrying.
# HISAT2 Alignment -- Graph-Indexed Spliced Mapping at a Quarter of STAR's Memory
**"Align my RNA-seq reads with low memory"** -> Map reads across exon-exon junctions with a hierarchical graph FM-index that fits a small machine -- because HISAT2 buys splice-aware alignment at ~7 GB instead of STAR's ~30 GB, its MAPQ is GATK-friendly, and its SNP-graph index can remove reference bias before a single read is mapped.
- CLI: `hisat2 -p 8 -x index -1 R1.fq.gz -2 R2.fq.gz | samtools sort -@4 -o aligned.bam -`
Scope: low-memory RNA splice-aware mapping with HISAT2 -- index building (plain / annotation-aware / SNP-graph), strandedness, the --dta transcript-assembly mode, and manual two-pass. Contig naming and the QC gate -> alignment-files. Feature-rich/high-RAM RNA alignment, native gene counts, and fusion detection -> star-alignment. Counting reads over genes -> rna-quantification. DE without a BAM -> rna-quantification/alignment-free-quant. OUT OF SCOPE: DNA (bwa-alignment/bowtie2-alignment), long reads (long-read-sequencing/long-read-alignment), HLA typing (HISAT-genotype, a separate tool).
## The Single Most Important Modern Insight
1. **The hierarchical graph FM-index is why HISAT2 exists: near-STAR spliced alignment at ~1/4 the RAM.** HISAT2 uses one global FM-index to anchor a read plus ~55,000 small local graph FM-indexes (each ~56 kb), and extends a spliced read within the relevant local index rather than stitching genome-wide as STAR does. Most introns fit inside one local window, so spliced extension is a cheap local operation -- the resident human index is ~4-7 GB vs STAR's ~30 GB. That memory win is the reason to choose HISAT2; the cost is slightly lower novel-junction sensitivity than STAR two-pass and no native gene counts or fusion output.
2. **The SNP/haplotype graph index removes reference bias in the index, and the MAPQ is GATK-friendly.** A `hisat2-build --snp --haplotype` (or the prebuilt `grch38_snp` index) encodes millions of known variants as alternate graph nodes, so a read carrying a known alt allele traverses the alt node with no mismatch penalty -- the bias that over-counts the reference allele is removed structurally, for all those sites at once, without a per-sample personalized reference. (Private/novel variants still cause bias, so rigorous ASE still needs WASP or a personalized reference.) HISAT2 also assigns unique reads MAPQ 60 (not STAR's 255), so its output goes into GATK without the reassignment STAR needs.
3. **--dta is for transcript assembly only, and using it for plain counting throws away reads.** `--dta` raises the minimum anchor length required to report a de-novo spliced alignment, deliberately suppressing short-anchor junction reads -- because StringTie/Cufflinks cannot reliably assemble a transcript from a 3-5 bp anchor and such reads produce spurious isoforms. That trades junction sensitivity for assembly cleanliness, so `--dta` belongs only in a transcript-assembly pipeline; for plain gene counting it just discards usable junction reads. Strandedness (`--rna-strandness RF` for the common dUTP/TruSeq case) must also be set, or sense reads land in "no feature" and counts roughly halve.
## How HISAT2 Splices (the mechanism in brief)
A read is seeded by the global FM-index, then the relevant ~56 kb local FM-index is selected and the read is extended across the junction within it: the unaligned remainder is anchored in the local index and extended by repeated FM-index extension. Because the spliced extension is a narrow, local operation rather than a genome-wide seed-cluster-stitch, HISAT2 needs far less RAM than STAR -- and evaluates a narrower set of candidate splice configurations, which is the source of both its speed/memory advantage and its slightly lower novel-junction sensitivity.
## Tool Taxonomy
| Mode / index | Citation | Mechanism / role | When |
|--------------|----------|------------------|------|
| `hisat2-build` (plain) | Kim 2019 Nat Biotechnol 37:907 | genome-only HGFM | quick index; junctions supplied at align time |
| `hisat2-build --ss --exon` | Kim 2019 | annotation-aware HGFM (better short-anchor placement) | when build RAM allows; or use prebuilt `*_tran` indexes |
| `hisat2-build --snp --haplotype` | Kim 2019 | SNP/haplotype graph (reference-bias reduction) | allele-robust mapping; the `grch38_snp` index |
| `hisat2` alignReads | Kim 2019 | spliced alignment via local FM-index extension | the default RNA-to-genome mapping |
| `--dta` / `--dta-cufflinks` | HISAT2 manual | longer-anchor reporting for assemblers | StringTie / Cufflinks transcript assembly ONLY |
| manual two-pass (`--novel-splicesite-*`) | HISAT2 manual | discover then reuse novel junctions | novel-junction sensitivity (cohort: merge across samples) |
| STAR | Dobin 2013 Bioinformatics 29:15 | higher RAM, native counts, fusions, 2-pass | feature-rich RNA (route OUT) -> star-alignment |
| Salmon / kallisto | Patro 2017 Nat Methods 14:417 | alignment-free quantification | DE on known transcripts only (route OUT) -> rna-quantification/alignment-free-quant |
## Decision Tree by Scenario
| Scenario | Recommended | Why |
|----------|-------------|-----|
| RNA-seq on a memory-constrained machine (<32 GB) | HISAT2 | ~7 GB graph index vs STAR's ~30 GB |
| StringTie/Cufflinks transcript assembly | HISAT2 `--dta` | longer-anchor reporting the assemblers need |
| Allele-robust mapping / known-variant-aware | HISAT2 SNP-graph index (`grch38_snp`) | alt-allele reads traverse graph nodes without penalty |
| RNA variant calling | HISAT2 (MAPQ 60) then GATK SplitNCigarReads | GATK-friendly MAPQ, no 255 reassignment |
| Need native gene counts, fusions, or top novel-junction sensitivity | route OUT to star-alignment | HISAT2 has no GeneCounts/chimeric output |
| DE on known transcripts only | route OUT to rna-quantification/alignment-free-quant | Salmon/kallisto are faster and model multimapping |
| Plain gene-level counting | HISAT2 without `--dta` | `--dta` discards short-anchor junction reads |
Default when uncertain: HISAT2 with `--rna-strandness RF` (verify the strand), streamed to a coordinate-sorted BAM; add `--dta` only for transcript assembly.
## Build Index
```bash
# Plain genome-only index (cheap; supply junctions at align time with --known-splicesite-infile).
hisat2-build -p 8 reference.fa hisat2_index
# Annotation-aware (better short-anchor placement). NOTE: a full human --ss --exon build needs a LOT of RAM;
# prefer the prebuilt grch38_tran / grch38_snp_tran indexes, or pass junctions at align time instead.
hisat2_extract_splice_sites.py annotation.gtf > splice_sites.txt
hisat2_extract_exons.py annotation.gtf > exons.txt
hisat2-build -p 8 --ss splice_sites.txt --exon exons.txt reference.fa hisat2_index
```
## Basic Alignment with Strandedness
```bash
# RF = reverse-stranded (dUTP / Illumina TruSeq Stranded mRNA -- the common case). Verify, do not assume.
hisat2 -p 8 -x hisat2_index --rna-strandness RF \
--rg-id sample1 --rg SM:sample1 --rg PL:ILLUMINA \
-1 reads_1.fq.gz -2 reads_2.fq.gz \
--new-summary --summary-file sample.summary.txt | \
samtools sort -@ 4 -o aligned.sorted.bam -
samtools index aligned.sorted.bam
# Single-end stranded: --rna-strandness R (reverse) or F (forward). Unstranded: omit the flag.
```
## For StringTie / Cufflinks (transcript assembly)
```bash
# --dta reports longer anchors the assemblers need; use ONLY for assembly, not for plain counting.
hisat2 -p 8 -x hisat2_index --rna-strandness RF --dta \
-1 r1.fq.gz -2 r2.fq.gz | samtools sort -@ 4 -o aligned.bam -
```
## Manual Two-Pass (cohort novel-junction discovery)
```bash
# Pass 1: discover novel junctions per sample.
for r1 in *_R1.fq.gz; do
base=$(basename "$r1" _R1.fq.gz); r2=${r1/_R1/_R2}
hisat2 -p 8 -x hisat2_index --novel-splicesite-outfile "${base}.novel.txt" \
-1 "$r1" -2 "$r2" -S /dev/null
done
# Merge across the cohort so every sample sees the same junction set (avoids a per-sample junction batch effect).
cat *.novel.txt | sort -u > cohort.novel.txt
# Pass 2: re-align every sample with the shared novel-junction set.
for r1 in *_R1.fq.gz; do
base=$(basename "$r1" _R1.fq.gz); r2=${r1/_R1/_R2}
hisat2 -p 8 -x hisat2_index --rna-strandness RF --novel-splicesite-infile cohort.novel.txt \
-1 "$r1" -2 "$r2" | samtools sort -@ 4 -o "${base}.bam" -
done
```
## Key Parameters
| Parameter | Default | Description |
|-----------|---------|-------------|
| -x | -- | index BASENAME |
| -1 / -2 / -U | -- | paired / single-end reads |
| --rna-strandness | unstranded | FR / RF / F / R (dUTP/TruSeq = RF / R) |
| --dta / --dta-cufflinks | off | longer anchors for StringTie / Cufflinks (assembly only) |
| --known-splicesite-infile | -- | supply junctions at align time (cheap-index alternative to --ss build) |
| --novel-splicesite-outfile / -infile | -- | manual two-pass |
| --max-intronlen | 500000 | shorter than STAR's effective ~1 Mb; raise for long-intron genes |
| -k | 5 (HFM) / 10 (HGFM) | max alignments reported per read |
| --no-softclip / --no-spliced-alignment | off | force end-to-end / disable splicing (DNA mode) |
## Per-Method Failure Modes
### --dta used for plain counting
**Trigger:** `--dta` on a run whose downstream is featureCounts/htseq, not StringTie. **Mechanism:** `--dta` suppresses short-anchor junction reads. **Symptom:** lower junction-read recovery and counts than a non-dta run. **Fix:** drop `--dta` for counting; keep it only for transcript assembly.
### Wrong strandedness
**Trigger:** omitting or mis-setting `--rna-strandness`. **Mechanism:** the XS strand tag is mislabeled and sense reads are assigned to "no feature." **Symptom:** counts ~halved; StringTie builds transcripts on the wrong strand. **Fix:** infer strand (RSeQC infer_experiment.py, or STAR GeneCounts) and set RF for dUTP/TruSeq.
### --ss --exon human build runs out of RAM
**Trigger:** a full human annotation-aware build on a small machine. **Mechanism:** building the annotation-aware HGFM needs far more RAM than a plain build. **Symptom:** the build is killed (OOM). **Fix:** use a prebuilt `grch38_tran`/`grch38_snp_tran` index, or build plain and pass junctions at align time via `--known-splicesite-infile`.
### max-intronlen too small for long-intron genes
**Trigger:** the default `--max-intronlen 500000` on genes with introns near or above ~1 Mb. **Mechanism:** junctions longer than the cap are not formed. **Symptom:** long-gene junction reads soft-clipped or mismapped. **Fix:** raise `--max-intronlen` for organisms/genes with very long introns.
### Genome/GTF contig-naming mismatch
**Trigger:** the BAM uses `chr1`/`chrM` but the counting GTF uses `1`/`MT`. **Mechanism:** no overlapping features. **Symptom:** zero counts despite a high alignment rate. **Fix:** reconcile naming (same source/release) -> alignment-files.
## Quantitative Thresholds
| Threshold | Source | Rationale |
|-----------|--------|-----------|
| HISAT2 human graph index RAM ~4.3 GB plain / ~6.7 GB SNP | Kim 2019 (approximate) | the ~1/4-of-STAR footprint that motivates choosing HISAT2 |
| --max-intronlen 500000 default | HISAT2 manual | shorter than STAR's ~1 Mb; raise for long-intron genes |
| --rna-strandness RF for dUTP/TruSeq | library-prep chemistry | the overwhelmingly common stranded protocol |
| unique-read MAPQ 60 (since v2.0.4) | HISAT2 manual / changelog | GATK-friendly; no 255 reassignment needed |
| -k 5 (HFM) / 10 (HGFM) | HISAT2 manual | max reported alignments differs by index type |
## Common Errors
| Error / symptom | Cause | Solution |
|-----------------|-------|----------|
| Counts ~halved, wrong-strand transcripts | missing/incorrect `--rna-strandness` | infer strand; set RF for dUTP/TruSeq |
| Lower counts than expected | `--dta` used for plain counting | drop `--dta` unless assembling transcripts |
| `--ss --exon` build killed (OOM) | full human annotation-aware build | use a prebuilt index or `--known-splicesite-infile` at align time |
| Long-gene junction reads clipped | `--max-intronlen` too small | raise it for long-intron genes |
| 0 counts despite high alignment rate | genome/GTF contig-naming mismatch | reconcile `chr1` vs `1` (same source/release) -> alignment-files |
| "Could not locate a HISAT2 index" | `-x` given a `.ht2` file | pass the index basename |
| htseq-count miscounts HISAT2 output | htseq wants name-sorted input | pipe to `samtools sort -n` for htseq; featureCounts accepts coordinate order |
## References
- Kim D, Paggi JM, Park C, Bennett C, Salzberg SL. 2019. Graph-based genome alignment and genotyping with HISAT2 and HISAT-genotype. *Nat Biotechnol* 37:907-915.
- Kim D, Langmead B, Salzberg SL. 2015. HISAT: a fast spliced aligner with low memory requirements. *Nat Methods* 12:357-360.
- Dobin A, Davis CA, Schlesinger F, et al. 2013. STAR: ultrafast universal RNA-seq aligner. *Bioinformatics* 29:15-21.
- Patro R, Duggal G, Love MI, Irizarry RA, Kingsford C. 2017. Salmon provides fast and bias-aware quantification of transcript expression. *Nat Methods* 14:417-419.
## Related Skills
- star-alignment - Feature-rich, higher-RAM splice-aware alternative (native counts, fusions)
- bwa-alignment - DNA short-read mapping (when reads do not cross junctions)
- read-qc/rnaseq-qc - RNA destination metrics: rRNA, gene-body coverage, strandedness
- read-qc/fastp-workflow - Trim adapters/poly-A before alignment
- alignment-files/bam-statistics - flagstat/idxstats QC gate; what a high mapping rate hides; contig naming
- rna-quantification/featurecounts-counting - Count aligned reads over genes
- rna-quantification/alignment-free-quant - Salmon/kallisto when only known-transcript DE is needed
- differential-expression/deseq2-basics - Downstream DE from the count matrix
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!