# RNA-seq Expression Workflow (`rnaseq_expression`)

> **Plugin**: `rnaseq_expression`
> **Status**: Active (2026-06-18)

## Workflow

```text
FASTQ
  → fastp (QC)
  → STAR / HISAT2 (alignment)
  → featureCounts (quantification)
  → DESeq2 (differential expression)
  → offline gene-symbol + GO/Reactome ORA/GSEA (GSEApy, optional)
  → report + figures
```

## Tool Chain

| Stage | Default Tool | Alternative | Category |
| --- | --- | --- | --- |
| QC | fastp | FastQC, MultiQC | qc |
| Alignment | STAR | HISAT2 | alignment |
| Quantification | featureCounts | Salmon, Kallisto | expression |
| Differential expression | DESeq2 | edgeR | differential_expression |
| Enrichment | ABI offline enrichment + GSEApy | — | enrichment |

## Standard Tables

| Table | Content | Required |
| --- | --- | --- |
| `qc_summary` | Read QC metrics (total reads, Q30, GC) | Yes |
| `alignment_summary` | Mapping rate, unique/multi-mapped reads | Yes |
| `gene_expression` | Per-gene raw counts | Yes |
| `normalized_expression` | DESeq2 median-of-ratios normalized counts | Yes |
| `differential_expression` | log2FC, p-value, padj per gene | Yes |
| `annotated_differential_expression` | DESeq2 rows with GTF `gene_symbol` | No |
| `go_overrepresentation`, `reactome_overrepresentation` | Complete ORA results with overlap symbols | No |
| `go_gsea`, `reactome_gsea` | Complete preranked GSEA results with leading-edge symbols | No |

## Figures

| Figure | File | Required |
| --- | --- | --- |
| QC read counts | `figures/qc_read_counts.png` | Yes |
| Mapping rate | `figures/mapping_rate.png` | Yes |
| PCA expression | `figures/pca_expression.png` | Yes |
| Volcano plot | `figures/volcano_deg.png` | Yes |
| MA plot | `figures/ma_plot.png` | No |
| Top DEG heatmap | `figures/top_deg_heatmap.png` | No |
| GO/Reactome ORA + GSEA | Four SciPlot PDF/SVG/PNG figure bundles | No |

## Quick Start

```bash
# Plan
abi plan --type rnaseq_expression \
  --config data/examples/rnaseq_expression/config.yaml \
  --outdir results/rnaseq_example

# Dry-run
abi dry-run --type rnaseq_expression \
  --config data/examples/rnaseq_expression/config.yaml \
  --outdir results/rnaseq_example

# Real execution (requires STAR index + GTF annotation)
abi run --type rnaseq_expression \
  --config data/examples/rnaseq_expression/config.yaml \
  --outdir results/rnaseq_example \
  --confirm-execution

# Report
abi report --type rnaseq_expression \
  --result-dir results/rnaseq_example
```

## Configuration

### Minimum config

```yaml
project_name: "rnaseq_expression_run"
mode: dry_run
threads: 4
outdir: results/rnaseq_expression
input:
  sample_sheet: sample_sheet.tsv
alignment:
  tool: star
resources:
  genome_index: /path/to/star_index
  annotation_gtf: /path/to/Homo_sapiens.GRCh37.75.gtf
  go_obo: /path/to/go-basic.obo
  go_gaf: /path/to/goa_human.gaf.gz
  reactome_gmt: /path/to/ReactomePathways.gmt
enrichment:
  enabled: true
  annotation_release: GRCh37.75
  rank_column: stat
  permutations: 1000
  gsea_fdr: 0.25
  seed: 20260727
differential_expression:
  comparison: "treatment_vs_control"
  alpha: 0.05
```

`enrichment.gsea_fdr` must be in `(0, 1]`. It only filters the SciPlot GSEA
preview; the complete GO and Reactome GSEA tables remain untruncated.

### Sample sheet format

```text
sample_id	group	condition	platform	read1	read2
sample1	treatment	treated	rna_seq	raw/s1_R1.fastq.gz	raw/s1_R2.fastq.gz
sample2	treatment	treated	rna_seq	raw/s2_R1.fastq.gz	raw/s2_R2.fastq.gz
sample3	control	untreated	rna_seq	raw/s3_R1.fastq.gz	raw/s3_R2.fastq.gz
sample4	control	untreated	rna_seq	raw/s4_R1.fastq.gz	raw/s4_R2.fastq.gz
```

Required columns: `sample_id`, `read1`, `read2`. Optional: `group`, `condition`, `platform`.

## Resource Requirements

Real execution requires:

1. **STAR genome index** — Build with `STAR --runMode genomeGenerate`.
2. **GTF annotation** — GENCODE, Ensembl, or RefSeq format.
3. **R + DESeq2** — `BiocManager::install("DESeq2")`.
4. **Optional enrichment resources** — local GO OBO, human GOA GAF, and Reactome GMT snapshots.
5. **Optional enrichment runtime** — the locked `rnaseq` environment includes GSEApy 1.3.0; the stage performs no network access.

All resources appear in `provenance/resource_manifest.json` after a real run.

## Known Limitations

See `plugins/rnaseq_expression/limitations.yaml` for the complete list. Key points:

1. RNA-seq measures transcript abundance, not protein levels.
2. Alignment rates depend on reference genome completeness.
3. DESeq2 assumes most genes are not differentially expressed.
4. Lowly expressed genes have inflated FDR.
5. Reference genome/annotation version affects results.

## Architecture Notes

This plugin is an **inline implementation** (no `_engine/` sub-package), following the
same pattern as `metatranscriptomics`. The parser functions live in the plugin module
itself rather than in a separate `parsers.py`.

### Plugin lifecycle

```
load_config()  →  build_plan()  →  run (ExternalExecutor)
  →  parse_outputs() (per step)  →  write_report()
```

### Parser dispatch

`parse_outputs(tool_id, output_dir, sample_id)` dispatches:
- `fastp` → `_parse_fastp()` → `qc_summary`
- `star` → `_parse_star()` → `alignment_summary`
- `featurecounts` → `_parse_featurecounts()` → `gene_expression`
- `deseq2` → `_parse_deseq2()` + `_parse_deseq2_normalized()` → `differential_expression` + `normalized_expression`
- `rnaseq_enrichment` → gene-symbol annotation + four complete enrichment tables + four top-N SciPlot tables
