Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
75e1e9d
update snapshot
antoniasaracco Aug 12, 2025
46f8d39
exchange gtf file for annot tsv file
antoniasaracco Aug 12, 2025
b5afaa8
remove parse_gtf function
antoniasaracco Aug 12, 2025
b879dbb
exchange gtf file for annot tsv file
antoniasaracco Aug 12, 2025
595cf26
update
antoniasaracco Aug 12, 2025
049f327
update
antoniasaracco Aug 12, 2025
f9f4830
update meta.yml
antoniasaracco Aug 12, 2025
cb092f6
fix
antoniasaracco Aug 12, 2025
a081c27
Include annotation file expected format
antoniasaracco Aug 12, 2025
85f0187
Update: reference file
antoniasaracco Aug 12, 2025
e8684dd
include decoupler to subworkflow
antoniasaracco Aug 13, 2025
fcdb6a4
Include decoupler test config
antoniasaracco Aug 13, 2025
86a4619
Include decoupler to test file
antoniasaracco Aug 13, 2025
30d8dbc
Update snapshot with decoupler output files
antoniasaracco Aug 13, 2025
bcc16d6
Add decoupler config
antoniasaracco Aug 13, 2025
2f0409f
Merge branch 'decoupler_to_differential_enrichment_subworkflow' into …
antoniasaracco Aug 13, 2025
e913655
Merge branch 'nf-core:master' into decoupler
antoniasaracco Aug 13, 2025
f2f035c
Replace gtf annotation file for tsv table for decoupler
antoniasaracco Aug 13, 2025
a9540fa
Update snapshot to remove pvals plots for decoupler
antoniasaracco Aug 13, 2025
fc5ee96
Merge branch 'decoupler' of https://github.com/antoniasaracco/modules…
antoniasaracco Aug 13, 2025
08128c0
include decoupler to subworkflow meta.yml
antoniasaracco Aug 13, 2025
5d4f199
fix syntax error
antoniasaracco Aug 13, 2025
595ccef
add decoupler/decoupler tag
antoniasaracco Aug 13, 2025
9adfd40
fix syntax issue
antoniasaracco Aug 13, 2025
a1f6990
fix component
antoniasaracco Aug 13, 2025
323bea3
Upgrade decoupler output assertion
antoniasaracco Aug 14, 2025
cd31720
Improve format validation for annotation tsv file
antoniasaracco Aug 14, 2025
bab932b
Merge branch 'nf-core:master' into decoupler
antoniasaracco Aug 15, 2025
a1e70ba
Include meta for all decoupler inputs
antoniasaracco Aug 15, 2025
887d4a6
Update decoupler test with new meta input requirement
antoniasaracco Aug 15, 2025
bb04579
Fix decoupler input channels
antoniasaracco Aug 15, 2025
45f36e6
Update decoupler prefix
antoniasaracco Aug 15, 2025
b791daa
Update decoupler test with new input channels
antoniasaracco Aug 15, 2025
7062ed9
Update snapshot
antoniasaracco Aug 15, 2025
2c07488
Merge branch 'decoupler' of https://github.com/antoniasaracco/modules…
antoniasaracco Aug 15, 2025
f402ea2
Merge branch 'nf-core:master' into decoupler
antoniasaracco Aug 17, 2025
4ad16ef
add meta for net and annot inputs
antoniasaracco Aug 17, 2025
389cac5
Merge branch 'nf-core:master' into decoupler
antoniasaracco Aug 22, 2025
015248f
Include method differential to stub results to avoid null names
antoniasaracco Aug 25, 2025
4e9f966
Add method differential to stub results to avoid null
antoniasaracco Aug 25, 2025
e0318a3
Include ch_featuresheet into ch_input_for_other
antoniasaracco Aug 26, 2025
b43aea4
Separate channel for other and channel for decoupler including featu…
antoniasaracco Aug 26, 2025
9a54972
update decoupler test
antoniasaracco Aug 26, 2025
4dc74a4
Remove hardcode of gene_id and gene_name columns
antoniasaracco Aug 26, 2025
bb5f16b
update decoupler meta.yml
antoniasaracco Aug 26, 2025
9994318
update decoupler test
antoniasaracco Aug 26, 2025
e86e9cc
Merge branch 'master' into decoupler
antoniasaracco Aug 26, 2025
8c26497
Merge branch 'master' into decoupler
antoniasaracco Aug 26, 2025
eb0adaa
Fix: Remove features id and symbol from decoupler meta.yml
antoniasaracco Aug 26, 2025
9b5ef02
Fix: Remove features id and symbol from decoupler input
antoniasaracco Aug 26, 2025
1437782
Fix: Take features id and symbol as external arguments
antoniasaracco Aug 26, 2025
abbfed2
Fix: Take features id and symbol as external arguments
antoniasaracco Aug 26, 2025
fe99b36
Fix: Take features id and symbol as external arguments
antoniasaracco Aug 26, 2025
f9b8cb2
Fix: remove ch_input_for_decoupler
antoniasaracco Aug 26, 2025
9fb43a2
correct method
antoniasaracco Aug 26, 2025
363e41e
Update: update nf-test to work with new input channel
antoniasaracco Aug 26, 2025
4c9dc22
Merge branch 'master' into decoupler
antoniasaracco Aug 26, 2025
b3ee6d0
Merge branch 'master' into decoupler
antoniasaracco Aug 27, 2025
f3c333f
Merge branch 'master' into decoupler
antoniasaracco Aug 27, 2025
24a1f74
Fix: change method
antoniasaracco Sep 1, 2025
36b354c
Fix: update ch_input_for_other channel to include featuresheet only f…
antoniasaracco Sep 1, 2025
e5ef67e
Update snapshot
antoniasaracco Sep 1, 2025
212bc18
Merge branch 'decoupler' of https://github.com/antoniasaracco/modules…
antoniasaracco Sep 1, 2025
5909225
Fix
antoniasaracco Sep 1, 2025
a1c1f5f
Merge branch 'master' into decoupler
antoniasaracco Sep 1, 2025
4348a6b
Merge branch 'nf-core:master' into decoupler
antoniasaracco Sep 12, 2025
8ed6172
Fix: Simplify features form input channel
antoniasaracco Sep 12, 2025
516ecd0
Update snapshot
antoniasaracco Sep 12, 2025
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
13 changes: 6 additions & 7 deletions modules/nf-core/decoupler/decoupler/main.nf
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
process DECOUPLER {
tag "$meta.id"
label 'process_medium'

conda "${moduleDir}/environment.yml"
container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ?
'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/dc/dc0ee6d6033b9f04c6377ad3b1cf5f924e3243626ab8d7be836d9d6617f8da4e/data' :
'community.wave.seqera.io/library/decoupler-py_matplotlib_pandas_scanpy:369a5afe315b9b30' }"

