From 8306f1adf8498dcfa05342de6c842ef3bebc3149 Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 20 Jul 2023 13:45:12 +0200 Subject: [PATCH 01/20] Remvoe fastqc from pipeline --- conf/modules.config | 4 --- modules.json | 5 ---- modules/nf-core/fastqc/main.nf | 51 -------------------------------- modules/nf-core/fastqc/meta.yml | 52 --------------------------------- workflows/mcmicro.nf | 11 ++----- 5 files changed, 3 insertions(+), 120 deletions(-) delete mode 100644 modules/nf-core/fastqc/main.nf delete mode 100644 modules/nf-core/fastqc/meta.yml diff --git a/conf/modules.config b/conf/modules.config index da58a5d..60f6467 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -26,10 +26,6 @@ process { ] } - withName: FASTQC { - ext.args = '--quiet' - } - withName: CUSTOM_DUMPSOFTWAREVERSIONS { publishDir = [ path: { "${params.outdir}/pipeline_info" }, diff --git a/modules.json b/modules.json index 2c9041b..282bf1c 100644 --- a/modules.json +++ b/modules.json @@ -10,11 +10,6 @@ "git_sha": "76cc4938c1f6ea5c7d83fed1eeffc146787f9543", "installed_by": ["modules"] }, - "fastqc": { - "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", - "installed_by": ["modules"] - }, "multiqc": { "branch": "master", "git_sha": "f2d63bd5b68925f98f572eed70993d205cc694b7", diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf deleted file mode 100644 index 9ae5838..0000000 --- a/modules/nf-core/fastqc/main.nf +++ /dev/null @@ -1,51 +0,0 @@ -process FASTQC { - tag "$meta.id" - label 'process_medium' - - conda "bioconda::fastqc=0.11.9" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/fastqc:0.11.9--0' : - 'quay.io/biocontainers/fastqc:0.11.9--0' }" - - input: - tuple val(meta), path(reads) - - output: - tuple val(meta), path("*.html"), emit: html - tuple val(meta), path("*.zip") , emit: zip - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" - // Make list of old name and new name pairs to use for renaming in the bash while loop - def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] } - def rename_to = old_new_pairs*.join(' ').join(' ') - def renamed_files = old_new_pairs.collect{ old_name, new_name -> new_name }.join(' ') - """ - printf "%s %s\\n" $rename_to | while read old_name new_name; do - [ -f "\${new_name}" ] || ln -s \$old_name \$new_name - done - fastqc $args --threads $task.cpus $renamed_files - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ - - stub: - def prefix = task.ext.prefix ?: "${meta.id}" - """ - touch ${prefix}.html - touch ${prefix}.zip - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ -} diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml deleted file mode 100644 index 4da5bb5..0000000 --- a/modules/nf-core/fastqc/meta.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: fastqc -description: Run FastQC on sequenced reads -keywords: - - quality control - - qc - - adapters - - fastq -tools: - - fastqc: - description: | - FastQC gives general quality metrics about your reads. - It provides information about the quality score distribution - across your reads, the per base sequence content (%A/C/G/T). - You get information about adapter contamination and other - overrepresented sequences. - homepage: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/ - documentation: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/ - licence: ["GPL-2.0-only"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - reads: - type: file - description: | - List of input FastQ files of size 1 and 2 for single-end and paired-end data, - respectively. -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - html: - type: file - description: FastQC report - pattern: "*_{fastqc.html}" - - zip: - type: file - description: FastQC report archive - pattern: "*_{fastqc.zip}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@drpatelh" - - "@grst" - - "@ewels" - - "@FelixKrueger" diff --git a/workflows/mcmicro.nf b/workflows/mcmicro.nf index bf07f49..d5c5870 100644 --- a/workflows/mcmicro.nf +++ b/workflows/mcmicro.nf @@ -46,7 +46,6 @@ include { INPUT_CHECK } from '../subworkflows/local/input_check' // // MODULE: Installed directly from nf-core/modules // -include { FASTQC } from '../modules/nf-core/fastqc/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' @@ -74,13 +73,9 @@ workflow MCMICRO { // See the documentation https://nextflow-io.github.io/nf-validation/samplesheets/fromSamplesheet/ // ! There is currently no tooling to help you write a sample sheet schema - // - // MODULE: Run FastQC - // - FASTQC ( - INPUT_CHECK.out.reads - ) - ch_versions = ch_versions.mix(FASTQC.out.versions.first()) + + + CUSTOM_DUMPSOFTWAREVERSIONS ( ch_versions.unique().collectFile(name: 'collated_versions.yml') From 534d0629e5a984fa96e84908aad605867c1ac0e1 Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 20 Jul 2023 14:53:29 +0200 Subject: [PATCH 02/20] Adding existing mcmirco --- modules/nf-core/backsub/main.nf | 46 +++++++++++++++ modules/nf-core/backsub/meta.yml | 73 ++++++++++++++++++++++++ modules/nf-core/cellpose/main.nf | 49 ++++++++++++++++ modules/nf-core/cellpose/meta.yml | 45 +++++++++++++++ modules/nf-core/deepcell/mesmer/main.nf | 39 +++++++++++++ modules/nf-core/deepcell/mesmer/meta.yml | 49 ++++++++++++++++ modules/nf-core/mcquant/main.nf | 48 ++++++++++++++++ modules/nf-core/mcquant/meta.yml | 69 ++++++++++++++++++++++ modules/nf-core/scimap/mcmicro/main.nf | 36 ++++++++++++ modules/nf-core/scimap/mcmicro/meta.yml | 53 +++++++++++++++++ 10 files changed, 507 insertions(+) create mode 100644 modules/nf-core/backsub/main.nf create mode 100644 modules/nf-core/backsub/meta.yml create mode 100644 modules/nf-core/cellpose/main.nf create mode 100644 modules/nf-core/cellpose/meta.yml create mode 100644 modules/nf-core/deepcell/mesmer/main.nf create mode 100644 modules/nf-core/deepcell/mesmer/meta.yml create mode 100644 modules/nf-core/mcquant/main.nf create mode 100644 modules/nf-core/mcquant/meta.yml create mode 100644 modules/nf-core/scimap/mcmicro/main.nf create mode 100644 modules/nf-core/scimap/mcmicro/meta.yml diff --git a/modules/nf-core/backsub/main.nf b/modules/nf-core/backsub/main.nf new file mode 100644 index 0000000..2d24277 --- /dev/null +++ b/modules/nf-core/backsub/main.nf @@ -0,0 +1,46 @@ +process BACKSUB { + tag "$meta.id" + label 'process_single' + + container "ghcr.io/schapirolabor/background_subtraction:v0.3.4" + + input: + tuple val(meta) , path(image) + tuple val(meta2), path(markerfile) + + output: + tuple val(meta), path("${prefix}.backsub.ome.tif"), emit: backsub_tif + tuple val(meta2), path("*.csv") , emit: markerout + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + """ + python3 /background_subtraction/background_sub.py \ + -o "${prefix}.backsub.ome.tif" \ + -mo markers_bs.csv \ + -r $image \ + -m $markerfile \ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + backsub: \$(python3 /background_subtraction/background_sub.py --version | sed 's/v//g') + END_VERSIONS + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}" + """ + touch "${prefix}.backsub.ome.tif" + touch "markers_bs.csv" + cat <<-END_VERSIONS > versions.yml + "${task.process}": + backsub: \$(python3 /background_subtraction/background_sub.py --version | sed 's/v//g') + END_VERSIONS + """ +} diff --git a/modules/nf-core/backsub/meta.yml b/modules/nf-core/backsub/meta.yml new file mode 100644 index 0000000..fedd7dd --- /dev/null +++ b/modules/nf-core/backsub/meta.yml @@ -0,0 +1,73 @@ +name: "backsub" +description: Pixel-by-pixel channel subtraction scaled by exposure times of pre-stitched `tif` images. +keywords: + - background + - cycif + - autofluorescence + - image_analysis + - mcmicro + - highly_multiplexed_imaging + +tools: + - "backsub": + description: "Module for pixel-by-pixel channel subtraction scaled by exposure times" + homepage: "https://github.com/SchapiroLabor/Background_subtraction" + documentation: "https://github.com/SchapiroLabor/Background_subtraction/blob/master/README.md" + tool_dev_url: "https://github.com/SchapiroLabor/Background_subtraction" + doi: "" + licence: "MIT licence" + +input: + # Only when we have meta + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - image: + type: file + description: Multi-channel image file + pattern: "*.{tif,tiff}" + + - meta2: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - markerfile: + type: file + description: Marker file with channel names, exposure times, and specified background to subtract (and remove to exclude channels from output) + pattern: "*.csv" + +output: + #Only when we have meta + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - backsub_tif: + type: file + description: Background corrected pyramidal ome.tif + pattern: "*.{tif}" + + - meta2: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - markerout: + type: file + description: Marker file adjusted to match the background corrected image + pattern: "*.{csv}" +authors: + - "@kbestak" diff --git a/modules/nf-core/cellpose/main.nf b/modules/nf-core/cellpose/main.nf new file mode 100644 index 0000000..a0925a9 --- /dev/null +++ b/modules/nf-core/cellpose/main.nf @@ -0,0 +1,49 @@ +process CELLPOSE { + tag "$meta.id" + label 'process_medium' + + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + exit 1, "I did not manage to create a cellpose module in Conda that works in all OSes. Please use Docker / Singularity / Podman instead."} + + container "biocontainers/cellpose:2.1.1_cv1" + + input: + tuple val(meta), path(image) + + output: + tuple val(meta), path("*masks.tif"), emit: mask + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def VERSION='2.1.1' + """ + cellpose \ + --image_path $image \ + --save_tif \ + --verbose \ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cellpose: $VERSION + END_VERSIONS + """ + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + def VERSION = "2.1.1" // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + """ + touch ${prefix}_cp_masks.tif + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cellpose: $VERSION + END_VERSIONS + """ + +} diff --git a/modules/nf-core/cellpose/meta.yml b/modules/nf-core/cellpose/meta.yml new file mode 100644 index 0000000..dc5c71d --- /dev/null +++ b/modules/nf-core/cellpose/meta.yml @@ -0,0 +1,45 @@ +name: "cellpose" +description: cellpose segments cells in images +keywords: + - segmentation +tools: + - "cellpose": + description: "cellpose is an anatomical segmentation algorithm written in Python 3 by Carsen Stringer and Marius Pachitariu" + homepage: "https://github.com/MouseLand/cellpose" + documentation: "https://cellpose.readthedocs.io/en/latest/command.html" + tool_dev_url: "https://github.com/MouseLand/cellpose" + doi: "https://doi.org/10.1038/s41592-022-01663-4" + licence: "BSD 3-Clause" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + (sample id) + - image: + type: image stack + description: tif file for ready for segmentation + pattern: "*.{tif,tiff}" + - model: + type: pretrained model from the model zoo + description: string for picking a pretrained model + pattern: "{nuclei,cyto,cyto2,tissuenet,tissuenet,TN1,TN2,TN3,LC1,LC2,LC3,LC4}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + [sample id] + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - image_mask: + type: tif_file + description: labelled mask output from cellpose in tif format + pattern: "*.{tif, tiff}" + +authors: + - "@josenimo" diff --git a/modules/nf-core/deepcell/mesmer/main.nf b/modules/nf-core/deepcell/mesmer/main.nf new file mode 100644 index 0000000..f3c02f6 --- /dev/null +++ b/modules/nf-core/deepcell/mesmer/main.nf @@ -0,0 +1,39 @@ +process DEEPCELL_MESMER { + tag "$meta.id" + label 'process_single' + + container "vanvalenlab/deepcell-applications:0.4.0" + + input: + tuple val(meta) , path(img) + tuple val(meta2), path(membrane_img) + + // Output a .tif image, don't touch versions + output: + tuple val(meta), path("mask.tif"), emit: mask + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def membrane_command = membrane_img ? "--membrane-image $membrane_img" : "" + def VERSION = "0.4.0" + + """ + python /usr/src/app/run_app.py mesmer \ + --squeeze \ + --nuclear-image $img \ + --output-directory . \ + --output-name mask.tif \ + $membrane_command \ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + deepcell_mesmer:: $VERSION + END_VERSIONS + """ +} diff --git a/modules/nf-core/deepcell/mesmer/meta.yml b/modules/nf-core/deepcell/mesmer/meta.yml new file mode 100644 index 0000000..c4c7715 --- /dev/null +++ b/modules/nf-core/deepcell/mesmer/meta.yml @@ -0,0 +1,49 @@ +name: "deepcell_mesmer" +description: Deepcell/mesmer segmentation for whole-cell +keywords: + - imaging + - spatial_omics + - segmentation +tools: + - "mesmer": + description: "Deep cell is a collection of tools to segment imaging data" + homepage: "https://github.com/vanvalenlab/deepcell-tf" + documentation: "https://github.com/vanvalenlab/intro-to-deepcell/tree/master/pretrained_models" + tool_dev_url: "https://githu/b.com/vanvalenlab/deepcell-tf" + doi: "https://doi.org/10.1038/s41587-021-01094-0" + licence: "APACHE2" + +input: + # Only when we have meta + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + # We always need to have an image of the tissue. (That's the whole point fo cell segmentation) + - img: + type: file + description: Multichannel image file + pattern: "*.{tiff,tif,h5,hdf5}" + +output: + #Only when we have meta + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + # + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - mask: + type: file + description: File containing the mask. + pattern: "*.{tif, tiff}" + +authors: + - "@migueLib" + - "@chiarasch" diff --git a/modules/nf-core/mcquant/main.nf b/modules/nf-core/mcquant/main.nf new file mode 100644 index 0000000..b78e87f --- /dev/null +++ b/modules/nf-core/mcquant/main.nf @@ -0,0 +1,48 @@ +process MCQUANT { + tag "$meta.id" + label 'process_single' + + // WARN: Version information not provided by tool on CLI. Please update version string below when bumping container versions. + container "labsyspharm/quantification:1.5.4" + + input: + tuple val(meta), path(image) + tuple val(meta2), path(mask) + tuple val(meta3), path(markerfile) + + output: + tuple val(meta), path("*.csv"), emit: csv + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def VERSION = '1.5.4' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + """ + python /app/CommandSingleCellExtraction.py \ + --masks $mask \ + --image $image \ + --channel_names $markerfile \ + --output . + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + mcquant: $VERSION + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + def VERSION = '1.5.4' + """ + touch ${prefix}.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + mcquant: $VERSION + END_VERSIONS + """ +} diff --git a/modules/nf-core/mcquant/meta.yml b/modules/nf-core/mcquant/meta.yml new file mode 100644 index 0000000..764dc40 --- /dev/null +++ b/modules/nf-core/mcquant/meta.yml @@ -0,0 +1,69 @@ +name: "mcquant" +description: write your description here +keywords: + - quantification + - image_analysis + - mcmicro + - highly_multiplexed_imaging +tools: + - "mcquant": + description: "Module for single-cell data extraction given a segmentation mask and multi-channel image. The CSV structure is aligned with histoCAT output." + homepage: "https://github.com/labsyspharm/quantification" + documentation: "https://github.com/labsyspharm/quantification/blob/master/README.md" + tool_dev_url: "https://github.com/labsyspharm/quantification" + doi: "https://doi.org/10.1038/s41592-021-01308-y" + licence: "" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - image: + type: file + description: Multi-channel image file + pattern: "*.{tiff,tif,h5,hdf5}" + + - meta2: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - mask: + type: file + description: Labeled segmentation mask for image + pattern: "*.{tiff,tif,h5,hdf5}" + + - meta3: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - markerfile: + type: file + description: Marker file with channel names for image to quantify + pattern: "*.{csv}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - csv: + type: file + description: Quantified regionprops_table + pattern: "*.{csv}" + +authors: + - "@FloWuenne" diff --git a/modules/nf-core/scimap/mcmicro/main.nf b/modules/nf-core/scimap/mcmicro/main.nf new file mode 100644 index 0000000..bc15922 --- /dev/null +++ b/modules/nf-core/scimap/mcmicro/main.nf @@ -0,0 +1,36 @@ +process SCIMAP_MCMICRO { + tag "$meta.id" + label 'process_single' + + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + exit 1, "Scimap module does not support Conda. Please use Docker / Singularity / Podman instead." + } + + container "labsyspharm/scimap:0.22.0" + + input: + tuple val(meta), path(cellbyfeature) + + output: + tuple val(meta), path("*.csv") , emit: annotedDataCsv, optional:true + tuple val(meta), path("*.h5ad") , emit: annotedDataH5ad, optional:true + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def VERSION='0.22.0' // WARN: Version information not provided by tool on CLI. Please update this string when bumping + """ + scimap-mcmicro $cellbyfeature -o . + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + scimap: $VERSION + END_VERSIONS + """ + +} diff --git a/modules/nf-core/scimap/mcmicro/meta.yml b/modules/nf-core/scimap/mcmicro/meta.yml new file mode 100644 index 0000000..eb86026 --- /dev/null +++ b/modules/nf-core/scimap/mcmicro/meta.yml @@ -0,0 +1,53 @@ +name: "scimap_mcmicro" +description: SCIMAP is a suite of tools that enables spatial single-cell analyses +keywords: + - sort +tools: + - "scimap": + description: "Scimap is a scalable toolkit for analyzing spatial molecular data." + homepage: "https://scimap.xyz/" + documentation: "https://scimap.xyz/All%20Functions/A.%20Pre%20Processing/sm.pp.mcmicro_to_scimap/" + tool_dev_url: "https://github.com/labsyspharm/scimap" + doi: "" + licence: "MIT License" + +input: + # Only when we have meta + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - cellByFeature: + type: file + description: CSV file with cell by feature table + pattern: "*.{csv}" + +output: + #Only when we have meta + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + # + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - annotedDataCsv: + type: file + description: Sorted CSV file + pattern: "*.{csv}" + - annotedDataH5ad: + type: file + description: Sorted H5AD file + pattern: "*.{h5ad}" + + # - clusterPlot: + # type: file + # description: UPMA plot of the data in pdf file + # pattern: "*.pdf" + +authors: + - "@luiskuhn" From 861877ca81d75bfb4b9250f0236c33812ee3d5e8 Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 20 Jul 2023 17:55:07 +0200 Subject: [PATCH 03/20] Adding basicpy --- modules/nf-core/basicpy/main.nf | 45 ++++++++++++++++++++++++++++++ modules/nf-core/basicpy/meta.yml | 47 ++++++++++++++++++++++++++++++++ workflows/mcmicro.nf | 27 ++++++++++++++++-- 3 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 modules/nf-core/basicpy/main.nf create mode 100644 modules/nf-core/basicpy/meta.yml diff --git a/modules/nf-core/basicpy/main.nf b/modules/nf-core/basicpy/main.nf new file mode 100644 index 0000000..bfebe90 --- /dev/null +++ b/modules/nf-core/basicpy/main.nf @@ -0,0 +1,45 @@ +process BASICPY { + tag "$meta.id" + label 'process_single' + + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + exit 1, "Basicpy module does not support Conda. Please use Docker / Singularity instead." + } + + container "docker.io/yfukai/basicpy-docker-mcmicro:0.2.1" + + input: + tuple val(meta), path(image) + + output: + tuple val(meta), path("*.tiff"), emit: fields + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def VERSION = "1.0.1" // WARN: Version information not provided by tool on CLI. Please update this string when bumping + """ + /opt/main.py -i $image -o . $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + basicpy:: $VERSION + END_VERSIONS + """ + + stub: + """ + touch ${prefix}.-dfp.tiff + touch ${prefix}.-dfp.tiff + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + basicpy:: $VERSION + END_VERSIONS + """ +} diff --git a/modules/nf-core/basicpy/meta.yml b/modules/nf-core/basicpy/meta.yml new file mode 100644 index 0000000..1415178 --- /dev/null +++ b/modules/nf-core/basicpy/meta.yml @@ -0,0 +1,47 @@ +name: "basicpy" +description: BaSiCPy is a python package for background and shading correction of optical microscopy images. It is developed based on the Matlab version of BaSiC tool with major improvements in the algorithm. +keywords: + - illumiation_correction + - background_correction + - microscopy + - imaging +tools: + - "basicpy": + description: "BaSiCPy is a python package for background and shading correction of optical microscopy images. It is developed based on the Matlab version of BaSiC tool with major improvements in the algorithm. The container of this tool needs to be initialized with an empty Entrypoint. See the nextflow.config of the tests for details." + homepage: "https://github.com/peng-lab/BaSiCPy" + documentation: "https://basicpy.readthedocs.io/en/latest/index.html" + tool_dev_url: "https://github.com/peng-lab/BaSiCPy" + doi: 10.1038/ncomms14836 + licence: "MIT License" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + + - image: + type: file + description: Tiff file to be used for dark and flat field illumination correction + pattern: "*.{tiff,tif}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - fields: + type: file + description: Tiff fields for dark and flat field illumination correction + pattern: "*.{tiff,tif}" + +authors: + - "@FloWuenne" diff --git a/workflows/mcmicro.nf b/workflows/mcmicro.nf index d5c5870..3464d57 100644 --- a/workflows/mcmicro.nf +++ b/workflows/mcmicro.nf @@ -46,6 +46,12 @@ include { INPUT_CHECK } from '../subworkflows/local/input_check' // // MODULE: Installed directly from nf-core/modules // + +include { BACKSUB } from './modules/nf-core/backsub/main' +include { CELLPOSE } from './modules/nf-core/cellpose/main' +include { DEEPCELL_MESMER } from './modules/nf-core/deepcell/mesmer/main' +include { MCQUANT } from './modules/nf-core/mcquant/main' +include { SCIMAP_MCMICRO } from './modules/nf-core/scimap/mcmicro/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' @@ -62,9 +68,13 @@ workflow MCMICRO { ch_versions = Channel.empty() + // Manually define inputs here + image_tuple = tuple([ id:'image' ], '/home/florian/Documents/tmp_data_folder/cycif_tonsil_registered.ome.tif') + marker_tuple = tuple([ id:'marker'], '/home/florian/Documents/tmp_data_folder/markers.csv') + // // SUBWORKFLOW: Read in samplesheet, validate and stage input files - // + /* INPUT_CHECK ( file(params.input) ) @@ -72,10 +82,22 @@ workflow MCMICRO { // TODO: OPTIONAL, you can use nf-validation plugin to create an input channel from the samplesheet with Channel.fromSamplesheet("input") // See the documentation https://nextflow-io.github.io/nf-validation/samplesheets/fromSamplesheet/ // ! There is currently no tooling to help you write a sample sheet schema + */ + + // Run Background Correction + BACKSUB(image_tuple,marker_tuple) + ch_versions = ch_versions.mix(BACKSUB.out.versions) - + CELLPOSE(BACKSUB.out.backsub_tif) + ch_versions = ch_versions.mix(CELLPOSE.out.versions) + MCQUANT(BACKSUB.out.backsub_tif, + CELLPOSE.out.mask, + BACKSUB.out.markerout) + ch_versions = ch_versions.mix(MCQUANT.out.versions) + SCIMAP_MCMICRO(MCQUANT.out.csv) + ch_versions = ch_versions.mix(SCIMAP_MCMICRO.out.versions) CUSTOM_DUMPSOFTWAREVERSIONS ( ch_versions.unique().collectFile(name: 'collated_versions.yml') @@ -94,7 +116,6 @@ workflow MCMICRO { ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(CUSTOM_DUMPSOFTWAREVERSIONS.out.mqc_yml.collect()) - ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it[1]}.ifEmpty([])) MULTIQC ( ch_multiqc_files.collect(), From 28fe046d1c1712621828092c11dee1eae755da4c Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 20 Jul 2023 17:55:22 +0200 Subject: [PATCH 04/20] Adding Ashlar --- modules/nf-core/ashlar/main.nf | 51 +++++++++++++++++++++++++++++++++ modules/nf-core/ashlar/meta.yml | 42 +++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 modules/nf-core/ashlar/main.nf create mode 100644 modules/nf-core/ashlar/meta.yml diff --git a/modules/nf-core/ashlar/main.nf b/modules/nf-core/ashlar/main.nf new file mode 100644 index 0000000..b3b78a2 --- /dev/null +++ b/modules/nf-core/ashlar/main.nf @@ -0,0 +1,51 @@ +process ASHLAR { + tag '$meta.id' + label 'process_single' + + conda "bioconda::ashlar=1.17.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/ashlar:1.17.0--pyh5e36f6f_0' : + 'biocontainers/ashlar:1.17.0--pyh5e36f6f_0' }" + + input: + tuple val(meta), path(file) + path(opt_dfp) + path(opt_ffp) + + output: + tuple val(meta), path("*.ome.tif"), emit: tif + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def dfp = opt_dfp ? "--dfp $opt_dfp" : "" + def ffp = opt_ffp ? "--ffp $opt_ffp" : "" + def num_files = file instanceof List ? file.size() : 1 + def opt_dfp_size = opt_dfp instanceof List ? opt_dfp.size() : 1 + def opt_ffp_size = opt_ffp instanceof List ? opt_ffp.size() : 1 + def dfp_validated = (opt_dfp_size == 0 || opt_dfp_size == 1 || opt_dfp_size == num_files) ? true : false + def ffp_validated = (opt_ffp_size == 0 || opt_ffp_size == 1 || opt_ffp_size == num_files) ? true : false + + """ + if [ "$dfp_validated" = "false" ]; then + echo "Error: please input only zero or one dfp files" + exit 1 + fi + if [ "$ffp_validated" = "false" ]; then + echo "Error: please input only zero or one ffp files" + exit 1 + fi + ashlar \\ + $file \\ + $args \\ + $dfp \\ + $ffp + cat <<-END_VERSIONS > versions.yml + "${task.process}": + ashlar: \$(ashlar --version 2>&1 | sed 's/^.*ashlar //; s/Using.*\$//' ) + END_VERSIONS + """ +} \ No newline at end of file diff --git a/modules/nf-core/ashlar/meta.yml b/modules/nf-core/ashlar/meta.yml new file mode 100644 index 0000000..cb9e888 --- /dev/null +++ b/modules/nf-core/ashlar/meta.yml @@ -0,0 +1,42 @@ +name: "ashlar" +description: Alignment by Simultaneous Harmonization of Layer/Adjacency Registration +keywords: + - image_processing + - alignment + - registration +tools: + - "ashlar": + description: "Alignment by Simultaneous Harmonization of Layer/Adjacency Registration" + homepage: "https://labsyspharm.github.io/ashlar/" + documentation: "https://labsyspharm.github.io/ashlar/" + doi: "10.1093/bioinformatics/btac544" + licence: ["MIT"] + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - file_in: + type: file + description: Overlapping tile image data in formats from most commercial microscopes + pattern: "*.{ome.tiff,ome.tif,rcpnl,btf,nd2,tiff,tif,czi}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - tif: + type: file + description: pyramidal OME-TIFF + pattern: "*.ome.tif" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@RobJY" + - "@jmuhlich" \ No newline at end of file From ae8706949c55e4429e0c52c9a7075a9ca89b0fc3 Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 20 Jul 2023 17:56:17 +0200 Subject: [PATCH 05/20] Adding basicpy and ashlar to workflow --- workflows/mcmicro.nf | 51 +++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/workflows/mcmicro.nf b/workflows/mcmicro.nf index 3464d57..7985011 100644 --- a/workflows/mcmicro.nf +++ b/workflows/mcmicro.nf @@ -47,6 +47,10 @@ include { INPUT_CHECK } from '../subworkflows/local/input_check' // MODULE: Installed directly from nf-core/modules // +//include { ILLUMINATION } from './modules/nf-core/local/illumination.nf' + +include { BASICPY } from './modules/nf-core/basicpy/main' +include { ASHLAR } from './modules/nf-core/ashlar/main' include { BACKSUB } from './modules/nf-core/backsub/main' include { CELLPOSE } from './modules/nf-core/cellpose/main' include { DEEPCELL_MESMER } from './modules/nf-core/deepcell/mesmer/main' @@ -61,6 +65,15 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +// Manually define inputs here +//image_tuple = tuple([ id:'image' ], '/home/florian/Documents/tmp_data_folder/cycif_tonsil_registered.ome.tif') +//marker_tuple = tuple([ id:'marker'], '/home/florian/Documents/tmp_data_folder/markers.csv') + +ch_input = file(params.input) + +// Identify marker information +ch_marker = Channel.fromPath( "${params.input}/markers.csv", checkIfExists: true ) + // Info required for completion email and summary def multiqc_report = [] @@ -68,20 +81,32 @@ workflow MCMICRO { ch_versions = Channel.empty() - // Manually define inputs here - image_tuple = tuple([ id:'image' ], '/home/florian/Documents/tmp_data_folder/cycif_tonsil_registered.ome.tif') - marker_tuple = tuple([ id:'marker'], '/home/florian/Documents/tmp_data_folder/markers.csv') + //ILLUMINATION(mcp.modules['illumination'], raw) - // - // SUBWORKFLOW: Read in samplesheet, validate and stage input files - /* - INPUT_CHECK ( - file(params.input) - ) - ch_versions = ch_versions.mix(INPUT_CHECK.out.versions) - // TODO: OPTIONAL, you can use nf-validation plugin to create an input channel from the samplesheet with Channel.fromSamplesheet("input") - // See the documentation https://nextflow-io.github.io/nf-validation/samplesheets/fromSamplesheet/ - // ! There is currently no tooling to help you write a sample sheet schema + // sample check here: + // ch_images = INPUT_CHECK( ch_input ).images + // ch_markers = INPUT_CHECK( ch_input ).markers + + BASICPY(ch_input) + ch_tif = BASICPY.outs.tif + ch_versions = ch_versions.mix(BASICPY.out.versions) + + ch_dfp = ch_tif.filter { file -> file.name.endsWith('.dfp.tiff') } + ch_ffp = ch_tif.filter { file -> file.name.endsWith('.ffp.tiff') } + + ASHLAR(ch_input, ch_dfp, ch_ffp) + + // Should background subtraction be applied? + /*img = img. + branch{ + nobs: !wfp.background + bs: wfp.background + } + chMrk = chMrk. + branch{ + nobs: !wfp.background + bs: wfp.background + } */ // Run Background Correction From aaf53a22057777eb4125070a143afe7a3596be2c Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 20 Jul 2023 19:01:34 +0200 Subject: [PATCH 06/20] Applying input check --- bin/check_samplesheet.py | 68 +++++++++++++++---------------- subworkflows/local/input_check.nf | 27 ++++++------ 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 4a758fe..1c523ac 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -25,16 +25,15 @@ class RowChecker: """ VALID_FORMATS = ( - ".fq.gz", - ".fastq.gz", + ".tiff", ) def __init__( self, sample_col="sample", - first_col="fastq_1", - second_col="fastq_2", - single_col="single_end", + first_col="channel", + second_col="tiff", + #single_col="single_end", **kwargs, ): """ @@ -43,20 +42,20 @@ def __init__( Args: sample_col (str): The name of the column that contains the sample name (default "sample"). - first_col (str): The name of the column that contains the first (or only) - FASTQ file path (default "fastq_1"). - second_col (str): The name of the column that contains the second (if any) - FASTQ file path (default "fastq_2"). - single_col (str): The name of the new column that will be inserted and - records whether the sample contains single- or paired-end sequencing - reads (default "single_end"). + first_col (str): The name of the column that contains the channel name + (default "channel"). + second_col (str): The name of the column that contains the tiff file + Tiff file path (default "tiff"). + #single_col (str): The name of the new column that will be inserted and + # records whether the sample contains single- or paired-end sequencing + # reads (default "single_end"). """ super().__init__(**kwargs) self._sample_col = sample_col self._first_col = first_col self._second_col = second_col - self._single_col = single_col + #self._single_col = single_col self._seen = set() self.modified = [] @@ -84,15 +83,16 @@ def _validate_sample(self, row): row[self._sample_col] = row[self._sample_col].replace(" ", "_") def _validate_first(self, row): - """Assert that the first FASTQ entry is non-empty and has the right format.""" + """Assert that the channel entry is non-empty and has the right format.""" if len(row[self._first_col]) <= 0: - raise AssertionError("At least the first FASTQ file is required.") - self._validate_fastq_format(row[self._first_col]) + raise AssertionError("Channel name required.") + row[self._first_col] = row[self._first_col].replace(" ", "_") def _validate_second(self, row): - """Assert that the second FASTQ entry has the right format if it exists.""" - if len(row[self._second_col]) > 0: - self._validate_fastq_format(row[self._second_col]) + """Assert that the tiff entry has the right format if it exists.""" + if len(row[self._second_col]) <= 0: + raise AssertionError("Tiff required.") + self._validate_tiff_format(row[self._second_col]) def _validate_pair(self, row): """Assert that read pairs have the same file extension. Report pair status.""" @@ -105,24 +105,24 @@ def _validate_pair(self, row): else: row[self._single_col] = True - def _validate_fastq_format(self, filename): - """Assert that a given filename has one of the expected FASTQ extensions.""" + def _validate_tiff_format(self, filename): + """Assert that a given filename has tiff extension.""" if not any(filename.endswith(extension) for extension in self.VALID_FORMATS): raise AssertionError( - f"The FASTQ file has an unrecognized extension: {filename}\n" + f"The tiff file has an unrecognized extension: {filename}\n" f"It should be one of: {', '.join(self.VALID_FORMATS)}" ) def validate_unique_samples(self): """ - Assert that the combination of sample name and FASTQ filename is unique. + Assert that the combination of sample name and tiff filename is unique. In addition to the validation, also rename all samples to have a suffix of _T{n}, where n is the - number of times the same sample exist, but with different FASTQ files, e.g., multiple runs per experiment. + number of times the same sample exist, but with different tiff files, e.g., multiple runs per experiment. """ if len(self._seen) != len(self.modified): - raise AssertionError("The pair of sample name and FASTQ must be unique.") + raise AssertionError("The pair of channel and tiff must be unique.") seen = Counter() for row in self.modified: sample = row[self._sample_col] @@ -166,8 +166,8 @@ def check_samplesheet(file_in, file_out): """ Check that the tabular samplesheet has the structure expected by nf-core pipelines. - Validate the general shape of the table, expected columns, and each row. Also add - an additional column which records whether one or two FASTQ reads were found. + Validate the general shape of the table, expected columns, and each row. + # Also add an additional column which records whether one or two FASTQ reads were found. Args: file_in (pathlib.Path): The given tabular samplesheet. The format can be either @@ -179,16 +179,16 @@ def check_samplesheet(file_in, file_out): This function checks that the samplesheet follows the following structure, see also the `viral recon samplesheet`_:: - sample,fastq_1,fastq_2 - SAMPLE_PE,SAMPLE_PE_RUN1_1.fastq.gz,SAMPLE_PE_RUN1_2.fastq.gz - SAMPLE_PE,SAMPLE_PE_RUN2_1.fastq.gz,SAMPLE_PE_RUN2_2.fastq.gz - SAMPLE_SE,SAMPLE_SE_RUN1_1.fastq.gz, + sample,channel,tiff + SAMPLE,001,exemplar-001-cycle-08.ome.tiff + SAMPLE,001,exemplar-001-cycle-07.ome.tiff + SAMPLE,001,exemplar-001-cycle-06.ome.tiff - .. _viral recon samplesheet: - https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv + #.. _viral recon samplesheet: + # https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv """ - required_columns = {"sample", "fastq_1", "fastq_2"} + required_columns = {"sample", "channel", "tiff"} # See https://docs.python.org/3.9/library/csv.html#id3 to read up on `newline=""`. with file_in.open(newline="") as in_handle: reader = csv.DictReader(in_handle, dialect=sniff_format(in_handle)) diff --git a/subworkflows/local/input_check.nf b/subworkflows/local/input_check.nf index 0aecf87..aba8856 100644 --- a/subworkflows/local/input_check.nf +++ b/subworkflows/local/input_check.nf @@ -13,10 +13,10 @@ workflow INPUT_CHECK { .csv .splitCsv ( header:true, sep:',' ) .map { create_fastq_channel(it) } - .set { reads } + .set { images } emit: - reads // channel: [ val(meta), [ reads ] ] + images // channel: [ val(meta), [ reads ] ] versions = SAMPLESHEET_CHECK.out.versions // channel: [ versions.yml ] } @@ -25,20 +25,21 @@ def create_fastq_channel(LinkedHashMap row) { // create meta map def meta = [:] meta.id = row.sample - meta.single_end = row.single_end.toBoolean() + meta.tiff = row.single_end.toBoolean() // add path(s) of the fastq file(s) to the meta map def fastq_meta = [] - if (!file(row.fastq_1).exists()) { - exit 1, "ERROR: Please check input samplesheet -> Read 1 FastQ file does not exist!\n${row.fastq_1}" - } - if (meta.single_end) { - fastq_meta = [ meta, [ file(row.fastq_1) ] ] - } else { - if (!file(row.fastq_2).exists()) { - exit 1, "ERROR: Please check input samplesheet -> Read 2 FastQ file does not exist!\n${row.fastq_2}" - } - fastq_meta = [ meta, [ file(row.fastq_1), file(row.fastq_2) ] ] + if (!file(row.tiff).exists()) { + exit 1, "ERROR: Please check input samplesheet -> tiff file does not exist!\n${row.tiff}" } + // if (meta.single_end) { + // fastq_meta = [ meta, [ file(row.fastq_1) ] ] + // } else { + // if (!file(row.fastq_2).exists()) { + // exit 1, "ERROR: Please check input samplesheet -> Read 2 FastQ file does not exist!\n${row.fastq_2}" + // } + //} + fastq_meta = [ meta, [ file(row.tiff) ] ] + return fastq_meta } From 8fd5543cc2ed5953d7372a1b9a413ecbdc420634 Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 20 Jul 2023 19:02:06 +0200 Subject: [PATCH 07/20] Adding parameter option for illumination step --- nextflow.config | 2 ++ workflows/mcmicro.nf | 29 +++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/nextflow.config b/nextflow.config index d0f038b..92b5818 100644 --- a/nextflow.config +++ b/nextflow.config @@ -17,6 +17,8 @@ params { igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false + // Illumination options + illumination = false // MultiQC options multiqc_config = null diff --git a/workflows/mcmicro.nf b/workflows/mcmicro.nf index 7985011..7f9f6fe 100644 --- a/workflows/mcmicro.nf +++ b/workflows/mcmicro.nf @@ -81,20 +81,33 @@ workflow MCMICRO { ch_versions = Channel.empty() + // + // SUBWORKFLOW: Read in samplesheet, validate and stage input files + // + INPUT_CHECK ( + file(params.input) + ) + ch_versions = ch_versions.mix(INPUT_CHECK.out.versions) + // TODO: OPTIONAL, you can use nf-validation plugin to create an input channel from the samplesheet with Channel.fromSamplesheet("input") + // See the documentation https://nextflow-io.github.io/nf-validation/samplesheets/fromSamplesheet/ + // ! There is currently no tooling to help you write a sample sheet schema + //ILLUMINATION(mcp.modules['illumination'], raw) // sample check here: - // ch_images = INPUT_CHECK( ch_input ).images - // ch_markers = INPUT_CHECK( ch_input ).markers + ch_images = INPUT_CHECK( ch_input ).images + ch_markers = INPUT_CHECK( ch_input ).markers - BASICPY(ch_input) - ch_tif = BASICPY.outs.tif - ch_versions = ch_versions.mix(BASICPY.out.versions) + if ( params.illumination ): + BASICPY(ch_input) + ch_tif = BASICPY.outs.tif + ch_versions = ch_versions.mix(BASICPY.out.versions) - ch_dfp = ch_tif.filter { file -> file.name.endsWith('.dfp.tiff') } - ch_ffp = ch_tif.filter { file -> file.name.endsWith('.ffp.tiff') } + ch_dfp = ch_tif.filter { file -> file.name.endsWith('.dfp.tiff') } + ch_ffp = ch_tif.filter { file -> file.name.endsWith('.ffp.tiff') } - ASHLAR(ch_input, ch_dfp, ch_ffp) + ch_images = ASHLAR(ch_input, ch_dfp, ch_ffp).tif + ch_versions = ch_versions.mix(ASHLAR.out.versions) // Should background subtraction be applied? /*img = img. From 3aa1fba092ae117dfa42a89275f0d37b6c07484c Mon Sep 17 00:00:00 2001 From: Florian Date: Fri, 21 Jul 2023 10:39:27 +0200 Subject: [PATCH 08/20] Moving ashlar to local --- modules/{nf-core => local}/ashlar/main.nf | 0 modules/{nf-core => local}/ashlar/meta.yml | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename modules/{nf-core => local}/ashlar/main.nf (100%) rename modules/{nf-core => local}/ashlar/meta.yml (100%) diff --git a/modules/nf-core/ashlar/main.nf b/modules/local/ashlar/main.nf similarity index 100% rename from modules/nf-core/ashlar/main.nf rename to modules/local/ashlar/main.nf diff --git a/modules/nf-core/ashlar/meta.yml b/modules/local/ashlar/meta.yml similarity index 100% rename from modules/nf-core/ashlar/meta.yml rename to modules/local/ashlar/meta.yml From 943452f0d640788e6369866b644f2a7a53a90a8d Mon Sep 17 00:00:00 2001 From: Florian Date: Fri, 21 Jul 2023 10:40:05 +0200 Subject: [PATCH 09/20] Updated module.json of new modules --- modules.json | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/modules.json b/modules.json index 282bf1c..85102b6 100644 --- a/modules.json +++ b/modules.json @@ -5,15 +5,45 @@ "https://github.com/nf-core/modules.git": { "modules": { "nf-core": { + "backsub": { + "branch": "master", + "git_sha": "497959008150b4b0df530d74941a448f8cf0d60e", + "installed_by": ["modules"] + }, + "basicpy": { + "branch": "master", + "git_sha": "b9829e1064382745d8dff7f1d74d2138d2864f71", + "installed_by": ["modules"] + }, + "cellpose": { + "branch": "master", + "git_sha": "8f65c1af123207d234ea3fc6dcd19d30b4a0e322", + "installed_by": ["modules"] + }, "custom/dumpsoftwareversions": { "branch": "master", "git_sha": "76cc4938c1f6ea5c7d83fed1eeffc146787f9543", "installed_by": ["modules"] }, + "deepcell/mesmer": { + "branch": "master", + "git_sha": "c0c79f6f8f027f75262a797525713178de4b60e7", + "installed_by": ["modules"] + }, + "mcquant": { + "branch": "master", + "git_sha": "96ca9f700f2c8b1cf1f0765419a79c09ff53db08", + "installed_by": ["modules"] + }, "multiqc": { "branch": "master", "git_sha": "f2d63bd5b68925f98f572eed70993d205cc694b7", "installed_by": ["modules"] + }, + "scimap/mcmicro": { + "branch": "master", + "git_sha": "423fa88f8e904b33cad103e8e69eb351b2a4ecb9", + "installed_by": ["modules"] } } } From 74daa93ec9b30d4999a1456c774f1af2787fa741 Mon Sep 17 00:00:00 2001 From: Florian Date: Fri, 21 Jul 2023 16:55:41 +0200 Subject: [PATCH 10/20] Updating sample checking --- bin/check_samplesheet.py | 91 ++++++++++++++++++------------- subworkflows/local/input_check.nf | 38 +++++++++---- 2 files changed, 79 insertions(+), 50 deletions(-) diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 1c523ac..9199613 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -24,15 +24,20 @@ class RowChecker: """ - VALID_FORMATS = ( + VALID_IMAGE_FORMATS = ( ".tiff", + ".tif" + ) + + VALID_MARKER_FORMATS = ( + ".csv" ) def __init__( self, sample_col="sample", - first_col="channel", - second_col="tiff", + first_col="image", + second_col="marker", #single_col="single_end", **kwargs, ): @@ -44,8 +49,8 @@ def __init__( (default "sample"). first_col (str): The name of the column that contains the channel name (default "channel"). - second_col (str): The name of the column that contains the tiff file - Tiff file path (default "tiff"). + second_col (str): The name of the column that contains the image file + image file path (default "tiff"). #single_col (str): The name of the new column that will be inserted and # records whether the sample contains single- or paired-end sequencing # reads (default "single_end"). @@ -71,7 +76,7 @@ def validate_and_transform(self, row): self._validate_sample(row) self._validate_first(row) self._validate_second(row) - self._validate_pair(row) + #self._validate_pair(row) self._seen.add((row[self._sample_col], row[self._first_col])) self.modified.append(row) @@ -83,51 +88,59 @@ def _validate_sample(self, row): row[self._sample_col] = row[self._sample_col].replace(" ", "_") def _validate_first(self, row): - """Assert that the channel entry is non-empty and has the right format.""" + """Assert that the image entry has the right format if it exists.""" if len(row[self._first_col]) <= 0: - raise AssertionError("Channel name required.") - row[self._first_col] = row[self._first_col].replace(" ", "_") + raise AssertionError("Image required.") + self._validate_image_format(row[self._first_col]) def _validate_second(self, row): - """Assert that the tiff entry has the right format if it exists.""" + """Assert that the image entry has the right format if it exists.""" if len(row[self._second_col]) <= 0: - raise AssertionError("Tiff required.") - self._validate_tiff_format(row[self._second_col]) - - def _validate_pair(self, row): - """Assert that read pairs have the same file extension. Report pair status.""" - if row[self._first_col] and row[self._second_col]: - row[self._single_col] = False - first_col_suffix = Path(row[self._first_col]).suffixes[-2:] - second_col_suffix = Path(row[self._second_col]).suffixes[-2:] - if first_col_suffix != second_col_suffix: - raise AssertionError("FASTQ pairs must have the same file extensions.") - else: - row[self._single_col] = True - - def _validate_tiff_format(self, filename): - """Assert that a given filename has tiff extension.""" - if not any(filename.endswith(extension) for extension in self.VALID_FORMATS): + raise AssertionError("Marker required.") + self._validate_marker_format(row[self._second_col]) + + # def _validate_pair(self, row): + # """Assert that read pairs have the same file extension. Report pair status.""" + # if row[self._first_col] and row[self._second_col]: + # row[self._single_col] = False + # first_col_suffix = Path(row[self._first_col]).suffixes[-2:] + # second_col_suffix = Path(row[self._second_col]).suffixes[-2:] + # if first_col_suffix != second_col_suffix: + # raise AssertionError("FASTQ pairs must have the same file extensions.") + # else: + # row[self._single_col] = True + + def _validate_image_format(self, filename): + """Assert that a given filename has image extension.""" + if not any(filename.endswith(extension) for extension in self.VALID_IMAGE_FORMATS): + raise AssertionError( + f"The image file has an unrecognized extension: {filename}\n" + f"It should be one of: {', '.join(self.VALID_IMAGE_FORMATS)}" + ) + + def _validate_marker_format(self, filename): + """Assert that a given filename has marker extension.""" + if not any(filename.endswith(extension) for extension in self.VALID_MARKER_FORMATS): raise AssertionError( - f"The tiff file has an unrecognized extension: {filename}\n" - f"It should be one of: {', '.join(self.VALID_FORMATS)}" + f"The marker file has an unrecognized extension: {filename}\n" + f"It should be one of: {', '.join(self.VALID_MARKER_FORMATS)}" ) def validate_unique_samples(self): """ - Assert that the combination of sample name and tiff filename is unique. + Assert that the combination of sample name and image filename is unique. In addition to the validation, also rename all samples to have a suffix of _T{n}, where n is the - number of times the same sample exist, but with different tiff files, e.g., multiple runs per experiment. + number of times the same sample exist, but with different image files, e.g., multiple runs per experiment. """ if len(self._seen) != len(self.modified): - raise AssertionError("The pair of channel and tiff must be unique.") + raise AssertionError("The pair of channel and image must be unique.") seen = Counter() for row in self.modified: sample = row[self._sample_col] seen[sample] += 1 - row[self._sample_col] = f"{sample}_T{seen[sample]}" + #row[self._sample_col] = f"{sample}_T{seen[sample]}" def read_head(handle, num_lines=10): @@ -179,16 +192,16 @@ def check_samplesheet(file_in, file_out): This function checks that the samplesheet follows the following structure, see also the `viral recon samplesheet`_:: - sample,channel,tiff - SAMPLE,001,exemplar-001-cycle-08.ome.tiff - SAMPLE,001,exemplar-001-cycle-07.ome.tiff - SAMPLE,001,exemplar-001-cycle-06.ome.tiff + sample,ffp,dfp + SAMPLE,001,exemplar-001-cycle-08.ome.tiff,markers.csv + SAMPLE,001,exemplar-001-cycle-07.ome.tiff,markers.csv + SAMPLE,001,exemplar-001-cycle-06.ome.tiff,markers.csv #.. _viral recon samplesheet: # https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv """ - required_columns = {"sample", "channel", "tiff"} + required_columns = {"sample", "image", "marker"} # See https://docs.python.org/3.9/library/csv.html#id3 to read up on `newline=""`. with file_in.open(newline="") as in_handle: reader = csv.DictReader(in_handle, dialect=sniff_format(in_handle)) @@ -207,7 +220,7 @@ def check_samplesheet(file_in, file_out): sys.exit(1) checker.validate_unique_samples() header = list(reader.fieldnames) - header.insert(1, "single_end") + #header.insert(1, "single_end") # See https://docs.python.org/3.9/library/csv.html#id3 to read up on `newline=""`. with file_out.open(mode="w", newline="") as out_handle: writer = csv.DictWriter(out_handle, header, delimiter=",") diff --git a/subworkflows/local/input_check.nf b/subworkflows/local/input_check.nf index aba8856..b271912 100644 --- a/subworkflows/local/input_check.nf +++ b/subworkflows/local/input_check.nf @@ -9,14 +9,26 @@ workflow INPUT_CHECK { samplesheet // file: /path/to/samplesheet.csv main: + + /* + if( params.illumination){ + SAMPLESHEET_CHECK ( samplesheet ) + .csv + .splitCsv ( header:true, sep:',' ) + .map { create_fastq_channel(it) } + .groupTuple(by: [0]) + .map { meta, reads -> [ meta, reads.flatten() ] } + .set { images_merged } + } + */ SAMPLESHEET_CHECK ( samplesheet ) - .csv - .splitCsv ( header:true, sep:',' ) - .map { create_fastq_channel(it) } - .set { images } + .csv + .splitCsv ( header:true, sep:',' ) + .map { create_fastq_channel(it) } + .set { input } emit: - images // channel: [ val(meta), [ reads ] ] + input // channel: [ val(meta), [ image ], [ marker ] ] versions = SAMPLESHEET_CHECK.out.versions // channel: [ versions.yml ] } @@ -25,13 +37,17 @@ def create_fastq_channel(LinkedHashMap row) { // create meta map def meta = [:] meta.id = row.sample - meta.tiff = row.single_end.toBoolean() + // meta.tiff = row.single_end.toBoolean() // add path(s) of the fastq file(s) to the meta map - def fastq_meta = [] - if (!file(row.tiff).exists()) { - exit 1, "ERROR: Please check input samplesheet -> tiff file does not exist!\n${row.tiff}" + //def fastq_meta = [] + if (!file(row.image).exists()) { + exit 1, "ERROR: Please check input samplesheet -> image file does not exist!\n${row.image}" } + if (!file(row.marker).exists()) { + exit 1, "ERROR: Please check input samplesheet -> image file does not exist!\n${row.marker}" + } + // if (meta.single_end) { // fastq_meta = [ meta, [ file(row.fastq_1) ] ] // } else { @@ -39,7 +55,7 @@ def create_fastq_channel(LinkedHashMap row) { // exit 1, "ERROR: Please check input samplesheet -> Read 2 FastQ file does not exist!\n${row.fastq_2}" // } //} - fastq_meta = [ meta, [ file(row.tiff) ] ] + image_meta = [ meta, [ file(row.image) ], [file(row.marker)] ] - return fastq_meta + return image_meta } From 74b186fcc2a35529b2641010882390fe1a7c0322 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 24 Jul 2023 17:59:24 +0200 Subject: [PATCH 11/20] Changes to nextflow schema and config for new parameters --- nextflow.config | 9 ++++++--- nextflow_schema.json | 40 +++++++++++----------------------------- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/nextflow.config b/nextflow.config index 92b5818..c3e54ab 100644 --- a/nextflow.config +++ b/nextflow.config @@ -12,10 +12,11 @@ params { // TODO nf-core: Specify your pipeline's command line flags // Input options input = null + // References - genome = null - igenomes_base = 's3://ngi-igenomes/igenomes' - igenomes_ignore = false + //genome = null + //igenomes_base = 's3://ngi-igenomes/igenomes' + //igenomes_ignore = false // Illumination options illumination = false @@ -186,11 +187,13 @@ plugins { } // Load igenomes.config if required +/* if (!params.igenomes_ignore) { includeConfig 'conf/igenomes.config' } else { params.genomes = [:] } +*/ // Export these variables to prevent local Python/R libraries from conflicting with those in the container // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. diff --git a/nextflow_schema.json b/nextflow_schema.json index 0429bf1..99d186b 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -48,12 +48,6 @@ "fa_icon": "fas fa-dna", "description": "Reference genome related files and options required for the workflow.", "properties": { - "genome": { - "type": "string", - "description": "Name of iGenomes reference.", - "fa_icon": "fas fa-book", - "help_text": "If using a reference genome configured in the pipeline using iGenomes, use this parameter to give the ID for the reference. This is then used to build the full paths for all required reference genome files e.g. `--genome GRCh38`. \n\nSee the [nf-core website docs](https://nf-co.re/usage/reference_genomes) for more details." - }, "fasta": { "type": "string", "format": "file-path", @@ -63,21 +57,6 @@ "description": "Path to FASTA genome file.", "help_text": "This parameter is *mandatory* if `--genome` is not specified. If you don't have a BWA index available this will be generated for you automatically. Combine with `--save_reference` to save BWA index for future runs.", "fa_icon": "far fa-file-code" - }, - "igenomes_base": { - "type": "string", - "format": "directory-path", - "description": "Directory / URL base for iGenomes references.", - "default": "s3://ngi-igenomes/igenomes", - "fa_icon": "fas fa-cloud-download-alt", - "hidden": true - }, - "igenomes_ignore": { - "type": "boolean", - "description": "Do not load the iGenomes reference config.", - "fa_icon": "fas fa-ban", - "hidden": true, - "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`." } } }, @@ -175,14 +154,12 @@ "type": "boolean", "description": "Display help text.", "fa_icon": "fas fa-question-circle", - "default": false, "hidden": true }, "version": { "type": "boolean", "description": "Display version and exit.", "fa_icon": "fas fa-question-circle", - "default": false, "hidden": true }, "publish_dir_mode": { @@ -206,7 +183,6 @@ "type": "boolean", "description": "Send plain-text email instead of HTML.", "fa_icon": "fas fa-remove-format", - "default": false, "hidden": true }, "max_multiqc_email_size": { @@ -221,7 +197,6 @@ "type": "boolean", "description": "Do not use coloured log outputs.", "fa_icon": "fas fa-palette", - "default": false, "hidden": true }, "hook_url": { @@ -260,7 +235,6 @@ "type": "boolean", "fa_icon": "far fa-eye-slash", "description": "Show all params when using `--help`", - "default": false, "hidden": true, "help_text": "By default, parameters set as _hidden_ in the schema are not shown on the command line when a user runs with `--help`. Specifying this option will tell the pipeline to show all parameters." }, @@ -268,7 +242,6 @@ "type": "boolean", "fa_icon": "far fa-check-circle", "description": "Validation of parameters fails when an unrecognised parameter is found.", - "default": false, "hidden": true, "help_text": "By default, when an unrecognised parameter is found, it returns a warinig." }, @@ -276,9 +249,12 @@ "type": "boolean", "fa_icon": "far fa-check-circle", "description": "Validation of parameters in lenient more.", - "default": false, "hidden": true, "help_text": "Allows string values that are parseable as numbers or booleans. For further information see [JSONSchema docs](https://github.com/everit-org/json-schema#lenient-mode)." + }, + "illumination": { + "type": "boolean", + "default": "false" } } } @@ -299,5 +275,11 @@ { "$ref": "#/definitions/generic_options" } - ] + ], + "properties": { + "validationSchemaIgnoreParams": { + "type": "string", + "default": "genomes" + } + } } From d5be3edaf82c798289ccbb19d62bebe2fa54b705 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 24 Jul 2023 17:59:50 +0200 Subject: [PATCH 12/20] Changes to groovys to take our genomics stuff --- lib/WorkflowMain.groovy | 2 ++ lib/WorkflowMcmicro.groovy | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index ac0dace..5ad7823 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -52,6 +52,7 @@ class WorkflowMain { // // Get attribute from genome config file e.g. fasta // + /* public static Object getGenomeAttribute(params, attribute) { if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { if (params.genomes[ params.genome ].containsKey(attribute)) { @@ -60,4 +61,5 @@ class WorkflowMain { } return null } + */ } diff --git a/lib/WorkflowMcmicro.groovy b/lib/WorkflowMcmicro.groovy index 9bd153d..acb07ce 100755 --- a/lib/WorkflowMcmicro.groovy +++ b/lib/WorkflowMcmicro.groovy @@ -10,15 +10,16 @@ class WorkflowMcmicro { // // Check and validate parameters // + /* public static void initialise(params, log) { genomeExistsError(params, log) - if (!params.fasta) { Nextflow.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." } } + */ // // Get workflow summary for MultiQC @@ -109,6 +110,7 @@ class WorkflowMcmicro { // // Exit pipeline if incorrect --genome key provided // + /* private static void genomeExistsError(params, log) { if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { def error_string = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + @@ -119,4 +121,5 @@ class WorkflowMcmicro { Nextflow.error(error_string) } } + */ } From 83e50d67ae66d8c7516553780ce952d433bbaef0 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 24 Jul 2023 18:00:10 +0200 Subject: [PATCH 13/20] Changes to basic py --- modules/nf-core/basicpy/main.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/nf-core/basicpy/main.nf b/modules/nf-core/basicpy/main.nf index bfebe90..24ed4fe 100644 --- a/modules/nf-core/basicpy/main.nf +++ b/modules/nf-core/basicpy/main.nf @@ -22,7 +22,8 @@ process BASICPY { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def VERSION = "1.0.1" // WARN: Version information not provided by tool on CLI. Please update this string when bumping + def VERSION = "0.2.1" // WARN: Version information not provided by tool on CLI. Please update this string when bumping + """ /opt/main.py -i $image -o . $args From 569c05795139bfea811b13899a11cb6403230156 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 24 Jul 2023 18:00:31 +0200 Subject: [PATCH 14/20] Change to main.nf to remove genomics stuff --- main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.nf b/main.nf index 30d2b65..f400498 100644 --- a/main.nf +++ b/main.nf @@ -17,7 +17,7 @@ nextflow.enable.dsl = 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -params.fasta = WorkflowMain.getGenomeAttribute(params, 'fasta') +//params.fasta = WorkflowMain.getGenomeAttribute(params, 'fasta') /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 9838ebbb7f0d6b5de1b0238c987339a7cc1401b0 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 24 Jul 2023 18:00:45 +0200 Subject: [PATCH 15/20] Changes tu mcmicro pipeline --- workflows/mcmicro.nf | 62 +++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/workflows/mcmicro.nf b/workflows/mcmicro.nf index 7f9f6fe..81c9d80 100644 --- a/workflows/mcmicro.nf +++ b/workflows/mcmicro.nf @@ -13,7 +13,7 @@ def summary_params = paramsSummaryMap(workflow) // Print parameter summary log to screen log.info logo + paramsSummaryLog(workflow) + citation -WorkflowMcmicro.initialise(params, log) +//WorkflowMcmicro.initialise(params, log) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -49,13 +49,13 @@ include { INPUT_CHECK } from '../subworkflows/local/input_check' //include { ILLUMINATION } from './modules/nf-core/local/illumination.nf' -include { BASICPY } from './modules/nf-core/basicpy/main' -include { ASHLAR } from './modules/nf-core/ashlar/main' -include { BACKSUB } from './modules/nf-core/backsub/main' -include { CELLPOSE } from './modules/nf-core/cellpose/main' -include { DEEPCELL_MESMER } from './modules/nf-core/deepcell/mesmer/main' -include { MCQUANT } from './modules/nf-core/mcquant/main' -include { SCIMAP_MCMICRO } from './modules/nf-core/scimap/mcmicro/main' +include { BASICPY } from '../modules/nf-core/basicpy/main' +include { ASHLAR } from '../modules/local/ashlar/main' +include { BACKSUB } from '../modules/nf-core/backsub/main' +include { CELLPOSE } from '../modules/nf-core/cellpose/main' +include { DEEPCELL_MESMER } from '../modules/nf-core/deepcell/mesmer/main' +include { MCQUANT } from '../modules/nf-core/mcquant/main' +include { SCIMAP_MCMICRO } from '../modules/nf-core/scimap/mcmicro/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' @@ -71,9 +71,6 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft ch_input = file(params.input) -// Identify marker information -ch_marker = Channel.fromPath( "${params.input}/markers.csv", checkIfExists: true ) - // Info required for completion email and summary def multiqc_report = [] @@ -95,45 +92,44 @@ workflow MCMICRO { //ILLUMINATION(mcp.modules['illumination'], raw) // sample check here: - ch_images = INPUT_CHECK( ch_input ).images - ch_markers = INPUT_CHECK( ch_input ).markers - - if ( params.illumination ): - BASICPY(ch_input) - ch_tif = BASICPY.outs.tif + ch_input = INPUT_CHECK.out.input + + // Split the original channel into two separate channels + ch_images = ch_input.map { item -> [item[0], item[1]]} + // Mapping and obtaining unique items based on item[2] + ch_markers = ch_input.map { item -> [item[0], item[2]] } + .groupTuple(by: [0]) + .map { sample, markers -> [ sample, markers.flatten().unique() ] } + + /* + if ( params.illumination ) { + BASICPY(ch_images) + ch_tif = BASICPY.out.fields ch_versions = ch_versions.mix(BASICPY.out.versions) ch_dfp = ch_tif.filter { file -> file.name.endsWith('.dfp.tiff') } ch_ffp = ch_tif.filter { file -> file.name.endsWith('.ffp.tiff') } - - ch_images = ASHLAR(ch_input, ch_dfp, ch_ffp).tif - ch_versions = ch_versions.mix(ASHLAR.out.versions) - - // Should background subtraction be applied? - /*img = img. - branch{ - nobs: !wfp.background - bs: wfp.background - } - chMrk = chMrk. - branch{ - nobs: !wfp.background - bs: wfp.background } */ + ASHLAR(ch_input, [], []) + ch_versions = ch_versions.mix(ASHLAR.out.versions) + // Run Background Correction - BACKSUB(image_tuple,marker_tuple) + BACKSUB(ASHLAR.out.tif, ch_markers) ch_versions = ch_versions.mix(BACKSUB.out.versions) + // Run Segmentation CELLPOSE(BACKSUB.out.backsub_tif) ch_versions = ch_versions.mix(CELLPOSE.out.versions) + // Run Quantification MCQUANT(BACKSUB.out.backsub_tif, CELLPOSE.out.mask, BACKSUB.out.markerout) ch_versions = ch_versions.mix(MCQUANT.out.versions) + // Run Reporting SCIMAP_MCMICRO(MCQUANT.out.csv) ch_versions = ch_versions.mix(SCIMAP_MCMICRO.out.versions) @@ -144,6 +140,7 @@ workflow MCMICRO { // // MODULE: MultiQC // + /* workflow_summary = WorkflowMcmicro.paramsSummaryMultiqc(workflow, summary_params) ch_workflow_summary = Channel.value(workflow_summary) @@ -162,6 +159,7 @@ workflow MCMICRO { ch_multiqc_logo.toList() ) multiqc_report = MULTIQC.out.report.toList() + */ } /* From 5bf51a997d68454ec86e3145289bafe9e32672f2 Mon Sep 17 00:00:00 2001 From: Florian Wuennemann Date: Wed, 9 Aug 2023 12:07:44 +0000 Subject: [PATCH 16/20] Updated README info. --- README.md | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 1499e96..04b0da3 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,11 @@ ## Introduction -**nf-core/mcmicro** is a bioinformatics pipeline that ... +!!! We are currently in the process of porting the original MCMICRO to nf-core. This pipeline is therefore in active development !!! + +**nf-core/mcmicro** is a nextflow pipeline for processing highly-multiplexed imaging data, as produced by technologies such as Cycif, MIBI, CODEX, SeqIF among others. + +If you want to run the original MCMICRO pipeline outside of nf-core, please see https://mcmicro.org/. -1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) -2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) - -## Usage + -Now, you can run the pipeline using: + -```bash + -> **Warning:** + -For more details and further functionality, please refer to the [usage documentation](https://nf-co.re/mcmicro/usage) and the [parameter documentation](https://nf-co.re/mcmicro/parameters). + -## Pipeline output + -## Credits + @@ -95,6 +96,8 @@ For further information or help, don't hesitate to get in touch on the [Slack `# +If you use nf-core/mcmicro for your analysis, please cite it using the following article: [Schapiro et al. 2022 Nat. Methods](https://www.nature.com/articles/s41592-021-01308-y) + An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. You can cite the `nf-core` publication as follows: From 3f54c8541d1fb920e3bcb1b34affe8c19ab48b5a Mon Sep 17 00:00:00 2001 From: Florian Wuennemann Date: Thu, 10 Aug 2023 21:42:33 +0200 Subject: [PATCH 17/20] Update README.md Co-authored-by: Phil Ewels --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 04b0da3..2275a65 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ ## Introduction -!!! We are currently in the process of porting the original MCMICRO to nf-core. This pipeline is therefore in active development !!! +> **Warning:** +> We are currently in the process of porting the original MCMICRO to nf-core. This pipeline is therefore in active development. **nf-core/mcmicro** is a nextflow pipeline for processing highly-multiplexed imaging data, as produced by technologies such as Cycif, MIBI, CODEX, SeqIF among others. From 216ca842d4a486ad078ceff2f52d9a51eac97654 Mon Sep 17 00:00:00 2001 From: Florian Wuennemann Date: Thu, 10 Aug 2023 21:42:50 +0200 Subject: [PATCH 18/20] Update README.md Co-authored-by: Phil Ewels --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2275a65..67759a5 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ **nf-core/mcmicro** is a nextflow pipeline for processing highly-multiplexed imaging data, as produced by technologies such as Cycif, MIBI, CODEX, SeqIF among others. -If you want to run the original MCMICRO pipeline outside of nf-core, please see https://mcmicro.org/. +If you want to run the original MCMICRO pipeline outside of nf-core, please see .