Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
152259d
Create angsd/dosaf process
ASendellPrice Jun 16, 2026
fa308b7
Update default value for minInd fraction to match angsd default
ASendellPrice Jun 19, 2026
f3e3c24
Update stub
ASendellPrice Jun 24, 2026
3a4f545
Add tests for angsd/dosaf
ASendellPrice Jun 24, 2026
c417429
Add environment configuration for angsd/dosaf
ASendellPrice Jun 25, 2026
9858417
Add test snapshot for angsd/dosaf
ASendellPrice Jun 25, 2026
b604f0e
Add meta configuration for angsd_dosaf module
ASendellPrice Jun 28, 2026
11a1724
Add validation step to check -doMajorMinor and -doMaf included in ext…
ASendellPrice Jul 5, 2026
22b5574
Add new test cases for dosaf 2 (missing -doMAF and -doMajorMinor), pl…
ASendellPrice Jul 5, 2026
558000c
Update test name for Failure Case 7
ASendellPrice Jul 5, 2026
eea9676
Fix syntax for ext.args and ext.args2 in ANGSD_DOSAF process
ASendellPrice Jul 5, 2026
b368eb6
Update meta
ASendellPrice Jul 5, 2026
8dc4f17
Switch test data path back to nf-core test-datasets repo
ASendellPrice Jul 14, 2026
d26e022
Bump hstlib version to v1.24
ASendellPrice Jul 14, 2026
3ae9d85
Fix meta.yml issues identified during linting
ASendellPrice Jul 14, 2026
52c0366
rollback htslib to version compatible with angsd 0.940
ASendellPrice Jul 14, 2026
802a9b9
Move gl_model and dosaf_mode from ext.args to input channels, remove …
ASendellPrice Jul 15, 2026
79a6153
Fix linting errors
ASendellPrice Jul 15, 2026
b9140fa
rename ref to ref_anc_arg
ASendellPrice Jul 16, 2026
a8c1c1d
Apply suggestion
ASendellPrice Jul 16, 2026
d0391cd
Refactor calibration comments and update reference argument to ref_an…
ASendellPrice Jul 16, 2026
38400e3
Update test snapshot
ASendellPrice Jul 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions modules/nf-core/angsd/dosaf/environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json
channels:
- conda-forge
- bioconda
dependencies:
- bioconda::angsd=0.940
- bioconda::htslib=1.23
137 changes: 137 additions & 0 deletions modules/nf-core/angsd/dosaf/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
process ANGSD_DOSAF {
tag "$meta.id"
label 'process_medium'

conda "${moduleDir}/environment.yml"
container "${ workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container ?
'https://depot.galaxyproject.org/singularity/angsd:0.940--h13024bc_4':
'quay.io/biocontainers/angsd:0.940--h13024bc_4' }"

input:
tuple val(meta), path(bams), path(bam_indices)
tuple path(reference_fasta), path(reference_fai)
tuple path(ancestral_fasta), path(ancestral_fai) // Optional. Provides ancestral state for unfolded SFS.
path(error_file) // Optional. Required for SYK model (-GL 4) only.
path(inbreeding_coefficients) // Optional. Required for -doSAF 2 (inbreeding-aware mode).
val(gl_model)
val(dosaf_mode)

Comment on lines +11 to +18

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need all these different meta maps?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only particularly useful one is the meta map associated with bam files, as would include population ID and associated samples. This would be used by downstream processes that consume output from angsd/dosaf. I will remove the other meta maps, unless you think meta maps should be included for fasta files? Is there any guidance on when meta maps should be provided?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://nf-co.re/docs/specifications/components/modules/general#use-of-meta-maps
you can also use the same meta map several times. the usage is a bit dependent on usual upstream and downstream processes.

@ASendellPrice ASendellPrice Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have removed unnecessary meta maps in commit 802a9b9

output:
tuple val(meta), path("*.saf.idx"), path("*.saf.pos.gz"), path("*.saf.gz"), emit: saf
tuple val("${task.process}"), val('angsd'), eval("angsd 2>&1 | sed '1!d;s/.*version: //;s/ .*//'"), emit: versions_angsd, topic: versions

when:
task.ext.when == null || task.ext.when

