diff --git a/.nf-core.yml b/.nf-core.yml index 1df527c..f1a0695 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -2,3 +2,4 @@ org_path: UMCUGenetics repository_type: modules container-registry: - ghcr.io + - 079623148045.dkr.ecr.eu-central-1.amazonaws.com diff --git a/modules/UMCUGenetics/dragen/main.nf b/modules/UMCUGenetics/dragen/main.nf new file mode 100644 index 0000000..cdcef2b --- /dev/null +++ b/modules/UMCUGenetics/dragen/main.nf @@ -0,0 +1,68 @@ +process DRAGEN { + // Dragen requires specific hardware (FPGA) to run. + // This process is therefore only executed on Illumina® BioInsight Platform Core / Illumina Connected Analytics (ICA) compute nodes with FPGA support. + // Test only contain a stub of the process, which can be executed on any compute node, but does not perform any actual processing. + tag "${meta.id}" + label 'process_fpga' + + // Dragen 4.2.4-2 (F2 compatible container) + container '079623148045.dkr.ecr.eu-central-1.amazonaws.com/cp-prod/f1b7ad6a-11ac-4bc1-b705-b275ff2887ad:latest' + + input: + // TODO: Move ref_tar unpacking to a separate process to avoid unpacking the reference for every sample? -> added in prs branch + tuple val(meta), path(r1_fastq), path(r2_fastq) + path fastq_list + path ref_tar + path repeat_genotype_specs + + output: + tuple val(meta), path("*"), emit: output + tuple val(meta), path('*.csv'), emit: csv + tuple val(meta), path("${prefix}.wgs_coverage_metrics.csv"), optional: true, emit: wgs_coverage_metrics + tuple val(meta), path("${prefix}.cnv_metrics.csv"), optional: true, emit: cnv_metrics + tuple val(meta), path("${prefix}.mapping_metrics.csv"), optional: true, emit: mapping_metrics + tuple val(meta), path("${prefix}.ploidy_estimation_metrics.csv"), optional: true, emit: ploidy_estimation_metrics + tuple val(meta), path("${prefix}.gvcf_metrics.csv"), optional: true, emit: gvcf_metrics + tuple val("${task.process}"), val('dragen'), eval("dragen --version 2>&1 | sed 's/^dragen Version //'"), topic: versions, emit: versions_dragen + + when: + task.ext.when == null || task.ext.when + + script: + prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + + if (repeat_genotype_specs) { + args = args + " --repeat-genotype-enable true --repeat-genotype-specs " + repeat_genotype_specs + } + + """ + mkdir -p /scratch/reference + tar -C /scratch/reference -xf ${ref_tar} + + /opt/edico/bin/dragen --partial-reconfig HMM --ignore-version-check true + + /opt/edico/bin/dragen --lic-instance-id-location /opt/instance-identity \\ + --ref-dir /scratch/reference/DRAGEN/9 \\ + --fastq-list ${fastq_list} \\ + --fastq-list-sample-id ${meta.id} \\ + --output-file-prefix ${prefix} \\ + --output-directory ./ \\ + --intermediate-results-dir /scratch \\ + ${args} + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + """ + echo ${args} + + touch ${prefix}.bam + touch ${prefix}.wgs_coverage_metrics.csv + touch ${prefix}.cnv_metrics.csv + touch ${prefix}.mapping_metrics.csv + touch ${prefix}.ploidy_estimation_metrics.csv + touch ${prefix}.gvcf_metrics.csv + """ +} diff --git a/modules/UMCUGenetics/dragen/tests/main.nf.test b/modules/UMCUGenetics/dragen/tests/main.nf.test new file mode 100644 index 0000000..5cdc46c --- /dev/null +++ b/modules/UMCUGenetics/dragen/tests/main.nf.test @@ -0,0 +1,37 @@ +nextflow_process { + + name "Test Process DRAGEN" + script "../main.nf" + process "DRAGEN" + + tag "modules" + tag "modules_UMCUGenetics" + tag "dragen" + + test("dragen - stub") { + options '-stub' + when { + process { + """ + input[0] = [ + [id:'sample1'], + [], + [] + ] + input[1] = [] + input[2] = [] + input[3] = [] + """ + } + } + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } + ) + } + } +} diff --git a/modules/UMCUGenetics/dragen/tests/main.nf.test.snap b/modules/UMCUGenetics/dragen/tests/main.nf.test.snap new file mode 100644 index 0000000..f18f987 --- /dev/null +++ b/modules/UMCUGenetics/dragen/tests/main.nf.test.snap @@ -0,0 +1,174 @@ +{ + "dragen - stub": { + "content": [ + { + "0": [ + [ + { + "id": "sample1" + }, + [ + "sample1.bam:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.cnv_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.gvcf_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.mapping_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.ploidy_estimation_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.wgs_coverage_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "1": [ + [ + { + "id": "sample1" + }, + [ + "sample1.cnv_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.gvcf_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.mapping_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.ploidy_estimation_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.wgs_coverage_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "2": [ + [ + { + "id": "sample1" + }, + "sample1.wgs_coverage_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "sample1" + }, + "sample1.cnv_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + [ + { + "id": "sample1" + }, + "sample1.mapping_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "5": [ + [ + { + "id": "sample1" + }, + "sample1.ploidy_estimation_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "6": [ + [ + { + "id": "sample1" + }, + "sample1.gvcf_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "7": [ + [ + "DRAGEN", + "dragen", + "bash: line 1: dragen: command not found" + ] + ], + "cnv_metrics": [ + [ + { + "id": "sample1" + }, + "sample1.cnv_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "csv": [ + [ + { + "id": "sample1" + }, + [ + "sample1.cnv_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.gvcf_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.mapping_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.ploidy_estimation_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.wgs_coverage_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "gvcf_metrics": [ + [ + { + "id": "sample1" + }, + "sample1.gvcf_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "mapping_metrics": [ + [ + { + "id": "sample1" + }, + "sample1.mapping_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "output": [ + [ + { + "id": "sample1" + }, + [ + "sample1.bam:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.cnv_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.gvcf_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.mapping_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.ploidy_estimation_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e", + "sample1.wgs_coverage_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "ploidy_estimation_metrics": [ + [ + { + "id": "sample1" + }, + "sample1.ploidy_estimation_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_dragen": [ + [ + "DRAGEN", + "dragen", + "bash: line 1: dragen: command not found" + ] + ], + "wgs_coverage_metrics": [ + [ + { + "id": "sample1" + }, + "sample1.wgs_coverage_metrics.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + }, + { + "versions_dragen": [ + [ + "DRAGEN", + "dragen", + "bash: line 1: dragen: command not found" + ] + ] + } + ], + "timestamp": "2026-08-18T11:08:58.003281", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.2" + } + } +} \ No newline at end of file diff --git a/modules/UMCUGenetics/dragenutils/dxqc/main.nf b/modules/UMCUGenetics/dragenutils/dxqc/main.nf new file mode 100644 index 0000000..6612708 --- /dev/null +++ b/modules/UMCUGenetics/dragenutils/dxqc/main.nf @@ -0,0 +1,37 @@ +process DRAGENUTILS_DXQC { + tag "${meta.id}" + label 'process_single' + + container 'ghcr.io/umcugenetics/dragen-utils:1.0.0' + + input: + tuple val(meta), path(wgs_coverage_metrics), path(cnv_metrics), path(mapping_metrics), path(ploidy_estimation_metrics), path(gvcf_metrics) + + output: + tuple val(meta), path("${prefix}.dragen_dx_qc.csv"), emit: csv + tuple val("${task.process}"), val('dragenutils'), eval("dragen-utils --version"), topic: versions, emit: versions_dragenutils + + when: + task.ext.when == null || task.ext.when + + script: + prefix = task.ext.prefix ?: "${meta.id}" + + """ + dragen-utils dx_qc \\ + ${prefix} \\ + ${wgs_coverage_metrics} \\ + ${cnv_metrics} \\ + ${mapping_metrics} \\ + ${ploidy_estimation_metrics} \\ + ${gvcf_metrics} \\ + > ${prefix}.dragen_dx_qc.csv + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}" + + """ + touch ${prefix}.dragen_dx_qc.csv + """ +} diff --git a/modules/UMCUGenetics/dragenutils/dxqc/tests/main.nf.test b/modules/UMCUGenetics/dragenutils/dxqc/tests/main.nf.test new file mode 100644 index 0000000..48bd4f1 --- /dev/null +++ b/modules/UMCUGenetics/dragenutils/dxqc/tests/main.nf.test @@ -0,0 +1,40 @@ +nextflow_process { + + name "Test Process DRAGENUTILS_DXQC" + script "../main.nf" + process "DRAGENUTILS_DXQC" + + tag "modules" + tag "modules_UMCUGenetics" + tag "dragenutils" + tag "dragenutils/dxqc" + + test("HG002 - srWGS QC csv files") { + when { + process { + """ + input[0] = [ + [ id:'HG002' ], + file(params.modules_umcu_testdata_base_path + "dragen_utils/qc/HG002.wgs_coverage_metrics.csv", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/qc/HG002.cnv_metrics.csv", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/qc/HG002.mapping_metrics.csv", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/qc/HG002.ploidy_estimation_metrics.csv", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/qc/HG002.gvcf_metrics.csv", checkIfExists: true), + ] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot( + process.out, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } + ) + } + + } + +} diff --git a/modules/UMCUGenetics/dragenutils/dxqc/tests/main.nf.test.snap b/modules/UMCUGenetics/dragenutils/dxqc/tests/main.nf.test.snap new file mode 100644 index 0000000..36b0775 --- /dev/null +++ b/modules/UMCUGenetics/dragenutils/dxqc/tests/main.nf.test.snap @@ -0,0 +1,52 @@ +{ + "HG002 - srWGS QC csv files": { + "content": [ + { + "0": [ + [ + { + "id": "HG002" + }, + "HG002.dragen_dx_qc.csv:md5,a6e8fd73836dd3b75ef50f082817cd24" + ] + ], + "1": [ + [ + "DRAGENUTILS_DXQC", + "dragenutils", + "1.0.0" + ] + ], + "csv": [ + [ + { + "id": "HG002" + }, + "HG002.dragen_dx_qc.csv:md5,a6e8fd73836dd3b75ef50f082817cd24" + ] + ], + "versions_dragenutils": [ + [ + "DRAGENUTILS_DXQC", + "dragenutils", + "1.0.0" + ] + ] + }, + { + "versions_dragenutils": [ + [ + "DRAGENUTILS_DXQC", + "dragenutils", + "1.0.0" + ] + ] + } + ], + "timestamp": "2026-08-20T15:11:59.763461", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.2" + } + } +} \ No newline at end of file diff --git a/modules/UMCUGenetics/dragenutils/fastqlist/main.nf b/modules/UMCUGenetics/dragenutils/fastqlist/main.nf new file mode 100644 index 0000000..9f0b613 --- /dev/null +++ b/modules/UMCUGenetics/dragenutils/fastqlist/main.nf @@ -0,0 +1,25 @@ +process DRAGENUTILS_FASTQLIST { + label 'process_single' + + container 'ghcr.io/umcugenetics/dragen-utils:1.0.0' + + input: + path fastq + + output: + path "fastq_list.csv", emit: csv + tuple val("${task.process}"), val('dragenutils'), eval("dragen-utils --version"), topic: versions, emit: versions_dragenutils + + when: + task.ext.when == null || task.ext.when + + script: + """ + dragen-utils fastq_list > fastq_list.csv + """ + + stub: + """ + touch fastq_list.csv + """ +} diff --git a/modules/UMCUGenetics/dragenutils/fastqlist/tests/main.nf.test b/modules/UMCUGenetics/dragenutils/fastqlist/tests/main.nf.test new file mode 100644 index 0000000..716f7a7 --- /dev/null +++ b/modules/UMCUGenetics/dragenutils/fastqlist/tests/main.nf.test @@ -0,0 +1,54 @@ +nextflow_process { + + name "Test Process DRAGENUTILS_FASTQLIST" + script "../main.nf" + process "DRAGENUTILS_FASTQLIST" + + tag "modules" + tag "modules_UMCUGenetics" + tag "dragenutils" + tag "dragenutils/fastqlist" + + test("HG002 - fastq") { + when { + process { + """ + input[0] = [ + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-1_23KCWCLT3_S8_L004_R1_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-1_23KCWCLT3_S8_L004_R2_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-1_23KCWCLT3_S8_L005_R1_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-1_23KCWCLT3_S8_L005_R2_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-1_23KCWCLT3_S8_L006_R1_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-1_23KCWCLT3_S8_L006_R2_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-1_23KCWCLT3_S8_L007_R1_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-1_23KCWCLT3_S8_L007_R2_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-1_23KCWCLT3_S8_L008_R1_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-1_23KCWCLT3_S8_L008_R2_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-2_23KCWCLT3_S14_L004_R1_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-2_23KCWCLT3_S14_L004_R2_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-2_23KCWCLT3_S14_L005_R1_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-2_23KCWCLT3_S14_L005_R2_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-2_23KCWCLT3_S14_L006_R1_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-2_23KCWCLT3_S14_L006_R2_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-2_23KCWCLT3_S14_L007_R1_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-2_23KCWCLT3_S14_L007_R2_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-2_23KCWCLT3_S14_L008_R1_001.fastq.gz", checkIfExists: true), + file(params.modules_umcu_testdata_base_path + "dragen_utils/fastq/HG002-2_23KCWCLT3_S14_L008_R2_001.fastq.gz", checkIfExists: true) + ] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot( + process.out, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } + ) + } + + } + +} diff --git a/modules/UMCUGenetics/dragenutils/fastqlist/tests/main.nf.test.snap b/modules/UMCUGenetics/dragenutils/fastqlist/tests/main.nf.test.snap new file mode 100644 index 0000000..c05c54f --- /dev/null +++ b/modules/UMCUGenetics/dragenutils/fastqlist/tests/main.nf.test.snap @@ -0,0 +1,42 @@ +{ + "HG002 - fastq": { + "content": [ + { + "0": [ + "fastq_list.csv:md5,2d99abf6c85e82473ee0a7e3b161a01a" + ], + "1": [ + [ + "DRAGENUTILS_FASTQLIST", + "dragenutils", + "1.0.0" + ] + ], + "csv": [ + "fastq_list.csv:md5,2d99abf6c85e82473ee0a7e3b161a01a" + ], + "versions_dragenutils": [ + [ + "DRAGENUTILS_FASTQLIST", + "dragenutils", + "1.0.0" + ] + ] + }, + { + "versions_dragenutils": [ + [ + "DRAGENUTILS_FASTQLIST", + "dragenutils", + "1.0.0" + ] + ] + } + ], + "timestamp": "2026-08-14T16:18:28.099028", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.2" + } + } +} \ No newline at end of file diff --git a/tests/config/modules.config b/tests/config/modules.config new file mode 100644 index 0000000..aa8301d --- /dev/null +++ b/tests/config/modules.config @@ -0,0 +1,5 @@ +process { + withName: DRAGEN { + container = 'quay.io/nextflow/bash' + } +} diff --git a/tests/config/nf-test.config b/tests/config/nf-test.config index f946df0..02e8a44 100644 --- a/tests/config/nf-test.config +++ b/tests/config/nf-test.config @@ -97,6 +97,9 @@ conda { createTimeout = "120 min" } // Load test_data.config containing paths to test data includeConfig 'test_data.config' +// Load module specific test config if it exists +includeConfig 'modules.config' + manifest { nextflowVersion = '!>=24.10.2' }