Skip to content

Commit 3c81fd4

Browse files
CaroAMNmashehu
andauthored
new module numorph-3dunet (#12130)
Co-authored-by: Matthias Hörtenhuber <mashehu@users.noreply.github.com>
1 parent 45c3553 commit 3c81fd4

7 files changed

Lines changed: 320 additions & 0 deletions

File tree

.github/skip_nf_test.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"conda": [
3+
"modules/nf-core/numorph/3dunet",
34
"modules/nf-core/numorph/intensity",
45
"modules/nf-core/numorph/resample",
56
"modules/nf-core/mat2json",
@@ -128,6 +129,7 @@
128129
"subworkflows/nf-core/deepvariant/tests/equality"
129130
],
130131
"singularity": [
132+
"modules/nf-core/numorph/3dunet",
131133
"modules/nf-core/bases2fastq",
132134
"modules/nf-core/deepsomatic",
133135
"modules/nf-core/deepvariant/rundeepvariant",
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
## optimized nvidia base container for older python and tensorflow
2+
FROM nvcr.io/nvidia/tensorflow:20.10-tf1-py3
3+
4+
ARG NUMORPH_3DUNET_VERSION="1.0.9"
5+
6+
LABEL org.opencontainers.image.authors=="Carolin Schwitalla <carolin.schwitalla@uni-tuebingen.de>"
7+
LABEL org.opencontainers.image.description="Docker image for the NuMorph 3D-UNet to perform nuclei quantification on light-sheet microscopy data"
8+
LABEL org.opencontainers.image.licenses="MIT"
9+
LABEL org.opencontainers.image.version="$NUMORPH_3DUNET_VERSION"
10+
11+
12+
13+
RUN apt-get update && apt-get install -y --no-install-recommends \
14+
git \
15+
libgl1-mesa-glx \
16+
libglib2.0-0 \
17+
libsm6 \
18+
libxext6 \
19+
libxrender-dev \
20+
&& rm -rf /var/lib/apt/lists/*
21+
22+
23+
RUN pip install --upgrade pip
24+
25+
# the tool needs this
26+
RUN pip install git+https://github.com/keras-team/keras-contrib.git
27+
28+
# Install the package
29+
RUN pip install numorph-3dunet==$NUMORPH_3DUNET_VERSION
30+
31+
# Create directory for models
32+
RUN mkdir -p /models
33+
34+
CMD ["/bin/bash"]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Updating the docker container and making a new module release
2+
3+
To update this tool :
4+
2. Edit the Dockerfile in the following lines:
5+
6+
```diff
7+
- ARG NUMORPH_PREPROCESSING_VERSION="1.0.0"
8+
+ ARG NUMORPH_PREPROCESSING_VERSION="<New version>"
9+
```
10+
11+
3. Open a PR against [nf-core/modules](https://github.com/nf-core/modules) directly, push the changes, and the Dockerfile should be built and uploaded to `quay.io/nf-core/numorph-3dunet`!
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
process NUMORPH_3DUNET {
2+
tag "$meta.id"
3+
label 'process_gpu'
4+
5+
container "quay.io/nf-core/numorph-3dunet:1.0.9"
6+
7+
input:
8+
tuple val(meta), path(img_directory), path(parameter_file)
9+
path(model_file)
10+
11+
output:
12+
tuple val(meta), path("${prefix}/") , emit: cellcounts
13+
14+
tuple val("${task.process}"), val('numorph_3dunet'), eval('numorph_3dunet --version'), emit: versions_numorph_3dunet, topic: versions
15+
16+
when:
17+
task.ext.when == null || task.ext.when
18+
19+
script:
20+
def args = task.ext.args ?: ''
21+
prefix = task.ext.prefix ?: "${meta.id}"
22+
23+
"""
24+
echo "Checking GPU access:"
25+
nvidia-smi
26+
mkdir -p ${prefix}
27+
img_dir=\$(readlink -f ${img_directory})
28+
29+
30+
31+
numorph_3dunet \\
32+
-i \$img_dir \\
33+
-o ${prefix} \\
34+
--model_file ${model_file} \\
35+
--sample_id ${prefix} \\
36+
$args
37+
38+
"""
39+
40+
stub:
41+
def args = task.ext.args ?: ''
42+
prefix = task.ext.prefix ?: "${meta.id}"
43+
44+
"""
45+
mkdir -p ${prefix}
46+
touch ${prefix}/${prefix}.csv
47+
touch ${prefix}/${prefix}_counts.csv
48+
49+
"""
50+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: "numorph_3dunet"
2+
description: "3DUnet for cell nuclei quantification on 3D microscopy images of the
3+
numorph toolkit."
4+
keywords:
5+
- segmentation
6+
- cell nuclei
7+
- light-sheet microscopy
8+
- numorph
9+
tools:
10+
- "numorph_3dunet":
11+
description: "This package contains the original 3DUnet for cell nuclei quantification
12+
on 3D microscopy images of the numorph toolkit."
13+
homepage: "https://github.com/qbic-pipelines/numorph_3dunet"
14+
documentation: "https://github.com/qbic-pipelines/numorph_3dunet"
15+
tool_dev_url: "https://github.com/qbic-pipelines/numorph_3dunet"
16+
licence:
17+
- "MIT"
18+
identifier: ""
19+
input:
20+
- - meta:
21+
type: map
22+
description: |
23+
Groovy Map containing sample information
24+
e.g. `[ id:'sample1' ]`
25+
- img_directory:
26+
type: directory
27+
description: Directory containing stitched image files
28+
pattern: "*.{tif,tiff}"
29+
ontologies:
30+
- edam: "http://edamontology.org/format_3591"
31+
- edam: "http://edamontology.org/format_3727"
32+
- parameter_file:
33+
type: file
34+
description: File containing parameters for numorph tools
35+
pattern: "*.{csv}"
36+
ontologies:
37+
- edam: "http://edamontology.org/format_3752"
38+
- model_file:
39+
type: file
40+
description: File containing the trained model
41+
pattern: "*.{h5}"
42+
ontologies:
43+
- edam: "http://edamontology.org/format_3590"
44+
output:
45+
cellcounts:
46+
- - meta:
47+
type: map
48+
description: |
49+
Groovy Map containing sample information
50+
e.g. `[ id:'sample1' ]`
51+
- ${prefix}/:
52+
type: directory
53+
description: Directory containing cell count results
54+
pattern: "${meta.id}/"
55+
56+
versions_numorph_3dunet:
57+
- - ${task.process}:
58+
type: string
59+
description: The name of the process
60+
- numorph_3dunet:
61+
type: string
62+
description: The name of the tool
63+
- "numorph_3dunet --version":
64+
type: eval
65+
description: The expression to obtain the version of the tool
66+
topics:
67+
versions:
68+
- - "${task.process}":
69+
type: string
70+
description: The name of the process
71+
- "numorph_3dunet":
72+
type: string
73+
description: The name of the tool
74+
- "numorph_3dunet --version":
75+
type: eval
76+
description: The expression to obtain the version of the tool
77+
authors:
78+
- "@CaroAMN"
79+
maintainers:
80+
- "@CaroAMN"
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// nf-core modules test numorph/3dunet
2+
nextflow_process {
3+
4+
name "Test Process NUMORPH_3DUNET"
5+
script "../main.nf"
6+
process "NUMORPH_3DUNET"
7+
8+
tag "modules"
9+
tag "modules_nfcore"
10+
tag "numorph"
11+
tag "numorph/3dunet"
12+
tag "unzip"
13+
tag "gpu"
14+
15+
test("numorph-3DUnet test - tif") {
16+
17+
setup {
18+
run ("UNZIP") {
19+
script "../../../unzip/main.nf"
20+
process {
21+
"""
22+
input[0] = Channel.fromList([
23+
tuple([ id:'TEST1'],
24+
file('https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/lsmquant/test_data/unet_test_images.zip'))
25+
])
26+
"""
27+
}
28+
}
29+
}
30+
31+
when {
32+
params {
33+
outdir = "$outputDir"
34+
}
35+
process {
36+
"""
37+
input[0] = UNZIP.out.unzipped_archive.map { meta, unzipped_archive ->
38+
def image_dir = file(unzipped_archive).listFiles().find { it.isDirectory() }
39+
tuple(
40+
meta,
41+
image_dir ?: unzipped_archive,
42+
file('https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/lsmquant/test_data/parameterfiles/params_TEST1_lsmquant.csv'))
43+
}
44+
input[1] = file('https://zenodo.org/records/16893708/files/075_121_model.h5')
45+
"""
46+
}
47+
}
48+
49+
then {
50+
def cellcounDir = process.out.cellcounts.get(0).get(1)
51+
def cellcountFiles = getAllFilesFromDir(cellcounDir, relative: true, includeDir: false)
52+
assertAll(
53+
{assert process.success },
54+
{assert cellcountFiles.size() == 2 },
55+
{ assert snapshot(
56+
cellcountFiles,
57+
process.out.findAll { key, val -> key.startsWith('versions') }
58+
).match() }
59+
)
60+
}
61+
62+
}
63+
64+
test("numorph-3DUnet stub test - tif") {
65+
66+
options '-stub'
67+
68+
when {
69+
process {
70+
"""
71+
input[0] = Channel.fromList([
72+
tuple([ id:'TEST1'],
73+
file('https://zenodo.org/records/14916478/files/ctip2_topro.zip'),
74+
file('https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/lsmquant/test_data/parameterfiles/params_TEST1_lsmquant.csv'))
75+
])
76+
input[1] = file('https://zenodo.org/records/16893708/files/075_121_model.h5')
77+
"""
78+
}
79+
}
80+
81+
then {
82+
assertAll(
83+
{ assert process.success },
84+
{ assert snapshot(sanitizeOutput(process.out)).match() }
85+
)
86+
}
87+
88+
}
89+
90+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"numorph-3DUnet test - tif": {
3+
"content": [
4+
[
5+
"TEST1.csv",
6+
"TEST1_counts.csv"
7+
],
8+
{
9+
"versions_numorph_3dunet": [
10+
[
11+
"NUMORPH_3DUNET",
12+
"numorph_3dunet",
13+
"1.0.9"
14+
]
15+
]
16+
}
17+
],
18+
"timestamp": "2026-06-23T14:16:39.850891617",
19+
"meta": {
20+
"nf-test": "0.9.4",
21+
"nextflow": "25.10.4"
22+
}
23+
},
24+
"numorph-3DUnet stub test - tif": {
25+
"content": [
26+
{
27+
"cellcounts": [
28+
[
29+
{
30+
"id": "TEST1"
31+
},
32+
[
33+
"TEST1.csv:md5,d41d8cd98f00b204e9800998ecf8427e",
34+
"TEST1_counts.csv:md5,d41d8cd98f00b204e9800998ecf8427e"
35+
]
36+
]
37+
],
38+
"versions_numorph_3dunet": [
39+
[
40+
"NUMORPH_3DUNET",
41+
"numorph_3dunet",
42+
"1.0.9"
43+
]
44+
]
45+
}
46+
],
47+
"timestamp": "2026-06-26T13:59:27.663751068",
48+
"meta": {
49+
"nf-test": "0.9.4",
50+
"nextflow": "25.10.4"
51+
}
52+
}
53+
}

0 commit comments

Comments
 (0)