featureCounts is a read counting program from the Subread package that assigns aligned reads to genomic features such as genes, exons, or promoters.
# Conda (recommended)
conda install -c bioconda subread
# Ubuntu/Debian
sudo apt install subread
# From source
wget https://sourceforge.net/projects/subread/files/subread-2.0.6/subread-2.0.6-Linux-x86_64.tar.gz
tar xzf subread-2.0.6-Linux-x86_64.tar.gz
export PATH=$PATH:$(pwd)/subread-2.0.6-Linux-x86_64/bin
Tell your AI agent what you want to do: - "Count reads in my BAM files using featureCounts" - "Generate a gene count matrix from my aligned samples" - "Run featureCounts on stranded paired-end data"
"Run featureCounts on my aligned BAM files using the GRCh38 GTF annotation"
"Count reads at the gene level for all samples in my data/ directory"
"Count reads with reverse-stranded library prep (TruSeq Stranded)"
"Help me determine the strandedness of my RNA-seq data"
"Count at the transcript level instead of gene level"
"Run featureCounts allowing multi-mapping reads"
| Parameter | Description | Default |
|---|---|---|
-a |
Annotation file (GTF/GFF/SAF) | Required |
-o |
Output file | Required |
-t |
Feature type to count | exon |
-g |
Attribute for grouping | gene_id |
-s |
Strandedness (0/1/2) | 0 (unstranded) |
-p |
Paired-end mode | Off |
--countReadPairs |
Count fragments not reads | Off |
-T |
Number of threads | 1 |
-M |
Count multi-mappers | Off |
-O |
Count overlapping features | Off |
| Library Type | -s Value |
Examples |
|---|---|---|
| Unstranded | 0 | Older non-directional Illumina |
| Forward (read 1 sense) | 1 | Ligation/directional (e.g. NSR) |
| Reverse (read 1 antisense) | 2 | dUTP, Illumina TruSeq Stranded, NEBNext Directional (most common) |
The wrong -s does not error; it silently assigns ~5-20% instead of ~80-90%. Determine it empirically (RSeQC infer_experiment.py, the STAR ReadsPerGene.out.tab columns 3 vs 4, or trying -s 0/1/2 and picking the highest Assigned), never from the kit name alone.
featureCounts \
-p --countReadPairs \
-s 2 \
-T 8 \
-a Homo_sapiens.GRCh38.gtf \
-o gene_counts.txt \
sample1.bam sample2.bam sample3.bam
featureCounts \
-s 0 \
-T 8 \
-a annotation.gtf \
-o gene_counts.txt \
*.bam
featureCounts is a gene-level counter. Grouping by -g transcript_id with -O is NOT valid transcript quantification: isoform-ambiguous reads (most reads) are either discarded or double-counted across shared exons, so the per-transcript numbers are biased. For transcript-level abundance and DTE/DTU, use alignment-free EM quantification (rna-quantification/alignment-free-quant) and the transcript-aware testing in alternative-splicing/isoform-switching. Use -g overrides only for genuinely distinct meta-features (e.g. custom intervals), not isoforms.
The main output file has these columns: 1. Geneid - Gene identifier from GTF 2. Chr - Chromosome(s) for the gene 3. Start - Start position(s) 4. End - End position(s) 5. Strand - Strand(s) 6. Length - Total exon length 7+ Sample columns - Raw counts per sample
Check the .summary file for:
- Assigned - Reads successfully counted (target: >70%)
- Unassigned_NoFeatures - Reads not overlapping any feature
- Unassigned_Ambiguity - Reads overlapping multiple features
- Unassigned_MultiMapping - Multi-mapped reads (if not using -M)
-p --countReadPairs for paired-end data - without this, each read in a pair is counted separatelyinfer_experiment.py