script:
def args = task.ext.args ?: ''
def prefix = task.ext.prefix ?: "${meta.id}"

// Validate GL model
if (!(gl_model in [1, 2, 3, 4])) {
error(
"ANGSD_DOSAF: Invalid GL model '${gl_model}'. Please pass one of 1, 2, 3, or 4 as the gl_model input."
)
}

Comment thread
mashehu marked this conversation as resolved.
// Validate doSAF mode
if (!(dosaf_mode in [1, 2])) {
error(
"ANGSD_DOSAF: Invalid doSAF mode '${dosaf_mode}'. Please pass 1 or 2 as the dosaf_mode input."
)
}

// Validate doSAF 2 has inbreeding coefficients
if (dosaf_mode == 2 && !inbreeding_coefficients) {
error(
"ANGSD_DOSAF: -doSAF 2 requires inbreeding coefficients (indF). Please supply an inbreeding_coefficients file."
)
}

// Validate doSAF 2 called alongside -doMajoMinor and -doMaf
if (dosaf_mode == 2 && !(args.contains("-doMajorMinor"))) {
error(
"ANGSD_DOSAF: -doSAF 2 requires -doMajorMinor to be specified. Please include in ext.args."
)
}
if (dosaf_mode == 2 && !(args.contains("-doMaf"))) {
error(
"ANGSD_DOSAF: -doSAF 2 requires -doMaf to be specified. Please include in ext.args."
)
}

// Validate GL 4 has error file
if (gl_model == 4 && !error_file) {
error(
"ANGSD_DOSAF: -GL 4 (SYK model) requires an error file. Please supply an error_file."
)
}

// Compute -minInd dynamically as a fraction of the population's BAM list size
// Default set to 0 as this mimics angsd default for minInd
def frac = (task.ext.args2 ?: '0') as Double
def n_samples = bams instanceof List ? bams.size() : 1
def min_ind_arg = frac > 0 ? "-minInd ${Math.ceil(n_samples * frac).toInteger()}" : ''

// Touch fai indices to ensure they are newer than their fasta (ANGSD requirement)
def touch_ref = reference_fai ? "sleep 1 && touch ${reference_fai}" : ''
def touch_anc = ancestral_fai ? "sleep 1 && touch ${ancestral_fai}" : ''

// Reference / ancestral args.
// If ancestral_fasta supplied: use as -anc and pass reference as -ref.
// If not supplied: use reference as -anc and -ref (suitable for folded SFS via realSFS -fold 1).
def ref_anc_arg = ancestral_fasta ? "-anc ${ancestral_fasta} -ref ${reference_fasta}" : "-anc ${reference_fasta} -ref ${reference_fasta}"

// Optional args
def indF_arg = inbreeding_coefficients ? "-indF ${inbreeding_coefficients}" : ""
def errors_arg = error_file ? "-errors ${error_file}" : ""

// Shared preamble
def preamble = """
${touch_ref}
${touch_anc}
printf '%s\\n' ${bams} > bamlist.txt
"""

// SOAPsnp (-GL 3) needs a calibration pass first to generate the matrix
// angsd reads back in during the doSAF step.
def calibration = ''
if (gl_model == 3) {
calibration = """
angsd \\
-nThreads ${task.cpus} \\
-bam bamlist.txt \\
-minQ 0 \\
-GL ${gl_model} \\
-ref ${reference_fasta} \\
-out ${prefix}
"""
}

// SYK model (-GL 4) needs an error file and -doCounts 1
def gl4_args = gl_model == 4 ? "${errors_arg} -doCounts 1" : ''

"""
${preamble}
${calibration}
angsd \\
-nThreads ${task.cpus} \\
-bam bamlist.txt \\
-GL ${gl_model} \\
-doSAF ${dosaf_mode} \\
${ref_anc_arg} \\
${indF_arg} \\
${gl4_args} \\
${args} \\
${min_ind_arg} \\
-out ${prefix}
"""

