pipeline-rnaseq
Execute ENCODE RNA-seq pipeline from FASTQ to gene quantification and signal tracks. Child of pipeline-guide. Provides Nextflow execution with Docker and cloud deployment. Use when processing RNA-seq data with STAR alignment, RSEM/Kallisto quantification, or generating expression
Install
npx skills add https://github.com/ammawla/encode-toolkit/tree/main/plugin/skills/pipeline-rnaseq
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install ammawla-encode-toolkit@llmmart
git clone https://github.com/ammawla/encode-toolkit.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole ammawla/encode-toolkit collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
ENCODE RNA-seq Pipeline
When to Use
- User wants to run an RNA-seq processing pipeline from FASTQ to gene quantification
- User asks about "RNA-seq pipeline", "STAR alignment", "RSEM", "gene expression quantification", or "Kallisto"
- User needs to process bulk RNA-seq data with ENCODE-standard 2-pass STAR alignment
- Example queries: "process my RNA-seq FASTQs", "quantify gene expression from RNA-seq", "run STAR and RSEM on my data"
Execute the ENCODE RNA-seq processing pipeline from raw FASTQ files through splice-aware alignment, gene/transcript quantification, and strand-specific signal track generation. This skill provides a complete Nextflow DSL2 implementation following ENCODE uniform analysis standards.
Overview
RNA-seq measures transcriptome-wide gene expression by sequencing cDNA derived from cellular RNA. The ENCODE pipeline processes RNA-seq data through quality control, splice-aware alignment with STAR (2-pass mode), gene and transcript quantification with RSEM, optional fast pseudoalignment with Kallisto, and generation of strand-specific signal tracks as bigWig files.
Key design decisions: STAR 2-pass mode for maximum splice junction sensitivity, RSEM for accurate gene/transcript/isoform quantification including multi-mapped reads, stranded library protocol (dUTP/rf-stranded) as the ENCODE standard, and paired-end sequencing with a minimum of 30 million uniquely mapped reads per replicate.
Key Literature
| Reference | Journal | Year | DOI | Relevance |
|---|---|---|---|---|
| Dobin et al. "STAR: ultrafast universal RNA-seq aligner" | Bioinformatics | 2013 | 10.1093/bioinformatics/bts635 | Splice-aware aligner (~12,000 citations) |
| Li & Dewey "RSEM: accurate transcript quantification from RNA-Seq data" | BMC Bioinformatics | 2011 | 10.1186/1471-2105-12-323 | Gene/transcript quantification (~6,000 citations) |
| Bray et al. "Near-optimal probabilistic RNA-seq quantification" | Nature Biotechnology | 2016 | 10.1038/nbt.3519 | Fast pseudoalignment (~4,000 citations) |
| Wang et al. "RSeQC: quality control of RNA-seq experiments" | Bioinformatics | 2012 | 10.1093/bioinformatics/bts356 | RNA-seq QC suite (~3,500 citations) |
| ENCODE Project Consortium "Expanded encyclopaedias" | Nature | 2020 | 10.1038/s41586-020-2493-4 | ENCODE Phase 3 standards |
| Frankish et al. "GENCODE 2021" | Nucleic Acids Research | 2021 | 10.1093/nar/gkaa1087 | Gene annotation reference |
Pipeline Stages
FASTQ
├─> FastQC (raw reads)
└─> Trim Galore (+ FastQC on the trimmed reads)
├─> Kallisto (optional) ──────────> kallisto/<sample>/abundance.tsv
└─> STAR (2-pass)
├─> transcriptome BAM ─> RSEM ─> <sample>.genes.results / .isoforms.results
├─> bedGraph str1/str2 ─> bedGraphToBigWig ─> signal/<sample>_{plus,minus}.bw
└─> genome BAM ─> RSeQC (infer_experiment, read_distribution,
geneBody_coverage, inner_distance)
MultiQC <── FastQC (raw + trimmed), trimming reports, STAR Log.final.out,
RSEM .stat/, RSeQC infer_experiment + read_distribution
└─> qc/multiqc/multiqc_report.html
The Kallisto abundances, the gene body coverage and the inner distance files are published but are not part of the MultiQC report; read those files directly.
Stage Summary
| Stage | Tool | Input | Output | Reference |
|---|---|---|---|---|
| 1. QC & Trimming | FastQC, Trim Galore | Raw FASTQ | Trimmed FASTQ + FastQC reports | references/01-qc-trimming.md |
| 2. Alignment | STAR (2-pass) | Trimmed FASTQ | Genome BAM + Transcriptome BAM + bedGraph | references/02-star-alignment.md |
| 3. Quantification | RSEM, Kallisto | Transcriptome BAM / trimmed FASTQ | Gene/transcript counts, TPM, FPKM | references/03-quantification.md |
| 4. Signal Tracks | bedGraphToBigWig | STAR bedGraph | Strand-specific bigWig | references/04-signal-tracks.md |
| 5. QC Metrics | RSeQC, MultiQC | Genome BAM, logs | Strandedness, read distribution, gene body coverage | references/05-qc-metrics.md |
Input Requirements
Required Files
- RNA-seq FASTQ: paired-end reads matched by the
--readsglob (ENCODE standard; single-end with--single_end) - STAR genome index directory (
--star_index) - RSEM reference prefix (
--rsem_index) produced byrsem-prepare-reference - BED12 gene model for RSeQC (
--rseqc_bed) - Kallisto index file (
--kallisto_index) built with kallisto 0.50.1, unless--skip_kallistois set. kallisto 0.50.1 writes index version 13 and rejects an index built with 0.48 or earlier
There is no sample sheet: samples are the pairs that --reads matches, and the sample
ID is the shared prefix of each pair. The gene annotation is not a workflow parameter
and there is no --gtf; the GTF is consumed when the STAR and RSEM references are built
(references/02 and references/03), so the annotation is fixed by the index you pass in.
Library Strandedness
--strandedness takes one value for the whole run — reverse (default), forward or
none — and is validated before the first task. It drives three things at once: the RSEM
--strandedness flag, the kallisto strand flag, and which STAR bedGraph becomes which
signal track.
| Protocol | --strandedness |
RSEM receives | Kallisto receives | Signal tracks |
|---|---|---|---|---|
| dUTP (ENCODE standard), Illumina TruSeq Stranded | reverse |
--strandedness reverse |
--rf-stranded |
<sample>_plus.bw, <sample>_minus.bw |
| Directional ligation (some legacy protocols) | forward |
--strandedness forward |
--fr-stranded |
<sample>_plus.bw, <sample>_minus.bw |
| SMARTer / SMART-Seq2 and other unstranded kits | none |
--strandedness none |
no strand flag | <sample>_unstranded.bw |
There is no per-sample strandedness and the workflow does not detect it. RSeQC
infer_experiment.py runs as a post-hoc check and writes
qc/rseqc/<sample>.infer_experiment.txt. If the library type is unknown, run a first
pass, read that file (references/05 explains the output), and rerun with the correct
--strandedness — the RSEM counts, the kallisto abundances and the signal tracks all
depend on it, so a wrong value has to be corrected by rerunning, not by post-processing.
QC Thresholds
| Metric | Threshold | Produced by |
|---|---|---|
| Total sequenced reads | >=30M PE reads | fastqc/, star/<sample>.Log.final.out |
| Uniquely mapped reads | >=70% of input reads | star/<sample>.Log.final.out |
| Multi-mapped reads | <10% | star/<sample>.Log.final.out |
| Strandedness agreement | >90% for a stranded library | qc/rseqc/<sample>.infer_experiment.txt |
| Exonic rate | >60% | qc/rseqc/<sample>.read_distribution.txt |
| Gene body coverage | Relatively uniform (5'/3' bias <1.5) | qc/rseqc/<sample>.geneBody_coverage.geneBodyCoverage.txt |
Not computed by this workflow: rRNA rate, library duplication rate (beyond the sequence-level estimate inside the FastQC report), detected-gene counts, and saturation curves. references/05-qc-metrics.md gives the commands to run those by hand on the published BAM and RSEM output.
Read Depth Guidelines
| Application | Minimum Reads (PE) | Recommended | Notes |
|---|---|---|---|
| Gene-level expression | 20M | 30M | ENCODE minimum |
| Transcript-level expression | 40M | 60M | Isoform resolution requires more depth |
| Differential expression | 20M per sample | 30M per sample | 3+ biological replicates per condition |
| Novel junction discovery | 60M | 100M+ | STAR 2-pass mode benefits from depth |
| Fusion detection | 50M | 80M+ | Chimeric reads are rare; needs a separate STAR run (references/02) |
Execution
The versions the workflow runs are the ones in scripts/Dockerfile: STAR 2.7.11b,
RSEM 1.3.3, kallisto 0.50.1, samtools 1.19, RSeQC 5.0.3, Trim Galore 0.6.10, cutadapt 4.6,
MultiQC 1.21 and FastQC 0.12.1. The conda environment in bioinformatics-installer
(environments/rnaseq-env.yml) is a separate manual route pinned to the same versions of
STAR, RSEM, kallisto, samtools, RSeQC, Trim Galore, FastQC and MultiQC; it leaves cutadapt
to the Trim Galore package, adds salmon and subread, and does not carry
bedGraphToBigWig, which the signal-track step needs.
Every index flag is shown in the examples below because the defaults are bare names
resolved in the launch directory (GRCh38_star_index, GRCh38_rsem_index/GRCh38,
gencode.v38.kallisto.idx, hg38_RefSeq.bed for --genome GRCh38). The run stops
before the first task if any of them is missing. --kallisto_index is the one exception:
it is not read when --skip_kallisto is set.
Quick Start (local, Docker)
nextflow run scripts/main.nf -profile local \
--reads 'fastq/*_R{1,2}.fq.gz' \
--genome GRCh38 \
--star_index /ref/GRCh38_star_index \
--rsem_index /ref/GRCh38_rsem_index/GRCh38 \
--kallisto_index /ref/gencode.v38.kallisto.idx \
--rseqc_bed /ref/hg38_RefSeq.bed \
--strandedness reverse \
--outdir results/
SLURM HPC
nextflow run scripts/main.nf -profile slurm \
--container /path/to/pipeline-rnaseq.sif \
--slurm_queue normal \
--reads 'fastq/*_R{1,2}.fq.gz' \
--genome GRCh38 \
--star_index /ref/GRCh38_star_index \
--rsem_index /ref/GRCh38_rsem_index/GRCh38 \
--kallisto_index /ref/gencode.v38.kallisto.idx \
--rseqc_bed /ref/hg38_RefSeq.bed \
--outdir results/
Cloud
# Google Cloud Batch
nextflow run scripts/main.nf -profile gcp \
--container us-docker.pkg.dev/<project>/<repo>/pipeline-rnaseq:1.0.0 \
--gcp_project <project> \
--gcp_workdir gs://<bucket>/work \
--reads 'gs://<bucket>/fastq/*_R{1,2}.fq.gz' \
--genome GRCh38 \
--star_index gs://<bucket>/ref/GRCh38_star_index \
--rsem_index gs://<bucket>/ref/GRCh38_rsem_index/GRCh38 \
--kallisto_index gs://<bucket>/ref/gencode.v38.kallisto.idx \
--rseqc_bed gs://<bucket>/ref/hg38_RefSeq.bed \
--outdir gs://<bucket>/results
# AWS Batch
nextflow run scripts/main.nf -profile aws \
--container <account>.dkr.ecr.<region>.amazonaws.com/pipeline-rnaseq:1.0.0 \
--aws_queue <job-queue> \
--aws_workdir s3://<bucket>/work \
--reads 's3://<bucket>/fastq/*_R{1,2}.fq.gz' \
--genome GRCh38 \
--star_index s3://<bucket>/ref/GRCh38_star_index \
--rsem_index s3://<bucket>/ref/GRCh38_rsem_index/GRCh38 \
--kallisto_index s3://<bucket>/ref/gencode.v38.kallisto.idx \
--rseqc_bed s3://<bucket>/ref/hg38_RefSeq.bed \
--outdir s3://<bucket>/results
--outdir only sets where results are published; Google Batch and AWS Batch stage every
task through the work directory, and the workflow stops with an error if it or the
project/queue is missing.
Pipeline Parameters
| Parameter | Default | Description |
|---|---|---|
--reads |
required | Glob matching the FASTQ pairs, e.g. 'fastq/*_R{1,2}.fq.gz'. Quote it |
--genome |
GRCh38 |
GRCh38 or mm10; selects the default index names and nothing else |
--outdir |
./results |
Directory results are published to |
--single_end |
false |
Treat --reads as single files; kallisto then runs with the fixed --single -l 200 -s 20, and RSeQC inner_distance.py is skipped |
--strandedness |
reverse |
reverse, forward or none; one value for the whole run |
--skip_kallisto |
false |
Skip KALLISTO_QUANT; --kallisto_index is then not read |
--star_index |
GRCh38_star_index (mm10_star_index) |
STAR genome directory |
--rsem_index |
GRCh38_rsem_index/GRCh38 (mm10_rsem_index/mm10) |
RSEM reference prefix, not a directory; every file starting with it is staged |
--kallisto_index |
gencode.v38.kallisto.idx (gencode.vM27.kallisto.idx) |
kallisto index file; must be built with kallisto 0.50.1 (index version 13), not with 0.48 or earlier |
--rseqc_bed |
hg38_RefSeq.bed (mm10_RefSeq.bed) |
BED12 gene model used by all four RSeQC modules |
--chrom_sizes |
<star_index>/chrNameLength.txt |
Chromosome sizes for bedGraphToBigWig |
Infrastructure parameters (nextflow.config)
| Parameter | Default | Description |
|---|---|---|
--container |
encode-toolkit/pipeline-rnaseq:1.0.0 |
Image built from scripts/Dockerfile. Pass a registry image for gcp/aws, or a .sif file for slurm |
--max_cpus, --max_memory, --max_time |
16, 64.GB, 24.h |
Upper bounds applied to every process |
--slurm_queue, --slurm_account |
normal, none |
SLURM partition and account |
--gcp_project, --gcp_workdir |
none (both required for -profile gcp) |
Google Cloud project and gs:// work directory |
--gcp_location, --gcp_disk |
us-central1, 200.GB |
Google Batch region and per-task disk |
--aws_queue, --aws_workdir |
none (both required for -profile aws) |
AWS Batch job queue and s3:// work directory |
--aws_region, --aws_cli_path |
us-east-1, /home/ec2-user/miniconda/bin/aws |
AWS region, and the AWS CLI path inside the Batch AMI |
Cloud Cost Estimates
| Platform | Instance | Cost/Sample | Time/Sample | Notes |
|---|---|---|---|---|
| GCP | n1-highmem-8 | ~$3-6 | 2-4 hours | STAR index loading dominates; the gcp profile uses spot VMs |
| AWS | r5.2xlarge | ~$3-6 | 2-4 hours | r-series for STAR memory; spot recommended |
| Local | 8 cores, 36 GB | $0 | 3-6 hours | Docker required |
| SLURM | 8 cores, 36 GB | Varies | 2-4 hours | Singularity; pass the .sif with --container |
Memory note: nextflow.config asks for 36 GB for STAR_ALIGN (multiplied by the
attempt number on a retry, capped by --max_memory). The local executor refuses the task
on a machine with less, so a 32 GB host is not enough. If 36 GB is out of reach, rebuild the STAR index
with a larger --genomeSAsparseD (which shrinks the loaded index at some cost in
mapping speed) or move to a bigger machine. --limitGenomeGenerateRAM is a
genomeGenerate option and is not a parameter of this workflow.
Output Directory Structure
results/
fastqc/ # FastQC HTML/zip for raw and trimmed reads
trimmed/
<sample>_R1_val_1.fq.gz, <sample>_R2_val_2.fq.gz
<sample>_R1.fq.gz_trimming_report.txt # one per input file
star/
<sample>.Aligned.sortedByCoord.out.bam
<sample>.Aligned.sortedByCoord.out.bam.bai
<sample>.Aligned.toTranscriptome.out.bam # RSEM input
<sample>.Log.final.out
<sample>.SJ.out.tab
<sample>.ReadsPerGene.out.tab # STAR gene counts
<sample>.Signal.UniqueMultiple.str1.out.bg # plus str2 unless --strandedness none
<sample>.Signal.Unique.str1.out.bg # same signal, unique mappers only
rsem/
<sample>.genes.results # gene_id, TPM, FPKM, expected_count
<sample>.isoforms.results # transcript_id, TPM, FPKM, IsoPct
<sample>.stat/ # RSEM model statistics, read by MultiQC
kallisto/ # absent with --skip_kallisto
<sample>/abundance.tsv
<sample>/abundance.h5 # only from a kallisto build with HDF5 support
<sample>/run_info.json
signal/
<sample>_plus.bw, <sample>_minus.bw # or <sample>_unstranded.bw
qc/
rseqc/
<sample>.infer_experiment.txt
<sample>.read_distribution.txt
<sample>.geneBody_coverage.*
<sample>.inner_distance.* # paired-end only
multiqc/
multiqc_report.html
multiqc_data/
pipeline_info/
timeline.html, report.html, trace.txt # Nextflow execution reports
Common Pitfalls
1. Insufficient Memory for STAR
STAR loads the whole genome index into memory. STAR_ALIGN is configured for 36 GB, so a
32 GB machine will not schedule the task at all under -profile local. On shared HPC
systems, check the per-job memory limit before submitting.
2. Wrong Strandedness Setting
Using incorrect strandedness results in near-zero gene counts. If you see uniformly low
counts, read qc/rseqc/<sample>.infer_experiment.txt and rerun with the matching
--strandedness. ENCODE dUTP libraries are reverse stranded.
3. Using FPKM for Cross-Sample Comparison
FPKM values are not comparable across samples because they depend on total library composition. Use TPM (comparable across samples) or raw counts with DESeq2/edgeR normalization for differential expression.
4. Ignoring Multi-Mapped Reads
RSEM uses an expectation-maximization algorithm to probabilistically assign multi-mapped reads. This is critical for gene families and repetitive elements. Do not pre-filter multi-mappers before RSEM quantification.
5. Assuming rRNA Contamination Was Checked
High rRNA contamination (>10%) indicates failed rRNA depletion and reduces effective
sequencing depth. This workflow does not measure it — run the manual check in
references/05-qc-metrics.md against star/<sample>.Aligned.sortedByCoord.out.bam before
trusting the quantifications.
6. Not Using 2-Pass Mode for Novel Junctions
STAR 1-pass mode only uses annotated splice junctions. 2-pass mode first discovers novel
junctions then re-maps, critical for non-model organisms or samples with extensive
alternative splicing. This workflow always runs --twopassMode Basic.
Pipeline Scripts
| File | Description |
|---|---|
scripts/main.nf |
Nextflow DSL2 pipeline |
scripts/nextflow.config |
Execution profiles (local/slurm/gcp/aws) |
scripts/Dockerfile |
Docker build with STAR, RSEM, Kallisto, RSeQC |
ENCODE Data Integration
After running on your own data, compare with ENCODE reference:
# Find matching ENCODE RNA-seq experiments
encode_search_experiments(
assay_title="total RNA-seq",
organ="pancreas",
biosample_type="tissue"
)
# Download ENCODE gene quantifications for comparison
encode_batch_download(
download_dir="/data/encode_reference/",
output_type="gene quantifications",
assay_title="total RNA-seq",
organ="pancreas",
assembly="GRCh38"
)
# Download ENCODE signal tracks for browser visualization
encode_search_files(
file_format="bigWig",
assay_title="total RNA-seq",
organ="pancreas",
output_type="signal of unique reads"
)
Pitfalls & Edge Cases
- Strandedness must match library prep:
--strandednessfeeds RSEM, kallisto and the signal tracks. Using the wrong value can halve gene counts, assign reads to antisense genes, and swap the plus/minus bigWigs. - rRNA contamination: rRNA >10% wastes sequencing depth. Ribosomal depletion libraries should have <5%, poly-A selection libraries <1%. The workflow does not measure it; see references/05-qc-metrics.md for a manual count, or run Picard CollectRnaSeqMetrics outside the container.
- STAR 2-pass mode is required: The first pass discovers novel splice junctions; the second pass uses them. Single-pass STAR misses tissue-specific or rare splicing events, reducing sensitivity for differential exon usage.
- Gene-level vs transcript-level quantification: RSEM provides transcript-level estimates but gene-level aggregation is more robust for differential expression. Transcript-level analysis requires many more replicates (≥6).
- TPM normalization is not for cross-sample comparison: TPM normalizes within a sample but is NOT appropriate for comparing expression across conditions. Use DESeq2 size factors or TMM normalization for differential expression.
- Batch effects in multi-lab data: RNA-seq is highly sensitive to library prep method, sequencer, and lab. Always check for batch effects with PCA before combining datasets from different sources.
Walkthrough: Processing ENCODE RNA-seq from FASTQ to Gene Quantification
Goal: Process raw RNA-seq FASTQ files through the ENCODE pipeline to generate gene expression quantifications (TPM/FPKM) and signal tracks. Context: The ENCODE RNA-seq pipeline uses STAR 2-pass alignment and RSEM quantification, producing both gene-level and transcript-level expression estimates.
Step 1: Find RNA-seq experiment
encode_get_experiment(accession="ENCSR000CPR")
Expected output:
{
"accession": "ENCSR000CPR",
"assay_title": "total RNA-seq",
"biosample_summary": "K562",
"assembly": ["GRCh38"],
"bio_replicate_count": 2,
"status": "released"
}
Step 2: List FASTQ files
encode_list_files(experiment_accession="ENCSR000CPR", file_format="fastq")
Expected output (a JSON array of file records; fields abridged):
[
{"accession": "ENCFF200RN1", "file_format": "fastq", "output_type": "reads", "file_size_human": "3.2 GB", "biological_replicates": [1], "status": "released"},
{"accession": "ENCFF201RN2", "file_format": "fastq", "output_type": "reads", "file_size_human": "3.3 GB", "biological_replicates": [1], "status": "released"}
]
Step 3: Download and name the FASTQs so a read-pair glob can find them
encode_download_files(file_accessions=["ENCFF200RN1", "ENCFF201RN2"], download_dir="/data/rnaseq/fastq")
ENCODE names every FASTQ after its accession (ENCFF200RN1.fastq.gz), with no _R1/_R2
in the name, so the two files of a pair share no prefix and the --reads glob cannot pair
them. Link them into the shape the glob expects. Which mate an accession is comes from the
ENCODE file record on encodeproject.org, which carries paired_end (1 or 2) and
paired_with; the MCP file tools do not return those two fields:
cd /data/rnaseq/fastq
ln -s ENCFF200RN1.fastq.gz k562_rep1_R1.fq.gz
ln -s ENCFF201RN2.fastq.gz k562_rep1_R2.fq.gz
Step 4: Run the RNA-seq pipeline
nextflow run scripts/main.nf -profile local \
--reads '/data/rnaseq/fastq/k562_*_R{1,2}.fq.gz' \
--genome GRCh38 \
--star_index /ref/GRCh38_star_index \
--rsem_index /ref/GRCh38_rsem_index/GRCh38 \
--kallisto_index /ref/gencode.v38.kallisto.idx \
--rseqc_bed /ref/hg38_RefSeq.bed \
--strandedness reverse \
--outdir results/
Key pipeline steps:
- FastQC on the raw reads, quality and adapter trimming with Trim Galore (which also runs FastQC on the trimmed reads)
- STAR 2-pass alignment (splice-aware), writing the genome BAM, the transcriptome BAM, gene counts and bedGraphs
- RSEM gene and isoform quantification (TPM, FPKM, expected counts)
- Kallisto transcript quantification (optional, skipped with
--skip_kallisto) - Signal track generation (bedGraph to bigWig)
- RSeQC (infer_experiment, read_distribution, geneBody_coverage, inner_distance) and MultiQC
Step 5: Validate output quality
| Metric | Threshold | Where to read it |
|---|---|---|
| Uniquely mapped rate | >= 70% | star/<sample>.Log.final.out |
| Strandedness agreement | > 90% and matching --strandedness |
qc/rseqc/<sample>.infer_experiment.txt |
| Exonic rate | > 60% | qc/rseqc/<sample>.read_distribution.txt |
| Replicate correlation | >= 0.9 | compute yourself from the TPM column of rsem/<sample>.genes.results |
Step 6: Use expression data with ENCODE epigenomic data
Compare gene expression with enhancer marks:
encode_search_experiments(assay_title="Histone ChIP-seq", biosample_term_name="K562", target="H3K27ac", organism="Homo sapiens")
Interpretation: Genes with high TPM AND nearby H3K27ac peaks have validated enhancer-gene connections. Low expression despite nearby enhancer marks suggests poised or tissue-specific regulation.
Integration with downstream skills
- Gene quantifications feed into -> peak-annotation for expression-validated peak targets
- Expression data connects to -> gtex-expression for tissue comparison
- Processed data feeds into -> compare-biosamples for differential expression analysis
- Pipeline provenance logged by -> data-provenance
Code Examples
1. Find RNA-seq experiments for a tissue
encode_search_experiments(assay_title="total RNA-seq", organ="liver", organism="Homo sapiens")
Expected output:
{
"results": [
{"accession": "ENCSR300RNA", "assay_title": "total RNA-seq", "biosample_summary": "liver tissue male adult (54 years)", "status": "released"}
],
"total": 35,
"limit": 25,
"offset": 0,
"has_more": true,
"next_offset": 25
}
2. Check for existing gene quantifications
encode_list_files(experiment_accession="ENCSR300RNA", file_format="tsv", output_type="gene quantifications", assembly="GRCh38")
Expected output (a JSON array of file records; fields abridged):
[
{"accession": "ENCFF400GEQ", "file_format": "tsv", "output_type": "gene quantifications", "assembly": "GRCh38", "file_size_human": "5.2 MB", "status": "released"}
]
3. Download expression data
encode_download_files(file_accessions=["ENCFF400GEQ"], download_dir="/data/rnaseq/quantification")
Expected output (fields abridged):
{
"downloaded": [
{"accession": "ENCFF400GEQ", "file_path": "/data/rnaseq/quantification/ENCFF400GEQ.tsv", "file_size_human": "5.2 MB", "success": true, "md5_verified": true}
],
"errors": [],
"summary": {"total_requested": 1, "successful": 1, "failed": 0, "total_size_human": "5.2 MB"}
}
Integration
| This skill produces... | Feed into... | Purpose |
|---|---|---|
| Gene expression (TPM/FPKM) | peak-annotation | Validate enhancer targets with expression data |
| Expression matrix | gtex-expression | Compare cell-line vs. tissue expression |
| Differential expression results | compare-biosamples | Identify tissue-specific gene regulation |
| Signal tracks (bigWig) | visualization-workflow | Display expression signal in genome browser |
| Expression quantifications | disease-research | Connect gene expression to disease phenotypes |
| Pipeline run parameters | data-provenance | Record STAR/RSEM versions and settings |
| QC metrics | quality-assessment | Validate against ENCODE RNA-seq standards |
Related Skills
- pipeline-guide (parent): General pipeline selection and resource assessment
- quality-assessment: Deep-dive QC analysis beyond basic metrics
- integrative-analysis: Combine RNA-seq with ChIP-seq/ATAC-seq for regulatory inference
- compare-biosamples: Compare expression profiles across cell types
- single-cell-encode: For scRNA-seq data processing (different pipeline)
- pipeline-chipseq: Sibling pipeline for ChIP-seq data
- pipeline-atacseq: Sibling pipeline for ATAC-seq data
- publication-trust: Verify literature claims backing analytical decisions
Presenting Results
When reporting RNA-seq pipeline results:
- Mapping rate: Report the STAR uniquely mapped rate (>70% expected), multi-mapped rate (<10%), and unmapped rate from
star/<sample>.Log.final.out - Quantification paths: Provide paths to
rsem/<sample>.genes.results(TPM, FPKM, expected_count),rsem/<sample>.isoforms.results, andkallisto/<sample>/abundance.tsvwhen Kallisto ran - Strandedness: Confirm the orientation reported in
qc/rseqc/<sample>.infer_experiment.txtmatches the--strandednessvalue the run used; if it does not, the run has to be repeated - Key QC metrics: Present the exonic rate from
read_distribution.txtand the gene body coverage uniformity fromgeneBody_coverage.geneBodyCoverage.txtin a summary table, alongside the MultiQC report atqc/multiqc/multiqc_report.html - Derived metrics: Detected-gene counts (TPM>1), rRNA rate, library duplication rate and saturation are not produced by this workflow. Compute them separately if they are needed, and say so when reporting
- Signal tracks: Provide paths to
signal/<sample>_plus.bwandsignal/<sample>_minus.bw(orsignal/<sample>_unstranded.bwfor an unstranded run) - Next steps: Suggest
integrative-analysisto combine RNA-seq with ChIP-seq/ATAC-seq for regulatory inference, orcompare-biosamplesfor cross-tissue expression comparison
For the request: "$ARGUMENTS"
Files (encode-toolkit)
-
references
-
01-qc-trimming.md 3.4 KB
# Stage 1: QC and Trimming ## Input - Raw paired-end FASTQ files (ENCODE standard is paired-end stranded RNA-seq) - Adapter sequences: TruSeq adapters (Illumina TruSeq Stranded mRNA kit) ## Tools - **FastQC 0.12.1**: Per-base quality, adapter content, sequence duplication estimate, GC bias - **Trim Galore 0.6.10** (wraps cutadapt 4.6): Adapter trimming + quality filtering ## Key Difference from ATAC-seq / ChIP-seq RNA-seq uses **Illumina TruSeq** adapters, not Nextera. Trim Galore auto-detects TruSeq adapters by default. RNA-seq reads tend to be longer (75-150 bp) and have higher quality than ATAC-seq, but poly-A tails in adapter read-through are common with short inserts. ## RNA-seq Specific QC Checks - **Poly-A tail contamination**: Adapter content plot may show poly-A sequences if library inserts are shorter than read length. Trim Galore handles this automatically. - **rRNA contamination**: High duplication rates combined with skewed GC content can indicate failed rRNA depletion. The workflow does not measure the rRNA rate; see the manual count in `05-qc-metrics.md`. - **GC bias**: RNA-seq GC content should reflect transcriptome composition, not genome. A bimodal GC plot may indicate contamination or degraded RNA. ## Parameters | Parameter | Default | Notes | |-----------|---------|-------| | Quality cutoff | 20 | Phred score minimum | | Min length | 36 | Longer minimum than ATAC-seq due to longer fragments | | Adapter | TruSeq (auto-detect) | Illumina TruSeq adapters | | Stringency | 1 | Overlap with adapter sequence required (Trim Galore default) | ## Commands ```bash # Raw QC fastqc -t 4 -o qc_raw/ sample_R1.fastq.gz sample_R2.fastq.gz # Paired-end trimming with TruSeq adapters (auto-detected) trim_galore --paired --quality 20 --length 36 --fastqc \ --cores 4 -o trimmed/ sample_R1.fastq.gz sample_R2.fastq.gz ``` ## Expected Output The workflow runs FastQC on the raw reads and Trim Galore with `--fastqc` on top, so both sets of reports exist: - `trimmed/*_trimming_report.txt` -- trimming statistics (one per input file) - `trimmed/*_val_1.fq.gz`, `trimmed/*_val_2.fq.gz` -- trimmed paired-end reads (`*_trimmed.fq.gz` with `--single_end`) - `fastqc/*.{html,zip}` -- FastQC reports for the raw reads and for the trimmed reads, both published to the same directory and both fed to MultiQC ## QC Checkpoints | Check | Threshold | Action if Failed | |-------|-----------|------------------| | Per-base quality | >Q20 after trimming | Check sequencing run quality | | Adapter content | <5% after trimming | Verify adapter detection | | GC content | Unimodal, ~50% for human transcriptome | Check for contamination or rRNA | | Duplication rate | <60% (variable in RNA-seq) | High duplication is common for abundant transcripts | | Read count | >=30M PE reads recommended | May need more sequencing | ## Troubleshooting - **High adapter content**: Short library inserts cause adapter read-through. Ensure `--length 36` retains enough reads after trimming. - **Bimodal GC content**: Likely rRNA contamination or DNA contamination. Confirm with the manual rRNA count in `05-qc-metrics.md` and the intronic/intergenic fractions in `qc/rseqc/<sample>.read_distribution.txt`. - **Very high duplication**: Some duplication is biological (highly expressed genes). True PCR duplicates are only a concern if NRF <0.5. Mark but do not remove duplicates for RNA-seq quantification. -
02-star-alignment.md 5.9 KB
# Stage 2: STAR Alignment ## Tools - **STAR 2.7.11b**: Splice-aware aligner (Dobin et al. 2013, ~12,000 citations) - **Samtools 1.19**: BAM conversion, sorting, indexing, and statistics ## Why STAR Instead of HISAT2 or Bowtie2 STAR is preferred for ENCODE RNA-seq because: 1. Native splice junction awareness with 2-pass mode for novel junction discovery 2. Simultaneous output of genome BAM + transcriptome BAM (for RSEM) 3. Built-in gene count quantification (`--quantMode GeneCounts`) 4. Native bedGraph signal generation (`--outWigType bedGraph`) 5. Chimeric read detection for gene fusion analysis 6. Standard in the ENCODE RNA-seq uniform pipeline ## Reference Genome and Annotation | Organism | Assembly | STAR Index Source | GTF Annotation | |----------|----------|-------------------|----------------| | Human | GRCh38 (hg38) | Build from ENCODE FASTA | GENCODE v38+ (comprehensive) | | Mouse | mm10 (GRCm38) | Build from ENCODE FASTA | GENCODE vM27+ (comprehensive) | Use the ENCODE "no alt" analysis set FASTA with GENCODE comprehensive gene annotation. The GTF is consumed here, when the index is built, and is not a parameter of the workflow — the directory produced below is what you pass as `--star_index`, and its `chrNameLength.txt` is the default `--chrom_sizes`. ## STAR Index Generation (one-time prep, outside the workflow) ```bash # Generate genome index (run once, requires ~32 GB RAM for human) STAR --runMode genomeGenerate \ --genomeDir star_index/ \ --genomeFastaFiles GRCh38.primary_assembly.genome.fa \ --sjdbGTFfile gencode.v38.primary_assembly.annotation.gtf \ --sjdbOverhang 100 \ --runThreadN 8 ``` The `--sjdbOverhang` should ideally be `read_length - 1`. The default of 100 works well for 101 bp reads and is robust across typical read lengths (75-150 bp). STAR 2.7.11b, the version in the image, reads genome indexes built with STAR 2.7.4a or later. An index generated by anything older has to be rebuilt. ## STAR 2-Pass Alignment ```bash STAR --genomeDir star_index/ \ --readFilesIn R1.fq.gz R2.fq.gz \ --readFilesCommand zcat \ --runThreadN 8 \ --outSAMtype BAM SortedByCoordinate \ --outSAMunmapped Within \ --outFilterMultimapNmax 20 \ --alignSJoverhangMin 8 \ --alignSJDBoverhangMin 1 \ --outFilterMismatchNmax 999 \ --outFilterMismatchNoverReadLmax 0.04 \ --alignIntronMin 20 \ --alignIntronMax 1000000 \ --alignMatesGapMax 1000000 \ --quantMode TranscriptomeSAM GeneCounts \ --twopassMode Basic \ --outWigType bedGraph \ --outWigStrand Stranded ``` `--outWigStrand` is the only part of the command the workflow varies: it passes `Stranded` for `--strandedness reverse|forward` and `Unstranded` for `--strandedness none`. Everything else is fixed. The ~32 GB above is the figure for `genomeGenerate`. Alignment is a separate budget: the `STAR_ALIGN` process is configured for 36 GB (see `nextflow.config`), multiplied by the attempt number on a retry, up to `--max_memory`. ## Parameters | Parameter | Value | Notes | |-----------|-------|-------| | 2-pass mode | `--twopassMode Basic` | Discovers novel junctions, re-maps in 2nd pass | | Multi-map max | `--outFilterMultimapNmax 20` | Allow up to 20 alignments (RSEM handles them) | | SJ overhang | `--alignSJoverhangMin 8` | Minimum overhang for unannotated junctions | | SJ DB overhang | `--alignSJDBoverhangMin 1` | Minimum overhang for annotated junctions | | Mismatch rate | `--outFilterMismatchNoverReadLmax 0.04` | Max 4% mismatch rate | | Intron min | `--alignIntronMin 20` | Minimum intron length | | Intron max | `--alignIntronMax 1000000` | Maximum intron length (1 Mb) | | Quant mode | `TranscriptomeSAM GeneCounts` | Output transcriptome BAM + gene counts | | Signal output | `--outWigType bedGraph --outWigStrand Stranded` | Strand-specific bedGraph (`Unstranded` when `--strandedness none`) | ## Expected Output All of these are published to `star/`, prefixed with the sample ID: - `<sample>.Aligned.sortedByCoord.out.bam` (+ `.bai`) -- genome-sorted BAM - `<sample>.Aligned.toTranscriptome.out.bam` -- transcriptome BAM (input for RSEM) - `<sample>.ReadsPerGene.out.tab` -- STAR gene counts (column 2: unstranded, 3: sense, 4: antisense) - `<sample>.SJ.out.tab` -- splice junction table (novel + annotated) - `<sample>.Signal.UniqueMultiple.str1.out.bg` -- fragments whose read 1 maps to the + strand - `<sample>.Signal.UniqueMultiple.str2.out.bg` -- the remaining fragments (absent when `--strandedness none`) - `<sample>.Signal.Unique.str1.out.bg` (and `str2`) -- the same signal counting only uniquely mapped reads - `<sample>.Log.final.out` -- alignment summary statistics Which transcript strand str1 and str2 correspond to depends on the library; see `04-signal-tracks.md`. Both the `UniqueMultiple` and the `Unique` bedGraphs are published to `star/`, but only the `UniqueMultiple` pair is converted to bigWig. ## QC Checkpoints | Check | Threshold | Action if Failed | |-------|-----------|------------------| | Uniquely mapped reads | >=70% | Check genome build, contamination, rRNA | | Multi-mapped reads | <10% | High multi-map suggests repetitive contamination | | Unmapped: too short | <10% | High rate suggests aggressive trimming or poor quality | | Unmapped: too many mismatches | <5% | Check for contamination (wrong organism) | | Chimeric reads | 0 unless chimeric detection is enabled | The workflow passes no `--chim*` options | | Splice junctions (novel) | Thousands expected | Very few suggests annotation mismatch | ## Notes - STAR 2-pass mode is slower than 1-pass but discovers 10-20% more novel splice junctions. - The transcriptome BAM (`Aligned.toTranscriptome.out.bam`) must NOT be coordinate-sorted; RSEM requires it in its native transcript-coordinate order. - `--outFilterMultimapNmax 20` is essential for RSEM. Do not reduce this before RSEM. - Chimeric/fusion detection is not part of this workflow. To do it, run STAR by hand with `--chimSegmentMin 12 --chimJunctionOverhangMin 8 --chimOutType Junctions WithinBAM SoftClip`. -
03-quantification.md 5.6 KB
# Stage 3: Gene and Transcript Quantification ## Tools - **RSEM 1.3.3**: Gene/transcript quantification (Li & Dewey 2011, ~6,000 citations) - **Kallisto 0.50.1**: Fast pseudoalignment quantification (Bray et al. 2016, ~4,000 citations) ## RSEM Quantification (Primary) RSEM uses an expectation-maximization (EM) algorithm to probabilistically assign multi-mapped reads to genes and transcripts, providing accurate quantification even for overlapping gene families and repetitive elements. ### RSEM Index Preparation (one-time prep, outside the workflow) ```bash # Prepare RSEM reference (run once) rsem-prepare-reference --gtf gencode.v38.primary_assembly.annotation.gtf \ --star GRCh38.primary_assembly.genome.fa rsem_index/GRCh38 ``` The last argument is a **prefix**, not a directory, and it is what you pass as `--rsem_index` (here `rsem_index/GRCh38`). The workflow stages every file whose name starts with that prefix. The annotation is fixed at this point; there is no `--gtf` parameter downstream. ### RSEM Quantification ```bash rsem-calculate-expression \ --paired-end \ --bam \ --no-bam-output \ --estimate-rspd \ --strandedness reverse \ --num-threads 8 \ Aligned.toTranscriptome.out.bam \ rsem_index/GRCh38 \ sample_name ``` ### RSEM Output Files | File | Contents | Key Columns | |------|----------|-------------| | `rsem/<sample>.genes.results` | Gene-level quantification | gene_id, transcript_id(s), length, effective_length, expected_count, TPM, FPKM | | `rsem/<sample>.isoforms.results` | Transcript-level quantification | transcript_id, gene_id, length, effective_length, expected_count, TPM, FPKM, IsoPct | | `rsem/<sample>.stat/` | Model and read statistics | Directory; parsed by MultiQC | `--no-bam-output` is passed, so RSEM writes no BAM of its own. ### RSEM Strandedness Flags The workflow passes its `--strandedness` value straight through to RSEM, so these are the same three values: | Library Type | Pipeline and RSEM value | Description | |-------------|-----------|-------------| | dUTP / rf-stranded | `--strandedness reverse` | ENCODE standard, the pipeline default | | fr-stranded | `--strandedness forward` | Directional ligation | | Unstranded | `--strandedness none` | SMARTer, SMART-Seq2, older protocols | ## Kallisto Quantification (Optional Fast Alternative) Kallisto uses pseudoalignment (k-mer matching without full alignment) for ultra-fast transcript quantification. It runs 10-100x faster than STAR+RSEM but does not produce BAM files or support fusion detection. In this workflow Kallisto runs on the trimmed FASTQ files, in parallel with (not instead of) STAR and RSEM. Skip it with `--skip_kallisto`, which also stops `--kallisto_index` from being read. ### Kallisto Index (one-time prep, outside the workflow) ```bash # Build Kallisto index from transcriptome FASTA (run once) kallisto index -i kallisto_index.idx gencode.v38.transcripts.fa ``` Pass the resulting file as `--kallisto_index`. Build it with kallisto 0.50.1, the version in the image: 0.50.1 writes index version 13, and an index built with kallisto 0.48 or earlier is rejected at load time. Rebuild rather than reuse an older `.idx`. ### Kallisto Quantification ```bash kallisto quant \ -i kallisto_index.idx \ -o sample/ \ --rf-stranded \ -t 8 \ R1.fq.gz R2.fq.gz ``` The strand flag follows `--strandedness`: `--rf-stranded` for `reverse`, `--fr-stranded` for `forward`, and no flag for `none`. With `--single_end` the workflow substitutes the fixed `--single -l 200 -s 20`; if your fragment length distribution differs, rerun kallisto by hand with the right values. ### Kallisto Output | File | Contents | Published | |------|----------|-----------| | `kallisto/<sample>/abundance.tsv` | transcript_id, length, effective_length, est_counts, tpm | Yes | | `kallisto/<sample>/run_info.json` | Run metadata and statistics | Yes | | `kallisto/<sample>/abundance.h5` | Binary HDF5 format (for sleuth) | Only when the kallisto build has HDF5 support; the process declares it as an optional output | ## TPM vs FPKM vs Raw Counts | Metric | Definition | Cross-Sample Comparable | Use Case | |--------|-----------|------------------------|----------| | **Raw counts** | Number of reads/fragments mapped to gene | No | Input for DESeq2/edgeR differential expression | | **TPM** (Transcripts Per Million) | Counts normalized by gene length then library size | Yes | Cross-sample expression comparison | | **FPKM** (Fragments Per Kilobase per Million) | Counts normalized by library size then gene length | No | Legacy; avoid for cross-sample comparison | ### When to Use Each - **Differential expression**: Use raw `expected_count` from RSEM with DESeq2 or edgeR. These tools apply their own normalization (median-of-ratios or TMM). - **Cross-sample comparison**: Use TPM. It sums to 1M per sample, enabling direct comparison. - **Single-gene reporting**: TPM is appropriate for reporting expression of individual genes. - **Avoid FPKM**: FPKM does not sum to a constant across samples, making it unreliable for cross-sample comparison. TPM is strictly preferred. ## QC Checkpoints None of these are computed by the workflow; each is a check to run on the published quantifications (see `05-qc-metrics.md` for the detected-gene command). | Check | Threshold | Action if Failed | |-------|-----------|------------------| | Detected genes (TPM>1) | >12,000 (human) | Check sequencing depth, RNA quality | | RSEM mapping rate (from `<sample>.stat/`) | >70% of transcriptome BAM reads | Check strandedness setting | | TPM correlation between replicates | r > 0.95 (Pearson) | Check batch effects, sample swap | | Gene count distribution | Log-normal shape expected | Skewed distribution suggests degradation | -
04-signal-tracks.md 5.2 KB
# Stage 4: Signal Track Generation ## Tools - **STAR**: Generates strand-specific bedGraph output during alignment - **bedGraphToBigWig**: Converts bedGraph to bigWig (UCSC Kent tools) ## Overview RNA-seq signal tracks display read coverage across the genome for visualization in genome browsers (UCSC, IGV, WashU Epigenome Browser). For stranded RNA-seq, separate plus-strand and minus-strand tracks are generated, enabling gene-level visualization of sense and antisense transcription. ## STAR bedGraph Output STAR generates bedGraph files directly during alignment. The workflow passes `--outWigType bedGraph` always, and `--outWigStrand` follows `--strandedness`: | `--strandedness` | STAR receives | bedGraph files written | |------------------|---------------|------------------------| | `reverse`, `forward` | `--outWigStrand Stranded` | `Signal.{Unique,UniqueMultiple}.str1.out.bg` and `...str2.out.bg` | | `none` | `--outWigStrand Unstranded` | `Signal.{Unique,UniqueMultiple}.str1.out.bg` only | ## What str1 and str2 Mean STAR assigns a fragment to str1 when **read 1 maps to the + strand** of the genome (`signalFromBAM.cpp`: `iStrand = ((flag&0x10)>0) == ((flag&0x80)==0)`). str1 is therefore not "the plus strand" in the transcript sense — which transcript strand it represents depends on the library: | `--strandedness` | Library | str1 holds | str2 holds | |------------------|---------|-----------|-----------| | `reverse` (dUTP, ENCODE standard) | read 1 is antisense to the transcript | minus-strand transcription | plus-strand transcription | | `forward` (directional ligation) | read 1 is sense to the transcript | plus-strand transcription | minus-strand transcription | | `none` | unstranded | all fragments, one track | — | The workflow applies exactly this mapping, matching ENCODE's `STAR_RSEM.sh` (`str[1]="-"; str[2]="+"` for the dUTP default), and names the outputs accordingly: | `--strandedness` | Published tracks | |------------------|------------------| | `reverse` | str1 -> `signal/<sample>_minus.bw`, str2 -> `signal/<sample>_plus.bw` | | `forward` | str1 -> `signal/<sample>_plus.bw`, str2 -> `signal/<sample>_minus.bw` | | `none` | str1 -> `signal/<sample>_unstranded.bw` | ## Unique vs UniqueMultiple `Signal.UniqueMultiple.*` includes multi-mapped reads (ENCODE standard) and is what the workflow converts to bigWig. `Signal.Unique.*` counts only uniquely mapped reads and is a more conservative estimate; it is published as `star/<sample>.Signal.Unique.str*.out.bg` but is not converted, so run the commands below on it yourself if you want that track as a bigWig. ## bedGraph to bigWig Conversion This is what the workflow runs for a `reverse`-stranded sample: ```bash # Sort bedGraph (required by bedGraphToBigWig) sort -k1,1 -k2,2n sample.Signal.UniqueMultiple.str1.out.bg > minus_sorted.bg sort -k1,1 -k2,2n sample.Signal.UniqueMultiple.str2.out.bg > plus_sorted.bg # Convert to bigWig bedGraphToBigWig minus_sorted.bg chrom.sizes sample_minus.bw bedGraphToBigWig plus_sorted.bg chrom.sizes sample_plus.bw ``` Swap the two strand labels for a `forward`-stranded library. ## Chromosome Sizes File The workflow uses `--chrom_sizes`, which defaults to `chrNameLength.txt` inside the STAR index directory. To build one by hand: ```bash # From the aligned BAM header samtools view -H sample.Aligned.sortedByCoord.out.bam | \ grep '@SQ' | awk '{print $2"\t"$3}' | \ sed 's/SN://;s/LN://' > chrom.sizes # Or fetch from UCSC wget https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.chrom.sizes ``` ## Signal Normalization STAR bedGraph output is raw read counts per position, and the workflow publishes the bigWigs unnormalized. For cross-sample comparison, normalize them yourself afterwards: | Method | Description | When to Use | |--------|-------------|-------------| | Raw | Unnormalized read counts (what this workflow writes) | Single-sample visualization | | RPM | Reads per million mapped | Cross-sample comparison (simple) | | RPKM | RPM per kilobase | Length-normalized (rarely needed for signal) | ENCODE distributes both raw and RPM-normalized bigWig files. For publication, RPM is standard for cross-sample comparison in browser screenshots. ## Manual Alternative: bamCoverage (deepTools, not run by this workflow) deepTools is in neither the container image nor `rnaseq-env.yml`, so this needs a separate install. It gives more control over normalization and strand selection: ```bash bamCoverage -b sample.Aligned.sortedByCoord.out.bam \ -o sample.bw \ --normalizeUsing RPKM \ --binSize 10 \ --filterRNAstrand forward \ --numberOfProcessors 8 ``` ## Expected Output - `signal/<sample>_plus.bw` -- plus-strand transcription (stranded runs) - `signal/<sample>_minus.bw` -- minus-strand transcription (stranded runs) - `signal/<sample>_unstranded.bw` -- single track when `--strandedness none` ## Notes - bedGraphToBigWig requires sorted input and a chromosome sizes file. - For stranded data, always keep separate plus/minus tracks. Combining them loses strand information and confounds sense/antisense transcription. - A swapped plus/minus pair is easy to miss: check a gene you know the orientation of in a browser before publishing tracks. - bigWig files are typically 50-200 MB each, much smaller than BAM files. -
05-qc-metrics.md 6.7 KB
# Stage 5: QC Metrics ## Tools - **RSeQC 5.0.3**: RNA-seq quality control suite (Wang et al. 2012, ~3,500 citations) - **MultiQC 1.21**: Aggregated QC report generation The workflow runs four RSeQC modules — `infer_experiment.py`, `read_distribution.py`, `geneBody_coverage.py` and, for paired-end runs, `inner_distance.py` — all against the BED12 file given by `--rseqc_bed`, and publishes their output to `qc/rseqc/`. R is not installed in the image, so the modules that end by calling Rscript write their `.txt` and `.r` files but no rendered plot. ## RSeQC Modules ### infer_experiment.py (Strandedness Check) ```bash infer_experiment.py -r hg38_RefSeq.bed -i sample.Aligned.sortedByCoord.out.bam \ > sample.infer_experiment.txt ``` Determines library strandedness by sampling read orientation relative to annotated transcripts. This is a post-hoc check: it does not feed back into quantification. If it disagrees with the `--strandedness` value the run used, rerun the pipeline with the correct value. | Output Pattern | Interpretation | `--strandedness` to use | |----------------|---------------|-------------| | "1++,1--,2+-,2-+" > 90% | Forward stranded | `forward` | | "1+-,1-+,2++,2--" > 90% | Reverse stranded (dUTP) | `reverse` | | ~50/50 split | Unstranded | `none` | **ENCODE standard**: Expect >90% reverse-stranded reads for dUTP libraries. ### read_distribution.py (Mapping Distribution) ```bash read_distribution.py -r hg38_RefSeq.bed -i sample.Aligned.sortedByCoord.out.bam \ > sample.read_distribution.txt ``` Reports fraction of reads mapping to CDS exons, 5' UTR, 3' UTR, introns, and intergenic regions. | Region | Expected (mRNA-seq) | Concern Threshold | |--------|--------------------|--------------------| | CDS exons | 40-60% | <30% suggests degradation or DNA contamination | | 5' UTR | 5-10% | <2% suggests 5' degradation | | 3' UTR | 15-25% | >40% suggests 3' bias (degraded RNA) | | Introns | 10-25% | >40% suggests DNA contamination or pre-mRNA | | Intergenic | <5% | >10% suggests DNA contamination | ### geneBody_coverage.py (Gene Body Coverage) ```bash geneBody_coverage.py -r hg38_RefSeq.bed \ -i sample.Aligned.sortedByCoord.out.bam -o sample.geneBody_coverage ``` The workflow passes the same `--rseqc_bed` file used by the other modules. A housekeeping-gene BED (for example `hg38_HouseKeeping.bed`) runs faster and is the usual choice when calling this module by hand; both are valid inputs. Reports normalized coverage across gene bodies (5' to 3') in `<sample>.geneBody_coverage.geneBodyCoverage.txt`. Uniform coverage indicates intact RNA; strong 3' bias indicates degradation. | Pattern | Interpretation | |---------|---------------| | Uniform (5'/3' ratio 0.7-1.3) | Good RNA quality | | 3' bias (5'/3' ratio <0.5) | RNA degradation | | 5' bias (5'/3' ratio >2.0) | Possible oligo-dT priming bias | ### inner_distance.py (Insert Size Distribution) ```bash inner_distance.py -r hg38_RefSeq.bed \ -i sample.Aligned.sortedByCoord.out.bam -o sample.inner_distance ``` Paired-end only; skipped when the run uses `--single_end`. Reports the inner distance between mates across a set of files matching `<sample>.inner_distance.*`. Negative values indicate overlapping reads (common for short inserts). The peak should match the expected library insert size (typically 150-300 bp). ### STAR Log Metrics The `star/<sample>.Log.final.out` from STAR provides critical metrics: | Metric | Threshold | Notes | |--------|-----------|-------| | Uniquely mapped reads % | >=70% | Primary quality indicator | | Multi-mapped reads % | <10% | High suggests repetitive contamination | | Unmapped: too short % | <10% | High suggests over-trimming | | % of reads mapped to multiple loci | <10% | Expected for gene families | | % of chimeric reads | <1% | Zero unless STAR is run with chimeric detection | | Number of splices: Total | Millions expected | Low count suggests annotation mismatch | ## Manual Checks (not run by this workflow) The metrics below are not produced by the pipeline. Run them yourself against the published BAM and RSEM output when you need them, and label them as separate steps when reporting. ### rRNA Rate Assessment ```bash # Count mapped reads overlapping rRNA loci. -L takes a BED file of regions; without it # samtools would read the file name as a region string and fail. samtools view -c -F 4 -L rRNA_intervals.bed star/sample.Aligned.sortedByCoord.out.bam ``` Divide by the total mapped count from `Log.final.out` to get the rate. | rRNA Rate | Interpretation | |-----------|---------------| | <5% | Excellent rRNA depletion | | 5-10% | Acceptable | | 10-30% | Suboptimal; reduced effective depth | | >30% | Failed rRNA depletion; consider re-prep | ### Saturation Analysis ```bash # RSeQC RPKM saturation (installed in the image, but never invoked by the workflow; # it writes an .r script that needs R to render) RPKM_saturation.py -r hg38_RefSeq.bed \ -i star/sample.Aligned.sortedByCoord.out.bam -o sample_saturation ``` Subsamples reads at increasing fractions (5%, 10%, ..., 100%) and measures gene detection. A plateau indicates sufficient sequencing depth. If the curve is still rising at 100%, more sequencing is recommended. ### Detected Genes ```bash # Genes with TPM > 1; the TPM column of RSEM genes.results is column 6 awk 'NR > 1 && $6 > 1 {n++} END {print "Genes with TPM>1:", n}' rsem/sample.genes.results ``` Expect >12,000 for a human sample at ENCODE depth. ### Library Duplication Rate Picard `MarkDuplicates` and `CollectRnaSeqMetrics` are not in the container image. The FastQC report does carry a sequence-level duplication estimate, which is not the same quantity; run Picard separately if you need the alignment-based rate. ## MultiQC Aggregation ```bash multiqc . -o . -f ``` The workflow feeds MultiQC exactly these inputs: FastQC reports for the raw reads, the Trim Galore trimming reports, the FastQC reports for the trimmed reads, the STAR `Log.final.out`, the RSEM `.stat/` directories, and the RSeQC `infer_experiment` and `read_distribution` outputs. `geneBody_coverage`, `inner_distance` and the Kallisto output are published but are not part of the report — read those files directly. The report is written to `qc/multiqc/multiqc_report.html` with the parsed values in `qc/multiqc/multiqc_data/`. ## Expected Output - `qc/rseqc/<sample>.infer_experiment.txt` -- strandedness inference - `qc/rseqc/<sample>.read_distribution.txt` -- mapping distribution by genomic feature - `qc/rseqc/<sample>.geneBody_coverage.geneBodyCoverage.txt` and `.r` -- gene body coverage (RSeQC also tries to draw `.curves.pdf`, which needs R and is therefore absent) - `qc/rseqc/<sample>.inner_distance.*` -- insert size, paired-end runs only (RSeQC also tries to draw a PDF, which needs R) - `qc/multiqc/multiqc_report.html` -- aggregated QC report -
literature.md 11.8 KB
# RNA-seq Pipeline — Literature References **Last updated:** 2026-03-07 **Purpose:** Reference catalog for the pipeline-rnaseq skill — papers defining ENCODE RNA-seq processing standards, splice-aware alignment, transcript quantification, and quality assessment tools. --- ## ENCODE Pipeline Standards --- ### ENCODE Project Consortium 2020 — Expanded encyclopaedias of DNA elements - **Citation:** ENCODE Project Consortium et al. Expanded encyclopaedias of DNA elements in the human and mouse genomes. Nature, 583(7818):699-710, 2020. - **DOI:** [10.1038/s41586-020-2493-4](https://doi.org/10.1038/s41586-020-2493-4) - **PMID:** 32728249 | **PMC:** PMC7410828 - **Citations:** ~2,500 - **Key findings:** ENCODE Phase 3 paper establishing RNA-seq as a core assay for the encyclopedia. RNA-seq quantification provides the expression data used to classify candidate cis-Regulatory Elements (cCREs) and annotate gene activity across cell types. Established uniform processing standards: stranded library protocol (dUTP), STAR 2-pass alignment, RSEM quantification, minimum 30M uniquely mapped reads per replicate, and GENCODE annotation as the reference gene model. Assembly standards: GRCh38/mm10. --- ### Hitz et al. 2023 — The ENCODE Uniform Analysis Pipelines - **Citation:** Hitz BC, Lee JW, Jolanki O, et al. The ENCODE Uniform Analysis Pipelines. Research Square (preprint), 2023. - **DOI:** [10.21203/rs.3.rs-311127/v1](https://doi.org/10.21203/rs.3.rs-311127/v1) - **Citations:** ~84 - **Key findings:** Documents the official ENCODE RNA-seq pipeline specification: STAR 2-pass mode for splice-aware alignment, RSEM for gene/transcript quantification, strand-specific signal track generation, and comprehensive QC with RSeQC. Pipeline infrastructure uses Docker containers and WDL for reproducible execution on local machines, HPC clusters, or cloud environments. --- ### Conesa et al. 2016 — A survey of best practices for RNA-seq data analysis - **Citation:** Conesa A, Madrigal P, Tarazona S, Gomez-Cabrero D, Cervera A, McPherson A, Szczesniak MW, Gaffney DJ, Elo LL, Zhang X, Mortazavi A. A survey of best practices for RNA-seq data analysis. Genome Biology, 17:13, 2016. - **DOI:** [10.1186/s13059-016-0881-8](https://doi.org/10.1186/s13059-016-0881-8) - **PMID:** 26813401 | **PMC:** PMC4728800 - **Citations:** ~4,500 - **Key findings:** Comprehensive best-practices review covering experimental design, quality control, alignment, quantification, normalization, differential expression, alternative splicing, functional analysis, and visualization. Recommended minimum sequencing depth of 10-30M reads for differential expression and >60M for transcript discovery. Established that RSEM with STAR alignment provides the most accurate quantification for multi-mapped reads through expectation-maximization. Defined key QC metrics: mapping rate >80%, rRNA contamination <10%, replicate Pearson correlation >= 0.9, and 3'/5' coverage bias assessment. This paper provides the scientific basis for many parameter choices in the ENCODE RNA-seq pipeline. --- ## Core Pipeline Tools --- ### Dobin et al. 2013 — STAR: ultrafast universal RNA-seq aligner - **Citation:** Dobin A, Davis CA, Schlesinger F, Drenkow J, Zaleski C, Jha S, Batut P, Chaisson M, Gingeras TR. STAR: ultrafast universal RNA-seq aligner. Bioinformatics, 29(1):15-21, 2013. - **DOI:** [10.1093/bioinformatics/bts635](https://doi.org/10.1093/bioinformatics/bts635) - **PMID:** 23104886 | **PMC:** PMC3530905 - **Citations:** ~12,700 - **Key findings:** Introduced the STAR (Spliced Transcripts Alignment to a Reference) aligner, developed specifically for the ENCODE Transcriptome project to align >80 billion reads. STAR uses sequential maximum mappable seed search in uncompressed suffix arrays followed by seed clustering and stitching. Outperforms other aligners by >50x in mapping speed (550M 2x76bp paired-end reads per hour on 12 cores) while improving alignment sensitivity and precision. Supports de novo detection of canonical and non-canonical splice junctions, chimeric transcripts, and full-length RNA sequences. The ENCODE pipeline uses STAR in 2-pass mode: first pass discovers novel splice junctions, second pass uses the full junction database for improved alignment. Experimentally validated 1,960 novel intergenic splice junctions with 80-90% success rate. --- ### Li & Dewey 2011 — RSEM: accurate transcript quantification - **Citation:** Li B, Dewey CN. RSEM: accurate transcript quantification from RNA-Seq data with or without a reference genome. BMC Bioinformatics, 12:323, 2011. - **DOI:** [10.1186/1471-2105-12-323](https://doi.org/10.1186/1471-2105-12-323) - **PMID:** 21816040 | **PMC:** PMC3163565 - **Citations:** ~18,600 - **Key findings:** Introduced RSEM (RNA-Seq by Expectation-Maximization), which uses a generative model and EM algorithm to handle multi-mapped reads for accurate gene and isoform quantification. RSEM outputs expected counts, TPM (Transcripts Per Million), and FPKM (Fragments Per Kilobase of transcript per Million mapped reads) along with 95% credibility intervals. Unlike simple counting methods (e.g., featureCounts), RSEM probabilistically assigns ambiguously mapped reads to their most likely transcripts of origin based on the overall expression landscape. Benchmarks showed RSEM slightly outperforms other quantification pipelines (Teng et al. 2016). The ENCODE pipeline uses RSEM with STAR's transcriptome BAM output for gene and transcript quantification. --- ### Bray et al. 2016 — Kallisto: near-optimal RNA-seq quantification - **Citation:** Bray NL, Pimentel H, Melsted P, Pachter L. Near-optimal probabilistic RNA-seq quantification. Nature Biotechnology, 34(5):525-527, 2016. - **DOI:** [10.1038/nbt.3519](https://doi.org/10.1038/nbt.3519) - **PMID:** 27043002 - **Citations:** ~4,000 - **Key findings:** Introduced Kallisto, which uses pseudoalignment to a de Bruijn graph built from a transcriptome reference to quantify transcript abundances without full read alignment. Kallisto processes 30M reads in minutes (vs hours for alignment-based methods) while maintaining accuracy comparable to or better than alignment-based quantification. The ENCODE pipeline includes Kallisto as an optional fast pseudoalignment step that operates directly on FASTQ files without requiring genome alignment, providing an independent quantification for cross-validation with RSEM results. --- ## Quality Control --- ### Wang et al. 2012 — RSeQC: quality control of RNA-seq experiments - **Citation:** Wang L, Wang S, Li W. RSeQC: quality control of RNA-seq experiments. Bioinformatics, 28(16):2184-2185, 2012. - **DOI:** [10.1093/bioinformatics/bts356](https://doi.org/10.1093/bioinformatics/bts356) - **PMID:** 22743226 - **Citations:** ~2,300 - **Key findings:** Comprehensive RNA-seq QC package evaluating sequence quality, GC bias, PCR bias, nucleotide composition bias, sequencing depth saturation, strand specificity, coverage uniformity, and read distribution over genome structure (exonic, intronic, intergenic). Key modules used in this pipeline: infer_experiment.py (strand specificity detection), read_distribution.py (exonic/intronic/intergenic classification), geneBody_coverage.py (3'/5' bias assessment), junction_saturation.py (splice junction discovery saturation), and inner_distance.py (fragment size estimation). RSeQC is the primary RNA-seq-specific QC tool in the ENCODE pipeline. --- ### Ewels et al. 2016 — MultiQC - **Citation:** Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics, 32(19):3047-3048, 2016. - **DOI:** [10.1093/bioinformatics/btw354](https://doi.org/10.1093/bioinformatics/btw354) - **PMID:** 27312411 | **Citations:** ~6,800 - **RNA-seq role:** Aggregates QC metrics from FastQC, STAR, RSEM, RSeQC, and Picard into a unified HTML report for batch-level assessment of RNA-seq experiments. --- ## Gene Annotation --- ### Frankish et al. 2021 — GENCODE 2021 - **Citation:** Frankish A, Diekhans M, Jungreis I, Lagarde J, Loveland JE, Mudge JM, Sisu C, Wright JC, Armstrong J, Barnes I, Berry A, Bignell A, Boix C, Carbonell Sala S, Cunningham F, Di Domenico T, Donaldson S, Fiddes IT, Garcia Giron C, Gonzalez JM, Grego T, Hardy M, Hourlier T, Howe KL, Hunt T, Izuogu OG, Johnson R, Martin FJ, Martinez L, Mohanan S, Muir P, Navarro FCP, Parker A, Pei B, Pozo F, Riera FC, Ruffier M, Schmitt BM, Stapleton E, Suner MM, Sycheva I, Uszczynska-Ratajczak B, Wolf MY, Xu J, Yang YT, Yates A, Zerbino D, Zhang Y, Choudhary JS, Gerstein M, Guigo R, Hubbard TJP, Kellis M, Paten B, Tress ML, Flicek P. GENCODE 2021. Nucleic Acids Research, 49(D1):D916-D923, 2021. - **DOI:** [10.1093/nar/gkaa1087](https://doi.org/10.1093/nar/gkaa1087) - **PMID:** 33270111 | **PMC:** PMC7778937 - **Citations:** ~2,500 - **Key findings:** GENCODE provides the comprehensive gene annotation used as the reference for RNA-seq quantification in ENCODE pipelines. Version 41 (GRCh38.p13) annotates 62,764 genes (20,090 protein-coding) and 248,396 transcripts. GENCODE annotations are distinguished from RefSeq by their inclusion of more alternative transcripts, non-coding RNA species, and pseudogenes. The ENCODE pipeline requires GENCODE GTF files for both STAR genome index generation and RSEM reference preparation, ensuring consistent annotation across all quantification steps. --- ## Supplementary Tools (Non-RNA-seq-Specific) See pipeline-chipseq/references/literature.md for detailed descriptions of shared tools. --- ### Li et al. 2009 — SAMtools - **DOI:** [10.1093/bioinformatics/btp352](https://doi.org/10.1093/bioinformatics/btp352) | **PMID:** 19505943 | **Citations:** ~53,700 - **RNA-seq role:** BAM sorting, indexing, and alignment statistics. Used for computing mapping rate and rRNA fraction. --- ### Broad Institute — Picard MarkDuplicates - **URL:** [https://broadinstitute.github.io/picard/](https://broadinstitute.github.io/picard/) - **RNA-seq role:** PCR duplicate marking. Note: duplicate removal is less critical for RNA-seq than for ChIP-seq because PCR duplicates in expression data do not create false peaks. ENCODE retains duplicates for quantification but marks them for QC statistics. --- ### Andrews 2010 — FastQC - **URL:** [https://www.bioinformatics.babraham.ac.uk/projects/fastqc/](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) - **RNA-seq role:** Raw read quality assessment. RNA-seq libraries may show characteristic GC bias from highly expressed transcripts and sequence duplication from abundant mRNAs — these are expected and not concerning. --- ### Martin 2011 — Cutadapt (basis for Trim Galore) - **DOI:** [10.14806/ej.17.1.200](https://doi.org/10.14806/ej.17.1.200) | **Citations:** ~13,000 - **RNA-seq role:** Adapter trimming with Phred quality cutoff of 20. Less critical for RNA-seq than for ATAC-seq since RNA-seq fragments are typically longer than read length, but still recommended for best alignment quality. --- ### Teng et al. 2016 — A benchmark for RNA-seq quantification pipelines - **Citation:** Teng M, Love MI, Davis CA, Djebali S, Dobin A, Graveley BR, Li S, Mason CE, Olson S, Pervouchine D, Sloan CA, Wei X, Zhan L, Irizarry RA. A benchmark for RNA-seq quantification pipelines. Genome Biology, 17:74, 2016. - **DOI:** [10.1186/s13059-016-0940-1](https://doi.org/10.1186/s13059-016-0940-1) - **PMID:** 27107712 | **PMC:** PMC4842274 - **Citations:** ~162 - **Key findings:** Benchmark of seven RNA-seq quantification pipelines using two independent datasets. Found that performance was generally poor across methods, with RSEM slightly outperforming the rest. Established metrics for evaluating quantification accuracy including specificity (proportion of truly non-expressed genes called as non-expressed) and sensitivity (correlation between estimated and true expression). Supports the ENCODE choice of RSEM as the primary quantification tool.
-
-
scripts
-
Dockerfile 2.7 KB · in bundle
-
main.nf 11.6 KB · in bundle
-
nextflow.config 4.7 KB · in bundle
-
-
SKILL.md 28.2 KB
--- name: pipeline-rnaseq description: "Execute ENCODE RNA-seq pipeline from FASTQ to gene quantification and signal tracks. Child of pipeline-guide. Provides Nextflow execution with Docker and cloud deployment. Use when processing RNA-seq data with STAR alignment, RSEM/Kallisto quantification, or generating expression matrices. Trigger on: RNA-seq pipeline, gene expression, STAR alignment, RSEM quantification, transcript quantification, TPM, FPKM, RNA processing, run RNA-seq." --- # ENCODE RNA-seq Pipeline ## When to Use - User wants to run an RNA-seq processing pipeline from FASTQ to gene quantification - User asks about "RNA-seq pipeline", "STAR alignment", "RSEM", "gene expression quantification", or "Kallisto" - User needs to process bulk RNA-seq data with ENCODE-standard 2-pass STAR alignment - Example queries: "process my RNA-seq FASTQs", "quantify gene expression from RNA-seq", "run STAR and RSEM on my data" Execute the ENCODE RNA-seq processing pipeline from raw FASTQ files through splice-aware alignment, gene/transcript quantification, and strand-specific signal track generation. This skill provides a complete Nextflow DSL2 implementation following ENCODE uniform analysis standards. ## Overview RNA-seq measures transcriptome-wide gene expression by sequencing cDNA derived from cellular RNA. The ENCODE pipeline processes RNA-seq data through quality control, splice-aware alignment with STAR (2-pass mode), gene and transcript quantification with RSEM, optional fast pseudoalignment with Kallisto, and generation of strand-specific signal tracks as bigWig files. Key design decisions: STAR 2-pass mode for maximum splice junction sensitivity, RSEM for accurate gene/transcript/isoform quantification including multi-mapped reads, stranded library protocol (dUTP/rf-stranded) as the ENCODE standard, and paired-end sequencing with a minimum of 30 million uniquely mapped reads per replicate. ## Key Literature | Reference | Journal | Year | DOI | Relevance | |-----------|---------|------|-----|-----------| | Dobin et al. "STAR: ultrafast universal RNA-seq aligner" | Bioinformatics | 2013 | 10.1093/bioinformatics/bts635 | Splice-aware aligner (~12,000 citations) | | Li & Dewey "RSEM: accurate transcript quantification from RNA-Seq data" | BMC Bioinformatics | 2011 | 10.1186/1471-2105-12-323 | Gene/transcript quantification (~6,000 citations) | | Bray et al. "Near-optimal probabilistic RNA-seq quantification" | Nature Biotechnology | 2016 | 10.1038/nbt.3519 | Fast pseudoalignment (~4,000 citations) | | Wang et al. "RSeQC: quality control of RNA-seq experiments" | Bioinformatics | 2012 | 10.1093/bioinformatics/bts356 | RNA-seq QC suite (~3,500 citations) | | ENCODE Project Consortium "Expanded encyclopaedias" | Nature | 2020 | 10.1038/s41586-020-2493-4 | ENCODE Phase 3 standards | | Frankish et al. "GENCODE 2021" | Nucleic Acids Research | 2021 | 10.1093/nar/gkaa1087 | Gene annotation reference | ## Pipeline Stages ``` FASTQ ├─> FastQC (raw reads) └─> Trim Galore (+ FastQC on the trimmed reads) ├─> Kallisto (optional) ──────────> kallisto/<sample>/abundance.tsv └─> STAR (2-pass) ├─> transcriptome BAM ─> RSEM ─> <sample>.genes.results / .isoforms.results ├─> bedGraph str1/str2 ─> bedGraphToBigWig ─> signal/<sample>_{plus,minus}.bw └─> genome BAM ─> RSeQC (infer_experiment, read_distribution, geneBody_coverage, inner_distance) MultiQC <── FastQC (raw + trimmed), trimming reports, STAR Log.final.out, RSEM .stat/, RSeQC infer_experiment + read_distribution └─> qc/multiqc/multiqc_report.html ``` The Kallisto abundances, the gene body coverage and the inner distance files are published but are not part of the MultiQC report; read those files directly. ### Stage Summary | Stage | Tool | Input | Output | Reference | |-------|------|-------|--------|-----------| | 1. QC & Trimming | FastQC, Trim Galore | Raw FASTQ | Trimmed FASTQ + FastQC reports | references/01-qc-trimming.md | | 2. Alignment | STAR (2-pass) | Trimmed FASTQ | Genome BAM + Transcriptome BAM + bedGraph | references/02-star-alignment.md | | 3. Quantification | RSEM, Kallisto | Transcriptome BAM / trimmed FASTQ | Gene/transcript counts, TPM, FPKM | references/03-quantification.md | | 4. Signal Tracks | bedGraphToBigWig | STAR bedGraph | Strand-specific bigWig | references/04-signal-tracks.md | | 5. QC Metrics | RSeQC, MultiQC | Genome BAM, logs | Strandedness, read distribution, gene body coverage | references/05-qc-metrics.md | ## Input Requirements ### Required Files - **RNA-seq FASTQ**: paired-end reads matched by the `--reads` glob (ENCODE standard; single-end with `--single_end`) - **STAR genome index directory** (`--star_index`) - **RSEM reference prefix** (`--rsem_index`) produced by `rsem-prepare-reference` - **BED12 gene model for RSeQC** (`--rseqc_bed`) - **Kallisto index file** (`--kallisto_index`) built with kallisto 0.50.1, unless `--skip_kallisto` is set. kallisto 0.50.1 writes index version 13 and rejects an index built with 0.48 or earlier There is no sample sheet: samples are the pairs that `--reads` matches, and the sample ID is the shared prefix of each pair. The gene annotation is not a workflow parameter and there is no `--gtf`; the GTF is consumed when the STAR and RSEM references are built (references/02 and references/03), so the annotation is fixed by the index you pass in. ## Library Strandedness `--strandedness` takes one value for the whole run — `reverse` (default), `forward` or `none` — and is validated before the first task. It drives three things at once: the RSEM `--strandedness` flag, the kallisto strand flag, and which STAR bedGraph becomes which signal track. | Protocol | `--strandedness` | RSEM receives | Kallisto receives | Signal tracks | |----------|------------------|---------------|-------------------|---------------| | dUTP (ENCODE standard), Illumina TruSeq Stranded | `reverse` | `--strandedness reverse` | `--rf-stranded` | `<sample>_plus.bw`, `<sample>_minus.bw` | | Directional ligation (some legacy protocols) | `forward` | `--strandedness forward` | `--fr-stranded` | `<sample>_plus.bw`, `<sample>_minus.bw` | | SMARTer / SMART-Seq2 and other unstranded kits | `none` | `--strandedness none` | no strand flag | `<sample>_unstranded.bw` | There is no per-sample strandedness and the workflow does not detect it. RSeQC `infer_experiment.py` runs as a post-hoc check and writes `qc/rseqc/<sample>.infer_experiment.txt`. If the library type is unknown, run a first pass, read that file (references/05 explains the output), and rerun with the correct `--strandedness` — the RSEM counts, the kallisto abundances and the signal tracks all depend on it, so a wrong value has to be corrected by rerunning, not by post-processing. ## QC Thresholds | Metric | Threshold | Produced by | |--------|-----------|-------------| | Total sequenced reads | >=30M PE reads | `fastqc/`, `star/<sample>.Log.final.out` | | Uniquely mapped reads | >=70% of input reads | `star/<sample>.Log.final.out` | | Multi-mapped reads | <10% | `star/<sample>.Log.final.out` | | Strandedness agreement | >90% for a stranded library | `qc/rseqc/<sample>.infer_experiment.txt` | | Exonic rate | >60% | `qc/rseqc/<sample>.read_distribution.txt` | | Gene body coverage | Relatively uniform (5'/3' bias <1.5) | `qc/rseqc/<sample>.geneBody_coverage.geneBodyCoverage.txt` | Not computed by this workflow: rRNA rate, library duplication rate (beyond the sequence-level estimate inside the FastQC report), detected-gene counts, and saturation curves. references/05-qc-metrics.md gives the commands to run those by hand on the published BAM and RSEM output. ### Read Depth Guidelines | Application | Minimum Reads (PE) | Recommended | Notes | |-------------|-------------------|-------------|-------| | Gene-level expression | 20M | 30M | ENCODE minimum | | Transcript-level expression | 40M | 60M | Isoform resolution requires more depth | | Differential expression | 20M per sample | 30M per sample | 3+ biological replicates per condition | | Novel junction discovery | 60M | 100M+ | STAR 2-pass mode benefits from depth | | Fusion detection | 50M | 80M+ | Chimeric reads are rare; needs a separate STAR run (references/02) | ## Execution The versions the workflow runs are the ones in `scripts/Dockerfile`: STAR 2.7.11b, RSEM 1.3.3, kallisto 0.50.1, samtools 1.19, RSeQC 5.0.3, Trim Galore 0.6.10, cutadapt 4.6, MultiQC 1.21 and FastQC 0.12.1. The conda environment in `bioinformatics-installer` (`environments/rnaseq-env.yml`) is a separate manual route pinned to the same versions of STAR, RSEM, kallisto, samtools, RSeQC, Trim Galore, FastQC and MultiQC; it leaves cutadapt to the Trim Galore package, adds salmon and subread, and does not carry `bedGraphToBigWig`, which the signal-track step needs. Every index flag is shown in the examples below because the defaults are bare names resolved in the launch directory (`GRCh38_star_index`, `GRCh38_rsem_index/GRCh38`, `gencode.v38.kallisto.idx`, `hg38_RefSeq.bed` for `--genome GRCh38`). The run stops before the first task if any of them is missing. `--kallisto_index` is the one exception: it is not read when `--skip_kallisto` is set. ### Quick Start (local, Docker) ```bash nextflow run scripts/main.nf -profile local \ --reads 'fastq/*_R{1,2}.fq.gz' \ --genome GRCh38 \ --star_index /ref/GRCh38_star_index \ --rsem_index /ref/GRCh38_rsem_index/GRCh38 \ --kallisto_index /ref/gencode.v38.kallisto.idx \ --rseqc_bed /ref/hg38_RefSeq.bed \ --strandedness reverse \ --outdir results/ ``` ### SLURM HPC ```bash nextflow run scripts/main.nf -profile slurm \ --container /path/to/pipeline-rnaseq.sif \ --slurm_queue normal \ --reads 'fastq/*_R{1,2}.fq.gz' \ --genome GRCh38 \ --star_index /ref/GRCh38_star_index \ --rsem_index /ref/GRCh38_rsem_index/GRCh38 \ --kallisto_index /ref/gencode.v38.kallisto.idx \ --rseqc_bed /ref/hg38_RefSeq.bed \ --outdir results/ ``` ### Cloud ```bash # Google Cloud Batch nextflow run scripts/main.nf -profile gcp \ --container us-docker.pkg.dev/<project>/<repo>/pipeline-rnaseq:1.0.0 \ --gcp_project <project> \ --gcp_workdir gs://<bucket>/work \ --reads 'gs://<bucket>/fastq/*_R{1,2}.fq.gz' \ --genome GRCh38 \ --star_index gs://<bucket>/ref/GRCh38_star_index \ --rsem_index gs://<bucket>/ref/GRCh38_rsem_index/GRCh38 \ --kallisto_index gs://<bucket>/ref/gencode.v38.kallisto.idx \ --rseqc_bed gs://<bucket>/ref/hg38_RefSeq.bed \ --outdir gs://<bucket>/results # AWS Batch nextflow run scripts/main.nf -profile aws \ --container <account>.dkr.ecr.<region>.amazonaws.com/pipeline-rnaseq:1.0.0 \ --aws_queue <job-queue> \ --aws_workdir s3://<bucket>/work \ --reads 's3://<bucket>/fastq/*_R{1,2}.fq.gz' \ --genome GRCh38 \ --star_index s3://<bucket>/ref/GRCh38_star_index \ --rsem_index s3://<bucket>/ref/GRCh38_rsem_index/GRCh38 \ --kallisto_index s3://<bucket>/ref/gencode.v38.kallisto.idx \ --rseqc_bed s3://<bucket>/ref/hg38_RefSeq.bed \ --outdir s3://<bucket>/results ``` `--outdir` only sets where results are published; Google Batch and AWS Batch stage every task through the work directory, and the workflow stops with an error if it or the project/queue is missing. ## Pipeline Parameters | Parameter | Default | Description | |-----------|---------|-------------| | `--reads` | required | Glob matching the FASTQ pairs, e.g. `'fastq/*_R{1,2}.fq.gz'`. Quote it | | `--genome` | `GRCh38` | `GRCh38` or `mm10`; selects the default index names and nothing else | | `--outdir` | `./results` | Directory results are published to | | `--single_end` | `false` | Treat `--reads` as single files; kallisto then runs with the fixed `--single -l 200 -s 20`, and RSeQC `inner_distance.py` is skipped | | `--strandedness` | `reverse` | `reverse`, `forward` or `none`; one value for the whole run | | `--skip_kallisto` | `false` | Skip `KALLISTO_QUANT`; `--kallisto_index` is then not read | | `--star_index` | `GRCh38_star_index` (`mm10_star_index`) | STAR genome directory | | `--rsem_index` | `GRCh38_rsem_index/GRCh38` (`mm10_rsem_index/mm10`) | RSEM reference **prefix**, not a directory; every file starting with it is staged | | `--kallisto_index` | `gencode.v38.kallisto.idx` (`gencode.vM27.kallisto.idx`) | kallisto index file; must be built with kallisto 0.50.1 (index version 13), not with 0.48 or earlier | | `--rseqc_bed` | `hg38_RefSeq.bed` (`mm10_RefSeq.bed`) | BED12 gene model used by all four RSeQC modules | | `--chrom_sizes` | `<star_index>/chrNameLength.txt` | Chromosome sizes for `bedGraphToBigWig` | ### Infrastructure parameters (`nextflow.config`) | Parameter | Default | Description | |-----------|---------|-------------| | `--container` | `encode-toolkit/pipeline-rnaseq:1.0.0` | Image built from `scripts/Dockerfile`. Pass a registry image for `gcp`/`aws`, or a `.sif` file for `slurm` | | `--max_cpus`, `--max_memory`, `--max_time` | `16`, `64.GB`, `24.h` | Upper bounds applied to every process | | `--slurm_queue`, `--slurm_account` | `normal`, none | SLURM partition and account | | `--gcp_project`, `--gcp_workdir` | none (both required for `-profile gcp`) | Google Cloud project and `gs://` work directory | | `--gcp_location`, `--gcp_disk` | `us-central1`, `200.GB` | Google Batch region and per-task disk | | `--aws_queue`, `--aws_workdir` | none (both required for `-profile aws`) | AWS Batch job queue and `s3://` work directory | | `--aws_region`, `--aws_cli_path` | `us-east-1`, `/home/ec2-user/miniconda/bin/aws` | AWS region, and the AWS CLI path inside the Batch AMI | ## Cloud Cost Estimates | Platform | Instance | Cost/Sample | Time/Sample | Notes | |----------|----------|-------------|-------------|-------| | GCP | n1-highmem-8 | ~$3-6 | 2-4 hours | STAR index loading dominates; the `gcp` profile uses spot VMs | | AWS | r5.2xlarge | ~$3-6 | 2-4 hours | r-series for STAR memory; spot recommended | | Local | 8 cores, 36 GB | $0 | 3-6 hours | Docker required | | SLURM | 8 cores, 36 GB | Varies | 2-4 hours | Singularity; pass the `.sif` with `--container` | **Memory note**: `nextflow.config` asks for 36 GB for `STAR_ALIGN` (multiplied by the attempt number on a retry, capped by `--max_memory`). The local executor refuses the task on a machine with less, so a 32 GB host is not enough. If 36 GB is out of reach, rebuild the STAR index with a larger `--genomeSAsparseD` (which shrinks the loaded index at some cost in mapping speed) or move to a bigger machine. `--limitGenomeGenerateRAM` is a `genomeGenerate` option and is not a parameter of this workflow. ## Output Directory Structure ``` results/ fastqc/ # FastQC HTML/zip for raw and trimmed reads trimmed/ <sample>_R1_val_1.fq.gz, <sample>_R2_val_2.fq.gz <sample>_R1.fq.gz_trimming_report.txt # one per input file star/ <sample>.Aligned.sortedByCoord.out.bam <sample>.Aligned.sortedByCoord.out.bam.bai <sample>.Aligned.toTranscriptome.out.bam # RSEM input <sample>.Log.final.out <sample>.SJ.out.tab <sample>.ReadsPerGene.out.tab # STAR gene counts <sample>.Signal.UniqueMultiple.str1.out.bg # plus str2 unless --strandedness none <sample>.Signal.Unique.str1.out.bg # same signal, unique mappers only rsem/ <sample>.genes.results # gene_id, TPM, FPKM, expected_count <sample>.isoforms.results # transcript_id, TPM, FPKM, IsoPct <sample>.stat/ # RSEM model statistics, read by MultiQC kallisto/ # absent with --skip_kallisto <sample>/abundance.tsv <sample>/abundance.h5 # only from a kallisto build with HDF5 support <sample>/run_info.json signal/ <sample>_plus.bw, <sample>_minus.bw # or <sample>_unstranded.bw qc/ rseqc/ <sample>.infer_experiment.txt <sample>.read_distribution.txt <sample>.geneBody_coverage.* <sample>.inner_distance.* # paired-end only multiqc/ multiqc_report.html multiqc_data/ pipeline_info/ timeline.html, report.html, trace.txt # Nextflow execution reports ``` ## Common Pitfalls ### 1. Insufficient Memory for STAR STAR loads the whole genome index into memory. `STAR_ALIGN` is configured for 36 GB, so a 32 GB machine will not schedule the task at all under `-profile local`. On shared HPC systems, check the per-job memory limit before submitting. ### 2. Wrong Strandedness Setting Using incorrect strandedness results in near-zero gene counts. If you see uniformly low counts, read `qc/rseqc/<sample>.infer_experiment.txt` and rerun with the matching `--strandedness`. ENCODE dUTP libraries are `reverse` stranded. ### 3. Using FPKM for Cross-Sample Comparison FPKM values are not comparable across samples because they depend on total library composition. Use TPM (comparable across samples) or raw counts with DESeq2/edgeR normalization for differential expression. ### 4. Ignoring Multi-Mapped Reads RSEM uses an expectation-maximization algorithm to probabilistically assign multi-mapped reads. This is critical for gene families and repetitive elements. Do not pre-filter multi-mappers before RSEM quantification. ### 5. Assuming rRNA Contamination Was Checked High rRNA contamination (>10%) indicates failed rRNA depletion and reduces effective sequencing depth. This workflow does not measure it — run the manual check in references/05-qc-metrics.md against `star/<sample>.Aligned.sortedByCoord.out.bam` before trusting the quantifications. ### 6. Not Using 2-Pass Mode for Novel Junctions STAR 1-pass mode only uses annotated splice junctions. 2-pass mode first discovers novel junctions then re-maps, critical for non-model organisms or samples with extensive alternative splicing. This workflow always runs `--twopassMode Basic`. ## Pipeline Scripts | File | Description | |------|-------------| | `scripts/main.nf` | Nextflow DSL2 pipeline | | `scripts/nextflow.config` | Execution profiles (local/slurm/gcp/aws) | | `scripts/Dockerfile` | Docker build with STAR, RSEM, Kallisto, RSeQC | ## ENCODE Data Integration After running on your own data, compare with ENCODE reference: ```python # Find matching ENCODE RNA-seq experiments encode_search_experiments( assay_title="total RNA-seq", organ="pancreas", biosample_type="tissue" ) # Download ENCODE gene quantifications for comparison encode_batch_download( download_dir="/data/encode_reference/", output_type="gene quantifications", assay_title="total RNA-seq", organ="pancreas", assembly="GRCh38" ) # Download ENCODE signal tracks for browser visualization encode_search_files( file_format="bigWig", assay_title="total RNA-seq", organ="pancreas", output_type="signal of unique reads" ) ``` ## Pitfalls & Edge Cases - **Strandedness must match library prep**: `--strandedness` feeds RSEM, kallisto and the signal tracks. Using the wrong value can halve gene counts, assign reads to antisense genes, and swap the plus/minus bigWigs. - **rRNA contamination**: rRNA >10% wastes sequencing depth. Ribosomal depletion libraries should have <5%, poly-A selection libraries <1%. The workflow does not measure it; see references/05-qc-metrics.md for a manual count, or run Picard CollectRnaSeqMetrics outside the container. - **STAR 2-pass mode is required**: The first pass discovers novel splice junctions; the second pass uses them. Single-pass STAR misses tissue-specific or rare splicing events, reducing sensitivity for differential exon usage. - **Gene-level vs transcript-level quantification**: RSEM provides transcript-level estimates but gene-level aggregation is more robust for differential expression. Transcript-level analysis requires many more replicates (≥6). - **TPM normalization is not for cross-sample comparison**: TPM normalizes within a sample but is NOT appropriate for comparing expression across conditions. Use DESeq2 size factors or TMM normalization for differential expression. - **Batch effects in multi-lab data**: RNA-seq is highly sensitive to library prep method, sequencer, and lab. Always check for batch effects with PCA before combining datasets from different sources. ## Walkthrough: Processing ENCODE RNA-seq from FASTQ to Gene Quantification **Goal**: Process raw RNA-seq FASTQ files through the ENCODE pipeline to generate gene expression quantifications (TPM/FPKM) and signal tracks. **Context**: The ENCODE RNA-seq pipeline uses STAR 2-pass alignment and RSEM quantification, producing both gene-level and transcript-level expression estimates. ### Step 1: Find RNA-seq experiment ``` encode_get_experiment(accession="ENCSR000CPR") ``` Expected output: ```json { "accession": "ENCSR000CPR", "assay_title": "total RNA-seq", "biosample_summary": "K562", "assembly": ["GRCh38"], "bio_replicate_count": 2, "status": "released" } ``` ### Step 2: List FASTQ files ``` encode_list_files(experiment_accession="ENCSR000CPR", file_format="fastq") ``` Expected output (a JSON array of file records; fields abridged): ```json [ {"accession": "ENCFF200RN1", "file_format": "fastq", "output_type": "reads", "file_size_human": "3.2 GB", "biological_replicates": [1], "status": "released"}, {"accession": "ENCFF201RN2", "file_format": "fastq", "output_type": "reads", "file_size_human": "3.3 GB", "biological_replicates": [1], "status": "released"} ] ``` ### Step 3: Download and name the FASTQs so a read-pair glob can find them ``` encode_download_files(file_accessions=["ENCFF200RN1", "ENCFF201RN2"], download_dir="/data/rnaseq/fastq") ``` ENCODE names every FASTQ after its accession (`ENCFF200RN1.fastq.gz`), with no `_R1`/`_R2` in the name, so the two files of a pair share no prefix and the `--reads` glob cannot pair them. Link them into the shape the glob expects. Which mate an accession is comes from the ENCODE file record on encodeproject.org, which carries `paired_end` (1 or 2) and `paired_with`; the MCP file tools do not return those two fields: ```bash cd /data/rnaseq/fastq ln -s ENCFF200RN1.fastq.gz k562_rep1_R1.fq.gz ln -s ENCFF201RN2.fastq.gz k562_rep1_R2.fq.gz ``` ### Step 4: Run the RNA-seq pipeline ```bash nextflow run scripts/main.nf -profile local \ --reads '/data/rnaseq/fastq/k562_*_R{1,2}.fq.gz' \ --genome GRCh38 \ --star_index /ref/GRCh38_star_index \ --rsem_index /ref/GRCh38_rsem_index/GRCh38 \ --kallisto_index /ref/gencode.v38.kallisto.idx \ --rseqc_bed /ref/hg38_RefSeq.bed \ --strandedness reverse \ --outdir results/ ``` Key pipeline steps: 1. FastQC on the raw reads, quality and adapter trimming with Trim Galore (which also runs FastQC on the trimmed reads) 2. STAR 2-pass alignment (splice-aware), writing the genome BAM, the transcriptome BAM, gene counts and bedGraphs 3. RSEM gene and isoform quantification (TPM, FPKM, expected counts) 4. Kallisto transcript quantification (optional, skipped with `--skip_kallisto`) 5. Signal track generation (bedGraph to bigWig) 6. RSeQC (infer_experiment, read_distribution, geneBody_coverage, inner_distance) and MultiQC ### Step 5: Validate output quality | Metric | Threshold | Where to read it | |---|---|---| | Uniquely mapped rate | >= 70% | `star/<sample>.Log.final.out` | | Strandedness agreement | > 90% and matching `--strandedness` | `qc/rseqc/<sample>.infer_experiment.txt` | | Exonic rate | > 60% | `qc/rseqc/<sample>.read_distribution.txt` | | Replicate correlation | >= 0.9 | compute yourself from the TPM column of `rsem/<sample>.genes.results` | ### Step 6: Use expression data with ENCODE epigenomic data Compare gene expression with enhancer marks: ``` encode_search_experiments(assay_title="Histone ChIP-seq", biosample_term_name="K562", target="H3K27ac", organism="Homo sapiens") ``` **Interpretation**: Genes with high TPM AND nearby H3K27ac peaks have validated enhancer-gene connections. Low expression despite nearby enhancer marks suggests poised or tissue-specific regulation. ### Integration with downstream skills - Gene quantifications feed into -> **peak-annotation** for expression-validated peak targets - Expression data connects to -> **gtex-expression** for tissue comparison - Processed data feeds into -> **compare-biosamples** for differential expression analysis - Pipeline provenance logged by -> **data-provenance** ## Code Examples ### 1. Find RNA-seq experiments for a tissue ``` encode_search_experiments(assay_title="total RNA-seq", organ="liver", organism="Homo sapiens") ``` Expected output: ```json { "results": [ {"accession": "ENCSR300RNA", "assay_title": "total RNA-seq", "biosample_summary": "liver tissue male adult (54 years)", "status": "released"} ], "total": 35, "limit": 25, "offset": 0, "has_more": true, "next_offset": 25 } ``` ### 2. Check for existing gene quantifications ``` encode_list_files(experiment_accession="ENCSR300RNA", file_format="tsv", output_type="gene quantifications", assembly="GRCh38") ``` Expected output (a JSON array of file records; fields abridged): ```json [ {"accession": "ENCFF400GEQ", "file_format": "tsv", "output_type": "gene quantifications", "assembly": "GRCh38", "file_size_human": "5.2 MB", "status": "released"} ] ``` ### 3. Download expression data ``` encode_download_files(file_accessions=["ENCFF400GEQ"], download_dir="/data/rnaseq/quantification") ``` Expected output (fields abridged): ```json { "downloaded": [ {"accession": "ENCFF400GEQ", "file_path": "/data/rnaseq/quantification/ENCFF400GEQ.tsv", "file_size_human": "5.2 MB", "success": true, "md5_verified": true} ], "errors": [], "summary": {"total_requested": 1, "successful": 1, "failed": 0, "total_size_human": "5.2 MB"} } ``` ## Integration | This skill produces... | Feed into... | Purpose | |---|---|---| | Gene expression (TPM/FPKM) | **peak-annotation** | Validate enhancer targets with expression data | | Expression matrix | **gtex-expression** | Compare cell-line vs. tissue expression | | Differential expression results | **compare-biosamples** | Identify tissue-specific gene regulation | | Signal tracks (bigWig) | **visualization-workflow** | Display expression signal in genome browser | | Expression quantifications | **disease-research** | Connect gene expression to disease phenotypes | | Pipeline run parameters | **data-provenance** | Record STAR/RSEM versions and settings | | QC metrics | **quality-assessment** | Validate against ENCODE RNA-seq standards | ## Related Skills - **pipeline-guide** (parent): General pipeline selection and resource assessment - **quality-assessment**: Deep-dive QC analysis beyond basic metrics - **integrative-analysis**: Combine RNA-seq with ChIP-seq/ATAC-seq for regulatory inference - **compare-biosamples**: Compare expression profiles across cell types - **single-cell-encode**: For scRNA-seq data processing (different pipeline) - **pipeline-chipseq**: Sibling pipeline for ChIP-seq data - **pipeline-atacseq**: Sibling pipeline for ATAC-seq data - **publication-trust**: Verify literature claims backing analytical decisions ## Presenting Results When reporting RNA-seq pipeline results: - **Mapping rate**: Report the STAR uniquely mapped rate (>70% expected), multi-mapped rate (<10%), and unmapped rate from `star/<sample>.Log.final.out` - **Quantification paths**: Provide paths to `rsem/<sample>.genes.results` (TPM, FPKM, expected_count), `rsem/<sample>.isoforms.results`, and `kallisto/<sample>/abundance.tsv` when Kallisto ran - **Strandedness**: Confirm the orientation reported in `qc/rseqc/<sample>.infer_experiment.txt` matches the `--strandedness` value the run used; if it does not, the run has to be repeated - **Key QC metrics**: Present the exonic rate from `read_distribution.txt` and the gene body coverage uniformity from `geneBody_coverage.geneBodyCoverage.txt` in a summary table, alongside the MultiQC report at `qc/multiqc/multiqc_report.html` - **Derived metrics**: Detected-gene counts (TPM>1), rRNA rate, library duplication rate and saturation are not produced by this workflow. Compute them separately if they are needed, and say so when reporting - **Signal tracks**: Provide paths to `signal/<sample>_plus.bw` and `signal/<sample>_minus.bw` (or `signal/<sample>_unstranded.bw` for an unstranded run) - **Next steps**: Suggest `integrative-analysis` to combine RNA-seq with ChIP-seq/ATAC-seq for regulatory inference, or `compare-biosamples` for cross-tissue expression comparison ## For the request: "$ARGUMENTS"
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.