Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3,383 changes: 3,383 additions & 0 deletions modules/nf-core/scdblfinder/.conda-lock/linux_amd64-bd-b97c9b42c2a89cba_1.txt

Large diffs are not rendered by default.

3,252 changes: 3,252 additions & 0 deletions modules/nf-core/scdblfinder/.conda-lock/linux_arm64-bd-0e6bd131698855ce_1.txt

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions modules/nf-core/scdblfinder/environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json
channels:
- conda-forge
- bioconda
dependencies:
- bioconda::bioconductor-anndatar=1.0.2
- bioconda::bioconductor-biocparallel=1.44.0
- bioconda::bioconductor-rhdf5=2.54.1
- bioconda::bioconductor-scdblfinder=1.24.0
- bioconda::bioconductor-singlecellexperiment=1.32.0
53 changes: 53 additions & 0 deletions modules/nf-core/scdblfinder/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) the nf-core community under an open-source MIT license.
// See https://github.com/nf-core/modules for full license, file patching instructions and upstream contributing.

process SCDBLFINDER {
tag "${meta.id}"
label 'process_medium'

conda "${moduleDir}/environment.yml"
container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container
? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/0b/0b7da7136d1cb87691c20da1e7b64b2b9bbd102baee2fbc803aedb7c5f634e7f/data'
: 'community.wave.seqera.io/library/bioconductor-anndatar_bioconductor-biocparallel_bioconductor-rhdf5_bioconductor-scdblfinder_bioconductor-singlecellexperiment:b97c9b42c2a89cba'}"

input:
tuple val(meta), path(h5ad)

output:
tuple val(meta), path("${prefix}.h5ad") , emit: h5ad
tuple val(meta), path("${prefix}.predictions.csv") , emit: predictions
tuple val(meta), path("${prefix}.scores.csv") , emit: scores
path "versions.yml" , emit: versions_scdblfinder, topic: versions

when:
task.ext.when == null || task.ext.when

script:
args = task.ext.args ?: ''
prefix = task.ext.prefix ?: "${meta.id}_scdblfinder"
if ("${h5ad}" == "${prefix}.h5ad") {
error("Input and output names are the same, use \"task.ext.prefix\" to disambiguate!")
}
template 'scdblfinder.R'

stub:
prefix = task.ext.prefix ?: "${meta.id}_scdblfinder"
if ("${h5ad}" == "${prefix}.h5ad") {
error("Input and output names are the same, use \"task.ext.prefix\" to disambiguate!")
}
"""
touch ${prefix}.h5ad
touch ${prefix}.predictions.csv
touch ${prefix}.scores.csv

cat <<-END_VERSIONS > versions.yml
"${task.process}":
r-base: \$(Rscript -e "cat(as.character(getRversion()))")
scdblfinder: \$(Rscript -e "suppressMessages(library(scDblFinder)); cat(as.character(packageVersion('scDblFinder')))")
anndatar: \$(Rscript -e "suppressMessages(library(anndataR)); cat(as.character(packageVersion('anndataR')))")
singlecellexperiment: \$(Rscript -e "suppressMessages(library(SingleCellExperiment)); cat(as.character(packageVersion('SingleCellExperiment')))")
biocparallel: \$(Rscript -e "suppressMessages(library(BiocParallel)); cat(as.character(packageVersion('BiocParallel')))")
rhdf5: \$(Rscript -e "cat(as.character(packageVersion('rhdf5')))")
END_VERSIONS
"""
}
112 changes: 112 additions & 0 deletions modules/nf-core/scdblfinder/meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: "scdblfinder"
description: Detect doublets in single-cell RNA-seq data with scDblFinder
keywords:
- doublet detection
- single-cell
- scrnaseq
- quality control
tools:
- "scdblfinder":
description: "Identifies doublets in single-cell RNA-seq data by comparing each cell with artificial doublets made from the data"
homepage: "https://bioconductor.org/packages/scDblFinder"
documentation: "https://bioconductor.org/packages/release/bioc/vignettes/scDblFinder/inst/doc/scDblFinder.html"
tool_dev_url: "https://github.com/plger/scDblFinder"
doi: "10.12688/f1000research.73600.2"
licence: ["GPL-3.0-only"]
identifier: biotools:scdblfinder