input:
tuple val(meta), path(mat)
path(net)
path(gtf)
tuple val(meta2), path(net)
tuple val(meta3), path(annot)

output:
tuple val(meta), path("*estimate_decoupler.tsv"), emit: dc_estimate
tuple val(meta), path("*pvals_decoupler.tsv"), emit: dc_pvals
tuple val(meta), path("*decoupler_plot.png"), emit: png
tuple val(meta), path("*estimate_decoupler_plot.png"), emit: png
path("versions.yml"), emit: versions

when:
Expand All @@ -26,9 +25,9 @@ process DECOUPLER {

stub:
"""
touch ${task.ext.prefix}_estimate_decoupler.tsv
touch ${task.ext.prefix}_pvals_decoupler.tsv
touch ${task.ext.prefix}_decoupler_plot.png
touch deseq2_estimate_decoupler.tsv
Copy link
Contributor

Choose a reason for hiding this comment

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

why 'deseq2'?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@suzannejin In the stub sections I used deseq2 as a placeholder so the filenames and metadata do not contain null. It is one of the valid values that real runs can produce. Outside of stub mode this field is set by the actual method used, so it may be deseq2, limma, etc. The placeholder is only to keep the stub outputs deterministic.

touch deseq2_pvals_decoupler.tsv
touch deseq2_estimate_decoupler_plot.png
touch versions.yml
"""
}
44 changes: 27 additions & 17 deletions modules/nf-core/decoupler/decoupler/meta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,31 @@ input:
pattern: "*.tsv"
ontologies:
- edam: http://edamontology.org/format_3475 # TSV
- net:
type: file
description: |
The prior knowledge network linking the features of the
expression matrix to a process/component (e.g. gene set,
transcription factor, kinase, etc.)
pattern: "*.tsv"
ontologies:
- edam: http://edamontology.org/format_3475 # TSV
- gtf:
type: file
description: |
Annotation file in GTF format
pattern: "*.gtf"
ontologies: []
- - meta2:
type: map
description: Groovy map
- net:
type: file
description: |
The prior knowledge network linking the features of the
expression matrix to a process/component (e.g. gene set,
transcription factor, kinase, etc.)
pattern: "*.tsv"
ontologies:
- edam: http://edamontology.org/format_3475 # TSV
- - meta3:
type: map
description: Groovy map
- annot:
type: file
description: |
Annotation file in TSV format containing gene ID to gene name mappings.
Used specifically for mapping Ensembl IDs to gene names.
Expected format: two columns with gene_id and gene_name headers.
pattern: "*.tsv"
required: false
ontologies:
- edam: http://edamontology.org/format_3475 # TSV
output:
dc_estimate:
- - meta:
Expand Down Expand Up @@ -90,12 +100,12 @@ output:
description: |
Groovy Map containing sample information
e.g. [ id:‘test’, single_end ]
- "*decoupler_plot.png":
- "*estimate_decoupler_plot.png":
type: file
description: |
The file containing the plots associated to the estimation
results of the enrichment(s)
pattern: "*decoupler_plot.png"
pattern: "*estimate_decoupler_plot.png"
ontologies:
- edam: http://edamontology.org/format_3475 # TSV
versions:
Expand Down
47 changes: 15 additions & 32 deletions modules/nf-core/decoupler/decoupler/templates/decoupler.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,52 +41,35 @@ def parse_ext_args(args_string: str):
parser.add_argument("--column", type=str, default="log2FoldChange", help="Column name to use for transposition")
parser.add_argument("--ensembl_ids", type=str, default="FALSE", help="Convert ENSEMBL IDs to gene symbols if TRUE")
parser.add_argument("--methods", type=str, default = "ulm", help="Comma-separated list of methods to use (e.g., 'mlm,ulm')")
parser.add_argument("--features_id_col", type=str, default="gene_id", help="Column name for feature IDs")
parser.add_argument("--features_symbol_col", type=str, default="gene_name", help="Column name for feature symbols")
return parser.parse_args(args_list)

