Skip to content

Commit ea8d54b

Browse files
MultiSeqDemux (#8638)
* local tests passed * first improvements * changes based on feedback for htodemux * adopted feedback from review * Update modules/nf-core/multiseqdemux/main.nf Co-authored-by: Nico Trummer <[email protected]> * update hashes --------- Co-authored-by: Nico Trummer <[email protected]>
1 parent 00d1ceb commit ea8d54b

File tree

6 files changed

+410
-0
lines changed

6 files changed

+410
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json
3+
channels:
4+
- conda-forge
5+
- bioconda
6+
dependencies:
7+
- "conda-forge::r-seurat=5.3.0"
8+
- "conda-forge::r-seuratobject=5.1.0"

modules/nf-core/multiseqdemux/main.nf

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
process MULTISEQDEMUX {
2+
tag "$meta.id"
3+
label 'process_low'
4+
5+
conda "${moduleDir}/environment.yml"
6+
container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ?
7+
'oras://community.wave.seqera.io/library/r-seurat_r-seuratobject:4c5a804804327d29':
8+
'community.wave.seqera.io/library/r-seurat_r-seuratobject:b11306d1bdc82827' }"
9+
10+
input:
11+
tuple val(meta), path(seurat_object), val(assay)
12+
13+
output:
14+
tuple val(meta), path("*_params_multiseqdemux.csv") , emit: params
15+
tuple val(meta), path("*_res_multiseqdemux.csv") , emit: results
16+
tuple val(meta), path("*_multiseqdemux.rds") , emit: rds
17+
path "versions.yml" , emit: versions
18+
19+
when:
20+
task.ext.when == null || task.ext.when
21+
22+
script:
23+
quantile = task.ext.assay ?: "0.7"
24+
autoThresh = task.ext.autoThresh ?: "TRUE"
25+
maxiter = task.ext.maxiter ?: "5"
26+
qrangeFrom = task.ext.qrangeFrom ?: "0.1"
27+
qrangeTo = task.ext.qrangeTo ?: "0.9"
28+
qrangeBy = task.ext.qrangeBy ?: "0.05"
29+
verbose = task.ext.verbose ?: 'TRUE'
30+
prefix = task.ext.prefix ?: "${meta.id}"
31+
32+
template 'MultiSeqDemux.R'
33+
34+
stub:
35+
def prefix = task.ext.prefix ?: "${meta.id}"
36+
"""
37+
touch ${prefix}_params_multiseqdemux.csv
38+
touch ${prefix}_res_multiseqdemux.csv
39+
touch ${prefix}_multiseqdemux.rds
40+
41+
cat <<-END_VERSIONS > versions.yml
42+
"${task.process}":
43+
r-seurat: \$(Rscript -e "library(Seurat); cat(as.character(packageVersion('Seurat')))")
44+
r-base: \$(Rscript -e "cat(strsplit(R.version[['version.string']], ' ')[[1]][3])")
45+
END_VERSIONS
46+
"""
47+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json
3+
name: "multiseqdemux"
4+
description: Identify singlets, doublets and negative cells from multiplexing experiments. Annotate singlets by tags.
5+
keywords:
6+
- demultiplexing
7+
- hashing-based deconvolution
8+
- single-cell
9+
tools:
10+
- "multiseqdemux":
11+
description: "MULTIseqDemux is the demultiplexing module of Seurat, which demultiplex samples based on data from cell hashing."
12+
homepage: "https://satijalab.org/seurat/reference/multiseqdemux"
13+
documentation: "https://satijalab.org/seurat/reference/multiseqdemux"
14+
tool_dev_url: "https://github.com/satijalab/seurat"
15+
doi: "10.1038/s41592-019-0433-8"
16+
licence: ["MIT"]
17+
identifier: ""
18+
19+
input:
20+
- - meta:
21+
type: map
22+
description: |
23+
Groovy Map containing sample information
24+
e.g. `[ id:'sample1' ]`
25+
- seurat_object:
26+
type: file
27+
description: |
28+
A `.rds` file containing the seurat object. Assumes that the hash tag oligo (HTO) data has been added and normalized.
29+
- assay:
30+
type: string
31+
description: |
32+
Name of the Hashtag assay, usually called "HTO" by default. Use the custom name if the assay has been named differently.
33+
34+
output:
35+
36+
- params:
37+
- meta:
38+
type: map
39+
description: |
40+
Groovy Map containing sample information
41+
e.g. `[ id:'sample1' ]`
42+
- "*_params_multiseqdemux.csv":
43+
type: file
44+
description: The used parameters to call MULTIseqDemux in the R-Script.
45+
pattern: "_params_multiseqdemux.csv"
46+
47+
- results:
48+
- meta:
49+
type: map
50+
description: |
51+
Groovy Map containing sample information
52+
e.g. `[ id:'sample1' ]`
53+
- "*_res_multiseqdemux.csv":
54+
type: file
55+
description: Resuls of MULTIseqDemux.
56+
pattern: "_res_multiseqdemux.csv"
57+
58+
- rds:
59+
- meta:
60+
type: map
61+
description: |
62+
Groovy Map containing sample information
63+
e.g. `[ id:'sample1' ]`
64+
- "*_multiseqdemux.rds":
65+
type: file
66+
description: SeuratObject saved as RDS.
67+
pattern: "_multiseqdemux.rds"
68+
69+
- versions:
70+
- "versions.yml":
71+
type: file
72+
description: File containing software versions
73+
pattern: "versions.yml"
74+
75+
authors:
76+
- "@LuisHeinzlmeier"
77+
maintainers:
78+
- "@LuisHeinzlmeier"
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env Rscript
2+
3+
################################################
4+
################################################
5+
## USE PARAMETERS FROM NEXTFLOW ##
6+
################################################
7+
################################################
8+
9+
# cast parameters from nextflow
10+
seuratObj = '$seurat_object'
11+
options(digits=5)
12+
quantile = as.double('$quantile')
13+
autoThresh = as.logical('$autoThresh')
14+
maxiter = as.integer('$maxiter')
15+
qrangeFrom = as.double('$qrangeFrom')
16+
qrangeTo = as.double('$qrangeTo')
17+
qrangeBy = as.double('$qrangeBy')
18+
verbose = as.logical('$verbose')
19+
assay ='$assay'
20+
prefix = '$prefix'
21+
22+
if (! file.exists(seuratObj)){
23+
stop(paste0(seuratObj, ' is not a valid file'))
24+
}
25+
26+
################################################
27+
################################################
28+
## Finish loading libraries ##
29+
################################################
30+
################################################
31+
32+
library(Seurat)
33+
34+
################################################
35+
################################################
36+
## Main Process ##
37+
################################################
38+
################################################
39+
40+
# Loading Seurat object
41+
hashtag <- readRDS(seuratObj)
42+
43+
# Demultiplex cells
44+
if (autoThresh == TRUE) {
45+
hashtag <- MULTIseqDemux(hashtag, assay = assay, quantile = quantile, autoThresh = TRUE, maxiter = maxiter, qrange = seq(from = qrangeFrom, to = qrangeTo, by = qrangeBy), verbose = verbose)
46+
} else {
47+
hashtag <- MULTIseqDemux(hashtag, assay = assay, quantile = quantile, verbose = verbose)
48+
}
49+
50+
################################################
51+
################################################
52+
## SAVING RESULTS ##
53+
################################################
54+
################################################
55+
56+
# create a data frame to save the used parameters in a csv file
57+
Argument <- c("seuratObjectPath", "quantile", "autoThresh", "maxiter", "qrangeFrom", "qrangeTo", "qrangeBy", "verbose", "assay")
58+
Value <- c(seuratObj, quantile, autoThresh, maxiter, qrangeFrom, qrangeTo, qrangeBy, verbose, assay)
59+
params <- data.frame(Argument, Value)
60+
write.csv(params, paste0(prefix ,"_params_multiseqdemux.csv"))
61+
62+
# save the results from MULTIseqDemux()
63+
write.csv(hashtag\$MULTI_ID, paste0(prefix , "_res_multiseqdemux.csv"))
64+
saveRDS(hashtag, file = paste0(prefix ,"_multiseqdemux.rds"))
65+
66+
################################################
67+
################################################
68+
## VERSIONS FILE ##
69+
################################################
70+
################################################
71+
72+
r.version <- paste(R.version[['major']],R.version[['minor']], sep = ".")
73+
seurat.version <- as.character(packageVersion('Seurat'))
74+
75+
writeLines(
76+
c(
77+
'"${task.process}":',
78+
paste(' r-base:', r.version),
79+
paste(' r-seurat:', seurat.version)
80+
),
81+
'versions.yml')
82+
83+
################################################
84+
################################################
85+
################################################
86+
################################################
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
nextflow_process {
2+
3+
name "Test Process MULTISEQDEMUX"
4+
script "../main.nf"
5+
process "MULTISEQDEMUX"
6+
7+
tag "modules"
8+
tag "modules_nfcore"
9+
tag "multiseqdemux"
10+
11+
test("seuratObject - rds") {
12+
13+
when {
14+
process {
15+
"""
16+
input[0] = [
17+
[ id:'test'], // meta map
18+
file(params.modules_testdata_base_path + '/genomics/homo_sapiens/10xgenomics/cellranger/hashing_demultiplexing/htodemux.rds', checkIfExists: true),
19+
"HTO"
20+
]
21+
"""
22+
}
23+
}
24+
25+
then {
26+
assertAll(
27+
{ assert process.success },
28+
{ assert snapshot(process.out).match() }
29+
)
30+
}
31+
32+
}
33+
34+
test("seuratObject - rds - stub") {
35+
36+
options "-stub"
37+
38+
when {
39+
process {
40+
"""
41+
input[0] = [
42+
[ id:'test'], // meta map
43+
file(params.modules_testdata_base_path + '/genomics/homo_sapiens/10xgenomics/cellranger/hashing_demultiplexing/htodemux.rds', checkIfExists: true),
44+
"HTO"
45+
]
46+
"""
47+
}
48+
}
49+
50+
then {
51+
assertAll(
52+
{ assert process.success },
53+
{ assert snapshot(process.out).match() }
54+
)
55+
}
56+
57+
}
58+
59+
}

0 commit comments

Comments
 (0)