Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
eda8ca9
feat (closes #7246): add new component: leafcutter/differentialsplicing
JTL-lab Jul 7, 2026
58b53d4
fix: update main.nf.test for non-deterministic outputs, update snapsh…
JTL-lab Jul 8, 2026
b92aec7
Merge branch 'master' into leafcutter/differentialsplicing
JTL-lab Jul 8, 2026
9a7cce3
Merge branch 'master' into leafcutter/differentialsplicing
JTL-lab Jul 13, 2026
e80e3b3
refactor, fix: incorporated cleaner syntax with sanitizeOutput for te…
JTL-lab Jul 28, 2026
70047f9
Merge branch 'master' into leafcutter/differentialsplicing
JTL-lab Jul 28, 2026
d17cd67
fix: increase pullTimeout for singularity in test profile
JTL-lab Jul 29, 2026
b28f3a7
refactor: add EOF space to nextflow.config for test profile
JTL-lab Jul 29, 2026
8333804
refactor: move environment variables from test config to module main.…
JTL-lab Jul 30, 2026
04cb43c
Merge branch 'master' into leafcutter/differentialsplicing
JTL-lab Jul 30, 2026
b4a7945
docs: update tools section of meta.yml with args_id per nf-core docs …
JTL-lab Aug 1, 2026
b048a4f
refactor: move ext.args from nextflow.config to be with test input in…
JTL-lab Aug 1, 2026
bea36d8
Update modules/nf-core/leafcutter/differentialsplicing/main.nf
JTL-lab Aug 2, 2026
f3a1fc8
refactor: correct stub profile output file naming and main.nf.test.sn…
JTL-lab Aug 3, 2026
9ad5bee
Merge branch 'master' into leafcutter/differentialsplicing
JTL-lab Aug 4, 2026
4632bf2
fix: update leafcutter/differentialsplicing main.nf.test and test sna…
JTL-lab Aug 4, 2026
82c3954
Merge branch 'master' into leafcutter/differentialsplicing
JTL-lab Aug 4, 2026
0faf3b9
Revert "fix: update leafcutter/differentialsplicing main.nf.test and …
JTL-lab Aug 4, 2026
cada80e
Merge branch 'master' into leafcutter/differentialsplicing
JTL-lab Aug 4, 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
Original file line number Diff line number Diff line change
@@ -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"
43 changes: 43 additions & 0 deletions modules/nf-core/leafcutter/differentialsplicing/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
process LEAFCUTTER_DIFFERENTIALSPLICING {
tag "$meta.id"
label 'process_medium'
Comment thread
SPPearce marked this conversation as resolved.

Comment thread
SPPearce marked this conversation as resolved.
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}"
export PYTHONHASHSEED=0

leafcutter-ds \\
$counts \\
$groups \\
--output_prefix ${prefix} \\
--num_threads $task.cpus \\
$args
"""

stub:
def prefix = task.ext.prefix ?: "${meta.id}"
"""
touch ${prefix}_cluster_significance.txt
touch ${prefix}_effect_sizes.txt
"""
}
83 changes: 83 additions & 0 deletions modules/nf-core/leafcutter/differentialsplicing/meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# 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
args_id: "$args"

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"
notes:
- 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).
123 changes: 123 additions & 0 deletions modules/nf-core/leafcutter/differentialsplicing/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
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 {
params {
module_args = '--min_samples_per_group 2 --min_samples_per_intron 2'
}
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(sanitizeOutput(process.out, unstableKeys: ["cluster_significance", "effect_sizes"])).match()}
)
}

}

test("homo_sapiens - bam - differential splicing - stub") {

config "./nextflow.config"

options "-stub"

when {
params {
module_args = ''
}
process {
"""
input[0] = [
[ id:'test' ],
file('test_perind.counts.gz'),
file('groups_file.txt')
]
"""
}
}

then {
assert process.success
assertAll(
{ assert snapshot(sanitizeOutput(process.out)).match() }
)
Comment thread
SPPearce marked this conversation as resolved.
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"homo_sapiens - bam - differential splicing": {
"content": [
{
"cluster_significance": [
[
{
"id": "test_ds"
},
"test_ds_cluster_significance.txt"
]
],
"effect_sizes": [
[
{
"id": "test_ds"
},
"test_ds_effect_sizes.txt"
]
],
"versions_leafcutter": [
[
"LEAFCUTTER_DIFFERENTIALSPLICING",
"leafcutter",
"2.0.3"
]
]
}
],
"timestamp": "2026-07-28T12:22:48.849459725",
"meta": {
"nf-test": "0.9.5",
"nextflow": "25.10.0"
}
},
"homo_sapiens - bam - differential splicing - stub": {
"content": [
{
"cluster_significance": [
[
{
"id": "test"
},
"test_cluster_significance.txt:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"effect_sizes": [
[
{
"id": "test"
},
"test_effect_sizes.txt:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"versions_leafcutter": [
[
"LEAFCUTTER_DIFFERENTIALSPLICING",
"leafcutter",
"2.0.3"
]
]
}
],
"timestamp": "2026-07-28T12:00:56.961347309",
"meta": {
"nf-test": "0.9.5",
"nextflow": "25.10.0"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
singularity {
pullTimeout = 30.m
}

process {

withName: 'LEAFCUTTER_DIFFERENTIALSPLICING' {
ext.args = { params.module_args ?: '' }
}
Comment thread
mahesh-panchal marked this conversation as resolved.

}