Lab 04 — Multi-Sample Pipelines and Modules
Key concepts and tools
- Samplesheets — CSV files as structured pipeline input
List<RecordType>params and automatic CSV parsingchannel.fromList(params.samplesheet)— channel from a typed list- Named record types:
record Sample { name: String; url: String } - Record field propagation — carrying
namethrough every process include { PROCESS } from './modules/...'— the modules systemstub:block and-stub-run— testing pipeline logic without real tools.map {},.collect()— channel operators for multi-sample aggregationpublishDiron a collection process
This lab extends the single-genome pipeline from lab 2 to process multiple bacterial genomes in parallel. The bioinformatics tools are unchanged — wget and genome_stats.py — so the focus is entirely on Nextflow patterns: samplesheets, typed records, modules, and aggregating per-sample results into a single summary.
Setup
module load miniconda
conda activate nextflow_latest
export NXF_SYNTAX_PARSER=v2
nextflow run main.nf -profile conda,local # local test
nextflow run main.nf -profile conda,cluster # submit to SCC
Structure
main.nf # complete — defines record types, includes, workflow
samplesheet.csv # three bacterial genomes
modules/
download/main.nf # typed I/O provided — fill in script block
genome_stats/main.nf
summarize/main.nf # fully complete — see how List<Path> input works
bin/
genome_stats.py
envs/
biopython_env.yml
Task 1 — Read main.nf and samplesheet.csv
main.nf is fully complete. Read it before writing any code. Notice:
- Three named record types at the top:
Sample,GenomeFile,StatsFile. TheSamplefieldsnameandurlmatch the CSV column names — Nextflow parses the CSV automatically. channel.fromList(params.samplesheet)emits one record per row.- Three
includestatements import processes frommodules/. - The workflow uses
.mapand.collect()to gather all per-sample stats files before passing them toSUMMARIZE.
Task 2 — Write the DOWNLOAD module
modules/download/main.nf has the typed I/O already filled in. Fill in the script block:
wget ${url} -O ${name}.fna.gz
Input record fields (name, url) are available as variables in the script block directly. Test wiring before downloading anything:
nextflow run main.nf -profile conda,local -stub-run
The stub: block runs instead of script:, creating empty placeholder files instantly. A clean stub run confirms that all includes resolve and channels wire correctly.
Task 3 — Write the GENOME_STATS module
modules/genome_stats/main.nf has the typed I/O already filled in. Fill in the script block:
genome_stats.py -i ${fa} -n ${name} -o ${name}_stats.tsv
Make the script executable first:
chmod +x bin/genome_stats.py
Task 4 — Run and inspect
nextflow run main.nf -profile conda,cluster
After the run, check results/summary.tsv — it should have a header row and one data line per genome. Then inspect the execution log:
nextflow log <run-name> -f hash,name,exit,status
Navigate into a work/ subdirectory and open .command.sh to see exactly what command ran for that task.
Optional
Add a fourth genome to samplesheet.csv and re-run. Only the new genome’s processes execute — the other three are served from cache.