From 2de69b350c10821c5bd00400b03d6ff863334a20 Mon Sep 17 00:00:00 2001 From: julianu Date: Mon, 30 Mar 2026 13:47:58 +0000 Subject: [PATCH 1/7] adding Percolator module --- modules/nf-core/percolator/environment.yml | 7 ++ modules/nf-core/percolator/main.nf | 46 +++++++ modules/nf-core/percolator/meta.yml | 80 ++++++++++++ modules/nf-core/percolator/tests/main.nf.test | 54 ++++++++ .../percolator/tests/main.nf.test.snap | 116 ++++++++++++++++++ 5 files changed, 303 insertions(+) create mode 100644 modules/nf-core/percolator/environment.yml create mode 100644 modules/nf-core/percolator/main.nf create mode 100644 modules/nf-core/percolator/meta.yml create mode 100644 modules/nf-core/percolator/tests/main.nf.test create mode 100644 modules/nf-core/percolator/tests/main.nf.test.snap diff --git a/modules/nf-core/percolator/environment.yml b/modules/nf-core/percolator/environment.yml new file mode 100644 index 000000000000..966fe62ad107 --- /dev/null +++ b/modules/nf-core/percolator/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - "bioconda::percolator=3.7.1" diff --git a/modules/nf-core/percolator/main.nf b/modules/nf-core/percolator/main.nf new file mode 100644 index 000000000000..2fce6be4c8a9 --- /dev/null +++ b/modules/nf-core/percolator/main.nf @@ -0,0 +1,46 @@ +process PERCOLATOR { + tag "${meta.id}" + label 'process_medium' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://depot.galaxyproject.org/singularity/percolator:3.7.1--h6351f2a_0' + : 'biocontainers/percolator:3.7.1--h6351f2a_0'}" + + input: + tuple val(meta), path(peptide_identification) + + output: + tuple val(meta), path("*.target.pout"), emit: target_pout + tuple val(meta), path("*.decoy.pout"), emit: decoy_pout + + tuple val("${task.process}"), val('percolator'), eval('percolator --help 2>&1 | head -1 | sed "s;Percolator version \\([^,]*\\),.*;\\1;"'), topic: versions, emit: versions_percolator + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + percolator \\ + ${args} \\ + --num-threads ${task.cpus} \\ + --only-psms \\ + --post-processing-tdc \\ + --search-input concatenated \\ + --results-psms ${prefix}.psm.target.pout \\ + --decoy-results-psms ${prefix}.psm.decoy.pout \\ + ${peptide_identification} + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + echo ${args} + + touch ${prefix}.psm.target.pout + touch ${prefix}.psm.decoy.pout + """ +} diff --git a/modules/nf-core/percolator/meta.yml b/modules/nf-core/percolator/meta.yml new file mode 100644 index 000000000000..93354d491ac8 --- /dev/null +++ b/modules/nf-core/percolator/meta.yml @@ -0,0 +1,80 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "percolator" +description: Rescore peptide-spectrum matches and estimate false discovery rates using the Percolator semi-supervised learning algorithm. +keywords: + - proteomics + - spectrum identification + - psm + - rescoring + - false discovery rate + - features +tools: + - "percolator": + description: "Semi-supervised learning for peptide identification from shotgun + proteomics datasets." + homepage: "http://percolator.ms" + documentation: "http://percolator.ms" + tool_dev_url: "https://github.com/percolator/percolator" + doi: "10.1038/nmeth1113" + licence: ["Apache-2.0"] + identifier: biotools:percolator + +input: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ + id:'sample1' ]` + - peptide_identification: + type: file + description: peptide identifications as PIN file + pattern: "*.{pin}" + ontologies: [] + +output: + target_pout: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ + id:'sample1' ]` + - "*.target.pout": + type: file + description: percolator output file containing the target PSMs + pattern: "*.{target.pout}" + ontologies: [] + + decoy_pout: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ + id:'sample1' ]` + - "*.decoy.pout": + type: file + description: percolator output file containing the decoys PSMs + pattern: "*.{decoy.pout}" + ontologies: [] + + versions_percolator: + - - ${task.process}: + type: string + description: The name of the process + - percolator: + type: string + description: The name of the tool + - percolator --help 2>&1 | head -1 | sed "s;Percolator version \([^,]*\),.*;\1;": + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - percolator: + type: string + description: The name of the tool + - percolator --help 2>&1 | head -1 | sed "s;Percolator version \([^,]*\),.*;\1;": + type: eval + description: The expression to obtain the version of the tool +authors: + - "@julianu" +maintainers: + - "@julianu" diff --git a/modules/nf-core/percolator/tests/main.nf.test b/modules/nf-core/percolator/tests/main.nf.test new file mode 100644 index 000000000000..f7348d377245 --- /dev/null +++ b/modules/nf-core/percolator/tests/main.nf.test @@ -0,0 +1,54 @@ +nextflow_process { + + name "Test Process PERCOLATOR" + script "../main.nf" + process "PERCOLATOR" + + tag "modules" + tag "modules_nfcore" + tag "percolator" + + test("percolator - OVEMB150205_12.pin") { + when { + process { + """ + input[0] = [ + [ id:'test' ], + file('https://raw.githubusercontent.com/medbioinf/test-datasets/refs/heads/percolator_tests/data/proteomics/percolator/OVEMB150205_12.pin', checkIfExists: true), + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + + test("percolator - OVEMB150205_12.pin - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test' ], + file('https://raw.githubusercontent.com/medbioinf/test-datasets/refs/heads/percolator_tests/data/proteomics/percolator/OVEMB150205_12.pin', checkIfExists: true), + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/nf-core/percolator/tests/main.nf.test.snap b/modules/nf-core/percolator/tests/main.nf.test.snap new file mode 100644 index 000000000000..bd4e38638869 --- /dev/null +++ b/modules/nf-core/percolator/tests/main.nf.test.snap @@ -0,0 +1,116 @@ +{ + "percolator - OVEMB150205_12.pin - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.psm.target.pout:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test" + }, + "test.psm.decoy.pout:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + "PERCOLATOR", + "percolator", + "3.07.1" + ] + ], + "decoy_pout": [ + [ + { + "id": "test" + }, + "test.psm.decoy.pout:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "target_pout": [ + [ + { + "id": "test" + }, + "test.psm.target.pout:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_percolator": [ + [ + "PERCOLATOR", + "percolator", + "3.07.1" + ] + ] + } + ], + "timestamp": "2026-03-30T13:40:12.100601718", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "percolator - OVEMB150205_12.pin": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.psm.target.pout:md5,7e8293ede65b0ffbff1e8fcd49cf7109" + ] + ], + "1": [ + [ + { + "id": "test" + }, + "test.psm.decoy.pout:md5,d5a63245b8efac18577df7b8fea58c91" + ] + ], + "2": [ + [ + "PERCOLATOR", + "percolator", + "3.07.1" + ] + ], + "decoy_pout": [ + [ + { + "id": "test" + }, + "test.psm.decoy.pout:md5,d5a63245b8efac18577df7b8fea58c91" + ] + ], + "target_pout": [ + [ + { + "id": "test" + }, + "test.psm.target.pout:md5,7e8293ede65b0ffbff1e8fcd49cf7109" + ] + ], + "versions_percolator": [ + [ + "PERCOLATOR", + "percolator", + "3.07.1" + ] + ] + } + ], + "timestamp": "2026-03-30T13:40:07.137394818", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + } +} \ No newline at end of file From d91864bf7e4abdfcd01294267dd84304cddc9112 Mon Sep 17 00:00:00 2001 From: julianu Date: Thu, 23 Apr 2026 10:47:06 +0000 Subject: [PATCH 2/7] setup required tests --- modules/nf-core/percolator/main.nf | 14 ++--- modules/nf-core/percolator/meta.yml | 15 +++--- modules/nf-core/percolator/tests/main.nf.test | 51 +++++++++++++++---- .../percolator/tests/main.nf.test.snap | 12 ++--- 4 files changed, 61 insertions(+), 31 deletions(-) diff --git a/modules/nf-core/percolator/main.nf b/modules/nf-core/percolator/main.nf index 2fce6be4c8a9..bbdd83106c9c 100644 --- a/modules/nf-core/percolator/main.nf +++ b/modules/nf-core/percolator/main.nf @@ -1,5 +1,5 @@ process PERCOLATOR { - tag "${meta.id}" + tag "$meta.id" label 'process_medium' conda "${moduleDir}/environment.yml" @@ -11,9 +11,8 @@ process PERCOLATOR { tuple val(meta), path(peptide_identification) output: - tuple val(meta), path("*.target.pout"), emit: target_pout - tuple val(meta), path("*.decoy.pout"), emit: decoy_pout - + tuple val(meta), path("${prefix}.psm.target.pout"), emit: target_pout + tuple val(meta), path("${prefix}.psm.decoy.pout"), emit: decoy_pout tuple val("${task.process}"), val('percolator'), eval('percolator --help 2>&1 | head -1 | sed "s;Percolator version \\([^,]*\\),.*;\\1;"'), topic: versions, emit: versions_percolator when: @@ -21,7 +20,7 @@ process PERCOLATOR { script: def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" + prefix = task.ext.prefix ?: "${meta.id}" """ percolator \\ ${args} \\ @@ -35,11 +34,8 @@ process PERCOLATOR { """ stub: - def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" + prefix = task.ext.prefix ?: "${meta.id}" """ - echo ${args} - touch ${prefix}.psm.target.pout touch ${prefix}.psm.decoy.pout """ diff --git a/modules/nf-core/percolator/meta.yml b/modules/nf-core/percolator/meta.yml index 93354d491ac8..675a62571dc0 100644 --- a/modules/nf-core/percolator/meta.yml +++ b/modules/nf-core/percolator/meta.yml @@ -26,8 +26,8 @@ input: id:'sample1' ]` - peptide_identification: type: file - description: peptide identifications as PIN file - pattern: "*.{pin}" + description: peptide identifications as PIN (Percolator input) file + pattern: "*.pin" ontologies: [] output: @@ -36,10 +36,10 @@ output: type: map description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` - - "*.target.pout": + - "${prefix}.psm.target.pout": type: file description: percolator output file containing the target PSMs - pattern: "*.{target.pout}" + pattern: "*.pout" ontologies: [] decoy_pout: @@ -47,10 +47,10 @@ output: type: map description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` - - "*.decoy.pout": + - "${prefix}.psm.decoy.pout": type: file description: percolator output file containing the decoys PSMs - pattern: "*.{decoy.pout}" + pattern: "*.pout" ontologies: [] versions_percolator: @@ -60,9 +60,10 @@ output: - percolator: type: string description: The name of the tool - - percolator --help 2>&1 | head -1 | sed "s;Percolator version \([^,]*\),.*;\1;": + - "percolator --help 2>&1 | head -1 | sed 's;Percolator version \\([^,]*\\),.*;\\1;'": type: eval description: The expression to obtain the version of the tool + topics: versions: - - ${task.process}: diff --git a/modules/nf-core/percolator/tests/main.nf.test b/modules/nf-core/percolator/tests/main.nf.test index f7348d377245..a58057eb3185 100644 --- a/modules/nf-core/percolator/tests/main.nf.test +++ b/modules/nf-core/percolator/tests/main.nf.test @@ -7,15 +7,52 @@ nextflow_process { tag "modules" tag "modules_nfcore" tag "percolator" + tag "comet" + tag "openms/decoydatabase" + + setup { + run("OPENMS_DECOYDATABASE") { + script "../../openms/decoydatabase/main.nf" + process { + """ + input[0] = channel.of([ + [ id:'test_db' ], + file(params.modules_testdata_base_path + 'proteomics/database/yeast_UPS.fasta', checkIfExists: true), + ]) + """ + } + } + + run("COMET") { + script "../../comet/main.nf" + + process { + """ + def originalParams = file(params.modules_testdata_base_path + 'proteomics/parameter/OVEMB150205.comet.params', checkIfExists: true) + def modifiedParams = new File('./modified.comet.params') + modifiedParams.text = originalParams.text + .replaceAll('(?m)^output_percolatorfile =.*', 'output_percolatorfile = 1') + .replaceAll('(?m)^output_txtfile =.*', 'output_txtfile = 0') + .replaceAll('(?m)^output_mzidentmlfile =.*', 'output_mzidentmlfile = 0') + + input[0] = OPENMS_DECOYDATABASE.out.decoy_fasta.map { meta, fasta -> + [ + [ id:'test'], + file(params.modules_testdata_base_path + 'proteomics/msspectra/OVEMB150205_12.mzML', checkIfExists: true), + fasta, + file(modifiedParams), + ] + } + """ + } + } + } test("percolator - OVEMB150205_12.pin") { when { process { """ - input[0] = [ - [ id:'test' ], - file('https://raw.githubusercontent.com/medbioinf/test-datasets/refs/heads/percolator_tests/data/proteomics/percolator/OVEMB150205_12.pin', checkIfExists: true), - ] + input[0] = COMET.out.pin """ } } @@ -27,7 +64,6 @@ nextflow_process { ) } } - test("percolator - OVEMB150205_12.pin - stub") { @@ -36,10 +72,7 @@ nextflow_process { when { process { """ - input[0] = [ - [ id:'test' ], - file('https://raw.githubusercontent.com/medbioinf/test-datasets/refs/heads/percolator_tests/data/proteomics/percolator/OVEMB150205_12.pin', checkIfExists: true), - ] + input[0] = COMET.out.pin """ } } diff --git a/modules/nf-core/percolator/tests/main.nf.test.snap b/modules/nf-core/percolator/tests/main.nf.test.snap index bd4e38638869..3dd89ec49c32 100644 --- a/modules/nf-core/percolator/tests/main.nf.test.snap +++ b/modules/nf-core/percolator/tests/main.nf.test.snap @@ -50,7 +50,7 @@ ] } ], - "timestamp": "2026-03-30T13:40:12.100601718", + "timestamp": "2026-04-23T10:35:47.104947826", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" @@ -64,7 +64,7 @@ { "id": "test" }, - "test.psm.target.pout:md5,7e8293ede65b0ffbff1e8fcd49cf7109" + "test.psm.target.pout:md5,61d48fdb8597aa5b5dde5c41b0cf1721" ] ], "1": [ @@ -72,7 +72,7 @@ { "id": "test" }, - "test.psm.decoy.pout:md5,d5a63245b8efac18577df7b8fea58c91" + "test.psm.decoy.pout:md5,7c9909537ccb675680e02504f07f2a74" ] ], "2": [ @@ -87,7 +87,7 @@ { "id": "test" }, - "test.psm.decoy.pout:md5,d5a63245b8efac18577df7b8fea58c91" + "test.psm.decoy.pout:md5,7c9909537ccb675680e02504f07f2a74" ] ], "target_pout": [ @@ -95,7 +95,7 @@ { "id": "test" }, - "test.psm.target.pout:md5,7e8293ede65b0ffbff1e8fcd49cf7109" + "test.psm.target.pout:md5,61d48fdb8597aa5b5dde5c41b0cf1721" ] ], "versions_percolator": [ @@ -107,7 +107,7 @@ ] } ], - "timestamp": "2026-03-30T13:40:07.137394818", + "timestamp": "2026-04-23T10:35:41.387430243", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" From 23074339e8f1fbeb9a1646cee7e0e33e3508c565 Mon Sep 17 00:00:00 2001 From: julianu Date: Thu, 23 Apr 2026 11:02:50 +0000 Subject: [PATCH 3/7] fixing linter issues --- modules/nf-core/percolator/meta.yml | 20 ++++++++----------- modules/nf-core/percolator/tests/main.nf.test | 2 +- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/modules/nf-core/percolator/meta.yml b/modules/nf-core/percolator/meta.yml index 675a62571dc0..57259cd124de 100644 --- a/modules/nf-core/percolator/meta.yml +++ b/modules/nf-core/percolator/meta.yml @@ -1,6 +1,6 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json name: "percolator" -description: Rescore peptide-spectrum matches and estimate false discovery rates using the Percolator semi-supervised learning algorithm. +description: Rescore peptide-spectrum matches and estimate false discovery rates + using the Percolator semi-supervised learning algorithm. keywords: - proteomics - spectrum identification @@ -22,37 +22,34 @@ tools: input: - - meta: type: map - description: Groovy Map containing sample information. e.g. `[ + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` - peptide_identification: type: file description: peptide identifications as PIN (Percolator input) file pattern: "*.pin" ontologies: [] - output: target_pout: - - meta: type: map - description: Groovy Map containing sample information. e.g. `[ + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` - - "${prefix}.psm.target.pout": + - ${prefix}.psm.target.pout: type: file description: percolator output file containing the target PSMs pattern: "*.pout" ontologies: [] - decoy_pout: - - meta: type: map - description: Groovy Map containing sample information. e.g. `[ + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` - - "${prefix}.psm.decoy.pout": + - ${prefix}.psm.decoy.pout: type: file description: percolator output file containing the decoys PSMs pattern: "*.pout" ontologies: [] - versions_percolator: - - ${task.process}: type: string @@ -60,10 +57,9 @@ output: - percolator: type: string description: The name of the tool - - "percolator --help 2>&1 | head -1 | sed 's;Percolator version \\([^,]*\\),.*;\\1;'": + - percolator --help 2>&1 | head -1 | sed "s;Percolator version \([^,]*\),.*;\1;": type: eval description: The expression to obtain the version of the tool - topics: versions: - - ${task.process}: diff --git a/modules/nf-core/percolator/tests/main.nf.test b/modules/nf-core/percolator/tests/main.nf.test index a58057eb3185..5713149d08a8 100644 --- a/modules/nf-core/percolator/tests/main.nf.test +++ b/modules/nf-core/percolator/tests/main.nf.test @@ -64,7 +64,7 @@ nextflow_process { ) } } - + test("percolator - OVEMB150205_12.pin - stub") { options "-stub" From b4a5093274adf31e7d72e72b91b64471afcdb27e Mon Sep 17 00:00:00 2001 From: julianu Date: Thu, 23 Apr 2026 12:03:53 +0000 Subject: [PATCH 4/7] fix linter issue --- modules/nf-core/percolator/meta.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/nf-core/percolator/meta.yml b/modules/nf-core/percolator/meta.yml index 57259cd124de..ec577c67e586 100644 --- a/modules/nf-core/percolator/meta.yml +++ b/modules/nf-core/percolator/meta.yml @@ -22,7 +22,7 @@ tools: input: - - meta: type: map - description: Groovy Map containing sample information. e.g. `[ + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` - peptide_identification: type: file @@ -33,7 +33,7 @@ output: target_pout: - - meta: type: map - description: Groovy Map containing sample information. e.g. `[ + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` - ${prefix}.psm.target.pout: type: file @@ -43,7 +43,7 @@ output: decoy_pout: - - meta: type: map - description: Groovy Map containing sample information. e.g. `[ + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` - ${prefix}.psm.decoy.pout: type: file From 274ccae4a61a5b17f2f818e2cc5bcacf9ca8e0bd Mon Sep 17 00:00:00 2001 From: julianu Date: Thu, 23 Apr 2026 12:10:08 +0000 Subject: [PATCH 5/7] adding container prefix --- modules/nf-core/percolator/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/percolator/main.nf b/modules/nf-core/percolator/main.nf index bbdd83106c9c..768c4c45c8fa 100644 --- a/modules/nf-core/percolator/main.nf +++ b/modules/nf-core/percolator/main.nf @@ -5,7 +5,7 @@ process PERCOLATOR { conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/percolator:3.7.1--h6351f2a_0' - : 'biocontainers/percolator:3.7.1--h6351f2a_0'}" + : 'quay.io/biocontainers/percolator:3.7.1--h6351f2a_0'}" input: tuple val(meta), path(peptide_identification) From fd9525c81e5259b71f672644d004256a4c04aeab Mon Sep 17 00:00:00 2001 From: julianu Date: Thu, 23 Apr 2026 16:00:47 +0000 Subject: [PATCH 6/7] sanitizing output --- modules/nf-core/percolator/tests/main.nf.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/nf-core/percolator/tests/main.nf.test b/modules/nf-core/percolator/tests/main.nf.test index 5713149d08a8..143ef83eeb4a 100644 --- a/modules/nf-core/percolator/tests/main.nf.test +++ b/modules/nf-core/percolator/tests/main.nf.test @@ -60,7 +60,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } } @@ -80,7 +80,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } } From b2de6952ae334a6ce3fc6b5db7dd65feb230ef3f Mon Sep 17 00:00:00 2001 From: julianu Date: Thu, 23 Apr 2026 18:39:07 +0000 Subject: [PATCH 7/7] fetching all of percolators outputs and adapting tests accordingly --- modules/nf-core/percolator/main.nf | 31 +++++- modules/nf-core/percolator/meta.yml | 94 ++++++++++++++-- modules/nf-core/percolator/tests/main.nf.test | 16 ++- .../percolator/tests/main.nf.test.snap | 105 ++++++++++++------ 4 files changed, 193 insertions(+), 53 deletions(-) diff --git a/modules/nf-core/percolator/main.nf b/modules/nf-core/percolator/main.nf index 768c4c45c8fa..cfcc0783f9ef 100644 --- a/modules/nf-core/percolator/main.nf +++ b/modules/nf-core/percolator/main.nf @@ -11,8 +11,16 @@ process PERCOLATOR { tuple val(meta), path(peptide_identification) output: - tuple val(meta), path("${prefix}.psm.target.pout"), emit: target_pout - tuple val(meta), path("${prefix}.psm.decoy.pout"), emit: decoy_pout + tuple val(meta), path("${prefix}.pout.xml"), emit: pout_xml + tuple val(meta), path("${prefix}.pep.xml"), emit: pout_pepxml + tuple val(meta), path("${prefix}.features.pin"), emit: features_pin + tuple val(meta), path("${prefix}.weights.tsv"), emit: weights + tuple val(meta), path("${prefix}.pep.target.pout"), emit: target_peptides, optional: true + tuple val(meta), path("${prefix}.pep.decoy.pout"), emit: decoy_peptides, optional: true + tuple val(meta), path("${prefix}.psm.target.pout"), emit: target_psms + tuple val(meta), path("${prefix}.psm.decoy.pout"), emit: decoy_psms + tuple val(meta), path("${prefix}.protein.target.pout"), emit: target_proteins, optional: true + tuple val(meta), path("${prefix}.protein.decoy.pout"), emit: decoy_proteins, optional: true tuple val("${task.process}"), val('percolator'), eval('percolator --help 2>&1 | head -1 | sed "s;Percolator version \\([^,]*\\),.*;\\1;"'), topic: versions, emit: versions_percolator when: @@ -25,18 +33,31 @@ process PERCOLATOR { percolator \\ ${args} \\ --num-threads ${task.cpus} \\ - --only-psms \\ - --post-processing-tdc \\ - --search-input concatenated \\ + --xmloutput ${prefix}.pout.xml \\ + --pepxml-output ${prefix}.pep.xml \\ + --tab-out ${prefix}.features.pin \\ + --weights ${prefix}.weights.tsv \\ + --results-peptides ${prefix}.pep.target.pout \\ + --decoy-results-peptides ${prefix}.pep.decoy.pout \\ --results-psms ${prefix}.psm.target.pout \\ --decoy-results-psms ${prefix}.psm.decoy.pout \\ + --results-proteins ${prefix}.protein.target.pout \\ + --decoy-results-proteins ${prefix}.protein.decoy.pout \\ ${peptide_identification} """ stub: prefix = task.ext.prefix ?: "${meta.id}" """ + touch ${prefix}.pout.xml + touch ${prefix}.pep.xml + touch ${prefix}.features.pin + touch ${prefix}.weights.tsv + touch ${prefix}.pep.target.pout + touch ${prefix}.pep.decoy.pout touch ${prefix}.psm.target.pout touch ${prefix}.psm.decoy.pout + touch ${prefix}.protein.target.pout + touch ${prefix}.protein.decoy.pout """ } diff --git a/modules/nf-core/percolator/meta.yml b/modules/nf-core/percolator/meta.yml index ec577c67e586..b057e827b943 100644 --- a/modules/nf-core/percolator/meta.yml +++ b/modules/nf-core/percolator/meta.yml @@ -5,6 +5,8 @@ keywords: - proteomics - spectrum identification - psm + - peptide + - protein - rescoring - false discovery rate - features @@ -30,25 +32,97 @@ input: pattern: "*.pin" ontologies: [] output: - target_pout: + pout_xml: - - meta: type: map - description: Groovy Map containing sample information. e.g. `[ - id:'sample1' ]` + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` + - ${prefix}.pout.xml: + type: file + description: Percolator output in XML format containing all PSM-level results + pattern: "*.pout.xml" + ontologies: + - edam: "http://edamontology.org/format_2332" # XML + pout_pepxml: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` + - ${prefix}.pep.xml: + type: file + description: Percolator output in pepXML format + pattern: "*.pep.xml" + ontologies: + - edam: "http://edamontology.org/format_3655" # pepXML + features_pin: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` + - ${prefix}.features.pin: + type: file + description: Tab-separated file with rescored features (PIN format) + pattern: "*.features.pin" + ontologies: [] + weights: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` + - ${prefix}.weights.tsv: + type: file + description: TSV file containing the final feature weights + pattern: "*.weights.tsv" + ontologies: [] + target_peptides: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` + - ${prefix}.pep.target.pout: + type: file + description: Target peptide-level results in tab separated format (pout) + pattern: "*.pep.target.pout" + ontologies: [] + decoy_peptides: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` + - ${prefix}.pep.decoy.pout: + type: file + description: Decoy peptide-level results in tab separated format (pout) + pattern: "*.pep.decoy.pout" + ontologies: [] + target_psms: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` - ${prefix}.psm.target.pout: type: file - description: percolator output file containing the target PSMs - pattern: "*.pout" + description: Target PSM-level results in tab separated format (pout) + pattern: "*.psm.target.pout" ontologies: [] - decoy_pout: + decoy_psms: - - meta: type: map - description: Groovy Map containing sample information. e.g. `[ - id:'sample1' ]` + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` - ${prefix}.psm.decoy.pout: type: file - description: percolator output file containing the decoys PSMs - pattern: "*.pout" + description: Decoy PSM-level results in tab separated format (pout) + pattern: "*.psm.decoy.pout" + ontologies: [] + target_proteins: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` + - ${prefix}.protein.target.pout: + type: file + description: Target protein-level results in tab separated format (pout) + pattern: "*.protein.target.pout" + ontologies: [] + decoy_proteins: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` + - ${prefix}.protein.decoy.pout: + type: file + description: Decoy protein-level results in tab separated format (pout) + pattern: "*.protein.decoy.pout" ontologies: [] versions_percolator: - - ${task.process}: diff --git a/modules/nf-core/percolator/tests/main.nf.test b/modules/nf-core/percolator/tests/main.nf.test index 143ef83eeb4a..f32c0193bd57 100644 --- a/modules/nf-core/percolator/tests/main.nf.test +++ b/modules/nf-core/percolator/tests/main.nf.test @@ -48,7 +48,7 @@ nextflow_process { } } - test("percolator - OVEMB150205_12.pin") { + test("percolator - OVEMB150205_12") { when { process { """ @@ -58,14 +58,24 @@ nextflow_process { } then { + def outputs = sanitizeOutput(process.out).findAll { key, val -> + ['pout_xml', 'features_pin', 'weights', 'target_psms', 'decoy_psms'].contains(key) + } + assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out)).match() } + // all but pepXML can be matched as whole, pepXML has a timestamp and must be treated separately + { assert snapshot(outputs).match() }, + // in pepXML: check some lines for existence + { assert path(process.out.pout_pepxml.get(0).get(1)).readLines().any { it.contains('') }} + ) + } } - test("percolator - OVEMB150205_12.pin - stub") { + test("percolator - OVEMB150205_12 - stub") { options "-stub" diff --git a/modules/nf-core/percolator/tests/main.nf.test.snap b/modules/nf-core/percolator/tests/main.nf.test.snap index 3dd89ec49c32..ff41981f14af 100644 --- a/modules/nf-core/percolator/tests/main.nf.test.snap +++ b/modules/nf-core/percolator/tests/main.nf.test.snap @@ -1,101 +1,128 @@ { - "percolator - OVEMB150205_12.pin - stub": { + "percolator - OVEMB150205_12": { "content": [ { - "0": [ + "decoy_psms": [ [ { "id": "test" }, - "test.psm.target.pout:md5,d41d8cd98f00b204e9800998ecf8427e" + "test.psm.decoy.pout:md5,7c9909537ccb675680e02504f07f2a74" ] ], - "1": [ + "features_pin": [ [ { "id": "test" }, - "test.psm.decoy.pout:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "2": [ - [ - "PERCOLATOR", - "percolator", - "3.07.1" + "test.features.pin:md5,4f49bdcb40d891c8bfb61f794465d1be" ] ], - "decoy_pout": [ + "pout_xml": [ [ { "id": "test" }, - "test.psm.decoy.pout:md5,d41d8cd98f00b204e9800998ecf8427e" + "test.pout.xml:md5,6a6be470f5961d54f2ee6c9c8596a476" ] ], - "target_pout": [ + "target_psms": [ [ { "id": "test" }, - "test.psm.target.pout:md5,d41d8cd98f00b204e9800998ecf8427e" + "test.psm.target.pout:md5,61d48fdb8597aa5b5dde5c41b0cf1721" ] ], - "versions_percolator": [ + "weights": [ [ - "PERCOLATOR", - "percolator", - "3.07.1" + { + "id": "test" + }, + "test.weights.tsv:md5,359b4a49c53892bef1738ae693520f69" ] ] } ], - "timestamp": "2026-04-23T10:35:47.104947826", + "timestamp": "2026-04-23T18:13:39.425266156", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" } }, - "percolator - OVEMB150205_12.pin": { + "percolator - OVEMB150205_12 - stub": { "content": [ { - "0": [ + "decoy_peptides": [ [ { "id": "test" }, - "test.psm.target.pout:md5,61d48fdb8597aa5b5dde5c41b0cf1721" + "test.pep.decoy.pout:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "1": [ + "decoy_proteins": [ [ { "id": "test" }, - "test.psm.decoy.pout:md5,7c9909537ccb675680e02504f07f2a74" + "test.protein.decoy.pout:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "2": [ + "decoy_psms": [ [ - "PERCOLATOR", - "percolator", - "3.07.1" + { + "id": "test" + }, + "test.psm.decoy.pout:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "decoy_pout": [ + "features_pin": [ [ { "id": "test" }, - "test.psm.decoy.pout:md5,7c9909537ccb675680e02504f07f2a74" + "test.features.pin:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "target_pout": [ + "pout_pepxml": [ [ { "id": "test" }, - "test.psm.target.pout:md5,61d48fdb8597aa5b5dde5c41b0cf1721" + "test.pep.xml:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "pout_xml": [ + [ + { + "id": "test" + }, + "test.pout.xml:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "target_peptides": [ + [ + { + "id": "test" + }, + "test.pep.target.pout:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "target_proteins": [ + [ + { + "id": "test" + }, + "test.protein.target.pout:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "target_psms": [ + [ + { + "id": "test" + }, + "test.psm.target.pout:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "versions_percolator": [ @@ -104,10 +131,18 @@ "percolator", "3.07.1" ] + ], + "weights": [ + [ + { + "id": "test" + }, + "test.weights.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] ] } ], - "timestamp": "2026-04-23T10:35:41.387430243", + "timestamp": "2026-04-23T18:13:45.966539564", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4"