input:
- - meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'sample1' ]`
- h5ad:
type: file
description: AnnData object in h5ad format with raw counts in `X`
pattern: "*.h5ad"
ontologies:
- edam: http://edamontology.org/format_3590 # HDF5

output:
h5ad:
- - meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'sample1' ]`
- "${prefix}.h5ad":
type: file
description: Input AnnData object with the scDblFinder columns added to `obs`, stored with gzip compression
pattern: "*.h5ad"
ontologies:
- edam: http://edamontology.org/format_3590 # HDF5
predictions:
- - meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'sample1' ]`
- "${prefix}.predictions.csv":
type: file
description: One boolean column per cell (TRUE = doublet), named after the prefix
pattern: "*.predictions.csv"
ontologies:
- edam: http://edamontology.org/format_3752 # CSV
scores:
- - meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'sample1' ]`
- "${prefix}.scores.csv":
type: file
description: Per-cell scDblFinder results (class, score and related columns)
pattern: "*.scores.csv"
ontologies:
- edam: http://edamontology.org/format_3752 # CSV
versions_scdblfinder:
- versions.yml:
type: file
Comment thread
iraajgangavaram marked this conversation as resolved.
description: File containing software versions
pattern: "versions.yml"
ontologies:
- edam: http://edamontology.org/format_3750 # YAML

topics:
versions:
- versions.yml:
type: file
description: File containing software versions
pattern: "versions.yml"
ontologies:
- edam: http://edamontology.org/format_3750 # YAML

authors:
- "@iraajgangavaram"
maintainers:
- "@iraajgangavaram"
containers:
docker:
linux/arm64:
name: community.wave.seqera.io/library/bioconductor-anndatar_bioconductor-biocparallel_bioconductor-rhdf5_bioconductor-scdblfinder_bioconductor-singlecellexperiment:0e6bd131698855ce
build_id: bd-0e6bd131698855ce_1
scan_id: sc-9c1f3d5cfe40ecb0_1
linux/amd64:
name: community.wave.seqera.io/library/bioconductor-anndatar_bioconductor-biocparallel_bioconductor-rhdf5_bioconductor-scdblfinder_bioconductor-singlecellexperiment:b97c9b42c2a89cba
build_id: bd-b97c9b42c2a89cba_1
scan_id: sc-6a352442ef2b8297_1
singularity:
linux/amd64:
name: oras://community.wave.seqera.io/library/bioconductor-anndatar_bioconductor-biocparallel_bioconductor-rhdf5_bioconductor-scdblfinder_bioconductor-singlecellexperiment:d467a3b6af9e4d7c
build_id: bd-d467a3b6af9e4d7c_1
https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/0b/0b7da7136d1cb87691c20da1e7b64b2b9bbd102baee2fbc803aedb7c5f634e7f/data
linux/arm64:
name: oras://community.wave.seqera.io/library/bioconductor-anndatar_bioconductor-biocparallel_bioconductor-rhdf5_bioconductor-scdblfinder_bioconductor-singlecellexperiment:d88863dbcee9a94d
build_id: bd-d88863dbcee9a94d_1
https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e6/e6e9f553f74e33b3bfa50f72ecbbee1e79e2633a5b8b59d3554f54bc8d3fde8f/data
conda:
linux/amd64:
lock_file: modules/nf-core/scdblfinder/.conda-lock/linux_amd64-bd-b97c9b42c2a89cba_1.txt
linux/arm64:
lock_file: modules/nf-core/scdblfinder/.conda-lock/linux_arm64-bd-0e6bd131698855ce_1.txt
74 changes: 74 additions & 0 deletions modules/nf-core/scdblfinder/templates/scdblfinder.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env Rscript

library(scDblFinder)
library(SingleCellExperiment)
library(BiocParallel)
library(anndataR)

set.seed(123)

sce <- read_h5ad("${h5ad}")\$as_SingleCellExperiment()

# Extra arguments for scDblFinder from task.ext.args, written as R named
# arguments, e.g. dbr = 0.08, samples = "batch", clusters = TRUE
extra <- list(${args})

# A single string given as 'samples' is read as the name of a column in the
# cell metadata (obs), so the cells can be split by sample or capture
if (is.character(extra\$samples) && length(extra\$samples) == 1) {
batch_col <- extra\$samples
if (!(batch_col %in% colnames(colData(sce)))) {
stop(
"Column '", batch_col, "' is not in the cell metadata. Available columns: ",
paste(colnames(colData(sce)), collapse = ", ")
)
}
extra\$samples <- as.vector(colData(sce)[[batch_col]])
if (anyNA(extra\$samples)) {
stop("Column '", batch_col, "' contains NA values.")
}
}