def parse_gtf(gtf_file: str):
"""
Parse an optional GTF file to create a mapping of ENSEMBL gene IDs to gene symbols (required to use Progeny data).
"""
mapping = {}
opener = gzip.open if gtf_file.endswith('.gz') else open
with opener(gtf_file, 'rt') as f:
for line in f:
if line.startswith("#"):
continue
fields = line.strip().split("\t")
if len(fields) < 9:
continue
attributes_field = fields[8]
attributes = {}
for attr in attributes_field.split(";"):
attr = attr.strip()
if not attr:
continue
parts = attr.split(" ", 1)
if len(parts) != 2:
continue
key, value = parts
attributes[key] = value.replace('"', '').strip()
gene_id = attributes.get("gene_id")
gene_symbol = attributes.get("gene_name") or attributes.get("gene_symbol") or attributes.get("external_gene_name")
if gene_id and gene_symbol:
mapping[gene_id] = gene_symbol
return mapping

# Parse external arguments
raw_args = "${task.ext.args}"
parsed_args = parse_ext_args(raw_args)
methods = [m.strip() for m in parsed_args.methods.split(",") if m.strip()]

if parsed_args.ensembl_ids.upper() == "TRUE":
try:
gene_mapping = parse_gtf("${gtf}")
if not os.path.exists("${annot}"):
raise FileNotFoundError(f"Annotation file not found: ${annot}")