stub:
def prefix = task.ext.prefix ?: "${meta.id}"
"""
touch ${prefix}.saf.idx
echo "" | gzip > ${prefix}.saf.pos.gz
echo "" | gzip > ${prefix}.saf.gz
"""
}
131 changes: 131 additions & 0 deletions modules/nf-core/angsd/dosaf/meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
name: "angsd_dosaf"
description: Estimate site allele frequencies from BAM files.
keywords:
- angsd
- genotype likelihood
- genomics
tools:
- "angsd":
description: "ANGSD: Analysis of next generation Sequencing Data"
homepage: "http://www.popgen.dk/angsd/"
documentation: "http://www.popgen.dk/angsd/"
tool_dev_url: "https://github.com/ANGSD/angsd"
doi: "10.1186/s12859-014-0356-4"
licence:
- "GPL v3"
- "MIT"
identifier: biotools:angsd
input:
- - meta:
type: map
description: |
Groovy Map containing population information
e.g. [ id:'test', population:'population id', samples:'sample IDs' ]
- bams:
type: file
description: A list of BAM or CRAM files.
pattern: "*.{bam,cram}"
ontologies:
- edam: "http://edamontology.org/format_2572"
- edam: "http://edamontology.org/format_3462"
- bam_indices:
type: file
description: A list of BAM or CRAM indices.
pattern: "*.{bam.bai,cram.crai}"
ontologies:
- edam: "http://edamontology.org/format_3327"
- edam: "http://edamontology.org/format_3462"
- - reference_fasta:
type: file
description: A reference genome in FASTA format.
pattern: "*.{fasta,fa,fasta.gz,fa.gz}"
ontologies:
- edam: "http://edamontology.org/format_1929"
- reference_fai:
type: file
description: Index of the reference genome FASTA file.
pattern: "*.{fasta,fa,fasta.gz,fa.gz}.fai"
ontologies:
- edam: "http://edamontology.org/format_1929"
- - ancestral_fasta:
type: file
description: An ancestral state genome in FASTA format.
pattern: "*.{fasta,fa,fasta.gz,fa.gz}"
ontologies:
- edam: "http://edamontology.org/format_1929"
- ancestral_fai:
type: file
description: Index of the ancestral state genome FASTA file.
pattern: "*.{fasta,fa,fasta.gz,fa.gz}.fai"
ontologies:
- edam: "http://edamontology.org/format_1929"
- error_file:
type: file
description: A file containing per-base substitution error rates for use
with the Sykes genotype likelihood model (-GL 4).
pattern: "*.errors"
ontologies: []
- inbreeding_coefficients:
type: file
description: A file containing estimates of individual inbreeding
coefficients.
pattern: "*.indF"
ontologies: []
- gl_model:
type: integer
description: |
Genotype likelihood model to use (angsd -GL). 1=SAMtools, 2=GATK, 3=SOAPsnp, 4=SYK.
- dosaf_mode:
type: integer
description: |
Site allele frequency likelihood estimation mode (angsd -doSAF). 1=standard, 2=inbreeding-aware (requires indF).
output:
saf:
- - meta:
type: map
description: Groovy Map containing population information. e.g. `[
id:'test', population:'population id', samples:'sample IDs' ]`
- "*.saf.idx":
type: file
description: ANGSD site allele frequency index file
pattern: "*.saf.idx"
ontologies: []
- "*.saf.pos.gz":
type: file
description: Gzipped file containing genomic positions of sites in the
SAF
pattern: "*.saf.pos.gz"
ontologies:
- edam: http://edamontology.org/format_3989
- "*.saf.gz":
type: file
description: Gzipped binary file containing per-site sample allele
frequency likelihoods
pattern: "*.saf.gz"
ontologies:
- edam: http://edamontology.org/format_3989
versions_angsd:
- - "${task.process}":
type: string
description: The name of the process
- angsd:
type: string
description: The name of the tool
- "angsd 2>&1 | sed '1!d;s/.*version: //;s/ .*//'":
type: eval
description: The expression to obtain the version of the tool
topics:
versions:
- - "${task.process}":
type: string
description: The name of the process
- angsd:
type: string
description: The name of the tool
- "angsd 2>&1 | sed '1!d;s/.*version: //;s/ .*//'":
type: eval
description: The expression to obtain the version of the tool
authors:
- "@ASendellPrice"
maintainers:
- "@ASendellPrice"
Loading