diff --git a/CHANGELOG.md b/CHANGELOG.md index 65eb95c..7ead7cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.2.0 - 2025-09-12 + +Add segmentation report. + ## v0.1.0 - 2025-08-29 Initial release of WEHI-SODA-Hub/spatialproteomics, created with the [nf-core](https://nf-co.re/) template. diff --git a/README.md b/README.md index 43d27e2..b3e5dc6 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,39 @@ are run separately, and then consolidated into whole cells with nuclei with full shape and intensity measurements per compartment. The output GeoJSON files can be viewed in QuPath. +
+ Click to view Mermaid diagram + ```mermaid + flowchart TD + A("COMET TIFF") --> B["Extract markers"] + B --> C["Background + subtraction"] + C --> D{"Segmentation + method"} & O["Backsub TIFF"] + N("COMET/MIBI TIFF") --> D + D -- Cellpose (COMET only) --> E["sopa convert"] + E --> F["sopa patchify"] + F --> G["cellpose + (nuclear)"] + F --> H["cellpose + (whole-cell)"] + G --> I["sopa resolve"] + H --> I + I --> J["parquet to tiff"] + J --> K["Cell measurement"] + D -- Mesmer (COMET/MIBI) --> L["mesmer + (nuclear)"] + D -- Mesmer (COMET/MIBI) --> M["mesmer + (whole-cell)"] + L --> K + M --> K + K --> P("GeoJSON") + K --> Q["segmentation + report"] + Q --> R("html file"] + ``` +
+ ![spatialproteomics workflow](assets/spatialproteomics_workflow.png) The pipeline uses the following tools: @@ -39,6 +72,8 @@ The pipeline uses the following tools: QuPath API to calculate compartment measurements and intensities. - [sopa](https://github.com/gustaveroussy/sopa) -- we use the sopa CLI tool to patchify images and perform cellpose segmentation. +- [spatialVis](https://github.com/WEHI-SODA-Hub/spatialVis) -- R package for spatial + analyses, used to generate plots for the segmentation report. Please see the [docs for more detailed information on pipeline usage and output](docs/README.md) diff --git a/assets/spatialproteomics_workflow.png b/assets/spatialproteomics_workflow.png old mode 100644 new mode 100755 index b6bcbc3..e974476 Binary files a/assets/spatialproteomics_workflow.png and b/assets/spatialproteomics_workflow.png differ diff --git a/docs/output.md b/docs/output.md index 71049fa..eedf3f6 100644 --- a/docs/output.md +++ b/docs/output.md @@ -50,6 +50,11 @@ The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes d segmentations, optionally containing measurements and intensity values per cell, compatible with QuPath. +#### Segmentation report + +- `segmentationreport/sample/sample.html` -- html file for visualising report. +- `segmentationreport/sample/sample_report_template_files` -- files necessary to display report. + #### Data provenance - `pipeline_info/` diff --git a/docs/usage.md b/docs/usage.md index 3fcef0c..d5858c3 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -160,6 +160,12 @@ The following Mesmer parameters can be set: | pixel_size_microns | Pixel size in microns, use 0.28 for COMET and 0.390625 for MIBI | | estimate_cell_boundary_dist | Where no matching membrane ROI exists, expand the nucleus by this many pixels | +### Report parameters + +| Parameter Name | Description | +| --------------- | ----------------------------------- | +| generate_report | Generate segmentation report for QC | + ### Updating the pipeline When you run the above command, Nextflow automatically pulls the pipeline code from GitHub and stores it as a cached version. When running the pipeline after this, it will always use the cached version if available - even if the pipeline has been updated since. To make sure that you're running the latest version of the pipeline, make sure that you regularly update the cached version of the pipeline: diff --git a/modules/local/segmentationreport/environment.yml b/modules/local/segmentationreport/environment.yml new file mode 100644 index 0000000..e6ee6ee --- /dev/null +++ b/modules/local/segmentationreport/environment.yml @@ -0,0 +1,11 @@ +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - conda-forge::r-tidyverse=2.0.0 + - conda-forge::r-quarto=1.4.4 + - conda-forge::r-magick=2.8.5 + - conda-forge::r-devtools=2.4.5 + - bioconda::bioconductor-spatialexperiment=1.16.0 + - bioconda::bioconductor-spasim=1.8.0 diff --git a/modules/local/segmentationreport/main.nf b/modules/local/segmentationreport/main.nf new file mode 100644 index 0000000..d23399c --- /dev/null +++ b/modules/local/segmentationreport/main.nf @@ -0,0 +1,87 @@ +process SEGMENTATIONREPORT { + tag "$meta.id" + label 'process_high' + + conda "${moduleDir}/environment.yml" + container 'ghcr.io/wehi-soda-hub/spatialvis:0.1.4' + + input: + tuple val(meta), + path(annotations), + val(run_mesmer), + val(run_cellpose), + val(nuclear_channel), + val(membrane_channels) + + output: + tuple val(meta), path("*/*.html"), path("*/*_files/*"), emit: report + tuple val(meta), path("*/*.rds"), emit: rds, optional: true + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + """ + Rscript -e "spatialVis::copy_report_template( + template_name = 'segmentation_report_template.qmd', + output_dir = '.', + overwrite = TRUE + )" + quarto render segmentation_report_template.qmd \\ + --to html \\ + --no-cache \\ + --output ${prefix}.html \\ + ${args} \\ + -P sample_name:${meta.id} \\ + -P geojson_file:${annotations} \\ + -P nuclear_channel:${nuclear_channel} \\ + -P membrane_channels:"${membrane_channels}" \\ + -P run_cellpose:${run_cellpose} \\ + -P cellpose_diameter:${params.cellpose_diameter} \\ + -P cellpose_min_area:${params.cellpose_min_area} \\ + -P cellpose_flow_threshold:${params.cellpose_flow_threshold} \\ + -P cellpose_cellprob_threshold:${params.cellpose_cellprob_threshold} \\ + -P cellpose_model_type:${params.cellpose_model_type} \\ + -P cellpose_pretrained_model:${params.cellpose_pretrained_model} \\ + -P run_mesmer:${run_mesmer} \\ + -P mesmer_segmentation_level:${params.mesmer_segmentation_level} \\ + -P mesmer_maxima_threshold:${params.mesmer_maxima_threshold} \\ + -P mesmer_interior_threshold:${params.mesmer_interior_threshold} \\ + -P mesmer_maxima_smooth:${params.mesmer_maxima_smooth} \\ + -P mesmer_min_nuclei_area:${params.mesmer_min_nuclei_area} \\ + -P mesmer_remove_border_cells:${params.mesmer_remove_border_cells} \\ + -P mesmer_pixel_expansion:${params.mesmer_pixel_expansion} \\ + -P mesmer_padding:${params.mesmer_padding} + + mkdir -p ${prefix} + mv ${prefix}.html ${prefix} + if [[ -f ${prefix}.rds ]]; then + mv ${prefix}.rds ${prefix} + fi + cp -r segmentation_report_template_files ${prefix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + r-base: \$(Rscript -e "cat(as.character(getRversion()))") + spatialVis: \$(Rscript -e "cat(as.character(packageVersion('spatialVis')))") + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + mkdir -p ${prefix}/segmentation_report_template_files + touch ${prefix}/${prefix}.html + touch ${prefix}/${prefix}.rds + touch ${prefix}/segmentation_report_template_files/foo.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + r-base: \$(Rscript -e "cat(as.character(getRversion()))") + spatialVis: \$(Rscript -e "cat(as.character(packageVersion('spatialVis')))") + END_VERSIONS + """ +} diff --git a/modules/local/segmentationreport/tests/main.nf.test b/modules/local/segmentationreport/tests/main.nf.test new file mode 100644 index 0000000..b068b9b --- /dev/null +++ b/modules/local/segmentationreport/tests/main.nf.test @@ -0,0 +1,61 @@ +nextflow_process { + + name "Test Process SEGMENTATIONREPORT" + script "../main.nf" + process "SEGMENTATIONREPORT" + + tag "modules" + tag "modules_nfcore" + tag "segmentationreport" + + test("segmentationreport - basic functionality") { + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file('/vast/scratch/users/cmero.ma/results/spatialproteomics_test/cellmeasurement/test.geojson'), + true, + false + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("segmentationreport - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'stub_test' ], // meta map + file('/vast/scratch/users/cmero.ma/results/spatialproteomics_test/cellmeasurement/test.geojson'), + true, + false + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/local/segmentationreport/tests/main.nf.test.snap b/modules/local/segmentationreport/tests/main.nf.test.snap new file mode 100644 index 0000000..780ed1c --- /dev/null +++ b/modules/local/segmentationreport/tests/main.nf.test.snap @@ -0,0 +1,150 @@ +{ + "segmentationreport - basic functionality": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.html:md5,978a4490880fb404e965aea8838d8f37", + [ + [ + "channel_intensities-1.png:md5,6a0c625d84e7e87344c68e83bd508505", + "compartment_measurements-1.png:md5,67e32361a18ca731b2b69e77c3ef3133", + "unnamed-chunk-1-1.png:md5,1bc975856040cdf40996f4a9ecee2af7" + ], + [ + [ + "bootstrap-bb462d781dde1847d9e3ccf7736099dd.min.css:md5,bb462d781dde1847d9e3ccf7736099dd", + "bootstrap-icons.css:md5,2318f137d201fbf51601fa0faba6bef7", + "bootstrap-icons.woff:md5,1a51dfbe5467607389d603c02a77cd10", + "bootstrap.min.js:md5,e2b09c06f0e714b6144a6788a28e3950" + ], + [ + "clipboard.min.js:md5,15f52a1ee547f2bdd46e56747332ca2d" + ], + [ + "anchor.min.js:md5,91bcf6cd1fd88fec3f109811e5fc3546", + "popper.min.js:md5,3a4a291ccf3f1ea0f82b641542fd3827", + "quarto-syntax-highlighting-c8ad9e5dbd60b7b70b38521ab19b7da4.css:md5,c8ad9e5dbd60b7b70b38521ab19b7da4", + "quarto.js:md5,6f4245742deb3cc92337dbe2701ccfe1", + [ + "tabsets.js:md5,e8d6a8862b33ccc461f8fd532e05b365" + ], + "tippy.css:md5,ebd6f8ce46a677e1a4f5f8a8317109a9", + "tippy.umd.min.js:md5,d828775275749701b48bd9d958814111" + ] + ] + ] + ] + ], + "1": [ + + ], + "2": [ + "versions.yml:md5,a36295eacb48d679e04b9d2c71e4f0eb" + ], + "rds": [ + + ], + "report": [ + [ + { + "id": "test" + }, + "test.html:md5,978a4490880fb404e965aea8838d8f37", + [ + [ + "channel_intensities-1.png:md5,6a0c625d84e7e87344c68e83bd508505", + "compartment_measurements-1.png:md5,67e32361a18ca731b2b69e77c3ef3133", + "unnamed-chunk-1-1.png:md5,1bc975856040cdf40996f4a9ecee2af7" + ], + [ + [ + "bootstrap-bb462d781dde1847d9e3ccf7736099dd.min.css:md5,bb462d781dde1847d9e3ccf7736099dd", + "bootstrap-icons.css:md5,2318f137d201fbf51601fa0faba6bef7", + "bootstrap-icons.woff:md5,1a51dfbe5467607389d603c02a77cd10", + "bootstrap.min.js:md5,e2b09c06f0e714b6144a6788a28e3950" + ], + [ + "clipboard.min.js:md5,15f52a1ee547f2bdd46e56747332ca2d" + ], + [ + "anchor.min.js:md5,91bcf6cd1fd88fec3f109811e5fc3546", + "popper.min.js:md5,3a4a291ccf3f1ea0f82b641542fd3827", + "quarto-syntax-highlighting-c8ad9e5dbd60b7b70b38521ab19b7da4.css:md5,c8ad9e5dbd60b7b70b38521ab19b7da4", + "quarto.js:md5,6f4245742deb3cc92337dbe2701ccfe1", + [ + "tabsets.js:md5,e8d6a8862b33ccc461f8fd532e05b365" + ], + "tippy.css:md5,ebd6f8ce46a677e1a4f5f8a8317109a9", + "tippy.umd.min.js:md5,d828775275749701b48bd9d958814111" + ] + ] + ] + ] + ], + "versions": [ + "versions.yml:md5,a36295eacb48d679e04b9d2c71e4f0eb" + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.4" + }, + "timestamp": "2025-09-01T13:49:50.280243443" + }, + "segmentationreport - stub": { + "content": [ + { + "0": [ + [ + { + "id": "stub_test" + }, + "stub_test.html:md5,d41d8cd98f00b204e9800998ecf8427e", + "foo.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "stub_test" + }, + "stub_test.rds:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,a36295eacb48d679e04b9d2c71e4f0eb" + ], + "rds": [ + [ + { + "id": "stub_test" + }, + "stub_test.rds:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "report": [ + [ + { + "id": "stub_test" + }, + "stub_test.html:md5,d41d8cd98f00b204e9800998ecf8427e", + "foo.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,a36295eacb48d679e04b9d2c71e4f0eb" + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.4" + }, + "timestamp": "2025-09-01T13:12:50.675902625" + } +} \ No newline at end of file diff --git a/nextflow.config b/nextflow.config index db417b8..1be2c1b 100644 --- a/nextflow.config +++ b/nextflow.config @@ -61,6 +61,9 @@ params { pixel_size_microns = 0.28 estimate_cell_boundary_dist = 3 + // report options + generate_report = true + // Config options config_profile_name = null config_profile_description = null @@ -387,7 +390,7 @@ manifest { description = """Cell segmentation and downstream analysis pipeline for the COMET and MIBI spatial platforms""" mainScript = 'main.nf' nextflowVersion = '!>=24.04.2' - version = '0.1.0' + version = '0.2.0' doi = '' } diff --git a/nextflow_schema.json b/nextflow_schema.json index 115f4e3..23afed0 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -213,6 +213,22 @@ } } }, + "report_options": { + "title": "Report options", + "type": "object", + "fa_icon": "fas fa-image", + "description": "Parameters used for segmentation report generation.", + "help_text": "These parameters controls parameters used by the segmentationreport step of the pipeline.", + "properties": { + "generate_report": { + "type": "boolean", + "default": true, + "description": "Generate segmentation report.", + "fa_icon": "fas fa-stopwatch", + "help_text": "Set this to `true` to generate a segmentation report. Skipping this step can save on processing time." + } + } + }, "institutional_config_options": { "title": "Institutional config options", "type": "object", @@ -356,6 +372,9 @@ { "$ref": "#/$defs/measurement_options" }, + { + "$ref": "#/$defs/report_options" + }, { "$ref": "#/$defs/institutional_config_options" }, diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 0aad565..6ebcea3 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -6,7 +6,7 @@ "@type": "Dataset", "creativeWorkStatus": "InProgress", "datePublished": "2025-08-06T02:29:12+00:00", - "description": "

\n \n \n \"WEHI-SODA-Hub/spatialproteomics\"\n \n

\n\n[![GitHub Actions CI Status](https://github.com/WEHI-SODA-Hub/spatialproteomics/actions/workflows/ci.yml/badge.svg)](https://github.com/WEHI-SODA-Hub/spatialproteomics/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/WEHI-SODA-Hub/spatialproteomics/actions/workflows/linting.yml/badge.svg)](https://github.com/WEHI-SODA-Hub/spatialproteomics/actions/workflows/linting.yml)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n\n[![Nextflow](https://img.shields.io/badge/version-%E2%89%A524.04.2-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-3.3.2-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/3.3.2)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/WEHI-SODA-Hub/spatialproteomics)\n\n## Introduction\n\n**WEHI-SODA-Hub/spatialproteomics** is a pipeline for running cell segmentation\non COMET and MIBI data. For COMET, background subtraction can be performed\nfollowed by patched cellpose segmentation, or non-patched mesmer segmentation.\nFor MIBI, mesmer segmentation can be run. Whole-cell and nuclear segmentations\nare run separately, and then consolidated into whole cells with nuclei with full\nshape and intensity measurements per compartment. The output GeoJSON files can\nbe viewed in QuPath.\n\n![spatialproteomics workflow](assets/spatialproteomics_workflow.png)\n\nThe pipeline uses the following tools:\n\n- [Background_subtraction](https://github.com/SchapiroLabor/Background_subtraction)\n -- background subtraction tool for COMET.\n- [MesmerSegmentation](https://github.com/WEHI-SODA-Hub/mesmersegmentation) -- a\n CLI for running Mesmer segmentation of MIBI and OME-XML TIFFs.\n- [cellmeasurement](https://github.com/WEHI-SODA-Hub/cellmeasurement) -- a\n Groovy app that matches whole-cell segmentations with nuclei, and uses the\n QuPath API to calculate compartment measurements and intensities.\n- [sopa](https://github.com/gustaveroussy/sopa) -- we use the sopa CLI tool to\n patchify images and perform cellpose segmentation.\n\nPlease see the [docs for more detailed information on pipeline usage and output](docs/README.md)\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` (to test cellpose segmentation) or `-profile test_mesmer` to test mesmer segmentation before running the workflow on actual data.\n\nIf you are running this pipeline from WEHI, it has been set up to run on [Seqera Platform](https://seqera.services.biocommons.org.au/).\n\n> [!NOTE]\n> If you don't have a .gradle directory in your home, make sure you create it with `mkdir $HOME/.gradle` before runnning the pipeline. You con't need to do this if you are running via WEHI's Seqera Platform mentioned above.\n\nUsage will depend on your desired steps. See [usage docs](docs/usage.md) for more detailed information.\n\n### Background subtraction\n\n> [!NOTE]\n> This step will only work with COMET OME-TIF files.\n\nPrepare a sample sheet as follows:\n\n`samplesheet.csv`:\n\n```csv\nsample,run_backsub,run_mesmer,run_cellpose,tiff\nsample1,true,true,false,/path/to/sample1.tiff\nsample2,true,false,true,/path/to/sample2.tiff\n```\n\nYou may also prefer to use YAML for your samplesheet, either is supported:\n\n`samplesheet.yml`:\n\n```yaml\n- sample: sample1\n run_backsub: true\n run_mesmer: true\n run_cellpose: false\n tiff: /path/to/sample1.tiff\n- sample: sample2\n run_backsub: true\n run_mesmer: true\n run_cellpose: false\n tiff: /path/to/sample2.tiff\n```\n\n> [!WARNING]\n> Please ensure that your image name and all directories in your file path do not contain spaces.\n\nIf you don't specify any segmentation algorithm to run (mesmer or cellpose), the\npipeline will run a background subtraction only.\n\nNow, you can run the pipeline using:\n\n```bash\nnextflow run WEHI-SODA-Hub/spatialproteomics \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/usage/getting_started/configuration#custom-configuration-files).\n\n### Mesmer segmentation\n\nBefore running Mesmer, ensure that you have a [deepcell access token](https://users.deepcell.org/login/)\nand that you have set it in your Nextflow secrets:\n\n```bash\nnextflow secrets set DEEPCELL_ACCESS_TOKEN $YOUR_TOKEN\n```\n\nIf you want to run Mesmer as your segmentation algorithm, you can specify a\nconfig file like so:\n\n```csv\nsample,run_backsub,run_mesmer,tiff,nuclear_channel,membrane_channels\nsample1,true,true,/path/to/sample1.tiff,DAPI,CD45:CD8\nsample2,false,true,/path/to/sample2.tiff,DAPI,CD45\n```\n\nNuclear channels only support one entry; membrane channels may have multiple\nvalues separated by `:` characters. If your channels have spaces in them, make\nsure that you surround your channel name with quotes. For example, CD45:\"HLA I\".\n\nYou can also set the segmentation parameters for mesmer either via CLI\n(e.g., `--combine_method prod` or in a config file pass to the workflow\nvia `-c`. See [usage](docs/usage.md) for a full list.\n\n> [!WARNING]\n> You cannot run both Mesmer and Cellpose segmentation on the same sample (with\n> the same name). If you want to run both on a sample, put it on a different\n> line and give it a different sample name.\n\n### Cellpose segmentation\n\nIf you want to run Cellpose as your segmentation algorithm, you can specify a\nconfig file like so:\n\n```csv\nsample,run_backsub,run_cellpose,tiff,nuclear_channel,membrane_channels\nsample1,true,true,/path/to/sample1.tiff,DAPI,CD45:CD8\nsample2,false,true,/path/to/sample2.tiff,DAPI,CD45\n```\n\nAs with Mesmer, nuclear channels only support one entry; membrane channels may\nhave multiple values separated by `:` characters. You can also set the following\nparameters, either via CLI (e.g., `--combine_method prod` or in a config\nfile pass to the workflow via `-c`. See [usage](docs/usage.md) for a full list.\n\nCellpose will run in a parallelised patched workflow using sopa. To control the\npatching process, you can use the `patch_width_pixel` and `patch_overlap_pixel`\nparameters.\n\nIf you want to skip measurements (this may take some time for large images), you\ncan use set the parameter `skip_measurements` to `true`.\n\n## Dealing with large images\n\nYou can run the pipeline with different profiles for different size images:\n\n- `small`: for images <150GB\n- `medium`: for images <300GB\n- `large`: for images <600GB\n\n> [!WARNING]\n> If you are combining many membrane channels, using `prod` as the combine method\n> may lead to large memory usage. In these cases, it is recommended to use `max`\n> instead.\n\n## Credits\n\nWEHI-SODA-Hub/spatialproteomics was originally written by the WEHI SODA-Hub.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n- Michael McKay (@mikemcka)\n- Emma Watson\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md).\n\n## Citations\n\n\n\n\n\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nThis pipeline was created using the `nf-core` template. You can cite the `nf-core` publication as follows:\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n", + "description": "

\n \n \n \"WEHI-SODA-Hub/spatialproteomics\"\n \n

\n\n[![GitHub Actions CI Status](https://github.com/WEHI-SODA-Hub/spatialproteomics/actions/workflows/ci.yml/badge.svg)](https://github.com/WEHI-SODA-Hub/spatialproteomics/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/WEHI-SODA-Hub/spatialproteomics/actions/workflows/linting.yml/badge.svg)](https://github.com/WEHI-SODA-Hub/spatialproteomics/actions/workflows/linting.yml)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n\n[![Nextflow](https://img.shields.io/badge/version-%E2%89%A524.04.2-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-3.3.2-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/3.3.2)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/WEHI-SODA-Hub/spatialproteomics)\n\n## Introduction\n\n**WEHI-SODA-Hub/spatialproteomics** is a pipeline for running cell segmentation\non COMET and MIBI data. For COMET, background subtraction can be performed\nfollowed by patched cellpose segmentation, or non-patched mesmer segmentation.\nFor MIBI, mesmer segmentation can be run. Whole-cell and nuclear segmentations\nare run separately, and then consolidated into whole cells with nuclei with full\nshape and intensity measurements per compartment. The output GeoJSON files can\nbe viewed in QuPath.\n\n
\n Click to view Mermaid diagram\n ```mermaid\n flowchart TD\n A(\"COMET TIFF\") --> B[\"Extract markers\"]\n B --> C[\"Background\n subtraction\"]\n C --> D{\"Segmentation\n method\"} & O[\"Backsub TIFF\"]\n N(\"COMET/MIBI TIFF\") --> D\n D -- Cellpose (COMET only) --> E[\"sopa convert\"]\n E --> F[\"sopa patchify\"]\n F --> G[\"cellpose\n (nuclear)\"]\n F --> H[\"cellpose\n (whole-cell)\"]\n G --> I[\"sopa resolve\"]\n H --> I\n I --> J[\"parquet to tiff\"]\n J --> K[\"Cell measurement\"]\n D -- Mesmer (COMET/MIBI) --> L[\"mesmer\n (nuclear)\"]\n D -- Mesmer (COMET/MIBI) --> M[\"mesmer\n (whole-cell)\"]\n L --> K\n M --> K\n K --> P(\"GeoJSON\")\n K --> Q[\"segmentation\n report\"]\n Q --> R(\"html file\"]\n ```\n
\n\n![spatialproteomics workflow](assets/spatialproteomics_workflow.png)\n\nThe pipeline uses the following tools:\n\n- [Background_subtraction](https://github.com/SchapiroLabor/Background_subtraction)\n -- background subtraction tool for COMET.\n- [MesmerSegmentation](https://github.com/WEHI-SODA-Hub/mesmersegmentation) -- a\n CLI for running Mesmer segmentation of MIBI and OME-XML TIFFs.\n- [cellmeasurement](https://github.com/WEHI-SODA-Hub/cellmeasurement) -- a\n Groovy app that matches whole-cell segmentations with nuclei, and uses the\n QuPath API to calculate compartment measurements and intensities.\n- [sopa](https://github.com/gustaveroussy/sopa) -- we use the sopa CLI tool to\n patchify images and perform cellpose segmentation.\n- [spatialVis](https://github.com/WEHI-SODA-Hub/spatialVis) -- R package for spatial\n analyses, used to generate plots for the segmentation report.\n\nPlease see the [docs for more detailed information on pipeline usage and output](docs/README.md)\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` (to test cellpose segmentation) or `-profile test_mesmer` to test mesmer segmentation before running the workflow on actual data.\n\nIf you are running this pipeline from WEHI, it has been set up to run on [Seqera Platform](https://seqera.services.biocommons.org.au/).\n\n> [!NOTE]\n> If you don't have a .gradle directory in your home, make sure you create it with `mkdir $HOME/.gradle` before runnning the pipeline. You con't need to do this if you are running via WEHI's Seqera Platform mentioned above.\n\nUsage will depend on your desired steps. See [usage docs](docs/usage.md) for more detailed information.\n\n### Background subtraction\n\n> [!NOTE]\n> This step will only work with COMET OME-TIF files.\n\nPrepare a sample sheet as follows:\n\n`samplesheet.csv`:\n\n```csv\nsample,run_backsub,run_mesmer,run_cellpose,tiff\nsample1,true,true,false,/path/to/sample1.tiff\nsample2,true,false,true,/path/to/sample2.tiff\n```\n\nYou may also prefer to use YAML for your samplesheet, either is supported:\n\n`samplesheet.yml`:\n\n```yaml\n- sample: sample1\n run_backsub: true\n run_mesmer: true\n run_cellpose: false\n tiff: /path/to/sample1.tiff\n- sample: sample2\n run_backsub: true\n run_mesmer: true\n run_cellpose: false\n tiff: /path/to/sample2.tiff\n```\n\n> [!WARNING]\n> Please ensure that your image name and all directories in your file path do not contain spaces.\n\nIf you don't specify any segmentation algorithm to run (mesmer or cellpose), the\npipeline will run a background subtraction only.\n\nNow, you can run the pipeline using:\n\n```bash\nnextflow run WEHI-SODA-Hub/spatialproteomics \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/usage/getting_started/configuration#custom-configuration-files).\n\n### Mesmer segmentation\n\nBefore running Mesmer, ensure that you have a [deepcell access token](https://users.deepcell.org/login/)\nand that you have set it in your Nextflow secrets:\n\n```bash\nnextflow secrets set DEEPCELL_ACCESS_TOKEN $YOUR_TOKEN\n```\n\nIf you want to run Mesmer as your segmentation algorithm, you can specify a\nconfig file like so:\n\n```csv\nsample,run_backsub,run_mesmer,tiff,nuclear_channel,membrane_channels\nsample1,true,true,/path/to/sample1.tiff,DAPI,CD45:CD8\nsample2,false,true,/path/to/sample2.tiff,DAPI,CD45\n```\n\nNuclear channels only support one entry; membrane channels may have multiple\nvalues separated by `:` characters. If your channels have spaces in them, make\nsure that you surround your channel name with quotes. For example, CD45:\"HLA I\".\n\nYou can also set the segmentation parameters for mesmer either via CLI\n(e.g., `--combine_method prod` or in a config file pass to the workflow\nvia `-c`. See [usage](docs/usage.md) for a full list.\n\n> [!WARNING]\n> You cannot run both Mesmer and Cellpose segmentation on the same sample (with\n> the same name). If you want to run both on a sample, put it on a different\n> line and give it a different sample name.\n\n### Cellpose segmentation\n\nIf you want to run Cellpose as your segmentation algorithm, you can specify a\nconfig file like so:\n\n```csv\nsample,run_backsub,run_cellpose,tiff,nuclear_channel,membrane_channels\nsample1,true,true,/path/to/sample1.tiff,DAPI,CD45:CD8\nsample2,false,true,/path/to/sample2.tiff,DAPI,CD45\n```\n\nAs with Mesmer, nuclear channels only support one entry; membrane channels may\nhave multiple values separated by `:` characters. You can also set the following\nparameters, either via CLI (e.g., `--combine_method prod` or in a config\nfile pass to the workflow via `-c`. See [usage](docs/usage.md) for a full list.\n\nCellpose will run in a parallelised patched workflow using sopa. To control the\npatching process, you can use the `patch_width_pixel` and `patch_overlap_pixel`\nparameters.\n\nIf you want to skip measurements (this may take some time for large images), you\ncan use set the parameter `skip_measurements` to `true`.\n\n## Dealing with large images\n\nYou can run the pipeline with different profiles for different size images:\n\n- `small`: for images <150GB\n- `medium`: for images <300GB\n- `large`: for images <600GB\n\n> [!WARNING]\n> If you are combining many membrane channels, using `prod` as the combine method\n> may lead to large memory usage. In these cases, it is recommended to use `max`\n> instead.\n\n## Credits\n\nWEHI-SODA-Hub/spatialproteomics was originally written by the WEHI SODA-Hub.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n- Michael McKay (@mikemcka)\n- Emma Watson\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md).\n\n## Citations\n\n\n\n\n\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nThis pipeline was created using the `nf-core` template. You can cite the `nf-core` publication as follows:\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n", "hasPart": [ { "@id": "main.nf" diff --git a/subworkflows/local/backgroundsubtract/tests/main.nf.test.snap b/subworkflows/local/backgroundsubtract/tests/main.nf.test.snap index b80d3ad..f0cb424 100644 --- a/subworkflows/local/backgroundsubtract/tests/main.nf.test.snap +++ b/subworkflows/local/backgroundsubtract/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test" }, - "test.ome.tif:md5,2752700d6af7994c85f5a3889b9a0f40" + "test.ome.tif:md5,b3849c21f908bca958ebc9ffcf81a6b9" ] ], "1": [ @@ -27,7 +27,7 @@ { "id": "test" }, - "test.ome.tif:md5,2752700d6af7994c85f5a3889b9a0f40" + "test.ome.tif:md5,b3849c21f908bca958ebc9ffcf81a6b9" ] ], "markers": [ @@ -48,6 +48,6 @@ "nf-test": "0.9.2", "nextflow": "25.04.4" }, - "timestamp": "2025-08-25T11:29:59.848431829" + "timestamp": "2025-09-12T10:00:35.92040009" } } \ No newline at end of file diff --git a/subworkflows/local/mesmer_segment/main.nf b/subworkflows/local/mesmer_segment/main.nf index 813ad4f..c3a075b 100644 --- a/subworkflows/local/mesmer_segment/main.nf +++ b/subworkflows/local/mesmer_segment/main.nf @@ -1,6 +1,7 @@ include { MESMERSEGMENT as MESMERWC } from '../../../modules/local/mesmersegment/main.nf' include { MESMERSEGMENT as MESMERNUC } from '../../../modules/local/mesmersegment/main.nf' include { CELLMEASUREMENT } from '../../../modules/local/cellmeasurement/main.nf' +include { SEGMENTATIONREPORT } from '../../../modules/local/segmentationreport/main.nf' workflow MESMER_SEGMENT { @@ -76,11 +77,45 @@ workflow MESMER_SEGMENT { ) ch_versions = ch_versions.mix(CELLMEASUREMENT.out.versions.first()) + // Optional SEGMENTATIONREPORT module + ch_report = Channel.empty() + if (params.generate_report) { + ch_mesmer_segment + .join(CELLMEASUREMENT.out.annotations) + .map { + sample, + _run_backsub, + run_mesmer, + run_cellpose, + _tiff, + nuclear_channel, + membrane_channels, + annotations -> [ + sample, + annotations, + run_mesmer, + run_cellpose, + nuclear_channel.first(), + membrane_channels.first() + ] + }.set { ch_segmentationreport } + + // + // Run SEGMENTATIONREPORT module to generate a report of the segmentation results + // + SEGMENTATIONREPORT( + ch_segmentationreport + ) + ch_versions = ch_versions.mix(SEGMENTATIONREPORT.out.versions.first()) + + ch_report = SEGMENTATIONREPORT.out.report + } emit: annotations = CELLMEASUREMENT.out.annotations // channel: [ val(meta), *.geojson ] whole_cell_tif = MESMERWC.out.segmentation_mask // channel: [ val(meta), *.tiff ] nuclear_tif = MESMERNUC.out.segmentation_mask // channel: [ val(meta), *.tiff ] + report = ch_report // channel: [ val(meta), *.html, */*_files/* ] OPTIONAL versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/mesmer_segment/tests/main.nf.test.snap b/subworkflows/local/mesmer_segment/tests/main.nf.test.snap index f49000e..528eddc 100644 --- a/subworkflows/local/mesmer_segment/tests/main.nf.test.snap +++ b/subworkflows/local/mesmer_segment/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test" }, - "test.geojson:md5,5de1ada9b73bbda0cf91a09a32b79a22" + "test.geojson:md5,fdab105fb77f396dad00a5827b7f18ec" ] ], "1": [ @@ -27,8 +27,47 @@ ] ], "3": [ + [ + { + "id": "test" + }, + "test.html:md5,72750bd0117f0d98c7efb5c5795ae3d1", + [ + [ + "channel_intensities-1.png:md5,c50783d23b885635ea4dd374ce0868e3", + "compartment_measurements-1.png:md5,539e4832c55f79c63ab2fe15e4faed61", + "unnamed-chunk-1-1.png:md5,a012e1a520748fe83303d0e567a61eb4", + "unnamed-chunk-2-1.png:md5,6c6dd80e916497b698001de35a8d12b7" + ], + [ + [ + "bootstrap-bb462d781dde1847d9e3ccf7736099dd.min.css:md5,bb462d781dde1847d9e3ccf7736099dd", + "bootstrap-icons.css:md5,2318f137d201fbf51601fa0faba6bef7", + "bootstrap-icons.woff:md5,1a51dfbe5467607389d603c02a77cd10", + "bootstrap.min.js:md5,e2b09c06f0e714b6144a6788a28e3950" + ], + [ + "clipboard.min.js:md5,15f52a1ee547f2bdd46e56747332ca2d" + ], + [ + "anchor.min.js:md5,91bcf6cd1fd88fec3f109811e5fc3546", + "popper.min.js:md5,3a4a291ccf3f1ea0f82b641542fd3827", + "quarto-syntax-highlighting-c8ad9e5dbd60b7b70b38521ab19b7da4.css:md5,c8ad9e5dbd60b7b70b38521ab19b7da4", + "quarto.js:md5,6f4245742deb3cc92337dbe2701ccfe1", + [ + "tabsets.js:md5,e8d6a8862b33ccc461f8fd532e05b365" + ], + "tippy.css:md5,ebd6f8ce46a677e1a4f5f8a8317109a9", + "tippy.umd.min.js:md5,d828775275749701b48bd9d958814111" + ] + ] + ] + ] + ], + "4": [ "versions.yml:md5,020f6b6c73631bfaf9a42689d3222190", "versions.yml:md5,298b46e76bb2bff02f635a89d94acc79", + "versions.yml:md5,e41d97cd1e8534823a90cecf53db55f3", "versions.yml:md5,ec8fbc92050f538763cdc496a2986c88" ], "annotations": [ @@ -36,7 +75,7 @@ { "id": "test" }, - "test.geojson:md5,5de1ada9b73bbda0cf91a09a32b79a22" + "test.geojson:md5,fdab105fb77f396dad00a5827b7f18ec" ] ], "nuclear_tif": [ @@ -47,9 +86,48 @@ "test_nuclear.tiff:md5,07dc3d7f48a3ebf926fe82d6d68175af" ] ], + "report": [ + [ + { + "id": "test" + }, + "test.html:md5,72750bd0117f0d98c7efb5c5795ae3d1", + [ + [ + "channel_intensities-1.png:md5,c50783d23b885635ea4dd374ce0868e3", + "compartment_measurements-1.png:md5,539e4832c55f79c63ab2fe15e4faed61", + "unnamed-chunk-1-1.png:md5,a012e1a520748fe83303d0e567a61eb4", + "unnamed-chunk-2-1.png:md5,6c6dd80e916497b698001de35a8d12b7" + ], + [ + [ + "bootstrap-bb462d781dde1847d9e3ccf7736099dd.min.css:md5,bb462d781dde1847d9e3ccf7736099dd", + "bootstrap-icons.css:md5,2318f137d201fbf51601fa0faba6bef7", + "bootstrap-icons.woff:md5,1a51dfbe5467607389d603c02a77cd10", + "bootstrap.min.js:md5,e2b09c06f0e714b6144a6788a28e3950" + ], + [ + "clipboard.min.js:md5,15f52a1ee547f2bdd46e56747332ca2d" + ], + [ + "anchor.min.js:md5,91bcf6cd1fd88fec3f109811e5fc3546", + "popper.min.js:md5,3a4a291ccf3f1ea0f82b641542fd3827", + "quarto-syntax-highlighting-c8ad9e5dbd60b7b70b38521ab19b7da4.css:md5,c8ad9e5dbd60b7b70b38521ab19b7da4", + "quarto.js:md5,6f4245742deb3cc92337dbe2701ccfe1", + [ + "tabsets.js:md5,e8d6a8862b33ccc461f8fd532e05b365" + ], + "tippy.css:md5,ebd6f8ce46a677e1a4f5f8a8317109a9", + "tippy.umd.min.js:md5,d828775275749701b48bd9d958814111" + ] + ] + ] + ] + ], "versions": [ "versions.yml:md5,020f6b6c73631bfaf9a42689d3222190", "versions.yml:md5,298b46e76bb2bff02f635a89d94acc79", + "versions.yml:md5,e41d97cd1e8534823a90cecf53db55f3", "versions.yml:md5,ec8fbc92050f538763cdc496a2986c88" ], "whole_cell_tif": [ @@ -66,6 +144,6 @@ "nf-test": "0.9.2", "nextflow": "25.04.4" }, - "timestamp": "2025-08-25T11:31:18.135939955" + "timestamp": "2025-09-12T10:02:14.019054565" } } \ No newline at end of file diff --git a/subworkflows/local/mesmer_segment_wbacksub/tests/main.nf.test.snap b/subworkflows/local/mesmer_segment_wbacksub/tests/main.nf.test.snap index 822a497..d189f12 100644 --- a/subworkflows/local/mesmer_segment_wbacksub/tests/main.nf.test.snap +++ b/subworkflows/local/mesmer_segment_wbacksub/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test" }, - "test.geojson:md5,e7e75973b64386bf6dd385983fa73ad3" + "test.geojson:md5,144dfea82c9e45da813ea5f06607f2af" ] ], "1": [ @@ -35,7 +35,7 @@ { "id": "test" }, - "test.geojson:md5,e7e75973b64386bf6dd385983fa73ad3" + "test.geojson:md5,144dfea82c9e45da813ea5f06607f2af" ] ], "nuclear_tif": [ @@ -64,6 +64,6 @@ "nf-test": "0.9.2", "nextflow": "25.04.4" }, - "timestamp": "2025-08-25T11:33:06.678243513" + "timestamp": "2025-09-12T10:04:23.479337445" } } \ No newline at end of file diff --git a/subworkflows/local/sopa_segment/main.nf b/subworkflows/local/sopa_segment/main.nf index fc26e75..f51fe76 100644 --- a/subworkflows/local/sopa_segment/main.nf +++ b/subworkflows/local/sopa_segment/main.nf @@ -2,6 +2,7 @@ include { COMBINECHANNELS } from '../../../mo include { SOPA_SEGMENT_COMPARTMENT as SOPA_SEGMENT_NUCLEAR } from '../sopa_segment_compartment/main.nf' include { SOPA_SEGMENT_COMPARTMENT as SOPA_SEGMENT_WHOLECELL } from '../sopa_segment_compartment/main.nf' include { CELLMEASUREMENT } from '../../../modules/local/cellmeasurement/main.nf' +include { SEGMENTATIONREPORT } from '../../../modules/local/segmentationreport/main.nf' workflow SOPA_SEGMENT { @@ -86,8 +87,40 @@ workflow SOPA_SEGMENT { ) ch_versions = ch_versions.mix(CELLMEASUREMENT.out.versions.first()) + // Optional SEGMENTATIONREPORT module + ch_report = Channel.empty() + if (params.generate_report) { + ch_sopa + .join(CELLMEASUREMENT.out.annotations) + .map { + sample, + _tiff, + nuclear_channel, + membrane_channels, + annotations -> [ + sample, + annotations, + false, // run_mesmer + true, // run_cellpose + nuclear_channel.first(), + membrane_channels.first() + ] + }.set { ch_segmentationreport } + + // + // Run SEGMENTATIONREPORT module to generate a report of the segmentation results + // + SEGMENTATIONREPORT( + ch_segmentationreport + ) + ch_versions = ch_versions.mix(SEGMENTATIONREPORT.out.versions.first()) + + ch_report = SEGMENTATIONREPORT.out.report // channel: [ val(meta), *.html, */*_files/* ] + } + emit: annotations = CELLMEASUREMENT.out.annotations // channel: [ val(meta), *.geojson ] + report = ch_report // channel: [ val(meta), *.html, */*_files/* ] OPTIONAL versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/sopa_segment/tests/main.nf.test.snap b/subworkflows/local/sopa_segment/tests/main.nf.test.snap index 77e6f4a..5557fde 100644 --- a/subworkflows/local/sopa_segment/tests/main.nf.test.snap +++ b/subworkflows/local/sopa_segment/tests/main.nf.test.snap @@ -7,12 +7,51 @@ { "id": "test" }, - "test.geojson:md5,167dc00eadfcd8b974f967e12a28f6d2" + "test.geojson:md5,5a504221b2ed3a212773b4c4c4a817bf" ] ], "1": [ + [ + { + "id": "test" + }, + "test.html:md5,e4b9e621cc108e3565ee75f22e939182", + [ + [ + "channel_intensities-1.png:md5,22fcfce431635b963fd9a96ccaf242b5", + "compartment_measurements-1.png:md5,94933882f0143e3ffb0c5b88779223e2", + "unnamed-chunk-1-1.png:md5,4106464d068b1f85755ae9ea9d8f48e2", + "unnamed-chunk-2-1.png:md5,822ee2edc18e1f7345b9d474851c9e6e" + ], + [ + [ + "bootstrap-bb462d781dde1847d9e3ccf7736099dd.min.css:md5,bb462d781dde1847d9e3ccf7736099dd", + "bootstrap-icons.css:md5,2318f137d201fbf51601fa0faba6bef7", + "bootstrap-icons.woff:md5,1a51dfbe5467607389d603c02a77cd10", + "bootstrap.min.js:md5,e2b09c06f0e714b6144a6788a28e3950" + ], + [ + "clipboard.min.js:md5,15f52a1ee547f2bdd46e56747332ca2d" + ], + [ + "anchor.min.js:md5,91bcf6cd1fd88fec3f109811e5fc3546", + "popper.min.js:md5,3a4a291ccf3f1ea0f82b641542fd3827", + "quarto-syntax-highlighting-c8ad9e5dbd60b7b70b38521ab19b7da4.css:md5,c8ad9e5dbd60b7b70b38521ab19b7da4", + "quarto.js:md5,6f4245742deb3cc92337dbe2701ccfe1", + [ + "tabsets.js:md5,e8d6a8862b33ccc461f8fd532e05b365" + ], + "tippy.css:md5,ebd6f8ce46a677e1a4f5f8a8317109a9", + "tippy.umd.min.js:md5,d828775275749701b48bd9d958814111" + ] + ] + ] + ] + ], + "2": [ "versions.yml:md5,4365d84aefd2e681fc09e75b49725961", "versions.yml:md5,7bef09a7858e9f47bf9108e779ddc6a1", + "versions.yml:md5,b415dcdfef3ac4967a7682e2e03400d1", "versions.yml:md5,dd7c9a4feb0c5710a638318159023030", "versions.yml:md5,faeace3d7ca5ba5d9d9ebf3a48c43c24" ], @@ -21,12 +60,51 @@ { "id": "test" }, - "test.geojson:md5,167dc00eadfcd8b974f967e12a28f6d2" + "test.geojson:md5,5a504221b2ed3a212773b4c4c4a817bf" + ] + ], + "report": [ + [ + { + "id": "test" + }, + "test.html:md5,e4b9e621cc108e3565ee75f22e939182", + [ + [ + "channel_intensities-1.png:md5,22fcfce431635b963fd9a96ccaf242b5", + "compartment_measurements-1.png:md5,94933882f0143e3ffb0c5b88779223e2", + "unnamed-chunk-1-1.png:md5,4106464d068b1f85755ae9ea9d8f48e2", + "unnamed-chunk-2-1.png:md5,822ee2edc18e1f7345b9d474851c9e6e" + ], + [ + [ + "bootstrap-bb462d781dde1847d9e3ccf7736099dd.min.css:md5,bb462d781dde1847d9e3ccf7736099dd", + "bootstrap-icons.css:md5,2318f137d201fbf51601fa0faba6bef7", + "bootstrap-icons.woff:md5,1a51dfbe5467607389d603c02a77cd10", + "bootstrap.min.js:md5,e2b09c06f0e714b6144a6788a28e3950" + ], + [ + "clipboard.min.js:md5,15f52a1ee547f2bdd46e56747332ca2d" + ], + [ + "anchor.min.js:md5,91bcf6cd1fd88fec3f109811e5fc3546", + "popper.min.js:md5,3a4a291ccf3f1ea0f82b641542fd3827", + "quarto-syntax-highlighting-c8ad9e5dbd60b7b70b38521ab19b7da4.css:md5,c8ad9e5dbd60b7b70b38521ab19b7da4", + "quarto.js:md5,6f4245742deb3cc92337dbe2701ccfe1", + [ + "tabsets.js:md5,e8d6a8862b33ccc461f8fd532e05b365" + ], + "tippy.css:md5,ebd6f8ce46a677e1a4f5f8a8317109a9", + "tippy.umd.min.js:md5,d828775275749701b48bd9d958814111" + ] + ] + ] ] ], "versions": [ "versions.yml:md5,4365d84aefd2e681fc09e75b49725961", "versions.yml:md5,7bef09a7858e9f47bf9108e779ddc6a1", + "versions.yml:md5,b415dcdfef3ac4967a7682e2e03400d1", "versions.yml:md5,dd7c9a4feb0c5710a638318159023030", "versions.yml:md5,faeace3d7ca5ba5d9d9ebf3a48c43c24" ] @@ -36,6 +114,6 @@ "nf-test": "0.9.2", "nextflow": "25.04.4" }, - "timestamp": "2025-08-25T13:27:49.360016637" + "timestamp": "2025-09-12T10:07:04.687289877" } } \ No newline at end of file diff --git a/subworkflows/local/sopa_segment_wbacksub/tests/main.nf.test.snap b/subworkflows/local/sopa_segment_wbacksub/tests/main.nf.test.snap index 71062c5..ed24a15 100644 --- a/subworkflows/local/sopa_segment_wbacksub/tests/main.nf.test.snap +++ b/subworkflows/local/sopa_segment_wbacksub/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test" }, - "test.geojson:md5,cb8854381fc9ce450d54699e2bea09ac" + "test.geojson:md5,a52037abb7566fda12e320e7e99bcc54" ] ], "1": [ @@ -19,7 +19,7 @@ { "id": "test" }, - "test.geojson:md5,cb8854381fc9ce450d54699e2bea09ac" + "test.geojson:md5,a52037abb7566fda12e320e7e99bcc54" ] ], "versions": [ @@ -32,6 +32,6 @@ "nf-test": "0.9.2", "nextflow": "25.04.4" }, - "timestamp": "2025-08-25T11:42:53.9036696" + "timestamp": "2025-09-12T10:13:33.539200685" } } \ No newline at end of file