Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7bba891
feat(cellpose): update to v4.0.8 with GPU support and public container
an-altosian Mar 2, 2026
1af93f5
fix: address CI lint failures for cellpose module
an-altosian Mar 2, 2026
ad58f11
fix: remove quay.io prefix from container URI
an-altosian Mar 2, 2026
7b1da7e
fix: update nf-test snapshots for cellpose 4.0.8
an-altosian Mar 2, 2026
20380ed
docs: improve cellpose module documentation
an-altosian Mar 2, 2026
671e750
fix: revert model input to path type for proper file staging
an-altosian Mar 3, 2026
818d767
feat: support both pretrained model names and custom model files
an-altosian Mar 3, 2026
b0894c1
refactor: replace NO_FILE sentinel with [] for optional model path
an-altosian Mar 3, 2026
ac65986
refactor: merge docker_self_hosted into docker profile
an-altosian Mar 3, 2026
5325355
Merge branch 'master' into feat/cellpose-v4-gpu
DongzeHE Mar 3, 2026
82549cc
Revert "refactor: merge docker_self_hosted into docker profile"
an-altosian Mar 3, 2026
7c6592b
refactor: simplify cellpose model input and fix version parsing for v4
an-altosian Mar 4, 2026
311b28d
Merge branch 'master' into feat/cellpose-v4-gpu
DongzeHE Mar 4, 2026
6d4b3ad
fix(cellpose): fix meta.yml input mismatch and switch to topic versions
an-altosian Mar 4, 2026
3b35ee5
fix(cellpose): add versions snapshot entry for lint compliance
an-altosian Mar 4, 2026
c4024b4
fix(cellpose): regenerate snapshots via nf-test
an-altosian Mar 4, 2026
d1f972f
fix(cellpose): regenerate snapshots with cellpose on PATH
an-altosian Mar 4, 2026
fc4912b
feat(cellpose): add conda support via environment.yml
an-altosian Mar 4, 2026
3eb0f4e
fix(cellpose): address PR review - fix version capture and add python…
an-altosian Mar 4, 2026
e79fbb4
Merge branch 'master' into feat/cellpose-v4-gpu
an-altosian Mar 4, 2026
7ca329d
feat(cellpose): switch to Seqera Containers GPU image
an-altosian Mar 4, 2026
b661552
docs(cellpose): update notes to reflect Seqera Containers with CUDA 12.8
an-altosian Mar 4, 2026
902d963
docs(cellpose): add @dongzehe to authors
an-altosian Mar 4, 2026
08bbeaf
fix: update cellpose snapshot with docker container Python version
an-altosian Mar 4, 2026
3743717
fix: add singularity URI for cellpose container
an-altosian Mar 4, 2026
6e3b096
Merge branch 'master' into feat/cellpose-v4-gpu
DongzeHE Mar 4, 2026
c1652d9
refactor: use pip show for version capture in cellpose
an-altosian Mar 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
9 changes: 9 additions & 0 deletions modules/nf-core/cellpose/environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json
channels:
- conda-forge
- bioconda
dependencies:
- conda-forge::python=3.12
- pip:
- cellpose==4.0.8
67 changes: 37 additions & 30 deletions modules/nf-core/cellpose/main.nf
Original file line number Diff line number Diff line change
@@ -1,56 +1,63 @@
process CELLPOSE {
tag "$meta.id"
label 'process_medium'
tag "${meta.id}"
label 'process_high'
label 'process_gpu'

container "docker.io/biocontainers/cellpose:3.1.0_cv1"
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/07/073531bf01cb425d0a869533c8751ac974c9f10b1e72c815efebdb893aa979d5/data' :
'community.wave.seqera.io/library/python_pip_cellpose:4be22f3ec4963ebe' }"

input:
tuple val(meta), path(image)
path(model)

output:
tuple val(meta), path("*masks.tif") , emit: mask
tuple val(meta), path("*flows.tif") , emit: flows, optional: true
path "versions.yml" , emit: versions
tuple val(meta), path("${prefix}/*masks.tif"), emit: mask
tuple val(meta), path("${prefix}/*flows.tif"), emit: flows, optional: true
tuple val(meta), path("${prefix}/*seg.npy"), emit: cells, optional: true
tuple val("${task.process}"), val('cellpose'), eval("pip show cellpose | grep '^Version:' | sed 's/Version: //'"), topic: versions, emit: versions_cellpose
tuple val("${task.process}"), val('python'), eval("python --version | sed 's/Python //'"), topic: versions, emit: versions_python
tuple val("${task.process}"), val('torch'), eval("pip show torch | grep '^Version:' | sed 's/Version: //'"), topic: versions, emit: versions_torch

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

script:
// Exit if running this module with -profile conda / -profile mamba
if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) {
error "I did not manage to create a cellpose module in Conda that works in all OSes. Please use Docker / Singularity / Podman instead."
}
def args = task.ext.args ?: ''
def model_command = model ? "--pretrained_model $model" : ""
def model_command = model ? "--pretrained_model ${model}" : ""
def gpu_flag = task.ext.use_gpu ? "--use_gpu" : ""
prefix = task.ext.prefix ?: "${meta.id}"
"""
export OMP_NUM_THREADS=${task.cpus}
export MKL_NUM_THREADS=${task.cpus}
# Container runs as root with HOME=/ which is not writable
export HOME=\$PWD
export MPLCONFIGDIR=\$PWD/.matplotlib
export CELLPOSE_LOCAL_MODELS_PATH=\$PWD/.cellpose
mkdir -p \$MPLCONFIGDIR \$CELLPOSE_LOCAL_MODELS_PATH

cellpose \\
--image_path $image \\
--image_path ${image} \\
--save_tif \\
$model_command \\
$args

cat <<-END_VERSIONS > versions.yml
"${task.process}":
cellpose: \$(cellpose --version | awk 'NR==2 {print \$3}')
END_VERSIONS
--verbose \\
${gpu_flag} \\
${model_command} \\
${args}

mkdir -p ${prefix}
mv *masks.tif ${prefix}/
mv *flows.tif ${prefix}/ 2>/dev/null || true
mv *seg.npy ${prefix}/ 2>/dev/null || true
"""

stub:
// Exit if running this module with -profile conda / -profile mamba
if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) {
error "I did not manage to create a cellpose module in Conda that works in all OSes. Please use Docker / Singularity / Podman instead."
}
def name = image.name
def base = name.lastIndexOf('.') != -1 ? name[0..name.lastIndexOf('.') - 1] : name
"""
touch ${base}_cp_masks.tif
prefix = task.ext.prefix ?: "${meta.id}"

cat <<-END_VERSIONS > versions.yml
"${task.process}":
cellpose: \$(cellpose --version | awk 'NR==2 {print \$3}')
END_VERSIONS
"""

mkdir -p ${prefix}
touch ${prefix}/${base}_cp_masks.tif
"""
}
116 changes: 102 additions & 14 deletions modules/nf-core/cellpose/meta.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: "cellpose"
description: cellpose segments cells in images
description: cellpose segments cells in images using GPU-accelerated deep learning
keywords:
- segmentation
- image
- cellpose
- gpu
- spatial-transcriptomics
tools:
- "cellpose":
description: "cellpose is an anatomical segmentation algorithm written in Python
Expand All @@ -22,13 +24,16 @@ input:
(sample id)
- image:
type: file
description: tif file for ready for segmentation
description: tif file ready for segmentation
pattern: "*.{tif,tiff}"
ontologies: []
- model:
type: file
description: Optional input file. Cellpose 2 model trained by user using human-in-the-loop
approach.
description: |
Optional custom cellpose model file. When provided, passed as
--pretrained_model to cellpose. Pass [] (empty list) to use the
default model (cpsam in cellpose 4).
pattern: "*"
ontologies: []
output:
mask:
Expand All @@ -37,32 +42,115 @@ output:
description: |
Groovy Map containing sample information
[sample id]
- "*masks.tif":
- "${prefix}/*masks.tif":
type: file
description: labelled mask output from cellpose in tif format
pattern: "*.{tif, tiff}"
pattern: "${prefix}/*masks.tif"
ontologies: []
flows:
- - meta:
type: map
description: |
Groovy Map containing sample information
[sample id]
- "*flows.tif":
- "${prefix}/*flows.tif":
type: file
description: cell flow output from cellpose
pattern: "*.{tif}"
pattern: "${prefix}/*flows.tif"
ontologies: []
cells:
- - meta:
type: map
description: |
Groovy Map containing sample information
[sample id]
- "${prefix}/*seg.npy":
type: file
description: numpy array with cell segmentation data
pattern: "${prefix}/*seg.npy"
ontologies: []
versions_cellpose:
- - ${task.process}:
type: string
description: The name of the process
- cellpose:
type: string
description: The name of the tool
- "pip show cellpose | grep '^Version:' | sed 's/Version: //'":
type: eval
description: The expression to obtain the version of the tool
versions_python:
- - ${task.process}:
type: string
description: The name of the process
- python:
type: string
description: The name of the tool
- "python --version | sed 's/Python //'":
type: eval
description: The expression to obtain the version of the tool
versions_torch:
- - ${task.process}:
type: string
description: The name of the process
- torch:
type: string
description: The name of the tool
- "pip show torch | grep '^Version:' | sed 's/Version: //'":
type: eval
description: The expression to obtain the version of the tool
topics:
versions:
- versions.yml:
type: file
description: File containing software versions
pattern: "versions.yml"
ontologies:
- edam: http://edamontology.org/format_3750 # YAML
- - ${task.process}:
type: string
description: The name of the process
- cellpose:
type: string
description: The name of the tool
- "pip show cellpose | grep '^Version:' | sed 's/Version: //'":
type: eval
description: The expression to obtain the version of the tool
- - ${task.process}:
type: string
description: The name of the process
- python:
type: string
description: The name of the tool
- "python --version | sed 's/Python //'":
type: eval
description: The expression to obtain the version of the tool
- - ${task.process}:
type: string
description: The name of the process
- torch:
type: string
description: The name of the tool
- "pip show torch | grep '^Version:' | sed 's/Version: //'":
type: eval
description: The expression to obtain the version of the tool
notes: |
GPU support: Set `task.ext.use_gpu = true` to pass `--use_gpu` to cellpose.
The container (built via Seqera Containers) includes PyTorch 2.10.0 with CUDA 12.8
and falls back to CPU automatically when no GPU is available. Use the `process_gpu`
label to request GPU resources from your executor. When running with conda/mamba,
GPU support depends on having a CUDA-enabled PyTorch installation in your environment.

Model selection via the model input channel:
- Custom model file: file("/path/to/model")
- Default (cpsam): []

Additional cellpose CLI arguments can be passed via `task.ext.args`:
ext.args = '--diameter 30 --flow_threshold 0.4 --cellprob_threshold 0'

Deprecated in cellpose 4.0.1+: `--chan`, `--chan2`, `--invert`, `--all_channels`,
`--diam_mean`, `--pretrained_model_ortho`. Do not pass these via ext.args.

Model weights are not bundled in the container. Cellpose downloads them on first
use to `$CELLPOSE_LOCAL_MODELS_PATH` (set to the work directory).
authors:
- "@josenimo"
- "@FloWuenne"
- "@dongzehe"
maintainers:
- "@josenimo"
- "@FloWuenne"
Expand Down
2 changes: 1 addition & 1 deletion modules/nf-core/cellpose/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ nextflow_process {
{ assert process.success },
{ assert snapshot(process.out.mask).match("mask") },
{ assert snapshot(process.out.flows).match("flows") },
{ assert snapshot(process.out.versions).match("versions") }
{ assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match("versions") }
)
}

Expand Down
Loading