annot_df = pd.read_csv("${annot}", sep="\t")

required_cols = {parsed_args.features_id_col, parsed_args.features_symbol_col}

missing = required_cols - set(annot_df.columns)
if missing:
raise ValueError(f"Missing required columns in annotation file: {missing}. Available columns: {list(annot_df.columns)}")

gene_mapping = dict(zip(annot_df[parsed_args.features_id_col], annot_df[parsed_args.features_symbol_col]))
new_index = [gene_mapping.get(ens, None) for ens in mat.index]
mat.index = new_index
mat = mat[mat.index.notnull()]
mat = mat[~mat.index.duplicated(keep='first')]
except Exception as e:
print("ERROR: Failed to parse GTF:", e)
print(f"ERROR: Failed to process annotation file: {e}")
sys.exit(1)

if parsed_args.transpose.upper() == "TRUE":
Expand Down
21 changes: 15 additions & 6 deletions modules/nf-core/decoupler/decoupler/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ nextflow_process {

when {
params {
module_args = "--min_n 2 --transpose TRUE --ensembl_ids TRUE --methods mlm"
module_args = "--min_n 2 --transpose TRUE --ensembl_ids TRUE --methods mlm --features_id_col gene_id --features_symbol_col gene_name"
}
process {
"""
Expand All @@ -23,9 +23,12 @@ nextflow_process {
file("https://github.com/nf-core/test-datasets/raw/differentialabundance/modules_testdata/treatment_mCherry_hND6_.deseq2.results.tsv", checkIfExists: true)
]
input[1] = [
['id':'network'],
file("https://github.com/nf-core/test-datasets/raw/differentialabundance/modules_testdata/progeny/mouse_network.tsv", checkIfExists: true)
]
input[2] = [file("https://ftp.ensembl.org/pub/release-81/gtf/mus_musculus/Mus_musculus.GRCm38.81.gtf.gz", checkIfExists: true)]
input[2] = [
['id':'annot'],
file("https://github.com/nf-core/test-datasets/raw/differentialabundance/modules_testdata/Mus_musculus.anno.feature_metadata.tsv", checkIfExists: true)]
"""
}
}
Expand Down Expand Up @@ -63,7 +66,7 @@ nextflow_process {

when {
params {
module_args = "--min_n 1"
module_args = "--min_n 1 --features_id_col gene_id --features_symbol_col gene_name"
}

process {
Expand All @@ -73,9 +76,12 @@ nextflow_process {
file(params.test_data['generic']['tsv']['expression'], checkIfExists: true)
]
input[1] = [
['id':'network'],
file(params.test_data['generic']['tsv']['network'], checkIfExists: true)
]
input[2] = [file("https://ftp.ensembl.org/pub/release-81/gtf/mus_musculus/Mus_musculus.GRCm38.81.gtf.gz", checkIfExists: true)]
input[2] = [
['id':'annot'],
file("https://github.com/nf-core/test-datasets/raw/differentialabundance/modules_testdata/Mus_musculus.anno.feature_metadata.tsv", checkIfExists: true)]
"""
}
}
Expand Down Expand Up @@ -114,7 +120,7 @@ nextflow_process {

when {
params {
module_args = "--min_n 1"
module_args = "--min_n 1 --features_id_col gene_id --features_symbol_col gene_name"
}
process {
"""
Expand All @@ -123,9 +129,12 @@ nextflow_process {
file(params.test_data['generic']['tsv']['expression'], checkIfExists: true)
]
input[1] = [
['id':'network'],
file(params.test_data['generic']['tsv']['network'], checkIfExists: true)
]
input[2] = [file("https://ftp.ensembl.org/pub/release-81/gtf/mus_musculus/Mus_musculus.GRCm38.81.gtf.gz", checkIfExists: true)]
input[2] = [
['id':'annot'],
file("https://github.com/nf-core/test-datasets/raw/differentialabundance/modules_testdata/Mus_musculus.anno.feature_metadata.tsv", checkIfExists: true)]
"""
}
}
Expand Down
22 changes: 11 additions & 11 deletions modules/nf-core/decoupler/decoupler/tests/main.nf.test.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"content": [
"[deseq2_treatment_mCherry_hND6_consensus_estimate_decoupler.tsv, deseq2_treatment_mCherry_hND6_mlm_estimate_decoupler.tsv]",
"[deseq2_treatment_mCherry_hND6_consensus_pvals_decoupler.tsv, deseq2_treatment_mCherry_hND6_mlm_pvals_decoupler.tsv]",
"[deseq2_treatment_mCherry_hND6_consensus_estimate_decoupler_plot.png, deseq2_treatment_mCherry_hND6_consensus_pvals_decoupler_plot.png, deseq2_treatment_mCherry_hND6_mlm_estimate_decoupler_plot.png, deseq2_treatment_mCherry_hND6_mlm_pvals_decoupler_plot.png]",
"[deseq2_treatment_mCherry_hND6_consensus_estimate_decoupler_plot.png, deseq2_treatment_mCherry_hND6_mlm_estimate_decoupler_plot.png]",
2,
2,
[
Expand All @@ -26,7 +26,7 @@
"nf-test": "0.9.2",
"nextflow": "25.04.6"
},
"timestamp": "2025-07-17T03:01:11.305706897"
"timestamp": "2025-08-12T18:24:03.118968335"
},
"decoupler stub": {
"content": [
Expand All @@ -36,23 +36,23 @@
{
"id": "test"
},
"null_test_estimate_decoupler.tsv:md5,d41d8cd98f00b204e9800998ecf8427e"
"deseq2_estimate_decoupler.tsv:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"1": [
[
{
"id": "test"
},
"null_test_pvals_decoupler.tsv:md5,d41d8cd98f00b204e9800998ecf8427e"
"deseq2_pvals_decoupler.tsv:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"2": [
[
{
"id": "test"
},
"null_test_decoupler_plot.png:md5,d41d8cd98f00b204e9800998ecf8427e"
"deseq2_estimate_decoupler_plot.png:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"3": [
Expand All @@ -63,23 +63,23 @@
{
"id": "test"
},
"null_test_estimate_decoupler.tsv:md5,d41d8cd98f00b204e9800998ecf8427e"
"deseq2_estimate_decoupler.tsv:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"dc_pvals": [
[
{
"id": "test"
},
"null_test_pvals_decoupler.tsv:md5,d41d8cd98f00b204e9800998ecf8427e"
"deseq2_pvals_decoupler.tsv:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"png": [
[
{
"id": "test"
},
"null_test_decoupler_plot.png:md5,d41d8cd98f00b204e9800998ecf8427e"
"deseq2_estimate_decoupler_plot.png:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"versions": [
Expand All @@ -91,13 +91,13 @@
"nf-test": "0.9.2",
"nextflow": "25.04.6"
},
"timestamp": "2025-07-17T01:49:26.123404951"
"timestamp": "2025-08-25T18:51:20.453145611"
},
"decoupler_test": {
"content": [
"[deseq2_test_consensus_estimate_decoupler.tsv, deseq2_test_ulm_estimate_decoupler.tsv]",
"[deseq2_test_consensus_pvals_decoupler.tsv, deseq2_test_ulm_pvals_decoupler.tsv]",
"[deseq2_test_consensus_estimate_decoupler_plot.png, deseq2_test_consensus_pvals_decoupler_plot.png, deseq2_test_ulm_estimate_decoupler_plot.png, deseq2_test_ulm_pvals_decoupler_plot.png]",
"[deseq2_test_consensus_estimate_decoupler_plot.png, deseq2_test_ulm_estimate_decoupler_plot.png]",
2,
2,
[
Expand All @@ -120,6 +120,6 @@
"nf-test": "0.9.2",
"nextflow": "25.04.6"
},
"timestamp": "2025-07-17T04:07:01.430446461"
"timestamp": "2025-08-12T18:27:18.094901759"
}
}
Loading
Loading