diff --git a/CHANGELOG.md b/CHANGELOG.md index 92ef4f0e..9cded24b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,26 @@ 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). +## [[1.2.0](https://github.com/nf-core/pixelator/releases/tag/1.1.0)] - 2024-05-?? + +### Enhancements & fixes + +- [[PR #90](https://github.com/nf-core/pixelator/pull/90)] - Update pixelator to 0.17.1 +- [[PR #90](https://github.com/nf-core/pixelator/pull/90)] - Add `pixelator single-cell layout` command +- [[PR #90](https://github.com/nf-core/pixelator/pull/90)] - The `graph` and `annotate` steps are now using `process_high` as their resource tags + +### Software dependencies + +| Dependency | Old version | New version | +| ----------- | ----------- | ----------- | +| `pixelator` | 0.16.2 | 0.17.1 | + +> **NB:** Dependency has been **updated** if both old and new version information is present. +> +> **NB:** Dependency has been **added** if just the new version information is present. +> +> **NB:** Dependency has been **removed** if new version information isn't present. + ## [[1.1.0](https://github.com/nf-core/pixelator/releases/tag/1.1.0)] - 2024-03-29 ### Enhancements & fixes diff --git a/conf/modules.config b/conf/modules.config index 7ab9ba43..6841052b 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -133,15 +133,25 @@ process { params.compute_polarization ? "--compute-polarization" : '', params.compute_colocalization ? "--compute-colocalization" : '', params.use_full_bipartite ? "--use-full-bipartite " : '', - params.polarization_normalization ? "--polarization-normalization ${params.polarization_normalization}" : '', - params.polarization_binarization ? "--polarization-binarization" : '', + params.polarization_min_marker_count ? "--polarization-min-marker-count ${params.polarization_min_marker_count}" : '', + params.polarization_transformation ? "--polarization-transformation ${params.polarization_transformation}" : '', params.colocalization_transformation ? "--colocalization-transformation ${params.colocalization_transformation}" : '', + params.polarization_n_permutations ? "--polarization-n-permutations ${params.polarization_n_permutations}" : '', (params.colocalization_neighbourhood_size instanceof Integer) ? "--colocalization-neighbourhood-size ${params.colocalization_neighbourhood_size}" : '', (params.colocalization_n_permutations instanceof Integer) ? "--colocalization-n-permutations ${params.colocalization_n_permutations}" : '', (params.colocalization_min_region_count instanceof Integer) ? "--colocalization-min-region-count ${params.colocalization_min_region_count}" : '', ].join(' ').trim() } + withName: PIXELATOR_LAYOUT { + ext.when = { !params.skip_layout } + ext.args = [ + params.no_node_marker_counts ? "--no-node-marker-counts" : '', + params.layout_algorithm ? "--layout-algorithm ${params.layout_algorithm} " : '', + ].join(' ').trim() + } + + withName: PIXELATOR_REPORT { ext.when = { !params.skip_report } } diff --git a/conf/test.config b/conf/test.config index e30c9238..3c1692b2 100644 --- a/conf/test.config +++ b/conf/test.config @@ -34,4 +34,10 @@ params { colocalization_min_region_count = 0 colocalization_n_permutations = 10 colocalization_neighbourhood_size = 1 + + // For now skip the layout step since it is very slow on these + // small test datasets + skip_layout = true + // using this since the default pmds_3d does not work on very small graphs + layout_algorithm = "fruchterman_reingold_3d" } diff --git a/docs/output.md b/docs/output.md index 5590fee4..36c88bc8 100644 --- a/docs/output.md +++ b/docs/output.md @@ -168,7 +168,7 @@ newly recovered components are stored in a file (components_recovered.csv). - `pixelator` - `annotate` - - `.dataset.pxl` + - `.annotated.dataset.pxl` - `.meta.json`: Command invocation metadata. - `.rank_vs_size.png` - `.raw_components_metrics.csv` @@ -193,7 +193,7 @@ edgelist to find putative cells, and it will generate a pxl file containing the - `analysis` - - `.dataset.pxl`: PXL file with the analysis results added to it. + - `.analysis.dataset.pxl`: PXL file with the analysis results added to it. - `.meta.json`: Command invocation metadata. - `.report.json`: Statistics for the analysis step. @@ -214,6 +214,30 @@ Currently, the following analysis are performed: Each analysis can be disabled by using respectively `--compute_polarization false` or `--compute_colocalization false`. This entire step can also be skipped using the `--skip_analysis` option. +### Compute layouts for visualization + +
+Output files + +- `pixelator` + + - `layout` + + - `.layout.dataset.pxl`: PXL file with the layout results added to it. + - `.meta.json`: Command invocation metadata. + - `.report.json`: Statistics for the layout step. + + - `logs` + - `.pixelator-layout.log`: pixelator log output. + +
+ +This step uses the `pixelator single-cell layout` command. +It will generate precomputed layouts that can be used to visualize cells +as part of the downstream analysis. + +This entire step can also be skipped using the `--skip_layout` option. + ### Generate reports
diff --git a/modules/local/pixelator/collect_metadata.nf b/modules/local/pixelator/collect_metadata.nf index 6f0f0ac1..1867abc0 100644 --- a/modules/local/pixelator/collect_metadata.nf +++ b/modules/local/pixelator/collect_metadata.nf @@ -6,10 +6,10 @@ process PIXELATOR_COLLECT_METADATA { label 'process_single' cache false - conda "bioconda::pixelator=0.16.2" + conda "bioconda::pixelator=0.17.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pixelator:0.16.2--pyhdfd78af_0' : - 'biocontainers/pixelator:0.16.2--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" input: diff --git a/modules/local/pixelator/list_options.nf b/modules/local/pixelator/list_options.nf index fe59c369..70854636 100644 --- a/modules/local/pixelator/list_options.nf +++ b/modules/local/pixelator/list_options.nf @@ -2,10 +2,10 @@ process PIXELATOR_LIST_OPTIONS { label 'process_single' - conda "bioconda::pixelator=0.16.2" + conda "bioconda::pixelator=0.17.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pixelator:0.16.2--pyhdfd78af_0' : - 'biocontainers/pixelator:0.16.2--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" output: path "design_options.txt" , emit: designs diff --git a/modules/local/pixelator/single-cell/amplicon/main.nf b/modules/local/pixelator/single-cell/amplicon/main.nf index bdd60d2a..0555312b 100644 --- a/modules/local/pixelator/single-cell/amplicon/main.nf +++ b/modules/local/pixelator/single-cell/amplicon/main.nf @@ -3,10 +3,10 @@ process PIXELATOR_AMPLICON { label 'process_low' - conda "bioconda::pixelator=0.16.2" + conda "bioconda::pixelator=0.17.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pixelator:0.16.2--pyhdfd78af_0' : - 'biocontainers/pixelator:0.16.2--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" input: tuple val(meta), path(reads) diff --git a/modules/local/pixelator/single-cell/analysis/main.nf b/modules/local/pixelator/single-cell/analysis/main.nf index 0ad705e0..4cab8af7 100644 --- a/modules/local/pixelator/single-cell/analysis/main.nf +++ b/modules/local/pixelator/single-cell/analysis/main.nf @@ -2,11 +2,10 @@ process PIXELATOR_ANALYSIS { tag "$meta.id" label 'process_medium' - - conda "bioconda::pixelator=0.16.2" + conda "bioconda::pixelator=0.17.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pixelator:0.16.2--pyhdfd78af_0' : - 'biocontainers/pixelator:0.16.2--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" input: tuple val(meta), path(data) diff --git a/modules/local/pixelator/single-cell/annotate/main.nf b/modules/local/pixelator/single-cell/annotate/main.nf index c7a44e82..0d3dac4e 100644 --- a/modules/local/pixelator/single-cell/annotate/main.nf +++ b/modules/local/pixelator/single-cell/annotate/main.nf @@ -1,12 +1,12 @@ process PIXELATOR_ANNOTATE { tag "$meta.id" - label 'process_medium' + label 'process_high' - conda "bioconda::pixelator=0.16.2" + conda "bioconda::pixelator=0.17.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pixelator:0.16.2--pyhdfd78af_0' : - 'biocontainers/pixelator:0.16.2--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" input: tuple val(meta), path(dataset), path(panel_file), val(panel) diff --git a/modules/local/pixelator/single-cell/collapse/main.nf b/modules/local/pixelator/single-cell/collapse/main.nf index 17918e76..22ad72a5 100644 --- a/modules/local/pixelator/single-cell/collapse/main.nf +++ b/modules/local/pixelator/single-cell/collapse/main.nf @@ -2,10 +2,10 @@ process PIXELATOR_COLLAPSE { tag "$meta.id" label 'process_medium' - conda "bioconda::pixelator=0.16.2" + conda "bioconda::pixelator=0.17.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pixelator:0.16.2--pyhdfd78af_0' : - 'biocontainers/pixelator:0.16.2--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" input: tuple val(meta), path(reads), path(panel_file), val(panel) diff --git a/modules/local/pixelator/single-cell/demux/main.nf b/modules/local/pixelator/single-cell/demux/main.nf index 6a02b0ac..41d6d99f 100644 --- a/modules/local/pixelator/single-cell/demux/main.nf +++ b/modules/local/pixelator/single-cell/demux/main.nf @@ -3,10 +3,10 @@ process PIXELATOR_DEMUX { label 'process_medium' - conda "bioconda::pixelator=0.16.2" + conda "bioconda::pixelator=0.17.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pixelator:0.16.2--pyhdfd78af_0' : - 'biocontainers/pixelator:0.16.2--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" input: tuple val(meta), path(reads), path(panel_file), val(panel) diff --git a/modules/local/pixelator/single-cell/graph/main.nf b/modules/local/pixelator/single-cell/graph/main.nf index 96e56324..35d9fb2a 100644 --- a/modules/local/pixelator/single-cell/graph/main.nf +++ b/modules/local/pixelator/single-cell/graph/main.nf @@ -1,12 +1,12 @@ process PIXELATOR_GRAPH { tag "$meta.id" - label 'process_medium' + label 'process_high' - conda "bioconda::pixelator=0.16.2" + conda "bioconda::pixelator=0.17.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pixelator:0.16.2--pyhdfd78af_0' : - 'biocontainers/pixelator:0.16.2--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" input: tuple val(meta), path(edge_list) diff --git a/modules/local/pixelator/single-cell/layout/main.nf b/modules/local/pixelator/single-cell/layout/main.nf new file mode 100644 index 00000000..9b534c1a --- /dev/null +++ b/modules/local/pixelator/single-cell/layout/main.nf @@ -0,0 +1,47 @@ +process PIXELATOR_LAYOUT { + tag "$meta.id" + label 'process_medium' + + + conda "bioconda::pixelator=0.17.1" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" + + input: + tuple val(meta), path(data) + + output: + tuple val(meta), path("layout/*dataset.pxl") , emit: dataset + tuple val(meta), path("layout/*report.json") , emit: report_json + tuple val(meta), path("layout/*.meta.json") , emit: metadata + tuple val(meta), path("layout/*") , emit: all_results + tuple val(meta), path("*pixelator-layout.log"), emit: log + + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + + prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + + """ + pixelator \\ + --cores $task.cpus \\ + --log-file ${prefix}.pixelator-layout.log \\ + --verbose \\ + single-cell \\ + layout \\ + --output . \\ + $args \\ + $data + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + pixelator: \$(echo \$(pixelator --version 2>/dev/null) | sed 's/pixelator, version //g' ) + END_VERSIONS + """ +} diff --git a/modules/local/pixelator/single-cell/qc/main.nf b/modules/local/pixelator/single-cell/qc/main.nf index 2650e5c4..fe9dbce3 100644 --- a/modules/local/pixelator/single-cell/qc/main.nf +++ b/modules/local/pixelator/single-cell/qc/main.nf @@ -3,10 +3,10 @@ process PIXELATOR_QC { label 'process_medium' - conda "bioconda::pixelator=0.16.2" + conda "bioconda::pixelator=0.17.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pixelator:0.16.2--pyhdfd78af_0' : - 'biocontainers/pixelator:0.16.2--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" input: tuple val(meta), path(reads) diff --git a/modules/local/pixelator/single-cell/report/main.nf b/modules/local/pixelator/single-cell/report/main.nf index c71b9749..6d891a62 100644 --- a/modules/local/pixelator/single-cell/report/main.nf +++ b/modules/local/pixelator/single-cell/report/main.nf @@ -3,10 +3,10 @@ process PIXELATOR_REPORT { label 'process_low' - conda "bioconda::pixelator=0.16.2" + conda "bioconda::pixelator=0.17.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pixelator:0.16.2--pyhdfd78af_0' : - 'biocontainers/pixelator:0.16.2--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/pixelator:0.17.1--pyhdfd78af_0' : + 'biocontainers/pixelator:0.17.1--pyhdfd78af_0' }" input: tuple val(meta), path(panel_file), val(panel) @@ -18,6 +18,7 @@ process PIXELATOR_REPORT { path graph_data , stageAs: "results/graph/*" path annotate_data , stageAs: "results/annotate/*" path analysis_data , stageAs: "results/analysis/*" + path layout_data , stageAs: "results/layout/*" output: diff --git a/nextflow.config b/nextflow.config index 6af56176..6ff12860 100644 --- a/nextflow.config +++ b/nextflow.config @@ -54,16 +54,22 @@ params { compute_polarization = true compute_colocalization = true use_full_bipartite = false - polarization_normalization = "clr" - polarization_binarization = false + polarization_transformation = "log1p" + polarization_min_marker_count = 5 + polarization_n_permutations = 50 colocalization_transformation = "log1p" colocalization_neighbourhood_size = 1 colocalization_n_permutations = 50 colocalization_min_region_count = 5 + // layout options + no_node_marker_counts = false + layout_algorithm = "pmds_3d" + // skip options skip_report = false skip_analysis = false + skip_layout = false // Main pixelator container override pixelator_container = null diff --git a/nextflow_schema.json b/nextflow_schema.json index 1659e2d6..2a87c891 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -256,21 +256,28 @@ "description": "Use the bipartite graph instead of the one-node projection when computing polarization, coabundance and colocalization scores", "type": "boolean" }, - "polarization_normalization": { - "description": "Which approach to use to normalize the antibody counts.", - "help_text": "- `raw`: use the raw counts.\n- `CLR`: use the CLR-transformed counts.\n- `denoise`: use CLR-transformed counts and subtract the counts of control antibodies", + "polarization_transformation": { + "description": "Which transformation to use for the antibody counts when calculating polarity scores.", + "help_text": "- `raw`: use the raw counts.\n- `log1p`: use the log1p-transformed counts.\n", "type": "string", - "enum": ["raw", "clr", "denoise"], - "default": "clr" + "enum": ["raw", "log1p"], + "default": "log1p" }, - "polarization_binarization": { - "fa_icon": "fas binary", - "description": "Transform the antibody counts to 0-1 (binarize) when computing polarization", - "type": "boolean" + "polarization_n_permutations": { + "type": "integer", + "description": "Set the number of permutations use to compute the empirical z- and p-values for the polarity score", + "default": 50, + "minimum": 5 + }, + "polarization_min_marker_count": { + "type": "integer", + "description": "The minimum number of counts of a marker to calculate the polarity score in the component", + "default": 5, + "minimum": 2 }, "colocalization_transformation": { "type": "string", - "enum": ["raw", "clr", "log1p", "relative"], + "enum": ["raw", "log1p", "rate-diff"], "default": "log1p", "description": "Select the type of transformation to use on the node by antibody counts matrix when computing colocalization" }, @@ -294,6 +301,27 @@ } } }, + "layout_options": { + "title": "Options for pixelator layout command.", + "type": "object", + "properties": { + "skip_layout": { + "description": "Skip layout step", + "type": "boolean" + }, + "no_node_marker_counts": { + "description": "Skip adding marker counts to the layout.", + "type": "boolean", + "default": false + }, + "layout_algorithm": { + "description": "Select a layout algorithm to use. This can be specified as a comma separated list to compute multiple layouts. Possible values are: fruchterman_reingold, fruchterman_reingold_3d, kamada_kawai, kamada_kawai_3d, pmds, pmds_3d", + "type": "string", + "pattern": "(\\S+)?(,\\S+)*", + "default": "pmds_3d" + } + } + }, "report_options": { "title": "Options for pixelator report command.", "type": "object", @@ -510,6 +538,9 @@ { "$ref": "#/definitions/analysis_options" }, + { + "$ref": "#/definitions/layout_options" + }, { "$ref": "#/definitions/report_options" }, diff --git a/subworkflows/local/generate_reports.nf b/subworkflows/local/generate_reports.nf index dc5fb42c..73c599b7 100644 --- a/subworkflows/local/generate_reports.nf +++ b/subworkflows/local/generate_reports.nf @@ -24,6 +24,7 @@ workflow GENERATE_REPORTS { graph_data // channel: [meta, [path, ...]] annotate_data // channel: [meta, [path, ...]] analysis_data // channel: [meta, [path, ...]] + layout_data // channel: [meta, [path, ...]] main: ch_versions = Channel.empty() @@ -57,6 +58,7 @@ workflow GENERATE_REPORTS { ch_graph_col = graph_data.map { meta, data -> [meta.id, data] } ch_annotate_col = annotate_data.map { meta, data -> [meta.id, data] } ch_analysis_col = analysis_data.map { meta, data -> [meta.id, data] } + ch_layout_col = layout_data.map { meta, data -> [meta.id, data] } // // Combine all inputs and group them, then split them up again. @@ -87,6 +89,7 @@ workflow GENERATE_REPORTS { .concat ( ch_graph_col ) .concat ( ch_annotate_col ) .concat ( ch_analysis_col ) + .concat ( ch_layout_col ) .groupTuple (size: 10) // @@ -108,6 +111,7 @@ workflow GENERATE_REPORTS { ch_graph_grouped = ch_report_data.map { id, data -> data[7] ? data[7].flatten() : [] } ch_annotate_grouped = ch_report_data.map { id, data -> data[8] ? data[8].flatten() : [] } ch_analysis_grouped = ch_report_data.map { id, data -> data[9] ? data[9].flatten() : [] } + ch_layout_grouped = ch_report_data.map { id, data -> data[10] ? data[10].flatten() : [] } // // MODULE: Run pixelator single-cell report for each samples @@ -124,6 +128,7 @@ workflow GENERATE_REPORTS { ch_graph_grouped, ch_annotate_grouped, ch_analysis_grouped, + ch_layout_grouped, ) ch_versions = ch_versions.mix(PIXELATOR_REPORT.out.versions.first()) diff --git a/workflows/pixelator.nf b/workflows/pixelator.nf index ec8735f3..018ef55e 100644 --- a/workflows/pixelator.nf +++ b/workflows/pixelator.nf @@ -60,6 +60,7 @@ include { PIXELATOR_COLLAPSE } from '../modules/local/pixelator/singl include { PIXELATOR_GRAPH } from '../modules/local/pixelator/single-cell/graph/main' include { PIXELATOR_ANALYSIS } from '../modules/local/pixelator/single-cell/analysis/main' include { PIXELATOR_ANNOTATE } from '../modules/local/pixelator/single-cell/annotate/main' +include { PIXELATOR_LAYOUT } from '../modules/local/pixelator/single-cell/layout/main' /* ======================================================================================== @@ -198,6 +199,13 @@ workflow PIXELATOR { ch_versions = ch_versions.mix(PIXELATOR_ANALYSIS.out.versions.first()) + // + // MODULE: Run pixelator single-cell layout + // + PIXELATOR_LAYOUT ( ch_analysed ) + ch_layout = PIXELATOR_LAYOUT.out.dataset + ch_versions = ch_versions.mix(PIXELATOR_LAYOUT.out.versions.first()) + // Prepare all data needed by reporting for each pixelator step ch_amplicon_data = PIXELATOR_AMPLICON.out.report_json @@ -223,6 +231,9 @@ workflow PIXELATOR { ch_cluster_data = PIXELATOR_GRAPH.out.all_results ch_annotate_data = PIXELATOR_ANNOTATE.out.all_results ch_analysis_data = PIXELATOR_ANALYSIS.out.all_results + ch_layout_data = PIXELATOR_LAYOUT.out.report_json + .concat(PIXELATOR_LAYOUT.out.metadata) + .groupTuple(size: 2) GENERATE_REPORTS( ch_cat_panel_files, @@ -233,7 +244,8 @@ workflow PIXELATOR { ch_collapse_data, ch_cluster_data, ch_annotate_data, - ch_analysis_data + ch_analysis_data, + ch_layout_data ) ch_versions = ch_versions.mix(GENERATE_REPORTS.out.versions)