{"id":"bulk-rnaseq","name":"bulk-rnaseq","summary":"エンドツーエンドのバルクRNA-seqオーケストレーター — 生のFASTQリードをQCとトリミング(FastQC、fastp/Trim Galore)、アラインメントと定量(STAR、Salmon、featureCounts)を行い、遺伝子レベルのカウントマトリックスを組み立て、その後差分発現(pydeseq2)、…","body":"# Bulk RNA-seq\n\n## Overview\n\nThis skill orchestrates a complete, **defensible** bulk RNA-seq differential-expression study, from raw sequencing reads to enriched pathways and figures. It is a router, not a reimplementation: most stages already have dedicated skills in this repo, and this skill connects them in the right order, fills the one real gap (raw reads → a gene-level counts matrix), and enforces the design and QC decisions that determine whether the final result is trustworthy.\n\n\"Defensible\" means three things, applied throughout:\n- **Reproducible** — pinned pipeline/tool versions, containers where possible, recorded parameters, fixed random seeds.\n- **Quality-gated** — QC is inspected and acted on before, during, and after quantification, not skipped.\n- **Statistically sound** — adequate replication, a design that matches the biology, counts handled correctly, and FDR-controlled testing.\n\nThe pipeline is: **FastQC/trim → align/quant (STAR/Salmon) → counts → DE (pydeseq2) → enrichment (pathway-enrichment) → figures**.\n\n## When to Use This Skill\n\nUse this skill when the user wants to:\n- Go from FASTQ files (or a sequencing run) to differentially expressed genes and pathways.\n- Run or configure `nf-core/rnaseq`, or align/quantify with STAR, Salmon, or featureCounts.\n- Turn Salmon/STAR/featureCounts output into a counts matrix ready for DESeq2/PyDESeq2.\n- Design or sanity-check a bulk RNA-seq experiment (replicates, batch, strandedness) before committing compute.\n- Scope an end-to-end RNA-seq analysis and decide which tools and skills to chain.\n\nThis is **bulk** RNA-seq (samples = biological specimens). For single-cell/nuclei data use `scanpy`; for the DE statistics alone use `pydeseq2`; for enrichment alone use `pathway-enrichment`.\n\n## The Pipeline at a Glance\n\n```mermaid\nflowchart TD\n    fastq[\"Raw FASTQ + samplesheet\"] --> qc[\"FastQC + MultiQC\"]\n    qc --> trim[\"Trim: fastp / Trim Galore\"]\n    trim --> align[\"Align + quant: STAR and/or Salmon\"]\n    align --> counts[\"Gene-level counts matrix\"]\n    counts --> de[\"Differential expression\"]\n    de --> enrich[\"Pathway / GSEA enrichment\"]\n    de --> fig[\"Figures\"]\n    enrich --> fig\n    nfcore[\"nf-core/rnaseq via nextflow skill\"] -.->|\"path A\"| align\n    manual[\"Standalone recipes (this skill)\"] -.->|\"path B\"| align\n    bridge[\"build_counts_matrix.py (this skill)\"] -.-> counts\n    pydeseq2skill[\"pydeseq2 skill\"] -.-> de\n    pwskill[\"pathway-enrichment skill\"] -.-> enrich\n    vizskill[\"scientific-visualization skill\"] -.-> fig\n```\n\n## Two Upstream Paths — Pick One\n\nThe reads → counts stage can be run two ways. They produce equivalent gene counts; choose by context, then stay on that path.\n\n| Use **Path A — `nf-core/rnaseq`** when… | Use **Path B — standalone tools** when… |\n|------------------------------------------|------------------------------------------|\n| You want the field-standard, audited, citable pipeline with one command | You have a few samples and want to learn/inspect each step |\n| Many samples, or you'll scale to HPC/cloud | No Nextflow/containers available, or a constrained environment |\n| Reproducibility and a full MultiQC report matter most | You need a non-standard step the pipeline doesn't expose |\n| → Drive it through the **`nextflow`** skill | → Follow `references/upstream-manual.md` |\n\nWhen unsure, prefer **Path A**: `nf-core/rnaseq` already wires together FastQC → trimming → STAR/Salmon → quantification → tximport → MultiQC with sensible, reviewed defaults, which is the most defensible option. Path B exists for transparency and constrained setups.\n\nBoth paths converge on a **gene-level counts matrix**, after which the workflow is identical.\n\n## Setup\n\n```bash\n# This skill's glue (bridge + handoffs) — Python\nuv pip install pytximport pandas\n\n# Downstream skills install their own deps:\n#   pydeseq2 skill           -> uv pip install pydeseq2\n#   pathway-enrichment skill -> uv pip install gseapy gprofiler-official\n\n# Path A (nf-core): only Nextflow + a container engine are needed — see the `nextflow` skill.\n\n# Path B (standalone tools): install via bioconda. Pin versions for reproducibility.\nconda create -n rnaseq -c bioconda -c conda-forge \\\n  fastqc fastp trim-galore \"star=2.7.11b\" \"salmon=1.10.3\" subread multiqc\n```\n\nRecord the exact versions you use (pipeline revision, tool versions, reference genome + annotation release) — they belong in the methods section and make the analysis reproducible.\n\n## Quick Start\n\n### Path A — nf-core/rnaseq (recommended)\n\n```bash\n# 0. Validate the samplesheet first (catches the most common failures early)\npython scripts/validate_samplesheet.py --samplesheet samplesheet.csv\n\n# 1. Smoke-test the environment with tiny bundled data\nnextflow run nf-core/rnaseq -r 3.26.0 -profile test,docker --outdir test_results\n\n# 2. Real run: pin the revision, pick an aligner, pass a samplesheet + reference\nnextflow run nf-core/rnaseq -r 3.26.0 \\\n  -profile docker \\\n  --input samplesheet.csv \\\n  --genome GRCh38 \\\n  --aligner star_salmon \\\n  --outdir results \\\n  -resume\n```\n\n`nf-core/rnaseq` runs tximport internally, so gene counts come out **already merged** — no bridge script needed. Use `results/star_salmon/salmon.merged.gene_counts_length_scaled.tsv` for DE. Samplesheet format, aligner choice, and outputs: `references/upstream-nfcore.md`. For engine/HPC/cloud/container detail, use the **`nextflow`** skill.\n\n### Path B — standalone STAR/Salmon (abbreviated)\n\n```bash\nfastqc -o qc/ reads/*.fastq.gz                      # 1. QC raw reads\nfastp -i s1_R1.fq.gz -I s1_R2.fq.gz \\\n      -o s1_R1.trim.fq.gz -O s1_R2.trim.fq.gz \\\n      --thread 4 -j s1.fastp.json                   # 2. Trim adapters/low-quality\nsalmon quant -i salmon_index -l A \\\n      -1 s1_R1.trim.fq.gz -2 s1_R2.trim.fq.gz \\\n      --gcBias --seqBias -p 8 -o quant/s1            # 3. Quantify (per sample)\n```\n\nFull recipes (FastQC, fastp/Trim Galore, STAR index+align+`--quantMode GeneCounts`, Salmon decoy-aware index, featureCounts, strandedness): `references/upstream-manual.md`.\n\n### Counts → DE → enrichment (both paths)\n\n```bash\n# Path B only: assemble a gene x sample counts matrix + metadata template for PyDESeq2\npython scripts/build_counts_matrix.py --from salmon \\\n  --quant-dir quant/ --tx2gene tx2gene.tsv --output-dir counts/\n\n# Then hand off (see the dedicated skills):\n#   pydeseq2:           counts.csv + metadata.csv -> DE table (log2FC, padj, stat)\n#   pathway-enrichment: rank by `stat` (GSEA) or padj+|LFC| hit list (ORA)\n#   scientific-visualization / matplotlib: volcano, MA, heatmap, PCA, enrichment dotplot\n```\n\n## Stage-by-Stage Workflow\n\nWork top to bottom. Each stage names the skill or file that owns the detail. Don't skip the design/QC stages — they are where bulk RNA-seq studies most often go wrong.\n\n1. **Design & sample sheet.** Confirm ≥3 biological replicates per group, identify batch/confounders, and choose the comparison(s). Build the samplesheet and validate it with `scripts/validate_samplesheet.py`. Rationale and rules: `references/design-and-qc.md`.\n2. **Raw-read QC.** FastQC per file; aggregate with MultiQC. Check per-base quality, adapter content, duplication, and over-representation. Thresholds: `references/design-and-qc.md`.\n3. **Trimming.** Remove adapters and low-quality tails (via `fastp` or `Trim Galore`). Re-run FastQC to confirm. Recipes: `references/upstream-manual.md` (Path A does this for you).\n4. **Align / quantify.** STAR (genome alignment + `--quantMode GeneCounts`) and/or Salmon (transcript quasi-mapping, decoy-aware). Determine strandedness — it is easy to get wrong and silently halves your counts. Detail: `references/upstream-manual.md`; pipeline params: `references/upstream-nfcore.md`.\n5. **Build the counts matrix.** Turn quant output into a gene × sample integer matrix and a metadata template (`scripts/build_counts_matrix.py`). The estimated-count and gene-ID-mapping nuances live in `references/counts-and-handoff.md`.\n6. **Differential expression → `pydeseq2` skill.** Load `counts.csv` + `metadata.csv`, set the design (e.g. `~batch + condition`), fit, and test with FDR control. Inspect the PCA and p-value histogram as QC.\n7. **Enrichment → `pathway-enrichment` skill.** For GSEA, rank the *full* gene list by the DESeq2 `stat`; for ORA, pass the thresholded hit list (padj < 0.05, optionally |log2FC| > 1). Map gene IDs to symbols first.\n8. **Figures → `scientific-visualization` skill.** Volcano, MA, sample-distance heatmap, PCA, and enrichment dotplots, plus the MultiQC report for the QC narrative.\n\n## The counts → DE bridge (the key glue)\n\nThis is the one stage with no upstream/downstream skill, so this skill owns it. `scripts/build_counts_matrix.py` converts quant output into exactly what `pydeseq2` expects:\n\n- **Salmon** (`--from salmon`): aggregates per-sample `quant.sf` to gene level with `pytximport` using `counts_from_abundance=\"length_scaled_tpm\"` (the right choice for gene-level DE), needs a `tx2gene` map.\n- **STAR** (`--from star`): reads each `ReadsPerGene.out.tab`, selecting the column for your `--strandedness` (unstranded/forward/reverse).\n- **featureCounts** (`--from featurecounts`): parses the combined `featureCounts` matrix.\n\nIt writes `counts.csv` (genes × samples, integers) and `metadata_template.csv` (one row per sample) for you to fill in. **Salmon/RSEM counts are estimates (non-integer); they are rounded to integers** because PyDESeq2 requires integer counts — see `references/counts-and-handoff.md` for why this is acceptable with `length_scaled_tpm` and how it differs from the offset-based DESeq2+tximport route. That reference also covers Ensembl→symbol mapping (needed before enrichment) and the exact orientation PyDESeq2 wants.\n\n## Common Pitfalls\n\nThese cause most wrong or irreproducible bulk RNA-seq results:\n\n1. **Too few replicates.** <3 biological replicates per group gives almost no power and unstable dispersion estimates. More replicates beat deeper sequencing.\n2. **Confounded batch and condition.** If every treated sample was processed on a different day/lane than controls, the effect is unrecoverable. Randomize, and model known batches (`~batch + condition`). See `references/design-and-qc.md`.\n3. **Wrong strandedness.** Choosing the wrong STAR column or featureCounts `-s`/Salmon library type silently discards ~half the reads. Use Salmon `-l A` or infer strandedness, and verify the assigned-reads fraction.\n4. **Feeding TPM/FPKM to DESeq2.** DESeq2 needs raw (or length-scaled) **counts**, never TPM/FPKM/normalized values. The bridge handles this.\n5. **Non-integer counts.** PyDESeq2 requires integers; round Salmon estimates (the bridge does this).\n6. **Gene-ID mismatch into enrichment.** DESeq2 output is often Ensembl IDs; Enrichr/MSigDB want symbols. Map IDs before `pathway-enrichment` or \"nothing is significant\".\n7. **Skipping post-quant QC.** Always look at the PCA and sample-distance heatmap before trusting DE — they expose swapped labels, outliers, and hidden batches.\n8. **Mixing aligners across samples.** Quantify every sample with the same tool, version, reference, and parameters.\n9. **Unpinned versions.** \"latest\" pipelines/genomes make results unreproducible; pin `-r`, tool versions, and the genome/annotation release.\n\n## Integration with Other Skills\n\n- **Upstream execution:** `nextflow` (runs `nf-core/rnaseq`, Path A; HPC/cloud/containers).\n- **Reference data / gene IDs:** `gget` (`gget ref` for genome+GTF, `gget info`/`gget search` for ID mapping), `database-lookup` (Ensembl/NCBI), `biopython`/`pysam` (FASTA/BAM handling).\n- **Differential expression:** `pydeseq2` (the DE engine this skill hands counts to).\n- **Enrichment:** `pathway-enrichment` (ORA + GSEA; its `scripts/run_enrichment.py` reads a DESeq2 results CSV directly).\n- **Figures & reporting:** `scientific-visualization`, `matplotlib`, `seaborn`; `scientific-writing` for the methods/results narrative.\n- **Related but distinct:** `scanpy` (single-cell), `statistical-analysis` (multiple-testing depth).\n\n## Reference Files\n\nRead the relevant file when you need depth — each is self-contained:\n\n- `references/upstream-nfcore.md` — Path A: samplesheet format, `--aligner`/`--pseudo_aligner` choice, key params, the `salmon.merged.gene_counts*.tsv` outputs, MultiQC, and what to hand to `pydeseq2`.\n- `references/upstream-manual.md` — Path B: FastQC, fastp/Trim Galore, STAR genome index + alignment + `--quantMode GeneCounts`, Salmon decoy-aware index + `quant`, featureCounts, and how to determine strandedness.\n- `references/counts-and-handoff.md` — turning quant output into PyDESeq2-ready `counts.csv`/`metadata.csv` (pytximport, STAR column selection, featureCounts), the integer/estimated-count nuance, Ensembl→symbol mapping, and the DE→enrichment rank/hit-list recipe.\n- `references/design-and-qc.md` — experimental design (replication, batch, confounding, design formulas) and QC-metric interpretation (mapping rate, duplication, rRNA, complexity, PCA/outliers) — the defensible-pipeline backbone.\n\n## Resources\n\n- nf-core/rnaseq: https://nf-co.re/rnaseq · STAR: https://github.com/alexdobin/STAR · Salmon: https://salmon.readthedocs.io\n- fastp: https://github.com/OpenGene/fastp · Trim Galore: https://github.com/FelixKrueger/TrimGalore · MultiQC: https://multiqc.info\n- pytximport: https://pytximport.complextissue.com · featureCounts (Subread): https://subread.sourceforge.net\n- Method background: Love et al. 2014 (DESeq2) DOI 10.1186/s13059-014-0550-8 · Soneson et al. 2015 (tximport) DOI 10.12688/f1000research.7563.2","author":"@K-Dense-AI","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/K-Dense-AI/scientific-agent-skills/tree/main/skills/bulk-rnaseq","license":"MIT","category":"devops","lang":"en","tokens":3504,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"references/counts-and-handoff.md","size":6133,"sha256":"957241bffd1ec772697c47dda3d3a4474abbbd9d6f0d8ed9d0c854b708158e77"},{"path":"references/design-and-qc.md","size":5117,"sha256":"cf28bd0ff327b3a271074c14390a6642d4f59604bff961f16fb5e875b0f244f1"},{"path":"references/upstream-manual.md","size":5487,"sha256":"d467f8a45e6464f5e0b4292fa14f3602cc01556771e2ce4f6eb695d329173a87"},{"path":"references/upstream-nfcore.md","size":6186,"sha256":"47ff74b1a2afeeaade186dbea15a46fc4b66d80660b8e954bb9363514f2bdbac"},{"path":"scripts/build_counts_matrix.py","size":8081,"sha256":"17e7de8ad99847fc6b87441e446f302679cadc138d31252dffabf9e43cd65553"},{"path":"scripts/validate_samplesheet.py","size":8130,"sha256":"a14ccabbea68b34741facf133d5fba3055f0bb86978918f61a7571c297de1ab6"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[{"code":"net.endpoints","kind":"exfiltration","excerpt":"multiqc.info, nf-co.re, pytximport.complextissue.com, salmon.readthedocs.io, subread.sourceforge.net","message":"bundled scripts reach 5 external host(s)","severity":"warn"}],"scannedAt":"2026-08-22","hasScripts":true,"networkEndpoints":["multiqc.info","nf-co.re","pytximport.complextissue.com","salmon.readthedocs.io","subread.sourceforge.net"]}}