From eda8ca9e4823bbc462181a4c25cb2161d9fb7924 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 7 Jul 2026 16:19:29 -0400 Subject: [PATCH 01/12] feat (closes #7246): add new component: leafcutter/differentialsplicing --- .../differentialsplicing/environment.yml | 7 + .../leafcutter/differentialsplicing/main.nf | 42 ++++++ .../leafcutter/differentialsplicing/meta.yml | 80 ++++++++++++ .../differentialsplicing/tests/main.nf.test | 121 ++++++++++++++++++ .../tests/main.nf.test.snap | 93 ++++++++++++++ .../tests/nextflow.config | 7 + 6 files changed, 350 insertions(+) create mode 100644 modules/nf-core/leafcutter/differentialsplicing/environment.yml create mode 100644 modules/nf-core/leafcutter/differentialsplicing/main.nf create mode 100644 modules/nf-core/leafcutter/differentialsplicing/meta.yml create mode 100644 modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test create mode 100644 modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap create mode 100644 modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config diff --git a/modules/nf-core/leafcutter/differentialsplicing/environment.yml b/modules/nf-core/leafcutter/differentialsplicing/environment.yml new file mode 100644 index 000000000000..e4c971910da0 --- /dev/null +++ b/modules/nf-core/leafcutter/differentialsplicing/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::leafcutter=2.0.3" diff --git a/modules/nf-core/leafcutter/differentialsplicing/main.nf b/modules/nf-core/leafcutter/differentialsplicing/main.nf new file mode 100644 index 000000000000..7e2279bc76fc --- /dev/null +++ b/modules/nf-core/leafcutter/differentialsplicing/main.nf @@ -0,0 +1,42 @@ +process LEAFCUTTER_DIFFERENTIALSPLICING { + 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/leafcutter:2.0.3--pyhd8ed1ab_0': + 'quay.io/biocontainers/leafcutter:2.0.3--pyhd8ed1ab_0' }" + + input: + tuple val(meta), path(counts), path(groups) + + output: + tuple val(meta), path("*_cluster_significance.txt"), emit: cluster_significance + tuple val(meta), path("*_effect_sizes.txt") , emit: effect_sizes + // WARN: Version information not provided by tool on CLI. Please update version string below when bumping container versions. + tuple val("${task.process}"), val('leafcutter'), val("2.0.3"), topic: versions, emit: versions_leafcutter + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + export USER=\${USER:-nobody} + + leafcutter-ds \\ + $counts \\ + $groups \\ + --output_prefix ${prefix}_results \\ + --num_threads $task.cpus \\ + $args + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}_results_cluster_significance.txt + touch ${prefix}_results_effect_sizes.txt + """ +} diff --git a/modules/nf-core/leafcutter/differentialsplicing/meta.yml b/modules/nf-core/leafcutter/differentialsplicing/meta.yml new file mode 100644 index 000000000000..cd5a48fb2bd9 --- /dev/null +++ b/modules/nf-core/leafcutter/differentialsplicing/meta.yml @@ -0,0 +1,80 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "leafcutter_differentialsplicing" +description: Perform differential splicing analysis to identify junctions with significant changes in splicing between conditions +keywords: + - alternative splicing + - differential splicing + - RNA-seq + - intron usage +tools: + - "leafcutter": + description: "Annotation-free quantification of RNA splicing from RNA-seq data" + homepage: "https://leafcutter2.github.io/leafcutter-ds/" + documentation: "https://leafcutter2.github.io/leafcutter-ds/tutorials/differential-splicing/" + tool_dev_url: "https://github.com/leafcutter2/leafcutter-ds" + doi: "10.1038/s41588-017-0004-9" + licence: ["Apache-2.0"] + identifier: biotools:leafcutter + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - counts: + type: file + description: Intron usage counts file from leafcutter-cluster (either perind.counts.gz or perind_numers.counts.gz) + pattern: "*.counts.gz" + - groups: + type: file + description: Tab-delimited file with sample names in column 1 and sample group/phenotype assignments in column 2 + pattern: "*.txt" + +output: + cluster_significance: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - "*_cluster_significance.txt": + type: file + description: Cluster-level differential splicing statistics including p-values and test status + pattern: "*_cluster_significance.txt" + effect_sizes: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - "*_effect_sizes.txt": + type: file + description: Per-intron junction effect sizes, PSI values, and delta PSI for each condition + pattern: "*_effect_sizes.txt" + versions_leafcutter: + - - "${task.process}": + type: string + description: The name of the process + - "leafcutter": + type: string + description: The name of the tool + - "2.0.3": + type: string + description: The version of the tool + +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - leafcutter: + type: string + description: The name of the tool + - "2.0.3": + type: string + description: The version of the tool +authors: + - "@JTL-lab" +maintainers: + - "@JTL-lab" diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test new file mode 100644 index 000000000000..a0625cd168e4 --- /dev/null +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test @@ -0,0 +1,121 @@ +nextflow_process { + + name "Test Process LEAFCUTTER_DIFFERENTIALSPLICING" + script "../main.nf" + process "LEAFCUTTER_DIFFERENTIALSPLICING" + + tag "modules" + tag "modules_nfcore" + tag "leafcutter" + tag "leafcutter/differentialsplicing" + tag "leafcutter/clusterregtools" + tag "regtools" + tag "regtools/junctionsextract" + + test("homo_sapiens - bam - differential splicing") { + + config "./nextflow.config" + + setup { + run("REGTOOLS_JUNCTIONSEXTRACT") { + script "../../../regtools/junctionsextract/main.nf" + process { + """ + input[0] = Channel.of( + [ + [ id:'ctrl_rep1', single_end:false ], + file(params.modules_testdata_base_path + "genomics/homo_sapiens/illumina/bam/test.rna.paired_end.sorted.chr6.bam", checkIfExists: true), + file(params.modules_testdata_base_path + "genomics/homo_sapiens/illumina/bam/test.rna.paired_end.sorted.chr6.bam.bai", checkIfExists: true) + ], + [ + [ id:'ctrl_rep2', single_end:false ], + file(params.modules_testdata_base_path + "genomics/homo_sapiens/illumina/bam/test.rna.paired_end.sorted.chr6.bam", checkIfExists: true), + file(params.modules_testdata_base_path + "genomics/homo_sapiens/illumina/bam/test.rna.paired_end.sorted.chr6.bam.bai", checkIfExists: true) + ], + [ + [ id:'kd_rep1', single_end:false ], + file(params.modules_testdata_base_path + "genomics/homo_sapiens/illumina/bam/test.rna.paired_end.sorted.chr6.bam", checkIfExists: true), + file(params.modules_testdata_base_path + "genomics/homo_sapiens/illumina/bam/test.rna.paired_end.sorted.chr6.bam.bai", checkIfExists: true) + ], + [ + [ id:'kd_rep2', single_end:false ], + file(params.modules_testdata_base_path + "genomics/homo_sapiens/illumina/bam/test.rna.paired_end.sorted.chr6.bam", checkIfExists: true), + file(params.modules_testdata_base_path + "genomics/homo_sapiens/illumina/bam/test.rna.paired_end.sorted.chr6.bam.bai", checkIfExists: true) + ] + ) + input[1] = '' + """ + } + } + + run("LEAFCUTTER_CLUSTERREGTOOLS") { + script "../../../leafcutter/clusterregtools/main.nf" + process { + """ + input[0] = REGTOOLS_JUNCTIONSEXTRACT.out.junc + .map { meta, junc -> junc } + .collect() + .map { junc_files -> [ [ id:'test_ds' ], junc_files ] } + """ + } + } + } + + when { + process { + """ + def groups_content = '''ctrl_rep1\\tCONTROL +ctrl_rep2\\tCONTROL +kd_rep1\\tKNOCKDOWN +kd_rep2\\tKNOCKDOWN +''' + def groups_file = file("\${workDir}/groups_file.txt") + groups_file.text = groups_content + + input[0] = LEAFCUTTER_CLUSTERREGTOOLS.out.numers + .map { meta, counts -> [ meta, counts, groups_file ] } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.cluster_significance, + process.out.effect_sizes, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } + ) + } + + } + + test("homo_sapiens - bam - differential splicing - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test' ], + file('test_perind.counts.gz'), + file('groups_file.txt') + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert process.out.cluster_significance != null }, + { assert process.out.effect_sizes != null } + ) + } + + } + +} diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap new file mode 100644 index 000000000000..bf1193bdcd1e --- /dev/null +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap @@ -0,0 +1,93 @@ +{ + "homo_sapiens - bam - differential splicing": { + "content": [ + [ + [ + { + "id": "test_ds" + }, + "test_ds_results_cluster_significance.txt:md5,222cfb8c25277ec24f84934b684d195a" + ] + ], + [ + [ + { + "id": "test_ds" + }, + "test_ds_results_effect_sizes.txt:md5,8535426635beacabae83a5b8cc6ed385" + ] + ], + { + "versions_leafcutter": [ + [ + "LEAFCUTTER_DIFFERENTIALSPLICING", + "leafcutter", + "2.0.3" + ] + ] + } + ], + "timestamp": "2026-07-07T15:56:29.391725645", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.0" + } + }, + "homo_sapiens - bam - differential splicing - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_results_cluster_significance.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test" + }, + "test_results_effect_sizes.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + "LEAFCUTTER_DIFFERENTIALSPLICING", + "leafcutter", + "2.0.3" + ] + ], + "cluster_significance": [ + [ + { + "id": "test" + }, + "test_results_cluster_significance.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "effect_sizes": [ + [ + { + "id": "test" + }, + "test_results_effect_sizes.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_leafcutter": [ + [ + "LEAFCUTTER_DIFFERENTIALSPLICING", + "leafcutter", + "2.0.3" + ] + ] + } + ], + "timestamp": "2026-07-07T15:56:35.602866997", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.0" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config new file mode 100644 index 000000000000..b859f0a57a23 --- /dev/null +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config @@ -0,0 +1,7 @@ +process { + + withName: 'LEAFCUTTER_DIFFERENTIALSPLICING' { + ext.args = '--min_samples_per_group 2 --min_samples_per_intron 2 --num_threads 1' + } + +} From 58b53d42168b0db24d4ad7fd9ed82685da40104c Mon Sep 17 00:00:00 2001 From: = Date: Wed, 8 Jul 2026 14:49:27 -0400 Subject: [PATCH 02/12] fix: update main.nf.test for non-deterministic outputs, update snapshot, set python environment hash variable --- .../leafcutter/differentialsplicing/main.nf | 2 ++ .../differentialsplicing/tests/main.nf.test | 11 +++++--- .../tests/main.nf.test.snap | 28 ++++++------------- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/modules/nf-core/leafcutter/differentialsplicing/main.nf b/modules/nf-core/leafcutter/differentialsplicing/main.nf index 7e2279bc76fc..af77288e2ab7 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/main.nf +++ b/modules/nf-core/leafcutter/differentialsplicing/main.nf @@ -24,6 +24,8 @@ process LEAFCUTTER_DIFFERENTIALSPLICING { def prefix = task.ext.prefix ?: "${meta.id}" """ export USER=\${USER:-nobody} + export PYTHONHASHSEED=0 + export CUBLAS_WORKSPACE_CONFIG=:4096:8 leafcutter-ds \\ $counts \\ diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test index a0625cd168e4..e65c5a4c5a69 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test @@ -82,10 +82,13 @@ kd_rep2\\tKNOCKDOWN assertAll( { assert process.success }, { assert snapshot( - process.out.cluster_significance, - process.out.effect_sizes, - process.out.findAll { key, val -> key.startsWith('versions') } - ).match() } + process.out.findAll { key, val -> key.startsWith('versions') }, + process.out.cluster_significance.collect { file(it[1]).getName() }, + process.out.effect_sizes.collect { file(it[1]).getName() } + ).match() }, + // Check non-deterministic files exist + { assert file(process.out.cluster_significance[0][1]).exists() }, + { assert file(process.out.effect_sizes[0][1]).exists() } ) } diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap index bf1193bdcd1e..35c2e90c45dd 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap @@ -1,22 +1,6 @@ { "homo_sapiens - bam - differential splicing": { "content": [ - [ - [ - { - "id": "test_ds" - }, - "test_ds_results_cluster_significance.txt:md5,222cfb8c25277ec24f84934b684d195a" - ] - ], - [ - [ - { - "id": "test_ds" - }, - "test_ds_results_effect_sizes.txt:md5,8535426635beacabae83a5b8cc6ed385" - ] - ], { "versions_leafcutter": [ [ @@ -25,9 +9,15 @@ "2.0.3" ] ] - } + }, + [ + "test_ds_results_cluster_significance.txt" + ], + [ + "test_ds_results_effect_sizes.txt" + ] ], - "timestamp": "2026-07-07T15:56:29.391725645", + "timestamp": "2026-07-08T14:38:48.580335473", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.0" @@ -84,7 +74,7 @@ ] } ], - "timestamp": "2026-07-07T15:56:35.602866997", + "timestamp": "2026-07-08T14:39:52.087856717", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.0" From e80e3b3e932a478fc6cc6acd626309e9cccc8dcd Mon Sep 17 00:00:00 2001 From: = Date: Tue, 28 Jul 2026 14:36:45 -0400 Subject: [PATCH 03/12] refactor, fix: incorporated cleaner syntax with sanitizeOutput for tests, removed redundant --num_threads param in test config args, move container options set in main.nf to main.nf.test and add note in meta.yml --- .../leafcutter/differentialsplicing/main.nf | 4 -- .../leafcutter/differentialsplicing/meta.yml | 2 + .../differentialsplicing/tests/main.nf.test | 15 ++---- .../tests/main.nf.test.snap | 51 +++++++------------ .../tests/nextflow.config | 5 +- 5 files changed, 28 insertions(+), 49 deletions(-) diff --git a/modules/nf-core/leafcutter/differentialsplicing/main.nf b/modules/nf-core/leafcutter/differentialsplicing/main.nf index af77288e2ab7..1f4f4a73e46d 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/main.nf +++ b/modules/nf-core/leafcutter/differentialsplicing/main.nf @@ -23,10 +23,6 @@ process LEAFCUTTER_DIFFERENTIALSPLICING { def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" """ - export USER=\${USER:-nobody} - export PYTHONHASHSEED=0 - export CUBLAS_WORKSPACE_CONFIG=:4096:8 - leafcutter-ds \\ $counts \\ $groups \\ diff --git a/modules/nf-core/leafcutter/differentialsplicing/meta.yml b/modules/nf-core/leafcutter/differentialsplicing/meta.yml index cd5a48fb2bd9..76ce8e363893 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/meta.yml +++ b/modules/nf-core/leafcutter/differentialsplicing/meta.yml @@ -78,3 +78,5 @@ authors: - "@JTL-lab" maintainers: - "@JTL-lab" +notes: + - This module uses PyTorch for statistical analysis. When running in containers, you may need to set environment variables in your pipeline configuration for reproducibility. For example, `containerOptions = '--env USER=nobody --env PYTHONHASHSEED=0 --env CUBLAS_WORKSPACE_CONFIG=:4096:8'` (Docker) or `containerOptions = '--env USER=nobody,PYTHONHASHSEED=0,CUBLAS_WORKSPACE_CONFIG=:4096:8'` (Singularity/Apptainer). diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test index e65c5a4c5a69..a3a60ef74eb6 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test @@ -81,14 +81,7 @@ kd_rep2\\tKNOCKDOWN then { assertAll( { assert process.success }, - { assert snapshot( - process.out.findAll { key, val -> key.startsWith('versions') }, - process.out.cluster_significance.collect { file(it[1]).getName() }, - process.out.effect_sizes.collect { file(it[1]).getName() } - ).match() }, - // Check non-deterministic files exist - { assert file(process.out.cluster_significance[0][1]).exists() }, - { assert file(process.out.effect_sizes[0][1]).exists() } + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["cluster_significance", "effect_sizes"])).match()} ) } @@ -111,11 +104,9 @@ kd_rep2\\tKNOCKDOWN } then { + assert process.success assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { assert process.out.cluster_significance != null }, - { assert process.out.effect_sizes != null } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap index 35c2e90c45dd..8e5ecd5f5bc3 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap @@ -2,6 +2,22 @@ "homo_sapiens - bam - differential splicing": { "content": [ { + "cluster_significance": [ + [ + { + "id": "test_ds" + }, + "test_ds_results_cluster_significance.txt" + ] + ], + "effect_sizes": [ + [ + { + "id": "test_ds" + }, + "test_ds_results_effect_sizes.txt" + ] + ], "versions_leafcutter": [ [ "LEAFCUTTER_DIFFERENTIALSPLICING", @@ -9,15 +25,9 @@ "2.0.3" ] ] - }, - [ - "test_ds_results_cluster_significance.txt" - ], - [ - "test_ds_results_effect_sizes.txt" - ] + } ], - "timestamp": "2026-07-08T14:38:48.580335473", + "timestamp": "2026-07-28T12:22:48.849459725", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.0" @@ -26,29 +36,6 @@ "homo_sapiens - bam - differential splicing - stub": { "content": [ { - "0": [ - [ - { - "id": "test" - }, - "test_results_cluster_significance.txt:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - { - "id": "test" - }, - "test_results_effect_sizes.txt:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "2": [ - [ - "LEAFCUTTER_DIFFERENTIALSPLICING", - "leafcutter", - "2.0.3" - ] - ], "cluster_significance": [ [ { @@ -74,7 +61,7 @@ ] } ], - "timestamp": "2026-07-08T14:39:52.087856717", + "timestamp": "2026-07-28T12:00:56.961347309", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.0" diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config index b859f0a57a23..8fcb07502f79 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config @@ -1,7 +1,10 @@ process { withName: 'LEAFCUTTER_DIFFERENTIALSPLICING' { - ext.args = '--min_samples_per_group 2 --min_samples_per_intron 2 --num_threads 1' + ext.args = '--min_samples_per_group 2 --min_samples_per_intron 2' + containerOptions = { workflow.containerEngine == 'singularity' ? + '--env USER=nobody,PYTHONHASHSEED=0,CUBLAS_WORKSPACE_CONFIG=:4096:8' : + '--env USER=nobody --env PYTHONHASHSEED=0 --env CUBLAS_WORKSPACE_CONFIG=:4096:8' } } } From d17cd67fffeb844b3752add78d2bb819c5f00d8c Mon Sep 17 00:00:00 2001 From: = Date: Tue, 28 Jul 2026 23:56:13 -0400 Subject: [PATCH 04/12] fix: increase pullTimeout for singularity in test profile --- .../leafcutter/differentialsplicing/tests/nextflow.config | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config index 8fcb07502f79..966a3f07d3a7 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config @@ -1,3 +1,7 @@ +singularity { + pullTimeout = 30.m +} + process { withName: 'LEAFCUTTER_DIFFERENTIALSPLICING' { @@ -7,4 +11,4 @@ process { '--env USER=nobody --env PYTHONHASHSEED=0 --env CUBLAS_WORKSPACE_CONFIG=:4096:8' } } -} +} \ No newline at end of file From b28f3a720416fe3f275a5adffd6bd72e6986d071 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 29 Jul 2026 00:06:14 -0400 Subject: [PATCH 05/12] refactor: add EOF space to nextflow.config for test profile --- .../leafcutter/differentialsplicing/tests/nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config index 966a3f07d3a7..9949e3230640 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config @@ -11,4 +11,4 @@ process { '--env USER=nobody --env PYTHONHASHSEED=0 --env CUBLAS_WORKSPACE_CONFIG=:4096:8' } } -} \ No newline at end of file +} From 833380495b697350b775a2f9e236546a9f320170 Mon Sep 17 00:00:00 2001 From: = Date: Thu, 30 Jul 2026 11:23:53 -0400 Subject: [PATCH 06/12] refactor: move environment variables from test config to module main.nf for better transparency as recommended, update meta.yml with note on what is set and why --- modules/nf-core/leafcutter/differentialsplicing/main.nf | 3 +++ modules/nf-core/leafcutter/differentialsplicing/meta.yml | 2 +- .../leafcutter/differentialsplicing/tests/nextflow.config | 3 --- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/nf-core/leafcutter/differentialsplicing/main.nf b/modules/nf-core/leafcutter/differentialsplicing/main.nf index 1f4f4a73e46d..c5f90279cbc4 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/main.nf +++ b/modules/nf-core/leafcutter/differentialsplicing/main.nf @@ -23,6 +23,9 @@ process LEAFCUTTER_DIFFERENTIALSPLICING { def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" """ + export USER="\${USER:-nobody}" + export PYTHONHASHSEED=0 + leafcutter-ds \\ $counts \\ $groups \\ diff --git a/modules/nf-core/leafcutter/differentialsplicing/meta.yml b/modules/nf-core/leafcutter/differentialsplicing/meta.yml index 76ce8e363893..570c7b7b40be 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/meta.yml +++ b/modules/nf-core/leafcutter/differentialsplicing/meta.yml @@ -79,4 +79,4 @@ authors: maintainers: - "@JTL-lab" notes: - - This module uses PyTorch for statistical analysis. When running in containers, you may need to set environment variables in your pipeline configuration for reproducibility. For example, `containerOptions = '--env USER=nobody --env PYTHONHASHSEED=0 --env CUBLAS_WORKSPACE_CONFIG=:4096:8'` (Docker) or `containerOptions = '--env USER=nobody,PYTHONHASHSEED=0,CUBLAS_WORKSPACE_CONFIG=:4096:8'` (Singularity/Apptainer). + - This module uses PyTorch for statistical analysis. Environment variables are automatically set in the module for container compatibility (`USER` defaults to 'nobody' if unset to prevent Pytorch cache initialization errors, `PYTHONHASHSEED=0` is set for reproducibility). diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config index 9949e3230640..289576488ca3 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config @@ -6,9 +6,6 @@ process { withName: 'LEAFCUTTER_DIFFERENTIALSPLICING' { ext.args = '--min_samples_per_group 2 --min_samples_per_intron 2' - containerOptions = { workflow.containerEngine == 'singularity' ? - '--env USER=nobody,PYTHONHASHSEED=0,CUBLAS_WORKSPACE_CONFIG=:4096:8' : - '--env USER=nobody --env PYTHONHASHSEED=0 --env CUBLAS_WORKSPACE_CONFIG=:4096:8' } } } From b4a79454686b2e2eba73e1cd93ed186d763e67a3 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 1 Aug 2026 13:25:15 -0400 Subject: [PATCH 07/12] docs: update tools section of meta.yml with args_id per nf-core docs best practices --- modules/nf-core/leafcutter/differentialsplicing/meta.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/nf-core/leafcutter/differentialsplicing/meta.yml b/modules/nf-core/leafcutter/differentialsplicing/meta.yml index 570c7b7b40be..e9f4624dc048 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/meta.yml +++ b/modules/nf-core/leafcutter/differentialsplicing/meta.yml @@ -15,6 +15,7 @@ tools: doi: "10.1038/s41588-017-0004-9" licence: ["Apache-2.0"] identifier: biotools:leafcutter + args_id: "$args" input: - - meta: From b048a4f6ddf06b2008e688f4ccd3b16e8ad3b1fe Mon Sep 17 00:00:00 2001 From: = Date: Sat, 1 Aug 2026 13:33:29 -0400 Subject: [PATCH 08/12] refactor: move ext.args from nextflow.config to be with test input in main.nf.test per nf-core docs best practices --- .../leafcutter/differentialsplicing/tests/main.nf.test | 8 ++++++++ .../leafcutter/differentialsplicing/tests/nextflow.config | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test index a3a60ef74eb6..c756d7c5943d 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test @@ -62,6 +62,9 @@ nextflow_process { } when { + params { + module_args = '--min_samples_per_group 2 --min_samples_per_intron 2' + } process { """ def groups_content = '''ctrl_rep1\\tCONTROL @@ -89,9 +92,14 @@ kd_rep2\\tKNOCKDOWN test("homo_sapiens - bam - differential splicing - stub") { + config "./nextflow.config" + options "-stub" when { + params { + module_args = '' + } process { """ input[0] = [ diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config index 289576488ca3..33a320a2dd72 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/nextflow.config @@ -5,7 +5,7 @@ singularity { process { withName: 'LEAFCUTTER_DIFFERENTIALSPLICING' { - ext.args = '--min_samples_per_group 2 --min_samples_per_intron 2' + ext.args = { params.module_args ?: '' } } } From bea36d8bec2c3b0ac1689fce80d78d03adc6b5b9 Mon Sep 17 00:00:00 2001 From: Julia Lewandowski <68295300+JTL-lab@users.noreply.github.com> Date: Sun, 2 Aug 2026 15:22:50 -0400 Subject: [PATCH 09/12] Update modules/nf-core/leafcutter/differentialsplicing/main.nf Co-authored-by: Simon Pearce <24893913+SPPearce@users.noreply.github.com> --- modules/nf-core/leafcutter/differentialsplicing/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/leafcutter/differentialsplicing/main.nf b/modules/nf-core/leafcutter/differentialsplicing/main.nf index c5f90279cbc4..c7fd29696581 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/main.nf +++ b/modules/nf-core/leafcutter/differentialsplicing/main.nf @@ -29,7 +29,7 @@ process LEAFCUTTER_DIFFERENTIALSPLICING { leafcutter-ds \\ $counts \\ $groups \\ - --output_prefix ${prefix}_results \\ + --output_prefix ${prefix} \\ --num_threads $task.cpus \\ $args """ From f3a1fc8c1683cd79e4eda7a75b47b03a9a6b3597 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 3 Aug 2026 11:28:20 -0400 Subject: [PATCH 10/12] refactor: correct stub profile output file naming and main.nf.test.snap expected file naming following refactor in previous commit #bea36d8 --- modules/nf-core/leafcutter/differentialsplicing/main.nf | 4 ++-- .../differentialsplicing/tests/main.nf.test.snap | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/nf-core/leafcutter/differentialsplicing/main.nf b/modules/nf-core/leafcutter/differentialsplicing/main.nf index c7fd29696581..7ceb35307bf6 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/main.nf +++ b/modules/nf-core/leafcutter/differentialsplicing/main.nf @@ -37,7 +37,7 @@ process LEAFCUTTER_DIFFERENTIALSPLICING { stub: def prefix = task.ext.prefix ?: "${meta.id}" """ - touch ${prefix}_results_cluster_significance.txt - touch ${prefix}_results_effect_sizes.txt + touch ${prefix}_cluster_significance.txt + touch ${prefix}_effect_sizes.txt """ } diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap index 8e5ecd5f5bc3..cf124e435216 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test_ds" }, - "test_ds_results_cluster_significance.txt" + "test_ds_cluster_significance.txt" ] ], "effect_sizes": [ @@ -15,7 +15,7 @@ { "id": "test_ds" }, - "test_ds_results_effect_sizes.txt" + "test_ds_effect_sizes.txt" ] ], "versions_leafcutter": [ @@ -41,7 +41,7 @@ { "id": "test" }, - "test_results_cluster_significance.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + "test_cluster_significance.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "effect_sizes": [ @@ -49,7 +49,7 @@ { "id": "test" }, - "test_results_effect_sizes.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + "test_effect_sizes.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "versions_leafcutter": [ From 4632bf2956782bf96b054c0b5f07ac43872a9577 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 4 Aug 2026 11:29:18 -0400 Subject: [PATCH 11/12] fix: update leafcutter/differentialsplicing main.nf.test and test snapshot to reflect now deterministic output files --- .../leafcutter/differentialsplicing/tests/main.nf.test | 2 +- .../leafcutter/differentialsplicing/tests/main.nf.test.snap | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test index c756d7c5943d..07afc21e41f2 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test @@ -84,7 +84,7 @@ kd_rep2\\tKNOCKDOWN then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["cluster_significance", "effect_sizes"])).match()} + { assert snapshot(sanitizeOutput(process.out)).match()} ) } diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap index cf124e435216..57a83f39641a 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test_ds" }, - "test_ds_cluster_significance.txt" + "test_ds_cluster_significance.txt:md5,fced1b0b3c0417c4f0c51eb2300d3441" ] ], "effect_sizes": [ @@ -15,7 +15,7 @@ { "id": "test_ds" }, - "test_ds_effect_sizes.txt" + "test_ds_effect_sizes.txt:md5,b2ca0c61567b8a78db594ac12fac1d5e" ] ], "versions_leafcutter": [ @@ -27,7 +27,7 @@ ] } ], - "timestamp": "2026-07-28T12:22:48.849459725", + "timestamp": "2026-08-04T11:23:11.169540122", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.0" From 0faf3b9d09bbebe24e556398a649bc20ee81445c Mon Sep 17 00:00:00 2001 From: = Date: Tue, 4 Aug 2026 11:58:23 -0400 Subject: [PATCH 12/12] Revert "fix: update leafcutter/differentialsplicing main.nf.test and test snapshot to reflect now deterministic output files" This reverts commit 4632bf2956782bf96b054c0b5f07ac43872a9577. --- .../leafcutter/differentialsplicing/tests/main.nf.test | 2 +- .../leafcutter/differentialsplicing/tests/main.nf.test.snap | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test index 07afc21e41f2..c756d7c5943d 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test @@ -84,7 +84,7 @@ kd_rep2\\tKNOCKDOWN then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out)).match()} + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["cluster_significance", "effect_sizes"])).match()} ) } diff --git a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap index 57a83f39641a..cf124e435216 100644 --- a/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap +++ b/modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test_ds" }, - "test_ds_cluster_significance.txt:md5,fced1b0b3c0417c4f0c51eb2300d3441" + "test_ds_cluster_significance.txt" ] ], "effect_sizes": [ @@ -15,7 +15,7 @@ { "id": "test_ds" }, - "test_ds_effect_sizes.txt:md5,b2ca0c61567b8a78db594ac12fac1d5e" + "test_ds_effect_sizes.txt" ] ], "versions_leafcutter": [ @@ -27,7 +27,7 @@ ] } ], - "timestamp": "2026-08-04T11:23:11.169540122", + "timestamp": "2026-07-28T12:22:48.849459725", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.0"