Configuration¶
All parameters are passed on the command line with --param value. Boolean flags are set with true or false.
Run nextflow run main.nf --help for a summary of every parameter.
Startup validation¶
Every parameter is checked before the pipeline submits a single task, and all problems
are reported together in one block. In particular, each path and glob pattern is resolved
at startup, so a --reads, --bam_input or --reference pattern that matches no files is
a fatal error rather than a run that completes without producing any variants.
The startup banner also reports what each input resolved to, which is the quickest way to confirm the pipeline sees the data you expect:
Resolved inputs
Reference : ecoli_REL606.fasta (4.5 MB)
Local FASTQ : 6 files -> 3 read pairs
Sample map : 9 run IDs -> 6 sample names
Non-fatal issues — files with no mate, accession lines that do not look like accessions,
flag combinations with no effect — are reported as WARN lines above the banner and do
not stop the run.
File paths and glob patterns¶
--reads, --hifi_reads and --bam_input take glob patterns; --reference, --SRA_index
and --hifi_SRA_index take a single file. The rules below apply to all of them.
Quoting¶
Always use single quotes around a glob pattern.
| Form | Works? | What happens |
|---|---|---|
--reads 'data/*_{1,2}.fastq.gz' |
✅ Use this | The pattern reaches Nextflow intact and Nextflow expands it. |
--reads "data/*_{1,2}.fastq.gz" |
⚠️ Usually | The shell does not glob-expand inside double quotes, so this normally behaves identically — but $ and ` are still interpreted, so a path containing them breaks. |
--reads data/*_{1,2}.fastq.gz |
❌ Silently wrong | The shell expands the pattern first. --reads receives only the first file and Nextflow discards the rest. |
The unquoted form is the dangerous one, because nothing about it looks wrong:
# The shell turns this ...
--reads data/*_{1,2}.fastq.gz
# ... into this, and only the first path is kept:
--reads data/A_1.fastq.gz data/B_1.fastq.gz data/A_2.fastq.gz data/B_2.fastq.gz
The pipeline detects this: any argument left unattached to a parameter is reported as an error naming the parameter that swallowed it, together with the files that were dropped. A quoted pattern is never at risk, so single-quoting is the habit worth keeping.
No quoting is needed for a plain path with no wildcard in it, such as
--reference /data/genome.fasta, though quoting does no harm.
Reading from several locations¶
Give one quoted value and separate the patterns with a semicolon:
Files matched by all the patterns are pooled into a single set of samples, and duplicates matched by more than one pattern are counted once. The startup banner reports the total, so you can confirm every location was picked up.
A comma is not a separator
A comma already means alternation inside a glob — the {1,2} in *_{1,2}.fastq.gz —
so it cannot also separate patterns. path1,path2, path1|path2 and path1 path2 are
each rejected at startup with a message pointing at the semicolon form.
--reference, --SRA_index and --hifi_SRA_index accept exactly one file each; a pattern matching several
files is rejected.
Execution mode¶
| Parameter | Type | Default | Description |
|---|---|---|---|
-profile |
string |
local |
Execution profile. local — up to 4 threads per task. local_highCPU — up to 24 threads. slurm — submit all tasks as SLURM jobs (requires --slurm_queue). |
-resume |
flag | — | Resume from the last completed step. Requires the work-dir to be intact. |
-work-dir |
path |
./work |
Directory for temporary and intermediate files. Use a fast scratch filesystem for large datasets. Note the single dash — --workdir is not a pipeline parameter and the pipeline will tell you so. |
--help |
flag | — | Print all parameters with their defaults and exit. |
--outdir |
path |
./nf_output |
Directory for final output files. |
--slurm_queue |
string |
— | Required with -profile slurm. Name of the SLURM partition to submit all jobs to. The partition should allow a maximum walltime of at least 7 days for large datasets. Shorter limits (1–2 days) may work for smaller genomes or low-depth sequencing, but any job exceeding the partition's walltime limit will fail. |
Read input options¶
Provide either or both of --reads and --SRA_index, optionally together with PacBio HiFi reads (--hifi_reads, --hifi_SRA_index; experimental). Alternatively, provide --bam_input if you have pre-processed BAM files (can't be combined with any read input). See below for details.
Local FASTQ files¶
| Parameter | Type | Default | Description |
|---|---|---|---|
--reads |
glob |
— | Glob pattern pointing to paired-end FASTQ files. Accepts paired-end reads only. Single-quote the pattern; separate several locations with ;. See File paths and glob patterns. |
SRA / ENA accessions¶
| Parameter | Type | Default | Description |
|---|---|---|---|
--SRA_index |
path |
— | Path to a plain-text file listing NCBI/ENA single or paired-end Illumina read accessions (one per line). Accepts SRR, SRX, SRP, PRJNA, ERR, etc. |
--NCBI_API_key |
string |
— | Highly recommended with --SRA_index. Passed to E-utilities as NCBI_API_KEY, raising the metadata lookup rate limit from 3 to 10 requests/second. Get your personal NCBI API key. |
--SRR_sample_map |
path |
false |
CSV file mapping run IDs to sample names, optionally with a library ID (Run_ID,Sample_Name[,Library_ID], no header). Must be comma-separated — a tab-separated file is rejected at startup, because sample names are looked up by comma and every lookup would silently miss. A leading UTF-8 byte-order mark (common in CSVs saved from Excel) is stripped automatically, so it cannot silently break the first line's lookup. See Getting started for format. |
Several runs, one sample
When more than one run maps to the same Sample_Name, the pipeline merges their
BAMs and marks duplicates across the combined reads — GATK's best practice, since
duplicate fragments from the same sample can only be recognised once every read is
in one BAM. Each merged sample still produces exactly one BAM and one gVCF,
which is what lets GenomicsDBImport accept it: a sample name that shows up on more
than one gVCF at the same interval is a fatal GenomicsDBImport error, not something
it merges for you.
Library_ID is optional. Without it, each run is treated as its own library —
assuming several runs share a library, with no other evidence, is not a safe
default, since duplicate marking is scoped to the library.
PacBio HiFi reads (experimental)¶
| Parameter | Type | Default | Description |
|---|---|---|---|
--hifi_reads |
glob |
— | Glob pattern pointing to PacBio HiFi FASTQ files (.fastq, .fq, optionally gzipped), one file per run. The run ID is the file name without its FASTQ extension and must be unique. It must not match any --reads run or any accession listed for download, since the same run would otherwise be merged into its sample twice. Single-quote the pattern; separate several locations with ;. |
--hifi_SRA_index |
path |
— | Plain-text file listing PacBio HiFi SRA/ENA accessions, one per line — in the same format as --SRA_index, but a separate file. An accession may not be listed in both. Paired-end runs resolved from it are skipped with a warning, since they cannot be PacBio data. |
HiFi runs can be given on their own or together with Illumina input. They are not trimmed
(HiFi reads are consensus-called and adapter-free) and are mapped with
pbmm2, PacBio's minimap2 wrapper, using
--preset CCS against a reference index built once per run. pbmm2 writes the read group
itself:
From there a HiFi BAM follows the same path as an Illumina one: runs of the same sample are merged, duplicates are marked, and the sample is called with GATK HaplotypeCaller and joint-genotyped with the rest of the panel.
Combining HiFi and Illumina reads of one sample
Give the HiFi run and the Illumina runs the same Sample_Name in --SRR_sample_map:
Their BAMs are merged into one and called as a single sample, since GATK groups reads by
the SM tag. Each run keeps its own read group ID and library LB. Duplicate
marking is scoped to the library, so HiFi reads are never compared with Illumina reads.
If you set Library_ID in the map yourself, never give a HiFi run the same library
as an Illumina run.
Experimental
- Treat indel calls in samples with HiFi data with caution. HiFi's main remaining
error is a wrong homopolymer length, and HaplotypeCaller's indel error model (its
default
--pcr-indel-model CONSERVATIVE, which the pipeline does not change) was built for short reads. Indel calling has not been benchmarked on HiFi data in this pipeline; a long-read caller such as DeepVariant is generally more accurate for HiFi indels. SNP calls are less affected. The same caution is printed at startup whenever HiFi input is given. - Only HiFi (CCS) reads are supported. Older PacBio subread or CLR data in the SRA downloads without error but maps poorly under the CCS preset. Check that each accession is a HiFi run.
- Unaligned PacBio BAM (
hifi_reads.bam) is not accepted by--hifi_reads. Convert it first withsamtools fastq hifi_reads.bam | gzip > run.fastq.gz. - HiFi runs appear in
4_bwa_mapping/as<run>_HiFicolumns, but not in the fastp tables, since they are not trimmed.
Pre-processed BAM files¶
| Parameter | Type | Default | Description |
|---|---|---|---|
--bam_input |
glob |
— | Glob pattern for pre-existing BAM files. Skips trimming and mapping and starts directly with variant calling. Cannot be combined with --reads, --SRA_index, --hifi_reads or --hifi_SRA_index. Single-quote the pattern; separate several locations with ;. See File paths and glob patterns. |
BAM file requirements
BAM files provided via --bam_input must be:
- Coordinate-sorted
- Containing
@RGread group information in the header, including anSM(sample) tag - Accompanied by a
.baiindex file in the same directory (eithersample.bam.baiorsample.bai)
The index is checked at startup and every BAM missing one is listed in a single error.
Coordinate sorting and the presence of @RG headers are not validated — ensure your
files comply before running.
Sample identity comes from the BAM header, not the filename
Several --bam_input files sharing one @RG SM tag are treated as one sample: merged
and put back through duplicate marking, the same as several runs mapped to one
Sample_Name under --reads/--SRA_index (see above) — including the pipeline's own
--keep_bam output, where a file is named by run but tagged by sample. A sample
backed by a single BAM is passed through unchanged, since --bam_input already expects
pre-processed, deduplicated BAMs and there is nothing to redo.
Reference genome options¶
| Parameter | Type | Default | Description |
|---|---|---|---|
--reference |
path |
— | Required. Absolute path to the reference genome in FASTA format, uncompressed. Accepts .fasta, .fa, .fna, and .fas extensions. Exactly one file — not a pattern. |
--reference_segments |
integer |
0 |
Size in bp of genome segments used for parallel variant calling. 0 calls one task per contig. Smaller values increase parallelism at the cost of per-task overhead. See the note below. |
--min_contig_length |
integer |
false |
Filter reference contigs shorter than this value (bp). Useful for excluding small scaffolds. false disables filtering. |
--bwa_index |
path |
— | Path to a pre-built BWA-mem2 index, given as the FASTA path the index was built from — normally the exact same value as --reference. Skips BWA indexing. See the warning below. |
When to set --reference_segments
With the default 0, variant calling is scattered one task per contig, so task
duration follows contig length. A genome with a few large chromosomes and many small
scaffolds produces a very uneven mix: most tasks finish in seconds while a handful run
for hours, and the stage cannot finish before its longest task. Adding cores or raising
maxForks does not shorten that tail.
Segmenting (for example --reference_segments 1000000 for 1 Mb windows) splits the
large contigs into comparable pieces and is usually the larger wall-clock win on such
assemblies. It costs one scheduling and container startup per extra task, and adds a
MergeGVCFs step when --keep_gvcf is set. Chromosome-scale assemblies with contigs
of similar size gain little from it.
--bwa_index takes the FASTA path, not an index file
bwa-mem2 index ref.fasta writes its five files by appending suffixes to the
FASTA name: ref.fasta.amb, ref.fasta.ann, ref.fasta.bwt.2bit.64,
ref.fasta.pac, ref.fasta.0123.
The pipeline rebuilds those names the same way — by appending each suffix to whatever you pass. So the value must be the FASTA path itself:
# correct - same value as --reference
--reference reference/genome.fasta \
--bwa_index reference/genome.fasta
Pointing at one of the index files instead is the common mistake, and it fails in a way that is hard to read:
That makes the pipeline look for genome.fasta.bwt.2bit.64.amb,
genome.fasta.bwt.2bit.64.bwt.2bit.64 and so on. None exist, so Nextflow
stages broken symlinks and every mapping task fails with:
If you see that message, check --bwa_index first. The index files must all
sit in the same directory as the FASTA.
Omit --bwa_index entirely to have the pipeline build the index itself.
Genotyping options¶
| Parameter | Type | Default | Description |
|---|---|---|---|
--ploidy |
integer |
— | Required. Ploidy level for GATK HaplotypeCaller. 1 for haploid (fungi, bacteria), 2 for diploid. Higher values can represent pooled samples. |
--call_invar_sites |
boolean |
false |
When true, GATK HaplotypeCaller also emits invariant (monomorphic) sites. Substantially increases output size. Useful for some downstream analyses requiring full genome coverage. |
Population-genetics analyses¶
Optional PLINK analyses run at the very end of the pipeline, on the population-genetics VCF
(thinned, MAF- and missingness-filtered). Each is off by default and enabled with its own flag.
All results are written to <outdir>/9_plink/.
| Parameter | Type | Default | Description |
|---|---|---|---|
--plink_pca |
boolean |
false |
Principal component analysis (PLINK 2, --pca). Up to 10 PCs, automatically capped at n samples − 1. |
--plink_relationships |
boolean |
false |
Pairwise relatedness between all samples. Runs both --make-rel (GRM) and --make-king (KING kinship) in PLINK 2, as the two answer different questions — see below. |
--plink_ld_prune |
boolean |
false |
Linkage-disequilibrium pruning (PLINK 2, --indep-pairwise 50 5 0.5), plus the pruned VCF. |
Choosing between the two relationship matrices¶
--plink_relationships produces two square matrices over the same samples and variants. They are
not interchangeable:
--make-rel → .rel |
--make-king → .king |
|
|---|---|---|
| Estimates | Genomic relationship matrix (GRM): an allele-sharing correlation matrix between individuals, based on identity by state | KING kinship coefficients: an identity-by-descent estimate of the co-segregation of alleles from shared ancestors |
| Scale | Correlation-like. Self-relatedness ≈ 1; a parent–child pair ≈ 0.5 | Kinship. Self-kinship = 0.5; a parent–child pair ≈ 0.25; unrelated ≈ 0 |
| Needs allele frequencies | Yes — supplied by the pipeline via --read-freq |
No — derived internally |
| Population structure | Sensitive. The zero-mean and variance normalisation is computed across the whole sample, so strong structure dominates the estimates and distorts familial relationships | Robust. Preferred when population structure is present or unaccounted for |
| Use it for | Mixed models, heritability, kinship-aware association testing — anything expecting a GRM | Identifying relatives and filtering duplicates or close kin before analysis |
Following the PLINK 2 relatedness tutorial,
prefer the KING matrix for relationship filtering whenever population structure may be unaccounted
for. The pipeline writes complete symmetric matrices (square) rather than the tutorial's
half-filled square0, so they load directly into R or Python without symmetrising.
Both matrices are computed from the population-genetics VCF, which vcftools has already filtered to MAF ≥ 0.05. Relatedness estimation needs reasonably common variants — empirical minor allele frequencies are reliable down to roughly n−0.5 — so no further MAF filter is applied.
KING requires heterozygous genotypes
The KING estimator divides by the heterozygous site count of the less heterozygous member of
each pair. Any pair in which one sample has no heterozygous calls therefore comes out as -inf,
and the .king matrix carries no information for that pair.
This affects haploid (--ploidy 1) data — where heterozygotes cannot exist — but also fully
homozygous diploid panels such as inbred lines, selfing species and clonal isolates. Raising
--ploidy does not fix it: calling a haploid organism as diploid yields 0/0 and 1/1
genotypes with essentially no heterozygotes, and the matrix stays -inf.
The .rel (GRM) matrix remains well defined in all of these cases and is the one to use. The
pipeline emits a warning at startup when --ploidy 1 is combined with this analysis; the
homozygous-diploid cases cannot be detected up front, so check the .king matrix for -inf
before relying on it.
Small panels
PLINK 2 declines to estimate allele frequencies and LD from fewer than 50 samples. The pipeline
works around this by supplying allele frequencies computed from the panel itself (--read-freq)
for PCA, and by passing --bad-ld for LD pruning. Both analyses therefore complete on small
panels, but the resulting estimates should be treated with caution.
Output options¶
| Parameter | Type | Default | Description |
|---|---|---|---|
--keep_bam |
boolean |
false |
When true, saves final per-sample BAM files (after duplicate marking) to <outdir>/5_bam_files/. |
--keep_gvcf |
boolean |
false |
When true, saves per-sample GVCF files to <outdir>/6_gvcf_files/. |
Advanced options¶
Minor, rarely-needed settings for special use cases.
| Parameter | Type | Default | Description |
|---|---|---|---|
--use_duplicate_reads |
boolean |
false |
When true, disables GATK HaplotypeCaller's NotDuplicateReadFilter, so reads flagged as duplicates by the dupRemoval process are still used for variant calling. By default, duplicate-flagged reads are excluded from calling. |
--genomicsdb_batch_size |
integer |
200 |
Number of samples GATK GenomicsDBImport loads per batch (--batch-size). The default is high enough that a typical panel imports in a single pass, which is the fastest option. Lower it to reduce peak memory on very large panels — smaller batches hold fewer samples open at once, at the cost of extra passes over the interval. |
SLURM and concurrency¶
These settings are found in nextflow.config and can be edited directly.
| Setting | Default | Description |
|---|---|---|
executor.queueSize |
500 | Maximum tasks in flight (submitted but not yet complete) across all processes. |
executor.submitRateLimit |
'500/1min' |
Maximum task submission rate (prevents overwhelming the scheduler). |
SRA download maxForks |
10 | Maximum concurrent SRA downloads (PE and SE each). Reduce if NCBI rate-limits your connection. |
fastp maxForks |
20 | Maximum concurrent trimming tasks (PE and SE each; I/O intensive). |
GATK HC maxForks |
500 | Maximum HaplotypeCaller tasks in flight. Capped in turn by executor.queueSize, so raise both together. |
These limits count tasks that are submitted but not yet complete, not tasks that are running, and they are deliberately set above the concurrency a cluster typically grants so that the surplus waits in the SLURM queue and backfills a freed core without a round trip through Nextflow. See Concurrency and rate limits for how to size them for your cluster.
SLURM partition walltime requirements
Several pipeline processes request up to 7 days of walltime (e.g. BWA mapping, GATK HaplotypeCaller, GenomicsDB import). When using -profile slurm, all jobs are submitted to the partition specified with --slurm_queue. This partition must allow a maximum walltime sufficient for the longest-running jobs.
Recommended: use a partition with a 7-day (or unlimited) walltime limit.
Shorter partitions (1–2 days) may still work if:
- Your reference genome is small (e.g. bacteria, fungi)
- Sequencing depth is low
- The number of samples is modest
If a job exceeds the partition's walltime limit, SLURM will kill it and the pipeline will fail at that step. Use -resume to restart from the last completed task after switching to a longer partition.
To list available partitions and their maximum walltimes on your cluster:
This prints each partition name alongside itsMaxTime limit. A value of UNLIMITED means no walltime cap.
Example usage: