From 0dc6b7941239c95f1b7326ebb4e4d7ac8dbc004c Mon Sep 17 00:00:00 2001 From: Adam Taylor Date: Tue, 3 Feb 2026 16:14:16 +0000 Subject: [PATCH 1/8] fix(segmentation): wrap process invocations in conditionals for AWS Batch On AWS Batch, input validation occurs before ext.when can skip process execution. This caused "Path value cannot be null" errors when params.cellpose_model (default []) was passed to CELLPOSE even though ext.when would have skipped the process. Wrap each segmentation process (DEEPCELL_MESMER, CELLPOSE, MCCELLPOSE) in conditionals that check params.segmentation, ensuring processes are only invoked when actually needed. Fixes: nf-core/mcmicro#140 Co-Authored-By: Claude Opus 4.5 --- workflows/mcmicro.nf | 54 +++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/workflows/mcmicro.nf b/workflows/mcmicro.nf index 53cf4741..49f6a24b 100644 --- a/workflows/mcmicro.nf +++ b/workflows/mcmicro.nf @@ -126,34 +126,42 @@ workflow MCMICRO { } // Run Segmentation + // Each segmenter is conditionally invoked based on params.segmentation to avoid + // input validation errors on AWS Batch when the process would be skipped by ext.when ch_masks = channel.empty() - ch_segmentation_input - .multiMap{ meta, image -> - img: [meta + [segmenter: 'mesmer'], image] - membrane_img: [[:], []] - } - | DEEPCELL_MESMER - ch_masks = ch_masks.mix(DEEPCELL_MESMER.out.mask) - ch_versions = ch_versions.mix(DEEPCELL_MESMER.out.versions) + if (params.segmentation?.split(',')?.contains('mesmer')) { + ch_segmentation_input + .multiMap{ meta, image -> + img: [meta + [segmenter: 'mesmer'], image] + membrane_img: [[:], []] + } + | DEEPCELL_MESMER + ch_masks = ch_masks.mix(DEEPCELL_MESMER.out.mask) + ch_versions = ch_versions.mix(DEEPCELL_MESMER.out.versions) + } - ch_segmentation_input - .multiMap{ meta, image -> - image: [meta + [segmenter: 'cellpose'], image] - model: params.cellpose_model - } - | CELLPOSE - ch_masks = ch_masks.mix(CELLPOSE.out.mask) - ch_versions = ch_versions.mix(CELLPOSE.out.versions) + if (params.segmentation?.split(',')?.contains('cellpose')) { + ch_segmentation_input + .multiMap{ meta, image -> + image: [meta + [segmenter: 'cellpose'], image] + model: params.cellpose_model + } + | CELLPOSE + ch_masks = ch_masks.mix(CELLPOSE.out.mask) + ch_versions = ch_versions.mix(CELLPOSE.out.versions) + } - ch_segmentation_input - .multiMap{ meta, image -> - image: [meta + [segmenter: 'mccellpose'], image] - } - | MCCELLPOSE - ch_masks = ch_masks.mix(MCCELLPOSE.out.mask) - ch_versions = ch_versions.mix(MCCELLPOSE.out.versions) + if (params.segmentation?.split(',')?.contains('mccellpose')) { + ch_segmentation_input + .multiMap{ meta, image -> + image: [meta + [segmenter: 'mccellpose'], image] + } + | MCCELLPOSE + ch_masks = ch_masks.mix(MCCELLPOSE.out.mask) + ch_versions = ch_versions.mix(MCCELLPOSE.out.versions) + } // Run Quantification From 8f3c844686af57094bfb2f980aebb19e17aec4d3 Mon Sep 17 00:00:00 2001 From: Adam Taylor Date: Tue, 3 Feb 2026 18:09:52 +0000 Subject: [PATCH 2/8] fix(mccellpose): add pixel size argument for MCCELLPOSE process --- conf/modules.config | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/modules.config b/conf/modules.config index 05da6fea..b19d07af 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -82,6 +82,7 @@ process { } withName: "MCCELLPOSE" { + ext.args = { "--pixel-size=${meta.pixel_size}" } ext.when = {params.segmentation && params.segmentation.split(',').contains('mccellpose')} publishDir = [ path: { "${params.outdir}/segmentation/mccellpose" }, From 9a3e628816bd09cc129bedf17d12f2ebe2f84262 Mon Sep 17 00:00:00 2001 From: Adam Taylor Date: Tue, 3 Feb 2026 18:36:34 +0000 Subject: [PATCH 3/8] fix(cellpose): refactor channel handling for cellpose segmentation process --- workflows/mcmicro.nf | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/workflows/mcmicro.nf b/workflows/mcmicro.nf index 49f6a24b..6a4cb3b5 100644 --- a/workflows/mcmicro.nf +++ b/workflows/mcmicro.nf @@ -143,12 +143,14 @@ workflow MCMICRO { } if (params.segmentation?.split(',')?.contains('cellpose')) { - ch_segmentation_input - .multiMap{ meta, image -> - image: [meta + [segmenter: 'cellpose'], image] - model: params.cellpose_model - } - | CELLPOSE + ch_cellpose_image = ch_segmentation_input + .map{ meta, image -> [meta + [segmenter: 'cellpose'], image] } + + ch_cellpose_model = params.cellpose_model + ? Channel.fromPath(params.cellpose_model, checkIfExists: true) + : Channel.value([]) + + CELLPOSE(ch_cellpose_image, ch_cellpose_model) ch_masks = ch_masks.mix(CELLPOSE.out.mask) ch_versions = ch_versions.mix(CELLPOSE.out.versions) } From 1454694f5f646a49d9ab6f166da085a7f77d1eb6 Mon Sep 17 00:00:00 2001 From: Adam Taylor Date: Wed, 4 Feb 2026 09:17:35 +0000 Subject: [PATCH 4/8] fix(cellpose): update model input to allow optional model path --- modules/nf-core/cellpose/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/cellpose/main.nf b/modules/nf-core/cellpose/main.nf index 32a15762..4cc96afe 100644 --- a/modules/nf-core/cellpose/main.nf +++ b/modules/nf-core/cellpose/main.nf @@ -6,7 +6,7 @@ process CELLPOSE { input: tuple val(meta), path(image) - path(model) + path(model, arity: '0..1') output: tuple val(meta), path("*masks.tif") , emit: mask From 90b092b85ba106316affaafd7e6a4e9fb87f48c2 Mon Sep 17 00:00:00 2001 From: Adam Taylor Date: Wed, 4 Feb 2026 09:28:54 +0000 Subject: [PATCH 5/8] fix(cellpose): update model input to use stageAs for optional model path --- modules/nf-core/cellpose/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/cellpose/main.nf b/modules/nf-core/cellpose/main.nf index 4cc96afe..aa79314e 100644 --- a/modules/nf-core/cellpose/main.nf +++ b/modules/nf-core/cellpose/main.nf @@ -6,7 +6,7 @@ process CELLPOSE { input: tuple val(meta), path(image) - path(model, arity: '0..1') + path(model, stageAs: '?/*') output: tuple val(meta), path("*masks.tif") , emit: mask From a15c5a92b50d082fcb07dcfa34783e26c535c8b9 Mon Sep 17 00:00:00 2001 From: Adam Taylor Date: Wed, 4 Feb 2026 19:53:03 +0000 Subject: [PATCH 6/8] fix(cellpose, deepcell): add 'process_gpu' label to CELLPOSE and DEEPCELL_MESMER processes --- modules/nf-core/cellpose/main.nf | 1 + modules/nf-core/deepcell/mesmer/main.nf | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/nf-core/cellpose/main.nf b/modules/nf-core/cellpose/main.nf index aa79314e..15d0fc2a 100644 --- a/modules/nf-core/cellpose/main.nf +++ b/modules/nf-core/cellpose/main.nf @@ -1,6 +1,7 @@ process CELLPOSE { tag "$meta.id" label 'process_medium' + label 'process_gpu' container "docker.io/biocontainers/cellpose:3.0.1_cv1" diff --git a/modules/nf-core/deepcell/mesmer/main.nf b/modules/nf-core/deepcell/mesmer/main.nf index ae44c2f7..cfb222bf 100644 --- a/modules/nf-core/deepcell/mesmer/main.nf +++ b/modules/nf-core/deepcell/mesmer/main.nf @@ -1,6 +1,7 @@ process DEEPCELL_MESMER { tag "$meta.id" label 'process_low' + label 'process_gpu' container "nf-core/deepcell_mesmer:0.4.1_noentry" From 760ff66831aa77fc9e4f5123a9be2e201ea17d6f Mon Sep 17 00:00:00 2001 From: Adam Taylor Date: Thu, 5 Feb 2026 10:35:44 +0000 Subject: [PATCH 7/8] fix(cellpose): add 'channel_axis' argument to CELLPOSE process --- conf/modules.config | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/modules.config b/conf/modules.config index b19d07af..3a8ebb3d 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -62,6 +62,7 @@ process { } withName: "CELLPOSE" { + ext.args = {"channel_axis=0"} ext.when = {params.segmentation && params.segmentation.split(',').contains('cellpose')} publishDir = [ path: { "${params.outdir}/segmentation/cellpose" }, From 876427a3c08839916c5eb7bf0d3fac7e1acae294 Mon Sep 17 00:00:00 2001 From: Adam Taylor Date: Thu, 5 Feb 2026 15:40:30 +0000 Subject: [PATCH 8/8] fix(cellpose): update CELLPOSE arguments to use '--channel_axis' format --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 3a8ebb3d..e1131714 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -62,7 +62,7 @@ process { } withName: "CELLPOSE" { - ext.args = {"channel_axis=0"} + ext.args = {"--channel_axis 0"} ext.when = {params.segmentation && params.segmentation.split(',').contains('cellpose')} publishDir = [ path: { "${params.outdir}/segmentation/cellpose" },