workers <- max(1L, as.integer("${task.cpus}"))
res <- do.call(
scDblFinder,
c(
list(assay(sce, 1), BPPARAM = MulticoreParam(workers = workers, RNGseed = 123)),
extra
)
)

# Add the scDblFinder results to the original object so the other
# cell metadata is kept
cols <- grep("^scDblFinder", colnames(colData(res)), value = TRUE)
for (nm in cols) {
sce[[nm]] <- res[[nm]]
}

message("scDblFinder results:")
print(table(sce\$scDblFinder.class))

write_h5ad(sce, "${prefix}.h5ad", compression = "gzip")

write.csv(as.data.frame(colData(sce))[, cols, drop = FALSE], "${prefix}.scores.csv")

# One boolean column (TRUE = doublet), named after the prefix and indexed by cell
# barcode. This is the same layout the other doublet detection modules return, so
# the calls from several methods can be combined without any conversion.
calls <- data.frame(sce\$scDblFinder.class == "doublet", row.names = colnames(sce))
colnames(calls) <- "${prefix}"
write.csv(calls, "${prefix}.predictions.csv")

r.version <- strsplit(version[['version.string']], ' ')[[1]][3]
writeLines(
c(
'"${task.process}":',
paste(' r-base:', r.version),
paste(' scdblfinder:', as.character(packageVersion('scDblFinder'))),
paste(' anndatar:', as.character(packageVersion('anndataR'))),
paste(' singlecellexperiment:', as.character(packageVersion('SingleCellExperiment'))),
paste(' biocparallel:', as.character(packageVersion('BiocParallel'))),
paste(' rhdf5:', as.character(packageVersion('rhdf5')))
),
'versions.yml'
Comment thread
iraajgangavaram marked this conversation as resolved.
)
107 changes: 107 additions & 0 deletions modules/nf-core/scdblfinder/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
nextflow_process {

name "Test Process SCDBLFINDER"
script "../main.nf"
config "./nextflow.config"
process "SCDBLFINDER"

tag "modules"
tag "modules_nfcore"
tag "scdblfinder"

test("homo sapiens - pbmc1k - h5ad") {

when {
process {
"""
input[0] = [
[ id:'test' ],
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/scrnaseq/h5ad/pbmc1k.h5ad', checkIfExists: true)
]
"""
}
}

then {
assert process.success
def calls = new File(process.out.predictions[0][1].toString()).readLines()
assert calls.size() == 1001
assert calls[0] == '"","test_scdblfinder"'
assert calls.drop(1).every { line -> line.endsWith(",TRUE") || line.endsWith(",FALSE") }
def scores = new File(process.out.scores[0][1].toString()).readLines()
assert scores.size() == 1001
def adata = anndata(process.out.h5ad[0][1])
with(adata) {
assert "scDblFinder.class" in obs.colnames
assert "scDblFinder.score" in obs.colnames
}
assert snapshot(
sanitizeOutput(process.out, unstableKeys: ['h5ad', 'scores']),
scores.size(),
adata.yaml
).match()
Comment thread
iraajgangavaram marked this conversation as resolved.
Comment thread
iraajgangavaram marked this conversation as resolved.
}

}

test("homo sapiens - pbmc1k - h5ad - doublet rate and batch column") {

when {
params {
module_args = 'dbr = 0.08, samples = "batch"'
}
process {
"""
input[0] = [
[ id:'test' ],
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/scrnaseq/h5ad/pbmc1k.h5ad', checkIfExists: true)
]
"""
}
}

then {
assert process.success
def calls = new File(process.out.predictions[0][1].toString()).readLines()
assert calls.size() == 1001
assert calls[0] == '"","test_scdblfinder"'
assert calls.drop(1).every { line -> line.endsWith(",TRUE") || line.endsWith(",FALSE") }
def scores = new File(process.out.scores[0][1].toString()).readLines()
assert scores.size() == 1001
def adata = anndata(process.out.h5ad[0][1])
with(adata) {
assert "scDblFinder.class" in obs.colnames
assert "scDblFinder.score" in obs.colnames
}
assert snapshot(
sanitizeOutput(process.out, unstableKeys: ['h5ad', 'scores']),
scores.size(),
adata.yaml
).match()
}

}

test("homo sapiens - pbmc1k - h5ad - stub") {

options "-stub"

when {
process {
"""
input[0] = [
[ id:'test' ],
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/scrnaseq/h5ad/pbmc1k.h5ad', checkIfExists: true)
]
"""
}
}

then {
assert process.success
assert snapshot(sanitizeOutput(process.out)).match()
}

}

}
Loading
Loading