# RNA-seq: fastp trim -> salmon quant -> MultiQC -> DESeq2. # Snakemake 8+. Run `snakemake -n` (dry run) to inspect the static DAG before executing. # Reproducibility note: container tags are PINNED (never :latest). Prefer a @sha256: digest over a # version tag for bit-reproducibility - a re-pushed version tag silently changes the tool and busts # the rerun cache. Activate deployment with `snakemake --sdm apptainer --cores N`. configfile: "config/config.yaml" SAMPLES = config["samples"] SALMON_INDEX = config["salmon_index"] # Constrain the sample wildcard: greedy `.+` would otherwise swallow path separators and adjacent # tokens, silently mis-routing a sample whose name contains an underscore or slash. wildcard_constraints: sample = r"[A-Za-z0-9\-]+" rule all: input: "results/multiqc_report.html", "results/de_results.csv" rule fastp_trim: input: r1 = "data/{sample}_R1.fq.gz", r2 = "data/{sample}_R2.fq.gz" output: r1 = "trimmed/{sample}_R1.fq.gz", r2 = "trimmed/{sample}_R2.fq.gz", json = "qc/{sample}_fastp.json", html = "qc/{sample}_fastp.html" threads: 4 resources: mem_mb = lambda wildcards, attempt: 4000 * attempt, # escalate RAM on an OOM retry runtime = 60 # MINUTES, not seconds retries: 2 container: "docker://quay.io/biocontainers/fastp:0.23.4--hadf994f_2" # pinned; swap for @sha256: digest for full repro log: "logs/fastp/{sample}.log" shell: """ fastp -i {input.r1} -I {input.r2} \ -o {output.r1} -O {output.r2} \ --json {output.json} --html {output.html} \ --thread {threads} 2> {log} """ rule salmon_quant: input: r1 = "trimmed/{sample}_R1.fq.gz", r2 = "trimmed/{sample}_R2.fq.gz", index = SALMON_INDEX output: directory("salmon/{sample}") threads: 8 resources: mem_mb = lambda wildcards, attempt: 8000 * attempt, runtime = 120 retries: 2 container: "docker://quay.io/biocontainers/salmon:1.10.2--h6dccd9a_2" log: "logs/salmon/{sample}.log" shell: """ salmon quant -i {input.index} -l A \ -1 {input.r1} -2 {input.r2} \ -o {output} --threads {threads} 2> {log} """ rule multiqc: input: fastp = expand("qc/{sample}_fastp.json", sample=SAMPLES), salmon = expand("salmon/{sample}", sample=SAMPLES) output: "results/multiqc_report.html" container: "docker://quay.io/biocontainers/multiqc:1.21--pyhdfd78af_0" log: "logs/multiqc.log" shell: """ multiqc qc/ salmon/ -o results/ -n multiqc_report 2> {log} """ rule deseq2_analysis: input: quants = expand("salmon/{sample}", sample=SAMPLES), metadata = config["metadata"] output: results = "results/de_results.csv", normalized = "results/normalized_counts.csv" log: "logs/deseq2.log" script: "scripts/run_deseq2.R"