diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 43669112..a8b797b3 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -15,18 +15,3 @@ export_plots: true disable_version_detection: true log_filesize_limit: 5000000000 # 5GB - -sp: - xenium/cell_feature_matrix: - fn: "*/cell_feature_matrix.h5" - xenium/cells: - fn: "*/cells.parquet" - xenium/experiment: - fn: "*/experiment.xenium" - num_lines: 50 - xenium/metrics: - contents: num_cells_detected - fn: "*/metrics_summary.csv" - num_lines: 5 - xenium/transcripts: - fn: "*/transcripts.parquet" diff --git a/conf/base.config b/conf/base.config index 457610f2..e0cec69f 100644 --- a/conf/base.config +++ b/conf/base.config @@ -11,9 +11,9 @@ process { // nf-core: Check the defaults for all processes - cpus = { 1 * task.attempt } - memory = { 6.GB * task.attempt } - time = { 4.h * task.attempt } + cpus = { 1 * task.attempt } + memory = { 6.GB * task.attempt } + time = { 4.h * task.attempt } errorStrategy = { task.exitStatus in ((130..145) + 104 + 175) ? 'retry' : 'finish' } maxRetries = 1 @@ -26,36 +26,36 @@ process { // adding in your local modules too. // nf-core: Customise requirements for specific processes. // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors - withLabel:process_single { - cpus = { 1 } + withLabel: process_single { + cpus = { 1 } memory = { 6.GB * task.attempt } - time = { 4.h * task.attempt } + time = { 4.h * task.attempt } } - withLabel:process_low { - cpus = { 2 * task.attempt } + withLabel: process_low { + cpus = { 2 * task.attempt } memory = { 12.GB * task.attempt } - time = { 4.h * task.attempt } + time = { 4.h * task.attempt } } - withLabel:process_medium { - cpus = { 6 * task.attempt } + withLabel: process_medium { + cpus = { 6 * task.attempt } memory = { 36.GB * task.attempt } - time = { 8.h * task.attempt } + time = { 8.h * task.attempt } } - withLabel:process_high { - cpus = { 12 * task.attempt } + withLabel: process_high { + cpus = { 12 * task.attempt } memory = { 72.GB * task.attempt } - time = { 16.h * task.attempt } + time = { 16.h * task.attempt } } - withLabel:process_long { - time = { 20.h * task.attempt } + withLabel: process_long { + time = { 20.h * task.attempt } } - withLabel:process_high_memory { + withLabel: process_high_memory { memory = { 200.GB * task.attempt } } - withLabel:error_ignore { + withLabel: error_ignore { errorStrategy = 'ignore' } - withLabel:error_retry { + withLabel: error_retry { errorStrategy = 'retry' maxRetries = 2 } diff --git a/conf/modules.config b/conf/modules.config index 42875673..713de69f 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -15,38 +15,36 @@ process { publishDir = [ path: { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + saveAs: { filename -> filename.equals('versions.yml') ? null : filename }, ] - withName: 'MULTIQC' { - ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } + withName: MULTIQC { + ext.args = { params.multiqc_title ? "--title \"${params.multiqc_title}\"" : '' } publishDir = [ path: { "${params.outdir}/multiqc" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + saveAs: { filename -> filename.equals('versions.yml') ? null : filename }, ] } withName: XENIUMRANGER_RESEGMENT { publishDir = [ path: "${params.outdir}/xeniumranger/resegment", - mode: params.publish_dir_mode + mode: params.publish_dir_mode, ] - ext.prefix = {"${meta.id}"} } withName: XENIUMRANGER_IMPORT_SEGMENTATION { publishDir = [ path: "${params.outdir}/xeniumranger/import_segementation", - mode: params.publish_dir_mode + mode: params.publish_dir_mode, ] - ext.prefix = {"${meta.id}"} } withName: FICTURE_PREPROCESS { publishDir = [ path: "${params.outdir}/ficture/preprocess", - mode: params.publish_dir_mode + mode: params.publish_dir_mode, ] } @@ -90,7 +88,7 @@ process { path: { "${params.outdir}/segger/train" }, mode: params.publish_dir_mode, ] - ext.args = { "--init_emb 8 --hidden_channels 32 --num_tx_tokens 500 --out_channels 8 --heads 2 --num_mid_layers 2 --strategy auto --precision 16-mixed" } + ext.args = { "--init_emb 8 --hidden_channels 32 --num_tx_tokens 500 --out_channels 8 --heads 2 --num_mid_layers 2 --strategy auto --precision 16-mixed" } } withName: SEGGER_PREDICT { @@ -133,7 +131,7 @@ process { path: { "${params.outdir}/cellpose" }, mode: params.publish_dir_mode, ] - ext.args = { "--diameter 9 --channel_axis 0 --save_flows" } + ext.args = { "--diameter 9 --channel_axis 0 --save_flows" } } // with new version of cellpose you can do --output_name cell_masks @@ -142,7 +140,7 @@ process { path: { "${params.outdir}/cellpose_cells" }, mode: params.publish_dir_mode, ] - ext.args = { "--diameter 9 --channel_axis 0 --save_flows" } + ext.args = { "--diameter 9 --channel_axis 0 --save_flows" } } // with new version of cellpose you can do --output_name nucleus_masks @@ -151,7 +149,7 @@ process { path: { "${params.outdir}/cellpose_nuclei" }, mode: params.publish_dir_mode, ] - ext.args = { "--diameter 9 --channel_axis 0 --save_flows" } + ext.args = { "--diameter 9 --channel_axis 0 --save_flows" } } withName: OPT_FLIP { diff --git a/conf/test_full.config b/conf/test_full.config index df7c6f84..9e0980c4 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -17,5 +17,5 @@ params { // Input data input = "${projectDir}/assets/samplesheet.csv" outdir = 'results' - mode = 'image' + mode = 'coordinate' } diff --git a/modules/local/baysor/create_dataset/main.nf b/modules/local/baysor/create_dataset/main.nf index c3daf0e0..91b585df 100644 --- a/modules/local/baysor/create_dataset/main.nf +++ b/modules/local/baysor/create_dataset/main.nf @@ -1,16 +1,16 @@ process BAYSOR_CREATE_DATASET { - tag "$meta.id" + tag "${meta.id}" label 'process_medium' container "khersameesh24/baysor:0.7.1" input: tuple val(meta), path(transcripts) - val(sample_fraction) + val sample_fraction output: tuple val(meta), path("${prefix}/sampled_transcripts.csv"), emit: sampled_transcripts - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -18,17 +18,17 @@ process BAYSOR_CREATE_DATASET { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "BAYSOR_CREATE_DATASET module does not support Conda. Please use Docker / Singularity / Podman instead." + error("BAYSOR_CREATE_DATASET module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" - template 'create_dataset.py' + template('create_dataset.py') stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "BAYSOR_CREATE_DATASET module does not support Conda. Please use Docker / Singularity / Podman instead." + error("BAYSOR_CREATE_DATASET module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/local/baysor/preprocess/main.nf b/modules/local/baysor/preprocess/main.nf index aaf9d378..5547c882 100644 --- a/modules/local/baysor/preprocess/main.nf +++ b/modules/local/baysor/preprocess/main.nf @@ -1,21 +1,20 @@ process BAYSOR_PREPROCESS_TRANSCRIPTS { - tag "$meta.id" + tag "${meta.id}" label 'process_low' container "ghcr.io/scverse/spatialdata:spatialdata0.3.0_spatialdata-io0.1.7_spatialdata-plot0.2.9" input: tuple val(meta), path(transcripts) - val(min_qv) - val(max_x) - val(min_x) - val(max_y) - val(min_y) + val min_qv + val max_x + val min_x + val max_y + val min_y output: - tuple val(meta), - path("${prefix}/filtered_transcripts.parquet"), emit: transcripts_parquet - path("versions.yml") , emit: versions + tuple val(meta), path("${prefix}/filtered_transcripts.parquet"), emit: transcripts_parquet + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -23,17 +22,17 @@ process BAYSOR_PREPROCESS_TRANSCRIPTS { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "BAYSOR_PREPROCESS_TRANSCRIPTS module does not support Conda. Please use Docker / Singularity / Podman instead." + error("BAYSOR_PREPROCESS_TRANSCRIPTS module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" - template 'preprocess_transcripts.py' + template('preprocess_transcripts.py') stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "BAYSOR_PREPROCESS_TRANSCRIPTS module does not support Conda. Please use Docker / Singularity / Podman instead." + error("BAYSOR_PREPROCESS_TRANSCRIPTS module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/local/baysor/preview/main.nf b/modules/local/baysor/preview/main.nf index 3b7582aa..0d80a895 100644 --- a/modules/local/baysor/preview/main.nf +++ b/modules/local/baysor/preview/main.nf @@ -1,16 +1,16 @@ process BAYSOR_PREVIEW { - tag "$meta.id" + tag "${meta.id}" label 'process_high' container "khersameesh24/baysor:0.7.1" input: tuple val(meta), path(transcripts) - path(config) + path config output: tuple val(meta), path("${prefix}/preview.html"), emit: preview_html - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -18,7 +18,7 @@ process BAYSOR_PREVIEW { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "BAYSOR_PREVIEW module does not support Conda. Please use Docker / Singularity / Podman instead." + error("BAYSOR_PREVIEW module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' @@ -43,7 +43,7 @@ process BAYSOR_PREVIEW { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "BAYSOR_PREVIEW module does not support Conda. Please use Docker / Singularity / Podman instead." + error("BAYSOR_PREVIEW module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/local/baysor/run/main.nf b/modules/local/baysor/run/main.nf index 94c8adf3..13572dee 100644 --- a/modules/local/baysor/run/main.nf +++ b/modules/local/baysor/run/main.nf @@ -1,21 +1,15 @@ process BAYSOR_RUN { - tag "$meta.id" + tag "${meta.id}" label 'process_high' container "khersameesh24/baysor:0.7.1" input: - tuple val(meta), - path(transcripts), - path(prior_segmentation), - path(config), - val(scale) + tuple val(meta), path(transcripts), path(prior_segmentation), path(config), val(scale) output: - tuple val(meta), - path("${prefix}/segmentation.csv"), - path("${prefix}/segmentation_polygons_2d.json"), emit: segmentation - path("versions.yml") , emit: versions + tuple val(meta), path("${prefix}/segmentation.csv"), path("${prefix}/segmentation_polygons_2d.json"), emit: segmentation + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -23,12 +17,12 @@ process BAYSOR_RUN { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "BAYSOR_RUN module does not support Conda. Please use Docker / Singularity / Podman instead." + error("BAYSOR_RUN module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' def prior_seg = "${prior_segmentation}" ? "${prior_segmentation}" : "" - def scaling_factor = scale ? "--scale=${scale}": "" + def scaling_factor = scale ? "--scale=${scale}" : "" prefix = task.ext.prefix ?: "${meta.id}" """ @@ -53,7 +47,7 @@ process BAYSOR_RUN { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "BAYSOR_RUN module does not support Conda. Please use Docker / Singularity / Podman instead." + error("BAYSOR_RUN module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/local/baysor/segfree/main.nf b/modules/local/baysor/segfree/main.nf index 62d4554e..739547a5 100644 --- a/modules/local/baysor/segfree/main.nf +++ b/modules/local/baysor/segfree/main.nf @@ -1,16 +1,16 @@ process BAYSOR_SEGFREE { - tag "$meta.id" + tag "${meta.id}" label 'process_high' container "khersameesh24/baysor:0.7.1" input: tuple val(meta), path(transcripts) - path(config) + path config output: tuple val(meta), path("${prefix}/ncvs.loom"), emit: ncvs - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -18,7 +18,7 @@ process BAYSOR_SEGFREE { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "BAYSOR_SEGFREE module does not support Conda. Please use Docker / Singularity / Podman instead." + error("BAYSOR_SEGFREE module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' @@ -42,7 +42,7 @@ process BAYSOR_SEGFREE { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "BAYSOR_SEGFREE module does not support Conda. Please use Docker / Singularity / Podman instead." + error("BAYSOR_SEGFREE module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/local/proseg/preset/main.nf b/modules/local/proseg/preset/main.nf index 3c7e1441..ac87127d 100644 --- a/modules/local/proseg/preset/main.nf +++ b/modules/local/proseg/preset/main.nf @@ -1,5 +1,5 @@ process PROSEG { - tag "$meta.id" + tag "${meta.id}" label 'process_high' container "khersameesh24/proseg:2.0.0" @@ -8,10 +8,8 @@ process PROSEG { tuple val(meta), path(transcripts) output: - tuple val(meta), - path("${prefix}/cell-polygons.geojson.gz"), - path("${prefix}/transcript-metadata.csv.gz"), emit: seg_outs - path("versions.yml") , emit: versions + tuple val(meta), path("${prefix}/cell-polygons.geojson.gz"), path("${prefix}/transcript-metadata.csv.gz"), emit: seg_outs + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -19,15 +17,15 @@ process PROSEG { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "PROSEG module does not support Conda. Please use Docker / Singularity / Podman instead." + error("PROSEG module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" // check for platform values - if ( !(params.format in ['xenium', 'cosmx', 'merscope']) ) { - error "${params.format} is an invalid platform type. Please specify xenium, cosmx, or merscope" + if (!(params.format in ['xenium', 'cosmx', 'merscope'])) { + error("${params.format} is an invalid platform type. Please specify xenium, cosmx, or merscope") } """ @@ -37,14 +35,14 @@ process PROSEG { --${params.format} \\ ${transcripts} \\ --nthreads ${task.cpus} \\ - --output-expected-counts "${prefix}/expected-counts.csv.gz" \\ - --output-cell-metadata "${prefix}/cell-metadata.csv.gz" \\ - --output-transcript-metadata "${prefix}/transcript-metadata.csv.gz" \\ - --output-gene-metadata "${prefix}/gene-metadata.csv.gz" \\ - --output-rates "${prefix}/rates.csv.gz" \\ - --output-cell-polygons "${prefix}/cell-polygons.geojson.gz" \\ - --output-cell-polygon-layers "${prefix}/cell-polygons-layers.geojson.gz" \\ - --output-cell-hulls "${prefix}/cell-hulls.geojson.gz" \\ + --output-expected-counts ${prefix}/expected-counts.csv.gz \\ + --output-cell-metadata ${prefix}/cell-metadata.csv.gz \\ + --output-transcript-metadata ${prefix}/transcript-metadata.csv.gz \\ + --output-gene-metadata ${prefix}/gene-metadata.csv.gz \\ + --output-rates ${prefix}/rates.csv.gz \\ + --output-cell-polygons ${prefix}/cell-polygons.geojson.gz \\ + --output-cell-polygon-layers ${prefix}/cell-polygons-layers.geojson.gz \\ + --output-cell-hulls ${prefix}/cell-hulls.geojson.gz \\ ${args} cat <<-END_VERSIONS > versions.yml @@ -56,7 +54,7 @@ process PROSEG { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "PROSEG module does not support Conda. Please use Docker / Singularity / Podman instead." + error("PROSEG module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/local/resolift/main.nf b/modules/local/resolift/main.nf index be75100a..451789db 100644 --- a/modules/local/resolift/main.nf +++ b/modules/local/resolift/main.nf @@ -1,16 +1,15 @@ process RESOLIFT { - tag "$meta.id" + tag "${meta.id}" label 'process_medium' - container "quay.io/khersameesh24/resolift:1.0.0" + container "khersameesh24/resolift:1.0.0" input: tuple val(meta), path(morphology_tiff) output: - tuple val(meta), - path("${prefix}/morphology.ome.enhanced.tiff"), emit: enhanced_tiff - path("versions.yml") , emit: versions + tuple val(meta), path("${prefix}/morphology.ome.enhanced.tiff"), emit: enhanced_tiff + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -18,7 +17,7 @@ process RESOLIFT { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "RESOLIFT module does not support Conda. Please use Docker / Singularity / Podman instead." + error("RESOLIFT module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' @@ -41,7 +40,7 @@ process RESOLIFT { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "RESOLIFT module does not support Conda. Please use Docker / Singularity / Podman instead." + error("RESOLIFT module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/local/segger/create_dataset/main.nf b/modules/local/segger/create_dataset/main.nf index 29057344..7b2f010f 100644 --- a/modules/local/segger/create_dataset/main.nf +++ b/modules/local/segger/create_dataset/main.nf @@ -1,5 +1,5 @@ process SEGGER_CREATE_DATASET { - tag "$meta.id" + tag "${meta.id}" label 'process_high' container "khersameesh24/segger:0.1.0" @@ -9,7 +9,7 @@ process SEGGER_CREATE_DATASET { output: tuple val(meta), path("${prefix}/"), emit: datasetdir - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -17,7 +17,7 @@ process SEGGER_CREATE_DATASET { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "SEGGER_CREATE_DATASET module does not support Conda. Please use Docker / Singularity / Podman instead." + error("SEGGER_CREATE_DATASET module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' @@ -25,8 +25,8 @@ process SEGGER_CREATE_DATASET { prefix = task.ext.prefix ?: "${meta.id}" // check for platform values - if ( !(params.format in ['xenium']) ) { - error "${params.format} is an invalid platform type." + if (!(params.format in ['xenium'])) { + error("${params.format} is an invalid platform type.") } """ @@ -48,7 +48,7 @@ process SEGGER_CREATE_DATASET { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "SEGGER_CREATE_DATASET module does not support Conda. Please use Docker / Singularity / Podman instead." + error("SEGGER_CREATE_DATASET module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/local/segger/predict/main.nf b/modules/local/segger/predict/main.nf index 3e08a803..c3dd795f 100644 --- a/modules/local/segger/predict/main.nf +++ b/modules/local/segger/predict/main.nf @@ -1,18 +1,18 @@ process SEGGER_PREDICT { - tag "$meta.id" + tag "${meta.id}" label 'process_gpu' container "khersameesh24/segger:0.1.0" input: tuple val(meta), path(segger_dataset) - path(models_dir) - path(transcripts) + path models_dir + path transcripts output: - tuple val(meta), path("${prefix}/benchmarks_dir") , emit: benchmarks + tuple val(meta), path("${prefix}/benchmarks_dir"), emit: benchmarks tuple val(meta), path("${prefix}/benchmarks_dir/*/segger_transcripts.parquet"), emit: transcripts - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -20,7 +20,7 @@ process SEGGER_PREDICT { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "SEGGER_PREDICT module does not support Conda. Please use Docker / Singularity / Podman instead." + error("SEGGER_PREDICT module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' @@ -48,7 +48,7 @@ process SEGGER_PREDICT { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "SEGGER_PREDICT module does not support Conda. Please use Docker / Singularity / Podman instead." + error("SEGGER_PREDICT module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/local/segger/train/main.nf b/modules/local/segger/train/main.nf index 70448258..0f8edc65 100644 --- a/modules/local/segger/train/main.nf +++ b/modules/local/segger/train/main.nf @@ -1,5 +1,5 @@ process SEGGER_TRAIN { - tag "$meta.id" + tag "${meta.id}" label 'process_high' container "khersameesh24/segger:0.1.0" @@ -9,7 +9,7 @@ process SEGGER_TRAIN { output: tuple val(meta), path("${prefix}/trained_models"), emit: trained_models - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -17,7 +17,7 @@ process SEGGER_TRAIN { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "SEGGER_TRAIN module does not support Conda. Please use Docker / Singularity / Podman instead." + error("SEGGER_TRAIN module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' @@ -45,7 +45,7 @@ process SEGGER_TRAIN { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "SEGGER_TRAIN module does not support Conda. Please use Docker / Singularity / Podman instead." + error("SEGGER_TRAIN module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/local/spatialdata/Dockerfile b/modules/local/spatialdata/Dockerfile index c46c9caa..3e2a2100 100644 --- a/modules/local/spatialdata/Dockerfile +++ b/modules/local/spatialdata/Dockerfile @@ -7,7 +7,9 @@ LABEL authors="Florian Heyl" \ # Set environment variables ENV PYTHONUNBUFFERED=1 # Set the environment variable NUMBA_CACHE_DIR -ENV NUMBA_CACHE_DIR '/tmp' +ENV NUMBA_CACHE_DIR='tmp' +ENV MPLCONFIGDIR='tmp/matplotlib' +ENV XDG_CACHE_HOME='tmp' # Install system dependencies RUN apt-get update && apt-get install -y \ diff --git a/modules/local/spatialdata/merge/main.nf b/modules/local/spatialdata/merge/main.nf index fc552b75..1ddb90dc 100644 --- a/modules/local/spatialdata/merge/main.nf +++ b/modules/local/spatialdata/merge/main.nf @@ -1,15 +1,15 @@ process SPATIALDATA_MERGE { - tag "$meta.id" - label 'process_low' + tag "${meta.id}" + label 'process_high_memory' - container "heylf/spatialdata:0.2.6" + container "khersameesh24/spatialdata:0.2.6" input: tuple val(meta), path(raw_bundle, stageAs: "*"), path(redefined_bundle, stageAs: "*") output: tuple val(meta), path("${prefix}/spatialdata_merged"), emit: merged_bundle - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -17,18 +17,18 @@ process SPATIALDATA_MERGE { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - exit 1, "SPATIALDATA_WRITE module does not support Conda. Please use Docker / Singularity / Podman instead." + exit(1, "SPATIALDATA_WRITE module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" - template 'merge.py' + template('merge.py') stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - exit 1, "SPATIALDATA_WRITE module does not support Conda. Please use Docker / Singularity / Podman instead." + exit(1, "SPATIALDATA_WRITE module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" @@ -42,5 +42,4 @@ process SPATIALDATA_MERGE { spatialdata: \$(echo \$( python -c "import spatialdata; print(spatialdata.__version__)" 2>&1) ) END_VERSIONS """ - } diff --git a/modules/local/spatialdata/meta/main.nf b/modules/local/spatialdata/meta/main.nf index b197bc1c..96feebd2 100644 --- a/modules/local/spatialdata/meta/main.nf +++ b/modules/local/spatialdata/meta/main.nf @@ -1,15 +1,15 @@ process SPATIALDATA_META { - tag "$meta.id" - label 'process_low' + tag "${meta.id}" + label 'process_high_memory' - container "heylf/spatialdata:0.2.6" + container "khersameesh24/spatialdata:0.2.6" input: tuple val(meta), path(spatialdata_bundle, stageAs: "*"), path(xenium_bundle, stageAs: "*") output: tuple val(meta), path("${prefix}/spatialdata_meta"), emit: metadata - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -17,17 +17,17 @@ process SPATIALDATA_META { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - exit 1, "SPATIALDATA_META module does not support Conda. Please use Docker / Singularity / Podman instead." + exit(1, "SPATIALDATA_META module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" - template 'meta.py' + template('meta.py') stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - exit 1, "SPATIALDATA_META module does not support Conda. Please use Docker / Singularity / Podman instead." + exit(1, "SPATIALDATA_META module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" @@ -41,5 +41,4 @@ process SPATIALDATA_META { spatialdata: \$(echo \$( python -c "import spatialdata; print(spatialdata.__version__)" 2>&1) ) END_VERSIONS """ - } diff --git a/modules/local/spatialdata/write/main.nf b/modules/local/spatialdata/write/main.nf index 7816ba68..bb4a3e3f 100644 --- a/modules/local/spatialdata/write/main.nf +++ b/modules/local/spatialdata/write/main.nf @@ -1,18 +1,18 @@ process SPATIALDATA_WRITE { - tag "$meta.id" - label 'process_low' + tag "${meta.id}" + label 'process_high_memory' - container "heylf/spatialdata:0.2.6" + container "khersameesh24/spatialdata:0.2.6" input: tuple val(meta), path(bundle, stageAs: "*") - val(outputfolder) - val(segmented_object) - val(coordinate_space) + val outputfolder + val segmented_object + val coordinate_space output: tuple val(meta), path("${prefix}/${outputfolder}"), emit: spatialdata - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -20,17 +20,17 @@ process SPATIALDATA_WRITE { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - exit 1, "SPATIALDATA_WRITE module does not support Conda. Please use Docker / Singularity / Podman instead." + exit(1, "SPATIALDATA_WRITE module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" - template 'write.py' + template('write.py') stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - exit 1, "SPATIALDATA_WRITE module does not support Conda. Please use Docker / Singularity / Podman instead." + exit(1, "SPATIALDATA_WRITE module does not support Conda. Please use Docker / Singularity / Podman instead.") } def outdir = "${outputfolder}" @@ -45,5 +45,4 @@ process SPATIALDATA_WRITE { spatialdata: \$(echo \$( python -c "import spatialdata; print(spatialdata.__version__)" 2>&1) ) END_VERSIONS """ - } diff --git a/modules/local/utility/resize_tif/Dockerfile b/modules/local/utility/resize_tif/Dockerfile new file mode 100644 index 00000000..79213ebb --- /dev/null +++ b/modules/local/utility/resize_tif/Dockerfile @@ -0,0 +1,11 @@ +FROM mambaorg/micromamba:1.5.10-noble +COPY --chown=$MAMBA_USER:$MAMBA_USER conda.yml /tmp/conda.yml +RUN micromamba install -y -n base -f /tmp/conda.yml \ + && micromamba install -y -n base conda-forge::procps-ng \ + && micromamba env export --name base --explicit > environment.lock \ + && echo ">> CONDA_LOCK_START" \ + && cat environment.lock \ + && echo "<< CONDA_LOCK_END" \ + && micromamba clean -a -y +USER root +ENV PATH="$MAMBA_ROOT_PREFIX/bin:$PATH" diff --git a/modules/local/utility/resize_tif/main.nf b/modules/local/utility/resize_tif/main.nf new file mode 100644 index 00000000..e8c83082 --- /dev/null +++ b/modules/local/utility/resize_tif/main.nf @@ -0,0 +1,43 @@ +process RESIZE_TIF { + tag "$meta.id" + label 'process_low' + + container "community.wave.seqera.io/library/scikit-image_pip_numpy_pandas_tifffile:ef6d9eac4fb80ac9" + + input: + tuple val(meta), path(mask), path(transcripts), path(metadata) + + output: + tuple val(meta), path("${meta.id}/resized_*.tif"), emit: resized_mask + path("versions.yml") , emit: versions + + 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 "RESIZE_TIF module does not support Conda. Please use Docker / Singularity / Podman instead." + } + + prefix = task.ext.prefix ?: "${meta.id}" + + template 'resize_tif.py' + + stub: + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + error "RESIZE_TIF module does not support Conda. Please use Docker / Singularity / Podman instead." + } + prefix = task.ext.prefix ?: "${meta.id}" + + """ + mkdir -p ${prefix} + touch "${prefix}/resized_${mask}.tif" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + resize_tif: "1.0.0" + END_VERSIONS + """ +} diff --git a/modules/local/utility/resize_tif/templates/resize_tif.py b/modules/local/utility/resize_tif/templates/resize_tif.py new file mode 100644 index 00000000..9897de44 --- /dev/null +++ b/modules/local/utility/resize_tif/templates/resize_tif.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +""" +Resize a segmentation TIFF mask to match transcript coordinates. + +This function rescales a segmentation mask image to match the coordinate +space of Xenium transcript data using microns-per-pixel metadata. +""" + +import json +import os +from typing import Tuple + +import numpy as np +import pandas as pd +import tifffile +from skimage.transform import resize + + +def read_mask(mask_path: str) -> np.ndarray: + """Read the segmentation mask from a TIFF file.""" + print(f"Reading mask: {mask_path}") + mask = tifffile.imread(mask_path) + print(f"Mask shape: {mask.shape}, dtype: {mask.dtype}") + return mask + + +def read_transcript_bounds(transcript_path: str) -> Tuple[float, float, float, float]: + """Read transcript coordinates and return their bounding box.""" + print(f"Reading transcripts: {transcript_path}") + transcripts = pd.read_csv(transcript_path) + + if "x_location" not in transcripts.columns or "y_location" not in transcripts.columns: + raise ValueError("Transcript CSV must contain 'x_location' and 'y_location' columns.") + + x_min, x_max = transcripts["x_location"].min(), transcripts["x_location"].max() + y_min, y_max = transcripts["y_location"].min(), transcripts["y_location"].max() + + print(f"Transcript bounds: X=({x_min:.2f}, {x_max:.2f}), Y=({y_min:.2f}, {y_max:.2f})") + return x_min, x_max, y_min, y_max + + +def read_microns_per_pixel(metadata_path: str) -> float: + """Extract microns_per_pixel or pixel_size from metadata JSON.""" + print(f"Reading metadata: {metadata_path}") + with open(metadata_path, "r") as f: + metadata = json.load(f) + + mpp = metadata.get("microns_per_pixel") or metadata.get("pixel_size") + if mpp is None: + raise KeyError("Metadata JSON must contain 'microns_per_pixel' or 'pixel_size'.") + + print(f"Microns per pixel: {mpp}") + return float(mpp) + + +def compute_target_size( + x_min: float, x_max: float, y_min: float, y_max: float, microns_per_pixel: float +) -> Tuple[int, int]: + """Compute new image size (in pixels) to cover given coordinates.""" + new_width = int(round((x_max - x_min) / microns_per_pixel)) + new_height = int(round((y_max - y_min) / microns_per_pixel)) + print(f"Target image size: {new_width} × {new_height} pixels") + return new_height, new_width + + +def resize_mask(mask: np.ndarray, new_shape: Tuple[int, int]) -> np.ndarray: + """Resize mask using nearest-neighbor interpolation (preserve labels).""" + print("Resizing mask...") + resized = resize( + mask, + new_shape, + order=0, # nearest neighbor to preserve segmentation labels + preserve_range=True, + anti_aliasing=False, + ).astype(mask.dtype) + print(f"Resized shape: {resized.shape}") + return resized + + +def main(mask_path: str, transcripts_path: str, metadata_path: str, output_path: str) -> None: + """Resize segmentation mask to match Xenium coordinate space.""" + # Validate input files + for path in [mask_path, transcripts_path, metadata_path]: + if not os.path.exists(path): + raise FileNotFoundError(f"File not found: {path}") + + # Load data + mask = read_mask(mask_path) + x_min, x_max, y_min, y_max = read_transcript_bounds(transcripts_path) + microns_per_pixel = read_microns_per_pixel(metadata_path) + + # Compute physical mask size + height, width = mask.shape + print(f"Original mask size: {width * microns_per_pixel:.2f} × {height * microns_per_pixel:.2f} µm") + + # Compute target size + new_height, new_width = compute_target_size(x_min, x_max, y_min, y_max, microns_per_pixel) + + # Resize and save + resized_mask = resize_mask(mask, (new_height, new_width)) + tifffile.imwrite(output_path, resized_mask) + + print(f"Saved resized mask → {output_path}") + + +if __name__ == "__main__": + + mask: str = "${mask}" + transcripts: str = "${transcripts}" + metadata: str = "${metadata}" + output_mask: str = "resized_${mask}.tif" + + main( + mask_path=mask, + transcript_path=transcripts, + metadata_path=metadata, + output_path=output_mask + ) + + #Output versions.yml + with open("versions.yml", "w") as f: + f.write('"${task.process}":\\n') + f.write('resize_tif: "1.0.0"\\n') diff --git a/modules/nf-core/cellpose/cellpose.diff b/modules/nf-core/cellpose/cellpose.diff index b4f73e87..6f40a5a8 100644 --- a/modules/nf-core/cellpose/cellpose.diff +++ b/modules/nf-core/cellpose/cellpose.diff @@ -1,14 +1,23 @@ Changes in component 'nf-core/cellpose' +'modules/nf-core/cellpose/meta.yml' is unchanged Changes in 'cellpose/main.nf': --- modules/nf-core/cellpose/main.nf +++ modules/nf-core/cellpose/main.nf -@@ -6,12 +6,14 @@ +@@ -1,17 +1,20 @@ + process CELLPOSE { +- tag "$meta.id" +- label 'process_medium' ++ tag "${meta.id}" ++ label 'process_high' ++ maxForks params.restrict_concurrency ? 1 : 0 + + container "docker.io/biocontainers/cellpose:3.1.0_cv1" input: tuple val(meta), path(image) - path(model) -+ val(model) -+ val(maskname) ++ val model ++ val maskname output: - tuple val(meta), path("*masks.tif") , emit: mask @@ -16,53 +25,57 @@ Changes in 'cellpose/main.nf': - 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 -+ path "versions.yml" , emit: versions ++ tuple val(meta), path("${prefix}/*seg.npy"), emit: cells, optional: true ++ path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when -@@ -19,37 +21,47 @@ +@@ -19,40 +22,49 @@ 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." -+ error "CELLPOSE module does not support conda. Please use Docker / Singularity / Podman instead." ++ error("CELLPOSE module does not support conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" - def model_command = model ? "--pretrained_model $model" : "" +- def model_command = model ? "--pretrained_model $model" : "" ++ def model_command = model ? "--pretrained_model ${model}" : "" + prefix = task.ext.prefix ?: "${meta.id}" """ export OMP_NUM_THREADS=${task.cpus} export MKL_NUM_THREADS=${task.cpus} + export NPY_PROMOTION_STATE=legacy cellpose \\ - --image_path $image \\ +- --image_path $image \\ ++ --image_path ${image} \\ --save_tif \\ - $model_command \\ - $args - +- $model_command \\ +- $args ++ ${model_command} \\ ++ ${args} ++ + mkdir -p ${prefix} + mv *masks.tif ${prefix}/morphology.ome_${maskname}_masks.tif -+ + cat <<-END_VERSIONS > versions.yml "${task.process}": cellpose: \$(cellpose --version | awk 'NR==2 {print \$3}') END_VERSIONS """ -+ ++ 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." -+ error "CELLPOSE module does not support conda. Please use Docker / Singularity / Podman instead." ++ error("CELLPOSE module does not support conda. Please use Docker / Singularity / Podman instead.") } - def prefix = task.ext.prefix ?: "${meta.id}" -+ ++ def name = image.name def base = name.lastIndexOf('.') != -1 ? name[0..name.lastIndexOf('.') - 1] : name + prefix = task.ext.prefix ?: "${meta.id}" -+ ++ """ + mkdir -p ${prefix} + touch ${prefix}/morphology.ome_${maskname}_masks.tif @@ -74,9 +87,11 @@ Changes in 'cellpose/main.nf': "${task.process}": cellpose: \$(cellpose --version | awk 'NR==2 {print \$3}') END_VERSIONS + """ +- + } -'modules/nf-core/cellpose/meta.yml' is unchanged -'modules/nf-core/cellpose/tests/main.nf.test' is unchanged 'modules/nf-core/cellpose/tests/main.nf.test.snap' is unchanged +'modules/nf-core/cellpose/tests/main.nf.test' is unchanged 'modules/nf-core/cellpose/tests/nextflow_wflows.config' is unchanged ************************************************************ diff --git a/modules/nf-core/cellpose/main.nf b/modules/nf-core/cellpose/main.nf index 272f3475..53c452cd 100644 --- a/modules/nf-core/cellpose/main.nf +++ b/modules/nf-core/cellpose/main.nf @@ -1,19 +1,20 @@ process CELLPOSE { - tag "$meta.id" - label 'process_medium' + tag "${meta.id}" + label 'process_high' + maxForks params.restrict_concurrency ? 1 : 0 container "docker.io/biocontainers/cellpose:3.1.0_cv1" input: tuple val(meta), path(image) - val(model) - val(maskname) + val model + val maskname output: 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 - path "versions.yml" , emit: versions + tuple val(meta), path("${prefix}/*seg.npy"), emit: cells, optional: true + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when @@ -21,20 +22,20 @@ process CELLPOSE { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "CELLPOSE module does not support conda. Please use Docker / Singularity / Podman instead." + error("CELLPOSE module does not support conda. 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}" : "" prefix = task.ext.prefix ?: "${meta.id}" """ export OMP_NUM_THREADS=${task.cpus} export MKL_NUM_THREADS=${task.cpus} export NPY_PROMOTION_STATE=legacy cellpose \\ - --image_path $image \\ + --image_path ${image} \\ --save_tif \\ - $model_command \\ - $args + ${model_command} \\ + ${args} mkdir -p ${prefix} mv *masks.tif ${prefix}/morphology.ome_${maskname}_masks.tif @@ -44,17 +45,17 @@ process CELLPOSE { cellpose: \$(cellpose --version | awk 'NR==2 {print \$3}') END_VERSIONS """ - + stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "CELLPOSE module does not support conda. Please use Docker / Singularity / Podman instead." + error("CELLPOSE module does not support conda. Please use Docker / Singularity / Podman instead.") } - + def name = image.name def base = name.lastIndexOf('.') != -1 ? name[0..name.lastIndexOf('.') - 1] : name prefix = task.ext.prefix ?: "${meta.id}" - + """ mkdir -p ${prefix} touch ${prefix}/morphology.ome_${maskname}_masks.tif @@ -66,5 +67,4 @@ process CELLPOSE { cellpose: \$(cellpose --version | awk 'NR==2 {print \$3}') END_VERSIONS """ - } diff --git a/modules/nf-core/xeniumranger/import-segmentation/main.nf b/modules/nf-core/xeniumranger/import-segmentation/main.nf index 985a709e..2bc145df 100644 --- a/modules/nf-core/xeniumranger/import-segmentation/main.nf +++ b/modules/nf-core/xeniumranger/import-segmentation/main.nf @@ -1,22 +1,15 @@ process XENIUMRANGER_IMPORT_SEGMENTATION { - tag "$meta.id" + tag "${meta.id}" label 'process_high' container "nf-core/xeniumranger:3.1.1" input: - tuple val(meta), - path(xenium_bundle), - path(coordinate_transform), - path(nuclei), - path(cells), - path(transcript_assignment), - path(viz_polygons), - val(units) + tuple val(meta), path(xenium_bundle, stageAs: "bundle/"), path(coordinate_transform), path(nuclei), path(cells), path(transcript_assignment), path(viz_polygons), val(units) output: tuple val(meta), path("${prefix}/outs"), emit: bundle - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -24,25 +17,25 @@ process XENIUMRANGER_IMPORT_SEGMENTATION { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "XENIUMRANGER_IMPORT-SEGMENTATION module does not support Conda. Please use Docker / Singularity / Podman instead." + error("XENIUMRANGER_IMPORT-SEGMENTATION module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" // image based segmentation options - def coord_transform = coordinate_transform ? "--coordinate-transform=\"${coordinate_transform}\"": "" - def nuclei_detection = nuclei ? "--nuclei=\"${nuclei}\"": "" - def cell_detection = cells ? "--cells=\"${cells}\"": "" + def coord_transform = coordinate_transform ? "--coordinate-transform=\"${coordinate_transform}\"" : "" + def nuclei_detection = nuclei ? "--nuclei=\"${nuclei}\"" : "" + def cell_detection = cells ? "--cells=\"${cells}\"" : "" // transcript based segmentation - def transcript_assign = transcript_assignment ? "--transcript-assignment=\"${transcript_assignment}\"": "" - def polygons = viz_polygons ? "--viz-polygons=\"${viz_polygons}\"":"" + def transcript_assign = transcript_assignment ? "--transcript-assignment=\"${transcript_assignment}\"" : "" + def polygons = viz_polygons ? "--viz-polygons=\"${viz_polygons}\"" : "" // shared argument def space = units ? "--units=${units}" : "" // conditional args - def exp_dist = nuclei ? "--expansion-distance=${params.expansion_distance}": "" + def exp_dist = nuclei ? "--expansion-distance=${params.expansion_distance}" : "" """ xeniumranger import-segmentation \\ @@ -68,11 +61,11 @@ process XENIUMRANGER_IMPORT_SEGMENTATION { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "XENIUMRANGER_IMPORT-SEGMENTATION module does not support Conda. Please use Docker / Singularity / Podman instead." + error("XENIUMRANGER_IMPORT-SEGMENTATION module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" - + """ mkdir -p "${prefix}/outs" touch "${prefix}/outs/fake_file.txt" diff --git a/modules/nf-core/xeniumranger/import-segmentation/xeniumranger-import-segmentation.diff b/modules/nf-core/xeniumranger/import-segmentation/xeniumranger-import-segmentation.diff index 57550231..7b64bd83 100644 --- a/modules/nf-core/xeniumranger/import-segmentation/xeniumranger-import-segmentation.diff +++ b/modules/nf-core/xeniumranger/import-segmentation/xeniumranger-import-segmentation.diff @@ -1,9 +1,51 @@ Changes in component 'nf-core/xeniumranger/import-segmentation' +Changes in 'xeniumranger/import-segmentation/meta.yml': +--- modules/nf-core/xeniumranger/import-segmentation/meta.yml ++++ modules/nf-core/xeniumranger/import-segmentation/meta.yml +@@ -62,22 +62,22 @@ + description: | + Cell boundary polygons (GeoJSON) for visualization from Baysor v0.6. Required if --transcript-assignment argument used. Error if --cells or --nuclei arguments used. + output: +- - outs: ++ - bundle: + - meta: +- type: file +- description: Files containing the outputs of Cell Ranger, see official 10X Genomics +- documentation for a complete list +- pattern: "${meta.id}/outs/*" +- - "**/outs/**": +- type: file +- description: Files containing the outputs of xenium ranger, see official 10X +- Genomics documentation for a complete list of outputs +- pattern: "${meta.id}/outs/*" ++ type: map ++ description: | ++ Groovy Map containing sample information ++ e.g. [ id:'sample' ] ++ - "${meta.id}/outs": ++ type: file ++ description: Files containing the outputs of xenium ranger, see official 10X ++ Genomics documentation for a complete list of outputs ++ pattern: "${meta.id}/outs" + - versions: + - versions.yml: +- type: file +- description: File containing software versions +- pattern: "versions.yml" ++ type: file ++ description: File containing software versions ++ pattern: "versions.yml" + authors: + - "@khersameesh24" + maintainers: + Changes in 'xeniumranger/import-segmentation/main.nf': --- modules/nf-core/xeniumranger/import-segmentation/main.nf +++ modules/nf-core/xeniumranger/import-segmentation/main.nf -@@ -2,20 +2,21 @@ - tag "$meta.id" +@@ -1,21 +1,15 @@ + process XENIUMRANGER_IMPORT_SEGMENTATION { +- tag "$meta.id" ++ tag "${meta.id}" label 'process_high' - container "nf-core/xeniumranger:3.0.1" @@ -17,25 +59,22 @@ Changes in 'xeniumranger/import-segmentation/main.nf': - path(cells) - path(transcript_assignment) - path(viz_polygons) -+ tuple val(meta), -+ path(xenium_bundle), -+ path(coordinate_transform), -+ path(nuclei), -+ path(cells), -+ path(transcript_assignment), -+ path(viz_polygons), -+ val(units) ++ tuple val(meta), path(xenium_bundle, stageAs: "bundle/"), path(coordinate_transform), path(nuclei), path(cells), path(transcript_assignment), path(viz_polygons), val(units) output: - tuple val(meta), path("**/outs/**"), emit: outs - path "versions.yml", emit: versions + tuple val(meta), path("${prefix}/outs"), emit: bundle -+ path("versions.yml") , emit: versions ++ path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when -@@ -26,35 +27,36 @@ - error "XENIUMRANGER_IMPORT-SEGMENTATION module does not support Conda. Please use Docker / Singularity / Podman instead." +@@ -23,38 +17,39 @@ + script: + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { +- error "XENIUMRANGER_IMPORT-SEGMENTATION module does not support Conda. Please use Docker / Singularity / Podman instead." ++ error("XENIUMRANGER_IMPORT-SEGMENTATION module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" @@ -45,23 +84,24 @@ Changes in 'xeniumranger/import-segmentation/main.nf': - def expansion_distance = expansion_distance ? "--expansion-distance=\"${expansion_distance}\"": "" // expansion distance (default - 5, range - 0 - 100) - def coordinate_transform = coordinate_transform ? "--coordinate-transform=\"${coordinate_transform}\"": "" - -+ def coord_transform = coordinate_transform ? "--coordinate-transform=\"${coordinate_transform}\"": "" - def nuclei_detection = nuclei ? "--nuclei=\"${nuclei}\"": "" +- def nuclei_detection = nuclei ? "--nuclei=\"${nuclei}\"": "" - def cells = cells ? "--cells=\"${cells}\"": "" -+ def cell_detection = cells ? "--cells=\"${cells}\"": "" ++ def coord_transform = coordinate_transform ? "--coordinate-transform=\"${coordinate_transform}\"" : "" ++ def nuclei_detection = nuclei ? "--nuclei=\"${nuclei}\"" : "" ++ def cell_detection = cells ? "--cells=\"${cells}\"" : "" // transcript based segmentation - def transcript_assignment = transcript_assignment ? "--transcript-assignment=\"${transcript_assignment}\"": "" - def viz_polygons = viz_polygons ? "--viz-polygons=\"${viz_polygons}\"":"" -+ def transcript_assign = transcript_assignment ? "--transcript-assignment=\"${transcript_assignment}\"": "" -+ def polygons = viz_polygons ? "--viz-polygons=\"${viz_polygons}\"":"" ++ def transcript_assign = transcript_assignment ? "--transcript-assignment=\"${transcript_assignment}\"" : "" ++ def polygons = viz_polygons ? "--viz-polygons=\"${viz_polygons}\"" : "" // shared argument - def units = coordinate_transform ? "--units=microns": "--units=pixels" + def space = units ? "--units=${units}" : "" + + // conditional args -+ def exp_dist = nuclei ? "--expansion-distance=${params.expansion_distance}": "" ++ def exp_dist = nuclei ? "--expansion-distance=${params.expansion_distance}" : "" """ xeniumranger import-segmentation \\ @@ -86,14 +126,17 @@ Changes in 'xeniumranger/import-segmentation/main.nf': ${args} cat <<-END_VERSIONS > versions.yml -@@ -68,9 +70,11 @@ +@@ -66,11 +61,13 @@ + stub: + // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "XENIUMRANGER_IMPORT-SEGMENTATION module does not support Conda. Please use Docker / Singularity / Podman instead." +- error "XENIUMRANGER_IMPORT-SEGMENTATION module does not support Conda. Please use Docker / Singularity / Podman instead." ++ error("XENIUMRANGER_IMPORT-SEGMENTATION module does not support Conda. Please use Docker / Singularity / Podman instead.") } - def prefix = task.ext.prefix ?: "${meta.id}" + + prefix = task.ext.prefix ?: "${meta.id}" -+ ++ """ - mkdir -p "${prefix}/outs/" + mkdir -p "${prefix}/outs" @@ -101,48 +144,8 @@ Changes in 'xeniumranger/import-segmentation/main.nf': cat <<-END_VERSIONS > versions.yml -Changes in 'xeniumranger/import-segmentation/meta.yml': ---- modules/nf-core/xeniumranger/import-segmentation/meta.yml -+++ modules/nf-core/xeniumranger/import-segmentation/meta.yml -@@ -62,22 +62,22 @@ - description: | - Cell boundary polygons (GeoJSON) for visualization from Baysor v0.6. Required if --transcript-assignment argument used. Error if --cells or --nuclei arguments used. - output: -- - outs: -+ - bundle: - - meta: -- type: file -- description: Files containing the outputs of Cell Ranger, see official 10X Genomics -- documentation for a complete list -- pattern: "${meta.id}/outs/*" -- - "**/outs/**": -- type: file -- description: Files containing the outputs of xenium ranger, see official 10X -- Genomics documentation for a complete list of outputs -- pattern: "${meta.id}/outs/*" -+ type: map -+ description: | -+ Groovy Map containing sample information -+ e.g. [ id:'sample' ] -+ - "${meta.id}/outs": -+ type: file -+ description: Files containing the outputs of xenium ranger, see official 10X -+ Genomics documentation for a complete list of outputs -+ pattern: "${meta.id}/outs" - - versions: - - versions.yml: -- type: file -- description: File containing software versions -- pattern: "versions.yml" -+ type: file -+ description: File containing software versions -+ pattern: "versions.yml" - authors: - - "@khersameesh24" - maintainers: - -'modules/nf-core/xeniumranger/import-segmentation/tests/main.nf.test' is unchanged 'modules/nf-core/xeniumranger/import-segmentation/tests/main.nf.test.snap' is unchanged -'modules/nf-core/xeniumranger/import-segmentation/tests/nextflow.config' is unchanged 'modules/nf-core/xeniumranger/import-segmentation/tests/tags.yml' is unchanged +'modules/nf-core/xeniumranger/import-segmentation/tests/nextflow.config' is unchanged +'modules/nf-core/xeniumranger/import-segmentation/tests/main.nf.test' is unchanged ************************************************************ diff --git a/modules/nf-core/xeniumranger/relabel/main.nf b/modules/nf-core/xeniumranger/relabel/main.nf index 03d55d9f..b0646966 100644 --- a/modules/nf-core/xeniumranger/relabel/main.nf +++ b/modules/nf-core/xeniumranger/relabel/main.nf @@ -1,16 +1,16 @@ process XENIUMRANGER_RELABEL { - tag "$meta.id" + tag "${meta.id}" label 'process_high' container "nf-core/xeniumranger:3.1.1" input: - tuple val(meta), path(xenium_bundle) - path(gene_panel) + tuple val(meta), path(xenium_bundle, stageAs: "bundle/") + path gene_panel output: tuple val(meta), path("${prefix}/outs"), emit: bundle - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -18,7 +18,7 @@ process XENIUMRANGER_RELABEL { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "XENIUMRANGER_RELABEL module does not support Conda. Please use Docker / Singularity / Podman instead." + error("XENIUMRANGER_RELABEL module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" @@ -41,7 +41,7 @@ process XENIUMRANGER_RELABEL { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "XENIUMRANGER_RELABEL module does not support Conda. Please use Docker / Singularity / Podman instead." + error("XENIUMRANGER_RELABEL module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/nf-core/xeniumranger/relabel/xeniumranger-relabel.diff b/modules/nf-core/xeniumranger/relabel/xeniumranger-relabel.diff index 3e7f3adb..9b166eba 100644 --- a/modules/nf-core/xeniumranger/relabel/xeniumranger-relabel.diff +++ b/modules/nf-core/xeniumranger/relabel/xeniumranger-relabel.diff @@ -1,28 +1,37 @@ Changes in component 'nf-core/xeniumranger/relabel' +'modules/nf-core/xeniumranger/relabel/meta.yml' is unchanged Changes in 'xeniumranger/relabel/main.nf': --- modules/nf-core/xeniumranger/relabel/main.nf +++ modules/nf-core/xeniumranger/relabel/main.nf -@@ -2,15 +2,15 @@ - tag "$meta.id" +@@ -1,16 +1,16 @@ + process XENIUMRANGER_RELABEL { +- tag "$meta.id" ++ tag "${meta.id}" label 'process_high' - container "nf-core/xeniumranger:3.0.1" + container "nf-core/xeniumranger:3.1.1" input: - tuple val(meta), path(xenium_bundle) - path(gene_panel) +- tuple val(meta), path(xenium_bundle) +- path(gene_panel) ++ tuple val(meta), path(xenium_bundle, stageAs: "bundle/") ++ path gene_panel output: - tuple val(meta), path("**/outs/**"), emit: outs - path "versions.yml", emit: versions + tuple val(meta), path("${prefix}/outs"), emit: bundle -+ path("versions.yml") , emit: versions ++ path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when -@@ -21,7 +21,7 @@ - error "XENIUMRANGER_RELABEL module does not support Conda. Please use Docker / Singularity / Podman instead." +@@ -18,10 +18,10 @@ + script: + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { +- error "XENIUMRANGER_RELABEL module does not support Conda. Please use Docker / Singularity / Podman instead." ++ error("XENIUMRANGER_RELABEL module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" @@ -30,9 +39,12 @@ Changes in 'xeniumranger/relabel/main.nf': """ xeniumranger relabel \\ -@@ -43,9 +43,10 @@ +@@ -41,11 +41,12 @@ + stub: + // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "XENIUMRANGER_RELABEL module does not support Conda. Please use Docker / Singularity / Podman instead." +- error "XENIUMRANGER_RELABEL module does not support Conda. Please use Docker / Singularity / Podman instead." ++ error("XENIUMRANGER_RELABEL module does not support Conda. Please use Docker / Singularity / Podman instead.") } - def prefix = task.ext.prefix ?: "${meta.id}" + prefix = task.ext.prefix ?: "${meta.id}" @@ -44,9 +56,8 @@ Changes in 'xeniumranger/relabel/main.nf': cat <<-END_VERSIONS > versions.yml -'modules/nf-core/xeniumranger/relabel/meta.yml' is unchanged -'modules/nf-core/xeniumranger/relabel/tests/main.nf.test' is unchanged 'modules/nf-core/xeniumranger/relabel/tests/main.nf.test.snap' is unchanged -'modules/nf-core/xeniumranger/relabel/tests/nextflow.config' is unchanged 'modules/nf-core/xeniumranger/relabel/tests/tags.yml' is unchanged +'modules/nf-core/xeniumranger/relabel/tests/nextflow.config' is unchanged +'modules/nf-core/xeniumranger/relabel/tests/main.nf.test' is unchanged ************************************************************ diff --git a/modules/nf-core/xeniumranger/resegment/main.nf b/modules/nf-core/xeniumranger/resegment/main.nf index 839aacaf..05d216a4 100644 --- a/modules/nf-core/xeniumranger/resegment/main.nf +++ b/modules/nf-core/xeniumranger/resegment/main.nf @@ -1,15 +1,15 @@ process XENIUMRANGER_RESEGMENT { - tag "$meta.id" + tag "${meta.id}" label 'process_high' container "nf-core/xeniumranger:3.1.1" input: - tuple val(meta), path(xenium_bundle) + tuple val(meta), path(xenium_bundle, stageAs: "bundle/") output: tuple val(meta), path("${prefix}/outs"), emit: bundle - path("versions.yml") , emit: versions + path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when @@ -17,15 +17,15 @@ process XENIUMRANGER_RESEGMENT { script: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "XENIUMRANGER_RESEGMENT module does not support Conda. Please use Docker / Singularity / Podman instead." + error("XENIUMRANGER_RESEGMENT module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: "" prefix = task.ext.prefix ?: "${meta.id}" // Do not use boundary stain in analysis, but keep default interior stain and DAPI - def boundary_stain = "${params.boundary_stain}" ? "": "--boundary-stain=disable" + def boundary_stain = "${params.boundary_stain}" ? "" : "--boundary-stain=disable" // Do not use interior stain in analysis, but keep default boundary stain and DAPI - def interior_stain = "${params.interior_stain}" ? "": "--interior-stain=disable" + def interior_stain = "${params.interior_stain}" ? "" : "--interior-stain=disable" """ xeniumranger resegment \\ @@ -48,7 +48,7 @@ process XENIUMRANGER_RESEGMENT { stub: // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "XENIUMRANGER_RESEGMENT module does not support Conda. Please use Docker / Singularity / Podman instead." + error("XENIUMRANGER_RESEGMENT module does not support Conda. Please use Docker / Singularity / Podman instead.") } prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/nf-core/xeniumranger/resegment/xeniumranger-resegment.diff b/modules/nf-core/xeniumranger/resegment/xeniumranger-resegment.diff index 9fffaf5a..3328ad9b 100644 --- a/modules/nf-core/xeniumranger/resegment/xeniumranger-resegment.diff +++ b/modules/nf-core/xeniumranger/resegment/xeniumranger-resegment.diff @@ -1,31 +1,39 @@ Changes in component 'nf-core/xeniumranger/resegment' +'modules/nf-core/xeniumranger/resegment/meta.yml' is unchanged Changes in 'xeniumranger/resegment/main.nf': --- modules/nf-core/xeniumranger/resegment/main.nf +++ modules/nf-core/xeniumranger/resegment/main.nf -@@ -2,18 +2,14 @@ - tag "$meta.id" +@@ -1,19 +1,15 @@ + process XENIUMRANGER_RESEGMENT { +- tag "$meta.id" ++ tag "${meta.id}" label 'process_high' - container "nf-core/xeniumranger:3.0.1" + container "nf-core/xeniumranger:3.1.1" input: - tuple val(meta), path(xenium_bundle) +- tuple val(meta), path(xenium_bundle) - val(expansion_distance) - val(dapi_filter) - val(boundary_stain) - val(interior_stain) ++ tuple val(meta), path(xenium_bundle, stageAs: "bundle/") output: - tuple val(meta), path("**/outs/**"), emit: outs - path "versions.yml", emit: versions + tuple val(meta), path("${prefix}/outs"), emit: bundle -+ path("versions.yml") , emit: versions ++ path ("versions.yml"), emit: versions when: task.ext.when == null || task.ext.when -@@ -24,22 +20,19 @@ - error "XENIUMRANGER_RESEGMENT module does not support Conda. Please use Docker / Singularity / Podman instead." +@@ -21,25 +17,22 @@ + script: + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { +- error "XENIUMRANGER_RESEGMENT module does not support Conda. Please use Docker / Singularity / Podman instead." ++ error("XENIUMRANGER_RESEGMENT module does not support Conda. Please use Docker / Singularity / Podman instead.") } def args = task.ext.args ?: "" - def prefix = task.ext.prefix ?: "${meta.id}" @@ -36,10 +44,10 @@ Changes in 'xeniumranger/resegment/main.nf': // Do not use boundary stain in analysis, but keep default interior stain and DAPI - def boundary_stain = boundary_stain ? "--boundary-stain=disable": "" -+ def boundary_stain = "${params.boundary_stain}" ? "": "--boundary-stain=disable" ++ def boundary_stain = "${params.boundary_stain}" ? "" : "--boundary-stain=disable" // Do not use interior stain in analysis, but keep default boundary stain and DAPI - def interior_stain = interior_stain ? "--interior-stain=disable": "" -+ def interior_stain = "${params.interior_stain}" ? "": "--interior-stain=disable" ++ def interior_stain = "${params.interior_stain}" ? "" : "--interior-stain=disable" """ xeniumranger resegment \\ @@ -52,9 +60,12 @@ Changes in 'xeniumranger/resegment/main.nf': ${boundary_stain} \\ ${interior_stain} \\ --localcores=${task.cpus} \\ -@@ -57,9 +50,10 @@ +@@ -55,11 +48,12 @@ + stub: + // Exit if running this module with -profile conda / -profile mamba if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "XENIUMRANGER_RESEGMENT module does not support Conda. Please use Docker / Singularity / Podman instead." +- error "XENIUMRANGER_RESEGMENT module does not support Conda. Please use Docker / Singularity / Podman instead." ++ error("XENIUMRANGER_RESEGMENT module does not support Conda. Please use Docker / Singularity / Podman instead.") } - def prefix = task.ext.prefix ?: "${meta.id}" + prefix = task.ext.prefix ?: "${meta.id}" @@ -66,9 +77,8 @@ Changes in 'xeniumranger/resegment/main.nf': cat <<-END_VERSIONS > versions.yml -'modules/nf-core/xeniumranger/resegment/meta.yml' is unchanged -'modules/nf-core/xeniumranger/resegment/tests/main.nf.test' is unchanged 'modules/nf-core/xeniumranger/resegment/tests/main.nf.test.snap' is unchanged -'modules/nf-core/xeniumranger/resegment/tests/nextflow.config' is unchanged 'modules/nf-core/xeniumranger/resegment/tests/tags.yml' is unchanged +'modules/nf-core/xeniumranger/resegment/tests/nextflow.config' is unchanged +'modules/nf-core/xeniumranger/resegment/tests/main.nf.test' is unchanged ************************************************************ diff --git a/subworkflows/local/baysor_generate_preview/main.nf b/subworkflows/local/baysor_generate_preview/main.nf index 09950ac7..5fc4f73e 100644 --- a/subworkflows/local/baysor_generate_preview/main.nf +++ b/subworkflows/local/baysor_generate_preview/main.nf @@ -7,38 +7,34 @@ include { BAYSOR_CREATE_DATASET } from '../../../modules/local/baysor/create_dat include { PARQUET_TO_CSV } from '../../../modules/local/utility/spatialconverter/parquet_to_csv/main' workflow BAYSOR_GENERATE_PREVIEW { - take: - ch_transcripts_parquet // channel: [ val(meta), ["path-to-transcripts.parquet"] ] ch_config // channel: ["path-to-xenium.toml"] main: - ch_versions = Channel.empty() - ch_preview_html = Channel.empty() + ch_versions = Channel.empty() + ch_preview_html = Channel.empty() // run parquet to csv - PARQUET_TO_CSV ( ch_transcripts_parquet, ".csv" ) - ch_versions = ch_versions.mix ( PARQUET_TO_CSV.out.versions ) + PARQUET_TO_CSV(ch_transcripts_parquet, ".csv") + ch_versions = ch_versions.mix(PARQUET_TO_CSV.out.versions) // generate randomised sample data - BAYSOR_CREATE_DATASET ( PARQUET_TO_CSV.out.transcripts_csv, 0.3 ) - ch_versions = ch_versions.mix ( BAYSOR_CREATE_DATASET.out.versions ) + BAYSOR_CREATE_DATASET(PARQUET_TO_CSV.out.transcripts_csv, 0.3) + ch_versions = ch_versions.mix(BAYSOR_CREATE_DATASET.out.versions) // run baysor preview if param - generate_preview is true - BAYSOR_PREVIEW ( + BAYSOR_PREVIEW( BAYSOR_CREATE_DATASET.out.sampled_transcripts, - ch_config + ch_config, ) - ch_versions = ch_versions.mix ( BAYSOR_PREVIEW.out.versions ) + ch_versions = ch_versions.mix(BAYSOR_PREVIEW.out.versions) ch_preview_html = BAYSOR_PREVIEW.out.preview_html emit: - - preview_html = ch_preview_html // channel: [ val(meta), ["preview.html"] ] - - versions = ch_versions // channel: [ versions.yml ] + preview_html = ch_preview_html // channel: [ val(meta), ["preview.html"] ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/baysor_generate_segfree/main.nf b/subworkflows/local/baysor_generate_segfree/main.nf index 54072fdb..3c43f734 100644 --- a/subworkflows/local/baysor_generate_segfree/main.nf +++ b/subworkflows/local/baysor_generate_segfree/main.nf @@ -6,9 +6,7 @@ include { BAYSOR_SEGFREE } from '../../../modules/local/baysor/segfree/main' // include a module to process the output loom file with scapny or anndata workflow BAYSOR_GENERATE_SEGFREE { - take: - ch_transcripts_parquet // channel: [ val(meta), ["transcripts.parquet"] ] ch_config // channel: [ ["path-to-xenium.toml"] ] @@ -17,15 +15,13 @@ workflow BAYSOR_GENERATE_SEGFREE { ch_versions = Channel.empty() // run baysor segfree - BAYSOR_SEGFREE ( + BAYSOR_SEGFREE( ch_transcripts_parquet, - ch_config + ch_config, ) - ch_versions = ch_versions.mix ( BAYSOR_SEGFREE.out.versions ) + ch_versions = ch_versions.mix(BAYSOR_SEGFREE.out.versions) emit: - ncvs = BAYSOR_SEGFREE.out.ncvs // channel: [ val(meta), ["ncvs.loom"] ] - - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/baysor_run_prior_segmentation_mask/main.nf b/subworkflows/local/baysor_run_prior_segmentation_mask/main.nf index 9aa4c94c..561e7618 100644 --- a/subworkflows/local/baysor_run_prior_segmentation_mask/main.nf +++ b/subworkflows/local/baysor_run_prior_segmentation_mask/main.nf @@ -8,9 +8,7 @@ include { XENIUMRANGER_IMPORT_SEGMENTATION } from '../../../modules/nf-core/xeni workflow BAYSOR_RUN_PRIOR_SEGMENTATION_MASK { - take: - ch_bundle_path // channel: [ val(meta), ["path-to-xenium-bundle"] ] ch_transcripts_parquet // channel: [ val(meta), ["path-to-transcripts.parquet"] ] ch_segmentation_mask // channel: [ ["path-to-prior-segmentation-mask"] ] @@ -18,29 +16,29 @@ workflow BAYSOR_RUN_PRIOR_SEGMENTATION_MASK { main: - ch_versions = Channel.empty() + ch_versions = Channel.empty() - ch_transcripts = Channel.empty() + ch_transcripts = Channel.empty() - ch_redefined_bundle = Channel.empty() - ch_coordinate_space = Channel.value("pixels") + ch_redefined_bundle = Channel.empty() + ch_coordinate_space = Channel.value("pixels") // filter transcripts.parquet based on thresholds - if ( params.filter_transcripts ) { + if (params.filter_transcripts) { - BAYSOR_PREPROCESS_TRANSCRIPTS ( + BAYSOR_PREPROCESS_TRANSCRIPTS( ch_transcripts_parquet, params.min_qv, params.max_x, params.min_x, params.max_y, - params.min_y + params.min_y, ) - ch_versions = ch_versions.mix ( BAYSOR_PREPROCESS_TRANSCRIPTS.out.versions ) + ch_versions = ch_versions.mix(BAYSOR_PREPROCESS_TRANSCRIPTS.out.versions) ch_transcripts = BAYSOR_PREPROCESS_TRANSCRIPTS.out.transcripts_parquet - - } else { + } + else { ch_transcripts = ch_transcripts_parquet } @@ -48,49 +46,45 @@ workflow BAYSOR_RUN_PRIOR_SEGMENTATION_MASK { // run baysor with prior segmentation mask ch_baysor_input = ch_transcripts - .combine(ch_segmentation_mask) - .combine(ch_config) - .map { meta, transcripts, mask, config -> - tuple ( - meta, // meta - transcripts, // transcripts - mask, // prior_segmentation - config, // config - 30 // scale - ) - } - BAYSOR_RUN ( ch_baysor_input ) - ch_versions = ch_versions.mix( BAYSOR_RUN.out.versions ) + .combine(ch_segmentation_mask) + .combine(ch_config) + .map { meta, transcripts, mask, config -> + tuple( + meta, + transcripts, + mask, + config, + 30, + ) + } + BAYSOR_RUN(ch_baysor_input) + ch_versions = ch_versions.mix(BAYSOR_RUN.out.versions) // run import-segmentation with baysor outs ch_imp_seg_inputs = ch_bundle_path - .combine(BAYSOR_RUN.out.segmentation, by: 0) - .map { - meta, bundle, _segmentation_csv, polygons2d -> - tuple ( - meta, // meta - bundle, // bundle - [], // coordinate_transform - polygons2d, // nuclei - polygons2d, // cells - [], // transcript_assignment - [], // viz_polygons - ch_coordinate_space.val // units - ) - } - XENIUMRANGER_IMPORT_SEGMENTATION ( + .combine(BAYSOR_RUN.out.segmentation, by: 0) + .map { meta, bundle, _segmentation_csv, polygons2d -> + tuple( + meta, + bundle, + [], + polygons2d, + polygons2d, + [], + [], + ch_coordinate_space.val, + ) + } + XENIUMRANGER_IMPORT_SEGMENTATION( ch_imp_seg_inputs ) - ch_versions = ch_versions.mix ( XENIUMRANGER_IMPORT_SEGMENTATION.out.versions ) + ch_versions = ch_versions.mix(XENIUMRANGER_IMPORT_SEGMENTATION.out.versions) ch_redefined_bundle = XENIUMRANGER_IMPORT_SEGMENTATION.out.bundle emit: - - coordinate_space = ch_coordinate_space // channel: [ "microns" ] - - redefined_bundle = ch_redefined_bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] - - versions = ch_versions // channel: [ versions.yml ] + coordinate_space = ch_coordinate_space // channel: [ "microns" ] + redefined_bundle = ch_redefined_bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/baysor_run_transcripts_parquet/main.nf b/subworkflows/local/baysor_run_transcripts_parquet/main.nf index d09827bb..44e43262 100644 --- a/subworkflows/local/baysor_run_transcripts_parquet/main.nf +++ b/subworkflows/local/baysor_run_transcripts_parquet/main.nf @@ -9,41 +9,39 @@ include { XENIUMRANGER_IMPORT_SEGMENTATION } from '../../../modules/nf-core/xeni workflow BAYSOR_RUN_TRANSCRIPTS_PARQUET { - take: - - ch_bundle_path // channel: [ val(meta), ["xenium-bundle"] ] - ch_transcripts_parquet // channel: [ val(meta), ["transcripts.parquet"] ] - ch_config // channel: ["path-to-xenium.toml"] + ch_bundle_path // channel: [ val(meta), ["xenium-bundle"] ] + ch_transcripts_parquet // channel: [ val(meta), ["transcripts.parquet"] ] + ch_config // channel: ["path-to-xenium.toml"] main: - ch_versions = Channel.empty() + ch_versions = Channel.empty() - ch_transcripts = Channel.empty() + ch_transcripts = Channel.empty() // ch_splits_csv = Channel.empty() - ch_redefined_bundle = Channel.empty() - ch_coordinate_space = Channel.value("microns") + ch_redefined_bundle = Channel.empty() + ch_coordinate_space = Channel.value("microns") // TODO: run baysor in parallel - next release issue // filter transcripts.parquet based on thresholds - if ( params.filter_transcripts ) { + if (params.filter_transcripts) { - BAYSOR_PREPROCESS_TRANSCRIPTS ( + BAYSOR_PREPROCESS_TRANSCRIPTS( ch_transcripts_parquet, params.min_qv, params.max_x, params.min_x, params.max_y, - params.min_y + params.min_y, ) - ch_versions = ch_versions.mix ( BAYSOR_PREPROCESS_TRANSCRIPTS.out.versions ) + ch_versions = ch_versions.mix(BAYSOR_PREPROCESS_TRANSCRIPTS.out.versions) ch_transcripts = BAYSOR_PREPROCESS_TRANSCRIPTS.out.transcripts_parquet - - } else { + } + else { ch_transcripts = ch_transcripts_parquet } @@ -51,49 +49,45 @@ workflow BAYSOR_RUN_TRANSCRIPTS_PARQUET { // run baysor with the filtered transcripts.parquet ch_baysor_input = ch_transcripts - .combine(ch_config) - .map { meta, transcripts, config -> - tuple ( - meta, // meta - transcripts, // transcripts - [], // prior_segmentation - config, // config - 30 // scale - ) - } - BAYSOR_RUN ( ch_baysor_input ) - ch_versions = ch_versions.mix ( BAYSOR_RUN.out.versions ) + .combine(ch_config) + .map { meta, transcripts, config -> + tuple( + meta, + transcripts, + [], + config, + 30, + ) + } + BAYSOR_RUN(ch_baysor_input) + ch_versions = ch_versions.mix(BAYSOR_RUN.out.versions) // run xeniumranger import-segmentation ch_imp_seg_inputs = ch_bundle_path - .combine(BAYSOR_RUN.out.segmentation, by: 0) - .map { - meta, bundle, segmentation_csv, polygons2d -> - tuple ( - meta, // meta - bundle, // bundle - [], // coordinate_transform - [], // nuclei - [], // cells - segmentation_csv, // transcript_assignment - polygons2d, // viz_polygons - ch_coordinate_space.val // units - ) - } - - XENIUMRANGER_IMPORT_SEGMENTATION ( + .combine(BAYSOR_RUN.out.segmentation, by: 0) + .map { meta, bundle, segmentation_csv, polygons2d -> + tuple( + meta, + bundle, + [], + [], + [], + segmentation_csv, + polygons2d, + ch_coordinate_space.val, + ) + } + + XENIUMRANGER_IMPORT_SEGMENTATION( ch_imp_seg_inputs ) - ch_versions = ch_versions.mix( XENIUMRANGER_IMPORT_SEGMENTATION.out.versions ) + ch_versions = ch_versions.mix(XENIUMRANGER_IMPORT_SEGMENTATION.out.versions) ch_redefined_bundle = XENIUMRANGER_IMPORT_SEGMENTATION.out.bundle emit: - - coordinate_space = ch_coordinate_space // channel: [ ["microns"] ] - - redefined_bundle = ch_redefined_bundle // channel: [ val(meta), "redefined-xenium-bundle" ] - - versions = ch_versions // channel: [ versions.yml ] + coordinate_space = ch_coordinate_space // channel: [ ["microns"] ] + redefined_bundle = ch_redefined_bundle // channel: [ val(meta), "redefined-xenium-bundle" ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/cellpose_baysor_import_segmentation/main.nf b/subworkflows/local/cellpose_baysor_import_segmentation/main.nf index dda337e5..2230665a 100644 --- a/subworkflows/local/cellpose_baysor_import_segmentation/main.nf +++ b/subworkflows/local/cellpose_baysor_import_segmentation/main.nf @@ -7,161 +7,152 @@ include { BAYSOR_RUN } from '../../../modules/local/baysor include { CELLPOSE as CELLPOSE_CELLS } from '../../../modules/nf-core/cellpose/main' include { CELLPOSE as CELLPOSE_NUCLEI } from '../../../modules/nf-core/cellpose/main' include { BAYSOR_PREPROCESS_TRANSCRIPTS } from '../../../modules/local/baysor/preprocess/main' +include { RESIZE_TIF } from '../../../modules/local/utility/resize_tif/main' include { XENIUMRANGER_IMPORT_SEGMENTATION } from '../../../modules/nf-core/xeniumranger/import-segmentation/main' workflow CELLPOSE_BAYSOR_IMPORT_SEGMENTATION { - take: - - ch_morphology_image // channel: [ val(meta), ["path-to-morphology.ome.tif"] ] - ch_bundle_path // channel: [ val(meta), ["path-to-xenium-bundle"] ] - ch_transcripts_parquet // channel: [ val(meta), ["path-to-transcripts.parquet"] ] - ch_config // channel: ["path-to-xenium.toml"] + ch_morphology_image // channel: [ val(meta), ["path-to-morphology.ome.tif"] ] + ch_bundle_path // channel: [ val(meta), ["path-to-xenium-bundle"] ] + ch_transcripts_parquet // channel: [ val(meta), ["path-to-transcripts.parquet"] ] + ch_config // channel: ["path-to-xenium.toml"] main: - ch_versions = Channel.empty() - ch_transcripts = Channel.empty() - ch_imp_seg_inputs = Channel.empty() - ch_filtered_transcripts = Channel.empty() - ch_coordinate_space = Channel.value("microns") + ch_versions = Channel.empty() + ch_transcripts = Channel.empty() + ch_imp_seg_inputs = Channel.empty() + ch_filtered_transcripts = Channel.empty() + ch_coordinate_space = Channel.value("microns") cellpose_model = params.cellpose_model ? (Channel.fromPath(params.cellpose_model, checkIfExists: true)) : [] // sharpen morphology tiff if param - sharpen_tiff is true - if ( params.sharpen_tiff ) { + if (params.sharpen_tiff) { - RESOLIFT ( ch_morphology_image ) - ch_versions = ch_versions.mix( RESOLIFT.out.versions ) + RESOLIFT(ch_morphology_image) + ch_versions = ch_versions.mix(RESOLIFT.out.versions) ch_image = RESOLIFT.out.enhanced_tiff - - } else { + } + else { ch_image = ch_morphology_image - } // run cellpose on the morphology (enhanced) tiff - if ( params.cell_segmentation_only ) { - - CELLPOSE_CELLS ( ch_image, cellpose_model, 'cells' ) - ch_versions = ch_versions.mix( CELLPOSE_CELLS.out.versions ) + if (params.cell_segmentation_only) { + CELLPOSE_CELLS(ch_image, cellpose_model, 'cells') + ch_versions = ch_versions.mix(CELLPOSE_CELLS.out.versions) } - if ( params.nucleus_segmentation_only ) { - - CELLPOSE_NUCLEI ( ch_image, 'nuclei', 'nuclei' ) - ch_versions = ch_versions.mix( CELLPOSE_NUCLEI.out.versions ) + if (params.nucleus_segmentation_only) { + CELLPOSE_NUCLEI(ch_image, 'nuclei', 'nuclei') + ch_versions = ch_versions.mix(CELLPOSE_NUCLEI.out.versions) } // filter transcripts.parquet based on thresholds - if ( params.filter_transcripts ) { + if (params.filter_transcripts) { - BAYSOR_PREPROCESS_TRANSCRIPTS ( + BAYSOR_PREPROCESS_TRANSCRIPTS( ch_transcripts_parquet, params.min_qv, params.max_x, params.min_x, params.max_y, - params.min_y + params.min_y, ) - ch_versions = ch_versions.mix ( BAYSOR_PREPROCESS_TRANSCRIPTS.out.versions ) + ch_versions = ch_versions.mix(BAYSOR_PREPROCESS_TRANSCRIPTS.out.versions) ch_filtered_transcripts = BAYSOR_PREPROCESS_TRANSCRIPTS.out.transcripts_parquet ch_transcripts = ch_filtered_transcripts - - } else { + } + else { ch_transcripts = ch_transcripts_parquet } // run baysor with cellpose results - if ( params.nucleus_segmentation_only ) { + if (params.nucleus_segmentation_only) { // run baysor with nuclei mask ch_baysor_input = ch_transcripts - .combine(CELLPOSE_NUCLEI.out.mask, by: 0) - .combine(ch_config) - .map { meta, transcripts, mask, config -> - tuple ( - meta, // meta - transcripts, // transcripts - mask, // prior_segmentation - config, // config - 30 // scale - ) - } - BAYSOR_RUN ( ch_baysor_input ) - ch_versions = ch_versions.mix ( BAYSOR_RUN.out.versions ) - - } else if ( params.cell_segmentation_only ) { + .combine(CELLPOSE_NUCLEI.out.mask, by: 0) + .combine(ch_config) + .map { meta, transcripts, mask, config -> + tuple( + meta, + transcripts, + mask, + config, + 30, + ) + } + BAYSOR_RUN(ch_baysor_input) + ch_versions = ch_versions.mix(BAYSOR_RUN.out.versions) + } + else if (params.cell_segmentation_only) { // run baysor with cell mask ch_baysor_input = ch_transcripts - .combine(CELLPOSE_CELLS.out.mask, by: 0) - .combine(ch_config) - .map { meta, transcripts, mask, config -> - tuple ( - meta, // meta - transcripts, // transcripts - mask, // prior_segmentation - config, // config - 30 // scale - ) - } - BAYSOR_RUN ( ch_baysor_input ) - ch_versions = ch_versions.mix ( BAYSOR_RUN.out.versions ) - - } else { + .combine(CELLPOSE_CELLS.out.mask, by: 0) + .combine(ch_config) + .map { meta, transcripts, mask, config -> + tuple( + meta, + transcripts, + mask, + config, + 30, + ) + } + BAYSOR_RUN(ch_baysor_input) + ch_versions = ch_versions.mix(BAYSOR_RUN.out.versions) + } + else { // run baysor without cell/nuclei mask ch_baysor_input = ch_transcripts - .combine(ch_config) - .map { meta, transcripts, config -> - tuple ( - meta, // meta - transcripts, // transcripts - [], // prior_segmentation - config, // config - 30 // scale - ) - } - BAYSOR_RUN ( ch_baysor_input ) - ch_versions = ch_versions.mix ( BAYSOR_RUN.out.versions ) - + .combine(ch_config) + .map { meta, transcripts, config -> + tuple( + meta, + transcripts, + [], + config, + 30, + ) + } + BAYSOR_RUN(ch_baysor_input) + ch_versions = ch_versions.mix(BAYSOR_RUN.out.versions) } // run import-segmentation with baysor outs ch_imp_seg_inputs = ch_bundle_path - .combine(BAYSOR_RUN.out.segmentation, by: 0) - .map { - meta, bundle, segmentation_csv, polygons2d -> - tuple ( - meta, // meta - bundle, // bundle - [], // coordinate_transform - [], // nuclei - [], // cells - segmentation_csv, // transcript_assignment - polygons2d, // viz_polygons - ch_coordinate_space.val // units - ) - } - - XENIUMRANGER_IMPORT_SEGMENTATION ( ch_imp_seg_inputs ) - ch_versions = ch_versions.mix ( XENIUMRANGER_IMPORT_SEGMENTATION.out.versions ) + .combine(BAYSOR_RUN.out.segmentation, by: 0) + .map { meta, bundle, segmentation_csv, polygons2d -> + tuple( + meta, + bundle, + [], + [], + [], + segmentation_csv, + polygons2d, + ch_coordinate_space.val, + ) + } + + XENIUMRANGER_IMPORT_SEGMENTATION(ch_imp_seg_inputs) + ch_versions = ch_versions.mix(XENIUMRANGER_IMPORT_SEGMENTATION.out.versions) emit: - - coordinate_space = ch_coordinate_space // channel: [ val("microns") ] - + coordinate_space = ch_coordinate_space // channel: [ val("microns") ] redefined_bundle = XENIUMRANGER_IMPORT_SEGMENTATION.out.bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] - - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/cellpose_resolift_morphology_ome_tif/main.nf b/subworkflows/local/cellpose_resolift_morphology_ome_tif/main.nf index 5d5216aa..737656bb 100644 --- a/subworkflows/local/cellpose_resolift_morphology_ome_tif/main.nf +++ b/subworkflows/local/cellpose_resolift_morphology_ome_tif/main.nf @@ -8,94 +8,86 @@ include { CELLPOSE as CELLPOSE_NUCLEI } from '../../../modules/nf-core/cell include { XENIUMRANGER_IMPORT_SEGMENTATION } from '../../../modules/nf-core/xeniumranger/import-segmentation/main' workflow CELLPOSE_RESOLIFT_MORPHOLOGY_OME_TIF { - take: - - ch_morphology_image // channel: [ val(meta), ["path-to-morphology.ome.tiff"] ] - ch_bundle_path // channel: [ val(meta), ["path-to-xenium-bundle"] ] + ch_morphology_image // channel: [ val(meta), ["path-to-morphology.ome.tiff"] ] + ch_bundle_path // channel: [ val(meta), ["path-to-xenium-bundle"] ] main: - ch_versions = Channel.empty() - ch_imp_seg_inputs = Channel.empty() - ch_coordinate_space = Channel.value("pixels") + ch_versions = Channel.empty() + ch_imp_seg_inputs = Channel.empty() + ch_coordinate_space = Channel.value("pixels") cellpose_model = params.cellpose_model ? (Channel.fromPath(params.cellpose_model, checkIfExists: true)) : [] // sharpen morphology tiff if param - sharpen_tiff is true - if ( params.sharpen_tiff ) { + if (params.sharpen_tiff) { - RESOLIFT ( ch_morphology_image ) - ch_versions = ch_versions.mix( RESOLIFT.out.versions ) + RESOLIFT(ch_morphology_image) + ch_versions = ch_versions.mix(RESOLIFT.out.versions) ch_image = RESOLIFT.out.enhanced_tiff - - } else { + } + else { ch_image = ch_morphology_image - } // run cellpose on morphology tiff - CELLPOSE_CELLS ( ch_image, cellpose_model, 'cells' ) - ch_versions = ch_versions.mix( CELLPOSE_CELLS.out.versions ) + CELLPOSE_CELLS(ch_image, cellpose_model, 'cells') + ch_versions = ch_versions.mix(CELLPOSE_CELLS.out.versions) - CELLPOSE_NUCLEI ( ch_image, 'nuclei', 'nuclei' ) - ch_versions = ch_versions.mix( CELLPOSE_NUCLEI.out.versions ) + CELLPOSE_NUCLEI(ch_image, 'nuclei', 'nuclei') + ch_versions = ch_versions.mix(CELLPOSE_NUCLEI.out.versions) // run import-segmentation with cellpose results - if ( params.nucleus_segmentation_only ) { + if (params.nucleus_segmentation_only) { ch_imp_seg_inputs = ch_bundle_path - .combine(CELLPOSE_NUCLEI.out.cells, by: 0) - .map { - meta, bundle, nuclei_seg -> - tuple ( - meta, // meta - bundle, // bundle - [], // coordinate_transform - nuclei_seg, // nuclei - [], // cells - [], // transcript_assignment - [], // viz_polygons - ch_coordinate_space.val // units - ) - } - XENIUMRANGER_IMPORT_SEGMENTATION ( + .combine(CELLPOSE_NUCLEI.out.cells, by: 0) + .map { meta, bundle, nuclei_seg -> + tuple( + meta, + bundle, + [], + nuclei_seg, + [], + [], + [], + ch_coordinate_space.val, + ) + } + XENIUMRANGER_IMPORT_SEGMENTATION( ch_imp_seg_inputs ) - ch_versions = ch_versions.mix( XENIUMRANGER_IMPORT_SEGMENTATION.out.versions ) - - } else { + ch_versions = ch_versions.mix(XENIUMRANGER_IMPORT_SEGMENTATION.out.versions) + } + else { ch_imp_seg_inputs = ch_bundle_path - .combine(CELLPOSE_CELLS.out.cells, by:0) - .combine(CELLPOSE_NUCLEI.out.cells, by:0) - .map { - meta, bundle, cells_seg, nuclei_seg -> tuple ( - meta, // meta - bundle, // bundle - [], // coordinate_transform - nuclei_seg, // nuclei - cells_seg, // cells - [], // transcript_assignment - [], // viz_polygons - ch_coordinate_space.val // units - ) - } - ch_imp_seg_inputs.view() - XENIUMRANGER_IMPORT_SEGMENTATION ( + .combine(CELLPOSE_CELLS.out.cells, by: 0) + .combine(CELLPOSE_NUCLEI.out.cells, by: 0) + .map { meta, bundle, cells_seg, nuclei_seg -> + tuple( + meta, + bundle, + [], + nuclei_seg, + cells_seg, + [], + [], + ch_coordinate_space.val, + ) + } + XENIUMRANGER_IMPORT_SEGMENTATION( ch_imp_seg_inputs ) - ch_versions = ch_versions.mix( XENIUMRANGER_IMPORT_SEGMENTATION.out.versions ) + ch_versions = ch_versions.mix(XENIUMRANGER_IMPORT_SEGMENTATION.out.versions) } emit: - - coordinate_space = ch_coordinate_space // channel: [ ["pixels"] ] - + coordinate_space = ch_coordinate_space // channel: [ ["pixels"] ] redefined_bundle = XENIUMRANGER_IMPORT_SEGMENTATION.out.bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] - - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/ficture_preprocess_model/main.nf b/subworkflows/local/ficture_preprocess_model/main.nf index 7c8d01c7..c2d12c87 100644 --- a/subworkflows/local/ficture_preprocess_model/main.nf +++ b/subworkflows/local/ficture_preprocess_model/main.nf @@ -9,9 +9,7 @@ include { PARQUET_TO_CSV } from '../../../modules/local/utility/spatialconve workflow FICTURE_PREPROCESS_MODEL { - take: - ch_transcripts_parquet // channel: [ val(meta), [ "transcripts.parquet" ] ] ch_features // channel: [ ["features"] ] @@ -20,34 +18,31 @@ workflow FICTURE_PREPROCESS_MODEL { ch_versions = Channel.empty() // convert parquet to csv - PARQUET_TO_CSV ( ch_transcripts_parquet, ".csv" ) - ch_versions = ch_versions.mix ( PARQUET_TO_CSV.out.versions ) + PARQUET_TO_CSV(ch_transcripts_parquet, ".csv") + ch_versions = ch_versions.mix(PARQUET_TO_CSV.out.versions) // run ficture preprocessing ch_transcripts = PARQUET_TO_CSV.out.transcripts_csv - FICTURE_PREPROCESS ( ch_transcripts, ch_features ) - ch_versions = ch_versions.mix ( FICTURE_PREPROCESS.out.versions ) + FICTURE_PREPROCESS(ch_transcripts, ch_features) + ch_versions = ch_versions.mix(FICTURE_PREPROCESS.out.versions) // run the ficture wrapper pipeline ch_features_clean = Channel.empty() - if ( params.features ) { + if (params.features) { ch_features_clean = FICTURE_PREPROCESS.out.features } - FICTURE ( + FICTURE( FICTURE_PREPROCESS.out.transcripts, FICTURE_PREPROCESS.out.coordinate_minmax, - ch_features_clean + ch_features_clean, ) - ch_versions = ch_versions.mix( FICTURE.out.versions ) + ch_versions = ch_versions.mix(FICTURE.out.versions) emit: - - transcripts = FICTURE_PREPROCESS.out.transcripts // channel: [ val(meta), [ "*processed_transcripts.tsv.gz" ] ] - coordinate_minmax = FICTURE_PREPROCESS.out.coordinate_minmax // channel: [ "*coordinate_minmax.tsv" ] - features = FICTURE_PREPROCESS.out.features // channel: [ "*feature.clean.tsv.gz" ] - - results = FICTURE.out.results // channel: [ val(meta), [ "results/** ] ] - - versions = ch_versions // channel: [ versions.yml ] + transcripts = FICTURE_PREPROCESS.out.transcripts // channel: [ val(meta), [ "*processed_transcripts.tsv.gz" ] ] + coordinate_minmax = FICTURE_PREPROCESS.out.coordinate_minmax // channel: [ "*coordinate_minmax.tsv" ] + features = FICTURE_PREPROCESS.out.features // channel: [ "*feature.clean.tsv.gz" ] + results = FICTURE.out.results // channel: [ val(meta), [ "results/** ] ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/opt_flip_track_stat/main.nf b/subworkflows/local/opt_flip_track_stat/main.nf index 66272ef9..916268ad 100644 --- a/subworkflows/local/opt_flip_track_stat/main.nf +++ b/subworkflows/local/opt_flip_track_stat/main.nf @@ -4,9 +4,7 @@ include { OPT_STAT } from '../../../modules/nf-core/opt/stat/main' workflow OPT_FLIP_TRACK_STAT { - take: - ch_probe_fasta // channel: [ val(meta), [ "panel_probes_sequences.fasta" ] ] ch_references // channel: [ val(meta), ["reference_annotations.gff"], ["reference_annotations.fa"] ] ch_gene_synonyms // channel: [ "path-to-gene-synonyms" ] @@ -14,25 +12,23 @@ workflow OPT_FLIP_TRACK_STAT { main: ch_versions = Channel.empty() - ch_summary = Channel.empty() + ch_summary = Channel.empty() // correct probes that are aligning to opposite strand with `flip` - OPT_FLIP ( ch_probe_fasta, ch_references ) - ch_versions = ch_versions.mix( OPT_FLIP.out.versions ) + OPT_FLIP(ch_probe_fasta, ch_references) + ch_versions = ch_versions.mix(OPT_FLIP.out.versions) // align query probe sequences to target transcriptome - OPT_TRACK ( OPT_FLIP.out.fwd_oriented_fa, ch_references ) - ch_versions = ch_versions.mix( OPT_TRACK.out.versions ) + OPT_TRACK(OPT_FLIP.out.fwd_oriented_fa, ch_references) + ch_versions = ch_versions.mix(OPT_TRACK.out.versions) // summarizes opt binding predictions - OPT_STAT ( OPT_TRACK.out.probes2target, OPT_FLIP.out.fwd_oriented_fa, ch_gene_synonyms ) - ch_versions = ch_versions.mix( OPT_STAT.out.versions ) + OPT_STAT(OPT_TRACK.out.probes2target, OPT_FLIP.out.fwd_oriented_fa, ch_gene_synonyms) + ch_versions = ch_versions.mix(OPT_STAT.out.versions) ch_summary = OPT_STAT.out.summary emit: - - summary = ch_summary // channel: [ val(meta), ["collapsed_summary.tsv", "other-summary-files"]] - - versions = ch_versions // channel: [ versions.yml ] + summary = ch_summary // channel: [ val(meta), ["collapsed_summary.tsv", "other-summary-files"]] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/proseg_preset_proseg2baysor/main.nf b/subworkflows/local/proseg_preset_proseg2baysor/main.nf index d0314e26..7df31af2 100644 --- a/subworkflows/local/proseg_preset_proseg2baysor/main.nf +++ b/subworkflows/local/proseg_preset_proseg2baysor/main.nf @@ -7,9 +7,7 @@ include { PROSEG2BAYSOR } from '../../../modules/local/proseg include { XENIUMRANGER_IMPORT_SEGMENTATION } from '../../../modules/nf-core/xeniumranger/import-segmentation/main' workflow PROSEG_PRESET_PROSEG2BAYSOR { - take: - ch_bundle_path // channel: [ val(meta), ["path-to-xenium-bundle"] ] ch_transcripts_parquet // channel: [ val(meta), [ "transcripts.parquet" ] ] @@ -19,42 +17,39 @@ workflow PROSEG_PRESET_PROSEG2BAYSOR { ch_coordinate_space = Channel.value("microns") // run proseg with the xenium format - PROSEG ( ch_transcripts_parquet ) - ch_versions = ch_versions.mix ( PROSEG.out.versions ) + PROSEG(ch_transcripts_parquet) + ch_versions = ch_versions.mix(PROSEG.out.versions) // run proseg-to-baysor on the data generated with the proseg run - PROSEG2BAYSOR ( PROSEG.out.seg_outs ) - ch_versions = ch_versions.mix ( PROSEG2BAYSOR.out.versions ) + PROSEG2BAYSOR(PROSEG.out.seg_outs) + ch_versions = ch_versions.mix(PROSEG2BAYSOR.out.versions) // run xeniumranger import-segmentation ch_imp_seg_inputs = ch_bundle_path - .combine( PROSEG2BAYSOR.out.xr_metadata, by: 0 ) - .combine( PROSEG2BAYSOR.out.xr_polygons, by: 0 ) - .map { - meta, bundle, metadata, polygons2d -> tuple ( - meta, // meta - bundle, // bundle - [], // coordinate_transform - [], // nuclei - [], // cells - metadata, // transcript_assignment - polygons2d, // viz_polygons - ch_coordinate_space.val // units - ) - } - - XENIUMRANGER_IMPORT_SEGMENTATION ( + .combine(PROSEG2BAYSOR.out.xr_metadata, by: 0) + .combine(PROSEG2BAYSOR.out.xr_polygons, by: 0) + .map { meta, bundle, metadata, polygons2d -> + tuple( + meta, + bundle, + [], + [], + [], + metadata, + polygons2d, + ch_coordinate_space.val, + ) + } + + XENIUMRANGER_IMPORT_SEGMENTATION( ch_imp_seg_inputs ) - ch_versions = ch_versions.mix ( XENIUMRANGER_IMPORT_SEGMENTATION.out.versions ) + ch_versions = ch_versions.mix(XENIUMRANGER_IMPORT_SEGMENTATION.out.versions) emit: - - coordinate_space = ch_coordinate_space // channel: [ "microns" ] - - redefined_bundle = XENIUMRANGER_IMPORT_SEGMENTATION.out.bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] - - versions = ch_versions // channel: [ versions.yml ] + coordinate_space = ch_coordinate_space // channel: [ "microns" ] + redefined_bundle = XENIUMRANGER_IMPORT_SEGMENTATION.out.bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/segger_create_train_predict/main.nf b/subworkflows/local/segger_create_train_predict/main.nf index 52423e0d..fd5f00dd 100644 --- a/subworkflows/local/segger_create_train_predict/main.nf +++ b/subworkflows/local/segger_create_train_predict/main.nf @@ -9,106 +9,55 @@ include { SEGGER_CREATE_DATASET } from '../../../modules/local/segger include { XENIUMRANGER_IMPORT_SEGMENTATION } from '../../../modules/nf-core/xeniumranger/import-segmentation/main' workflow SEGGER_CREATE_TRAIN_PREDICT { - take: - ch_bundle // channel: [ val(meta), ["path-to-xenium-bundle"] ] ch_transcripts_parquet // channel: [ val(meta), [bundle + "/transcripts.parquet"]] - main: - ch_versions = Channel.empty() + ch_versions = Channel.empty() - ch_updated_bundle = Channel.empty() - ch_redefined_bundle = Channel.empty() - ch_segger_transcripts = Channel.empty() - ch_coordinate_space = Channel.value("pixels") + ch_updated_bundle = Channel.empty() + ch_redefined_bundle = Channel.empty() + ch_coordinate_space = Channel.value("pixels") // create dataset - SEGGER_CREATE_DATASET ( ch_bundle ) - ch_versions = ch_versions.mix ( SEGGER_CREATE_DATASET.out.versions ) + SEGGER_CREATE_DATASET(ch_bundle) + ch_versions = ch_versions.mix(SEGGER_CREATE_DATASET.out.versions) // train a model with the dataset created - SEGGER_TRAIN ( SEGGER_CREATE_DATASET.out.datasetdir ) - ch_versions = ch_versions.mix ( SEGGER_TRAIN.out.versions ) + SEGGER_TRAIN(SEGGER_CREATE_DATASET.out.datasetdir) + ch_versions = ch_versions.mix(SEGGER_TRAIN.out.versions) // run prediction with the trained models - ch_just_trained_models = SEGGER_TRAIN.out.trained_models.map { - _meta, models -> return [ models ] + ch_just_trained_models = SEGGER_TRAIN.out.trained_models.map { _meta, models -> + return [models] } - ch_just_transcripts_parquet = ch_transcripts_parquet.map { - _meta, transcripts -> return [ transcripts ] + ch_just_transcripts_parquet = ch_transcripts_parquet.map { _meta, transcripts -> + return [transcripts] } - SEGGER_PREDICT ( + SEGGER_PREDICT( SEGGER_CREATE_DATASET.out.datasetdir, ch_just_trained_models, - ch_just_transcripts_parquet + ch_just_transcripts_parquet, ) - ch_versions = ch_versions.mix ( SEGGER_PREDICT.out.versions ) + ch_versions = ch_versions.mix(SEGGER_PREDICT.out.versions) // convert parquet to XR compatible form - SEGGER2XR ( SEGGER_PREDICT.out.transcripts ) - ch_versions = ch_versions.mix( SEGGER2XR.out.versions ) + SEGGER2XR(SEGGER_PREDICT.out.transcripts) + ch_versions = ch_versions.mix(SEGGER2XR.out.versions) - ch_segger_transcripts_parquet = SEGGER2XR.out.transcripts_parquet.map { - _meta, transcripts -> return [ transcripts ] + ch_segger_transcripts_parquet = SEGGER2XR.out.transcripts_parquet.map { _meta, transcripts -> + return [transcripts] } - // swap transscripts.parquet with segger transcripts ch_updated_bundle = ch_bundle.map { _meta, fileobj -> fileobj == "transcripts.parquet" ? ch_segger_transcripts_parquet : fileobj } - - // run xeniumranger import-segmentation - // cells = ch_updated_bundle.map { _meta, bundle -> - // return [ bundle + "/cells.zarr.zip" ] - // } - - // if ( params.nucleus_segmentation_only ) { - - // XENIUMRANGER_IMPORT_SEGMENTATION ( - // ch_updated_bundle, - // [], - // cells, - // cells, - // [], - // [], - // ch_coordinate_space - // ) - // ch_redefined_bundle = XENIUMRANGER_IMPORT_SEGMENTATION.out.bundle - - // ch_versions = ch_versions.mix ( XENIUMRANGER_IMPORT_SEGMENTATION.out.versions ) - - // } else { - - // XENIUMRANGER_IMPORT_SEGMENTATION ( - // ch_updated_bundle, - // [], - // [], - // cells, - // [], - // [], - // ch_coordinate_space - // ) - // ch_redefined_bundle = XENIUMRANGER_IMPORT_SEGMENTATION.out.bundle - - // ch_versions = ch_versions.mix ( XENIUMRANGER_IMPORT_SEGMENTATION.out.versions ) - - // } - emit: - - datasetdir = SEGGER_CREATE_DATASET.out.datasetdir // channel: [ val(meta), [ datasetdir ] ] - trained_models = SEGGER_TRAIN.out.trained_models // channel: [ val(meta), [ trained_models ] ] - benchmarks = SEGGER_PREDICT.out.benchmarks // channel: [ val(meta), [ benchmarks ] ] - segger_transcripts = ch_segger_transcripts // channel: [ [ transcripts.parquet ] ] - - coordinate_space = ch_coordinate_space // channel: [ ["pixels"] ] - - redefined_bundle = ch_redefined_bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] - - versions = ch_versions // channel: [ versions.yml ] + coordinate_space = ch_coordinate_space // channel: [ ["pixels"] ] + redefined_bundle = ch_redefined_bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/spatialdata_write_meta_merge/main.nf b/subworkflows/local/spatialdata_write_meta_merge/main.nf index fc53a282..6b569433 100644 --- a/subworkflows/local/spatialdata_write_meta_merge/main.nf +++ b/subworkflows/local/spatialdata_write_meta_merge/main.nf @@ -8,77 +8,75 @@ include { SPATIALDATA_MERGE as SPATIALDATA_MERGE_RAW_REDEFINED } from '../../ include { SPATIALDATA_WRITE as SPATIALDATA_WRITE_REDEFINED_BUNDLE } from '../../../modules/local/spatialdata/write/main' workflow SPATIALDATA_WRITE_META_MERGE { - take: - ch_bundle_path // channel: [ val(meta), [ "path-to-xenium-bundle" ] ] - ch_redefined_bundle // channel: [ val(meta), [ "redefined-xenium-bundle" ] ] - ch_coordinate_space // channel: [ "pixels" or "microns" ] + ch_bundle_path // channel: [ val(meta), [ "path-to-xenium-bundle" ] ] + ch_redefined_bundle // channel: [ val(meta), [ "redefined-xenium-bundle" ] ] + ch_coordinate_space // channel: [ "pixels" or "microns" ] main: - ch_versions = Channel.empty() + ch_versions = Channel.empty() ch_segmented_object = Channel.empty() // check segmentation - only nuclei, cells or both cells & nuclei - if ( params.mode == 'image') { + if (params.mode == 'image') { - if ( params.nucleus_segmentation_only && params.cell_segmentation_only ) { + if (params.nucleus_segmentation_only && params.cell_segmentation_only) { ch_segmented_object = Channel.value('cells_and_nuclei') } - else if ( params.nucleus_segmentation_only ) { + else if (params.nucleus_segmentation_only) { ch_segmented_object = Channel.value('nuclei') } - else if ( params.cell_segmentation_only ) { + else if (params.cell_segmentation_only) { ch_segmented_object = Channel.value('cells') - } else { + } + else { ch_segmented_object = Channel.value([]) } } // set all boundaries as false - default - if ( params.mode == 'coordinate') { + if (params.mode == 'coordinate') { ch_segmented_object = Channel.value([]) } // write spatialdata object from the raw xenium bundle - SPATIALDATA_WRITE_RAW_BUNDLE ( + SPATIALDATA_WRITE_RAW_BUNDLE( ch_bundle_path, 'spatialdata_raw', ch_segmented_object, - ch_coordinate_space + ch_coordinate_space, ) - ch_versions = ch_versions.mix ( SPATIALDATA_WRITE_RAW_BUNDLE.out.versions ) + ch_versions = ch_versions.mix(SPATIALDATA_WRITE_RAW_BUNDLE.out.versions) // write spatialdata object after running IMP_SEG - SPATIALDATA_WRITE_REDEFINED_BUNDLE ( + SPATIALDATA_WRITE_REDEFINED_BUNDLE( ch_redefined_bundle, 'spatialdata_redefined', ch_segmented_object, - ch_coordinate_space + ch_coordinate_space, ) - ch_versions = ch_versions.mix ( SPATIALDATA_WRITE_REDEFINED_BUNDLE.out.versions ) + ch_versions = ch_versions.mix(SPATIALDATA_WRITE_REDEFINED_BUNDLE.out.versions) // merge raw & redefined spatialdata objects - SPATIALDATA_MERGE_RAW_REDEFINED ( - SPATIALDATA_WRITE_RAW_BUNDLE.out.spatialdata.combine( ch_redefined_bundle, by: 0 ) + SPATIALDATA_MERGE_RAW_REDEFINED( + SPATIALDATA_WRITE_RAW_BUNDLE.out.spatialdata.combine(ch_redefined_bundle, by: 0) ) - ch_versions = ch_versions.mix ( SPATIALDATA_MERGE_RAW_REDEFINED.out.versions ) + ch_versions = ch_versions.mix(SPATIALDATA_MERGE_RAW_REDEFINED.out.versions) // write metadata with spatialdata object - SPATIALDATA_META ( - SPATIALDATA_MERGE_RAW_REDEFINED.out.merged_bundle.combine( ch_bundle_path, by: 0 ) + SPATIALDATA_META( + SPATIALDATA_MERGE_RAW_REDEFINED.out.merged_bundle.combine(ch_bundle_path, by: 0) ) - ch_versions = ch_versions.mix ( SPATIALDATA_META.out.versions ) + ch_versions = ch_versions.mix(SPATIALDATA_META.out.versions) emit: - - sd_raw_bundle = SPATIALDATA_WRITE_RAW_BUNDLE.out.spatialdata // channel: [ val(meta), "spatialdata_raw" ] - sd_redefined_bundle = SPATIALDATA_WRITE_REDEFINED_BUNDLE.out.spatialdata // channel: [ val(meta), "spatialdata_redefined" ] - sd_merged_bundle = SPATIALDATA_MERGE_RAW_REDEFINED.out.merged_bundle // channel: [ val(meta), "spatialdata_merged" ] - sd_metadata = SPATIALDATA_META.out.metadata // channel: [ val(meta), "spatialdata_meta" ] - - versions = ch_versions // channel: [ versions.yml ] + sd_raw_bundle = SPATIALDATA_WRITE_RAW_BUNDLE.out.spatialdata // channel: [ val(meta), "spatialdata_raw" ] + sd_redefined_bundle = SPATIALDATA_WRITE_REDEFINED_BUNDLE.out.spatialdata // channel: [ val(meta), "spatialdata_redefined" ] + sd_merged_bundle = SPATIALDATA_MERGE_RAW_REDEFINED.out.merged_bundle // channel: [ val(meta), "spatialdata_merged" ] + sd_metadata = SPATIALDATA_META.out.metadata // channel: [ val(meta), "spatialdata_meta" ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/utils_nfcore_spatialxe_pipeline/main.nf b/subworkflows/local/utils_nfcore_spatialxe_pipeline/main.nf index 184f4ab0..5f1ba189 100644 --- a/subworkflows/local/utils_nfcore_spatialxe_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_spatialxe_pipeline/main.nf @@ -8,14 +8,14 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' -include { paramsSummaryMap } from 'plugin/nf-schema' -include { samplesheetToList } from 'plugin/nf-schema' -include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' -include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' -include { imNotification } from '../../nf-core/utils_nfcore_pipeline' -include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' -include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' +include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' +include { paramsSummaryMap } from 'plugin/nf-schema' +include { samplesheetToList } from 'plugin/nf-schema' +include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' +include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' +include { imNotification } from '../../nf-core/utils_nfcore_pipeline' +include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' +include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -24,7 +24,6 @@ include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipelin */ workflow PIPELINE_INITIALISATION { - take: version // boolean: Display version and exit validate_params // boolean: Boolean whether to validate parameters against the schema at runtime @@ -40,26 +39,26 @@ workflow PIPELINE_INITIALISATION { // // Print version and exit if required and dump pipeline parameters to JSON file // - UTILS_NEXTFLOW_PIPELINE ( + UTILS_NEXTFLOW_PIPELINE( version, true, outdir, - workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1 + workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1, ) // // Validate parameters and generate parameter summary to stdout // - UTILS_NFSCHEMA_PLUGIN ( + UTILS_NFSCHEMA_PLUGIN( workflow, validate_params, - null + null, ) // // Check config provided to the pipeline // - UTILS_NFCORE_PIPELINE ( + UTILS_NFCORE_PIPELINE( nextflow_cli_args ) @@ -67,43 +66,38 @@ workflow PIPELINE_INITIALISATION { // Custom validation for pipeline parameters // validateInputParameters() - log.info "INFO Pipeline parameters validated ✅ " + log.info("INFO Pipeline parameters validated ✅ ") // // Create channel from input file provided through params.input // try { - Channel - .fromList(samplesheetToList(input, "${projectDir}/assets/schema_input.json")) - .map { - meta, bundle, image -> return [ [id: meta.id], bundle, image ] - } - .set { ch_samplesheet } - - log.info "INFO Samplesheet fields validated ✅ " + Channel.fromList(samplesheetToList(input, "${projectDir}/assets/schema_input.json")) + .map { meta, bundle, image -> + return [[id: meta.id], bundle, image] + } + .set { ch_samplesheet } - } catch (Exception e) { + log.info("INFO Samplesheet fields validated ✅ ") + } + catch (Exception e) { - log.error "❌ Samplesheet validation failed: ${e.message}" - exit 1 + log.error("❌ Samplesheet validation failed: ${e.message}") + exit(1) } // // Check and validate xenium bundle // - if ( !workflow.profile.contains('test')) { + if (!workflow.profile.contains('test')) { validateXeniumBundle(ch_samplesheet) } - emit: - samplesheet = ch_samplesheet versions = ch_versions - - } /* @@ -113,7 +107,6 @@ workflow PIPELINE_INITIALISATION { */ workflow PIPELINE_COMPLETION { - take: email // string: email address email_on_fail // string: email address sent on pipeline failure @@ -150,7 +143,7 @@ workflow PIPELINE_COMPLETION { } workflow.onError { - log.error "❌ Pipeline failed. Please refer to troubleshooting docs: https://nf-co.re/docs/usage/troubleshooting" + log.error("❌ Pipeline failed. Please refer to troubleshooting docs: https://nf-co.re/docs/usage/troubleshooting") } } @@ -165,48 +158,48 @@ workflow PIPELINE_COMPLETION { def validateInputParameters() { // check if the samplesheet provided with the test config is assets/samplesheet.csv - if ( workflow.profile.contains('test') && params.input != "${projectDir}/assets/samplesheet.csv" ) { - log.error "❌ Error: Use the samplesheet at: ${projectDir}/assets/samplesheet.csv with `--input` when running the pipeline in test profile." - exit 1 + if (workflow.profile.contains('test') && !"${params.input}".endsWith("assets/samplesheet.csv")) { + log.error("❌ Error: Use the samplesheet at: ${projectDir}/assets/samplesheet.csv with `--input` when running the pipeline in test profile.") + exit(1) } // check if the segmentation method provided is valid for a mode - if ( params.mode == 'image' && params.method ) { - if ( !params.image_seg_methods.contains(params.method) ) { - log.error "❌ Error: Invalid segmentation method: ${params.method} provided for the `image` based mode. Options: ${params.image_seg_methods}" - exit 1 + if (params.mode == 'image' && params.method) { + if (!params.image_seg_methods.contains(params.method)) { + log.error("❌ Error: Invalid segmentation method: ${params.method} provided for the `image` based mode. Options: ${params.image_seg_methods}") + exit(1) } } - if ( params.mode == 'coordinate' && params.method ) { - if ( !params.transcript_seg_methods.contains(params.method) ) { - log.error "❌ Error: Invalid segmentation method: `${params.method}` provided for the `coordinate` based mode. Options: ${params.transcript_seg_methods}" - exit 1 + if (params.mode == 'coordinate' && params.method) { + if (!params.transcript_seg_methods.contains(params.method)) { + log.error("❌ Error: Invalid segmentation method: `${params.method}` provided for the `coordinate` based mode. Options: ${params.transcript_seg_methods}") + exit(1) } } // check if --relabel_genes is true but --gene_panel is not provided - if ( params.relabel_genes && !params.gene_panel ) { - log.warn "⚠️ Relabel genes is enabled, but gene panel is not provided with the `--gene_panel`. Using `gene_panel.json` in the xenium bundle." + if (params.relabel_genes && !params.gene_panel) { + log.warn("⚠️ Relabel genes is enabled, but gene panel is not provided with the `--gene_panel`. Using `gene_panel.json` in the xenium bundle.") } // check if --relabel_genes is true but --gene_panel is not provided - if ( params.gene_panel && !params.relabel_genes ) { - log.warn "⚠️ Gene panel provided, but relabel genes is disabled. Using `gene_panel.json` only to generate metadata." + if (params.gene_panel && !params.relabel_genes) { + log.warn("⚠️ Gene panel provided, but relabel genes is disabled. Using `gene_panel.json` only to generate metadata.") } // check if segmentation method is xeniumranger and nucleus_ony_segmentation is enabled - if ( params.method == 'xeniumranger' && !params.nucleus_segmentation_only ) { - log.warn "⚠️ Nucleus segmentation is disabled. Running xeniumranger resegment module to redefine xenium bundle without nucleus segmentation." - log.warn "⚠️ Use --nucleus_segmentation_only to enable nucleus segmentation to redefine xenium bundle with import-segmentation module." + if (params.method == 'xeniumranger' && !params.nucleus_segmentation_only) { + log.warn("⚠️ Nucleus segmentation is disabled. Running xeniumranger resegment module to redefine xenium bundle without nucleus segmentation.") + log.warn("⚠️ Use --nucleus_segmentation_only to enable nucleus segmentation to redefine xenium bundle with import-segmentation module.") } // check if segmentation mask is provided in image mode and baysor method - if ( params.mode == 'image' && params.method == 'baysor' ) - if (!params.segmentation_mask ) { - log.warn "⚠️ Missing segmentation mask with `--segmentation_mask` when pipeline is run in ${params.mode} and with the ${params.method}. Running in coordinate mode." + if (params.mode == 'image' && params.method == 'baysor') { + if (!params.segmentation_mask) { + log.warn("⚠️ Missing segmentation mask with `--segmentation_mask` when pipeline is run in ${params.mode} and with the ${params.method}. Running in coordinate mode.") + } } - } // @@ -235,26 +228,25 @@ def validateXeniumBundle(ch_samplesheet) { "nucleus_boundaries.csv.gz", "nucleus_boundaries.parquet", "transcripts.parquet", - "transcripts.zarr.zip" + "transcripts.zarr.zip", ] // get bundle path - def ch_bundle_path = ch_samplesheet.map { - _meta, bundle, _image -> - def bundle_path = file ( - bundle.toString().replaceFirst(/\/$/, ''), + def ch_bundle_path = ch_samplesheet.map { _meta, bundle, _image -> + def bundle_path = file( + bundle.toString().replaceFirst(/\/$/, '') ) return bundle_path } // check if the path exists - if ( !ch_bundle_path.map { it.exists() } ) { - error "❌ Error: Xenium bundle path not found. Check if the path provided in the samplesheet exists." - exit 1 + if (!ch_bundle_path.map { it.exists() }) { + error("❌ Error: Xenium bundle path not found. Check if the path provided in the samplesheet exists.") + exit(1) } // if the path exists, check for the presence of xenium files - if ( ch_bundle_path.map { it.exists() } ) { + if (ch_bundle_path.map { it.exists() }) { ch_bundle_path.map { path -> def missing_files = [] @@ -265,16 +257,16 @@ def validateXeniumBundle(ch_samplesheet) { missing_files.add(filename) return false } - return true + return true } if (!allExist) { - log.error "❌ Missing file(s) at bundle path provided in the samplesheet: ${missing_files}" - exit 1 + log.error("❌ Missing file(s) at bundle path provided in the samplesheet: ${missing_files}") + exit(1) } } } - log.info "INFO Xenium bundle validated ✅ \n" + log.info("INFO Xenium bundle validated ✅ \n") } // @@ -285,10 +277,10 @@ def toolCitationText() { // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "Tool (Foo et al. 2023)" : "", // Uncomment function in methodsDescriptionText to render in MultiQC report def citation_text = [ - "Tools used in the workflow included:", - "MultiQC (Ewels et al. 2016)", - "." - ].join(' ').trim() + "Tools used in the workflow included:", + "MultiQC (Ewels et al. 2016)", + ".", + ].join(' ').trim() return citation_text } @@ -298,8 +290,8 @@ def toolBibliographyText() { // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "
  • Author (2023) Pub name, Journal, DOI
  • " : "", // Uncomment function in methodsDescriptionText to render in MultiQC report def reference_text = [ - "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics , 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " - ].join(' ').trim() + "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics , 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " + ].join(' ').trim() return reference_text } @@ -321,7 +313,10 @@ def methodsDescriptionText(mqc_methods_yaml) { temp_doi_ref += "(doi: ${doi_ref.replace("https://doi.org/", "").replace(" ", "")}), " } meta["doi_text"] = temp_doi_ref.substring(0, temp_doi_ref.length() - 2) - } else meta["doi_text"] = "" + } + else { + meta["doi_text"] = "" + } meta["nodoi_text"] = meta.manifest_map.doi ? "" : "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " // Tool references @@ -335,7 +330,7 @@ def methodsDescriptionText(mqc_methods_yaml) { def methods_text = mqc_methods_yaml.text - def engine = new groovy.text.SimpleTemplateEngine() + def engine = new groovy.text.SimpleTemplateEngine() def description_html = engine.createTemplate(methods_text).make(meta) return description_html.toString() diff --git a/subworkflows/local/xeniumranger_import_segmentation_redefine_bundle/main.nf b/subworkflows/local/xeniumranger_import_segmentation_redefine_bundle/main.nf index fd534b3b..f299ffc0 100644 --- a/subworkflows/local/xeniumranger_import_segmentation_redefine_bundle/main.nf +++ b/subworkflows/local/xeniumranger_import_segmentation_redefine_bundle/main.nf @@ -8,9 +8,7 @@ include { XENIUMRANGER_IMPORT_SEGMENTATION as IMP_SEG_TRANS_MATRIX_INPUT workflow XENIUMRANGER_IMPORT_SEGMENTATION_REDEFINE_BUNDLE { - take: - ch_bundle_path // channel: [ val(meta), [ "path-to-xenium-bundle" ] ] main: @@ -19,90 +17,86 @@ workflow XENIUMRANGER_IMPORT_SEGMENTATION_REDEFINE_BUNDLE { ch_redefined_bundle = Channel.empty() ch_coordinate_space = Channel.empty() - cells = ch_bundle_path.map { - meta, bundle -> return [ meta, bundle + "/cells.zarr.zip" ] + cells = ch_bundle_path.map { meta, bundle -> + return [meta, bundle + "/cells.zarr.zip"] } // scenario - 1 change nuclear expansion distance / create a nucleus-only count matrix(--expansion_distance=0) - if ( params.expansion_distance == 0 || params.expansion_distance != 5 ) { + if (params.expansion_distance == 0 || params.expansion_distance != 5) { ch_coordinate_space = "microns" ch_imp_seg_inputs = ch_bundle_path - .combine(cells, by:0) - .map { - meta, bundle, cells_zarr -> - tuple ( - meta, // meta - bundle, // bundle - [], // coordinate_transform - cells_zarr, // nuclei - [], // cells - [], // transcript_assignment - [], // viz_polygons - ch_coordinate_space.val // units - ) - } - - IMP_SEG_COUNT_MATRIX_EXP_DISTANCE ( + .combine(cells, by: 0) + .map { meta, bundle, cells_zarr -> + tuple( + meta, + bundle, + [], + cells_zarr, + [], + [], + [], + ch_coordinate_space.val, + ) + } + + IMP_SEG_COUNT_MATRIX_EXP_DISTANCE( ch_imp_seg_inputs ) ch_redefined_bundle = IMP_SEG_COUNT_MATRIX_EXP_DISTANCE.out.bundle - ch_versions = ch_versions.mix ( IMP_SEG_COUNT_MATRIX_EXP_DISTANCE.out.versions ) + ch_versions = ch_versions.mix(IMP_SEG_COUNT_MATRIX_EXP_DISTANCE.out.versions) } // scenario - 2 polygon input - geojson format (from QuPath) - if ( params.qupath_polygons && params.nucleus_segmentation_only ) { + if (params.qupath_polygons && params.nucleus_segmentation_only) { ch_coordinate_space = "microns" ch_imp_seg_inputs = ch_bundle_path - .combine(params.qupath_polygons) - .map { - meta, bundle, polygons_geojson -> - tuple ( - meta, // meta - bundle, // bundle - [], // coordinate_transform - polygons_geojson, // nuclei - [], // cells - [], // transcript_assignment - [], // viz_polygons - ch_coordinate_space.val // units - ) - } - - IMP_SEG_POLYGON_GEOJSON_INPUT ( + .combine(params.qupath_polygons) + .map { meta, bundle, polygons_geojson -> + tuple( + meta, + bundle, + [], + polygons_geojson, + [], + [], + [], + ch_coordinate_space.val, + ) + } + + IMP_SEG_POLYGON_GEOJSON_INPUT( ch_imp_seg_inputs ) ch_redefined_bundle = IMP_SEG_POLYGON_GEOJSON_INPUT.out.bundle - ch_versions = ch_versions.mix ( IMP_SEG_POLYGON_GEOJSON_INPUT.out.versions ) - - } else if ( params.qupath_polygons ) { + ch_versions = ch_versions.mix(IMP_SEG_POLYGON_GEOJSON_INPUT.out.versions) + } + else if (params.qupath_polygons) { ch_coordinate_space = "microns" ch_imp_seg_inputs = ch_bundle_path - .combine(params.qupath_polygons) - .map { - meta, bundle, polygons_geojson -> - tuple ( - meta, // meta - bundle, // bundle - [], // coordinate_transform - polygons_geojson, // nuclei - polygons_geojson, // cells - [], // transcript_assignment - [], // viz_polygons - ch_coordinate_space.val // units - ) - } - - IMP_SEG_POLYGON_GEOJSON_INPUT ( + .combine(params.qupath_polygons) + .map { meta, bundle, polygons_geojson -> + tuple( + meta, + bundle, + [], + polygons_geojson, + polygons_geojson, + [], + [], + ch_coordinate_space.val, + ) + } + + IMP_SEG_POLYGON_GEOJSON_INPUT( ch_imp_seg_inputs ) ch_redefined_bundle = IMP_SEG_POLYGON_GEOJSON_INPUT.out.bundle - ch_versions = ch_versions.mix ( IMP_SEG_POLYGON_GEOJSON_INPUT.out.versions ) - + ch_versions = ch_versions.mix(IMP_SEG_POLYGON_GEOJSON_INPUT.out.versions) } // scenario 3 - mask input - included in the cellpose subworkflow @@ -110,39 +104,34 @@ workflow XENIUMRANGER_IMPORT_SEGMENTATION_REDEFINE_BUNDLE { // scenario 4 - transcript assignment input - included in the baysor & proseg subworkflows // scenario 5 - transformation matrix input - if ( params.qupath_polygons && params.alignment_csv ) { + if (params.qupath_polygons && params.alignment_csv) { ch_imp_seg_inputs = ch_bundle_path - .combine(params.qupath_polygins) - .combine(params.alignment_csv) - .map { - meta, bundle, polygons_geojson, alignment_csv -> - tuple ( - meta, // meta - bundle, // bundle - alignment_csv, // coordinate_transform - polygons_geojson, // nuclei - polygons_geojson, // cells - [], // transcript_assignment - [], // viz_polygons - ch_coordinate_space.val // units - ) - } - - IMP_SEG_TRANS_MATRIX_INPUT ( + .combine(params.qupath_polygins) + .combine(params.alignment_csv) + .map { meta, bundle, polygons_geojson, alignment_csv -> + tuple( + meta, + bundle, + alignment_csv, + polygons_geojson, + polygons_geojson, + [], + [], + ch_coordinate_space.val, + ) + } + + IMP_SEG_TRANS_MATRIX_INPUT( ch_imp_seg_inputs ) ch_redefined_bundle = IMP_SEG_TRANS_MATRIX_INPUT.out.bundle - ch_versions = ch_versions.mix ( IMP_SEG_TRANS_MATRIX_INPUT.out.versions ) + ch_versions = ch_versions.mix(IMP_SEG_TRANS_MATRIX_INPUT.out.versions) } - emit: - - redefined_bundle = ch_redefined_bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] - - coordinate_space = ch_coordinate_space // channel: [ ["pixels"] ] - - versions = ch_versions // channel: [ versions.yml ] + redefined_bundle = ch_redefined_bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] + coordinate_space = ch_coordinate_space // channel: [ ["pixels"] ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/xeniumranger_relabel_resegment/main.nf b/subworkflows/local/xeniumranger_relabel_resegment/main.nf index 1151e69a..d7242b14 100644 --- a/subworkflows/local/xeniumranger_relabel_resegment/main.nf +++ b/subworkflows/local/xeniumranger_relabel_resegment/main.nf @@ -6,31 +6,26 @@ include { XENIUMRANGER_RELABEL } from '../../../modules/nf-core/xeniumranger/r include { XENIUMRANGER_RESEGMENT } from '../../../modules/nf-core/xeniumranger/resegment/main' workflow XENIUMRANGER_RELABEL_RESEGMENT { - take: - - ch_bundle_path // channel: [ val(meta), [ "path-to-xenium-bundle" ] ] - ch_gene_panel // channel: [ ["gene_panel.json"] ] + ch_bundle_path // channel: [ val(meta), [ "path-to-xenium-bundle" ] ] + ch_gene_panel // channel: [ ["path-to-gene_panel.json"] ] main: ch_versions = Channel.empty() - XENIUMRANGER_RELABEL ( + XENIUMRANGER_RELABEL( ch_bundle_path, - ch_gene_panel + ch_gene_panel, ) - ch_versions = ch_versions.mix ( XENIUMRANGER_RELABEL.out.versions ) + ch_versions = ch_versions.mix(XENIUMRANGER_RELABEL.out.versions) - XENIUMRANGER_RESEGMENT ( + XENIUMRANGER_RESEGMENT( XENIUMRANGER_RELABEL.out.bundle ) - ch_versions = ch_versions.mix ( XENIUMRANGER_RESEGMENT.out.versions ) - + ch_versions = ch_versions.mix(XENIUMRANGER_RESEGMENT.out.versions) emit: - redefined_bundle = XENIUMRANGER_RESEGMENT.out.bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] - - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/xeniumranger_resegment_morphology_ome_tif/main.nf b/subworkflows/local/xeniumranger_resegment_morphology_ome_tif/main.nf index bea27214..003368dc 100644 --- a/subworkflows/local/xeniumranger_resegment_morphology_ome_tif/main.nf +++ b/subworkflows/local/xeniumranger_resegment_morphology_ome_tif/main.nf @@ -6,63 +6,58 @@ include { XENIUMRANGER_RESEGMENT } from '../../../modules/nf-core/xeni include { XENIUMRANGER_IMPORT_SEGMENTATION } from '../../../modules/nf-core/xeniumranger/import-segmentation/main' workflow XENIUMRANGER_RESEGMENT_MORPHOLOGY_OME_TIF { - take: - - ch_bundle_path // channel: [ val(meta), ["path-to-xenium-bundle"] ] + ch_bundle_path // channel: [ val(meta), ["path-to-xenium-bundle"] ] main: - ch_versions = Channel.empty() + ch_versions = Channel.empty() ch_redefined_bundle = Channel.empty() ch_coordinate_space = Channel.value("pixels") // run resegment with changed config values - XENIUMRANGER_RESEGMENT ( ch_bundle_path ) - ch_versions = ch_versions.mix( XENIUMRANGER_RESEGMENT.out.versions ) + XENIUMRANGER_RESEGMENT(ch_bundle_path) + ch_versions = ch_versions.mix(XENIUMRANGER_RESEGMENT.out.versions) // run import segmentation to redine xenium bundle along with nuclear segmentation - cells = XENIUMRANGER_RESEGMENT.out.bundle.map { - _meta, bundle -> return [ bundle + "/cells.zarr.zip" ] + cells = XENIUMRANGER_RESEGMENT.out.bundle.map { _meta, bundle -> + return [bundle + "/cells.zarr.zip"] } // adjust the nuclear expansion distance without altering nuclei detection - if ( params.nucleus_segmentation_only ) { + if (params.nucleus_segmentation_only) { ch_imp_seg_inputs = ch_bundle_path - .combine(XENIUMRANGER_RESEGMENT.out.bundle, by:0) - .combine(cells) - .map { - meta, bundle, cells_zarr -> tuple ( - meta, // meta - bundle, // bundle - [], // coordinate_transform - cells_zarr, // nuclei - [], // cells - [], // transcript_assignment - [], // viz_polygons - ch_coordinate_space.val // units - ) - } - - XENIUMRANGER_IMPORT_SEGMENTATION ( + .combine(XENIUMRANGER_RESEGMENT.out.bundle, by: 0) + .combine(cells) + .map { meta, bundle, cells_zarr -> + tuple( + meta, + bundle, + [], + cells_zarr, + [], + [], + [], + ch_coordinate_space.val, + ) + } + + XENIUMRANGER_IMPORT_SEGMENTATION( ch_imp_seg_inputs ) - ch_versions = ch_versions.mix( XENIUMRANGER_IMPORT_SEGMENTATION.out.versions ) + ch_versions = ch_versions.mix(XENIUMRANGER_IMPORT_SEGMENTATION.out.versions) ch_redefined_bundle = XENIUMRANGER_IMPORT_SEGMENTATION.out.bundle - - } else { + } + else { ch_redefined_bundle = XENIUMRANGER_RESEGMENT.out.bundle } emit: - redefined_bundle = ch_redefined_bundle // channel: [ val(meta), ["redefined-xenium-bundle"] ] - coordinate_space = ch_coordinate_space // channel: [ ["pixels"] ] - - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] }