From 0924995d2290561620d2c70a31fd2a2de60d3253 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 28 Nov 2022 20:53:13 +1100 Subject: [PATCH 001/562] Transfer umccr/hmftools-nf to nf-core template Pipeline code moved from github.com/umccr/hmftools-nf to new nf-core template. See previous repository for full commit history. --- README.md | 182 ++-- conf/base.config | 187 +++- conf/igenomes.config | 846 ++++++++-------- conf/modules.config | 243 ++++- conf/test.config | 49 +- examples/README.md | 109 ++ lib/Constants.groovy | 28 + lib/NfcoreSchema.groovy | 930 +++++++++--------- lib/NfcoreTemplate.groovy | 521 +++++----- lib/Processes.groovy | 100 ++ lib/Utils.groovy | 61 +- lib/WorkflowGridss.groovy | 104 ++ lib/WorkflowHmftools.groovy | 165 ++++ lib/WorkflowLilac.groovy | 80 ++ lib/WorkflowMain.groovy | 154 +-- main.nf | 35 +- modules.json | 26 +- modules/local/amber/Dockerfile | 19 + modules/local/amber/main.nf | 46 + modules/local/amber/meta.yml | 58 ++ modules/local/check_samplesheet/main.nf | 33 + modules/local/cobalt/Dockerfile | 19 + modules/local/cobalt/main.nf | 44 + modules/local/cobalt/meta.yml | 58 ++ modules/local/cuppa/Dockerfile | 36 + modules/local/cuppa/classifier/main.nf | 46 + modules/local/cuppa/visualiser/main.nf | 38 + .../lilac_extract_and_index_contig/Dockerfile | 19 + .../lilac_extract_and_index_contig/main.nf | 40 + .../lilac_extract_and_index_contig/meta.yml | 40 + .../lilac_realign_reads_lilac/Dockerfile | 20 + .../custom/lilac_realign_reads_lilac/main.nf | 50 + .../custom/lilac_realign_reads_lilac/meta.yml | 57 ++ modules/local/custom/lilac_slice/main.nf | 40 + modules/local/custom/lilac_slice/meta.yml | 49 + modules/local/gpgr/linx_report/main.nf | 38 + modules/local/gpgr/linx_report/meta.yml | 46 + modules/local/gridss/Dockerfile | 28 + modules/local/gridss/assemble/main.nf | 88 ++ modules/local/gridss/assemble/meta.yml | 78 ++ modules/local/gridss/call/main.nf | 93 ++ modules/local/gridss/call/meta.yml | 79 ++ modules/local/gridss/preprocess/main.nf | 52 + modules/local/gridss/preprocess/meta.yml | 64 ++ modules/local/gripss/Dockerfile | 22 + modules/local/gripss/germline/main.nf | 62 ++ modules/local/gripss/germline/meta.yml | 74 ++ modules/local/gripss/somatic/main.nf | 63 ++ modules/local/gripss/somatic/meta.yml | 74 ++ modules/local/isofox/Dockerfile | 22 + modules/local/isofox/main.nf | 54 + modules/local/lilac/Dockerfile | 22 + modules/local/lilac/main.nf | 64 ++ modules/local/lilac/meta.yml | 65 ++ modules/local/linx/Dockerfile | 30 + modules/local/linx/germline/main.nf | 50 + modules/local/linx/germline/meta.yml | 61 ++ modules/local/linx/somatic/main.nf | 53 + modules/local/linx/somatic/meta.yml | 64 ++ modules/local/linx/visualiser/main.nf | 51 + modules/local/linx/visualiser/meta.yml | 49 + modules/local/pave/Dockerfile | 22 + modules/local/pave/germline/main.nf | 60 ++ modules/local/pave/germline/meta.yml | 85 ++ modules/local/pave/somatic/main.nf | 57 ++ modules/local/pave/somatic/meta.yml | 77 ++ modules/local/purple/Dockerfile | 32 + modules/local/purple/main.nf | 94 ++ modules/local/purple/meta.yml | 109 ++ modules/local/sage/Dockerfile | 31 + modules/local/sage/germline/main.nf | 63 ++ modules/local/sage/germline/meta.yml | 89 ++ modules/local/sage/somatic/main.nf | 55 ++ modules/local/sage/somatic/meta.yml | 89 ++ modules/local/svprep/Dockerfile | 15 + modules/local/svprep/assemble/main.nf | 89 ++ modules/local/svprep/assets/gridss.svprep | 825 ++++++++++++++++ modules/local/svprep/call/main.nf | 94 ++ modules/local/svprep/depth_annotator/main.nf | 47 + modules/local/svprep/preprocess/main.nf | 54 + modules/local/svprep/svprep/main.nf | 58 ++ modules/local/svprep/svprep/meta.yml | 78 ++ modules/local/teal/Dockerfile | 22 + modules/local/teal/main.nf | 52 + modules/local/teal/meta.yml | 65 ++ modules/local/virusbreakend/main.nf | 50 + modules/local/virusinterpreter/Dockerfile | 22 + modules/local/virusinterpreter/main.nf | 45 + modules/nf-core/bwa/index/main.nf | 51 + modules/nf-core/bwa/index/meta.yml | 42 + .../custom/dumpsoftwareversions/main.nf | 24 + .../custom/dumpsoftwareversions/meta.yml | 34 + .../templates/dumpsoftwareversions.py | 89 ++ .../modules/picard/collectwgsmetrics/main.nf | 56 ++ .../modules/picard/collectwgsmetrics/meta.yml | 47 + modules/nf-core/samtools/dict/main.nf | 44 + modules/nf-core/samtools/dict/meta.yml | 41 + modules/nf-core/samtools/faidx/main.nf | 44 + modules/nf-core/samtools/faidx/meta.yml | 47 + modules/nf-core/star/genomegenerate/main.nf | 96 ++ modules/nf-core/star/genomegenerate/meta.yml | 37 + nextflow.config | 363 +++---- nextflow_schema.json | 772 +++++++++------ subworkflows/local/gridss.nf | 129 +++ subworkflows/local/gridss_svprep.nf | 216 ++++ subworkflows/local/gripss.nf | 66 ++ subworkflows/local/lilac.nf | 87 ++ subworkflows/local/linx.nf | 65 ++ subworkflows/local/pave.nf | 60 ++ subworkflows/local/sage.nf | 61 ++ workflows/hmftools.nf | 735 ++++++++++++++ 111 files changed, 9597 insertions(+), 1966 deletions(-) create mode 100644 examples/README.md create mode 100644 lib/Constants.groovy create mode 100644 lib/Processes.groovy mode change 100644 => 100755 lib/Utils.groovy create mode 100755 lib/WorkflowGridss.groovy create mode 100755 lib/WorkflowHmftools.groovy create mode 100755 lib/WorkflowLilac.groovy mode change 100644 => 100755 main.nf create mode 100644 modules/local/amber/Dockerfile create mode 100644 modules/local/amber/main.nf create mode 100644 modules/local/amber/meta.yml create mode 100644 modules/local/check_samplesheet/main.nf create mode 100644 modules/local/cobalt/Dockerfile create mode 100644 modules/local/cobalt/main.nf create mode 100644 modules/local/cobalt/meta.yml create mode 100644 modules/local/cuppa/Dockerfile create mode 100644 modules/local/cuppa/classifier/main.nf create mode 100644 modules/local/cuppa/visualiser/main.nf create mode 100644 modules/local/custom/lilac_extract_and_index_contig/Dockerfile create mode 100644 modules/local/custom/lilac_extract_and_index_contig/main.nf create mode 100644 modules/local/custom/lilac_extract_and_index_contig/meta.yml create mode 100644 modules/local/custom/lilac_realign_reads_lilac/Dockerfile create mode 100644 modules/local/custom/lilac_realign_reads_lilac/main.nf create mode 100644 modules/local/custom/lilac_realign_reads_lilac/meta.yml create mode 100644 modules/local/custom/lilac_slice/main.nf create mode 100644 modules/local/custom/lilac_slice/meta.yml create mode 100644 modules/local/gpgr/linx_report/main.nf create mode 100644 modules/local/gpgr/linx_report/meta.yml create mode 100644 modules/local/gridss/Dockerfile create mode 100644 modules/local/gridss/assemble/main.nf create mode 100644 modules/local/gridss/assemble/meta.yml create mode 100644 modules/local/gridss/call/main.nf create mode 100644 modules/local/gridss/call/meta.yml create mode 100644 modules/local/gridss/preprocess/main.nf create mode 100644 modules/local/gridss/preprocess/meta.yml create mode 100644 modules/local/gripss/Dockerfile create mode 100644 modules/local/gripss/germline/main.nf create mode 100644 modules/local/gripss/germline/meta.yml create mode 100644 modules/local/gripss/somatic/main.nf create mode 100644 modules/local/gripss/somatic/meta.yml create mode 100644 modules/local/isofox/Dockerfile create mode 100644 modules/local/isofox/main.nf create mode 100644 modules/local/lilac/Dockerfile create mode 100644 modules/local/lilac/main.nf create mode 100644 modules/local/lilac/meta.yml create mode 100644 modules/local/linx/Dockerfile create mode 100644 modules/local/linx/germline/main.nf create mode 100644 modules/local/linx/germline/meta.yml create mode 100644 modules/local/linx/somatic/main.nf create mode 100644 modules/local/linx/somatic/meta.yml create mode 100644 modules/local/linx/visualiser/main.nf create mode 100644 modules/local/linx/visualiser/meta.yml create mode 100644 modules/local/pave/Dockerfile create mode 100644 modules/local/pave/germline/main.nf create mode 100644 modules/local/pave/germline/meta.yml create mode 100644 modules/local/pave/somatic/main.nf create mode 100644 modules/local/pave/somatic/meta.yml create mode 100644 modules/local/purple/Dockerfile create mode 100644 modules/local/purple/main.nf create mode 100644 modules/local/purple/meta.yml create mode 100644 modules/local/sage/Dockerfile create mode 100644 modules/local/sage/germline/main.nf create mode 100644 modules/local/sage/germline/meta.yml create mode 100644 modules/local/sage/somatic/main.nf create mode 100644 modules/local/sage/somatic/meta.yml create mode 100644 modules/local/svprep/Dockerfile create mode 100644 modules/local/svprep/assemble/main.nf create mode 100644 modules/local/svprep/assets/gridss.svprep create mode 100644 modules/local/svprep/call/main.nf create mode 100644 modules/local/svprep/depth_annotator/main.nf create mode 100644 modules/local/svprep/preprocess/main.nf create mode 100644 modules/local/svprep/svprep/main.nf create mode 100644 modules/local/svprep/svprep/meta.yml create mode 100644 modules/local/teal/Dockerfile create mode 100644 modules/local/teal/main.nf create mode 100644 modules/local/teal/meta.yml create mode 100644 modules/local/virusbreakend/main.nf create mode 100644 modules/local/virusinterpreter/Dockerfile create mode 100644 modules/local/virusinterpreter/main.nf create mode 100644 modules/nf-core/bwa/index/main.nf create mode 100644 modules/nf-core/bwa/index/meta.yml create mode 100644 modules/nf-core/modules/custom/dumpsoftwareversions/main.nf create mode 100644 modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml create mode 100644 modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py create mode 100644 modules/nf-core/modules/picard/collectwgsmetrics/main.nf create mode 100644 modules/nf-core/modules/picard/collectwgsmetrics/meta.yml create mode 100644 modules/nf-core/samtools/dict/main.nf create mode 100644 modules/nf-core/samtools/dict/meta.yml create mode 100644 modules/nf-core/samtools/faidx/main.nf create mode 100644 modules/nf-core/samtools/faidx/meta.yml create mode 100644 modules/nf-core/star/genomegenerate/main.nf create mode 100644 modules/nf-core/star/genomegenerate/meta.yml create mode 100644 subworkflows/local/gridss.nf create mode 100644 subworkflows/local/gridss_svprep.nf create mode 100644 subworkflows/local/gripss.nf create mode 100644 subworkflows/local/lilac.nf create mode 100644 subworkflows/local/linx.nf create mode 100644 subworkflows/local/pave.nf create mode 100644 subworkflows/local/sage.nf create mode 100644 workflows/hmftools.nf diff --git a/README.md b/README.md index 95bace73..4ba9007c 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,90 @@ -# ![nf-core/oncoanalyser](docs/images/nf-core-oncoanalyser_logo_light.png#gh-light-mode-only) ![nf-core/oncoanalyser](docs/images/nf-core-oncoanalyser_logo_dark.png#gh-dark-mode-only) - -[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/oncoanalyser/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) - -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg)](https://www.nextflow.io/) -[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) -[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) -[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) -[![Launch on Nextflow Tower](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/oncoanalyser) - -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23oncoanalyser-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/oncoanalyser)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) - -## Introduction - - - -**nf-core/oncoanalyser** is a comprehensive cancer WGS/WTS analysis and reporting pipeline. - -The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. Where possible, these processes have been submitted to and installed from [nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to everyone within the Nextflow community! - - - -On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources.The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/oncoanalyser/results). - -## Pipeline summary - - - -1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) -2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) - -## Quick Start - -1. Install [`Nextflow`](https://www.nextflow.io/docs/latest/getstarted.html#installation) (`>=21.10.3`) - -2. Install any of [`Docker`](https://docs.docker.com/engine/installation/), [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/) (you can follow [this tutorial](https://singularity-tutorial.github.io/01-installation/)), [`Podman`](https://podman.io/), [`Shifter`](https://nersc.gitlab.io/development/shifter/how-to-use/) or [`Charliecloud`](https://hpc.github.io/charliecloud/) for full pipeline reproducibility _(you can use [`Conda`](https://conda.io/miniconda.html) both to install Nextflow itself and also to manage software within pipelines. Please only use it within pipelines as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles))_. - -3. Download the pipeline and test it on a minimal dataset with a single command: - - ```bash - nextflow run nf-core/oncoanalyser -profile test,YOURPROFILE --outdir - ``` - - Note that some form of configuration will be needed so that Nextflow knows how to fetch the required software. This is usually done in the form of a config profile (`YOURPROFILE` in the example command above). You can chain multiple config profiles in a comma-separated string. - - > - The pipeline comes with config profiles called `docker`, `singularity`, `podman`, `shifter`, `charliecloud` and `conda` which instruct the pipeline to use the named tool for software management. For example, `-profile test,docker`. - > - Please check [nf-core/configs](https://github.com/nf-core/configs#documentation) to see if a custom config file to run nf-core pipelines already exists for your Institute. If so, you can simply use `-profile ` in your command. This will enable either `docker` or `singularity` and set the appropriate execution settings for your local compute environment. - > - If you are using `singularity`, please use the [`nf-core download`](https://nf-co.re/tools/#downloading-pipelines-for-offline-use) command to download images first, before running the pipeline. Setting the [`NXF_SINGULARITY_CACHEDIR` or `singularity.cacheDir`](https://www.nextflow.io/docs/latest/singularity.html?#singularity-docker-hub) Nextflow options enables you to store and re-use the images from a central location for future pipeline runs. - > - If you are using `conda`, it is highly recommended to use the [`NXF_CONDA_CACHEDIR` or `conda.cacheDir`](https://www.nextflow.io/docs/latest/conda.html) settings to store the environments in a central location for future pipeline runs. - -4. Start running your own analysis! - - - - ```bash - nextflow run nf-core/oncoanalyser --input samplesheet.csv --outdir --genome GRCh37 -profile - ``` - -## Documentation - -The nf-core/oncoanalyser pipeline comes with documentation about the pipeline [usage](https://nf-co.re/oncoanalyser/usage), [parameters](https://nf-co.re/oncoanalyser/parameters) and [output](https://nf-co.re/oncoanalyser/output). - -## Credits - -nf-core/oncoanalyser was originally written by Stephen Watts. - -We thank the following people for their extensive assistance in the development of this pipeline: - - - -## Contributions and Support - -If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). - -For further information or help, don't hesitate to get in touch on the [Slack `#oncoanalyser` channel](https://nfcore.slack.com/channels/oncoanalyser) (you can join with [this invite](https://nf-co.re/join/slack)). - -## Citations - - - - - - -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: - -> **The nf-core framework for community-curated bioinformatics pipelines.** -> -> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen. -> -> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). +  +  +  +

+🚧🚨 Under development 🚨🚧 +

+ +# HMF tools + +A comprehensive cancer WGS/WTS analysis and reporting pipeline from the Hartwig Medical Foundation. + +## Table of contents + +* [Quick start](#quick-start) +* [Pipeline modes](#pipeline-modes) +* [Pipeline tests](#pipeline-tests) +* [License](#license) + +## Quick start + +1. Install dependencies. +> Assumes `Conda` is installed. +```bash +conda create -y \ + -n hmftools \ + -c bioconda \ + -c conda-forge \ + -c defaults \ + 'bcftools >=1.15' \ + 'dvc >=2.12.0' \ + 'git >=2.37.0' \ + 'nextflow >=22.04.0' +conda activate hmftools +``` + +2. Install [`Docker`](https://docs.docker.com/engine/installation/). + +3. Download the pipeline and reference data. +```bash +# Download pipeline and reference data +git clone https://github.com/umccr/hmftools && cd ./hmftools/hmftools/ + +git clone https://github.com/umccr/reference_data -b dev reference_data_gitrepo/ && cd reference_data_gitrepo/ +dvc pull reference_data/{genomes,hmftools}/ -r storage-s3 && cd ../ +ln -s reference_data_gitrepo/reference_data/ reference_data +``` + +4. Run the pipeline with your data. +```bash +nextflow run ./main.nf -profile docker --input --outdir +``` + +## Pipeline modes + +Several modes of execution are offered and can be accessed using the `--mode` argument. + +| Name | Description | +| --- | --- | +| `full` | Run all processes in the pipeline | +| `gridss-purple-linx` | Run AMBER, COBALT, GRIDSS, GRIPSS, and PURPLE | +| `gridss` | Run only GRIDSS and GRIPSS | +| `purple` | Run only PURPLE | +| `linx` | Run only LINX | +| `lilac` | Run only LILAC | +| `teal` | Run only TEAL | + +See [examples/README.md](examples/README.md) for example samplesheet required for each mode. + +## Pipeline tests + +The internal pipeline logic can be tested using a stub run. No actual outputs are generated in a stub run and +only the `stub` definition block of a process is executed. Hence, it completes in a short amount of time but does not +test validity of actual processes beyond declared inputs and outputs. + +```bash +nextflow run main.nf --input ./assets/samplesheet.tsv --outdir output_stub/ --max_memory '1.GB' -stub +``` + +A more comprehensive test that involves both the process `script` definition block and internal pipeline logic can be +run with the supplied downsampled test dataset. This of course takes longer (on the order of minutes) but replicates a +full run and generates 'real' process outputs. + +```bash +nextflow run ./main.nf -profile docker,test --outdir output_test/ --max_memory '6.GB' +``` + +## License + +Software and code in this repository are under [GNU General Public License +v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html) unless otherwise indicated. diff --git a/conf/base.config b/conf/base.config index 05eac721..ea217ee4 100644 --- a/conf/base.config +++ b/conf/base.config @@ -1,65 +1,144 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - nf-core/oncoanalyser Nextflow base config file + umccr/hmftools Nextflow base config file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - A 'blank slate' config file, appropriate for general use on most high performance - compute environments. Assumes that all software is installed and available on - the PATH. Runs in `local` mode - all jobs will be run on the logged in environment. + A 'blank slate' config file, appropriate for general use on most high performance + compute environments. Assumes that all software is installed and available on + the PATH. Runs in `local` mode - all jobs will be run on the logged in environment. ---------------------------------------------------------------------------------------- */ process { - // TODO nf-core: Check the defaults for all processes - cpus = { check_max( 1 * task.attempt, 'cpus' ) } - memory = { check_max( 6.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } + cpus = { check_max( 8 * task.attempt, 'cpus' ) } + memory = { check_max( 6.GB * task.attempt, 'memory' ) } + time = { check_max( 24.h * task.attempt, 'time' ) } - errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } - maxRetries = 1 - maxErrors = '-1' + errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } + maxRetries = 1 + maxErrors = '-1' - // Process-specific resource requirements - // NOTE - Please try and re-use the labels below as much as possible. - // These labels are used and recognised by default in DSL2 files hosted on nf-core/modules. - // If possible, it would be nice to keep the same label naming convention when - // adding in your local modules too. - // TODO nf-core: Customise requirements for specific processes. - // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors - withLabel:process_single { - cpus = { check_max( 1 , 'cpus' ) } - memory = { check_max( 6.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } - } - withLabel:process_low { - cpus = { check_max( 2 * task.attempt, 'cpus' ) } - memory = { check_max( 12.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } - } - withLabel:process_medium { - cpus = { check_max( 6 * task.attempt, 'cpus' ) } - memory = { check_max( 36.GB * task.attempt, 'memory' ) } - time = { check_max( 8.h * task.attempt, 'time' ) } - } - withLabel:process_high { - cpus = { check_max( 12 * task.attempt, 'cpus' ) } - memory = { check_max( 72.GB * task.attempt, 'memory' ) } - time = { check_max( 16.h * task.attempt, 'time' ) } - } - withLabel:process_long { - time = { check_max( 20.h * task.attempt, 'time' ) } - } - withLabel:process_high_memory { - memory = { check_max( 200.GB * task.attempt, 'memory' ) } - } - withLabel:error_ignore { - errorStrategy = 'ignore' - } - withLabel:error_retry { - errorStrategy = 'retry' - maxRetries = 2 - } - withName:CUSTOM_DUMPSOFTWAREVERSIONS { - cache = false - } + // Process-specific resource requirements + // NOTE - Please try and re-use the labels below as much as possible. + // These labels are used and recognised by default in DSL2 files hosted on nf-core/modules. + // If possible, it would be nice to keep the same label naming convention when + // adding in your local modules too. + // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors + withLabel:process_low { + cpus = { check_max( 2 * task.attempt, 'cpus' ) } + memory = { check_max( 12.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } + } + withLabel:process_medium { + cpus = { check_max( 6 * task.attempt, 'cpus' ) } + memory = { check_max( 36.GB * task.attempt, 'memory' ) } + time = { check_max( 8.h * task.attempt, 'time' ) } + } + withLabel:process_high { + cpus = { check_max( 12 * task.attempt, 'cpus' ) } + memory = { check_max( 72.GB * task.attempt, 'memory' ) } + time = { check_max( 16.h * task.attempt, 'time' ) } + } + withLabel:process_long { + time = { check_max( 20.h * task.attempt, 'time' ) } + } + withLabel:process_high_memory { + memory = { check_max( 200.GB * task.attempt, 'memory' ) } + } + withLabel:error_ignore { + errorStrategy = 'ignore' + } + withLabel:error_retry { + errorStrategy = 'retry' + maxRetries = 2 + } + withName:'CHECK_SAMPLESHEET' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 1.GB, 'memory' ) } + } + withName:'AMBER' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'COBALT' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:CUSTOM_DUMPSOFTWAREVERSIONS { + cache = false + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 1.GB, 'memory' ) } + } + withName:'SVPREP.*' { + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'.*:GRIDSS:.*' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 30.GB, 'memory' ) } + } + withName:'.*GRIPSS.*' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName: 'LILAC_PROCESS' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName: '.*LILAC:REALIGN_READS' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName: '.*LILAC:SLICE' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 6.GB, 'memory' ) } + } + withName: '.*LILAC:EXTRACT_AND_INDEX_CONTIG' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 6.GB, 'memory' ) } + } + withName:'.*LINX:.*' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'LINX_REPORT' { + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'.*PAVE.*' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'PURPLE' { + cpus = { check_max( 2, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'.*SAGE.*' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'SLICE' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'TEAL' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'COLLECTWGSMETRICS' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + time = { check_max( 24.h , 'time' ) } + } + withName:'VIRUSBREAKEND' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 64.GB, 'memory' ) } + } + withName:'VIRUSINTERPRETER' { + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'ISOFOX' { + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'CUPPA.*' { + memory = { check_max( 12.GB, 'memory' ) } + } } diff --git a/conf/igenomes.config b/conf/igenomes.config index 7a1b3ac6..17e698eb 100644 --- a/conf/igenomes.config +++ b/conf/igenomes.config @@ -1,432 +1,432 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for iGenomes paths + Nextflow config file for iGenomes paths ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defines reference genomes using iGenome paths. - Can be used by any config that customises the base path using: - $params.igenomes_base / --igenomes_base + Defines reference genomes using iGenome paths. + Can be used by any config that customises the base path using: + $params.igenomes_base / --igenomes_base ---------------------------------------------------------------------------------------- */ params { - // illumina iGenomes reference file paths - genomes { - 'GRCh37' { - fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/GRCh37-blacklist.bed" - } - 'GRCh38' { - fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'GRCm38' { - fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/GRCm38-blacklist.bed" - } - 'TAIR10' { - fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" - mito_name = "Mt" - } - 'EB2' { - fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" - } - 'UMD3.1' { - fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" - mito_name = "MT" - } - 'WBcel235' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" - mito_name = "MtDNA" - macs_gsize = "9e7" - } - 'CanFam3.1' { - fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" - mito_name = "MT" - } - 'GRCz10' { - fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'BDGP6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" - mito_name = "M" - macs_gsize = "1.2e8" - } - 'EquCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" - mito_name = "MT" - } - 'EB1' { - fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" - } - 'Galgal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Gm01' { - fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" - } - 'Mmul_1' { - fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" - mito_name = "MT" - } - 'IRGSP-1.0' { - fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'CHIMP2.1.4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" - mito_name = "MT" - } - 'Rnor_5.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Rnor_6.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'R64-1-1' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" - mito_name = "MT" - macs_gsize = "1.2e7" - } - 'EF2' { - fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.21e7" - } - 'Sbi1' { - fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" - } - 'Sscrofa10.2' { - fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" - mito_name = "MT" - } - 'AGPv3' { - fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'hg38' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'hg19' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg19-blacklist.bed" - } - 'mm10' { - fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/mm10-blacklist.bed" - } - 'bosTau8' { - fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'ce10' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "9e7" - } - 'canFam3' { - fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" - mito_name = "chrM" - } - 'danRer10' { - fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.37e9" - } - 'dm6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.2e8" - } - 'equCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" - mito_name = "chrM" - } - 'galGal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" - mito_name = "chrM" - } - 'panTro4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" - mito_name = "chrM" - } - 'rn6' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'sacCer3' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" - readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.2e7" - } - 'susScr3' { - fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" - mito_name = "chrM" - } + // illumina iGenomes reference file paths + genomes { + 'GRCh37' { + fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/GRCh37-blacklist.bed" } + 'GRCh38' { + fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" + } + 'GRCm38' { + fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "1.87e9" + blacklist = "${projectDir}/assets/blacklists/GRCm38-blacklist.bed" + } + 'TAIR10' { + fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" + mito_name = "Mt" + } + 'EB2' { + fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" + } + 'UMD3.1' { + fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" + mito_name = "MT" + } + 'WBcel235' { + fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" + mito_name = "MtDNA" + macs_gsize = "9e7" + } + 'CanFam3.1' { + fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" + mito_name = "MT" + } + 'GRCz10' { + fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'BDGP6' { + fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" + mito_name = "M" + macs_gsize = "1.2e8" + } + 'EquCab2' { + fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" + mito_name = "MT" + } + 'EB1' { + fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" + } + 'Galgal4' { + fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'Gm01' { + fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" + } + 'Mmul_1' { + fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" + mito_name = "MT" + } + 'IRGSP-1.0' { + fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" + mito_name = "Mt" + } + 'CHIMP2.1.4' { + fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" + mito_name = "MT" + } + 'Rnor_5.0' { + fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'Rnor_6.0' { + fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'R64-1-1' { + fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" + mito_name = "MT" + macs_gsize = "1.2e7" + } + 'EF2' { + fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "1.21e7" + } + 'Sbi1' { + fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" + } + 'Sscrofa10.2' { + fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" + mito_name = "MT" + } + 'AGPv3' { + fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" + mito_name = "Mt" + } + 'hg38' { + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" + } + 'hg19' { + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/hg19-blacklist.bed" + } + 'mm10' { + fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "1.87e9" + blacklist = "${projectDir}/assets/blacklists/mm10-blacklist.bed" + } + 'bosTau8' { + fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" + mito_name = "chrM" + } + 'ce10' { + fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "9e7" + } + 'canFam3' { + fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" + mito_name = "chrM" + } + 'danRer10' { + fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "1.37e9" + } + 'dm6' { + fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "1.2e8" + } + 'equCab2' { + fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" + mito_name = "chrM" + } + 'galGal4' { + fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" + mito_name = "chrM" + } + 'panTro4' { + fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" + mito_name = "chrM" + } + 'rn6' { + fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" + mito_name = "chrM" + } + 'sacCer3' { + fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" + readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "1.2e7" + } + 'susScr3' { + fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" + mito_name = "chrM" + } + } } diff --git a/conf/modules.config b/conf/modules.config index da58a5d8..916efec0 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -1,41 +1,230 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Config file for defining DSL2 per module options and publishing paths + Config file for defining DSL2 per module options and publishing paths ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Available keys to override module options: - ext.args = Additional arguments appended to command in module. - ext.args2 = Second set of arguments appended to command in module (multi-tool modules). - ext.args3 = Third set of arguments appended to command in module (multi-tool modules). - ext.prefix = File name prefix for output files. + Available keys to override module options: + ext.args = Additional arguments appended to command in module. + ext.args2 = Second set of arguments appended to command in module (multi-tool modules). + ext.args3 = Third set of arguments appended to command in module (multi-tool modules). + ext.prefix = File name prefix for output files. ---------------------------------------------------------------------------------------- */ - process { + withName: 'AMBER' { + ext.jarPath = '/opt/conda/share/hmftools-amber-3.9-1/amber.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'COBALT' { + ext.jarPath = '/opt/conda/share/hmftools-cobalt-1.13-1/cobalt.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'CUSTOM_DUMPSOFTWAREVERSIONS' { + publishDir = [ + path: { "${params.outdir}/pipeline_info" }, + mode: params.publish_dir_mode, + pattern: '*_versions.yml', + ] + } + + withName:'.*:(? + if(filename.equals('versions.yml')) { + return null + } else { + def tokens = filename.split('[/]') + return "${meta.id}/gridss/${tokens[-1]}" + } + } + ] + } + + withName: 'SVPREP_DEPTH_ANNOTATOR' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gridss/sv.vcf.gz" } + ] + } + + withName: 'GRIPSS.*' { + ext.jarPath = '/opt/gripss/gripss.jar' + } + + withName: '.*GRIPSS_GERMLINE' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gripss/germline/${filename}" }, + ] + } + + withName: '.*GRIPSS_SOMATIC' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gripss/somatic/${filename}" }, + ] + } + withName: 'LILAC_PROCESS' { + ext.jarPath = '/opt/lilac/lilac.jar' publishDir = [ - path: { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" } ] + } - withName: SAMPLESHEET_CHECK { - publishDir = [ - path: { "${params.outdir}/pipeline_info" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } - ] - } + withName: '.*LINX:.*' { + ext.jarPath = '/opt/linx/linx.jar' + } - withName: FASTQC { - ext.args = '--quiet' - } + withName: '.*LINX_GERMLINE' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/germline/" }, + ] + } + + withName: '.*LINX_SOMATIC' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic/" }, + ] + } - withName: CUSTOM_DUMPSOFTWAREVERSIONS { - publishDir = [ - path: { "${params.outdir}/pipeline_info" }, - mode: params.publish_dir_mode, - pattern: '*_versions.yml' - ] - } + withName: '.*LINX:VISUALISER' { + ext.path_circos = 'circos' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic/plots/" }, + ] + } + withName: 'LINX_REPORT' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'PAVE.*' { + ext.jarPath = '/opt/pave/pave.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/pave/${filename}" }, + ] + } + + withName: 'COLLECTWGSMETRICS' { + tag = { "${task.index}" } + label = null + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/wgs_metrics/${filename}" }, + ] + } + + withName: 'PURPLE' { + ext.jarPath = '/opt/purple/purple.jar' + ext.circosPath = 'circos' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'SAGE.*' { + ext.jarPath = '/opt/sage/sage.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/${filename}" }, + ] + } + + withName: 'TEAL' { + ext.jarPath = '/opt/teal/teal.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'VIRUSBREAKEND' { + ext.jarPath = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/virusbreakend/${filename}" }, + ] + } + + withName: 'VIRUSINTERPRETER' { + ext.jarPath = '/opt/virusinterpreter/virusinterpreter.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'ISOFOX' { + ext.jarPath = '/opt/isofox/isofox.jar' + ext.args = '-functions "TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS"' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'CUPPA_CLASSIFIER' { + ext.jarPath = '/opt/cuppa/cuppa.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/cuppa/${filename}" }, + ] + } + + withName: 'CUPPA_VISUALISER' { + ext.pythonPath = '/opt/cuppa/chart/cuppa-chart.py' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/cuppa/${filename}" }, + ] + } } diff --git a/conf/test.config b/conf/test.config index 42f23058..6811c4b5 100644 --- a/conf/test.config +++ b/conf/test.config @@ -1,29 +1,46 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for running minimal tests + Nextflow config file for running minimal tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defines input files and everything required to run a fast and simple pipeline test. + Defines input files and everything required to run a fast and simple pipeline test. - Use as follows: - nextflow run nf-core/oncoanalyser -profile test, --outdir + Use as follows: + nextflow run umccr/hmftools -profile test, --outdir ---------------------------------------------------------------------------------------- */ +process { + memory = 16.GB + + withName: 'SAGE_GERMLINE' { + ext.args = '-specific_regions \'chr10:87864102:87966988\'' + } + + withName: 'SAGE_SOMATIC' { + ext.args = '-specific_regions \'chr10:87736200:88056500;chr17:59748500:59828700\'' + } + + withName: 'COLLECTWGSMETRICS' { + // NOTE(SW): wrapped by a closure to delay eval until process creation/execution + ext.args = { "--INTERVALS ${params.ref_data_wgsmetrics_intervals_local}" } + } +} + params { - config_profile_name = 'Test profile' - config_profile_description = 'Minimal test dataset to check pipeline function' + config_profile_name = 'Test profile' + config_profile_description = 'Minimal test dataset to check pipeline function' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + // Defined here to be accessible within a workflow script; downloaded manually prior to process + // execution. + ref_data_wgsmetrics_intervals_url = 'https://raw.githubusercontent.com/scwatts/nextflow_testdata/main/hmftools/collectwgsmetrics/intervals.interval_list' + schema_ignore_params = 'ref_data_wgsmetrics_intervals_url' - // Input data - // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets - // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = 'https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv' + // Limit resources so that this can run on GitHub Actions + max_cpus = 1 + max_memory = 16.GB + max_time = 20.m - // Genome references - genome = 'R64-1-1' + // Input data + input = '/Users/stephen/repos/nextflow_testdata/hmftools/input_tsv/samplesheet.tsv' } diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..2d88ffdf --- /dev/null +++ b/examples/README.md @@ -0,0 +1,109 @@ +# Examples + +## Full + +| Filetype | Keyword | Description | Type | +| --- | --- | --- | --- | +| BAM (WGS) | `bam_wgs` | WGS read alignments | Required | +| BAM (WTS) | `bam_wts` | WTS read alignments | Optional | +| SV VCF | `vcf` | SV VCF produced by an external caller [_used to filter reads for GRIDSS_] | Optional | + +```text +id subject_name sample_name sample_type filetype filepath +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor bam_wgs /path/to/tumor_bam/sample_one_tumor.bam +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor bam_wts /path/to/tumor_bam/sample_one_tumor.rna.bam +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_sv /path/to/tumor_sv_vcf/sample_one_tumor.vcf.gz +SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal bam_wgs /path/to/normal_bam/sample_one_normal.bam +STWO-1 SUBJECT_TWO SAMPLE_TWO_TUMOR-1 tumor bam_wgs /path/to/tumor_bam/sample_two_tumor_one.bam +STWO-1 SUBJECT_TWO SAMPLE_TWO_NORMAL normal bam_wgs /path/to/normal_bam/sample_two_normal.bam +STWO-2 SUBJECT_TWO SAMPLE_TWO_TUMOR-2 tumor bam_wgs /path/to/tumor_bam/sample_two_tumor_two.bam +STWO-2 SUBJECT_TWO SAMPLE_TWO_NORMAL normal bam_wgs /path/to/normal_bam/sample_two_normal.bam +STRHEE-1 SUBJECT_THREE SAMPLE_THREE_TUMOR tumor bam_wgs /path/to/tumor_bam/sample_three_tumor.bam +STRHEE-1 SUBJECT_THREE SAMPLE_THREE_TUMOR tumor vcf_sv /path/to/tumor_sv_vcf/sample_three_tumor.vcf.gz +STRHEE-1 SUBJECT_THREE SAMPLE_THREE_NORMAL normal bam_wgs /path/to/normal_bam/sample_three_normal.bam +``` + +## GRIDSS + +See [Full section](#full) + +## PURPLE + +| Filetype | Keyword | Description | Type | +| --- | --- | --- | --- | +| AMBER directory | `amber_dir` | AMBER output directory | Required | +| COBALT directory | `cobalt_dir` | COBALT output directory | Required | +| GRIPSS SV VCF (hard filtered) | `vcf_sv_gripss_hard` | Hard filtered GRIPSS SV VCF | Required | +| GRIPSS SV VCF (soft filtered) | `vcf_sv_gripss_soft` | Soft filtered GRIPSS SV VCF | Required | +| SNV/MNV and INDEL VCF | `vcf_smlv` | Small SNV/MNV VCF | Optional | + +```text +id subject_name sample_name sample_type filetype filepath +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor amber_dir /path/to/amber_dir/ +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor cobalt_dir /path/to/cobalt_dir/ +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_sv_gripss_hard /path/to/tumor_gripss_hard_sv/sample_one_tumor.vcf.gz +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_sv_gripss_soft /path/to/tumor_gripss_soft_sv/sample_one_tumor.vcf.gz +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_smlv /path/to/tumor_smlv_vcf/sample_one_tumor.vcf.gz +SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal vcf_smlv /path/to/normal_smlv_vcf/sample_one_normal.vcf.gz +``` + +## LINX + +| Filetype | Keyword | Description | Type | +| --- | --- | --- | --- | +| PURPLE directory | `purple_dir` | PURPLE output directory [_LINX somatic_] | Required | +| GRIPSS SV VCF (hard filtered) | `vcf_sv_gripss_hard` | Hard filtered GRIPSS SV VCF [_LINX germline_] | Required | + +```text +id subject_name sample_name sample_type filetype filepath +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor purple_dir /path/to/purple_dir/ +SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal vcf_sv_gripss_hard /path/to/normal_gripss_hard_sv/sample_one_normal.vcf.gz +``` + +## GRIDSS-PURPLE-LINX + +| Filetype | Keyword | Description | Type | +| --- | --- | --- | --- | +| BAM (WGS) | `bam` | WGS read alignments | Required | +| SV VCF | `vcf_sv` | SV VCF produced by an external caller [_used to filter reads for GRIDSS_] | Optional | +| SNV/MNV and INDEL VCF | `vcf_smlv` | Small SNV/MNV VCF | Optional | + +```text +id subject_name sample_name sample_type filetype filepath +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor bam_wgs /path/to/tumor_bam/sample_one_tumor.bam +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_sv /path/to/tumor_sv_vcf/sample_one_tumor.vcf.gz +SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal bam_wgs /path/to/normal_bam/sample_one_normal.bam +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_smlv /path/to/tumor_smlv_vcf/sample_one_tumor.vcf.gz +SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal vcf_smlv /path/to/normal_smlv_vcf/sample_one_normal.vcf.gz +``` + + +## LILAC + +| Filetype | Keyword | Description | Type | +| --- | --- | --- | --- | +| BAM (WGS) | `bam_wgs` | WGS read alignments | Required | +| PURPLE directory | `purple_dir` | PURPLE output directory | Required | + +```text +id subject_name sample_name sample_type filetype filepath +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor bam_wgs /path/to/tumor_bam/sample_one_tumor.bam +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor purple_dir /path/to/purple_dir/ +SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal bam_wgs /path/to/normal_bam/sample_one_normal.bam +``` + +## TEAL + +| Filetype | Keyword | Description | Type | +| --- | --- | --- | --- | +| BAM (WGS) | `bam_wgs` | WGS read alignments | Required | +| COBALT directory | `cobalt_dir` | COBALT output directory | Required | +| PURPLE directory | `purple_dir` | PURPLE output directory | Required | + +```text +id subject_name sample_name sample_type filetype filepath +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor bam_wgs /path/to/tumor_bam/sample_one_tumor.bam +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor purple_dir /path/to/purple_dir/ +SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor cobalt_dir /path/to/cobalt_dir/ +SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal bam_wgs /path/to/normal_bam/sample_one_normal.bam +``` diff --git a/lib/Constants.groovy b/lib/Constants.groovy new file mode 100644 index 00000000..73710c38 --- /dev/null +++ b/lib/Constants.groovy @@ -0,0 +1,28 @@ +class Constants { + + static enum PipelineMode { + FULL, + MANUAL, + GRIDSS_PURPLE_LINX, + CUPPA, + } + + static enum Process { + AMBER, + COBALT, + COLLECTWGSMETRICS, + CUPPA, + GRIDSS, + GRIPSS, + ISOFOX, + LILAC, + LINX, + PAVE, + PURPLE, + SAGE, + SVPREP, + TEAL, + VIRUSINTERPRETER, + } + +} diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy index b3d092f8..1b136381 100755 --- a/lib/NfcoreSchema.groovy +++ b/lib/NfcoreSchema.groovy @@ -13,517 +13,517 @@ import groovy.json.JsonBuilder class NfcoreSchema { - // - // Resolve Schema path relative to main workflow directory - // - public static String getSchemaPath(workflow, schema_filename='nextflow_schema.json') { - return "${workflow.projectDir}/${schema_filename}" - } + // + // Resolve Schema path relative to main workflow directory + // + public static String getSchemaPath(workflow, schema_filename='nextflow_schema.json') { + return "${workflow.projectDir}/${schema_filename}" + } - // - // Function to loop over all parameters defined in schema and check - // whether the given parameters adhere to the specifications - // - /* groovylint-disable-next-line UnusedPrivateMethodParameter */ - public static void validateParameters(workflow, params, log, schema_filename='nextflow_schema.json') { - def has_error = false - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - // Check for nextflow core params and unexpected params - def json = new File(getSchemaPath(workflow, schema_filename=schema_filename)).text - def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions') - def nf_params = [ - // Options for base `nextflow` command - 'bg', - 'c', - 'C', - 'config', - 'd', - 'D', - 'dockerize', - 'h', - 'log', - 'q', - 'quiet', - 'syslog', - 'v', - 'version', + // + // Function to loop over all parameters defined in schema and check + // whether the given parameters adhere to the specifications + // + /* groovylint-disable-next-line UnusedPrivateMethodParameter */ + public static void validateParameters(workflow, params, log, schema_filename='nextflow_schema.json') { + def has_error = false + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Check for nextflow core params and unexpected params + def json = new File(getSchemaPath(workflow, schema_filename=schema_filename)).text + def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions') + def nf_params = [ + // Options for base `nextflow` command + 'bg', + 'c', + 'C', + 'config', + 'd', + 'D', + 'dockerize', + 'h', + 'log', + 'q', + 'quiet', + 'syslog', + 'v', + 'version', - // Options for `nextflow run` command - 'ansi', - 'ansi-log', - 'bg', - 'bucket-dir', - 'c', - 'cache', - 'config', - 'dsl2', - 'dump-channels', - 'dump-hashes', - 'E', - 'entry', - 'latest', - 'lib', - 'main-script', - 'N', - 'name', - 'offline', - 'params-file', - 'pi', - 'plugins', - 'poll-interval', - 'pool-size', - 'profile', - 'ps', - 'qs', - 'queue-size', - 'r', - 'resume', - 'revision', - 'stdin', - 'stub', - 'stub-run', - 'test', - 'w', - 'with-charliecloud', - 'with-conda', - 'with-dag', - 'with-docker', - 'with-mpi', - 'with-notification', - 'with-podman', - 'with-report', - 'with-singularity', - 'with-timeline', - 'with-tower', - 'with-trace', - 'with-weblog', - 'without-docker', - 'without-podman', - 'work-dir' - ] - def unexpectedParams = [] + // Options for `nextflow run` command + 'ansi', + 'ansi-log', + 'bg', + 'bucket-dir', + 'c', + 'cache', + 'config', + 'dsl2', + 'dump-channels', + 'dump-hashes', + 'E', + 'entry', + 'latest', + 'lib', + 'main-script', + 'N', + 'name', + 'offline', + 'params-file', + 'pi', + 'plugins', + 'poll-interval', + 'pool-size', + 'profile', + 'ps', + 'qs', + 'queue-size', + 'r', + 'resume', + 'revision', + 'stdin', + 'stub', + 'stub-run', + 'test', + 'w', + 'with-charliecloud', + 'with-conda', + 'with-dag', + 'with-docker', + 'with-mpi', + 'with-notification', + 'with-podman', + 'with-report', + 'with-singularity', + 'with-timeline', + 'with-tower', + 'with-trace', + 'with-weblog', + 'without-docker', + 'without-podman', + 'work-dir' + ] + def unexpectedParams = [] - // Collect expected parameters from the schema - def expectedParams = [] - def enums = [:] - for (group in schemaParams) { - for (p in group.value['properties']) { - expectedParams.push(p.key) - if (group.value['properties'][p.key].containsKey('enum')) { - enums[p.key] = group.value['properties'][p.key]['enum'] - } - } + // Collect expected parameters from the schema + def expectedParams = [] + def enums = [:] + for (group in schemaParams) { + for (p in group.value['properties']) { + expectedParams.push(p.key) + if (group.value['properties'][p.key].containsKey('enum')) { + enums[p.key] = group.value['properties'][p.key]['enum'] } + } + } - for (specifiedParam in params.keySet()) { - // nextflow params - if (nf_params.contains(specifiedParam)) { - log.error "ERROR: You used a core Nextflow option with two hyphens: '--${specifiedParam}'. Please resubmit with '-${specifiedParam}'" - has_error = true - } - // unexpected params - def params_ignore = params.schema_ignore_params.split(',') + 'schema_ignore_params' - def expectedParamsLowerCase = expectedParams.collect{ it.replace("-", "").toLowerCase() } - def specifiedParamLowerCase = specifiedParam.replace("-", "").toLowerCase() - def isCamelCaseBug = (specifiedParam.contains("-") && !expectedParams.contains(specifiedParam) && expectedParamsLowerCase.contains(specifiedParamLowerCase)) - if (!expectedParams.contains(specifiedParam) && !params_ignore.contains(specifiedParam) && !isCamelCaseBug) { - // Temporarily remove camelCase/camel-case params #1035 - def unexpectedParamsLowerCase = unexpectedParams.collect{ it.replace("-", "").toLowerCase()} - if (!unexpectedParamsLowerCase.contains(specifiedParamLowerCase)){ - unexpectedParams.push(specifiedParam) - } - } + for (specifiedParam in params.keySet()) { + // nextflow params + if (nf_params.contains(specifiedParam)) { + log.error "ERROR: You used a core Nextflow option with two hyphens: '--${specifiedParam}'. Please resubmit with '-${specifiedParam}'" + has_error = true + } + // unexpected params + def params_ignore = params.schema_ignore_params.split(',') + 'schema_ignore_params' + def expectedParamsLowerCase = expectedParams.collect{ it.replace("-", "").toLowerCase() } + def specifiedParamLowerCase = specifiedParam.replace("-", "").toLowerCase() + def isCamelCaseBug = (specifiedParam.contains("-") && !expectedParams.contains(specifiedParam) && expectedParamsLowerCase.contains(specifiedParamLowerCase)) + if (!expectedParams.contains(specifiedParam) && !params_ignore.contains(specifiedParam) && !isCamelCaseBug) { + // Temporarily remove camelCase/camel-case params #1035 + def unexpectedParamsLowerCase = unexpectedParams.collect{ it.replace("-", "").toLowerCase()} + if (!unexpectedParamsLowerCase.contains(specifiedParamLowerCase)){ + unexpectedParams.push(specifiedParam) } + } + } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - // Validate parameters against the schema - InputStream input_stream = new File(getSchemaPath(workflow, schema_filename=schema_filename)).newInputStream() - JSONObject raw_schema = new JSONObject(new JSONTokener(input_stream)) - - // Remove anything that's in params.schema_ignore_params - raw_schema = removeIgnoredParams(raw_schema, params) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Validate parameters against the schema + InputStream input_stream = new File(getSchemaPath(workflow, schema_filename=schema_filename)).newInputStream() + JSONObject raw_schema = new JSONObject(new JSONTokener(input_stream)) - Schema schema = SchemaLoader.load(raw_schema) + // Remove anything that's in params.schema_ignore_params + raw_schema = removeIgnoredParams(raw_schema, params) - // Clean the parameters - def cleanedParams = cleanParameters(params) + Schema schema = SchemaLoader.load(raw_schema) - // Convert to JSONObject - def jsonParams = new JsonBuilder(cleanedParams) - JSONObject params_json = new JSONObject(jsonParams.toString()) + // Clean the parameters + def cleanedParams = cleanParameters(params) - // Validate - try { - schema.validate(params_json) - } catch (ValidationException e) { - println '' - log.error 'ERROR: Validation of pipeline parameters failed!' - JSONObject exceptionJSON = e.toJSON() - printExceptions(exceptionJSON, params_json, log, enums) - println '' - has_error = true - } + // Convert to JSONObject + def jsonParams = new JsonBuilder(cleanedParams) + JSONObject params_json = new JSONObject(jsonParams.toString()) - // Check for unexpected parameters - if (unexpectedParams.size() > 0) { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - println '' - def warn_msg = 'Found unexpected parameters:' - for (unexpectedParam in unexpectedParams) { - warn_msg = warn_msg + "\n* --${unexpectedParam}: ${params[unexpectedParam].toString()}" - } - log.warn warn_msg - log.info "- ${colors.dim}Ignore this warning: params.schema_ignore_params = \"${unexpectedParams.join(',')}\" ${colors.reset}" - println '' - } + // Validate + try { + schema.validate(params_json) + } catch (ValidationException e) { + println '' + log.error 'ERROR: Validation of pipeline parameters failed!' + JSONObject exceptionJSON = e.toJSON() + printExceptions(exceptionJSON, params_json, log, enums) + println '' + has_error = true + } - if (has_error) { - System.exit(1) - } + // Check for unexpected parameters + if (unexpectedParams.size() > 0) { + Map colors = NfcoreTemplate.logColours(params.monochrome_logs) + println '' + def warn_msg = 'Found unexpected parameters:' + for (unexpectedParam in unexpectedParams) { + warn_msg = warn_msg + "\n* --${unexpectedParam}: ${params[unexpectedParam].toString()}" + } + log.warn warn_msg + log.info "- ${colors.dim}Ignore this warning: params.schema_ignore_params = \"${unexpectedParams.join(',')}\" ${colors.reset}" + println '' } - // - // Beautify parameters for --help - // - public static String paramsHelp(workflow, params, command, schema_filename='nextflow_schema.json') { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - Integer num_hidden = 0 - String output = '' - output += 'Typical pipeline command:\n\n' - output += " ${colors.cyan}${command}${colors.reset}\n\n" - Map params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) - Integer max_chars = paramsMaxChars(params_map) + 1 - Integer desc_indent = max_chars + 14 - Integer dec_linewidth = 160 - desc_indent - for (group in params_map.keySet()) { - Integer num_params = 0 - String group_output = colors.underlined + colors.bold + group + colors.reset + '\n' - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (group_params.get(param).hidden && !params.show_hidden_params) { - num_hidden += 1 - continue; - } - def type = '[' + group_params.get(param).type + ']' - def description = group_params.get(param).description - def defaultValue = group_params.get(param).default != null ? " [default: " + group_params.get(param).default.toString() + "]" : '' - def description_default = description + colors.dim + defaultValue + colors.reset - // Wrap long description texts - // Loosely based on https://dzone.com/articles/groovy-plain-text-word-wrap - if (description_default.length() > dec_linewidth){ - List olines = [] - String oline = "" // " " * indent - description_default.split(" ").each() { wrd -> - if ((oline.size() + wrd.size()) <= dec_linewidth) { - oline += wrd + " " - } else { - olines += oline - oline = wrd + " " - } - } - olines += oline - description_default = olines.join("\n" + " " * desc_indent) - } - group_output += " --" + param.padRight(max_chars) + colors.dim + type.padRight(10) + colors.reset + description_default + '\n' - num_params += 1 - } - group_output += '\n' - if (num_params > 0){ - output += group_output - } - } - if (num_hidden > 0){ - output += colors.dim + "!! Hiding $num_hidden params, use --show_hidden_params to show them !!\n" + colors.reset - } - output += NfcoreTemplate.dashedLine(params.monochrome_logs) - return output + if (has_error) { + System.exit(1) } + } - // - // Groovy Map summarising parameters/workflow options used by the pipeline - // - public static LinkedHashMap paramsSummaryMap(workflow, params, schema_filename='nextflow_schema.json') { - // Get a selection of core Nextflow workflow options - def Map workflow_summary = [:] - if (workflow.revision) { - workflow_summary['revision'] = workflow.revision - } - workflow_summary['runName'] = workflow.runName - if (workflow.containerEngine) { - workflow_summary['containerEngine'] = workflow.containerEngine + // + // Beautify parameters for --help + // + public static String paramsHelp(workflow, params, command, schema_filename='nextflow_schema.json') { + Map colors = NfcoreTemplate.logColours(params.monochrome_logs) + Integer num_hidden = 0 + String output = '' + output += 'Typical pipeline command:\n\n' + output += " ${colors.cyan}${command}${colors.reset}\n\n" + Map params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) + Integer max_chars = paramsMaxChars(params_map) + 1 + Integer desc_indent = max_chars + 14 + Integer dec_linewidth = 160 - desc_indent + for (group in params_map.keySet()) { + Integer num_params = 0 + String group_output = colors.underlined + colors.bold + group + colors.reset + '\n' + def group_params = params_map.get(group) // This gets the parameters of that particular group + for (param in group_params.keySet()) { + if (group_params.get(param).hidden && !params.show_hidden_params) { + num_hidden += 1 + continue; } - if (workflow.container) { - workflow_summary['container'] = workflow.container - } - workflow_summary['launchDir'] = workflow.launchDir - workflow_summary['workDir'] = workflow.workDir - workflow_summary['projectDir'] = workflow.projectDir - workflow_summary['userName'] = workflow.userName - workflow_summary['profile'] = workflow.profile - workflow_summary['configFiles'] = workflow.configFiles.join(', ') - - // Get pipeline parameters defined in JSON Schema - def Map params_summary = [:] - def params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) - for (group in params_map.keySet()) { - def sub_params = new LinkedHashMap() - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (params.containsKey(param)) { - def params_value = params.get(param) - def schema_value = group_params.get(param).default - def param_type = group_params.get(param).type - if (schema_value != null) { - if (param_type == 'string') { - if (schema_value.contains('$projectDir') || schema_value.contains('${projectDir}')) { - def sub_string = schema_value.replace('\$projectDir', '') - sub_string = sub_string.replace('\${projectDir}', '') - if (params_value.contains(sub_string)) { - schema_value = params_value - } - } - if (schema_value.contains('$params.outdir') || schema_value.contains('${params.outdir}')) { - def sub_string = schema_value.replace('\$params.outdir', '') - sub_string = sub_string.replace('\${params.outdir}', '') - if ("${params.outdir}${sub_string}" == params_value) { - schema_value = params_value - } - } - } - } - - // We have a default in the schema, and this isn't it - if (schema_value != null && params_value != schema_value) { - sub_params.put(param, params_value) - } - // No default in the schema, and this isn't empty - else if (schema_value == null && params_value != "" && params_value != null && params_value != false) { - sub_params.put(param, params_value) - } - } + def type = '[' + group_params.get(param).type + ']' + def description = group_params.get(param).description + def defaultValue = group_params.get(param).default != null ? " [default: " + group_params.get(param).default.toString() + "]" : '' + def description_default = description + colors.dim + defaultValue + colors.reset + // Wrap long description texts + // Loosely based on https://dzone.com/articles/groovy-plain-text-word-wrap + if (description_default.length() > dec_linewidth){ + List olines = [] + String oline = "" // " " * indent + description_default.split(" ").each() { wrd -> + if ((oline.size() + wrd.size()) <= dec_linewidth) { + oline += wrd + " " + } else { + olines += oline + oline = wrd + " " } - params_summary.put(group, sub_params) + } + olines += oline + description_default = olines.join("\n" + " " * desc_indent) } - return [ 'Core Nextflow options' : workflow_summary ] << params_summary + group_output += " --" + param.padRight(max_chars) + colors.dim + type.padRight(10) + colors.reset + description_default + '\n' + num_params += 1 + } + group_output += '\n' + if (num_params > 0){ + output += group_output + } } + if (num_hidden > 0){ + output += colors.dim + "!! Hiding $num_hidden params, use --show_hidden_params to show them !!\n" + colors.reset + } + output += NfcoreTemplate.dashedLine(params.monochrome_logs) + return output + } - // - // Beautify parameters for summary and return as string - // - public static String paramsSummaryLog(workflow, params) { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - String output = '' - def params_map = paramsSummaryMap(workflow, params) - def max_chars = paramsMaxChars(params_map) - for (group in params_map.keySet()) { - def group_params = params_map.get(group) // This gets the parameters of that particular group - if (group_params) { - output += colors.bold + group + colors.reset + '\n' - for (param in group_params.keySet()) { - output += " " + colors.blue + param.padRight(max_chars) + ": " + colors.green + group_params.get(param) + colors.reset + '\n' - } - output += '\n' - } - } - output += "!! Only displaying parameters that differ from the pipeline defaults !!\n" - output += NfcoreTemplate.dashedLine(params.monochrome_logs) - return output + // + // Groovy Map summarising parameters/workflow options used by the pipeline + // + public static LinkedHashMap paramsSummaryMap(workflow, params, schema_filename='nextflow_schema.json') { + // Get a selection of core Nextflow workflow options + def Map workflow_summary = [:] + if (workflow.revision) { + workflow_summary['revision'] = workflow.revision + } + workflow_summary['runName'] = workflow.runName + if (workflow.containerEngine) { + workflow_summary['containerEngine'] = workflow.containerEngine } + if (workflow.container) { + workflow_summary['container'] = workflow.container + } + workflow_summary['launchDir'] = workflow.launchDir + workflow_summary['workDir'] = workflow.workDir + workflow_summary['projectDir'] = workflow.projectDir + workflow_summary['userName'] = workflow.userName + workflow_summary['profile'] = workflow.profile + workflow_summary['configFiles'] = workflow.configFiles.join(', ') - // - // Loop over nested exceptions and print the causingException - // - private static void printExceptions(ex_json, params_json, log, enums, limit=5) { - def causingExceptions = ex_json['causingExceptions'] - if (causingExceptions.length() == 0) { - def m = ex_json['message'] =~ /required key \[([^\]]+)\] not found/ - // Missing required param - if (m.matches()) { - log.error "* Missing required parameter: --${m[0][1]}" - } - // Other base-level error - else if (ex_json['pointerToViolation'] == '#') { - log.error "* ${ex_json['message']}" - } - // Error with specific param - else { - def param = ex_json['pointerToViolation'] - ~/^#\// - def param_val = params_json[param].toString() - if (enums.containsKey(param)) { - def error_msg = "* --${param}: '${param_val}' is not a valid choice (Available choices" - if (enums[param].size() > limit) { - log.error "${error_msg} (${limit} of ${enums[param].size()}): ${enums[param][0..limit-1].join(', ')}, ... )" - } else { - log.error "${error_msg}: ${enums[param].join(', ')})" - } - } else { - log.error "* --${param}: ${ex_json['message']} (${param_val})" + // Get pipeline parameters defined in JSON Schema + def Map params_summary = [:] + def params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) + for (group in params_map.keySet()) { + def sub_params = new LinkedHashMap() + def group_params = params_map.get(group) // This gets the parameters of that particular group + for (param in group_params.keySet()) { + if (params.containsKey(param)) { + def params_value = params.get(param) + def schema_value = group_params.get(param).default + def param_type = group_params.get(param).type + if (schema_value != null) { + if (param_type == 'string') { + if (schema_value.contains('$projectDir') || schema_value.contains('${projectDir}')) { + def sub_string = schema_value.replace('\$projectDir', '') + sub_string = sub_string.replace('\${projectDir}', '') + if (params_value.contains(sub_string)) { + schema_value = params_value + } + } + if (schema_value.contains('$params.outdir') || schema_value.contains('${params.outdir}')) { + def sub_string = schema_value.replace('\$params.outdir', '') + sub_string = sub_string.replace('\${params.outdir}', '') + if ("${params.outdir}${sub_string}" == params_value) { + schema_value = params_value } + } } + } + + // We have a default in the schema, and this isn't it + if (schema_value != null && params_value != schema_value) { + sub_params.put(param, params_value) + } + // No default in the schema, and this isn't empty + else if (schema_value == null && params_value != "" && params_value != null && params_value != false) { + sub_params.put(param, params_value) + } } - for (ex in causingExceptions) { - printExceptions(ex, params_json, log, enums) - } + } + params_summary.put(group, sub_params) } + return [ 'Core Nextflow options' : workflow_summary ] << params_summary + } - // - // Remove an element from a JSONArray - // - private static JSONArray removeElement(json_array, element) { - def list = [] - int len = json_array.length() - for (int i=0;i - if(raw_schema.keySet().contains('definitions')){ - raw_schema.definitions.each { definition -> - for (key in definition.keySet()){ - if (definition[key].get("properties").keySet().contains(ignore_param)){ - // Remove the param to ignore - definition[key].get("properties").remove(ignore_param) - // If the param was required, change this - if (definition[key].has("required")) { - def cleaned_required = removeElement(definition[key].required, ignore_param) - definition[key].put("required", cleaned_required) - } - } - } - } - } - if(raw_schema.keySet().contains('properties') && raw_schema.get('properties').keySet().contains(ignore_param)) { - raw_schema.get("properties").remove(ignore_param) - } - if(raw_schema.keySet().contains('required') && raw_schema.required.contains(ignore_param)) { - def cleaned_required = removeElement(raw_schema.required, ignore_param) - raw_schema.put("required", cleaned_required) - } + // + // Loop over nested exceptions and print the causingException + // + private static void printExceptions(ex_json, params_json, log, enums, limit=5) { + def causingExceptions = ex_json['causingExceptions'] + if (causingExceptions.length() == 0) { + def m = ex_json['message'] =~ /required key \[([^\]]+)\] not found/ + // Missing required param + if (m.matches()) { + log.error "* Missing required parameter: --${m[0][1]}" + } + // Other base-level error + else if (ex_json['pointerToViolation'] == '#') { + log.error "* ${ex_json['message']}" + } + // Error with specific param + else { + def param = ex_json['pointerToViolation'] - ~/^#\// + def param_val = params_json[param].toString() + if (enums.containsKey(param)) { + def error_msg = "* --${param}: '${param_val}' is not a valid choice (Available choices" + if (enums[param].size() > limit) { + log.error "${error_msg} (${limit} of ${enums[param].size()}): ${enums[param][0..limit-1].join(', ')}, ... )" + } else { + log.error "${error_msg}: ${enums[param].join(', ')})" + } + } else { + log.error "* --${param}: ${ex_json['message']} (${param_val})" } - return raw_schema + } + } + for (ex in causingExceptions) { + printExceptions(ex, params_json, log, enums) } + } - // - // Clean and check parameters relative to Nextflow native classes - // - private static Map cleanParameters(params) { - def new_params = params.getClass().newInstance(params) - for (p in params) { - // remove anything evaluating to false - if (!p['value']) { - new_params.remove(p.key) - } - // Cast MemoryUnit to String - if (p['value'].getClass() == nextflow.util.MemoryUnit) { - new_params.replace(p.key, p['value'].toString()) - } - // Cast Duration to String - if (p['value'].getClass() == nextflow.util.Duration) { - new_params.replace(p.key, p['value'].toString().replaceFirst(/d(?!\S)/, "day")) - } - // Cast LinkedHashMap to String - if (p['value'].getClass() == LinkedHashMap) { - new_params.replace(p.key, p['value'].toString()) + // + // Remove an element from a JSONArray + // + private static JSONArray removeElement(json_array, element) { + def list = [] + int len = json_array.length() + for (int i=0;i + if(raw_schema.keySet().contains('definitions')){ + raw_schema.definitions.each { definition -> + for (key in definition.keySet()){ + if (definition[key].get("properties").keySet().contains(ignore_param)){ + // Remove the param to ignore + definition[key].get("properties").remove(ignore_param) + // If the param was required, change this + if (definition[key].has("required")) { + def cleaned_required = removeElement(definition[key].required, ignore_param) + definition[key].put("required", cleaned_required) + } } + } } - return new_params + } + if(raw_schema.keySet().contains('properties') && raw_schema.get('properties').keySet().contains(ignore_param)) { + raw_schema.get("properties").remove(ignore_param) + } + if(raw_schema.keySet().contains('required') && raw_schema.required.contains(ignore_param)) { + def cleaned_required = removeElement(raw_schema.required, ignore_param) + raw_schema.put("required", cleaned_required) + } } + return raw_schema + } - // - // This function tries to read a JSON params file - // - private static LinkedHashMap paramsLoad(String json_schema) { - def params_map = new LinkedHashMap() - try { - params_map = paramsRead(json_schema) - } catch (Exception e) { - println "Could not read parameters settings from JSON. $e" - params_map = new LinkedHashMap() - } - return params_map + // + // Clean and check parameters relative to Nextflow native classes + // + private static Map cleanParameters(params) { + def new_params = params.getClass().newInstance(params) + for (p in params) { + // remove anything evaluating to false + if (!p['value']) { + new_params.remove(p.key) + } + // Cast MemoryUnit to String + if (p['value'].getClass() == nextflow.util.MemoryUnit) { + new_params.replace(p.key, p['value'].toString()) + } + // Cast Duration to String + if (p['value'].getClass() == nextflow.util.Duration) { + new_params.replace(p.key, p['value'].toString().replaceFirst(/d(?!\S)/, "day")) + } + // Cast LinkedHashMap to String + if (p['value'].getClass() == LinkedHashMap) { + new_params.replace(p.key, p['value'].toString()) + } } + return new_params + } - // - // Method to actually read in JSON file using Groovy. - // Group (as Key), values are all parameters - // - Parameter1 as Key, Description as Value - // - Parameter2 as Key, Description as Value - // .... - // Group - // - - private static LinkedHashMap paramsRead(String json_schema) throws Exception { - def json = new File(json_schema).text - def Map schema_definitions = (Map) new JsonSlurper().parseText(json).get('definitions') - def Map schema_properties = (Map) new JsonSlurper().parseText(json).get('properties') - /* Tree looks like this in nf-core schema - * definitions <- this is what the first get('definitions') gets us - group 1 - title - description - properties - parameter 1 - type - description - parameter 2 - type - description - group 2 - title - description - properties - parameter 1 - type - description - * properties <- parameters can also be ungrouped, outside of definitions - parameter 1 - type - description - */ + // + // This function tries to read a JSON params file + // + private static LinkedHashMap paramsLoad(String json_schema) { + def params_map = new LinkedHashMap() + try { + params_map = paramsRead(json_schema) + } catch (Exception e) { + println "Could not read parameters settings from JSON. $e" + params_map = new LinkedHashMap() + } + return params_map + } - // Grouped params - def params_map = new LinkedHashMap() - schema_definitions.each { key, val -> - def Map group = schema_definitions."$key".properties // Gets the property object of the group - def title = schema_definitions."$key".title - def sub_params = new LinkedHashMap() - group.each { innerkey, value -> - sub_params.put(innerkey, value) - } - params_map.put(title, sub_params) - } + // + // Method to actually read in JSON file using Groovy. + // Group (as Key), values are all parameters + // - Parameter1 as Key, Description as Value + // - Parameter2 as Key, Description as Value + // .... + // Group + // - + private static LinkedHashMap paramsRead(String json_schema) throws Exception { + def json = new File(json_schema).text + def Map schema_definitions = (Map) new JsonSlurper().parseText(json).get('definitions') + def Map schema_properties = (Map) new JsonSlurper().parseText(json).get('properties') + /* Tree looks like this in nf-core schema + * definitions <- this is what the first get('definitions') gets us + group 1 + title + description + properties + parameter 1 + type + description + parameter 2 + type + description + group 2 + title + description + properties + parameter 1 + type + description + * properties <- parameters can also be ungrouped, outside of definitions + parameter 1 + type + description + */ - // Ungrouped params - def ungrouped_params = new LinkedHashMap() - schema_properties.each { innerkey, value -> - ungrouped_params.put(innerkey, value) - } - params_map.put("Other parameters", ungrouped_params) + // Grouped params + def params_map = new LinkedHashMap() + schema_definitions.each { key, val -> + def Map group = schema_definitions."$key".properties // Gets the property object of the group + def title = schema_definitions."$key".title + def sub_params = new LinkedHashMap() + group.each { innerkey, value -> + sub_params.put(innerkey, value) + } + params_map.put(title, sub_params) + } - return params_map + // Ungrouped params + def ungrouped_params = new LinkedHashMap() + schema_properties.each { innerkey, value -> + ungrouped_params.put(innerkey, value) } + params_map.put("Other parameters", ungrouped_params) - // - // Get maximum number of characters across all parameter names - // - private static Integer paramsMaxChars(params_map) { - Integer max_chars = 0 - for (group in params_map.keySet()) { - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (param.size() > max_chars) { - max_chars = param.size() - } - } + return params_map + } + + // + // Get maximum number of characters across all parameter names + // + private static Integer paramsMaxChars(params_map) { + Integer max_chars = 0 + for (group in params_map.keySet()) { + def group_params = params_map.get(group) // This gets the parameters of that particular group + for (param in group_params.keySet()) { + if (param.size() > max_chars) { + max_chars = param.size() } - return max_chars + } } + return max_chars + } } diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 27feb009..10e5ccd0 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -6,308 +6,253 @@ import org.yaml.snakeyaml.Yaml class NfcoreTemplate { - // - // Check AWS Batch related parameters have been specified correctly - // - public static void awsBatch(workflow, params) { - if (workflow.profile.contains('awsbatch')) { - // Check params.awsqueue and params.awsregion have been set if running on AWSBatch - assert (params.awsqueue && params.awsregion) : "Specify correct --awsqueue and --awsregion parameters on AWSBatch!" - // Check outdir paths to be S3 buckets if running on AWSBatch - assert params.outdir.startsWith('s3:') : "Outdir not on S3 - specify S3 Bucket to run on AWSBatch!" - } + // + // Check AWS Batch related parameters have been specified correctly + // + public static void awsBatch(workflow, params) { + if (workflow.profile.contains('awsbatch')) { + // Check params.awsqueue and params.awsregion have been set if running on AWSBatch + assert (params.awsqueue && params.awsregion) : "Specify correct --awsqueue and --awsregion parameters on AWSBatch!" + // Check outdir paths to be S3 buckets if running on AWSBatch + assert params.outdir.startsWith('s3:') : "Outdir not on S3 - specify S3 Bucket to run on AWSBatch!" } - - // - // Warn if a -profile or Nextflow config has not been provided to run the pipeline - // - public static void checkConfigProvided(workflow, log) { - if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { - log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + - "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + - " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + - " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + - " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + - "Please refer to the quick start section and usage docs for the pipeline.\n " - } + } + + // + // Warn if a -profile or Nextflow config has not been provided to run the pipeline + // + public static void checkConfigProvided(workflow, log) { + if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { + log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + + "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + + " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + + " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + + " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + + "Please refer to the quick start section and usage docs for the pipeline.\n " } + } - // - // Construct and send completion email - // - public static void email(workflow, params, summary_params, projectDir, log, multiqc_report=[]) { - - // Set up the e-mail variables - def subject = "[$workflow.manifest.name] Successful: $workflow.runName" - if (!workflow.success) { - subject = "[$workflow.manifest.name] FAILED: $workflow.runName" - } - - def summary = [:] - for (group in summary_params.keySet()) { - summary << summary_params[group] - } - - def misc_fields = [:] - misc_fields['Date Started'] = workflow.start - misc_fields['Date Completed'] = workflow.complete - misc_fields['Pipeline script file path'] = workflow.scriptFile - misc_fields['Pipeline script hash ID'] = workflow.scriptId - if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository - if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId - if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision - misc_fields['Nextflow Version'] = workflow.nextflow.version - misc_fields['Nextflow Build'] = workflow.nextflow.build - misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp - - def email_fields = [:] - email_fields['version'] = workflow.manifest.version - email_fields['runName'] = workflow.runName - email_fields['success'] = workflow.success - email_fields['dateComplete'] = workflow.complete - email_fields['duration'] = workflow.duration - email_fields['exitStatus'] = workflow.exitStatus - email_fields['errorMessage'] = (workflow.errorMessage ?: 'None') - email_fields['errorReport'] = (workflow.errorReport ?: 'None') - email_fields['commandLine'] = workflow.commandLine - email_fields['projectDir'] = workflow.projectDir - email_fields['summary'] = summary << misc_fields - - // On success try attach the multiqc report - def mqc_report = null - try { - if (workflow.success) { - mqc_report = multiqc_report.getVal() - if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { - if (mqc_report.size() > 1) { - log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" - } - mqc_report = mqc_report[0] - } - } - } catch (all) { - if (multiqc_report) { - log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" - } - } - - // Check if we are only sending emails on failure - def email_address = params.email - if (!params.email && params.email_on_fail && !workflow.success) { - email_address = params.email_on_fail - } - - // Render the TXT template - def engine = new groovy.text.GStringTemplateEngine() - def tf = new File("$projectDir/assets/email_template.txt") - def txt_template = engine.createTemplate(tf).make(email_fields) - def email_txt = txt_template.toString() - - // Render the HTML template - def hf = new File("$projectDir/assets/email_template.html") - def html_template = engine.createTemplate(hf).make(email_fields) - def email_html = html_template.toString() - - // Render the sendmail template - def max_multiqc_email_size = params.max_multiqc_email_size as nextflow.util.MemoryUnit - def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] - def sf = new File("$projectDir/assets/sendmail_template.txt") - def sendmail_template = engine.createTemplate(sf).make(smail_fields) - def sendmail_html = sendmail_template.toString() - - // Send the HTML e-mail - Map colors = logColours(params.monochrome_logs) - if (email_address) { - try { - if (params.plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } - // Try to send HTML e-mail using sendmail - [ 'sendmail', '-t' ].execute() << sendmail_html - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" - } catch (all) { - // Catch failures and try with plaintext - def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] - if ( mqc_report.size() <= max_multiqc_email_size.toBytes() ) { - mail_cmd += [ '-A', mqc_report ] - } - mail_cmd.execute() << email_html - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" - } - } + // + // Construct and send completion email + // + public static void email(workflow, params, summary_params, projectDir, log, multiqc_report=[]) { - // Write summary e-mail HTML to a file - def output_d = new File("${params.outdir}/pipeline_info/") - if (!output_d.exists()) { - output_d.mkdirs() - } - def output_hf = new File(output_d, "pipeline_report.html") - output_hf.withWriter { w -> w << email_html } - def output_tf = new File(output_d, "pipeline_report.txt") - output_tf.withWriter { w -> w << email_txt } + // Set up the e-mail variables + def subject = "[$workflow.manifest.name] Successful: $workflow.runName" + if (!workflow.success) { + subject = "[$workflow.manifest.name] FAILED: $workflow.runName" } - // - // Construct and send adaptive card - // https://adaptivecards.io - // - public static void adaptivecard(workflow, params, summary_params, projectDir, log) { - def hook_url = params.hook_url - - def summary = [:] - for (group in summary_params.keySet()) { - summary << summary_params[group] - } - - def misc_fields = [:] - misc_fields['start'] = workflow.start - misc_fields['complete'] = workflow.complete - misc_fields['scriptfile'] = workflow.scriptFile - misc_fields['scriptid'] = workflow.scriptId - if (workflow.repository) misc_fields['repository'] = workflow.repository - if (workflow.commitId) misc_fields['commitid'] = workflow.commitId - if (workflow.revision) misc_fields['revision'] = workflow.revision - misc_fields['nxf_version'] = workflow.nextflow.version - misc_fields['nxf_build'] = workflow.nextflow.build - misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp - - def msg_fields = [:] - msg_fields['version'] = workflow.manifest.version - msg_fields['runName'] = workflow.runName - msg_fields['success'] = workflow.success - msg_fields['dateComplete'] = workflow.complete - msg_fields['duration'] = workflow.duration - msg_fields['exitStatus'] = workflow.exitStatus - msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') - msg_fields['errorReport'] = (workflow.errorReport ?: 'None') - msg_fields['commandLine'] = workflow.commandLine - msg_fields['projectDir'] = workflow.projectDir - msg_fields['summary'] = summary << misc_fields - - // Render the JSON template - def engine = new groovy.text.GStringTemplateEngine() - def hf = new File("$projectDir/assets/adaptivecard.json") - def json_template = engine.createTemplate(hf).make(msg_fields) - def json_message = json_template.toString() - - // POST - def post = new URL(hook_url).openConnection(); - post.setRequestMethod("POST") - post.setDoOutput(true) - post.setRequestProperty("Content-Type", "application/json") - post.getOutputStream().write(json_message.getBytes("UTF-8")); - def postRC = post.getResponseCode(); - if (! postRC.equals(200)) { - log.warn(post.getErrorStream().getText()); - } + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] } - // - // Print pipeline summary on completion - // - public static void summary(workflow, params, log) { - Map colors = logColours(params.monochrome_logs) - if (workflow.success) { - if (workflow.stats.ignoredCount == 0) { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" - } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" - } - } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" + def misc_fields = [:] + misc_fields['Date Started'] = workflow.start + misc_fields['Date Completed'] = workflow.complete + misc_fields['Pipeline script file path'] = workflow.scriptFile + misc_fields['Pipeline script hash ID'] = workflow.scriptId + if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository + if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId + if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision + misc_fields['Nextflow Version'] = workflow.nextflow.version + misc_fields['Nextflow Build'] = workflow.nextflow.build + misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp + + def email_fields = [:] + email_fields['version'] = workflow.manifest.version + email_fields['runName'] = workflow.runName + email_fields['success'] = workflow.success + email_fields['dateComplete'] = workflow.complete + email_fields['duration'] = workflow.duration + email_fields['exitStatus'] = workflow.exitStatus + email_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + email_fields['errorReport'] = (workflow.errorReport ?: 'None') + email_fields['commandLine'] = workflow.commandLine + email_fields['projectDir'] = workflow.projectDir + email_fields['summary'] = summary << misc_fields + + // On success try attach the multiqc report + def mqc_report = null + try { + if (workflow.success) { + mqc_report = multiqc_report.getVal() + if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { + if (mqc_report.size() > 1) { + log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" + } + mqc_report = mqc_report[0] } + } + } catch (all) { + if (multiqc_report) { + log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" + } } - // - // ANSII Colours used for terminal logging - // - public static Map logColours(Boolean monochrome_logs) { - Map colorcodes = [:] - - // Reset / Meta - colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" - colorcodes['bold'] = monochrome_logs ? '' : "\033[1m" - colorcodes['dim'] = monochrome_logs ? '' : "\033[2m" - colorcodes['underlined'] = monochrome_logs ? '' : "\033[4m" - colorcodes['blink'] = monochrome_logs ? '' : "\033[5m" - colorcodes['reverse'] = monochrome_logs ? '' : "\033[7m" - colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" - - // Regular Colors - colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" - colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" - colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" - colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" - colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" - colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" - colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" - colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" - - // Bold - colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" - colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" - colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" - colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" - colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" - colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" - colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" - colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" - - // Underline - colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" - colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" - colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" - colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" - colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" - colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" - colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" - colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" - - // High Intensity - colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" - colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" - colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" - colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" - colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" - colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" - colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" - colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" - - // Bold High Intensity - colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" - colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" - colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" - colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" - colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" - colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" - colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" - colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" - - return colorcodes + // Check if we are only sending emails on failure + def email_address = params.email + if (!params.email && params.email_on_fail && !workflow.success) { + email_address = params.email_on_fail } - // - // Does what is says on the tin - // - public static String dashedLine(monochrome_logs) { - Map colors = logColours(monochrome_logs) - return "-${colors.dim}----------------------------------------------------${colors.reset}-" + // Render the TXT template + def engine = new groovy.text.GStringTemplateEngine() + def tf = new File("$projectDir/assets/email_template.txt") + def txt_template = engine.createTemplate(tf).make(email_fields) + def email_txt = txt_template.toString() + + // Render the HTML template + def hf = new File("$projectDir/assets/email_template.html") + def html_template = engine.createTemplate(hf).make(email_fields) + def email_html = html_template.toString() + + // Render the sendmail template + def max_multiqc_email_size = params.max_multiqc_email_size as nextflow.util.MemoryUnit + def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] + def sf = new File("$projectDir/assets/sendmail_template.txt") + def sendmail_template = engine.createTemplate(sf).make(smail_fields) + def sendmail_html = sendmail_template.toString() + + // Send the HTML e-mail + Map colors = logColours(params.monochrome_logs) + if (email_address) { + try { + if (params.plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } + // Try to send HTML e-mail using sendmail + [ 'sendmail', '-t' ].execute() << sendmail_html + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" + } catch (all) { + // Catch failures and try with plaintext + def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] + if ( mqc_report.size() <= max_multiqc_email_size.toBytes() ) { + mail_cmd += [ '-A', mqc_report ] + } + mail_cmd.execute() << email_html + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" + } } - // - // nf-core logo - // - public static String logo(workflow, monochrome_logs) { - Map colors = logColours(monochrome_logs) - String.format( - """\n - ${dashedLine(monochrome_logs)} - ${colors.green},--.${colors.black}/${colors.green},-.${colors.reset} - ${colors.blue} ___ __ __ __ ___ ${colors.green}/,-._.--~\'${colors.reset} - ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} - ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} - ${colors.green}`._,._,\'${colors.reset} - ${colors.purple} ${workflow.manifest.name} v${workflow.manifest.version}${colors.reset} - ${dashedLine(monochrome_logs)} - """.stripIndent() - ) + // Write summary e-mail HTML to a file + def output_d = new File("${params.outdir}/pipeline_info/") + if (!output_d.exists()) { + output_d.mkdirs() + } + def output_hf = new File(output_d, "pipeline_report.html") + output_hf.withWriter { w -> w << email_html } + def output_tf = new File(output_d, "pipeline_report.txt") + output_tf.withWriter { w -> w << email_txt } + } + + // + // Print pipeline summary on completion + // + public static void summary(workflow, params, log) { + Map colors = logColours(params.monochrome_logs) + if (workflow.success) { + if (workflow.stats.ignoredCount == 0) { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" + } else { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" + } + } else { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" } + } + + // + // ANSII Colours used for terminal logging + // + public static Map logColours(Boolean monochrome_logs) { + Map colorcodes = [:] + + // Reset / Meta + colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" + colorcodes['bold'] = monochrome_logs ? '' : "\033[1m" + colorcodes['dim'] = monochrome_logs ? '' : "\033[2m" + colorcodes['underlined'] = monochrome_logs ? '' : "\033[4m" + colorcodes['blink'] = monochrome_logs ? '' : "\033[5m" + colorcodes['reverse'] = monochrome_logs ? '' : "\033[7m" + colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" + + // Regular Colors + colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" + colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" + colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" + colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" + colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" + colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" + colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" + colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" + + // Bold + colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" + colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" + colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" + colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" + colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" + colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" + colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" + colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" + + // Underline + colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" + colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" + colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" + colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" + colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" + colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" + colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" + colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" + + // High Intensity + colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" + colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" + colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" + colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" + colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" + colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" + colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" + colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" + + // Bold High Intensity + colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" + colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" + colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" + colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" + colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" + colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" + colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" + colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" + + return colorcodes + } + + // + // Does what is says on the tin + // + public static String dashedLine(monochrome_logs) { + Map colors = logColours(monochrome_logs) + return "-${colors.dim}----------------------------------------------------${colors.reset}-" + } + + // + // nf-core logo + // + public static String logo(workflow, monochrome_logs) { + Map colors = logColours(monochrome_logs) + String.format( + """\n + ${dashedLine(monochrome_logs)} + ${colors.green},--.${colors.black}/${colors.green},-.${colors.reset} + ${colors.blue} ___ __ __ __ ___ ${colors.green}/,-._.--~\'${colors.reset} + ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} + ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} + ${colors.green}`._,._,\'${colors.reset} + ${colors.purple} ${workflow.manifest.name} v${workflow.manifest.version}${colors.reset} + ${dashedLine(monochrome_logs)} + """.stripIndent() + ) + } } diff --git a/lib/Processes.groovy b/lib/Processes.groovy new file mode 100644 index 00000000..d41ba2a6 --- /dev/null +++ b/lib/Processes.groovy @@ -0,0 +1,100 @@ +import Constants + + +class Processes { + + public static set_processes(mode_str, log) { + def mode_enum + + try { + mode_enum = Constants.PipelineMode.valueOf(mode_str.toUpperCase()) + } catch(java.lang.IllegalArgumentException e) { + def workflows_str = Processes.get_workflow_names().join('\n - ') + log.error "\nERROR: recieved invalid pipeline mode: '${mode_str}'. Valid options are:\n - ${workflows_str}" + System.exit(1) + } + + def processes = [] + switch(mode_enum) { + case Constants.PipelineMode.FULL: + processes = Constants.Process.values() as List + break + case Constants.PipelineMode.MANUAL: + break + case Constants.PipelineMode.GRIDSS_PURPLE_LINX: + processes = [ + Constants.Process.AMBER, + Constants.Process.COBALT, + Constants.Process.GRIDSS, + Constants.Process.GRIPSS, + Constants.Process.LINX, + Constants.Process.PURPLE, + Constants.Process.SVPREP, + ] + break + case Constants.PipelineMode.CUPPA: + processes = [ + Constants.Process.AMBER, + Constants.Process.COBALT, + Constants.Process.COLLECTWGSMETRICS, + Constants.Process.CUPPA, + Constants.Process.GRIDSS, + Constants.Process.GRIPSS, + Constants.Process.ISOFOX, + Constants.Process.LINX, + Constants.Process.PURPLE, + Constants.Process.SVPREP, + Constants.Process.VIRUSINTERPRETER, + ] + break + default: + log.error "\nERROR: we should never have come here" + System.exit(1) + } + return processes + } + + public static get_process_list(process_str, log) { + return process_str + .tokenize(',') + .collect { name -> + try { + return Constants.Process.valueOf(name.toUpperCase()) + } catch(java.lang.IllegalArgumentException e) { + def processes_str = Processes.get_process_names().join('\n - ') + log.error "\nERROR: recieved invalid process: '${name}'. Valid options are:\n - ${processes_str}" + System.exit(1) + } + } + .unique() + } + + public static check_include_exclude_list(include_list, exclude_list, log) { + def processes_shared = [*include_list, *exclude_list] + .countBy { it } + .findAll { k, v -> v > 1 } + .keySet() + + if (processes_shared) { + def processes_shared_str = processes_shared.join('\n - ') + def message_base = 'the following processes was found in the include and the exclude list' + log.error "\nERROR: ${message_base}:\n - ${processes_shared_str}" + System.exit(1) + } + } + + public static get_workflow_names() { + Constants.PipelineMode + .values() + *.name() + *.toLowerCase() + } + + public static get_process_names() { + Constants.Process + .values() + *.name() + *.toLowerCase() + } + +} diff --git a/lib/Utils.groovy b/lib/Utils.groovy old mode 100644 new mode 100755 index 8d030f4e..d8dc27d2 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -6,42 +6,35 @@ import org.yaml.snakeyaml.Yaml class Utils { - // - // When running with -profile conda, warn if channels have not been set-up appropriately - // - public static void checkCondaChannels(log) { - Yaml parser = new Yaml() - def channels = [] - try { - def config = parser.load("conda config --show channels".execute().text) - channels = config.channels - } catch(NullPointerException | IOException e) { - log.warn "Could not verify conda channel configuration." - return - } + // + // When running with -profile conda, warn if channels have not been set-up appropriately + // + public static void checkCondaChannels(log) { + Yaml parser = new Yaml() + def channels = [] + try { + def config = parser.load("conda config --show channels".execute().text) + channels = config.channels + } catch(NullPointerException | IOException e) { + log.warn "Could not verify conda channel configuration." + return + } - // Check that all channels are present - // This channel list is ordered by required channel priority. - def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] - def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean + // Check that all channels are present + def required_channels = ['conda-forge', 'bioconda', 'defaults'] + def conda_check_failed = !required_channels.every { ch -> ch in channels } - // Check that they are in the right order - def channel_priority_violation = false - def n = required_channels_in_order.size() - for (int i = 0; i < n - 1; i++) { - channel_priority_violation |= !(channels.indexOf(required_channels_in_order[i]) < channels.indexOf(required_channels_in_order[i+1])) - } + // Check that they are in the right order + conda_check_failed |= !(channels.indexOf('conda-forge') < channels.indexOf('bioconda')) + conda_check_failed |= !(channels.indexOf('bioconda') < channels.indexOf('defaults')) - if (channels_missing | channel_priority_violation) { - log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " There is a problem with your Conda configuration!\n\n" + - " You will need to set-up the conda-forge and bioconda channels correctly.\n" + - " Please refer to https://bioconda.github.io/\n" + - " The observed channel order is \n" + - " ${channels}\n" + - " but the following channel order is required:\n" + - " ${required_channels_in_order}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - } + if (conda_check_failed) { + log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " There is a problem with your Conda configuration!\n\n" + + " You will need to set-up the conda-forge and bioconda channels correctly.\n" + + " Please refer to https://bioconda.github.io/user/install.html#set-up-channels\n" + + " NB: The order of the channels matters!\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" } + } } diff --git a/lib/WorkflowGridss.groovy b/lib/WorkflowGridss.groovy new file mode 100755 index 00000000..7f464bc8 --- /dev/null +++ b/lib/WorkflowGridss.groovy @@ -0,0 +1,104 @@ +// +// This file holds several functions specific to the subworkflows/gridss.nf in the umccr/hmftools pipeline +// + +class WorkflowGridss { + + public static get_inputs(ch) { + // channel (a): [val(meta_gridss), bam, bai, sv] + // channel (b): [val(meta_gridss), bam] + def sample_types = ['tumor', 'normal'] + def d = ch + .flatMap { meta -> + sample_types + .collect { sample_type -> + def key_sname = ['sample_name', sample_type] + def key_bam = ['bam_wgs', sample_type] + def key_sv = ['vcf_sv', sample_type] + if (! meta.containsKey(key_sname) && ! meta.containsKey(key_bam)) { + return [] + } + def meta_gridss = [ + id: meta.get(key_sname), + group_key: meta.id, + sample_type: sample_type, + subject_name: meta.subject_name, + ] + def v = [meta_gridss, meta.get(key_bam)] + def has_sv = meta.containsKey(key_sv) + if (has_sv) { + v = v + ["${meta.get(key_bam)}.bai", meta.get(key_sv)] + } + return [has_sv, v] + } + } + return d + } + + public static get_unique_input_files(ch) { + // channel (a): [val(meta_gridss), bam, bai, sv] + // channel (b): [val(meta_gridss), bam] + def d = ch + .map { [it[1..-1], it[0]] } + // NOTE(SW): number of grouped elements is unknown here but does not block since all inputs + // are derived directly from the samplesheet + .groupTuple() + .map { filepaths, meta_gridsss -> + def (sample_names, ids, sample_types, subject_names) = meta_gridsss + .collect { + [it.id, it.group_key, it.sample_type, it.subject_name] + } + .transpose() + + def sample_name = sample_names.unique(false) + def sample_type = sample_types.unique(false) + def subject_name = subject_names.unique(false) + assert sample_name.size() == 1 + assert sample_type.size() == 1 + assert subject_name.size() == 1 + + def meta_gridss_new = [ + id: ids.join('__'), + id_list: ids, + sample_name: sample_name[0], + sample_type: sample_type[0], + subject_name: subject_name[0], + ] + return [meta_gridss_new, *filepaths] + } + return d + } + + public static get_assemble_inputs(ch) { + // NOTE(SW): elements in the bams, preprocess_dirs, and labels are linked with via consistent ordering + // channel: [val(meta_gridss), [bams], [preprocess_dirs], [labels]] + def d = ch + .map { subject_name, other -> + def data = [:] + def ids = [] as Set + + // NOTE(SW): must determine whether input ordering is determininistic here + + other + .each { meta_gridss, bam, preprocess_dir -> + data.get([meta_gridss.sample_type, 'label'], []) << meta_gridss.sample_name + data.get([meta_gridss.sample_type, 'bam_wgs'], []) << bam + data.get([meta_gridss.sample_type, 'preprocess_dir'], []) << preprocess_dir + ids += meta_gridss.id_list + } + def meta_gridss_new = [ + id: ids.join('__'), + id_list: ids, + ] + + def sample_types = ['normal', 'tumor'] + return [ + meta_gridss_new, + sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'bam_wgs'], []) }, + sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'preprocess_dir'], []) }, + sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'label'], []) }, + ] + } + return d + } +} diff --git a/lib/WorkflowHmftools.groovy b/lib/WorkflowHmftools.groovy new file mode 100755 index 00000000..06b14306 --- /dev/null +++ b/lib/WorkflowHmftools.groovy @@ -0,0 +1,165 @@ +// +// This file holds several functions specific to the workflows/hmftools.nf in the umccr/hmftools pipeline +// + +import static groovy.io.FileType.FILES + +import nextflow.Channel +import nextflow.Nextflow + +class WorkflowHmftools { + + // + // Check and validate parameters + // + public static void initialise(params, workflow, log) { + // Download region file for collectwgsmetrics if in test mode + if (workflow.profile.contains('test')) { + def stage_dir = new File(workflow.workDir.toString(), 'stage/manual/') + def interval_file = new File(stage_dir, 'collectwgsmetrics.interval_list') + if (! interval_file.exists()) { + stage_dir.mkdirs() + interval_file.createNewFile() + interval_file << new URL (params.ref_data_wgsmetrics_intervals_url).getText() + } + params.ref_data_wgsmetrics_intervals_local = interval_file + } + } + + public static prepare_inputs(ch, stub_run, log) { + return ch + .splitCsv(header: true, strip: true, sep: '\t') + .map { [it.id, it] } + .groupTuple() + .map { id, inputs -> + def meta = [ + 'id': id, + ] + inputs.each { + assert meta.id == it.id + // Add subject name if not already present + if (meta.containsKey('subject_name')) { + assert meta.subject_name == it.subject_name + } else { + meta.subject_name = it.subject_name + } + + // Set sample name + def key = [] + if (it.sample_type == 'tumor') { + key = ['sample_name', 'tumor'] + } else if (it.sample_type == 'normal') { + key = ['sample_name', 'normal'] + } else { + assert false + } + if (meta.containsKey(key)) { + assert meta[key] == it.sample_name + } else { + meta[key] = it.sample_name + } + + // Add file + def key_file = [it.filetype, it.sample_type] + assert ! meta.containsKey(key_file) + meta[key_file] = it.filepath + + if (! stub_run) { + // For BAM file inputs, require co-located index + if (it.filepath.endsWith('.bam')) { + def bam_index_fp_str = "${it.filepath}.bai".toString() + def bam_index_fp = Nextflow.file(bam_index_fp_str) + if (! bam_index_fp.exists()) { + log.error "\nERROR: No index found for ${it.filepath}" + System.exit(1) + } + } + + // For GRIPSS SV VCFs, require co-located index + if (it.filetype.startsWith('gripss')) { + def vcf_index_fp = Nextflow.file("${it.filepath}.tbi".toString()) + if (! vcf_index_fp.exists()) { + log.error "\nERROR: No index found for ${it.filepath}" + System.exit(1) + } + } + } + + // NOTE(SW): CHECK_SAMPLESHEET curently enforces T/N; this may be relevant in the future + //// Set sample type: tumor_normal, tumor_only, normal_only + //if (meta.containsKey(['sample_name', 'tumor']) && meta.containsKey(['sample_name', 'normal'])) { + // meta.sample_type = 'tumor_normal' + //} else if (meta.containsKey(['sample_name', 'tumor'])) { + // meta.sample_type = 'tumor_only' + //} else if (meta.containsKey(['sample_name', 'normal'])) { + // meta.sample_type = 'normal_only' + //} else { + // assert false + //} + } + + // For PURPLE only runs, we must get normal sample name from inputs since there is no way to provide this + // in the samplesheet + if (meta.containsKey(['cobalt_dir', 'tumor']) && ! meta.containsKey(['sample_name', 'normal'])) { + // Discover files + def normal_ratio_fps = [] + new File(meta[['cobalt_dir', 'tumor']]) + .eachFileMatch(groovy.io.FileType.FILES, ~/.+\.cobalt\.gc\.median\.tsv/, { normal_ratio_fps << it }) + // Select normal sample file + def normal_ratio_fp = normal_ratio_fps + .findAll { ! it.getName().contains(meta[['sample_name', 'tumor']]) } + assert normal_ratio_fp.size() == 1 + // Set normal sample name + def m = (normal_ratio_fp =~ /.+\/(.+)\.cobalt\.gc\.median\.tsv/) + meta[['sample_name', 'normal']] = m[0][1] + } + + return meta + } + } + + public static group_by_meta(Map named_args, ... channels) { + def r = channels + // Set position; required to use non-blocking .mix operator + // NOTE(SW): operating on native list object containing channels + def i = 0 + r = r + .collect { ch -> + def ii = i + def d = ch.map { data -> + def meta = data[0] + def values = data[1..-1] + return [meta, [position: ii, values: values]] + } + i++ + return d + } + + r = Channel.empty().mix(*r) + r = r + .groupTuple(size: channels.size()) + .map { data -> + def meta = data[0] + def values_map = data[1] + + def values_list = values_map + .sort { it.position } + .collect { it.values } + return [meta, *values_list] + } + + if (named_args.get('flatten', true)) { + r = r.map { it.flatten() } + } + return r + } + + // NOTE(SW): function signature required to catch where no named arguments are passed + public static group_by_meta(... channels) { + return group_by_meta([:], *channels) + } + + public static get_input(ch, key) { + return ch.map { meta -> [meta, meta.getAt(key)] } + } +} diff --git a/lib/WorkflowLilac.groovy b/lib/WorkflowLilac.groovy new file mode 100755 index 00000000..885f8787 --- /dev/null +++ b/lib/WorkflowLilac.groovy @@ -0,0 +1,80 @@ +// +// This file holds several functions specific to the subworkflows/lilac.nf in the umccr/hmftools pipeline +// + +class WorkflowLilac { + + public static get_slice_inputs(ch, hla_bed) { + // channel: [val(meta_lilac), bam, bai, bed] + def d = ch + .flatMap { meta, tbam, nbam, tbai, nbai -> + def sample_types = ['tumor': [tbam, tbai], 'normal': [nbam, nbai]] + sample_types + .keySet() + .collect { sample_type -> + def fps = sample_types[sample_type] + def sample_name = meta.get(['sample_name', sample_type]) + def meta_lilac = [ + id: sample_name, + sample_type: sample_type, + meta_full: meta, + ] + return [meta_lilac, *fps, hla_bed] + } + } + return d + } + + public static get_unique_input_files(ch) { + // channel: [val(meta_lilac), bam, bai, bed] + def d = ch + .map { [it[1..-1], it[0]] } + .groupTuple() + .map { filepaths, meta_lilacs -> + def (meta_fulls, sample_types) = meta_lilacs + .collect { + [it.meta_full, it.sample_type] + } + .transpose() + + def sample_type = sample_types.unique(false) + assert sample_type.size() == 1 + + def id = meta_fulls.collect { it.id }.join('__') + def meta_lilac_new = [ + id: "${id}_${sample_type[0]}", + metas_full: meta_fulls, + sample_type: sample_type[0], + ] + return [meta_lilac_new, *filepaths] + } + return d + } + + public static sort_slices(ch) { + // Collect T/N pairs into single channel element + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] + def d = ch + .flatMap{ data -> + def meta_lilac = data[0] + def fps = data[1..-1] + meta_lilac.metas_full.collect { meta -> [meta.id, meta, [meta_lilac.sample_type, *fps]] } + } + .groupTuple(size: 2) + .map { id, meta, other -> + def data = [:] + other.each { sample_type, bam, bai -> + data[[sample_type, 'bam']] = bam + data[[sample_type, 'bai']] = bai + } + [ + meta[0], + data.get(['tumor', 'bam']), + data.get(['normal', 'bam']), + data.get(['tumor', 'bai']), + data.get(['normal', 'bai']), + ] + } + return d + } +} diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 07f95372..957fdc84 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -1,93 +1,97 @@ // -// This file holds several functions specific to the main.nf workflow in the nf-core/oncoanalyser pipeline +// This file holds several functions specific to the main.nf workflow in the umccr/hmftools pipeline // class WorkflowMain { - // - // Citation string for pipeline - // - public static String citation(workflow) { - return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + - // TODO nf-core: Add Zenodo DOI for pipeline after first release - //"* The pipeline\n" + - //" https://doi.org/10.5281/zenodo.XXXXXXX\n\n" + - "* The nf-core framework\n" + - " https://doi.org/10.1038/s41587-020-0439-x\n\n" + - "* Software dependencies\n" + - " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" - } + // + // Citation string for pipeline + // + public static String citation(workflow) { + return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + + // TODO nf-core: Add Zenodo DOI for pipeline after first release + //"* The pipeline\n" + + //" https://doi.org/10.5281/zenodo.XXXXXXX\n\n" + + "* The nf-core framework\n" + + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + + "* Software dependencies\n" + + " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" + } + + // TODO(SW): update this + // + // Print help to screen if required + // + public static String help(workflow, params, log) { + def command = "nextflow run main.nf --input samplesheet.csv --outdir output/ -profile docker" + def help_string = '' + help_string += NfcoreTemplate.logo(workflow, params.monochrome_logs) + help_string += NfcoreSchema.paramsHelp(workflow, params, command) + help_string += '\n' + citation(workflow) + '\n' + help_string += NfcoreTemplate.dashedLine(params.monochrome_logs) + return help_string + } + + // + // Print parameter summary log to screen + // + public static String paramsSummaryLog(workflow, params, log) { + def summary_log = '' + summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) + summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) + summary_log += '\n' + citation(workflow) + '\n' + summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) + return summary_log + } - // + // + // Validate parameters and print summary to screen + // + public static void initialise(workflow, params, log) { // Print help to screen if required - // - public static String help(workflow, params, log) { - def command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh37 -profile docker" - def help_string = '' - help_string += NfcoreTemplate.logo(workflow, params.monochrome_logs) - help_string += NfcoreSchema.paramsHelp(workflow, params, command) - help_string += '\n' + citation(workflow) + '\n' - help_string += NfcoreTemplate.dashedLine(params.monochrome_logs) - return help_string + if (params.help) { + log.info help(workflow, params, log) + System.exit(0) } - // - // Print parameter summary log to screen - // - public static String paramsSummaryLog(workflow, params, log) { - def summary_log = '' - summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) - summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) - summary_log += '\n' + citation(workflow) + '\n' - summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) - return summary_log + // Validate workflow parameters via the JSON schema + if (params.validate_params) { + NfcoreSchema.validateParameters(workflow, params, log) } - // - // Validate parameters and print summary to screen - // - public static void initialise(workflow, params, log) { - // Print help to screen if required - if (params.help) { - log.info help(workflow, params, log) - System.exit(0) - } - - // Validate workflow parameters via the JSON schema - if (params.validate_params) { - NfcoreSchema.validateParameters(workflow, params, log) - } - - // Print parameter summary log to screen - - log.info paramsSummaryLog(workflow, params, log) + // Print parameter summary log to screen + log.info paramsSummaryLog(workflow, params, log) - // Check that a -profile or Nextflow config has been provided to run the pipeline - NfcoreTemplate.checkConfigProvided(workflow, log) + // Check that a -profile or Nextflow config has been provided to run the pipeline + NfcoreTemplate.checkConfigProvided(workflow, log) - // Check that conda channels are set-up correctly - if (params.enable_conda) { - Utils.checkCondaChannels(log) - } + // Check that conda channels are set-up correctly + if (params.enable_conda) { + Utils.checkCondaChannels(log) + } - // Check AWS batch settings - NfcoreTemplate.awsBatch(workflow, params) + // TODO(SW): update this + // Check AWS batch settings + NfcoreTemplate.awsBatch(workflow, params) - // Check input has been provided - if (!params.input) { - log.error "Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'" - System.exit(1) - } + // TODO(SW): update this + // Check input has been provided + if (!params.input) { + log.error "Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'" + System.exit(1) } - // - // 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)) { - return params.genomes[ params.genome ][ attribute ] - } - } - return null + } + + // + // Get attribute from genome config file e.g. fasta + // + public static String getGenomeAttribute(params, attribute) { + def val = '' + if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { + if (params.genomes[ params.genome ].containsKey(attribute)) { + val = params.genomes[ params.genome ][ attribute ] + } } + return val + } } diff --git a/main.nf b/main.nf old mode 100644 new mode 100755 index 5fa2e2fb..419c94f2 --- a/main.nf +++ b/main.nf @@ -1,12 +1,11 @@ #!/usr/bin/env nextflow /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - nf-core/oncoanalyser + umccr/hmftools ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Github : https://github.com/nf-core/oncoanalyser - - Website: https://nf-co.re/oncoanalyser - Slack : https://nfcore.slack.com/channels/oncoanalyser + Github : https://github.com/umccr/hmftools + Website: https://nf-co.re/hmftools + Slack : https://nfcore.slack.com/channels/hmftools ---------------------------------------------------------------------------------------- */ @@ -14,15 +13,7 @@ nextflow.enable.dsl = 2 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - GENOME PARAMETER VALUES -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -params.fasta = WorkflowMain.getGenomeAttribute(params, 'fasta') - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - VALIDATE & PRINT PARAMETER SUMMARY + VALIDATE & PRINT PARAMETER SUMMARY ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -30,22 +21,22 @@ WorkflowMain.initialise(workflow, params, log) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - NAMED WORKFLOW FOR PIPELINE + NAMED WORKFLOW FOR PIPELINE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { ONCOANALYSER } from './workflows/oncoanalyser' +include { HMFTOOLS } from './workflows/hmftools' // -// WORKFLOW: Run main nf-core/oncoanalyser analysis pipeline +// WORKFLOW: Run main umccr/hmftools analysis pipeline // -workflow NFCORE_ONCOANALYSER { - ONCOANALYSER () +workflow NFCORE_HMFTOOLS { + HMFTOOLS() } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - RUN ALL WORKFLOWS + RUN ALL WORKFLOWS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -54,11 +45,11 @@ workflow NFCORE_ONCOANALYSER { // See: https://github.com/nf-core/rnaseq/issues/619 // workflow { - NFCORE_ONCOANALYSER () + NFCORE_HMFTOOLS() } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - THE END + THE END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/modules.json b/modules.json index 4ce9f998..7a27a4dd 100644 --- a/modules.json +++ b/modules.json @@ -1,23 +1,13 @@ { - "name": "nf-core/oncoanalyser", - "homePage": "https://github.com/nf-core/oncoanalyser", + "name": "umccr/hmftools", + "homePage": "https://github.com/umccr/hmftools", "repos": { - "https://github.com/nf-core/modules.git": { - "modules": { - "nf-core": { - "custom/dumpsoftwareversions": { - "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" - }, - "fastqc": { - "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" - }, - "multiqc": { - "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" - } - } + "nf-core/modules": { + "custom/dumpsoftwareversions": { + "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" + }, + "picard/collectwgsmetrics": { + "git_sha": "ac1c6ad7104c7863842a322a8cf74f4fee1d20b4" } } } diff --git a/modules/local/amber/Dockerfile b/modules/local/amber/Dockerfile new file mode 100644 index 00000000..45967ed2 --- /dev/null +++ b/modules/local/amber/Dockerfile @@ -0,0 +1,19 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'hmftools-amber==3.9' \ + r-dplyr && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf new file mode 100644 index 00000000..734b3ff7 --- /dev/null +++ b/modules/local/amber/main.nf @@ -0,0 +1,46 @@ +process AMBER { + //conda (params.enable_conda ? "bioconda::hmftools-amber=3.9" : null) + container 'docker.io/scwatts/amber:3.9--3' + + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) + val ref_genome_ver + path loci + + output: + tuple val(meta), path('amber/'), emit: amber_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -tumor "${meta.get(['sample_name', 'tumor'])}" \\ + -tumor_bam "${tumor_bam}" \\ + -reference "${meta.get(['sample_name', 'normal'])}" \\ + -reference_bam "${normal_bam}" \\ + -ref_genome_version ${ref_genome_ver} \\ + -output_dir amber/ \\ + -threads "${task.cpus}" \\ + -loci "${loci}" + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + amber: 3.9 + END_VERSIONS + """ + + stub: + """ + mkdir -p amber/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/amber/meta.yml b/modules/local/amber/meta.yml new file mode 100644 index 00000000..08075526 --- /dev/null +++ b/modules/local/amber/meta.yml @@ -0,0 +1,58 @@ +name: "AMBER" +description: Generate a tumor BAF file for PURPLE copy number fit +keywords: + - amber + - baf + - cnv +tools: + - "AMBER": + description: "Generate a tumor BAF file for PURPLE copy number fit." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/amber" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/amber" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/amber" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + - tumor_bam: + type: file + description: Tumor BAM file + pattern: "*.{bam}" + - normal_bam: + type: file + description: Normal BAM file + pattern: "*.{bam}" + - tumor_bai: + type: file + description: Tumor BAI file + pattern: "*.{bai}" + - normal_bai: + type: file + description: Normal BAI file + pattern: "*.{bai}" + - loci: + type: file + description: AMBER loci file + pattern: "*.{vcf.gz}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + - amber_dir: + type: directory + description: AMBER output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/check_samplesheet/main.nf b/modules/local/check_samplesheet/main.nf new file mode 100644 index 00000000..1fb7c5d2 --- /dev/null +++ b/modules/local/check_samplesheet/main.nf @@ -0,0 +1,33 @@ +process CHECK_SAMPLESHEET { + conda (params.enable_conda ? "conda-forge::python=3.9.5" : null) + container 'quay.io/biocontainers/python:3.9--1' + + input: + path samplesheet + val mode + + output: + path samplesheet + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + check_samplesheet.py \\ + --input_fp "${samplesheet}" \\ + --mode "${mode}" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + """ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/cobalt/Dockerfile b/modules/local/cobalt/Dockerfile new file mode 100644 index 00000000..867f4e7e --- /dev/null +++ b/modules/local/cobalt/Dockerfile @@ -0,0 +1,19 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'hmftools-cobalt==1.13' \ + r-dplyr && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf new file mode 100644 index 00000000..487ebf9b --- /dev/null +++ b/modules/local/cobalt/main.nf @@ -0,0 +1,44 @@ +process COBALT { + //conda (params.enable_conda ? "bioconda::hmftools-cobalt=1.13" : null) + container 'docker.io/scwatts/cobalt:1.13--1' + + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) + path gc_profile + + output: + tuple val(meta), path('cobalt/'), emit: cobalt_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -tumor "${meta.get(['sample_name', 'tumor'])}" \\ + -tumor_bam "${tumor_bam}" \\ + -reference "${meta.get(['sample_name', 'normal'])}" \\ + -reference_bam "${normal_bam}" \\ + -output_dir cobalt/ \\ + -threads "${task.cpus}" \\ + -gc_profile "${gc_profile}" + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cobalt: 1.13 + END_VERSIONS + """ + + stub: + """ + mkdir -p cobalt/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/cobalt/meta.yml b/modules/local/cobalt/meta.yml new file mode 100644 index 00000000..fc577f07 --- /dev/null +++ b/modules/local/cobalt/meta.yml @@ -0,0 +1,58 @@ +name: "COBALT" +description: Count bam lines determines the read depth ratios of the supplied tumor and reference genomes +keywords: + - cobalt + - read depth ratios + - cnv +tools: + - "COBALT": + description: "Count bam lines determines the read depth ratios of the supplied tumor and reference genomes." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/cobalt" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/cobalt" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/cobalt" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + - tumor_bam: + type: file + description: Tumor BAM file + pattern: "*.{bam}" + - normal_bam: + type: file + description: Normal BAM file + pattern: "*.{bam}" + - tumor_bai: + type: file + description: Tumor BAI file + pattern: "*.{bai}" + - normal_bai: + type: file + description: Normal BAI file + pattern: "*.{bai}" + - gc_profile: + type: file + description: COBALT GC Profile file + pattern: "*.{cnp}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + - cobalt: + type: directory + description: COBALT output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/cuppa/Dockerfile b/modules/local/cuppa/Dockerfile new file mode 100644 index 00000000..b697f5c9 --- /dev/null +++ b/modules/local/cuppa/Dockerfile @@ -0,0 +1,36 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/cuppa/ && \ + wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.7/cuppa_v1.7.jar' + +ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.7/cuppa/src/main/resources/cuppa-chart +ARG DIR_BASE=/opt/cuppa/chart +RUN \ + mkdir -p ${DIR_BASE}/ && \ + wget -P ${DIR_BASE}/ ${URL_BASE}/requirements.txt && \ + wget -P ${DIR_BASE}/ ${URL_BASE}/cuppa-chart.py && \ + wget -P ${DIR_BASE}/main/ ${URL_BASE}/main/create_chart.py && \ + wget -P ${DIR_BASE}/main/ ${URL_BASE}/main/prepare_data.py + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'matplotlib >=3.3,<4' \ + 'numpy >=1.19,<2' \ + 'openjdk >=8' \ + 'pandas >=1.1,<2' \ + 'scipy >=1,<2' \ + 'seaborn >=0.11,<1' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf new file mode 100644 index 00000000..76fc843f --- /dev/null +++ b/modules/local/cuppa/classifier/main.nf @@ -0,0 +1,46 @@ +process CUPPA_CLASSIFIER { + container 'docker.io/scwatts/cuppa:1.7--0' + + input: + tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) + path reference_data + + 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 ?: '' + + """ + # Symlink input files into a single directory + mkdir sample_data/ + input_dirs="${isofox_dir} ${purple_dir} ${linx_dir} ${virusinterpreter_dir}" + find -L \${input_dirs} -maxdepth 1 -type f -exec ln -s ../{} sample_data/ \\; + + java \\ + -Xmx${task.memory.giga}g \\ + -jar ${task.ext.jarPath} \\ + -categories ALL \\ + -ref_data_dir ${reference_data} \\ + -sample_data ${meta.get(['sample_name', 'tumor'])} \\ + -sample_data_dir sample_data/ \\ + -output_dir ./ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cuppa: 1.7 + END_VERSIONS + """ + + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}.cup.data.csv + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} + diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf new file mode 100644 index 00000000..0aac2a4d --- /dev/null +++ b/modules/local/cuppa/visualiser/main.nf @@ -0,0 +1,38 @@ +process CUPPA_VISUALISER { + container 'docker.io/scwatts/cuppa:1.7--0' + + input: + tuple val(meta), path(cuppa_csv) + + output: + path '*png' + path '*txt' + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + python ${task.ext.pythonPath} \\ + -sample ${meta.get(['sample_name', 'tumor'])} \\ + -sample_data ${cuppa_csv} \\ + -output_dir ./ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cuppa: 1.7 + END_VERSIONS + """ + + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}.cuppa.chart.png + touch ${meta.get(['sample_name', 'tumor'])}.cuppa.conclusion.txt + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} + diff --git a/modules/local/custom/lilac_extract_and_index_contig/Dockerfile b/modules/local/custom/lilac_extract_and_index_contig/Dockerfile new file mode 100644 index 00000000..d356441d --- /dev/null +++ b/modules/local/custom/lilac_extract_and_index_contig/Dockerfile @@ -0,0 +1,19 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + bwa \ + samtools && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf new file mode 100644 index 00000000..74debc9a --- /dev/null +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -0,0 +1,40 @@ +process EXTRACT_AND_INDEX_CONTIG { + //conda (params.enable_conda ? "bioconda::null" : null) + container 'docker.io/scwatts/custom-extract_and_index_contig:0.0.1--3' + + input: + val contig_name + path genome_fa + path genome_fai + + output: + path "*extracted.fa" , emit: contig + path "*extracted.fa.*", emit: bwa_indices + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + samtools faidx \\ + -o ${contig_name}_extracted.fa \\ + ${genome_fa} \\ + ${contig_name} + bwa index ${contig_name}_extracted.fa + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + """ + touch ${contig_name}_extracted.fa ${contig_name}_extracted.fa.amb + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/custom/lilac_extract_and_index_contig/meta.yml b/modules/local/custom/lilac_extract_and_index_contig/meta.yml new file mode 100644 index 00000000..1125a44f --- /dev/null +++ b/modules/local/custom/lilac_extract_and_index_contig/meta.yml @@ -0,0 +1,40 @@ +name: "lilac_extract_and_index_contig" +description: Extract a contig FASTA record from a reference genome and index with BWA +keywords: + - reference + - contig + - extract +tools: + - custom: + description: "Extract and index contig" + homepage: "https://github.com/umccr/hmftools" + documentation: "https://github.com/umccr/hmftools" + doi: "" + licence: "['GPL v3']" + +input: + - contig_name: + type: string + description: Contig name + - ref_data_genome_dir: + type: directory + description: Directory containing reference genome + - ref_data_genome_fn: + type: string + description: Reference genome filename + +output: + - contig: + type: file + description: FASTA containing extracted contig + pattern: "*.{fa}" + - bwa_indices: + type: list + description: BWA indices for extracted contig + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/custom/lilac_realign_reads_lilac/Dockerfile b/modules/local/custom/lilac_realign_reads_lilac/Dockerfile new file mode 100644 index 00000000..ff6213ff --- /dev/null +++ b/modules/local/custom/lilac_realign_reads_lilac/Dockerfile @@ -0,0 +1,20 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + bwa \ + sambamba \ + samtools && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf new file mode 100644 index 00000000..6ea93f9c --- /dev/null +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -0,0 +1,50 @@ +process REALIGN_READS { + //conda (params.enable_conda ? "bioconda::hmftools-lilac=1.2" : null) + container 'docker.io/scwatts/custom-realign_reads_lilac:0.0.1--3' + + input: + tuple val(meta), path(bam), path(bai) + path reference + path reference_indices + + output: + tuple val(meta), path("*realigned.bam"), path("*realigned.bam.bai"), emit: bam + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + sambamba sort -n ${bam} -o ${meta.id}_sorted.bam + samtools fastq -@${task.threads} ${meta.id}_sorted.bam \\ + -1 ${meta.id}_R1.fastq.gz \\ + -2 ${meta.id}_R2.fastq.gz \\ + -0 ${meta.id}_other.fastq.gz \\ + -s ${meta.id}_singleton.fastq.gz; + + bwa mem \\ + -t${task.cpus} \\ + -Y \\ + ${reference} \\ + ${meta.id}_R1.fastq.gz \\ + ${meta.id}_R2.fastq.gz | \\ + samtools sort -T tmp -o ${meta.id}_realigned.bam + samtools index ${meta.id}_realigned.bam + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + sambamba: \$(sambamba --version 2>&1 | sed -n '/sambamba/ s/^sambamba \\(.\\+\\)/\\1/p' | head -n1) + END_VERSIONS + """ + + stub: + """ + touch ${meta.id}_realigned.bam ${meta.id}_realigned.bam.bai + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/custom/lilac_realign_reads_lilac/meta.yml b/modules/local/custom/lilac_realign_reads_lilac/meta.yml new file mode 100644 index 00000000..524152b5 --- /dev/null +++ b/modules/local/custom/lilac_realign_reads_lilac/meta.yml @@ -0,0 +1,57 @@ +name: "lilac_realign_reads_lilac" +description: Realign reads for LILAC +keywords: + - alignment + - lilac + - preprocessing +tools: + - custom: + description: "Realign reads for LILAC" + homepage: "https://github.com/umccr/hmftools" + documentation: "https://github.com/umccr/hmftools" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. ['id': 'sample_name'] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - bai: + type: file + description: BAI file + pattern: "*.{bai}" + - reference: + type: path + description: Reference FASTA file + pattern: "*.{fa}" + - reference_indices: + type: list + description: BWA indices for reference FASTA file + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. ['id': 'sample_name'] + - bam: + type: list + description: BAM file + pattern: "*.{bam}" + - bai: + type: list + description: BAI file + pattern: "*.{bai}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf new file mode 100644 index 00000000..7962588f --- /dev/null +++ b/modules/local/custom/lilac_slice/main.nf @@ -0,0 +1,40 @@ +process SLICE { + //conda (params.enable_conda ? "bioconda::samtools:1.15.1" : null) + container 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' + + input: + tuple val(meta), path(bam), path(bai), path(bed) + + output: + tuple val(meta), path("*sliced.bam"), path("*sliced.bam.bai"), emit: bam + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + samtools view \\ + ${args} \\ + -L "${bed}" \\ + -@${task.cpus} \\ + -Obam \\ + ${bam} | \\ + samtools sort -T tmp -o "${bam.simpleName}.sliced.bam" + + samtools index "${bam.simpleName}.sliced.bam" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + """ + touch ${bam.simpleName}.sliced.bam ${bam.simpleName}.sliced.bam.bai + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/custom/lilac_slice/meta.yml b/modules/local/custom/lilac_slice/meta.yml new file mode 100644 index 00000000..f1c5076c --- /dev/null +++ b/modules/local/custom/lilac_slice/meta.yml @@ -0,0 +1,49 @@ +name: "lilac_slice" +description: Slice BAM for LILAC +keywords: + - samtools + - slice +tools: + - custom: + description: "Slice BAM for LILAC" + homepage: "https://github.com/umccr/hmftools" + documentation: "https://github.com/umccr/hmftools" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - bai: + type: file + description: BAI file + pattern: "*.{bai}" + - bed: + type: file + description: Optional slice regions BED file + pattern: "*.{bed}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bam: + type: file + description: Sliced BAM file + pattern: "*.{bam}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/gpgr/linx_report/main.nf b/modules/local/gpgr/linx_report/main.nf new file mode 100644 index 00000000..3ee5ec24 --- /dev/null +++ b/modules/local/gpgr/linx_report/main.nf @@ -0,0 +1,38 @@ +process LINX_REPORT { + //conda (params.enable_conda ? "umccr::r-gpgr==1.4.1" : null) + container 'ghcr.io/umccr/gpgr:1.4.1' + + input: + tuple val(meta), path(linx_annotation), path(linx_visualiser) + + output: + tuple val(meta), path('*_linx.html'), emit: html + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + gpgr.R linx \\ + ${args} \\ + --sample ${meta.get(['sample_name', 'tumor'])} \\ + --plot ${linx_visualiser}/ \\ + --table ${linx_annotation}/ \\ + --out ${meta.get(['sample_name', 'tumor'])}_linx.html; + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + R: \$(R --version | head -n1 | sed 's/^R version \\([0-9.]\\+\\).\\+/\\1/') + gpgr: \$(gpgr.R --version | cut -f2 -d' ') + END_VERSIONS + """ + + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}_linx.html + echo -e '${task.process}:\n stub: noversions\n' > versions.yml + """ +} diff --git a/modules/local/gpgr/linx_report/meta.yml b/modules/local/gpgr/linx_report/meta.yml new file mode 100644 index 00000000..16e4dabb --- /dev/null +++ b/modules/local/gpgr/linx_report/meta.yml @@ -0,0 +1,46 @@ +name: "LINX_REPORT" +description: Read and process output files from somatic LINX +keywords: + - gpgr + - linx report + - sv + - cnv +tools: + - "gpgr": + description: "Read and process output files from LINX." + homepage: "https://github.com/umccr/gpgr" + documentation: "https://github.com/umccr/gpgr" + tool_dev_url: "https://github.com/umccr/gpgr" + doi: "" + licence: "['MIT']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor'] + - linx_annotation: + type: directory + description: Somatic LINX annotation output directory + - linx_visualiser: + type: directory + description: Somatic LINX visualiser output directory + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor'] + - html: + type: file + description: gpgr LINX report file + pattern: "*.{html}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/gridss/Dockerfile b/modules/local/gridss/Dockerfile new file mode 100644 index 00000000..b270f82c --- /dev/null +++ b/modules/local/gridss/Dockerfile @@ -0,0 +1,28 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'gridss==2.13.2' && \ + micromamba clean --all --yes + +RUN \ + sed -i \ + -e '209s/grep samtools/head -n1 | grep samtools/' \ + /opt/conda/share/gridss-2.13.2-1/gridss_extract_overlapping_fragments + +RUN \ + ln -sf \ + /opt/conda/pkgs/gridss-2.13.2-h20b1175_1/share/gridss-2.13.2-1/gridss \ + /opt/conda/bin/gridss + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/gridss/assemble/main.nf b/modules/local/gridss/assemble/main.nf new file mode 100644 index 00000000..a555963c --- /dev/null +++ b/modules/local/gridss/assemble/main.nf @@ -0,0 +1,88 @@ +process ASSEMBLE { + //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) + container 'docker.io/scwatts/gridss:2.13.2--3' + + input: + tuple val(meta), path(bams), path(preprocess_dirs), val(labels) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + path blacklist + + output: + tuple val(meta), path('gridss_assemble/'), emit: assemble_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + def output_dirname = 'gridss_assemble' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = bams_list.join(' ') + + """ + # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation + # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + shadow_input_directory() { + src=\${1} + dst="${output_dirname}/work/\${src##*/}" + for filepath_src in \$(find -L \${src} ! -type d); do + # Get destination location for symlink + filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) + filepath_dst=\${dst%/}/\${filepath_src_rel} + # Create directory for symlink + mkdir -p \${filepath_dst%/*}; + # Get path for symlink source file, then create it + # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only + # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers + symlinkpath=\$(realpath \${filepath_src}) + ln -s \${symlinkpath} \${filepath_dst}; + done + if [[ -L "\${src##*/}" ]]; then + rm "\${src}" + fi + } + for preprocess_dir in ${preprocess_dirs}; do + shadow_input_directory \${preprocess_dir}; + done + + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + # Run + gridss \\ + ${args} \\ + --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ + --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ + --jar "${task.ext.jarPath}" \\ + --steps assemble \\ + --labels "${labels_arg}" \\ + --reference "${genome_fa}" \\ + --blacklist "${blacklist}" \\ + --workingdir "${output_dirname}/work" \\ + --assembly "${output_dirname}/sv_assemblies.bam" \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + ${bams_arg} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_assemble/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/gridss/assemble/meta.yml b/modules/local/gridss/assemble/meta.yml new file mode 100644 index 00000000..0d000fb4 --- /dev/null +++ b/modules/local/gridss/assemble/meta.yml @@ -0,0 +1,78 @@ +name: "ASSEMBLE" +description: Assemble SVs with GRIDSS +keywords: + - gridss + - assemble + - sv +tools: + - "gridss": + description: "GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements." + homepage: "https://github.com/PapenfussLab/gridss" + documentation: "https://github.com/PapenfussLab/gridss" + tool_dev_url: "https://github.com/PapenfussLab/gridss" + doi: "" + licence: "['GPL >=3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bams: + type: list + description: List of BAM files + pattern: "*.{bam}" + - preprocess_dirs: + type: list + description: List of GRIDSS preprocess output directories + - labels: + type: list + description: List of labels corresponding to BAMs and GRIDSS preprocess output directories + - gridss_config: + type: file + description: Optional GRIDSS configuration file + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_bwa_index_dir: + type: directory + description: Directory containing reference genome assembly BWA index + - genome_bwa_index_image: + type: file + description: Reference genome assembly BWA index img file + pattern: "*.{img}" + - genome_gridss_index: + type: file + description: Reference genome assembly GRIDSS index file + pattern: "*.{gridsscache}" + - blacklist: + type: file + description: GRIDSS blacklist file + pattern: "*.{bed.gz}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - assembly_dir: + type: directory + description: GRIDSS assemble output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/gridss/call/main.nf b/modules/local/gridss/call/main.nf new file mode 100644 index 00000000..628c545f --- /dev/null +++ b/modules/local/gridss/call/main.nf @@ -0,0 +1,93 @@ +process CALL { + //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) + container 'docker.io/scwatts/gridss:2.13.2--3' + + input: + tuple val(meta), path(bams), path(assemble_dir), val(labels) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + path blacklist + + output: + tuple val(meta), path('gridss_call/sv_vcf.vcf.gz'), emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + def output_dirname = 'gridss_call' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = bams_list.join(' ') + + """ + # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation + # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + shadow_input_directory() { + src=\${1} + dst="${output_dirname}/" + for filepath_src in \$(find -L \${src} ! -type d); do + # Get destination location for symlink + filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) + filepath_dst=\${dst%/}/\${filepath_src_rel} + # Create directory for symlink + mkdir -p \${filepath_dst%/*}; + # Get path for symlink source file, then create it + # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only + # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers + symlinkpath=\$(realpath \${filepath_src}) + ln -s \${symlinkpath} \${filepath_dst}; + done + if [[ -L "\${src##*/}" ]]; then + rm "\${src}" + fi + } + shadow_input_directory ${assemble_dir} + + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + # Run + gridss \\ + ${args} \\ + --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ + --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ + --jar "${task.ext.jarPath}" \\ + --steps call \\ + --labels "${labels_arg}" \\ + --reference "${genome_fa}" \\ + --blacklist "${blacklist}" \\ + --workingdir "${output_dirname}/work/" \\ + --assembly "${output_dirname}/sv_assemblies.bam" \\ + --output "${output_dirname}/sv_vcf.vcf.gz" \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + ${bams_arg} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_call/ + cat < gridss_call/sv_vcf.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/gridss/call/meta.yml b/modules/local/gridss/call/meta.yml new file mode 100644 index 00000000..18e35602 --- /dev/null +++ b/modules/local/gridss/call/meta.yml @@ -0,0 +1,79 @@ +name: "CALL" +description: Call SVs with GRIDSS +keywords: + - gridss + - variant calling + - sv +tools: + - "gridss": + description: "GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements." + homepage: "https://github.com/PapenfussLab/gridss" + documentation: "https://github.com/PapenfussLab/gridss" + tool_dev_url: "https://github.com/PapenfussLab/gridss" + doi: "" + licence: "['GPL >=3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bams: + type: list + description: List of BAM files + pattern: "*.{bam}" + - assemble_dir: + type: directory + description: GRIDSS assemble output directory + - labels: + type: list + description: List of labels corresponding to BAMs and GRIDSS preprocess output directories + - gridss_config: + type: file + description: Optional GRIDSS configuration file + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_bwa_index_dir: + type: directory + description: Directory containing reference genome assembly BWA index + - genome_bwa_index_image: + type: file + description: Reference genome assembly BWA index img file + pattern: "*.{img}" + - genome_gridss_index: + type: file + description: Reference genome assembly GRIDSS index file + pattern: "*.{gridsscache}" + - blacklist: + type: file + description: GRIDSS blacklist file + pattern: "*.{bed.gz}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - vcf: + type: file + description: GRIDSS SV VCF file + pattern: "*.{vcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/gridss/preprocess/main.nf b/modules/local/gridss/preprocess/main.nf new file mode 100644 index 00000000..fe5ebcc4 --- /dev/null +++ b/modules/local/gridss/preprocess/main.nf @@ -0,0 +1,52 @@ +process PREPROCESS { + //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) + container 'docker.io/scwatts/gridss:2.13.2--3' + + input: + tuple val(meta), path(bam) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + + output: + tuple val(meta), path("gridss_preprocess/${bam.name}.gridss.working/"), emit: preprocess_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + + """ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + gridss \\ + ${args} \\ + --jvmheap "${task.memory.giga}g" \\ + --jar "${task.ext.jarPath}" \\ + --steps preprocess \\ + --reference "${genome_fa}" \\ + --workingdir gridss_preprocess/ \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + ${bam} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_preprocess/${bam.name}.gridss.working/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/gridss/preprocess/meta.yml b/modules/local/gridss/preprocess/meta.yml new file mode 100644 index 00000000..e43512b5 --- /dev/null +++ b/modules/local/gridss/preprocess/meta.yml @@ -0,0 +1,64 @@ +name: "PREPROCESS" +description: Preprocess reads for GRIDSS +keywords: + - gridss + - read processing + - sv +tools: + - "gridss": + description: "GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements." + homepage: "https://github.com/PapenfussLab/gridss" + documentation: "https://github.com/PapenfussLab/gridss" + tool_dev_url: "https://github.com/PapenfussLab/gridss" + doi: "" + licence: "['GPL >=3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - gridss_config: + type: file + description: Optional GRIDSS configuration file + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_bwa_index_dir: + type: directory + description: Directory containing reference genome assembly BWA index + - genome_bwa_index_image: + type: file + description: Reference genome assembly BWA index img file + pattern: "*.{img}" + - genome_gridss_index: + type: file + description: Reference genome assembly GRIDSS index file + pattern: "*.{gridsscache}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - preprocess_dir: + type: directory + description: GRIDSS preprocess output directory + +authors: + - "@scwatts" diff --git a/modules/local/gripss/Dockerfile b/modules/local/gripss/Dockerfile new file mode 100644 index 00000000..fee84c90 --- /dev/null +++ b/modules/local/gripss/Dockerfile @@ -0,0 +1,22 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/gripss/ && \ + wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.3.1/gripss_v2.3.1.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'openjdk >=8' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf new file mode 100644 index 00000000..248e0b6d --- /dev/null +++ b/modules/local/gripss/germline/main.nf @@ -0,0 +1,62 @@ +process GRIPSS_GERMLINE { + //conda (params.enable_conda ? "bioconda::hmftools-gripss=2.2" : null) + container 'docker.io/scwatts/gripss:2.3.1--0' + + input: + tuple val(meta), path(gridss_vcf) + path genome_fa + path genome_fai + val genome_ver + path breakend_pon + path breakpoint_pon + path known_fusions + path repeat_mask_file + + output: + tuple val(meta), path('*.gripss.filtered.vcf.gz'), path('*.gripss.filtered.vcf.gz.tbi'), emit: vcf_hard + tuple val(meta), path('*.gripss.vcf.gz'), path('*.gripss.vcf.gz.tbi') , emit: vcf_soft + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def repeat_mask_file_arg = repeat_mask_file ? "-repeat_mask_file ${repeat_mask_file}" : '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'normal'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -pon_sgl_file "${breakend_pon}" \\ + -pon_sv_file "${breakpoint_pon}" \\ + -known_hotspot_file "${known_fusions}" \\ + -vcf "${gridss_vcf}" \\ + ${repeat_mask_file_arg} \\ + -output_dir ./ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gripss: 2.3.1 + END_VERSIONS + """ + + stub: + """ + cat < ${meta.get(['sample_name', 'normal'])}.gripss.filtered.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + touch ${meta.get(['sample_name', 'normal'])}.gripss.filtered.vcf.gz.tbi + touch ${meta.get(['sample_name', 'normal'])}.gripss.vcf.gz + touch ${meta.get(['sample_name', 'normal'])}.gripss.vcf.gz.tbi + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/gripss/germline/meta.yml b/modules/local/gripss/germline/meta.yml new file mode 100644 index 00000000..35142e05 --- /dev/null +++ b/modules/local/gripss/germline/meta.yml @@ -0,0 +1,74 @@ +name: "GRIPSS_germline" +description: GRIPSS applies a set of filtering and post processing steps on GRIDSS SVs +keywords: + - gripss + - sv filtering + - germline +tools: + - "GRIPSS": + description: "GRIPSS applies a set of filtering and post processing steps on GRIDSS SVs." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'normal']: 'sample_normal'] + - gridss_vcf: + type: file + description: VCF file + pattern: "*.{vcf.gz}" + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_ver: + type: string + description: Reference genome version + - breakend_pon: + type: file + description: GRIDSS breakend PON file + pattern: "*.{bed.gz}" + - breakpoint_pon: + type: file + description: GRIDSS breakpoint PON file + pattern: "*.{bedpe.gz}" + - known_fusions: + type: file + description: HMF Known Fusions file + pattern: "*.{bedpe}" + - repeat_mask_file: + type: file + description: RepeatMasker resource file (optional) + pattern: "*.{fa.out.gz}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'normal']: 'sample_normal'] + - vcf_hard: + type: list + description: Hard filtered VCF file and index file + pattern: "*.{vcf.gz,vcf.gz.tbi}" + - vcf_soft: + type: list + description: Soft filtered VCF file and index file + pattern: "*.{vcf.gz,vcf.gz.tbi}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf new file mode 100644 index 00000000..f01b06cb --- /dev/null +++ b/modules/local/gripss/somatic/main.nf @@ -0,0 +1,63 @@ +process GRIPSS_SOMATIC { + //conda (params.enable_conda ? "bioconda::hmftools-gripss=2.2" : null) + container 'docker.io/scwatts/gripss:2.3.1--0' + + input: + tuple val(meta), path(gridss_vcf) + path genome_fa + path genome_fai + val genome_ver + path breakend_pon + path breakpoint_pon + path known_fusions + path repeat_mask_file + + output: + tuple val(meta), path('*.gripss.filtered.vcf.gz'), path('*.gripss.filtered.vcf.gz.tbi'), emit: vcf_hard + tuple val(meta), path('*.gripss.vcf.gz'), path('*.gripss.vcf.gz.tbi') , emit: vcf_soft + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def repeat_mask_file_arg = repeat_mask_file ? "-repeat_mask_file ${repeat_mask_file}" : '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'tumor'])}" \\ + -reference "${meta.get(['sample_name', 'normal'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -pon_sgl_file "${breakend_pon}" \\ + -pon_sv_file "${breakpoint_pon}" \\ + -known_hotspot_file "${known_fusions}" \\ + -vcf "${gridss_vcf}" \\ + ${repeat_mask_file_arg} \\ + -output_dir ./ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gripss: 2.3.1 + END_VERSIONS + """ + + stub: + """ + cat < ${meta.get(['sample_name', 'tumor'])}.gripss.filtered.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + touch ${meta.get(['sample_name', 'tumor'])}.gripss.filtered.vcf.gz.tbi + touch ${meta.get(['sample_name', 'tumor'])}.gripss.vcf.gz + touch ${meta.get(['sample_name', 'tumor'])}.gripss.vcf.gz.tbi + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/gripss/somatic/meta.yml b/modules/local/gripss/somatic/meta.yml new file mode 100644 index 00000000..402c1ead --- /dev/null +++ b/modules/local/gripss/somatic/meta.yml @@ -0,0 +1,74 @@ +name: "GRIPSS_somatic" +description: GRIPSS applies a set of filtering and post processing steps on GRIDSS SVs +keywords: + - gripss + - sv filtering + - germline +tools: + - "GRIPSS": + description: "GRIPSS applies a set of filtering and post processing steps on GRIDSS SVs." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'somatic']: 'sample_somatic'] + - gridss_vcf: + type: file + description: VCF file + pattern: "*.{vcf.gz}" + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_ver: + type: string + description: Reference genome version + - breakend_pon: + type: file + description: GRIDSS breakend PON file + pattern: "*.{bed.gz}" + - breakpoint_pon: + type: file + description: GRIDSS breakpoint PON file + pattern: "*.{bedpe.gz}" + - known_fusions: + type: file + description: HMF Known Fusions file + pattern: "*.{bedpe}" + - repeat_mask_file: + type: file + description: RepeatMasker resource file (optional) + pattern: "*.{fa.out.gz}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'somatic']: 'sample_somatic'] + - vcf_hard: + type: list + description: Hard filtered VCF file and index file + pattern: "*.{vcf.gz,vcf.gz.tbi}" + - vcf_soft: + type: list + description: Soft filtered VCF file and index file + pattern: "*.{vcf.gz,vcf.gz.tbi}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/isofox/Dockerfile b/modules/local/isofox/Dockerfile new file mode 100644 index 00000000..6e4b5b11 --- /dev/null +++ b/modules/local/isofox/Dockerfile @@ -0,0 +1,22 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/isofox/ && \ + wget -O /opt/isofox/isofox.jar 'https://github.com/hartwigmedical/hmftools/releases/download/isofox-v1.5/isofox_v1.5_rc3.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'openjdk >=8' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf new file mode 100644 index 00000000..32116490 --- /dev/null +++ b/modules/local/isofox/main.nf @@ -0,0 +1,54 @@ +// NOTE(SW): care must be taken for using exp_counts; only supports read length of 151 bp + + +process ISOFOX { + container 'docker.io/scwatts/isofox:1.5--0' + + input: + tuple val(meta), path(bam) + path genome_fa + path genome_fai + val genome_ver + path ensembl_data_dir + path exp_counts + path exp_gc_ratios + + output: + tuple val(meta), path('isofox/'), emit: isofox_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + mkdir -p isofox/ + + java \\ + -Xmx${task.memory.giga}g \\ + -jar ${task.ext.jarPath} \\ + ${args} \\ + -sample ${meta.get(['sample_name', 'tumor'])} \\ + -bam_file ${bam} \\ + -ref_genome ${genome_fa} \\ + -ref_genome_version ${genome_ver} \\ + -ensembl_data_dir ${ensembl_data_dir} \\ + -exp_counts_file ${exp_counts} \\ + -exp_gc_ratios_file ${exp_gc_ratios} \\ + -output_dir ./isofox/ \\ + -threads ${task.cpus} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + isofox: \$(java -jar ${task.ext.jarPath} | sed -n '1s/^.*version: //p') + END_VERSIONS + """ + + stub: + """ + mkdir -p isofox/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/lilac/Dockerfile b/modules/local/lilac/Dockerfile new file mode 100644 index 00000000..b0d3891b --- /dev/null +++ b/modules/local/lilac/Dockerfile @@ -0,0 +1,22 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/lilac/ && \ + wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.4/lilac_v1.4.1.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'openjdk >=8' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf new file mode 100644 index 00000000..c3aeb215 --- /dev/null +++ b/modules/local/lilac/main.nf @@ -0,0 +1,64 @@ +process LILAC { + //conda (params.enable_conda ? "bioconda::hmftools-lilac=1.2" : null) + container 'docker.io/scwatts/lilac:1.4.1--0' + + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumour_bai), path(normal_bai), path(purple_dir) + path genome_fa + val genome_ver + path lilac_resource_dir, stageAs: 'lilac_resource_dir' + + output: + tuple val(meta), path('lilac/'), emit: lilac_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def sample_name = get_sample_name(meta, tumor_bam, normal_bam) + def tumor_bam_arg = tumor_bam ? "-tumor_bam ${tumor_bam}" : '' + def purple_args = purple_dir ? """ + -gene_copy_number ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ + -somatic_vcf ${purple_dir}/${sample_name}.purple.sv.vcf.gz \\ + """ : '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${sample_name}" \\ + ${tumor_bam_arg} \\ + -reference_bam ${normal_bam} \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -resource_dir "${lilac_resource_dir}" \\ + ${purple_args.replaceAll('\\n', '')} \\ + -threads "${task.cpus}" \\ + -output_dir lilac/ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + lilac: 1.4.1 + END_VERSIONS + """ + + stub: + """ + mkdir -p lilac/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} + +def get_sample_name(meta, tumor_bam, normal_bam) { + if (tumor_bam) { + return meta.get(['sample_name', 'tumor']) + } else if (normal_bam) { + return meta.get(['sample_name', 'normal']) + } else { + Sys.exit(1) + } +} diff --git a/modules/local/lilac/meta.yml b/modules/local/lilac/meta.yml new file mode 100644 index 00000000..0e493729 --- /dev/null +++ b/modules/local/lilac/meta.yml @@ -0,0 +1,65 @@ +name: "LILAC" +description: LILAC is a WGS tool for HLA typing and somatic CNV and SNV calling +keywords: + - lilac +tools: + - "LILAC": + description: "LILAC is a WGS tool for HLA typing and somatic CNV and SNV calling." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/lilac" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/lilac" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/lilac" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. ['subject_name': 'subject', ['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + - tumor_bam: + type: file + description: Optional tumor BAM file + pattern: "*.{bam}" + - normal_bam: + type: file + description: Normal BAM file + pattern: "*.{bam}" + - tumor_bai: + type: file + description: Optional tumor BAI file + pattern: "*.{bai}" + - normal_bai: + type: file + description: Normal BAI file + pattern: "*.{bai}" + - purple_dir: + type: directory + description: Optional PURPLE output directory + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version + - lilac_resource_dir: + type: directory + description: LILAC resource directory + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. ['subject_name': 'subject', ['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + - lilac_dir: + type: file + description: LILAC output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/linx/Dockerfile b/modules/local/linx/Dockerfile new file mode 100644 index 00000000..846feb27 --- /dev/null +++ b/modules/local/linx/Dockerfile @@ -0,0 +1,30 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/linx/ && \ + wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.22/linx_v1.22.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + bioconductor-gviz \ + 'circos >=0.69.6' \ + 'openjdk >=8' \ + r-cowplot \ + r-dplyr \ + r-ggplot2 \ + r-magick \ + r-tidyr \ + xorg-libxtst && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf new file mode 100644 index 00000000..263b01cf --- /dev/null +++ b/modules/local/linx/germline/main.nf @@ -0,0 +1,50 @@ +process LINX_GERMLINE { + //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) + container 'docker.io/scwatts/linx:1.22--0' + + input: + tuple val(meta), path(gripss_sv) + val genome_ver + path fragile_sites + path lines + path ensembl_data_dir + path driver_gene_panel + + output: + tuple val(meta), path('linx_germline/'), emit: annotation_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'normal'])}" \\ + -germline \\ + -ref_genome_version "${genome_ver}" \\ + -sv_vcf "${gripss_sv}" \\ + -fragile_site_file "${fragile_sites}" \\ + -line_element_file "${lines}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -check_drivers \\ + -driver_gene_panel "${driver_gene_panel}" \\ + -output_dir linx_germline/ + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') + END_VERSIONS + """ + + stub: + """ + mkdir linx_germline/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/linx/germline/meta.yml b/modules/local/linx/germline/meta.yml new file mode 100644 index 00000000..335b3de4 --- /dev/null +++ b/modules/local/linx/germline/meta.yml @@ -0,0 +1,61 @@ +name: "LINX_germline" +description: Generate LINX germline annotation data +keywords: + - linx + - germline + - sv + - annotation +tools: + - "LINX": + description: "LINX is an annotation, interpretation and visualisation tool for structural variants." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/linx" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/linx" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/linx" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'normal']: 'sample_normal'] + - gridss_sv: + type: file + description: GRIPSS hard filtered VCF + pattern: "*.{vcf.gz}" + - genome_ver: + type: string + description: Reference genome version + - fragile_sites: + type: file + description: LINX fragile sites file + pattern: "*.{csv}" + - lines: + type: file + description: LINEs file + pattern: "*.{csv}" + - ensembl_data_dir: + type: directory + description: HMF Ensembl Data Cache directory + - driver_gene_panel: + type: file + description: HMF Driver Gene Panel file + pattern: "*.{csv}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'normal']: 'sample_normal'] + - annotation_dir: + type: directory + description: LINX annotation output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf new file mode 100644 index 00000000..de11621f --- /dev/null +++ b/modules/local/linx/somatic/main.nf @@ -0,0 +1,53 @@ +process LINX_SOMATIC { + //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) + container 'docker.io/scwatts/linx:1.22--0' + + input: + tuple val(meta), path(purple_dir) + val genome_ver + path fragile_sites + path lines + path ensembl_data_dir + path known_fusion_data + path driver_gene_panel + + output: + tuple val(meta), path('linx_somatic/'), emit: annotation_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'tumor'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -sv_vcf "${purple_dir}/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz" \\ + -purple_dir "${purple_dir}" \\ + -fragile_site_file "${fragile_sites}" \\ + -line_element_file "${lines}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -check_fusions \\ + -known_fusion_file "${known_fusion_data}" \\ + -check_drivers \\ + -driver_gene_panel "${driver_gene_panel}" \\ + -output_dir linx_somatic/ + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') + END_VERSIONS + """ + + stub: + """ + mkdir linx_somatic/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/linx/somatic/meta.yml b/modules/local/linx/somatic/meta.yml new file mode 100644 index 00000000..b620c8d1 --- /dev/null +++ b/modules/local/linx/somatic/meta.yml @@ -0,0 +1,64 @@ +name: "LINX_somatic" +description: Generate LINX somatic annotation data +keywords: + - linx + - somatic + - sv + - annotation +tools: + - "LINX": + description: "LINX is an annotation, interpretation and visualisation tool for structural variants." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/linx" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/linx" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/linx" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor'] + - purple_dir: + type: directory + description: PURPLE output directory + - genome_ver: + type: string + description: Reference genome version + - fragile_sites: + type: file + description: LINX fragile sites file + pattern: "*.{csv}" + - lines: + type: file + description: LINEs file + pattern: "*.{csv}" + - ensembl_data_dir: + type: directory + description: HMF Ensembl Data Cache directory + - known_fusion_data: + type: file + description: HMF Known Fusions Data file + pattern: "*.{bedpe}" + - driver_gene_panel: + type: file + description: HMF Driver Gene Panel file + pattern: "*.{csv}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor'] + - annotation_dir: + type: directory + description: LINX annotation output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf new file mode 100644 index 00000000..8c555904 --- /dev/null +++ b/modules/local/linx/visualiser/main.nf @@ -0,0 +1,51 @@ +process VISUALISER { + //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) + container 'docker.io/scwatts/linx:1.22--0' + + // Lenient caching is required here as the hash of the LINX_SOMATIC + // 'annotation_dir' output changes between runs even when the LINX_SOMATIC + // process itself is cached. + cache = 'lenient' + + input: + tuple val(meta), path(linx) + val genome_ver + path ensembl_data_dir + + output: + tuple val(meta), path('linx_visualiser/plot/'), emit: visualiser_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -cp "${task.ext.jarPath}" \\ + com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'tumor'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -plot_out linx_visualiser/plot \\ + -data_out linx_visualiser/data \\ + -vis_file_dir "${linx}" \\ + -circos "${task.ext.path_circos}" \\ + -threads "${task.cpus}" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') + END_VERSIONS + """ + + stub: + """ + mkdir -p linx_visualiser/plot/ + echo -e '${task.process}:\n stub: noversions\n' > versions.yml + """ +} diff --git a/modules/local/linx/visualiser/meta.yml b/modules/local/linx/visualiser/meta.yml new file mode 100644 index 00000000..725e21d8 --- /dev/null +++ b/modules/local/linx/visualiser/meta.yml @@ -0,0 +1,49 @@ +name: "VISUALISER" +description: Visualise LINX somatic annotations +keywords: + - linx + - somatic + - sv + - annotation + - visualisation +tools: + - "LINX": + description: "LINX is an annotation, interpretation and visualisation tool for structural variants." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/linx" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/linx" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/linx" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. ['subject_name': 'subject', ['sample_name', 'tumor']: 'sample', ['tumor', 'bam']: 'path/to/bam'] + - genome_ver: + type: string + description: Reference genome version + - linx: + type: directory + description: LINX somatic annotation output directory + - ensembl_data_dir: + type: directory + description: HMF Ensembl Data Cache directory + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. ['subject_name': 'subject', ['sample_name', 'tumor']: 'sample', ['tumor', 'bam']: 'path/to/bam'] + - visualiser_dir: + type: directory + description: LINX visualiser output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/pave/Dockerfile b/modules/local/pave/Dockerfile new file mode 100644 index 00000000..d2cbefa9 --- /dev/null +++ b/modules/local/pave/Dockerfile @@ -0,0 +1,22 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/pave/ && \ + wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.4/pave_v1.4.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'openjdk >=8' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf new file mode 100644 index 00000000..591481ff --- /dev/null +++ b/modules/local/pave/germline/main.nf @@ -0,0 +1,60 @@ +// NOTE(SW): PAVE gnomad filtering is not yet documented but is used in Pipeline5 https://github.com/hartwigmedical/pipeline5/blob/master/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L27-L28 + +process PAVE_GERMLINE { + //conda (params.enable_conda ? "bioconda::hmftools-pave=1.3" : null) + container 'docker.io/scwatts/pave:1.4--0' + + input: + tuple val(meta), path(sage_vcf) + path genome_fa + path genome_fai + val genome_ver + path sage_blacklist_bed + path sage_blacklist_vcf + path clinvar_vcf + path mappability_bed + path driver_gene_panel + path ensembl_data_dir + + output: + tuple val(meta), path("*.vcf.gz") , emit: vcf + tuple val(meta), path("*.vcf.gz.tbi"), emit: index + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'tumor'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -driver_gene_panel "${driver_gene_panel}" \\ + -clinvar_vcf "${clinvar_vcf}" \\ + -blacklist_bed "${sage_blacklist_bed}" \\ + -blacklist_vcf "${sage_blacklist_vcf}" \\ + -mappability_bed "${mappability_bed}" \\ + -vcf_file "${sage_vcf}" \\ + -read_pass_only \\ + -output_dir ./ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + pave: 1.4 + END_VERSIONS + """ + + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}.sage.pave_germline.vcf.gz{,.tbi} + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/pave/germline/meta.yml b/modules/local/pave/germline/meta.yml new file mode 100644 index 00000000..fca88ea4 --- /dev/null +++ b/modules/local/pave/germline/meta.yml @@ -0,0 +1,85 @@ +name: "PAVE_germline" +description: PAVE annotates a somatic variant VCF with gene and transcript coding and protein effects +keywords: + - pave + - annotation + - gene + - transcript + - protein + - vcf +tools: + - "PAVE": + description: "PAVE annotates a somatic variant VCF with gene and transcript coding and protein effects." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/pave" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/pave" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/pave" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor'] + - sage_vcf: + type: file + description: SAGE VCF + pattern: "*.{vcf.gz}" + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_ver: + type: string + description: Reference genome version + - sage_blacklist_bed: + type: file + description: SAGE blacklist BED + pattern: "*.{bed}" + - sage_blacklist_vcf: + type: file + description: SAGE blacklist VCF + pattern: "*.{vcf.gz}" + - clinvar_vcf: + type: file + description: HMF ClinVar VCF + pattern: "*.{vcf.gz}" + - mappability_bed: + type: file + description: HMF mappability BED + pattern: "*.{bed.gz}" + - driver_gene_panel: + type: file + description: HMF Driver Gene Panel file + pattern: "*.{tsv}" + - ensembl_data_dir: + type: directory + description: HMF Ensembl Data Cache directory + pattern: "*.{tsv}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor'] + - vcf: + type: file + description: PAVE VCF file + pattern: "*.{vcf.gz}" + - index: + type: file + description: PAVE VCF index file + pattern: "*.{vcf.gz.tbi}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf new file mode 100644 index 00000000..09a6a00a --- /dev/null +++ b/modules/local/pave/somatic/main.nf @@ -0,0 +1,57 @@ +// NOTE(SW): PAVE gnomad filtering is not yet documented but is used in Pipeline5 https://github.com/hartwigmedical/pipeline5/blob/master/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L27-L28 + +process PAVE_SOMATIC { + //conda (params.enable_conda ? "bioconda::hmftools-pave=1.3" : null) + container 'docker.io/scwatts/pave:1.4--0' + + input: + tuple val(meta), path(sage_vcf) + path genome_fa + path genome_fai + val genome_ver + path sage_pon_file + path mappability_bed + path driver_gene_panel + path ensembl_data_dir + + output: + tuple val(meta), path("*.vcf.gz") , emit: vcf + tuple val(meta), path("*.vcf.gz.tbi"), emit: index + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def pon_filters = "HOTSPOT:5:5;PANEL:2:5;UNKNOWN:2:0" + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + -sample "${meta.get(['sample_name', 'tumor'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -driver_gene_panel "${driver_gene_panel}" \\ + -pon_file "${sage_pon_file}" \\ + -pon_filters "${pon_filters}" \\ + -mappability_bed "${mappability_bed}" \\ + -vcf_file "${sage_vcf}" \\ + -read_pass_only \\ + -output_dir ./ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + pave: 1.4 + END_VERSIONS + """ + + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}.sage.pave_somatic.vcf.gz{,.tbi} + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/pave/somatic/meta.yml b/modules/local/pave/somatic/meta.yml new file mode 100644 index 00000000..f5539f84 --- /dev/null +++ b/modules/local/pave/somatic/meta.yml @@ -0,0 +1,77 @@ +name: "PAVE_somatic" +description: PAVE annotates a somatic variant VCF with gene and transcript coding and protein effects +keywords: + - pave + - annotation + - gene + - transcript + - protein + - vcf +tools: + - "PAVE": + description: "PAVE annotates a somatic variant VCF with gene and transcript coding and protein effects." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/pave" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/pave" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/pave" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor'] + - sage_vcf: + type: file + description: SAGE VCF + pattern: "*.{vcf.gz}" + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_ver: + type: string + description: Reference genome version + - sage_pon_file: + type: file + description: SAGE PON file + pattern: "*.{tsv.gz}" + - mappability_bed: + type: file + description: HMF mappability BED + pattern: "*.{bed.gz}" + - driver_gene_panel: + type: file + description: HMF Driver Gene Panel file + pattern: "*.{tsv}" + - ensembl_data_dir: + type: directory + description: HMF Ensembl Data Cache directory + pattern: "*.{tsv}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor'] + - vcf: + type: file + description: PAVE VCF file + pattern: "*.{vcf.gz}" + - index: + type: file + description: PAVE VCF index file + pattern: "*.{vcf.gz.tbi}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/purple/Dockerfile b/modules/local/purple/Dockerfile new file mode 100644 index 00000000..d00dd84a --- /dev/null +++ b/modules/local/purple/Dockerfile @@ -0,0 +1,32 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/purple/ && \ + wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.7/purple_v3.7.1.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + bcftools \ + bioconductor-variantannotation \ + 'circos >=0.69.6' \ + 'openjdk >=8' \ + r-cairo \ + r-cowplot \ + r-dplyr \ + r-ggplot2 \ + r-tidyr \ + xorg-libxtst \ + zlib && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf new file mode 100644 index 00000000..7591372e --- /dev/null +++ b/modules/local/purple/main.nf @@ -0,0 +1,94 @@ +process PURPLE { + //conda (params.enable_conda ? "bioconda::hmftools-purple=3.6" : null) + container 'docker.io/scwatts/purple:3.6--4' + + input: + tuple val(meta), path(amber), path(cobalt), path(sv_hard_vcf), path(sv_hard_vcf_index), path(sv_soft_vcf), path(sv_soft_vcf_index), path(smlv_tumor_vcf), path(smlv_normal_vcf) + path genome_fa + path genome_fai + path genome_dict + val genome_ver + path gc_profile + path sage_known_hotspots_somatic + path sage_known_hotspots_germline + path driver_gene_panel + path ensembl_data_dir + path germline_del_freq + + output: + tuple val(meta), path('purple/'), emit: purple_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def smlv_tumor_vcf_fp = smlv_tumor_vcf ?: '' + def smlv_normal_vcf_fp = smlv_normal_vcf ?: '' + def germline_del_freq_arg = germline_del_freq ? "-germline_del_freq_file ${germline_del_freq}" : '' + + """ + # For provided smlv VCFs, filter records that do not contain the required FORMAT/AD field and + # get argument for PURPLE + get_smlv_arg() { + fp=\${1} + fn=\${fp##*/} + if [[ "\${fp}" != '' ]]; then + fp_out="prepared__\${2}__\${fn}" + bcftools filter -Oz -e 'FORMAT/AD[*]="."' "\${fp}" > \${fp_out} + echo "-\${2} \${fp_out}" + fi + } + smlv_tumor_vcf_arg=\$(get_smlv_arg "${smlv_tumor_vcf_fp}" somatic_vcf) + smlv_normal_vcf_arg=\$(get_smlv_arg "${smlv_normal_vcf_fp}" germline_vcf) + + # Run PURPLE + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -tumor "${meta.get(['sample_name', 'tumor'])}" \\ + -reference "${meta.get(['sample_name', 'normal'])}" \\ + -sv_recovery_vcf "${sv_soft_vcf}" \\ + -structural_vcf "${sv_hard_vcf}" \\ + \${smlv_tumor_vcf_arg} \\ + \${smlv_normal_vcf_arg} \\ + -amber "${amber}" \\ + -cobalt "${cobalt}" \\ + -output_dir purple/ \\ + -gc_profile "${gc_profile}" \\ + -run_drivers \\ + -driver_gene_panel "${driver_gene_panel}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -somatic_hotspots "${sage_known_hotspots_somatic}" \\ + -germline_hotspots "${sage_known_hotspots_germline}" \\ + ${germline_del_freq_arg} \\ + -ref_genome "${genome_fa}" \\ + -ref_genome_version "${genome_ver}" \\ + -threads "${task.cpus}" \\ + -circos "${task.ext.circosPath}" + + # PURPLE can fail silently, check that at least the PURPLE SV VCF is created + if [[ ! -s "purple/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz" ]]; then + exit 1; + fi + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + purple: \$(java -jar "${task.ext.jarPath}" -version | sed 's/.*Purple version: //') + END_VERSIONS + """ + + stub: + """ + mkdir purple/ + cat < purple/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/purple/meta.yml b/modules/local/purple/meta.yml new file mode 100644 index 00000000..915f63a8 --- /dev/null +++ b/modules/local/purple/meta.yml @@ -0,0 +1,109 @@ +name: "PURPLE" +description: PURPLE is a purity ploidy estimator for whole genome sequenced data +keywords: + - purple + - variant caller + - ploidy + - purity + - cnv + - sv +tools: + - "PURPLE": + description: "PURPLE is a purity ploidy estimator for whole genome sequenced data." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/purple" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/purple" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/purple" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + - amber: + type: directory + description: AMBER output directory + - cobalt: + type: directory + description: COBALT output directory + - sv_hard_vcf: + type: file + description: GRIPSS hard filtered VCF file + pattern: "*.{vcf.gz}" + - sv_hard_vcf_index: + type: file + description: GRIPSS hard filtered VCF index file + pattern: "*.{vcf.gz.tbi}" + - sv_soft_vcf: + type: file + description: GRIPSS soft filtered VCF file + pattern: "*.{vcf.gz}" + - sv_soft_vcf_index: + type: file + description: GRIPSS soft filtered VCF index file + pattern: "*.{vcf.gz.tbi}" + - smlv_tumor_vcf: + type: file + description: Optional small variant tumor VCF file + pattern: "*.{vcf.gz}" + - smlv_normal_vcf: + type: file + description: Optional small variant normal VCF file + pattern: "*.{vcf.gz}" + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_ver: + type: string + description: Reference genome version + - gc_profile: + type: file + description: COBALT GC Profile file + pattern: "*.{cnp}" + - sage_known_hotspots_somatic: + type: file + description: SAGE somatic Known Hotspots file + pattern: "*.{vcf.gz}" + - sage_known_hotspots_germline: + type: file + description: SAGE germline Known Hotspots file + pattern: "*.{vcf.gz}" + - driver_gene_panel: + type: file + description: HMF Driver Gene Panel file + pattern: "*.{csv}" + - ensembl_data_dir: + type: directory + description: HMF Ensembl Data Cache directory + - germline_del_freq: + type: file + description: Cohort frequency for germline deletions + pattern: "*.{csv}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + - purple_dir: + type: directory + description: PURPLE output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/sage/Dockerfile b/modules/local/sage/Dockerfile new file mode 100644 index 00000000..b2b738b4 --- /dev/null +++ b/modules/local/sage/Dockerfile @@ -0,0 +1,31 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/sage/ && \ + wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.2/sage_v3.2.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + bioconductor-genomicranges \ + bioconductor-variantannotation \ + font-ttf-dejavu \ + 'openjdk >=8' \ + r-dplyr \ + r-ggplot2 \ + r-tidyr \ + xorg-libxt \ + zlib && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" + diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf new file mode 100644 index 00000000..a288c996 --- /dev/null +++ b/modules/local/sage/germline/main.nf @@ -0,0 +1,63 @@ +process SAGE_GERMLINE { + //conda (params.enable_conda ? "bioconda::hmftools-sage=3.1" : null) + container 'docker.io/scwatts/sage:3.2--0' + + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) + path genome_fa + path genome_fai + path genome_dict + val genome_ver + path sage_known_hotspots_germline + path sage_coding_panel + path sage_high_confidence + path ensembl_data_dir + + output: + tuple val(meta), path("${meta.subject_name}.sage_germline.vcf.gz"), emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -reference "${meta.get(['sample_name', 'tumor'])}" \\ + -reference_bam "${tumor_bam}" \\ + -tumor "${meta.get(['sample_name', 'normal'])}" \\ + -tumor_bam "${normal_bam}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -hotspots "${sage_known_hotspots_germline}" \\ + -panel_bed "${sage_coding_panel}" \\ + -high_confidence_bed "${sage_high_confidence}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -hotspot_min_tumor_qual 50 \\ + -panel_min_tumor_qual 75 \\ + -hotspot_max_germline_vaf 100 \\ + -hotspot_max_germline_rel_raw_base_qual 100 \\ + -panel_max_germline_vaf 100 \\ + -panel_max_germline_rel_raw_base_qual 100 \\ + -mnv_filter_enabled false \\ + -panel_only \\ + -threads "${task.cpus}" \\ + -out "${meta.subject_name}.sage_germline.vcf.gz" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sage: \$(java -jar "${task.ext.jarPath}" | head -n1 | sed 's/.*Sage version: //') + END_VERSIONS + """ + + stub: + """ + touch "${meta.subject_name}.sage_germline.vcf.gz" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/sage/germline/meta.yml b/modules/local/sage/germline/meta.yml new file mode 100644 index 00000000..d18bb6ab --- /dev/null +++ b/modules/local/sage/germline/meta.yml @@ -0,0 +1,89 @@ +name: "SAGE_germline" +description: A precise and highly sensitive somatic SNV, MNV and small INDEL caller +keywords: + - sage + - germline + - variant caller + - snv + - mnv + - small indel +tools: + - "SAGE": + description: "A precise and highly sensitive somatic SNV, MNV and small INDEL caller." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/sage" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/sage" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/sage" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample informatio + e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + - tumor_bam: + type: file + description: Tumor BAM file + pattern: "*.{bam}" + - normal_bam: + type: file + description: Normal BAM file + pattern: "*.{bam}" + - tumor_bai: + type: file + description: Tumor BAI file + pattern: "*.{bai}" + - normal_bai: + type: file + description: Normal BAI file + pattern: "*.{bai}" + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_ver: + type: string + description: Reference genome version + - sage_known_hotspots_germline: + type: file + description: SAGE germline Known Hotspots file + pattern: "*.{vcf.gz}" + - sage_coding_panel: + type: file + description: SAGE Coding Panel file + pattern: "*.{bed.gz}" + - sage_high_confidence: + type: file + description: SAGE High Confidence file + pattern: "*.{bed.gz}" + - ensembl_data_dir: + type: directory + description: HMF Ensembl Data Cache directory + pattern: "*.{tsv}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + - vcf: + type: file + description: SAGE VCF file + pattern: "*.{vcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf new file mode 100644 index 00000000..863c2447 --- /dev/null +++ b/modules/local/sage/somatic/main.nf @@ -0,0 +1,55 @@ +process SAGE_SOMATIC { + //conda (params.enable_conda ? "bioconda::hmftools-sage=3.1" : null) + container 'docker.io/scwatts/sage:3.2--0' + + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) + path genome_fa + path genome_fai + path genome_dict + val genome_ver + path sage_known_hotspots_somatic + path sage_coding_panel + path sage_high_confidence + path ensembl_data_dir + + output: + tuple val(meta), path("${meta.subject_name}.sage_somatic.vcf.gz"), emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -reference "${meta.get(['sample_name', 'normal'])}" \\ + -reference_bam "${normal_bam}" \\ + -tumor "${meta.get(['sample_name', 'tumor'])}" \\ + -tumor_bam "${tumor_bam}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -hotspots "${sage_known_hotspots_somatic}" \\ + -panel_bed "${sage_coding_panel}" \\ + -high_confidence_bed "${sage_high_confidence}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -threads "${task.cpus}" \\ + -out "${meta.subject_name}.sage_somatic.vcf.gz" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sage: \$(java -jar "${task.ext.jarPath}" | head -n1 | sed 's/.*Sage version: //') + END_VERSIONS + """ + + stub: + """ + touch "${meta.subject_name}.sage_somatic.vcf.gz" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/sage/somatic/meta.yml b/modules/local/sage/somatic/meta.yml new file mode 100644 index 00000000..5dec8815 --- /dev/null +++ b/modules/local/sage/somatic/meta.yml @@ -0,0 +1,89 @@ +name: "SAGE_somatic" +description: A precise and highly sensitive somatic SNV, MNV and small INDEL caller +keywords: + - sage + - somatic + - variant caller + - snv + - mnv + - small indel +tools: + - "SAGE": + description: "A precise and highly sensitive somatic SNV, MNV and small INDEL caller." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/sage" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/sage" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/sage" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample informatio + e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + - tumor_bam: + type: file + description: Tumor BAM file + pattern: "*.{bam}" + - normal_bam: + type: file + description: Normal BAM file + pattern: "*.{bam}" + - tumor_bai: + type: file + description: Tumor BAI file + pattern: "*.{bai}" + - normal_bai: + type: file + description: Normal BAI file + pattern: "*.{bai}" + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_ver: + type: string + description: Reference genome version + - sage_known_hotspots_somatic: + type: file + description: SAGE somatic Known Hotspots file + pattern: "*.{vcf.gz}" + - sage_coding_panel: + type: file + description: SAGE Coding Panel file + pattern: "*.{bed.gz}" + - sage_high_confidence: + type: file + description: SAGE High Confidence file + pattern: "*.{bed.gz}" + - ensembl_data_dir: + type: directory + description: HMF Ensembl Data Cache directory + pattern: "*.{tsv}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + - vcf: + type: file + description: SAGE VCF file + pattern: "*.{vcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile new file mode 100644 index 00000000..742d4390 --- /dev/null +++ b/modules/local/svprep/Dockerfile @@ -0,0 +1,15 @@ +FROM docker.io/scwatts/gridss:2.13.2--3 + +ARG GH_BASE_URL='https://github.com/hartwigmedical/hmftools' +USER root + +RUN \ + mkdir -p /opt/svprep/ && \ + wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.1/sv-prep_v1.1_beta.jar' + +COPY assets/gridss.svprep /opt/svprep/gridss_svprep +RUN \ + chmod 755 /opt/svprep/gridss_svprep && \ + ln -s /opt/svprep/gridss_svprep /usr/local/bin/ + +USER mambauser diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf new file mode 100644 index 00000000..778338b9 --- /dev/null +++ b/modules/local/svprep/assemble/main.nf @@ -0,0 +1,89 @@ +process ASSEMBLE { + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + path blacklist + + output: + tuple val(meta), path('gridss_assemble/'), emit: assemble_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + def output_dirname = 'gridss_assemble' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = "--bams ${bams_list.join(',')}" + def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] + def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" + + """ + # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation + # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + shadow_input_directory() { + src=\${1} + dst="${output_dirname}/work/\${src##*/}" + for filepath_src in \$(find -L \${src} ! -type d); do + # Get destination location for symlink + filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) + filepath_dst=\${dst%/}/\${filepath_src_rel} + # Create directory for symlink + mkdir -p \${filepath_dst%/*}; + # Get path for symlink source file, then create it + # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only + # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers + symlinkpath=\$(realpath \${filepath_src}) + ln -s \${symlinkpath} \${filepath_dst}; + done + if [[ -L "\${src##*/}" ]]; then + rm "\${src}" + fi + } + for preprocess_dir in ${preprocess_dirs}; do + shadow_input_directory \${preprocess_dir}; + done + + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + # Run + gridss_svprep \\ + ${args} \\ + --jvmheap "${task.memory.giga}g" \\ + --jar "${task.ext.jarPath}" \\ + --steps assemble \\ + --labels "${labels_arg}" \\ + --reference "${genome_fa}" \\ + --blacklist "${blacklist}" \\ + --workingdir "${output_dirname}/work" \\ + --assembly "${output_dirname}/sv_assemblies.bam" \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + ${bams_arg} \\ + ${bams_filtered_arg} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_assemble/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/svprep/assets/gridss.svprep b/modules/local/svprep/assets/gridss.svprep new file mode 100644 index 00000000..d1b1f3e8 --- /dev/null +++ b/modules/local/svprep/assets/gridss.svprep @@ -0,0 +1,825 @@ +#!/bin/bash +# GRIDSS execution script using SvPrep BAMs + +getopt --test +if [[ ${PIPESTATUS[0]} -ne 4 ]]; then + echo 'WARNING: "getopt --test"` failed in this environment.' 1>&2 + echo "WARNING: The version of getopt(1) installed on this system might not be compatible with the GRIDSS driver script." 1>&2 +fi +unset DISPLAY # Prevents errors attempting to connecting to an X server when starting the R plotting device +ulimit -n $(ulimit -Hn 2>/dev/null) 2>/dev/null # Reduce likelihood of running out of open file handles +set -o errexit -o pipefail -o noclobber -o nounset +last_command="" +current_command="" +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'echo "\"${last_command}\" command completed with exit code $?."' EXIT +#253 forcing C locale for everything +export LC_ALL=C + +EX_USAGE=64 +EX_NOINPUT=66 +EX_CANTCREAT=73 +EX_CONFIG=78 + +workingdir="." +reference="" +output_vcf="" +assembly="" +threads=8 +jvmheap="30g" +otherjvmheap="4g" +blacklist="" +metricsrecords=10000000 +maxcoverage=50000 +config_file="" +labels="" +bams="" +filtered_bams="" +full_bams="" +keepTempFiles="false" + +steps="all" +do_preprocess=false +do_assemble=false +do_call=false + +USAGE_MESSAGE=" +Usage: gridss [options] -r -o -a input1.bam [input2.bam [...]] + + -r/--reference: reference genome to use. + -o/--output: output VCF. + -a/--assembly: location of the GRIDSS assembly BAM. This file will be + created by GRIDSS. + -t/--threads: number of threads to use. (Default: $threads) + -j/--jar: location of GRIDSS jar + -w/--workingdir: directory to place GRIDSS intermediate and temporary files + .gridss.working subdirectories will be created. (Default: $workingdir) + -s/--steps: processing steps to run. Defaults to all steps. + Multiple steps are specified using comma separators. Possible steps are: + preprocess, assemble, call, all + -e/--blacklist: BED file containing regions to ignore + -c/--configuration: configuration file use to override default GRIDSS + settings. + -l/--labels: comma separated labels to use in the output VCF for the input + files. Supporting read counts for input files with the same label are + aggregated (useful for multiple sequencing runs of the same sample). + Labels default to input filenames, unless a single read group with a + non-empty sample name exists in which case the read group sample name + is used (which can be disabled by \"useReadGroupSampleNameCategoryLabel=false\" + in the configuration file). If labels are specified, they must be + specified for all input files. + -b/bams: comma separated full-path BAM files + -f/filtered_bams: comma separated full-path filtered BAM files + --jvmheap: size of JVM heap for the high-memory component of assembly and variant calling. (Default: $jvmheap) + " + +OPTIONS=r:o:a:t:j:w:e:s:c:l:b:f: +LONGOPTS=reference:,output:,assembly:,threads:,jar:,workingdir:,jvmheap:,blacklist:,steps:,configuration:,labels:,bams:,filtered_bams: +! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") +if [[ ${PIPESTATUS[0]} -ne 0 ]]; then + # e.g. return value is 1 + # then getopt has complained about wrong arguments to stdout + echo "$USAGE_MESSAGE" 1>&2 + exit $EX_USAGE +fi +eval set -- "$PARSED" + +POSITIONAL_ARGS=() + +#while true; do +while [[ $# -gt 0 ]]; do + case "$1" in + -r|--reference) + reference="$2" + shift 2 + ;; + -l|--labels) + labels="$2" + shift 2 + ;; + -b|--bams) + bams="$2" + shift 2 + ;; + -f|--filtered_bams) + filtered_bams="$2" + shift 2 + ;; + -s|--steps) + steps="$2" + shift 2 + ;; + -w|--workingdir) + workingdir="$2" + shift 2 + ;; + -o|--output) + output_vcf="$2" + shift 2 + ;; + -a|--assembly) + if [[ "$assembly" == "" ]] ; then + assembly="$2" + else + assembly="$assembly $2" + fi + # TODO: support multiple assembly files + shift 2 + ;; + -e|--blacklist) + blacklist="$2" + shift 2 + ;; + -j|--jar) + GRIDSS_JAR="$2" + shift 2 + ;; + --jvmheap) + jvmheap="$2" + shift 2 + ;; + -t|--threads) + printf -v threads '%d\n' "$2" 2>/dev/null + printf -v threads '%d' "$2" 2>/dev/null + shift 2 + ;; + -c|--configuration) + config_file=$2 + shift 2 + ;; + *) + POSITIONAL_ARGS+=("$1") # save positional arg + # echo "Unparsed param" + shift + ;; + esac +done + +##### --workingdir +echo "Using working directory \"$workingdir\"" 1>&2 +if [[ "$workingdir" == "" ]] ; then + echo "$USAGE_MESSAGE" 1>&2 + echo "Working directory must be specified. Specify using the --workingdir command line argument" 1>&2 + exit $EX_USAGE +fi +if [[ "$(tr -d ' \n' <<< "$workingdir")" != "$workingdir" ]] ; then + echo "workingdir cannot contain whitespace" 1>&2 + exit $EX_USAGE + fi +if [[ ! -d $workingdir ]] ; then + mkdir -p $workingdir + if [[ ! -d $workingdir ]] ; then + echo Unable to create working directory $workingdir 1>&2 + exit $EX_CANTCREAT + fi +fi +workingdir=$(dirname $workingdir/placeholder) +timestamp=$(date +%Y%m%d_%H%M%S) +# Logging +logfile=$workingdir/gridss.full.$timestamp.$HOSTNAME.$$.log +# $1 is message to write +write_status() { + echo "$(date): $1" | tee -a $logfile 1>&2 +} +write_status "Full log file is: $logfile" +trap 'echo "\"${last_command}\" command completed with exit code $?. +***** +The underlying error message can be found in $logfile +*****"' EXIT +# Timing instrumentation +timinglogfile=$workingdir/gridss.timing.$timestamp.$HOSTNAME.$$.log +if which /usr/bin/time >/dev/null ; then + timecmd="/usr/bin/time" + write_status "Found /usr/bin/time" +else + timecmd="" + write_status "Not found /usr/bin/time" +fi +if [[ "$timecmd" != "" ]] ; then + timecmd="/usr/bin/time --verbose -a -o $timinglogfile" + if ! $timecmd echo 2>&1 > /dev/null; then + timecmd="/usr/bin/time -a -o $timinglogfile" + fi + if ! $timecmd echo 2>&1 > /dev/null ; then + timecmd="" + write_status "Unexpected /usr/bin/time version. Not logging timing information." + fi + # We don't need timing info of the echo + rm -f $timinglogfile +fi + +### Find the jars +find_jar() { + env_name=$1 + if [[ -f "${!env_name:-}" ]] ; then + echo "${!env_name}" + else + write_status "Unable to find $2 jar. Specify using the environment variant $env_name, or the --jar command line parameter." + exit $EX_NOINPUT + fi +} +gridss_jar=$(find_jar GRIDSS_JAR gridss) +write_status "Using GRIDSS jar $gridss_jar" + +# Check all key inputs: + +if [[ "$labels" == "" ]] ; then + write_status "Labels must be specified" + exit $EX_USAGE +fi + +if [[ "$bams" == "" ]] ; then + write_status "Full BAMs must be specified" + exit $EX_USAGE +fi + +if [[ "$filtered_bams" == "" ]] ; then + write_status "Filtered BAMs must be specified" + exit $EX_USAGE +fi + +##### --reference +if [[ "$reference" == "" ]] ; then + write_status "$USAGE_MESSAGE" + write_status "Reference genome must be specified. Specify using the --reference command line argument" + exit $EX_USAGE +fi + +if [ ! -f $reference ] ; then + write_status "$USAGE_MESSAGE" + write_status "Missing reference genome $reference. Specify reference location using the --reference command line argument" + exit $EX_USAGE +fi +write_status "Using reference genome \"$reference\"" + +##### --output +if [[ $do_call == "true" ]] ; then + if [[ "$output_vcf" == "" ]] ; then + write_status "$USAGE_MESSAGE" + write_status "Output VCF not specified. Use --output to specify output file." + exit $EX_USAGE + fi + mkdir -p $(dirname $output_vcf) + if [[ ! -d $(dirname $output_vcf) ]] ; then + write_status "Unable to create directory for $output_vcf for output VCF." + exit $EX_CANTCREAT + fi + write_status "Using output VCF $output_vcf" +fi +write_status "Using output VCF $output_vcf" + +##### --assembly +if [[ $do_assemble == "true" ]] || [[ $do_call == "true" ]]; then + if [[ "$assembly" == "" ]] ; then + if [[ "$output_vcf" == "" ]] ; then + write_status "Either the assembly output file must explicitly specified with -a, or the output VCF specified with -o" + exit $EX_USAGE + fi + assembly=$output_vcf.assembly.bam + fi + write_status "Using assembly bam $assembly" + if [[ $do_assemble == "true" ]] ; then + mkdir -p $(dirname $assembly) + if [[ ! -d $(dirname $assembly) ]] ; then + write_status "Unable to parent create directory for $assembly" + exit $EX_CANTCREAT + fi + else + if [[ ! -f $assembly ]] ; then + write_status "Missing assembly file $assembly" + write_status "Ensure the GRIDSS assembly step has been run" + exit $EX_NOINPUT + fi + fi +fi + +##### --threads +if [[ "$threads" -lt 1 ]] ; then + write_status "$USAGE_MESSAGE" + write_status "Illegal thread count: $threads. Specify an integer thread count using the --threads command line argument" + exit $EX_USAGE +fi +if [[ "$threads" -gt 8 ]] ; then + write_status "WARNING: GRIDSS scales sub-linearly at high thread count. Up to 8 threads is the recommended level of parallelism." +fi +write_status "Using $threads worker threads." + +if [[ "$blacklist" == "" ]] ; then + blacklist_arg="" + write_status "Using no blacklist bed. The encode DAC blacklist is recommended for hg19." +elif [[ ! -f $blacklist ]] ; then + write_status "$USAGE_MESSAGE" + write_status "Missing blacklist file $blacklist" + exit $EX_NOINPUT +else + blacklist_arg="BLACKLIST=$blacklist" + write_status "Using blacklist $blacklist" + if [[ "$(tr -d ' \n' <<< "$blacklist_arg")" != "$blacklist_arg" ]] ; then + write_status "blacklist cannot contain whitespace" + exit $EX_USAGE + fi +fi + +if [[ "$jvmheap" == "" ]] ; then + if [[ $threads -gt 8 ]] ; then + write_status "Warning: GRIDSS assembly may stall and run out of memory. with $threads and $jvmheap heap size." + fi +fi + +write_status "Using JVM maximum heap size of $jvmheap for assembly and variant calling." + +config_args="" +if [[ "$config_file" != "" ]] ; then + if [[ ! -f $config_file ]] ; then + write_status "Configuration file $config_file does not exist" + exit $EX_NOINPUT + fi + config_args="CONFIGURATION_FILE=$config_file" +fi + +input_args="" +input_filtered_args="" + +# no longer read in the BAM file list from the end of the arguments list + +nows_labels=$(tr -d ' \n' <<< "$labels") +if [[ "$nows_labels" != "$labels" ]] ; then + write_status "input labels cannot contain whitespace" + exit $EX_USAGE +fi +IFS=',' read -ra LABEL_ARRAY <<< "$nows_labels" +label_count=${#LABEL_ARRAY[@]} + +for label in "${LABEL_ARRAY[@]}" ; do + input_args="$input_args INPUT_LABEL=$label" + input_filtered_args="$input_filtered_args INPUT_LABEL=$label" + #write_status "label is $label" +done + +nows_bams=$(tr -d ' \n' <<< "$bams") +if [[ "$nows_bams" != "$bams" ]] ; then + write_status "input filtered BAMs cannot contain whitespace" + exit $EX_USAGE +fi +IFS=',' read -ra BAM_ARRAY <<< "$nows_bams" +for bam_file in "${BAM_ARRAY[@]}" ; do + + if [[ "$(basename $bam_file)" == "$(basename $assembly)" ]] ; then + write_status "assembly and input filtered bam files must have different filenames" + exit $EX_USAGE + fi + + input_args="$input_args INPUT=$bam_file" + # write_status "full bam file is $bam_file" +done + +nows_bams=$(tr -d ' \n' <<< "$filtered_bams") +if [[ "$nows_bams" != "$filtered_bams" ]] ; then + write_status "input filtered BAMs cannot contain whitespace" + exit $EX_USAGE +fi +IFS=',' read -ra FILT_BAM_ARRAY <<< "$nows_bams" +for filtered_bam_file in "${FILT_BAM_ARRAY[@]}" ; do + + if [[ "$(basename $filtered_bam_file)" == "$(basename $assembly)" ]] ; then + write_status "assembly and input filtered bam files must have different filenames" + exit $EX_USAGE + fi + + input_filtered_args="$input_filtered_args INPUT=$filtered_bam_file" + # write_status "filtered bam file is $filtered_bam_file" +done + +for (( i=0; i < $label_count; ++i )) +do + write_status "Label $i: name=${LABEL_ARRAY[$i]} full-bam=${BAM_ARRAY[$i]} filtered-bam=${FILT_BAM_ARRAY[$i]}" +done + +write_status "Full BAM args: $input_args" +write_status "Filtered BAM args: $input_filtered_args" + + +# Validate tools exist on path +for tool in Rscript samtools java bwa ; do #minimap2 + if ! which $tool >/dev/null; then + write_status "Error: unable to find $tool on \$PATH" + exit $EX_CONFIG + fi + write_status "Found $(which $tool)" +done +if $(samtools --version-only >/dev/null) ; then + write_status "samtools version: $(samtools --version-only 2>&1)" +else + write_status "Your samtools version does not support --version-only. Update samtools." + exit $EX_CONFIG +fi +if [[ "$(samtools --version-only)" =~ ^([0-9]+)[.]([0-9]+) ]] ; then + samtools_major_version=${BASH_REMATCH[1]} + samtools_minor_version=${BASH_REMATCH[2]} + if [[ "$samtools_major_version" -le 1 ]] && [[ "$samtools_minor_version" -lt 10 ]] ; then + write_status "samtools 1.13 or later is required." + exit $EX_CONFIG + fi +else + write_status "Unable to determine samtools version" + exit $EX_CONFIG +fi + +# write_status "R version: $(Rscript --version 2>&1)" + +write_status "bwa $(bwa 2>&1 | grep Version || echo -n)" + +if [[ "$timecmd" != "" ]] ; then + if which /usr/bin/time >/dev/null ; then + write_status "time version: $(/usr/bin/time --version 2>&1)" + fi +fi +write_status "bash version: $(/bin/bash --version 2>&1 | head -1)" + +# check java version is ok using the gridss.Echo entry point +if java -cp $gridss_jar gridss.Echo ; then + write_status "java version: $(java -version 2>&1 | tr '\n' '\t')" +else + write_status "Unable to run GRIDSS jar - requires java 1.8 or later" + write_status "java version: $(java -version 2>&1)" + exit $EX_CONFIG +fi + +if ! java -Xms$jvmheap -cp $gridss_jar gridss.Echo ; then + write_status "Failure invoking java with --jvmheap parameter of \"$jvmheap\". Specify a JVM heap size (e.g. \"31g\") that is valid for this machine." + exit 1 +fi + +write_status "Max file handles: $(ulimit -n)" 1>&2 + +steps_message="Running GRIDSS steps:" + +for step in $(echo $steps | tr ',' ' ' ) ; do + if [[ "$step" == "all" ]] ; then + do_preprocess=true + do_assemble=true + do_call=true + steps_message="$steps_message all" + elif [[ "$step" == "preprocess" ]] ; then + do_preprocess=true + steps_message="$steps_message pre-process" + elif [[ "$step" == "assemble" ]] ; then + do_assemble=true + steps_message="$steps_message assembly" + elif [[ "$step" == "call" ]] ; then + do_call=true + steps_message="$steps_message call" + else + write_status "Unknown step \"$step\"" + exit $EX_USAGE + fi +done + +write_status "$steps_message" + +# don't keep files +if [[ $keepTempFiles == "true" ]] ; then + rmcmd="echo rm disabled:" + jvm_args="-Dgridss.keepTempFiles=true" +else + rmcmd="rm" + jvm_args="" +fi + +jvm_args="$jvm_args \ + -XX:ParallelGCThreads=$threads \ + -Dsamjdk.reference_fasta=$reference \ + -Dsamjdk.use_async_io_read_samtools=true \ + -Dsamjdk.use_async_io_write_samtools=true \ + -Dsamjdk.use_async_io_write_tribble=true \ + -Dsamjdk.buffer_size=4194304 \ + -Dsamjdk.async_io_read_threads=$threads" + +aligner_args=' + ALIGNER_COMMAND_LINE=null + ALIGNER_COMMAND_LINE=bwa + ALIGNER_COMMAND_LINE=mem + ALIGNER_COMMAND_LINE=-K + ALIGNER_COMMAND_LINE=10000000 + ALIGNER_COMMAND_LINE=-L + ALIGNER_COMMAND_LINE=0,0 + ALIGNER_COMMAND_LINE=-t + ALIGNER_COMMAND_LINE=%3$d + ALIGNER_COMMAND_LINE=%2$s + ALIGNER_COMMAND_LINE=%1$s' + +samtools_sort="samtools sort --no-PG -@ $threads" + +readpairing_args="READ_PAIR_CONCORDANT_PERCENT=null" + + +# set-up reference has been removed since can assume to exist + +#### +# Pre-process for each filtered BAM file +#### + +if [[ $do_preprocess == true ]] ; then + write_status "*** PRE-PROCESS ***" + + for (( i=0; i < $label_count; ++i )) + do + label=${LABEL_ARRAY[$i]} + bam_file=${FILT_BAM_ARRAY[$i]} + write_status "Processing: sample ${LABEL_ARRAY[$i]}, filtered-bam ${FILT_BAM_ARRAY[$i]}" + + dir=$workingdir/$(basename $bam_file).gridss.working + prefix=$dir/$(basename $bam_file) + write_status "Start pre-processing: $bam_file, working dir: $dir, prefix: $prefix" + + tmp_prefix=$workingdir/$(basename $bam_file).gridss.working/tmp.$(basename $bam_file) + mkdir -p $dir + if [[ ! -d $dir ]] ; then + write_status "Unable to create directory $dir" + exit $EX_CANTCREAT + fi + + name_sorted_bam=$tmp_prefix.namedsorted.bam + write_status "Creating name-sorted BAM from $bam_file, writing to $name_sorted_bam" + + $timecmd $samtools_sort -l 1 -n \ + -T $tmp_prefix.namedsorted-tmp \ + -Obam \ + -o ${name_sorted_bam} \ + ${bam_file} + + write_status "Running ComputeSamTags|samtools: $bam_file" + + rm -f $tmp_prefix.coordinate-tmp* + + { $timecmd java -Xmx$otherjvmheap $jvm_args \ + -cp $gridss_jar gridss.ComputeSamTags \ + TMP_DIR=$dir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + COMPRESSION_LEVEL=0 \ + I=$name_sorted_bam \ + O=/dev/stdout \ + WORKER_THREADS=$threads \ + ASSUME_SORTED=true \ + REMOVE_TAGS=aa \ + MODIFICATION_SUMMARY_FILE=$prefix.computesamtags.changes.tsv \ + | $timecmd $samtools_sort \ + -l 1 \ + -T $tmp_prefix.coordinate-tmp \ + -Obam \ + -o $tmp_prefix.coordinate.bam \ + /dev/stdin \ + ; } 1>&2 2>> $logfile + + write_status "Removing name-sorted bam: $tmp_prefix.namedsorted.bam" + $rmcmd $tmp_prefix.namedsorted.bam + + write_status "Running SoftClipsToSplitReads: sample $label, input: $tmp_prefix.coordinate.bam, output: $tmp_prefix.sc2sr.primary.sv.bam" + rm -f $tmp_prefix.sc2sr.suppsorted.sv-tmp* + { $timecmd java -Xmx$otherjvmheap $jvm_args \ + -Dsamjdk.create_index=false \ + -cp $gridss_jar gridss.SoftClipsToSplitReads \ + TMP_DIR=$workingdir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + I=$tmp_prefix.coordinate.bam \ + O=$tmp_prefix.sc2sr.primary.sv.bam \ + COMPRESSION_LEVEL=1 \ + OUTPUT_UNORDERED_RECORDS=$tmp_prefix.sc2sr.supp.sv.bam \ + WORKER_THREADS=$threads \ + $aligner_args \ + && $rmcmd $tmp_prefix.coordinate.bam \ + && $timecmd $samtools_sort \ + -l 1 \ + -T $tmp_prefix.sc2sr.suppsorted.sv-tmp \ + -Obam \ + -o $tmp_prefix.sc2sr.suppsorted.sv.bam \ + $tmp_prefix.sc2sr.supp.sv.bam \ + && $rmcmd $tmp_prefix.sc2sr.supp.sv.bam \ + && $rmcmd -f $prefix.sv.tmp.bam $prefix.sv.tmp.bam.bai \ + && $timecmd samtools merge \ + -c \ + -p \ + --write-index \ + -@ $threads \ + $prefix.sv.tmp.bam \ + $tmp_prefix.sc2sr.primary.sv.bam \ + $tmp_prefix.sc2sr.suppsorted.sv.bam \ + && $rmcmd $tmp_prefix.sc2sr.primary.sv.bam \ + && $rmcmd $tmp_prefix.sc2sr.suppsorted.sv.bam \ + && mv $prefix.sv.tmp.bam $prefix.sv.bam \ + && mv $prefix.sv.tmp.bam.csi $prefix.sv.bam.csi \ + ; } 1>&2 2>> $logfile + + write_status "Produced SV bam:: $prefix.sv.bam" + + # create metrics on the full BAM and then copy these over the metrics made from the filtered BAMs + full_bam_file=${BAM_ARRAY[$i]} + write_status "Running CollectGridssMetrics on $label full BAM $full_bam_file" + + # test_prefix=$prefix.cp + + { $timecmd java -Xmx$otherjvmheap $jvm_args \ + -cp $gridss_jar gridss.analysis.CollectGridssMetrics \ + REFERENCE_SEQUENCE=$reference \ + TMP_DIR=$dir \ + ASSUME_SORTED=true \ + I=$full_bam_file \ + O=$prefix \ + THRESHOLD_COVERAGE=$maxcoverage \ + FILE_EXTENSION=null \ + GRIDSS_PROGRAM=null \ + GRIDSS_PROGRAM=CollectCigarMetrics \ + GRIDSS_PROGRAM=CollectMapqMetrics \ + GRIDSS_PROGRAM=CollectTagMetrics \ + GRIDSS_PROGRAM=CollectIdsvMetrics \ + PROGRAM=null \ + PROGRAM=CollectInsertSizeMetrics \ + STOP_AFTER=$metricsrecords \ + ; } 1>&2 2>> $logfile + + write_status "Complete pre-processing sample: $label" + done + + write_status "*** PRE-PROCESS COMPLETE ***" +fi + +##### +# ASSEMBLY +#### + +assembly_args="ASSEMBLY=$assembly" + +if [[ $do_assemble == true ]] ; then + + write_status "*** ASSEMBLY ***" + write_status "Running AssembleBreakends: writing output to dir $assembly" + { $timecmd java -Xmx$jvmheap $jvm_args \ + -Dgridss.output_to_temp_file=true \ + -cp $gridss_jar gridss.AssembleBreakends \ + JOB_INDEX=0 \ + JOB_NODES=1 \ + TMP_DIR=$workingdir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + WORKER_THREADS=$threads \ + $input_filtered_args \ + $blacklist_arg \ + $config_args \ + $readpairing_args \ + O=$assembly \ + ; } 1>&2 2>> $logfile + + write_status "AssemblyBreakends complete" + + dir=$workingdir/$(basename $assembly).gridss.working/ + prefix=$dir/$(basename $assembly) + tmp_prefix=$dir/tmp.$(basename $assembly) + + write_status "RunningSoftClipsToSplitReads: running on assembly output dir $assembly" + rm -f $tmp_prefix.sc2sr.suppsorted.sv-tmp* + { $timecmd java -Xmx$otherjvmheap $jvm_args \ + -Dgridss.async.buffersize=16 \ + -Dsamjdk.create_index=false \ + -Dgridss.output_to_temp_file=true \ + -cp $gridss_jar gridss.SoftClipsToSplitReads \ + TMP_DIR=$dir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + WORKER_THREADS=$threads \ + I=$assembly \ + O=$tmp_prefix.sc2sr.primary.sv.bam \ + OUTPUT_UNORDERED_RECORDS=$tmp_prefix.sc2sr.supp.sv.bam \ + REALIGN_ENTIRE_READ=true \ + READJUST_PRIMARY_ALIGNMENT_POSITION=true \ + $aligner_args \ + && $timecmd $samtools_sort \ + -T $tmp_prefix.sc2sr.suppsorted.sv-tmp \ + -Obam \ + -o $tmp_prefix.sc2sr.suppsorted.sv.bam \ + $tmp_prefix.sc2sr.supp.sv.bam \ + && $rmcmd $tmp_prefix.sc2sr.supp.sv.bam \ + && $rmcmd -f $prefix.sv.tmp.bam $prefix.sv.tmp.bam.bai \ + && $timecmd samtools merge \ + -c \ + -p \ + -@ $threads \ + $prefix.sv.tmp.bam \ + $tmp_prefix.sc2sr.primary.sv.bam \ + $tmp_prefix.sc2sr.suppsorted.sv.bam \ + && $timecmd samtools index $prefix.sv.tmp.bam \ + && $rmcmd $tmp_prefix.sc2sr.primary.sv.bam \ + && $rmcmd $tmp_prefix.sc2sr.suppsorted.sv.bam \ + && mv $prefix.sv.tmp.bam $prefix.sv.bam \ + && mv $prefix.sv.tmp.bam.bai $prefix.sv.bam.bai \ + ; } 1>&2 2>> $logfile + + write_status "Produced assembly BAM: $prefix.sv.bam" + + write_status "Complete Assembly" + + # no idea why this is a for loop, could just be: ASSEMBLY=$assembly + #assembly_args="" + #for ass in $assembly ; do + # assembly_args="$assembly_args ASSEMBLY=$ass" + #done + write_status "Assembly args: $assembly_args" + + write_status "*** ASSEMBLY COMPLETE ***" +fi + +#### +# VARIANT CALLING +#### + +if [[ $do_call == true ]] ; then + write_status "*** VARIANT CALLING ***" + + write_status "Creating variant VCF: $output_vcf" + + dir=$workingdir/$(basename $output_vcf).gridss.working + prefix=$dir/$(basename $output_vcf) + mkdir -p $dir + if [[ ! -d $dir ]] ; then + write_status "Unable to create directory $dir" + exit $EX_CANTCREAT + fi + + # create symbolic links to the full BAM as though they were produced by the pre-process step + # eg: ./gridss_02/COLO829R.bam.gridss.working/COLO829R.bam.sv.bam + for (( i=0; i < $label_count; ++i )) + do + bam_file=${BAM_ARRAY[$i]} + bam_dir=$workingdir/$(basename $bam_file).gridss.working + + if [[ ! -d $bam_dir ]] ; then + mkdir -p $bam_dir + fi + + sv_bam_file=$bam_dir/$(basename $bam_file).sv.bam + # write_status "Making soft-link to ${sv_bam_file}" + #ln -sfr ${bam_file} ${sv_bam_file} + #ln -sfr ${bam_file}.bai ${sv_bam_file}.bai + done + + write_status "Running IdentifyVariants" + { $timecmd java -Xmx$jvmheap $jvm_args \ + -Dgridss.output_to_temp_file=true \ + -cp $gridss_jar gridss.IdentifyVariants \ + TMP_DIR=$workingdir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + WORKER_THREADS=$threads \ + $input_filtered_args \ + $blacklist_arg \ + $config_args \ + $assembly_args \ + OUTPUT_VCF=$prefix.unallocated.vcf \ + $readpairing_args \ + ; } 1>&2 2>> $logfile + write_status "IdentifyVariants complete, produced $prefix.unallocated.vcf" + + write_status "Running AnnotateVariants" + { $timecmd java -Xmx$jvmheap $jvm_args \ + -Dgridss.output_to_temp_file=true \ + -Dgridss.async.buffersize=2048 \ + -cp $gridss_jar gridss.AnnotateVariants \ + TMP_DIR=$workingdir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + WORKER_THREADS=$threads \ + $input_filtered_args \ + $blacklist_arg \ + $config_args \ + $assembly_args \ + INPUT_VCF=$prefix.unallocated.vcf \ + OUTPUT_VCF=$prefix.allocated.vcf \ + $readpairing_args \ + ; } 1>&2 2>> $logfile + $rmcmd $prefix.unallocated.vcf + write_status "AnnotateVariants complete, produced $prefix.allocated.vcf" + + write_status "Running AnnotateInsertedSequence" + + { $timecmd java -Xmx$otherjvmheap $jvm_args \ + -Dgridss.output_to_temp_file=true \ + -cp $gridss_jar gridss.AnnotateInsertedSequence \ + TMP_DIR=$workingdir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + WORKER_THREADS=$threads \ + INPUT=$prefix.allocated.vcf \ + OUTPUT=$output_vcf \ + && $rmcmd $prefix.allocated.vcf \ + ; } 1>&2 2>> $logfile + write_status "AnnotateInsertedSequence complete, produced $output_vcf" + + write_status "*** VARIANT CALLING COMPLETE ***" +fi + +if [[ -f $logfile ]] ; then + write_status "Run complete with $(grep WARNING $logfile | wc -l) warnings and $(grep ERROR $logfile | wc -l) errors." +fi +trap - EXIT +exit 0 # success! diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf new file mode 100644 index 00000000..4494c361 --- /dev/null +++ b/modules/local/svprep/call/main.nf @@ -0,0 +1,94 @@ +process CALL { + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + path blacklist + + output: + tuple val(meta), path('gridss_call/sv.svprep.gridss.vcf.gz'), emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + def output_dirname = 'gridss_call' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = "--bams ${bams_list.join(',')}" + def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] + def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" + + """ + # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation + # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + shadow_input_directory() { + src=\${1} + dst="${output_dirname}/" + for filepath_src in \$(find -L \${src} ! -type d); do + # Get destination location for symlink + filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) + filepath_dst=\${dst%/}/\${filepath_src_rel} + # Create directory for symlink + mkdir -p \${filepath_dst%/*}; + # Get path for symlink source file, then create it + # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only + # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers + symlinkpath=\$(realpath \${filepath_src}) + ln -s \${symlinkpath} \${filepath_dst}; + done + if [[ -L "\${src##*/}" ]]; then + rm "\${src}" + fi + } + shadow_input_directory ${assemble_dir} + + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + # Run + gridss_svprep \\ + ${args} \\ + --jvmheap "${task.memory.giga}g" \\ + --jar "${task.ext.jarPath}" \\ + --steps call \\ + --labels "${labels_arg}" \\ + --reference "${genome_fa}" \\ + --blacklist "${blacklist}" \\ + --workingdir "${output_dirname}/work/" \\ + --assembly "${output_dirname}/sv_assemblies.bam" \\ + --output "${output_dirname}/sv.svprep.gridss.vcf.gz" \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + ${bams_arg} \\ + ${bams_filtered_arg} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_call/ + cat < gridss_call/sv.svprep.gridss.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf new file mode 100644 index 00000000..7e78ff20 --- /dev/null +++ b/modules/local/svprep/depth_annotator/main.nf @@ -0,0 +1,47 @@ +process DEPTH_ANNOTATOR { + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bams), path(bais), path(vcf), val(labels) + path genome_fa + val genome_ver + + output: + tuple val(meta), path("*.vcf.gz"), emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = "${bams_list.join(',')}" + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -cp "${task.ext.jarPath}" com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ + ${args} \\ + -input_vcf ${vcf} \\ + -output_vcf sv.svprep.gridss.depths.vcf.gz \\ + -samples "${labels_arg}" \\ + -bam_files "${bams_arg}" \\ + -ref_genome ${genome_fa} \\ + -ref_genome_version ${genome_ver} \\ + -threads ${task.cpus} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + svprep: \$(java -jar "${task.ext.jarPath}" 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + END_VERSIONS + """ + + stub: + """ + touch sv_vcf.depths.vcf.gz + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf new file mode 100644 index 00000000..995c949b --- /dev/null +++ b/modules/local/svprep/preprocess/main.nf @@ -0,0 +1,54 @@ +process PREPROCESS { + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bam), path(bam_filtered) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + + output: + tuple val(meta), path("gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/"), emit: preprocess_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + + """ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + gridss_svprep \\ + ${args} \\ + --jvmheap "${task.memory.giga}g" \\ + --jar "${task.ext.jarPath}" \\ + --steps preprocess \\ + --reference "${genome_fa}" \\ + --workingdir gridss_preprocess/ \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + --labels ${meta.id} \\ + --bams ${bam} \\ + --filtered_bams ${bam_filtered} \\ + --output placeholder + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf new file mode 100644 index 00000000..3438b217 --- /dev/null +++ b/modules/local/svprep/svprep/main.nf @@ -0,0 +1,58 @@ +process SVPREP { + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bam), path(bai), path(junctions) + path genome_fa + val genome_ver + path sv_blacklist + path known_fusions + val write_types + val calc_fragment_length + + output: + tuple val(meta), path("*.sorted.bam") , emit: bam + tuple val(meta), path("*.sv_prep.junctions.csv"), emit: junctions + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def write_types_arg = write_types ? "-write_types \'${write_types}\'" : '' + def existing_juction_file_arg = junctions ? "-existing_junction_file ${junctions}" : "" + def calc_fragment_length_arg = calc_fragment_length ? "-calc_fragment_length" : "" + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.id}" \\ + -bam_file "${bam}" \\ + -ref_genome "${genome_fa}" \\ + -ref_genome_version "${genome_ver}" \\ + -blacklist_bed "${sv_blacklist}" \\ + -known_fusion_bed "${known_fusions}" \\ + ${write_types_arg} \\ + ${existing_juction_file_arg} \\ + ${calc_fragment_length_arg} \\ + -threads "${task.cpus}" \\ + -output_dir ./ + + samtools sort -O bam "${meta.id}.sv_prep.bam" -o "${meta.id}.sv_prep.sorted.bam" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sage: \$(java -jar "${task.ext.jarPath}" 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + END_VERSIONS + """ + + stub: + """ + touch "${meta.id}.sv_prep.sorted.bam" + touch "${meta.id}.sv_prep.junctions.csv" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/svprep/svprep/meta.yml b/modules/local/svprep/svprep/meta.yml new file mode 100644 index 00000000..a1b0b77b --- /dev/null +++ b/modules/local/svprep/svprep/meta.yml @@ -0,0 +1,78 @@ +name: "SVPREP" +description: +keywords: + - svprep + - filtering +tools: + - "SVPREP": + description: "" + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/sv-prep" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/sv-prep" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/sv-prep" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample informatio + e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + - tumor_bam: + type: file + description: Tumor BAM file + pattern: "*.{bam}" + - normal_bam: + type: file + description: Normal BAM file + pattern: "*.{bam}" + - tumor_bai: + type: file + description: Tumor BAI file + pattern: "*.{bai}" + - normal_bai: + type: file + description: Normal BAI file + pattern: "*.{bai}" + + + + + + - genome_fa: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_ver: + type: string + description: Reference genome version + - ensembl_data_dir: + type: directory + description: HMF Ensembl Data Cache directory + pattern: "*.{tsv}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + - vcf: + type: file + description: SAGE VCF file + pattern: "*.{vcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/teal/Dockerfile b/modules/local/teal/Dockerfile new file mode 100644 index 00000000..79715d2c --- /dev/null +++ b/modules/local/teal/Dockerfile @@ -0,0 +1,22 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/teal/ && \ + wget -O /opt/teal/teal.jar 'https://github.com/hartwigmedical/hmftools/releases/download/teal-v1.0.1/teal-1.0.1.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + picard && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/teal/main.nf b/modules/local/teal/main.nf new file mode 100644 index 00000000..b37db994 --- /dev/null +++ b/modules/local/teal/main.nf @@ -0,0 +1,52 @@ +process TEAL { + //conda (params.enable_conda ? "bioconda::hmftools-teal=1.0.1" : null) + container 'docker.io/scwatts/teal:1.0.1--2' + + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai), path(tumor_wgs_metrics), path(normal_wgs_metrics), path(cobalt_dir), path(purple_dir) + + output: + tuple val(meta), path('teal/'), emit: teal_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def tumor_args = normal_bam ? """ + -tumor ${meta.get(['sample_name', 'tumor'])} + -tumor_bam ${tumor_bam} + -tumor_wgs_metrics ${tumor_wgs_metrics} + """ : '' + def reference_args = normal_bam ? """ + -reference ${meta.get(['sample_name', 'normal'])} + -reference_bam ${normal_bam} + -reference_wgs_metrics ${normal_wgs_metrics} + """ : '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + ${tumor_args.replaceAll('\n', '')} \\ + ${reference_args.replaceAll('\n', '')} \\ + -cobalt "${cobalt_dir}" \\ + -purple "${purple_dir}" \\ + -threads "${task.cpus}" \\ + -output_dir teal/ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + teal: 1.0.1 + END_VERSIONS + """ + + stub: + """ + mkdir -p teal/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/teal/meta.yml b/modules/local/teal/meta.yml new file mode 100644 index 00000000..74234dba --- /dev/null +++ b/modules/local/teal/meta.yml @@ -0,0 +1,65 @@ +name: "TEAL" +description: TEAL measures telomere content, and estimates telomeric length based on WGS read data +keywords: + - teal + - telomere +tools: + - "TEAL": + description: "TEAL measures telomere content, and estimates telomeric length based on WGS read data." + homepage: "https://github.com/hartwigmedical/hmftools/tree/master/teal" + documentation: "https://github.com/hartwigmedical/hmftools/tree/master/teal" + tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/teal" + doi: "" + licence: "['GPL v3']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + - tumor_bam: + type: file + description: Optional tumor BAM file + pattern: "*.{bam}" + - normal_bam: + type: file + description: Optional normal BAM file + pattern: "*.{bam}" + - tumor_bai: + type: file + description: Tumor BAI file + pattern: "*.{bai}" + - normal_bai: + type: file + description: Normal BAI file + pattern: "*.{bai}" + - tumor_wgs_metrics: + type: file + description: Optional tumor WGS metrics file + - normal_wgs_metrics: + type: file + description: Optional normal WGS metrics file + - cobalt_dir: + type: directory + description: COBALT output directory + - purple_dir: + type: directory + description: PURPLE output directory + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + - teal_dir: + type: directory + description: TEAL output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@scwatts" diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf new file mode 100644 index 00000000..44a7e28e --- /dev/null +++ b/modules/local/virusbreakend/main.nf @@ -0,0 +1,50 @@ +// NOTE(SW): the --db argument for the virusbreakend command must have a trailing slash if it is a +// symlink + +process VIRUSBREAKEND { + container 'docker.io/scwatts/gridss:2.13.2--3' + + input: + tuple val(meta), path(bam) + path virusbreakenddb + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + + output: + tuple val(meta), path("*.summary.tsv"), emit: tsv + path "*.virusbreakend.vcf" , emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + virusbreakend \\ + --jar ${task.ext.jarPath} \\ + --gridssargs "--jvmheap ${task.memory.giga}g" \\ + --threads ${task.cpus} \\ + --db ${virusbreakenddb.toString().replaceAll("/\$", "")}/ \\ + --output ${meta.id}.virusbreakend.vcf \\ + --reference ${genome_fa} \\ + ${bam} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + touch ${meta.id}.virusbreakend.vcf ${meta.id}.summary.tsv + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/virusinterpreter/Dockerfile b/modules/local/virusinterpreter/Dockerfile new file mode 100644 index 00000000..7a330493 --- /dev/null +++ b/modules/local/virusinterpreter/Dockerfile @@ -0,0 +1,22 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/virusinterpreter/ && \ + wget -O /opt/virusinterpreter/virusinterpreter.jar 'https://github.com/hartwigmedical/hmftools/releases/download/virus-interpreter-v1.2/virus-interpreter.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'openjdk >=8' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf new file mode 100644 index 00000000..3ec4479e --- /dev/null +++ b/modules/local/virusinterpreter/main.nf @@ -0,0 +1,45 @@ +process VIRUSINTERPRETER { + container 'docker.io/scwatts/virus_interpreter:1.2--0' + + input: + tuple val(meta), path(virus_tsv), path(purple_purity), path(purple_qc), path(wgs_metrics) + path taxonomy + path virus_reporting + + output: + tuple val(meta), path('virusinterpreter'), emit: virusinterpreter_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + mkdir -p virusinterpreter/ + + java \\ + -Xmx${task.memory.giga}g \\ + -jar ${task.ext.jarPath} \\ + -sample_id ${meta.get(['sample_name', 'tumor'])} \\ + -purple_purity_tsv ${purple_purity} \\ + -purple_qc_file ${purple_qc} \\ + -tumor_sample_wgs_metrics_file ${wgs_metrics} \\ + -virus_breakend_tsv ${virus_tsv} \\ + -taxonomy_db_tsv ${taxonomy} \\ + -virus_reporting_db_tsv ${virus_reporting} \\ + -output_dir ./virusinterpreter/ + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + "virus interpreter": \$(java -jar "${task.ext.jarPath}" | sed -n '1s/^.*Interpreter v//p') + END_VERSIONS + """ + + stub: + """ + mkdir virusinterpreter/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/nf-core/bwa/index/main.nf b/modules/nf-core/bwa/index/main.nf new file mode 100644 index 00000000..6d70fc15 --- /dev/null +++ b/modules/nf-core/bwa/index/main.nf @@ -0,0 +1,51 @@ +process BWA_INDEX { + tag "$fasta" + label 'process_single' + + conda (params.enable_conda ? "bioconda::bwa=0.7.17" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bwa:0.7.17--hed695b0_7' : + 'quay.io/biocontainers/bwa:0.7.17--hed695b0_7' }" + + input: + tuple val(meta), path(fasta) + + output: + tuple val(meta), path(bwa) , emit: index + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + mkdir bwa + bwa \\ + index \\ + $args \\ + -p bwa/${fasta.baseName} \\ + $fasta + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + END_VERSIONS + """ + + stub: + """ + mkdir bwa + + touch bwa/genome.amb + touch bwa/genome.ann + touch bwa/genome.bwt + touch bwa/genome.pac + touch bwa/genome.sa + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/bwa/index/meta.yml b/modules/nf-core/bwa/index/meta.yml new file mode 100644 index 00000000..2c6cfcd7 --- /dev/null +++ b/modules/nf-core/bwa/index/meta.yml @@ -0,0 +1,42 @@ +name: bwa_index +description: Create BWA index for reference genome +keywords: + - index + - fasta + - genome + - reference +tools: + - bwa: + description: | + BWA is a software package for mapping DNA sequences against + a large reference genome, such as the human genome. + homepage: http://bio-bwa.sourceforge.net/ + documentation: http://www.htslib.org/doc/samtools.html + arxiv: arXiv:1303.3997 + licence: ["GPL-3.0-or-later"] +input: + - meta: + type: map + description: | + Groovy Map containing reference information. + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: Input genome fasta file +output: + - meta: + type: map + description: | + Groovy Map containing reference information. + e.g. [ id:'test', single_end:false ] + - index: + type: file + description: BWA genome index files + pattern: "*.{amb,ann,bwt,pac,sa}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@maxulysse" diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf b/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf new file mode 100644 index 00000000..327d5100 --- /dev/null +++ b/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf @@ -0,0 +1,24 @@ +process CUSTOM_DUMPSOFTWAREVERSIONS { + label 'process_low' + + // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container + conda (params.enable_conda ? "bioconda::multiqc=1.11" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/multiqc:1.11--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.11--pyhdfd78af_0' }" + + input: + path versions + + output: + path "software_versions.yml" , emit: yml + path "software_versions_mqc.yml", emit: mqc_yml + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + template 'dumpsoftwareversions.py' +} diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml new file mode 100644 index 00000000..60b546a0 --- /dev/null +++ b/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml @@ -0,0 +1,34 @@ +name: custom_dumpsoftwareversions +description: Custom module used to dump software versions within the nf-core pipeline template +keywords: + - custom + - version +tools: + - custom: + description: Custom module used to dump software versions within the nf-core pipeline template + homepage: https://github.com/nf-core/tools + documentation: https://github.com/nf-core/tools + licence: ["MIT"] +input: + - versions: + type: file + description: YML file containing software versions + pattern: "*.yml" + +output: + - yml: + type: file + description: Standard YML file containing software versions + pattern: "software_versions.yml" + - mqc_yml: + type: file + description: MultiQC custom content YML file containing software versions + pattern: "software_versions_mqc.yml" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@drpatelh" + - "@grst" diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py new file mode 100644 index 00000000..d1390392 --- /dev/null +++ b/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +import yaml +import platform +from textwrap import dedent + + +def _make_versions_html(versions): + html = [ + dedent( + """\\ + + + + + + + + + + """ + ) + ] + for process, tmp_versions in sorted(versions.items()): + html.append("") + for i, (tool, version) in enumerate(sorted(tmp_versions.items())): + html.append( + dedent( + f"""\\ + + + + + + """ + ) + ) + html.append("") + html.append("
Process Name Software Version
{process if (i == 0) else ''}{tool}{version}
") + return "\\n".join(html) + + +versions_this_module = {} +versions_this_module["${task.process}"] = { + "python": platform.python_version(), + "yaml": yaml.__version__, +} + +with open("$versions") as f: + versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module + +# aggregate versions by the module name (derived from fully-qualified process name) +versions_by_module = {} +for process, process_versions in versions_by_process.items(): + module = process.split(":")[-1] + try: + assert versions_by_module[module] == process_versions, ( + "We assume that software versions are the same between all modules. " + "If you see this error-message it means you discovered an edge-case " + "and should open an issue in nf-core/tools. " + ) + except KeyError: + versions_by_module[module] = process_versions + +versions_by_module["Workflow"] = { + "Nextflow": "$workflow.nextflow.version", + "$workflow.manifest.name": "$workflow.manifest.version", +} + +versions_mqc = { + "id": "software_versions", + "section_name": "${workflow.manifest.name} Software Versions", + "section_href": "https://github.com/${workflow.manifest.name}", + "plot_type": "html", + "description": "are collected at run time from the software output.", + "data": _make_versions_html(versions_by_module), +} + +with open("software_versions.yml", "w") as f: + yaml.dump(versions_by_module, f, default_flow_style=False) +with open("software_versions_mqc.yml", "w") as f: + yaml.dump(versions_mqc, f, default_flow_style=False) + +with open("versions.yml", "w") as f: + yaml.dump(versions_this_module, f, default_flow_style=False) diff --git a/modules/nf-core/modules/picard/collectwgsmetrics/main.nf b/modules/nf-core/modules/picard/collectwgsmetrics/main.nf new file mode 100644 index 00000000..2b0aeefe --- /dev/null +++ b/modules/nf-core/modules/picard/collectwgsmetrics/main.nf @@ -0,0 +1,56 @@ +process PICARD_COLLECTWGSMETRICS { + tag "$meta.id" + label 'process_medium' + + conda (params.enable_conda ? "bioconda::picard=2.27.4 r::r-base" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/picard:2.27.4--hdfd78af_0' : + 'quay.io/biocontainers/picard:2.27.4--hdfd78af_0' }" + + input: + tuple val(meta), path(bam) + path fasta + + output: + tuple val(meta), path("*_metrics"), emit: metrics + 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 avail_mem = 3 + if (!task.memory) { + log.info '[Picard CollectWgsMetrics] Available memory not known - defaulting to 3GB. Specify process memory requirements to change this.' + } else { + avail_mem = task.memory.giga + } + """ + picard \\ + -Xmx${avail_mem}g \\ + CollectWgsMetrics \\ + $args \\ + --INPUT $bam \\ + --OUTPUT ${prefix}.CollectWgsMetrics.coverage_metrics \\ + --REFERENCE_SEQUENCE ${fasta} + + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + picard: \$(picard CollectWgsMetrics --version 2>&1 | grep -o 'Version.*' | cut -f2- -d:) + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.CollectWgsMetrics.coverage_metrics + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + picard: \$(picard CollectWgsMetrics --version 2>&1 | grep -o 'Version.*' | cut -f2- -d:) + END_VERSIONS + """ +} diff --git a/modules/nf-core/modules/picard/collectwgsmetrics/meta.yml b/modules/nf-core/modules/picard/collectwgsmetrics/meta.yml new file mode 100644 index 00000000..d6c3d012 --- /dev/null +++ b/modules/nf-core/modules/picard/collectwgsmetrics/meta.yml @@ -0,0 +1,47 @@ +name: picard_collectwgsmetrics +description: Collect metrics about coverage and performance of whole genome sequencing (WGS) experiments. +keywords: + - alignment + - metrics + - statistics + - quality + - bam +tools: + - picard: + description: | + A set of command line tools (in Java) for manipulating high-throughput sequencing (HTS) + data and formats such as SAM/BAM/CRAM and VCF. + homepage: https://broadinstitute.github.io/picard/ + documentation: https://broadinstitute.github.io/picard/ + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - fasta: + type: file + description: Genome fasta file +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - metrics: + type: file + description: Alignment metrics files generated by picard + pattern: "*_{metrics}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@flowuenne" + - "@lassefolkersen" diff --git a/modules/nf-core/samtools/dict/main.nf b/modules/nf-core/samtools/dict/main.nf new file mode 100644 index 00000000..1b8a4f17 --- /dev/null +++ b/modules/nf-core/samtools/dict/main.nf @@ -0,0 +1,44 @@ +process SAMTOOLS_DICT { + tag "$fasta" + label 'process_single' + + conda (params.enable_conda ? "bioconda::samtools=1.16.1" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + + input: + tuple val(meta), path(fasta) + + output: + tuple val(meta), path ("*.dict"), emit: dict + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + samtools \\ + dict \\ + $args \\ + $fasta \\ + > ${fasta}.dict + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + """ + touch ${fasta}.dict + cat <<-END_VERSIONS > versions.yml + + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/samtools/dict/meta.yml b/modules/nf-core/samtools/dict/meta.yml new file mode 100644 index 00000000..e3eeccc8 --- /dev/null +++ b/modules/nf-core/samtools/dict/meta.yml @@ -0,0 +1,41 @@ +name: samtools_dict +description: Create a sequence dictionary file from a FASTA file +keywords: + - dict + - fasta +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: FASTA file + pattern: "*.{fa,fasta}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - dict: + type: file + description: FASTA dictionary file + pattern: "*.{dict}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@muffato" diff --git a/modules/nf-core/samtools/faidx/main.nf b/modules/nf-core/samtools/faidx/main.nf new file mode 100644 index 00000000..2830963e --- /dev/null +++ b/modules/nf-core/samtools/faidx/main.nf @@ -0,0 +1,44 @@ +process SAMTOOLS_FAIDX { + tag "$fasta" + label 'process_single' + + conda (params.enable_conda ? "bioconda::samtools=1.16.1" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + + input: + tuple val(meta), path(fasta) + + output: + tuple val(meta), path ("*.fai"), emit: fai + tuple val(meta), path ("*.gzi"), emit: gzi, optional: true + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + samtools \\ + faidx \\ + $args \\ + $fasta + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + """ + touch ${fasta}.fai + cat <<-END_VERSIONS > versions.yml + + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/samtools/faidx/meta.yml b/modules/nf-core/samtools/faidx/meta.yml new file mode 100644 index 00000000..fe2fe9a1 --- /dev/null +++ b/modules/nf-core/samtools/faidx/meta.yml @@ -0,0 +1,47 @@ +name: samtools_faidx +description: Index FASTA file +keywords: + - index + - fasta +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: FASTA file + pattern: "*.{fa,fasta}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fai: + type: file + description: FASTA index file + pattern: "*.{fai}" + - gzi: + type: file + description: Optional gzip index file for compressed inputs + pattern: "*.gzi" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@ewels" + - "@phue" diff --git a/modules/nf-core/star/genomegenerate/main.nf b/modules/nf-core/star/genomegenerate/main.nf new file mode 100644 index 00000000..0fe88cbf --- /dev/null +++ b/modules/nf-core/star/genomegenerate/main.nf @@ -0,0 +1,96 @@ +process STAR_GENOMEGENERATE { + tag "$fasta" + label 'process_high' + + conda (params.enable_conda ? "bioconda::star=2.7.10a bioconda::samtools=1.16.1 conda-forge::gawk=5.1.0" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:1df389393721fc66f3fd8778ad938ac711951107-0' : + 'quay.io/biocontainers/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:1df389393721fc66f3fd8778ad938ac711951107-0' }" + + input: + path fasta + path gtf + + output: + path "star" , emit: index + path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def args_list = args.tokenize() + def memory = task.memory ? "--limitGenomeGenerateRAM ${task.memory.toBytes() - 100000000}" : '' + if (args_list.contains('--genomeSAindexNbases')) { + """ + mkdir star + STAR \\ + --runMode genomeGenerate \\ + --genomeDir star/ \\ + --genomeFastaFiles $fasta \\ + --sjdbGTFfile $gtf \\ + --runThreadN $task.cpus \\ + $memory \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + star: \$(STAR --version | sed -e "s/STAR_//g") + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') + END_VERSIONS + """ + } else { + """ + samtools faidx $fasta + NUM_BASES=`gawk '{sum = sum + \$2}END{if ((log(sum)/log(2))/2 - 1 > 14) {printf "%.0f", 14} else {printf "%.0f", (log(sum)/log(2))/2 - 1}}' ${fasta}.fai` + + mkdir star + STAR \\ + --runMode genomeGenerate \\ + --genomeDir star/ \\ + --genomeFastaFiles $fasta \\ + --sjdbGTFfile $gtf \\ + --runThreadN $task.cpus \\ + --genomeSAindexNbases \$NUM_BASES \\ + $memory \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + star: \$(STAR --version | sed -e "s/STAR_//g") + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') + END_VERSIONS + """ + } + + stub: + """ + mkdir star + touch star/Genome + touch star/Log.out + touch star/SA + touch star/SAindex + touch star/chrLength.txt + touch star/chrName.txt + touch star/chrNameLength.txt + touch star/chrStart.txt + touch star/exonGeTrInfo.tab + touch star/exonInfo.tab + touch star/geneInfo.tab + touch star/genomeParameters.txt + touch star/sjdbInfo.txt + touch star/sjdbList.fromGTF.out.tab + touch star/sjdbList.out.tab + touch star/transcriptInfo.tab + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + star: \$(STAR --version | sed -e "s/STAR_//g") + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/star/genomegenerate/meta.yml b/modules/nf-core/star/genomegenerate/meta.yml new file mode 100644 index 00000000..8181157a --- /dev/null +++ b/modules/nf-core/star/genomegenerate/meta.yml @@ -0,0 +1,37 @@ +name: star_genomegenerate +description: Create index for STAR +keywords: + - index + - fasta + - genome + - reference +tools: + - star: + description: | + STAR is a software package for mapping DNA sequences against + a large reference genome, such as the human genome. + homepage: https://github.com/alexdobin/STAR + manual: https://github.com/alexdobin/STAR/blob/master/doc/STARmanual.pdf + doi: 10.1093/bioinformatics/bts635 + licence: ["MIT"] +input: + - fasta: + type: file + description: Fasta file of the reference genome + - gtf: + type: file + description: GTF file of the reference genome + +output: + - index: + type: directory + description: Folder containing the star index files + pattern: "star" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@kevinmenden" + - "@drpatelh" diff --git a/nextflow.config b/nextflow.config index 0eef462b..e73feefd 100644 --- a/nextflow.config +++ b/nextflow.config @@ -1,61 +1,100 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - nf-core/oncoanalyser Nextflow config file + nf-core/hmftools Nextflow config file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Default config options for all compute environments + Default config options for all compute environments ---------------------------------------------------------------------------------------- */ // Global default params, used in configs 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 - // MultiQC options - multiqc_config = null - multiqc_title = null - multiqc_logo = null - max_multiqc_email_size = '25.MB' - multiqc_methods_description = null - - // Boilerplate options - outdir = null - tracedir = "${params.outdir}/pipeline_info" - publish_dir_mode = 'copy' - email = null - email_on_fail = null - plaintext_email = false - monochrome_logs = false - hook_url = null - help = false - validate_params = true - show_hidden_params = false - schema_ignore_params = 'genomes' - enable_conda = false - - - // Config options - custom_config_version = 'master' - custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" - config_profile_description = null - config_profile_contact = null - config_profile_url = null - config_profile_name = null - - - // Max resource options - // Defaults only, expecting to be overwritten - max_memory = '128.GB' - max_cpus = 16 - max_time = '240.h' - + // Input options + input = null + + // Pipeline run type + mode = 'full' + processes_include = '' + processes_exclude = '' + + // Reference data + ref_data_genome_fa = './reference_data/genomes/GRCh38/hg38.fa' + ref_data_genome_version = '38' + + // Reference indices + ref_data_genome_fai = './reference_data/genomes/GRCh38/samtools_index/1.12/hg38.fa.fai' + ref_data_genome_dict = './reference_data/genomes/GRCh38/samtools_index/1.12/hg38.fa.dict' + ref_data_genome_bwa_index = './reference_data/genomes/GRCh38/bwamem2_index/0.7.17-r1188' + ref_data_genome_bwa_index_image = './reference_data/genomes/GRCh38/bwamem2_index_image/0.7.17-r1188/hg38.fa.img' + ref_data_genome_gridss_index = './reference_data/genomes/GRCh38/gridss_index/2.13.2/hg38.fa.gridsscache' + + // AMBER, COBALT + ref_data_amber_loci = './reference_data/hmftools/amber/GermlineHetPon.38.vcf.gz' + ref_data_cobalt_gc_profile = './reference_data/hmftools/cobalt/GC_profile.1000bp.38.cnp' + // CUPPA + ref_data_cuppa = './reference_data/hmftools/cuppa/' + // SVPREP, GRIDSS, GRIPSS + ref_data_sv_prep_blacklist = './reference_data/hmftools/gridss/sv_prep_blacklist.38.bed' + ref_data_gridss_blacklist = './reference_data/hmftools/gridss/ENCFF356LFX.bed.gz' + ref_data_gridss_breakend_pon = './reference_data/hmftools/gridss/gridss_pon_single_breakend.38.bed.gz' + ref_data_gridss_breakpoint_pon = './reference_data/hmftools/gridss/gridss_pon_breakpoint.38.bedpe.gz' + ref_data_repeat_masker_file = './reference_data/hmftools/repeatmasker/38.fa.out.gz' + // Isofox + ref_data_rna_exp_counts = './reference_data/hmftools/isofox/read_100_exp_gc_ratios.csv' + ref_data_rna_exp_gc_ratios = './reference_data/hmftools/isofox/read_151_exp_counts.csv' + // LINX + ref_data_linx_fragile_sites = './reference_data/hmftools/linx/fragile_sites_hmf.38.csv' + ref_data_linx_lines = './reference_data/hmftools/linx/line_elements.38.csv' + // SAGE, PAVE + ref_data_sage_blacklist_bed = './reference_data/hmftools/sage/KnownBlacklist.germline.38.bed' + ref_data_sage_blacklist_vcf = './reference_data/hmftools/sage/KnownBlacklist.germline.38.vcf.gz' + ref_data_sage_coding_panel = './reference_data/hmftools/sage/ActionableCodingPanel.38.bed.gz' + ref_data_sage_high_confidence = './reference_data/hmftools/sage/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz' + ref_data_sage_known_hotspots_germline = './reference_data/hmftools/sage/KnownHotspots.germline.38.vcf.gz' + ref_data_sage_known_hotspots_somatic = './reference_data/hmftools/sage/KnownHotspots.somatic.38.vcf.gz' + ref_data_sage_pon_file = './reference_data/hmftools/sage/SageGermlinePon.98x.38.tsv.gz' + ref_data_clinvar_vcf = './reference_data/hmftools/sage/clinvar.38.vcf.gz' + // LILAC + ref_data_lilac_resource_dir = './reference_data/hmftools/lilac' + // VIRUSBreakend, Virus Interpreter + ref_data_virusbreakenddb = './reference_data/hmftools/virusbreakend/' + ref_data_virus_taxonomy = './reference_data/hmftools/virus_interpreter/taxonomy_db.tsv' + ref_data_virus_reporting = './reference_data/hmftools/virus_interpreter/virus_reporting_db.tsv' + // Misc + ref_data_purple_germline_del = './reference_data/hmftools/purple/cohort_germline_del_freq.38.csv' + ref_data_driver_gene_panel = './reference_data/hmftools/gene_panel/DriverGenePanel.38.tsv' + ref_data_ensembl_data_dir = './reference_data/hmftools/ensembl_data_cache' + ref_data_known_fusion_data = './reference_data/hmftools/known_fusions/known_fusion_data.38.csv' + ref_data_known_fusions = './reference_data/hmftools/known_fusions/known_fusions.38.bedpe' + ref_data_mappability_bed = './reference_data/hmftools/mappability/mappability_150.38.bed.gz' + + // Boilerplate options + outdir = null + tracedir = "${params.outdir}/pipeline_info" + publish_dir_mode = 'symlink' + email = null + email_on_fail = null + plaintext_email = false + monochrome_logs = false + help = false + validate_params = true + show_hidden_params = false + schema_ignore_params = 'genomes' + enable_conda = false + gridss_config = null + + // Config options + custom_config_version = 'master' + custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" + config_profile_description = null + config_profile_contact = null + config_profile_url = null + config_profile_name = null + + // Max resource options + // Defaults only, expecting to be overwritten + max_memory = '128.GB' + max_cpus = 16 + max_time = '240.h' } // Load base.config by default for all pipelines @@ -63,103 +102,79 @@ includeConfig 'conf/base.config' // Load nf-core custom profiles from different Institutions try { - includeConfig "${params.custom_config_base}/nfcore_custom.config" + includeConfig "${params.custom_config_base}/nfcore_custom.config" } catch (Exception e) { - System.err.println("WARNING: Could not load nf-core/config profiles: ${params.custom_config_base}/nfcore_custom.config") + System.err.println("WARNING: Could not load nf-core/config profiles: ${params.custom_config_base}/nfcore_custom.config") } -// Load nf-core/oncoanalyser custom profiles from different institutions. +// Load nf-core/hmftools custom profiles from different institutions. // Warning: Uncomment only if a pipeline-specific instititutional config already exists on nf-core/configs! // try { -// includeConfig "${params.custom_config_base}/pipeline/oncoanalyser.config" +// includeConfig "${params.custom_config_base}/pipeline/hmftools.config" // } catch (Exception e) { -// System.err.println("WARNING: Could not load nf-core/config/oncoanalyser profiles: ${params.custom_config_base}/pipeline/oncoanalyser.config") +// System.err.println("WARNING: Could not load nf-core/config/hmftools profiles: ${params.custom_config_base}/pipeline/hmftools.config") // } - profiles { - debug { process.beforeScript = 'echo $HOSTNAME' } - conda { - params.enable_conda = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - } - mamba { - params.enable_conda = true - conda.useMamba = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - } - docker { - docker.enabled = true - docker.userEmulation = true - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - } - singularity { - singularity.enabled = true - singularity.autoMounts = true - docker.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - } - podman { - podman.enabled = true - docker.enabled = false - singularity.enabled = false - shifter.enabled = false - charliecloud.enabled = false - } - shifter { - shifter.enabled = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - charliecloud.enabled = false - } - charliecloud { - charliecloud.enabled = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - } - gitpod { - executor.name = 'local' - executor.cpus = 16 - executor.memory = 60.GB - } - test { includeConfig 'conf/test.config' } - test_full { includeConfig 'conf/test_full.config' } -} - - -// Load igenomes.config if required -if (!params.igenomes_ignore) { - includeConfig 'conf/igenomes.config' -} else { - params.genomes = [:] + debug { process.beforeScript = 'echo $HOSTNAME' } + conda { + params.enable_conda = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + docker { + docker.enabled = true + docker.userEmulation = true + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + singularity { + singularity.enabled = true + singularity.autoMounts = true + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + podman { + podman.enabled = true + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + shifter { + shifter.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false + } + charliecloud { + charliecloud.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + } + test { includeConfig 'conf/test.config' } + test_full { includeConfig 'conf/test_full.config' } } - // 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. env { - PYTHONNOUSERSITE = 1 - R_PROFILE_USER = "/.Rprofile" - R_ENVIRON_USER = "/.Renviron" - JULIA_DEPOT_PATH = "/usr/local/share/julia" + PYTHONNOUSERSITE = 1 + R_PROFILE_USER = "/.Rprofile" + R_ENVIRON_USER = "/.Renviron" + JULIA_DEPOT_PATH = "/usr/local/share/julia" } // Capture exit codes from upstream processes when piping @@ -167,31 +182,31 @@ process.shell = ['/bin/bash', '-euo', 'pipefail'] def trace_timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') timeline { - enabled = true - file = "${params.tracedir}/execution_timeline_${trace_timestamp}.html" + enabled = true + file = "${params.tracedir}/execution_timeline_${trace_timestamp}.html" } report { - enabled = true - file = "${params.tracedir}/execution_report_${trace_timestamp}.html" + enabled = true + file = "${params.tracedir}/execution_report_${trace_timestamp}.html" } trace { - enabled = true - file = "${params.tracedir}/execution_trace_${trace_timestamp}.txt" + enabled = true + file = "${params.tracedir}/execution_trace_${trace_timestamp}.txt" } dag { - enabled = true - file = "${params.tracedir}/pipeline_dag_${trace_timestamp}.html" + enabled = true + file = "${params.tracedir}/pipeline_dag_${trace_timestamp}.html" } manifest { - name = 'nf-core/oncoanalyser' - author = 'Stephen Watts' - homePage = 'https://github.com/nf-core/oncoanalyser' - description = 'A comprehensive cancer WGS/WTS analysis and reporting pipeline' - mainScript = 'main.nf' - nextflowVersion = '!>=21.10.3' - version = '1.0dev' - doi = '' + name = 'nf-core/hmftools' + author = 'Stephen Watts' + homePage = 'https://github.com/nf-core/hmftools' + defaultBranch = 'main' + description = 'Comprehensive cancer genomics analysis pipeline' + mainScript = 'main.nf' + nextflowVersion = '!>=21.10.3' + version = '1.0dev' } // Load modules.config for DSL2 module specific options @@ -200,32 +215,32 @@ includeConfig 'conf/modules.config' // Function to ensure that resource requirements don't go beyond // a maximum limit def check_max(obj, type) { - if (type == 'memory') { - try { - if (obj.compareTo(params.max_memory as nextflow.util.MemoryUnit) == 1) - return params.max_memory as nextflow.util.MemoryUnit - else - return obj - } catch (all) { - println " ### ERROR ### Max memory '${params.max_memory}' is not valid! Using default value: $obj" - return obj - } - } else if (type == 'time') { - try { - if (obj.compareTo(params.max_time as nextflow.util.Duration) == 1) - return params.max_time as nextflow.util.Duration - else - return obj - } catch (all) { - println " ### ERROR ### Max time '${params.max_time}' is not valid! Using default value: $obj" - return obj - } - } else if (type == 'cpus') { - try { - return Math.min( obj, params.max_cpus as int ) - } catch (all) { - println " ### ERROR ### Max cpus '${params.max_cpus}' is not valid! Using default value: $obj" - return obj - } + if (type == 'memory') { + try { + if (obj.compareTo(params.max_memory as nextflow.util.MemoryUnit) == 1) + return params.max_memory as nextflow.util.MemoryUnit + else + return obj + } catch (all) { + println " ### ERROR ### Max memory '${params.max_memory}' is not valid! Using default value: $obj" + return obj + } + } else if (type == 'time') { + try { + if (obj.compareTo(params.max_time as nextflow.util.Duration) == 1) + return params.max_time as nextflow.util.Duration + else + return obj + } catch (all) { + println " ### ERROR ### Max time '${params.max_time}' is not valid! Using default value: $obj" + return obj + } + } else if (type == 'cpus') { + try { + return Math.min( obj, params.max_cpus as int ) + } catch (all) { + println " ### ERROR ### Max cpus '${params.max_cpus}' is not valid! Using default value: $obj" + return obj } + } } diff --git a/nextflow_schema.json b/nextflow_schema.json index d570597b..f8439c67 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -1,287 +1,503 @@ { - "$schema": "http://json-schema.org/draft-07/schema", - "$id": "https://raw.githubusercontent.com/nf-core/oncoanalyser/master/nextflow_schema.json", - "title": "nf-core/oncoanalyser pipeline parameters", - "description": "A comprehensive cancer WGS/WTS analysis and reporting pipeline", - "type": "object", - "definitions": { - "input_output_options": { - "title": "Input/output options", - "type": "object", - "fa_icon": "fas fa-terminal", - "description": "Define where the pipeline should find input data and save output data.", - "required": ["input", "outdir"], - "properties": { - "input": { - "type": "string", - "format": "file-path", - "mimetype": "text/csv", - "pattern": "^\\S+\\.csv$", - "schema": "assets/schema_input.json", - "description": "Path to comma-separated file containing information about the samples in the experiment.", - "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/oncoanalyser/usage#samplesheet-input).", - "fa_icon": "fas fa-file-csv" - }, - "outdir": { - "type": "string", - "format": "directory-path", - "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", - "fa_icon": "fas fa-folder-open" - }, - "email": { - "type": "string", - "description": "Email address for completion summary.", - "fa_icon": "fas fa-envelope", - "help_text": "Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run.", - "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" - }, - "multiqc_title": { - "type": "string", - "description": "MultiQC report title. Printed as page header, used for filename if not otherwise specified.", - "fa_icon": "fas fa-file-signature" - } - } - }, - "reference_genome_options": { - "title": "Reference genome options", - "type": "object", - "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", - "mimetype": "text/plain", - "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", - "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`." - } - } - }, - "institutional_config_options": { - "title": "Institutional config options", - "type": "object", - "fa_icon": "fas fa-university", - "description": "Parameters used to describe centralised config profiles. These should not be edited.", - "help_text": "The centralised nf-core configuration profiles use a handful of pipeline parameters to describe themselves. This information is then printed to the Nextflow log when you run a pipeline. You should not need to change these values when you run a pipeline.", - "properties": { - "custom_config_version": { - "type": "string", - "description": "Git commit id for Institutional configs.", - "default": "master", - "hidden": true, - "fa_icon": "fas fa-users-cog" - }, - "custom_config_base": { - "type": "string", - "description": "Base directory for Institutional configs.", - "default": "https://raw.githubusercontent.com/nf-core/configs/master", - "hidden": true, - "help_text": "If you're running offline, Nextflow will not be able to fetch the institutional config files from the internet. If you don't need them, then this is not a problem. If you do need them, you should download the files from the repo and tell Nextflow where to find them with this parameter.", - "fa_icon": "fas fa-users-cog" - }, - "config_profile_name": { - "type": "string", - "description": "Institutional config name.", - "hidden": true, - "fa_icon": "fas fa-users-cog" - }, - "config_profile_description": { - "type": "string", - "description": "Institutional config description.", - "hidden": true, - "fa_icon": "fas fa-users-cog" - }, - "config_profile_contact": { - "type": "string", - "description": "Institutional config contact information.", - "hidden": true, - "fa_icon": "fas fa-users-cog" - }, - "config_profile_url": { - "type": "string", - "description": "Institutional config URL link.", - "hidden": true, - "fa_icon": "fas fa-users-cog" - } - } - }, - "max_job_request_options": { - "title": "Max job request options", - "type": "object", - "fa_icon": "fab fa-acquisitions-incorporated", - "description": "Set the top limit for requested resources for any single job.", - "help_text": "If you are running on a smaller system, a pipeline step requesting more resources than are available may cause the Nextflow to stop the run with an error. These options allow you to cap the maximum resources requested by any single job so that the pipeline will run on your system.\n\nNote that you can not _increase_ the resources requested by any job using these options. For that you will need your own configuration file. See [the nf-core website](https://nf-co.re/usage/configuration) for details.", - "properties": { - "max_cpus": { - "type": "integer", - "description": "Maximum number of CPUs that can be requested for any single job.", - "default": 16, - "fa_icon": "fas fa-microchip", - "hidden": true, - "help_text": "Use to set an upper-limit for the CPU requirement for each process. Should be an integer e.g. `--max_cpus 1`" - }, - "max_memory": { - "type": "string", - "description": "Maximum amount of memory that can be requested for any single job.", - "default": "128.GB", - "fa_icon": "fas fa-memory", - "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", - "hidden": true, - "help_text": "Use to set an upper-limit for the memory requirement for each process. Should be a string in the format integer-unit e.g. `--max_memory '8.GB'`" - }, - "max_time": { - "type": "string", - "description": "Maximum amount of time that can be requested for any single job.", - "default": "240.h", - "fa_icon": "far fa-clock", - "pattern": "^(\\d+\\.?\\s*(s|m|h|day)\\s*)+$", - "hidden": true, - "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" - } - } - }, - "generic_options": { - "title": "Generic options", - "type": "object", - "fa_icon": "fas fa-file-import", - "description": "Less common options for the pipeline, typically set in a config file.", - "help_text": "These options are common to all nf-core pipelines and allow you to customise some of the core preferences for how the pipeline runs.\n\nTypically these options would be set in a Nextflow config file loaded for all pipeline runs, such as `~/.nextflow/config`.", - "properties": { - "help": { - "type": "boolean", - "description": "Display help text.", - "fa_icon": "fas fa-question-circle", - "hidden": true - }, - "publish_dir_mode": { - "type": "string", - "default": "copy", - "description": "Method used to save pipeline results to output directory.", - "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", - "fa_icon": "fas fa-copy", - "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], - "hidden": true - }, - "email_on_fail": { - "type": "string", - "description": "Email address for completion summary, only when pipeline fails.", - "fa_icon": "fas fa-exclamation-triangle", - "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$", - "help_text": "An email address to send a summary email to when the pipeline is completed - ONLY sent if the pipeline does not exit successfully.", - "hidden": true - }, - "plaintext_email": { - "type": "boolean", - "description": "Send plain-text email instead of HTML.", - "fa_icon": "fas fa-remove-format", - "hidden": true - }, - "max_multiqc_email_size": { - "type": "string", - "description": "File size limit when attaching MultiQC reports to summary emails.", - "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", - "default": "25.MB", - "fa_icon": "fas fa-file-upload", - "hidden": true - }, - "monochrome_logs": { - "type": "boolean", - "description": "Do not use coloured log outputs.", - "fa_icon": "fas fa-palette", - "hidden": true - }, - "hook_url": { - "type": "string", - "description": "Incoming hook URL for messaging service", - "fa_icon": "fas fa-people-group", - "help_text": "Incoming hook URL for messaging service. Currently, only MS Teams is supported.", - "hidden": true - }, - "multiqc_config": { - "type": "string", - "description": "Custom config file to supply to MultiQC.", - "fa_icon": "fas fa-cog", - "hidden": true - }, - "multiqc_logo": { - "type": "string", - "description": "Custom logo file to supply to MultiQC. File name must also be set in the MultiQC config file", - "fa_icon": "fas fa-image", - "hidden": true - }, - "multiqc_methods_description": { - "type": "string", - "description": "Custom MultiQC yaml file containing HTML including a methods description.", - "fa_icon": "fas fa-cog" - }, - "tracedir": { - "type": "string", - "description": "Directory to keep pipeline Nextflow logs and reports.", - "default": "${params.outdir}/pipeline_info", - "fa_icon": "fas fa-cogs", - "hidden": true - }, - "validate_params": { - "type": "boolean", - "description": "Boolean whether to validate parameters against the schema at runtime", - "default": true, - "fa_icon": "fas fa-check-square", - "hidden": true - }, - "show_hidden_params": { - "type": "boolean", - "fa_icon": "far fa-eye-slash", - "description": "Show all params when using `--help`", - "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." - }, - "enable_conda": { - "type": "boolean", - "description": "Run this workflow with Conda. You can also use '-profile conda' instead of providing this parameter.", - "hidden": true, - "fa_icon": "fas fa-bacon" - } - } + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "https://raw.githubusercontent.com/umccr/hmftools/master/nextflow_schema.json", + "title": "umccr/hmftools pipeline parameters", + "description": "Comprehensive genomic oncogenic analysis pipeline", + "type": "object", + "definitions": { + "input_output_options": { + "title": "Input/output options", + "type": "object", + "fa_icon": "fas fa-terminal", + "description": "Define where the pipeline should find input data and save output data.", + "required": ["input", "outdir"], + "properties": { + "input": { + "type": "string", + "format": "file-path", + "mimetype": "text/tsv", + "pattern": "^\\S+\\.tsv$", + "schema": "assets/schema_input.json", + "description": "Path to comma-separated file containing information about the samples in the experiment.", + "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/hmftools/usage#samplesheet-input).", + "fa_icon": "fas fa-file-tsv" + }, + "outdir": { + "type": "string", + "format": "directory-path", + "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", + "fa_icon": "fas fa-folder-open" + } + } + }, + "other_options": { + "title": "Other options", + "type": "object", + "fa_icon": "fas fa-book", + "description": "Other options specific to this pipeline.", + "properties": { + "email": { + "type": "string", + "description": "Email address for completion summary.", + "fa_icon": "fas fa-envelope", + "help_text": "Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run.", + "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" + }, + "mode": { + "type": "string", + "default": "full", + "description": "Pipeline mode to use.", + "fa_icon": "fas fa-diagram-project" + }, + "gridss_config": { + "type": "string", + "description": "Path to GRIDSS configuration file.", + "fa_icon": "fas fa-cog" + } + } + }, + "reference_data_options": { + "title": "Reference data options", + "type": "object", + "fa_icon": "fas fa-dna", + "description": "Reference data files and options required for the workflow.", + "properties": { + "ref_data_genome_fa": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", + "description": "Path to reference genome FASTA file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_genome_version": { + "type": "string", + "description": "Reference genome version (37 or 38).", + "fa_icon": "far fa-file-code", + "enum": ["37", "38", "38_noalt"] + }, + "ref_data_genome_fai": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.fai$", + "description": "Path to reference genome FAI file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_genome_dict": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.dict$", + "description": "Path to reference genome sequence dictionary file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_genome_bwa_index": { + "type": "string", + "format": "directory-path", + "description": "Path to directory containing reference genome BWA indices.", + "fa_icon": "far fa-file-code" + }, + "ref_data_genome_bwa_index_image": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.img$", + "description": "Path to reference genome BWA indices image file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_genome_gridss_index": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.gridsscache$", + "description": "Path to reference genome GRIDSS index file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_amber_loci": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.vcf\\.gz$", + "description": "Path to AMBER loci file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_cobalt_gc_profile": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.cnp", + "description": "Path to COBALT GC profile file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_cuppa": { + "type": "string", + "format": "directory-path", + "description": "Path to CUPPA reference file directory.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sv_prep_blacklist": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed$", + "description": "Path to SV Prep blacklist file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_gridss_blacklist": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed.gz$", + "description": "Path to GRIDSS blacklist file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_gridss_breakend_pon": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed\\.gz", + "description": "Path to GRIDSS breakend PON file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_gridss_breakpoint_pon": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bedpe\\.gz$", + "description": "Path to GRIDSS breakpoint PON file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_repeat_masker_file": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.fa(\\.out)?\\.gz$", + "description": "Path to RepeatMasker file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_rna_exp_counts": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to Isofox expected read counts file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_rna_exp_gc_ratios": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to Isofox expected GC ratios file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_linx_fragile_sites": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to LINX fragile sites file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_linx_lines": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to LINX LINEs file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_ensembl_data_dir": { + "type": "string", + "format": "directory-path", + "description": "Path to HMF Ensembl Data Cache directory.", + "fa_icon": "far fa-file-code" + }, + "ref_data_lilac_resource_dir": { + "type": "string", + "format": "directory-path", + "description": "Path to LILAC resource directory.", + "fa_icon": "far fa-folder-open" + }, + "ref_data_virusbreakenddb": { + "type": "string", + "format": "directory-path", + "description": "Path to VIRUSBreakend database directory.", + "fa_icon": "far fa-folder-open" + }, + "ref_data_virus_taxonomy": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv$", + "description": "Path to Virus Interpreter taxonomy file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_virus_reporting": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv$", + "description": "Path to Virus Interpreter reporting file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_mappability_bed": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed\\.gz$", + "description": "Path to HMF mappability file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_clinvar_vcf": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.vcf\\.gz$", + "description": "Path to HMF ClinVar file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_blacklist_vcf": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.vcf\\.gz$", + "description": "Path to HMF SAGE Known Blacklist VCF file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_blacklist_bed": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed$", + "description": "Path to HMF SAGE Known Blacklist BED file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_pon_file": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv\\.gz$", + "description": "Path to HMF SAGE Panel of Normals file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_high_confidence": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed\\.gz$", + "description": "Path to HMF distributed High Confidence regions file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_coding_panel": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed\\.gz$", + "description": "Path to somatic SAGE Coding Panel file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_known_hotspots_germline": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.vcf\\.gz$", + "description": "Path to germline SAGE Known Hotspots file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_known_hotspots_somatic": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.vcf\\.gz$", + "description": "Path to somatic SAGE Known Hotspots file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_known_fusions": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bedpe$", + "description": "Path to HMF Known Fusions file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_known_fusion_data": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to HMF Known Fusions Data file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_purple_germline_del": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to HMF PURPLE Germline Cohort Deletion Frequency file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_driver_gene_panel": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv$", + "description": "Path to HMF Driver Gene Panel file.", + "fa_icon": "far fa-file-code" + } + } + }, + "institutional_config_options": { + "title": "Institutional config options", + "type": "object", + "fa_icon": "fas fa-university", + "description": "Parameters used to describe centralised config profiles. These should not be edited.", + "help_text": "The centralised nf-core configuration profiles use a handful of pipeline parameters to describe themselves. This information is then printed to the Nextflow log when you run a pipeline. You should not need to change these values when you run a pipeline.", + "properties": { + "custom_config_version": { + "type": "string", + "description": "Git commit id for Institutional configs.", + "default": "master", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "custom_config_base": { + "type": "string", + "description": "Base directory for Institutional configs.", + "default": "https://raw.githubusercontent.com/nf-core/configs/master", + "hidden": true, + "help_text": "If you're running offline, Nextflow will not be able to fetch the institutional config files from the internet. If you don't need them, then this is not a problem. If you do need them, you should download the files from the repo and tell Nextflow where to find them with this parameter.", + "fa_icon": "fas fa-users-cog" + }, + "config_profile_name": { + "type": "string", + "description": "Institutional config name.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_description": { + "type": "string", + "description": "Institutional config description.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_contact": { + "type": "string", + "description": "Institutional config contact information.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_url": { + "type": "string", + "description": "Institutional config URL link.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + } + } + }, + "max_job_request_options": { + "title": "Max job request options", + "type": "object", + "fa_icon": "fab fa-acquisitions-incorporated", + "description": "Set the top limit for requested resources for any single job.", + "help_text": "If you are running on a smaller system, a pipeline step requesting more resources than are available may cause the Nextflow to stop the run with an error. These options allow you to cap the maximum resources requested by any single job so that the pipeline will run on your system.\n\nNote that you can not _increase_ the resources requested by any job using these options. For that you will need your own configuration file. See [the nf-core website](https://nf-co.re/usage/configuration) for details.", + "properties": { + "max_cpus": { + "type": "integer", + "description": "Maximum number of CPUs that can be requested for any single job.", + "default": 16, + "fa_icon": "fas fa-microchip", + "hidden": true, + "help_text": "Use to set an upper-limit for the CPU requirement for each process. Should be an integer e.g. `--max_cpus 1`" + }, + "max_memory": { + "type": "string", + "description": "Maximum amount of memory that can be requested for any single job.", + "default": "128.GB", + "fa_icon": "fas fa-memory", + "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", + "hidden": true, + "help_text": "Use to set an upper-limit for the memory requirement for each process. Should be a string in the format integer-unit e.g. `--max_memory '8.GB'`" + }, + "max_time": { + "type": "string", + "description": "Maximum amount of time that can be requested for any single job.", + "default": "240.h", + "fa_icon": "far fa-clock", + "pattern": "^(\\d+\\.?\\s*(s|m|h|day)\\s*)+$", + "hidden": true, + "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" } + } }, - "allOf": [ - { - "$ref": "#/definitions/input_output_options" + "generic_options": { + "title": "Generic options", + "type": "object", + "fa_icon": "fas fa-file-import", + "description": "Less common options for the pipeline, typically set in a config file.", + "help_text": "These options are common to all nf-core pipelines and allow you to customise some of the core preferences for how the pipeline runs.\n\nTypically these options would be set in a Nextflow config file loaded for all pipeline runs, such as `~/.nextflow/config`.", + "properties": { + "help": { + "type": "boolean", + "description": "Display help text.", + "fa_icon": "fas fa-question-circle", + "hidden": true + }, + "publish_dir_mode": { + "type": "string", + "default": "copy", + "description": "Method used to save pipeline results to output directory.", + "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", + "fa_icon": "fas fa-copy", + "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], + "hidden": true + }, + "email_on_fail": { + "type": "string", + "description": "Email address for completion summary, only when pipeline fails.", + "fa_icon": "fas fa-exclamation-triangle", + "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$", + "help_text": "An email address to send a summary email to when the pipeline is completed - ONLY sent if the pipeline does not exit successfully.", + "hidden": true }, - { - "$ref": "#/definitions/reference_genome_options" + "plaintext_email": { + "type": "boolean", + "description": "Send plain-text email instead of HTML.", + "fa_icon": "fas fa-remove-format", + "hidden": true }, - { - "$ref": "#/definitions/institutional_config_options" + "max_multiqc_email_size": { + "type": "string", + "description": "File size limit when attaching MultiQC reports to summary emails.", + "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", + "default": "25.MB", + "fa_icon": "fas fa-file-upload", + "hidden": true }, - { - "$ref": "#/definitions/max_job_request_options" + "monochrome_logs": { + "type": "boolean", + "description": "Do not use coloured log outputs.", + "fa_icon": "fas fa-palette", + "hidden": true }, - { - "$ref": "#/definitions/generic_options" + "tracedir": { + "type": "string", + "description": "Directory to keep pipeline Nextflow logs and reports.", + "default": "${params.outdir}/pipeline_info", + "fa_icon": "fas fa-cogs", + "hidden": true + }, + "validate_params": { + "type": "boolean", + "description": "Boolean whether to validate parameters against the schema at runtime", + "default": true, + "fa_icon": "fas fa-check-square", + "hidden": true + }, + "show_hidden_params": { + "type": "boolean", + "fa_icon": "far fa-eye-slash", + "description": "Show all params when using `--help`", + "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." + }, + "enable_conda": { + "type": "boolean", + "description": "Run this workflow with Conda. You can also use '-profile conda' instead of providing this parameter.", + "hidden": true, + "fa_icon": "fas fa-bacon" } - ] + } + } + }, + "allOf": [ + { + "$ref": "#/definitions/input_output_options" + }, + { + "$ref": "#/definitions/other_options" + }, + { + "$ref": "#/definitions/reference_data_options" + }, + { + "$ref": "#/definitions/institutional_config_options" + }, + { + "$ref": "#/definitions/max_job_request_options" + }, + { + "$ref": "#/definitions/generic_options" + } + ] } diff --git a/subworkflows/local/gridss.nf b/subworkflows/local/gridss.nf new file mode 100644 index 00000000..1e9de67e --- /dev/null +++ b/subworkflows/local/gridss.nf @@ -0,0 +1,129 @@ +// +// GRIDSS is a software suite containing tools useful for the detection of genomic rearrangements. +// + +include { ASSEMBLE } from '../../modules/local/gridss/assemble/main' +include { CALL } from '../../modules/local/gridss/call/main' +include { PREPROCESS } from '../../modules/local/gridss/preprocess/main' + +workflow GRIDSS { + take: + ch_inputs // channel: [val(meta), bam_tumor, bam_normal] + gridss_config // file: /path/to/gridss_config (optional) + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_dict // file: /path/to/genome_dict + ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ + ref_data_genome_bwa_index_image // file: /path/to/genome_bwa_index_image + ref_data_genome_gridss_index // file: /path/to/genome_gridss_index + ref_data_gridss_blacklist // val: /path/to/gridss_blacklist + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Build a channel of individual BAMs for preprocessing + // channel: [val(meta_gridss), bam] + ch_preprocess_inputs = ch_inputs + .flatMap { meta, tbam, nbam -> + def bam_map = ['tumor': tbam, 'normal': nbam] + bam_map + .keySet() + .collect { sample_type -> + def meta_gridss = [ + id: meta.get(['sample_name', sample_type]), + sample_type: sample_type, + subject_id: meta.id, + ] + return [meta_gridss, bam_map[sample_type]] + } + } + + // Preprocess reads + PREPROCESS( + ch_preprocess_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ) + ch_versions = ch_versions.mix(PREPROCESS.out.versions) + + // Gather BAMs and outputs from preprocessing for each tumor/normal set + // channel: [subject_id, [[val(meta_gridss), bam, preprocess_dir], ...]] + ch_bams_and_preprocess = WorkflowHmftools.group_by_meta( + ch_preprocess_inputs, + PREPROCESS.out.preprocess_dir, + ) + .map { [it[0].subject_id, it] } + .groupTuple(size: 2) + + // Order and organise inputs for assembly + // channel: [val(meta_gridss), [bams], [preprocess_dirs], [labels]] + ch_assemble_inputs = ch_bams_and_preprocess + .map { subject_id, entries -> + def (tmeta, tbam, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } + def (nmeta, nbam, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } + def meta_gridss = [id: tmeta.subject_id] + return [meta_gridss, [nbam, tbam], [npreprocess, tpreprocess], [nmeta.id, tmeta.id]] + } + + // Assemble variants + ASSEMBLE( + ch_assemble_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ) + ch_versions = ch_versions.mix(ASSEMBLE.out.versions) + + // Prepare inputs for variant calling + // channel: [val(meta_gridss), [bams], assemble_dir, [labels]] + ch_call_inputs = WorkflowHmftools.group_by_meta( + ch_assemble_inputs, + ASSEMBLE.out.assemble_dir, + flatten: false, + ) + .map { data -> + def meta = data[0] + def (bams, preprocess_dirs, labels) = data[1] + def (assemble_dir) = data[2] + return [meta, bams, assemble_dir, labels] + } + + // Call variants + CALL( + ch_call_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ) + ch_versions = ch_versions.mix(CALL.out.versions) + + // Reunite final VCF with the corresponding input meta object + ch_out = Channel.empty() + .concat( + ch_inputs.map { meta, tbam, nbam -> [meta.id, meta] }, + CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + ) + .groupTuple(size: 2) + .map { id, other -> other.flatten() } + + emit: + results = ch_out // channel: [val(meta), vcf] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep.nf new file mode 100644 index 00000000..6b83f16d --- /dev/null +++ b/subworkflows/local/gridss_svprep.nf @@ -0,0 +1,216 @@ +// +// SV Prep is a BAM filter designed to select only reads relevant to SV events run prior to GRIDSS. +// GRIDSS is a software suite containing tools useful for the detection of genomic rearrangements. +// + +include { ASSEMBLE as GRIDSS_ASSEMBLE } from '../../modules/local/svprep/assemble/main' +include { CALL as GRIDSS_CALL } from '../../modules/local/svprep/call/main' +include { PREPROCESS as GRIDSS_PREPROCESS } from '../../modules/local/svprep/preprocess/main' +include { SVPREP as SVPREP_NORMAL } from '../../modules/local/svprep/svprep/main' +include { SVPREP as SVPREP_TUMOR } from '../../modules/local/svprep/svprep/main' +include { DEPTH_ANNOTATOR as SVPREP_DEPTH_ANNOTATOR } from '../../modules/local/svprep/depth_annotator/main' + +workflow GRIDSS_SVPREP { + take: + ch_inputs // channel: [val(meta)] + gridss_config // file: /path/to/gridss_config (optional) + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_version // val: genome version + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_dict // file: /path/to/genome_dict + ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ + ref_data_genome_bwa_index_image // file: /path/to/genome_bwa_index_image + ref_data_genome_gridss_index // file: /path/to/genome_gridss_index + ref_data_gridss_blacklist // val: /path/to/gridss_blacklist + ref_data_sv_prep_blacklist // file: /path/to/sv_prep_blacklist + ref_data_known_fusions // file: /path/to/known_fusions + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Prepare tumor sample inputs + // channel: [val(meta_svprep), bam, bai, []] + ch_svprep_tumor_inputs = ch_inputs + .map { meta -> + def meta_svprep = [id: meta.get(['sample_name', 'tumor']), meta_full: meta] + def bam = meta.get(['bam_wgs', 'tumor']) + def bai = "${bam}.bai" + return [meta_svprep, bam, bai, []] + } + + // Filter tumor BAM + SVPREP_TUMOR( + ch_svprep_tumor_inputs, + ref_data_genome_fa, + ref_data_genome_version, + ref_data_sv_prep_blacklist, + ref_data_known_fusions, + 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument switch and value + false, // -calc_fragment_length argument switch + ) + ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) + + // Prepare normal sample inputs + // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] + ch_svprep_normal_inputs = SVPREP_TUMOR.out.junctions + .map { meta_tumor_svprep, junctions_tumor -> + def meta = meta_tumor_svprep['meta_full'] + def meta_svprep = [id: meta.get(['sample_name', 'normal']), meta_full: meta] + def bam_normal = meta.get(['bam_wgs', 'normal']) + return [meta_svprep, bam_normal, "${bam_normal}.bai", junctions_tumor] + } + + SVPREP_NORMAL( + ch_svprep_normal_inputs, + ref_data_genome_fa, + ref_data_genome_version, + ref_data_sv_prep_blacklist, + ref_data_known_fusions, + false, // -write_types argument switch and value + true, // -calc_fragment_length argument switch + ) + ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) + + ch_preprocess_inputs_tumor = WorkflowHmftools.group_by_meta( + SVPREP_TUMOR.out.bam, + ch_svprep_tumor_inputs, + ) + .map { meta_svprep, bam_filtered, bam, bai -> + def meta_gridss = [ + id: meta_svprep.id, + sample_type: 'tumor', + subject_id: meta_svprep.meta_full.id, + ] + return [meta_gridss, bam, bam_filtered] + } + + ch_preprocess_inputs_normal = WorkflowHmftools.group_by_meta( + SVPREP_NORMAL.out.bam, + ch_svprep_normal_inputs, + ) + .map { meta_svprep, bam_filtered, bam, bai, junctions -> + def meta_gridss = [ + id: meta_svprep.id, + sample_type: 'normal', + subject_id: meta_svprep.meta_full.id, + ] + return [meta_gridss, bam, bam_filtered] + } + + ch_preprocess_inputs = Channel.empty() + .mix( + ch_preprocess_inputs_tumor, + ch_preprocess_inputs_normal, + ) + + // Preprocess reads + GRIDSS_PREPROCESS( + ch_preprocess_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ) + ch_versions = ch_versions.mix(GRIDSS_PREPROCESS.out.versions) + + // Gather BAMs and outputs from preprocessing for each tumor/normal set + // channel: [subject_id, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] + ch_bams_and_preprocess = WorkflowHmftools.group_by_meta( + ch_preprocess_inputs, + GRIDSS_PREPROCESS.out.preprocess_dir, + ) + .map { [it[0].subject_id, it] } + .groupTuple(size: 2) + + // Order and organise inputs for assembly + // channel: [val(meta_gridss), [bams], [bams_filtered], [preprocess_dirs], [labels]] + ch_assemble_inputs = ch_bams_and_preprocess + .map { subject_id, entries -> + def (tmeta, tbam, tbam_filtered, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } + def (nmeta, nbam, nbam_filtered, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } + def meta_gridss = [id: tmeta.subject_id] + return [ + meta_gridss, + [nbam, tbam], + [nbam_filtered, tbam_filtered], + [npreprocess, tpreprocess], + [nmeta.id, tmeta.id], + ] + } + + // Assemble variants + GRIDSS_ASSEMBLE( + ch_assemble_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ) + ch_versions = ch_versions.mix(GRIDSS_ASSEMBLE.out.versions) + + // Prepare inputs for variant calling + // channel: [val(meta_gridss), [bams], [bams_filtered], assemble_dir, [labels]] + ch_call_inputs = WorkflowHmftools.group_by_meta( + ch_assemble_inputs, + GRIDSS_ASSEMBLE.out.assemble_dir, + flatten: false, + ) + .map { data -> + def meta = data[0] + def (bams, bams_filtered, preprocess_dirs, labels) = data[1] + def (assemble_dir) = data[2] + return [meta, bams, bams_filtered, assemble_dir, labels] + } + + // Call variants + GRIDSS_CALL( + ch_call_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ) + ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) + + // Prepare inputs for depth annotation + // channel: [val(meta), [bams], [bais], vcf, [labels]] + ch_depth_inputs = WorkflowHmftools.group_by_meta( + ch_inputs.map { meta -> [meta.id, meta] }, + GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + ) + .map { id, meta, vcf -> + def tbam = meta.get(['bam_wgs', 'tumor']) + def nbam = meta.get(['bam_wgs', 'normal']) + return [ + meta, + [nbam, tbam], + ["${nbam}.bai", "${tbam}.bai"], + vcf, + [meta.get(['sample_name', 'normal']), meta.get(['sample_name', 'tumor'])], + ] + } + + // Add depth annotations to SVs + SVPREP_DEPTH_ANNOTATOR( + ch_depth_inputs, + ref_data_genome_fa, + ref_data_genome_version, + ) + + emit: + results = SVPREP_DEPTH_ANNOTATOR.out.vcf // channel: [val(meta), vcf] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/gripss.nf b/subworkflows/local/gripss.nf new file mode 100644 index 00000000..405cc415 --- /dev/null +++ b/subworkflows/local/gripss.nf @@ -0,0 +1,66 @@ +// +// GRIPSS performs SV filtering. +// + +include { GRIPSS_GERMLINE } from '../../modules/local/gripss/germline/main' +include { GRIPSS_SOMATIC } from '../../modules/local/gripss/somatic/main' + +workflow GRIPSS { + take: + ch_inputs // channel: [val(meta), gridss_vcf] + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_version // val: genome version + breakend_pon // file: /path/to/breakend_pon + breakpoint_pon // file: /path/to/breakpoint_pon + known_fusions // file: /path/to/known_fusions + repeat_masker_file // file: /path/to/repeat_masker_file + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Germline + GRIPSS_GERMLINE( + ch_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + breakend_pon, + breakpoint_pon, + known_fusions, + repeat_masker_file, + ) + ch_versions = ch_versions.mix(GRIPSS_GERMLINE.out.versions) + + // Somatic + GRIPSS_SOMATIC( + ch_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + breakend_pon, + breakpoint_pon, + known_fusions, + repeat_masker_file, + ) + ch_versions = ch_versions.mix(GRIPSS_SOMATIC.out.versions) + + // Pack output + // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + ch_germline_out = WorkflowHmftools.group_by_meta( + GRIPSS_GERMLINE.out.vcf_hard, + GRIPSS_GERMLINE.out.vcf_soft, + ) + // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + ch_somatic_out = WorkflowHmftools.group_by_meta( + GRIPSS_SOMATIC.out.vcf_hard, + GRIPSS_SOMATIC.out.vcf_soft, + ) + + emit: + germline = ch_germline_out // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + somatic = ch_somatic_out // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf new file mode 100644 index 00000000..b50cda72 --- /dev/null +++ b/subworkflows/local/lilac.nf @@ -0,0 +1,87 @@ +// +// LILAC is a WGS tool for HLA typing and somatic CNV and SNV calling +// + +include { EXTRACT_AND_INDEX_CONTIG } from '../../modules/local/custom/lilac_extract_and_index_contig/main' +include { REALIGN_READS } from '../../modules/local/custom/lilac_realign_reads_lilac/main' +include { SLICE } from '../../modules/local/custom/lilac_slice/main' + +include { LILAC as LILAC_PROCESS } from '../../modules/local/lilac/main' + +workflow LILAC { + take: + ch_inputs_bams // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_inputs_purple_dir // channel: [val(meta), purple_dir] + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_version // val: genome version + ref_data_lilac_resource_dir // file: /path/to/lilac_resource_dir/ + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Slice HLA regions + if (ref_data_genome_version == '38') { + slice_bed = file("${params.ref_data_lilac_resource_dir}/hla.38.alt.umccr.bed", checkIfExists: true) + } else { + slice_bed = file("${params.ref_data_lilac_resource_dir}/hla.${ref_data_genome_version}.bed", checkIfExists: true) + } + // NOTE(SW): here I remove duplicate files so that we only process each input once + // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used + // in Pipeline5, see LilacBamSlicer.java#L115 + // channel: [val(meta_lilac), bam, bai, bed] + ch_slice_inputs = WorkflowLilac.get_slice_inputs(ch_inputs_bams, slice_bed) + // channel: [val(meta_lilac), bam, bai, bed] + ch_slice_inputs = WorkflowLilac.get_unique_input_files(ch_slice_inputs) + SLICE( + ch_slice_inputs, + ) + ch_versions = ch_versions.mix(SLICE.out.versions) + + // Realign contigs if using hg38 (use of ALT contigs implied) + if (ref_data_genome_version == '38') { + // Align reads with chr6 + // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them + // to the three relevant HLA genes on chr6. All reads including those previously mapped to chr6 + // are realigned for consistency. + EXTRACT_AND_INDEX_CONTIG( + 'chr6', + ref_data_genome_fa, + ref_data_genome_fai, + ) + REALIGN_READS( + SLICE.out.bam, + EXTRACT_AND_INDEX_CONTIG.out.contig, + EXTRACT_AND_INDEX_CONTIG.out.bwa_indices, + ) + + // Create input channel for LILAC + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] + ch_lilac_inputs = WorkflowHmftools.group_by_meta( + WorkflowLilac.sort_slices(REALIGN_READS.out.bam), + ch_inputs_purple_dir, + ) + } else { + // Create input channel for LILAC + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] + ch_lilac_inputs = WorkflowHmftools.group_by_meta( + WorkflowLilac.sort_slices(SLICE.out.bam), + ch_inputs_purple_dir, + ) + } + + // Run LILAC + LILAC_PROCESS( + ch_lilac_inputs, + ref_data_genome_fa, + ref_data_genome_version, + ref_data_lilac_resource_dir, + ) + ch_versions = ch_versions.mix(LILAC_PROCESS.out.versions) + + emit: + results = LILAC_PROCESS.out.lilac_dir // channel: [val(meta), lilac_dir] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/linx.nf b/subworkflows/local/linx.nf new file mode 100644 index 00000000..93d07b21 --- /dev/null +++ b/subworkflows/local/linx.nf @@ -0,0 +1,65 @@ +// +// Linx is an annotation, interpretation and visualisation tool for structural variants. +// + +include { LINX_GERMLINE } from '../../modules/local/linx/germline/main' +include { LINX_SOMATIC } from '../../modules/local/linx/somatic/main' +include { VISUALISER } from '../../modules/local/linx/visualiser/main' + +workflow LINX { + take: + ch_linx_germline_inputs // channel: [val(meta), gripss_hard_vcf] + ch_linx_somatic_inputs // channel: [val(meta), purple_dir] + ref_data_genome_version // val: genome version + ref_data_linx_fragile_sites // file: /path/to/linx_fragile_sites + ref_data_linx_lines // file: /path/to/linx_lines + ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ + ref_data_known_fusion_data // file: /path/to/known_fusion_data + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + + main: + // Channel for versions.yml files + ch_versions = Channel.empty() + + // Germline + LINX_GERMLINE( + ch_linx_germline_inputs, + ref_data_genome_version, + ref_data_linx_fragile_sites, + ref_data_linx_lines, + ref_data_ensembl_data_dir, + ref_data_driver_gene_panel, + ) + ch_versions = ch_versions.mix(LINX_GERMLINE.out.versions) + + // Somatic + LINX_SOMATIC( + ch_linx_somatic_inputs, + ref_data_genome_version, + ref_data_linx_fragile_sites, + ref_data_linx_lines, + ref_data_ensembl_data_dir, + ref_data_known_fusion_data, + ref_data_driver_gene_panel, + ) + ch_versions = ch_versions.mix(LINX_SOMATIC.out.versions) + + VISUALISER( + LINX_SOMATIC.out.annotation_dir, + ref_data_genome_version, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(VISUALISER.out.versions) + + // channel: [val(meta), linx_annotation_dir, linx_visualiser_dir] + ch_linx_somatic_out = WorkflowHmftools.group_by_meta( + LINX_SOMATIC.out.annotation_dir, + VISUALISER.out.visualiser_dir, + ) + + emit: + somatic = ch_linx_somatic_out // channel: [val(meta), linx_annotation_dir, linx_visualiser_dir] + germline = LINX_GERMLINE.out.annotation_dir // channel: [val(meta), linx_annotation_dir] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/pave.nf b/subworkflows/local/pave.nf new file mode 100644 index 00000000..01886aca --- /dev/null +++ b/subworkflows/local/pave.nf @@ -0,0 +1,60 @@ +// +// PAVE annotates somatic and germline variant VCFs with gene and transcript coding and protein effects. +// + +include { PAVE_GERMLINE } from '../../modules/local/pave/germline/main' +include { PAVE_SOMATIC } from '../../modules/local/pave/somatic/main' + +workflow PAVE { + take: + ch_inputs_germline // channel: [val(meta), sage_germline_vcf] + ch_inputs_somatic // channel: [val(meta), sage_somatic_vcf] + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_version // val: genome version + ref_data_sage_pon_file // file: /path/to/sage_pon_file + ref_data_sage_blacklist_bed // file: /path/to/sage_blacklist_bed + ref_data_sage_blacklist_vcf // file: /path/to/sage_black_list_vcf + ref_data_clinvar_vcf // file: /path/to/clinvar_vcf + ref_data_mappability_bed // file: /path/to/mappability_bed + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Germline + PAVE_GERMLINE( + ch_inputs_germline, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_sage_blacklist_bed, + ref_data_sage_blacklist_vcf, + ref_data_clinvar_vcf, + ref_data_mappability_bed, + ref_data_driver_gene_panel, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(PAVE_GERMLINE.out.versions) + + // Somatic + PAVE_SOMATIC( + ch_inputs_somatic, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_sage_pon_file, + ref_data_mappability_bed, + ref_data_driver_gene_panel, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(PAVE_SOMATIC.out.versions) + + emit: + germline = PAVE_GERMLINE.out.vcf // channel: [val(meta), pave_vcf] + somatic = PAVE_SOMATIC.out.vcf // channel: [val(meta), pave_vcf] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/sage.nf b/subworkflows/local/sage.nf new file mode 100644 index 00000000..88351338 --- /dev/null +++ b/subworkflows/local/sage.nf @@ -0,0 +1,61 @@ +// +// SAGE is a precise and highly sensitive somatic SNV, MNV and small INDEL caller. +// + +include { SAGE_GERMLINE } from '../../modules/local/sage/germline/main' +include { SAGE_SOMATIC } from '../../modules/local/sage/somatic/main' + +workflow SAGE { + take: + ch_inputs // channel: [meta, tumor_bam, normal_bam, tumor_bai, normal_bai] + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_dict // file: /path/to/genome_dict + ref_data_genome_version // val: genome version + ref_data_sage_known_hotspots_germline // file: /path/to/sage_known_hotspots_germline + ref_data_sage_known_hotspots_somatic // file: /path/to/sage_known_hotspots_somatic + ref_data_sage_coding_panel // file: /path/to/sage_coding_panel + ref_data_sage_high_confidence // file: /path/to/sage_high_confidence + ref_data_sage_pon_file // file: /path/to/sage_pon + ref_data_mappability_bed // file: /path/to/mappability_bed + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Germline + SAGE_GERMLINE( + ch_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_sage_known_hotspots_germline, + ref_data_sage_coding_panel, + ref_data_sage_high_confidence, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(SAGE_GERMLINE.out.versions) + + // Somatic + SAGE_SOMATIC( + ch_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_sage_known_hotspots_somatic, + ref_data_sage_coding_panel, + ref_data_sage_high_confidence, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(SAGE_SOMATIC.out.versions) + + emit: + germline = SAGE_GERMLINE.out.vcf // channel: [val(meta), sage_vcf] + somatic = SAGE_SOMATIC.out.vcf // channel: [val(meta), sage_vcf] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/workflows/hmftools.nf b/workflows/hmftools.nf new file mode 100644 index 00000000..86c963c6 --- /dev/null +++ b/workflows/hmftools.nf @@ -0,0 +1,735 @@ +import Processes +import Constants + + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + VALIDATE INPUTS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) + +// Validate input parameters +WorkflowHmftools.initialise(params, workflow, log) + +// Check input path parameters to see if they exist +def checkPathParamList = [ + params.input, + // Reference genome + params.ref_data_genome_fa, + params.ref_data_genome_fai, + params.ref_data_genome_dict, + params.ref_data_genome_bwa_index, + params.ref_data_genome_bwa_index_image, + params.ref_data_genome_gridss_index, + // AMBER and COBALT + params.ref_data_amber_loci, + params.ref_data_cobalt_gc_profile, + // CUPPA + params.ref_data_cuppa, + // SVPREP, GRIDSS, GRIPSS + params.gridss_config, + params.ref_data_sv_prep_blacklist, + params.ref_data_gridss_blacklist, + params.ref_data_gridss_breakend_pon, + params.ref_data_gridss_breakpoint_pon, + params.ref_data_repeat_masker_file, + // Isofox + params.ref_data_rna_exp_counts, + params.ref_data_rna_exp_gc_ratios, + // LINX + params.ref_data_linx_fragile_sites, + params.ref_data_linx_lines, + // SAGE, PAVE + params.ref_data_sage_blacklist_bed, + params.ref_data_sage_blacklist_vcf, + params.ref_data_sage_coding_panel, + params.ref_data_sage_high_confidence, + params.ref_data_sage_known_hotspots_germline, + params.ref_data_sage_known_hotspots_somatic, + params.ref_data_sage_pon_file, + // LILAC + params.ref_data_lilac_resource_dir, + // VIRUSBreakend, Virus Interpreter + params.ref_data_virusbreakenddb, + params.ref_data_virus_taxonomy, + params.ref_data_virus_reporting, + // Other + params.ref_data_purple_germline_del, + params.ref_data_clinvar_vcf, + params.ref_data_driver_gene_panel, + params.ref_data_ensembl_data_dir, + params.ref_data_known_fusion_data, + params.ref_data_known_fusions, + params.ref_data_mappability_bed, +] + +for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } + +// Check mandatory parameters +if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CONFIG FILES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT LOCAL MODULES/SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// +// MODULES +// +include { CHECK_SAMPLESHEET } from '../modules/local/check_samplesheet/main' + +include { AMBER } from '../modules/local/amber/main' +include { COBALT } from '../modules/local/cobalt/main' +include { CUPPA_CLASSIFIER } from '../modules/local/cuppa/classifier/main' +include { CUPPA_VISUALISER } from '../modules/local/cuppa/visualiser/main' +include { ISOFOX } from '../modules/local/isofox/main' +include { LINX_REPORT } from '../modules/local/gpgr/linx_report/main' +include { PURPLE } from '../modules/local/purple/main' +include { TEAL } from '../modules/local/teal/main' +include { VIRUSBREAKEND } from '../modules/local/virusbreakend/main' +include { VIRUSINTERPRETER } from '../modules/local/virusinterpreter/main' + +include { PICARD_COLLECTWGSMETRICS as COLLECTWGSMETRICS } from '../modules/nf-core/modules/picard/collectwgsmetrics/main' + +// +// SUBWORKFLOWS +// +include { GRIDSS } from '../subworkflows/local/gridss' +include { GRIDSS_SVPREP } from '../subworkflows/local/gridss_svprep' +include { GRIPSS } from '../subworkflows/local/gripss' +include { LILAC } from '../subworkflows/local/lilac' +include { LINX } from '../subworkflows/local/linx' +include { PAVE } from '../subworkflows/local/pave' +include { SAGE } from '../subworkflows/local/sage' + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT NF-CORE MODULES/SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// +// MODULES +// +include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + RUN MAIN WORKFLOW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// Get absolute file paths +def get_file_object(path) { + return path ? file(path) : [] +} + +samplesheet = get_file_object(params.input) +// Reference genome +ref_data_genome_fa = get_file_object(params.ref_data_genome_fa) +ref_data_genome_version = params.ref_data_genome_version +ref_data_genome_fai = get_file_object(params.ref_data_genome_fai) +ref_data_genome_dict = get_file_object(params.ref_data_genome_dict) +ref_data_genome_bwa_index = get_file_object(params.ref_data_genome_bwa_index) +ref_data_genome_bwa_index_image = get_file_object(params.ref_data_genome_bwa_index_image) +ref_data_genome_gridss_index = get_file_object(params.ref_data_genome_gridss_index) +// AMBER and COBALT +ref_data_amber_loci = get_file_object(params.ref_data_amber_loci) +ref_data_cobalt_gc_profile = get_file_object(params.ref_data_cobalt_gc_profile) +// CUPPA +ref_data_cuppa = get_file_object(params.ref_data_cuppa) +// SVPREP, GRIDSS, GRIPSS +gridss_config = get_file_object(params.gridss_config) +ref_data_sv_prep_blacklist = get_file_object(params.ref_data_sv_prep_blacklist) +ref_data_gridss_blacklist = get_file_object(params.ref_data_gridss_blacklist) +ref_data_gridss_breakend_pon = get_file_object(params.ref_data_gridss_breakend_pon) +ref_data_gridss_breakpoint_pon = get_file_object(params.ref_data_gridss_breakpoint_pon) +ref_data_repeat_masker_file = get_file_object(params.ref_data_repeat_masker_file) +// Isofox +ref_data_rna_exp_counts = get_file_object(params.ref_data_rna_exp_counts) +ref_data_rna_exp_gc_ratios = get_file_object(params.ref_data_rna_exp_gc_ratios) +// LINX +ref_data_linx_fragile_sites = get_file_object(params.ref_data_linx_fragile_sites) +ref_data_linx_lines = get_file_object(params.ref_data_linx_lines) +// SAGE, PAVE +ref_data_sage_blacklist_bed = get_file_object(params.ref_data_sage_blacklist_bed) +ref_data_sage_blacklist_vcf = get_file_object(params.ref_data_sage_blacklist_vcf) +ref_data_sage_coding_panel = get_file_object(params.ref_data_sage_coding_panel) +ref_data_sage_high_confidence = get_file_object(params.ref_data_sage_high_confidence) +ref_data_sage_known_hotspots_germline = get_file_object(params.ref_data_sage_known_hotspots_germline) +ref_data_sage_known_hotspots_somatic = get_file_object(params.ref_data_sage_known_hotspots_somatic) +ref_data_sage_pon_file = get_file_object(params.ref_data_sage_pon_file) +// LILAC +ref_data_lilac_resource_dir = get_file_object(params.ref_data_lilac_resource_dir) +// VIRUSBreakend, Virus Interpreter +ref_data_virusbreakenddb = get_file_object(params.ref_data_virusbreakenddb) +ref_data_virus_taxonomy = get_file_object(params.ref_data_virus_taxonomy) +ref_data_virus_reporting = get_file_object(params.ref_data_virus_reporting) +// Other +ref_data_purple_germline_del = get_file_object(params.ref_data_purple_germline_del) +ref_data_clinvar_vcf = get_file_object(params.ref_data_clinvar_vcf) +ref_data_driver_gene_panel = get_file_object(params.ref_data_driver_gene_panel) +ref_data_ensembl_data_dir = get_file_object(params.ref_data_ensembl_data_dir) +ref_data_known_fusion_data = get_file_object(params.ref_data_known_fusion_data) +ref_data_known_fusions = get_file_object(params.ref_data_known_fusions) +ref_data_mappability_bed = get_file_object(params.ref_data_mappability_bed) + +// Set processes to run +processes = Processes.set_processes(params.mode, log) + +processes_include = Processes.get_process_list(params.processes_include, log) +processes_exclude = Processes.get_process_list(params.processes_exclude, log) +Processes.check_include_exclude_list(processes_include, processes_exclude, log) + +processes.addAll(processes_include) +processes.removeAll(processes_exclude) + +run = Constants.Process + .values() + .collectEntries { p -> [p.name().toLowerCase(), p in processes] } + + +workflow HMFTOOLS { + // Create channel for versions + // channel: [versions.yml] + ch_versions = Channel.empty() + + // Check samplesheet and prepare input channel + CHECK_SAMPLESHEET( + samplesheet, + params.mode, + ) + // channel: [val(meta)] + ch_inputs = WorkflowHmftools.prepare_inputs(CHECK_SAMPLESHEET.out, workflow.stubRun, log) + + // Set up channel with common inputs for several processes + if (run.amber || run.cobalt || run.pave || run.lilac || run.teal) { + + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_bams_and_indices = ch_inputs + .map { meta -> + def tumor_bam = meta.get(['bam_wgs', 'tumor']) + def normal_bam = meta.get(['bam_wgs', 'normal']) + [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] + } + } + + // channel (present): [val(meta)] + // channel (absent): [val(meta)] + ch_inputs_wts = ch_inputs + .branch { meta -> + def key = ['bam_wts', 'tumor'] + present: meta.containsKey(key) + return meta + absent: ! meta.containsKey(key) + return meta + } + + // + // MODULE: Run Isofox to analyse WTS data + // + ch_isofox_out = Channel.empty() + if (run.isofox) { + + // channel: [meta, tumor_bam_wts] + ch_isofox_inputs = ch_inputs_wts.present + .map { meta -> + return [meta, meta.get(['bam_wts', 'tumor'])] + } + ISOFOX( + ch_isofox_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_ensembl_data_dir, + ref_data_rna_exp_counts, + ref_data_rna_exp_gc_ratios, + ) + ch_versions = ch_versions.mix(ISOFOX.out.versions) + ch_isofox_out = ch_isofox_out.mix(ISOFOX.out.isofox_dir) + } + + // + // MODULE: Run COLLECTWGSMETRICS to generate stats required for downstream processes + // + if (run.virusinterpreter || run.teal) { + + // NOTE(SW): CUPPA only requires collectwgsmetrics for the tumor sample in + // the upstream process Virus Interpreter but TEAL currently requires + // collectwgsmetrics for both tumor and normal sample + // channel: [val(meta_cwm), bam] + ch_cwm_inputs_all = ch_inputs + .flatMap { meta -> + def sample_types = run.teal ? ['tumor', 'normal'] : ['tumor'] + return sample_types + .collect { sample_type -> + def bam = meta.get(['bam_wgs', sample_type]) + def sample_name = meta.get(['sample_name', sample_type]) + def meta_cwm = [ + id: sample_name, + sample_type: sample_type, + meta_full: meta, + ] + return [meta_cwm, bam] + } + } + + // Gather duplicate files e.g. repeated normal BAMs for multiple tumor samples + // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent + // on any process + // channel: [val(meta_cwm), bam] + ch_cwm_inputs = ch_cwm_inputs_all + .map { [it[1..-1], it[0]] } + .groupTuple() + .map { filepaths, meta_cwm -> + def (meta_fulls, sample_types) = meta_cwm + .collect { + [it.meta_full, it.sample_type] + } + .transpose() + + def sample_type = sample_types.unique(false) + assert sample_type.size() == 1 + + def id = meta_fulls.collect { it.id }.join('__') + def meta_cwm_new = [ + id: "${id}_${sample_type[0]}", + id_simple: id, + metas_full: meta_fulls, + sample_type: sample_type[0], + ] + return [meta_cwm_new, *filepaths] + } + + COLLECTWGSMETRICS( + ch_cwm_inputs, + ref_data_genome_fa, + ) + ch_versions = ch_versions.mix(COLLECTWGSMETRICS.out.versions) + + // Replicate outputs to undo unique operation + // channel (tumor): [val(meta), metrics] + // channel (normal): [val(meta), metrics] + ch_cwm_output = COLLECTWGSMETRICS.out.metrics + .flatMap { meta_cwm, metrics -> + meta_cwm.metas_full.collect { meta -> [meta, meta_cwm.sample_type, metrics] } + } + .branch { meta, sample_type, metrics -> + tumor: sample_type == 'tumor' + return [meta, metrics] + normal: sample_type == 'normal' + return [meta, metrics] + } + } + + // + // MODULE: Run AMBER to obtain b-allele frequencies + // + // channel: [val(meta), amber_dir] + ch_amber_out = Channel.empty() + if (run.amber) { + + AMBER( + ch_bams_and_indices, + ref_data_genome_version, + ref_data_amber_loci, + ) + ch_versions = ch_versions.mix(AMBER.out.versions) + ch_amber_out = ch_amber_out.mix(AMBER.out.amber_dir) + } + + // + // MODULE: Run COBALT to obtain read ratios + // + // channel: [val(meta), cobalt_dir] + ch_cobalt_out = Channel.empty() + if (run.cobalt) { + + COBALT( + ch_bams_and_indices, + ref_data_cobalt_gc_profile, + ) + ch_versions = ch_versions.mix(COBALT.out.versions) + ch_cobalt_out = ch_cobalt_out.mix(COBALT.out.cobalt_dir) + } + + // + // SUBWORKFLOW: Call structural variants with GRIDSS + // + // channel: [val(meta), gridss_vcf] + ch_gridss_out = Channel.empty() + if (run.gridss) { + + if (run.svprep) { + GRIDSS_SVPREP( + ch_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_version, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ref_data_sv_prep_blacklist, + ref_data_known_fusions, + ) + ch_versions = ch_versions.mix(GRIDSS_SVPREP.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP.out.results) + } else { + ch_gridss_inputs = ch_inputs + .map { meta -> + def tumor_bam = meta.get(['bam_wgs', 'tumor']) + def normal_bam = meta.get(['bam_wgs', 'normal']) + [meta, tumor_bam, normal_bam] + } + GRIDSS( + ch_gridss_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ) + ch_versions = ch_versions.mix(GRIDSS.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS.out.results) + } + } + + // + // MODULE: Run GRIPSS to filter GRIDSS SV calls + // + // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + ch_gripss_germline_out = Channel.empty() + // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + ch_gripss_somatic_out = Channel.empty() + if (run.gripss) { + + GRIPSS( + run.gridss ? ch_gridss_out : WorkflowHmftools.get_input(ch_inputs, ['gridss_vcf', 'tumor_normal']), + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_gridss_breakend_pon, + ref_data_gridss_breakpoint_pon, + ref_data_known_fusions, + ref_data_repeat_masker_file, + ) + ch_versions = ch_versions.mix(GRIPSS.out.versions) + ch_gripss_germline_out = ch_gripss_germline_out.mix(GRIPSS.out.germline) + ch_gripss_somatic_out = ch_gripss_somatic_out.mix(GRIPSS.out.somatic) + } + + // + // SUBWORKFLOW: call SNV, MNV, and small INDELS with SAGE + // + // channel: [val(meta), sage_vcf] + ch_sage_germline_out = Channel.empty() + // channel: [val(meta), sage_vcf] + ch_sage_somatic_out = Channel.empty() + if (run.sage) { + + SAGE( + ch_bams_and_indices, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_sage_known_hotspots_germline, + ref_data_sage_known_hotspots_somatic, + ref_data_sage_coding_panel, + ref_data_sage_high_confidence, + ref_data_sage_pon_file, + ref_data_mappability_bed, + ref_data_driver_gene_panel, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(SAGE.out.versions) + ch_sage_germline_out = ch_sage_germline_out.mix(SAGE.out.germline) + ch_sage_somatic_out = ch_sage_somatic_out.mix(SAGE.out.somatic) + } + + // + // SUBWORKFLOW: Annotate variants with PAVE + // + // channel: [val(meta), pave_vcf] + ch_pave_germline_out = Channel.empty() + // channel: [val(meta), pave_vcf] + ch_pave_somatic_out = Channel.empty() + if (run.pave) { + + PAVE( + run.sage ? ch_sage_germline_out : WorkflowHmftools.get_input(ch_inputs, ['sage_vcf', 'normal']), + run.sage ? ch_sage_somatic_out : WorkflowHmftools.get_input(ch_inputs, ['sage_vcf', 'tumor']), + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_sage_pon_file, + ref_data_sage_blacklist_bed, + ref_data_sage_blacklist_vcf, + ref_data_clinvar_vcf, + ref_data_mappability_bed, + ref_data_driver_gene_panel, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(PAVE.out.versions) + ch_pave_germline_out = ch_pave_germline_out.mix(PAVE.out.germline) + ch_pave_somatic_out = ch_pave_somatic_out.mix(PAVE.out.somatic) + } + + // + // MODULE: Run PURPLE for CNV calling, purity and ploidy inference, SV recovery + // + // channel: [val(meta), purple_dir] + ch_purple_out = Channel.empty() + if (run.purple) { + + // channel: [val(meta), sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi] + if (run.gripss) { + ch_purple_inputs_sv = ch_gripss_somatic_out + } else { + ch_purple_inputs_sv = ch_inputs + .map { meta -> + def sv_hard_vcf = meta[['vcf_sv_gripss_hard', 'tumor']] + def sv_soft_vcf = meta[['vcf_sv_gripss_soft', 'tumor']] + return [ + meta, + sv_hard_vcf, + "${sv_hard_vcf}.tbi", + sv_soft_vcf, + "${sv_soft_vcf}.tbi", + ] + } + } + + // channel: [val(meta), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] + ch_purple_inputs = WorkflowHmftools.group_by_meta( + run.amber ? ch_amber_out : WorkflowHmftools.get_input(ch_inputs, ['amber_dir', 'tumor_normal']), + run.cobalt ? ch_cobalt_out : WorkflowHmftools.get_input(ch_inputs, ['cobalt_dir', 'tumor_normal']), + ch_purple_inputs_sv, + run.pave ? ch_pave_somatic_out : WorkflowHmftools.get_input(ch_inputs, ['vcf_smlv', 'tumor']), + run.pave ? ch_pave_germline_out : WorkflowHmftools.get_input(ch_inputs, ['vcf_smlv', 'normal']), + ) + + PURPLE( + ch_purple_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_cobalt_gc_profile, + ref_data_sage_known_hotspots_somatic, + ref_data_sage_known_hotspots_germline, + ref_data_driver_gene_panel, + ref_data_ensembl_data_dir, + ref_data_purple_germline_del, + ) + ch_versions = ch_versions.mix(PURPLE.out.versions) + ch_purple_out = ch_purple_out.mix(PURPLE.out.purple_dir) + } + + // + // MODULE: Run TEAL to characterise teleomeres + // + if (run.teal) { + + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, tumor_wgs_metrics, normal_wgs_metrics, cobalt_dir, purple_dir] + // NOTE(SW): assuming here that TEAL is being run in tumor/normal mode and so we expect a tumor metrics file and normal metrics file + ch_teal_inputs = WorkflowHmftools.group_by_meta( + ch_bams_and_indices, + run.collectwgsmetrics ? ch_cwm_output.tumor : WorkflowHmftools.get_input(ch_inputs, ['collectmetrics', 'tumor']), + run.collectwgsmetrics ? ch_cwm_output.normal : WorkflowHmftools.get_input(ch_inputs, ['collectmetrics', 'normal']), + run.purple ? ch_purple_out : WorkflowHmftools.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), + run.cobalt ? ch_cobalt_out : WorkflowHmftools.get_input(ch_inputs, ['cobalt_dir', 'tumor_normal']), + ) + + TEAL( + ch_teal_inputs, + ) + ch_versions = ch_versions.mix(TEAL.out.versions) + } + + // + // SUBWORKFLOW: Run LILAC for HLA typing and somatic CNV and SNV calling + // + if (run.lilac) { + + LILAC( + ch_bams_and_indices, + run.purple ? ch_purple_out : WorkflowHmftools.get_input(['purple_dir', 'tumor_normal']), + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_lilac_resource_dir, + ) + ch_versions = ch_versions.mix(LILAC.out.versions) + } + + // + // MODULE: Run VIRUSBreakend and Virus Interpreter to quantify viral content + // + // NOTE(SW): kept separate from CUPPA conditional block since we'll allow users to run this independently + ch_virusinterpreter_out = Channel.empty() + if (run.virusinterpreter) { + + // channel: [val(meta), tumor_bam] + ch_virusbreakend_inputs = ch_inputs.map { meta -> [meta, meta.get(['bam_wgs', 'tumor'])] } + + VIRUSBREAKEND( + ch_virusbreakend_inputs, + ref_data_virusbreakenddb, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ) + ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) + + // channel: [val(meta), purple_purity, purple_qc] + ch_virusinterpreter_inputs_purple = ch_purple_out + .map { meta, purple_dir -> + def purple_purity = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.purity.tsv") + def purple_qc = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.qc") + return [meta, purple_purity, purple_qc] + } + + // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] + ch_virusinterpreter_inputs = WorkflowHmftools.group_by_meta( + VIRUSBREAKEND.out.tsv, + ch_virusinterpreter_inputs_purple, + ch_cwm_output.tumor, + ) + + VIRUSINTERPRETER( + ch_virusinterpreter_inputs, + ref_data_virus_taxonomy, + ref_data_virus_reporting, + ) + ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) + ch_virusinterpreter_out = ch_virusinterpreter_out.mix(VIRUSINTERPRETER.out.virusinterpreter_dir) + } + + // + // SUBWORKFLOW: Group structural variants into higher order events with LINX + // + // channel: [val(meta), linx_annotation_dir, linx_visuliaser_dir] + ch_linx_somatic_out = Channel.empty() + if (run.linx) { + + // channel: [val(meta), vcf] + ch_gripps_germline_hard = ch_gripss_germline_out.map { meta, h, hi, s, si -> [meta, h] } + + LINX( + run.gripss ? ch_gripps_germline_hard : WorkflowHmftools.get_input(ch_inputs, ['vcf_sv_gripss_hard', 'normal']), + run.purple ? ch_purple_out : WorkflowHmftools.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), + ref_data_genome_version, + ref_data_linx_fragile_sites, + ref_data_linx_lines, + ref_data_ensembl_data_dir, + ref_data_known_fusion_data, + ref_data_driver_gene_panel, + ) + ch_versions = ch_versions.mix(LINX.out.versions) + ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX.out.somatic) + + // + // MODULE: Run gpgr to generate a LINX report + // + LINX_REPORT( + ch_linx_somatic_out, + ) + ch_versions = ch_versions.mix(LINX_REPORT.out.versions) + } + + // + // MODULE: Run CUPPA predict tissue of origin + // + if (run.cuppa) { + + // channel: [val(meta), isofox_dir] + if (run.isofox) { + ch_cuppa_inputs_isofox = Channel.empty() + .mix( + ch_inputs_wts.absent.map { meta -> [meta, []] }, + ch_isofox_out, + ) + } else { + ch_cuppa_inputs_isofox = ch_inputs + .map { meta -> [meta, meta.get(['isofox_dir', 'tumor'], [])] } + } + + // channel: [val(meta), linx_somatic_annotation_dir] + ch_linx_anno = ch_linx_somatic_out.map { meta, anno_dir, vis_dir -> [meta, anno_dir]} + + // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter_dir] + // NOTE(SW): the Groovy Collection.flatten method used in + // WorkflowHmftools.group_by_meta removes optional Isofox input; flattening + // done manually below to preserve + ch_cuppa_inputs = WorkflowHmftools.group_by_meta( + ch_cuppa_inputs_isofox, + run.purple ? ch_purple_out : WorkflowHmftools.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), + run.linx ? ch_linx_anno : WorkflowHmftools.get_input(ch_inputs, ['linx_dir', 'tumor']), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowHmftools.get_input(ch_inputs, ['virusinterpreter', 'tumor']), + flatten: false, + ) + .map { data -> + def meta = data[0] + def inputs = data[1..-1].collect { it[0] } + return [meta, *inputs] + } + + CUPPA_CLASSIFIER( + ch_cuppa_inputs, + ref_data_cuppa, + ) + ch_versions = ch_versions.mix(CUPPA_CLASSIFIER.out.versions) + + CUPPA_VISUALISER( + CUPPA_CLASSIFIER.out.csv, + ) + ch_versions = ch_versions.mix(CUPPA_VISUALISER.out.versions) + } + + // + // MODULE: Pipeline reporting + // + CUSTOM_DUMPSOFTWAREVERSIONS( + ch_versions.unique().collectFile(name: 'collated_versions.yml') + ) +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + COMPLETION EMAIL AND SUMMARY +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +workflow.onComplete { + if (params.email || params.email_on_fail) { + NfcoreTemplate.email(workflow, params, summary_params, projectDir, log, multiqc_report) + } + NfcoreTemplate.summary(workflow, params, log) +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + THE END +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ From 60e8e3b1680a8c6580283299252ae18499c8de42 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 28 Nov 2022 18:32:20 +1100 Subject: [PATCH 002/562] Migrate umccr/hmftools --- README.md | 182 ++-- bin/check_samplesheet.py | 478 ++++----- conf/base.config | 273 ++--- conf/igenomes.config | 846 +++++++-------- conf/modules.config | 447 ++++---- conf/test.config | 54 +- lib/Constants.groovy | 46 +- lib/NfcoreSchema.groovy | 930 ++++++++-------- lib/NfcoreTemplate.groovy | 521 +++++---- lib/Processes.groovy | 168 +-- lib/Utils.groovy | 61 +- lib/WorkflowGridss.groovy | 180 ++-- lib/WorkflowHmftools.groovy | 165 --- lib/WorkflowLilac.groovy | 140 +-- lib/WorkflowMain.groovy | 153 ++- lib/WorkflowOncoanalyser.groovy | 191 +++- main.nf | 27 +- modules.json | 22 +- modules/local/amber/main.nf | 74 +- modules/local/check_samplesheet/main.nf | 46 +- modules/local/cobalt/main.nf | 70 +- modules/local/cuppa/classifier/main.nf | 86 +- modules/local/cuppa/visualiser/main.nf | 70 +- .../lilac_extract_and_index_contig/main.nf | 62 +- .../custom/lilac_realign_reads_lilac/main.nf | 96 +- modules/local/custom/lilac_slice/main.nf | 76 +- modules/local/gpgr/linx_report/main.nf | 58 +- modules/local/gridss/assemble/main.nf | 152 +-- modules/local/gridss/call/main.nf | 164 +-- modules/local/gridss/preprocess/main.nf | 100 +- modules/local/gripss/germline/main.nf | 106 +- modules/local/gripss/somatic/main.nf | 108 +- modules/local/isofox/main.nf | 98 +- modules/local/lilac/main.nf | 104 +- modules/local/linx/germline/main.nf | 82 +- modules/local/linx/somatic/main.nf | 88 +- modules/local/linx/visualiser/main.nf | 98 +- modules/local/pave/germline/main.nf | 112 +- modules/local/pave/somatic/main.nf | 106 +- modules/local/purple/main.nf | 166 +-- modules/local/sage/germline/main.nf | 108 +- modules/local/sage/somatic/main.nf | 92 +- modules/local/samplesheet_check.nf | 40 +- modules/local/svprep/assemble/main.nf | 154 +-- modules/local/svprep/call/main.nf | 166 +-- modules/local/svprep/depth_annotator/main.nf | 76 +- modules/local/svprep/preprocess/main.nf | 104 +- modules/local/svprep/svprep/main.nf | 112 +- modules/local/teal/main.nf | 86 +- modules/local/virusbreakend/main.nf | 90 +- modules/local/virusinterpreter/main.nf | 86 +- modules/nf-core/bwa/index/main.nf | 51 - modules/nf-core/bwa/index/meta.yml | 42 - .../custom/dumpsoftwareversions/main.nf | 8 +- .../templates/dumpsoftwareversions.py | 14 +- modules/nf-core/fastqc/main.nf | 59 -- modules/nf-core/fastqc/meta.yml | 52 - .../custom/dumpsoftwareversions/main.nf | 24 - .../custom/dumpsoftwareversions/meta.yml | 34 - .../templates/dumpsoftwareversions.py | 89 -- modules/nf-core/multiqc/main.nf | 53 - modules/nf-core/multiqc/meta.yml | 55 - .../picard/collectwgsmetrics/main.nf | 0 .../picard/collectwgsmetrics/meta.yml | 0 modules/nf-core/samtools/dict/main.nf | 44 - modules/nf-core/samtools/dict/meta.yml | 41 - modules/nf-core/samtools/faidx/main.nf | 44 - modules/nf-core/samtools/faidx/meta.yml | 47 - modules/nf-core/star/genomegenerate/main.nf | 96 -- modules/nf-core/star/genomegenerate/meta.yml | 37 - nextflow.config | 406 +++---- nextflow_schema.json | 993 +++++++++--------- subworkflows/local/gridss.nf | 216 ++-- subworkflows/local/gridss_svprep.nf | 404 +++---- subworkflows/local/gripss.nf | 102 +- subworkflows/local/input_check.nf | 56 +- subworkflows/local/lilac.nf | 136 +-- subworkflows/local/linx.nf | 96 +- subworkflows/local/pave.nf | 92 +- subworkflows/local/sage.nf | 94 +- workflows/hmftools.nf | 735 ------------- workflows/oncoanalyser.nf | 695 +++++++++++- 82 files changed, 6035 insertions(+), 6900 deletions(-) mode change 100755 => 100644 lib/Utils.groovy delete mode 100755 lib/WorkflowHmftools.groovy mode change 100755 => 100644 main.nf delete mode 100644 modules/nf-core/bwa/index/main.nf delete mode 100644 modules/nf-core/bwa/index/meta.yml delete mode 100644 modules/nf-core/fastqc/main.nf delete mode 100644 modules/nf-core/fastqc/meta.yml delete mode 100644 modules/nf-core/modules/custom/dumpsoftwareversions/main.nf delete mode 100644 modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml delete mode 100644 modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py delete mode 100644 modules/nf-core/multiqc/main.nf delete mode 100644 modules/nf-core/multiqc/meta.yml rename modules/nf-core/{modules => }/picard/collectwgsmetrics/main.nf (100%) rename modules/nf-core/{modules => }/picard/collectwgsmetrics/meta.yml (100%) delete mode 100644 modules/nf-core/samtools/dict/main.nf delete mode 100644 modules/nf-core/samtools/dict/meta.yml delete mode 100644 modules/nf-core/samtools/faidx/main.nf delete mode 100644 modules/nf-core/samtools/faidx/meta.yml delete mode 100644 modules/nf-core/star/genomegenerate/main.nf delete mode 100644 modules/nf-core/star/genomegenerate/meta.yml delete mode 100644 workflows/hmftools.nf diff --git a/README.md b/README.md index 4ba9007c..95bace73 100644 --- a/README.md +++ b/README.md @@ -1,90 +1,92 @@ -  -  -  -

-🚧🚨 Under development 🚨🚧 -

- -# HMF tools - -A comprehensive cancer WGS/WTS analysis and reporting pipeline from the Hartwig Medical Foundation. - -## Table of contents - -* [Quick start](#quick-start) -* [Pipeline modes](#pipeline-modes) -* [Pipeline tests](#pipeline-tests) -* [License](#license) - -## Quick start - -1. Install dependencies. -> Assumes `Conda` is installed. -```bash -conda create -y \ - -n hmftools \ - -c bioconda \ - -c conda-forge \ - -c defaults \ - 'bcftools >=1.15' \ - 'dvc >=2.12.0' \ - 'git >=2.37.0' \ - 'nextflow >=22.04.0' -conda activate hmftools -``` - -2. Install [`Docker`](https://docs.docker.com/engine/installation/). - -3. Download the pipeline and reference data. -```bash -# Download pipeline and reference data -git clone https://github.com/umccr/hmftools && cd ./hmftools/hmftools/ - -git clone https://github.com/umccr/reference_data -b dev reference_data_gitrepo/ && cd reference_data_gitrepo/ -dvc pull reference_data/{genomes,hmftools}/ -r storage-s3 && cd ../ -ln -s reference_data_gitrepo/reference_data/ reference_data -``` - -4. Run the pipeline with your data. -```bash -nextflow run ./main.nf -profile docker --input --outdir -``` - -## Pipeline modes - -Several modes of execution are offered and can be accessed using the `--mode` argument. - -| Name | Description | -| --- | --- | -| `full` | Run all processes in the pipeline | -| `gridss-purple-linx` | Run AMBER, COBALT, GRIDSS, GRIPSS, and PURPLE | -| `gridss` | Run only GRIDSS and GRIPSS | -| `purple` | Run only PURPLE | -| `linx` | Run only LINX | -| `lilac` | Run only LILAC | -| `teal` | Run only TEAL | - -See [examples/README.md](examples/README.md) for example samplesheet required for each mode. - -## Pipeline tests - -The internal pipeline logic can be tested using a stub run. No actual outputs are generated in a stub run and -only the `stub` definition block of a process is executed. Hence, it completes in a short amount of time but does not -test validity of actual processes beyond declared inputs and outputs. - -```bash -nextflow run main.nf --input ./assets/samplesheet.tsv --outdir output_stub/ --max_memory '1.GB' -stub -``` - -A more comprehensive test that involves both the process `script` definition block and internal pipeline logic can be -run with the supplied downsampled test dataset. This of course takes longer (on the order of minutes) but replicates a -full run and generates 'real' process outputs. - -```bash -nextflow run ./main.nf -profile docker,test --outdir output_test/ --max_memory '6.GB' -``` - -## License - -Software and code in this repository are under [GNU General Public License -v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html) unless otherwise indicated. +# ![nf-core/oncoanalyser](docs/images/nf-core-oncoanalyser_logo_light.png#gh-light-mode-only) ![nf-core/oncoanalyser](docs/images/nf-core-oncoanalyser_logo_dark.png#gh-dark-mode-only) + +[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/oncoanalyser/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) + +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg)](https://www.nextflow.io/) +[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) +[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) +[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) +[![Launch on Nextflow Tower](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/oncoanalyser) + +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23oncoanalyser-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/oncoanalyser)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) + +## Introduction + + + +**nf-core/oncoanalyser** is a comprehensive cancer WGS/WTS analysis and reporting pipeline. + +The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. Where possible, these processes have been submitted to and installed from [nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to everyone within the Nextflow community! + + + +On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources.The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/oncoanalyser/results). + +## Pipeline summary + + + +1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) +2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) + +## Quick Start + +1. Install [`Nextflow`](https://www.nextflow.io/docs/latest/getstarted.html#installation) (`>=21.10.3`) + +2. Install any of [`Docker`](https://docs.docker.com/engine/installation/), [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/) (you can follow [this tutorial](https://singularity-tutorial.github.io/01-installation/)), [`Podman`](https://podman.io/), [`Shifter`](https://nersc.gitlab.io/development/shifter/how-to-use/) or [`Charliecloud`](https://hpc.github.io/charliecloud/) for full pipeline reproducibility _(you can use [`Conda`](https://conda.io/miniconda.html) both to install Nextflow itself and also to manage software within pipelines. Please only use it within pipelines as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles))_. + +3. Download the pipeline and test it on a minimal dataset with a single command: + + ```bash + nextflow run nf-core/oncoanalyser -profile test,YOURPROFILE --outdir + ``` + + Note that some form of configuration will be needed so that Nextflow knows how to fetch the required software. This is usually done in the form of a config profile (`YOURPROFILE` in the example command above). You can chain multiple config profiles in a comma-separated string. + + > - The pipeline comes with config profiles called `docker`, `singularity`, `podman`, `shifter`, `charliecloud` and `conda` which instruct the pipeline to use the named tool for software management. For example, `-profile test,docker`. + > - Please check [nf-core/configs](https://github.com/nf-core/configs#documentation) to see if a custom config file to run nf-core pipelines already exists for your Institute. If so, you can simply use `-profile ` in your command. This will enable either `docker` or `singularity` and set the appropriate execution settings for your local compute environment. + > - If you are using `singularity`, please use the [`nf-core download`](https://nf-co.re/tools/#downloading-pipelines-for-offline-use) command to download images first, before running the pipeline. Setting the [`NXF_SINGULARITY_CACHEDIR` or `singularity.cacheDir`](https://www.nextflow.io/docs/latest/singularity.html?#singularity-docker-hub) Nextflow options enables you to store and re-use the images from a central location for future pipeline runs. + > - If you are using `conda`, it is highly recommended to use the [`NXF_CONDA_CACHEDIR` or `conda.cacheDir`](https://www.nextflow.io/docs/latest/conda.html) settings to store the environments in a central location for future pipeline runs. + +4. Start running your own analysis! + + + + ```bash + nextflow run nf-core/oncoanalyser --input samplesheet.csv --outdir --genome GRCh37 -profile + ``` + +## Documentation + +The nf-core/oncoanalyser pipeline comes with documentation about the pipeline [usage](https://nf-co.re/oncoanalyser/usage), [parameters](https://nf-co.re/oncoanalyser/parameters) and [output](https://nf-co.re/oncoanalyser/output). + +## Credits + +nf-core/oncoanalyser was originally written by Stephen Watts. + +We thank the following people for their extensive assistance in the development of this pipeline: + + + +## Contributions and Support + +If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). + +For further information or help, don't hesitate to get in touch on the [Slack `#oncoanalyser` channel](https://nfcore.slack.com/channels/oncoanalyser) (you can join with [this invite](https://nf-co.re/join/slack)). + +## Citations + + + + + + +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: + +> **The nf-core framework for community-curated bioinformatics pipelines.** +> +> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen. +> +> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 11b15572..c937b7d2 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -1,262 +1,248 @@ -#!/usr/bin/env python - +#!/usr/bin/env python3 +import argparse +import collections +import enum +import pathlib +import sys -"""Provide a command line tool to validate and transform tabular samplesheets.""" +HEADER_COLS = ( + 'id', + 'subject_name', + 'sample_name', + 'sample_type', + 'filetype', + 'filepath', +) + + +class FileType(enum.Enum): + + BAM_WGS = 'bam_wgs' + BAM_WTS = 'bam_wts' + VCF_SV = 'vcf_sv' + SMLV_VCF = 'vcf_smlv' + VCF_SV_GRIPSS_SOFT = 'vcf_sv_gripss_soft' + VCF_SV_GRIPSS_HARD = 'vcf_sv_gripss_hard' + AMBER_DIR = 'amber_dir' + COBALT_DIR = 'cobalt_dir' + PURPLE_DIR = 'purple_dir' + + def __repr__(self): + return self.value + + +class SampleType(enum.Enum): + + TUMOR = 'tumor' + NORMAL = 'normal' + + def __repr__(self): + return self.value + + +FILETYPES_EXPECTED = { + 'full': { + 'required': [ + (SampleType.TUMOR, FileType.BAM_WGS), + (SampleType.NORMAL, FileType.BAM_WGS), + ], + 'optional': [ + (SampleType.TUMOR, FileType.BAM_WTS), + (SampleType.TUMOR, FileType.VCF_SV), + (SampleType.NORMAL, FileType.VCF_SV), + ], + }, + 'gridss_purple_linx': { + 'required': [ + (SampleType.TUMOR, FileType.BAM_WGS), + (SampleType.NORMAL, FileType.BAM_WGS), + ], + 'optional': [ + (SampleType.TUMOR, FileType.VCF_SV), + (SampleType.NORMAL, FileType.VCF_SV), + (SampleType.TUMOR, FileType.SMLV_VCF), + (SampleType.NORMAL, FileType.SMLV_VCF) + ], + }, + 'gridss': { + 'required': [ + (SampleType.TUMOR, FileType.BAM_WGS), + (SampleType.NORMAL, FileType.BAM_WGS), + ], + 'optional': [ + (SampleType.TUMOR, FileType.VCF_SV), + (SampleType.NORMAL, FileType.VCF_SV), + ], + }, + 'purple': { + 'required': [ + (SampleType.TUMOR, FileType.AMBER_DIR), + (SampleType.TUMOR, FileType.COBALT_DIR), + (SampleType.TUMOR, FileType.VCF_SV_GRIPSS_HARD), + (SampleType.TUMOR, FileType.VCF_SV_GRIPSS_SOFT), + ], + 'optional': [ + (SampleType.TUMOR, FileType.SMLV_VCF), + (SampleType.NORMAL, FileType.SMLV_VCF), + ], + }, + # NOTE(SW): expectation that we always at least want to run LINX somatic + 'linx': { + 'required': [ + (SampleType.TUMOR, FileType.PURPLE_DIR), + ], + 'optional': [ + (SampleType.NORMAL, FileType.VCF_SV_GRIPSS_HARD), + ], + }, + 'lilac': { + 'required': [ + (SampleType.TUMOR, FileType.BAM_WGS), + (SampleType.NORMAL, FileType.BAM_WGS), + (SampleType.TUMOR, FileType.PURPLE_DIR), + ], + 'optional': [], + }, + 'teal': { + 'required': [ + (SampleType.TUMOR, FileType.BAM_WGS), + (SampleType.NORMAL, FileType.BAM_WGS), + (SampleType.TUMOR, FileType.COBALT_DIR), + (SampleType.TUMOR, FileType.PURPLE_DIR), + ], + 'optional': [], + }, +} + + +def get_arguments(): + parser = argparse.ArgumentParser() + parser.add_argument( + '--input_fp', + required=True, + type=pathlib.Path, + help='Input samplesheet filepath', + ) + parser.add_argument( + '--mode', + required=True, + type=str, + choices=FILETYPES_EXPECTED.keys(), + help='Pipeline execution mode', + ) + args = parser.parse_args() + if not args.input_fp.exists(): + parser.error(f'Input file {args.input_fp} does not exist') + return args + + +def main(): + # Get commandline arguments + args = get_arguments() + + # Read data + runs = collections.defaultdict(list) + with args.input_fp.open('r') as fh: + line_token_gen = (line.rstrip().split('\t') for line in fh) + header_tokens = next(line_token_gen) + check_header(header_tokens, HEADER_COLS) + for lts in line_token_gen: + record = {k: v for k, v in zip(header_tokens, lts)} + record['sample_type_enum'] = get_enum(record, 'sample_type', SampleType) + record['filetype_enum'] = get_enum(record, 'filetype', FileType) + runs[record['id']].append(record) + + # Validate data + for rid, records in runs.items(): + input_types = {(r['sample_type_enum'], r['filetype_enum']) for r in records} + check_input_types( + input_types, + FILETYPES_EXPECTED[args.mode]['required'], + FILETYPES_EXPECTED[args.mode]['optional'], + ) + check_subject_names(rid, records) + check_bam_sample_names(records, FileType.BAM_WGS) + check_bam_sample_names(records, FileType.BAM_WTS) + check_sample_type_sample_names(rid, records) + + +def get_enum(record, name, enum_class): + value = record[name] + try: + return enum_class(value) + except ValueError: + print(f'Got invalid {name} for {record["id"]}: {value}', file=sys.stderr) + sys.exit(1) -import argparse -import csv -import logging -import sys -from collections import Counter -from pathlib import Path -logger = logging.getLogger() +def check_subject_names(rid, records): + subject_names = {r['subject_name'] for r in records} + if len(subject_names) > 1: + subject_names_str = ', '.join(subject_names) + msg = f'Got multiple subject names for {rid}: {subject_names_str}' + print(msg, file=sys.stderr) + sys.exit(1) -class RowChecker: - """ - Define a service that can validate and transform each given row. +def check_bam_sample_names(records, bam_filetype): + record_tumor_bam = None + record_normal_bam = None + for record in records: + if record['filetype_enum'] != bam_filetype: + continue + if record['sample_type_enum'] == SampleType.TUMOR: + record_tumor_bam = record + elif record['sample_type_enum'] == SampleType.NORMAL: + record_normal_bam = record - Attributes: - modified (list): A list of dicts, where each dict corresponds to a previously - validated and transformed row. The order of rows is maintained. + if record_tumor_bam is None or record_normal_bam is None: + return - """ + if record_tumor_bam['sample_name'] == record_normal_bam['sample_name']: + sample_name = record_tumor_bam['sample_name'] + print(f'Got identical sample names for \'{repr(bam_filetype)}\' BAMs: {sample_name}', file=sys.stderr) + sys.exit(1) - VALID_FORMATS = ( - ".fq.gz", - ".fastq.gz", - ) - def __init__( - self, - sample_col="sample", - first_col="fastq_1", - second_col="fastq_2", - single_col="single_end", - **kwargs, - ): - """ - Initialize the row checker with the expected column names. - - 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"). - - """ - super().__init__(**kwargs) - self._sample_col = sample_col - self._first_col = first_col - self._second_col = second_col - self._single_col = single_col - self._seen = set() - self.modified = [] - - def validate_and_transform(self, row): - """ - Perform all validations on the given row and insert the read pairing status. - - Args: - row (dict): A mapping from column headers (keys) to elements of that row - (values). - - """ - self._validate_sample(row) - self._validate_first(row) - self._validate_second(row) - self._validate_pair(row) - self._seen.add((row[self._sample_col], row[self._first_col])) - self.modified.append(row) - - def _validate_sample(self, row): - """Assert that the sample name exists and convert spaces to underscores.""" - if len(row[self._sample_col]) <= 0: - raise AssertionError("Sample input is required.") - # Sanitize samples slightly. - 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.""" - 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]) - - 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]) - - 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.") +def check_sample_type_sample_names(rid, records): + sample_names_tumor = set() + sample_names_normal = set() + for record in records: + if record['sample_type_enum'] == SampleType.TUMOR: + sample_names_tumor.add(record['sample_name']) + elif record['sample_type_enum'] == SampleType.NORMAL: + sample_names_normal.add(record['sample_name']) else: - row[self._single_col] = True - - def _validate_fastq_format(self, filename): - """Assert that a given filename has one of the expected FASTQ extensions.""" - 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"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. - - 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. - - """ - if len(self._seen) != len(self.modified): - raise AssertionError("The pair of sample name and FASTQ 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]}" - - -def read_head(handle, num_lines=10): - """Read the specified number of lines from the current position in the file.""" - lines = [] - for idx, line in enumerate(handle): - if idx == num_lines: - break - lines.append(line) - return "".join(lines) - - -def sniff_format(handle): - """ - Detect the tabular format. - - Args: - handle (text file): A handle to a `text file`_ object. The read position is - expected to be at the beginning (index 0). - - Returns: - csv.Dialect: The detected tabular format. - - .. _text file: - https://docs.python.org/3/glossary.html#term-text-file - - """ - peek = read_head(handle) - handle.seek(0) - sniffer = csv.Sniffer() - if not sniffer.has_header(peek): - logger.critical("The given sample sheet does not appear to contain a header.") + assert False + if len(sample_names_tumor) > 1: + sn_tumor_str = ', '.join(sample_names_tumor) + print(f'Got mismatch sample names for {rid} tumor: {sn_tumor_str}', file=sys.stderr) sys.exit(1) - dialect = sniffer.sniff(peek) - return dialect - - -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. - - Args: - file_in (pathlib.Path): The given tabular samplesheet. The format can be either - CSV, TSV, or any other format automatically recognized by ``csv.Sniffer``. - file_out (pathlib.Path): Where the validated and transformed samplesheet should - be created; always in CSV format. - - Example: - 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, - - .. _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"} - # 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)) - # Validate the existence of the expected header columns. - if not required_columns.issubset(reader.fieldnames): - req_cols = ", ".join(required_columns) - logger.critical(f"The sample sheet **must** contain these column headers: {req_cols}.") - sys.exit(1) - # Validate each row. - checker = RowChecker() - for i, row in enumerate(reader): - try: - checker.validate_and_transform(row) - except AssertionError as error: - logger.critical(f"{str(error)} On line {i + 2}.") - sys.exit(1) - checker.validate_unique_samples() - header = list(reader.fieldnames) - 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=",") - writer.writeheader() - for row in checker.modified: - writer.writerow(row) - - -def parse_args(argv=None): - """Define and immediately parse command line arguments.""" - parser = argparse.ArgumentParser( - description="Validate and transform a tabular samplesheet.", - epilog="Example: python check_samplesheet.py samplesheet.csv samplesheet.valid.csv", - ) - parser.add_argument( - "file_in", - metavar="FILE_IN", - type=Path, - help="Tabular input samplesheet in CSV or TSV format.", - ) - parser.add_argument( - "file_out", - metavar="FILE_OUT", - type=Path, - help="Transformed output samplesheet in CSV format.", - ) - parser.add_argument( - "-l", - "--log-level", - help="The desired log level (default WARNING).", - choices=("CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"), - default="WARNING", - ) - return parser.parse_args(argv) + if len(sample_names_normal) > 1: + sn_normal_str = ', '.join(sample_names_normal) + print(f'Got mismatch sample names for {rid} normal: {sn_normal_str}', file=sys.stderr) + sys.exit(1) + + +def check_header(header_tokens, required_cols): + check_set_difference(header_tokens, required_cols, 'Found unknown header column') + check_set_difference(required_cols, header_tokens, 'Missing required column') -def main(argv=None): - """Coordinate argument parsing and program execution.""" - args = parse_args(argv) - logging.basicConfig(level=args.log_level, format="[%(levelname)s] %(message)s") - if not args.file_in.is_file(): - logger.error(f"The given input file {args.file_in} was not found!") - sys.exit(2) - args.file_out.parent.mkdir(parents=True, exist_ok=True) - check_samplesheet(args.file_in, args.file_out) +def check_input_types(input_types, required, optional): + check_set_difference(input_types, required + optional, 'Found unknown input type') + check_set_difference(required, input_types, 'Missing required input type') + + +def check_set_difference(a, b, message_base): + d = set(a).difference(b) + if d : + d_str = ', '.join(str(e) for e in d) + plurality = 's' if len(d) > 1 else '' + print(f'{message_base}{plurality}: {d_str}', file=sys.stderr) + sys.exit(1) -if __name__ == "__main__": - sys.exit(main()) +if __name__ == '__main__': + main() diff --git a/conf/base.config b/conf/base.config index ea217ee4..e6b629f2 100644 --- a/conf/base.config +++ b/conf/base.config @@ -1,144 +1,151 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - umccr/hmftools Nextflow base config file + nf-core/oncoanalyser Nextflow base config file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - A 'blank slate' config file, appropriate for general use on most high performance - compute environments. Assumes that all software is installed and available on - the PATH. Runs in `local` mode - all jobs will be run on the logged in environment. + A 'blank slate' config file, appropriate for general use on most high performance + compute environments. Assumes that all software is installed and available on + the PATH. Runs in `local` mode - all jobs will be run on the logged in environment. ---------------------------------------------------------------------------------------- */ process { - cpus = { check_max( 8 * task.attempt, 'cpus' ) } - memory = { check_max( 6.GB * task.attempt, 'memory' ) } - time = { check_max( 24.h * task.attempt, 'time' ) } + // TODO nf-core: Check the defaults for all processes + cpus = { check_max( 1 * task.attempt, 'cpus' ) } + memory = { check_max( 6.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } - errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } - maxRetries = 1 - maxErrors = '-1' + errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } + maxRetries = 1 + maxErrors = '-1' - // Process-specific resource requirements - // NOTE - Please try and re-use the labels below as much as possible. - // These labels are used and recognised by default in DSL2 files hosted on nf-core/modules. - // If possible, it would be nice to keep the same label naming convention when - // adding in your local modules too. - // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors - withLabel:process_low { - cpus = { check_max( 2 * task.attempt, 'cpus' ) } - memory = { check_max( 12.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } - } - withLabel:process_medium { - cpus = { check_max( 6 * task.attempt, 'cpus' ) } - memory = { check_max( 36.GB * task.attempt, 'memory' ) } - time = { check_max( 8.h * task.attempt, 'time' ) } - } - withLabel:process_high { - cpus = { check_max( 12 * task.attempt, 'cpus' ) } - memory = { check_max( 72.GB * task.attempt, 'memory' ) } - time = { check_max( 16.h * task.attempt, 'time' ) } - } - withLabel:process_long { - time = { check_max( 20.h * task.attempt, 'time' ) } - } - withLabel:process_high_memory { - memory = { check_max( 200.GB * task.attempt, 'memory' ) } - } - withLabel:error_ignore { - errorStrategy = 'ignore' - } - withLabel:error_retry { - errorStrategy = 'retry' - maxRetries = 2 - } - withName:'CHECK_SAMPLESHEET' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 1.GB, 'memory' ) } - } - withName:'AMBER' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'COBALT' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName:CUSTOM_DUMPSOFTWAREVERSIONS { - cache = false - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 1.GB, 'memory' ) } - } - withName:'SVPREP.*' { - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'.*:GRIDSS:.*' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 30.GB, 'memory' ) } - } - withName:'.*GRIPSS.*' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName: 'LILAC_PROCESS' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName: '.*LILAC:REALIGN_READS' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName: '.*LILAC:SLICE' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 6.GB, 'memory' ) } - } - withName: '.*LILAC:EXTRACT_AND_INDEX_CONTIG' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 6.GB, 'memory' ) } - } - withName:'.*LINX:.*' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'LINX_REPORT' { - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'.*PAVE.*' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'PURPLE' { - cpus = { check_max( 2, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'.*SAGE.*' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'SLICE' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'TEAL' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'COLLECTWGSMETRICS' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - time = { check_max( 24.h , 'time' ) } - } - withName:'VIRUSBREAKEND' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 64.GB, 'memory' ) } - } - withName:'VIRUSINTERPRETER' { - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'ISOFOX' { - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'CUPPA.*' { - memory = { check_max( 12.GB, 'memory' ) } - } + // Process-specific resource requirements + // NOTE - Please try and re-use the labels below as much as possible. + // These labels are used and recognised by default in DSL2 files hosted on nf-core/modules. + // If possible, it would be nice to keep the same label naming convention when + // adding in your local modules too. + // TODO nf-core: Customise requirements for specific processes. + // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors + withLabel:process_single { + cpus = { check_max( 1 , 'cpus' ) } + memory = { check_max( 6.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } + } + withLabel:process_low { + cpus = { check_max( 2 * task.attempt, 'cpus' ) } + memory = { check_max( 12.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } + } + withLabel:process_medium { + cpus = { check_max( 6 * task.attempt, 'cpus' ) } + memory = { check_max( 36.GB * task.attempt, 'memory' ) } + time = { check_max( 8.h * task.attempt, 'time' ) } + } + withLabel:process_high { + cpus = { check_max( 12 * task.attempt, 'cpus' ) } + memory = { check_max( 72.GB * task.attempt, 'memory' ) } + time = { check_max( 16.h * task.attempt, 'time' ) } + } + withLabel:process_long { + time = { check_max( 20.h * task.attempt, 'time' ) } + } + withLabel:process_high_memory { + memory = { check_max( 200.GB * task.attempt, 'memory' ) } + } + withLabel:error_ignore { + errorStrategy = 'ignore' + } + withLabel:error_retry { + errorStrategy = 'retry' + maxRetries = 2 + } + withName:'CHECK_SAMPLESHEET' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 1.GB, 'memory' ) } + } + withName:'AMBER' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'COBALT' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:CUSTOM_DUMPSOFTWAREVERSIONS { + cache = false + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 1.GB, 'memory' ) } + } + withName:'SVPREP.*' { + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'.*:GRIDSS:.*' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 30.GB, 'memory' ) } + } + withName:'.*GRIPSS.*' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName: 'LILAC_PROCESS' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName: '.*LILAC:REALIGN_READS' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName: '.*LILAC:SLICE' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 6.GB, 'memory' ) } + } + withName: '.*LILAC:EXTRACT_AND_INDEX_CONTIG' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 6.GB, 'memory' ) } + } + withName:'.*LINX:.*' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'LINX_REPORT' { + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'.*PAVE.*' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'PURPLE' { + cpus = { check_max( 2, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'.*SAGE.*' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'SLICE' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'TEAL' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'COLLECTWGSMETRICS' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + time = { check_max( 24.h , 'time' ) } + } + withName:'VIRUSBREAKEND' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 64.GB, 'memory' ) } + } + withName:'VIRUSINTERPRETER' { + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'ISOFOX' { + memory = { check_max( 12.GB, 'memory' ) } + } + withName:'CUPPA.*' { + memory = { check_max( 12.GB, 'memory' ) } + } } diff --git a/conf/igenomes.config b/conf/igenomes.config index 17e698eb..7a1b3ac6 100644 --- a/conf/igenomes.config +++ b/conf/igenomes.config @@ -1,432 +1,432 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for iGenomes paths + Nextflow config file for iGenomes paths ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defines reference genomes using iGenome paths. - Can be used by any config that customises the base path using: - $params.igenomes_base / --igenomes_base + Defines reference genomes using iGenome paths. + Can be used by any config that customises the base path using: + $params.igenomes_base / --igenomes_base ---------------------------------------------------------------------------------------- */ params { - // illumina iGenomes reference file paths - genomes { - 'GRCh37' { - fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/GRCh37-blacklist.bed" + // illumina iGenomes reference file paths + genomes { + 'GRCh37' { + fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/GRCh37-blacklist.bed" + } + 'GRCh38' { + fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" + } + 'GRCm38' { + fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "1.87e9" + blacklist = "${projectDir}/assets/blacklists/GRCm38-blacklist.bed" + } + 'TAIR10' { + fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" + mito_name = "Mt" + } + 'EB2' { + fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" + } + 'UMD3.1' { + fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" + mito_name = "MT" + } + 'WBcel235' { + fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" + mito_name = "MtDNA" + macs_gsize = "9e7" + } + 'CanFam3.1' { + fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" + mito_name = "MT" + } + 'GRCz10' { + fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'BDGP6' { + fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" + mito_name = "M" + macs_gsize = "1.2e8" + } + 'EquCab2' { + fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" + mito_name = "MT" + } + 'EB1' { + fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" + } + 'Galgal4' { + fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'Gm01' { + fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" + } + 'Mmul_1' { + fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" + mito_name = "MT" + } + 'IRGSP-1.0' { + fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" + mito_name = "Mt" + } + 'CHIMP2.1.4' { + fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" + mito_name = "MT" + } + 'Rnor_5.0' { + fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'Rnor_6.0' { + fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'R64-1-1' { + fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" + mito_name = "MT" + macs_gsize = "1.2e7" + } + 'EF2' { + fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "1.21e7" + } + 'Sbi1' { + fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" + } + 'Sscrofa10.2' { + fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" + mito_name = "MT" + } + 'AGPv3' { + fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" + mito_name = "Mt" + } + 'hg38' { + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" + } + 'hg19' { + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/hg19-blacklist.bed" + } + 'mm10' { + fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "1.87e9" + blacklist = "${projectDir}/assets/blacklists/mm10-blacklist.bed" + } + 'bosTau8' { + fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" + mito_name = "chrM" + } + 'ce10' { + fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "9e7" + } + 'canFam3' { + fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" + mito_name = "chrM" + } + 'danRer10' { + fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "1.37e9" + } + 'dm6' { + fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "1.2e8" + } + 'equCab2' { + fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" + mito_name = "chrM" + } + 'galGal4' { + fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" + mito_name = "chrM" + } + 'panTro4' { + fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" + mito_name = "chrM" + } + 'rn6' { + fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" + mito_name = "chrM" + } + 'sacCer3' { + fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" + readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "1.2e7" + } + 'susScr3' { + fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" + mito_name = "chrM" + } } - 'GRCh38' { - fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'GRCm38' { - fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/GRCm38-blacklist.bed" - } - 'TAIR10' { - fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" - mito_name = "Mt" - } - 'EB2' { - fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" - } - 'UMD3.1' { - fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" - mito_name = "MT" - } - 'WBcel235' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" - mito_name = "MtDNA" - macs_gsize = "9e7" - } - 'CanFam3.1' { - fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" - mito_name = "MT" - } - 'GRCz10' { - fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'BDGP6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" - mito_name = "M" - macs_gsize = "1.2e8" - } - 'EquCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" - mito_name = "MT" - } - 'EB1' { - fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" - } - 'Galgal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Gm01' { - fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" - } - 'Mmul_1' { - fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" - mito_name = "MT" - } - 'IRGSP-1.0' { - fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'CHIMP2.1.4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" - mito_name = "MT" - } - 'Rnor_5.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Rnor_6.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'R64-1-1' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" - mito_name = "MT" - macs_gsize = "1.2e7" - } - 'EF2' { - fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.21e7" - } - 'Sbi1' { - fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" - } - 'Sscrofa10.2' { - fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" - mito_name = "MT" - } - 'AGPv3' { - fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'hg38' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'hg19' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg19-blacklist.bed" - } - 'mm10' { - fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/mm10-blacklist.bed" - } - 'bosTau8' { - fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'ce10' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "9e7" - } - 'canFam3' { - fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" - mito_name = "chrM" - } - 'danRer10' { - fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.37e9" - } - 'dm6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.2e8" - } - 'equCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" - mito_name = "chrM" - } - 'galGal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" - mito_name = "chrM" - } - 'panTro4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" - mito_name = "chrM" - } - 'rn6' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'sacCer3' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" - readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.2e7" - } - 'susScr3' { - fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" - mito_name = "chrM" - } - } } diff --git a/conf/modules.config b/conf/modules.config index 916efec0..32df7844 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -1,230 +1,231 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Config file for defining DSL2 per module options and publishing paths + Config file for defining DSL2 per module options and publishing paths ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Available keys to override module options: - ext.args = Additional arguments appended to command in module. - ext.args2 = Second set of arguments appended to command in module (multi-tool modules). - ext.args3 = Third set of arguments appended to command in module (multi-tool modules). - ext.prefix = File name prefix for output files. + Available keys to override module options: + ext.args = Additional arguments appended to command in module. + ext.args2 = Second set of arguments appended to command in module (multi-tool modules). + ext.args3 = Third set of arguments appended to command in module (multi-tool modules). + ext.prefix = File name prefix for output files. ---------------------------------------------------------------------------------------- */ + process { - withName: 'AMBER' { - ext.jarPath = '/opt/conda/share/hmftools-amber-3.9-1/amber.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, - ] - } - - withName: 'COBALT' { - ext.jarPath = '/opt/conda/share/hmftools-cobalt-1.13-1/cobalt.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, - ] - } - - withName: 'CUSTOM_DUMPSOFTWAREVERSIONS' { - publishDir = [ - path: { "${params.outdir}/pipeline_info" }, - mode: params.publish_dir_mode, - pattern: '*_versions.yml', - ] - } - - withName:'.*:(? - if(filename.equals('versions.yml')) { - return null - } else { - def tokens = filename.split('[/]') - return "${meta.id}/gridss/${tokens[-1]}" - } - } - ] - } - - withName: 'SVPREP_DEPTH_ANNOTATOR' { - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gridss/sv.vcf.gz" } - ] - } - - withName: 'GRIPSS.*' { - ext.jarPath = '/opt/gripss/gripss.jar' - } - - withName: '.*GRIPSS_GERMLINE' { - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gripss/germline/${filename}" }, - ] - } - - withName: '.*GRIPSS_SOMATIC' { - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gripss/somatic/${filename}" }, - ] - } - - withName: 'LILAC_PROCESS' { - ext.jarPath = '/opt/lilac/lilac.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" } - ] - } - - withName: '.*LINX:.*' { - ext.jarPath = '/opt/linx/linx.jar' - } - - withName: '.*LINX_GERMLINE' { - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/germline/" }, - ] - } - - withName: '.*LINX_SOMATIC' { - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic/" }, - ] - } - - withName: '.*LINX:VISUALISER' { - ext.path_circos = 'circos' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic/plots/" }, - ] - } - - withName: 'LINX_REPORT' { - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, - ] - } - - withName: 'PAVE.*' { - ext.jarPath = '/opt/pave/pave.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/pave/${filename}" }, - ] - } - - withName: 'COLLECTWGSMETRICS' { - tag = { "${task.index}" } - label = null - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/wgs_metrics/${filename}" }, - ] - } - - withName: 'PURPLE' { - ext.jarPath = '/opt/purple/purple.jar' - ext.circosPath = 'circos' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, - ] - } - - withName: 'SAGE.*' { - ext.jarPath = '/opt/sage/sage.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/${filename}" }, - ] - } - - withName: 'TEAL' { - ext.jarPath = '/opt/teal/teal.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, - ] - } - - withName: 'VIRUSBREAKEND' { - ext.jarPath = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/virusbreakend/${filename}" }, - ] - } - - withName: 'VIRUSINTERPRETER' { - ext.jarPath = '/opt/virusinterpreter/virusinterpreter.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, - ] - } - - withName: 'ISOFOX' { - ext.jarPath = '/opt/isofox/isofox.jar' - ext.args = '-functions "TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS"' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, - ] - } - - withName: 'CUPPA_CLASSIFIER' { - ext.jarPath = '/opt/cuppa/cuppa.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/cuppa/${filename}" }, - ] - } - - withName: 'CUPPA_VISUALISER' { - ext.pythonPath = '/opt/cuppa/chart/cuppa-chart.py' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/cuppa/${filename}" }, - ] - } + withName: 'AMBER' { + ext.jarPath = '/opt/conda/share/hmftools-amber-3.9-1/amber.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'COBALT' { + ext.jarPath = '/opt/conda/share/hmftools-cobalt-1.13-1/cobalt.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'CUSTOM_DUMPSOFTWAREVERSIONS' { + publishDir = [ + path: { "${params.outdir}/pipeline_info" }, + mode: params.publish_dir_mode, + pattern: '*_versions.yml', + ] + } + + withName:'.*:(? + if(filename.equals('versions.yml')) { + return null + } else { + def tokens = filename.split('[/]') + return "${meta.id}/gridss/${tokens[-1]}" + } + } + ] + } + + withName: 'SVPREP_DEPTH_ANNOTATOR' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gridss/sv.vcf.gz" } + ] + } + + withName: 'GRIPSS.*' { + ext.jarPath = '/opt/gripss/gripss.jar' + } + + withName: '.*GRIPSS_GERMLINE' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gripss/germline/${filename}" }, + ] + } + + withName: '.*GRIPSS_SOMATIC' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gripss/somatic/${filename}" }, + ] + } + + withName: 'LILAC_PROCESS' { + ext.jarPath = '/opt/lilac/lilac.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" } + ] + } + + withName: '.*LINX:.*' { + ext.jarPath = '/opt/linx/linx.jar' + } + + withName: '.*LINX_GERMLINE' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/germline/" }, + ] + } + + withName: '.*LINX_SOMATIC' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic/" }, + ] + } + + withName: '.*LINX:VISUALISER' { + ext.path_circos = 'circos' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic/plots/" }, + ] + } + + withName: 'LINX_REPORT' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'PAVE.*' { + ext.jarPath = '/opt/pave/pave.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/pave/${filename}" }, + ] + } + + withName: 'COLLECTWGSMETRICS' { + tag = { "${task.index}" } + label = null + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/wgs_metrics/${filename}" }, + ] + } + + withName: 'PURPLE' { + ext.jarPath = '/opt/purple/purple.jar' + ext.circosPath = 'circos' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'SAGE.*' { + ext.jarPath = '/opt/sage/sage.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/${filename}" }, + ] + } + + withName: 'TEAL' { + ext.jarPath = '/opt/teal/teal.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'VIRUSBREAKEND' { + ext.jarPath = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/virusbreakend/${filename}" }, + ] + } + + withName: 'VIRUSINTERPRETER' { + ext.jarPath = '/opt/virusinterpreter/virusinterpreter.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'ISOFOX' { + ext.jarPath = '/opt/isofox/isofox.jar' + ext.args = '-functions "TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS"' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + + withName: 'CUPPA_CLASSIFIER' { + ext.jarPath = '/opt/cuppa/cuppa.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/cuppa/${filename}" }, + ] + } + + withName: 'CUPPA_VISUALISER' { + ext.pythonPath = '/opt/cuppa/chart/cuppa-chart.py' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/cuppa/${filename}" }, + ] + } } diff --git a/conf/test.config b/conf/test.config index 6811c4b5..cafe270e 100644 --- a/conf/test.config +++ b/conf/test.config @@ -1,46 +1,46 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for running minimal tests + Nextflow config file for running minimal tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defines input files and everything required to run a fast and simple pipeline test. + Defines input files and everything required to run a fast and simple pipeline test. - Use as follows: - nextflow run umccr/hmftools -profile test, --outdir + Use as follows: + nextflow run nf-core/oncoanalyser -profile test, --outdir ---------------------------------------------------------------------------------------- */ process { - memory = 16.GB + memory = 16.GB - withName: 'SAGE_GERMLINE' { - ext.args = '-specific_regions \'chr10:87864102:87966988\'' - } + withName: 'SAGE_GERMLINE' { + ext.args = '-specific_regions \'chr10:87864102:87966988\'' + } - withName: 'SAGE_SOMATIC' { - ext.args = '-specific_regions \'chr10:87736200:88056500;chr17:59748500:59828700\'' - } + withName: 'SAGE_SOMATIC' { + ext.args = '-specific_regions \'chr10:87736200:88056500;chr17:59748500:59828700\'' + } - withName: 'COLLECTWGSMETRICS' { - // NOTE(SW): wrapped by a closure to delay eval until process creation/execution - ext.args = { "--INTERVALS ${params.ref_data_wgsmetrics_intervals_local}" } - } + withName: 'COLLECTWGSMETRICS' { + // NOTE(SW): wrapped by a closure to delay eval until process creation/execution + ext.args = { "--INTERVALS ${params.ref_data_wgsmetrics_intervals_local}" } + } } params { - config_profile_name = 'Test profile' - config_profile_description = 'Minimal test dataset to check pipeline function' + config_profile_name = 'Test profile' + config_profile_description = 'Minimal test dataset to check pipeline function' - // Defined here to be accessible within a workflow script; downloaded manually prior to process - // execution. - ref_data_wgsmetrics_intervals_url = 'https://raw.githubusercontent.com/scwatts/nextflow_testdata/main/hmftools/collectwgsmetrics/intervals.interval_list' - schema_ignore_params = 'ref_data_wgsmetrics_intervals_url' + // Defined here to be accessible within a workflow script; downloaded manually prior to process + // execution. + ref_data_wgsmetrics_intervals_url = 'https://raw.githubusercontent.com/scwatts/nextflow_testdata/main/hmftools/collectwgsmetrics/intervals.interval_list' + schema_ignore_params = 'ref_data_wgsmetrics_intervals_url' - // Limit resources so that this can run on GitHub Actions - max_cpus = 1 - max_memory = 16.GB - max_time = 20.m + // Limit resources so that this can run on GitHub Actions + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' - // Input data - input = '/Users/stephen/repos/nextflow_testdata/hmftools/input_tsv/samplesheet.tsv' + // Input data + input = '/Users/stephen/repos/nextflow_testdata/hmftools/input_tsv/samplesheet.tsv' } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 73710c38..5ec2e49d 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -1,28 +1,28 @@ class Constants { - static enum PipelineMode { - FULL, - MANUAL, - GRIDSS_PURPLE_LINX, - CUPPA, - } + static enum PipelineMode { + FULL, + MANUAL, + GRIDSS_PURPLE_LINX, + CUPPA, + } - static enum Process { - AMBER, - COBALT, - COLLECTWGSMETRICS, - CUPPA, - GRIDSS, - GRIPSS, - ISOFOX, - LILAC, - LINX, - PAVE, - PURPLE, - SAGE, - SVPREP, - TEAL, - VIRUSINTERPRETER, - } + static enum Process { + AMBER, + COBALT, + COLLECTWGSMETRICS, + CUPPA, + GRIDSS, + GRIPSS, + ISOFOX, + LILAC, + LINX, + PAVE, + PURPLE, + SAGE, + SVPREP, + TEAL, + VIRUSINTERPRETER, + } } diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy index 1b136381..b3d092f8 100755 --- a/lib/NfcoreSchema.groovy +++ b/lib/NfcoreSchema.groovy @@ -13,517 +13,517 @@ import groovy.json.JsonBuilder class NfcoreSchema { - // - // Resolve Schema path relative to main workflow directory - // - public static String getSchemaPath(workflow, schema_filename='nextflow_schema.json') { - return "${workflow.projectDir}/${schema_filename}" - } + // + // Resolve Schema path relative to main workflow directory + // + public static String getSchemaPath(workflow, schema_filename='nextflow_schema.json') { + return "${workflow.projectDir}/${schema_filename}" + } - // - // Function to loop over all parameters defined in schema and check - // whether the given parameters adhere to the specifications - // - /* groovylint-disable-next-line UnusedPrivateMethodParameter */ - public static void validateParameters(workflow, params, log, schema_filename='nextflow_schema.json') { - def has_error = false - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - // Check for nextflow core params and unexpected params - def json = new File(getSchemaPath(workflow, schema_filename=schema_filename)).text - def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions') - def nf_params = [ - // Options for base `nextflow` command - 'bg', - 'c', - 'C', - 'config', - 'd', - 'D', - 'dockerize', - 'h', - 'log', - 'q', - 'quiet', - 'syslog', - 'v', - 'version', + // + // Function to loop over all parameters defined in schema and check + // whether the given parameters adhere to the specifications + // + /* groovylint-disable-next-line UnusedPrivateMethodParameter */ + public static void validateParameters(workflow, params, log, schema_filename='nextflow_schema.json') { + def has_error = false + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Check for nextflow core params and unexpected params + def json = new File(getSchemaPath(workflow, schema_filename=schema_filename)).text + def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions') + def nf_params = [ + // Options for base `nextflow` command + 'bg', + 'c', + 'C', + 'config', + 'd', + 'D', + 'dockerize', + 'h', + 'log', + 'q', + 'quiet', + 'syslog', + 'v', + 'version', - // Options for `nextflow run` command - 'ansi', - 'ansi-log', - 'bg', - 'bucket-dir', - 'c', - 'cache', - 'config', - 'dsl2', - 'dump-channels', - 'dump-hashes', - 'E', - 'entry', - 'latest', - 'lib', - 'main-script', - 'N', - 'name', - 'offline', - 'params-file', - 'pi', - 'plugins', - 'poll-interval', - 'pool-size', - 'profile', - 'ps', - 'qs', - 'queue-size', - 'r', - 'resume', - 'revision', - 'stdin', - 'stub', - 'stub-run', - 'test', - 'w', - 'with-charliecloud', - 'with-conda', - 'with-dag', - 'with-docker', - 'with-mpi', - 'with-notification', - 'with-podman', - 'with-report', - 'with-singularity', - 'with-timeline', - 'with-tower', - 'with-trace', - 'with-weblog', - 'without-docker', - 'without-podman', - 'work-dir' - ] - def unexpectedParams = [] + // Options for `nextflow run` command + 'ansi', + 'ansi-log', + 'bg', + 'bucket-dir', + 'c', + 'cache', + 'config', + 'dsl2', + 'dump-channels', + 'dump-hashes', + 'E', + 'entry', + 'latest', + 'lib', + 'main-script', + 'N', + 'name', + 'offline', + 'params-file', + 'pi', + 'plugins', + 'poll-interval', + 'pool-size', + 'profile', + 'ps', + 'qs', + 'queue-size', + 'r', + 'resume', + 'revision', + 'stdin', + 'stub', + 'stub-run', + 'test', + 'w', + 'with-charliecloud', + 'with-conda', + 'with-dag', + 'with-docker', + 'with-mpi', + 'with-notification', + 'with-podman', + 'with-report', + 'with-singularity', + 'with-timeline', + 'with-tower', + 'with-trace', + 'with-weblog', + 'without-docker', + 'without-podman', + 'work-dir' + ] + def unexpectedParams = [] - // Collect expected parameters from the schema - def expectedParams = [] - def enums = [:] - for (group in schemaParams) { - for (p in group.value['properties']) { - expectedParams.push(p.key) - if (group.value['properties'][p.key].containsKey('enum')) { - enums[p.key] = group.value['properties'][p.key]['enum'] + // Collect expected parameters from the schema + def expectedParams = [] + def enums = [:] + for (group in schemaParams) { + for (p in group.value['properties']) { + expectedParams.push(p.key) + if (group.value['properties'][p.key].containsKey('enum')) { + enums[p.key] = group.value['properties'][p.key]['enum'] + } + } } - } - } - for (specifiedParam in params.keySet()) { - // nextflow params - if (nf_params.contains(specifiedParam)) { - log.error "ERROR: You used a core Nextflow option with two hyphens: '--${specifiedParam}'. Please resubmit with '-${specifiedParam}'" - has_error = true - } - // unexpected params - def params_ignore = params.schema_ignore_params.split(',') + 'schema_ignore_params' - def expectedParamsLowerCase = expectedParams.collect{ it.replace("-", "").toLowerCase() } - def specifiedParamLowerCase = specifiedParam.replace("-", "").toLowerCase() - def isCamelCaseBug = (specifiedParam.contains("-") && !expectedParams.contains(specifiedParam) && expectedParamsLowerCase.contains(specifiedParamLowerCase)) - if (!expectedParams.contains(specifiedParam) && !params_ignore.contains(specifiedParam) && !isCamelCaseBug) { - // Temporarily remove camelCase/camel-case params #1035 - def unexpectedParamsLowerCase = unexpectedParams.collect{ it.replace("-", "").toLowerCase()} - if (!unexpectedParamsLowerCase.contains(specifiedParamLowerCase)){ - unexpectedParams.push(specifiedParam) + for (specifiedParam in params.keySet()) { + // nextflow params + if (nf_params.contains(specifiedParam)) { + log.error "ERROR: You used a core Nextflow option with two hyphens: '--${specifiedParam}'. Please resubmit with '-${specifiedParam}'" + has_error = true + } + // unexpected params + def params_ignore = params.schema_ignore_params.split(',') + 'schema_ignore_params' + def expectedParamsLowerCase = expectedParams.collect{ it.replace("-", "").toLowerCase() } + def specifiedParamLowerCase = specifiedParam.replace("-", "").toLowerCase() + def isCamelCaseBug = (specifiedParam.contains("-") && !expectedParams.contains(specifiedParam) && expectedParamsLowerCase.contains(specifiedParamLowerCase)) + if (!expectedParams.contains(specifiedParam) && !params_ignore.contains(specifiedParam) && !isCamelCaseBug) { + // Temporarily remove camelCase/camel-case params #1035 + def unexpectedParamsLowerCase = unexpectedParams.collect{ it.replace("-", "").toLowerCase()} + if (!unexpectedParamsLowerCase.contains(specifiedParamLowerCase)){ + unexpectedParams.push(specifiedParam) + } + } } - } - } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - // Validate parameters against the schema - InputStream input_stream = new File(getSchemaPath(workflow, schema_filename=schema_filename)).newInputStream() - JSONObject raw_schema = new JSONObject(new JSONTokener(input_stream)) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Validate parameters against the schema + InputStream input_stream = new File(getSchemaPath(workflow, schema_filename=schema_filename)).newInputStream() + JSONObject raw_schema = new JSONObject(new JSONTokener(input_stream)) - // Remove anything that's in params.schema_ignore_params - raw_schema = removeIgnoredParams(raw_schema, params) + // Remove anything that's in params.schema_ignore_params + raw_schema = removeIgnoredParams(raw_schema, params) - Schema schema = SchemaLoader.load(raw_schema) + Schema schema = SchemaLoader.load(raw_schema) - // Clean the parameters - def cleanedParams = cleanParameters(params) + // Clean the parameters + def cleanedParams = cleanParameters(params) - // Convert to JSONObject - def jsonParams = new JsonBuilder(cleanedParams) - JSONObject params_json = new JSONObject(jsonParams.toString()) + // Convert to JSONObject + def jsonParams = new JsonBuilder(cleanedParams) + JSONObject params_json = new JSONObject(jsonParams.toString()) - // Validate - try { - schema.validate(params_json) - } catch (ValidationException e) { - println '' - log.error 'ERROR: Validation of pipeline parameters failed!' - JSONObject exceptionJSON = e.toJSON() - printExceptions(exceptionJSON, params_json, log, enums) - println '' - has_error = true - } + // Validate + try { + schema.validate(params_json) + } catch (ValidationException e) { + println '' + log.error 'ERROR: Validation of pipeline parameters failed!' + JSONObject exceptionJSON = e.toJSON() + printExceptions(exceptionJSON, params_json, log, enums) + println '' + has_error = true + } - // Check for unexpected parameters - if (unexpectedParams.size() > 0) { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - println '' - def warn_msg = 'Found unexpected parameters:' - for (unexpectedParam in unexpectedParams) { - warn_msg = warn_msg + "\n* --${unexpectedParam}: ${params[unexpectedParam].toString()}" - } - log.warn warn_msg - log.info "- ${colors.dim}Ignore this warning: params.schema_ignore_params = \"${unexpectedParams.join(',')}\" ${colors.reset}" - println '' - } + // Check for unexpected parameters + if (unexpectedParams.size() > 0) { + Map colors = NfcoreTemplate.logColours(params.monochrome_logs) + println '' + def warn_msg = 'Found unexpected parameters:' + for (unexpectedParam in unexpectedParams) { + warn_msg = warn_msg + "\n* --${unexpectedParam}: ${params[unexpectedParam].toString()}" + } + log.warn warn_msg + log.info "- ${colors.dim}Ignore this warning: params.schema_ignore_params = \"${unexpectedParams.join(',')}\" ${colors.reset}" + println '' + } - if (has_error) { - System.exit(1) + if (has_error) { + System.exit(1) + } } - } - // - // Beautify parameters for --help - // - public static String paramsHelp(workflow, params, command, schema_filename='nextflow_schema.json') { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - Integer num_hidden = 0 - String output = '' - output += 'Typical pipeline command:\n\n' - output += " ${colors.cyan}${command}${colors.reset}\n\n" - Map params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) - Integer max_chars = paramsMaxChars(params_map) + 1 - Integer desc_indent = max_chars + 14 - Integer dec_linewidth = 160 - desc_indent - for (group in params_map.keySet()) { - Integer num_params = 0 - String group_output = colors.underlined + colors.bold + group + colors.reset + '\n' - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (group_params.get(param).hidden && !params.show_hidden_params) { - num_hidden += 1 - continue; - } - def type = '[' + group_params.get(param).type + ']' - def description = group_params.get(param).description - def defaultValue = group_params.get(param).default != null ? " [default: " + group_params.get(param).default.toString() + "]" : '' - def description_default = description + colors.dim + defaultValue + colors.reset - // Wrap long description texts - // Loosely based on https://dzone.com/articles/groovy-plain-text-word-wrap - if (description_default.length() > dec_linewidth){ - List olines = [] - String oline = "" // " " * indent - description_default.split(" ").each() { wrd -> - if ((oline.size() + wrd.size()) <= dec_linewidth) { - oline += wrd + " " - } else { - olines += oline - oline = wrd + " " + // + // Beautify parameters for --help + // + public static String paramsHelp(workflow, params, command, schema_filename='nextflow_schema.json') { + Map colors = NfcoreTemplate.logColours(params.monochrome_logs) + Integer num_hidden = 0 + String output = '' + output += 'Typical pipeline command:\n\n' + output += " ${colors.cyan}${command}${colors.reset}\n\n" + Map params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) + Integer max_chars = paramsMaxChars(params_map) + 1 + Integer desc_indent = max_chars + 14 + Integer dec_linewidth = 160 - desc_indent + for (group in params_map.keySet()) { + Integer num_params = 0 + String group_output = colors.underlined + colors.bold + group + colors.reset + '\n' + def group_params = params_map.get(group) // This gets the parameters of that particular group + for (param in group_params.keySet()) { + if (group_params.get(param).hidden && !params.show_hidden_params) { + num_hidden += 1 + continue; + } + def type = '[' + group_params.get(param).type + ']' + def description = group_params.get(param).description + def defaultValue = group_params.get(param).default != null ? " [default: " + group_params.get(param).default.toString() + "]" : '' + def description_default = description + colors.dim + defaultValue + colors.reset + // Wrap long description texts + // Loosely based on https://dzone.com/articles/groovy-plain-text-word-wrap + if (description_default.length() > dec_linewidth){ + List olines = [] + String oline = "" // " " * indent + description_default.split(" ").each() { wrd -> + if ((oline.size() + wrd.size()) <= dec_linewidth) { + oline += wrd + " " + } else { + olines += oline + oline = wrd + " " + } + } + olines += oline + description_default = olines.join("\n" + " " * desc_indent) + } + group_output += " --" + param.padRight(max_chars) + colors.dim + type.padRight(10) + colors.reset + description_default + '\n' + num_params += 1 + } + group_output += '\n' + if (num_params > 0){ + output += group_output } - } - olines += oline - description_default = olines.join("\n" + " " * desc_indent) } - group_output += " --" + param.padRight(max_chars) + colors.dim + type.padRight(10) + colors.reset + description_default + '\n' - num_params += 1 - } - group_output += '\n' - if (num_params > 0){ - output += group_output - } - } - if (num_hidden > 0){ - output += colors.dim + "!! Hiding $num_hidden params, use --show_hidden_params to show them !!\n" + colors.reset + if (num_hidden > 0){ + output += colors.dim + "!! Hiding $num_hidden params, use --show_hidden_params to show them !!\n" + colors.reset + } + output += NfcoreTemplate.dashedLine(params.monochrome_logs) + return output } - output += NfcoreTemplate.dashedLine(params.monochrome_logs) - return output - } - // - // Groovy Map summarising parameters/workflow options used by the pipeline - // - public static LinkedHashMap paramsSummaryMap(workflow, params, schema_filename='nextflow_schema.json') { - // Get a selection of core Nextflow workflow options - def Map workflow_summary = [:] - if (workflow.revision) { - workflow_summary['revision'] = workflow.revision - } - workflow_summary['runName'] = workflow.runName - if (workflow.containerEngine) { - workflow_summary['containerEngine'] = workflow.containerEngine - } - if (workflow.container) { - workflow_summary['container'] = workflow.container - } - workflow_summary['launchDir'] = workflow.launchDir - workflow_summary['workDir'] = workflow.workDir - workflow_summary['projectDir'] = workflow.projectDir - workflow_summary['userName'] = workflow.userName - workflow_summary['profile'] = workflow.profile - workflow_summary['configFiles'] = workflow.configFiles.join(', ') + // + // Groovy Map summarising parameters/workflow options used by the pipeline + // + public static LinkedHashMap paramsSummaryMap(workflow, params, schema_filename='nextflow_schema.json') { + // Get a selection of core Nextflow workflow options + def Map workflow_summary = [:] + if (workflow.revision) { + workflow_summary['revision'] = workflow.revision + } + workflow_summary['runName'] = workflow.runName + if (workflow.containerEngine) { + workflow_summary['containerEngine'] = workflow.containerEngine + } + if (workflow.container) { + workflow_summary['container'] = workflow.container + } + workflow_summary['launchDir'] = workflow.launchDir + workflow_summary['workDir'] = workflow.workDir + workflow_summary['projectDir'] = workflow.projectDir + workflow_summary['userName'] = workflow.userName + workflow_summary['profile'] = workflow.profile + workflow_summary['configFiles'] = workflow.configFiles.join(', ') - // Get pipeline parameters defined in JSON Schema - def Map params_summary = [:] - def params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) - for (group in params_map.keySet()) { - def sub_params = new LinkedHashMap() - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (params.containsKey(param)) { - def params_value = params.get(param) - def schema_value = group_params.get(param).default - def param_type = group_params.get(param).type - if (schema_value != null) { - if (param_type == 'string') { - if (schema_value.contains('$projectDir') || schema_value.contains('${projectDir}')) { - def sub_string = schema_value.replace('\$projectDir', '') - sub_string = sub_string.replace('\${projectDir}', '') - if (params_value.contains(sub_string)) { - schema_value = params_value - } - } - if (schema_value.contains('$params.outdir') || schema_value.contains('${params.outdir}')) { - def sub_string = schema_value.replace('\$params.outdir', '') - sub_string = sub_string.replace('\${params.outdir}', '') - if ("${params.outdir}${sub_string}" == params_value) { - schema_value = params_value + // Get pipeline parameters defined in JSON Schema + def Map params_summary = [:] + def params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) + for (group in params_map.keySet()) { + def sub_params = new LinkedHashMap() + def group_params = params_map.get(group) // This gets the parameters of that particular group + for (param in group_params.keySet()) { + if (params.containsKey(param)) { + def params_value = params.get(param) + def schema_value = group_params.get(param).default + def param_type = group_params.get(param).type + if (schema_value != null) { + if (param_type == 'string') { + if (schema_value.contains('$projectDir') || schema_value.contains('${projectDir}')) { + def sub_string = schema_value.replace('\$projectDir', '') + sub_string = sub_string.replace('\${projectDir}', '') + if (params_value.contains(sub_string)) { + schema_value = params_value + } + } + if (schema_value.contains('$params.outdir') || schema_value.contains('${params.outdir}')) { + def sub_string = schema_value.replace('\$params.outdir', '') + sub_string = sub_string.replace('\${params.outdir}', '') + if ("${params.outdir}${sub_string}" == params_value) { + schema_value = params_value + } + } + } + } + + // We have a default in the schema, and this isn't it + if (schema_value != null && params_value != schema_value) { + sub_params.put(param, params_value) + } + // No default in the schema, and this isn't empty + else if (schema_value == null && params_value != "" && params_value != null && params_value != false) { + sub_params.put(param, params_value) + } } - } } - } - - // We have a default in the schema, and this isn't it - if (schema_value != null && params_value != schema_value) { - sub_params.put(param, params_value) - } - // No default in the schema, and this isn't empty - else if (schema_value == null && params_value != "" && params_value != null && params_value != false) { - sub_params.put(param, params_value) - } + params_summary.put(group, sub_params) } - } - params_summary.put(group, sub_params) + return [ 'Core Nextflow options' : workflow_summary ] << params_summary } - return [ 'Core Nextflow options' : workflow_summary ] << params_summary - } - // - // Beautify parameters for summary and return as string - // - public static String paramsSummaryLog(workflow, params) { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - String output = '' - def params_map = paramsSummaryMap(workflow, params) - def max_chars = paramsMaxChars(params_map) - for (group in params_map.keySet()) { - def group_params = params_map.get(group) // This gets the parameters of that particular group - if (group_params) { - output += colors.bold + group + colors.reset + '\n' - for (param in group_params.keySet()) { - output += " " + colors.blue + param.padRight(max_chars) + ": " + colors.green + group_params.get(param) + colors.reset + '\n' + // + // Beautify parameters for summary and return as string + // + public static String paramsSummaryLog(workflow, params) { + Map colors = NfcoreTemplate.logColours(params.monochrome_logs) + String output = '' + def params_map = paramsSummaryMap(workflow, params) + def max_chars = paramsMaxChars(params_map) + for (group in params_map.keySet()) { + def group_params = params_map.get(group) // This gets the parameters of that particular group + if (group_params) { + output += colors.bold + group + colors.reset + '\n' + for (param in group_params.keySet()) { + output += " " + colors.blue + param.padRight(max_chars) + ": " + colors.green + group_params.get(param) + colors.reset + '\n' + } + output += '\n' + } } - output += '\n' - } + output += "!! Only displaying parameters that differ from the pipeline defaults !!\n" + output += NfcoreTemplate.dashedLine(params.monochrome_logs) + return output } - output += "!! Only displaying parameters that differ from the pipeline defaults !!\n" - output += NfcoreTemplate.dashedLine(params.monochrome_logs) - return output - } - // - // Loop over nested exceptions and print the causingException - // - private static void printExceptions(ex_json, params_json, log, enums, limit=5) { - def causingExceptions = ex_json['causingExceptions'] - if (causingExceptions.length() == 0) { - def m = ex_json['message'] =~ /required key \[([^\]]+)\] not found/ - // Missing required param - if (m.matches()) { - log.error "* Missing required parameter: --${m[0][1]}" - } - // Other base-level error - else if (ex_json['pointerToViolation'] == '#') { - log.error "* ${ex_json['message']}" - } - // Error with specific param - else { - def param = ex_json['pointerToViolation'] - ~/^#\// - def param_val = params_json[param].toString() - if (enums.containsKey(param)) { - def error_msg = "* --${param}: '${param_val}' is not a valid choice (Available choices" - if (enums[param].size() > limit) { - log.error "${error_msg} (${limit} of ${enums[param].size()}): ${enums[param][0..limit-1].join(', ')}, ... )" - } else { - log.error "${error_msg}: ${enums[param].join(', ')})" - } - } else { - log.error "* --${param}: ${ex_json['message']} (${param_val})" + // + // Loop over nested exceptions and print the causingException + // + private static void printExceptions(ex_json, params_json, log, enums, limit=5) { + def causingExceptions = ex_json['causingExceptions'] + if (causingExceptions.length() == 0) { + def m = ex_json['message'] =~ /required key \[([^\]]+)\] not found/ + // Missing required param + if (m.matches()) { + log.error "* Missing required parameter: --${m[0][1]}" + } + // Other base-level error + else if (ex_json['pointerToViolation'] == '#') { + log.error "* ${ex_json['message']}" + } + // Error with specific param + else { + def param = ex_json['pointerToViolation'] - ~/^#\// + def param_val = params_json[param].toString() + if (enums.containsKey(param)) { + def error_msg = "* --${param}: '${param_val}' is not a valid choice (Available choices" + if (enums[param].size() > limit) { + log.error "${error_msg} (${limit} of ${enums[param].size()}): ${enums[param][0..limit-1].join(', ')}, ... )" + } else { + log.error "${error_msg}: ${enums[param].join(', ')})" + } + } else { + log.error "* --${param}: ${ex_json['message']} (${param_val})" + } + } + } + for (ex in causingExceptions) { + printExceptions(ex, params_json, log, enums) } - } - } - for (ex in causingExceptions) { - printExceptions(ex, params_json, log, enums) } - } - // - // Remove an element from a JSONArray - // - private static JSONArray removeElement(json_array, element) { - def list = [] - int len = json_array.length() - for (int i=0;i - if(raw_schema.keySet().contains('definitions')){ - raw_schema.definitions.each { definition -> - for (key in definition.keySet()){ - if (definition[key].get("properties").keySet().contains(ignore_param)){ - // Remove the param to ignore - definition[key].get("properties").remove(ignore_param) - // If the param was required, change this - if (definition[key].has("required")) { - def cleaned_required = removeElement(definition[key].required, ignore_param) - definition[key].put("required", cleaned_required) - } + // + // Remove ignored parameters + // + private static JSONObject removeIgnoredParams(raw_schema, params) { + // Remove anything that's in params.schema_ignore_params + params.schema_ignore_params.split(',').each{ ignore_param -> + if(raw_schema.keySet().contains('definitions')){ + raw_schema.definitions.each { definition -> + for (key in definition.keySet()){ + if (definition[key].get("properties").keySet().contains(ignore_param)){ + // Remove the param to ignore + definition[key].get("properties").remove(ignore_param) + // If the param was required, change this + if (definition[key].has("required")) { + def cleaned_required = removeElement(definition[key].required, ignore_param) + definition[key].put("required", cleaned_required) + } + } + } + } + } + if(raw_schema.keySet().contains('properties') && raw_schema.get('properties').keySet().contains(ignore_param)) { + raw_schema.get("properties").remove(ignore_param) + } + if(raw_schema.keySet().contains('required') && raw_schema.required.contains(ignore_param)) { + def cleaned_required = removeElement(raw_schema.required, ignore_param) + raw_schema.put("required", cleaned_required) } - } } - } - if(raw_schema.keySet().contains('properties') && raw_schema.get('properties').keySet().contains(ignore_param)) { - raw_schema.get("properties").remove(ignore_param) - } - if(raw_schema.keySet().contains('required') && raw_schema.required.contains(ignore_param)) { - def cleaned_required = removeElement(raw_schema.required, ignore_param) - raw_schema.put("required", cleaned_required) - } + return raw_schema } - return raw_schema - } - // - // Clean and check parameters relative to Nextflow native classes - // - private static Map cleanParameters(params) { - def new_params = params.getClass().newInstance(params) - for (p in params) { - // remove anything evaluating to false - if (!p['value']) { - new_params.remove(p.key) - } - // Cast MemoryUnit to String - if (p['value'].getClass() == nextflow.util.MemoryUnit) { - new_params.replace(p.key, p['value'].toString()) - } - // Cast Duration to String - if (p['value'].getClass() == nextflow.util.Duration) { - new_params.replace(p.key, p['value'].toString().replaceFirst(/d(?!\S)/, "day")) - } - // Cast LinkedHashMap to String - if (p['value'].getClass() == LinkedHashMap) { - new_params.replace(p.key, p['value'].toString()) - } + // + // Clean and check parameters relative to Nextflow native classes + // + private static Map cleanParameters(params) { + def new_params = params.getClass().newInstance(params) + for (p in params) { + // remove anything evaluating to false + if (!p['value']) { + new_params.remove(p.key) + } + // Cast MemoryUnit to String + if (p['value'].getClass() == nextflow.util.MemoryUnit) { + new_params.replace(p.key, p['value'].toString()) + } + // Cast Duration to String + if (p['value'].getClass() == nextflow.util.Duration) { + new_params.replace(p.key, p['value'].toString().replaceFirst(/d(?!\S)/, "day")) + } + // Cast LinkedHashMap to String + if (p['value'].getClass() == LinkedHashMap) { + new_params.replace(p.key, p['value'].toString()) + } + } + return new_params } - return new_params - } - // - // This function tries to read a JSON params file - // - private static LinkedHashMap paramsLoad(String json_schema) { - def params_map = new LinkedHashMap() - try { - params_map = paramsRead(json_schema) - } catch (Exception e) { - println "Could not read parameters settings from JSON. $e" - params_map = new LinkedHashMap() + // + // This function tries to read a JSON params file + // + private static LinkedHashMap paramsLoad(String json_schema) { + def params_map = new LinkedHashMap() + try { + params_map = paramsRead(json_schema) + } catch (Exception e) { + println "Could not read parameters settings from JSON. $e" + params_map = new LinkedHashMap() + } + return params_map } - return params_map - } - // - // Method to actually read in JSON file using Groovy. - // Group (as Key), values are all parameters - // - Parameter1 as Key, Description as Value - // - Parameter2 as Key, Description as Value - // .... - // Group - // - - private static LinkedHashMap paramsRead(String json_schema) throws Exception { - def json = new File(json_schema).text - def Map schema_definitions = (Map) new JsonSlurper().parseText(json).get('definitions') - def Map schema_properties = (Map) new JsonSlurper().parseText(json).get('properties') - /* Tree looks like this in nf-core schema - * definitions <- this is what the first get('definitions') gets us - group 1 - title - description - properties - parameter 1 - type - description - parameter 2 - type - description - group 2 - title - description - properties - parameter 1 - type - description - * properties <- parameters can also be ungrouped, outside of definitions - parameter 1 - type - description - */ + // + // Method to actually read in JSON file using Groovy. + // Group (as Key), values are all parameters + // - Parameter1 as Key, Description as Value + // - Parameter2 as Key, Description as Value + // .... + // Group + // - + private static LinkedHashMap paramsRead(String json_schema) throws Exception { + def json = new File(json_schema).text + def Map schema_definitions = (Map) new JsonSlurper().parseText(json).get('definitions') + def Map schema_properties = (Map) new JsonSlurper().parseText(json).get('properties') + /* Tree looks like this in nf-core schema + * definitions <- this is what the first get('definitions') gets us + group 1 + title + description + properties + parameter 1 + type + description + parameter 2 + type + description + group 2 + title + description + properties + parameter 1 + type + description + * properties <- parameters can also be ungrouped, outside of definitions + parameter 1 + type + description + */ - // Grouped params - def params_map = new LinkedHashMap() - schema_definitions.each { key, val -> - def Map group = schema_definitions."$key".properties // Gets the property object of the group - def title = schema_definitions."$key".title - def sub_params = new LinkedHashMap() - group.each { innerkey, value -> - sub_params.put(innerkey, value) - } - params_map.put(title, sub_params) - } + // Grouped params + def params_map = new LinkedHashMap() + schema_definitions.each { key, val -> + def Map group = schema_definitions."$key".properties // Gets the property object of the group + def title = schema_definitions."$key".title + def sub_params = new LinkedHashMap() + group.each { innerkey, value -> + sub_params.put(innerkey, value) + } + params_map.put(title, sub_params) + } - // Ungrouped params - def ungrouped_params = new LinkedHashMap() - schema_properties.each { innerkey, value -> - ungrouped_params.put(innerkey, value) - } - params_map.put("Other parameters", ungrouped_params) + // Ungrouped params + def ungrouped_params = new LinkedHashMap() + schema_properties.each { innerkey, value -> + ungrouped_params.put(innerkey, value) + } + params_map.put("Other parameters", ungrouped_params) - return params_map - } + return params_map + } - // - // Get maximum number of characters across all parameter names - // - private static Integer paramsMaxChars(params_map) { - Integer max_chars = 0 - for (group in params_map.keySet()) { - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (param.size() > max_chars) { - max_chars = param.size() + // + // Get maximum number of characters across all parameter names + // + private static Integer paramsMaxChars(params_map) { + Integer max_chars = 0 + for (group in params_map.keySet()) { + def group_params = params_map.get(group) // This gets the parameters of that particular group + for (param in group_params.keySet()) { + if (param.size() > max_chars) { + max_chars = param.size() + } + } } - } + return max_chars } - return max_chars - } } diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 10e5ccd0..27feb009 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -6,253 +6,308 @@ import org.yaml.snakeyaml.Yaml class NfcoreTemplate { - // - // Check AWS Batch related parameters have been specified correctly - // - public static void awsBatch(workflow, params) { - if (workflow.profile.contains('awsbatch')) { - // Check params.awsqueue and params.awsregion have been set if running on AWSBatch - assert (params.awsqueue && params.awsregion) : "Specify correct --awsqueue and --awsregion parameters on AWSBatch!" - // Check outdir paths to be S3 buckets if running on AWSBatch - assert params.outdir.startsWith('s3:') : "Outdir not on S3 - specify S3 Bucket to run on AWSBatch!" + // + // Check AWS Batch related parameters have been specified correctly + // + public static void awsBatch(workflow, params) { + if (workflow.profile.contains('awsbatch')) { + // Check params.awsqueue and params.awsregion have been set if running on AWSBatch + assert (params.awsqueue && params.awsregion) : "Specify correct --awsqueue and --awsregion parameters on AWSBatch!" + // Check outdir paths to be S3 buckets if running on AWSBatch + assert params.outdir.startsWith('s3:') : "Outdir not on S3 - specify S3 Bucket to run on AWSBatch!" + } } - } - - // - // Warn if a -profile or Nextflow config has not been provided to run the pipeline - // - public static void checkConfigProvided(workflow, log) { - if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { - log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + - "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + - " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + - " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + - " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + - "Please refer to the quick start section and usage docs for the pipeline.\n " + + // + // Warn if a -profile or Nextflow config has not been provided to run the pipeline + // + public static void checkConfigProvided(workflow, log) { + if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { + log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + + "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + + " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + + " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + + " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + + "Please refer to the quick start section and usage docs for the pipeline.\n " + } } - } - // - // Construct and send completion email - // - public static void email(workflow, params, summary_params, projectDir, log, multiqc_report=[]) { + // + // Construct and send completion email + // + public static void email(workflow, params, summary_params, projectDir, log, multiqc_report=[]) { - // Set up the e-mail variables - def subject = "[$workflow.manifest.name] Successful: $workflow.runName" - if (!workflow.success) { - subject = "[$workflow.manifest.name] FAILED: $workflow.runName" - } + // Set up the e-mail variables + def subject = "[$workflow.manifest.name] Successful: $workflow.runName" + if (!workflow.success) { + subject = "[$workflow.manifest.name] FAILED: $workflow.runName" + } - def summary = [:] - for (group in summary_params.keySet()) { - summary << summary_params[group] - } + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['Date Started'] = workflow.start + misc_fields['Date Completed'] = workflow.complete + misc_fields['Pipeline script file path'] = workflow.scriptFile + misc_fields['Pipeline script hash ID'] = workflow.scriptId + if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository + if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId + if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision + misc_fields['Nextflow Version'] = workflow.nextflow.version + misc_fields['Nextflow Build'] = workflow.nextflow.build + misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp + + def email_fields = [:] + email_fields['version'] = workflow.manifest.version + email_fields['runName'] = workflow.runName + email_fields['success'] = workflow.success + email_fields['dateComplete'] = workflow.complete + email_fields['duration'] = workflow.duration + email_fields['exitStatus'] = workflow.exitStatus + email_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + email_fields['errorReport'] = (workflow.errorReport ?: 'None') + email_fields['commandLine'] = workflow.commandLine + email_fields['projectDir'] = workflow.projectDir + email_fields['summary'] = summary << misc_fields + + // On success try attach the multiqc report + def mqc_report = null + try { + if (workflow.success) { + mqc_report = multiqc_report.getVal() + if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { + if (mqc_report.size() > 1) { + log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" + } + mqc_report = mqc_report[0] + } + } + } catch (all) { + if (multiqc_report) { + log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" + } + } + + // Check if we are only sending emails on failure + def email_address = params.email + if (!params.email && params.email_on_fail && !workflow.success) { + email_address = params.email_on_fail + } + + // Render the TXT template + def engine = new groovy.text.GStringTemplateEngine() + def tf = new File("$projectDir/assets/email_template.txt") + def txt_template = engine.createTemplate(tf).make(email_fields) + def email_txt = txt_template.toString() + + // Render the HTML template + def hf = new File("$projectDir/assets/email_template.html") + def html_template = engine.createTemplate(hf).make(email_fields) + def email_html = html_template.toString() + + // Render the sendmail template + def max_multiqc_email_size = params.max_multiqc_email_size as nextflow.util.MemoryUnit + def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] + def sf = new File("$projectDir/assets/sendmail_template.txt") + def sendmail_template = engine.createTemplate(sf).make(smail_fields) + def sendmail_html = sendmail_template.toString() + + // Send the HTML e-mail + Map colors = logColours(params.monochrome_logs) + if (email_address) { + try { + if (params.plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } + // Try to send HTML e-mail using sendmail + [ 'sendmail', '-t' ].execute() << sendmail_html + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" + } catch (all) { + // Catch failures and try with plaintext + def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] + if ( mqc_report.size() <= max_multiqc_email_size.toBytes() ) { + mail_cmd += [ '-A', mqc_report ] + } + mail_cmd.execute() << email_html + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" + } + } - def misc_fields = [:] - misc_fields['Date Started'] = workflow.start - misc_fields['Date Completed'] = workflow.complete - misc_fields['Pipeline script file path'] = workflow.scriptFile - misc_fields['Pipeline script hash ID'] = workflow.scriptId - if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository - if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId - if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision - misc_fields['Nextflow Version'] = workflow.nextflow.version - misc_fields['Nextflow Build'] = workflow.nextflow.build - misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp - - def email_fields = [:] - email_fields['version'] = workflow.manifest.version - email_fields['runName'] = workflow.runName - email_fields['success'] = workflow.success - email_fields['dateComplete'] = workflow.complete - email_fields['duration'] = workflow.duration - email_fields['exitStatus'] = workflow.exitStatus - email_fields['errorMessage'] = (workflow.errorMessage ?: 'None') - email_fields['errorReport'] = (workflow.errorReport ?: 'None') - email_fields['commandLine'] = workflow.commandLine - email_fields['projectDir'] = workflow.projectDir - email_fields['summary'] = summary << misc_fields - - // On success try attach the multiqc report - def mqc_report = null - try { - if (workflow.success) { - mqc_report = multiqc_report.getVal() - if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { - if (mqc_report.size() > 1) { - log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" - } - mqc_report = mqc_report[0] + // Write summary e-mail HTML to a file + def output_d = new File("${params.outdir}/pipeline_info/") + if (!output_d.exists()) { + output_d.mkdirs() } - } - } catch (all) { - if (multiqc_report) { - log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" - } + def output_hf = new File(output_d, "pipeline_report.html") + output_hf.withWriter { w -> w << email_html } + def output_tf = new File(output_d, "pipeline_report.txt") + output_tf.withWriter { w -> w << email_txt } } - // Check if we are only sending emails on failure - def email_address = params.email - if (!params.email && params.email_on_fail && !workflow.success) { - email_address = params.email_on_fail + // + // Construct and send adaptive card + // https://adaptivecards.io + // + public static void adaptivecard(workflow, params, summary_params, projectDir, log) { + def hook_url = params.hook_url + + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['start'] = workflow.start + misc_fields['complete'] = workflow.complete + misc_fields['scriptfile'] = workflow.scriptFile + misc_fields['scriptid'] = workflow.scriptId + if (workflow.repository) misc_fields['repository'] = workflow.repository + if (workflow.commitId) misc_fields['commitid'] = workflow.commitId + if (workflow.revision) misc_fields['revision'] = workflow.revision + misc_fields['nxf_version'] = workflow.nextflow.version + misc_fields['nxf_build'] = workflow.nextflow.build + misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp + + def msg_fields = [:] + msg_fields['version'] = workflow.manifest.version + msg_fields['runName'] = workflow.runName + msg_fields['success'] = workflow.success + msg_fields['dateComplete'] = workflow.complete + msg_fields['duration'] = workflow.duration + msg_fields['exitStatus'] = workflow.exitStatus + msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + msg_fields['errorReport'] = (workflow.errorReport ?: 'None') + msg_fields['commandLine'] = workflow.commandLine + msg_fields['projectDir'] = workflow.projectDir + msg_fields['summary'] = summary << misc_fields + + // Render the JSON template + def engine = new groovy.text.GStringTemplateEngine() + def hf = new File("$projectDir/assets/adaptivecard.json") + def json_template = engine.createTemplate(hf).make(msg_fields) + def json_message = json_template.toString() + + // POST + def post = new URL(hook_url).openConnection(); + post.setRequestMethod("POST") + post.setDoOutput(true) + post.setRequestProperty("Content-Type", "application/json") + post.getOutputStream().write(json_message.getBytes("UTF-8")); + def postRC = post.getResponseCode(); + if (! postRC.equals(200)) { + log.warn(post.getErrorStream().getText()); + } } - // Render the TXT template - def engine = new groovy.text.GStringTemplateEngine() - def tf = new File("$projectDir/assets/email_template.txt") - def txt_template = engine.createTemplate(tf).make(email_fields) - def email_txt = txt_template.toString() - - // Render the HTML template - def hf = new File("$projectDir/assets/email_template.html") - def html_template = engine.createTemplate(hf).make(email_fields) - def email_html = html_template.toString() - - // Render the sendmail template - def max_multiqc_email_size = params.max_multiqc_email_size as nextflow.util.MemoryUnit - def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] - def sf = new File("$projectDir/assets/sendmail_template.txt") - def sendmail_template = engine.createTemplate(sf).make(smail_fields) - def sendmail_html = sendmail_template.toString() - - // Send the HTML e-mail - Map colors = logColours(params.monochrome_logs) - if (email_address) { - try { - if (params.plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } - // Try to send HTML e-mail using sendmail - [ 'sendmail', '-t' ].execute() << sendmail_html - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" - } catch (all) { - // Catch failures and try with plaintext - def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] - if ( mqc_report.size() <= max_multiqc_email_size.toBytes() ) { - mail_cmd += [ '-A', mqc_report ] - } - mail_cmd.execute() << email_html - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" + // + // Print pipeline summary on completion + // + public static void summary(workflow, params, log) { + Map colors = logColours(params.monochrome_logs) + if (workflow.success) { + if (workflow.stats.ignoredCount == 0) { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" + } else { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" + } + } else { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" } } - // Write summary e-mail HTML to a file - def output_d = new File("${params.outdir}/pipeline_info/") - if (!output_d.exists()) { - output_d.mkdirs() + // + // ANSII Colours used for terminal logging + // + public static Map logColours(Boolean monochrome_logs) { + Map colorcodes = [:] + + // Reset / Meta + colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" + colorcodes['bold'] = monochrome_logs ? '' : "\033[1m" + colorcodes['dim'] = monochrome_logs ? '' : "\033[2m" + colorcodes['underlined'] = monochrome_logs ? '' : "\033[4m" + colorcodes['blink'] = monochrome_logs ? '' : "\033[5m" + colorcodes['reverse'] = monochrome_logs ? '' : "\033[7m" + colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" + + // Regular Colors + colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" + colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" + colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" + colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" + colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" + colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" + colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" + colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" + + // Bold + colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" + colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" + colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" + colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" + colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" + colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" + colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" + colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" + + // Underline + colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" + colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" + colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" + colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" + colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" + colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" + colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" + colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" + + // High Intensity + colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" + colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" + colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" + colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" + colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" + colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" + colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" + colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" + + // Bold High Intensity + colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" + colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" + colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" + colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" + colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" + colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" + colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" + colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" + + return colorcodes + } + + // + // Does what is says on the tin + // + public static String dashedLine(monochrome_logs) { + Map colors = logColours(monochrome_logs) + return "-${colors.dim}----------------------------------------------------${colors.reset}-" } - def output_hf = new File(output_d, "pipeline_report.html") - output_hf.withWriter { w -> w << email_html } - def output_tf = new File(output_d, "pipeline_report.txt") - output_tf.withWriter { w -> w << email_txt } - } - - // - // Print pipeline summary on completion - // - public static void summary(workflow, params, log) { - Map colors = logColours(params.monochrome_logs) - if (workflow.success) { - if (workflow.stats.ignoredCount == 0) { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" - } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" - } - } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" + + // + // nf-core logo + // + public static String logo(workflow, monochrome_logs) { + Map colors = logColours(monochrome_logs) + String.format( + """\n + ${dashedLine(monochrome_logs)} + ${colors.green},--.${colors.black}/${colors.green},-.${colors.reset} + ${colors.blue} ___ __ __ __ ___ ${colors.green}/,-._.--~\'${colors.reset} + ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} + ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} + ${colors.green}`._,._,\'${colors.reset} + ${colors.purple} ${workflow.manifest.name} v${workflow.manifest.version}${colors.reset} + ${dashedLine(monochrome_logs)} + """.stripIndent() + ) } - } - - // - // ANSII Colours used for terminal logging - // - public static Map logColours(Boolean monochrome_logs) { - Map colorcodes = [:] - - // Reset / Meta - colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" - colorcodes['bold'] = monochrome_logs ? '' : "\033[1m" - colorcodes['dim'] = monochrome_logs ? '' : "\033[2m" - colorcodes['underlined'] = monochrome_logs ? '' : "\033[4m" - colorcodes['blink'] = monochrome_logs ? '' : "\033[5m" - colorcodes['reverse'] = monochrome_logs ? '' : "\033[7m" - colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" - - // Regular Colors - colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" - colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" - colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" - colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" - colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" - colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" - colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" - colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" - - // Bold - colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" - colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" - colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" - colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" - colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" - colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" - colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" - colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" - - // Underline - colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" - colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" - colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" - colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" - colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" - colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" - colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" - colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" - - // High Intensity - colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" - colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" - colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" - colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" - colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" - colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" - colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" - colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" - - // Bold High Intensity - colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" - colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" - colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" - colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" - colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" - colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" - colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" - colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" - - return colorcodes - } - - // - // Does what is says on the tin - // - public static String dashedLine(monochrome_logs) { - Map colors = logColours(monochrome_logs) - return "-${colors.dim}----------------------------------------------------${colors.reset}-" - } - - // - // nf-core logo - // - public static String logo(workflow, monochrome_logs) { - Map colors = logColours(monochrome_logs) - String.format( - """\n - ${dashedLine(monochrome_logs)} - ${colors.green},--.${colors.black}/${colors.green},-.${colors.reset} - ${colors.blue} ___ __ __ __ ___ ${colors.green}/,-._.--~\'${colors.reset} - ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} - ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} - ${colors.green}`._,._,\'${colors.reset} - ${colors.purple} ${workflow.manifest.name} v${workflow.manifest.version}${colors.reset} - ${dashedLine(monochrome_logs)} - """.stripIndent() - ) - } } diff --git a/lib/Processes.groovy b/lib/Processes.groovy index d41ba2a6..803a72b5 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -3,98 +3,98 @@ import Constants class Processes { - public static set_processes(mode_str, log) { - def mode_enum + public static set_processes(mode_str, log) { + def mode_enum - try { - mode_enum = Constants.PipelineMode.valueOf(mode_str.toUpperCase()) - } catch(java.lang.IllegalArgumentException e) { - def workflows_str = Processes.get_workflow_names().join('\n - ') - log.error "\nERROR: recieved invalid pipeline mode: '${mode_str}'. Valid options are:\n - ${workflows_str}" - System.exit(1) - } - - def processes = [] - switch(mode_enum) { - case Constants.PipelineMode.FULL: - processes = Constants.Process.values() as List - break - case Constants.PipelineMode.MANUAL: - break - case Constants.PipelineMode.GRIDSS_PURPLE_LINX: - processes = [ - Constants.Process.AMBER, - Constants.Process.COBALT, - Constants.Process.GRIDSS, - Constants.Process.GRIPSS, - Constants.Process.LINX, - Constants.Process.PURPLE, - Constants.Process.SVPREP, - ] - break - case Constants.PipelineMode.CUPPA: - processes = [ - Constants.Process.AMBER, - Constants.Process.COBALT, - Constants.Process.COLLECTWGSMETRICS, - Constants.Process.CUPPA, - Constants.Process.GRIDSS, - Constants.Process.GRIPSS, - Constants.Process.ISOFOX, - Constants.Process.LINX, - Constants.Process.PURPLE, - Constants.Process.SVPREP, - Constants.Process.VIRUSINTERPRETER, - ] - break - default: - log.error "\nERROR: we should never have come here" - System.exit(1) - } - return processes - } - - public static get_process_list(process_str, log) { - return process_str - .tokenize(',') - .collect { name -> try { - return Constants.Process.valueOf(name.toUpperCase()) + mode_enum = Constants.PipelineMode.valueOf(mode_str.toUpperCase()) } catch(java.lang.IllegalArgumentException e) { - def processes_str = Processes.get_process_names().join('\n - ') - log.error "\nERROR: recieved invalid process: '${name}'. Valid options are:\n - ${processes_str}" - System.exit(1) + def workflows_str = Processes.get_workflow_names().join('\n - ') + log.error "\nERROR: recieved invalid pipeline mode: '${mode_str}'. Valid options are:\n - ${workflows_str}" + System.exit(1) + } + + def processes = [] + switch(mode_enum) { + case Constants.PipelineMode.FULL: + processes = Constants.Process.values() as List + break + case Constants.PipelineMode.MANUAL: + break + case Constants.PipelineMode.GRIDSS_PURPLE_LINX: + processes = [ + Constants.Process.AMBER, + Constants.Process.COBALT, + Constants.Process.GRIDSS, + Constants.Process.GRIPSS, + Constants.Process.LINX, + Constants.Process.PURPLE, + Constants.Process.SVPREP, + ] + break + case Constants.PipelineMode.CUPPA: + processes = [ + Constants.Process.AMBER, + Constants.Process.COBALT, + Constants.Process.COLLECTWGSMETRICS, + Constants.Process.CUPPA, + Constants.Process.GRIDSS, + Constants.Process.GRIPSS, + Constants.Process.ISOFOX, + Constants.Process.LINX, + Constants.Process.PURPLE, + Constants.Process.SVPREP, + Constants.Process.VIRUSINTERPRETER, + ] + break + default: + log.error "\nERROR: we should never have come here" + System.exit(1) } - } - .unique() - } + return processes + } + + public static get_process_list(process_str, log) { + return process_str + .tokenize(',') + .collect { name -> + try { + return Constants.Process.valueOf(name.toUpperCase()) + } catch(java.lang.IllegalArgumentException e) { + def processes_str = Processes.get_process_names().join('\n - ') + log.error "\nERROR: recieved invalid process: '${name}'. Valid options are:\n - ${processes_str}" + System.exit(1) + } + } + .unique() + } - public static check_include_exclude_list(include_list, exclude_list, log) { - def processes_shared = [*include_list, *exclude_list] - .countBy { it } - .findAll { k, v -> v > 1 } - .keySet() + public static check_include_exclude_list(include_list, exclude_list, log) { + def processes_shared = [*include_list, *exclude_list] + .countBy { it } + .findAll { k, v -> v > 1 } + .keySet() - if (processes_shared) { - def processes_shared_str = processes_shared.join('\n - ') - def message_base = 'the following processes was found in the include and the exclude list' - log.error "\nERROR: ${message_base}:\n - ${processes_shared_str}" - System.exit(1) + if (processes_shared) { + def processes_shared_str = processes_shared.join('\n - ') + def message_base = 'the following processes was found in the include and the exclude list' + log.error "\nERROR: ${message_base}:\n - ${processes_shared_str}" + System.exit(1) + } } - } - public static get_workflow_names() { - Constants.PipelineMode - .values() - *.name() - *.toLowerCase() - } + public static get_workflow_names() { + Constants.PipelineMode + .values() + *.name() + *.toLowerCase() + } - public static get_process_names() { - Constants.Process - .values() - *.name() - *.toLowerCase() - } + public static get_process_names() { + Constants.Process + .values() + *.name() + *.toLowerCase() + } } diff --git a/lib/Utils.groovy b/lib/Utils.groovy old mode 100755 new mode 100644 index d8dc27d2..8d030f4e --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -6,35 +6,42 @@ import org.yaml.snakeyaml.Yaml class Utils { - // - // When running with -profile conda, warn if channels have not been set-up appropriately - // - public static void checkCondaChannels(log) { - Yaml parser = new Yaml() - def channels = [] - try { - def config = parser.load("conda config --show channels".execute().text) - channels = config.channels - } catch(NullPointerException | IOException e) { - log.warn "Could not verify conda channel configuration." - return - } + // + // When running with -profile conda, warn if channels have not been set-up appropriately + // + public static void checkCondaChannels(log) { + Yaml parser = new Yaml() + def channels = [] + try { + def config = parser.load("conda config --show channels".execute().text) + channels = config.channels + } catch(NullPointerException | IOException e) { + log.warn "Could not verify conda channel configuration." + return + } - // Check that all channels are present - def required_channels = ['conda-forge', 'bioconda', 'defaults'] - def conda_check_failed = !required_channels.every { ch -> ch in channels } + // Check that all channels are present + // This channel list is ordered by required channel priority. + def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] + def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean - // Check that they are in the right order - conda_check_failed |= !(channels.indexOf('conda-forge') < channels.indexOf('bioconda')) - conda_check_failed |= !(channels.indexOf('bioconda') < channels.indexOf('defaults')) + // Check that they are in the right order + def channel_priority_violation = false + def n = required_channels_in_order.size() + for (int i = 0; i < n - 1; i++) { + channel_priority_violation |= !(channels.indexOf(required_channels_in_order[i]) < channels.indexOf(required_channels_in_order[i+1])) + } - if (conda_check_failed) { - log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " There is a problem with your Conda configuration!\n\n" + - " You will need to set-up the conda-forge and bioconda channels correctly.\n" + - " Please refer to https://bioconda.github.io/user/install.html#set-up-channels\n" + - " NB: The order of the channels matters!\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + if (channels_missing | channel_priority_violation) { + log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " There is a problem with your Conda configuration!\n\n" + + " You will need to set-up the conda-forge and bioconda channels correctly.\n" + + " Please refer to https://bioconda.github.io/\n" + + " The observed channel order is \n" + + " ${channels}\n" + + " but the following channel order is required:\n" + + " ${required_channels_in_order}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + } } - } } diff --git a/lib/WorkflowGridss.groovy b/lib/WorkflowGridss.groovy index 7f464bc8..d3e26991 100755 --- a/lib/WorkflowGridss.groovy +++ b/lib/WorkflowGridss.groovy @@ -1,104 +1,104 @@ // -// This file holds several functions specific to the subworkflows/gridss.nf in the umccr/hmftools pipeline +// This file holds several functions specific to the subworkflows/gridss.nf in the nf-core/oncoanalyser pipeline // class WorkflowGridss { - public static get_inputs(ch) { - // channel (a): [val(meta_gridss), bam, bai, sv] - // channel (b): [val(meta_gridss), bam] - def sample_types = ['tumor', 'normal'] - def d = ch - .flatMap { meta -> - sample_types - .collect { sample_type -> - def key_sname = ['sample_name', sample_type] - def key_bam = ['bam_wgs', sample_type] - def key_sv = ['vcf_sv', sample_type] - if (! meta.containsKey(key_sname) && ! meta.containsKey(key_bam)) { - return [] + public static get_inputs(ch) { + // channel (a): [val(meta_gridss), bam, bai, sv] + // channel (b): [val(meta_gridss), bam] + def sample_types = ['tumor', 'normal'] + def d = ch + .flatMap { meta -> + sample_types + .collect { sample_type -> + def key_sname = ['sample_name', sample_type] + def key_bam = ['bam_wgs', sample_type] + def key_sv = ['vcf_sv', sample_type] + if (! meta.containsKey(key_sname) && ! meta.containsKey(key_bam)) { + return [] + } + def meta_gridss = [ + id: meta.get(key_sname), + group_key: meta.id, + sample_type: sample_type, + subject_name: meta.subject_name, + ] + def v = [meta_gridss, meta.get(key_bam)] + def has_sv = meta.containsKey(key_sv) + if (has_sv) { + v = v + ["${meta.get(key_bam)}.bai", meta.get(key_sv)] + } + return [has_sv, v] + } } - def meta_gridss = [ - id: meta.get(key_sname), - group_key: meta.id, - sample_type: sample_type, - subject_name: meta.subject_name, - ] - def v = [meta_gridss, meta.get(key_bam)] - def has_sv = meta.containsKey(key_sv) - if (has_sv) { - v = v + ["${meta.get(key_bam)}.bai", meta.get(key_sv)] - } - return [has_sv, v] - } - } - return d - } + return d + } - public static get_unique_input_files(ch) { - // channel (a): [val(meta_gridss), bam, bai, sv] - // channel (b): [val(meta_gridss), bam] - def d = ch - .map { [it[1..-1], it[0]] } - // NOTE(SW): number of grouped elements is unknown here but does not block since all inputs - // are derived directly from the samplesheet - .groupTuple() - .map { filepaths, meta_gridsss -> - def (sample_names, ids, sample_types, subject_names) = meta_gridsss - .collect { - [it.id, it.group_key, it.sample_type, it.subject_name] - } - .transpose() + public static get_unique_input_files(ch) { + // channel (a): [val(meta_gridss), bam, bai, sv] + // channel (b): [val(meta_gridss), bam] + def d = ch + .map { [it[1..-1], it[0]] } + // NOTE(SW): number of grouped elements is unknown here but does not block since all inputs + // are derived directly from the samplesheet + .groupTuple() + .map { filepaths, meta_gridsss -> + def (sample_names, ids, sample_types, subject_names) = meta_gridsss + .collect { + [it.id, it.group_key, it.sample_type, it.subject_name] + } + .transpose() - def sample_name = sample_names.unique(false) - def sample_type = sample_types.unique(false) - def subject_name = subject_names.unique(false) - assert sample_name.size() == 1 - assert sample_type.size() == 1 - assert subject_name.size() == 1 + def sample_name = sample_names.unique(false) + def sample_type = sample_types.unique(false) + def subject_name = subject_names.unique(false) + assert sample_name.size() == 1 + assert sample_type.size() == 1 + assert subject_name.size() == 1 - def meta_gridss_new = [ - id: ids.join('__'), - id_list: ids, - sample_name: sample_name[0], - sample_type: sample_type[0], - subject_name: subject_name[0], - ] - return [meta_gridss_new, *filepaths] - } - return d - } + def meta_gridss_new = [ + id: ids.join('__'), + id_list: ids, + sample_name: sample_name[0], + sample_type: sample_type[0], + subject_name: subject_name[0], + ] + return [meta_gridss_new, *filepaths] + } + return d + } - public static get_assemble_inputs(ch) { - // NOTE(SW): elements in the bams, preprocess_dirs, and labels are linked with via consistent ordering - // channel: [val(meta_gridss), [bams], [preprocess_dirs], [labels]] - def d = ch - .map { subject_name, other -> - def data = [:] - def ids = [] as Set + public static get_assemble_inputs(ch) { + // NOTE(SW): elements in the bams, preprocess_dirs, and labels are linked with via consistent ordering + // channel: [val(meta_gridss), [bams], [preprocess_dirs], [labels]] + def d = ch + .map { subject_name, other -> + def data = [:] + def ids = [] as Set - // NOTE(SW): must determine whether input ordering is determininistic here + // NOTE(SW): must determine whether input ordering is determininistic here - other - .each { meta_gridss, bam, preprocess_dir -> - data.get([meta_gridss.sample_type, 'label'], []) << meta_gridss.sample_name - data.get([meta_gridss.sample_type, 'bam_wgs'], []) << bam - data.get([meta_gridss.sample_type, 'preprocess_dir'], []) << preprocess_dir - ids += meta_gridss.id_list - } - def meta_gridss_new = [ - id: ids.join('__'), - id_list: ids, - ] + other + .each { meta_gridss, bam, preprocess_dir -> + data.get([meta_gridss.sample_type, 'label'], []) << meta_gridss.sample_name + data.get([meta_gridss.sample_type, 'bam_wgs'], []) << bam + data.get([meta_gridss.sample_type, 'preprocess_dir'], []) << preprocess_dir + ids += meta_gridss.id_list + } + def meta_gridss_new = [ + id: ids.join('__'), + id_list: ids, + ] - def sample_types = ['normal', 'tumor'] - return [ - meta_gridss_new, - sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'bam_wgs'], []) }, - sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'preprocess_dir'], []) }, - sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'label'], []) }, - ] - } - return d - } + def sample_types = ['normal', 'tumor'] + return [ + meta_gridss_new, + sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'bam_wgs'], []) }, + sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'preprocess_dir'], []) }, + sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'label'], []) }, + ] + } + return d + } } diff --git a/lib/WorkflowHmftools.groovy b/lib/WorkflowHmftools.groovy deleted file mode 100755 index 06b14306..00000000 --- a/lib/WorkflowHmftools.groovy +++ /dev/null @@ -1,165 +0,0 @@ -// -// This file holds several functions specific to the workflows/hmftools.nf in the umccr/hmftools pipeline -// - -import static groovy.io.FileType.FILES - -import nextflow.Channel -import nextflow.Nextflow - -class WorkflowHmftools { - - // - // Check and validate parameters - // - public static void initialise(params, workflow, log) { - // Download region file for collectwgsmetrics if in test mode - if (workflow.profile.contains('test')) { - def stage_dir = new File(workflow.workDir.toString(), 'stage/manual/') - def interval_file = new File(stage_dir, 'collectwgsmetrics.interval_list') - if (! interval_file.exists()) { - stage_dir.mkdirs() - interval_file.createNewFile() - interval_file << new URL (params.ref_data_wgsmetrics_intervals_url).getText() - } - params.ref_data_wgsmetrics_intervals_local = interval_file - } - } - - public static prepare_inputs(ch, stub_run, log) { - return ch - .splitCsv(header: true, strip: true, sep: '\t') - .map { [it.id, it] } - .groupTuple() - .map { id, inputs -> - def meta = [ - 'id': id, - ] - inputs.each { - assert meta.id == it.id - // Add subject name if not already present - if (meta.containsKey('subject_name')) { - assert meta.subject_name == it.subject_name - } else { - meta.subject_name = it.subject_name - } - - // Set sample name - def key = [] - if (it.sample_type == 'tumor') { - key = ['sample_name', 'tumor'] - } else if (it.sample_type == 'normal') { - key = ['sample_name', 'normal'] - } else { - assert false - } - if (meta.containsKey(key)) { - assert meta[key] == it.sample_name - } else { - meta[key] = it.sample_name - } - - // Add file - def key_file = [it.filetype, it.sample_type] - assert ! meta.containsKey(key_file) - meta[key_file] = it.filepath - - if (! stub_run) { - // For BAM file inputs, require co-located index - if (it.filepath.endsWith('.bam')) { - def bam_index_fp_str = "${it.filepath}.bai".toString() - def bam_index_fp = Nextflow.file(bam_index_fp_str) - if (! bam_index_fp.exists()) { - log.error "\nERROR: No index found for ${it.filepath}" - System.exit(1) - } - } - - // For GRIPSS SV VCFs, require co-located index - if (it.filetype.startsWith('gripss')) { - def vcf_index_fp = Nextflow.file("${it.filepath}.tbi".toString()) - if (! vcf_index_fp.exists()) { - log.error "\nERROR: No index found for ${it.filepath}" - System.exit(1) - } - } - } - - // NOTE(SW): CHECK_SAMPLESHEET curently enforces T/N; this may be relevant in the future - //// Set sample type: tumor_normal, tumor_only, normal_only - //if (meta.containsKey(['sample_name', 'tumor']) && meta.containsKey(['sample_name', 'normal'])) { - // meta.sample_type = 'tumor_normal' - //} else if (meta.containsKey(['sample_name', 'tumor'])) { - // meta.sample_type = 'tumor_only' - //} else if (meta.containsKey(['sample_name', 'normal'])) { - // meta.sample_type = 'normal_only' - //} else { - // assert false - //} - } - - // For PURPLE only runs, we must get normal sample name from inputs since there is no way to provide this - // in the samplesheet - if (meta.containsKey(['cobalt_dir', 'tumor']) && ! meta.containsKey(['sample_name', 'normal'])) { - // Discover files - def normal_ratio_fps = [] - new File(meta[['cobalt_dir', 'tumor']]) - .eachFileMatch(groovy.io.FileType.FILES, ~/.+\.cobalt\.gc\.median\.tsv/, { normal_ratio_fps << it }) - // Select normal sample file - def normal_ratio_fp = normal_ratio_fps - .findAll { ! it.getName().contains(meta[['sample_name', 'tumor']]) } - assert normal_ratio_fp.size() == 1 - // Set normal sample name - def m = (normal_ratio_fp =~ /.+\/(.+)\.cobalt\.gc\.median\.tsv/) - meta[['sample_name', 'normal']] = m[0][1] - } - - return meta - } - } - - public static group_by_meta(Map named_args, ... channels) { - def r = channels - // Set position; required to use non-blocking .mix operator - // NOTE(SW): operating on native list object containing channels - def i = 0 - r = r - .collect { ch -> - def ii = i - def d = ch.map { data -> - def meta = data[0] - def values = data[1..-1] - return [meta, [position: ii, values: values]] - } - i++ - return d - } - - r = Channel.empty().mix(*r) - r = r - .groupTuple(size: channels.size()) - .map { data -> - def meta = data[0] - def values_map = data[1] - - def values_list = values_map - .sort { it.position } - .collect { it.values } - return [meta, *values_list] - } - - if (named_args.get('flatten', true)) { - r = r.map { it.flatten() } - } - return r - } - - // NOTE(SW): function signature required to catch where no named arguments are passed - public static group_by_meta(... channels) { - return group_by_meta([:], *channels) - } - - public static get_input(ch, key) { - return ch.map { meta -> [meta, meta.getAt(key)] } - } -} diff --git a/lib/WorkflowLilac.groovy b/lib/WorkflowLilac.groovy index 885f8787..b83e685c 100755 --- a/lib/WorkflowLilac.groovy +++ b/lib/WorkflowLilac.groovy @@ -1,80 +1,80 @@ // -// This file holds several functions specific to the subworkflows/lilac.nf in the umccr/hmftools pipeline +// This file holds several functions specific to the subworkflows/lilac.nf in the nf-core/oncoanalyser pipeline // class WorkflowLilac { - public static get_slice_inputs(ch, hla_bed) { - // channel: [val(meta_lilac), bam, bai, bed] - def d = ch - .flatMap { meta, tbam, nbam, tbai, nbai -> - def sample_types = ['tumor': [tbam, tbai], 'normal': [nbam, nbai]] - sample_types - .keySet() - .collect { sample_type -> - def fps = sample_types[sample_type] - def sample_name = meta.get(['sample_name', sample_type]) - def meta_lilac = [ - id: sample_name, - sample_type: sample_type, - meta_full: meta, - ] - return [meta_lilac, *fps, hla_bed] - } - } - return d - } + public static get_slice_inputs(ch, hla_bed) { + // channel: [val(meta_lilac), bam, bai, bed] + def d = ch + .flatMap { meta, tbam, nbam, tbai, nbai -> + def sample_types = ['tumor': [tbam, tbai], 'normal': [nbam, nbai]] + sample_types + .keySet() + .collect { sample_type -> + def fps = sample_types[sample_type] + def sample_name = meta.get(['sample_name', sample_type]) + def meta_lilac = [ + id: sample_name, + sample_type: sample_type, + meta_full: meta, + ] + return [meta_lilac, *fps, hla_bed] + } + } + return d + } - public static get_unique_input_files(ch) { - // channel: [val(meta_lilac), bam, bai, bed] - def d = ch - .map { [it[1..-1], it[0]] } - .groupTuple() - .map { filepaths, meta_lilacs -> - def (meta_fulls, sample_types) = meta_lilacs - .collect { - [it.meta_full, it.sample_type] - } - .transpose() + public static get_unique_input_files(ch) { + // channel: [val(meta_lilac), bam, bai, bed] + def d = ch + .map { [it[1..-1], it[0]] } + .groupTuple() + .map { filepaths, meta_lilacs -> + def (meta_fulls, sample_types) = meta_lilacs + .collect { + [it.meta_full, it.sample_type] + } + .transpose() - def sample_type = sample_types.unique(false) - assert sample_type.size() == 1 + def sample_type = sample_types.unique(false) + assert sample_type.size() == 1 - def id = meta_fulls.collect { it.id }.join('__') - def meta_lilac_new = [ - id: "${id}_${sample_type[0]}", - metas_full: meta_fulls, - sample_type: sample_type[0], - ] - return [meta_lilac_new, *filepaths] - } - return d - } + def id = meta_fulls.collect { it.id }.join('__') + def meta_lilac_new = [ + id: "${id}_${sample_type[0]}", + metas_full: meta_fulls, + sample_type: sample_type[0], + ] + return [meta_lilac_new, *filepaths] + } + return d + } - public static sort_slices(ch) { - // Collect T/N pairs into single channel element - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] - def d = ch - .flatMap{ data -> - def meta_lilac = data[0] - def fps = data[1..-1] - meta_lilac.metas_full.collect { meta -> [meta.id, meta, [meta_lilac.sample_type, *fps]] } - } - .groupTuple(size: 2) - .map { id, meta, other -> - def data = [:] - other.each { sample_type, bam, bai -> - data[[sample_type, 'bam']] = bam - data[[sample_type, 'bai']] = bai - } - [ - meta[0], - data.get(['tumor', 'bam']), - data.get(['normal', 'bam']), - data.get(['tumor', 'bai']), - data.get(['normal', 'bai']), - ] - } - return d - } + public static sort_slices(ch) { + // Collect T/N pairs into single channel element + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] + def d = ch + .flatMap{ data -> + def meta_lilac = data[0] + def fps = data[1..-1] + meta_lilac.metas_full.collect { meta -> [meta.id, meta, [meta_lilac.sample_type, *fps]] } + } + .groupTuple(size: 2) + .map { id, meta, other -> + def data = [:] + other.each { sample_type, bam, bai -> + data[[sample_type, 'bam']] = bam + data[[sample_type, 'bai']] = bai + } + [ + meta[0], + data.get(['tumor', 'bam']), + data.get(['normal', 'bam']), + data.get(['tumor', 'bai']), + data.get(['normal', 'bai']), + ] + } + return d + } } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 957fdc84..b30cd096 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -1,97 +1,92 @@ // -// This file holds several functions specific to the main.nf workflow in the umccr/hmftools pipeline +// This file holds several functions specific to the main.nf workflow in the nf-core/oncoanalyser pipeline // class WorkflowMain { - // - // Citation string for pipeline - // - public static String citation(workflow) { - return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + - // TODO nf-core: Add Zenodo DOI for pipeline after first release - //"* The pipeline\n" + - //" https://doi.org/10.5281/zenodo.XXXXXXX\n\n" + - "* The nf-core framework\n" + - " https://doi.org/10.1038/s41587-020-0439-x\n\n" + - "* Software dependencies\n" + - " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" - } - - // TODO(SW): update this - // - // Print help to screen if required - // - public static String help(workflow, params, log) { - def command = "nextflow run main.nf --input samplesheet.csv --outdir output/ -profile docker" - def help_string = '' - help_string += NfcoreTemplate.logo(workflow, params.monochrome_logs) - help_string += NfcoreSchema.paramsHelp(workflow, params, command) - help_string += '\n' + citation(workflow) + '\n' - help_string += NfcoreTemplate.dashedLine(params.monochrome_logs) - return help_string - } - - // - // Print parameter summary log to screen - // - public static String paramsSummaryLog(workflow, params, log) { - def summary_log = '' - summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) - summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) - summary_log += '\n' + citation(workflow) + '\n' - summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) - return summary_log - } + // + // Citation string for pipeline + // + public static String citation(workflow) { + return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + + // TODO nf-core: Add Zenodo DOI for pipeline after first release + //"* The pipeline\n" + + //" https://doi.org/10.5281/zenodo.XXXXXXX\n\n" + + "* The nf-core framework\n" + + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + + "* Software dependencies\n" + + " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" + } - // - // Validate parameters and print summary to screen - // - public static void initialise(workflow, params, log) { + // // Print help to screen if required - if (params.help) { - log.info help(workflow, params, log) - System.exit(0) + // + public static String help(workflow, params, log) { + def command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh38 -profile docker" + def help_string = '' + help_string += NfcoreTemplate.logo(workflow, params.monochrome_logs) + help_string += NfcoreSchema.paramsHelp(workflow, params, command) + help_string += '\n' + citation(workflow) + '\n' + help_string += NfcoreTemplate.dashedLine(params.monochrome_logs) + return help_string } - // Validate workflow parameters via the JSON schema - if (params.validate_params) { - NfcoreSchema.validateParameters(workflow, params, log) + // + // Print parameter summary log to screen + // + public static String paramsSummaryLog(workflow, params, log) { + def summary_log = '' + summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) + summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) + summary_log += '\n' + citation(workflow) + '\n' + summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) + return summary_log } - // Print parameter summary log to screen - log.info paramsSummaryLog(workflow, params, log) + // + // Validate parameters and print summary to screen + // + public static void initialise(workflow, params, log) { + // Print help to screen if required + if (params.help) { + log.info help(workflow, params, log) + System.exit(0) + } - // Check that a -profile or Nextflow config has been provided to run the pipeline - NfcoreTemplate.checkConfigProvided(workflow, log) + // Validate workflow parameters via the JSON schema + if (params.validate_params) { + NfcoreSchema.validateParameters(workflow, params, log) + } - // Check that conda channels are set-up correctly - if (params.enable_conda) { - Utils.checkCondaChannels(log) - } + // Print parameter summary log to screen + log.info paramsSummaryLog(workflow, params, log) - // TODO(SW): update this - // Check AWS batch settings - NfcoreTemplate.awsBatch(workflow, params) + // Check that a -profile or Nextflow config has been provided to run the pipeline + NfcoreTemplate.checkConfigProvided(workflow, log) - // TODO(SW): update this - // Check input has been provided - if (!params.input) { - log.error "Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'" - System.exit(1) - } - } + // Check that conda channels are set-up correctly + if (params.enable_conda) { + Utils.checkCondaChannels(log) + } - // - // Get attribute from genome config file e.g. fasta - // - public static String getGenomeAttribute(params, attribute) { - def val = '' - if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { - if (params.genomes[ params.genome ].containsKey(attribute)) { - val = params.genomes[ params.genome ][ attribute ] - } + // Check AWS batch settings + NfcoreTemplate.awsBatch(workflow, params) + + // Check input has been provided + if (!params.input) { + log.error "Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'" + System.exit(1) + } + } + // + // 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)) { + return params.genomes[ params.genome ][ attribute ] + } + } + return null } - return val - } } diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index ae6958ad..191da7db 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -2,68 +2,173 @@ // This file holds several functions specific to the workflow/oncoanalyser.nf in the nf-core/oncoanalyser pipeline // -import groovy.text.SimpleTemplateEngine +import static groovy.io.FileType.FILES + +import nextflow.Channel +import nextflow.Nextflow class WorkflowOncoanalyser { // // Check and validate parameters // - public static void initialise(params, log) { - genomeExistsError(params, log) + public static void initialise(params, workflow, log) { + //genomeExistsError(params, log) + //if (!params.fasta) { + // log.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." + // System.exit(1) + //} + // Download region file for collectwgsmetrics if in test mode + if (workflow.profile.contains('test')) { + def stage_dir = new File(workflow.workDir.toString(), 'stage/manual/') + def interval_file = new File(stage_dir, 'collectwgsmetrics.interval_list') + if (! interval_file.exists()) { + stage_dir.mkdirs() + interval_file.createNewFile() + interval_file << new URL (params.ref_data_wgsmetrics_intervals_url).getText() + } + params.ref_data_wgsmetrics_intervals_local = interval_file + } + } + public static prepare_inputs(ch, stub_run, log) { + return ch + .splitCsv(header: true, strip: true, sep: '\t') + .map { [it.id, it] } + .groupTuple() + .map { id, inputs -> + def meta = [ + 'id': id, + ] + inputs.each { + assert meta.id == it.id + // Add subject name if not already present + if (meta.containsKey('subject_name')) { + assert meta.subject_name == it.subject_name + } else { + meta.subject_name = it.subject_name + } - if (!params.fasta) { - log.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." - System.exit(1) - } + // Set sample name + def key = [] + if (it.sample_type == 'tumor') { + key = ['sample_name', 'tumor'] + } else if (it.sample_type == 'normal') { + key = ['sample_name', 'normal'] + } else { + assert false + } + if (meta.containsKey(key)) { + assert meta[key] == it.sample_name + } else { + meta[key] = it.sample_name + } + + // Add file + def key_file = [it.filetype, it.sample_type] + assert ! meta.containsKey(key_file) + meta[key_file] = it.filepath + + if (! stub_run) { + // For BAM file inputs, require co-located index + if (it.filepath.endsWith('.bam')) { + def bam_index_fp_str = "${it.filepath}.bai".toString() + def bam_index_fp = Nextflow.file(bam_index_fp_str) + if (! bam_index_fp.exists()) { + log.error "\nERROR: No index found for ${it.filepath}" + System.exit(1) + } + } + + // For GRIPSS SV VCFs, require co-located index + if (it.filetype.startsWith('gripss')) { + def vcf_index_fp = Nextflow.file("${it.filepath}.tbi".toString()) + if (! vcf_index_fp.exists()) { + log.error "\nERROR: No index found for ${it.filepath}" + System.exit(1) + } + } + } + + // NOTE(SW): CHECK_SAMPLESHEET curently enforces T/N; this may be relevant in the future + //// Set sample type: tumor_normal, tumor_only, normal_only + //if (meta.containsKey(['sample_name', 'tumor']) && meta.containsKey(['sample_name', 'normal'])) { + // meta.sample_type = 'tumor_normal' + //} else if (meta.containsKey(['sample_name', 'tumor'])) { + // meta.sample_type = 'tumor_only' + //} else if (meta.containsKey(['sample_name', 'normal'])) { + // meta.sample_type = 'normal_only' + //} else { + // assert false + //} + } + + // For PURPLE only runs, we must get normal sample name from inputs since there is no way to provide this + // in the samplesheet + if (meta.containsKey(['cobalt_dir', 'tumor']) && ! meta.containsKey(['sample_name', 'normal'])) { + // Discover files + def normal_ratio_fps = [] + new File(meta[['cobalt_dir', 'tumor']]) + .eachFileMatch(groovy.io.FileType.FILES, ~/.+\.cobalt\.gc\.median\.tsv/, { normal_ratio_fps << it }) + // Select normal sample file + def normal_ratio_fp = normal_ratio_fps + .findAll { ! it.getName().contains(meta[['sample_name', 'tumor']]) } + assert normal_ratio_fp.size() == 1 + // Set normal sample name + def m = (normal_ratio_fp =~ /.+\/(.+)\.cobalt\.gc\.median\.tsv/) + meta[['sample_name', 'normal']] = m[0][1] + } + + return meta + } } - // - // Get workflow summary for MultiQC - // - public static String paramsSummaryMultiqc(workflow, summary) { - String summary_section = '' - for (group in summary.keySet()) { - def group_params = summary.get(group) // This gets the parameters of that particular group - if (group_params) { - summary_section += "

$group

\n" - summary_section += "
\n" - for (param in group_params.keySet()) { - summary_section += "
$param
${group_params.get(param) ?: 'N/A'}
\n" + public static group_by_meta(Map named_args, ... channels) { + def r = channels + // Set position; required to use non-blocking .mix operator + // NOTE(SW): operating on native list object containing channels + def i = 0 + r = r + .collect { ch -> + def ii = i + def d = ch.map { data -> + def meta = data[0] + def values = data[1..-1] + return [meta, [position: ii, values: values]] } - summary_section += "
\n" + i++ + return d } - } - String yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" - yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" - yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" - yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" - yaml_file_text += "plot_type: 'html'\n" - yaml_file_text += "data: |\n" - yaml_file_text += "${summary_section}" - return yaml_file_text - } + r = Channel.empty().mix(*r) + r = r + .groupTuple(size: channels.size()) + .map { data -> + def meta = data[0] + def values_map = data[1] - public static String methodsDescriptionText(run_workflow, mqc_methods_yaml) { - // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file - def meta = [:] - meta.workflow = run_workflow.toMap() - meta["manifest_map"] = run_workflow.manifest.toMap() + def values_list = values_map + .sort { it.position } + .collect { it.values } + return [meta, *values_list] + } - meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" - meta["nodoi_text"] = meta.manifest_map.doi ? "": "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " + if (named_args.get('flatten', true)) { + r = r.map { it.flatten() } + } + return r + } - def methods_text = mqc_methods_yaml.text + // NOTE(SW): function signature required to catch where no named arguments are passed + public static group_by_meta(... channels) { + return group_by_meta([:], *channels) + } - def engine = new SimpleTemplateEngine() - def description_html = engine.createTemplate(methods_text).make(meta) + public static get_input(ch, key) { + return ch.map { meta -> [meta, meta.getAt(key)] } + } - return description_html - }// // Exit pipeline if incorrect --genome key provided - // private static void genomeExistsError(params, log) { if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + diff --git a/main.nf b/main.nf old mode 100755 new mode 100644 index 419c94f2..433a7029 --- a/main.nf +++ b/main.nf @@ -1,11 +1,12 @@ #!/usr/bin/env nextflow /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - umccr/hmftools + nf-core/oncoanalyser ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Github : https://github.com/umccr/hmftools - Website: https://nf-co.re/hmftools - Slack : https://nfcore.slack.com/channels/hmftools + Github : https://github.com/nf-core/oncoanalyser + + Website: https://nf-co.re/oncoanalyser + Slack : https://nfcore.slack.com/channels/oncoanalyser ---------------------------------------------------------------------------------------- */ @@ -13,7 +14,7 @@ nextflow.enable.dsl = 2 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - VALIDATE & PRINT PARAMETER SUMMARY + VALIDATE & PRINT PARAMETER SUMMARY ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -21,22 +22,22 @@ WorkflowMain.initialise(workflow, params, log) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - NAMED WORKFLOW FOR PIPELINE + NAMED WORKFLOW FOR PIPELINE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { HMFTOOLS } from './workflows/hmftools' +include { ONCOANALYSER } from './workflows/oncoanalyser' // -// WORKFLOW: Run main umccr/hmftools analysis pipeline +// WORKFLOW: Run main nf-core/oncoanalyser analysis pipeline // -workflow NFCORE_HMFTOOLS { - HMFTOOLS() +workflow NFCORE_ONCOANALYSER { + ONCOANALYSER() } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - RUN ALL WORKFLOWS + RUN ALL WORKFLOWS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -45,11 +46,11 @@ workflow NFCORE_HMFTOOLS { // See: https://github.com/nf-core/rnaseq/issues/619 // workflow { - NFCORE_HMFTOOLS() + NFCORE_ONCOANALYSER() } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - THE END + THE END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/modules.json b/modules.json index 7a27a4dd..7d495180 100644 --- a/modules.json +++ b/modules.json @@ -1,13 +1,19 @@ { - "name": "umccr/hmftools", - "homePage": "https://github.com/umccr/hmftools", + "name": "nf-core/oncoanalyser", + "homePage": "https://github.com/nf-core/oncoanalyser", "repos": { - "nf-core/modules": { - "custom/dumpsoftwareversions": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "picard/collectwgsmetrics": { - "git_sha": "ac1c6ad7104c7863842a322a8cf74f4fee1d20b4" + "https://github.com/nf-core/modules.git": { + "modules": { + "nf-core": { + "custom/dumpsoftwareversions": { + "branch": "master", + "git_sha": "8022c68e7403eecbd8ba9c49496f69f8c49d50f0" + }, + "picard/collectwgsmetrics": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + } + } } } } diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index 734b3ff7..9d4efb55 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -1,46 +1,46 @@ process AMBER { - //conda (params.enable_conda ? "bioconda::hmftools-amber=3.9" : null) - container 'docker.io/scwatts/amber:3.9--3' + //conda (params.enable_conda ? "bioconda::hmftools-amber=3.9" : null) + container 'docker.io/scwatts/amber:3.9--3' - input: - tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) - val ref_genome_ver - path loci + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) + val ref_genome_ver + path loci - output: - tuple val(meta), path('amber/'), emit: amber_dir - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('amber/'), emit: amber_dir + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' + script: + def args = task.ext.args ?: '' - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -tumor "${meta.get(['sample_name', 'tumor'])}" \\ - -tumor_bam "${tumor_bam}" \\ - -reference "${meta.get(['sample_name', 'normal'])}" \\ - -reference_bam "${normal_bam}" \\ - -ref_genome_version ${ref_genome_ver} \\ - -output_dir amber/ \\ - -threads "${task.cpus}" \\ - -loci "${loci}" + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -tumor "${meta.get(['sample_name', 'tumor'])}" \\ + -tumor_bam "${tumor_bam}" \\ + -reference "${meta.get(['sample_name', 'normal'])}" \\ + -reference_bam "${normal_bam}" \\ + -ref_genome_version ${ref_genome_ver} \\ + -output_dir amber/ \\ + -threads "${task.cpus}" \\ + -loci "${loci}" - # NOTE(SW): hard coded since there is no reliable way to obtain version information. - cat <<-END_VERSIONS > versions.yml - "${task.process}": - amber: 3.9 - END_VERSIONS - """ + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + amber: 3.9 + END_VERSIONS + """ - stub: - """ - mkdir -p amber/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir -p amber/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/check_samplesheet/main.nf b/modules/local/check_samplesheet/main.nf index 1fb7c5d2..3bafa9f1 100644 --- a/modules/local/check_samplesheet/main.nf +++ b/modules/local/check_samplesheet/main.nf @@ -1,33 +1,33 @@ process CHECK_SAMPLESHEET { - conda (params.enable_conda ? "conda-forge::python=3.9.5" : null) - container 'quay.io/biocontainers/python:3.9--1' + conda (params.enable_conda ? "conda-forge::python=3.9.5" : null) + container 'quay.io/biocontainers/python:3.9--1' - input: - path samplesheet - val mode + input: + path samplesheet + val mode - output: - path samplesheet + output: + path samplesheet - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' + script: + def args = task.ext.args ?: '' - """ - check_samplesheet.py \\ - --input_fp "${samplesheet}" \\ - --mode "${mode}" + """ + check_samplesheet.py \\ + --input_fp "${samplesheet}" \\ + --mode "${mode}" - cat <<-END_VERSIONS > versions.yml + cat <<-END_VERSIONS > versions.yml "${task.process}": - python: \$(python --version | sed 's/Python //g') - END_VERSIONS - """ + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ - stub: - """ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index 487ebf9b..7a0ceb9d 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -1,44 +1,44 @@ process COBALT { - //conda (params.enable_conda ? "bioconda::hmftools-cobalt=1.13" : null) - container 'docker.io/scwatts/cobalt:1.13--1' + //conda (params.enable_conda ? "bioconda::hmftools-cobalt=1.13" : null) + container 'docker.io/scwatts/cobalt:1.13--1' - input: - tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) - path gc_profile + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) + path gc_profile - output: - tuple val(meta), path('cobalt/'), emit: cobalt_dir - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('cobalt/'), emit: cobalt_dir + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' + script: + def args = task.ext.args ?: '' - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -tumor "${meta.get(['sample_name', 'tumor'])}" \\ - -tumor_bam "${tumor_bam}" \\ - -reference "${meta.get(['sample_name', 'normal'])}" \\ - -reference_bam "${normal_bam}" \\ - -output_dir cobalt/ \\ - -threads "${task.cpus}" \\ - -gc_profile "${gc_profile}" + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -tumor "${meta.get(['sample_name', 'tumor'])}" \\ + -tumor_bam "${tumor_bam}" \\ + -reference "${meta.get(['sample_name', 'normal'])}" \\ + -reference_bam "${normal_bam}" \\ + -output_dir cobalt/ \\ + -threads "${task.cpus}" \\ + -gc_profile "${gc_profile}" - # NOTE(SW): hard coded since there is no reliable way to obtain version information. - cat <<-END_VERSIONS > versions.yml - "${task.process}": - cobalt: 1.13 - END_VERSIONS - """ + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cobalt: 1.13 + END_VERSIONS + """ - stub: - """ - mkdir -p cobalt/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir -p cobalt/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index 76fc843f..5deaa9d3 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -1,46 +1,46 @@ process CUPPA_CLASSIFIER { - container 'docker.io/scwatts/cuppa:1.7--0' - - input: - tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) - path reference_data - - 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 ?: '' - - """ - # Symlink input files into a single directory - mkdir sample_data/ - input_dirs="${isofox_dir} ${purple_dir} ${linx_dir} ${virusinterpreter_dir}" - find -L \${input_dirs} -maxdepth 1 -type f -exec ln -s ../{} sample_data/ \\; - - java \\ - -Xmx${task.memory.giga}g \\ - -jar ${task.ext.jarPath} \\ - -categories ALL \\ - -ref_data_dir ${reference_data} \\ - -sample_data ${meta.get(['sample_name', 'tumor'])} \\ - -sample_data_dir sample_data/ \\ - -output_dir ./ - - # NOTE(SW): hard coded since there is no reliable way to obtain version information. - cat <<-END_VERSIONS > versions.yml - "${task.process}": - cuppa: 1.7 - END_VERSIONS - """ - - stub: - """ - touch ${meta.get(['sample_name', 'tumor'])}.cup.data.csv - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + container 'docker.io/scwatts/cuppa:1.7--0' + + input: + tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) + path reference_data + + 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 ?: '' + + """ + # Symlink input files into a single directory + mkdir sample_data/ + input_dirs="${isofox_dir} ${purple_dir} ${linx_dir} ${virusinterpreter_dir}" + find -L \${input_dirs} -maxdepth 1 -type f -exec ln -s ../{} sample_data/ \\; + + java \\ + -Xmx${task.memory.giga}g \\ + -jar ${task.ext.jarPath} \\ + -categories ALL \\ + -ref_data_dir ${reference_data} \\ + -sample_data ${meta.get(['sample_name', 'tumor'])} \\ + -sample_data_dir sample_data/ \\ + -output_dir ./ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cuppa: 1.7 + END_VERSIONS + """ + + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}.cup.data.csv + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf index 0aac2a4d..d21e03cb 100644 --- a/modules/local/cuppa/visualiser/main.nf +++ b/modules/local/cuppa/visualiser/main.nf @@ -1,38 +1,38 @@ process CUPPA_VISUALISER { - container 'docker.io/scwatts/cuppa:1.7--0' - - input: - tuple val(meta), path(cuppa_csv) - - output: - path '*png' - path '*txt' - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - python ${task.ext.pythonPath} \\ - -sample ${meta.get(['sample_name', 'tumor'])} \\ - -sample_data ${cuppa_csv} \\ - -output_dir ./ - - # NOTE(SW): hard coded since there is no reliable way to obtain version information. - cat <<-END_VERSIONS > versions.yml - "${task.process}": - cuppa: 1.7 - END_VERSIONS - """ - - stub: - """ - touch ${meta.get(['sample_name', 'tumor'])}.cuppa.chart.png - touch ${meta.get(['sample_name', 'tumor'])}.cuppa.conclusion.txt - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + container 'docker.io/scwatts/cuppa:1.7--0' + + input: + tuple val(meta), path(cuppa_csv) + + output: + path '*png' + path '*txt' + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + python ${task.ext.pythonPath} \\ + -sample ${meta.get(['sample_name', 'tumor'])} \\ + -sample_data ${cuppa_csv} \\ + -output_dir ./ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cuppa: 1.7 + END_VERSIONS + """ + + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}.cuppa.chart.png + touch ${meta.get(['sample_name', 'tumor'])}.cuppa.conclusion.txt + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index 74debc9a..08e3946f 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -1,40 +1,40 @@ process EXTRACT_AND_INDEX_CONTIG { - //conda (params.enable_conda ? "bioconda::null" : null) - container 'docker.io/scwatts/custom-extract_and_index_contig:0.0.1--3' + //conda (params.enable_conda ? "bioconda::null" : null) + container 'docker.io/scwatts/custom-extract_and_index_contig:0.0.1--3' - input: - val contig_name - path genome_fa - path genome_fai + input: + val contig_name + path genome_fa + path genome_fai - output: - path "*extracted.fa" , emit: contig - path "*extracted.fa.*", emit: bwa_indices - path 'versions.yml' , emit: versions + output: + path "*extracted.fa" , emit: contig + path "*extracted.fa.*", emit: bwa_indices + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' + script: + def args = task.ext.args ?: '' - """ - samtools faidx \\ - -o ${contig_name}_extracted.fa \\ - ${genome_fa} \\ - ${contig_name} - bwa index ${contig_name}_extracted.fa + """ + samtools faidx \\ + -o ${contig_name}_extracted.fa \\ + ${genome_fa} \\ + ${contig_name} + bwa index ${contig_name}_extracted.fa - cat <<-END_VERSIONS > versions.yml - "${task.process}": - bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ - stub: - """ - touch ${contig_name}_extracted.fa ${contig_name}_extracted.fa.amb - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + touch ${contig_name}_extracted.fa ${contig_name}_extracted.fa.amb + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf index 6ea93f9c..5d1b2f00 100644 --- a/modules/local/custom/lilac_realign_reads_lilac/main.nf +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -1,50 +1,50 @@ process REALIGN_READS { - //conda (params.enable_conda ? "bioconda::hmftools-lilac=1.2" : null) - container 'docker.io/scwatts/custom-realign_reads_lilac:0.0.1--3' - - input: - tuple val(meta), path(bam), path(bai) - path reference - path reference_indices - - output: - tuple val(meta), path("*realigned.bam"), path("*realigned.bam.bai"), emit: bam - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - sambamba sort -n ${bam} -o ${meta.id}_sorted.bam - samtools fastq -@${task.threads} ${meta.id}_sorted.bam \\ - -1 ${meta.id}_R1.fastq.gz \\ - -2 ${meta.id}_R2.fastq.gz \\ - -0 ${meta.id}_other.fastq.gz \\ - -s ${meta.id}_singleton.fastq.gz; - - bwa mem \\ - -t${task.cpus} \\ - -Y \\ - ${reference} \\ - ${meta.id}_R1.fastq.gz \\ - ${meta.id}_R2.fastq.gz | \\ - samtools sort -T tmp -o ${meta.id}_realigned.bam - samtools index ${meta.id}_realigned.bam - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - sambamba: \$(sambamba --version 2>&1 | sed -n '/sambamba/ s/^sambamba \\(.\\+\\)/\\1/p' | head -n1) - END_VERSIONS - """ - - stub: - """ - touch ${meta.id}_realigned.bam ${meta.id}_realigned.bam.bai - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + //conda (params.enable_conda ? "bioconda::hmftools-lilac=1.2" : null) + container 'docker.io/scwatts/custom-realign_reads_lilac:0.0.1--3' + + input: + tuple val(meta), path(bam), path(bai) + path reference + path reference_indices + + output: + tuple val(meta), path("*realigned.bam"), path("*realigned.bam.bai"), emit: bam + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + sambamba sort -n ${bam} -o ${meta.id}_sorted.bam + samtools fastq -@${task.threads} ${meta.id}_sorted.bam \\ + -1 ${meta.id}_R1.fastq.gz \\ + -2 ${meta.id}_R2.fastq.gz \\ + -0 ${meta.id}_other.fastq.gz \\ + -s ${meta.id}_singleton.fastq.gz; + + bwa mem \\ + -t${task.cpus} \\ + -Y \\ + ${reference} \\ + ${meta.id}_R1.fastq.gz \\ + ${meta.id}_R2.fastq.gz | \\ + samtools sort -T tmp -o ${meta.id}_realigned.bam + samtools index ${meta.id}_realigned.bam + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + sambamba: \$(sambamba --version 2>&1 | sed -n '/sambamba/ s/^sambamba \\(.\\+\\)/\\1/p' | head -n1) + END_VERSIONS + """ + + stub: + """ + touch ${meta.id}_realigned.bam ${meta.id}_realigned.bam.bai + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index 7962588f..b3496a4a 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -1,40 +1,40 @@ process SLICE { - //conda (params.enable_conda ? "bioconda::samtools:1.15.1" : null) - container 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' - - input: - tuple val(meta), path(bam), path(bai), path(bed) - - output: - tuple val(meta), path("*sliced.bam"), path("*sliced.bam.bai"), emit: bam - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - samtools view \\ - ${args} \\ - -L "${bed}" \\ - -@${task.cpus} \\ - -Obam \\ - ${bam} | \\ - samtools sort -T tmp -o "${bam.simpleName}.sliced.bam" - - samtools index "${bam.simpleName}.sliced.bam" - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - END_VERSIONS - """ - - stub: - """ - touch ${bam.simpleName}.sliced.bam ${bam.simpleName}.sliced.bam.bai - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + //conda (params.enable_conda ? "bioconda::samtools:1.15.1" : null) + container 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' + + input: + tuple val(meta), path(bam), path(bai), path(bed) + + output: + tuple val(meta), path("*sliced.bam"), path("*sliced.bam.bai"), emit: bam + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + samtools view \\ + ${args} \\ + -L "${bed}" \\ + -@${task.cpus} \\ + -Obam \\ + ${bam} | \\ + samtools sort -T tmp -o "${bam.simpleName}.sliced.bam" + + samtools index "${bam.simpleName}.sliced.bam" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + """ + touch ${bam.simpleName}.sliced.bam ${bam.simpleName}.sliced.bam.bai + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/gpgr/linx_report/main.nf b/modules/local/gpgr/linx_report/main.nf index 3ee5ec24..0f9e8885 100644 --- a/modules/local/gpgr/linx_report/main.nf +++ b/modules/local/gpgr/linx_report/main.nf @@ -1,38 +1,38 @@ process LINX_REPORT { - //conda (params.enable_conda ? "umccr::r-gpgr==1.4.1" : null) - container 'ghcr.io/umccr/gpgr:1.4.1' + //conda (params.enable_conda ? "umccr::r-gpgr==1.4.1" : null) + container 'ghcr.io/umccr/gpgr:1.4.1' - input: - tuple val(meta), path(linx_annotation), path(linx_visualiser) + input: + tuple val(meta), path(linx_annotation), path(linx_visualiser) - output: - tuple val(meta), path('*_linx.html'), emit: html - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('*_linx.html'), emit: html + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' + script: + def args = task.ext.args ?: '' - """ - gpgr.R linx \\ - ${args} \\ - --sample ${meta.get(['sample_name', 'tumor'])} \\ - --plot ${linx_visualiser}/ \\ - --table ${linx_annotation}/ \\ - --out ${meta.get(['sample_name', 'tumor'])}_linx.html; + """ + gpgr.R linx \\ + ${args} \\ + --sample ${meta.get(['sample_name', 'tumor'])} \\ + --plot ${linx_visualiser}/ \\ + --table ${linx_annotation}/ \\ + --out ${meta.get(['sample_name', 'tumor'])}_linx.html; - cat <<-END_VERSIONS > versions.yml - "${task.process}": - R: \$(R --version | head -n1 | sed 's/^R version \\([0-9.]\\+\\).\\+/\\1/') - gpgr: \$(gpgr.R --version | cut -f2 -d' ') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + R: \$(R --version | head -n1 | sed 's/^R version \\([0-9.]\\+\\).\\+/\\1/') + gpgr: \$(gpgr.R --version | cut -f2 -d' ') + END_VERSIONS + """ - stub: - """ - touch ${meta.get(['sample_name', 'tumor'])}_linx.html - echo -e '${task.process}:\n stub: noversions\n' > versions.yml - """ + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}_linx.html + echo -e '${task.process}:\n stub: noversions\n' > versions.yml + """ } diff --git a/modules/local/gridss/assemble/main.nf b/modules/local/gridss/assemble/main.nf index a555963c..efdf9fde 100644 --- a/modules/local/gridss/assemble/main.nf +++ b/modules/local/gridss/assemble/main.nf @@ -1,88 +1,88 @@ process ASSEMBLE { - //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) - container 'docker.io/scwatts/gridss:2.13.2--3' + //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) + container 'docker.io/scwatts/gridss:2.13.2--3' - input: - tuple val(meta), path(bams), path(preprocess_dirs), val(labels) - path gridss_config - path genome_fa - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - path blacklist + input: + tuple val(meta), path(bams), path(preprocess_dirs), val(labels) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + path blacklist - output: - tuple val(meta), path('gridss_assemble/'), emit: assemble_dir - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('gridss_assemble/'), emit: assemble_dir + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - def output_dirname = 'gridss_assemble' - def labels_arg = labels.join(',') - // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below - def bams_list = bams instanceof List ? bams : [bams] - def bams_arg = bams_list.join(' ') + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + def output_dirname = 'gridss_assemble' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = bams_list.join(' ') - """ - # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation - # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present - shadow_input_directory() { - src=\${1} - dst="${output_dirname}/work/\${src##*/}" - for filepath_src in \$(find -L \${src} ! -type d); do - # Get destination location for symlink - filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) - filepath_dst=\${dst%/}/\${filepath_src_rel} - # Create directory for symlink - mkdir -p \${filepath_dst%/*}; - # Get path for symlink source file, then create it - # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only - # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers - symlinkpath=\$(realpath \${filepath_src}) - ln -s \${symlinkpath} \${filepath_dst}; + """ + # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation + # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + shadow_input_directory() { + src=\${1} + dst="${output_dirname}/work/\${src##*/}" + for filepath_src in \$(find -L \${src} ! -type d); do + # Get destination location for symlink + filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) + filepath_dst=\${dst%/}/\${filepath_src_rel} + # Create directory for symlink + mkdir -p \${filepath_dst%/*}; + # Get path for symlink source file, then create it + # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only + # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers + symlinkpath=\$(realpath \${filepath_src}) + ln -s \${symlinkpath} \${filepath_dst}; + done + if [[ -L "\${src##*/}" ]]; then + rm "\${src}" + fi + } + for preprocess_dir in ${preprocess_dirs}; do + shadow_input_directory \${preprocess_dir}; done - if [[ -L "\${src##*/}" ]]; then - rm "\${src}" - fi - } - for preprocess_dir in ${preprocess_dirs}; do - shadow_input_directory \${preprocess_dir}; - done - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - # Run - gridss \\ - ${args} \\ - --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ - --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ - --jar "${task.ext.jarPath}" \\ - --steps assemble \\ - --labels "${labels_arg}" \\ - --reference "${genome_fa}" \\ - --blacklist "${blacklist}" \\ - --workingdir "${output_dirname}/work" \\ - --assembly "${output_dirname}/sv_assemblies.bam" \\ - --threads "${task.cpus}" \\ - ${config_arg} \\ - ${bams_arg} + # Run + gridss \\ + ${args} \\ + --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ + --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ + --jar "${task.ext.jarPath}" \\ + --steps assemble \\ + --labels "${labels_arg}" \\ + --reference "${genome_fa}" \\ + --blacklist "${blacklist}" \\ + --workingdir "${output_dirname}/work" \\ + --assembly "${output_dirname}/sv_assemblies.bam" \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + ${bams_arg} - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ - stub: - """ - mkdir -p gridss_assemble/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir -p gridss_assemble/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/gridss/call/main.nf b/modules/local/gridss/call/main.nf index 628c545f..d6143f21 100644 --- a/modules/local/gridss/call/main.nf +++ b/modules/local/gridss/call/main.nf @@ -1,93 +1,93 @@ process CALL { - //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) - container 'docker.io/scwatts/gridss:2.13.2--3' + //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) + container 'docker.io/scwatts/gridss:2.13.2--3' - input: - tuple val(meta), path(bams), path(assemble_dir), val(labels) - path gridss_config - path genome_fa - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - path blacklist + input: + tuple val(meta), path(bams), path(assemble_dir), val(labels) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + path blacklist - output: - tuple val(meta), path('gridss_call/sv_vcf.vcf.gz'), emit: vcf - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('gridss_call/sv_vcf.vcf.gz'), emit: vcf + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - def output_dirname = 'gridss_call' - def labels_arg = labels.join(',') - // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below - def bams_list = bams instanceof List ? bams : [bams] - def bams_arg = bams_list.join(' ') + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + def output_dirname = 'gridss_call' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = bams_list.join(' ') - """ - # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation - # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present - shadow_input_directory() { - src=\${1} - dst="${output_dirname}/" - for filepath_src in \$(find -L \${src} ! -type d); do - # Get destination location for symlink - filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) - filepath_dst=\${dst%/}/\${filepath_src_rel} - # Create directory for symlink - mkdir -p \${filepath_dst%/*}; - # Get path for symlink source file, then create it - # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only - # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers - symlinkpath=\$(realpath \${filepath_src}) - ln -s \${symlinkpath} \${filepath_dst}; - done - if [[ -L "\${src##*/}" ]]; then - rm "\${src}" - fi - } - shadow_input_directory ${assemble_dir} + """ + # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation + # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + shadow_input_directory() { + src=\${1} + dst="${output_dirname}/" + for filepath_src in \$(find -L \${src} ! -type d); do + # Get destination location for symlink + filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) + filepath_dst=\${dst%/}/\${filepath_src_rel} + # Create directory for symlink + mkdir -p \${filepath_dst%/*}; + # Get path for symlink source file, then create it + # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only + # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers + symlinkpath=\$(realpath \${filepath_src}) + ln -s \${symlinkpath} \${filepath_dst}; + done + if [[ -L "\${src##*/}" ]]; then + rm "\${src}" + fi + } + shadow_input_directory ${assemble_dir} - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - # Run - gridss \\ - ${args} \\ - --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ - --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ - --jar "${task.ext.jarPath}" \\ - --steps call \\ - --labels "${labels_arg}" \\ - --reference "${genome_fa}" \\ - --blacklist "${blacklist}" \\ - --workingdir "${output_dirname}/work/" \\ - --assembly "${output_dirname}/sv_assemblies.bam" \\ - --output "${output_dirname}/sv_vcf.vcf.gz" \\ - --threads "${task.cpus}" \\ - ${config_arg} \\ - ${bams_arg} + # Run + gridss \\ + ${args} \\ + --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ + --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ + --jar "${task.ext.jarPath}" \\ + --steps call \\ + --labels "${labels_arg}" \\ + --reference "${genome_fa}" \\ + --blacklist "${blacklist}" \\ + --workingdir "${output_dirname}/work/" \\ + --assembly "${output_dirname}/sv_assemblies.bam" \\ + --output "${output_dirname}/sv_vcf.vcf.gz" \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + ${bams_arg} - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ - stub: - """ - mkdir -p gridss_call/ - cat < gridss_call/sv_vcf.vcf.gz - ##fileformat=VCFv4.1 - ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . - EOF - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir -p gridss_call/ + cat < gridss_call/sv_vcf.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/gridss/preprocess/main.nf b/modules/local/gridss/preprocess/main.nf index fe5ebcc4..81722608 100644 --- a/modules/local/gridss/preprocess/main.nf +++ b/modules/local/gridss/preprocess/main.nf @@ -1,52 +1,52 @@ process PREPROCESS { - //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) - container 'docker.io/scwatts/gridss:2.13.2--3' - - input: - tuple val(meta), path(bam) - path gridss_config - path genome_fa - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - - output: - tuple val(meta), path("gridss_preprocess/${bam.name}.gridss.working/"), emit: preprocess_dir - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - - """ - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - - gridss \\ - ${args} \\ - --jvmheap "${task.memory.giga}g" \\ - --jar "${task.ext.jarPath}" \\ - --steps preprocess \\ - --reference "${genome_fa}" \\ - --workingdir gridss_preprocess/ \\ - --threads "${task.cpus}" \\ - ${config_arg} \\ - ${bam} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ - - stub: - """ - mkdir -p gridss_preprocess/${bam.name}.gridss.working/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) + container 'docker.io/scwatts/gridss:2.13.2--3' + + input: + tuple val(meta), path(bam) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + + output: + tuple val(meta), path("gridss_preprocess/${bam.name}.gridss.working/"), emit: preprocess_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + + """ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + gridss \\ + ${args} \\ + --jvmheap "${task.memory.giga}g" \\ + --jar "${task.ext.jarPath}" \\ + --steps preprocess \\ + --reference "${genome_fa}" \\ + --workingdir gridss_preprocess/ \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + ${bam} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_preprocess/${bam.name}.gridss.working/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 248e0b6d..0d0ae156 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -1,62 +1,62 @@ process GRIPSS_GERMLINE { - //conda (params.enable_conda ? "bioconda::hmftools-gripss=2.2" : null) - container 'docker.io/scwatts/gripss:2.3.1--0' + //conda (params.enable_conda ? "bioconda::hmftools-gripss=2.2" : null) + container 'docker.io/scwatts/gripss:2.3.1--0' - input: - tuple val(meta), path(gridss_vcf) - path genome_fa - path genome_fai - val genome_ver - path breakend_pon - path breakpoint_pon - path known_fusions - path repeat_mask_file + input: + tuple val(meta), path(gridss_vcf) + path genome_fa + path genome_fai + val genome_ver + path breakend_pon + path breakpoint_pon + path known_fusions + path repeat_mask_file - output: - tuple val(meta), path('*.gripss.filtered.vcf.gz'), path('*.gripss.filtered.vcf.gz.tbi'), emit: vcf_hard - tuple val(meta), path('*.gripss.vcf.gz'), path('*.gripss.vcf.gz.tbi') , emit: vcf_soft - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('*.gripss.filtered.vcf.gz'), path('*.gripss.filtered.vcf.gz.tbi'), emit: vcf_hard + tuple val(meta), path('*.gripss.vcf.gz'), path('*.gripss.vcf.gz.tbi') , emit: vcf_soft + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' - def repeat_mask_file_arg = repeat_mask_file ? "-repeat_mask_file ${repeat_mask_file}" : '' + script: + def args = task.ext.args ?: '' + def repeat_mask_file_arg = repeat_mask_file ? "-repeat_mask_file ${repeat_mask_file}" : '' - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -sample "${meta.get(['sample_name', 'normal'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ - -pon_sgl_file "${breakend_pon}" \\ - -pon_sv_file "${breakpoint_pon}" \\ - -known_hotspot_file "${known_fusions}" \\ - -vcf "${gridss_vcf}" \\ - ${repeat_mask_file_arg} \\ - -output_dir ./ + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'normal'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -pon_sgl_file "${breakend_pon}" \\ + -pon_sv_file "${breakpoint_pon}" \\ + -known_hotspot_file "${known_fusions}" \\ + -vcf "${gridss_vcf}" \\ + ${repeat_mask_file_arg} \\ + -output_dir ./ - # NOTE(SW): hard coded since there is no reliable way to obtain version information - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gripss: 2.3.1 - END_VERSIONS - """ + # NOTE(SW): hard coded since there is no reliable way to obtain version information + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gripss: 2.3.1 + END_VERSIONS + """ - stub: - """ - cat < ${meta.get(['sample_name', 'normal'])}.gripss.filtered.vcf.gz - ##fileformat=VCFv4.1 - ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . - EOF - touch ${meta.get(['sample_name', 'normal'])}.gripss.filtered.vcf.gz.tbi - touch ${meta.get(['sample_name', 'normal'])}.gripss.vcf.gz - touch ${meta.get(['sample_name', 'normal'])}.gripss.vcf.gz.tbi - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + cat < ${meta.get(['sample_name', 'normal'])}.gripss.filtered.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + touch ${meta.get(['sample_name', 'normal'])}.gripss.filtered.vcf.gz.tbi + touch ${meta.get(['sample_name', 'normal'])}.gripss.vcf.gz + touch ${meta.get(['sample_name', 'normal'])}.gripss.vcf.gz.tbi + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index f01b06cb..cd148c36 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -1,63 +1,63 @@ process GRIPSS_SOMATIC { - //conda (params.enable_conda ? "bioconda::hmftools-gripss=2.2" : null) - container 'docker.io/scwatts/gripss:2.3.1--0' + //conda (params.enable_conda ? "bioconda::hmftools-gripss=2.2" : null) + container 'docker.io/scwatts/gripss:2.3.1--0' - input: - tuple val(meta), path(gridss_vcf) - path genome_fa - path genome_fai - val genome_ver - path breakend_pon - path breakpoint_pon - path known_fusions - path repeat_mask_file + input: + tuple val(meta), path(gridss_vcf) + path genome_fa + path genome_fai + val genome_ver + path breakend_pon + path breakpoint_pon + path known_fusions + path repeat_mask_file - output: - tuple val(meta), path('*.gripss.filtered.vcf.gz'), path('*.gripss.filtered.vcf.gz.tbi'), emit: vcf_hard - tuple val(meta), path('*.gripss.vcf.gz'), path('*.gripss.vcf.gz.tbi') , emit: vcf_soft - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('*.gripss.filtered.vcf.gz'), path('*.gripss.filtered.vcf.gz.tbi'), emit: vcf_hard + tuple val(meta), path('*.gripss.vcf.gz'), path('*.gripss.vcf.gz.tbi') , emit: vcf_soft + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' - def repeat_mask_file_arg = repeat_mask_file ? "-repeat_mask_file ${repeat_mask_file}" : '' + script: + def args = task.ext.args ?: '' + def repeat_mask_file_arg = repeat_mask_file ? "-repeat_mask_file ${repeat_mask_file}" : '' - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -sample "${meta.get(['sample_name', 'tumor'])}" \\ - -reference "${meta.get(['sample_name', 'normal'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ - -pon_sgl_file "${breakend_pon}" \\ - -pon_sv_file "${breakpoint_pon}" \\ - -known_hotspot_file "${known_fusions}" \\ - -vcf "${gridss_vcf}" \\ - ${repeat_mask_file_arg} \\ - -output_dir ./ + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'tumor'])}" \\ + -reference "${meta.get(['sample_name', 'normal'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -pon_sgl_file "${breakend_pon}" \\ + -pon_sv_file "${breakpoint_pon}" \\ + -known_hotspot_file "${known_fusions}" \\ + -vcf "${gridss_vcf}" \\ + ${repeat_mask_file_arg} \\ + -output_dir ./ - # NOTE(SW): hard coded since there is no reliable way to obtain version information - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gripss: 2.3.1 - END_VERSIONS - """ + # NOTE(SW): hard coded since there is no reliable way to obtain version information + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gripss: 2.3.1 + END_VERSIONS + """ - stub: - """ - cat < ${meta.get(['sample_name', 'tumor'])}.gripss.filtered.vcf.gz - ##fileformat=VCFv4.1 - ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . - EOF - touch ${meta.get(['sample_name', 'tumor'])}.gripss.filtered.vcf.gz.tbi - touch ${meta.get(['sample_name', 'tumor'])}.gripss.vcf.gz - touch ${meta.get(['sample_name', 'tumor'])}.gripss.vcf.gz.tbi - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + cat < ${meta.get(['sample_name', 'tumor'])}.gripss.filtered.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + touch ${meta.get(['sample_name', 'tumor'])}.gripss.filtered.vcf.gz.tbi + touch ${meta.get(['sample_name', 'tumor'])}.gripss.vcf.gz + touch ${meta.get(['sample_name', 'tumor'])}.gripss.vcf.gz.tbi + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 32116490..1b2e5e2a 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -2,53 +2,53 @@ process ISOFOX { - container 'docker.io/scwatts/isofox:1.5--0' - - input: - tuple val(meta), path(bam) - path genome_fa - path genome_fai - val genome_ver - path ensembl_data_dir - path exp_counts - path exp_gc_ratios - - output: - tuple val(meta), path('isofox/'), emit: isofox_dir - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - mkdir -p isofox/ - - java \\ - -Xmx${task.memory.giga}g \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -sample ${meta.get(['sample_name', 'tumor'])} \\ - -bam_file ${bam} \\ - -ref_genome ${genome_fa} \\ - -ref_genome_version ${genome_ver} \\ - -ensembl_data_dir ${ensembl_data_dir} \\ - -exp_counts_file ${exp_counts} \\ - -exp_gc_ratios_file ${exp_gc_ratios} \\ - -output_dir ./isofox/ \\ - -threads ${task.cpus} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - isofox: \$(java -jar ${task.ext.jarPath} | sed -n '1s/^.*version: //p') - END_VERSIONS - """ - - stub: - """ - mkdir -p isofox/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + container 'docker.io/scwatts/isofox:1.5--0' + + input: + tuple val(meta), path(bam) + path genome_fa + path genome_fai + val genome_ver + path ensembl_data_dir + path exp_counts + path exp_gc_ratios + + output: + tuple val(meta), path('isofox/'), emit: isofox_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + mkdir -p isofox/ + + java \\ + -Xmx${task.memory.giga}g \\ + -jar ${task.ext.jarPath} \\ + ${args} \\ + -sample ${meta.get(['sample_name', 'tumor'])} \\ + -bam_file ${bam} \\ + -ref_genome ${genome_fa} \\ + -ref_genome_version ${genome_ver} \\ + -ensembl_data_dir ${ensembl_data_dir} \\ + -exp_counts_file ${exp_counts} \\ + -exp_gc_ratios_file ${exp_gc_ratios} \\ + -output_dir ./isofox/ \\ + -threads ${task.cpus} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + isofox: \$(java -jar ${task.ext.jarPath} | sed -n '1s/^.*version: //p') + END_VERSIONS + """ + + stub: + """ + mkdir -p isofox/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index c3aeb215..cbf57b0f 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -1,64 +1,64 @@ process LILAC { - //conda (params.enable_conda ? "bioconda::hmftools-lilac=1.2" : null) - container 'docker.io/scwatts/lilac:1.4.1--0' + //conda (params.enable_conda ? "bioconda::hmftools-lilac=1.2" : null) + container 'docker.io/scwatts/lilac:1.4.1--0' - input: - tuple val(meta), path(tumor_bam), path(normal_bam), path(tumour_bai), path(normal_bai), path(purple_dir) - path genome_fa - val genome_ver - path lilac_resource_dir, stageAs: 'lilac_resource_dir' + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumour_bai), path(normal_bai), path(purple_dir) + path genome_fa + val genome_ver + path lilac_resource_dir, stageAs: 'lilac_resource_dir' - output: - tuple val(meta), path('lilac/'), emit: lilac_dir - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('lilac/'), emit: lilac_dir + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' - def sample_name = get_sample_name(meta, tumor_bam, normal_bam) - def tumor_bam_arg = tumor_bam ? "-tumor_bam ${tumor_bam}" : '' - def purple_args = purple_dir ? """ - -gene_copy_number ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ - -somatic_vcf ${purple_dir}/${sample_name}.purple.sv.vcf.gz \\ - """ : '' + script: + def args = task.ext.args ?: '' + def sample_name = get_sample_name(meta, tumor_bam, normal_bam) + def tumor_bam_arg = tumor_bam ? "-tumor_bam ${tumor_bam}" : '' + def purple_args = purple_dir ? """ + -gene_copy_number ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ + -somatic_vcf ${purple_dir}/${sample_name}.purple.sv.vcf.gz \\ + """ : '' - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -sample "${sample_name}" \\ - ${tumor_bam_arg} \\ - -reference_bam ${normal_bam} \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ - -resource_dir "${lilac_resource_dir}" \\ - ${purple_args.replaceAll('\\n', '')} \\ - -threads "${task.cpus}" \\ - -output_dir lilac/ + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${sample_name}" \\ + ${tumor_bam_arg} \\ + -reference_bam ${normal_bam} \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -resource_dir "${lilac_resource_dir}" \\ + ${purple_args.replaceAll('\\n', '')} \\ + -threads "${task.cpus}" \\ + -output_dir lilac/ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. - cat <<-END_VERSIONS > versions.yml - "${task.process}": - lilac: 1.4.1 - END_VERSIONS - """ + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + lilac: 1.4.1 + END_VERSIONS + """ - stub: - """ - mkdir -p lilac/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir -p lilac/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } def get_sample_name(meta, tumor_bam, normal_bam) { - if (tumor_bam) { - return meta.get(['sample_name', 'tumor']) - } else if (normal_bam) { - return meta.get(['sample_name', 'normal']) - } else { - Sys.exit(1) - } + if (tumor_bam) { + return meta.get(['sample_name', 'tumor']) + } else if (normal_bam) { + return meta.get(['sample_name', 'normal']) + } else { + Sys.exit(1) + } } diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 263b01cf..a2b2c293 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -1,50 +1,50 @@ process LINX_GERMLINE { - //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) - container 'docker.io/scwatts/linx:1.22--0' + //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) + container 'docker.io/scwatts/linx:1.22--0' - input: - tuple val(meta), path(gripss_sv) - val genome_ver - path fragile_sites - path lines - path ensembl_data_dir - path driver_gene_panel + input: + tuple val(meta), path(gripss_sv) + val genome_ver + path fragile_sites + path lines + path ensembl_data_dir + path driver_gene_panel - output: - tuple val(meta), path('linx_germline/'), emit: annotation_dir - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('linx_germline/'), emit: annotation_dir + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' + script: + def args = task.ext.args ?: '' - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -sample "${meta.get(['sample_name', 'normal'])}" \\ - -germline \\ - -ref_genome_version "${genome_ver}" \\ - -sv_vcf "${gripss_sv}" \\ - -fragile_site_file "${fragile_sites}" \\ - -line_element_file "${lines}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -check_drivers \\ - -driver_gene_panel "${driver_gene_panel}" \\ - -output_dir linx_germline/ + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'normal'])}" \\ + -germline \\ + -ref_genome_version "${genome_ver}" \\ + -sv_vcf "${gripss_sv}" \\ + -fragile_site_file "${fragile_sites}" \\ + -line_element_file "${lines}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -check_drivers \\ + -driver_gene_panel "${driver_gene_panel}" \\ + -output_dir linx_germline/ - cat <<-END_VERSIONS > versions.yml - "${task.process}": - linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') + END_VERSIONS + """ - stub: - """ - mkdir linx_germline/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir linx_germline/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index de11621f..39b51d7c 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -1,53 +1,53 @@ process LINX_SOMATIC { - //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) - container 'docker.io/scwatts/linx:1.22--0' + //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) + container 'docker.io/scwatts/linx:1.22--0' - input: - tuple val(meta), path(purple_dir) - val genome_ver - path fragile_sites - path lines - path ensembl_data_dir - path known_fusion_data - path driver_gene_panel + input: + tuple val(meta), path(purple_dir) + val genome_ver + path fragile_sites + path lines + path ensembl_data_dir + path known_fusion_data + path driver_gene_panel - output: - tuple val(meta), path('linx_somatic/'), emit: annotation_dir - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('linx_somatic/'), emit: annotation_dir + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' + script: + def args = task.ext.args ?: '' - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -sample "${meta.get(['sample_name', 'tumor'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -sv_vcf "${purple_dir}/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz" \\ - -purple_dir "${purple_dir}" \\ - -fragile_site_file "${fragile_sites}" \\ - -line_element_file "${lines}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -check_fusions \\ - -known_fusion_file "${known_fusion_data}" \\ - -check_drivers \\ - -driver_gene_panel "${driver_gene_panel}" \\ - -output_dir linx_somatic/ + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'tumor'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -sv_vcf "${purple_dir}/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz" \\ + -purple_dir "${purple_dir}" \\ + -fragile_site_file "${fragile_sites}" \\ + -line_element_file "${lines}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -check_fusions \\ + -known_fusion_file "${known_fusion_data}" \\ + -check_drivers \\ + -driver_gene_panel "${driver_gene_panel}" \\ + -output_dir linx_somatic/ - cat <<-END_VERSIONS > versions.yml - "${task.process}": - linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') + END_VERSIONS + """ - stub: - """ - mkdir linx_somatic/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir linx_somatic/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 8c555904..e611c3a2 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -1,51 +1,51 @@ process VISUALISER { - //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) - container 'docker.io/scwatts/linx:1.22--0' - - // Lenient caching is required here as the hash of the LINX_SOMATIC - // 'annotation_dir' output changes between runs even when the LINX_SOMATIC - // process itself is cached. - cache = 'lenient' - - input: - tuple val(meta), path(linx) - val genome_ver - path ensembl_data_dir - - output: - tuple val(meta), path('linx_visualiser/plot/'), emit: visualiser_dir - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - java \\ - -Xmx${task.memory.giga}g \\ - -cp "${task.ext.jarPath}" \\ - com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ - ${args} \\ - -sample "${meta.get(['sample_name', 'tumor'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -plot_out linx_visualiser/plot \\ - -data_out linx_visualiser/data \\ - -vis_file_dir "${linx}" \\ - -circos "${task.ext.path_circos}" \\ - -threads "${task.cpus}" - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') - END_VERSIONS - """ - - stub: - """ - mkdir -p linx_visualiser/plot/ - echo -e '${task.process}:\n stub: noversions\n' > versions.yml - """ + //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) + container 'docker.io/scwatts/linx:1.22--0' + + // Lenient caching is required here as the hash of the LINX_SOMATIC + // 'annotation_dir' output changes between runs even when the LINX_SOMATIC + // process itself is cached. + cache = 'lenient' + + input: + tuple val(meta), path(linx) + val genome_ver + path ensembl_data_dir + + output: + tuple val(meta), path('linx_visualiser/plot/'), emit: visualiser_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -cp "${task.ext.jarPath}" \\ + com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'tumor'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -plot_out linx_visualiser/plot \\ + -data_out linx_visualiser/data \\ + -vis_file_dir "${linx}" \\ + -circos "${task.ext.path_circos}" \\ + -threads "${task.cpus}" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') + END_VERSIONS + """ + + stub: + """ + mkdir -p linx_visualiser/plot/ + echo -e '${task.process}:\n stub: noversions\n' > versions.yml + """ } diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 591481ff..57f8023d 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -1,60 +1,60 @@ // NOTE(SW): PAVE gnomad filtering is not yet documented but is used in Pipeline5 https://github.com/hartwigmedical/pipeline5/blob/master/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L27-L28 process PAVE_GERMLINE { - //conda (params.enable_conda ? "bioconda::hmftools-pave=1.3" : null) - container 'docker.io/scwatts/pave:1.4--0' - - input: - tuple val(meta), path(sage_vcf) - path genome_fa - path genome_fai - val genome_ver - path sage_blacklist_bed - path sage_blacklist_vcf - path clinvar_vcf - path mappability_bed - path driver_gene_panel - path ensembl_data_dir - - output: - tuple val(meta), path("*.vcf.gz") , emit: vcf - tuple val(meta), path("*.vcf.gz.tbi"), emit: index - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -sample "${meta.get(['sample_name', 'tumor'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -driver_gene_panel "${driver_gene_panel}" \\ - -clinvar_vcf "${clinvar_vcf}" \\ - -blacklist_bed "${sage_blacklist_bed}" \\ - -blacklist_vcf "${sage_blacklist_vcf}" \\ - -mappability_bed "${mappability_bed}" \\ - -vcf_file "${sage_vcf}" \\ - -read_pass_only \\ - -output_dir ./ - - # NOTE(SW): hard coded since there is no reliable way to obtain version information. - cat <<-END_VERSIONS > versions.yml - "${task.process}": - pave: 1.4 - END_VERSIONS - """ - - stub: - """ - touch ${meta.get(['sample_name', 'tumor'])}.sage.pave_germline.vcf.gz{,.tbi} - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + //conda (params.enable_conda ? "bioconda::hmftools-pave=1.3" : null) + container 'docker.io/scwatts/pave:1.4--0' + + input: + tuple val(meta), path(sage_vcf) + path genome_fa + path genome_fai + val genome_ver + path sage_blacklist_bed + path sage_blacklist_vcf + path clinvar_vcf + path mappability_bed + path driver_gene_panel + path ensembl_data_dir + + output: + tuple val(meta), path("*.vcf.gz") , emit: vcf + tuple val(meta), path("*.vcf.gz.tbi"), emit: index + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.get(['sample_name', 'tumor'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -driver_gene_panel "${driver_gene_panel}" \\ + -clinvar_vcf "${clinvar_vcf}" \\ + -blacklist_bed "${sage_blacklist_bed}" \\ + -blacklist_vcf "${sage_blacklist_vcf}" \\ + -mappability_bed "${mappability_bed}" \\ + -vcf_file "${sage_vcf}" \\ + -read_pass_only \\ + -output_dir ./ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + pave: 1.4 + END_VERSIONS + """ + + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}.sage.pave_germline.vcf.gz{,.tbi} + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 09a6a00a..43b1f6ef 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -1,57 +1,57 @@ // NOTE(SW): PAVE gnomad filtering is not yet documented but is used in Pipeline5 https://github.com/hartwigmedical/pipeline5/blob/master/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L27-L28 process PAVE_SOMATIC { - //conda (params.enable_conda ? "bioconda::hmftools-pave=1.3" : null) - container 'docker.io/scwatts/pave:1.4--0' - - input: - tuple val(meta), path(sage_vcf) - path genome_fa - path genome_fai - val genome_ver - path sage_pon_file - path mappability_bed - path driver_gene_panel - path ensembl_data_dir - - output: - tuple val(meta), path("*.vcf.gz") , emit: vcf - tuple val(meta), path("*.vcf.gz.tbi"), emit: index - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def pon_filters = "HOTSPOT:5:5;PANEL:2:5;UNKNOWN:2:0" - - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - -sample "${meta.get(['sample_name', 'tumor'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -driver_gene_panel "${driver_gene_panel}" \\ - -pon_file "${sage_pon_file}" \\ - -pon_filters "${pon_filters}" \\ - -mappability_bed "${mappability_bed}" \\ - -vcf_file "${sage_vcf}" \\ - -read_pass_only \\ - -output_dir ./ - - # NOTE(SW): hard coded since there is no reliable way to obtain version information. - cat <<-END_VERSIONS > versions.yml - "${task.process}": - pave: 1.4 - END_VERSIONS - """ - - stub: - """ - touch ${meta.get(['sample_name', 'tumor'])}.sage.pave_somatic.vcf.gz{,.tbi} - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + //conda (params.enable_conda ? "bioconda::hmftools-pave=1.3" : null) + container 'docker.io/scwatts/pave:1.4--0' + + input: + tuple val(meta), path(sage_vcf) + path genome_fa + path genome_fai + val genome_ver + path sage_pon_file + path mappability_bed + path driver_gene_panel + path ensembl_data_dir + + output: + tuple val(meta), path("*.vcf.gz") , emit: vcf + tuple val(meta), path("*.vcf.gz.tbi"), emit: index + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def pon_filters = "HOTSPOT:5:5;PANEL:2:5;UNKNOWN:2:0" + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + -sample "${meta.get(['sample_name', 'tumor'])}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -driver_gene_panel "${driver_gene_panel}" \\ + -pon_file "${sage_pon_file}" \\ + -pon_filters "${pon_filters}" \\ + -mappability_bed "${mappability_bed}" \\ + -vcf_file "${sage_vcf}" \\ + -read_pass_only \\ + -output_dir ./ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + pave: 1.4 + END_VERSIONS + """ + + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}.sage.pave_somatic.vcf.gz{,.tbi} + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 7591372e..ffbc06f6 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -1,94 +1,94 @@ process PURPLE { - //conda (params.enable_conda ? "bioconda::hmftools-purple=3.6" : null) - container 'docker.io/scwatts/purple:3.6--4' + //conda (params.enable_conda ? "bioconda::hmftools-purple=3.6" : null) + container 'docker.io/scwatts/purple:3.6--4' - input: - tuple val(meta), path(amber), path(cobalt), path(sv_hard_vcf), path(sv_hard_vcf_index), path(sv_soft_vcf), path(sv_soft_vcf_index), path(smlv_tumor_vcf), path(smlv_normal_vcf) - path genome_fa - path genome_fai - path genome_dict - val genome_ver - path gc_profile - path sage_known_hotspots_somatic - path sage_known_hotspots_germline - path driver_gene_panel - path ensembl_data_dir - path germline_del_freq + input: + tuple val(meta), path(amber), path(cobalt), path(sv_hard_vcf), path(sv_hard_vcf_index), path(sv_soft_vcf), path(sv_soft_vcf_index), path(smlv_tumor_vcf), path(smlv_normal_vcf) + path genome_fa + path genome_fai + path genome_dict + val genome_ver + path gc_profile + path sage_known_hotspots_somatic + path sage_known_hotspots_germline + path driver_gene_panel + path ensembl_data_dir + path germline_del_freq - output: - tuple val(meta), path('purple/'), emit: purple_dir - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('purple/'), emit: purple_dir + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' - def smlv_tumor_vcf_fp = smlv_tumor_vcf ?: '' - def smlv_normal_vcf_fp = smlv_normal_vcf ?: '' - def germline_del_freq_arg = germline_del_freq ? "-germline_del_freq_file ${germline_del_freq}" : '' + script: + def args = task.ext.args ?: '' + def smlv_tumor_vcf_fp = smlv_tumor_vcf ?: '' + def smlv_normal_vcf_fp = smlv_normal_vcf ?: '' + def germline_del_freq_arg = germline_del_freq ? "-germline_del_freq_file ${germline_del_freq}" : '' - """ - # For provided smlv VCFs, filter records that do not contain the required FORMAT/AD field and - # get argument for PURPLE - get_smlv_arg() { - fp=\${1} - fn=\${fp##*/} - if [[ "\${fp}" != '' ]]; then - fp_out="prepared__\${2}__\${fn}" - bcftools filter -Oz -e 'FORMAT/AD[*]="."' "\${fp}" > \${fp_out} - echo "-\${2} \${fp_out}" - fi - } - smlv_tumor_vcf_arg=\$(get_smlv_arg "${smlv_tumor_vcf_fp}" somatic_vcf) - smlv_normal_vcf_arg=\$(get_smlv_arg "${smlv_normal_vcf_fp}" germline_vcf) + """ + # For provided smlv VCFs, filter records that do not contain the required FORMAT/AD field and + # get argument for PURPLE + get_smlv_arg() { + fp=\${1} + fn=\${fp##*/} + if [[ "\${fp}" != '' ]]; then + fp_out="prepared__\${2}__\${fn}" + bcftools filter -Oz -e 'FORMAT/AD[*]="."' "\${fp}" > \${fp_out} + echo "-\${2} \${fp_out}" + fi + } + smlv_tumor_vcf_arg=\$(get_smlv_arg "${smlv_tumor_vcf_fp}" somatic_vcf) + smlv_normal_vcf_arg=\$(get_smlv_arg "${smlv_normal_vcf_fp}" germline_vcf) - # Run PURPLE - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -tumor "${meta.get(['sample_name', 'tumor'])}" \\ - -reference "${meta.get(['sample_name', 'normal'])}" \\ - -sv_recovery_vcf "${sv_soft_vcf}" \\ - -structural_vcf "${sv_hard_vcf}" \\ - \${smlv_tumor_vcf_arg} \\ - \${smlv_normal_vcf_arg} \\ - -amber "${amber}" \\ - -cobalt "${cobalt}" \\ - -output_dir purple/ \\ - -gc_profile "${gc_profile}" \\ - -run_drivers \\ - -driver_gene_panel "${driver_gene_panel}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -somatic_hotspots "${sage_known_hotspots_somatic}" \\ - -germline_hotspots "${sage_known_hotspots_germline}" \\ - ${germline_del_freq_arg} \\ - -ref_genome "${genome_fa}" \\ - -ref_genome_version "${genome_ver}" \\ - -threads "${task.cpus}" \\ - -circos "${task.ext.circosPath}" + # Run PURPLE + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -tumor "${meta.get(['sample_name', 'tumor'])}" \\ + -reference "${meta.get(['sample_name', 'normal'])}" \\ + -sv_recovery_vcf "${sv_soft_vcf}" \\ + -structural_vcf "${sv_hard_vcf}" \\ + \${smlv_tumor_vcf_arg} \\ + \${smlv_normal_vcf_arg} \\ + -amber "${amber}" \\ + -cobalt "${cobalt}" \\ + -output_dir purple/ \\ + -gc_profile "${gc_profile}" \\ + -run_drivers \\ + -driver_gene_panel "${driver_gene_panel}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -somatic_hotspots "${sage_known_hotspots_somatic}" \\ + -germline_hotspots "${sage_known_hotspots_germline}" \\ + ${germline_del_freq_arg} \\ + -ref_genome "${genome_fa}" \\ + -ref_genome_version "${genome_ver}" \\ + -threads "${task.cpus}" \\ + -circos "${task.ext.circosPath}" - # PURPLE can fail silently, check that at least the PURPLE SV VCF is created - if [[ ! -s "purple/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz" ]]; then - exit 1; - fi + # PURPLE can fail silently, check that at least the PURPLE SV VCF is created + if [[ ! -s "purple/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz" ]]; then + exit 1; + fi - cat <<-END_VERSIONS > versions.yml - "${task.process}": - purple: \$(java -jar "${task.ext.jarPath}" -version | sed 's/.*Purple version: //') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + purple: \$(java -jar "${task.ext.jarPath}" -version | sed 's/.*Purple version: //') + END_VERSIONS + """ - stub: - """ - mkdir purple/ - cat < purple/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz - ##fileformat=VCFv4.1 - ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . - EOF - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir purple/ + cat < purple/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index a288c996..285ed2f0 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -1,63 +1,63 @@ process SAGE_GERMLINE { - //conda (params.enable_conda ? "bioconda::hmftools-sage=3.1" : null) - container 'docker.io/scwatts/sage:3.2--0' + //conda (params.enable_conda ? "bioconda::hmftools-sage=3.1" : null) + container 'docker.io/scwatts/sage:3.2--0' - input: - tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) - path genome_fa - path genome_fai - path genome_dict - val genome_ver - path sage_known_hotspots_germline - path sage_coding_panel - path sage_high_confidence - path ensembl_data_dir + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) + path genome_fa + path genome_fai + path genome_dict + val genome_ver + path sage_known_hotspots_germline + path sage_coding_panel + path sage_high_confidence + path ensembl_data_dir - output: - tuple val(meta), path("${meta.subject_name}.sage_germline.vcf.gz"), emit: vcf - path 'versions.yml' , emit: versions + output: + tuple val(meta), path("${meta.subject_name}.sage_germline.vcf.gz"), emit: vcf + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' + script: + def args = task.ext.args ?: '' - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -reference "${meta.get(['sample_name', 'tumor'])}" \\ - -reference_bam "${tumor_bam}" \\ - -tumor "${meta.get(['sample_name', 'normal'])}" \\ - -tumor_bam "${normal_bam}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ - -hotspots "${sage_known_hotspots_germline}" \\ - -panel_bed "${sage_coding_panel}" \\ - -high_confidence_bed "${sage_high_confidence}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -hotspot_min_tumor_qual 50 \\ - -panel_min_tumor_qual 75 \\ - -hotspot_max_germline_vaf 100 \\ - -hotspot_max_germline_rel_raw_base_qual 100 \\ - -panel_max_germline_vaf 100 \\ - -panel_max_germline_rel_raw_base_qual 100 \\ - -mnv_filter_enabled false \\ - -panel_only \\ - -threads "${task.cpus}" \\ - -out "${meta.subject_name}.sage_germline.vcf.gz" + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -reference "${meta.get(['sample_name', 'tumor'])}" \\ + -reference_bam "${tumor_bam}" \\ + -tumor "${meta.get(['sample_name', 'normal'])}" \\ + -tumor_bam "${normal_bam}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -hotspots "${sage_known_hotspots_germline}" \\ + -panel_bed "${sage_coding_panel}" \\ + -high_confidence_bed "${sage_high_confidence}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -hotspot_min_tumor_qual 50 \\ + -panel_min_tumor_qual 75 \\ + -hotspot_max_germline_vaf 100 \\ + -hotspot_max_germline_rel_raw_base_qual 100 \\ + -panel_max_germline_vaf 100 \\ + -panel_max_germline_rel_raw_base_qual 100 \\ + -mnv_filter_enabled false \\ + -panel_only \\ + -threads "${task.cpus}" \\ + -out "${meta.subject_name}.sage_germline.vcf.gz" - cat <<-END_VERSIONS > versions.yml - "${task.process}": - sage: \$(java -jar "${task.ext.jarPath}" | head -n1 | sed 's/.*Sage version: //') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sage: \$(java -jar "${task.ext.jarPath}" | head -n1 | sed 's/.*Sage version: //') + END_VERSIONS + """ - stub: - """ - touch "${meta.subject_name}.sage_germline.vcf.gz" - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + touch "${meta.subject_name}.sage_germline.vcf.gz" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 863c2447..fc2da9a1 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -1,55 +1,55 @@ process SAGE_SOMATIC { - //conda (params.enable_conda ? "bioconda::hmftools-sage=3.1" : null) - container 'docker.io/scwatts/sage:3.2--0' + //conda (params.enable_conda ? "bioconda::hmftools-sage=3.1" : null) + container 'docker.io/scwatts/sage:3.2--0' - input: - tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) - path genome_fa - path genome_fai - path genome_dict - val genome_ver - path sage_known_hotspots_somatic - path sage_coding_panel - path sage_high_confidence - path ensembl_data_dir + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) + path genome_fa + path genome_fai + path genome_dict + val genome_ver + path sage_known_hotspots_somatic + path sage_coding_panel + path sage_high_confidence + path ensembl_data_dir - output: - tuple val(meta), path("${meta.subject_name}.sage_somatic.vcf.gz"), emit: vcf - path 'versions.yml' , emit: versions + output: + tuple val(meta), path("${meta.subject_name}.sage_somatic.vcf.gz"), emit: vcf + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' + script: + def args = task.ext.args ?: '' - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -reference "${meta.get(['sample_name', 'normal'])}" \\ - -reference_bam "${normal_bam}" \\ - -tumor "${meta.get(['sample_name', 'tumor'])}" \\ - -tumor_bam "${tumor_bam}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ - -hotspots "${sage_known_hotspots_somatic}" \\ - -panel_bed "${sage_coding_panel}" \\ - -high_confidence_bed "${sage_high_confidence}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -threads "${task.cpus}" \\ - -out "${meta.subject_name}.sage_somatic.vcf.gz" + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -reference "${meta.get(['sample_name', 'normal'])}" \\ + -reference_bam "${normal_bam}" \\ + -tumor "${meta.get(['sample_name', 'tumor'])}" \\ + -tumor_bam "${tumor_bam}" \\ + -ref_genome_version "${genome_ver}" \\ + -ref_genome "${genome_fa}" \\ + -hotspots "${sage_known_hotspots_somatic}" \\ + -panel_bed "${sage_coding_panel}" \\ + -high_confidence_bed "${sage_high_confidence}" \\ + -ensembl_data_dir "${ensembl_data_dir}" \\ + -threads "${task.cpus}" \\ + -out "${meta.subject_name}.sage_somatic.vcf.gz" - cat <<-END_VERSIONS > versions.yml - "${task.process}": - sage: \$(java -jar "${task.ext.jarPath}" | head -n1 | sed 's/.*Sage version: //') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sage: \$(java -jar "${task.ext.jarPath}" | head -n1 | sed 's/.*Sage version: //') + END_VERSIONS + """ - stub: - """ - touch "${meta.subject_name}.sage_somatic.vcf.gz" - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + touch "${meta.subject_name}.sage_somatic.vcf.gz" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf index 6df76a07..0c2c85bc 100644 --- a/modules/local/samplesheet_check.nf +++ b/modules/local/samplesheet_check.nf @@ -1,27 +1,27 @@ process SAMPLESHEET_CHECK { - tag "$samplesheet" + tag "$samplesheet" - conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/python:3.8.3' : - 'quay.io/biocontainers/python:3.8.3' }" + conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/python:3.8.3' : + 'quay.io/biocontainers/python:3.8.3' }" - input: - path samplesheet + input: + path samplesheet - output: - path '*.csv' , emit: csv - path "versions.yml", emit: versions + output: + path '*.csv' , emit: csv + path "versions.yml", emit: versions - script: // This script is bundled with the pipeline, in nf-core/oncoanalyser/bin/ - """ - check_samplesheet.py \\ - $samplesheet \\ - samplesheet.valid.csv + script: // This script is bundled with the pipeline, in nf-core/oncoanalyser/bin/ + """ + check_samplesheet.py \\ + $samplesheet \\ + samplesheet.valid.csv - cat <<-END_VERSIONS > versions.yml - "${task.process}": - python: \$(python --version | sed 's/Python //g') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ } diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 778338b9..a127a10a 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -1,89 +1,89 @@ process ASSEMBLE { - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.1--0' - input: - tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) - path gridss_config - path genome_fa - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - path blacklist + input: + tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + path blacklist - output: - tuple val(meta), path('gridss_assemble/'), emit: assemble_dir - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('gridss_assemble/'), emit: assemble_dir + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - def output_dirname = 'gridss_assemble' - def labels_arg = labels.join(',') - // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below - def bams_list = bams instanceof List ? bams : [bams] - def bams_arg = "--bams ${bams_list.join(',')}" - def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] - def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + def output_dirname = 'gridss_assemble' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = "--bams ${bams_list.join(',')}" + def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] + def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" - """ - # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation - # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present - shadow_input_directory() { - src=\${1} - dst="${output_dirname}/work/\${src##*/}" - for filepath_src in \$(find -L \${src} ! -type d); do - # Get destination location for symlink - filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) - filepath_dst=\${dst%/}/\${filepath_src_rel} - # Create directory for symlink - mkdir -p \${filepath_dst%/*}; - # Get path for symlink source file, then create it - # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only - # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers - symlinkpath=\$(realpath \${filepath_src}) - ln -s \${symlinkpath} \${filepath_dst}; + """ + # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation + # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + shadow_input_directory() { + src=\${1} + dst="${output_dirname}/work/\${src##*/}" + for filepath_src in \$(find -L \${src} ! -type d); do + # Get destination location for symlink + filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) + filepath_dst=\${dst%/}/\${filepath_src_rel} + # Create directory for symlink + mkdir -p \${filepath_dst%/*}; + # Get path for symlink source file, then create it + # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only + # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers + symlinkpath=\$(realpath \${filepath_src}) + ln -s \${symlinkpath} \${filepath_dst}; + done + if [[ -L "\${src##*/}" ]]; then + rm "\${src}" + fi + } + for preprocess_dir in ${preprocess_dirs}; do + shadow_input_directory \${preprocess_dir}; done - if [[ -L "\${src##*/}" ]]; then - rm "\${src}" - fi - } - for preprocess_dir in ${preprocess_dirs}; do - shadow_input_directory \${preprocess_dir}; - done - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - # Run - gridss_svprep \\ - ${args} \\ - --jvmheap "${task.memory.giga}g" \\ - --jar "${task.ext.jarPath}" \\ - --steps assemble \\ - --labels "${labels_arg}" \\ - --reference "${genome_fa}" \\ - --blacklist "${blacklist}" \\ - --workingdir "${output_dirname}/work" \\ - --assembly "${output_dirname}/sv_assemblies.bam" \\ - --threads "${task.cpus}" \\ - ${config_arg} \\ - ${bams_arg} \\ - ${bams_filtered_arg} + # Run + gridss_svprep \\ + ${args} \\ + --jvmheap "${task.memory.giga}g" \\ + --jar "${task.ext.jarPath}" \\ + --steps assemble \\ + --labels "${labels_arg}" \\ + --reference "${genome_fa}" \\ + --blacklist "${blacklist}" \\ + --workingdir "${output_dirname}/work" \\ + --assembly "${output_dirname}/sv_assemblies.bam" \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + ${bams_arg} \\ + ${bams_filtered_arg} - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ - stub: - """ - mkdir -p gridss_assemble/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir -p gridss_assemble/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 4494c361..afa6c72c 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -1,94 +1,94 @@ process CALL { - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.1--0' - input: - tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) - path gridss_config - path genome_fa - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - path blacklist + input: + tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + path blacklist - output: - tuple val(meta), path('gridss_call/sv.svprep.gridss.vcf.gz'), emit: vcf - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('gridss_call/sv.svprep.gridss.vcf.gz'), emit: vcf + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - def output_dirname = 'gridss_call' - def labels_arg = labels.join(',') - // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below - def bams_list = bams instanceof List ? bams : [bams] - def bams_arg = "--bams ${bams_list.join(',')}" - def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] - def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + def output_dirname = 'gridss_call' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = "--bams ${bams_list.join(',')}" + def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] + def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" - """ - # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation - # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present - shadow_input_directory() { - src=\${1} - dst="${output_dirname}/" - for filepath_src in \$(find -L \${src} ! -type d); do - # Get destination location for symlink - filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) - filepath_dst=\${dst%/}/\${filepath_src_rel} - # Create directory for symlink - mkdir -p \${filepath_dst%/*}; - # Get path for symlink source file, then create it - # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only - # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers - symlinkpath=\$(realpath \${filepath_src}) - ln -s \${symlinkpath} \${filepath_dst}; - done - if [[ -L "\${src##*/}" ]]; then - rm "\${src}" - fi - } - shadow_input_directory ${assemble_dir} + """ + # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation + # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + shadow_input_directory() { + src=\${1} + dst="${output_dirname}/" + for filepath_src in \$(find -L \${src} ! -type d); do + # Get destination location for symlink + filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) + filepath_dst=\${dst%/}/\${filepath_src_rel} + # Create directory for symlink + mkdir -p \${filepath_dst%/*}; + # Get path for symlink source file, then create it + # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only + # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers + symlinkpath=\$(realpath \${filepath_src}) + ln -s \${symlinkpath} \${filepath_dst}; + done + if [[ -L "\${src##*/}" ]]; then + rm "\${src}" + fi + } + shadow_input_directory ${assemble_dir} - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - # Run - gridss_svprep \\ - ${args} \\ - --jvmheap "${task.memory.giga}g" \\ - --jar "${task.ext.jarPath}" \\ - --steps call \\ - --labels "${labels_arg}" \\ - --reference "${genome_fa}" \\ - --blacklist "${blacklist}" \\ - --workingdir "${output_dirname}/work/" \\ - --assembly "${output_dirname}/sv_assemblies.bam" \\ - --output "${output_dirname}/sv.svprep.gridss.vcf.gz" \\ - --threads "${task.cpus}" \\ - ${config_arg} \\ - ${bams_arg} \\ - ${bams_filtered_arg} + # Run + gridss_svprep \\ + ${args} \\ + --jvmheap "${task.memory.giga}g" \\ + --jar "${task.ext.jarPath}" \\ + --steps call \\ + --labels "${labels_arg}" \\ + --reference "${genome_fa}" \\ + --blacklist "${blacklist}" \\ + --workingdir "${output_dirname}/work/" \\ + --assembly "${output_dirname}/sv_assemblies.bam" \\ + --output "${output_dirname}/sv.svprep.gridss.vcf.gz" \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + ${bams_arg} \\ + ${bams_filtered_arg} - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ - stub: - """ - mkdir -p gridss_call/ - cat < gridss_call/sv.svprep.gridss.vcf.gz - ##fileformat=VCFv4.1 - ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . - EOF - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir -p gridss_call/ + cat < gridss_call/sv.svprep.gridss.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 7e78ff20..4aa93f98 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -1,47 +1,47 @@ process DEPTH_ANNOTATOR { - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.1--0' - input: - tuple val(meta), path(bams), path(bais), path(vcf), val(labels) - path genome_fa - val genome_ver + input: + tuple val(meta), path(bams), path(bais), path(vcf), val(labels) + path genome_fa + val genome_ver - output: - tuple val(meta), path("*.vcf.gz"), emit: vcf - path 'versions.yml' , emit: versions + output: + tuple val(meta), path("*.vcf.gz"), emit: vcf + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' - def labels_arg = labels.join(',') - // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below - def bams_list = bams instanceof List ? bams : [bams] - def bams_arg = "${bams_list.join(',')}" + script: + def args = task.ext.args ?: '' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = "${bams_list.join(',')}" - """ - java \\ - -Xmx${task.memory.giga}g \\ - -cp "${task.ext.jarPath}" com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ - ${args} \\ - -input_vcf ${vcf} \\ - -output_vcf sv.svprep.gridss.depths.vcf.gz \\ - -samples "${labels_arg}" \\ - -bam_files "${bams_arg}" \\ - -ref_genome ${genome_fa} \\ - -ref_genome_version ${genome_ver} \\ - -threads ${task.cpus} + """ + java \\ + -Xmx${task.memory.giga}g \\ + -cp "${task.ext.jarPath}" com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ + ${args} \\ + -input_vcf ${vcf} \\ + -output_vcf sv.svprep.gridss.depths.vcf.gz \\ + -samples "${labels_arg}" \\ + -bam_files "${bams_arg}" \\ + -ref_genome ${genome_fa} \\ + -ref_genome_version ${genome_ver} \\ + -threads ${task.cpus} - cat <<-END_VERSIONS > versions.yml - "${task.process}": - svprep: \$(java -jar "${task.ext.jarPath}" 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') - END_VERSIONS - """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + svprep: \$(java -jar "${task.ext.jarPath}" 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + END_VERSIONS + """ - stub: - """ - touch sv_vcf.depths.vcf.gz - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + touch sv_vcf.depths.vcf.gz + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 995c949b..94ba3686 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -1,54 +1,54 @@ process PREPROCESS { - container 'docker.io/scwatts/svprep:1.1--0' - - input: - tuple val(meta), path(bam), path(bam_filtered) - path gridss_config - path genome_fa - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - - output: - tuple val(meta), path("gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/"), emit: preprocess_dir - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - - """ - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - - gridss_svprep \\ - ${args} \\ - --jvmheap "${task.memory.giga}g" \\ - --jar "${task.ext.jarPath}" \\ - --steps preprocess \\ - --reference "${genome_fa}" \\ - --workingdir gridss_preprocess/ \\ - --threads "${task.cpus}" \\ - ${config_arg} \\ - --labels ${meta.id} \\ - --bams ${bam} \\ - --filtered_bams ${bam_filtered} \\ - --output placeholder - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ - - stub: - """ - mkdir -p gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bam), path(bam_filtered) + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + + output: + tuple val(meta), path("gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/"), emit: preprocess_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + + """ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + gridss_svprep \\ + ${args} \\ + --jvmheap "${task.memory.giga}g" \\ + --jar "${task.ext.jarPath}" \\ + --steps preprocess \\ + --reference "${genome_fa}" \\ + --workingdir gridss_preprocess/ \\ + --threads "${task.cpus}" \\ + ${config_arg} \\ + --labels ${meta.id} \\ + --bams ${bam} \\ + --filtered_bams ${bam_filtered} \\ + --output placeholder + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 3438b217..174e3a5e 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -1,58 +1,58 @@ process SVPREP { - container 'docker.io/scwatts/svprep:1.1--0' - - input: - tuple val(meta), path(bam), path(bai), path(junctions) - path genome_fa - val genome_ver - path sv_blacklist - path known_fusions - val write_types - val calc_fragment_length - - output: - tuple val(meta), path("*.sorted.bam") , emit: bam - tuple val(meta), path("*.sv_prep.junctions.csv"), emit: junctions - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def write_types_arg = write_types ? "-write_types \'${write_types}\'" : '' - def existing_juction_file_arg = junctions ? "-existing_junction_file ${junctions}" : "" - def calc_fragment_length_arg = calc_fragment_length ? "-calc_fragment_length" : "" - - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - -sample "${meta.id}" \\ - -bam_file "${bam}" \\ - -ref_genome "${genome_fa}" \\ - -ref_genome_version "${genome_ver}" \\ - -blacklist_bed "${sv_blacklist}" \\ - -known_fusion_bed "${known_fusions}" \\ - ${write_types_arg} \\ - ${existing_juction_file_arg} \\ - ${calc_fragment_length_arg} \\ - -threads "${task.cpus}" \\ - -output_dir ./ - - samtools sort -O bam "${meta.id}.sv_prep.bam" -o "${meta.id}.sv_prep.sorted.bam" - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - sage: \$(java -jar "${task.ext.jarPath}" 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') - END_VERSIONS - """ - - stub: - """ - touch "${meta.id}.sv_prep.sorted.bam" - touch "${meta.id}.sv_prep.junctions.csv" - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bam), path(bai), path(junctions) + path genome_fa + val genome_ver + path sv_blacklist + path known_fusions + val write_types + val calc_fragment_length + + output: + tuple val(meta), path("*.sorted.bam") , emit: bam + tuple val(meta), path("*.sv_prep.junctions.csv"), emit: junctions + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def write_types_arg = write_types ? "-write_types \'${write_types}\'" : '' + def existing_juction_file_arg = junctions ? "-existing_junction_file ${junctions}" : "" + def calc_fragment_length_arg = calc_fragment_length ? "-calc_fragment_length" : "" + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + -sample "${meta.id}" \\ + -bam_file "${bam}" \\ + -ref_genome "${genome_fa}" \\ + -ref_genome_version "${genome_ver}" \\ + -blacklist_bed "${sv_blacklist}" \\ + -known_fusion_bed "${known_fusions}" \\ + ${write_types_arg} \\ + ${existing_juction_file_arg} \\ + ${calc_fragment_length_arg} \\ + -threads "${task.cpus}" \\ + -output_dir ./ + + samtools sort -O bam "${meta.id}.sv_prep.bam" -o "${meta.id}.sv_prep.sorted.bam" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sage: \$(java -jar "${task.ext.jarPath}" 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + END_VERSIONS + """ + + stub: + """ + touch "${meta.id}.sv_prep.sorted.bam" + touch "${meta.id}.sv_prep.junctions.csv" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/teal/main.nf b/modules/local/teal/main.nf index b37db994..9239797c 100644 --- a/modules/local/teal/main.nf +++ b/modules/local/teal/main.nf @@ -1,52 +1,52 @@ process TEAL { - //conda (params.enable_conda ? "bioconda::hmftools-teal=1.0.1" : null) - container 'docker.io/scwatts/teal:1.0.1--2' + //conda (params.enable_conda ? "bioconda::hmftools-teal=1.0.1" : null) + container 'docker.io/scwatts/teal:1.0.1--2' - input: - tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai), path(tumor_wgs_metrics), path(normal_wgs_metrics), path(cobalt_dir), path(purple_dir) + input: + tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai), path(tumor_wgs_metrics), path(normal_wgs_metrics), path(cobalt_dir), path(purple_dir) - output: - tuple val(meta), path('teal/'), emit: teal_dir - path 'versions.yml' , emit: versions + output: + tuple val(meta), path('teal/'), emit: teal_dir + path 'versions.yml' , emit: versions - when: - task.ext.when == null || task.ext.when + when: + task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' - def tumor_args = normal_bam ? """ - -tumor ${meta.get(['sample_name', 'tumor'])} - -tumor_bam ${tumor_bam} - -tumor_wgs_metrics ${tumor_wgs_metrics} - """ : '' - def reference_args = normal_bam ? """ - -reference ${meta.get(['sample_name', 'normal'])} - -reference_bam ${normal_bam} - -reference_wgs_metrics ${normal_wgs_metrics} - """ : '' + script: + def args = task.ext.args ?: '' + def tumor_args = normal_bam ? """ + -tumor ${meta.get(['sample_name', 'tumor'])} + -tumor_bam ${tumor_bam} + -tumor_wgs_metrics ${tumor_wgs_metrics} + """ : '' + def reference_args = normal_bam ? """ + -reference ${meta.get(['sample_name', 'normal'])} + -reference_bam ${normal_bam} + -reference_wgs_metrics ${normal_wgs_metrics} + """ : '' - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - ${args} \\ - ${tumor_args.replaceAll('\n', '')} \\ - ${reference_args.replaceAll('\n', '')} \\ - -cobalt "${cobalt_dir}" \\ - -purple "${purple_dir}" \\ - -threads "${task.cpus}" \\ - -output_dir teal/ + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar "${task.ext.jarPath}" \\ + ${args} \\ + ${tumor_args.replaceAll('\n', '')} \\ + ${reference_args.replaceAll('\n', '')} \\ + -cobalt "${cobalt_dir}" \\ + -purple "${purple_dir}" \\ + -threads "${task.cpus}" \\ + -output_dir teal/ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. - cat <<-END_VERSIONS > versions.yml - "${task.process}": - teal: 1.0.1 - END_VERSIONS - """ + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + teal: 1.0.1 + END_VERSIONS + """ - stub: - """ - mkdir -p teal/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + stub: + """ + mkdir -p teal/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 44a7e28e..4d4e8ba9 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -2,49 +2,49 @@ // symlink process VIRUSBREAKEND { - container 'docker.io/scwatts/gridss:2.13.2--3' - - input: - tuple val(meta), path(bam) - path virusbreakenddb - path gridss_config - path genome_fa - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - - output: - tuple val(meta), path("*.summary.tsv"), emit: tsv - path "*.virusbreakend.vcf" , emit: vcf - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - virusbreakend \\ - --jar ${task.ext.jarPath} \\ - --gridssargs "--jvmheap ${task.memory.giga}g" \\ - --threads ${task.cpus} \\ - --db ${virusbreakenddb.toString().replaceAll("/\$", "")}/ \\ - --output ${meta.id}.virusbreakend.vcf \\ - --reference ${genome_fa} \\ - ${bam} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ - - stub: - """ - touch ${meta.id}.virusbreakend.vcf ${meta.id}.summary.tsv - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + container 'docker.io/scwatts/gridss:2.13.2--3' + + input: + tuple val(meta), path(bam) + path virusbreakenddb + path gridss_config + path genome_fa + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + + output: + tuple val(meta), path("*.summary.tsv"), emit: tsv + path "*.virusbreakend.vcf" , emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + virusbreakend \\ + --jar ${task.ext.jarPath} \\ + --gridssargs "--jvmheap ${task.memory.giga}g" \\ + --threads ${task.cpus} \\ + --db ${virusbreakenddb.toString().replaceAll("/\$", "")}/ \\ + --output ${meta.id}.virusbreakend.vcf \\ + --reference ${genome_fa} \\ + ${bam} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + touch ${meta.id}.virusbreakend.vcf ${meta.id}.summary.tsv + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index 3ec4479e..19a6a2c9 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -1,45 +1,45 @@ process VIRUSINTERPRETER { - container 'docker.io/scwatts/virus_interpreter:1.2--0' - - input: - tuple val(meta), path(virus_tsv), path(purple_purity), path(purple_qc), path(wgs_metrics) - path taxonomy - path virus_reporting - - output: - tuple val(meta), path('virusinterpreter'), emit: virusinterpreter_dir - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - mkdir -p virusinterpreter/ - - java \\ - -Xmx${task.memory.giga}g \\ - -jar ${task.ext.jarPath} \\ - -sample_id ${meta.get(['sample_name', 'tumor'])} \\ - -purple_purity_tsv ${purple_purity} \\ - -purple_qc_file ${purple_qc} \\ - -tumor_sample_wgs_metrics_file ${wgs_metrics} \\ - -virus_breakend_tsv ${virus_tsv} \\ - -taxonomy_db_tsv ${taxonomy} \\ - -virus_reporting_db_tsv ${virus_reporting} \\ - -output_dir ./virusinterpreter/ - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - "virus interpreter": \$(java -jar "${task.ext.jarPath}" | sed -n '1s/^.*Interpreter v//p') - END_VERSIONS - """ - - stub: - """ - mkdir virusinterpreter/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ + container 'docker.io/scwatts/virus_interpreter:1.2--0' + + input: + tuple val(meta), path(virus_tsv), path(purple_purity), path(purple_qc), path(wgs_metrics) + path taxonomy + path virus_reporting + + output: + tuple val(meta), path('virusinterpreter'), emit: virusinterpreter_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + mkdir -p virusinterpreter/ + + java \\ + -Xmx${task.memory.giga}g \\ + -jar ${task.ext.jarPath} \\ + -sample_id ${meta.get(['sample_name', 'tumor'])} \\ + -purple_purity_tsv ${purple_purity} \\ + -purple_qc_file ${purple_qc} \\ + -tumor_sample_wgs_metrics_file ${wgs_metrics} \\ + -virus_breakend_tsv ${virus_tsv} \\ + -taxonomy_db_tsv ${taxonomy} \\ + -virus_reporting_db_tsv ${virus_reporting} \\ + -output_dir ./virusinterpreter/ + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + "virus interpreter": \$(java -jar "${task.ext.jarPath}" | sed -n '1s/^.*Interpreter v//p') + END_VERSIONS + """ + + stub: + """ + mkdir virusinterpreter/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/nf-core/bwa/index/main.nf b/modules/nf-core/bwa/index/main.nf deleted file mode 100644 index 6d70fc15..00000000 --- a/modules/nf-core/bwa/index/main.nf +++ /dev/null @@ -1,51 +0,0 @@ -process BWA_INDEX { - tag "$fasta" - label 'process_single' - - conda (params.enable_conda ? "bioconda::bwa=0.7.17" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/bwa:0.7.17--hed695b0_7' : - 'quay.io/biocontainers/bwa:0.7.17--hed695b0_7' }" - - input: - tuple val(meta), path(fasta) - - output: - tuple val(meta), path(bwa) , emit: index - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - """ - mkdir bwa - bwa \\ - index \\ - $args \\ - -p bwa/${fasta.baseName} \\ - $fasta - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') - END_VERSIONS - """ - - stub: - """ - mkdir bwa - - touch bwa/genome.amb - touch bwa/genome.ann - touch bwa/genome.bwt - touch bwa/genome.pac - touch bwa/genome.sa - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') - END_VERSIONS - """ -} diff --git a/modules/nf-core/bwa/index/meta.yml b/modules/nf-core/bwa/index/meta.yml deleted file mode 100644 index 2c6cfcd7..00000000 --- a/modules/nf-core/bwa/index/meta.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: bwa_index -description: Create BWA index for reference genome -keywords: - - index - - fasta - - genome - - reference -tools: - - bwa: - description: | - BWA is a software package for mapping DNA sequences against - a large reference genome, such as the human genome. - homepage: http://bio-bwa.sourceforge.net/ - documentation: http://www.htslib.org/doc/samtools.html - arxiv: arXiv:1303.3997 - licence: ["GPL-3.0-or-later"] -input: - - meta: - type: map - description: | - Groovy Map containing reference information. - e.g. [ id:'test', single_end:false ] - - fasta: - type: file - description: Input genome fasta file -output: - - meta: - type: map - description: | - Groovy Map containing reference information. - e.g. [ id:'test', single_end:false ] - - index: - type: file - description: BWA genome index files - pattern: "*.{amb,ann,bwt,pac,sa}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@drpatelh" - - "@maxulysse" diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf index cebb6e05..327d5100 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -1,11 +1,11 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { - label 'process_single' + label 'process_low' // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) + conda (params.enable_conda ? "bioconda::multiqc=1.11" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.11--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.11--pyhdfd78af_0' }" input: path versions diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py index 787bdb7b..d1390392 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -1,10 +1,9 @@ #!/usr/bin/env python +import yaml import platform from textwrap import dedent -import yaml - def _make_versions_html(versions): html = [ @@ -59,12 +58,11 @@ def _make_versions_html(versions): for process, process_versions in versions_by_process.items(): module = process.split(":")[-1] try: - if versions_by_module[module] != process_versions: - raise AssertionError( - "We assume that software versions are the same between all modules. " - "If you see this error-message it means you discovered an edge-case " - "and should open an issue in nf-core/tools. " - ) + assert versions_by_module[module] == process_versions, ( + "We assume that software versions are the same between all modules. " + "If you see this error-message it means you discovered an edge-case " + "and should open an issue in nf-core/tools. " + ) except KeyError: versions_by_module[module] = process_versions diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf deleted file mode 100644 index 05730368..00000000 --- a/modules/nf-core/fastqc/main.nf +++ /dev/null @@ -1,59 +0,0 @@ -process FASTQC { - tag "$meta.id" - label 'process_medium' - - conda (params.enable_conda ? "bioconda::fastqc=0.11.9" : null) - 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 ?: '' - // Add soft-links to original FastQs for consistent naming in pipeline - def prefix = task.ext.prefix ?: "${meta.id}" - if (meta.single_end) { - """ - [ ! -f ${prefix}.fastq.gz ] && ln -s $reads ${prefix}.fastq.gz - fastqc $args --threads $task.cpus ${prefix}.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ - } else { - """ - [ ! -f ${prefix}_1.fastq.gz ] && ln -s ${reads[0]} ${prefix}_1.fastq.gz - [ ! -f ${prefix}_2.fastq.gz ] && ln -s ${reads[1]} ${prefix}_2.fastq.gz - fastqc $args --threads $task.cpus ${prefix}_1.fastq.gz ${prefix}_2.fastq.gz - - 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 4da5bb5a..00000000 --- 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/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf b/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf deleted file mode 100644 index 327d5100..00000000 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf +++ /dev/null @@ -1,24 +0,0 @@ -process CUSTOM_DUMPSOFTWAREVERSIONS { - label 'process_low' - - // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda (params.enable_conda ? "bioconda::multiqc=1.11" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.11--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.11--pyhdfd78af_0' }" - - input: - path versions - - output: - path "software_versions.yml" , emit: yml - path "software_versions_mqc.yml", emit: mqc_yml - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - template 'dumpsoftwareversions.py' -} diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml deleted file mode 100644 index 60b546a0..00000000 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: custom_dumpsoftwareversions -description: Custom module used to dump software versions within the nf-core pipeline template -keywords: - - custom - - version -tools: - - custom: - description: Custom module used to dump software versions within the nf-core pipeline template - homepage: https://github.com/nf-core/tools - documentation: https://github.com/nf-core/tools - licence: ["MIT"] -input: - - versions: - type: file - description: YML file containing software versions - pattern: "*.yml" - -output: - - yml: - type: file - description: Standard YML file containing software versions - pattern: "software_versions.yml" - - mqc_yml: - type: file - description: MultiQC custom content YML file containing software versions - pattern: "software_versions_mqc.yml" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - -authors: - - "@drpatelh" - - "@grst" diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py deleted file mode 100644 index d1390392..00000000 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python - -import yaml -import platform -from textwrap import dedent - - -def _make_versions_html(versions): - html = [ - dedent( - """\\ - - - - - - - - - - """ - ) - ] - for process, tmp_versions in sorted(versions.items()): - html.append("") - for i, (tool, version) in enumerate(sorted(tmp_versions.items())): - html.append( - dedent( - f"""\\ - - - - - - """ - ) - ) - html.append("") - html.append("
    Process Name Software Version
    {process if (i == 0) else ''}{tool}{version}
    ") - return "\\n".join(html) - - -versions_this_module = {} -versions_this_module["${task.process}"] = { - "python": platform.python_version(), - "yaml": yaml.__version__, -} - -with open("$versions") as f: - versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module - -# aggregate versions by the module name (derived from fully-qualified process name) -versions_by_module = {} -for process, process_versions in versions_by_process.items(): - module = process.split(":")[-1] - try: - assert versions_by_module[module] == process_versions, ( - "We assume that software versions are the same between all modules. " - "If you see this error-message it means you discovered an edge-case " - "and should open an issue in nf-core/tools. " - ) - except KeyError: - versions_by_module[module] = process_versions - -versions_by_module["Workflow"] = { - "Nextflow": "$workflow.nextflow.version", - "$workflow.manifest.name": "$workflow.manifest.version", -} - -versions_mqc = { - "id": "software_versions", - "section_name": "${workflow.manifest.name} Software Versions", - "section_href": "https://github.com/${workflow.manifest.name}", - "plot_type": "html", - "description": "are collected at run time from the software output.", - "data": _make_versions_html(versions_by_module), -} - -with open("software_versions.yml", "w") as f: - yaml.dump(versions_by_module, f, default_flow_style=False) -with open("software_versions_mqc.yml", "w") as f: - yaml.dump(versions_mqc, f, default_flow_style=False) - -with open("versions.yml", "w") as f: - yaml.dump(versions_this_module, f, default_flow_style=False) diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf deleted file mode 100644 index a8159a57..00000000 --- a/modules/nf-core/multiqc/main.nf +++ /dev/null @@ -1,53 +0,0 @@ -process MULTIQC { - label 'process_single' - - conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" - - input: - path multiqc_files, stageAs: "?/*" - path(multiqc_config) - path(extra_multiqc_config) - path(multiqc_logo) - - output: - path "*multiqc_report.html", emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def config = multiqc_config ? "--config $multiqc_config" : '' - def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' - """ - multiqc \\ - --force \\ - $args \\ - $config \\ - $extra_config \\ - . - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS - """ - - stub: - """ - touch multiqc_data - touch multiqc_plots - touch multiqc_report.html - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS - """ -} diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml deleted file mode 100644 index ebc29b27..00000000 --- a/modules/nf-core/multiqc/meta.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: MultiQC -description: Aggregate results from bioinformatics analyses across many samples into a single report -keywords: - - QC - - bioinformatics tools - - Beautiful stand-alone HTML report -tools: - - multiqc: - description: | - MultiQC searches a given directory for analysis logs and compiles a HTML report. - It's a general use tool, perfect for summarising the output from numerous bioinformatics tools. - homepage: https://multiqc.info/ - documentation: https://multiqc.info/docs/ - licence: ["GPL-3.0-or-later"] - -input: - - multiqc_files: - type: file - description: | - List of reports / files recognised by MultiQC, for example the html and zip output of FastQC - - multiqc_config: - type: file - description: Optional config yml for MultiQC - pattern: "*.{yml,yaml}" - - extra_multiqc_config: - type: file - description: Second optional config yml for MultiQC. Will override common sections in multiqc_config. - pattern: "*.{yml,yaml}" - - multiqc_logo: - type: file - description: Optional logo file for MultiQC - pattern: "*.{png}" - -output: - - report: - type: file - description: MultiQC report file - pattern: "multiqc_report.html" - - data: - type: dir - description: MultiQC data dir - pattern: "multiqc_data" - - plots: - type: file - description: Plots created by MultiQC - pattern: "*_data" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@abhi18av" - - "@bunop" - - "@drpatelh" - - "@jfy133" diff --git a/modules/nf-core/modules/picard/collectwgsmetrics/main.nf b/modules/nf-core/picard/collectwgsmetrics/main.nf similarity index 100% rename from modules/nf-core/modules/picard/collectwgsmetrics/main.nf rename to modules/nf-core/picard/collectwgsmetrics/main.nf diff --git a/modules/nf-core/modules/picard/collectwgsmetrics/meta.yml b/modules/nf-core/picard/collectwgsmetrics/meta.yml similarity index 100% rename from modules/nf-core/modules/picard/collectwgsmetrics/meta.yml rename to modules/nf-core/picard/collectwgsmetrics/meta.yml diff --git a/modules/nf-core/samtools/dict/main.nf b/modules/nf-core/samtools/dict/main.nf deleted file mode 100644 index 1b8a4f17..00000000 --- a/modules/nf-core/samtools/dict/main.nf +++ /dev/null @@ -1,44 +0,0 @@ -process SAMTOOLS_DICT { - tag "$fasta" - label 'process_single' - - conda (params.enable_conda ? "bioconda::samtools=1.16.1" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : - 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" - - input: - tuple val(meta), path(fasta) - - output: - tuple val(meta), path ("*.dict"), emit: dict - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - """ - samtools \\ - dict \\ - $args \\ - $fasta \\ - > ${fasta}.dict - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - END_VERSIONS - """ - - stub: - """ - touch ${fasta}.dict - cat <<-END_VERSIONS > versions.yml - - "${task.process}": - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - END_VERSIONS - """ -} diff --git a/modules/nf-core/samtools/dict/meta.yml b/modules/nf-core/samtools/dict/meta.yml deleted file mode 100644 index e3eeccc8..00000000 --- a/modules/nf-core/samtools/dict/meta.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: samtools_dict -description: Create a sequence dictionary file from a FASTA file -keywords: - - dict - - fasta -tools: - - samtools: - description: | - SAMtools is a set of utilities for interacting with and post-processing - short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. - These files are generated as output by short read aligners like BWA. - homepage: http://www.htslib.org/ - documentation: http://www.htslib.org/doc/samtools.html - doi: 10.1093/bioinformatics/btp352 - licence: ["MIT"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - fasta: - type: file - description: FASTA file - pattern: "*.{fa,fasta}" -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - dict: - type: file - description: FASTA dictionary file - pattern: "*.{dict}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@muffato" diff --git a/modules/nf-core/samtools/faidx/main.nf b/modules/nf-core/samtools/faidx/main.nf deleted file mode 100644 index 2830963e..00000000 --- a/modules/nf-core/samtools/faidx/main.nf +++ /dev/null @@ -1,44 +0,0 @@ -process SAMTOOLS_FAIDX { - tag "$fasta" - label 'process_single' - - conda (params.enable_conda ? "bioconda::samtools=1.16.1" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : - 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" - - input: - tuple val(meta), path(fasta) - - output: - tuple val(meta), path ("*.fai"), emit: fai - tuple val(meta), path ("*.gzi"), emit: gzi, optional: true - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - """ - samtools \\ - faidx \\ - $args \\ - $fasta - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - END_VERSIONS - """ - - stub: - """ - touch ${fasta}.fai - cat <<-END_VERSIONS > versions.yml - - "${task.process}": - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - END_VERSIONS - """ -} diff --git a/modules/nf-core/samtools/faidx/meta.yml b/modules/nf-core/samtools/faidx/meta.yml deleted file mode 100644 index fe2fe9a1..00000000 --- a/modules/nf-core/samtools/faidx/meta.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: samtools_faidx -description: Index FASTA file -keywords: - - index - - fasta -tools: - - samtools: - description: | - SAMtools is a set of utilities for interacting with and post-processing - short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. - These files are generated as output by short read aligners like BWA. - homepage: http://www.htslib.org/ - documentation: http://www.htslib.org/doc/samtools.html - doi: 10.1093/bioinformatics/btp352 - licence: ["MIT"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - fasta: - type: file - description: FASTA file - pattern: "*.{fa,fasta}" -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - fai: - type: file - description: FASTA index file - pattern: "*.{fai}" - - gzi: - type: file - description: Optional gzip index file for compressed inputs - pattern: "*.gzi" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@drpatelh" - - "@ewels" - - "@phue" diff --git a/modules/nf-core/star/genomegenerate/main.nf b/modules/nf-core/star/genomegenerate/main.nf deleted file mode 100644 index 0fe88cbf..00000000 --- a/modules/nf-core/star/genomegenerate/main.nf +++ /dev/null @@ -1,96 +0,0 @@ -process STAR_GENOMEGENERATE { - tag "$fasta" - label 'process_high' - - conda (params.enable_conda ? "bioconda::star=2.7.10a bioconda::samtools=1.16.1 conda-forge::gawk=5.1.0" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:1df389393721fc66f3fd8778ad938ac711951107-0' : - 'quay.io/biocontainers/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:1df389393721fc66f3fd8778ad938ac711951107-0' }" - - input: - path fasta - path gtf - - output: - path "star" , emit: index - path "versions.yml", emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def args_list = args.tokenize() - def memory = task.memory ? "--limitGenomeGenerateRAM ${task.memory.toBytes() - 100000000}" : '' - if (args_list.contains('--genomeSAindexNbases')) { - """ - mkdir star - STAR \\ - --runMode genomeGenerate \\ - --genomeDir star/ \\ - --genomeFastaFiles $fasta \\ - --sjdbGTFfile $gtf \\ - --runThreadN $task.cpus \\ - $memory \\ - $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - star: \$(STAR --version | sed -e "s/STAR_//g") - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') - END_VERSIONS - """ - } else { - """ - samtools faidx $fasta - NUM_BASES=`gawk '{sum = sum + \$2}END{if ((log(sum)/log(2))/2 - 1 > 14) {printf "%.0f", 14} else {printf "%.0f", (log(sum)/log(2))/2 - 1}}' ${fasta}.fai` - - mkdir star - STAR \\ - --runMode genomeGenerate \\ - --genomeDir star/ \\ - --genomeFastaFiles $fasta \\ - --sjdbGTFfile $gtf \\ - --runThreadN $task.cpus \\ - --genomeSAindexNbases \$NUM_BASES \\ - $memory \\ - $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - star: \$(STAR --version | sed -e "s/STAR_//g") - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') - END_VERSIONS - """ - } - - stub: - """ - mkdir star - touch star/Genome - touch star/Log.out - touch star/SA - touch star/SAindex - touch star/chrLength.txt - touch star/chrName.txt - touch star/chrNameLength.txt - touch star/chrStart.txt - touch star/exonGeTrInfo.tab - touch star/exonInfo.tab - touch star/geneInfo.tab - touch star/genomeParameters.txt - touch star/sjdbInfo.txt - touch star/sjdbList.fromGTF.out.tab - touch star/sjdbList.out.tab - touch star/transcriptInfo.tab - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - star: \$(STAR --version | sed -e "s/STAR_//g") - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') - END_VERSIONS - """ -} diff --git a/modules/nf-core/star/genomegenerate/meta.yml b/modules/nf-core/star/genomegenerate/meta.yml deleted file mode 100644 index 8181157a..00000000 --- a/modules/nf-core/star/genomegenerate/meta.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: star_genomegenerate -description: Create index for STAR -keywords: - - index - - fasta - - genome - - reference -tools: - - star: - description: | - STAR is a software package for mapping DNA sequences against - a large reference genome, such as the human genome. - homepage: https://github.com/alexdobin/STAR - manual: https://github.com/alexdobin/STAR/blob/master/doc/STARmanual.pdf - doi: 10.1093/bioinformatics/bts635 - licence: ["MIT"] -input: - - fasta: - type: file - description: Fasta file of the reference genome - - gtf: - type: file - description: GTF file of the reference genome - -output: - - index: - type: directory - description: Folder containing the star index files - pattern: "star" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - -authors: - - "@kevinmenden" - - "@drpatelh" diff --git a/nextflow.config b/nextflow.config index e73feefd..0308950f 100644 --- a/nextflow.config +++ b/nextflow.config @@ -1,100 +1,104 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - nf-core/hmftools Nextflow config file + nf-core/oncoanalyser Nextflow config file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Default config options for all compute environments + Default config options for all compute environments ---------------------------------------------------------------------------------------- */ // Global default params, used in configs params { - // Input options - input = null - - // Pipeline run type - mode = 'full' - processes_include = '' - processes_exclude = '' - - // Reference data - ref_data_genome_fa = './reference_data/genomes/GRCh38/hg38.fa' - ref_data_genome_version = '38' - - // Reference indices - ref_data_genome_fai = './reference_data/genomes/GRCh38/samtools_index/1.12/hg38.fa.fai' - ref_data_genome_dict = './reference_data/genomes/GRCh38/samtools_index/1.12/hg38.fa.dict' - ref_data_genome_bwa_index = './reference_data/genomes/GRCh38/bwamem2_index/0.7.17-r1188' - ref_data_genome_bwa_index_image = './reference_data/genomes/GRCh38/bwamem2_index_image/0.7.17-r1188/hg38.fa.img' - ref_data_genome_gridss_index = './reference_data/genomes/GRCh38/gridss_index/2.13.2/hg38.fa.gridsscache' - - // AMBER, COBALT - ref_data_amber_loci = './reference_data/hmftools/amber/GermlineHetPon.38.vcf.gz' - ref_data_cobalt_gc_profile = './reference_data/hmftools/cobalt/GC_profile.1000bp.38.cnp' - // CUPPA - ref_data_cuppa = './reference_data/hmftools/cuppa/' - // SVPREP, GRIDSS, GRIPSS - ref_data_sv_prep_blacklist = './reference_data/hmftools/gridss/sv_prep_blacklist.38.bed' - ref_data_gridss_blacklist = './reference_data/hmftools/gridss/ENCFF356LFX.bed.gz' - ref_data_gridss_breakend_pon = './reference_data/hmftools/gridss/gridss_pon_single_breakend.38.bed.gz' - ref_data_gridss_breakpoint_pon = './reference_data/hmftools/gridss/gridss_pon_breakpoint.38.bedpe.gz' - ref_data_repeat_masker_file = './reference_data/hmftools/repeatmasker/38.fa.out.gz' - // Isofox - ref_data_rna_exp_counts = './reference_data/hmftools/isofox/read_100_exp_gc_ratios.csv' - ref_data_rna_exp_gc_ratios = './reference_data/hmftools/isofox/read_151_exp_counts.csv' - // LINX - ref_data_linx_fragile_sites = './reference_data/hmftools/linx/fragile_sites_hmf.38.csv' - ref_data_linx_lines = './reference_data/hmftools/linx/line_elements.38.csv' - // SAGE, PAVE - ref_data_sage_blacklist_bed = './reference_data/hmftools/sage/KnownBlacklist.germline.38.bed' - ref_data_sage_blacklist_vcf = './reference_data/hmftools/sage/KnownBlacklist.germline.38.vcf.gz' - ref_data_sage_coding_panel = './reference_data/hmftools/sage/ActionableCodingPanel.38.bed.gz' - ref_data_sage_high_confidence = './reference_data/hmftools/sage/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz' - ref_data_sage_known_hotspots_germline = './reference_data/hmftools/sage/KnownHotspots.germline.38.vcf.gz' - ref_data_sage_known_hotspots_somatic = './reference_data/hmftools/sage/KnownHotspots.somatic.38.vcf.gz' - ref_data_sage_pon_file = './reference_data/hmftools/sage/SageGermlinePon.98x.38.tsv.gz' - ref_data_clinvar_vcf = './reference_data/hmftools/sage/clinvar.38.vcf.gz' - // LILAC - ref_data_lilac_resource_dir = './reference_data/hmftools/lilac' - // VIRUSBreakend, Virus Interpreter - ref_data_virusbreakenddb = './reference_data/hmftools/virusbreakend/' - ref_data_virus_taxonomy = './reference_data/hmftools/virus_interpreter/taxonomy_db.tsv' - ref_data_virus_reporting = './reference_data/hmftools/virus_interpreter/virus_reporting_db.tsv' - // Misc - ref_data_purple_germline_del = './reference_data/hmftools/purple/cohort_germline_del_freq.38.csv' - ref_data_driver_gene_panel = './reference_data/hmftools/gene_panel/DriverGenePanel.38.tsv' - ref_data_ensembl_data_dir = './reference_data/hmftools/ensembl_data_cache' - ref_data_known_fusion_data = './reference_data/hmftools/known_fusions/known_fusion_data.38.csv' - ref_data_known_fusions = './reference_data/hmftools/known_fusions/known_fusions.38.bedpe' - ref_data_mappability_bed = './reference_data/hmftools/mappability/mappability_150.38.bed.gz' - - // Boilerplate options - outdir = null - tracedir = "${params.outdir}/pipeline_info" - publish_dir_mode = 'symlink' - email = null - email_on_fail = null - plaintext_email = false - monochrome_logs = false - help = false - validate_params = true - show_hidden_params = false - schema_ignore_params = 'genomes' - enable_conda = false - gridss_config = null - - // Config options - custom_config_version = 'master' - custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" - config_profile_description = null - config_profile_contact = null - config_profile_url = null - config_profile_name = null - - // Max resource options - // Defaults only, expecting to be overwritten - max_memory = '128.GB' - max_cpus = 16 - max_time = '240.h' + + // Input options + input = null + + // Pipeline run type + mode = 'full' + processes_include = '' + processes_exclude = '' + + // Genome reference data + ref_data_genome_fa = './reference_data/genomes/GRCh38/hg38.fa' + ref_data_genome_version = '38' + // Indices + ref_data_genome_fai = './reference_data/genomes/GRCh38/samtools_index/1.12/hg38.fa.fai' + ref_data_genome_dict = './reference_data/genomes/GRCh38/samtools_index/1.12/hg38.fa.dict' + ref_data_genome_bwa_index = './reference_data/genomes/GRCh38/bwamem2_index/0.7.17-r1188' + ref_data_genome_bwa_index_image = './reference_data/genomes/GRCh38/bwamem2_index_image/0.7.17-r1188/hg38.fa.img' + ref_data_genome_gridss_index = './reference_data/genomes/GRCh38/gridss_index/2.13.2/hg38.fa.gridsscache' + + // HMF tools reference data + // AMBER, COBALT + ref_data_amber_loci = './reference_data/hmftools/amber/GermlineHetPon.38.vcf.gz' + ref_data_cobalt_gc_profile = './reference_data/hmftools/cobalt/GC_profile.1000bp.38.cnp' + // CUPPA + ref_data_cuppa = './reference_data/hmftools/cuppa/' + // SVPREP, GRIDSS, GRIPSS + ref_data_sv_prep_blacklist = './reference_data/hmftools/gridss/sv_prep_blacklist.38.bed' + ref_data_gridss_blacklist = './reference_data/hmftools/gridss/ENCFF356LFX.bed.gz' + ref_data_gridss_breakend_pon = './reference_data/hmftools/gridss/gridss_pon_single_breakend.38.bed.gz' + ref_data_gridss_breakpoint_pon = './reference_data/hmftools/gridss/gridss_pon_breakpoint.38.bedpe.gz' + ref_data_repeat_masker_file = './reference_data/hmftools/repeatmasker/38.fa.out.gz' + // Isofox + ref_data_rna_exp_counts = './reference_data/hmftools/isofox/read_100_exp_gc_ratios.csv' + ref_data_rna_exp_gc_ratios = './reference_data/hmftools/isofox/read_151_exp_counts.csv' + // LINX + ref_data_linx_fragile_sites = './reference_data/hmftools/linx/fragile_sites_hmf.38.csv' + ref_data_linx_lines = './reference_data/hmftools/linx/line_elements.38.csv' + // SAGE, PAVE + ref_data_sage_blacklist_bed = './reference_data/hmftools/sage/KnownBlacklist.germline.38.bed' + ref_data_sage_blacklist_vcf = './reference_data/hmftools/sage/KnownBlacklist.germline.38.vcf.gz' + ref_data_sage_coding_panel = './reference_data/hmftools/sage/ActionableCodingPanel.38.bed.gz' + ref_data_sage_high_confidence = './reference_data/hmftools/sage/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz' + ref_data_sage_known_hotspots_germline = './reference_data/hmftools/sage/KnownHotspots.germline.38.vcf.gz' + ref_data_sage_known_hotspots_somatic = './reference_data/hmftools/sage/KnownHotspots.somatic.38.vcf.gz' + ref_data_sage_pon_file = './reference_data/hmftools/sage/SageGermlinePon.98x.38.tsv.gz' + ref_data_clinvar_vcf = './reference_data/hmftools/sage/clinvar.38.vcf.gz' + // LILAC + ref_data_lilac_resource_dir = './reference_data/hmftools/lilac' + // VIRUSBreakend, Virus Interpreter + ref_data_virusbreakenddb = './reference_data/hmftools/virusbreakend/' + ref_data_virus_taxonomy = './reference_data/hmftools/virus_interpreter/taxonomy_db.tsv' + ref_data_virus_reporting = './reference_data/hmftools/virus_interpreter/virus_reporting_db.tsv' + // Misc + ref_data_purple_germline_del = './reference_data/hmftools/purple/cohort_germline_del_freq.38.csv' + ref_data_driver_gene_panel = './reference_data/hmftools/gene_panel/DriverGenePanel.38.tsv' + ref_data_ensembl_data_dir = './reference_data/hmftools/ensembl_data_cache' + ref_data_known_fusion_data = './reference_data/hmftools/known_fusions/known_fusion_data.38.csv' + ref_data_known_fusions = './reference_data/hmftools/known_fusions/known_fusions.38.bedpe' + ref_data_mappability_bed = './reference_data/hmftools/mappability/mappability_150.38.bed.gz' + + // Boilerplate options + outdir = null + tracedir = "${params.outdir}/pipeline_info" + publish_dir_mode = 'symlink' + email = null + email_on_fail = null + plaintext_email = false + monochrome_logs = false + hook_url = null + help = false + validate_params = true + show_hidden_params = false + schema_ignore_params = 'genomes' + enable_conda = false + gridss_config = null + + // Config options + custom_config_version = 'master' + custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" + config_profile_description = null + config_profile_contact = null + config_profile_url = null + config_profile_name = null + + + // Max resource options + // Defaults only, expecting to be overwritten + max_memory = '128.GB' + max_cpus = 16 + max_time = '240.h' + } // Load base.config by default for all pipelines @@ -102,79 +106,103 @@ includeConfig 'conf/base.config' // Load nf-core custom profiles from different Institutions try { - includeConfig "${params.custom_config_base}/nfcore_custom.config" + includeConfig "${params.custom_config_base}/nfcore_custom.config" } catch (Exception e) { - System.err.println("WARNING: Could not load nf-core/config profiles: ${params.custom_config_base}/nfcore_custom.config") + System.err.println("WARNING: Could not load nf-core/config profiles: ${params.custom_config_base}/nfcore_custom.config") } -// Load nf-core/hmftools custom profiles from different institutions. +// Load nf-core/oncoanalyser custom profiles from different institutions. // Warning: Uncomment only if a pipeline-specific instititutional config already exists on nf-core/configs! // try { -// includeConfig "${params.custom_config_base}/pipeline/hmftools.config" +// includeConfig "${params.custom_config_base}/pipeline/oncoanalyser.config" // } catch (Exception e) { -// System.err.println("WARNING: Could not load nf-core/config/hmftools profiles: ${params.custom_config_base}/pipeline/hmftools.config") +// System.err.println("WARNING: Could not load nf-core/config/oncoanalyser profiles: ${params.custom_config_base}/pipeline/oncoanalyser.config") // } + profiles { - debug { process.beforeScript = 'echo $HOSTNAME' } - conda { - params.enable_conda = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - } - docker { - docker.enabled = true - docker.userEmulation = true - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - } - singularity { - singularity.enabled = true - singularity.autoMounts = true - docker.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - } - podman { - podman.enabled = true - docker.enabled = false - singularity.enabled = false - shifter.enabled = false - charliecloud.enabled = false - } - shifter { - shifter.enabled = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - charliecloud.enabled = false - } - charliecloud { - charliecloud.enabled = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - } - test { includeConfig 'conf/test.config' } - test_full { includeConfig 'conf/test_full.config' } + debug { process.beforeScript = 'echo $HOSTNAME' } + conda { + params.enable_conda = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + mamba { + params.enable_conda = true + conda.useMamba = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + docker { + docker.enabled = true + docker.userEmulation = true + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + singularity { + singularity.enabled = true + singularity.autoMounts = true + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + podman { + podman.enabled = true + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + shifter { + shifter.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false + } + charliecloud { + charliecloud.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + } + gitpod { + executor.name = 'local' + executor.cpus = 16 + executor.memory = 60.GB + } + test { includeConfig 'conf/test.config' } + test_full { includeConfig 'conf/test_full.config' } } + +//// 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. env { - PYTHONNOUSERSITE = 1 - R_PROFILE_USER = "/.Rprofile" - R_ENVIRON_USER = "/.Renviron" - JULIA_DEPOT_PATH = "/usr/local/share/julia" + PYTHONNOUSERSITE = 1 + R_PROFILE_USER = "/.Rprofile" + R_ENVIRON_USER = "/.Renviron" + JULIA_DEPOT_PATH = "/usr/local/share/julia" } // Capture exit codes from upstream processes when piping @@ -182,31 +210,31 @@ process.shell = ['/bin/bash', '-euo', 'pipefail'] def trace_timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') timeline { - enabled = true - file = "${params.tracedir}/execution_timeline_${trace_timestamp}.html" + enabled = true + file = "${params.tracedir}/execution_timeline_${trace_timestamp}.html" } report { - enabled = true - file = "${params.tracedir}/execution_report_${trace_timestamp}.html" + enabled = true + file = "${params.tracedir}/execution_report_${trace_timestamp}.html" } trace { - enabled = true - file = "${params.tracedir}/execution_trace_${trace_timestamp}.txt" + enabled = true + file = "${params.tracedir}/execution_trace_${trace_timestamp}.txt" } dag { - enabled = true - file = "${params.tracedir}/pipeline_dag_${trace_timestamp}.html" + enabled = true + file = "${params.tracedir}/pipeline_dag_${trace_timestamp}.html" } manifest { - name = 'nf-core/hmftools' - author = 'Stephen Watts' - homePage = 'https://github.com/nf-core/hmftools' - defaultBranch = 'main' - description = 'Comprehensive cancer genomics analysis pipeline' - mainScript = 'main.nf' - nextflowVersion = '!>=21.10.3' - version = '1.0dev' + name = 'nf-core/oncoanalyser' + author = 'Stephen Watts' + homePage = 'https://github.com/nf-core/oncoanalyser' + description = 'A comprehensive cancer NGS analysis and reporting pipeline' + mainScript = 'main.nf' + nextflowVersion = '!>=21.10.3' + version = '0.0.1' + doi = '' } // Load modules.config for DSL2 module specific options @@ -215,32 +243,32 @@ includeConfig 'conf/modules.config' // Function to ensure that resource requirements don't go beyond // a maximum limit def check_max(obj, type) { - if (type == 'memory') { - try { - if (obj.compareTo(params.max_memory as nextflow.util.MemoryUnit) == 1) - return params.max_memory as nextflow.util.MemoryUnit - else - return obj - } catch (all) { - println " ### ERROR ### Max memory '${params.max_memory}' is not valid! Using default value: $obj" - return obj - } - } else if (type == 'time') { - try { - if (obj.compareTo(params.max_time as nextflow.util.Duration) == 1) - return params.max_time as nextflow.util.Duration - else - return obj - } catch (all) { - println " ### ERROR ### Max time '${params.max_time}' is not valid! Using default value: $obj" - return obj - } - } else if (type == 'cpus') { - try { - return Math.min( obj, params.max_cpus as int ) - } catch (all) { - println " ### ERROR ### Max cpus '${params.max_cpus}' is not valid! Using default value: $obj" - return obj + if (type == 'memory') { + try { + if (obj.compareTo(params.max_memory as nextflow.util.MemoryUnit) == 1) + return params.max_memory as nextflow.util.MemoryUnit + else + return obj + } catch (all) { + println " ### ERROR ### Max memory '${params.max_memory}' is not valid! Using default value: $obj" + return obj + } + } else if (type == 'time') { + try { + if (obj.compareTo(params.max_time as nextflow.util.Duration) == 1) + return params.max_time as nextflow.util.Duration + else + return obj + } catch (all) { + println " ### ERROR ### Max time '${params.max_time}' is not valid! Using default value: $obj" + return obj + } + } else if (type == 'cpus') { + try { + return Math.min( obj, params.max_cpus as int ) + } catch (all) { + println " ### ERROR ### Max cpus '${params.max_cpus}' is not valid! Using default value: $obj" + return obj + } } - } } diff --git a/nextflow_schema.json b/nextflow_schema.json index f8439c67..b0de3f8d 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -1,503 +1,510 @@ { - "$schema": "http://json-schema.org/draft-07/schema", - "$id": "https://raw.githubusercontent.com/umccr/hmftools/master/nextflow_schema.json", - "title": "umccr/hmftools pipeline parameters", - "description": "Comprehensive genomic oncogenic analysis pipeline", - "type": "object", - "definitions": { - "input_output_options": { - "title": "Input/output options", - "type": "object", - "fa_icon": "fas fa-terminal", - "description": "Define where the pipeline should find input data and save output data.", - "required": ["input", "outdir"], - "properties": { - "input": { - "type": "string", - "format": "file-path", - "mimetype": "text/tsv", - "pattern": "^\\S+\\.tsv$", - "schema": "assets/schema_input.json", - "description": "Path to comma-separated file containing information about the samples in the experiment.", - "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/hmftools/usage#samplesheet-input).", - "fa_icon": "fas fa-file-tsv" - }, - "outdir": { - "type": "string", - "format": "directory-path", - "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", - "fa_icon": "fas fa-folder-open" - } - } - }, - "other_options": { - "title": "Other options", - "type": "object", - "fa_icon": "fas fa-book", - "description": "Other options specific to this pipeline.", - "properties": { - "email": { - "type": "string", - "description": "Email address for completion summary.", - "fa_icon": "fas fa-envelope", - "help_text": "Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run.", - "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" - }, - "mode": { - "type": "string", - "default": "full", - "description": "Pipeline mode to use.", - "fa_icon": "fas fa-diagram-project" - }, - "gridss_config": { - "type": "string", - "description": "Path to GRIDSS configuration file.", - "fa_icon": "fas fa-cog" + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "https://raw.githubusercontent.com/nf-core/oncoanalyser/master/nextflow_schema.json", + "title": "nf-core/oncoanalyser pipeline parameters", + "description": "A comprehensive cancer NGS analysis and reporting pipeline", + "type": "object", + "definitions": { + "input_output_options": { + "title": "Input/output options", + "type": "object", + "fa_icon": "fas fa-terminal", + "description": "Define where the pipeline should find input data and save output data.", + "required": ["input", "outdir"], + "properties": { + "input": { + "type": "string", + "format": "file-path", + "mimetype": "text/tsv", + "pattern": "^\\S+\\.tsv$", + "schema": "assets/schema_input.json", + "description": "Path to tab-separated file containing information about the samples in the experiment.", + "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a tab-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/oncoanalyser/usage#samplesheet-input).", + "fa_icon": "fas fa-file-tsv" + }, + "outdir": { + "type": "string", + "format": "directory-path", + "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", + "fa_icon": "fas fa-folder-open" + } + } + }, + "other_options": { + "title": "Other options", + "type": "object", + "fa_icon": "fas fa-book", + "description": "Other options specific to this pipeline.", + "properties": { + "email": { + "type": "string", + "description": "Email address for completion summary.", + "fa_icon": "fas fa-envelope", + "help_text": "Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run.", + "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" + }, + "mode": { + "type": "string", + "default": "full", + "description": "Pipeline mode to use.", + "fa_icon": "fas fa-diagram-project" + }, + "gridss_config": { + "type": "string", + "description": "Path to GRIDSS configuration file.", + "fa_icon": "fas fa-cog" + } + } + }, + "reference_data_options": { + "title": "Reference data options", + "type": "object", + "fa_icon": "fas fa-dna", + "description": "Reference data files and options required for the workflow.", + "properties": { + "ref_data_genome_fa": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", + "description": "Path to reference genome FASTA file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_genome_version": { + "type": "string", + "description": "Reference genome version (37 or 38).", + "fa_icon": "far fa-file-code", + "enum": ["37", "38", "38_noalt"] + }, + "ref_data_genome_fai": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.fai$", + "description": "Path to reference genome FAI file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_genome_dict": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.dict$", + "description": "Path to reference genome sequence dictionary file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_genome_bwa_index": { + "type": "string", + "format": "directory-path", + "description": "Path to directory containing reference genome BWA indices.", + "fa_icon": "far fa-file-code" + }, + "ref_data_genome_bwa_index_image": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.img$", + "description": "Path to reference genome BWA indices image file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_genome_gridss_index": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.gridsscache$", + "description": "Path to reference genome GRIDSS index file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_amber_loci": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.vcf\\.gz$", + "description": "Path to AMBER loci file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_cobalt_gc_profile": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.cnp", + "description": "Path to COBALT GC profile file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_cuppa": { + "type": "string", + "format": "directory-path", + "description": "Path to CUPPA reference file directory.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sv_prep_blacklist": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed$", + "description": "Path to SV Prep blacklist file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_gridss_blacklist": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed.gz$", + "description": "Path to GRIDSS blacklist file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_gridss_breakend_pon": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed\\.gz", + "description": "Path to GRIDSS breakend PON file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_gridss_breakpoint_pon": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bedpe\\.gz$", + "description": "Path to GRIDSS breakpoint PON file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_repeat_masker_file": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.fa(\\.out)?\\.gz$", + "description": "Path to RepeatMasker file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_rna_exp_counts": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to Isofox expected read counts file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_rna_exp_gc_ratios": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to Isofox expected GC ratios file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_linx_fragile_sites": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to LINX fragile sites file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_linx_lines": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to LINX LINEs file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_ensembl_data_dir": { + "type": "string", + "format": "directory-path", + "description": "Path to HMF Ensembl Data Cache directory.", + "fa_icon": "far fa-file-code" + }, + "ref_data_lilac_resource_dir": { + "type": "string", + "format": "directory-path", + "description": "Path to LILAC resource directory.", + "fa_icon": "far fa-folder-open" + }, + "ref_data_virusbreakenddb": { + "type": "string", + "format": "directory-path", + "description": "Path to VIRUSBreakend database directory.", + "fa_icon": "far fa-folder-open" + }, + "ref_data_virus_taxonomy": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv$", + "description": "Path to Virus Interpreter taxonomy file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_virus_reporting": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv$", + "description": "Path to Virus Interpreter reporting file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_mappability_bed": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed\\.gz$", + "description": "Path to HMF mappability file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_clinvar_vcf": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.vcf\\.gz$", + "description": "Path to HMF ClinVar file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_blacklist_vcf": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.vcf\\.gz$", + "description": "Path to HMF SAGE Known Blacklist VCF file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_blacklist_bed": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed$", + "description": "Path to HMF SAGE Known Blacklist BED file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_pon_file": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv\\.gz$", + "description": "Path to HMF SAGE Panel of Normals file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_high_confidence": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed\\.gz$", + "description": "Path to HMF distributed High Confidence regions file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_coding_panel": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed\\.gz$", + "description": "Path to somatic SAGE Coding Panel file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_known_hotspots_germline": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.vcf\\.gz$", + "description": "Path to germline SAGE Known Hotspots file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_sage_known_hotspots_somatic": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.vcf\\.gz$", + "description": "Path to somatic SAGE Known Hotspots file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_known_fusions": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bedpe$", + "description": "Path to HMF Known Fusions file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_known_fusion_data": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to HMF Known Fusions Data file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_purple_germline_del": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to HMF PURPLE Germline Cohort Deletion Frequency file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_driver_gene_panel": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv$", + "description": "Path to HMF Driver Gene Panel file.", + "fa_icon": "far fa-file-code" + } + } + }, + "institutional_config_options": { + "title": "Institutional config options", + "type": "object", + "fa_icon": "fas fa-university", + "description": "Parameters used to describe centralised config profiles. These should not be edited.", + "help_text": "The centralised nf-core configuration profiles use a handful of pipeline parameters to describe themselves. This information is then printed to the Nextflow log when you run a pipeline. You should not need to change these values when you run a pipeline.", + "properties": { + "custom_config_version": { + "type": "string", + "description": "Git commit id for Institutional configs.", + "default": "master", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "custom_config_base": { + "type": "string", + "description": "Base directory for Institutional configs.", + "default": "https://raw.githubusercontent.com/nf-core/configs/master", + "hidden": true, + "help_text": "If you're running offline, Nextflow will not be able to fetch the institutional config files from the internet. If you don't need them, then this is not a problem. If you do need them, you should download the files from the repo and tell Nextflow where to find them with this parameter.", + "fa_icon": "fas fa-users-cog" + }, + "config_profile_name": { + "type": "string", + "description": "Institutional config name.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_description": { + "type": "string", + "description": "Institutional config description.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_contact": { + "type": "string", + "description": "Institutional config contact information.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_url": { + "type": "string", + "description": "Institutional config URL link.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + } + } + }, + "max_job_request_options": { + "title": "Max job request options", + "type": "object", + "fa_icon": "fab fa-acquisitions-incorporated", + "description": "Set the top limit for requested resources for any single job.", + "help_text": "If you are running on a smaller system, a pipeline step requesting more resources than are available may cause the Nextflow to stop the run with an error. These options allow you to cap the maximum resources requested by any single job so that the pipeline will run on your system.\n\nNote that you can not _increase_ the resources requested by any job using these options. For that you will need your own configuration file. See [the nf-core website](https://nf-co.re/usage/configuration) for details.", + "properties": { + "max_cpus": { + "type": "integer", + "description": "Maximum number of CPUs that can be requested for any single job.", + "default": 16, + "fa_icon": "fas fa-microchip", + "hidden": true, + "help_text": "Use to set an upper-limit for the CPU requirement for each process. Should be an integer e.g. `--max_cpus 1`" + }, + "max_memory": { + "type": "string", + "description": "Maximum amount of memory that can be requested for any single job.", + "default": "128.GB", + "fa_icon": "fas fa-memory", + "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", + "hidden": true, + "help_text": "Use to set an upper-limit for the memory requirement for each process. Should be a string in the format integer-unit e.g. `--max_memory '8.GB'`" + }, + "max_time": { + "type": "string", + "description": "Maximum amount of time that can be requested for any single job.", + "default": "240.h", + "fa_icon": "far fa-clock", + "pattern": "^(\\d+\\.?\\s*(s|m|h|day)\\s*)+$", + "hidden": true, + "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" + } + } + }, + "generic_options": { + "title": "Generic options", + "type": "object", + "fa_icon": "fas fa-file-import", + "description": "Less common options for the pipeline, typically set in a config file.", + "help_text": "These options are common to all nf-core pipelines and allow you to customise some of the core preferences for how the pipeline runs.\n\nTypically these options would be set in a Nextflow config file loaded for all pipeline runs, such as `~/.nextflow/config`.", + "properties": { + "help": { + "type": "boolean", + "description": "Display help text.", + "fa_icon": "fas fa-question-circle", + "hidden": true + }, + "publish_dir_mode": { + "type": "string", + "default": "copy", + "description": "Method used to save pipeline results to output directory.", + "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", + "fa_icon": "fas fa-copy", + "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], + "hidden": true + }, + "email_on_fail": { + "type": "string", + "description": "Email address for completion summary, only when pipeline fails.", + "fa_icon": "fas fa-exclamation-triangle", + "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$", + "help_text": "An email address to send a summary email to when the pipeline is completed - ONLY sent if the pipeline does not exit successfully.", + "hidden": true + }, + "plaintext_email": { + "type": "boolean", + "description": "Send plain-text email instead of HTML.", + "fa_icon": "fas fa-remove-format", + "hidden": true + }, + "max_multiqc_email_size": { + "type": "string", + "description": "File size limit when attaching MultiQC reports to summary emails.", + "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", + "default": "25.MB", + "fa_icon": "fas fa-file-upload", + "hidden": true + }, + "monochrome_logs": { + "type": "boolean", + "description": "Do not use coloured log outputs.", + "fa_icon": "fas fa-palette", + "hidden": true + }, + "hook_url": { + "type": "string", + "description": "Incoming hook URL for messaging service", + "fa_icon": "fas fa-people-group", + "help_text": "Incoming hook URL for messaging service. Currently, only MS Teams is supported.", + "hidden": true + }, + "tracedir": { + "type": "string", + "description": "Directory to keep pipeline Nextflow logs and reports.", + "default": "${params.outdir}/pipeline_info", + "fa_icon": "fas fa-cogs", + "hidden": true + }, + "validate_params": { + "type": "boolean", + "description": "Boolean whether to validate parameters against the schema at runtime", + "default": true, + "fa_icon": "fas fa-check-square", + "hidden": true + }, + "show_hidden_params": { + "type": "boolean", + "fa_icon": "far fa-eye-slash", + "description": "Show all params when using `--help`", + "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." + }, + "enable_conda": { + "type": "boolean", + "description": "Run this workflow with Conda. You can also use '-profile conda' instead of providing this parameter.", + "hidden": true, + "fa_icon": "fas fa-bacon" + } + } } - } }, - "reference_data_options": { - "title": "Reference data options", - "type": "object", - "fa_icon": "fas fa-dna", - "description": "Reference data files and options required for the workflow.", - "properties": { - "ref_data_genome_fa": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", - "description": "Path to reference genome FASTA file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_genome_version": { - "type": "string", - "description": "Reference genome version (37 or 38).", - "fa_icon": "far fa-file-code", - "enum": ["37", "38", "38_noalt"] - }, - "ref_data_genome_fai": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.fai$", - "description": "Path to reference genome FAI file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_genome_dict": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.dict$", - "description": "Path to reference genome sequence dictionary file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_genome_bwa_index": { - "type": "string", - "format": "directory-path", - "description": "Path to directory containing reference genome BWA indices.", - "fa_icon": "far fa-file-code" - }, - "ref_data_genome_bwa_index_image": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.img$", - "description": "Path to reference genome BWA indices image file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_genome_gridss_index": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.gridsscache$", - "description": "Path to reference genome GRIDSS index file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_amber_loci": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to AMBER loci file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_cobalt_gc_profile": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.cnp", - "description": "Path to COBALT GC profile file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_cuppa": { - "type": "string", - "format": "directory-path", - "description": "Path to CUPPA reference file directory.", - "fa_icon": "far fa-file-code" - }, - "ref_data_sv_prep_blacklist": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed$", - "description": "Path to SV Prep blacklist file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_gridss_blacklist": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed.gz$", - "description": "Path to GRIDSS blacklist file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_gridss_breakend_pon": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz", - "description": "Path to GRIDSS breakend PON file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_gridss_breakpoint_pon": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bedpe\\.gz$", - "description": "Path to GRIDSS breakpoint PON file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_repeat_masker_file": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.fa(\\.out)?\\.gz$", - "description": "Path to RepeatMasker file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_rna_exp_counts": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to Isofox expected read counts file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_rna_exp_gc_ratios": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to Isofox expected GC ratios file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_linx_fragile_sites": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to LINX fragile sites file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_linx_lines": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to LINX LINEs file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_ensembl_data_dir": { - "type": "string", - "format": "directory-path", - "description": "Path to HMF Ensembl Data Cache directory.", - "fa_icon": "far fa-file-code" - }, - "ref_data_lilac_resource_dir": { - "type": "string", - "format": "directory-path", - "description": "Path to LILAC resource directory.", - "fa_icon": "far fa-folder-open" - }, - "ref_data_virusbreakenddb": { - "type": "string", - "format": "directory-path", - "description": "Path to VIRUSBreakend database directory.", - "fa_icon": "far fa-folder-open" - }, - "ref_data_virus_taxonomy": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to Virus Interpreter taxonomy file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_virus_reporting": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to Virus Interpreter reporting file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_mappability_bed": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to HMF mappability file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_clinvar_vcf": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to HMF ClinVar file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_sage_blacklist_vcf": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to HMF SAGE Known Blacklist VCF file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_sage_blacklist_bed": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed$", - "description": "Path to HMF SAGE Known Blacklist BED file.", - "fa_icon": "far fa-file-code" + "allOf": [ + { + "$ref": "#/definitions/input_output_options" }, - "ref_data_sage_pon_file": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv\\.gz$", - "description": "Path to HMF SAGE Panel of Normals file.", - "fa_icon": "far fa-file-code" + { + "$ref": "#/definitions/other_options" }, - "ref_data_sage_high_confidence": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to HMF distributed High Confidence regions file.", - "fa_icon": "far fa-file-code" + { + "$ref": "#/definitions/reference_data_options" }, - "ref_data_sage_coding_panel": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to somatic SAGE Coding Panel file.", - "fa_icon": "far fa-file-code" + { + "$ref": "#/definitions/institutional_config_options" }, - "ref_data_sage_known_hotspots_germline": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to germline SAGE Known Hotspots file.", - "fa_icon": "far fa-file-code" + { + "$ref": "#/definitions/max_job_request_options" }, - "ref_data_sage_known_hotspots_somatic": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to somatic SAGE Known Hotspots file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_known_fusions": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bedpe$", - "description": "Path to HMF Known Fusions file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_known_fusion_data": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to HMF Known Fusions Data file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_purple_germline_del": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to HMF PURPLE Germline Cohort Deletion Frequency file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_driver_gene_panel": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to HMF Driver Gene Panel file.", - "fa_icon": "far fa-file-code" - } - } - }, - "institutional_config_options": { - "title": "Institutional config options", - "type": "object", - "fa_icon": "fas fa-university", - "description": "Parameters used to describe centralised config profiles. These should not be edited.", - "help_text": "The centralised nf-core configuration profiles use a handful of pipeline parameters to describe themselves. This information is then printed to the Nextflow log when you run a pipeline. You should not need to change these values when you run a pipeline.", - "properties": { - "custom_config_version": { - "type": "string", - "description": "Git commit id for Institutional configs.", - "default": "master", - "hidden": true, - "fa_icon": "fas fa-users-cog" - }, - "custom_config_base": { - "type": "string", - "description": "Base directory for Institutional configs.", - "default": "https://raw.githubusercontent.com/nf-core/configs/master", - "hidden": true, - "help_text": "If you're running offline, Nextflow will not be able to fetch the institutional config files from the internet. If you don't need them, then this is not a problem. If you do need them, you should download the files from the repo and tell Nextflow where to find them with this parameter.", - "fa_icon": "fas fa-users-cog" - }, - "config_profile_name": { - "type": "string", - "description": "Institutional config name.", - "hidden": true, - "fa_icon": "fas fa-users-cog" - }, - "config_profile_description": { - "type": "string", - "description": "Institutional config description.", - "hidden": true, - "fa_icon": "fas fa-users-cog" - }, - "config_profile_contact": { - "type": "string", - "description": "Institutional config contact information.", - "hidden": true, - "fa_icon": "fas fa-users-cog" - }, - "config_profile_url": { - "type": "string", - "description": "Institutional config URL link.", - "hidden": true, - "fa_icon": "fas fa-users-cog" - } - } - }, - "max_job_request_options": { - "title": "Max job request options", - "type": "object", - "fa_icon": "fab fa-acquisitions-incorporated", - "description": "Set the top limit for requested resources for any single job.", - "help_text": "If you are running on a smaller system, a pipeline step requesting more resources than are available may cause the Nextflow to stop the run with an error. These options allow you to cap the maximum resources requested by any single job so that the pipeline will run on your system.\n\nNote that you can not _increase_ the resources requested by any job using these options. For that you will need your own configuration file. See [the nf-core website](https://nf-co.re/usage/configuration) for details.", - "properties": { - "max_cpus": { - "type": "integer", - "description": "Maximum number of CPUs that can be requested for any single job.", - "default": 16, - "fa_icon": "fas fa-microchip", - "hidden": true, - "help_text": "Use to set an upper-limit for the CPU requirement for each process. Should be an integer e.g. `--max_cpus 1`" - }, - "max_memory": { - "type": "string", - "description": "Maximum amount of memory that can be requested for any single job.", - "default": "128.GB", - "fa_icon": "fas fa-memory", - "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", - "hidden": true, - "help_text": "Use to set an upper-limit for the memory requirement for each process. Should be a string in the format integer-unit e.g. `--max_memory '8.GB'`" - }, - "max_time": { - "type": "string", - "description": "Maximum amount of time that can be requested for any single job.", - "default": "240.h", - "fa_icon": "far fa-clock", - "pattern": "^(\\d+\\.?\\s*(s|m|h|day)\\s*)+$", - "hidden": true, - "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" + { + "$ref": "#/definitions/generic_options" } - } - }, - "generic_options": { - "title": "Generic options", - "type": "object", - "fa_icon": "fas fa-file-import", - "description": "Less common options for the pipeline, typically set in a config file.", - "help_text": "These options are common to all nf-core pipelines and allow you to customise some of the core preferences for how the pipeline runs.\n\nTypically these options would be set in a Nextflow config file loaded for all pipeline runs, such as `~/.nextflow/config`.", - "properties": { - "help": { - "type": "boolean", - "description": "Display help text.", - "fa_icon": "fas fa-question-circle", - "hidden": true - }, - "publish_dir_mode": { - "type": "string", - "default": "copy", - "description": "Method used to save pipeline results to output directory.", - "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", - "fa_icon": "fas fa-copy", - "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], - "hidden": true - }, - "email_on_fail": { - "type": "string", - "description": "Email address for completion summary, only when pipeline fails.", - "fa_icon": "fas fa-exclamation-triangle", - "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$", - "help_text": "An email address to send a summary email to when the pipeline is completed - ONLY sent if the pipeline does not exit successfully.", - "hidden": true - }, - "plaintext_email": { - "type": "boolean", - "description": "Send plain-text email instead of HTML.", - "fa_icon": "fas fa-remove-format", - "hidden": true - }, - "max_multiqc_email_size": { - "type": "string", - "description": "File size limit when attaching MultiQC reports to summary emails.", - "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", - "default": "25.MB", - "fa_icon": "fas fa-file-upload", - "hidden": true - }, - "monochrome_logs": { - "type": "boolean", - "description": "Do not use coloured log outputs.", - "fa_icon": "fas fa-palette", - "hidden": true - }, - "tracedir": { - "type": "string", - "description": "Directory to keep pipeline Nextflow logs and reports.", - "default": "${params.outdir}/pipeline_info", - "fa_icon": "fas fa-cogs", - "hidden": true - }, - "validate_params": { - "type": "boolean", - "description": "Boolean whether to validate parameters against the schema at runtime", - "default": true, - "fa_icon": "fas fa-check-square", - "hidden": true - }, - "show_hidden_params": { - "type": "boolean", - "fa_icon": "far fa-eye-slash", - "description": "Show all params when using `--help`", - "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." - }, - "enable_conda": { - "type": "boolean", - "description": "Run this workflow with Conda. You can also use '-profile conda' instead of providing this parameter.", - "hidden": true, - "fa_icon": "fas fa-bacon" - } - } - } - }, - "allOf": [ - { - "$ref": "#/definitions/input_output_options" - }, - { - "$ref": "#/definitions/other_options" - }, - { - "$ref": "#/definitions/reference_data_options" - }, - { - "$ref": "#/definitions/institutional_config_options" - }, - { - "$ref": "#/definitions/max_job_request_options" - }, - { - "$ref": "#/definitions/generic_options" - } - ] + ] } diff --git a/subworkflows/local/gridss.nf b/subworkflows/local/gridss.nf index 1e9de67e..35603000 100644 --- a/subworkflows/local/gridss.nf +++ b/subworkflows/local/gridss.nf @@ -7,123 +7,123 @@ include { CALL } from '../../modules/local/gridss/call/main' include { PREPROCESS } from '../../modules/local/gridss/preprocess/main' workflow GRIDSS { - take: - ch_inputs // channel: [val(meta), bam_tumor, bam_normal] - gridss_config // file: /path/to/gridss_config (optional) - ref_data_genome_fa // file: /path/to/genome_fa - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_dict // file: /path/to/genome_dict - ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ - ref_data_genome_bwa_index_image // file: /path/to/genome_bwa_index_image - ref_data_genome_gridss_index // file: /path/to/genome_gridss_index - ref_data_gridss_blacklist // val: /path/to/gridss_blacklist + take: + ch_inputs // channel: [val(meta), bam_tumor, bam_normal] + gridss_config // file: /path/to/gridss_config (optional) + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_dict // file: /path/to/genome_dict + ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ + ref_data_genome_bwa_index_image // file: /path/to/genome_bwa_index_image + ref_data_genome_gridss_index // file: /path/to/genome_gridss_index + ref_data_gridss_blacklist // val: /path/to/gridss_blacklist - main: - // Channel for version.yml files - ch_versions = Channel.empty() + main: + // Channel for version.yml files + ch_versions = Channel.empty() - // Build a channel of individual BAMs for preprocessing - // channel: [val(meta_gridss), bam] - ch_preprocess_inputs = ch_inputs - .flatMap { meta, tbam, nbam -> - def bam_map = ['tumor': tbam, 'normal': nbam] - bam_map - .keySet() - .collect { sample_type -> - def meta_gridss = [ - id: meta.get(['sample_name', sample_type]), - sample_type: sample_type, - subject_id: meta.id, - ] - return [meta_gridss, bam_map[sample_type]] - } - } + // Build a channel of individual BAMs for preprocessing + // channel: [val(meta_gridss), bam] + ch_preprocess_inputs = ch_inputs + .flatMap { meta, tbam, nbam -> + def bam_map = ['tumor': tbam, 'normal': nbam] + bam_map + .keySet() + .collect { sample_type -> + def meta_gridss = [ + id: meta.get(['sample_name', sample_type]), + sample_type: sample_type, + subject_id: meta.id, + ] + return [meta_gridss, bam_map[sample_type]] + } + } - // Preprocess reads - PREPROCESS( - ch_preprocess_inputs, - gridss_config, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ) - ch_versions = ch_versions.mix(PREPROCESS.out.versions) + // Preprocess reads + PREPROCESS( + ch_preprocess_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ) + ch_versions = ch_versions.mix(PREPROCESS.out.versions) - // Gather BAMs and outputs from preprocessing for each tumor/normal set - // channel: [subject_id, [[val(meta_gridss), bam, preprocess_dir], ...]] - ch_bams_and_preprocess = WorkflowHmftools.group_by_meta( - ch_preprocess_inputs, - PREPROCESS.out.preprocess_dir, - ) - .map { [it[0].subject_id, it] } - .groupTuple(size: 2) + // Gather BAMs and outputs from preprocessing for each tumor/normal set + // channel: [subject_id, [[val(meta_gridss), bam, preprocess_dir], ...]] + ch_bams_and_preprocess = WorkflowOncoanalyser.group_by_meta( + ch_preprocess_inputs, + PREPROCESS.out.preprocess_dir, + ) + .map { [it[0].subject_id, it] } + .groupTuple(size: 2) - // Order and organise inputs for assembly - // channel: [val(meta_gridss), [bams], [preprocess_dirs], [labels]] - ch_assemble_inputs = ch_bams_and_preprocess - .map { subject_id, entries -> - def (tmeta, tbam, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } - def (nmeta, nbam, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } - def meta_gridss = [id: tmeta.subject_id] - return [meta_gridss, [nbam, tbam], [npreprocess, tpreprocess], [nmeta.id, tmeta.id]] - } + // Order and organise inputs for assembly + // channel: [val(meta_gridss), [bams], [preprocess_dirs], [labels]] + ch_assemble_inputs = ch_bams_and_preprocess + .map { subject_id, entries -> + def (tmeta, tbam, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } + def (nmeta, nbam, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } + def meta_gridss = [id: tmeta.subject_id] + return [meta_gridss, [nbam, tbam], [npreprocess, tpreprocess], [nmeta.id, tmeta.id]] + } - // Assemble variants - ASSEMBLE( - ch_assemble_inputs, - gridss_config, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ) - ch_versions = ch_versions.mix(ASSEMBLE.out.versions) + // Assemble variants + ASSEMBLE( + ch_assemble_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ) + ch_versions = ch_versions.mix(ASSEMBLE.out.versions) - // Prepare inputs for variant calling - // channel: [val(meta_gridss), [bams], assemble_dir, [labels]] - ch_call_inputs = WorkflowHmftools.group_by_meta( - ch_assemble_inputs, - ASSEMBLE.out.assemble_dir, - flatten: false, - ) - .map { data -> - def meta = data[0] - def (bams, preprocess_dirs, labels) = data[1] - def (assemble_dir) = data[2] - return [meta, bams, assemble_dir, labels] - } + // Prepare inputs for variant calling + // channel: [val(meta_gridss), [bams], assemble_dir, [labels]] + ch_call_inputs = WorkflowOncoanalyser.group_by_meta( + ch_assemble_inputs, + ASSEMBLE.out.assemble_dir, + flatten: false, + ) + .map { data -> + def meta = data[0] + def (bams, preprocess_dirs, labels) = data[1] + def (assemble_dir) = data[2] + return [meta, bams, assemble_dir, labels] + } - // Call variants - CALL( - ch_call_inputs, - gridss_config, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ) - ch_versions = ch_versions.mix(CALL.out.versions) + // Call variants + CALL( + ch_call_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ) + ch_versions = ch_versions.mix(CALL.out.versions) - // Reunite final VCF with the corresponding input meta object - ch_out = Channel.empty() - .concat( - ch_inputs.map { meta, tbam, nbam -> [meta.id, meta] }, - CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, - ) - .groupTuple(size: 2) - .map { id, other -> other.flatten() } + // Reunite final VCF with the corresponding input meta object + ch_out = Channel.empty() + .concat( + ch_inputs.map { meta, tbam, nbam -> [meta.id, meta] }, + CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + ) + .groupTuple(size: 2) + .map { id, other -> other.flatten() } - emit: - results = ch_out // channel: [val(meta), vcf] + emit: + results = ch_out // channel: [val(meta), vcf] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep.nf index 6b83f16d..d9870fd5 100644 --- a/subworkflows/local/gridss_svprep.nf +++ b/subworkflows/local/gridss_svprep.nf @@ -11,206 +11,206 @@ include { SVPREP as SVPREP_TUMOR } from '../../modules/local/ include { DEPTH_ANNOTATOR as SVPREP_DEPTH_ANNOTATOR } from '../../modules/local/svprep/depth_annotator/main' workflow GRIDSS_SVPREP { - take: - ch_inputs // channel: [val(meta)] - gridss_config // file: /path/to/gridss_config (optional) - ref_data_genome_fa // file: /path/to/genome_fa - ref_data_genome_version // val: genome version - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_dict // file: /path/to/genome_dict - ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ - ref_data_genome_bwa_index_image // file: /path/to/genome_bwa_index_image - ref_data_genome_gridss_index // file: /path/to/genome_gridss_index - ref_data_gridss_blacklist // val: /path/to/gridss_blacklist - ref_data_sv_prep_blacklist // file: /path/to/sv_prep_blacklist - ref_data_known_fusions // file: /path/to/known_fusions - - main: - // Channel for version.yml files - ch_versions = Channel.empty() - - // Prepare tumor sample inputs - // channel: [val(meta_svprep), bam, bai, []] - ch_svprep_tumor_inputs = ch_inputs - .map { meta -> - def meta_svprep = [id: meta.get(['sample_name', 'tumor']), meta_full: meta] - def bam = meta.get(['bam_wgs', 'tumor']) - def bai = "${bam}.bai" - return [meta_svprep, bam, bai, []] - } - - // Filter tumor BAM - SVPREP_TUMOR( - ch_svprep_tumor_inputs, - ref_data_genome_fa, - ref_data_genome_version, - ref_data_sv_prep_blacklist, - ref_data_known_fusions, - 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument switch and value - false, // -calc_fragment_length argument switch - ) - ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) - - // Prepare normal sample inputs - // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] - ch_svprep_normal_inputs = SVPREP_TUMOR.out.junctions - .map { meta_tumor_svprep, junctions_tumor -> - def meta = meta_tumor_svprep['meta_full'] - def meta_svprep = [id: meta.get(['sample_name', 'normal']), meta_full: meta] - def bam_normal = meta.get(['bam_wgs', 'normal']) - return [meta_svprep, bam_normal, "${bam_normal}.bai", junctions_tumor] - } - - SVPREP_NORMAL( - ch_svprep_normal_inputs, - ref_data_genome_fa, - ref_data_genome_version, - ref_data_sv_prep_blacklist, - ref_data_known_fusions, - false, // -write_types argument switch and value - true, // -calc_fragment_length argument switch - ) - ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) - - ch_preprocess_inputs_tumor = WorkflowHmftools.group_by_meta( - SVPREP_TUMOR.out.bam, - ch_svprep_tumor_inputs, - ) - .map { meta_svprep, bam_filtered, bam, bai -> - def meta_gridss = [ - id: meta_svprep.id, - sample_type: 'tumor', - subject_id: meta_svprep.meta_full.id, - ] - return [meta_gridss, bam, bam_filtered] - } - - ch_preprocess_inputs_normal = WorkflowHmftools.group_by_meta( - SVPREP_NORMAL.out.bam, - ch_svprep_normal_inputs, - ) - .map { meta_svprep, bam_filtered, bam, bai, junctions -> - def meta_gridss = [ - id: meta_svprep.id, - sample_type: 'normal', - subject_id: meta_svprep.meta_full.id, - ] - return [meta_gridss, bam, bam_filtered] - } - - ch_preprocess_inputs = Channel.empty() - .mix( - ch_preprocess_inputs_tumor, - ch_preprocess_inputs_normal, - ) - - // Preprocess reads - GRIDSS_PREPROCESS( - ch_preprocess_inputs, - gridss_config, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ) - ch_versions = ch_versions.mix(GRIDSS_PREPROCESS.out.versions) - - // Gather BAMs and outputs from preprocessing for each tumor/normal set - // channel: [subject_id, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] - ch_bams_and_preprocess = WorkflowHmftools.group_by_meta( - ch_preprocess_inputs, - GRIDSS_PREPROCESS.out.preprocess_dir, - ) - .map { [it[0].subject_id, it] } - .groupTuple(size: 2) - - // Order and organise inputs for assembly - // channel: [val(meta_gridss), [bams], [bams_filtered], [preprocess_dirs], [labels]] - ch_assemble_inputs = ch_bams_and_preprocess - .map { subject_id, entries -> - def (tmeta, tbam, tbam_filtered, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } - def (nmeta, nbam, nbam_filtered, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } - def meta_gridss = [id: tmeta.subject_id] - return [ - meta_gridss, - [nbam, tbam], - [nbam_filtered, tbam_filtered], - [npreprocess, tpreprocess], - [nmeta.id, tmeta.id], - ] - } - - // Assemble variants - GRIDSS_ASSEMBLE( - ch_assemble_inputs, - gridss_config, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ) - ch_versions = ch_versions.mix(GRIDSS_ASSEMBLE.out.versions) - - // Prepare inputs for variant calling - // channel: [val(meta_gridss), [bams], [bams_filtered], assemble_dir, [labels]] - ch_call_inputs = WorkflowHmftools.group_by_meta( - ch_assemble_inputs, - GRIDSS_ASSEMBLE.out.assemble_dir, - flatten: false, - ) - .map { data -> - def meta = data[0] - def (bams, bams_filtered, preprocess_dirs, labels) = data[1] - def (assemble_dir) = data[2] - return [meta, bams, bams_filtered, assemble_dir, labels] - } - - // Call variants - GRIDSS_CALL( - ch_call_inputs, - gridss_config, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ) - ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) - - // Prepare inputs for depth annotation - // channel: [val(meta), [bams], [bais], vcf, [labels]] - ch_depth_inputs = WorkflowHmftools.group_by_meta( - ch_inputs.map { meta -> [meta.id, meta] }, - GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, - ) - .map { id, meta, vcf -> - def tbam = meta.get(['bam_wgs', 'tumor']) - def nbam = meta.get(['bam_wgs', 'normal']) - return [ - meta, - [nbam, tbam], - ["${nbam}.bai", "${tbam}.bai"], - vcf, - [meta.get(['sample_name', 'normal']), meta.get(['sample_name', 'tumor'])], - ] - } - - // Add depth annotations to SVs - SVPREP_DEPTH_ANNOTATOR( - ch_depth_inputs, - ref_data_genome_fa, - ref_data_genome_version, - ) - - emit: - results = SVPREP_DEPTH_ANNOTATOR.out.vcf // channel: [val(meta), vcf] - - versions = ch_versions // channel: [versions.yml] + take: + ch_inputs // channel: [val(meta)] + gridss_config // file: /path/to/gridss_config (optional) + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_version // val: genome version + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_dict // file: /path/to/genome_dict + ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ + ref_data_genome_bwa_index_image // file: /path/to/genome_bwa_index_image + ref_data_genome_gridss_index // file: /path/to/genome_gridss_index + ref_data_gridss_blacklist // val: /path/to/gridss_blacklist + ref_data_sv_prep_blacklist // file: /path/to/sv_prep_blacklist + ref_data_known_fusions // file: /path/to/known_fusions + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Prepare tumor sample inputs + // channel: [val(meta_svprep), bam, bai, []] + ch_svprep_tumor_inputs = ch_inputs + .map { meta -> + def meta_svprep = [id: meta.get(['sample_name', 'tumor']), meta_full: meta] + def bam = meta.get(['bam_wgs', 'tumor']) + def bai = "${bam}.bai" + return [meta_svprep, bam, bai, []] + } + + // Filter tumor BAM + SVPREP_TUMOR( + ch_svprep_tumor_inputs, + ref_data_genome_fa, + ref_data_genome_version, + ref_data_sv_prep_blacklist, + ref_data_known_fusions, + 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument switch and value + false, // -calc_fragment_length argument switch + ) + ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) + + // Prepare normal sample inputs + // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] + ch_svprep_normal_inputs = SVPREP_TUMOR.out.junctions + .map { meta_tumor_svprep, junctions_tumor -> + def meta = meta_tumor_svprep['meta_full'] + def meta_svprep = [id: meta.get(['sample_name', 'normal']), meta_full: meta] + def bam_normal = meta.get(['bam_wgs', 'normal']) + return [meta_svprep, bam_normal, "${bam_normal}.bai", junctions_tumor] + } + + SVPREP_NORMAL( + ch_svprep_normal_inputs, + ref_data_genome_fa, + ref_data_genome_version, + ref_data_sv_prep_blacklist, + ref_data_known_fusions, + false, // -write_types argument switch and value + true, // -calc_fragment_length argument switch + ) + ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) + + ch_preprocess_inputs_tumor = WorkflowOncoanalyser.group_by_meta( + SVPREP_TUMOR.out.bam, + ch_svprep_tumor_inputs, + ) + .map { meta_svprep, bam_filtered, bam, bai -> + def meta_gridss = [ + id: meta_svprep.id, + sample_type: 'tumor', + subject_id: meta_svprep.meta_full.id, + ] + return [meta_gridss, bam, bam_filtered] + } + + ch_preprocess_inputs_normal = WorkflowOncoanalyser.group_by_meta( + SVPREP_NORMAL.out.bam, + ch_svprep_normal_inputs, + ) + .map { meta_svprep, bam_filtered, bam, bai, junctions -> + def meta_gridss = [ + id: meta_svprep.id, + sample_type: 'normal', + subject_id: meta_svprep.meta_full.id, + ] + return [meta_gridss, bam, bam_filtered] + } + + ch_preprocess_inputs = Channel.empty() + .mix( + ch_preprocess_inputs_tumor, + ch_preprocess_inputs_normal, + ) + + // Preprocess reads + GRIDSS_PREPROCESS( + ch_preprocess_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ) + ch_versions = ch_versions.mix(GRIDSS_PREPROCESS.out.versions) + + // Gather BAMs and outputs from preprocessing for each tumor/normal set + // channel: [subject_id, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] + ch_bams_and_preprocess = WorkflowOncoanalyser.group_by_meta( + ch_preprocess_inputs, + GRIDSS_PREPROCESS.out.preprocess_dir, + ) + .map { [it[0].subject_id, it] } + .groupTuple(size: 2) + + // Order and organise inputs for assembly + // channel: [val(meta_gridss), [bams], [bams_filtered], [preprocess_dirs], [labels]] + ch_assemble_inputs = ch_bams_and_preprocess + .map { subject_id, entries -> + def (tmeta, tbam, tbam_filtered, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } + def (nmeta, nbam, nbam_filtered, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } + def meta_gridss = [id: tmeta.subject_id] + return [ + meta_gridss, + [nbam, tbam], + [nbam_filtered, tbam_filtered], + [npreprocess, tpreprocess], + [nmeta.id, tmeta.id], + ] + } + + // Assemble variants + GRIDSS_ASSEMBLE( + ch_assemble_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ) + ch_versions = ch_versions.mix(GRIDSS_ASSEMBLE.out.versions) + + // Prepare inputs for variant calling + // channel: [val(meta_gridss), [bams], [bams_filtered], assemble_dir, [labels]] + ch_call_inputs = WorkflowOncoanalyser.group_by_meta( + ch_assemble_inputs, + GRIDSS_ASSEMBLE.out.assemble_dir, + flatten: false, + ) + .map { data -> + def meta = data[0] + def (bams, bams_filtered, preprocess_dirs, labels) = data[1] + def (assemble_dir) = data[2] + return [meta, bams, bams_filtered, assemble_dir, labels] + } + + // Call variants + GRIDSS_CALL( + ch_call_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ) + ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) + + // Prepare inputs for depth annotation + // channel: [val(meta), [bams], [bais], vcf, [labels]] + ch_depth_inputs = WorkflowOncoanalyser.group_by_meta( + ch_inputs.map { meta -> [meta.id, meta] }, + GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + ) + .map { id, meta, vcf -> + def tbam = meta.get(['bam_wgs', 'tumor']) + def nbam = meta.get(['bam_wgs', 'normal']) + return [ + meta, + [nbam, tbam], + ["${nbam}.bai", "${tbam}.bai"], + vcf, + [meta.get(['sample_name', 'normal']), meta.get(['sample_name', 'tumor'])], + ] + } + + // Add depth annotations to SVs + SVPREP_DEPTH_ANNOTATOR( + ch_depth_inputs, + ref_data_genome_fa, + ref_data_genome_version, + ) + + emit: + results = SVPREP_DEPTH_ANNOTATOR.out.vcf // channel: [val(meta), vcf] + + versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/gripss.nf b/subworkflows/local/gripss.nf index 405cc415..786bebcb 100644 --- a/subworkflows/local/gripss.nf +++ b/subworkflows/local/gripss.nf @@ -6,61 +6,61 @@ include { GRIPSS_GERMLINE } from '../../modules/local/gripss/germline/main' include { GRIPSS_SOMATIC } from '../../modules/local/gripss/somatic/main' workflow GRIPSS { - take: - ch_inputs // channel: [val(meta), gridss_vcf] - ref_data_genome_fa // file: /path/to/genome_fa - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_version // val: genome version - breakend_pon // file: /path/to/breakend_pon - breakpoint_pon // file: /path/to/breakpoint_pon - known_fusions // file: /path/to/known_fusions - repeat_masker_file // file: /path/to/repeat_masker_file + take: + ch_inputs // channel: [val(meta), gridss_vcf] + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_version // val: genome version + breakend_pon // file: /path/to/breakend_pon + breakpoint_pon // file: /path/to/breakpoint_pon + known_fusions // file: /path/to/known_fusions + repeat_masker_file // file: /path/to/repeat_masker_file - main: - // Channel for version.yml files - ch_versions = Channel.empty() + main: + // Channel for version.yml files + ch_versions = Channel.empty() - // Germline - GRIPSS_GERMLINE( - ch_inputs, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - breakend_pon, - breakpoint_pon, - known_fusions, - repeat_masker_file, - ) - ch_versions = ch_versions.mix(GRIPSS_GERMLINE.out.versions) + // Germline + GRIPSS_GERMLINE( + ch_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + breakend_pon, + breakpoint_pon, + known_fusions, + repeat_masker_file, + ) + ch_versions = ch_versions.mix(GRIPSS_GERMLINE.out.versions) - // Somatic - GRIPSS_SOMATIC( - ch_inputs, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - breakend_pon, - breakpoint_pon, - known_fusions, - repeat_masker_file, - ) - ch_versions = ch_versions.mix(GRIPSS_SOMATIC.out.versions) + // Somatic + GRIPSS_SOMATIC( + ch_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + breakend_pon, + breakpoint_pon, + known_fusions, + repeat_masker_file, + ) + ch_versions = ch_versions.mix(GRIPSS_SOMATIC.out.versions) - // Pack output - // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - ch_germline_out = WorkflowHmftools.group_by_meta( - GRIPSS_GERMLINE.out.vcf_hard, - GRIPSS_GERMLINE.out.vcf_soft, - ) - // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - ch_somatic_out = WorkflowHmftools.group_by_meta( - GRIPSS_SOMATIC.out.vcf_hard, - GRIPSS_SOMATIC.out.vcf_soft, - ) + // Pack output + // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + ch_germline_out = WorkflowOncoanalyser.group_by_meta( + GRIPSS_GERMLINE.out.vcf_hard, + GRIPSS_GERMLINE.out.vcf_soft, + ) + // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + ch_somatic_out = WorkflowOncoanalyser.group_by_meta( + GRIPSS_SOMATIC.out.vcf_hard, + GRIPSS_SOMATIC.out.vcf_soft, + ) - emit: - germline = ch_germline_out // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - somatic = ch_somatic_out // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + emit: + germline = ch_germline_out // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + somatic = ch_somatic_out // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/input_check.nf b/subworkflows/local/input_check.nf index 0aecf87f..db1795cc 100644 --- a/subworkflows/local/input_check.nf +++ b/subworkflows/local/input_check.nf @@ -5,40 +5,40 @@ include { SAMPLESHEET_CHECK } from '../../modules/local/samplesheet_check' workflow INPUT_CHECK { - take: - samplesheet // file: /path/to/samplesheet.csv + take: + samplesheet // file: /path/to/samplesheet.csv - main: - SAMPLESHEET_CHECK ( samplesheet ) - .csv - .splitCsv ( header:true, sep:',' ) - .map { create_fastq_channel(it) } - .set { reads } + main: + SAMPLESHEET_CHECK ( samplesheet ) + .csv + .splitCsv ( header:true, sep:',' ) + .map { create_fastq_channel(it) } + .set { reads } - emit: - reads // channel: [ val(meta), [ reads ] ] - versions = SAMPLESHEET_CHECK.out.versions // channel: [ versions.yml ] + emit: + reads // channel: [ val(meta), [ reads ] ] + versions = SAMPLESHEET_CHECK.out.versions // channel: [ versions.yml ] } // Function to get list of [ meta, [ fastq_1, fastq_2 ] ] def create_fastq_channel(LinkedHashMap row) { - // create meta map - def meta = [:] - meta.id = row.sample - meta.single_end = row.single_end.toBoolean() + // create meta map + def meta = [:] + meta.id = row.sample + meta.single_end = 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}" + // 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}" } - fastq_meta = [ meta, [ file(row.fastq_1), file(row.fastq_2) ] ] - } - return fastq_meta + 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) ] ] + } + return fastq_meta } diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index b50cda72..aaba4f7b 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -9,79 +9,79 @@ include { SLICE } from '../../modules/local/cust include { LILAC as LILAC_PROCESS } from '../../modules/local/lilac/main' workflow LILAC { - take: - ch_inputs_bams // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] - ch_inputs_purple_dir // channel: [val(meta), purple_dir] - ref_data_genome_fa // file: /path/to/genome_fa - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_version // val: genome version - ref_data_lilac_resource_dir // file: /path/to/lilac_resource_dir/ + take: + ch_inputs_bams // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_inputs_purple_dir // channel: [val(meta), purple_dir] + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_version // val: genome version + ref_data_lilac_resource_dir // file: /path/to/lilac_resource_dir/ - main: - // Channel for version.yml files - ch_versions = Channel.empty() + main: + // Channel for version.yml files + ch_versions = Channel.empty() - // Slice HLA regions - if (ref_data_genome_version == '38') { - slice_bed = file("${params.ref_data_lilac_resource_dir}/hla.38.alt.umccr.bed", checkIfExists: true) - } else { - slice_bed = file("${params.ref_data_lilac_resource_dir}/hla.${ref_data_genome_version}.bed", checkIfExists: true) - } - // NOTE(SW): here I remove duplicate files so that we only process each input once - // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used - // in Pipeline5, see LilacBamSlicer.java#L115 - // channel: [val(meta_lilac), bam, bai, bed] - ch_slice_inputs = WorkflowLilac.get_slice_inputs(ch_inputs_bams, slice_bed) - // channel: [val(meta_lilac), bam, bai, bed] - ch_slice_inputs = WorkflowLilac.get_unique_input_files(ch_slice_inputs) - SLICE( - ch_slice_inputs, - ) - ch_versions = ch_versions.mix(SLICE.out.versions) + // Slice HLA regions + if (ref_data_genome_version == '38') { + slice_bed = file("${params.ref_data_lilac_resource_dir}/hla.38.alt.umccr.bed", checkIfExists: true) + } else { + slice_bed = file("${params.ref_data_lilac_resource_dir}/hla.${ref_data_genome_version}.bed", checkIfExists: true) + } + // NOTE(SW): here I remove duplicate files so that we only process each input once + // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used + // in Pipeline5, see LilacBamSlicer.java#L115 + // channel: [val(meta_lilac), bam, bai, bed] + ch_slice_inputs = WorkflowLilac.get_slice_inputs(ch_inputs_bams, slice_bed) + // channel: [val(meta_lilac), bam, bai, bed] + ch_slice_inputs = WorkflowLilac.get_unique_input_files(ch_slice_inputs) + SLICE( + ch_slice_inputs, + ) + ch_versions = ch_versions.mix(SLICE.out.versions) - // Realign contigs if using hg38 (use of ALT contigs implied) - if (ref_data_genome_version == '38') { - // Align reads with chr6 - // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them - // to the three relevant HLA genes on chr6. All reads including those previously mapped to chr6 - // are realigned for consistency. - EXTRACT_AND_INDEX_CONTIG( - 'chr6', - ref_data_genome_fa, - ref_data_genome_fai, - ) - REALIGN_READS( - SLICE.out.bam, - EXTRACT_AND_INDEX_CONTIG.out.contig, - EXTRACT_AND_INDEX_CONTIG.out.bwa_indices, - ) + // Realign contigs if using hg38 (use of ALT contigs implied) + if (ref_data_genome_version == '38') { + // Align reads with chr6 + // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them + // to the three relevant HLA genes on chr6. All reads including those previously mapped to chr6 + // are realigned for consistency. + EXTRACT_AND_INDEX_CONTIG( + 'chr6', + ref_data_genome_fa, + ref_data_genome_fai, + ) + REALIGN_READS( + SLICE.out.bam, + EXTRACT_AND_INDEX_CONTIG.out.contig, + EXTRACT_AND_INDEX_CONTIG.out.bwa_indices, + ) - // Create input channel for LILAC - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] - ch_lilac_inputs = WorkflowHmftools.group_by_meta( - WorkflowLilac.sort_slices(REALIGN_READS.out.bam), - ch_inputs_purple_dir, - ) - } else { - // Create input channel for LILAC - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] - ch_lilac_inputs = WorkflowHmftools.group_by_meta( - WorkflowLilac.sort_slices(SLICE.out.bam), - ch_inputs_purple_dir, - ) - } + // Create input channel for LILAC + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] + ch_lilac_inputs = WorkflowOncoanalyser.group_by_meta( + WorkflowLilac.sort_slices(REALIGN_READS.out.bam), + ch_inputs_purple_dir, + ) + } else { + // Create input channel for LILAC + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] + ch_lilac_inputs = WorkflowOncoanalyser.group_by_meta( + WorkflowLilac.sort_slices(SLICE.out.bam), + ch_inputs_purple_dir, + ) + } - // Run LILAC - LILAC_PROCESS( - ch_lilac_inputs, - ref_data_genome_fa, - ref_data_genome_version, - ref_data_lilac_resource_dir, - ) - ch_versions = ch_versions.mix(LILAC_PROCESS.out.versions) + // Run LILAC + LILAC_PROCESS( + ch_lilac_inputs, + ref_data_genome_fa, + ref_data_genome_version, + ref_data_lilac_resource_dir, + ) + ch_versions = ch_versions.mix(LILAC_PROCESS.out.versions) - emit: - results = LILAC_PROCESS.out.lilac_dir // channel: [val(meta), lilac_dir] + emit: + results = LILAC_PROCESS.out.lilac_dir // channel: [val(meta), lilac_dir] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/linx.nf b/subworkflows/local/linx.nf index 93d07b21..cd7d42ef 100644 --- a/subworkflows/local/linx.nf +++ b/subworkflows/local/linx.nf @@ -7,59 +7,59 @@ include { LINX_SOMATIC } from '../../modules/local/linx/somatic/main' include { VISUALISER } from '../../modules/local/linx/visualiser/main' workflow LINX { - take: - ch_linx_germline_inputs // channel: [val(meta), gripss_hard_vcf] - ch_linx_somatic_inputs // channel: [val(meta), purple_dir] - ref_data_genome_version // val: genome version - ref_data_linx_fragile_sites // file: /path/to/linx_fragile_sites - ref_data_linx_lines // file: /path/to/linx_lines - ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ - ref_data_known_fusion_data // file: /path/to/known_fusion_data - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + take: + ch_linx_germline_inputs // channel: [val(meta), gripss_hard_vcf] + ch_linx_somatic_inputs // channel: [val(meta), purple_dir] + ref_data_genome_version // val: genome version + ref_data_linx_fragile_sites // file: /path/to/linx_fragile_sites + ref_data_linx_lines // file: /path/to/linx_lines + ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ + ref_data_known_fusion_data // file: /path/to/known_fusion_data + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - main: - // Channel for versions.yml files - ch_versions = Channel.empty() + main: + // Channel for versions.yml files + ch_versions = Channel.empty() - // Germline - LINX_GERMLINE( - ch_linx_germline_inputs, - ref_data_genome_version, - ref_data_linx_fragile_sites, - ref_data_linx_lines, - ref_data_ensembl_data_dir, - ref_data_driver_gene_panel, - ) - ch_versions = ch_versions.mix(LINX_GERMLINE.out.versions) + // Germline + LINX_GERMLINE( + ch_linx_germline_inputs, + ref_data_genome_version, + ref_data_linx_fragile_sites, + ref_data_linx_lines, + ref_data_ensembl_data_dir, + ref_data_driver_gene_panel, + ) + ch_versions = ch_versions.mix(LINX_GERMLINE.out.versions) - // Somatic - LINX_SOMATIC( - ch_linx_somatic_inputs, - ref_data_genome_version, - ref_data_linx_fragile_sites, - ref_data_linx_lines, - ref_data_ensembl_data_dir, - ref_data_known_fusion_data, - ref_data_driver_gene_panel, - ) - ch_versions = ch_versions.mix(LINX_SOMATIC.out.versions) + // Somatic + LINX_SOMATIC( + ch_linx_somatic_inputs, + ref_data_genome_version, + ref_data_linx_fragile_sites, + ref_data_linx_lines, + ref_data_ensembl_data_dir, + ref_data_known_fusion_data, + ref_data_driver_gene_panel, + ) + ch_versions = ch_versions.mix(LINX_SOMATIC.out.versions) - VISUALISER( - LINX_SOMATIC.out.annotation_dir, - ref_data_genome_version, - ref_data_ensembl_data_dir, - ) - ch_versions = ch_versions.mix(VISUALISER.out.versions) + VISUALISER( + LINX_SOMATIC.out.annotation_dir, + ref_data_genome_version, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(VISUALISER.out.versions) - // channel: [val(meta), linx_annotation_dir, linx_visualiser_dir] - ch_linx_somatic_out = WorkflowHmftools.group_by_meta( - LINX_SOMATIC.out.annotation_dir, - VISUALISER.out.visualiser_dir, - ) + // channel: [val(meta), linx_annotation_dir, linx_visualiser_dir] + ch_linx_somatic_out = WorkflowOncoanalyser.group_by_meta( + LINX_SOMATIC.out.annotation_dir, + VISUALISER.out.visualiser_dir, + ) - emit: - somatic = ch_linx_somatic_out // channel: [val(meta), linx_annotation_dir, linx_visualiser_dir] - germline = LINX_GERMLINE.out.annotation_dir // channel: [val(meta), linx_annotation_dir] + emit: + somatic = ch_linx_somatic_out // channel: [val(meta), linx_annotation_dir, linx_visualiser_dir] + germline = LINX_GERMLINE.out.annotation_dir // channel: [val(meta), linx_annotation_dir] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/pave.nf b/subworkflows/local/pave.nf index 01886aca..c3fd0357 100644 --- a/subworkflows/local/pave.nf +++ b/subworkflows/local/pave.nf @@ -6,55 +6,55 @@ include { PAVE_GERMLINE } from '../../modules/local/pave/germline/main' include { PAVE_SOMATIC } from '../../modules/local/pave/somatic/main' workflow PAVE { - take: - ch_inputs_germline // channel: [val(meta), sage_germline_vcf] - ch_inputs_somatic // channel: [val(meta), sage_somatic_vcf] - ref_data_genome_fa // file: /path/to/genome_fa - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_version // val: genome version - ref_data_sage_pon_file // file: /path/to/sage_pon_file - ref_data_sage_blacklist_bed // file: /path/to/sage_blacklist_bed - ref_data_sage_blacklist_vcf // file: /path/to/sage_black_list_vcf - ref_data_clinvar_vcf // file: /path/to/clinvar_vcf - ref_data_mappability_bed // file: /path/to/mappability_bed - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ + take: + ch_inputs_germline // channel: [val(meta), sage_germline_vcf] + ch_inputs_somatic // channel: [val(meta), sage_somatic_vcf] + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_version // val: genome version + ref_data_sage_pon_file // file: /path/to/sage_pon_file + ref_data_sage_blacklist_bed // file: /path/to/sage_blacklist_bed + ref_data_sage_blacklist_vcf // file: /path/to/sage_black_list_vcf + ref_data_clinvar_vcf // file: /path/to/clinvar_vcf + ref_data_mappability_bed // file: /path/to/mappability_bed + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ - main: - // Channel for version.yml files - ch_versions = Channel.empty() + main: + // Channel for version.yml files + ch_versions = Channel.empty() - // Germline - PAVE_GERMLINE( - ch_inputs_germline, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_sage_blacklist_bed, - ref_data_sage_blacklist_vcf, - ref_data_clinvar_vcf, - ref_data_mappability_bed, - ref_data_driver_gene_panel, - ref_data_ensembl_data_dir, - ) - ch_versions = ch_versions.mix(PAVE_GERMLINE.out.versions) + // Germline + PAVE_GERMLINE( + ch_inputs_germline, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_sage_blacklist_bed, + ref_data_sage_blacklist_vcf, + ref_data_clinvar_vcf, + ref_data_mappability_bed, + ref_data_driver_gene_panel, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(PAVE_GERMLINE.out.versions) - // Somatic - PAVE_SOMATIC( - ch_inputs_somatic, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_sage_pon_file, - ref_data_mappability_bed, - ref_data_driver_gene_panel, - ref_data_ensembl_data_dir, - ) - ch_versions = ch_versions.mix(PAVE_SOMATIC.out.versions) + // Somatic + PAVE_SOMATIC( + ch_inputs_somatic, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_sage_pon_file, + ref_data_mappability_bed, + ref_data_driver_gene_panel, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(PAVE_SOMATIC.out.versions) - emit: - germline = PAVE_GERMLINE.out.vcf // channel: [val(meta), pave_vcf] - somatic = PAVE_SOMATIC.out.vcf // channel: [val(meta), pave_vcf] + emit: + germline = PAVE_GERMLINE.out.vcf // channel: [val(meta), pave_vcf] + somatic = PAVE_SOMATIC.out.vcf // channel: [val(meta), pave_vcf] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/sage.nf b/subworkflows/local/sage.nf index 88351338..07fb9ad0 100644 --- a/subworkflows/local/sage.nf +++ b/subworkflows/local/sage.nf @@ -6,56 +6,56 @@ include { SAGE_GERMLINE } from '../../modules/local/sage/germline/main' include { SAGE_SOMATIC } from '../../modules/local/sage/somatic/main' workflow SAGE { - take: - ch_inputs // channel: [meta, tumor_bam, normal_bam, tumor_bai, normal_bai] - ref_data_genome_fa // file: /path/to/genome_fa - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_dict // file: /path/to/genome_dict - ref_data_genome_version // val: genome version - ref_data_sage_known_hotspots_germline // file: /path/to/sage_known_hotspots_germline - ref_data_sage_known_hotspots_somatic // file: /path/to/sage_known_hotspots_somatic - ref_data_sage_coding_panel // file: /path/to/sage_coding_panel - ref_data_sage_high_confidence // file: /path/to/sage_high_confidence - ref_data_sage_pon_file // file: /path/to/sage_pon - ref_data_mappability_bed // file: /path/to/mappability_bed - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ + take: + ch_inputs // channel: [meta, tumor_bam, normal_bam, tumor_bai, normal_bai] + ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_dict // file: /path/to/genome_dict + ref_data_genome_version // val: genome version + ref_data_sage_known_hotspots_germline // file: /path/to/sage_known_hotspots_germline + ref_data_sage_known_hotspots_somatic // file: /path/to/sage_known_hotspots_somatic + ref_data_sage_coding_panel // file: /path/to/sage_coding_panel + ref_data_sage_high_confidence // file: /path/to/sage_high_confidence + ref_data_sage_pon_file // file: /path/to/sage_pon + ref_data_mappability_bed // file: /path/to/mappability_bed + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ - main: - // Channel for version.yml files - ch_versions = Channel.empty() + main: + // Channel for version.yml files + ch_versions = Channel.empty() - // Germline - SAGE_GERMLINE( - ch_inputs, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_sage_known_hotspots_germline, - ref_data_sage_coding_panel, - ref_data_sage_high_confidence, - ref_data_ensembl_data_dir, - ) - ch_versions = ch_versions.mix(SAGE_GERMLINE.out.versions) + // Germline + SAGE_GERMLINE( + ch_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_sage_known_hotspots_germline, + ref_data_sage_coding_panel, + ref_data_sage_high_confidence, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(SAGE_GERMLINE.out.versions) - // Somatic - SAGE_SOMATIC( - ch_inputs, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_sage_known_hotspots_somatic, - ref_data_sage_coding_panel, - ref_data_sage_high_confidence, - ref_data_ensembl_data_dir, - ) - ch_versions = ch_versions.mix(SAGE_SOMATIC.out.versions) + // Somatic + SAGE_SOMATIC( + ch_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_sage_known_hotspots_somatic, + ref_data_sage_coding_panel, + ref_data_sage_high_confidence, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(SAGE_SOMATIC.out.versions) - emit: - germline = SAGE_GERMLINE.out.vcf // channel: [val(meta), sage_vcf] - somatic = SAGE_SOMATIC.out.vcf // channel: [val(meta), sage_vcf] + emit: + germline = SAGE_GERMLINE.out.vcf // channel: [val(meta), sage_vcf] + somatic = SAGE_SOMATIC.out.vcf // channel: [val(meta), sage_vcf] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/workflows/hmftools.nf b/workflows/hmftools.nf deleted file mode 100644 index 86c963c6..00000000 --- a/workflows/hmftools.nf +++ /dev/null @@ -1,735 +0,0 @@ -import Processes -import Constants - - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - VALIDATE INPUTS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) - -// Validate input parameters -WorkflowHmftools.initialise(params, workflow, log) - -// Check input path parameters to see if they exist -def checkPathParamList = [ - params.input, - // Reference genome - params.ref_data_genome_fa, - params.ref_data_genome_fai, - params.ref_data_genome_dict, - params.ref_data_genome_bwa_index, - params.ref_data_genome_bwa_index_image, - params.ref_data_genome_gridss_index, - // AMBER and COBALT - params.ref_data_amber_loci, - params.ref_data_cobalt_gc_profile, - // CUPPA - params.ref_data_cuppa, - // SVPREP, GRIDSS, GRIPSS - params.gridss_config, - params.ref_data_sv_prep_blacklist, - params.ref_data_gridss_blacklist, - params.ref_data_gridss_breakend_pon, - params.ref_data_gridss_breakpoint_pon, - params.ref_data_repeat_masker_file, - // Isofox - params.ref_data_rna_exp_counts, - params.ref_data_rna_exp_gc_ratios, - // LINX - params.ref_data_linx_fragile_sites, - params.ref_data_linx_lines, - // SAGE, PAVE - params.ref_data_sage_blacklist_bed, - params.ref_data_sage_blacklist_vcf, - params.ref_data_sage_coding_panel, - params.ref_data_sage_high_confidence, - params.ref_data_sage_known_hotspots_germline, - params.ref_data_sage_known_hotspots_somatic, - params.ref_data_sage_pon_file, - // LILAC - params.ref_data_lilac_resource_dir, - // VIRUSBreakend, Virus Interpreter - params.ref_data_virusbreakenddb, - params.ref_data_virus_taxonomy, - params.ref_data_virus_reporting, - // Other - params.ref_data_purple_germline_del, - params.ref_data_clinvar_vcf, - params.ref_data_driver_gene_panel, - params.ref_data_ensembl_data_dir, - params.ref_data_known_fusion_data, - params.ref_data_known_fusions, - params.ref_data_mappability_bed, -] - -for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } - -// Check mandatory parameters -if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - CONFIG FILES -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - IMPORT LOCAL MODULES/SUBWORKFLOWS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -// -// MODULES -// -include { CHECK_SAMPLESHEET } from '../modules/local/check_samplesheet/main' - -include { AMBER } from '../modules/local/amber/main' -include { COBALT } from '../modules/local/cobalt/main' -include { CUPPA_CLASSIFIER } from '../modules/local/cuppa/classifier/main' -include { CUPPA_VISUALISER } from '../modules/local/cuppa/visualiser/main' -include { ISOFOX } from '../modules/local/isofox/main' -include { LINX_REPORT } from '../modules/local/gpgr/linx_report/main' -include { PURPLE } from '../modules/local/purple/main' -include { TEAL } from '../modules/local/teal/main' -include { VIRUSBREAKEND } from '../modules/local/virusbreakend/main' -include { VIRUSINTERPRETER } from '../modules/local/virusinterpreter/main' - -include { PICARD_COLLECTWGSMETRICS as COLLECTWGSMETRICS } from '../modules/nf-core/modules/picard/collectwgsmetrics/main' - -// -// SUBWORKFLOWS -// -include { GRIDSS } from '../subworkflows/local/gridss' -include { GRIDSS_SVPREP } from '../subworkflows/local/gridss_svprep' -include { GRIPSS } from '../subworkflows/local/gripss' -include { LILAC } from '../subworkflows/local/lilac' -include { LINX } from '../subworkflows/local/linx' -include { PAVE } from '../subworkflows/local/pave' -include { SAGE } from '../subworkflows/local/sage' - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - IMPORT NF-CORE MODULES/SUBWORKFLOWS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -// -// MODULES -// -include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - RUN MAIN WORKFLOW -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -// Get absolute file paths -def get_file_object(path) { - return path ? file(path) : [] -} - -samplesheet = get_file_object(params.input) -// Reference genome -ref_data_genome_fa = get_file_object(params.ref_data_genome_fa) -ref_data_genome_version = params.ref_data_genome_version -ref_data_genome_fai = get_file_object(params.ref_data_genome_fai) -ref_data_genome_dict = get_file_object(params.ref_data_genome_dict) -ref_data_genome_bwa_index = get_file_object(params.ref_data_genome_bwa_index) -ref_data_genome_bwa_index_image = get_file_object(params.ref_data_genome_bwa_index_image) -ref_data_genome_gridss_index = get_file_object(params.ref_data_genome_gridss_index) -// AMBER and COBALT -ref_data_amber_loci = get_file_object(params.ref_data_amber_loci) -ref_data_cobalt_gc_profile = get_file_object(params.ref_data_cobalt_gc_profile) -// CUPPA -ref_data_cuppa = get_file_object(params.ref_data_cuppa) -// SVPREP, GRIDSS, GRIPSS -gridss_config = get_file_object(params.gridss_config) -ref_data_sv_prep_blacklist = get_file_object(params.ref_data_sv_prep_blacklist) -ref_data_gridss_blacklist = get_file_object(params.ref_data_gridss_blacklist) -ref_data_gridss_breakend_pon = get_file_object(params.ref_data_gridss_breakend_pon) -ref_data_gridss_breakpoint_pon = get_file_object(params.ref_data_gridss_breakpoint_pon) -ref_data_repeat_masker_file = get_file_object(params.ref_data_repeat_masker_file) -// Isofox -ref_data_rna_exp_counts = get_file_object(params.ref_data_rna_exp_counts) -ref_data_rna_exp_gc_ratios = get_file_object(params.ref_data_rna_exp_gc_ratios) -// LINX -ref_data_linx_fragile_sites = get_file_object(params.ref_data_linx_fragile_sites) -ref_data_linx_lines = get_file_object(params.ref_data_linx_lines) -// SAGE, PAVE -ref_data_sage_blacklist_bed = get_file_object(params.ref_data_sage_blacklist_bed) -ref_data_sage_blacklist_vcf = get_file_object(params.ref_data_sage_blacklist_vcf) -ref_data_sage_coding_panel = get_file_object(params.ref_data_sage_coding_panel) -ref_data_sage_high_confidence = get_file_object(params.ref_data_sage_high_confidence) -ref_data_sage_known_hotspots_germline = get_file_object(params.ref_data_sage_known_hotspots_germline) -ref_data_sage_known_hotspots_somatic = get_file_object(params.ref_data_sage_known_hotspots_somatic) -ref_data_sage_pon_file = get_file_object(params.ref_data_sage_pon_file) -// LILAC -ref_data_lilac_resource_dir = get_file_object(params.ref_data_lilac_resource_dir) -// VIRUSBreakend, Virus Interpreter -ref_data_virusbreakenddb = get_file_object(params.ref_data_virusbreakenddb) -ref_data_virus_taxonomy = get_file_object(params.ref_data_virus_taxonomy) -ref_data_virus_reporting = get_file_object(params.ref_data_virus_reporting) -// Other -ref_data_purple_germline_del = get_file_object(params.ref_data_purple_germline_del) -ref_data_clinvar_vcf = get_file_object(params.ref_data_clinvar_vcf) -ref_data_driver_gene_panel = get_file_object(params.ref_data_driver_gene_panel) -ref_data_ensembl_data_dir = get_file_object(params.ref_data_ensembl_data_dir) -ref_data_known_fusion_data = get_file_object(params.ref_data_known_fusion_data) -ref_data_known_fusions = get_file_object(params.ref_data_known_fusions) -ref_data_mappability_bed = get_file_object(params.ref_data_mappability_bed) - -// Set processes to run -processes = Processes.set_processes(params.mode, log) - -processes_include = Processes.get_process_list(params.processes_include, log) -processes_exclude = Processes.get_process_list(params.processes_exclude, log) -Processes.check_include_exclude_list(processes_include, processes_exclude, log) - -processes.addAll(processes_include) -processes.removeAll(processes_exclude) - -run = Constants.Process - .values() - .collectEntries { p -> [p.name().toLowerCase(), p in processes] } - - -workflow HMFTOOLS { - // Create channel for versions - // channel: [versions.yml] - ch_versions = Channel.empty() - - // Check samplesheet and prepare input channel - CHECK_SAMPLESHEET( - samplesheet, - params.mode, - ) - // channel: [val(meta)] - ch_inputs = WorkflowHmftools.prepare_inputs(CHECK_SAMPLESHEET.out, workflow.stubRun, log) - - // Set up channel with common inputs for several processes - if (run.amber || run.cobalt || run.pave || run.lilac || run.teal) { - - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] - ch_bams_and_indices = ch_inputs - .map { meta -> - def tumor_bam = meta.get(['bam_wgs', 'tumor']) - def normal_bam = meta.get(['bam_wgs', 'normal']) - [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] - } - } - - // channel (present): [val(meta)] - // channel (absent): [val(meta)] - ch_inputs_wts = ch_inputs - .branch { meta -> - def key = ['bam_wts', 'tumor'] - present: meta.containsKey(key) - return meta - absent: ! meta.containsKey(key) - return meta - } - - // - // MODULE: Run Isofox to analyse WTS data - // - ch_isofox_out = Channel.empty() - if (run.isofox) { - - // channel: [meta, tumor_bam_wts] - ch_isofox_inputs = ch_inputs_wts.present - .map { meta -> - return [meta, meta.get(['bam_wts', 'tumor'])] - } - ISOFOX( - ch_isofox_inputs, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_ensembl_data_dir, - ref_data_rna_exp_counts, - ref_data_rna_exp_gc_ratios, - ) - ch_versions = ch_versions.mix(ISOFOX.out.versions) - ch_isofox_out = ch_isofox_out.mix(ISOFOX.out.isofox_dir) - } - - // - // MODULE: Run COLLECTWGSMETRICS to generate stats required for downstream processes - // - if (run.virusinterpreter || run.teal) { - - // NOTE(SW): CUPPA only requires collectwgsmetrics for the tumor sample in - // the upstream process Virus Interpreter but TEAL currently requires - // collectwgsmetrics for both tumor and normal sample - // channel: [val(meta_cwm), bam] - ch_cwm_inputs_all = ch_inputs - .flatMap { meta -> - def sample_types = run.teal ? ['tumor', 'normal'] : ['tumor'] - return sample_types - .collect { sample_type -> - def bam = meta.get(['bam_wgs', sample_type]) - def sample_name = meta.get(['sample_name', sample_type]) - def meta_cwm = [ - id: sample_name, - sample_type: sample_type, - meta_full: meta, - ] - return [meta_cwm, bam] - } - } - - // Gather duplicate files e.g. repeated normal BAMs for multiple tumor samples - // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent - // on any process - // channel: [val(meta_cwm), bam] - ch_cwm_inputs = ch_cwm_inputs_all - .map { [it[1..-1], it[0]] } - .groupTuple() - .map { filepaths, meta_cwm -> - def (meta_fulls, sample_types) = meta_cwm - .collect { - [it.meta_full, it.sample_type] - } - .transpose() - - def sample_type = sample_types.unique(false) - assert sample_type.size() == 1 - - def id = meta_fulls.collect { it.id }.join('__') - def meta_cwm_new = [ - id: "${id}_${sample_type[0]}", - id_simple: id, - metas_full: meta_fulls, - sample_type: sample_type[0], - ] - return [meta_cwm_new, *filepaths] - } - - COLLECTWGSMETRICS( - ch_cwm_inputs, - ref_data_genome_fa, - ) - ch_versions = ch_versions.mix(COLLECTWGSMETRICS.out.versions) - - // Replicate outputs to undo unique operation - // channel (tumor): [val(meta), metrics] - // channel (normal): [val(meta), metrics] - ch_cwm_output = COLLECTWGSMETRICS.out.metrics - .flatMap { meta_cwm, metrics -> - meta_cwm.metas_full.collect { meta -> [meta, meta_cwm.sample_type, metrics] } - } - .branch { meta, sample_type, metrics -> - tumor: sample_type == 'tumor' - return [meta, metrics] - normal: sample_type == 'normal' - return [meta, metrics] - } - } - - // - // MODULE: Run AMBER to obtain b-allele frequencies - // - // channel: [val(meta), amber_dir] - ch_amber_out = Channel.empty() - if (run.amber) { - - AMBER( - ch_bams_and_indices, - ref_data_genome_version, - ref_data_amber_loci, - ) - ch_versions = ch_versions.mix(AMBER.out.versions) - ch_amber_out = ch_amber_out.mix(AMBER.out.amber_dir) - } - - // - // MODULE: Run COBALT to obtain read ratios - // - // channel: [val(meta), cobalt_dir] - ch_cobalt_out = Channel.empty() - if (run.cobalt) { - - COBALT( - ch_bams_and_indices, - ref_data_cobalt_gc_profile, - ) - ch_versions = ch_versions.mix(COBALT.out.versions) - ch_cobalt_out = ch_cobalt_out.mix(COBALT.out.cobalt_dir) - } - - // - // SUBWORKFLOW: Call structural variants with GRIDSS - // - // channel: [val(meta), gridss_vcf] - ch_gridss_out = Channel.empty() - if (run.gridss) { - - if (run.svprep) { - GRIDSS_SVPREP( - ch_inputs, - gridss_config, - ref_data_genome_fa, - ref_data_genome_version, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ref_data_sv_prep_blacklist, - ref_data_known_fusions, - ) - ch_versions = ch_versions.mix(GRIDSS_SVPREP.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP.out.results) - } else { - ch_gridss_inputs = ch_inputs - .map { meta -> - def tumor_bam = meta.get(['bam_wgs', 'tumor']) - def normal_bam = meta.get(['bam_wgs', 'normal']) - [meta, tumor_bam, normal_bam] - } - GRIDSS( - ch_gridss_inputs, - gridss_config, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ) - ch_versions = ch_versions.mix(GRIDSS.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS.out.results) - } - } - - // - // MODULE: Run GRIPSS to filter GRIDSS SV calls - // - // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - ch_gripss_germline_out = Channel.empty() - // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - ch_gripss_somatic_out = Channel.empty() - if (run.gripss) { - - GRIPSS( - run.gridss ? ch_gridss_out : WorkflowHmftools.get_input(ch_inputs, ['gridss_vcf', 'tumor_normal']), - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_gridss_breakend_pon, - ref_data_gridss_breakpoint_pon, - ref_data_known_fusions, - ref_data_repeat_masker_file, - ) - ch_versions = ch_versions.mix(GRIPSS.out.versions) - ch_gripss_germline_out = ch_gripss_germline_out.mix(GRIPSS.out.germline) - ch_gripss_somatic_out = ch_gripss_somatic_out.mix(GRIPSS.out.somatic) - } - - // - // SUBWORKFLOW: call SNV, MNV, and small INDELS with SAGE - // - // channel: [val(meta), sage_vcf] - ch_sage_germline_out = Channel.empty() - // channel: [val(meta), sage_vcf] - ch_sage_somatic_out = Channel.empty() - if (run.sage) { - - SAGE( - ch_bams_and_indices, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_sage_known_hotspots_germline, - ref_data_sage_known_hotspots_somatic, - ref_data_sage_coding_panel, - ref_data_sage_high_confidence, - ref_data_sage_pon_file, - ref_data_mappability_bed, - ref_data_driver_gene_panel, - ref_data_ensembl_data_dir, - ) - ch_versions = ch_versions.mix(SAGE.out.versions) - ch_sage_germline_out = ch_sage_germline_out.mix(SAGE.out.germline) - ch_sage_somatic_out = ch_sage_somatic_out.mix(SAGE.out.somatic) - } - - // - // SUBWORKFLOW: Annotate variants with PAVE - // - // channel: [val(meta), pave_vcf] - ch_pave_germline_out = Channel.empty() - // channel: [val(meta), pave_vcf] - ch_pave_somatic_out = Channel.empty() - if (run.pave) { - - PAVE( - run.sage ? ch_sage_germline_out : WorkflowHmftools.get_input(ch_inputs, ['sage_vcf', 'normal']), - run.sage ? ch_sage_somatic_out : WorkflowHmftools.get_input(ch_inputs, ['sage_vcf', 'tumor']), - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_sage_pon_file, - ref_data_sage_blacklist_bed, - ref_data_sage_blacklist_vcf, - ref_data_clinvar_vcf, - ref_data_mappability_bed, - ref_data_driver_gene_panel, - ref_data_ensembl_data_dir, - ) - ch_versions = ch_versions.mix(PAVE.out.versions) - ch_pave_germline_out = ch_pave_germline_out.mix(PAVE.out.germline) - ch_pave_somatic_out = ch_pave_somatic_out.mix(PAVE.out.somatic) - } - - // - // MODULE: Run PURPLE for CNV calling, purity and ploidy inference, SV recovery - // - // channel: [val(meta), purple_dir] - ch_purple_out = Channel.empty() - if (run.purple) { - - // channel: [val(meta), sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi] - if (run.gripss) { - ch_purple_inputs_sv = ch_gripss_somatic_out - } else { - ch_purple_inputs_sv = ch_inputs - .map { meta -> - def sv_hard_vcf = meta[['vcf_sv_gripss_hard', 'tumor']] - def sv_soft_vcf = meta[['vcf_sv_gripss_soft', 'tumor']] - return [ - meta, - sv_hard_vcf, - "${sv_hard_vcf}.tbi", - sv_soft_vcf, - "${sv_soft_vcf}.tbi", - ] - } - } - - // channel: [val(meta), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] - ch_purple_inputs = WorkflowHmftools.group_by_meta( - run.amber ? ch_amber_out : WorkflowHmftools.get_input(ch_inputs, ['amber_dir', 'tumor_normal']), - run.cobalt ? ch_cobalt_out : WorkflowHmftools.get_input(ch_inputs, ['cobalt_dir', 'tumor_normal']), - ch_purple_inputs_sv, - run.pave ? ch_pave_somatic_out : WorkflowHmftools.get_input(ch_inputs, ['vcf_smlv', 'tumor']), - run.pave ? ch_pave_germline_out : WorkflowHmftools.get_input(ch_inputs, ['vcf_smlv', 'normal']), - ) - - PURPLE( - ch_purple_inputs, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_cobalt_gc_profile, - ref_data_sage_known_hotspots_somatic, - ref_data_sage_known_hotspots_germline, - ref_data_driver_gene_panel, - ref_data_ensembl_data_dir, - ref_data_purple_germline_del, - ) - ch_versions = ch_versions.mix(PURPLE.out.versions) - ch_purple_out = ch_purple_out.mix(PURPLE.out.purple_dir) - } - - // - // MODULE: Run TEAL to characterise teleomeres - // - if (run.teal) { - - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, tumor_wgs_metrics, normal_wgs_metrics, cobalt_dir, purple_dir] - // NOTE(SW): assuming here that TEAL is being run in tumor/normal mode and so we expect a tumor metrics file and normal metrics file - ch_teal_inputs = WorkflowHmftools.group_by_meta( - ch_bams_and_indices, - run.collectwgsmetrics ? ch_cwm_output.tumor : WorkflowHmftools.get_input(ch_inputs, ['collectmetrics', 'tumor']), - run.collectwgsmetrics ? ch_cwm_output.normal : WorkflowHmftools.get_input(ch_inputs, ['collectmetrics', 'normal']), - run.purple ? ch_purple_out : WorkflowHmftools.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), - run.cobalt ? ch_cobalt_out : WorkflowHmftools.get_input(ch_inputs, ['cobalt_dir', 'tumor_normal']), - ) - - TEAL( - ch_teal_inputs, - ) - ch_versions = ch_versions.mix(TEAL.out.versions) - } - - // - // SUBWORKFLOW: Run LILAC for HLA typing and somatic CNV and SNV calling - // - if (run.lilac) { - - LILAC( - ch_bams_and_indices, - run.purple ? ch_purple_out : WorkflowHmftools.get_input(['purple_dir', 'tumor_normal']), - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_lilac_resource_dir, - ) - ch_versions = ch_versions.mix(LILAC.out.versions) - } - - // - // MODULE: Run VIRUSBreakend and Virus Interpreter to quantify viral content - // - // NOTE(SW): kept separate from CUPPA conditional block since we'll allow users to run this independently - ch_virusinterpreter_out = Channel.empty() - if (run.virusinterpreter) { - - // channel: [val(meta), tumor_bam] - ch_virusbreakend_inputs = ch_inputs.map { meta -> [meta, meta.get(['bam_wgs', 'tumor'])] } - - VIRUSBREAKEND( - ch_virusbreakend_inputs, - ref_data_virusbreakenddb, - gridss_config, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ) - ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) - - // channel: [val(meta), purple_purity, purple_qc] - ch_virusinterpreter_inputs_purple = ch_purple_out - .map { meta, purple_dir -> - def purple_purity = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.purity.tsv") - def purple_qc = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.qc") - return [meta, purple_purity, purple_qc] - } - - // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] - ch_virusinterpreter_inputs = WorkflowHmftools.group_by_meta( - VIRUSBREAKEND.out.tsv, - ch_virusinterpreter_inputs_purple, - ch_cwm_output.tumor, - ) - - VIRUSINTERPRETER( - ch_virusinterpreter_inputs, - ref_data_virus_taxonomy, - ref_data_virus_reporting, - ) - ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) - ch_virusinterpreter_out = ch_virusinterpreter_out.mix(VIRUSINTERPRETER.out.virusinterpreter_dir) - } - - // - // SUBWORKFLOW: Group structural variants into higher order events with LINX - // - // channel: [val(meta), linx_annotation_dir, linx_visuliaser_dir] - ch_linx_somatic_out = Channel.empty() - if (run.linx) { - - // channel: [val(meta), vcf] - ch_gripps_germline_hard = ch_gripss_germline_out.map { meta, h, hi, s, si -> [meta, h] } - - LINX( - run.gripss ? ch_gripps_germline_hard : WorkflowHmftools.get_input(ch_inputs, ['vcf_sv_gripss_hard', 'normal']), - run.purple ? ch_purple_out : WorkflowHmftools.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), - ref_data_genome_version, - ref_data_linx_fragile_sites, - ref_data_linx_lines, - ref_data_ensembl_data_dir, - ref_data_known_fusion_data, - ref_data_driver_gene_panel, - ) - ch_versions = ch_versions.mix(LINX.out.versions) - ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX.out.somatic) - - // - // MODULE: Run gpgr to generate a LINX report - // - LINX_REPORT( - ch_linx_somatic_out, - ) - ch_versions = ch_versions.mix(LINX_REPORT.out.versions) - } - - // - // MODULE: Run CUPPA predict tissue of origin - // - if (run.cuppa) { - - // channel: [val(meta), isofox_dir] - if (run.isofox) { - ch_cuppa_inputs_isofox = Channel.empty() - .mix( - ch_inputs_wts.absent.map { meta -> [meta, []] }, - ch_isofox_out, - ) - } else { - ch_cuppa_inputs_isofox = ch_inputs - .map { meta -> [meta, meta.get(['isofox_dir', 'tumor'], [])] } - } - - // channel: [val(meta), linx_somatic_annotation_dir] - ch_linx_anno = ch_linx_somatic_out.map { meta, anno_dir, vis_dir -> [meta, anno_dir]} - - // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter_dir] - // NOTE(SW): the Groovy Collection.flatten method used in - // WorkflowHmftools.group_by_meta removes optional Isofox input; flattening - // done manually below to preserve - ch_cuppa_inputs = WorkflowHmftools.group_by_meta( - ch_cuppa_inputs_isofox, - run.purple ? ch_purple_out : WorkflowHmftools.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), - run.linx ? ch_linx_anno : WorkflowHmftools.get_input(ch_inputs, ['linx_dir', 'tumor']), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowHmftools.get_input(ch_inputs, ['virusinterpreter', 'tumor']), - flatten: false, - ) - .map { data -> - def meta = data[0] - def inputs = data[1..-1].collect { it[0] } - return [meta, *inputs] - } - - CUPPA_CLASSIFIER( - ch_cuppa_inputs, - ref_data_cuppa, - ) - ch_versions = ch_versions.mix(CUPPA_CLASSIFIER.out.versions) - - CUPPA_VISUALISER( - CUPPA_CLASSIFIER.out.csv, - ) - ch_versions = ch_versions.mix(CUPPA_VISUALISER.out.versions) - } - - // - // MODULE: Pipeline reporting - // - CUSTOM_DUMPSOFTWAREVERSIONS( - ch_versions.unique().collectFile(name: 'collated_versions.yml') - ) -} - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - COMPLETION EMAIL AND SUMMARY -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -workflow.onComplete { - if (params.email || params.email_on_fail) { - NfcoreTemplate.email(workflow, params, summary_params, projectDir, log, multiqc_report) - } - NfcoreTemplate.summary(workflow, params, log) -} - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - THE END -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 50bc12ad..a55df642 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -1,3 +1,7 @@ +import Processes +import Constants + + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALIDATE INPUTS @@ -7,11 +11,60 @@ def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) // Validate input parameters -WorkflowOncoanalyser.initialise(params, log) +WorkflowOncoanalyser.initialise(params, workflow, log) -// TODO nf-core: Add all file path parameters for the pipeline to the list below // Check input path parameters to see if they exist -def checkPathParamList = [ params.input, params.multiqc_config, params.fasta ] +def checkPathParamList = [ + params.input, + // Reference genome + params.ref_data_genome_fa, + params.ref_data_genome_fai, + params.ref_data_genome_dict, + params.ref_data_genome_bwa_index, + params.ref_data_genome_bwa_index_image, + params.ref_data_genome_gridss_index, + // AMBER and COBALT + params.ref_data_amber_loci, + params.ref_data_cobalt_gc_profile, + // CUPPA + params.ref_data_cuppa, + // SVPREP, GRIDSS, GRIPSS + params.gridss_config, + params.ref_data_sv_prep_blacklist, + params.ref_data_gridss_blacklist, + params.ref_data_gridss_breakend_pon, + params.ref_data_gridss_breakpoint_pon, + params.ref_data_repeat_masker_file, + // Isofox + params.ref_data_rna_exp_counts, + params.ref_data_rna_exp_gc_ratios, + // LINX + params.ref_data_linx_fragile_sites, + params.ref_data_linx_lines, + // SAGE, PAVE + params.ref_data_sage_blacklist_bed, + params.ref_data_sage_blacklist_vcf, + params.ref_data_sage_coding_panel, + params.ref_data_sage_high_confidence, + params.ref_data_sage_known_hotspots_germline, + params.ref_data_sage_known_hotspots_somatic, + params.ref_data_sage_pon_file, + // LILAC + params.ref_data_lilac_resource_dir, + // VIRUSBreakend, Virus Interpreter + params.ref_data_virusbreakenddb, + params.ref_data_virus_taxonomy, + params.ref_data_virus_reporting, + // Other + params.ref_data_purple_germline_del, + params.ref_data_clinvar_vcf, + params.ref_data_driver_gene_panel, + params.ref_data_ensembl_data_dir, + params.ref_data_known_fusion_data, + params.ref_data_known_fusions, + params.ref_data_mappability_bed, +] + for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } // Check mandatory parameters @@ -23,10 +76,6 @@ if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input sample ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) -ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath( params.multiqc_config, checkIfExists: true ) : Channel.empty() -ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath( params.multiqc_logo, checkIfExists: true ) : Channel.empty() -ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -35,9 +84,33 @@ ch_multiqc_custom_methods_description = params.multiqc_methods_description ? fil */ // -// SUBWORKFLOW: Consisting of a mix of local and nf-core/modules +// MODULES +// +include { CHECK_SAMPLESHEET } from '../modules/local/check_samplesheet/main' + +include { AMBER } from '../modules/local/amber/main' +include { COBALT } from '../modules/local/cobalt/main' +include { CUPPA_CLASSIFIER } from '../modules/local/cuppa/classifier/main' +include { CUPPA_VISUALISER } from '../modules/local/cuppa/visualiser/main' +include { ISOFOX } from '../modules/local/isofox/main' +include { LINX_REPORT } from '../modules/local/gpgr/linx_report/main' +include { PURPLE } from '../modules/local/purple/main' +include { TEAL } from '../modules/local/teal/main' +include { VIRUSBREAKEND } from '../modules/local/virusbreakend/main' +include { VIRUSINTERPRETER } from '../modules/local/virusinterpreter/main' + +include { PICARD_COLLECTWGSMETRICS as COLLECTWGSMETRICS } from '../modules/nf-core/picard/collectwgsmetrics/main' + +// +// SUBWORKFLOWS // -include { INPUT_CHECK } from '../subworkflows/local/input_check' +include { GRIDSS } from '../subworkflows/local/gridss' +include { GRIDSS_SVPREP } from '../subworkflows/local/gridss_svprep' +include { GRIPSS } from '../subworkflows/local/gripss' +include { LILAC } from '../subworkflows/local/lilac' +include { LINX } from '../subworkflows/local/linx' +include { PAVE } from '../subworkflows/local/pave' +include { SAGE } from '../subworkflows/local/sage' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -46,10 +119,8 @@ include { INPUT_CHECK } from '../subworkflows/local/input_check' */ // -// MODULE: Installed directly from nf-core/modules +// 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' /* @@ -58,56 +129,590 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -// Info required for completion email and summary -def multiqc_report = [] +// Get absolute file paths +def get_file_object(path) { + return path ? file(path) : [] +} + +samplesheet = get_file_object(params.input) +// Reference genome +ref_data_genome_fa = get_file_object(params.ref_data_genome_fa) +ref_data_genome_version = params.ref_data_genome_version +ref_data_genome_fai = get_file_object(params.ref_data_genome_fai) +ref_data_genome_dict = get_file_object(params.ref_data_genome_dict) +ref_data_genome_bwa_index = get_file_object(params.ref_data_genome_bwa_index) +ref_data_genome_bwa_index_image = get_file_object(params.ref_data_genome_bwa_index_image) +ref_data_genome_gridss_index = get_file_object(params.ref_data_genome_gridss_index) +// AMBER and COBALT +ref_data_amber_loci = get_file_object(params.ref_data_amber_loci) +ref_data_cobalt_gc_profile = get_file_object(params.ref_data_cobalt_gc_profile) +// CUPPA +ref_data_cuppa = get_file_object(params.ref_data_cuppa) +// SVPREP, GRIDSS, GRIPSS +gridss_config = get_file_object(params.gridss_config) +ref_data_sv_prep_blacklist = get_file_object(params.ref_data_sv_prep_blacklist) +ref_data_gridss_blacklist = get_file_object(params.ref_data_gridss_blacklist) +ref_data_gridss_breakend_pon = get_file_object(params.ref_data_gridss_breakend_pon) +ref_data_gridss_breakpoint_pon = get_file_object(params.ref_data_gridss_breakpoint_pon) +ref_data_repeat_masker_file = get_file_object(params.ref_data_repeat_masker_file) +// Isofox +ref_data_rna_exp_counts = get_file_object(params.ref_data_rna_exp_counts) +ref_data_rna_exp_gc_ratios = get_file_object(params.ref_data_rna_exp_gc_ratios) +// LINX +ref_data_linx_fragile_sites = get_file_object(params.ref_data_linx_fragile_sites) +ref_data_linx_lines = get_file_object(params.ref_data_linx_lines) +// SAGE, PAVE +ref_data_sage_blacklist_bed = get_file_object(params.ref_data_sage_blacklist_bed) +ref_data_sage_blacklist_vcf = get_file_object(params.ref_data_sage_blacklist_vcf) +ref_data_sage_coding_panel = get_file_object(params.ref_data_sage_coding_panel) +ref_data_sage_high_confidence = get_file_object(params.ref_data_sage_high_confidence) +ref_data_sage_known_hotspots_germline = get_file_object(params.ref_data_sage_known_hotspots_germline) +ref_data_sage_known_hotspots_somatic = get_file_object(params.ref_data_sage_known_hotspots_somatic) +ref_data_sage_pon_file = get_file_object(params.ref_data_sage_pon_file) +// LILAC +ref_data_lilac_resource_dir = get_file_object(params.ref_data_lilac_resource_dir) +// VIRUSBreakend, Virus Interpreter +ref_data_virusbreakenddb = get_file_object(params.ref_data_virusbreakenddb) +ref_data_virus_taxonomy = get_file_object(params.ref_data_virus_taxonomy) +ref_data_virus_reporting = get_file_object(params.ref_data_virus_reporting) +// Other +ref_data_purple_germline_del = get_file_object(params.ref_data_purple_germline_del) +ref_data_clinvar_vcf = get_file_object(params.ref_data_clinvar_vcf) +ref_data_driver_gene_panel = get_file_object(params.ref_data_driver_gene_panel) +ref_data_ensembl_data_dir = get_file_object(params.ref_data_ensembl_data_dir) +ref_data_known_fusion_data = get_file_object(params.ref_data_known_fusion_data) +ref_data_known_fusions = get_file_object(params.ref_data_known_fusions) +ref_data_mappability_bed = get_file_object(params.ref_data_mappability_bed) -workflow ONCOANALYSER { +// Set processes to run +processes = Processes.set_processes(params.mode, log) + +processes_include = Processes.get_process_list(params.processes_include, log) +processes_exclude = Processes.get_process_list(params.processes_exclude, log) +Processes.check_include_exclude_list(processes_include, processes_exclude, log) + +processes.addAll(processes_include) +processes.removeAll(processes_exclude) + +run = Constants.Process + .values() + .collectEntries { p -> [p.name().toLowerCase(), p in processes] } + +workflow ONCOANALYSER { + // Create channel for versions + // channel: [versions.yml] ch_versions = Channel.empty() + // Check samplesheet and prepare input channel + CHECK_SAMPLESHEET( + samplesheet, + params.mode, + ) + // channel: [val(meta)] + ch_inputs = WorkflowOncoanalyser.prepare_inputs(CHECK_SAMPLESHEET.out, workflow.stubRun, log) + + // Set up channel with common inputs for several processes + if (run.amber || run.cobalt || run.pave || run.lilac || run.teal) { + + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_bams_and_indices = ch_inputs + .map { meta -> + def tumor_bam = meta.get(['bam_wgs', 'tumor']) + def normal_bam = meta.get(['bam_wgs', 'normal']) + [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] + } + } + + // channel (present): [val(meta)] + // channel (absent): [val(meta)] + ch_inputs_wts = ch_inputs + .branch { meta -> + def key = ['bam_wts', 'tumor'] + present: meta.containsKey(key) + return meta + absent: ! meta.containsKey(key) + return meta + } + // - // SUBWORKFLOW: Read in samplesheet, validate and stage input files + // MODULE: Run Isofox to analyse WTS data // - INPUT_CHECK ( - ch_input - ) - ch_versions = ch_versions.mix(INPUT_CHECK.out.versions) + ch_isofox_out = Channel.empty() + if (run.isofox) { + + // channel: [meta, tumor_bam_wts] + ch_isofox_inputs = ch_inputs_wts.present + .map { meta -> + return [meta, meta.get(['bam_wts', 'tumor'])] + } + ISOFOX( + ch_isofox_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_ensembl_data_dir, + ref_data_rna_exp_counts, + ref_data_rna_exp_gc_ratios, + ) + ch_versions = ch_versions.mix(ISOFOX.out.versions) + ch_isofox_out = ch_isofox_out.mix(ISOFOX.out.isofox_dir) + } // - // MODULE: Run FastQC + // MODULE: Run COLLECTWGSMETRICS to generate stats required for downstream processes // - FASTQC ( - INPUT_CHECK.out.reads - ) - ch_versions = ch_versions.mix(FASTQC.out.versions.first()) + if (run.virusinterpreter || run.teal) { - CUSTOM_DUMPSOFTWAREVERSIONS ( - ch_versions.unique().collectFile(name: 'collated_versions.yml') - ) + // NOTE(SW): CUPPA only requires collectwgsmetrics for the tumor sample in + // the upstream process Virus Interpreter but TEAL currently requires + // collectwgsmetrics for both tumor and normal sample + // channel: [val(meta_cwm), bam] + ch_cwm_inputs_all = ch_inputs + .flatMap { meta -> + def sample_types = run.teal ? ['tumor', 'normal'] : ['tumor'] + return sample_types + .collect { sample_type -> + def bam = meta.get(['bam_wgs', sample_type]) + def sample_name = meta.get(['sample_name', sample_type]) + def meta_cwm = [ + id: sample_name, + sample_type: sample_type, + meta_full: meta, + ] + return [meta_cwm, bam] + } + } + + // Gather duplicate files e.g. repeated normal BAMs for multiple tumor samples + // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent + // on any process + // channel: [val(meta_cwm), bam] + ch_cwm_inputs = ch_cwm_inputs_all + .map { [it[1..-1], it[0]] } + .groupTuple() + .map { filepaths, meta_cwm -> + def (meta_fulls, sample_types) = meta_cwm + .collect { + [it.meta_full, it.sample_type] + } + .transpose() + + def sample_type = sample_types.unique(false) + assert sample_type.size() == 1 + + def id = meta_fulls.collect { it.id }.join('__') + def meta_cwm_new = [ + id: "${id}_${sample_type[0]}", + id_simple: id, + metas_full: meta_fulls, + sample_type: sample_type[0], + ] + return [meta_cwm_new, *filepaths] + } + + COLLECTWGSMETRICS( + ch_cwm_inputs, + ref_data_genome_fa, + ) + ch_versions = ch_versions.mix(COLLECTWGSMETRICS.out.versions) + + // Replicate outputs to undo unique operation + // channel (tumor): [val(meta), metrics] + // channel (normal): [val(meta), metrics] + ch_cwm_output = COLLECTWGSMETRICS.out.metrics + .flatMap { meta_cwm, metrics -> + meta_cwm.metas_full.collect { meta -> [meta, meta_cwm.sample_type, metrics] } + } + .branch { meta, sample_type, metrics -> + tumor: sample_type == 'tumor' + return [meta, metrics] + normal: sample_type == 'normal' + return [meta, metrics] + } + } + + // + // MODULE: Run AMBER to obtain b-allele frequencies + // + // channel: [val(meta), amber_dir] + ch_amber_out = Channel.empty() + if (run.amber) { + + AMBER( + ch_bams_and_indices, + ref_data_genome_version, + ref_data_amber_loci, + ) + ch_versions = ch_versions.mix(AMBER.out.versions) + ch_amber_out = ch_amber_out.mix(AMBER.out.amber_dir) + } + + // + // MODULE: Run COBALT to obtain read ratios + // + // channel: [val(meta), cobalt_dir] + ch_cobalt_out = Channel.empty() + if (run.cobalt) { + + COBALT( + ch_bams_and_indices, + ref_data_cobalt_gc_profile, + ) + ch_versions = ch_versions.mix(COBALT.out.versions) + ch_cobalt_out = ch_cobalt_out.mix(COBALT.out.cobalt_dir) + } // - // MODULE: MultiQC + // SUBWORKFLOW: Call structural variants with GRIDSS // - workflow_summary = WorkflowOncoanalyser.paramsSummaryMultiqc(workflow, summary_params) - ch_workflow_summary = Channel.value(workflow_summary) + // channel: [val(meta), gridss_vcf] + ch_gridss_out = Channel.empty() + if (run.gridss) { - methods_description = WorkflowOncoanalyser.methodsDescriptionText(workflow, ch_multiqc_custom_methods_description) - ch_methods_description = Channel.value(methods_description) + if (run.svprep) { + GRIDSS_SVPREP( + ch_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_version, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ref_data_sv_prep_blacklist, + ref_data_known_fusions, + ) + ch_versions = ch_versions.mix(GRIDSS_SVPREP.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP.out.results) + } else { + ch_gridss_inputs = ch_inputs + .map { meta -> + def tumor_bam = meta.get(['bam_wgs', 'tumor']) + def normal_bam = meta.get(['bam_wgs', 'normal']) + [meta, tumor_bam, normal_bam] + } + GRIDSS( + ch_gridss_inputs, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blacklist, + ) + ch_versions = ch_versions.mix(GRIDSS.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS.out.results) + } + } - ch_multiqc_files = Channel.empty() - 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([])) + // + // MODULE: Run GRIPSS to filter GRIDSS SV calls + // + // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + ch_gripss_germline_out = Channel.empty() + // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + ch_gripss_somatic_out = Channel.empty() + if (run.gripss) { - MULTIQC ( - ch_multiqc_files.collect(), - ch_multiqc_config.collect().ifEmpty([]), - ch_multiqc_custom_config.collect().ifEmpty([]), - ch_multiqc_logo.collect().ifEmpty([]) + GRIPSS( + run.gridss ? ch_gridss_out : WorkflowOncoanalyser.get_input(ch_inputs, ['gridss_vcf', 'tumor_normal']), + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_gridss_breakend_pon, + ref_data_gridss_breakpoint_pon, + ref_data_known_fusions, + ref_data_repeat_masker_file, + ) + ch_versions = ch_versions.mix(GRIPSS.out.versions) + ch_gripss_germline_out = ch_gripss_germline_out.mix(GRIPSS.out.germline) + ch_gripss_somatic_out = ch_gripss_somatic_out.mix(GRIPSS.out.somatic) + } + + // + // SUBWORKFLOW: call SNV, MNV, and small INDELS with SAGE + // + // channel: [val(meta), sage_vcf] + ch_sage_germline_out = Channel.empty() + // channel: [val(meta), sage_vcf] + ch_sage_somatic_out = Channel.empty() + if (run.sage) { + + SAGE( + ch_bams_and_indices, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_sage_known_hotspots_germline, + ref_data_sage_known_hotspots_somatic, + ref_data_sage_coding_panel, + ref_data_sage_high_confidence, + ref_data_sage_pon_file, + ref_data_mappability_bed, + ref_data_driver_gene_panel, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(SAGE.out.versions) + ch_sage_germline_out = ch_sage_germline_out.mix(SAGE.out.germline) + ch_sage_somatic_out = ch_sage_somatic_out.mix(SAGE.out.somatic) + } + + // + // SUBWORKFLOW: Annotate variants with PAVE + // + // channel: [val(meta), pave_vcf] + ch_pave_germline_out = Channel.empty() + // channel: [val(meta), pave_vcf] + ch_pave_somatic_out = Channel.empty() + if (run.pave) { + + PAVE( + run.sage ? ch_sage_germline_out : WorkflowOncoanalyser.get_input(ch_inputs, ['sage_vcf', 'normal']), + run.sage ? ch_sage_somatic_out : WorkflowOncoanalyser.get_input(ch_inputs, ['sage_vcf', 'tumor']), + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_sage_pon_file, + ref_data_sage_blacklist_bed, + ref_data_sage_blacklist_vcf, + ref_data_clinvar_vcf, + ref_data_mappability_bed, + ref_data_driver_gene_panel, + ref_data_ensembl_data_dir, + ) + ch_versions = ch_versions.mix(PAVE.out.versions) + ch_pave_germline_out = ch_pave_germline_out.mix(PAVE.out.germline) + ch_pave_somatic_out = ch_pave_somatic_out.mix(PAVE.out.somatic) + } + + // + // MODULE: Run PURPLE for CNV calling, purity and ploidy inference, SV recovery + // + // channel: [val(meta), purple_dir] + ch_purple_out = Channel.empty() + if (run.purple) { + + // channel: [val(meta), sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi] + if (run.gripss) { + ch_purple_inputs_sv = ch_gripss_somatic_out + } else { + ch_purple_inputs_sv = ch_inputs + .map { meta -> + def sv_hard_vcf = meta[['vcf_sv_gripss_hard', 'tumor']] + def sv_soft_vcf = meta[['vcf_sv_gripss_soft', 'tumor']] + return [ + meta, + sv_hard_vcf, + "${sv_hard_vcf}.tbi", + sv_soft_vcf, + "${sv_soft_vcf}.tbi", + ] + } + } + + // channel: [val(meta), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] + ch_purple_inputs = WorkflowOncoanalyser.group_by_meta( + run.amber ? ch_amber_out : WorkflowOncoanalyser.get_input(ch_inputs, ['amber_dir', 'tumor_normal']), + run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.get_input(ch_inputs, ['cobalt_dir', 'tumor_normal']), + ch_purple_inputs_sv, + run.pave ? ch_pave_somatic_out : WorkflowOncoanalyser.get_input(ch_inputs, ['vcf_smlv', 'tumor']), + run.pave ? ch_pave_germline_out : WorkflowOncoanalyser.get_input(ch_inputs, ['vcf_smlv', 'normal']), + ) + + PURPLE( + ch_purple_inputs, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_cobalt_gc_profile, + ref_data_sage_known_hotspots_somatic, + ref_data_sage_known_hotspots_germline, + ref_data_driver_gene_panel, + ref_data_ensembl_data_dir, + ref_data_purple_germline_del, + ) + ch_versions = ch_versions.mix(PURPLE.out.versions) + ch_purple_out = ch_purple_out.mix(PURPLE.out.purple_dir) + } + + // + // MODULE: Run TEAL to characterise teleomeres + // + if (run.teal) { + + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, tumor_wgs_metrics, normal_wgs_metrics, cobalt_dir, purple_dir] + // NOTE(SW): assuming here that TEAL is being run in tumor/normal mode and so we expect a tumor metrics file and normal metrics file + ch_teal_inputs = WorkflowOncoanalyser.group_by_meta( + ch_bams_and_indices, + run.collectwgsmetrics ? ch_cwm_output.tumor : WorkflowOncoanalyser.get_input(ch_inputs, ['collectmetrics', 'tumor']), + run.collectwgsmetrics ? ch_cwm_output.normal : WorkflowOncoanalyser.get_input(ch_inputs, ['collectmetrics', 'normal']), + run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), + run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.get_input(ch_inputs, ['cobalt_dir', 'tumor_normal']), + ) + + TEAL( + ch_teal_inputs, + ) + ch_versions = ch_versions.mix(TEAL.out.versions) + } + + // + // SUBWORKFLOW: Run LILAC for HLA typing and somatic CNV and SNV calling + // + if (run.lilac) { + + LILAC( + ch_bams_and_indices, + run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(['purple_dir', 'tumor_normal']), + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_lilac_resource_dir, + ) + ch_versions = ch_versions.mix(LILAC.out.versions) + } + + // + // MODULE: Run VIRUSBreakend and Virus Interpreter to quantify viral content + // + // NOTE(SW): kept separate from CUPPA conditional block since we'll allow users to run this independently + ch_virusinterpreter_out = Channel.empty() + if (run.virusinterpreter) { + + // channel: [val(meta), tumor_bam] + ch_virusbreakend_inputs = ch_inputs.map { meta -> [meta, meta.get(['bam_wgs', 'tumor'])] } + + VIRUSBREAKEND( + ch_virusbreakend_inputs, + ref_data_virusbreakenddb, + gridss_config, + ref_data_genome_fa, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ) + ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) + + // channel: [val(meta), purple_purity, purple_qc] + ch_virusinterpreter_inputs_purple = ch_purple_out + .map { meta, purple_dir -> + def purple_purity = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.purity.tsv") + def purple_qc = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.qc") + return [meta, purple_purity, purple_qc] + } + + // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] + ch_virusinterpreter_inputs = WorkflowOncoanalyser.group_by_meta( + VIRUSBREAKEND.out.tsv, + ch_virusinterpreter_inputs_purple, + ch_cwm_output.tumor, + ) + + VIRUSINTERPRETER( + ch_virusinterpreter_inputs, + ref_data_virus_taxonomy, + ref_data_virus_reporting, + ) + ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) + ch_virusinterpreter_out = ch_virusinterpreter_out.mix(VIRUSINTERPRETER.out.virusinterpreter_dir) + } + + // + // SUBWORKFLOW: Group structural variants into higher order events with LINX + // + // channel: [val(meta), linx_annotation_dir, linx_visuliaser_dir] + ch_linx_somatic_out = Channel.empty() + if (run.linx) { + + // channel: [val(meta), vcf] + ch_gripps_germline_hard = ch_gripss_germline_out.map { meta, h, hi, s, si -> [meta, h] } + + LINX( + run.gripss ? ch_gripps_germline_hard : WorkflowOncoanalyser.get_input(ch_inputs, ['vcf_sv_gripss_hard', 'normal']), + run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), + ref_data_genome_version, + ref_data_linx_fragile_sites, + ref_data_linx_lines, + ref_data_ensembl_data_dir, + ref_data_known_fusion_data, + ref_data_driver_gene_panel, + ) + ch_versions = ch_versions.mix(LINX.out.versions) + ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX.out.somatic) + + // + // MODULE: Run gpgr to generate a LINX report + // + LINX_REPORT( + ch_linx_somatic_out, + ) + ch_versions = ch_versions.mix(LINX_REPORT.out.versions) + } + + // + // MODULE: Run CUPPA predict tissue of origin + // + if (run.cuppa) { + + // channel: [val(meta), isofox_dir] + if (run.isofox) { + ch_cuppa_inputs_isofox = Channel.empty() + .mix( + ch_inputs_wts.absent.map { meta -> [meta, []] }, + ch_isofox_out, + ) + } else { + ch_cuppa_inputs_isofox = ch_inputs + .map { meta -> [meta, meta.get(['isofox_dir', 'tumor'], [])] } + } + + // channel: [val(meta), linx_somatic_annotation_dir] + ch_linx_anno = ch_linx_somatic_out.map { meta, anno_dir, vis_dir -> [meta, anno_dir]} + + // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter_dir] + // NOTE(SW): the Groovy Collection.flatten method used in + // WorkflowOncoanalyser.group_by_meta removes optional Isofox input; flattening + // done manually below to preserve + ch_cuppa_inputs = WorkflowOncoanalyser.group_by_meta( + ch_cuppa_inputs_isofox, + run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), + run.linx ? ch_linx_anno : WorkflowOncoanalyser.get_input(ch_inputs, ['linx_dir', 'tumor']), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.get_input(ch_inputs, ['virusinterpreter', 'tumor']), + flatten: false, + ) + .map { data -> + def meta = data[0] + def inputs = data[1..-1].collect { it[0] } + return [meta, *inputs] + } + + CUPPA_CLASSIFIER( + ch_cuppa_inputs, + ref_data_cuppa, + ) + ch_versions = ch_versions.mix(CUPPA_CLASSIFIER.out.versions) + + CUPPA_VISUALISER( + CUPPA_CLASSIFIER.out.csv, + ) + ch_versions = ch_versions.mix(CUPPA_VISUALISER.out.versions) + } + + // + // MODULE: Pipeline reporting + // + CUSTOM_DUMPSOFTWAREVERSIONS( + ch_versions.unique().collectFile(name: 'collated_versions.yml') ) - multiqc_report = MULTIQC.out.report.toList() - ch_versions = ch_versions.mix(MULTIQC.out.versions) } /* From 1cd56b2b25b43e804dde5d46e98a3a00c399ca09 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 28 Nov 2022 21:07:04 +1100 Subject: [PATCH 003/562] Add prepare genome and reference subworkflow --- conf/hmfgenomes.config | 29 ++ conf/igenomes.config | 424 +----------------- conf/test.config | 2 +- lib/Constants.groovy | 48 ++ lib/Processes.groovy | 11 +- lib/WorkflowOncoanalyser.groovy | 61 ++- main.nf | 13 + modules.json | 12 + modules/local/custom/hmf_reference/main.nf | 81 ++++ .../lilac_extract_and_index_contig/main.nf | 4 +- modules/local/gridss/assemble/main.nf | 4 +- modules/local/gridss/assemble/meta.yml | 2 +- modules/local/gridss/call/main.nf | 4 +- modules/local/gridss/call/meta.yml | 2 +- modules/local/gridss/index/main.nf | 60 +++ modules/local/gridss/preprocess/main.nf | 4 +- modules/local/gridss/preprocess/meta.yml | 2 +- modules/local/gripss/germline/main.nf | 4 +- modules/local/gripss/germline/meta.yml | 2 +- modules/local/gripss/somatic/main.nf | 4 +- modules/local/gripss/somatic/meta.yml | 2 +- modules/local/isofox/main.nf | 4 +- modules/local/lilac/main.nf | 4 +- modules/local/lilac/meta.yml | 2 +- modules/local/pave/germline/main.nf | 4 +- modules/local/pave/germline/meta.yml | 2 +- modules/local/pave/somatic/main.nf | 4 +- modules/local/pave/somatic/meta.yml | 2 +- modules/local/purple/main.nf | 4 +- modules/local/purple/meta.yml | 2 +- modules/local/sage/germline/main.nf | 4 +- modules/local/sage/germline/meta.yml | 2 +- modules/local/sage/somatic/main.nf | 4 +- modules/local/sage/somatic/meta.yml | 2 +- modules/local/svprep/assemble/main.nf | 4 +- modules/local/svprep/call/main.nf | 4 +- modules/local/svprep/depth_annotator/main.nf | 4 +- modules/local/svprep/preprocess/main.nf | 4 +- modules/local/svprep/svprep/main.nf | 4 +- modules/local/svprep/svprep/meta.yml | 78 ---- modules/local/virusbreakend/main.nf | 6 +- modules/nf-core/bwa/index/main.nf | 51 +++ modules/nf-core/bwa/index/meta.yml | 42 ++ modules/nf-core/samtools/dict/main.nf | 44 ++ modules/nf-core/samtools/dict/meta.yml | 41 ++ modules/nf-core/samtools/faidx/main.nf | 44 ++ modules/nf-core/samtools/faidx/meta.yml | 47 ++ nextflow.config | 81 +--- nextflow_schema.json | 62 ++- subworkflows/local/gridss.nf | 8 +- subworkflows/local/gridss_svprep.nf | 14 +- subworkflows/local/gripss.nf | 6 +- subworkflows/local/lilac.nf | 6 +- subworkflows/local/pave.nf | 6 +- subworkflows/local/prepare_reference.nf | 174 +++++++ subworkflows/local/sage.nf | 6 +- workflows/oncoanalyser.nf | 309 +++++-------- 57 files changed, 1010 insertions(+), 850 deletions(-) create mode 100644 conf/hmfgenomes.config create mode 100644 modules/local/custom/hmf_reference/main.nf create mode 100644 modules/local/gridss/index/main.nf delete mode 100644 modules/local/svprep/svprep/meta.yml create mode 100644 modules/nf-core/bwa/index/main.nf create mode 100644 modules/nf-core/bwa/index/meta.yml create mode 100644 modules/nf-core/samtools/dict/main.nf create mode 100644 modules/nf-core/samtools/dict/meta.yml create mode 100644 modules/nf-core/samtools/faidx/main.nf create mode 100644 modules/nf-core/samtools/faidx/meta.yml create mode 100644 subworkflows/local/prepare_reference.nf diff --git a/conf/hmfgenomes.config b/conf/hmfgenomes.config new file mode 100644 index 00000000..89533274 --- /dev/null +++ b/conf/hmfgenomes.config @@ -0,0 +1,29 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for HMF genome paths +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines reference genomes using HMF genome paths. +---------------------------------------------------------------------------------------- +*/ + + +params { + genomes { + 'GRCh37_hmf' { + fasta = "GRCh37_fasta" + fai = "GRCh37_fai" + dict = "GRCh37_dict" + bwa_index = "GRCh37_bwa_index" + bwa_index_image = "GRCh37_bwa_index_image" + gridss_index = "GRCh37_gridss_index" + } + 'GRCh38_hmf' { + fasta = "GRCh38_fasta" + fai = "GRCh38_fai" + dict = "GRCh38_dict" + bwa_index = "GRCh38_bwa_index" + bwa_index_image = "GRCh38_bwa_index_image" + gridss_index = "GRCh38_gridss_index" + } + } +} diff --git a/conf/igenomes.config b/conf/igenomes.config index 7a1b3ac6..5799f674 100644 --- a/conf/igenomes.config +++ b/conf/igenomes.config @@ -10,423 +10,25 @@ params { // illumina iGenomes reference file paths + // NOTE(SW): the HMF reference data files are incompatible with hg19 due to different contig naming genomes { 'GRCh37' { - fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/GRCh37-blacklist.bed" + fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" + fai = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa.fai" + dict = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.dict" + bwa_index = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" } 'GRCh38' { - fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'GRCm38' { - fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/GRCm38-blacklist.bed" - } - 'TAIR10' { - fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" - mito_name = "Mt" - } - 'EB2' { - fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" - } - 'UMD3.1' { - fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" - mito_name = "MT" - } - 'WBcel235' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" - mito_name = "MtDNA" - macs_gsize = "9e7" - } - 'CanFam3.1' { - fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" - mito_name = "MT" - } - 'GRCz10' { - fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'BDGP6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" - mito_name = "M" - macs_gsize = "1.2e8" - } - 'EquCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" - mito_name = "MT" - } - 'EB1' { - fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" - } - 'Galgal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Gm01' { - fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" - } - 'Mmul_1' { - fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" - mito_name = "MT" - } - 'IRGSP-1.0' { - fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'CHIMP2.1.4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" - mito_name = "MT" - } - 'Rnor_5.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Rnor_6.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'R64-1-1' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" - mito_name = "MT" - macs_gsize = "1.2e7" - } - 'EF2' { - fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.21e7" - } - 'Sbi1' { - fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" - } - 'Sscrofa10.2' { - fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" - mito_name = "MT" - } - 'AGPv3' { - fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" - mito_name = "Mt" + fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" + fai = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa.fai" + dict = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa.dict" + bwa_image = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" } 'hg38' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'hg19' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg19-blacklist.bed" - } - 'mm10' { - fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/mm10-blacklist.bed" - } - 'bosTau8' { - fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'ce10' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "9e7" - } - 'canFam3' { - fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" - mito_name = "chrM" - } - 'danRer10' { - fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.37e9" - } - 'dm6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.2e8" - } - 'equCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" - mito_name = "chrM" - } - 'galGal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" - mito_name = "chrM" - } - 'panTro4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" - mito_name = "chrM" - } - 'rn6' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'sacCer3' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" - readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.2e7" - } - 'susScr3' { - fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" - mito_name = "chrM" + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" + fai = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa.fai" + dict = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.dict" + bwa_image = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" } } } diff --git a/conf/test.config b/conf/test.config index cafe270e..ff055aac 100644 --- a/conf/test.config +++ b/conf/test.config @@ -34,7 +34,7 @@ params { // Defined here to be accessible within a workflow script; downloaded manually prior to process // execution. ref_data_wgsmetrics_intervals_url = 'https://raw.githubusercontent.com/scwatts/nextflow_testdata/main/hmftools/collectwgsmetrics/intervals.interval_list' - schema_ignore_params = 'ref_data_wgsmetrics_intervals_url' + schema_ignore_params = 'genomes,ref_data_wgsmetrics_intervals_url' // Limit resources so that this can run on GitHub Actions max_cpus = 2 diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 5ec2e49d..eb0fe44c 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -1,5 +1,13 @@ class Constants { + // NOTE(SW): the HMF reference data files are incompatible with hg19 due to different contig naming + static List genomes_version_37 = ['GRCh37_hmf', 'GRCh37'] + static List genomes_version_38 = ['GRCh38', 'hg38'] + static List genomes_version_38_noalt = ['GRCh38_hmf'] + + static String hmf_reference_data_37_bundle_path = 'PLACEHOLDER_hmf_reference_data_37_bundle_path' + static String hmf_reference_data_38_bundle_path = 'PLACEHOLDER_hmf_reference_data_38_bundle_path' + static enum PipelineMode { FULL, MANUAL, @@ -25,4 +33,44 @@ class Constants { VIRUSINTERPRETER, } + static public get_enum_from_string(s, e) { + try { + return e.valueOf(s.toUpperCase()) + } catch(java.lang.IllegalArgumentException err) { + return null + } + } + + static public java.util.Map HMF_DATA_PATHS = [ + AMBER_LOCI: 'amber/GermlineHetPon.vcf.gz', + COBALT_GC_PROFILE: 'cobalt/DiploidRegions.bed.gz', + CUPPA: 'cuppa/', + SV_PREP_BLACKLIST: 'svprep/sv_prep_blacklist.bed', + GRIDSS_BLACKLIST: 'gridss/ENCFF356LFX.bed.gz', + GRIDSS_BREAKEND_PON: 'gridss/gridss_pon_single_breakend.bed.gz', + GRIDSS_BREAKPOINT_PON: 'gridss/gridss_pon_breakpoint.bedpe.gz', + REPEAT_MASKER_FILE: 'gridss/repeat_masker.fa.out.gz', + ISOFOX_EXP_COUNTS: 'isofox/read_151_exp_counts.csv', + ISOFOX_EXP_GC_RATIOS: 'isofox/read_100_exp_gc_ratios.csv', + LINX_FRAGILE_SITES: 'linx/fragile_sites_hmf.csv', + LINX_LINES: 'linx/line_elements.csv', + SAGE_BLACKLIST_BED: 'sage/KnownBlacklist.germline.bed', + SAGE_BLACKLIST_VCF: 'sage/KnownHotspots.somatic.vcf.gz', + SAGE_CODING_PANEL: 'sage/ActionableCodingPanel.bed.gz', + SAGE_HIGH_CONFIDENCE: 'sage/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz', + SAGE_KNOWN_HOTSPOTS_GERMLINE: 'sage/KnownBlacklist.germline.vcf.gz', + SAGE_KNOWN_HOTSPOTS_SOMATIC: 'sage/KnownHotspots.somatic.vcf.gz', + SAGE_PON_FILE: 'sage/SageGermlinePon.98x.tsv.gz', + CLINVAR_VCF: 'sage/clinvar.vcf.gz', + LILAC_RESOURCE_DIR: 'lilac/', + VIRUSBREAKENDDB: 'virusbreakend/', + VIRUSINTERPRETER_TAXONOMY: 'virusinterpreter/taxonomy_db.tsv', + VIRUSINTERPRETER_REPORTING: 'virusinterpreter/virus_reporting_db.tsv', + PURPLE_GERMLINE_DEL: 'purple/cohort_germline_del_freq.csv', + DRIVER_GENE_PANEL: 'gene_panel/DriverGenePanel.tsv', + ENSEMBL_DATA_DIR: 'ensembl_data_cache/', + KNOWN_FUSION_DATA: 'known_fusions/known_fusion_data.csv', + KNOWN_FUSIONS: 'known_fusions/known_fusions.bedpe', + MAPPABILITY_BED: 'mappability/mappability_150.bed.gz', + ] } diff --git a/lib/Processes.groovy b/lib/Processes.groovy index 803a72b5..8b209589 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -4,11 +4,8 @@ import Constants class Processes { public static set_processes(mode_str, log) { - def mode_enum - - try { - mode_enum = Constants.PipelineMode.valueOf(mode_str.toUpperCase()) - } catch(java.lang.IllegalArgumentException e) { + def mode_enum = Constants.get_enum_from_string(mode_str, Constants.PipelineMode) + if (!mode_enum) { def workflows_str = Processes.get_workflow_names().join('\n - ') log.error "\nERROR: recieved invalid pipeline mode: '${mode_str}'. Valid options are:\n - ${workflows_str}" System.exit(1) @@ -55,6 +52,9 @@ class Processes { } public static get_process_list(process_str, log) { + if (!process_str) { + return [] + } return process_str .tokenize(',') .collect { name -> @@ -96,5 +96,4 @@ class Processes { *.name() *.toLowerCase() } - } diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 191da7db..9966d5cd 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -7,18 +7,57 @@ import static groovy.io.FileType.FILES import nextflow.Channel import nextflow.Nextflow +import Constants + class WorkflowOncoanalyser { // // Check and validate parameters // public static void initialise(params, workflow, log) { - //genomeExistsError(params, log) - //if (!params.fasta) { - // log.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." - // System.exit(1) - //} + + if (params.genome && params.genomes && ! params.genomes.containsKey(params.genome)) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + + " Currently, the available genome keys are:\n" + + " ${params.genomes.keySet().join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + if (Constants.genomes_version_37.contains(params.genome)) { + params.ref_data_genome_version = '37' + } else if (Constants.genomes_version_38.contains(params.genome)) { + params.ref_data_genome_version = '38' + } else if (Constants.genomes_version_38_noalt.contains(params.genome)) { + params.ref_data_genome_version = '38_noalt' + } else { + def genome_version_list_all = Constants.genomes_version_37 + Constants.genomes_version_38 + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome '${params.genome}' is not defined in genome version list. \n" + + " Currently, the list of genomes in the version list include:\n" + + " ${genome_version_list_all.join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + if (!params.containsKey('ref_data_hmf_bundle')) { + if (params.ref_data_genome_version == '37') { + params.ref_data_hmf_bundle = Constants.hmf_reference_data_37_bundle_path + } else if (params.ref_data_genome_version == '38') { + params.ref_data_hmf_bundle = Constants.hmf_reference_data_38_bundle_path + } else { + assert false : "Got a bad genome version: ${params.ref_data_genome_version}" + } + } + + if (!params.ref_data_genome_fasta) { + log.error "Genome fasta file not specified with e.g. '--ref_data_genome_fasta genome.fa' or via a detectable config file." + System.exit(1) + } + // Download region file for collectwgsmetrics if in test mode + // NOTE(SW): this will be removed as part of the overhaul for testing if (workflow.profile.contains('test')) { def stage_dir = new File(workflow.workDir.toString(), 'stage/manual/') def interval_file = new File(stage_dir, 'collectwgsmetrics.interval_list') @@ -167,16 +206,4 @@ class WorkflowOncoanalyser { public static get_input(ch, key) { return ch.map { meta -> [meta, meta.getAt(key)] } } - - // Exit pipeline if incorrect --genome key provided - private static void genomeExistsError(params, log) { - if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + - " Currently, the available genome keys are:\n" + - " ${params.genomes.keySet().join(", ")}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - } } diff --git a/main.nf b/main.nf index 433a7029..d653bb03 100644 --- a/main.nf +++ b/main.nf @@ -12,6 +12,19 @@ nextflow.enable.dsl = 2 +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + GENOME PARAMETER VALUES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +params.ref_data_genome_fasta = WorkflowMain.getGenomeAttribute(params, 'fasta') +params.ref_data_genome_fai = WorkflowMain.getGenomeAttribute(params, 'fai') +params.ref_data_genome_dict = WorkflowMain.getGenomeAttribute(params, 'dict') +params.ref_data_genome_bwa_index = WorkflowMain.getGenomeAttribute(params, 'bwa_index') +params.ref_data_genome_bwa_index_image = WorkflowMain.getGenomeAttribute(params, 'bwa_index_image') +params.ref_data_genome_gridss_index = WorkflowMain.getGenomeAttribute(params, 'gridss_index') + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALIDATE & PRINT PARAMETER SUMMARY diff --git a/modules.json b/modules.json index 7d495180..1b2686bc 100644 --- a/modules.json +++ b/modules.json @@ -5,6 +5,10 @@ "https://github.com/nf-core/modules.git": { "modules": { "nf-core": { + "bwa/index": { + "branch": "master", + "git_sha": "9518fa4f65f3fb8cde24fde7d40333b39ec8fd65" + }, "custom/dumpsoftwareversions": { "branch": "master", "git_sha": "8022c68e7403eecbd8ba9c49496f69f8c49d50f0" @@ -12,6 +16,14 @@ "picard/collectwgsmetrics": { "branch": "master", "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/dict": { + "branch": "master", + "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01" + }, + "samtools/faidx": { + "branch": "master", + "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01" } } } diff --git a/modules/local/custom/hmf_reference/main.nf b/modules/local/custom/hmf_reference/main.nf new file mode 100644 index 00000000..a28e9999 --- /dev/null +++ b/modules/local/custom/hmf_reference/main.nf @@ -0,0 +1,81 @@ +process HMF_REFERENCE { + container 'public.ecr.aws/ubuntu/ubuntu:20.04_stable' + + input: + path hmf_bundle + + output: + path 'output' , emit: dir + path 'versions.yml', emit: versions + + script: + """ + # if tar.gz + # tar -xzvf ${hmf_bundle} --strip-components 1 -C output/ + # else + # ln -s ${hmf_bundle} output/ + + sleep 5 + + touch versions.yml + + mkdir -p output/amber/ + touch output/amber/GermlineHetPon.vcf.gz + + mkdir -p output/cobalt/ + touch output/cobalt/DiploidRegions.bed.gz + + mkdir -p output/cuppa/ + + mkdir -p output/svprep/ + touch output/svprep/sv_prep_blacklist.bed + + mkdir -p output/gridss/ + touch output/gridss/ENCFF356LFX.bed.gz + touch output/gridss/gridss_pon_single_breakend.bed.gz + touch output/gridss/gridss_pon_breakpoint.bedpe.gz + touch output/gridss/repeat_masker.fa.out.gz + + mkdir -p output/isofox/ + touch output/isofox/read_151_exp_counts.csv + touch output/isofox/read_100_exp_gc_ratios.csv + + mkdir -p output/linx/ + touch output/linx/fragile_sites_hmf.csv + touch output/linx/line_elements.csv + + mkdir -p output/sage/ + touch output/sage/KnownBlacklist.germline.bed + touch output/sage/KnownBlacklist.germline.bed + touch output/sage/KnownHotspots.somatic.vcf.gz + touch output/sage/ActionableCodingPanel.bed.gz + touch output/sage/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz + touch output/sage/KnownBlacklist.germline.vcf.gz + touch output/sage/KnownHotspots.somatic.vcf.gz + touch output/sage/SageGermlinePon.98x.tsv.gz + touch output/sage/clinvar.vcf.gz + + mkdir -p output/lilac/ + + mkdir -p output/virusbreakend/ + + mkdir -p output/virusinterpreter/ + touch output/virusinterpreter/taxonomy_db.tsv + touch output/virusinterpreter/virus_reporting_db.tsv + + mkdir -p output/purple/ + touch output/purple/cohort_germline_del_freq.csv + + mkdir -p output/gene_panel/ + touch output/gene_panel/DriverGenePanel.tsv + + mkdir -p output/ensembl_data_cache/ + + mkdir -p output/known_fusions/ + touch output/known_fusions/known_fusion_data.csv + touch output/known_fusions/known_fusions.bedpe + + mkdir -p output/mappability/ + touch output/mappability/mappability_150.bed.gz + """ +} diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index 08e3946f..8edd1f60 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -4,7 +4,7 @@ process EXTRACT_AND_INDEX_CONTIG { input: val contig_name - path genome_fa + path genome_fasta path genome_fai output: @@ -21,7 +21,7 @@ process EXTRACT_AND_INDEX_CONTIG { """ samtools faidx \\ -o ${contig_name}_extracted.fa \\ - ${genome_fa} \\ + ${genome_fasta} \\ ${contig_name} bwa index ${contig_name}_extracted.fa diff --git a/modules/local/gridss/assemble/main.nf b/modules/local/gridss/assemble/main.nf index efdf9fde..0f878009 100644 --- a/modules/local/gridss/assemble/main.nf +++ b/modules/local/gridss/assemble/main.nf @@ -5,7 +5,7 @@ process ASSEMBLE { input: tuple val(meta), path(bams), path(preprocess_dirs), val(labels) path gridss_config - path genome_fa + path genome_fasta path genome_fai path genome_dict path genome_bwa_index_dir, stageAs: 'bwa_index' @@ -66,7 +66,7 @@ process ASSEMBLE { --jar "${task.ext.jarPath}" \\ --steps assemble \\ --labels "${labels_arg}" \\ - --reference "${genome_fa}" \\ + --reference "${genome_fasta}" \\ --blacklist "${blacklist}" \\ --workingdir "${output_dirname}/work" \\ --assembly "${output_dirname}/sv_assemblies.bam" \\ diff --git a/modules/local/gridss/assemble/meta.yml b/modules/local/gridss/assemble/meta.yml index 0d000fb4..f49fb610 100644 --- a/modules/local/gridss/assemble/meta.yml +++ b/modules/local/gridss/assemble/meta.yml @@ -32,7 +32,7 @@ input: - gridss_config: type: file description: Optional GRIDSS configuration file - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/gridss/call/main.nf b/modules/local/gridss/call/main.nf index d6143f21..5809927a 100644 --- a/modules/local/gridss/call/main.nf +++ b/modules/local/gridss/call/main.nf @@ -5,7 +5,7 @@ process CALL { input: tuple val(meta), path(bams), path(assemble_dir), val(labels) path gridss_config - path genome_fa + path genome_fasta path genome_fai path genome_dict path genome_bwa_index_dir, stageAs: 'bwa_index' @@ -64,7 +64,7 @@ process CALL { --jar "${task.ext.jarPath}" \\ --steps call \\ --labels "${labels_arg}" \\ - --reference "${genome_fa}" \\ + --reference "${genome_fasta}" \\ --blacklist "${blacklist}" \\ --workingdir "${output_dirname}/work/" \\ --assembly "${output_dirname}/sv_assemblies.bam" \\ diff --git a/modules/local/gridss/call/meta.yml b/modules/local/gridss/call/meta.yml index 18e35602..04b037e4 100644 --- a/modules/local/gridss/call/meta.yml +++ b/modules/local/gridss/call/meta.yml @@ -32,7 +32,7 @@ input: - gridss_config: type: file description: Optional GRIDSS configuration file - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf new file mode 100644 index 00000000..e7c23d7c --- /dev/null +++ b/modules/local/gridss/index/main.nf @@ -0,0 +1,60 @@ +process INDEX { + container 'docker.io/scwatts/gridss:2.13.2--3' + + input: + path genome_fasta + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + val indices + + output: + path '*.dict' , emit: dict, optional: true + path '*.img' , emit: img, optional: true + path '*.gridsscache', emit: index, optional: true + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def sequence_dict_arg = indices.contains('samtools_dict') ? 'true' : 'false' + def bwa_index_image_arg = indices.contains('bwa_index_image') ? 'true' : 'false' + def gridss_index_arg = indices.contains('gridss_index') ? 'true' : 'false' + + """ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + # Run + java -Xmx${task.memory.giga}g \\ + -XX:ParallelGCThreads=${task.cpus} \\ + -Dsamjdk.reference_fasta=${genome_fasta} \\ + -Dsamjdk.use_async_io_read_samtools=true \\ + -Dsamjdk.use_async_io_write_samtools=true \\ + -Dsamjdk.use_async_io_write_tribble=true \\ + -Dsamjdk.buffer_size=4194304 \\ + -Dsamjdk.async_io_read_threads=${task.cpus} \\ + -cp ${task.ext.jarPath} \\ + REFERENCE_SEQUENCE=${genome_fasta} \\ + CREATE_SEQUENCE_DICTIONARY=${sequence_dict_arg} \\ + CREATE_BWA_INDEX_IMAGE=${bwa_index_image_arg} \\ + CREATE_GRIDSS_REFERENCE_CACHE=${gridss_index_arg} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + touch ${genome_fasta.name}.dict + touch ${genome_fasta.name}.img + touch ${genome_fasta.name}.gridsscache + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} + diff --git a/modules/local/gridss/preprocess/main.nf b/modules/local/gridss/preprocess/main.nf index 81722608..8f6c9fe3 100644 --- a/modules/local/gridss/preprocess/main.nf +++ b/modules/local/gridss/preprocess/main.nf @@ -5,7 +5,7 @@ process PREPROCESS { input: tuple val(meta), path(bam) path gridss_config - path genome_fa + path genome_fasta path genome_fai path genome_dict path genome_bwa_index_dir, stageAs: 'bwa_index' @@ -32,7 +32,7 @@ process PREPROCESS { --jvmheap "${task.memory.giga}g" \\ --jar "${task.ext.jarPath}" \\ --steps preprocess \\ - --reference "${genome_fa}" \\ + --reference "${genome_fasta}" \\ --workingdir gridss_preprocess/ \\ --threads "${task.cpus}" \\ ${config_arg} \\ diff --git a/modules/local/gridss/preprocess/meta.yml b/modules/local/gridss/preprocess/meta.yml index e43512b5..3eef6890 100644 --- a/modules/local/gridss/preprocess/meta.yml +++ b/modules/local/gridss/preprocess/meta.yml @@ -26,7 +26,7 @@ input: - gridss_config: type: file description: Optional GRIDSS configuration file - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 0d0ae156..977c96c0 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -4,7 +4,7 @@ process GRIPSS_GERMLINE { input: tuple val(meta), path(gridss_vcf) - path genome_fa + path genome_fasta path genome_fai val genome_ver path breakend_pon @@ -31,7 +31,7 @@ process GRIPSS_GERMLINE { ${args} \\ -sample "${meta.get(['sample_name', 'normal'])}" \\ -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ + -ref_genome "${genome_fasta}" \\ -pon_sgl_file "${breakend_pon}" \\ -pon_sv_file "${breakpoint_pon}" \\ -known_hotspot_file "${known_fusions}" \\ diff --git a/modules/local/gripss/germline/meta.yml b/modules/local/gripss/germline/meta.yml index 35142e05..6666ef77 100644 --- a/modules/local/gripss/germline/meta.yml +++ b/modules/local/gripss/germline/meta.yml @@ -23,7 +23,7 @@ input: type: file description: VCF file pattern: "*.{vcf.gz}" - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index cd148c36..b652e162 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -4,7 +4,7 @@ process GRIPSS_SOMATIC { input: tuple val(meta), path(gridss_vcf) - path genome_fa + path genome_fasta path genome_fai val genome_ver path breakend_pon @@ -32,7 +32,7 @@ process GRIPSS_SOMATIC { -sample "${meta.get(['sample_name', 'tumor'])}" \\ -reference "${meta.get(['sample_name', 'normal'])}" \\ -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ + -ref_genome "${genome_fasta}" \\ -pon_sgl_file "${breakend_pon}" \\ -pon_sv_file "${breakpoint_pon}" \\ -known_hotspot_file "${known_fusions}" \\ diff --git a/modules/local/gripss/somatic/meta.yml b/modules/local/gripss/somatic/meta.yml index 402c1ead..826c74af 100644 --- a/modules/local/gripss/somatic/meta.yml +++ b/modules/local/gripss/somatic/meta.yml @@ -23,7 +23,7 @@ input: type: file description: VCF file pattern: "*.{vcf.gz}" - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 1b2e5e2a..214779be 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -6,7 +6,7 @@ process ISOFOX { input: tuple val(meta), path(bam) - path genome_fa + path genome_fasta path genome_fai val genome_ver path ensembl_data_dir @@ -32,7 +32,7 @@ process ISOFOX { ${args} \\ -sample ${meta.get(['sample_name', 'tumor'])} \\ -bam_file ${bam} \\ - -ref_genome ${genome_fa} \\ + -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_dir} \\ -exp_counts_file ${exp_counts} \\ diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index cbf57b0f..4298c2fd 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -4,7 +4,7 @@ process LILAC { input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumour_bai), path(normal_bai), path(purple_dir) - path genome_fa + path genome_fasta val genome_ver path lilac_resource_dir, stageAs: 'lilac_resource_dir' @@ -33,7 +33,7 @@ process LILAC { ${tumor_bam_arg} \\ -reference_bam ${normal_bam} \\ -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ + -ref_genome "${genome_fasta}" \\ -resource_dir "${lilac_resource_dir}" \\ ${purple_args.replaceAll('\\n', '')} \\ -threads "${task.cpus}" \\ diff --git a/modules/local/lilac/meta.yml b/modules/local/lilac/meta.yml index 0e493729..083812cd 100644 --- a/modules/local/lilac/meta.yml +++ b/modules/local/lilac/meta.yml @@ -36,7 +36,7 @@ input: - purple_dir: type: directory description: Optional PURPLE output directory - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 57f8023d..484466b6 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -6,7 +6,7 @@ process PAVE_GERMLINE { input: tuple val(meta), path(sage_vcf) - path genome_fa + path genome_fasta path genome_fai val genome_ver path sage_blacklist_bed @@ -34,7 +34,7 @@ process PAVE_GERMLINE { ${args} \\ -sample "${meta.get(['sample_name', 'tumor'])}" \\ -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ + -ref_genome "${genome_fasta}" \\ -ensembl_data_dir "${ensembl_data_dir}" \\ -driver_gene_panel "${driver_gene_panel}" \\ -clinvar_vcf "${clinvar_vcf}" \\ diff --git a/modules/local/pave/germline/meta.yml b/modules/local/pave/germline/meta.yml index fca88ea4..662b1088 100644 --- a/modules/local/pave/germline/meta.yml +++ b/modules/local/pave/germline/meta.yml @@ -26,7 +26,7 @@ input: type: file description: SAGE VCF pattern: "*.{vcf.gz}" - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 43b1f6ef..36134f44 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -6,7 +6,7 @@ process PAVE_SOMATIC { input: tuple val(meta), path(sage_vcf) - path genome_fa + path genome_fasta path genome_fai val genome_ver path sage_pon_file @@ -32,7 +32,7 @@ process PAVE_SOMATIC { -jar "${task.ext.jarPath}" \\ -sample "${meta.get(['sample_name', 'tumor'])}" \\ -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ + -ref_genome "${genome_fasta}" \\ -ensembl_data_dir "${ensembl_data_dir}" \\ -driver_gene_panel "${driver_gene_panel}" \\ -pon_file "${sage_pon_file}" \\ diff --git a/modules/local/pave/somatic/meta.yml b/modules/local/pave/somatic/meta.yml index f5539f84..53f6b87c 100644 --- a/modules/local/pave/somatic/meta.yml +++ b/modules/local/pave/somatic/meta.yml @@ -26,7 +26,7 @@ input: type: file description: SAGE VCF pattern: "*.{vcf.gz}" - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index ffbc06f6..715f5185 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -4,7 +4,7 @@ process PURPLE { input: tuple val(meta), path(amber), path(cobalt), path(sv_hard_vcf), path(sv_hard_vcf_index), path(sv_soft_vcf), path(sv_soft_vcf_index), path(smlv_tumor_vcf), path(smlv_normal_vcf) - path genome_fa + path genome_fasta path genome_fai path genome_dict val genome_ver @@ -64,7 +64,7 @@ process PURPLE { -somatic_hotspots "${sage_known_hotspots_somatic}" \\ -germline_hotspots "${sage_known_hotspots_germline}" \\ ${germline_del_freq_arg} \\ - -ref_genome "${genome_fa}" \\ + -ref_genome "${genome_fasta}" \\ -ref_genome_version "${genome_ver}" \\ -threads "${task.cpus}" \\ -circos "${task.ext.circosPath}" diff --git a/modules/local/purple/meta.yml b/modules/local/purple/meta.yml index 915f63a8..8c0a815c 100644 --- a/modules/local/purple/meta.yml +++ b/modules/local/purple/meta.yml @@ -52,7 +52,7 @@ input: type: file description: Optional small variant normal VCF file pattern: "*.{vcf.gz}" - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 285ed2f0..71fb0ee6 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -4,7 +4,7 @@ process SAGE_GERMLINE { input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) - path genome_fa + path genome_fasta path genome_fai path genome_dict val genome_ver @@ -33,7 +33,7 @@ process SAGE_GERMLINE { -tumor "${meta.get(['sample_name', 'normal'])}" \\ -tumor_bam "${normal_bam}" \\ -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ + -ref_genome "${genome_fasta}" \\ -hotspots "${sage_known_hotspots_germline}" \\ -panel_bed "${sage_coding_panel}" \\ -high_confidence_bed "${sage_high_confidence}" \\ diff --git a/modules/local/sage/germline/meta.yml b/modules/local/sage/germline/meta.yml index d18bb6ab..86cfefb0 100644 --- a/modules/local/sage/germline/meta.yml +++ b/modules/local/sage/germline/meta.yml @@ -38,7 +38,7 @@ input: type: file description: Normal BAI file pattern: "*.{bai}" - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index fc2da9a1..4106c07b 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -4,7 +4,7 @@ process SAGE_SOMATIC { input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) - path genome_fa + path genome_fasta path genome_fai path genome_dict val genome_ver @@ -33,7 +33,7 @@ process SAGE_SOMATIC { -tumor "${meta.get(['sample_name', 'tumor'])}" \\ -tumor_bam "${tumor_bam}" \\ -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fa}" \\ + -ref_genome "${genome_fasta}" \\ -hotspots "${sage_known_hotspots_somatic}" \\ -panel_bed "${sage_coding_panel}" \\ -high_confidence_bed "${sage_high_confidence}" \\ diff --git a/modules/local/sage/somatic/meta.yml b/modules/local/sage/somatic/meta.yml index 5dec8815..692be7cf 100644 --- a/modules/local/sage/somatic/meta.yml +++ b/modules/local/sage/somatic/meta.yml @@ -38,7 +38,7 @@ input: type: file description: Normal BAI file pattern: "*.{bai}" - - genome_fa: + - genome_fasta: type: file description: Reference genome assembly fa file pattern: "*.{fa,fasta}" diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index a127a10a..4cde069e 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -4,7 +4,7 @@ process ASSEMBLE { input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) path gridss_config - path genome_fa + path genome_fasta path genome_fai path genome_dict path genome_bwa_index_dir, stageAs: 'bwa_index' @@ -66,7 +66,7 @@ process ASSEMBLE { --jar "${task.ext.jarPath}" \\ --steps assemble \\ --labels "${labels_arg}" \\ - --reference "${genome_fa}" \\ + --reference "${genome_fasta}" \\ --blacklist "${blacklist}" \\ --workingdir "${output_dirname}/work" \\ --assembly "${output_dirname}/sv_assemblies.bam" \\ diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index afa6c72c..523dd1e0 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -4,7 +4,7 @@ process CALL { input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) path gridss_config - path genome_fa + path genome_fasta path genome_fai path genome_dict path genome_bwa_index_dir, stageAs: 'bwa_index' @@ -64,7 +64,7 @@ process CALL { --jar "${task.ext.jarPath}" \\ --steps call \\ --labels "${labels_arg}" \\ - --reference "${genome_fa}" \\ + --reference "${genome_fasta}" \\ --blacklist "${blacklist}" \\ --workingdir "${output_dirname}/work/" \\ --assembly "${output_dirname}/sv_assemblies.bam" \\ diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 4aa93f98..b3026665 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -3,7 +3,7 @@ process DEPTH_ANNOTATOR { input: tuple val(meta), path(bams), path(bais), path(vcf), val(labels) - path genome_fa + path genome_fasta val genome_ver output: @@ -29,7 +29,7 @@ process DEPTH_ANNOTATOR { -output_vcf sv.svprep.gridss.depths.vcf.gz \\ -samples "${labels_arg}" \\ -bam_files "${bams_arg}" \\ - -ref_genome ${genome_fa} \\ + -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -threads ${task.cpus} diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 94ba3686..a893b7c6 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -4,7 +4,7 @@ process PREPROCESS { input: tuple val(meta), path(bam), path(bam_filtered) path gridss_config - path genome_fa + path genome_fasta path genome_fai path genome_dict path genome_bwa_index_dir, stageAs: 'bwa_index' @@ -31,7 +31,7 @@ process PREPROCESS { --jvmheap "${task.memory.giga}g" \\ --jar "${task.ext.jarPath}" \\ --steps preprocess \\ - --reference "${genome_fa}" \\ + --reference "${genome_fasta}" \\ --workingdir gridss_preprocess/ \\ --threads "${task.cpus}" \\ ${config_arg} \\ diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 174e3a5e..49cd4d75 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -3,7 +3,7 @@ process SVPREP { input: tuple val(meta), path(bam), path(bai), path(junctions) - path genome_fa + path genome_fasta val genome_ver path sv_blacklist path known_fusions @@ -31,7 +31,7 @@ process SVPREP { ${args} \\ -sample "${meta.id}" \\ -bam_file "${bam}" \\ - -ref_genome "${genome_fa}" \\ + -ref_genome "${genome_fasta}" \\ -ref_genome_version "${genome_ver}" \\ -blacklist_bed "${sv_blacklist}" \\ -known_fusion_bed "${known_fusions}" \\ diff --git a/modules/local/svprep/svprep/meta.yml b/modules/local/svprep/svprep/meta.yml deleted file mode 100644 index a1b0b77b..00000000 --- a/modules/local/svprep/svprep/meta.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: "SVPREP" -description: -keywords: - - svprep - - filtering -tools: - - "SVPREP": - description: "" - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/sv-prep" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/sv-prep" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/sv-prep" - doi: "" - licence: "['GPL v3']" - -input: - - meta: - type: map - description: | - Groovy Map containing sample informatio - e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] - - tumor_bam: - type: file - description: Tumor BAM file - pattern: "*.{bam}" - - normal_bam: - type: file - description: Normal BAM file - pattern: "*.{bam}" - - tumor_bai: - type: file - description: Tumor BAI file - pattern: "*.{bai}" - - normal_bai: - type: file - description: Normal BAI file - pattern: "*.{bai}" - - - - - - - genome_fa: - type: file - description: Reference genome assembly fa file - pattern: "*.{fa,fasta}" - - genome_fai: - type: file - description: Reference genome assembly fai file - pattern: "*.{fai}" - - genome_dict: - type: file - description: Reference genome assembly dict file - pattern: "*.{dict}" - - genome_ver: - type: string - description: Reference genome version - - ensembl_data_dir: - type: directory - description: HMF Ensembl Data Cache directory - pattern: "*.{tsv}" - -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] - - vcf: - type: file - description: SAGE VCF file - pattern: "*.{vcf.gz}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - -authors: - - "@scwatts" diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 4d4e8ba9..f95fe708 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -6,14 +6,14 @@ process VIRUSBREAKEND { input: tuple val(meta), path(bam) - path virusbreakenddb path gridss_config - path genome_fa + path genome_fasta path genome_fai path genome_dict path genome_bwa_index_dir, stageAs: 'bwa_index' path genome_bwa_index_image path genome_gridss_index + path virusbreakenddb output: tuple val(meta), path("*.summary.tsv"), emit: tsv @@ -33,7 +33,7 @@ process VIRUSBREAKEND { --threads ${task.cpus} \\ --db ${virusbreakenddb.toString().replaceAll("/\$", "")}/ \\ --output ${meta.id}.virusbreakend.vcf \\ - --reference ${genome_fa} \\ + --reference ${genome_fasta} \\ ${bam} cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/bwa/index/main.nf b/modules/nf-core/bwa/index/main.nf new file mode 100644 index 00000000..6d70fc15 --- /dev/null +++ b/modules/nf-core/bwa/index/main.nf @@ -0,0 +1,51 @@ +process BWA_INDEX { + tag "$fasta" + label 'process_single' + + conda (params.enable_conda ? "bioconda::bwa=0.7.17" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bwa:0.7.17--hed695b0_7' : + 'quay.io/biocontainers/bwa:0.7.17--hed695b0_7' }" + + input: + tuple val(meta), path(fasta) + + output: + tuple val(meta), path(bwa) , emit: index + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + mkdir bwa + bwa \\ + index \\ + $args \\ + -p bwa/${fasta.baseName} \\ + $fasta + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + END_VERSIONS + """ + + stub: + """ + mkdir bwa + + touch bwa/genome.amb + touch bwa/genome.ann + touch bwa/genome.bwt + touch bwa/genome.pac + touch bwa/genome.sa + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/bwa/index/meta.yml b/modules/nf-core/bwa/index/meta.yml new file mode 100644 index 00000000..2c6cfcd7 --- /dev/null +++ b/modules/nf-core/bwa/index/meta.yml @@ -0,0 +1,42 @@ +name: bwa_index +description: Create BWA index for reference genome +keywords: + - index + - fasta + - genome + - reference +tools: + - bwa: + description: | + BWA is a software package for mapping DNA sequences against + a large reference genome, such as the human genome. + homepage: http://bio-bwa.sourceforge.net/ + documentation: http://www.htslib.org/doc/samtools.html + arxiv: arXiv:1303.3997 + licence: ["GPL-3.0-or-later"] +input: + - meta: + type: map + description: | + Groovy Map containing reference information. + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: Input genome fasta file +output: + - meta: + type: map + description: | + Groovy Map containing reference information. + e.g. [ id:'test', single_end:false ] + - index: + type: file + description: BWA genome index files + pattern: "*.{amb,ann,bwt,pac,sa}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@maxulysse" diff --git a/modules/nf-core/samtools/dict/main.nf b/modules/nf-core/samtools/dict/main.nf new file mode 100644 index 00000000..1b8a4f17 --- /dev/null +++ b/modules/nf-core/samtools/dict/main.nf @@ -0,0 +1,44 @@ +process SAMTOOLS_DICT { + tag "$fasta" + label 'process_single' + + conda (params.enable_conda ? "bioconda::samtools=1.16.1" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + + input: + tuple val(meta), path(fasta) + + output: + tuple val(meta), path ("*.dict"), emit: dict + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + samtools \\ + dict \\ + $args \\ + $fasta \\ + > ${fasta}.dict + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + """ + touch ${fasta}.dict + cat <<-END_VERSIONS > versions.yml + + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/samtools/dict/meta.yml b/modules/nf-core/samtools/dict/meta.yml new file mode 100644 index 00000000..e3eeccc8 --- /dev/null +++ b/modules/nf-core/samtools/dict/meta.yml @@ -0,0 +1,41 @@ +name: samtools_dict +description: Create a sequence dictionary file from a FASTA file +keywords: + - dict + - fasta +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: FASTA file + pattern: "*.{fa,fasta}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - dict: + type: file + description: FASTA dictionary file + pattern: "*.{dict}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@muffato" diff --git a/modules/nf-core/samtools/faidx/main.nf b/modules/nf-core/samtools/faidx/main.nf new file mode 100644 index 00000000..2830963e --- /dev/null +++ b/modules/nf-core/samtools/faidx/main.nf @@ -0,0 +1,44 @@ +process SAMTOOLS_FAIDX { + tag "$fasta" + label 'process_single' + + conda (params.enable_conda ? "bioconda::samtools=1.16.1" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + + input: + tuple val(meta), path(fasta) + + output: + tuple val(meta), path ("*.fai"), emit: fai + tuple val(meta), path ("*.gzi"), emit: gzi, optional: true + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + samtools \\ + faidx \\ + $args \\ + $fasta + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + """ + touch ${fasta}.fai + cat <<-END_VERSIONS > versions.yml + + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/samtools/faidx/meta.yml b/modules/nf-core/samtools/faidx/meta.yml new file mode 100644 index 00000000..fe2fe9a1 --- /dev/null +++ b/modules/nf-core/samtools/faidx/meta.yml @@ -0,0 +1,47 @@ +name: samtools_faidx +description: Index FASTA file +keywords: + - index + - fasta +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: FASTA file + pattern: "*.{fa,fasta}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fai: + type: file + description: FASTA index file + pattern: "*.{fai}" + - gzi: + type: file + description: Optional gzip index file for compressed inputs + pattern: "*.gzi" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@ewels" + - "@phue" diff --git a/nextflow.config b/nextflow.config index 0308950f..5cad486d 100644 --- a/nextflow.config +++ b/nextflow.config @@ -14,59 +14,15 @@ params { // Pipeline run type mode = 'full' - processes_include = '' - processes_exclude = '' + processes_include = null + processes_exclude = null - // Genome reference data - ref_data_genome_fa = './reference_data/genomes/GRCh38/hg38.fa' - ref_data_genome_version = '38' - // Indices - ref_data_genome_fai = './reference_data/genomes/GRCh38/samtools_index/1.12/hg38.fa.fai' - ref_data_genome_dict = './reference_data/genomes/GRCh38/samtools_index/1.12/hg38.fa.dict' - ref_data_genome_bwa_index = './reference_data/genomes/GRCh38/bwamem2_index/0.7.17-r1188' - ref_data_genome_bwa_index_image = './reference_data/genomes/GRCh38/bwamem2_index_image/0.7.17-r1188/hg38.fa.img' - ref_data_genome_gridss_index = './reference_data/genomes/GRCh38/gridss_index/2.13.2/hg38.fa.gridsscache' - - // HMF tools reference data - // AMBER, COBALT - ref_data_amber_loci = './reference_data/hmftools/amber/GermlineHetPon.38.vcf.gz' - ref_data_cobalt_gc_profile = './reference_data/hmftools/cobalt/GC_profile.1000bp.38.cnp' - // CUPPA - ref_data_cuppa = './reference_data/hmftools/cuppa/' - // SVPREP, GRIDSS, GRIPSS - ref_data_sv_prep_blacklist = './reference_data/hmftools/gridss/sv_prep_blacklist.38.bed' - ref_data_gridss_blacklist = './reference_data/hmftools/gridss/ENCFF356LFX.bed.gz' - ref_data_gridss_breakend_pon = './reference_data/hmftools/gridss/gridss_pon_single_breakend.38.bed.gz' - ref_data_gridss_breakpoint_pon = './reference_data/hmftools/gridss/gridss_pon_breakpoint.38.bedpe.gz' - ref_data_repeat_masker_file = './reference_data/hmftools/repeatmasker/38.fa.out.gz' - // Isofox - ref_data_rna_exp_counts = './reference_data/hmftools/isofox/read_100_exp_gc_ratios.csv' - ref_data_rna_exp_gc_ratios = './reference_data/hmftools/isofox/read_151_exp_counts.csv' - // LINX - ref_data_linx_fragile_sites = './reference_data/hmftools/linx/fragile_sites_hmf.38.csv' - ref_data_linx_lines = './reference_data/hmftools/linx/line_elements.38.csv' - // SAGE, PAVE - ref_data_sage_blacklist_bed = './reference_data/hmftools/sage/KnownBlacklist.germline.38.bed' - ref_data_sage_blacklist_vcf = './reference_data/hmftools/sage/KnownBlacklist.germline.38.vcf.gz' - ref_data_sage_coding_panel = './reference_data/hmftools/sage/ActionableCodingPanel.38.bed.gz' - ref_data_sage_high_confidence = './reference_data/hmftools/sage/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz' - ref_data_sage_known_hotspots_germline = './reference_data/hmftools/sage/KnownHotspots.germline.38.vcf.gz' - ref_data_sage_known_hotspots_somatic = './reference_data/hmftools/sage/KnownHotspots.somatic.38.vcf.gz' - ref_data_sage_pon_file = './reference_data/hmftools/sage/SageGermlinePon.98x.38.tsv.gz' - ref_data_clinvar_vcf = './reference_data/hmftools/sage/clinvar.38.vcf.gz' - // LILAC - ref_data_lilac_resource_dir = './reference_data/hmftools/lilac' - // VIRUSBreakend, Virus Interpreter - ref_data_virusbreakenddb = './reference_data/hmftools/virusbreakend/' - ref_data_virus_taxonomy = './reference_data/hmftools/virus_interpreter/taxonomy_db.tsv' - ref_data_virus_reporting = './reference_data/hmftools/virus_interpreter/virus_reporting_db.tsv' - // Misc - ref_data_purple_germline_del = './reference_data/hmftools/purple/cohort_germline_del_freq.38.csv' - ref_data_driver_gene_panel = './reference_data/hmftools/gene_panel/DriverGenePanel.38.tsv' - ref_data_ensembl_data_dir = './reference_data/hmftools/ensembl_data_cache' - ref_data_known_fusion_data = './reference_data/hmftools/known_fusions/known_fusion_data.38.csv' - ref_data_known_fusions = './reference_data/hmftools/known_fusions/known_fusions.38.bedpe' - ref_data_mappability_bed = './reference_data/hmftools/mappability/mappability_150.38.bed.gz' + // TODO(SW): default/suggest (very strongly) to use GRCh37_hmf or + // GRCh38_hmf (or whatever is equivalent); we may be able to get away with + // using an igenome in place of the HMF references, need to investigate + genome = null + igenomes_base = 's3://ngi-igenomes/igenomes' + igenomes_ignore = false // Boilerplate options outdir = null @@ -95,9 +51,9 @@ params { // Max resource options // Defaults only, expecting to be overwritten - max_memory = '128.GB' - max_cpus = 16 - max_time = '240.h' + max_memory = '128.GB' + max_cpus = 16 + max_time = '240.h' } @@ -186,12 +142,15 @@ profiles { } -//// Load igenomes.config if required -//if (!params.igenomes_ignore) { -// includeConfig 'conf/igenomes.config' -//} else { -// params.genomes = [:] -//} +// Load igenomes.config if required +if (!params.igenomes_ignore) { + includeConfig 'conf/igenomes.config' +} else { + params.genomes = [:] +} + +// Load hmfgenomes.config +includeConfig 'conf/hmfgenomes.config' // Export these variables to prevent local Python/R libraries from conflicting with those in the container diff --git a/nextflow_schema.json b/nextflow_schema.json index b0de3f8d..ec50a313 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -49,6 +49,16 @@ "description": "Pipeline mode to use.", "fa_icon": "fas fa-diagram-project" }, + "processes_exclude": { + "type": "string", + "description": "Pipeline processes to exclude.", + "fa_icon": "fas fa-diagram-project" + }, + "processes_include": { + "type": "string", + "description": "Pipeline processes to include.", + "fa_icon": "fas fa-diagram-project" + }, "gridss_config": { "type": "string", "description": "Path to GRIDSS configuration file.", @@ -62,19 +72,43 @@ "fa_icon": "fas fa-dna", "description": "Reference data files and options required for the workflow.", "properties": { - "ref_data_genome_fa": { + "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", + "mimetype": "text/plain", + "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", + "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 c lashes between custom parameters and those supplied in `igenomes.config`." + }, + "ref_data_genome_fasta": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", "description": "Path to reference genome FASTA file.", "fa_icon": "far fa-file-code" }, - "ref_data_genome_version": { - "type": "string", - "description": "Reference genome version (37 or 38).", - "fa_icon": "far fa-file-code", - "enum": ["37", "38", "38_noalt"] - }, "ref_data_genome_fai": { "type": "string", "format": "file-path", @@ -109,6 +143,12 @@ "description": "Path to reference genome GRIDSS index file.", "fa_icon": "far fa-file-code" }, + "ref_data_hmf_bundle": { + "type": "string", + "format": "directory-path", + "description": "Path HMF reference data bundle.", + "fa_icon": "far fa-file-code" + }, "ref_data_amber_loci": { "type": "string", "format": "file-path", @@ -164,14 +204,14 @@ "description": "Path to RepeatMasker file.", "fa_icon": "far fa-file-code" }, - "ref_data_rna_exp_counts": { + "ref_data_isofox_exp_counts": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", "description": "Path to Isofox expected read counts file.", "fa_icon": "far fa-file-code" }, - "ref_data_rna_exp_gc_ratios": { + "ref_data_isofox_exp_gc_ratios": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", @@ -210,14 +250,14 @@ "description": "Path to VIRUSBreakend database directory.", "fa_icon": "far fa-folder-open" }, - "ref_data_virus_taxonomy": { + "ref_data_virusinterpreter_taxonomy": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.tsv$", "description": "Path to Virus Interpreter taxonomy file.", "fa_icon": "far fa-file-code" }, - "ref_data_virus_reporting": { + "ref_data_virusinterpreter_reporting": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.tsv$", diff --git a/subworkflows/local/gridss.nf b/subworkflows/local/gridss.nf index 35603000..4057aae9 100644 --- a/subworkflows/local/gridss.nf +++ b/subworkflows/local/gridss.nf @@ -10,7 +10,7 @@ workflow GRIDSS { take: ch_inputs // channel: [val(meta), bam_tumor, bam_normal] gridss_config // file: /path/to/gridss_config (optional) - ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_dict // file: /path/to/genome_dict ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ @@ -43,7 +43,7 @@ workflow GRIDSS { PREPROCESS( ch_preprocess_inputs, gridss_config, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_dict, ref_data_genome_bwa_index, @@ -75,7 +75,7 @@ workflow GRIDSS { ASSEMBLE( ch_assemble_inputs, gridss_config, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_dict, ref_data_genome_bwa_index, @@ -103,7 +103,7 @@ workflow GRIDSS { CALL( ch_call_inputs, gridss_config, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_dict, ref_data_genome_bwa_index, diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep.nf index d9870fd5..d0189225 100644 --- a/subworkflows/local/gridss_svprep.nf +++ b/subworkflows/local/gridss_svprep.nf @@ -14,7 +14,7 @@ workflow GRIDSS_SVPREP { take: ch_inputs // channel: [val(meta)] gridss_config // file: /path/to/gridss_config (optional) - ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_version // val: genome version ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_dict // file: /path/to/genome_dict @@ -42,7 +42,7 @@ workflow GRIDSS_SVPREP { // Filter tumor BAM SVPREP_TUMOR( ch_svprep_tumor_inputs, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_version, ref_data_sv_prep_blacklist, ref_data_known_fusions, @@ -63,7 +63,7 @@ workflow GRIDSS_SVPREP { SVPREP_NORMAL( ch_svprep_normal_inputs, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_version, ref_data_sv_prep_blacklist, ref_data_known_fusions, @@ -108,7 +108,7 @@ workflow GRIDSS_SVPREP { GRIDSS_PREPROCESS( ch_preprocess_inputs, gridss_config, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_dict, ref_data_genome_bwa_index, @@ -146,7 +146,7 @@ workflow GRIDSS_SVPREP { GRIDSS_ASSEMBLE( ch_assemble_inputs, gridss_config, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_dict, ref_data_genome_bwa_index, @@ -174,7 +174,7 @@ workflow GRIDSS_SVPREP { GRIDSS_CALL( ch_call_inputs, gridss_config, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_dict, ref_data_genome_bwa_index, @@ -205,7 +205,7 @@ workflow GRIDSS_SVPREP { // Add depth annotations to SVs SVPREP_DEPTH_ANNOTATOR( ch_depth_inputs, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_version, ) diff --git a/subworkflows/local/gripss.nf b/subworkflows/local/gripss.nf index 786bebcb..06a57524 100644 --- a/subworkflows/local/gripss.nf +++ b/subworkflows/local/gripss.nf @@ -8,7 +8,7 @@ include { GRIPSS_SOMATIC } from '../../modules/local/gripss/somatic/main' workflow GRIPSS { take: ch_inputs // channel: [val(meta), gridss_vcf] - ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_version // val: genome version breakend_pon // file: /path/to/breakend_pon @@ -23,7 +23,7 @@ workflow GRIPSS { // Germline GRIPSS_GERMLINE( ch_inputs, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_version, breakend_pon, @@ -36,7 +36,7 @@ workflow GRIPSS { // Somatic GRIPSS_SOMATIC( ch_inputs, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_version, breakend_pon, diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index aaba4f7b..92358f20 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -12,7 +12,7 @@ workflow LILAC { take: ch_inputs_bams // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] ch_inputs_purple_dir // channel: [val(meta), purple_dir] - ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_version // val: genome version ref_data_lilac_resource_dir // file: /path/to/lilac_resource_dir/ @@ -47,7 +47,7 @@ workflow LILAC { // are realigned for consistency. EXTRACT_AND_INDEX_CONTIG( 'chr6', - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ) REALIGN_READS( @@ -74,7 +74,7 @@ workflow LILAC { // Run LILAC LILAC_PROCESS( ch_lilac_inputs, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_version, ref_data_lilac_resource_dir, ) diff --git a/subworkflows/local/pave.nf b/subworkflows/local/pave.nf index c3fd0357..2b79b705 100644 --- a/subworkflows/local/pave.nf +++ b/subworkflows/local/pave.nf @@ -9,7 +9,7 @@ workflow PAVE { take: ch_inputs_germline // channel: [val(meta), sage_germline_vcf] ch_inputs_somatic // channel: [val(meta), sage_somatic_vcf] - ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_version // val: genome version ref_data_sage_pon_file // file: /path/to/sage_pon_file @@ -27,7 +27,7 @@ workflow PAVE { // Germline PAVE_GERMLINE( ch_inputs_germline, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_version, ref_data_sage_blacklist_bed, @@ -42,7 +42,7 @@ workflow PAVE { // Somatic PAVE_SOMATIC( ch_inputs_somatic, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_version, ref_data_sage_pon_file, diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf new file mode 100644 index 00000000..df0cf42c --- /dev/null +++ b/subworkflows/local/prepare_reference.nf @@ -0,0 +1,174 @@ +// +// Prepare reference data as required +// + +include { SAMTOOLS_FAIDX } from '../../modules/nf-core/samtools/faidx/main' +include { SAMTOOLS_DICT } from '../../modules/nf-core/samtools/dict/main' +include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' + +include { INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' +include { INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' +include { HMF_REFERENCE } from '../../modules/local/custom/hmf_reference/main' + +workflow PREPARE_REFERENCE { + take: + run // map: stages to run + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // + // Set reference genome FASTA for consistency + // + ch_genome_fasta = params.ref_data_genome_fasta + + // + // Create .fai and .dict for reference genome if required + // + // The fai and dict files should always be present if using a genome preset. These are + // always created where they are not present without checking processes to run given they + // are used in numerous processes and have a neglibile cost to generate. + ch_genome_fai = params.ref_data_genome_fai + ch_genome_dict = params.ref_data_genome_dict + if (!params.ref_data_genome_fai) { + SAMTOOLS_FAIDX([:], ch_genome_fasta) + ch_genome_fai = SAMTOOLS_FAIDX.out.fai + ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions) + } + if (!params.ref_data_genome_dict) { + SAMTOOLS_DICT([:], ch_genome_fasta) + ch_genome_dict = SAMTOOLS_DICT.out.dict + ch_versions = ch_versions.mix(SAMTOOLS_DICT.out.versions) + } + + // + // Create BWA index, BWA index image, and GRIDSS index for reference genome if required + // + ch_genome_bwa_index = params.ref_data_genome_bwa_index + ch_genome_bwa_index_image = params.ref_data_genome_bwa_index_image + ch_genome_gridss_index = params.ref_data_genome_gridss_index + if (run.gridss || run.virusbreakend) { + if (!params.ref_data_genome_bwa_index) { + BWA_INDEX([[:], ch_genome_fasta]) + ch_genome_bwa_index = BWA_INDEX.out.index.map { it[1] } + ch_versions = ch_versions.mix(BWA_INDEX.out.versions) + } + if (!params.ref_data_genome_bwa_index_image) { + GRIDSS_BWA_INDEX_IMAGE( + ch_genome_fasta, + ch_genome_fai, + ch_genome_dict, + ch_genome_bwa_index, + [], + ['bwa_index_image'], + ) + ch_genome_bwa_index_image = GRIDSS_BWA_INDEX_IMAGE.out.img + ch_versions = ch_versions.mix(GRIDSS_BWA_INDEX_IMAGE.out.versions) + } + if (!params.ref_data_genome_gridss_index) { + GRIDSS_INDEX( + ch_genome_fasta, + ch_genome_fai, + ch_genome_dict, + ch_genome_bwa_index, + ch_genome_bwa_index_image, + ['gridss_index'], + ) + ch_genome_gridss_index = GRIDSS_INDEX.out.index + ch_versions = ch_versions.mix(GRIDSS_INDEX.out.versions) + } + } + + // + // Set HMF reference paths / stage, unpack if required + // + if (params.ref_data_hmf_bundle) { + HMF_REFERENCE(params.ref_data_hmf_bundle) + + // Obtain paths and convert queue channel to value channel + // NOTE(SW): any relevant HMF reference file parameter explicitly set in config will take priority + ch_hmf_data = HMF_REFERENCE.out.dir + .collect() + .map { dir_list -> + assert dir_list.size() == 1 + return create_hmf_data_map(dir_list[0], false /* params_only */) + } + ch_versions = ch_versions.mix(HMF_REFERENCE.out.versions) + } else { + // If no HMF data bundle is supplied we construct from *only* params + ch_hmf_data = create_hmf_data_map(null, true /* params_only */) + } + + emit: + genome_fasta = ch_genome_fasta // path: genome_fasta + genome_fai = ch_genome_fai // path: genome_fai + genome_dict = ch_genome_dict // path: genome_dict + genome_bwa_index = ch_genome_bwa_index // path: genome_bwa_index + genome_bwa_index_image = ch_genome_bwa_index_image // path: genome_bwa_index_image + genome_gridss_index = ch_genome_gridss_index // path: genome_gridss_index + genome_version = params.ref_data_genome_version // val: genome_version + hmf_data = ch_hmf_data // map: HMF data paths + + versions = ch_versions // channel: [versions.yml] +} + +def create_hmf_data_map(hmf_bundle_dir, params_only) { + return [ + // AMBER + 'amber_loci': get_hmf_data_file_object('ref_data_amber_loci', 'AMBER_LOCI', hmf_bundle_dir, params_only), + // COBALT + 'cobalt_gc_profile': get_hmf_data_file_object('ref_data_cobalt_gc_profile', 'COBALT_GC_PROFILE', hmf_bundle_dir, params_only), + // CUPPA + 'cuppa': get_hmf_data_file_object('ref_data_cuppa', 'CUPPA', hmf_bundle_dir, params_only), + // SVPREP + 'sv_prep_blacklist': get_hmf_data_file_object('ref_data_sv_prep_blacklist', 'SV_PREP_BLACKLIST', hmf_bundle_dir, params_only), + // GRIDSS, GRIPSS + 'gridss_blacklist': get_hmf_data_file_object('ref_data_gridss_blacklist', 'GRIDSS_BLACKLIST', hmf_bundle_dir, params_only), + 'gridss_breakend_pon': get_hmf_data_file_object('ref_data_gridss_breakend_pon', 'GRIDSS_BREAKEND_PON', hmf_bundle_dir, params_only), + 'gridss_breakpoint_pon': get_hmf_data_file_object('ref_data_gridss_breakpoint_pon', 'GRIDSS_BREAKPOINT_PON', hmf_bundle_dir, params_only), + 'repeat_masker_file': get_hmf_data_file_object('ref_data_repeat_masker_file', 'REPEAT_MASKER_FILE', hmf_bundle_dir, params_only), + // Isofox + 'isofox_exp_counts': get_hmf_data_file_object('ref_data_isofox_exp_counts', 'ISOFOX_EXP_COUNTS', hmf_bundle_dir, params_only), + 'isofox_exp_gc_ratios': get_hmf_data_file_object('ref_data_isofox_exp_gc_ratios', 'ISOFOX_EXP_GC_RATIOS', hmf_bundle_dir, params_only), + // LINX + 'linx_fragile_sites': get_hmf_data_file_object('ref_data_linx_fragile_sites', 'LINX_FRAGILE_SITES', hmf_bundle_dir, params_only), + 'linx_lines': get_hmf_data_file_object('ref_data_linx_lines', 'LINX_LINES', hmf_bundle_dir, params_only), + // SAGE, PAVE + 'sage_blacklist_bed': get_hmf_data_file_object('ref_data_sage_blacklist_bed', 'SAGE_BLACKLIST_BED', hmf_bundle_dir, params_only), + 'sage_blacklist_vcf': get_hmf_data_file_object('ref_data_sage_blacklist_vcf', 'SAGE_BLACKLIST_VCF', hmf_bundle_dir, params_only), + 'sage_coding_panel': get_hmf_data_file_object('ref_data_sage_coding_panel', 'SAGE_CODING_PANEL', hmf_bundle_dir, params_only), + 'sage_high_confidence': get_hmf_data_file_object('ref_data_sage_high_confidence', 'SAGE_HIGH_CONFIDENCE', hmf_bundle_dir, params_only), + 'sage_known_hotspots_germline': get_hmf_data_file_object('ref_data_sage_known_hotspots_germline', 'SAGE_KNOWN_HOTSPOTS_GERMLINE', hmf_bundle_dir, params_only), + 'sage_known_hotspots_somatic': get_hmf_data_file_object('ref_data_sage_known_hotspots_somatic', 'SAGE_KNOWN_HOTSPOTS_SOMATIC', hmf_bundle_dir, params_only), + 'sage_pon_file': get_hmf_data_file_object('ref_data_sage_pon_file', 'SAGE_PON_FILE', hmf_bundle_dir, params_only), + 'clinvar_vcf': get_hmf_data_file_object('ref_data_clinvar_vcf', 'CLINVAR_VCF', hmf_bundle_dir, params_only), + // LILAC + 'lilac_resource_dir': get_hmf_data_file_object('ref_data_lilac_resource_dir', 'LILAC_RESOURCE_DIR', hmf_bundle_dir, params_only), + // VIRUSBreakend + 'virusbreakenddb': get_hmf_data_file_object('ref_data_virusbreakenddb', 'VIRUSBREAKENDDB', hmf_bundle_dir, params_only), + // Virus Interpreter + 'virus_taxonomy': get_hmf_data_file_object('ref_data_virus_taxonomy', 'VIRUSINTERPRETER_TAXONOMY', hmf_bundle_dir, params_only), + 'virus_reporting': get_hmf_data_file_object('ref_data_virus_reporting', 'VIRUSINTERPRETER_REPORTING', hmf_bundle_dir, params_only), + // Misc + 'purple_germline_del': get_hmf_data_file_object('ref_data_purple_germline_del', 'PURPLE_GERMLINE_DEL', hmf_bundle_dir, params_only), + 'driver_gene_panel': get_hmf_data_file_object('ref_data_driver_gene_panel', 'DRIVER_GENE_PANEL', hmf_bundle_dir, params_only), + 'ensembl_data_dir': get_hmf_data_file_object('ref_data_ensembl_data_dir', 'ENSEMBL_DATA_DIR', hmf_bundle_dir, params_only), + 'known_fusion_data': get_hmf_data_file_object('ref_data_known_fusion_data', 'KNOWN_FUSION_DATA', hmf_bundle_dir, params_only), + 'known_fusions': get_hmf_data_file_object('ref_data_known_fusions', 'KNOWN_FUSIONS', hmf_bundle_dir, params_only), + 'mappability_bed': get_hmf_data_file_object('ref_data_mappability_bed', 'MAPPABILITY_BED', hmf_bundle_dir, params_only), + ] +} + +def get_hmf_data_file_object(pk, hk, base_dir, params_only) { + if (params.containsKey(pk)) { + return file(params.getAt(pk), checkIfExists: true) + } else if (params_only) { + assert false : "TODO(SW): more helpful message about missing param ${pk}" + } else if (!Constants.HMF_DATA_PATHS.containsKey(hk)) { + assert false : "bad key for Constants.HMF_DATA_PATHS ${hk}" + } else { + def base_dir_noslash = base_dir.toString().replaceAll('/$', '') + return file("${base_dir_noslash}/${Constants.HMF_DATA_PATHS.getAt(hk)}", checkIfExists: true) + } +} diff --git a/subworkflows/local/sage.nf b/subworkflows/local/sage.nf index 07fb9ad0..7c9cacc9 100644 --- a/subworkflows/local/sage.nf +++ b/subworkflows/local/sage.nf @@ -8,7 +8,7 @@ include { SAGE_SOMATIC } from '../../modules/local/sage/somatic/main' workflow SAGE { take: ch_inputs // channel: [meta, tumor_bam, normal_bam, tumor_bai, normal_bai] - ref_data_genome_fa // file: /path/to/genome_fa + ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_dict // file: /path/to/genome_dict ref_data_genome_version // val: genome version @@ -28,7 +28,7 @@ workflow SAGE { // Germline SAGE_GERMLINE( ch_inputs, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_dict, ref_data_genome_version, @@ -42,7 +42,7 @@ workflow SAGE { // Somatic SAGE_SOMATIC( ch_inputs, - ref_data_genome_fa, + ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_dict, ref_data_genome_version, diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index a55df642..fcf3af17 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -13,56 +13,26 @@ def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) // Validate input parameters WorkflowOncoanalyser.initialise(params, workflow, log) + +// Set processes to run +processes = Processes.set_processes(params.mode, log) + +processes_include = Processes.get_process_list(params.processes_include, log) +processes_exclude = Processes.get_process_list(params.processes_exclude, log) +Processes.check_include_exclude_list(processes_include, processes_exclude, log) + +processes.addAll(processes_include) +processes.removeAll(processes_exclude) + +run = Constants.Process + .values() + .collectEntries { p -> [p.name().toLowerCase(), p in processes] } + + // Check input path parameters to see if they exist def checkPathParamList = [ params.input, - // Reference genome - params.ref_data_genome_fa, - params.ref_data_genome_fai, - params.ref_data_genome_dict, - params.ref_data_genome_bwa_index, - params.ref_data_genome_bwa_index_image, - params.ref_data_genome_gridss_index, - // AMBER and COBALT - params.ref_data_amber_loci, - params.ref_data_cobalt_gc_profile, - // CUPPA - params.ref_data_cuppa, - // SVPREP, GRIDSS, GRIPSS params.gridss_config, - params.ref_data_sv_prep_blacklist, - params.ref_data_gridss_blacklist, - params.ref_data_gridss_breakend_pon, - params.ref_data_gridss_breakpoint_pon, - params.ref_data_repeat_masker_file, - // Isofox - params.ref_data_rna_exp_counts, - params.ref_data_rna_exp_gc_ratios, - // LINX - params.ref_data_linx_fragile_sites, - params.ref_data_linx_lines, - // SAGE, PAVE - params.ref_data_sage_blacklist_bed, - params.ref_data_sage_blacklist_vcf, - params.ref_data_sage_coding_panel, - params.ref_data_sage_high_confidence, - params.ref_data_sage_known_hotspots_germline, - params.ref_data_sage_known_hotspots_somatic, - params.ref_data_sage_pon_file, - // LILAC - params.ref_data_lilac_resource_dir, - // VIRUSBreakend, Virus Interpreter - params.ref_data_virusbreakenddb, - params.ref_data_virus_taxonomy, - params.ref_data_virus_reporting, - // Other - params.ref_data_purple_germline_del, - params.ref_data_clinvar_vcf, - params.ref_data_driver_gene_panel, - params.ref_data_ensembl_data_dir, - params.ref_data_known_fusion_data, - params.ref_data_known_fusions, - params.ref_data_mappability_bed, ] for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } @@ -99,18 +69,17 @@ include { TEAL } from '../modules/local/teal/main' include { VIRUSBREAKEND } from '../modules/local/virusbreakend/main' include { VIRUSINTERPRETER } from '../modules/local/virusinterpreter/main' -include { PICARD_COLLECTWGSMETRICS as COLLECTWGSMETRICS } from '../modules/nf-core/picard/collectwgsmetrics/main' - // // SUBWORKFLOWS // -include { GRIDSS } from '../subworkflows/local/gridss' -include { GRIDSS_SVPREP } from '../subworkflows/local/gridss_svprep' -include { GRIPSS } from '../subworkflows/local/gripss' -include { LILAC } from '../subworkflows/local/lilac' -include { LINX } from '../subworkflows/local/linx' -include { PAVE } from '../subworkflows/local/pave' -include { SAGE } from '../subworkflows/local/sage' +include { GRIDSS } from '../subworkflows/local/gridss' +include { GRIDSS_SVPREP } from '../subworkflows/local/gridss_svprep' +include { GRIPSS } from '../subworkflows/local/gripss' +include { LILAC } from '../subworkflows/local/lilac' +include { LINX } from '../subworkflows/local/linx' +include { PAVE } from '../subworkflows/local/pave' +include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' +include { SAGE } from '../subworkflows/local/sage' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -122,6 +91,7 @@ include { SAGE } from '../subworkflows/local/sage' // MODULES // include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' +include { PICARD_COLLECTWGSMETRICS as COLLECTWGSMETRICS } from '../modules/nf-core/picard/collectwgsmetrics/main' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -133,60 +103,11 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft def get_file_object(path) { return path ? file(path) : [] } - -samplesheet = get_file_object(params.input) -// Reference genome -ref_data_genome_fa = get_file_object(params.ref_data_genome_fa) -ref_data_genome_version = params.ref_data_genome_version -ref_data_genome_fai = get_file_object(params.ref_data_genome_fai) -ref_data_genome_dict = get_file_object(params.ref_data_genome_dict) -ref_data_genome_bwa_index = get_file_object(params.ref_data_genome_bwa_index) -ref_data_genome_bwa_index_image = get_file_object(params.ref_data_genome_bwa_index_image) -ref_data_genome_gridss_index = get_file_object(params.ref_data_genome_gridss_index) -// AMBER and COBALT -ref_data_amber_loci = get_file_object(params.ref_data_amber_loci) -ref_data_cobalt_gc_profile = get_file_object(params.ref_data_cobalt_gc_profile) -// CUPPA -ref_data_cuppa = get_file_object(params.ref_data_cuppa) -// SVPREP, GRIDSS, GRIPSS -gridss_config = get_file_object(params.gridss_config) -ref_data_sv_prep_blacklist = get_file_object(params.ref_data_sv_prep_blacklist) -ref_data_gridss_blacklist = get_file_object(params.ref_data_gridss_blacklist) -ref_data_gridss_breakend_pon = get_file_object(params.ref_data_gridss_breakend_pon) -ref_data_gridss_breakpoint_pon = get_file_object(params.ref_data_gridss_breakpoint_pon) -ref_data_repeat_masker_file = get_file_object(params.ref_data_repeat_masker_file) -// Isofox -ref_data_rna_exp_counts = get_file_object(params.ref_data_rna_exp_counts) -ref_data_rna_exp_gc_ratios = get_file_object(params.ref_data_rna_exp_gc_ratios) -// LINX -ref_data_linx_fragile_sites = get_file_object(params.ref_data_linx_fragile_sites) -ref_data_linx_lines = get_file_object(params.ref_data_linx_lines) -// SAGE, PAVE -ref_data_sage_blacklist_bed = get_file_object(params.ref_data_sage_blacklist_bed) -ref_data_sage_blacklist_vcf = get_file_object(params.ref_data_sage_blacklist_vcf) -ref_data_sage_coding_panel = get_file_object(params.ref_data_sage_coding_panel) -ref_data_sage_high_confidence = get_file_object(params.ref_data_sage_high_confidence) -ref_data_sage_known_hotspots_germline = get_file_object(params.ref_data_sage_known_hotspots_germline) -ref_data_sage_known_hotspots_somatic = get_file_object(params.ref_data_sage_known_hotspots_somatic) -ref_data_sage_pon_file = get_file_object(params.ref_data_sage_pon_file) -// LILAC -ref_data_lilac_resource_dir = get_file_object(params.ref_data_lilac_resource_dir) -// VIRUSBreakend, Virus Interpreter -ref_data_virusbreakenddb = get_file_object(params.ref_data_virusbreakenddb) -ref_data_virus_taxonomy = get_file_object(params.ref_data_virus_taxonomy) -ref_data_virus_reporting = get_file_object(params.ref_data_virus_reporting) -// Other -ref_data_purple_germline_del = get_file_object(params.ref_data_purple_germline_del) -ref_data_clinvar_vcf = get_file_object(params.ref_data_clinvar_vcf) -ref_data_driver_gene_panel = get_file_object(params.ref_data_driver_gene_panel) -ref_data_ensembl_data_dir = get_file_object(params.ref_data_ensembl_data_dir) -ref_data_known_fusion_data = get_file_object(params.ref_data_known_fusion_data) -ref_data_known_fusions = get_file_object(params.ref_data_known_fusions) -ref_data_mappability_bed = get_file_object(params.ref_data_mappability_bed) +samplesheet = get_file_object(params.input) +gridss_config = get_file_object(params.gridss_config) // Set processes to run processes = Processes.set_processes(params.mode, log) - processes_include = Processes.get_process_list(params.processes_include, log) processes_exclude = Processes.get_process_list(params.processes_exclude, log) Processes.check_include_exclude_list(processes_include, processes_exclude, log) @@ -212,6 +133,10 @@ workflow ONCOANALYSER { // channel: [val(meta)] ch_inputs = WorkflowOncoanalyser.prepare_inputs(CHECK_SAMPLESHEET.out, workflow.stubRun, log) + // Set up reference data and unpack HMF data map for convenience + PREPARE_REFERENCE(run) + hmf_data = PREPARE_REFERENCE.out.hmf_data + // Set up channel with common inputs for several processes if (run.amber || run.cobalt || run.pave || run.lilac || run.teal) { @@ -248,12 +173,12 @@ workflow ONCOANALYSER { } ISOFOX( ch_isofox_inputs, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_ensembl_data_dir, - ref_data_rna_exp_counts, - ref_data_rna_exp_gc_ratios, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_version, + hmf_data.ensembl_data_dir, + hmf_data.isofox_exp_counts, + hmf_data.isofox_exp_gc_ratios, ) ch_versions = ch_versions.mix(ISOFOX.out.versions) ch_isofox_out = ch_isofox_out.mix(ISOFOX.out.isofox_dir) @@ -313,7 +238,7 @@ workflow ONCOANALYSER { COLLECTWGSMETRICS( ch_cwm_inputs, - ref_data_genome_fa, + PREPARE_REFERENCE.out.genome_fasta, ) ch_versions = ch_versions.mix(COLLECTWGSMETRICS.out.versions) @@ -341,8 +266,8 @@ workflow ONCOANALYSER { AMBER( ch_bams_and_indices, - ref_data_genome_version, - ref_data_amber_loci, + PREPARE_REFERENCE.out.genome_version, + hmf_data.amber_loci, ) ch_versions = ch_versions.mix(AMBER.out.versions) ch_amber_out = ch_amber_out.mix(AMBER.out.amber_dir) @@ -357,7 +282,7 @@ workflow ONCOANALYSER { COBALT( ch_bams_and_indices, - ref_data_cobalt_gc_profile, + hmf_data.cobalt_gc_profile, ) ch_versions = ch_versions.mix(COBALT.out.versions) ch_cobalt_out = ch_cobalt_out.mix(COBALT.out.cobalt_dir) @@ -374,16 +299,16 @@ workflow ONCOANALYSER { GRIDSS_SVPREP( ch_inputs, gridss_config, - ref_data_genome_fa, - ref_data_genome_version, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ref_data_sv_prep_blacklist, - ref_data_known_fusions, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_version, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_bwa_index, + PREPARE_REFERENCE.out.genome_bwa_index_image, + PREPARE_REFERENCE.out.genome_gridss_index, + hmf_data.gridss_blacklist, + hmf_data.sv_prep_blacklist, + hmf_data.known_fusions, ) ch_versions = ch_versions.mix(GRIDSS_SVPREP.out.versions) ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP.out.results) @@ -397,13 +322,13 @@ workflow ONCOANALYSER { GRIDSS( ch_gridss_inputs, gridss_config, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_bwa_index, + PREPARE_REFERENCE.out.genome_bwa_index_image, + PREPARE_REFERENCE.out.genome_gridss_index, + hmf_data.gridss_blacklist, ) ch_versions = ch_versions.mix(GRIDSS.out.versions) ch_gridss_out = ch_gridss_out.mix(GRIDSS.out.results) @@ -421,13 +346,13 @@ workflow ONCOANALYSER { GRIPSS( run.gridss ? ch_gridss_out : WorkflowOncoanalyser.get_input(ch_inputs, ['gridss_vcf', 'tumor_normal']), - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_gridss_breakend_pon, - ref_data_gridss_breakpoint_pon, - ref_data_known_fusions, - ref_data_repeat_masker_file, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_version, + hmf_data.gridss_breakend_pon, + hmf_data.gridss_breakpoint_pon, + hmf_data.known_fusions, + hmf_data.repeat_masker_file, ) ch_versions = ch_versions.mix(GRIPSS.out.versions) ch_gripss_germline_out = ch_gripss_germline_out.mix(GRIPSS.out.germline) @@ -445,18 +370,18 @@ workflow ONCOANALYSER { SAGE( ch_bams_and_indices, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_sage_known_hotspots_germline, - ref_data_sage_known_hotspots_somatic, - ref_data_sage_coding_panel, - ref_data_sage_high_confidence, - ref_data_sage_pon_file, - ref_data_mappability_bed, - ref_data_driver_gene_panel, - ref_data_ensembl_data_dir, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_version, + hmf_data.sage_known_hotspots_germline, + hmf_data.sage_known_hotspots_somatic, + hmf_data.sage_coding_panel, + hmf_data.sage_high_confidence, + hmf_data.sage_pon_file, + hmf_data.mappability_bed, + hmf_data.driver_gene_panel, + hmf_data.ensembl_data_dir, ) ch_versions = ch_versions.mix(SAGE.out.versions) ch_sage_germline_out = ch_sage_germline_out.mix(SAGE.out.germline) @@ -475,16 +400,16 @@ workflow ONCOANALYSER { PAVE( run.sage ? ch_sage_germline_out : WorkflowOncoanalyser.get_input(ch_inputs, ['sage_vcf', 'normal']), run.sage ? ch_sage_somatic_out : WorkflowOncoanalyser.get_input(ch_inputs, ['sage_vcf', 'tumor']), - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_sage_pon_file, - ref_data_sage_blacklist_bed, - ref_data_sage_blacklist_vcf, - ref_data_clinvar_vcf, - ref_data_mappability_bed, - ref_data_driver_gene_panel, - ref_data_ensembl_data_dir, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_version, + hmf_data.sage_pon_file, + hmf_data.sage_blacklist_bed, + hmf_data.sage_blacklist_vcf, + hmf_data.clinvar_vcf, + hmf_data.mappability_bed, + hmf_data.driver_gene_panel, + hmf_data.ensembl_data_dir, ) ch_versions = ch_versions.mix(PAVE.out.versions) ch_pave_germline_out = ch_pave_germline_out.mix(PAVE.out.germline) @@ -527,16 +452,16 @@ workflow ONCOANALYSER { PURPLE( ch_purple_inputs, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_cobalt_gc_profile, - ref_data_sage_known_hotspots_somatic, - ref_data_sage_known_hotspots_germline, - ref_data_driver_gene_panel, - ref_data_ensembl_data_dir, - ref_data_purple_germline_del, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_version, + hmf_data.cobalt_gc_profile, + hmf_data.sage_known_hotspots_somatic, + hmf_data.sage_known_hotspots_germline, + hmf_data.driver_gene_panel, + hmf_data.ensembl_data_dir, + hmf_data.purple_germline_del, ) ch_versions = ch_versions.mix(PURPLE.out.versions) ch_purple_out = ch_purple_out.mix(PURPLE.out.purple_dir) @@ -571,10 +496,10 @@ workflow ONCOANALYSER { LILAC( ch_bams_and_indices, run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(['purple_dir', 'tumor_normal']), - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_lilac_resource_dir, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_version, + hmf_data.lilac_resource_dir, ) ch_versions = ch_versions.mix(LILAC.out.versions) } @@ -591,14 +516,14 @@ workflow ONCOANALYSER { VIRUSBREAKEND( ch_virusbreakend_inputs, - ref_data_virusbreakenddb, gridss_config, - ref_data_genome_fa, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_bwa_index, + PREPARE_REFERENCE.out.genome_bwa_index_image, + PREPARE_REFERENCE.out.genome_gridss_index, + hmf_data.virusbreakenddb, ) ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) @@ -619,8 +544,8 @@ workflow ONCOANALYSER { VIRUSINTERPRETER( ch_virusinterpreter_inputs, - ref_data_virus_taxonomy, - ref_data_virus_reporting, + hmf_data.virus_taxonomy, + hmf_data.virus_reporting, ) ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) ch_virusinterpreter_out = ch_virusinterpreter_out.mix(VIRUSINTERPRETER.out.virusinterpreter_dir) @@ -639,12 +564,12 @@ workflow ONCOANALYSER { LINX( run.gripss ? ch_gripps_germline_hard : WorkflowOncoanalyser.get_input(ch_inputs, ['vcf_sv_gripss_hard', 'normal']), run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), - ref_data_genome_version, - ref_data_linx_fragile_sites, - ref_data_linx_lines, - ref_data_ensembl_data_dir, - ref_data_known_fusion_data, - ref_data_driver_gene_panel, + PREPARE_REFERENCE.out.genome_version, + hmf_data.linx_fragile_sites, + hmf_data.linx_lines, + hmf_data.ensembl_data_dir, + hmf_data.known_fusion_data, + hmf_data.driver_gene_panel, ) ch_versions = ch_versions.mix(LINX.out.versions) ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX.out.somatic) @@ -697,7 +622,7 @@ workflow ONCOANALYSER { CUPPA_CLASSIFIER( ch_cuppa_inputs, - ref_data_cuppa, + hmf_data.cuppa, ) ch_versions = ch_versions.mix(CUPPA_CLASSIFIER.out.versions) From d979b4229572b76cd85e21c6e37fc1dc4832885d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 2 Dec 2022 09:59:10 +1100 Subject: [PATCH 004/562] Add Sigs module --- conf/base.config | 4 +++ conf/modules.config | 9 +++++ lib/Constants.groovy | 2 ++ modules/local/custom/hmf_reference/main.nf | 3 ++ modules/local/sigs/Dockerfile | 22 +++++++++++++ modules/local/sigs/main.nf | 38 ++++++++++++++++++++++ nextflow_schema.json | 7 ++++ subworkflows/local/prepare_reference.nf | 2 ++ workflows/oncoanalyser.nf | 21 ++++++++++++ 9 files changed, 108 insertions(+) create mode 100644 modules/local/sigs/Dockerfile create mode 100644 modules/local/sigs/main.nf diff --git a/conf/base.config b/conf/base.config index e6b629f2..ce4f787c 100644 --- a/conf/base.config +++ b/conf/base.config @@ -122,6 +122,10 @@ process { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } + withName:'SIGS' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 4.GB, 'memory' ) } + } withName:'SLICE' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } diff --git a/conf/modules.config b/conf/modules.config index 32df7844..54d55ea5 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -174,6 +174,15 @@ process { ] } + withName: 'SIGS' { + ext.jarPath = '/opt/sigs/sigs.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + ] + } + withName: 'TEAL' { ext.jarPath = '/opt/teal/teal.jar' publishDir = [ diff --git a/lib/Constants.groovy b/lib/Constants.groovy index eb0fe44c..13b85bfc 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -28,6 +28,7 @@ class Constants { PAVE, PURPLE, SAGE, + SIGS, SVPREP, TEAL, VIRUSINTERPRETER, @@ -62,6 +63,7 @@ class Constants { SAGE_KNOWN_HOTSPOTS_SOMATIC: 'sage/KnownHotspots.somatic.vcf.gz', SAGE_PON_FILE: 'sage/SageGermlinePon.98x.tsv.gz', CLINVAR_VCF: 'sage/clinvar.vcf.gz', + SIGS_SIGNATURES: 'sigs/snv_cosmic_signatures.csv', LILAC_RESOURCE_DIR: 'lilac/', VIRUSBREAKENDDB: 'virusbreakend/', VIRUSINTERPRETER_TAXONOMY: 'virusinterpreter/taxonomy_db.tsv', diff --git a/modules/local/custom/hmf_reference/main.nf b/modules/local/custom/hmf_reference/main.nf index a28e9999..1caea133 100644 --- a/modules/local/custom/hmf_reference/main.nf +++ b/modules/local/custom/hmf_reference/main.nf @@ -55,6 +55,9 @@ process HMF_REFERENCE { touch output/sage/SageGermlinePon.98x.tsv.gz touch output/sage/clinvar.vcf.gz + mkdir -p output/sigs/ + touch output/sigs/snv_cosmic_signatures.csv + mkdir -p output/lilac/ mkdir -p output/virusbreakend/ diff --git a/modules/local/sigs/Dockerfile b/modules/local/sigs/Dockerfile new file mode 100644 index 00000000..10014b84 --- /dev/null +++ b/modules/local/sigs/Dockerfile @@ -0,0 +1,22 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/sigs/ && \ + wget -O /opt/sigs/sigs.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sigs-v1.1/sigs_v1.1.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'openjdk >=8' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf new file mode 100644 index 00000000..885fbb05 --- /dev/null +++ b/modules/local/sigs/main.nf @@ -0,0 +1,38 @@ +process SIGS { + container 'docker.io/scwatts/sigs:1.1--0' + + input: + tuple val(meta), path(smlv_vcf) + path signatures_file + + output: + tuple val(meta), path('sigs/'), emit: sigs_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar ${task.ext.jarPath} \\ + -sample ${meta.id} \\ + -signatures_file ${signatures_file} \\ + -output_dir ./sigs/ + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sigs: 1.1 + END_VERSIONS + """ + + stub: + """ + mkdir sigs/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/nextflow_schema.json b/nextflow_schema.json index ec50a313..937af534 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -327,6 +327,13 @@ "description": "Path to somatic SAGE Known Hotspots file.", "fa_icon": "far fa-file-code" }, + "ref_data_sigs_signatures": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to signature definition file.", + "fa_icon": "far fa-file-code" + }, "ref_data_known_fusions": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index df0cf42c..10e95336 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -143,6 +143,8 @@ def create_hmf_data_map(hmf_bundle_dir, params_only) { 'sage_known_hotspots_somatic': get_hmf_data_file_object('ref_data_sage_known_hotspots_somatic', 'SAGE_KNOWN_HOTSPOTS_SOMATIC', hmf_bundle_dir, params_only), 'sage_pon_file': get_hmf_data_file_object('ref_data_sage_pon_file', 'SAGE_PON_FILE', hmf_bundle_dir, params_only), 'clinvar_vcf': get_hmf_data_file_object('ref_data_clinvar_vcf', 'CLINVAR_VCF', hmf_bundle_dir, params_only), + // SIGS + 'sigs_signatures': get_hmf_data_file_object('ref_data_sigs_signatures', 'SIGS_SIGNATURES', hmf_bundle_dir, params_only), // LILAC 'lilac_resource_dir': get_hmf_data_file_object('ref_data_lilac_resource_dir', 'LILAC_RESOURCE_DIR', hmf_bundle_dir, params_only), // VIRUSBreakend diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index fcf3af17..c15fd32a 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -65,6 +65,7 @@ include { CUPPA_VISUALISER } from '../modules/local/cuppa/visualiser/main' include { ISOFOX } from '../modules/local/isofox/main' include { LINX_REPORT } from '../modules/local/gpgr/linx_report/main' include { PURPLE } from '../modules/local/purple/main' +include { SIGS } from '../modules/local/sigs/main' include { TEAL } from '../modules/local/teal/main' include { VIRUSBREAKEND } from '../modules/local/virusbreakend/main' include { VIRUSINTERPRETER } from '../modules/local/virusinterpreter/main' @@ -467,6 +468,26 @@ workflow ONCOANALYSER { ch_purple_out = ch_purple_out.mix(PURPLE.out.purple_dir) } + // + // MODULE: Run SIGS to fit somatic smlv to signature definitions + // + if (run.sigs) { + // channel: [val(meta), purple_dir] + ch_sigs_inputs_purple_dir = run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']) + // channel: [val(meta), smlv_vcf] + ch_sigs_inputs = ch_sigs_inputs_purple_dir + .map { meta, purple_dir -> + def smlv_vcf = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.somatic.vcf.gz") + return [meta, smlv_vcf] + } + + SIGS( + ch_sigs_inputs, + hmf_data.sigs_signatures, + ) + ch_versions = ch_versions.mix(SIGS.out.versions) + } + // // MODULE: Run TEAL to characterise teleomeres // From 1e99732f7cedb421ed2d2512ee050b7e4551f1cd Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 2 Dec 2022 09:59:22 +1100 Subject: [PATCH 005/562] Add CHORD module --- conf/base.config | 4 ++ conf/modules.config | 8 +++ lib/Constants.groovy | 1 + modules/local/chord/Dockerfile | 36 ++++++++++++ .../chord/assets/extractSigPredictHRD.R.patch | 56 +++++++++++++++++++ modules/local/chord/main.nf | 43 ++++++++++++++ workflows/oncoanalyser.nf | 22 ++++++++ 7 files changed, 170 insertions(+) create mode 100644 modules/local/chord/Dockerfile create mode 100644 modules/local/chord/assets/extractSigPredictHRD.R.patch create mode 100644 modules/local/chord/main.nf diff --git a/conf/base.config b/conf/base.config index ce4f787c..ddbef918 100644 --- a/conf/base.config +++ b/conf/base.config @@ -126,6 +126,10 @@ process { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 4.GB, 'memory' ) } } + withName:'CHORD' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 4.GB, 'memory' ) } + } withName:'SLICE' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } diff --git a/conf/modules.config b/conf/modules.config index 54d55ea5..76907405 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -183,6 +183,14 @@ process { ] } + withName: 'CHORD' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/chord/${filename}" }, + ] + } + withName: 'TEAL' { ext.jarPath = '/opt/teal/teal.jar' publishDir = [ diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 13b85bfc..7fb963c0 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -17,6 +17,7 @@ class Constants { static enum Process { AMBER, + CHORD, COBALT, COLLECTWGSMETRICS, CUPPA, diff --git a/modules/local/chord/Dockerfile b/modules/local/chord/Dockerfile new file mode 100644 index 00000000..747c73f5 --- /dev/null +++ b/modules/local/chord/Dockerfile @@ -0,0 +1,36 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y patch procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +ARG GH_BASE_URL=https://raw.githubusercontent.com/hartwigmedical/pipeline5 +COPY assets/extractSigPredictHRD.R.patch /tmp/ +RUN \ + mkdir -p /opt/chord/ && \ + wget -P /opt/chord/ ${GH_BASE_URL}/v5.30/cluster/images/extractSigPredictHRD.R && \ + patch -p1 /opt/chord/extractSigPredictHRD.R /tmp/extractSigPredictHRD.R.patch && \ + rm /tmp/extractSigPredictHRD.R.patch && \ + chmod 755 /opt/chord/extractSigPredictHRD.R + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + bioconductor-bsgenome \ + bioconductor-bsgenome.hsapiens.ucsc.hg19 \ + bioconductor-bsgenome.hsapiens.ucsc.hg38 \ + r-base \ + r-devtools \ + r-randomforest && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}:/opt/chord/" + +RUN \ + R -e "devtools::install_github('https://github.com/UMCUGenetics/mutSigExtractor', ref='1.14')" && \ + R -e "devtools::install_github('https://github.com/UMCUGenetics/CHORD', ref='2.00')" diff --git a/modules/local/chord/assets/extractSigPredictHRD.R.patch b/modules/local/chord/assets/extractSigPredictHRD.R.patch new file mode 100644 index 00000000..b4dc9508 --- /dev/null +++ b/modules/local/chord/assets/extractSigPredictHRD.R.patch @@ -0,0 +1,56 @@ +--- a/extractSigPredictHRD.R ++++ b/extractSigPredictHRD.R +@@ -4,12 +4,11 @@ options(stringsAsFactors=F) # to avoid invalid factor level warning + + args <- commandArgs(TRUE) + +-chordToolDir <- args[1] +- workingDir <- args[2] +- sampleName <- args[3] +- snvIndVcf <- args[4] +- svVcf <- args[5] +-refGenomeVsn <- args[6] # RG_37 or RG_38 ++ workingDir <- args[1] ++ sampleName <- args[2] ++ snvIndVcf <- args[3] ++ svVcf <- args[4] ++refGenomeVsn <- args[5] # RG_37 or RG_38 + sigOutTxt <- paste0( workingDir, '/', sampleName, '_chord_signatures.txt') + prdOutTxt <- paste0( workingDir, '/', sampleName, '_chord_prediction.txt') + +@@ -18,8 +17,8 @@ setwd(workingDir) + + suppressPackageStartupMessages(library('devtools')) + suppressPackageStartupMessages(library('randomForest')) +-suppressPackageStartupMessages(load_all(paste0(chordToolDir, '/mutSigExtractor-1.14'))) +-suppressPackageStartupMessages(load_all(paste0(chordToolDir, '/CHORD-2.00'))) ++suppressPackageStartupMessages(library('mutSigExtractor')) ++suppressPackageStartupMessages(library('CHORD')) + + cat("[INFO] Package NamespaceVersions after loading:\n") + for (pkgName in c("mutSigExtractor", "CHORD")){ +@@ -28,14 +27,14 @@ for (pkgName in c("mutSigExtractor", "CHORD")){ + } + + ## Convert genome name to BSGenome name +-if (refGenomeVsn == "RG_37") { ++if (refGenomeVsn == "37") { + suppressPackageStartupMessages(library(BSgenome.Hsapiens.UCSC.hg19)) + refGenome <- BSgenome.Hsapiens.UCSC.hg19 +-} else if (refGenomeVsn == "RG_38") { ++} else if (refGenomeVsn == "38") { + suppressPackageStartupMessages(library(BSgenome.Hsapiens.UCSC.hg38)) + refGenome <- BSgenome.Hsapiens.UCSC.hg38 + } else { +- stop("Unsupported ref genome version: ", refGenomeVsn," (should be HG37 or HG38)\n") ++ stop("Unsupported ref genome version: ", refGenomeVsn," (should be 37 or 38)\n") + } + + cat("[INFO] CHORD Settings:\n") +@@ -73,4 +72,4 @@ write.table(signatures, file=sigOutTxt, sep="\t") + cat("[INFO] Writing output file:", prdOutTxt,"\n") + write.table(prediction, file=prdOutTxt, sep="\t", quote=FALSE, row.names=FALSE) + +-cat("[INFO] FINISHED CHORD signature extraction and HRD prediction\n") +\ No newline at end of file ++cat("[INFO] FINISHED CHORD signature extraction and HRD prediction\n") diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf new file mode 100644 index 00000000..05b8e0ca --- /dev/null +++ b/modules/local/chord/main.nf @@ -0,0 +1,43 @@ +process CHORD { + container 'docker.io/scwatts/chord:2.00--0' + + input: + tuple val(meta), path(smlv_vcf), path(sv_vcf) + val genome_ver + + output: + path '*_chord_signatures.txt', emit: signatures + path '*_chord_prediction.txt', emit: prediction + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + extractSigPredictHRD.R \\ + ./ \\ + ${meta.get(['sample_name', 'tumor'])} \\ + ${smlv_vcf} \\ + ${sv_vcf} \\ + ${genome_ver} \\ + ${meta.get(['sample_name', 'tumor'])}_chord_signatures.txt \\ + ${meta.get(['sample_name', 'tumor'])}_chord_prediction.txt + + # NOTE(SW): hard coded since there is no reliable way to obtain version information. + cat <<-END_VERSIONS > versions.yml + "${task.process}": + CHORD: \$(R -s -e "message(packageVersion('CHORD'))") + mutSigExtractor: \$(R -s -e "message(packageVersion('mutSigExtractor'))") + END_VERSIONS + """ + + stub: + """ + touch ${meta.get(['sample_name', 'tumor'])}_chord_signatures.txt + touch ${meta.get(['sample_name', 'tumor'])}_chord_prediction.txt + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index c15fd32a..831a3c43 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -59,6 +59,7 @@ if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input sample include { CHECK_SAMPLESHEET } from '../modules/local/check_samplesheet/main' include { AMBER } from '../modules/local/amber/main' +include { CHORD } from '../modules/local/chord/main' include { COBALT } from '../modules/local/cobalt/main' include { CUPPA_CLASSIFIER } from '../modules/local/cuppa/classifier/main' include { CUPPA_VISUALISER } from '../modules/local/cuppa/visualiser/main' @@ -488,6 +489,27 @@ workflow ONCOANALYSER { ch_versions = ch_versions.mix(SIGS.out.versions) } + // + // MODULE: Run CHORD to predict HR deficiency status + // + if (run.chord) { + // channel: [val(meta), purple_dir] + ch_chord_inputs_purple_dir = run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']) + // channel: [val(meta), smlv_vcf, sv_vcf] + ch_chord_inputs = ch_chord_inputs_purple_dir + .map { meta, purple_dir -> + def smlv_vcf = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.somatic.vcf.gz") + def sv_vcf = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz") + return [meta, smlv_vcf, sv_vcf] + } + + CHORD( + ch_chord_inputs, + PREPARE_REFERENCE.out.genome_version, + ) + ch_versions = ch_versions.mix(CHORD.out.versions) + } + // // MODULE: Run TEAL to characterise teleomeres // From 1a10c975190c436debffe7cdbdb9e2549cebd913 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 2 Dec 2022 17:00:29 +1100 Subject: [PATCH 006/562] Module updates and input overhaul --- conf/base.config | 4 +- conf/modules.config | 2 - lib/WorkflowGridss.groovy | 104 ----- lib/WorkflowLilac.groovy | 39 +- lib/WorkflowOncoanalyser.groovy | 33 ++ modules/local/amber/main.nf | 18 +- modules/local/chord/main.nf | 13 +- modules/local/cobalt/main.nf | 18 +- modules/local/cuppa/classifier/main.nf | 8 +- modules/local/cuppa/visualiser/main.nf | 10 +- modules/local/custom/hmf_reference/main.nf | 4 + .../lilac_extract_and_index_contig/main.nf | 4 +- .../custom/lilac_realign_reads_lilac/main.nf | 4 +- modules/local/custom/lilac_slice/main.nf | 8 +- modules/local/gpgr/linx_report/main.nf | 10 +- modules/local/gridss/assemble/main.nf | 20 +- modules/local/gridss/call/main.nf | 22 +- modules/local/gridss/index/main.nf | 13 +- modules/local/gridss/preprocess/main.nf | 14 +- modules/local/gripss/germline/main.nf | 28 +- modules/local/gripss/somatic/main.nf | 30 +- modules/local/isofox/main.nf | 8 +- modules/local/lilac/main.nf | 30 +- modules/local/linx/germline/main.nf | 22 +- modules/local/linx/somatic/main.nf | 26 +- modules/local/linx/visualiser/main.nf | 20 +- modules/local/pave/germline/main.nf | 34 +- modules/local/pave/somatic/main.nf | 26 +- modules/local/purple/main.nf | 42 +- modules/local/sage/germline/main.nf | 38 +- modules/local/sage/somatic/main.nf | 36 +- modules/local/sigs/main.nf | 3 + modules/local/svprep/assemble/main.nf | 21 +- modules/local/svprep/call/main.nf | 23 +- modules/local/svprep/depth_annotator/main.nf | 11 +- modules/local/svprep/preprocess/main.nf | 13 +- modules/local/svprep/svprep/main.nf | 21 +- modules/local/teal/main.nf | 16 +- modules/local/virusbreakend/main.nf | 6 +- modules/local/virusinterpreter/main.nf | 5 +- subworkflows/local/gridss_svprep.nf | 57 +-- subworkflows/local/gripss.nf | 12 +- subworkflows/local/lilac.nf | 56 ++- subworkflows/local/sage.nf | 2 +- workflows/oncoanalyser.nf | 392 +++++++++++++++--- 45 files changed, 813 insertions(+), 513 deletions(-) delete mode 100755 lib/WorkflowGridss.groovy diff --git a/conf/base.config b/conf/base.config index ddbef918..91edae56 100644 --- a/conf/base.config +++ b/conf/base.config @@ -9,8 +9,7 @@ */ process { - - // TODO nf-core: Check the defaults for all processes + // Defaults for all processes cpus = { check_max( 1 * task.attempt, 'cpus' ) } memory = { check_max( 6.GB * task.attempt, 'memory' ) } time = { check_max( 4.h * task.attempt, 'time' ) } @@ -24,7 +23,6 @@ process { // These labels are used and recognised by default in DSL2 files hosted on nf-core/modules. // If possible, it would be nice to keep the same label naming convention when // adding in your local modules too. - // TODO nf-core: Customise requirements for specific processes. // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors withLabel:process_single { cpus = { check_max( 1 , 'cpus' ) } diff --git a/conf/modules.config b/conf/modules.config index 76907405..99dc61cd 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -146,8 +146,6 @@ process { } withName: 'COLLECTWGSMETRICS' { - tag = { "${task.index}" } - label = null publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, diff --git a/lib/WorkflowGridss.groovy b/lib/WorkflowGridss.groovy deleted file mode 100755 index d3e26991..00000000 --- a/lib/WorkflowGridss.groovy +++ /dev/null @@ -1,104 +0,0 @@ -// -// This file holds several functions specific to the subworkflows/gridss.nf in the nf-core/oncoanalyser pipeline -// - -class WorkflowGridss { - - public static get_inputs(ch) { - // channel (a): [val(meta_gridss), bam, bai, sv] - // channel (b): [val(meta_gridss), bam] - def sample_types = ['tumor', 'normal'] - def d = ch - .flatMap { meta -> - sample_types - .collect { sample_type -> - def key_sname = ['sample_name', sample_type] - def key_bam = ['bam_wgs', sample_type] - def key_sv = ['vcf_sv', sample_type] - if (! meta.containsKey(key_sname) && ! meta.containsKey(key_bam)) { - return [] - } - def meta_gridss = [ - id: meta.get(key_sname), - group_key: meta.id, - sample_type: sample_type, - subject_name: meta.subject_name, - ] - def v = [meta_gridss, meta.get(key_bam)] - def has_sv = meta.containsKey(key_sv) - if (has_sv) { - v = v + ["${meta.get(key_bam)}.bai", meta.get(key_sv)] - } - return [has_sv, v] - } - } - return d - } - - public static get_unique_input_files(ch) { - // channel (a): [val(meta_gridss), bam, bai, sv] - // channel (b): [val(meta_gridss), bam] - def d = ch - .map { [it[1..-1], it[0]] } - // NOTE(SW): number of grouped elements is unknown here but does not block since all inputs - // are derived directly from the samplesheet - .groupTuple() - .map { filepaths, meta_gridsss -> - def (sample_names, ids, sample_types, subject_names) = meta_gridsss - .collect { - [it.id, it.group_key, it.sample_type, it.subject_name] - } - .transpose() - - def sample_name = sample_names.unique(false) - def sample_type = sample_types.unique(false) - def subject_name = subject_names.unique(false) - assert sample_name.size() == 1 - assert sample_type.size() == 1 - assert subject_name.size() == 1 - - def meta_gridss_new = [ - id: ids.join('__'), - id_list: ids, - sample_name: sample_name[0], - sample_type: sample_type[0], - subject_name: subject_name[0], - ] - return [meta_gridss_new, *filepaths] - } - return d - } - - public static get_assemble_inputs(ch) { - // NOTE(SW): elements in the bams, preprocess_dirs, and labels are linked with via consistent ordering - // channel: [val(meta_gridss), [bams], [preprocess_dirs], [labels]] - def d = ch - .map { subject_name, other -> - def data = [:] - def ids = [] as Set - - // NOTE(SW): must determine whether input ordering is determininistic here - - other - .each { meta_gridss, bam, preprocess_dir -> - data.get([meta_gridss.sample_type, 'label'], []) << meta_gridss.sample_name - data.get([meta_gridss.sample_type, 'bam_wgs'], []) << bam - data.get([meta_gridss.sample_type, 'preprocess_dir'], []) << preprocess_dir - ids += meta_gridss.id_list - } - def meta_gridss_new = [ - id: ids.join('__'), - id_list: ids, - ] - - def sample_types = ['normal', 'tumor'] - return [ - meta_gridss_new, - sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'bam_wgs'], []) }, - sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'preprocess_dir'], []) }, - sample_types.inject([]) { d, sample_type -> d + data.get([sample_type, 'label'], []) }, - ] - } - return d - } -} diff --git a/lib/WorkflowLilac.groovy b/lib/WorkflowLilac.groovy index b83e685c..359bb162 100755 --- a/lib/WorkflowLilac.groovy +++ b/lib/WorkflowLilac.groovy @@ -4,8 +4,8 @@ class WorkflowLilac { - public static get_slice_inputs(ch, hla_bed) { - // channel: [val(meta_lilac), bam, bai, bed] + public static get_slice_inputs(ch, ch_slice_bed) { + // channel: [val(meta_lilac), bam, bai] def d = ch .flatMap { meta, tbam, nbam, tbai, nbai -> def sample_types = ['tumor': [tbam, tbai], 'normal': [nbam, nbai]] @@ -15,14 +15,15 @@ class WorkflowLilac { def fps = sample_types[sample_type] def sample_name = meta.get(['sample_name', sample_type]) def meta_lilac = [ + key: meta.id, id: sample_name, sample_type: sample_type, - meta_full: meta, ] - return [meta_lilac, *fps, hla_bed] + return [meta_lilac, *fps] } } - return d + // channel: [val(meta_lilac), bam, bai, bed] + return d.combine(ch_slice_bed) } public static get_unique_input_files(ch) { @@ -30,21 +31,23 @@ class WorkflowLilac { def d = ch .map { [it[1..-1], it[0]] } .groupTuple() - .map { filepaths, meta_lilacs -> - def (meta_fulls, sample_types) = meta_lilacs + .map { filepaths, meta_lilac -> + def (keys, sample_names, sample_types) = meta_lilac .collect { - [it.meta_full, it.sample_type] + [it.key, it.id, it.sample_type] } .transpose() - def sample_type = sample_types.unique(false) - assert sample_type.size() == 1 + def sample_types_unique = sample_types.unique(false) + assert sample_types_unique.size() == 1 + def sample_type = sample_types_unique[0] - def id = meta_fulls.collect { it.id }.join('__') + def key = keys.join('__') def meta_lilac_new = [ - id: "${id}_${sample_type[0]}", - metas_full: meta_fulls, - sample_type: sample_type[0], + keys: keys, + id: sample_names.join('__'), + id_simple: keys.join('__'), + sample_type: sample_type, ] return [meta_lilac_new, *filepaths] } @@ -58,17 +61,19 @@ class WorkflowLilac { .flatMap{ data -> def meta_lilac = data[0] def fps = data[1..-1] - meta_lilac.metas_full.collect { meta -> [meta.id, meta, [meta_lilac.sample_type, *fps]] } + meta_lilac.keys.collect { key -> + return [key, [meta_lilac.sample_type, *fps]] + } } .groupTuple(size: 2) - .map { id, meta, other -> + .map { key, other -> def data = [:] other.each { sample_type, bam, bai -> data[[sample_type, 'bam']] = bam data[[sample_type, 'bai']] = bai } [ - meta[0], + [key: key], data.get(['tumor', 'bam']), data.get(['normal', 'bam']), data.get(['tumor', 'bai']), diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 9966d5cd..7b7e466e 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -206,4 +206,37 @@ class WorkflowOncoanalyser { public static get_input(ch, key) { return ch.map { meta -> [meta, meta.getAt(key)] } } + + public static restore_meta(ch_output, ch_metas) { + // NOTE(SW): ch_output must contain a Map in the first position with a key named 'key' that + // contains the corresponding meta.id value, for example: [val(meta_process), *process_outputs] + + //return Channel.empty() + // .mix( + // // channel: [val(key), val(meta)] + // ch_metas.map { meta -> [meta.id, meta] }, + // // channel: [val(key), list(process_outputs)] + // // NOTE(SW): process meta is discarded + // ch_output.map { [it[0].key, it[1..-1]] }, + // ) + // .groupTuple(size: 2) + // // channel: [meta, *process_outputs] + // .map { it.flatten()[1..-1] } + + //def ch_left = ch_metas.map { meta -> [meta.id, meta] } + //def ch_right = ch_output.map { [it[0].key, it[1..-1]] } + //return ch_left + // .join(ch_right, failOnDuplicate: true) + // .map { it[1..-1] } + + def ch_source = ch_metas.map { meta -> [meta.id, meta] } + def ch_target = ch_output.map { [it[0].key, it[1..-1]] } + return ch_source + .cross(ch_target) + .map { d_meta, d_outputs -> + def (skey, meta) = d_meta + def (dkey, outputs) = d_outputs + return [meta, *outputs] + } + } } diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index 9d4efb55..da3f0acd 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -1,5 +1,7 @@ process AMBER { - //conda (params.enable_conda ? "bioconda::hmftools-amber=3.9" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/amber:3.9--3' input: @@ -20,16 +22,16 @@ process AMBER { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -tumor "${meta.get(['sample_name', 'tumor'])}" \\ - -tumor_bam "${tumor_bam}" \\ - -reference "${meta.get(['sample_name', 'normal'])}" \\ - -reference_bam "${normal_bam}" \\ + -tumor ${meta.tumor_id} \\ + -tumor_bam ${tumor_bam} \\ + -reference ${meta.normal_id} \\ + -reference_bam ${normal_bam} \\ -ref_genome_version ${ref_genome_ver} \\ -output_dir amber/ \\ - -threads "${task.cpus}" \\ - -loci "${loci}" + -threads ${task.cpus} \\ + -loci ${loci} # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf index 05b8e0ca..851c2742 100644 --- a/modules/local/chord/main.nf +++ b/modules/local/chord/main.nf @@ -1,4 +1,7 @@ process CHORD { + tag "${meta.id}" + label 'process_low' + container 'docker.io/scwatts/chord:2.00--0' input: @@ -19,12 +22,12 @@ process CHORD { """ extractSigPredictHRD.R \\ ./ \\ - ${meta.get(['sample_name', 'tumor'])} \\ + ${meta.id} \\ ${smlv_vcf} \\ ${sv_vcf} \\ ${genome_ver} \\ - ${meta.get(['sample_name', 'tumor'])}_chord_signatures.txt \\ - ${meta.get(['sample_name', 'tumor'])}_chord_prediction.txt + ${meta.id}_chord_signatures.txt \\ + ${meta.id}_chord_prediction.txt # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml @@ -36,8 +39,8 @@ process CHORD { stub: """ - touch ${meta.get(['sample_name', 'tumor'])}_chord_signatures.txt - touch ${meta.get(['sample_name', 'tumor'])}_chord_prediction.txt + touch ${meta.id}_chord_signatures.txt + touch ${meta.id}_chord_prediction.txt echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index 7a0ceb9d..4c91e657 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -1,5 +1,7 @@ process COBALT { - //conda (params.enable_conda ? "bioconda::hmftools-cobalt=1.13" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/cobalt:1.13--1' input: @@ -19,15 +21,15 @@ process COBALT { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -tumor "${meta.get(['sample_name', 'tumor'])}" \\ - -tumor_bam "${tumor_bam}" \\ - -reference "${meta.get(['sample_name', 'normal'])}" \\ - -reference_bam "${normal_bam}" \\ + -tumor ${meta.tumor_id} \\ + -tumor_bam ${tumor_bam} \\ + -reference ${meta.normal_id} \\ + -reference_bam ${normal_bam} \\ -output_dir cobalt/ \\ - -threads "${task.cpus}" \\ - -gc_profile "${gc_profile}" + -threads ${task.cpus} \\ + -gc_profile ${gc_profile} # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index 5deaa9d3..7a593d0b 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -1,4 +1,7 @@ process CUPPA_CLASSIFIER { + tag "${meta.id}" + label 'process_low' + container 'docker.io/scwatts/cuppa:1.7--0' input: @@ -26,7 +29,7 @@ process CUPPA_CLASSIFIER { -jar ${task.ext.jarPath} \\ -categories ALL \\ -ref_data_dir ${reference_data} \\ - -sample_data ${meta.get(['sample_name', 'tumor'])} \\ + -sample_data ${meta.id} \\ -sample_data_dir sample_data/ \\ -output_dir ./ @@ -39,8 +42,7 @@ process CUPPA_CLASSIFIER { stub: """ - touch ${meta.get(['sample_name', 'tumor'])}.cup.data.csv + touch ${meta.id}.cup.data.csv echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } - diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf index d21e03cb..4088bd52 100644 --- a/modules/local/cuppa/visualiser/main.nf +++ b/modules/local/cuppa/visualiser/main.nf @@ -1,4 +1,7 @@ process CUPPA_VISUALISER { + tag "${meta.id}" + label 'process_low' + container 'docker.io/scwatts/cuppa:1.7--0' input: @@ -17,7 +20,7 @@ process CUPPA_VISUALISER { """ python ${task.ext.pythonPath} \\ - -sample ${meta.get(['sample_name', 'tumor'])} \\ + -sample ${meta.id} \\ -sample_data ${cuppa_csv} \\ -output_dir ./ @@ -30,9 +33,8 @@ process CUPPA_VISUALISER { stub: """ - touch ${meta.get(['sample_name', 'tumor'])}.cuppa.chart.png - touch ${meta.get(['sample_name', 'tumor'])}.cuppa.conclusion.txt + touch ${meta.id}.cuppa.chart.png + touch ${meta.id}.cuppa.conclusion.txt echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } - diff --git a/modules/local/custom/hmf_reference/main.nf b/modules/local/custom/hmf_reference/main.nf index 1caea133..8312985e 100644 --- a/modules/local/custom/hmf_reference/main.nf +++ b/modules/local/custom/hmf_reference/main.nf @@ -1,4 +1,6 @@ process HMF_REFERENCE { + label 'process_single' + container 'public.ecr.aws/ubuntu/ubuntu:20.04_stable' input: @@ -59,6 +61,8 @@ process HMF_REFERENCE { touch output/sigs/snv_cosmic_signatures.csv mkdir -p output/lilac/ + touch output/lilac/hla.38.alt.umccr.bed + touch output/lilac/hla.38_noalt.bed mkdir -p output/virusbreakend/ diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index 8edd1f60..23492a67 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -1,5 +1,7 @@ process EXTRACT_AND_INDEX_CONTIG { - //conda (params.enable_conda ? "bioconda::null" : null) + tag "${meta.id}" + label 'process_single' + container 'docker.io/scwatts/custom-extract_and_index_contig:0.0.1--3' input: diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf index 5d1b2f00..c569a73b 100644 --- a/modules/local/custom/lilac_realign_reads_lilac/main.nf +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -1,5 +1,7 @@ process REALIGN_READS { - //conda (params.enable_conda ? "bioconda::hmftools-lilac=1.2" : null) + tag "${meta.id}" + label 'process_low' + container 'docker.io/scwatts/custom-realign_reads_lilac:0.0.1--3' input: diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index b3496a4a..3a70b216 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -1,5 +1,7 @@ process SLICE { - //conda (params.enable_conda ? "bioconda::samtools:1.15.1" : null) + tag "${meta.id}" + label 'process_single' + container 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' input: @@ -18,11 +20,11 @@ process SLICE { """ samtools view \\ ${args} \\ - -L "${bed}" \\ + -L ${bed} \\ -@${task.cpus} \\ -Obam \\ ${bam} | \\ - samtools sort -T tmp -o "${bam.simpleName}.sliced.bam" + samtools sort -T tmp -o ${bam.simpleName}.sliced.bam samtools index "${bam.simpleName}.sliced.bam" diff --git a/modules/local/gpgr/linx_report/main.nf b/modules/local/gpgr/linx_report/main.nf index 0f9e8885..4098089f 100644 --- a/modules/local/gpgr/linx_report/main.nf +++ b/modules/local/gpgr/linx_report/main.nf @@ -1,5 +1,7 @@ process LINX_REPORT { - //conda (params.enable_conda ? "umccr::r-gpgr==1.4.1" : null) + tag "${meta.id}" + label 'process_single' + container 'ghcr.io/umccr/gpgr:1.4.1' input: @@ -18,10 +20,10 @@ process LINX_REPORT { """ gpgr.R linx \\ ${args} \\ - --sample ${meta.get(['sample_name', 'tumor'])} \\ + --sample ${meta.id} \\ --plot ${linx_visualiser}/ \\ --table ${linx_annotation}/ \\ - --out ${meta.get(['sample_name', 'tumor'])}_linx.html; + --out ${meta.id}_linx.html; cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -32,7 +34,7 @@ process LINX_REPORT { stub: """ - touch ${meta.get(['sample_name', 'tumor'])}_linx.html + touch ${meta.id}_linx.html echo -e '${task.process}:\n stub: noversions\n' > versions.yml """ } diff --git a/modules/local/gridss/assemble/main.nf b/modules/local/gridss/assemble/main.nf index 0f878009..49eee518 100644 --- a/modules/local/gridss/assemble/main.nf +++ b/modules/local/gridss/assemble/main.nf @@ -1,5 +1,7 @@ process ASSEMBLE { - //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/gridss:2.13.2--3' input: @@ -63,20 +65,20 @@ process ASSEMBLE { ${args} \\ --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ - --jar "${task.ext.jarPath}" \\ + --jar ${task.ext.jarPath} \\ --steps assemble \\ - --labels "${labels_arg}" \\ - --reference "${genome_fasta}" \\ - --blacklist "${blacklist}" \\ - --workingdir "${output_dirname}/work" \\ - --assembly "${output_dirname}/sv_assemblies.bam" \\ - --threads "${task.cpus}" \\ + --labels ${labels_arg} \\ + --reference ${genome_fasta} \\ + --blacklist ${blacklist} \\ + --workingdir ${output_dirname}/work \\ + --assembly ${output_dirname}/sv_assemblies.bam \\ + --threads ${task.cpus} \\ ${config_arg} \\ ${bams_arg} cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') END_VERSIONS """ diff --git a/modules/local/gridss/call/main.nf b/modules/local/gridss/call/main.nf index 5809927a..ccf37224 100644 --- a/modules/local/gridss/call/main.nf +++ b/modules/local/gridss/call/main.nf @@ -1,5 +1,7 @@ process CALL { - //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/gridss:2.13.2--3' input: @@ -61,21 +63,21 @@ process CALL { ${args} \\ --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ - --jar "${task.ext.jarPath}" \\ + --jar ${task.ext.jarPath} \\ --steps call \\ - --labels "${labels_arg}" \\ - --reference "${genome_fasta}" \\ - --blacklist "${blacklist}" \\ - --workingdir "${output_dirname}/work/" \\ - --assembly "${output_dirname}/sv_assemblies.bam" \\ - --output "${output_dirname}/sv_vcf.vcf.gz" \\ - --threads "${task.cpus}" \\ + --labels ${labels_arg} \\ + --reference ${genome_fasta} \\ + --blacklist ${blacklist} \\ + --workingdir ${output_dirname}/work/ \\ + --assembly ${output_dirname}/sv_assemblies.bam \\ + --output ${output_dirname}/sv_vcf.vcf.gz \\ + --threads ${task.cpus} \\ ${config_arg} \\ ${bams_arg} cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') END_VERSIONS """ diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index e7c23d7c..63e31b85 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -1,4 +1,7 @@ process INDEX { + tag "${genome_fasta.name}" + label 'process_single' + container 'docker.io/scwatts/gridss:2.13.2--3' input: @@ -38,14 +41,14 @@ process INDEX { -Dsamjdk.buffer_size=4194304 \\ -Dsamjdk.async_io_read_threads=${task.cpus} \\ -cp ${task.ext.jarPath} \\ - REFERENCE_SEQUENCE=${genome_fasta} \\ - CREATE_SEQUENCE_DICTIONARY=${sequence_dict_arg} \\ - CREATE_BWA_INDEX_IMAGE=${bwa_index_image_arg} \\ - CREATE_GRIDSS_REFERENCE_CACHE=${gridss_index_arg} + REFERENCE_SEQUENCE=${genome_fasta} \\ + CREATE_SEQUENCE_DICTIONARY=${sequence_dict_arg} \\ + CREATE_BWA_INDEX_IMAGE=${bwa_index_image_arg} \\ + CREATE_GRIDSS_REFERENCE_CACHE=${gridss_index_arg} cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') END_VERSIONS """ diff --git a/modules/local/gridss/preprocess/main.nf b/modules/local/gridss/preprocess/main.nf index 8f6c9fe3..fd8af8fa 100644 --- a/modules/local/gridss/preprocess/main.nf +++ b/modules/local/gridss/preprocess/main.nf @@ -1,5 +1,7 @@ process PREPROCESS { - //conda (params.enable_conda ? "bioconda::gridss=2.13.2" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/gridss:2.13.2--3' input: @@ -29,18 +31,18 @@ process PREPROCESS { gridss \\ ${args} \\ - --jvmheap "${task.memory.giga}g" \\ - --jar "${task.ext.jarPath}" \\ + --jvmheap ${task.memory.giga}g \\ + --jar ${task.ext.jarPath} \\ --steps preprocess \\ - --reference "${genome_fasta}" \\ + --reference ${genome_fasta} \\ --workingdir gridss_preprocess/ \\ - --threads "${task.cpus}" \\ + --threads ${task.cpus} \\ ${config_arg} \\ ${bam} cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') END_VERSIONS """ diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 977c96c0..b62db6e9 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -1,5 +1,7 @@ process GRIPSS_GERMLINE { - //conda (params.enable_conda ? "bioconda::hmftools-gripss=2.2" : null) + tag "${meta.id}" + label 'process_low' + container 'docker.io/scwatts/gripss:2.3.1--0' input: @@ -27,15 +29,15 @@ process GRIPSS_GERMLINE { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -sample "${meta.get(['sample_name', 'normal'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fasta}" \\ - -pon_sgl_file "${breakend_pon}" \\ - -pon_sv_file "${breakpoint_pon}" \\ - -known_hotspot_file "${known_fusions}" \\ - -vcf "${gridss_vcf}" \\ + -sample ${meta.normal_id} \\ + -ref_genome_version ${genome_ver} \\ + -ref_genome ${genome_fasta} \\ + -pon_sgl_file ${breakend_pon} \\ + -pon_sv_file ${breakpoint_pon} \\ + -known_hotspot_file ${known_fusions} \\ + -vcf ${gridss_vcf} \\ ${repeat_mask_file_arg} \\ -output_dir ./ @@ -48,15 +50,15 @@ process GRIPSS_GERMLINE { stub: """ - cat < ${meta.get(['sample_name', 'normal'])}.gripss.filtered.vcf.gz + cat < ${meta.normal_id}.gripss.filtered.vcf.gz ##fileformat=VCFv4.1 ##contig= #CHROM POS ID REF ALT QUAL FILTER INFO . . . . . . . EOF - touch ${meta.get(['sample_name', 'normal'])}.gripss.filtered.vcf.gz.tbi - touch ${meta.get(['sample_name', 'normal'])}.gripss.vcf.gz - touch ${meta.get(['sample_name', 'normal'])}.gripss.vcf.gz.tbi + touch ${meta.normal_id}.gripss.filtered.vcf.gz.tbi + touch ${meta.normal_id}.gripss.vcf.gz + touch ${meta.normal_id}.gripss.vcf.gz.tbi echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index b652e162..326764c0 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -1,5 +1,7 @@ process GRIPSS_SOMATIC { - //conda (params.enable_conda ? "bioconda::hmftools-gripss=2.2" : null) + tag "${meta.id}" + label 'process_low' + container 'docker.io/scwatts/gripss:2.3.1--0' input: @@ -27,16 +29,16 @@ process GRIPSS_SOMATIC { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -sample "${meta.get(['sample_name', 'tumor'])}" \\ - -reference "${meta.get(['sample_name', 'normal'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fasta}" \\ - -pon_sgl_file "${breakend_pon}" \\ - -pon_sv_file "${breakpoint_pon}" \\ - -known_hotspot_file "${known_fusions}" \\ - -vcf "${gridss_vcf}" \\ + -sample ${meta.tumor_id} \\ + -reference ${meta.normal_id} \\ + -ref_genome_version ${genome_ver} \\ + -ref_genome ${genome_fasta} \\ + -pon_sgl_file ${breakend_pon} \\ + -pon_sv_file ${breakpoint_pon} \\ + -known_hotspot_file ${known_fusions} \\ + -vcf ${gridss_vcf} \\ ${repeat_mask_file_arg} \\ -output_dir ./ @@ -49,15 +51,15 @@ process GRIPSS_SOMATIC { stub: """ - cat < ${meta.get(['sample_name', 'tumor'])}.gripss.filtered.vcf.gz + cat < ${meta.tumor_id}.gripss.filtered.vcf.gz ##fileformat=VCFv4.1 ##contig= #CHROM POS ID REF ALT QUAL FILTER INFO . . . . . . . EOF - touch ${meta.get(['sample_name', 'tumor'])}.gripss.filtered.vcf.gz.tbi - touch ${meta.get(['sample_name', 'tumor'])}.gripss.vcf.gz - touch ${meta.get(['sample_name', 'tumor'])}.gripss.vcf.gz.tbi + touch ${meta.tumor_id}.gripss.filtered.vcf.gz.tbi + touch ${meta.tumor_id}.gripss.vcf.gz + touch ${meta.tumor_id}.gripss.vcf.gz.tbi echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 214779be..bb368418 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -1,7 +1,7 @@ -// NOTE(SW): care must be taken for using exp_counts; only supports read length of 151 bp - - process ISOFOX { + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/isofox:1.5--0' input: @@ -30,7 +30,7 @@ process ISOFOX { -Xmx${task.memory.giga}g \\ -jar ${task.ext.jarPath} \\ ${args} \\ - -sample ${meta.get(['sample_name', 'tumor'])} \\ + -sample ${meta.id} \\ -bam_file ${bam} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 4298c2fd..a2fcf6f7 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -1,5 +1,7 @@ process LILAC { - //conda (params.enable_conda ? "bioconda::hmftools-lilac=1.2" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/lilac:1.4.1--0' input: @@ -27,16 +29,16 @@ process LILAC { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -sample "${sample_name}" \\ + -sample ${sample_name} \\ ${tumor_bam_arg} \\ -reference_bam ${normal_bam} \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fasta}" \\ - -resource_dir "${lilac_resource_dir}" \\ + -ref_genome_version ${genome_ver} \\ + -ref_genome ${genome_fasta} \\ + -resource_dir ${lilac_resource_dir} \\ ${purple_args.replaceAll('\\n', '')} \\ - -threads "${task.cpus}" \\ + -threads ${task.cpus} \\ -output_dir lilac/ # NOTE(SW): hard coded since there is no reliable way to obtain version information. @@ -54,11 +56,11 @@ process LILAC { } def get_sample_name(meta, tumor_bam, normal_bam) { - if (tumor_bam) { - return meta.get(['sample_name', 'tumor']) - } else if (normal_bam) { - return meta.get(['sample_name', 'normal']) - } else { - Sys.exit(1) - } + if (tumor_bam) { + return meta.tumor_id + } else if (normal_bam) { + return meta.normal_id + } else { + Sys.exit(1) + } } diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index a2b2c293..b95b907a 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -1,5 +1,7 @@ process LINX_GERMLINE { - //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) + tag "${meta.id}" + label 'process_low' + container 'docker.io/scwatts/linx:1.22--0' input: @@ -23,22 +25,22 @@ process LINX_GERMLINE { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -sample "${meta.get(['sample_name', 'normal'])}" \\ + -sample ${meta.id} \\ -germline \\ - -ref_genome_version "${genome_ver}" \\ - -sv_vcf "${gripss_sv}" \\ - -fragile_site_file "${fragile_sites}" \\ - -line_element_file "${lines}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ + -ref_genome_version ${genome_ver} \\ + -sv_vcf ${gripss_sv} \\ + -fragile_site_file ${fragile_sites} \\ + -line_element_file ${lines} \\ + -ensembl_data_dir ${ensembl_data_dir} \\ -check_drivers \\ - -driver_gene_panel "${driver_gene_panel}" \\ + -driver_gene_panel ${driver_gene_panel} \\ -output_dir linx_germline/ cat <<-END_VERSIONS > versions.yml "${task.process}": - linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') + linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*LINX version: //') END_VERSIONS """ diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 39b51d7c..e9c3618d 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -1,5 +1,7 @@ process LINX_SOMATIC { - //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) + tag "${meta.id}" + label 'process_low' + container 'docker.io/scwatts/linx:1.22--0' input: @@ -24,24 +26,24 @@ process LINX_SOMATIC { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -sample "${meta.get(['sample_name', 'tumor'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -sv_vcf "${purple_dir}/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz" \\ - -purple_dir "${purple_dir}" \\ - -fragile_site_file "${fragile_sites}" \\ - -line_element_file "${lines}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ + -sample ${meta.id} \\ + -ref_genome_version ${genome_ver} \\ + -sv_vcf ${purple_dir}/${meta.id}.purple.sv.vcf.gz \\ + -purple_dir ${purple_dir} \\ + -fragile_site_file ${fragile_sites} \\ + -line_element_file ${lines} \\ + -ensembl_data_dir ${ensembl_data_dir} \\ -check_fusions \\ - -known_fusion_file "${known_fusion_data}" \\ + -known_fusion_file ${known_fusion_data} \\ -check_drivers \\ - -driver_gene_panel "${driver_gene_panel}" \\ + -driver_gene_panel ${driver_gene_panel} \\ -output_dir linx_somatic/ cat <<-END_VERSIONS > versions.yml "${task.process}": - linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') + linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*LINX version: //') END_VERSIONS """ diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index e611c3a2..cfffa8a0 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -1,5 +1,7 @@ process VISUALISER { - //conda (params.enable_conda ? "bioconda::hmftools-linx=1.21" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/linx:1.22--0' // Lenient caching is required here as the hash of the LINX_SOMATIC @@ -25,21 +27,21 @@ process VISUALISER { """ java \\ -Xmx${task.memory.giga}g \\ - -cp "${task.ext.jarPath}" \\ + -cp ${task.ext.jarPath} \\ com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ ${args} \\ - -sample "${meta.get(['sample_name', 'tumor'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ + -sample ${meta.id} \\ + -ref_genome_version ${genome_ver} \\ + -ensembl_data_dir ${ensembl_data_dir} \\ -plot_out linx_visualiser/plot \\ -data_out linx_visualiser/data \\ - -vis_file_dir "${linx}" \\ - -circos "${task.ext.path_circos}" \\ - -threads "${task.cpus}" + -vis_file_dir ${linx} \\ + -circos ${task.ext.path_circos} \\ + -threads ${task.cpus} cat <<-END_VERSIONS > versions.yml "${task.process}": - linx: \$(java -jar "${task.ext.jarPath}" | sed 's/^.*LINX version: //') + linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*LINX version: //') END_VERSIONS """ diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 484466b6..42e3eb3b 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -1,7 +1,13 @@ -// NOTE(SW): PAVE gnomad filtering is not yet documented but is used in Pipeline5 https://github.com/hartwigmedical/pipeline5/blob/master/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L27-L28 +// NOTE(SW): PAVE gnomad filtering is not yet documented but is used in Pipeline5: +// - cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L27-L28 +// NOTE(SW): use of tumor sample name here is consistent with pipeline5 +// - cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveGermline.java#L35-L39 +// - cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L34-L44 process PAVE_GERMLINE { - //conda (params.enable_conda ? "bioconda::hmftools-pave=1.3" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/pave:1.4--0' input: @@ -30,18 +36,18 @@ process PAVE_GERMLINE { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -sample "${meta.get(['sample_name', 'tumor'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fasta}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -driver_gene_panel "${driver_gene_panel}" \\ - -clinvar_vcf "${clinvar_vcf}" \\ - -blacklist_bed "${sage_blacklist_bed}" \\ - -blacklist_vcf "${sage_blacklist_vcf}" \\ - -mappability_bed "${mappability_bed}" \\ - -vcf_file "${sage_vcf}" \\ + -sample ${meta.id} \\ + -ref_genome_version ${genome_ver} \\ + -ref_genome ${genome_fasta} \\ + -ensembl_data_dir ${ensembl_data_dir} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -clinvar_vcf ${clinvar_vcf} \\ + -blacklist_bed ${sage_blacklist_bed} \\ + -blacklist_vcf ${sage_blacklist_vcf} \\ + -mappability_bed ${mappability_bed} \\ + -vcf_file ${sage_vcf} \\ -read_pass_only \\ -output_dir ./ @@ -54,7 +60,7 @@ process PAVE_GERMLINE { stub: """ - touch ${meta.get(['sample_name', 'tumor'])}.sage.pave_germline.vcf.gz{,.tbi} + touch ${meta.id}.sage.pave_germline.vcf.gz{,.tbi} echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 36134f44..c4627e60 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -1,7 +1,9 @@ // NOTE(SW): PAVE gnomad filtering is not yet documented but is used in Pipeline5 https://github.com/hartwigmedical/pipeline5/blob/master/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L27-L28 process PAVE_SOMATIC { - //conda (params.enable_conda ? "bioconda::hmftools-pave=1.3" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/pave:1.4--0' input: @@ -29,16 +31,16 @@ process PAVE_SOMATIC { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ - -sample "${meta.get(['sample_name', 'tumor'])}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fasta}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -driver_gene_panel "${driver_gene_panel}" \\ - -pon_file "${sage_pon_file}" \\ - -pon_filters "${pon_filters}" \\ - -mappability_bed "${mappability_bed}" \\ - -vcf_file "${sage_vcf}" \\ + -jar ${task.ext.jarPath} \\ + -sample ${meta.id} \\ + -ref_genome_version ${genome_ver} \\ + -ref_genome ${genome_fasta} \\ + -ensembl_data_dir ${ensembl_data_dir} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -pon_file ${sage_pon_file} \\ + -pon_filters ${pon_filters} \\ + -mappability_bed ${mappability_bed} \\ + -vcf_file ${sage_vcf} \\ -read_pass_only \\ -output_dir ./ @@ -51,7 +53,7 @@ process PAVE_SOMATIC { stub: """ - touch ${meta.get(['sample_name', 'tumor'])}.sage.pave_somatic.vcf.gz{,.tbi} + touch ${meta.id}.sage.pave_somatic.vcf.gz{,.tbi} echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 715f5185..4c597cd0 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -1,5 +1,7 @@ process PURPLE { - //conda (params.enable_conda ? "bioconda::hmftools-purple=3.6" : null) + tag "${meta.id}" + label 'process_low' + container 'docker.io/scwatts/purple:3.6--4' input: @@ -46,44 +48,44 @@ process PURPLE { # Run PURPLE java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -tumor "${meta.get(['sample_name', 'tumor'])}" \\ - -reference "${meta.get(['sample_name', 'normal'])}" \\ - -sv_recovery_vcf "${sv_soft_vcf}" \\ - -structural_vcf "${sv_hard_vcf}" \\ + -tumor ${meta.tumor_id} \\ + -reference ${meta.normal_id} \\ + -sv_recovery_vcf ${sv_soft_vcf} \\ + -structural_vcf ${sv_hard_vcf} \\ \${smlv_tumor_vcf_arg} \\ \${smlv_normal_vcf_arg} \\ - -amber "${amber}" \\ - -cobalt "${cobalt}" \\ + -amber ${amber} \\ + -cobalt ${cobalt} \\ -output_dir purple/ \\ - -gc_profile "${gc_profile}" \\ + -gc_profile ${gc_profile} \\ -run_drivers \\ - -driver_gene_panel "${driver_gene_panel}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -somatic_hotspots "${sage_known_hotspots_somatic}" \\ - -germline_hotspots "${sage_known_hotspots_germline}" \\ + -driver_gene_panel ${driver_gene_panel} \\ + -ensembl_data_dir ${ensembl_data_dir} \\ + -somatic_hotspots ${sage_known_hotspots_somatic} \\ + -germline_hotspots ${sage_known_hotspots_germline} \\ ${germline_del_freq_arg} \\ - -ref_genome "${genome_fasta}" \\ - -ref_genome_version "${genome_ver}" \\ - -threads "${task.cpus}" \\ - -circos "${task.ext.circosPath}" + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -threads ${task.cpus} \\ + -circos ${task.ext.circosPath} # PURPLE can fail silently, check that at least the PURPLE SV VCF is created - if [[ ! -s "purple/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz" ]]; then + if [[ ! -s "purple/${meta.tumor_id}.purple.sv.vcf.gz" ]]; then exit 1; fi cat <<-END_VERSIONS > versions.yml "${task.process}": - purple: \$(java -jar "${task.ext.jarPath}" -version | sed 's/.*Purple version: //') + purple: \$(java -jar ${task.ext.jarPath} -version | sed 's/.*Purple version: //') END_VERSIONS """ stub: """ mkdir purple/ - cat < purple/${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz + cat < purple/${meta.tumor_id}.purple.sv.vcf.gz ##fileformat=VCFv4.1 ##contig= #CHROM POS ID REF ALT QUAL FILTER INFO diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 71fb0ee6..3c1068af 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -1,5 +1,7 @@ process SAGE_GERMLINE { - //conda (params.enable_conda ? "bioconda::hmftools-sage=3.1" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/sage:3.2--0' input: @@ -14,8 +16,8 @@ process SAGE_GERMLINE { path ensembl_data_dir output: - tuple val(meta), path("${meta.subject_name}.sage_germline.vcf.gz"), emit: vcf - path 'versions.yml' , emit: versions + tuple val(meta), path("${meta.tumor_id}.sage_germline.vcf.gz"), emit: vcf + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -26,18 +28,18 @@ process SAGE_GERMLINE { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -reference "${meta.get(['sample_name', 'tumor'])}" \\ - -reference_bam "${tumor_bam}" \\ - -tumor "${meta.get(['sample_name', 'normal'])}" \\ - -tumor_bam "${normal_bam}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fasta}" \\ - -hotspots "${sage_known_hotspots_germline}" \\ - -panel_bed "${sage_coding_panel}" \\ - -high_confidence_bed "${sage_high_confidence}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ + -reference ${meta.tumor_id} \\ + -reference_bam ${tumor_bam} \\ + -tumor ${meta.normal_id} \\ + -tumor_bam ${normal_bam} \\ + -ref_genome_version ${genome_ver} \\ + -ref_genome ${genome_fasta} \\ + -hotspots ${sage_known_hotspots_germline} \\ + -panel_bed ${sage_coding_panel} \\ + -high_confidence_bed ${sage_high_confidence} \\ + -ensembl_data_dir ${ensembl_data_dir} \\ -hotspot_min_tumor_qual 50 \\ -panel_min_tumor_qual 75 \\ -hotspot_max_germline_vaf 100 \\ @@ -46,18 +48,18 @@ process SAGE_GERMLINE { -panel_max_germline_rel_raw_base_qual 100 \\ -mnv_filter_enabled false \\ -panel_only \\ - -threads "${task.cpus}" \\ - -out "${meta.subject_name}.sage_germline.vcf.gz" + -threads ${task.cpus} \\ + -out ${meta.tumor_id}.sage_germline.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: \$(java -jar "${task.ext.jarPath}" | head -n1 | sed 's/.*Sage version: //') + sage: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*Sage version: //') END_VERSIONS """ stub: """ - touch "${meta.subject_name}.sage_germline.vcf.gz" + touch "${meta.tumor_id}.sage_germline.vcf.gz" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 4106c07b..ca3a5e16 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -1,5 +1,7 @@ process SAGE_SOMATIC { - //conda (params.enable_conda ? "bioconda::hmftools-sage=3.1" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/sage:3.2--0' input: @@ -14,7 +16,7 @@ process SAGE_SOMATIC { path ensembl_data_dir output: - tuple val(meta), path("${meta.subject_name}.sage_somatic.vcf.gz"), emit: vcf + tuple val(meta), path("${meta.tumor_id}.sage_somatic.vcf.gz"), emit: vcf path 'versions.yml' , emit: versions when: @@ -26,30 +28,30 @@ process SAGE_SOMATIC { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -reference "${meta.get(['sample_name', 'normal'])}" \\ - -reference_bam "${normal_bam}" \\ - -tumor "${meta.get(['sample_name', 'tumor'])}" \\ - -tumor_bam "${tumor_bam}" \\ - -ref_genome_version "${genome_ver}" \\ - -ref_genome "${genome_fasta}" \\ - -hotspots "${sage_known_hotspots_somatic}" \\ - -panel_bed "${sage_coding_panel}" \\ - -high_confidence_bed "${sage_high_confidence}" \\ - -ensembl_data_dir "${ensembl_data_dir}" \\ - -threads "${task.cpus}" \\ - -out "${meta.subject_name}.sage_somatic.vcf.gz" + -reference ${meta.normal_id} \\ + -reference_bam ${normal_bam} \\ + -tumor ${meta.tumor_id}} \\ + -tumor_bam ${tumor_bam} \\ + -ref_genome_version ${genome_ver} \\ + -ref_genome ${genome_fasta} \\ + -hotspots ${sage_known_hotspots_somatic} \\ + -panel_bed ${sage_coding_panel} \\ + -high_confidence_bed ${sage_high_confidence} \\ + -ensembl_data_dir ${ensembl_data_dir} \\ + -threads ${task.cpus} \\ + -out ${meta.tumor_id}.sage_somatic.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: \$(java -jar "${task.ext.jarPath}" | head -n1 | sed 's/.*Sage version: //') + sage: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*Sage version: //') END_VERSIONS """ stub: """ - touch "${meta.subject_name}.sage_somatic.vcf.gz" + touch "${meta.tumor_id}.sage_somatic.vcf.gz" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 885fbb05..413f7871 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -1,4 +1,7 @@ process SIGS { + tag "${meta.id}" + label 'process_low' + container 'docker.io/scwatts/sigs:1.1--0' input: diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 4cde069e..030f1cb3 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -1,4 +1,7 @@ process ASSEMBLE { + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/svprep:1.1--0' input: @@ -62,22 +65,22 @@ process ASSEMBLE { # Run gridss_svprep \\ ${args} \\ - --jvmheap "${task.memory.giga}g" \\ - --jar "${task.ext.jarPath}" \\ + --jvmheap ${task.memory.giga}g \\ + --jar ${task.ext.jarPath} \\ --steps assemble \\ - --labels "${labels_arg}" \\ - --reference "${genome_fasta}" \\ - --blacklist "${blacklist}" \\ - --workingdir "${output_dirname}/work" \\ - --assembly "${output_dirname}/sv_assemblies.bam" \\ - --threads "${task.cpus}" \\ + --labels ${labels_arg} \\ + --reference ${genome_fasta} \\ + --blacklist ${blacklist} \\ + --workingdir ${output_dirname}/work \\ + --assembly ${output_dirname}/sv_assemblies.bam \\ + --threads ${task.cpus} \\ ${config_arg} \\ ${bams_arg} \\ ${bams_filtered_arg} cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') END_VERSIONS """ diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 523dd1e0..aa7e8bc9 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -1,4 +1,7 @@ process CALL { + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/svprep:1.1--0' input: @@ -60,23 +63,23 @@ process CALL { # Run gridss_svprep \\ ${args} \\ - --jvmheap "${task.memory.giga}g" \\ - --jar "${task.ext.jarPath}" \\ + --jvmheap ${task.memory.giga}g \\ + --jar ${task.ext.jarPath} \\ --steps call \\ - --labels "${labels_arg}" \\ - --reference "${genome_fasta}" \\ - --blacklist "${blacklist}" \\ - --workingdir "${output_dirname}/work/" \\ - --assembly "${output_dirname}/sv_assemblies.bam" \\ - --output "${output_dirname}/sv.svprep.gridss.vcf.gz" \\ - --threads "${task.cpus}" \\ + --labels ${labels_arg} \\ + --reference ${genome_fasta} \\ + --blacklist ${blacklist} \\ + --workingdir ${output_dirname}/work/ \\ + --assembly ${output_dirname}/sv_assemblies.bam \\ + --output ${output_dirname}/sv.svprep.gridss.vcf.gz \\ + --threads ${task.cpus} \\ ${config_arg} \\ ${bams_arg} \\ ${bams_filtered_arg} cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') END_VERSIONS """ diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index b3026665..06f267bf 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -1,4 +1,7 @@ process DEPTH_ANNOTATOR { + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/svprep:1.1--0' input: @@ -23,19 +26,19 @@ process DEPTH_ANNOTATOR { """ java \\ -Xmx${task.memory.giga}g \\ - -cp "${task.ext.jarPath}" com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ + -cp ${task.ext.jarPath} com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ ${args} \\ -input_vcf ${vcf} \\ -output_vcf sv.svprep.gridss.depths.vcf.gz \\ - -samples "${labels_arg}" \\ - -bam_files "${bams_arg}" \\ + -samples ${labels_arg} \\ + -bam_files ${bams_arg} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -threads ${task.cpus} cat <<-END_VERSIONS > versions.yml "${task.process}": - svprep: \$(java -jar "${task.ext.jarPath}" 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + svprep: \$(java -jar ${task.ext.jarPath} 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') END_VERSIONS """ diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index a893b7c6..bb388ead 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -1,4 +1,7 @@ process PREPROCESS { + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/svprep:1.1--0' input: @@ -28,12 +31,12 @@ process PREPROCESS { gridss_svprep \\ ${args} \\ - --jvmheap "${task.memory.giga}g" \\ - --jar "${task.ext.jarPath}" \\ + --jvmheap ${task.memory.giga}g \\ + --jar ${task.ext.jarPath} \\ --steps preprocess \\ - --reference "${genome_fasta}" \\ + --reference ${genome_fasta} \\ --workingdir gridss_preprocess/ \\ - --threads "${task.cpus}" \\ + --threads ${task.cpus} \\ ${config_arg} \\ --labels ${meta.id} \\ --bams ${bam} \\ @@ -42,7 +45,7 @@ process PREPROCESS { cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') END_VERSIONS """ diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 49cd4d75..2068f3cd 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -1,4 +1,7 @@ process SVPREP { + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/svprep:1.1--0' input: @@ -27,25 +30,25 @@ process SVPREP { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ - -sample "${meta.id}" \\ - -bam_file "${bam}" \\ - -ref_genome "${genome_fasta}" \\ - -ref_genome_version "${genome_ver}" \\ - -blacklist_bed "${sv_blacklist}" \\ - -known_fusion_bed "${known_fusions}" \\ + -sample ${meta.id} \\ + -bam_file ${bam} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -blacklist_bed ${sv_blacklist} \\ + -known_fusion_bed ${known_fusions} \\ ${write_types_arg} \\ ${existing_juction_file_arg} \\ ${calc_fragment_length_arg} \\ - -threads "${task.cpus}" \\ + -threads ${task.cpus} \\ -output_dir ./ samtools sort -O bam "${meta.id}.sv_prep.bam" -o "${meta.id}.sv_prep.sorted.bam" cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: \$(java -jar "${task.ext.jarPath}" 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + sage: \$(java -jar ${task.ext.jarPath} 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') END_VERSIONS """ diff --git a/modules/local/teal/main.nf b/modules/local/teal/main.nf index 9239797c..6f0cb586 100644 --- a/modules/local/teal/main.nf +++ b/modules/local/teal/main.nf @@ -1,5 +1,7 @@ process TEAL { - //conda (params.enable_conda ? "bioconda::hmftools-teal=1.0.1" : null) + tag "${meta.id}" + label 'process_medium' + container 'docker.io/scwatts/teal:1.0.1--2' input: @@ -15,12 +17,12 @@ process TEAL { script: def args = task.ext.args ?: '' def tumor_args = normal_bam ? """ - -tumor ${meta.get(['sample_name', 'tumor'])} + -tumor ${meta.tumor_id} -tumor_bam ${tumor_bam} -tumor_wgs_metrics ${tumor_wgs_metrics} """ : '' def reference_args = normal_bam ? """ - -reference ${meta.get(['sample_name', 'normal'])} + -reference ${meta.normal_id} -reference_bam ${normal_bam} -reference_wgs_metrics ${normal_wgs_metrics} """ : '' @@ -28,13 +30,13 @@ process TEAL { """ java \\ -Xmx${task.memory.giga}g \\ - -jar "${task.ext.jarPath}" \\ + -jar ${task.ext.jarPath} \\ ${args} \\ ${tumor_args.replaceAll('\n', '')} \\ ${reference_args.replaceAll('\n', '')} \\ - -cobalt "${cobalt_dir}" \\ - -purple "${purple_dir}" \\ - -threads "${task.cpus}" \\ + -cobalt ${cobalt_dir} \\ + -purple ${purple_dir} \\ + -threads ${task.cpus} \\ -output_dir teal/ # NOTE(SW): hard coded since there is no reliable way to obtain version information. diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index f95fe708..7b5e39b0 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -1,7 +1,9 @@ -// NOTE(SW): the --db argument for the virusbreakend command must have a trailing slash if it is a -// symlink +// NOTE(SW): the --db argument for the virusbreakend command must have a trailing slash if it is a symlink process VIRUSBREAKEND { + tag "${meta.id}" + label 'process_high' + container 'docker.io/scwatts/gridss:2.13.2--3' input: diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index 19a6a2c9..884c1b01 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -1,4 +1,7 @@ process VIRUSINTERPRETER { + tag "${meta.id}" + label 'process_single' + container 'docker.io/scwatts/virus_interpreter:1.2--0' input: @@ -22,7 +25,7 @@ process VIRUSINTERPRETER { java \\ -Xmx${task.memory.giga}g \\ -jar ${task.ext.jarPath} \\ - -sample_id ${meta.get(['sample_name', 'tumor'])} \\ + -sample_id ${meta.id} \\ -purple_purity_tsv ${purple_purity} \\ -purple_qc_file ${purple_qc} \\ -tumor_sample_wgs_metrics_file ${wgs_metrics} \\ diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep.nf index d0189225..d8226172 100644 --- a/subworkflows/local/gridss_svprep.nf +++ b/subworkflows/local/gridss_svprep.nf @@ -30,13 +30,16 @@ workflow GRIDSS_SVPREP { ch_versions = Channel.empty() // Prepare tumor sample inputs - // channel: [val(meta_svprep), bam, bai, []] + // channel: [val(meta_svprep), bam_tumor, bai_tumor, []] ch_svprep_tumor_inputs = ch_inputs .map { meta -> - def meta_svprep = [id: meta.get(['sample_name', 'tumor']), meta_full: meta] - def bam = meta.get(['bam_wgs', 'tumor']) - def bai = "${bam}.bai" - return [meta_svprep, bam, bai, []] + def meta_svprep = [ + key: meta.id, + id: meta.get(['sample_name', 'tumor']), + sample_type: 'tumor', + ] + def bam_tumor = meta.get(['bam_wgs', 'tumor']) + return [meta_svprep, bam_tumor, "${bam_tumor}.bai", []] } // Filter tumor BAM @@ -53,10 +56,13 @@ workflow GRIDSS_SVPREP { // Prepare normal sample inputs // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] - ch_svprep_normal_inputs = SVPREP_TUMOR.out.junctions - .map { meta_tumor_svprep, junctions_tumor -> - def meta = meta_tumor_svprep['meta_full'] - def meta_svprep = [id: meta.get(['sample_name', 'normal']), meta_full: meta] + ch_svprep_normal_inputs = WorkflowOncoanalyser.restore_meta(SVPREP_TUMOR.out.junctions, ch_inputs) + .map { meta, junctions_tumor -> + def meta_svprep = [ + key: meta.id, + id: meta.get(['sample_name', 'normal']), + sample_type: 'normal', + ] def bam_normal = meta.get(['bam_wgs', 'normal']) return [meta_svprep, bam_normal, "${bam_normal}.bai", junctions_tumor] } @@ -72,32 +78,25 @@ workflow GRIDSS_SVPREP { ) ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) + // channel: [val(meta_gridss), bam_tumor, bam_tumor_filtered] ch_preprocess_inputs_tumor = WorkflowOncoanalyser.group_by_meta( SVPREP_TUMOR.out.bam, ch_svprep_tumor_inputs, ) .map { meta_svprep, bam_filtered, bam, bai -> - def meta_gridss = [ - id: meta_svprep.id, - sample_type: 'tumor', - subject_id: meta_svprep.meta_full.id, - ] - return [meta_gridss, bam, bam_filtered] + return [meta_svprep, bam, bam_filtered] } + // channel: [val(meta_gridss), bam_normal, bam_normal_filtered] ch_preprocess_inputs_normal = WorkflowOncoanalyser.group_by_meta( SVPREP_NORMAL.out.bam, ch_svprep_normal_inputs, ) .map { meta_svprep, bam_filtered, bam, bai, junctions -> - def meta_gridss = [ - id: meta_svprep.id, - sample_type: 'normal', - subject_id: meta_svprep.meta_full.id, - ] - return [meta_gridss, bam, bam_filtered] + return [meta_svprep, bam, bam_filtered] } + // channel: [val(meta_gridss), bam, bam_filtered] ch_preprocess_inputs = Channel.empty() .mix( ch_preprocess_inputs_tumor, @@ -117,22 +116,28 @@ workflow GRIDSS_SVPREP { ) ch_versions = ch_versions.mix(GRIDSS_PREPROCESS.out.versions) + + + // Gather BAMs and outputs from preprocessing for each tumor/normal set - // channel: [subject_id, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] + // channel: [key, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] ch_bams_and_preprocess = WorkflowOncoanalyser.group_by_meta( ch_preprocess_inputs, GRIDSS_PREPROCESS.out.preprocess_dir, ) - .map { [it[0].subject_id, it] } + .map { [it[0].key, it] } .groupTuple(size: 2) + + + // Order and organise inputs for assembly // channel: [val(meta_gridss), [bams], [bams_filtered], [preprocess_dirs], [labels]] ch_assemble_inputs = ch_bams_and_preprocess - .map { subject_id, entries -> + .map { key, entries -> def (tmeta, tbam, tbam_filtered, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } def (nmeta, nbam, nbam_filtered, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } - def meta_gridss = [id: tmeta.subject_id] + def meta_gridss = [id: tmeta.key] return [ meta_gridss, [nbam, tbam], @@ -184,7 +189,7 @@ workflow GRIDSS_SVPREP { ) ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) - // Prepare inputs for depth annotation + // Prepare inputs for depth annotation, restore original meta // channel: [val(meta), [bams], [bais], vcf, [labels]] ch_depth_inputs = WorkflowOncoanalyser.group_by_meta( ch_inputs.map { meta -> [meta.id, meta] }, diff --git a/subworkflows/local/gripss.nf b/subworkflows/local/gripss.nf index 06a57524..b50494ed 100644 --- a/subworkflows/local/gripss.nf +++ b/subworkflows/local/gripss.nf @@ -7,7 +7,7 @@ include { GRIPSS_SOMATIC } from '../../modules/local/gripss/somatic/main' workflow GRIPSS { take: - ch_inputs // channel: [val(meta), gridss_vcf] + ch_inputs // channel: [val(meta_gripss), gridss_vcf] ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_version // val: genome version @@ -20,7 +20,7 @@ workflow GRIPSS { // Channel for version.yml files ch_versions = Channel.empty() - // Germline + // Germline; set correct ID in meta GRIPSS_GERMLINE( ch_inputs, ref_data_genome_fasta, @@ -47,20 +47,20 @@ workflow GRIPSS { ch_versions = ch_versions.mix(GRIPSS_SOMATIC.out.versions) // Pack output - // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + // channel: [val(meta_gripss), hard_vcf, hard_tbi, soft_vcf, soft_tbi] ch_germline_out = WorkflowOncoanalyser.group_by_meta( GRIPSS_GERMLINE.out.vcf_hard, GRIPSS_GERMLINE.out.vcf_soft, ) - // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + // channel: [val(meta_gripss), hard_vcf, hard_tbi, soft_vcf, soft_tbi] ch_somatic_out = WorkflowOncoanalyser.group_by_meta( GRIPSS_SOMATIC.out.vcf_hard, GRIPSS_SOMATIC.out.vcf_soft, ) emit: - germline = ch_germline_out // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - somatic = ch_somatic_out // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + germline = ch_germline_out // channel: [val(meta_gripss), hard_vcf, hard_tbi, soft_vcf, soft_tbi] + somatic = ch_somatic_out // channel: [val(meta_gripss), hard_vcf, hard_tbi, soft_vcf, soft_tbi] versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index 92358f20..ec654424 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -10,11 +10,10 @@ include { LILAC as LILAC_PROCESS } from '../../modules/local/lila workflow LILAC { take: - ch_inputs_bams // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] - ch_inputs_purple_dir // channel: [val(meta), purple_dir] + ch_inputs_bams // channel: [val(meta_lilac), tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_inputs_purple_dir // channel: [val(meta_lilac), purple_dir] ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_version // val: genome version ref_data_lilac_resource_dir // file: /path/to/lilac_resource_dir/ main: @@ -22,16 +21,17 @@ workflow LILAC { ch_versions = Channel.empty() // Slice HLA regions - if (ref_data_genome_version == '38') { - slice_bed = file("${params.ref_data_lilac_resource_dir}/hla.38.alt.umccr.bed", checkIfExists: true) - } else { - slice_bed = file("${params.ref_data_lilac_resource_dir}/hla.${ref_data_genome_version}.bed", checkIfExists: true) - } + ch_slice_bed = ref_data_lilac_resource_dir + .map { lilac_dir -> + def genome_ver = params.ref_data_genome_version + def filename = genome_ver == '38' ? 'hla.38.alt.umccr.bed' : "hla.${genome_ver}.bed" + return file("${lilac_dir}/${filename}", checkIfExists: true) + } // NOTE(SW): here I remove duplicate files so that we only process each input once // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used // in Pipeline5, see LilacBamSlicer.java#L115 // channel: [val(meta_lilac), bam, bai, bed] - ch_slice_inputs = WorkflowLilac.get_slice_inputs(ch_inputs_bams, slice_bed) + ch_slice_inputs = WorkflowLilac.get_slice_inputs(ch_inputs_bams, ch_slice_bed) // channel: [val(meta_lilac), bam, bai, bed] ch_slice_inputs = WorkflowLilac.get_unique_input_files(ch_slice_inputs) SLICE( @@ -39,8 +39,10 @@ workflow LILAC { ) ch_versions = ch_versions.mix(SLICE.out.versions) - // Realign contigs if using hg38 (use of ALT contigs implied) - if (ref_data_genome_version == '38') { + // Realign contigs if using 38 (use of ALT contigs implied) + // channel: [val(meta)] + ch_metas = ch_inputs_bams.map { return it[0] } + if (params.ref_data_genome_version == '38') { // Align reads with chr6 // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them // to the three relevant HLA genes on chr6. All reads including those previously mapped to chr6 @@ -57,25 +59,47 @@ workflow LILAC { ) // Create input channel for LILAC - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] - ch_lilac_inputs = WorkflowOncoanalyser.group_by_meta( + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_lilac_inputs_slices = WorkflowOncoanalyser.restore_meta( WorkflowLilac.sort_slices(REALIGN_READS.out.bam), + ch_metas, + ) + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] + ch_lilac_inputs_full = WorkflowOncoanalyser.group_by_meta( + ch_lilac_inputs_slices, ch_inputs_purple_dir, ) } else { // Create input channel for LILAC - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] - ch_lilac_inputs = WorkflowOncoanalyser.group_by_meta( + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_lilac_inputs_slices = WorkflowOncoanalyser.restore_meta( WorkflowLilac.sort_slices(SLICE.out.bam), + ch_metas, + ) + // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] + ch_lilac_inputs_full = WorkflowOncoanalyser.group_by_meta( + ch_lilac_inputs_slices, ch_inputs_purple_dir, ) } // Run LILAC + // channel: [val(meta_lilac), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] + ch_lilac_inputs = ch_lilac_inputs_full + .map { + def meta = it[0] + def meta_lilac = [ + key: meta.id, + id: meta.id, + tumor_id: meta.get(['sample_name', 'tumor']), + normal_id: meta.get(['sample_name', 'normal']), + ] + return [meta_lilac, *it[1..-1]] + } LILAC_PROCESS( ch_lilac_inputs, ref_data_genome_fasta, - ref_data_genome_version, + params.ref_data_genome_version, ref_data_lilac_resource_dir, ) ch_versions = ch_versions.mix(LILAC_PROCESS.out.versions) diff --git a/subworkflows/local/sage.nf b/subworkflows/local/sage.nf index 7c9cacc9..9391e684 100644 --- a/subworkflows/local/sage.nf +++ b/subworkflows/local/sage.nf @@ -7,7 +7,7 @@ include { SAGE_SOMATIC } from '../../modules/local/sage/somatic/main' workflow SAGE { take: - ch_inputs // channel: [meta, tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_inputs // channel: [meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai] ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_dict // file: /path/to/genome_dict diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 831a3c43..40a82ac0 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -165,14 +165,17 @@ workflow ONCOANALYSER { // // MODULE: Run Isofox to analyse WTS data // + // channel: [meta, isofox_dir] ch_isofox_out = Channel.empty() if (run.isofox) { - - // channel: [meta, tumor_bam_wts] + // Create inputs and create process-specific meta + // channel: [meta_isofox, tumor_bam_wts] ch_isofox_inputs = ch_inputs_wts.present .map { meta -> - return [meta, meta.get(['bam_wts', 'tumor'])] + return [[key: meta.id, id: meta.id], meta.get(['bam_wts', 'tumor'])] } + + // Run process ISOFOX( ch_isofox_inputs, PREPARE_REFERENCE.out.genome_fasta, @@ -182,18 +185,20 @@ workflow ONCOANALYSER { hmf_data.isofox_exp_counts, hmf_data.isofox_exp_gc_ratios, ) + + // Set outputs, restoring original meta ch_versions = ch_versions.mix(ISOFOX.out.versions) - ch_isofox_out = ch_isofox_out.mix(ISOFOX.out.isofox_dir) + ch_isofox_out = ch_isofox_out.mix(WorkflowOncoanalyser.restore_meta(ISOFOX.out.isofox_dir, ch_inputs)) } // // MODULE: Run COLLECTWGSMETRICS to generate stats required for downstream processes // if (run.virusinterpreter || run.teal) { - - // NOTE(SW): CUPPA only requires collectwgsmetrics for the tumor sample in - // the upstream process Virus Interpreter but TEAL currently requires - // collectwgsmetrics for both tumor and normal sample + // Create inputs and create process-specific meta + // NOTE(SW): CUPPA only requires collectwgsmetrics for the tumor sample in the upstream + // process Virus Interpreter but TEAL currently requires collectwgsmetrics for both tumor + // and normal sample // channel: [val(meta_cwm), bam] ch_cwm_inputs_all = ch_inputs .flatMap { meta -> @@ -203,15 +208,15 @@ workflow ONCOANALYSER { def bam = meta.get(['bam_wgs', sample_type]) def sample_name = meta.get(['sample_name', sample_type]) def meta_cwm = [ + key: meta.id, id: sample_name, sample_type: sample_type, - meta_full: meta, ] return [meta_cwm, bam] } } - // Gather duplicate files e.g. repeated normal BAMs for multiple tumor samples + // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent // on any process // channel: [val(meta_cwm), bam] @@ -219,38 +224,47 @@ workflow ONCOANALYSER { .map { [it[1..-1], it[0]] } .groupTuple() .map { filepaths, meta_cwm -> - def (meta_fulls, sample_types) = meta_cwm + def (keys, sample_names, sample_types) = meta_cwm .collect { - [it.meta_full, it.sample_type] + [it.key, it.id, it.sample_type] } .transpose() - def sample_type = sample_types.unique(false) - assert sample_type.size() == 1 + def sample_types_unique = sample_types.unique(false) + assert sample_types_unique.size() == 1 + def sample_type = sample_types_unique[0] - def id = meta_fulls.collect { it.id }.join('__') def meta_cwm_new = [ - id: "${id}_${sample_type[0]}", - id_simple: id, - metas_full: meta_fulls, - sample_type: sample_type[0], + keys: keys, + id: sample_names.join('__'), + id_simple: keys.join('__'), + sample_type: sample_type, ] return [meta_cwm_new, *filepaths] } + // Run process COLLECTWGSMETRICS( ch_cwm_inputs, PREPARE_REFERENCE.out.genome_fasta, ) + + // Set outputs, process outputs and restore original meta ch_versions = ch_versions.mix(COLLECTWGSMETRICS.out.versions) - // Replicate outputs to undo unique operation + // Replicate outputs to reverse unique operation + // channel: [val(meta_cwm_individual), sample_type, metrics] + ch_cwm_output_individual = COLLECTWGSMETRICS.out.metrics + .flatMap { meta_cwm_shared, metrics -> + meta_cwm_shared.keys.collect { key -> + return [meta_cwm_shared + [key: key], meta_cwm_shared.sample_type, metrics] + } + } + + // Match outputs to original meta and set output // channel (tumor): [val(meta), metrics] // channel (normal): [val(meta), metrics] - ch_cwm_output = COLLECTWGSMETRICS.out.metrics - .flatMap { meta_cwm, metrics -> - meta_cwm.metas_full.collect { meta -> [meta, meta_cwm.sample_type, metrics] } - } + ch_cwm_output = WorkflowOncoanalyser.restore_meta(ch_cwm_output_individual, ch_inputs) .branch { meta, sample_type, metrics -> tumor: sample_type == 'tumor' return [meta, metrics] @@ -265,14 +279,31 @@ workflow ONCOANALYSER { // channel: [val(meta), amber_dir] ch_amber_out = Channel.empty() if (run.amber) { + // Create inputs and create process-specific meta + // channel: [val(meta_amber), tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_amber_inputs = ch_bams_and_indices + .map { + def meta = it[0] + def fps = it[1..-1] + def meta_amber = [ + key: meta.id, + id: meta.id, + tumor_id: meta.get(['sample_name', 'tumor']), + normal_id: meta.get(['sample_name', 'normal']), + ] + return [meta_amber, *fps] + } + // Run process AMBER( - ch_bams_and_indices, + ch_amber_inputs, PREPARE_REFERENCE.out.genome_version, hmf_data.amber_loci, ) + + // Set outputs, restoring original meta ch_versions = ch_versions.mix(AMBER.out.versions) - ch_amber_out = ch_amber_out.mix(AMBER.out.amber_dir) + ch_amber_out = ch_amber_out.mix(WorkflowOncoanalyser.restore_meta(AMBER.out.amber_dir, ch_inputs)) } // @@ -281,13 +312,30 @@ workflow ONCOANALYSER { // channel: [val(meta), cobalt_dir] ch_cobalt_out = Channel.empty() if (run.cobalt) { + // Create inputs and create process-specific meta + // channel: [meta_cobalt, tbam, nbam, tbai, nbai] + ch_cobalt_inputs = ch_bams_and_indices + .map { + def meta = it[0] + def fps = it[1..-1] + def meta_cobalt = [ + key: meta.id, + id: meta.id, + tumor_id: meta.get(['sample_name', 'tumor']), + normal_id: meta.get(['sample_name', 'normal']), + ] + return [meta_cobalt, *fps] + } + // Run process COBALT( - ch_bams_and_indices, + ch_cobalt_inputs, hmf_data.cobalt_gc_profile, ) + + // Set outputs, restoring original meta ch_versions = ch_versions.mix(COBALT.out.versions) - ch_cobalt_out = ch_cobalt_out.mix(COBALT.out.cobalt_dir) + ch_cobalt_out = ch_cobalt_out.mix(WorkflowOncoanalyser.restore_meta(COBALT.out.cobalt_dir, ch_inputs)) } // @@ -296,7 +344,6 @@ workflow ONCOANALYSER { // channel: [val(meta), gridss_vcf] ch_gridss_out = Channel.empty() if (run.gridss) { - if (run.svprep) { GRIDSS_SVPREP( ch_inputs, @@ -345,9 +392,30 @@ workflow ONCOANALYSER { // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] ch_gripss_somatic_out = Channel.empty() if (run.gripss) { + // Select input source + // channel: [val(meta), gridss_vcf] + if (run.gridss) { + ch_gripss_inputs_source = ch_gridss_out + } else { + ch_gripss_inputs_source = WorkflowOncoanalyser.get_input(ch_inputs, ['gridss_vcf', 'tumor_normal']) + } + // Create inputs and create process-specific meta + // channel: [val(meta_gripss), gridss_vcf] + ch_gripss_inputs = ch_gripss_inputs_source + .map { meta, gridss_vcf -> + def meta_gripss = [ + key: meta.id, + id: meta.id, + tumor_id: meta.get(['sample_name', 'tumor']), + normal_id: meta.get(['sample_name', 'normal']), + ] + return [meta_gripss, gridss_vcf] + } + + // Call subworkflow to run processes GRIPSS( - run.gridss ? ch_gridss_out : WorkflowOncoanalyser.get_input(ch_inputs, ['gridss_vcf', 'tumor_normal']), + ch_gripss_inputs, PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, PREPARE_REFERENCE.out.genome_version, @@ -356,9 +424,11 @@ workflow ONCOANALYSER { hmf_data.known_fusions, hmf_data.repeat_masker_file, ) + + // Set outputs, restoring original meta ch_versions = ch_versions.mix(GRIPSS.out.versions) - ch_gripss_germline_out = ch_gripss_germline_out.mix(GRIPSS.out.germline) - ch_gripss_somatic_out = ch_gripss_somatic_out.mix(GRIPSS.out.somatic) + ch_gripss_germline_out = ch_gripss_germline_out.mix(WorkflowOncoanalyser.restore_meta(GRIPSS.out.germline, ch_inputs)) + ch_gripss_somatic_out = ch_gripss_somatic_out.mix(WorkflowOncoanalyser.restore_meta(GRIPSS.out.somatic, ch_inputs)) } // @@ -369,9 +439,21 @@ workflow ONCOANALYSER { // channel: [val(meta), sage_vcf] ch_sage_somatic_out = Channel.empty() if (run.sage) { + // Create inputs and create process-specific meta + ch_sage_inputs = ch_bams_and_indices + .map { meta, tbam, nbam, tbai, nbai -> + def meta_sage = [ + key: meta.id, + id: meta.id, + tumor_id: meta.get(['sample_name', 'tumor']), + normal_id: meta.get(['sample_name', 'normal']), + ] + return [meta_sage, tbam, nbam, tbai, nbai] + } + // Call subworkflow to run processes SAGE( - ch_bams_and_indices, + ch_sage_inputs, PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, PREPARE_REFERENCE.out.genome_dict, @@ -385,9 +467,11 @@ workflow ONCOANALYSER { hmf_data.driver_gene_panel, hmf_data.ensembl_data_dir, ) + + // Set outputs, restoring original meta ch_versions = ch_versions.mix(SAGE.out.versions) - ch_sage_germline_out = ch_sage_germline_out.mix(SAGE.out.germline) - ch_sage_somatic_out = ch_sage_somatic_out.mix(SAGE.out.somatic) + ch_sage_germline_out = ch_sage_germline_out.mix(WorkflowOncoanalyser.restore_meta(SAGE.out.germline, ch_inputs)) + ch_sage_somatic_out = ch_sage_somatic_out.mix(WorkflowOncoanalyser.restore_meta(SAGE.out.somatic, ch_inputs)) } // @@ -398,10 +482,39 @@ workflow ONCOANALYSER { // channel: [val(meta), pave_vcf] ch_pave_somatic_out = Channel.empty() if (run.pave) { + // Select input sources + // channel: [meta, sage_vcf] + if (run.sage) { + ch_pave_germline_inputs_source = ch_sage_germline_out + ch_pave_somatic_inputs_source = ch_sage_somatic_out + } else { + ch_pave_germline_inputs_source = WorkflowOncoanalyser.get_input(ch_inputs, ['sage_vcf', 'normal']) + ch_pave_somatic_inputs_source = WorkflowOncoanalyser.get_input(ch_inputs, ['sage_vcf', 'tumor']) + } + // Create inputs and create process-specific meta + // channel: [val(meta_pave), sage_vcf] + ch_pave_germline_inputs = ch_pave_germline_inputs_source + .map { meta, sage_vcf -> + def pave_meta = [ + key: meta.id, + id: meta.get(['sample_name', 'tumor']), + ] + return [pave_meta, sage_vcf] + } + ch_pave_somatic_inputs = ch_pave_germline_inputs_source + .map { meta, sage_vcf -> + def pave_meta = [ + key: meta.id, + id: meta.get(['sample_name', 'tumor']), + ] + return [pave_meta, sage_vcf] + } + + // Call subworkflow to run processes PAVE( - run.sage ? ch_sage_germline_out : WorkflowOncoanalyser.get_input(ch_inputs, ['sage_vcf', 'normal']), - run.sage ? ch_sage_somatic_out : WorkflowOncoanalyser.get_input(ch_inputs, ['sage_vcf', 'tumor']), + ch_pave_germline_inputs, + ch_pave_somatic_inputs, PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, PREPARE_REFERENCE.out.genome_version, @@ -413,9 +526,11 @@ workflow ONCOANALYSER { hmf_data.driver_gene_panel, hmf_data.ensembl_data_dir, ) + + // Set outputs, restoring original meta ch_versions = ch_versions.mix(PAVE.out.versions) - ch_pave_germline_out = ch_pave_germline_out.mix(PAVE.out.germline) - ch_pave_somatic_out = ch_pave_somatic_out.mix(PAVE.out.somatic) + ch_pave_germline_out = ch_pave_germline_out.mix(WorkflowOncoanalyser.restore_meta(PAVE.out.germline, ch_inputs)) + ch_pave_somatic_out = ch_pave_somatic_out.mix(WorkflowOncoanalyser.restore_meta(PAVE.out.somatic, ch_inputs)) } // @@ -424,7 +539,7 @@ workflow ONCOANALYSER { // channel: [val(meta), purple_dir] ch_purple_out = Channel.empty() if (run.purple) { - + // Select input sources // channel: [val(meta), sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi] if (run.gripss) { ch_purple_inputs_sv = ch_gripss_somatic_out @@ -444,7 +559,7 @@ workflow ONCOANALYSER { } // channel: [val(meta), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] - ch_purple_inputs = WorkflowOncoanalyser.group_by_meta( + ch_purple_inputs_sources = WorkflowOncoanalyser.group_by_meta( run.amber ? ch_amber_out : WorkflowOncoanalyser.get_input(ch_inputs, ['amber_dir', 'tumor_normal']), run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.get_input(ch_inputs, ['cobalt_dir', 'tumor_normal']), ch_purple_inputs_sv, @@ -452,6 +567,20 @@ workflow ONCOANALYSER { run.pave ? ch_pave_germline_out : WorkflowOncoanalyser.get_input(ch_inputs, ['vcf_smlv', 'normal']), ) + // channel: [val(meta_purple), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] + ch_purple_inputs = ch_purple_inputs_sources + .map { + def meta = it[0] + def other = it[1..-1] + def meta_purple = [ + key: meta.id, + id: meta.id, + tumor_id: meta.get(['sample_name', 'tumor']), + normal_id: meta.get(['sample_name', 'normal']), + ] + return [meta_purple, *other] + } + PURPLE( ch_purple_inputs, PREPARE_REFERENCE.out.genome_fasta, @@ -465,20 +594,30 @@ workflow ONCOANALYSER { hmf_data.ensembl_data_dir, hmf_data.purple_germline_del, ) + + // Set outputs, restoring original meta ch_versions = ch_versions.mix(PURPLE.out.versions) - ch_purple_out = ch_purple_out.mix(PURPLE.out.purple_dir) + ch_purple_out = ch_purple_out.mix(WorkflowOncoanalyser.restore_meta(PURPLE.out.purple_dir, ch_inputs)) } // - // MODULE: Run SIGS to fit somatic smlv to signature definitions + // MODULE: Run Sigs to fit somatic smlv to signature definitions // if (run.sigs) { + // Select input sources // channel: [val(meta), purple_dir] - ch_sigs_inputs_purple_dir = run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']) - // channel: [val(meta), smlv_vcf] - ch_sigs_inputs = ch_sigs_inputs_purple_dir + if (run.purple) { + ch_sigs_inputs_source = ch_purple_out + } else { + ch_sigs_inputs_source = WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']) + } + + // Create inputs and create process-specific meta + // channel: [val(meta_sigs), smlv_vcf] + ch_sigs_inputs = ch_sigs_inputs_source .map { meta, purple_dir -> def smlv_vcf = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.somatic.vcf.gz") + def meta_sigs = [id: meta.id] return [meta, smlv_vcf] } @@ -486,6 +625,8 @@ workflow ONCOANALYSER { ch_sigs_inputs, hmf_data.sigs_signatures, ) + + // Set outputs ch_versions = ch_versions.mix(SIGS.out.versions) } @@ -493,20 +634,32 @@ workflow ONCOANALYSER { // MODULE: Run CHORD to predict HR deficiency status // if (run.chord) { + // Select input sources // channel: [val(meta), purple_dir] - ch_chord_inputs_purple_dir = run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']) + if (run.purple) { + ch_chord_inputs_source = ch_purple_out + } else { + ch_chord_inputs_source = WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']) + } + + // Create inputs and create process-specific meta // channel: [val(meta), smlv_vcf, sv_vcf] - ch_chord_inputs = ch_chord_inputs_purple_dir + ch_chord_inputs = ch_chord_inputs_source .map { meta, purple_dir -> - def smlv_vcf = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.somatic.vcf.gz") - def sv_vcf = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.sv.vcf.gz") - return [meta, smlv_vcf, sv_vcf] + def tumor_id = meta.get(['sample_name', 'tumor']) + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") + def meta_chord = [id: meta.id] + return [meta_chord, smlv_vcf, sv_vcf] } + // Run process CHORD( ch_chord_inputs, PREPARE_REFERENCE.out.genome_version, ) + + // Set outputs ch_versions = ch_versions.mix(CHORD.out.versions) } @@ -514,10 +667,10 @@ workflow ONCOANALYSER { // MODULE: Run TEAL to characterise teleomeres // if (run.teal) { - + // Select input sources // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, tumor_wgs_metrics, normal_wgs_metrics, cobalt_dir, purple_dir] // NOTE(SW): assuming here that TEAL is being run in tumor/normal mode and so we expect a tumor metrics file and normal metrics file - ch_teal_inputs = WorkflowOncoanalyser.group_by_meta( + ch_teal_inputs_source = WorkflowOncoanalyser.group_by_meta( ch_bams_and_indices, run.collectwgsmetrics ? ch_cwm_output.tumor : WorkflowOncoanalyser.get_input(ch_inputs, ['collectmetrics', 'tumor']), run.collectwgsmetrics ? ch_cwm_output.normal : WorkflowOncoanalyser.get_input(ch_inputs, ['collectmetrics', 'normal']), @@ -525,9 +678,26 @@ workflow ONCOANALYSER { run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.get_input(ch_inputs, ['cobalt_dir', 'tumor_normal']), ) + // Create inputs and create process-specific meta + // channel: [val(meta_teal), tumor_bam, normal_bam, tumor_bai, normal_bai, tumor_wgs_metrics, normal_wgs_metrics, cobalt_dir, purple_dir] + ch_teal_inputs = ch_teal_inputs_source + .map { + def meta = it[0] + def other = it[1..-1] + def meta_teal = [ + id: meta.id, + tumor_id: meta.get(['sample_name', 'tumor']), + normal_id: meta.get(['sample_name', 'normal']), + ] + return [meta_teal, *other] + } + + // Run process TEAL( ch_teal_inputs, ) + + // Set outputs ch_versions = ch_versions.mix(TEAL.out.versions) } @@ -535,15 +705,24 @@ workflow ONCOANALYSER { // SUBWORKFLOW: Run LILAC for HLA typing and somatic CNV and SNV calling // if (run.lilac) { + // Select input sources + // channel: [val(meta), purple_dir] + if (run.purple) { + ch_lilac_inputs_source = ch_purple_out + } else { + ch_lilac_inputs_source = WorkflowOncoanalyser.get_input(['purple_dir', 'tumor_normal']) + } + // Run process LILAC( ch_bams_and_indices, run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(['purple_dir', 'tumor_normal']), PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_version, hmf_data.lilac_resource_dir, ) + + // Set outputs ch_versions = ch_versions.mix(LILAC.out.versions) } @@ -553,10 +732,18 @@ workflow ONCOANALYSER { // NOTE(SW): kept separate from CUPPA conditional block since we'll allow users to run this independently ch_virusinterpreter_out = Channel.empty() if (run.virusinterpreter) { + // Create inputs and create process-specific meta + // channel: [val(meta_virus), tumor_bam] + ch_virusbreakend_inputs = ch_inputs + .map { meta -> + def meta_virus = [ + key: meta.id, + id: meta.id, + ] + return [meta_virus, meta.get(['bam_wgs', 'tumor'])] + } - // channel: [val(meta), tumor_bam] - ch_virusbreakend_inputs = ch_inputs.map { meta -> [meta, meta.get(['bam_wgs', 'tumor'])] } - + // Run process VIRUSBREAKEND( ch_virusbreakend_inputs, gridss_config, @@ -568,8 +755,11 @@ workflow ONCOANALYSER { PREPARE_REFERENCE.out.genome_gridss_index, hmf_data.virusbreakenddb, ) + + // Set outputs ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) + // Create inputs and create process-specific meta // channel: [val(meta), purple_purity, purple_qc] ch_virusinterpreter_inputs_purple = ch_purple_out .map { meta, purple_dir -> @@ -579,19 +769,34 @@ workflow ONCOANALYSER { } // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] - ch_virusinterpreter_inputs = WorkflowOncoanalyser.group_by_meta( - VIRUSBREAKEND.out.tsv, + ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.group_by_meta( + WorkflowOncoanalyser.restore_meta(VIRUSBREAKEND.out.tsv, ch_inputs), ch_virusinterpreter_inputs_purple, ch_cwm_output.tumor, ) + // Create inputs and create process-specific meta + // channel: [val(meta_virus), virus_tsv, purple_purity, purple_qc, wgs_metrics] + ch_virusinterpreter_inputs = ch_virusinterpreter_inputs_full + .map { + def meta = it[0] + def meta_virus = [ + key: meta.id, + id: meta.id, + ] + return [meta_virus, *it[1..-1]] + } + + // Run process VIRUSINTERPRETER( ch_virusinterpreter_inputs, hmf_data.virus_taxonomy, hmf_data.virus_reporting, ) + + // Set outputs, restoring original meta ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) - ch_virusinterpreter_out = ch_virusinterpreter_out.mix(VIRUSINTERPRETER.out.virusinterpreter_dir) + ch_virusinterpreter_out = ch_virusinterpreter_out.mix(WorkflowOncoanalyser.restore_meta(VIRUSINTERPRETER.out.virusinterpreter_dir, ch_inputs)) } // @@ -600,13 +805,42 @@ workflow ONCOANALYSER { // channel: [val(meta), linx_annotation_dir, linx_visuliaser_dir] ch_linx_somatic_out = Channel.empty() if (run.linx) { - + // Select input sources // channel: [val(meta), vcf] - ch_gripps_germline_hard = ch_gripss_germline_out.map { meta, h, hi, s, si -> [meta, h] } + if (run.gripss) { + ch_linx_inputs_germline_source = ch_gripss_germline_out.map { meta, h, hi, s, si -> [meta, h] } + } else { + ch_linx_inputs_germline_source = WorkflowOncoanalyser.get_input(ch_inputs, ['vcf_sv_gripss_hard', 'normal']) + } + // channel: [val(meta), sv_vcf, purple_dir] + ch_linx_inputs_somatic_source = run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']) + + // Create inputs and create process-specific meta + // channel: [val(meta_linx), sv_vcf] + ch_linx_inputs_germline = ch_linx_inputs_germline_source + .map { + def meta = it[0] + def meta_linx = [ + key: meta.id, + id: meta.id, + ] + return [meta_linx, it[1..-1]] + } + // channel: [val(meta_linx), purple_dir] + ch_linx_inputs_somatic = ch_linx_inputs_somatic_source + .map { + def meta = it[0] + def meta_linx = [ + key: meta.id, + id: meta.id, + ] + return [meta_linx, it[1..-1]] + } + // Run process LINX( - run.gripss ? ch_gripps_germline_hard : WorkflowOncoanalyser.get_input(ch_inputs, ['vcf_sv_gripss_hard', 'normal']), - run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), + ch_linx_inputs_germline, + ch_linx_inputs_somatic, PREPARE_REFERENCE.out.genome_version, hmf_data.linx_fragile_sites, hmf_data.linx_lines, @@ -614,15 +848,20 @@ workflow ONCOANALYSER { hmf_data.known_fusion_data, hmf_data.driver_gene_panel, ) + + // Set outputs, restoring original meta ch_versions = ch_versions.mix(LINX.out.versions) - ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX.out.somatic) + ch_linx_somatic_out = ch_linx_somatic_out.mix(WorkflowOncoanalyser.restore_meta(LINX.out.somatic, ch_inputs)) // // MODULE: Run gpgr to generate a LINX report // + // Run process LINX_REPORT( ch_linx_somatic_out, ) + + // Set outputs ch_versions = ch_versions.mix(LINX_REPORT.out.versions) } @@ -630,7 +869,7 @@ workflow ONCOANALYSER { // MODULE: Run CUPPA predict tissue of origin // if (run.cuppa) { - + // Select input sources // channel: [val(meta), isofox_dir] if (run.isofox) { ch_cuppa_inputs_isofox = Channel.empty() @@ -650,7 +889,7 @@ workflow ONCOANALYSER { // NOTE(SW): the Groovy Collection.flatten method used in // WorkflowOncoanalyser.group_by_meta removes optional Isofox input; flattening // done manually below to preserve - ch_cuppa_inputs = WorkflowOncoanalyser.group_by_meta( + ch_cuppa_inputs_source = WorkflowOncoanalyser.group_by_meta( ch_cuppa_inputs_isofox, run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), run.linx ? ch_linx_anno : WorkflowOncoanalyser.get_input(ch_inputs, ['linx_dir', 'tumor']), @@ -663,21 +902,40 @@ workflow ONCOANALYSER { return [meta, *inputs] } + // Create inputs and create process-specific meta + // channel: [val(meta_cuppa), isofox_dir, purple_dir, linx_dir, virusinterpreter_dir] + ch_cuppa_inputs = ch_cuppa_inputs_source + .map { + def meta = it[0] + def meta_cuppa = [ + key: meta.id, + id: meta.get(['sample_name', 'tumor']), + ] + return [meta_cuppa, *it[1..-1]] + } + + // Run process CUPPA_CLASSIFIER( ch_cuppa_inputs, hmf_data.cuppa, ) + + // Set outputs ch_versions = ch_versions.mix(CUPPA_CLASSIFIER.out.versions) + // Run process CUPPA_VISUALISER( CUPPA_CLASSIFIER.out.csv, ) + + // Set outputs ch_versions = ch_versions.mix(CUPPA_VISUALISER.out.versions) } // // MODULE: Pipeline reporting // + // Run process CUSTOM_DUMPSOFTWAREVERSIONS( ch_versions.unique().collectFile(name: 'collated_versions.yml') ) From c272cac5633b1945e847e26012c8acf5554871cb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 5 Dec 2022 18:34:11 +1100 Subject: [PATCH 007/562] Remove samplesheet_check.nf, update output locations --- conf/modules.config | 6 +++--- modules/local/samplesheet_check.nf | 27 --------------------------- 2 files changed, 3 insertions(+), 30 deletions(-) delete mode 100644 modules/local/samplesheet_check.nf diff --git a/conf/modules.config b/conf/modules.config index 99dc61cd..6b222ded 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -141,7 +141,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/pave/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/pave/${filename}" }, ] } @@ -231,7 +231,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/cuppa/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/cuppa/${filename}" }, ] } @@ -240,7 +240,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/cuppa/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/cuppa/${filename}" }, ] } } diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf deleted file mode 100644 index 0c2c85bc..00000000 --- a/modules/local/samplesheet_check.nf +++ /dev/null @@ -1,27 +0,0 @@ -process SAMPLESHEET_CHECK { - tag "$samplesheet" - - conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/python:3.8.3' : - 'quay.io/biocontainers/python:3.8.3' }" - - input: - path samplesheet - - output: - path '*.csv' , emit: csv - path "versions.yml", emit: versions - - script: // This script is bundled with the pipeline, in nf-core/oncoanalyser/bin/ - """ - check_samplesheet.py \\ - $samplesheet \\ - samplesheet.valid.csv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - python: \$(python --version | sed 's/Python //g') - END_VERSIONS - """ -} From 568c79c701bb823fe277c1771dbc63b7eb5c4880 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 5 Dec 2022 17:12:29 +1100 Subject: [PATCH 008/562] Select appropriate CUPPA classification categories --- modules/local/cuppa/classifier/main.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index 7a593d0b..a5d43677 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -17,6 +17,7 @@ process CUPPA_CLASSIFIER { script: def args = task.ext.args ?: '' + def categories_arg = isofox_dir ? 'ALL' : 'DNA' """ # Symlink input files into a single directory @@ -27,7 +28,7 @@ process CUPPA_CLASSIFIER { java \\ -Xmx${task.memory.giga}g \\ -jar ${task.ext.jarPath} \\ - -categories ALL \\ + -categories ${categories_arg} \\ -ref_data_dir ${reference_data} \\ -sample_data ${meta.id} \\ -sample_data_dir sample_data/ \\ From d5f04ab32aecb1a9a6cf1e7679b7d230ec636c5a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 6 Dec 2022 11:32:47 +1100 Subject: [PATCH 009/562] Update LINX publish paths to avoid changing output --- conf/modules.config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 6b222ded..adff181c 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -107,7 +107,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/germline/" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/germline_annotations/" }, ] } @@ -115,7 +115,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic/" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic_annotations/" }, ] } @@ -124,7 +124,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic/plots/" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic_plots/" }, ] } From e32f2ea414ea9895d9e15289f2b68a9ff6ac8cfd Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 6 Dec 2022 12:04:22 +1100 Subject: [PATCH 010/562] Use camel case for functions --- lib/Constants.groovy | 8 -- lib/Processes.groovy | 17 ++-- lib/Utils.groovy | 14 +++ lib/WorkflowLilac.groovy | 6 +- lib/WorkflowOncoanalyser.groovy | 12 +-- modules/local/lilac/main.nf | 4 +- subworkflows/local/gridss.nf | 4 +- subworkflows/local/gridss_svprep.nf | 12 +-- subworkflows/local/gripss.nf | 4 +- subworkflows/local/lilac.nf | 16 ++-- subworkflows/local/linx.nf | 2 +- subworkflows/local/prepare_reference.nf | 70 +++++++-------- workflows/oncoanalyser.nf | 115 ++++++++++-------------- 13 files changed, 136 insertions(+), 148 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 7fb963c0..d8ed5f8d 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -35,14 +35,6 @@ class Constants { VIRUSINTERPRETER, } - static public get_enum_from_string(s, e) { - try { - return e.valueOf(s.toUpperCase()) - } catch(java.lang.IllegalArgumentException err) { - return null - } - } - static public java.util.Map HMF_DATA_PATHS = [ AMBER_LOCI: 'amber/GermlineHetPon.vcf.gz', COBALT_GC_PROFILE: 'cobalt/DiploidRegions.bed.gz', diff --git a/lib/Processes.groovy b/lib/Processes.groovy index 8b209589..f290dc08 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -1,12 +1,13 @@ import Constants +import Utils class Processes { - public static set_processes(mode_str, log) { - def mode_enum = Constants.get_enum_from_string(mode_str, Constants.PipelineMode) + public static setProcesses(mode_str, log) { + def mode_enum = Utils.getEnumFromString(mode_str, Constants.PipelineMode) if (!mode_enum) { - def workflows_str = Processes.get_workflow_names().join('\n - ') + def workflows_str = Processes.getWorkflowNames().join('\n - ') log.error "\nERROR: recieved invalid pipeline mode: '${mode_str}'. Valid options are:\n - ${workflows_str}" System.exit(1) } @@ -51,7 +52,7 @@ class Processes { return processes } - public static get_process_list(process_str, log) { + public static getProcessList(process_str, log) { if (!process_str) { return [] } @@ -61,7 +62,7 @@ class Processes { try { return Constants.Process.valueOf(name.toUpperCase()) } catch(java.lang.IllegalArgumentException e) { - def processes_str = Processes.get_process_names().join('\n - ') + def processes_str = Processes.getProcessNames().join('\n - ') log.error "\nERROR: recieved invalid process: '${name}'. Valid options are:\n - ${processes_str}" System.exit(1) } @@ -69,7 +70,7 @@ class Processes { .unique() } - public static check_include_exclude_list(include_list, exclude_list, log) { + public static checkIncludeExcludeList(include_list, exclude_list, log) { def processes_shared = [*include_list, *exclude_list] .countBy { it } .findAll { k, v -> v > 1 } @@ -83,14 +84,14 @@ class Processes { } } - public static get_workflow_names() { + public static getWorkflowNames() { Constants.PipelineMode .values() *.name() *.toLowerCase() } - public static get_process_names() { + public static getProcessNames() { Constants.Process .values() *.name() diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 8d030f4e..42b410a6 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -4,6 +4,8 @@ import org.yaml.snakeyaml.Yaml +import nextflow.Nextflow + class Utils { // @@ -44,4 +46,16 @@ class Utils { "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" } } + + static public getEnumFromString(s, e) { + try { + return e.valueOf(s.toUpperCase()) + } catch(java.lang.IllegalArgumentException err) { + return null + } + } + + static public getFileObject(path) { + return path ? Nextflow.file(path) : [] + } } diff --git a/lib/WorkflowLilac.groovy b/lib/WorkflowLilac.groovy index 359bb162..54d3d516 100755 --- a/lib/WorkflowLilac.groovy +++ b/lib/WorkflowLilac.groovy @@ -4,7 +4,7 @@ class WorkflowLilac { - public static get_slice_inputs(ch, ch_slice_bed) { + public static getSliceInputs(ch, ch_slice_bed) { // channel: [val(meta_lilac), bam, bai] def d = ch .flatMap { meta, tbam, nbam, tbai, nbai -> @@ -26,7 +26,7 @@ class WorkflowLilac { return d.combine(ch_slice_bed) } - public static get_unique_input_files(ch) { + public static getUniqueInputFiles(ch) { // channel: [val(meta_lilac), bam, bai, bed] def d = ch .map { [it[1..-1], it[0]] } @@ -54,7 +54,7 @@ class WorkflowLilac { return d } - public static sort_slices(ch) { + public static sortSlices(ch) { // Collect T/N pairs into single channel element // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] def d = ch diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 7b7e466e..a5ecbd01 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -70,7 +70,7 @@ class WorkflowOncoanalyser { } } - public static prepare_inputs(ch, stub_run, log) { + public static prepareInputs(ch, stub_run, log) { return ch .splitCsv(header: true, strip: true, sep: '\t') .map { [it.id, it] } @@ -162,7 +162,7 @@ class WorkflowOncoanalyser { } } - public static group_by_meta(Map named_args, ... channels) { + public static groupByMeta(Map named_args, ... channels) { def r = channels // Set position; required to use non-blocking .mix operator // NOTE(SW): operating on native list object containing channels @@ -199,15 +199,15 @@ class WorkflowOncoanalyser { } // NOTE(SW): function signature required to catch where no named arguments are passed - public static group_by_meta(... channels) { - return group_by_meta([:], *channels) + public static groupByMeta(... channels) { + return groupByMeta([:], *channels) } - public static get_input(ch, key) { + public static getInput(ch, key) { return ch.map { meta -> [meta, meta.getAt(key)] } } - public static restore_meta(ch_output, ch_metas) { + public static restoreMeta(ch_output, ch_metas) { // NOTE(SW): ch_output must contain a Map in the first position with a key named 'key' that // contains the corresponding meta.id value, for example: [val(meta_process), *process_outputs] diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index a2fcf6f7..79103baa 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -19,7 +19,7 @@ process LILAC { script: def args = task.ext.args ?: '' - def sample_name = get_sample_name(meta, tumor_bam, normal_bam) + def sample_name = getSampleName(meta, tumor_bam, normal_bam) def tumor_bam_arg = tumor_bam ? "-tumor_bam ${tumor_bam}" : '' def purple_args = purple_dir ? """ -gene_copy_number ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ @@ -55,7 +55,7 @@ process LILAC { """ } -def get_sample_name(meta, tumor_bam, normal_bam) { +def getSampleName(meta, tumor_bam, normal_bam) { if (tumor_bam) { return meta.tumor_id } else if (normal_bam) { diff --git a/subworkflows/local/gridss.nf b/subworkflows/local/gridss.nf index 4057aae9..a347fba3 100644 --- a/subworkflows/local/gridss.nf +++ b/subworkflows/local/gridss.nf @@ -54,7 +54,7 @@ workflow GRIDSS { // Gather BAMs and outputs from preprocessing for each tumor/normal set // channel: [subject_id, [[val(meta_gridss), bam, preprocess_dir], ...]] - ch_bams_and_preprocess = WorkflowOncoanalyser.group_by_meta( + ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( ch_preprocess_inputs, PREPROCESS.out.preprocess_dir, ) @@ -87,7 +87,7 @@ workflow GRIDSS { // Prepare inputs for variant calling // channel: [val(meta_gridss), [bams], assemble_dir, [labels]] - ch_call_inputs = WorkflowOncoanalyser.group_by_meta( + ch_call_inputs = WorkflowOncoanalyser.groupByMeta( ch_assemble_inputs, ASSEMBLE.out.assemble_dir, flatten: false, diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep.nf index d8226172..42d02ab3 100644 --- a/subworkflows/local/gridss_svprep.nf +++ b/subworkflows/local/gridss_svprep.nf @@ -56,7 +56,7 @@ workflow GRIDSS_SVPREP { // Prepare normal sample inputs // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] - ch_svprep_normal_inputs = WorkflowOncoanalyser.restore_meta(SVPREP_TUMOR.out.junctions, ch_inputs) + ch_svprep_normal_inputs = WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs) .map { meta, junctions_tumor -> def meta_svprep = [ key: meta.id, @@ -79,7 +79,7 @@ workflow GRIDSS_SVPREP { ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) // channel: [val(meta_gridss), bam_tumor, bam_tumor_filtered] - ch_preprocess_inputs_tumor = WorkflowOncoanalyser.group_by_meta( + ch_preprocess_inputs_tumor = WorkflowOncoanalyser.groupByMeta( SVPREP_TUMOR.out.bam, ch_svprep_tumor_inputs, ) @@ -88,7 +88,7 @@ workflow GRIDSS_SVPREP { } // channel: [val(meta_gridss), bam_normal, bam_normal_filtered] - ch_preprocess_inputs_normal = WorkflowOncoanalyser.group_by_meta( + ch_preprocess_inputs_normal = WorkflowOncoanalyser.groupByMeta( SVPREP_NORMAL.out.bam, ch_svprep_normal_inputs, ) @@ -121,7 +121,7 @@ workflow GRIDSS_SVPREP { // Gather BAMs and outputs from preprocessing for each tumor/normal set // channel: [key, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] - ch_bams_and_preprocess = WorkflowOncoanalyser.group_by_meta( + ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( ch_preprocess_inputs, GRIDSS_PREPROCESS.out.preprocess_dir, ) @@ -163,7 +163,7 @@ workflow GRIDSS_SVPREP { // Prepare inputs for variant calling // channel: [val(meta_gridss), [bams], [bams_filtered], assemble_dir, [labels]] - ch_call_inputs = WorkflowOncoanalyser.group_by_meta( + ch_call_inputs = WorkflowOncoanalyser.groupByMeta( ch_assemble_inputs, GRIDSS_ASSEMBLE.out.assemble_dir, flatten: false, @@ -191,7 +191,7 @@ workflow GRIDSS_SVPREP { // Prepare inputs for depth annotation, restore original meta // channel: [val(meta), [bams], [bais], vcf, [labels]] - ch_depth_inputs = WorkflowOncoanalyser.group_by_meta( + ch_depth_inputs = WorkflowOncoanalyser.groupByMeta( ch_inputs.map { meta -> [meta.id, meta] }, GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) diff --git a/subworkflows/local/gripss.nf b/subworkflows/local/gripss.nf index b50494ed..dd4e8426 100644 --- a/subworkflows/local/gripss.nf +++ b/subworkflows/local/gripss.nf @@ -48,12 +48,12 @@ workflow GRIPSS { // Pack output // channel: [val(meta_gripss), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - ch_germline_out = WorkflowOncoanalyser.group_by_meta( + ch_germline_out = WorkflowOncoanalyser.groupByMeta( GRIPSS_GERMLINE.out.vcf_hard, GRIPSS_GERMLINE.out.vcf_soft, ) // channel: [val(meta_gripss), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - ch_somatic_out = WorkflowOncoanalyser.group_by_meta( + ch_somatic_out = WorkflowOncoanalyser.groupByMeta( GRIPSS_SOMATIC.out.vcf_hard, GRIPSS_SOMATIC.out.vcf_soft, ) diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index ec654424..323940ba 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -31,9 +31,9 @@ workflow LILAC { // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used // in Pipeline5, see LilacBamSlicer.java#L115 // channel: [val(meta_lilac), bam, bai, bed] - ch_slice_inputs = WorkflowLilac.get_slice_inputs(ch_inputs_bams, ch_slice_bed) + ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_inputs_bams, ch_slice_bed) // channel: [val(meta_lilac), bam, bai, bed] - ch_slice_inputs = WorkflowLilac.get_unique_input_files(ch_slice_inputs) + ch_slice_inputs = WorkflowLilac.getUniqueInputFiles(ch_slice_inputs) SLICE( ch_slice_inputs, ) @@ -60,24 +60,24 @@ workflow LILAC { // Create input channel for LILAC // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] - ch_lilac_inputs_slices = WorkflowOncoanalyser.restore_meta( - WorkflowLilac.sort_slices(REALIGN_READS.out.bam), + ch_lilac_inputs_slices = WorkflowOncoanalyser.restoreMeta( + WorkflowLilac.sortSlices(REALIGN_READS.out.bam), ch_metas, ) // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] - ch_lilac_inputs_full = WorkflowOncoanalyser.group_by_meta( + ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( ch_lilac_inputs_slices, ch_inputs_purple_dir, ) } else { // Create input channel for LILAC // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] - ch_lilac_inputs_slices = WorkflowOncoanalyser.restore_meta( - WorkflowLilac.sort_slices(SLICE.out.bam), + ch_lilac_inputs_slices = WorkflowOncoanalyser.restoreMeta( + WorkflowLilac.sortSlices(SLICE.out.bam), ch_metas, ) // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] - ch_lilac_inputs_full = WorkflowOncoanalyser.group_by_meta( + ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( ch_lilac_inputs_slices, ch_inputs_purple_dir, ) diff --git a/subworkflows/local/linx.nf b/subworkflows/local/linx.nf index cd7d42ef..ee0a99dc 100644 --- a/subworkflows/local/linx.nf +++ b/subworkflows/local/linx.nf @@ -52,7 +52,7 @@ workflow LINX { ch_versions = ch_versions.mix(VISUALISER.out.versions) // channel: [val(meta), linx_annotation_dir, linx_visualiser_dir] - ch_linx_somatic_out = WorkflowOncoanalyser.group_by_meta( + ch_linx_somatic_out = WorkflowOncoanalyser.groupByMeta( LINX_SOMATIC.out.annotation_dir, VISUALISER.out.visualiser_dir, ) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 10e95336..b73ce89f 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -92,12 +92,12 @@ workflow PREPARE_REFERENCE { .collect() .map { dir_list -> assert dir_list.size() == 1 - return create_hmf_data_map(dir_list[0], false /* params_only */) + return createHmfDataMap(dir_list[0], false /* params_only */) } ch_versions = ch_versions.mix(HMF_REFERENCE.out.versions) } else { // If no HMF data bundle is supplied we construct from *only* params - ch_hmf_data = create_hmf_data_map(null, true /* params_only */) + ch_hmf_data = createHmfDataMap(null, true /* params_only */) } emit: @@ -113,56 +113,56 @@ workflow PREPARE_REFERENCE { versions = ch_versions // channel: [versions.yml] } -def create_hmf_data_map(hmf_bundle_dir, params_only) { +def createHmfDataMap(hmf_bundle_dir, params_only) { return [ // AMBER - 'amber_loci': get_hmf_data_file_object('ref_data_amber_loci', 'AMBER_LOCI', hmf_bundle_dir, params_only), + 'amber_loci': getHmfDataFileObject('ref_data_amber_loci', 'AMBER_LOCI', hmf_bundle_dir, params_only), // COBALT - 'cobalt_gc_profile': get_hmf_data_file_object('ref_data_cobalt_gc_profile', 'COBALT_GC_PROFILE', hmf_bundle_dir, params_only), + 'cobalt_gc_profile': getHmfDataFileObject('ref_data_cobalt_gc_profile', 'COBALT_GC_PROFILE', hmf_bundle_dir, params_only), // CUPPA - 'cuppa': get_hmf_data_file_object('ref_data_cuppa', 'CUPPA', hmf_bundle_dir, params_only), + 'cuppa': getHmfDataFileObject('ref_data_cuppa', 'CUPPA', hmf_bundle_dir, params_only), // SVPREP - 'sv_prep_blacklist': get_hmf_data_file_object('ref_data_sv_prep_blacklist', 'SV_PREP_BLACKLIST', hmf_bundle_dir, params_only), + 'sv_prep_blacklist': getHmfDataFileObject('ref_data_sv_prep_blacklist', 'SV_PREP_BLACKLIST', hmf_bundle_dir, params_only), // GRIDSS, GRIPSS - 'gridss_blacklist': get_hmf_data_file_object('ref_data_gridss_blacklist', 'GRIDSS_BLACKLIST', hmf_bundle_dir, params_only), - 'gridss_breakend_pon': get_hmf_data_file_object('ref_data_gridss_breakend_pon', 'GRIDSS_BREAKEND_PON', hmf_bundle_dir, params_only), - 'gridss_breakpoint_pon': get_hmf_data_file_object('ref_data_gridss_breakpoint_pon', 'GRIDSS_BREAKPOINT_PON', hmf_bundle_dir, params_only), - 'repeat_masker_file': get_hmf_data_file_object('ref_data_repeat_masker_file', 'REPEAT_MASKER_FILE', hmf_bundle_dir, params_only), + 'gridss_blacklist': getHmfDataFileObject('ref_data_gridss_blacklist', 'GRIDSS_BLACKLIST', hmf_bundle_dir, params_only), + 'gridss_breakend_pon': getHmfDataFileObject('ref_data_gridss_breakend_pon', 'GRIDSS_BREAKEND_PON', hmf_bundle_dir, params_only), + 'gridss_breakpoint_pon': getHmfDataFileObject('ref_data_gridss_breakpoint_pon', 'GRIDSS_BREAKPOINT_PON', hmf_bundle_dir, params_only), + 'repeat_masker_file': getHmfDataFileObject('ref_data_repeat_masker_file', 'REPEAT_MASKER_FILE', hmf_bundle_dir, params_only), // Isofox - 'isofox_exp_counts': get_hmf_data_file_object('ref_data_isofox_exp_counts', 'ISOFOX_EXP_COUNTS', hmf_bundle_dir, params_only), - 'isofox_exp_gc_ratios': get_hmf_data_file_object('ref_data_isofox_exp_gc_ratios', 'ISOFOX_EXP_GC_RATIOS', hmf_bundle_dir, params_only), + 'isofox_exp_counts': getHmfDataFileObject('ref_data_isofox_exp_counts', 'ISOFOX_EXP_COUNTS', hmf_bundle_dir, params_only), + 'isofox_exp_gc_ratios': getHmfDataFileObject('ref_data_isofox_exp_gc_ratios', 'ISOFOX_EXP_GC_RATIOS', hmf_bundle_dir, params_only), // LINX - 'linx_fragile_sites': get_hmf_data_file_object('ref_data_linx_fragile_sites', 'LINX_FRAGILE_SITES', hmf_bundle_dir, params_only), - 'linx_lines': get_hmf_data_file_object('ref_data_linx_lines', 'LINX_LINES', hmf_bundle_dir, params_only), + 'linx_fragile_sites': getHmfDataFileObject('ref_data_linx_fragile_sites', 'LINX_FRAGILE_SITES', hmf_bundle_dir, params_only), + 'linx_lines': getHmfDataFileObject('ref_data_linx_lines', 'LINX_LINES', hmf_bundle_dir, params_only), // SAGE, PAVE - 'sage_blacklist_bed': get_hmf_data_file_object('ref_data_sage_blacklist_bed', 'SAGE_BLACKLIST_BED', hmf_bundle_dir, params_only), - 'sage_blacklist_vcf': get_hmf_data_file_object('ref_data_sage_blacklist_vcf', 'SAGE_BLACKLIST_VCF', hmf_bundle_dir, params_only), - 'sage_coding_panel': get_hmf_data_file_object('ref_data_sage_coding_panel', 'SAGE_CODING_PANEL', hmf_bundle_dir, params_only), - 'sage_high_confidence': get_hmf_data_file_object('ref_data_sage_high_confidence', 'SAGE_HIGH_CONFIDENCE', hmf_bundle_dir, params_only), - 'sage_known_hotspots_germline': get_hmf_data_file_object('ref_data_sage_known_hotspots_germline', 'SAGE_KNOWN_HOTSPOTS_GERMLINE', hmf_bundle_dir, params_only), - 'sage_known_hotspots_somatic': get_hmf_data_file_object('ref_data_sage_known_hotspots_somatic', 'SAGE_KNOWN_HOTSPOTS_SOMATIC', hmf_bundle_dir, params_only), - 'sage_pon_file': get_hmf_data_file_object('ref_data_sage_pon_file', 'SAGE_PON_FILE', hmf_bundle_dir, params_only), - 'clinvar_vcf': get_hmf_data_file_object('ref_data_clinvar_vcf', 'CLINVAR_VCF', hmf_bundle_dir, params_only), + 'sage_blacklist_bed': getHmfDataFileObject('ref_data_sage_blacklist_bed', 'SAGE_BLACKLIST_BED', hmf_bundle_dir, params_only), + 'sage_blacklist_vcf': getHmfDataFileObject('ref_data_sage_blacklist_vcf', 'SAGE_BLACKLIST_VCF', hmf_bundle_dir, params_only), + 'sage_coding_panel': getHmfDataFileObject('ref_data_sage_coding_panel', 'SAGE_CODING_PANEL', hmf_bundle_dir, params_only), + 'sage_high_confidence': getHmfDataFileObject('ref_data_sage_high_confidence', 'SAGE_HIGH_CONFIDENCE', hmf_bundle_dir, params_only), + 'sage_known_hotspots_germline': getHmfDataFileObject('ref_data_sage_known_hotspots_germline', 'SAGE_KNOWN_HOTSPOTS_GERMLINE', hmf_bundle_dir, params_only), + 'sage_known_hotspots_somatic': getHmfDataFileObject('ref_data_sage_known_hotspots_somatic', 'SAGE_KNOWN_HOTSPOTS_SOMATIC', hmf_bundle_dir, params_only), + 'sage_pon_file': getHmfDataFileObject('ref_data_sage_pon_file', 'SAGE_PON_FILE', hmf_bundle_dir, params_only), + 'clinvar_vcf': getHmfDataFileObject('ref_data_clinvar_vcf', 'CLINVAR_VCF', hmf_bundle_dir, params_only), // SIGS - 'sigs_signatures': get_hmf_data_file_object('ref_data_sigs_signatures', 'SIGS_SIGNATURES', hmf_bundle_dir, params_only), + 'sigs_signatures': getHmfDataFileObject('ref_data_sigs_signatures', 'SIGS_SIGNATURES', hmf_bundle_dir, params_only), // LILAC - 'lilac_resource_dir': get_hmf_data_file_object('ref_data_lilac_resource_dir', 'LILAC_RESOURCE_DIR', hmf_bundle_dir, params_only), + 'lilac_resource_dir': getHmfDataFileObject('ref_data_lilac_resource_dir', 'LILAC_RESOURCE_DIR', hmf_bundle_dir, params_only), // VIRUSBreakend - 'virusbreakenddb': get_hmf_data_file_object('ref_data_virusbreakenddb', 'VIRUSBREAKENDDB', hmf_bundle_dir, params_only), + 'virusbreakenddb': getHmfDataFileObject('ref_data_virusbreakenddb', 'VIRUSBREAKENDDB', hmf_bundle_dir, params_only), // Virus Interpreter - 'virus_taxonomy': get_hmf_data_file_object('ref_data_virus_taxonomy', 'VIRUSINTERPRETER_TAXONOMY', hmf_bundle_dir, params_only), - 'virus_reporting': get_hmf_data_file_object('ref_data_virus_reporting', 'VIRUSINTERPRETER_REPORTING', hmf_bundle_dir, params_only), + 'virus_taxonomy': getHmfDataFileObject('ref_data_virus_taxonomy', 'VIRUSINTERPRETER_TAXONOMY', hmf_bundle_dir, params_only), + 'virus_reporting': getHmfDataFileObject('ref_data_virus_reporting', 'VIRUSINTERPRETER_REPORTING', hmf_bundle_dir, params_only), // Misc - 'purple_germline_del': get_hmf_data_file_object('ref_data_purple_germline_del', 'PURPLE_GERMLINE_DEL', hmf_bundle_dir, params_only), - 'driver_gene_panel': get_hmf_data_file_object('ref_data_driver_gene_panel', 'DRIVER_GENE_PANEL', hmf_bundle_dir, params_only), - 'ensembl_data_dir': get_hmf_data_file_object('ref_data_ensembl_data_dir', 'ENSEMBL_DATA_DIR', hmf_bundle_dir, params_only), - 'known_fusion_data': get_hmf_data_file_object('ref_data_known_fusion_data', 'KNOWN_FUSION_DATA', hmf_bundle_dir, params_only), - 'known_fusions': get_hmf_data_file_object('ref_data_known_fusions', 'KNOWN_FUSIONS', hmf_bundle_dir, params_only), - 'mappability_bed': get_hmf_data_file_object('ref_data_mappability_bed', 'MAPPABILITY_BED', hmf_bundle_dir, params_only), + 'purple_germline_del': getHmfDataFileObject('ref_data_purple_germline_del', 'PURPLE_GERMLINE_DEL', hmf_bundle_dir, params_only), + 'driver_gene_panel': getHmfDataFileObject('ref_data_driver_gene_panel', 'DRIVER_GENE_PANEL', hmf_bundle_dir, params_only), + 'ensembl_data_dir': getHmfDataFileObject('ref_data_ensembl_data_dir', 'ENSEMBL_DATA_DIR', hmf_bundle_dir, params_only), + 'known_fusion_data': getHmfDataFileObject('ref_data_known_fusion_data', 'KNOWN_FUSION_DATA', hmf_bundle_dir, params_only), + 'known_fusions': getHmfDataFileObject('ref_data_known_fusions', 'KNOWN_FUSIONS', hmf_bundle_dir, params_only), + 'mappability_bed': getHmfDataFileObject('ref_data_mappability_bed', 'MAPPABILITY_BED', hmf_bundle_dir, params_only), ] } -def get_hmf_data_file_object(pk, hk, base_dir, params_only) { +def getHmfDataFileObject(pk, hk, base_dir, params_only) { if (params.containsKey(pk)) { return file(params.getAt(pk), checkIfExists: true) } else if (params_only) { diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 40a82ac0..d3fa57fb 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -1,5 +1,6 @@ -import Processes import Constants +import Processes +import Utils /* @@ -13,13 +14,11 @@ def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) // Validate input parameters WorkflowOncoanalyser.initialise(params, workflow, log) - // Set processes to run -processes = Processes.set_processes(params.mode, log) - -processes_include = Processes.get_process_list(params.processes_include, log) -processes_exclude = Processes.get_process_list(params.processes_exclude, log) -Processes.check_include_exclude_list(processes_include, processes_exclude, log) +processes = Processes.setProcesses(params.mode, log) +processes_include = Processes.getProcessList(params.processes_include, log) +processes_exclude = Processes.getProcessList(params.processes_exclude, log) +Processes.checkIncludeExcludeList(processes_include, processes_exclude, log) processes.addAll(processes_include) processes.removeAll(processes_exclude) @@ -28,7 +27,6 @@ run = Constants.Process .values() .collectEntries { p -> [p.name().toLowerCase(), p in processes] } - // Check input path parameters to see if they exist def checkPathParamList = [ params.input, @@ -102,25 +100,8 @@ include { PICARD_COLLECTWGSMETRICS as COLLECTWGSMETRICS } from '../modules/nf-co */ // Get absolute file paths -def get_file_object(path) { - return path ? file(path) : [] -} -samplesheet = get_file_object(params.input) -gridss_config = get_file_object(params.gridss_config) - -// Set processes to run -processes = Processes.set_processes(params.mode, log) -processes_include = Processes.get_process_list(params.processes_include, log) -processes_exclude = Processes.get_process_list(params.processes_exclude, log) -Processes.check_include_exclude_list(processes_include, processes_exclude, log) - -processes.addAll(processes_include) -processes.removeAll(processes_exclude) - -run = Constants.Process - .values() - .collectEntries { p -> [p.name().toLowerCase(), p in processes] } - +samplesheet = Utils.getFileObject(params.input) +gridss_config = Utils.getFileObject(params.gridss_config) workflow ONCOANALYSER { // Create channel for versions @@ -133,7 +114,7 @@ workflow ONCOANALYSER { params.mode, ) // channel: [val(meta)] - ch_inputs = WorkflowOncoanalyser.prepare_inputs(CHECK_SAMPLESHEET.out, workflow.stubRun, log) + ch_inputs = WorkflowOncoanalyser.prepareInputs(CHECK_SAMPLESHEET.out, workflow.stubRun, log) // Set up reference data and unpack HMF data map for convenience PREPARE_REFERENCE(run) @@ -188,7 +169,7 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(ISOFOX.out.versions) - ch_isofox_out = ch_isofox_out.mix(WorkflowOncoanalyser.restore_meta(ISOFOX.out.isofox_dir, ch_inputs)) + ch_isofox_out = ch_isofox_out.mix(WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs)) } // @@ -264,7 +245,7 @@ workflow ONCOANALYSER { // Match outputs to original meta and set output // channel (tumor): [val(meta), metrics] // channel (normal): [val(meta), metrics] - ch_cwm_output = WorkflowOncoanalyser.restore_meta(ch_cwm_output_individual, ch_inputs) + ch_cwm_output = WorkflowOncoanalyser.restoreMeta(ch_cwm_output_individual, ch_inputs) .branch { meta, sample_type, metrics -> tumor: sample_type == 'tumor' return [meta, metrics] @@ -303,7 +284,7 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(AMBER.out.versions) - ch_amber_out = ch_amber_out.mix(WorkflowOncoanalyser.restore_meta(AMBER.out.amber_dir, ch_inputs)) + ch_amber_out = ch_amber_out.mix(WorkflowOncoanalyser.restoreMeta(AMBER.out.amber_dir, ch_inputs)) } // @@ -335,7 +316,7 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(COBALT.out.versions) - ch_cobalt_out = ch_cobalt_out.mix(WorkflowOncoanalyser.restore_meta(COBALT.out.cobalt_dir, ch_inputs)) + ch_cobalt_out = ch_cobalt_out.mix(WorkflowOncoanalyser.restoreMeta(COBALT.out.cobalt_dir, ch_inputs)) } // @@ -397,7 +378,7 @@ workflow ONCOANALYSER { if (run.gridss) { ch_gripss_inputs_source = ch_gridss_out } else { - ch_gripss_inputs_source = WorkflowOncoanalyser.get_input(ch_inputs, ['gridss_vcf', 'tumor_normal']) + ch_gripss_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, ['gridss_vcf', 'tumor_normal']) } // Create inputs and create process-specific meta @@ -427,8 +408,8 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(GRIPSS.out.versions) - ch_gripss_germline_out = ch_gripss_germline_out.mix(WorkflowOncoanalyser.restore_meta(GRIPSS.out.germline, ch_inputs)) - ch_gripss_somatic_out = ch_gripss_somatic_out.mix(WorkflowOncoanalyser.restore_meta(GRIPSS.out.somatic, ch_inputs)) + ch_gripss_germline_out = ch_gripss_germline_out.mix(WorkflowOncoanalyser.restoreMeta(GRIPSS.out.germline, ch_inputs)) + ch_gripss_somatic_out = ch_gripss_somatic_out.mix(WorkflowOncoanalyser.restoreMeta(GRIPSS.out.somatic, ch_inputs)) } // @@ -470,8 +451,8 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(SAGE.out.versions) - ch_sage_germline_out = ch_sage_germline_out.mix(WorkflowOncoanalyser.restore_meta(SAGE.out.germline, ch_inputs)) - ch_sage_somatic_out = ch_sage_somatic_out.mix(WorkflowOncoanalyser.restore_meta(SAGE.out.somatic, ch_inputs)) + ch_sage_germline_out = ch_sage_germline_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.germline, ch_inputs)) + ch_sage_somatic_out = ch_sage_somatic_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.somatic, ch_inputs)) } // @@ -488,8 +469,8 @@ workflow ONCOANALYSER { ch_pave_germline_inputs_source = ch_sage_germline_out ch_pave_somatic_inputs_source = ch_sage_somatic_out } else { - ch_pave_germline_inputs_source = WorkflowOncoanalyser.get_input(ch_inputs, ['sage_vcf', 'normal']) - ch_pave_somatic_inputs_source = WorkflowOncoanalyser.get_input(ch_inputs, ['sage_vcf', 'tumor']) + ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, ['sage_vcf', 'normal']) + ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, ['sage_vcf', 'tumor']) } // Create inputs and create process-specific meta @@ -529,8 +510,8 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(PAVE.out.versions) - ch_pave_germline_out = ch_pave_germline_out.mix(WorkflowOncoanalyser.restore_meta(PAVE.out.germline, ch_inputs)) - ch_pave_somatic_out = ch_pave_somatic_out.mix(WorkflowOncoanalyser.restore_meta(PAVE.out.somatic, ch_inputs)) + ch_pave_germline_out = ch_pave_germline_out.mix(WorkflowOncoanalyser.restoreMeta(PAVE.out.germline, ch_inputs)) + ch_pave_somatic_out = ch_pave_somatic_out.mix(WorkflowOncoanalyser.restoreMeta(PAVE.out.somatic, ch_inputs)) } // @@ -559,12 +540,12 @@ workflow ONCOANALYSER { } // channel: [val(meta), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] - ch_purple_inputs_sources = WorkflowOncoanalyser.group_by_meta( - run.amber ? ch_amber_out : WorkflowOncoanalyser.get_input(ch_inputs, ['amber_dir', 'tumor_normal']), - run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.get_input(ch_inputs, ['cobalt_dir', 'tumor_normal']), + ch_purple_inputs_sources = WorkflowOncoanalyser.groupByMeta( + run.amber ? ch_amber_out : WorkflowOncoanalyser.getInput(ch_inputs, ['amber_dir', 'tumor_normal']), + run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, ['cobalt_dir', 'tumor_normal']), ch_purple_inputs_sv, - run.pave ? ch_pave_somatic_out : WorkflowOncoanalyser.get_input(ch_inputs, ['vcf_smlv', 'tumor']), - run.pave ? ch_pave_germline_out : WorkflowOncoanalyser.get_input(ch_inputs, ['vcf_smlv', 'normal']), + run.pave ? ch_pave_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, ['vcf_smlv', 'tumor']), + run.pave ? ch_pave_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, ['vcf_smlv', 'normal']), ) // channel: [val(meta_purple), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] @@ -597,7 +578,7 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(PURPLE.out.versions) - ch_purple_out = ch_purple_out.mix(WorkflowOncoanalyser.restore_meta(PURPLE.out.purple_dir, ch_inputs)) + ch_purple_out = ch_purple_out.mix(WorkflowOncoanalyser.restoreMeta(PURPLE.out.purple_dir, ch_inputs)) } // @@ -609,7 +590,7 @@ workflow ONCOANALYSER { if (run.purple) { ch_sigs_inputs_source = ch_purple_out } else { - ch_sigs_inputs_source = WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']) + ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, ['purple_dir', 'tumor_normal']) } // Create inputs and create process-specific meta @@ -639,7 +620,7 @@ workflow ONCOANALYSER { if (run.purple) { ch_chord_inputs_source = ch_purple_out } else { - ch_chord_inputs_source = WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']) + ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, ['purple_dir', 'tumor_normal']) } // Create inputs and create process-specific meta @@ -670,12 +651,12 @@ workflow ONCOANALYSER { // Select input sources // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, tumor_wgs_metrics, normal_wgs_metrics, cobalt_dir, purple_dir] // NOTE(SW): assuming here that TEAL is being run in tumor/normal mode and so we expect a tumor metrics file and normal metrics file - ch_teal_inputs_source = WorkflowOncoanalyser.group_by_meta( + ch_teal_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_bams_and_indices, - run.collectwgsmetrics ? ch_cwm_output.tumor : WorkflowOncoanalyser.get_input(ch_inputs, ['collectmetrics', 'tumor']), - run.collectwgsmetrics ? ch_cwm_output.normal : WorkflowOncoanalyser.get_input(ch_inputs, ['collectmetrics', 'normal']), - run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), - run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.get_input(ch_inputs, ['cobalt_dir', 'tumor_normal']), + run.collectwgsmetrics ? ch_cwm_output.tumor : WorkflowOncoanalyser.getInput(ch_inputs, ['collectmetrics', 'tumor']), + run.collectwgsmetrics ? ch_cwm_output.normal : WorkflowOncoanalyser.getInput(ch_inputs, ['collectmetrics', 'normal']), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, ['purple_dir', 'tumor_normal']), + run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, ['cobalt_dir', 'tumor_normal']), ) // Create inputs and create process-specific meta @@ -710,13 +691,13 @@ workflow ONCOANALYSER { if (run.purple) { ch_lilac_inputs_source = ch_purple_out } else { - ch_lilac_inputs_source = WorkflowOncoanalyser.get_input(['purple_dir', 'tumor_normal']) + ch_lilac_inputs_source = WorkflowOncoanalyser.getInput(['purple_dir', 'tumor_normal']) } // Run process LILAC( ch_bams_and_indices, - run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(['purple_dir', 'tumor_normal']), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(['purple_dir', 'tumor_normal']), PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, hmf_data.lilac_resource_dir, @@ -769,8 +750,8 @@ workflow ONCOANALYSER { } // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] - ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.group_by_meta( - WorkflowOncoanalyser.restore_meta(VIRUSBREAKEND.out.tsv, ch_inputs), + ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( + WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), ch_virusinterpreter_inputs_purple, ch_cwm_output.tumor, ) @@ -796,7 +777,7 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) - ch_virusinterpreter_out = ch_virusinterpreter_out.mix(WorkflowOncoanalyser.restore_meta(VIRUSINTERPRETER.out.virusinterpreter_dir, ch_inputs)) + ch_virusinterpreter_out = ch_virusinterpreter_out.mix(WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter_dir, ch_inputs)) } // @@ -810,10 +791,10 @@ workflow ONCOANALYSER { if (run.gripss) { ch_linx_inputs_germline_source = ch_gripss_germline_out.map { meta, h, hi, s, si -> [meta, h] } } else { - ch_linx_inputs_germline_source = WorkflowOncoanalyser.get_input(ch_inputs, ['vcf_sv_gripss_hard', 'normal']) + ch_linx_inputs_germline_source = WorkflowOncoanalyser.getInput(ch_inputs, ['vcf_sv_gripss_hard', 'normal']) } // channel: [val(meta), sv_vcf, purple_dir] - ch_linx_inputs_somatic_source = run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']) + ch_linx_inputs_somatic_source = run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, ['purple_dir', 'tumor_normal']) // Create inputs and create process-specific meta // channel: [val(meta_linx), sv_vcf] @@ -851,7 +832,7 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(LINX.out.versions) - ch_linx_somatic_out = ch_linx_somatic_out.mix(WorkflowOncoanalyser.restore_meta(LINX.out.somatic, ch_inputs)) + ch_linx_somatic_out = ch_linx_somatic_out.mix(WorkflowOncoanalyser.restoreMeta(LINX.out.somatic, ch_inputs)) // // MODULE: Run gpgr to generate a LINX report @@ -887,13 +868,13 @@ workflow ONCOANALYSER { // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter_dir] // NOTE(SW): the Groovy Collection.flatten method used in - // WorkflowOncoanalyser.group_by_meta removes optional Isofox input; flattening + // WorkflowOncoanalyser.groupByMeta removes optional Isofox input; flattening // done manually below to preserve - ch_cuppa_inputs_source = WorkflowOncoanalyser.group_by_meta( + ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, - run.purple ? ch_purple_out : WorkflowOncoanalyser.get_input(ch_inputs, ['purple_dir', 'tumor_normal']), - run.linx ? ch_linx_anno : WorkflowOncoanalyser.get_input(ch_inputs, ['linx_dir', 'tumor']), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.get_input(ch_inputs, ['virusinterpreter', 'tumor']), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, ['purple_dir', 'tumor_normal']), + run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, ['linx_dir', 'tumor']), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, ['virusinterpreter', 'tumor']), flatten: false, ) .map { data -> From 5f5e5707eeb994b3d84662c7194d0755fb4abd45 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 7 Dec 2022 12:10:46 +1100 Subject: [PATCH 011/562] Replace samplesheet check process with subworkflow --- lib/Constants.groovy | 25 +++++ lib/Processes.groovy | 9 +- lib/Utils.groovy | 8 ++ lib/WorkflowLilac.groovy | 43 +++++---- lib/WorkflowOncoanalyser.groovy | 111 ----------------------- nextflow_schema.json | 8 +- subworkflows/local/gridss.nf | 31 +++++-- subworkflows/local/gridss_svprep.nf | 39 ++++---- subworkflows/local/input_check.nf | 44 --------- subworkflows/local/prepare_input.nf | 104 +++++++++++++++++++++ workflows/oncoanalyser.nf | 136 +++++++++++++++------------- 11 files changed, 287 insertions(+), 271 deletions(-) delete mode 100644 subworkflows/local/input_check.nf create mode 100644 subworkflows/local/prepare_input.nf diff --git a/lib/Constants.groovy b/lib/Constants.groovy index d8ed5f8d..60cd6aad 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -35,6 +35,31 @@ class Constants { VIRUSINTERPRETER, } + static enum DataType { + TUMOR, + NORMAL, + TUMOR_NORMAL, + } + + static enum FileType { + // Generic + BAM_WGS, + BAM_WTS, + // Process + AMBER_DIR, + COBALT_DIR, + COLLECTWGSMETRICS, + GRIDSS_VCF, + GRIPSS_HARD_VCF, + GRIPSS_SOFT_VCF, + ISOFOX_DIR, + LINX_DIR, + PAVE_VCF, + PURPLE_DIR, + SAGE_VCF, + VIRUSINTERPRETER, + } + static public java.util.Map HMF_DATA_PATHS = [ AMBER_LOCI: 'amber/GermlineHetPon.vcf.gz', COBALT_GC_PROFILE: 'cobalt/DiploidRegions.bed.gz', diff --git a/lib/Processes.groovy b/lib/Processes.groovy index f290dc08..7284ce4c 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -7,7 +7,7 @@ class Processes { public static setProcesses(mode_str, log) { def mode_enum = Utils.getEnumFromString(mode_str, Constants.PipelineMode) if (!mode_enum) { - def workflows_str = Processes.getWorkflowNames().join('\n - ') + def workflows_str = Utils.getEnumNames(Constants.PipelineMode).join('\n - ') log.error "\nERROR: recieved invalid pipeline mode: '${mode_str}'. Valid options are:\n - ${workflows_str}" System.exit(1) } @@ -84,13 +84,6 @@ class Processes { } } - public static getWorkflowNames() { - Constants.PipelineMode - .values() - *.name() - *.toLowerCase() - } - public static getProcessNames() { Constants.Process .values() diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 42b410a6..6b54c65c 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -55,6 +55,14 @@ class Utils { } } + public static getEnumNames(e) { + e + .values() + *.name() + *.toLowerCase() + } + + static public getFileObject(path) { return path ? Nextflow.file(path) : [] } diff --git a/lib/WorkflowLilac.groovy b/lib/WorkflowLilac.groovy index 54d3d516..310c4985 100755 --- a/lib/WorkflowLilac.groovy +++ b/lib/WorkflowLilac.groovy @@ -1,6 +1,9 @@ // // This file holds several functions specific to the subworkflows/lilac.nf in the nf-core/oncoanalyser pipeline // +import Constants +import Utils + class WorkflowLilac { @@ -8,16 +11,23 @@ class WorkflowLilac { // channel: [val(meta_lilac), bam, bai] def d = ch .flatMap { meta, tbam, nbam, tbai, nbai -> - def sample_types = ['tumor': [tbam, tbai], 'normal': [nbam, nbai]] + def sample_types = [Constants.DataType.TUMOR, Constants.DataType.NORMAL] sample_types - .keySet() .collect { sample_type -> - def fps = sample_types[sample_type] + def fps + if (sample_type == Constants.DataType.TUMOR) { + fps = [tbam, tbai] + } else if (sample_type == Constants.DataType.NORMAL) { + fps = [nbam, nbai] + } else { + assert false : "got bad sample type" + } def sample_name = meta.get(['sample_name', sample_type]) def meta_lilac = [ key: meta.id, id: sample_name, - sample_type: sample_type, + // NOTE(SW): must use string representation for caching purposes + sample_type_str: sample_type.name(), ] return [meta_lilac, *fps] } @@ -32,22 +42,22 @@ class WorkflowLilac { .map { [it[1..-1], it[0]] } .groupTuple() .map { filepaths, meta_lilac -> - def (keys, sample_names, sample_types) = meta_lilac + def (keys, sample_names, sample_type_strs) = meta_lilac .collect { - [it.key, it.id, it.sample_type] + [it.key, it.id, it.sample_type_str] } .transpose() - def sample_types_unique = sample_types.unique(false) - assert sample_types_unique.size() == 1 - def sample_type = sample_types_unique[0] + def sample_type_strs_unique = sample_type_strs.unique(false) + assert sample_type_strs_unique.size() == 1 + def sample_type_str = sample_type_strs_unique[0] def key = keys.join('__') def meta_lilac_new = [ keys: keys, id: sample_names.join('__'), id_simple: keys.join('__'), - sample_type: sample_type, + sample_type_str: sample_type_str, ] return [meta_lilac_new, *filepaths] } @@ -62,22 +72,23 @@ class WorkflowLilac { def meta_lilac = data[0] def fps = data[1..-1] meta_lilac.keys.collect { key -> - return [key, [meta_lilac.sample_type, *fps]] + return [key, [meta_lilac.sample_type_str, *fps]] } } .groupTuple(size: 2) .map { key, other -> def data = [:] - other.each { sample_type, bam, bai -> + other.each { sample_type_str, bam, bai -> + def sample_type = Utils.getEnumFromString(sample_type_str, Constants.DataType) data[[sample_type, 'bam']] = bam data[[sample_type, 'bai']] = bai } [ [key: key], - data.get(['tumor', 'bam']), - data.get(['normal', 'bam']), - data.get(['tumor', 'bai']), - data.get(['normal', 'bai']), + data.get([Constants.DataType.TUMOR, 'bam']), + data.get([Constants.DataType.NORMAL, 'bam']), + data.get([Constants.DataType.TUMOR, 'bai']), + data.get([Constants.DataType.NORMAL, 'bai']), ] } return d diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index a5ecbd01..a110cb04 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -70,98 +70,6 @@ class WorkflowOncoanalyser { } } - public static prepareInputs(ch, stub_run, log) { - return ch - .splitCsv(header: true, strip: true, sep: '\t') - .map { [it.id, it] } - .groupTuple() - .map { id, inputs -> - def meta = [ - 'id': id, - ] - inputs.each { - assert meta.id == it.id - // Add subject name if not already present - if (meta.containsKey('subject_name')) { - assert meta.subject_name == it.subject_name - } else { - meta.subject_name = it.subject_name - } - - // Set sample name - def key = [] - if (it.sample_type == 'tumor') { - key = ['sample_name', 'tumor'] - } else if (it.sample_type == 'normal') { - key = ['sample_name', 'normal'] - } else { - assert false - } - if (meta.containsKey(key)) { - assert meta[key] == it.sample_name - } else { - meta[key] = it.sample_name - } - - // Add file - def key_file = [it.filetype, it.sample_type] - assert ! meta.containsKey(key_file) - meta[key_file] = it.filepath - - if (! stub_run) { - // For BAM file inputs, require co-located index - if (it.filepath.endsWith('.bam')) { - def bam_index_fp_str = "${it.filepath}.bai".toString() - def bam_index_fp = Nextflow.file(bam_index_fp_str) - if (! bam_index_fp.exists()) { - log.error "\nERROR: No index found for ${it.filepath}" - System.exit(1) - } - } - - // For GRIPSS SV VCFs, require co-located index - if (it.filetype.startsWith('gripss')) { - def vcf_index_fp = Nextflow.file("${it.filepath}.tbi".toString()) - if (! vcf_index_fp.exists()) { - log.error "\nERROR: No index found for ${it.filepath}" - System.exit(1) - } - } - } - - // NOTE(SW): CHECK_SAMPLESHEET curently enforces T/N; this may be relevant in the future - //// Set sample type: tumor_normal, tumor_only, normal_only - //if (meta.containsKey(['sample_name', 'tumor']) && meta.containsKey(['sample_name', 'normal'])) { - // meta.sample_type = 'tumor_normal' - //} else if (meta.containsKey(['sample_name', 'tumor'])) { - // meta.sample_type = 'tumor_only' - //} else if (meta.containsKey(['sample_name', 'normal'])) { - // meta.sample_type = 'normal_only' - //} else { - // assert false - //} - } - - // For PURPLE only runs, we must get normal sample name from inputs since there is no way to provide this - // in the samplesheet - if (meta.containsKey(['cobalt_dir', 'tumor']) && ! meta.containsKey(['sample_name', 'normal'])) { - // Discover files - def normal_ratio_fps = [] - new File(meta[['cobalt_dir', 'tumor']]) - .eachFileMatch(groovy.io.FileType.FILES, ~/.+\.cobalt\.gc\.median\.tsv/, { normal_ratio_fps << it }) - // Select normal sample file - def normal_ratio_fp = normal_ratio_fps - .findAll { ! it.getName().contains(meta[['sample_name', 'tumor']]) } - assert normal_ratio_fp.size() == 1 - // Set normal sample name - def m = (normal_ratio_fp =~ /.+\/(.+)\.cobalt\.gc\.median\.tsv/) - meta[['sample_name', 'normal']] = m[0][1] - } - - return meta - } - } - public static groupByMeta(Map named_args, ... channels) { def r = channels // Set position; required to use non-blocking .mix operator @@ -210,25 +118,6 @@ class WorkflowOncoanalyser { public static restoreMeta(ch_output, ch_metas) { // NOTE(SW): ch_output must contain a Map in the first position with a key named 'key' that // contains the corresponding meta.id value, for example: [val(meta_process), *process_outputs] - - //return Channel.empty() - // .mix( - // // channel: [val(key), val(meta)] - // ch_metas.map { meta -> [meta.id, meta] }, - // // channel: [val(key), list(process_outputs)] - // // NOTE(SW): process meta is discarded - // ch_output.map { [it[0].key, it[1..-1]] }, - // ) - // .groupTuple(size: 2) - // // channel: [meta, *process_outputs] - // .map { it.flatten()[1..-1] } - - //def ch_left = ch_metas.map { meta -> [meta.id, meta] } - //def ch_right = ch_output.map { [it[0].key, it[1..-1]] } - //return ch_left - // .join(ch_right, failOnDuplicate: true) - // .map { it[1..-1] } - def ch_source = ch_metas.map { meta -> [meta.id, meta] } def ch_target = ch_output.map { [it[0].key, it[1..-1]] } return ch_source diff --git a/nextflow_schema.json b/nextflow_schema.json index 937af534..ebeaadbd 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -15,11 +15,11 @@ "input": { "type": "string", "format": "file-path", - "mimetype": "text/tsv", - "pattern": "^\\S+\\.tsv$", + "mimetype": "text/csv", + "pattern": "^\\S+\\.csv$", "schema": "assets/schema_input.json", - "description": "Path to tab-separated file containing information about the samples in the experiment.", - "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a tab-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/oncoanalyser/usage#samplesheet-input).", + "description": "Path to csv-separated file containing information about the samples in the experiment.", + "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a csv-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/oncoanalyser/usage#samplesheet-input).", "fa_icon": "fas fa-file-tsv" }, "outdir": { diff --git a/subworkflows/local/gridss.nf b/subworkflows/local/gridss.nf index a347fba3..2c0c88ad 100644 --- a/subworkflows/local/gridss.nf +++ b/subworkflows/local/gridss.nf @@ -1,6 +1,8 @@ // // GRIDSS is a software suite containing tools useful for the detection of genomic rearrangements. // +import Constants +import Utils include { ASSEMBLE } from '../../modules/local/gridss/assemble/main' include { CALL } from '../../modules/local/gridss/call/main' @@ -26,16 +28,24 @@ workflow GRIDSS { // channel: [val(meta_gridss), bam] ch_preprocess_inputs = ch_inputs .flatMap { meta, tbam, nbam -> - def bam_map = ['tumor': tbam, 'normal': nbam] - bam_map - .keySet() + def sample_types = [Constants.DataType.TUMOR, Constants.DataType.NORMAL] + sample_types .collect { sample_type -> + def bam_fp + if (sample_type == Constants.DataType.TUMOR) { + bam_fp = tbam + } else if (sample_type == Constants.DataType.NORMAL) { + bam_fp = nbam + } else { + assert false : "got bad sample type" + } def meta_gridss = [ id: meta.get(['sample_name', sample_type]), - sample_type: sample_type, + // NOTE(SW): must use string representation for caching purposes + sample_type_str: sample_type.name(), subject_id: meta.id, ] - return [meta_gridss, bam_map[sample_type]] + return [meta_gridss, bam_fp] } } @@ -65,8 +75,8 @@ workflow GRIDSS { // channel: [val(meta_gridss), [bams], [preprocess_dirs], [labels]] ch_assemble_inputs = ch_bams_and_preprocess .map { subject_id, entries -> - def (tmeta, tbam, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } - def (nmeta, nbam, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } + def (tmeta, tbam, tpreprocess) = get_sample_type_entry(entries, Constants.DataType.TUMOR) + def (nmeta, nbam, npreprocess) = get_sample_type_entry(entries, Constants.DataType.NORMAL) def meta_gridss = [id: tmeta.subject_id] return [meta_gridss, [nbam, tbam], [npreprocess, tpreprocess], [nmeta.id, tmeta.id]] } @@ -127,3 +137,10 @@ workflow GRIDSS { versions = ch_versions // channel: [versions.yml] } + +def get_sample_type_entry(entries, sample_type) { + entries.find { e -> + def meta = e[0] + return Utils.getEnumFromString(meta.sample_type_str, Constants.DataType) == sample_type + } +} diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep.nf index 42d02ab3..cfa426fb 100644 --- a/subworkflows/local/gridss_svprep.nf +++ b/subworkflows/local/gridss_svprep.nf @@ -2,6 +2,7 @@ // SV Prep is a BAM filter designed to select only reads relevant to SV events run prior to GRIDSS. // GRIDSS is a software suite containing tools useful for the detection of genomic rearrangements. // +import Constants include { ASSEMBLE as GRIDSS_ASSEMBLE } from '../../modules/local/svprep/assemble/main' include { CALL as GRIDSS_CALL } from '../../modules/local/svprep/call/main' @@ -35,10 +36,10 @@ workflow GRIDSS_SVPREP { .map { meta -> def meta_svprep = [ key: meta.id, - id: meta.get(['sample_name', 'tumor']), + id: meta.get(['sample_name', Constants.DataType.TUMOR]), sample_type: 'tumor', ] - def bam_tumor = meta.get(['bam_wgs', 'tumor']) + def bam_tumor = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) return [meta_svprep, bam_tumor, "${bam_tumor}.bai", []] } @@ -60,10 +61,10 @@ workflow GRIDSS_SVPREP { .map { meta, junctions_tumor -> def meta_svprep = [ key: meta.id, - id: meta.get(['sample_name', 'normal']), + id: meta.get(['sample_name', Constants.DataType.NORMAL]), sample_type: 'normal', ] - def bam_normal = meta.get(['bam_wgs', 'normal']) + def bam_normal = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) return [meta_svprep, bam_normal, "${bam_normal}.bai", junctions_tumor] } @@ -116,9 +117,6 @@ workflow GRIDSS_SVPREP { ) ch_versions = ch_versions.mix(GRIDSS_PREPROCESS.out.versions) - - - // Gather BAMs and outputs from preprocessing for each tumor/normal set // channel: [key, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( @@ -128,9 +126,6 @@ workflow GRIDSS_SVPREP { .map { [it[0].key, it] } .groupTuple(size: 2) - - - // Order and organise inputs for assembly // channel: [val(meta_gridss), [bams], [bams_filtered], [preprocess_dirs], [labels]] ch_assemble_inputs = ch_bams_and_preprocess @@ -190,20 +185,21 @@ workflow GRIDSS_SVPREP { ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) // Prepare inputs for depth annotation, restore original meta - // channel: [val(meta), [bams], [bais], vcf, [labels]] + // channel: [val(meta_svprep), [bams], [bais], vcf, [labels]] ch_depth_inputs = WorkflowOncoanalyser.groupByMeta( ch_inputs.map { meta -> [meta.id, meta] }, GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .map { id, meta, vcf -> - def tbam = meta.get(['bam_wgs', 'tumor']) - def nbam = meta.get(['bam_wgs', 'normal']) + def tbam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) + def nbam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) + def meta_svprep = [id: meta.id] return [ - meta, + meta_svprep, [nbam, tbam], ["${nbam}.bai", "${tbam}.bai"], vcf, - [meta.get(['sample_name', 'normal']), meta.get(['sample_name', 'tumor'])], + [meta.get(['sample_name', Constants.DataType.NORMAL]), meta.get(['sample_name', Constants.DataType.TUMOR])], ] } @@ -214,8 +210,17 @@ workflow GRIDSS_SVPREP { ref_data_genome_version, ) + // Reunite final VCF with the corresponding input meta object + ch_out = Channel.empty() + .concat( + ch_inputs.map { meta -> [meta.id, meta] }, + SVPREP_DEPTH_ANNOTATOR.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + ) + .groupTuple(size: 2) + .map { id, other -> other.flatten() } + emit: - results = SVPREP_DEPTH_ANNOTATOR.out.vcf // channel: [val(meta), vcf] + results = ch_out // channel: [val(meta), vcf] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/input_check.nf b/subworkflows/local/input_check.nf deleted file mode 100644 index db1795cc..00000000 --- a/subworkflows/local/input_check.nf +++ /dev/null @@ -1,44 +0,0 @@ -// -// Check input samplesheet and get read channels -// - -include { SAMPLESHEET_CHECK } from '../../modules/local/samplesheet_check' - -workflow INPUT_CHECK { - take: - samplesheet // file: /path/to/samplesheet.csv - - main: - SAMPLESHEET_CHECK ( samplesheet ) - .csv - .splitCsv ( header:true, sep:',' ) - .map { create_fastq_channel(it) } - .set { reads } - - emit: - reads // channel: [ val(meta), [ reads ] ] - versions = SAMPLESHEET_CHECK.out.versions // channel: [ versions.yml ] -} - -// Function to get list of [ meta, [ fastq_1, fastq_2 ] ] -def create_fastq_channel(LinkedHashMap row) { - // create meta map - def meta = [:] - meta.id = row.sample - meta.single_end = 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) ] ] - } - return fastq_meta -} diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf new file mode 100644 index 00000000..a5e532a1 --- /dev/null +++ b/subworkflows/local/prepare_input.nf @@ -0,0 +1,104 @@ +import Constants +import Utils + + +workflow PREPARE_INPUT { + take: + ch_samplesheet + + main: + ch_inputs = Channel.of(ch_samplesheet) + .splitCsv(header: true) + .map { [it.id, it] } + .groupTuple() + .map { key, entries -> + def meta = [id: key] + def input_types_seen = [] + + // Process each entry + entries.each { + // Add subject name if absent or check if current matches existing + if (meta.containsKey('subject_name') && meta.subject_name != it.subject_name) { + log.error "\nERROR: got unexpected subject name for ${key}/${meta.subject_name}: ${it.subject_name}" + System.exit(1) + } else { + meta.subject_name = it.subject_name + } + + // Sample type + def sample_type_enum = Utils.getEnumFromString(it.sample_type, Constants.DataType) + if (!sample_type_enum) { + def sample_type_str = Utils.getEnumNames(Constants.DataType).join('\n - ') + log.error "\nERROR: recieved invalid sample type: '${it.sample_type}'. Valid options are:\n - ${sample_type_str}" + System.exit(1) + } + + // Filetype + def filetype_enum = Utils.getEnumFromString(it.filetype, Constants.FileType) + if (!filetype_enum) { + def filetype_str = Utils.getEnumNames(Constants.FileType).join('\n - ') + log.error "\nERROR: recieved invalid file type: '${it.filetype}'. Valid options are:\n - ${filetype_str}" + System.exit(1) + } + + // Check whether this input type already exists + if (input_types_seen.contains([sample_type_enum, filetype_enum])) { + log.error "\nERROR: got duplicate inputs for ${key}: ${sample_type_enum}/${filetype_enum}" + System.exit(1) + } + input_types_seen.push([sample_type_enum, filetype_enum]) + + // Check for relevant indices + if (!workflow.stubRun) { + def filetype_bai = [ + Constants.FileType.BAM_WGS, + Constants.FileType.BAM_WTS, + ] + + def filetype_tbi = [ + Constants.FileType.GRIDSS_VCF, + Constants.FileType.GRIPSS_HARD_VCF, + Constants.FileType.GRIPSS_SOFT_VCF, + ] + + def index_ext + if (filetype_bai.contains(filetype)) { + index_ext = 'bai' + } else if (filetype_tbi.contains(filetype)) { + index_ext = 'tbi' + } else { + return + } + + def index_fp_str = "${it.filepath}.${index_ext}".toString() + def index_fp = file(index_fp_str) + if (! index_fp.exists()) { + log.error "\nERROR: No index found for ${it.filepath}" + System.exit(1) + } + } + + // Sample name + def key_sample_name = ['sample_name', sample_type_enum] + if (meta.containsKey(key_sample_name) && meta[key_sample_name] != it.sample_name) { + log.error "\nERROR: got unexpected sample name for ${key}/${meta[key_sample_name]}: ${it.sample_name}" + System.exit(1) + } else { + meta[key_sample_name] = it.sample_name + } + + // Filepath + def key_file = [filetype_enum, sample_type_enum] + if (meta.containsKey(key_file)) { + log.error "\nERROR: got duplicate file for ${key}: ${filetype_enum}/${sample_type_enum}" + System.exit(1) + } else { + meta[key_file] = it.filepath + } + } + return meta + } + + emit: + data = ch_inputs +} diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index d3fa57fb..ab62535e 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -78,6 +78,7 @@ include { GRIPSS } from '../subworkflows/local/gripss' include { LILAC } from '../subworkflows/local/lilac' include { LINX } from '../subworkflows/local/linx' include { PAVE } from '../subworkflows/local/pave' +include { PREPARE_INPUT } from '../subworkflows/local/prepare_input' include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' include { SAGE } from '../subworkflows/local/sage' @@ -108,13 +109,11 @@ workflow ONCOANALYSER { // channel: [versions.yml] ch_versions = Channel.empty() - // Check samplesheet and prepare input channel - CHECK_SAMPLESHEET( + // Get inputs from samplesheet + PREPARE_INPUT( samplesheet, - params.mode, ) - // channel: [val(meta)] - ch_inputs = WorkflowOncoanalyser.prepareInputs(CHECK_SAMPLESHEET.out, workflow.stubRun, log) + ch_inputs = PREPARE_INPUT.out.data // Set up reference data and unpack HMF data map for convenience PREPARE_REFERENCE(run) @@ -122,12 +121,11 @@ workflow ONCOANALYSER { // Set up channel with common inputs for several processes if (run.amber || run.cobalt || run.pave || run.lilac || run.teal) { - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] ch_bams_and_indices = ch_inputs .map { meta -> - def tumor_bam = meta.get(['bam_wgs', 'tumor']) - def normal_bam = meta.get(['bam_wgs', 'normal']) + def tumor_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) + def normal_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] } } @@ -136,7 +134,7 @@ workflow ONCOANALYSER { // channel (absent): [val(meta)] ch_inputs_wts = ch_inputs .branch { meta -> - def key = ['bam_wts', 'tumor'] + def key = [Constants.FileType.BAM_WTS, Constants.DataType.TUMOR] present: meta.containsKey(key) return meta absent: ! meta.containsKey(key) @@ -153,7 +151,7 @@ workflow ONCOANALYSER { // channel: [meta_isofox, tumor_bam_wts] ch_isofox_inputs = ch_inputs_wts.present .map { meta -> - return [[key: meta.id, id: meta.id], meta.get(['bam_wts', 'tumor'])] + return [[key: meta.id, id: meta.id], meta.get([Constants.FileType.BAM_WTS, Constants.DataType.TUMOR])] } // Run process @@ -183,15 +181,16 @@ workflow ONCOANALYSER { // channel: [val(meta_cwm), bam] ch_cwm_inputs_all = ch_inputs .flatMap { meta -> - def sample_types = run.teal ? ['tumor', 'normal'] : ['tumor'] + def sample_types = run.teal ? [Constants.DataType.TUMOR, Constants.DataType.NORMAL] : [Constants.DataType.TUMOR] return sample_types .collect { sample_type -> - def bam = meta.get(['bam_wgs', sample_type]) + def bam = meta.get([Constants.FileType.BAM_WGS, sample_type]) def sample_name = meta.get(['sample_name', sample_type]) def meta_cwm = [ key: meta.id, id: sample_name, - sample_type: sample_type, + // NOTE(SW): must use string representation for caching purposes + sample_type: sample_type.name(), ] return [meta_cwm, bam] } @@ -246,10 +245,11 @@ workflow ONCOANALYSER { // channel (tumor): [val(meta), metrics] // channel (normal): [val(meta), metrics] ch_cwm_output = WorkflowOncoanalyser.restoreMeta(ch_cwm_output_individual, ch_inputs) - .branch { meta, sample_type, metrics -> - tumor: sample_type == 'tumor' + .branch { meta, sample_type_str, metrics -> + def sample_type = Utils.getEnumFromString(sample_type_str, Constants.DataType) + tumor: sample_type == Constants.DataType.TUMOR return [meta, metrics] - normal: sample_type == 'normal' + normal: sample_type == Constants.DataType.NORMAL return [meta, metrics] } } @@ -269,8 +269,8 @@ workflow ONCOANALYSER { def meta_amber = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', 'tumor']), - normal_id: meta.get(['sample_name', 'normal']), + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), ] return [meta_amber, *fps] } @@ -302,8 +302,8 @@ workflow ONCOANALYSER { def meta_cobalt = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', 'tumor']), - normal_id: meta.get(['sample_name', 'normal']), + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), ] return [meta_cobalt, *fps] } @@ -345,8 +345,8 @@ workflow ONCOANALYSER { } else { ch_gridss_inputs = ch_inputs .map { meta -> - def tumor_bam = meta.get(['bam_wgs', 'tumor']) - def normal_bam = meta.get(['bam_wgs', 'normal']) + def tumor_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) + def normal_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) [meta, tumor_bam, normal_bam] } GRIDSS( @@ -378,7 +378,7 @@ workflow ONCOANALYSER { if (run.gridss) { ch_gripss_inputs_source = ch_gridss_out } else { - ch_gripss_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, ['gridss_vcf', 'tumor_normal']) + ch_gripss_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.GRIDSS_VCF, Constants.DataType.TUMOR_NORMAL]) } // Create inputs and create process-specific meta @@ -388,8 +388,8 @@ workflow ONCOANALYSER { def meta_gripss = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', 'tumor']), - normal_id: meta.get(['sample_name', 'normal']), + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), ] return [meta_gripss, gridss_vcf] } @@ -426,8 +426,8 @@ workflow ONCOANALYSER { def meta_sage = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', 'tumor']), - normal_id: meta.get(['sample_name', 'normal']), + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), ] return [meta_sage, tbam, nbam, tbai, nbai] } @@ -469,8 +469,8 @@ workflow ONCOANALYSER { ch_pave_germline_inputs_source = ch_sage_germline_out ch_pave_somatic_inputs_source = ch_sage_somatic_out } else { - ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, ['sage_vcf', 'normal']) - ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, ['sage_vcf', 'tumor']) + ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_VCF, Constants.DataType.NORMAL]) + ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_VCF, Constants.DataType.TUMOR]) } // Create inputs and create process-specific meta @@ -479,7 +479,7 @@ workflow ONCOANALYSER { .map { meta, sage_vcf -> def pave_meta = [ key: meta.id, - id: meta.get(['sample_name', 'tumor']), + id: meta.get(['sample_name', Constants.DataType.TUMOR]), ] return [pave_meta, sage_vcf] } @@ -487,7 +487,7 @@ workflow ONCOANALYSER { .map { meta, sage_vcf -> def pave_meta = [ key: meta.id, - id: meta.get(['sample_name', 'tumor']), + id: meta.get(['sample_name', Constants.DataType.TUMOR]), ] return [pave_meta, sage_vcf] } @@ -527,8 +527,8 @@ workflow ONCOANALYSER { } else { ch_purple_inputs_sv = ch_inputs .map { meta -> - def sv_hard_vcf = meta[['vcf_sv_gripss_hard', 'tumor']] - def sv_soft_vcf = meta[['vcf_sv_gripss_soft', 'tumor']] + def sv_hard_vcf = meta[[Constants.FileType.GRIPSS_HARD_VCF, Constants.DataType.TUMOR]] + def sv_soft_vcf = meta[[Constants.FileType.GRIPSS_SOFT_VCF, Constants.DataType.TUMOR]] return [ meta, sv_hard_vcf, @@ -541,11 +541,11 @@ workflow ONCOANALYSER { // channel: [val(meta), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] ch_purple_inputs_sources = WorkflowOncoanalyser.groupByMeta( - run.amber ? ch_amber_out : WorkflowOncoanalyser.getInput(ch_inputs, ['amber_dir', 'tumor_normal']), - run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, ['cobalt_dir', 'tumor_normal']), + run.amber ? ch_amber_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.AMBER_DIR, Constants.DataType.TUMOR_NORMAL]), + run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COBALT_DIR, Constants.DataType.TUMOR_NORMAL]), ch_purple_inputs_sv, - run.pave ? ch_pave_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, ['vcf_smlv', 'tumor']), - run.pave ? ch_pave_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, ['vcf_smlv', 'normal']), + run.pave ? ch_pave_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PAVE_VCF, Constants.DataType.TUMOR]), + run.pave ? ch_pave_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PAVE_VCF, Constants.DataType.NORMAL]), ) // channel: [val(meta_purple), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] @@ -556,8 +556,8 @@ workflow ONCOANALYSER { def meta_purple = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', 'tumor']), - normal_id: meta.get(['sample_name', 'normal']), + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), ] return [meta_purple, *other] } @@ -590,16 +590,16 @@ workflow ONCOANALYSER { if (run.purple) { ch_sigs_inputs_source = ch_purple_out } else { - ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, ['purple_dir', 'tumor_normal']) + ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) } // Create inputs and create process-specific meta // channel: [val(meta_sigs), smlv_vcf] ch_sigs_inputs = ch_sigs_inputs_source .map { meta, purple_dir -> - def smlv_vcf = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.somatic.vcf.gz") + def smlv_vcf = file(purple_dir).resolve("${meta.get(['sample_name', Constants.DataType.TUMOR])}.purple.somatic.vcf.gz") def meta_sigs = [id: meta.id] - return [meta, smlv_vcf] + return [meta_sigs, smlv_vcf] } SIGS( @@ -620,14 +620,14 @@ workflow ONCOANALYSER { if (run.purple) { ch_chord_inputs_source = ch_purple_out } else { - ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, ['purple_dir', 'tumor_normal']) + ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) } // Create inputs and create process-specific meta // channel: [val(meta), smlv_vcf, sv_vcf] ch_chord_inputs = ch_chord_inputs_source .map { meta, purple_dir -> - def tumor_id = meta.get(['sample_name', 'tumor']) + def tumor_id = meta.get(['sample_name', Constants.DataType.TUMOR]) def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") def meta_chord = [id: meta.id] @@ -653,10 +653,10 @@ workflow ONCOANALYSER { // NOTE(SW): assuming here that TEAL is being run in tumor/normal mode and so we expect a tumor metrics file and normal metrics file ch_teal_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_bams_and_indices, - run.collectwgsmetrics ? ch_cwm_output.tumor : WorkflowOncoanalyser.getInput(ch_inputs, ['collectmetrics', 'tumor']), - run.collectwgsmetrics ? ch_cwm_output.normal : WorkflowOncoanalyser.getInput(ch_inputs, ['collectmetrics', 'normal']), - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, ['purple_dir', 'tumor_normal']), - run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, ['cobalt_dir', 'tumor_normal']), + run.collectwgsmetrics ? ch_cwm_output.tumor : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COLLECTWGSMETRICS, Constants.DataType.TUMOR]), + run.collectwgsmetrics ? ch_cwm_output.normal : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COLLECTWGSMETRICS, Constants.DataType.NORMAL]), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), + run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COBALT_DIR, Constants.DataType.TUMOR_NORMAL]), ) // Create inputs and create process-specific meta @@ -667,8 +667,8 @@ workflow ONCOANALYSER { def other = it[1..-1] def meta_teal = [ id: meta.id, - tumor_id: meta.get(['sample_name', 'tumor']), - normal_id: meta.get(['sample_name', 'normal']), + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), ] return [meta_teal, *other] } @@ -691,13 +691,13 @@ workflow ONCOANALYSER { if (run.purple) { ch_lilac_inputs_source = ch_purple_out } else { - ch_lilac_inputs_source = WorkflowOncoanalyser.getInput(['purple_dir', 'tumor_normal']) + ch_lilac_inputs_source = WorkflowOncoanalyser.getInput([Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) } - // Run process + // Call subworkflow to run processes LILAC( ch_bams_and_indices, - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(['purple_dir', 'tumor_normal']), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput([Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, hmf_data.lilac_resource_dir, @@ -721,7 +721,7 @@ workflow ONCOANALYSER { key: meta.id, id: meta.id, ] - return [meta_virus, meta.get(['bam_wgs', 'tumor'])] + return [meta_virus, meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR])] } // Run process @@ -744,8 +744,8 @@ workflow ONCOANALYSER { // channel: [val(meta), purple_purity, purple_qc] ch_virusinterpreter_inputs_purple = ch_purple_out .map { meta, purple_dir -> - def purple_purity = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.purity.tsv") - def purple_qc = file(purple_dir).resolve("${meta.get(['sample_name', 'tumor'])}.purple.qc") + def purple_purity = file(purple_dir).resolve("${meta.get(['sample_name', Constants.DataType.TUMOR])}.purple.purity.tsv") + def purple_qc = file(purple_dir).resolve("${meta.get(['sample_name', Constants.DataType.TUMOR])}.purple.qc") return [meta, purple_purity, purple_qc] } @@ -791,10 +791,10 @@ workflow ONCOANALYSER { if (run.gripss) { ch_linx_inputs_germline_source = ch_gripss_germline_out.map { meta, h, hi, s, si -> [meta, h] } } else { - ch_linx_inputs_germline_source = WorkflowOncoanalyser.getInput(ch_inputs, ['vcf_sv_gripss_hard', 'normal']) + ch_linx_inputs_germline_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.GRIPSS_HARD_VCF, Constants.DataType.NORMAL]) } // channel: [val(meta), sv_vcf, purple_dir] - ch_linx_inputs_somatic_source = run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, ['purple_dir', 'tumor_normal']) + ch_linx_inputs_somatic_source = run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) // Create inputs and create process-specific meta // channel: [val(meta_linx), sv_vcf] @@ -837,9 +837,17 @@ workflow ONCOANALYSER { // // MODULE: Run gpgr to generate a LINX report // + // Create inputs and create process-specific meta + // channel: [meta(meta_linx_report), anno_dir, vis_dir] + ch_linx_report_inputs = ch_linx_somatic_out + .map { meta, anno_dir, vis_dir -> + def meta_linx_report = [id: meta.id] + return [meta_linx_report, anno_dir, vis_dir] + } + // Run process LINX_REPORT( - ch_linx_somatic_out, + ch_linx_report_inputs, ) // Set outputs @@ -860,7 +868,7 @@ workflow ONCOANALYSER { ) } else { ch_cuppa_inputs_isofox = ch_inputs - .map { meta -> [meta, meta.get(['isofox_dir', 'tumor'], [])] } + .map { meta -> [meta, meta.get([Constants.FileType.ISOFOX_DIR, Constants.DataType.TUMOR], [])] } } // channel: [val(meta), linx_somatic_annotation_dir] @@ -872,9 +880,9 @@ workflow ONCOANALYSER { // done manually below to preserve ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, ['purple_dir', 'tumor_normal']), - run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, ['linx_dir', 'tumor']), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, ['virusinterpreter', 'tumor']), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), + run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_DIR, Constants.DataType.TUMOR_NORMAL]), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.VIRUSINTERPRETER, Constants.DataType.TUMOR]), flatten: false, ) .map { data -> @@ -890,7 +898,7 @@ workflow ONCOANALYSER { def meta = it[0] def meta_cuppa = [ key: meta.id, - id: meta.get(['sample_name', 'tumor']), + id: meta.get(['sample_name', Constants.DataType.TUMOR]), ] return [meta_cuppa, *it[1..-1]] } From 4ab36df7be7f08f39c336eae76e74f91006494c5 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 8 Dec 2022 15:45:13 +1100 Subject: [PATCH 012/562] Decouple VIRUSBreakend db from HMF data bundle --- lib/Constants.groovy | 2 ++ lib/WorkflowOncoanalyser.groovy | 4 +++ modules/local/custom/extract_tarball/main.nf | 18 +++++++++++++ nextflow_schema.json | 12 ++++----- subworkflows/local/prepare_reference.nf | 28 ++++++++++++++++---- workflows/oncoanalyser.nf | 2 +- 6 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 modules/local/custom/extract_tarball/main.nf diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 60cd6aad..2d2156d3 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -8,6 +8,8 @@ class Constants { static String hmf_reference_data_37_bundle_path = 'PLACEHOLDER_hmf_reference_data_37_bundle_path' static String hmf_reference_data_38_bundle_path = 'PLACEHOLDER_hmf_reference_data_38_bundle_path' + static String virusbreakenddb_path = 's3://virusbreakend/virusbreakenddb_20210401.tar.gz' + static enum PipelineMode { FULL, MANUAL, diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index a110cb04..d51b7efa 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -51,6 +51,10 @@ class WorkflowOncoanalyser { } } + if (!params.containsKey('ref_data_virusbreakenddb_path')) { + params.ref_data_virusbreakenddb_path = Constants.virusbreakenddb_path + } + if (!params.ref_data_genome_fasta) { log.error "Genome fasta file not specified with e.g. '--ref_data_genome_fasta genome.fa' or via a detectable config file." System.exit(1) diff --git a/modules/local/custom/extract_tarball/main.nf b/modules/local/custom/extract_tarball/main.nf new file mode 100644 index 00000000..5c70b2a2 --- /dev/null +++ b/modules/local/custom/extract_tarball/main.nf @@ -0,0 +1,18 @@ +process EXTRACT_TARBALL { + tag "${meta.id}" + label 'process_single' + + container 'public.ecr.aws/ubuntu/ubuntu:20.04_stable' + + input: + tuple val(meta), path(tarball) + + output: + path "${meta.id}/", emit: dir + + script: + """ + mkdir -p ${meta.id}/ + tar -xzvf ${tarball} --strip-components 1 -C ${meta.id}/ + """ +} diff --git a/nextflow_schema.json b/nextflow_schema.json index ebeaadbd..85de0a43 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -149,6 +149,12 @@ "description": "Path HMF reference data bundle.", "fa_icon": "far fa-file-code" }, + "ref_data_virusbreakenddb_path": { + "type": "string", + "format": "directory-path", + "description": "Path to VIRUSBreakend database.", + "fa_icon": "far fa-file-code" + }, "ref_data_amber_loci": { "type": "string", "format": "file-path", @@ -244,12 +250,6 @@ "description": "Path to LILAC resource directory.", "fa_icon": "far fa-folder-open" }, - "ref_data_virusbreakenddb": { - "type": "string", - "format": "directory-path", - "description": "Path to VIRUSBreakend database directory.", - "fa_icon": "far fa-folder-open" - }, "ref_data_virusinterpreter_taxonomy": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index b73ce89f..a769ff90 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -6,9 +6,10 @@ include { SAMTOOLS_FAIDX } from '../../modules/nf-core/samtools/faidx/ma include { SAMTOOLS_DICT } from '../../modules/nf-core/samtools/dict/main' include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' -include { INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' -include { INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' -include { HMF_REFERENCE } from '../../modules/local/custom/hmf_reference/main' +include { EXTRACT_TARBALL as EXTRACT_TARBALL_VIRUSBREAKENDDB } from '../../modules/local/custom/extract_tarball/main' +include { INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' +include { INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' +include { HMF_REFERENCE } from '../../modules/local/custom/hmf_reference/main' workflow PREPARE_REFERENCE { take: @@ -80,6 +81,23 @@ workflow PREPARE_REFERENCE { } } + // + // Set VIRUSBreakend database paths / stage, unpack if required + // + ch_virusbreakenddb = Channel.empty() + if (run.virusinterpreter) { + if (params.ref_data_virusbreakenddb_path.endsWith('.tar.gz')) { + ch_virusbreakenddb_inputs = [ + [id: 'virusbreakenddb'], + file(params.ref_data_virusbreakenddb_path), + ] + EXTRACT_TARBALL_VIRUSBREAKENDDB(ch_virusbreakenddb_inputs) + ch_virusbreakenddb = EXTRACT_TARBALL_VIRUSBREAKENDDB.out.dir + } else { + ch_virusbreakenddb = file(params.ref_data_virusbreakenddb_path) + } + } + // // Set HMF reference paths / stage, unpack if required // @@ -108,6 +126,8 @@ workflow PREPARE_REFERENCE { genome_bwa_index_image = ch_genome_bwa_index_image // path: genome_bwa_index_image genome_gridss_index = ch_genome_gridss_index // path: genome_gridss_index genome_version = params.ref_data_genome_version // val: genome_version + + virusbreakenddb = ch_virusbreakenddb // path: VIRUSBreakend database hmf_data = ch_hmf_data // map: HMF data paths versions = ch_versions // channel: [versions.yml] @@ -147,8 +167,6 @@ def createHmfDataMap(hmf_bundle_dir, params_only) { 'sigs_signatures': getHmfDataFileObject('ref_data_sigs_signatures', 'SIGS_SIGNATURES', hmf_bundle_dir, params_only), // LILAC 'lilac_resource_dir': getHmfDataFileObject('ref_data_lilac_resource_dir', 'LILAC_RESOURCE_DIR', hmf_bundle_dir, params_only), - // VIRUSBreakend - 'virusbreakenddb': getHmfDataFileObject('ref_data_virusbreakenddb', 'VIRUSBREAKENDDB', hmf_bundle_dir, params_only), // Virus Interpreter 'virus_taxonomy': getHmfDataFileObject('ref_data_virus_taxonomy', 'VIRUSINTERPRETER_TAXONOMY', hmf_bundle_dir, params_only), 'virus_reporting': getHmfDataFileObject('ref_data_virus_reporting', 'VIRUSINTERPRETER_REPORTING', hmf_bundle_dir, params_only), diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index ab62535e..365dde17 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -734,7 +734,7 @@ workflow ONCOANALYSER { PREPARE_REFERENCE.out.genome_bwa_index, PREPARE_REFERENCE.out.genome_bwa_index_image, PREPARE_REFERENCE.out.genome_gridss_index, - hmf_data.virusbreakenddb, + PREPARE_REFERENCE.out.virusbreakenddb, ) // Set outputs From 0c34fbe260ba5cdc72966f0c0a0ebec7d1d56fcb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 8 Dec 2022 15:48:41 +1100 Subject: [PATCH 013/562] Update HMF bundle processing --- lib/Constants.groovy | 4 +- modules/local/custom/hmf_reference/main.nf | 88 ---------------------- nextflow_schema.json | 2 +- subworkflows/local/prepare_reference.nf | 14 ++-- 4 files changed, 12 insertions(+), 96 deletions(-) delete mode 100644 modules/local/custom/hmf_reference/main.nf diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 2d2156d3..97fdf50d 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -5,8 +5,8 @@ class Constants { static List genomes_version_38 = ['GRCh38', 'hg38'] static List genomes_version_38_noalt = ['GRCh38_hmf'] - static String hmf_reference_data_37_bundle_path = 'PLACEHOLDER_hmf_reference_data_37_bundle_path' - static String hmf_reference_data_38_bundle_path = 'PLACEHOLDER_hmf_reference_data_38_bundle_path' + static String hmf_reference_data_37_bundle_path = 's3://umccr-research-dev/stephen/hmftools_reference_data/2_repack/gcloud_vm_v5.23/hmf_data_bundle_5.23_37_0.0.1.tar.gz' + static String hmf_reference_data_38_bundle_path = 's3://umccr-research-dev/stephen/hmftools_reference_data/2_repack/gcloud_vm_v5.23/hmf_data_bundle_5.23_38_0.0.1.tar.gz' static String virusbreakenddb_path = 's3://virusbreakend/virusbreakenddb_20210401.tar.gz' diff --git a/modules/local/custom/hmf_reference/main.nf b/modules/local/custom/hmf_reference/main.nf deleted file mode 100644 index 8312985e..00000000 --- a/modules/local/custom/hmf_reference/main.nf +++ /dev/null @@ -1,88 +0,0 @@ -process HMF_REFERENCE { - label 'process_single' - - container 'public.ecr.aws/ubuntu/ubuntu:20.04_stable' - - input: - path hmf_bundle - - output: - path 'output' , emit: dir - path 'versions.yml', emit: versions - - script: - """ - # if tar.gz - # tar -xzvf ${hmf_bundle} --strip-components 1 -C output/ - # else - # ln -s ${hmf_bundle} output/ - - sleep 5 - - touch versions.yml - - mkdir -p output/amber/ - touch output/amber/GermlineHetPon.vcf.gz - - mkdir -p output/cobalt/ - touch output/cobalt/DiploidRegions.bed.gz - - mkdir -p output/cuppa/ - - mkdir -p output/svprep/ - touch output/svprep/sv_prep_blacklist.bed - - mkdir -p output/gridss/ - touch output/gridss/ENCFF356LFX.bed.gz - touch output/gridss/gridss_pon_single_breakend.bed.gz - touch output/gridss/gridss_pon_breakpoint.bedpe.gz - touch output/gridss/repeat_masker.fa.out.gz - - mkdir -p output/isofox/ - touch output/isofox/read_151_exp_counts.csv - touch output/isofox/read_100_exp_gc_ratios.csv - - mkdir -p output/linx/ - touch output/linx/fragile_sites_hmf.csv - touch output/linx/line_elements.csv - - mkdir -p output/sage/ - touch output/sage/KnownBlacklist.germline.bed - touch output/sage/KnownBlacklist.germline.bed - touch output/sage/KnownHotspots.somatic.vcf.gz - touch output/sage/ActionableCodingPanel.bed.gz - touch output/sage/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz - touch output/sage/KnownBlacklist.germline.vcf.gz - touch output/sage/KnownHotspots.somatic.vcf.gz - touch output/sage/SageGermlinePon.98x.tsv.gz - touch output/sage/clinvar.vcf.gz - - mkdir -p output/sigs/ - touch output/sigs/snv_cosmic_signatures.csv - - mkdir -p output/lilac/ - touch output/lilac/hla.38.alt.umccr.bed - touch output/lilac/hla.38_noalt.bed - - mkdir -p output/virusbreakend/ - - mkdir -p output/virusinterpreter/ - touch output/virusinterpreter/taxonomy_db.tsv - touch output/virusinterpreter/virus_reporting_db.tsv - - mkdir -p output/purple/ - touch output/purple/cohort_germline_del_freq.csv - - mkdir -p output/gene_panel/ - touch output/gene_panel/DriverGenePanel.tsv - - mkdir -p output/ensembl_data_cache/ - - mkdir -p output/known_fusions/ - touch output/known_fusions/known_fusion_data.csv - touch output/known_fusions/known_fusions.bedpe - - mkdir -p output/mappability/ - touch output/mappability/mappability_150.bed.gz - """ -} diff --git a/nextflow_schema.json b/nextflow_schema.json index 85de0a43..1147cc8b 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -146,7 +146,7 @@ "ref_data_hmf_bundle": { "type": "string", "format": "directory-path", - "description": "Path HMF reference data bundle.", + "description": "Path to HMF reference data bundle.", "fa_icon": "far fa-file-code" }, "ref_data_virusbreakenddb_path": { diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index a769ff90..a67e0fea 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -6,10 +6,10 @@ include { SAMTOOLS_FAIDX } from '../../modules/nf-core/samtools/faidx/ma include { SAMTOOLS_DICT } from '../../modules/nf-core/samtools/dict/main' include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' +include { EXTRACT_TARBALL as EXTRACT_TARBALL_HMF_BUNDLE } from '../../modules/local/custom/extract_tarball/main' include { EXTRACT_TARBALL as EXTRACT_TARBALL_VIRUSBREAKENDDB } from '../../modules/local/custom/extract_tarball/main' include { INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' include { INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' -include { HMF_REFERENCE } from '../../modules/local/custom/hmf_reference/main' workflow PREPARE_REFERENCE { take: @@ -101,18 +101,22 @@ workflow PREPARE_REFERENCE { // // Set HMF reference paths / stage, unpack if required // - if (params.ref_data_hmf_bundle) { - HMF_REFERENCE(params.ref_data_hmf_bundle) + // NOTE(SW): requiring all HMF reference data for now + if (params.ref_data_hmf_bundle.endsWith('.tar.gz')) { + // Decompress and set paths + EXTRACT_TARBALL_HMF_BUNDLE([[id: 'hmf_bundle'], file(params.ref_data_hmf_bundle)]) // Obtain paths and convert queue channel to value channel // NOTE(SW): any relevant HMF reference file parameter explicitly set in config will take priority - ch_hmf_data = HMF_REFERENCE.out.dir + ch_hmf_data = EXTRACT_TARBALL_HMF_BUNDLE.out.dir .collect() .map { dir_list -> assert dir_list.size() == 1 return createHmfDataMap(dir_list[0], false /* params_only */) } - ch_versions = ch_versions.mix(HMF_REFERENCE.out.versions) + } else if (params.ref_data_hmf_bundle) { + // If provided as path to directory, set paths + ch_hmf_data = createHmfDataMap(params.ref_data_hmf_bundle, false /* params_only */) } else { // If no HMF data bundle is supplied we construct from *only* params ch_hmf_data = createHmfDataMap(null, true /* params_only */) From 16822410ec1c11114df04a0506d6d28523ed0770 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 8 Dec 2022 15:50:37 +1100 Subject: [PATCH 014/562] Create file objects from input reference paths --- subworkflows/local/prepare_reference.nf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index a67e0fea..6de70ada 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -22,7 +22,7 @@ workflow PREPARE_REFERENCE { // // Set reference genome FASTA for consistency // - ch_genome_fasta = params.ref_data_genome_fasta + ch_genome_fasta = file(params.ref_data_genome_fasta) // // Create .fai and .dict for reference genome if required @@ -30,8 +30,8 @@ workflow PREPARE_REFERENCE { // The fai and dict files should always be present if using a genome preset. These are // always created where they are not present without checking processes to run given they // are used in numerous processes and have a neglibile cost to generate. - ch_genome_fai = params.ref_data_genome_fai - ch_genome_dict = params.ref_data_genome_dict + ch_genome_fai = file(params.ref_data_genome_fai) + ch_genome_dict = file(params.ref_data_genome_dict) if (!params.ref_data_genome_fai) { SAMTOOLS_FAIDX([:], ch_genome_fasta) ch_genome_fai = SAMTOOLS_FAIDX.out.fai @@ -46,9 +46,9 @@ workflow PREPARE_REFERENCE { // // Create BWA index, BWA index image, and GRIDSS index for reference genome if required // - ch_genome_bwa_index = params.ref_data_genome_bwa_index - ch_genome_bwa_index_image = params.ref_data_genome_bwa_index_image - ch_genome_gridss_index = params.ref_data_genome_gridss_index + ch_genome_bwa_index = file(params.ref_data_genome_bwa_index) + ch_genome_bwa_index_image = file(params.ref_data_genome_bwa_index_image) + ch_genome_gridss_index = file(params.ref_data_genome_gridss_index) if (run.gridss || run.virusbreakend) { if (!params.ref_data_genome_bwa_index) { BWA_INDEX([[:], ch_genome_fasta]) From 23b9e62720a0835bcc6b340c9e71283459981acc Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 8 Dec 2022 15:51:05 +1100 Subject: [PATCH 015/562] Correct custom/lilac_extract_and_index_contig tag --- modules/local/custom/lilac_extract_and_index_contig/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index 23492a67..39077940 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -1,5 +1,5 @@ process EXTRACT_AND_INDEX_CONTIG { - tag "${meta.id}" + tag "${contig_name}" label 'process_single' container 'docker.io/scwatts/custom-extract_and_index_contig:0.0.1--3' From c9ad1068558ee3bf240d23e492a8192d09ae1441 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 8 Dec 2022 15:51:51 +1100 Subject: [PATCH 016/562] Fix process check for GRIDSS index creation --- subworkflows/local/prepare_reference.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 6de70ada..fae052c0 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -49,7 +49,7 @@ workflow PREPARE_REFERENCE { ch_genome_bwa_index = file(params.ref_data_genome_bwa_index) ch_genome_bwa_index_image = file(params.ref_data_genome_bwa_index_image) ch_genome_gridss_index = file(params.ref_data_genome_gridss_index) - if (run.gridss || run.virusbreakend) { + if (run.gridss || run.virusinterpreter) { if (!params.ref_data_genome_bwa_index) { BWA_INDEX([[:], ch_genome_fasta]) ch_genome_bwa_index = BWA_INDEX.out.index.map { it[1] } From b60b34c17b5999f4da8f274af26947e89e48fb71 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 8 Dec 2022 15:57:38 +1100 Subject: [PATCH 017/562] Apply upper letter case to more constants --- lib/Constants.groovy | 12 ++++++------ lib/WorkflowOncoanalyser.groovy | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 97fdf50d..022124b2 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -1,14 +1,14 @@ class Constants { // NOTE(SW): the HMF reference data files are incompatible with hg19 due to different contig naming - static List genomes_version_37 = ['GRCh37_hmf', 'GRCh37'] - static List genomes_version_38 = ['GRCh38', 'hg38'] - static List genomes_version_38_noalt = ['GRCh38_hmf'] + static List GENOMES_VERSION_37 = ['GRCh37_hmf', 'GRCh37'] + static List GENOMES_VERSION_38 = ['GRCh38', 'hg38'] + static List GENOMES_VERSION_38_NOALT = ['GRCh38_hmf'] - static String hmf_reference_data_37_bundle_path = 's3://umccr-research-dev/stephen/hmftools_reference_data/2_repack/gcloud_vm_v5.23/hmf_data_bundle_5.23_37_0.0.1.tar.gz' - static String hmf_reference_data_38_bundle_path = 's3://umccr-research-dev/stephen/hmftools_reference_data/2_repack/gcloud_vm_v5.23/hmf_data_bundle_5.23_38_0.0.1.tar.gz' + static String HMF_REFERENCE_DATA_37_BUNDLE_PATH = 's3://umccr-research-dev/stephen/hmftools_reference_data/2_repack/gcloud_vm_v5.23/hmf_data_bundle_5.23_37_0.0.1.tar.gz' + static String HMF_REFERENCE_DATA_38_BUNDLE_PATH = 's3://umccr-research-dev/stephen/hmftools_reference_data/2_repack/gcloud_vm_v5.23/hmf_data_bundle_5.23_38_0.0.1.tar.gz' - static String virusbreakenddb_path = 's3://virusbreakend/virusbreakenddb_20210401.tar.gz' + static String VIRUSBREAKENDDB_PATH = 's3://virusbreakend/virusbreakenddb_20210401.tar.gz' static enum PipelineMode { FULL, diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index d51b7efa..e350ef97 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -25,14 +25,14 @@ class WorkflowOncoanalyser { System.exit(1) } - if (Constants.genomes_version_37.contains(params.genome)) { + if (Constants.GENOMES_VERSION_37.contains(params.genome)) { params.ref_data_genome_version = '37' - } else if (Constants.genomes_version_38.contains(params.genome)) { + } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { params.ref_data_genome_version = '38' - } else if (Constants.genomes_version_38_noalt.contains(params.genome)) { + } else if (Constants.GENOMES_VERSION_38_NOALT.contains(params.genome)) { params.ref_data_genome_version = '38_noalt' } else { - def genome_version_list_all = Constants.genomes_version_37 + Constants.genomes_version_38 + def genome_version_list_all = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome '${params.genome}' is not defined in genome version list. \n" + " Currently, the list of genomes in the version list include:\n" + @@ -43,16 +43,16 @@ class WorkflowOncoanalyser { if (!params.containsKey('ref_data_hmf_bundle')) { if (params.ref_data_genome_version == '37') { - params.ref_data_hmf_bundle = Constants.hmf_reference_data_37_bundle_path + params.ref_data_hmf_bundle = Constants.HMF_REFERENCE_DATA_37_BUNDLE_PATH } else if (params.ref_data_genome_version == '38') { - params.ref_data_hmf_bundle = Constants.hmf_reference_data_38_bundle_path + params.ref_data_hmf_bundle = Constants.HMF_REFERENCE_DATA_38_BUNDLE_PATH } else { assert false : "Got a bad genome version: ${params.ref_data_genome_version}" } } if (!params.containsKey('ref_data_virusbreakenddb_path')) { - params.ref_data_virusbreakenddb_path = Constants.virusbreakenddb_path + params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH } if (!params.ref_data_genome_fasta) { From e5549cc7ada2fe523f44b36cccc2ea22c290135a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 8 Dec 2022 15:58:03 +1100 Subject: [PATCH 018/562] Fix LILAC ALT genome processing branch --- lib/WorkflowOncoanalyser.groovy | 5 ++++- subworkflows/local/lilac.nf | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index e350ef97..e91c331b 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -27,10 +27,13 @@ class WorkflowOncoanalyser { if (Constants.GENOMES_VERSION_37.contains(params.genome)) { params.ref_data_genome_version = '37' + params.ref_data_genome_type = 'no_alt' } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { params.ref_data_genome_version = '38' + params.ref_data_genome_type = 'alt' } else if (Constants.GENOMES_VERSION_38_NOALT.contains(params.genome)) { - params.ref_data_genome_version = '38_noalt' + params.ref_data_genome_version = '38' + params.ref_data_genome_type = 'no_alt' } else { def genome_version_list_all = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index 323940ba..f03dccb0 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -42,7 +42,7 @@ workflow LILAC { // Realign contigs if using 38 (use of ALT contigs implied) // channel: [val(meta)] ch_metas = ch_inputs_bams.map { return it[0] } - if (params.ref_data_genome_version == '38') { + if (params.ref_data_genome_type == 'alt') { // Align reads with chr6 // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them // to the three relevant HLA genes on chr6. All reads including those previously mapped to chr6 From f2dd262e27bbfe4c23603e4aa7f5630d421d21b7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 8 Dec 2022 16:49:28 +1100 Subject: [PATCH 019/562] Update HMF genome paths --- conf/hmfgenomes.config | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/conf/hmfgenomes.config b/conf/hmfgenomes.config index 89533274..a99c225c 100644 --- a/conf/hmfgenomes.config +++ b/conf/hmfgenomes.config @@ -10,20 +10,20 @@ params { genomes { 'GRCh37_hmf' { - fasta = "GRCh37_fasta" - fai = "GRCh37_fai" - dict = "GRCh37_dict" - bwa_index = "GRCh37_bwa_index" - bwa_index_image = "GRCh37_bwa_index_image" - gridss_index = "GRCh37_gridss_index" + fasta = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/Homo_sapiens.GRCh37.GATK.illumina.fasta" + fai = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" + dict = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" + bwa_index = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/bwa_index/" + bwa_index_image = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" + gridss_index = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" } 'GRCh38_hmf' { - fasta = "GRCh38_fasta" - fai = "GRCh38_fai" - dict = "GRCh38_dict" - bwa_index = "GRCh38_bwa_index" - bwa_index_image = "GRCh38_bwa_index_image" - gridss_index = "GRCh38_gridss_index" + fasta = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" + fai = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" + dict = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" + bwa_index = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/bwa_index/" + bwa_index_image = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" + gridss_index = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" } } } From e3b9842b216450c52ac85ef08bf1b8ebd95b91c9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 9 Dec 2022 17:43:04 +1100 Subject: [PATCH 020/562] Update variable name for HMF bundle path --- lib/WorkflowOncoanalyser.groovy | 8 ++++---- nextflow_schema.json | 2 +- subworkflows/local/prepare_reference.nf | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index e91c331b..050dee04 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -16,7 +16,7 @@ class WorkflowOncoanalyser { // public static void initialise(params, workflow, log) { - if (params.genome && params.genomes && ! params.genomes.containsKey(params.genome)) { + if (params.genomes && ! params.genomes.containsKey(params.genome)) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + " Currently, the available genome keys are:\n" + @@ -44,11 +44,11 @@ class WorkflowOncoanalyser { System.exit(1) } - if (!params.containsKey('ref_data_hmf_bundle')) { + if (!params.containsKey('ref_data_hmf_bundle_path')) { if (params.ref_data_genome_version == '37') { - params.ref_data_hmf_bundle = Constants.HMF_REFERENCE_DATA_37_BUNDLE_PATH + params.ref_data_hmf_bundle_path = Constants.HMF_REFERENCE_DATA_37_BUNDLE_PATH } else if (params.ref_data_genome_version == '38') { - params.ref_data_hmf_bundle = Constants.HMF_REFERENCE_DATA_38_BUNDLE_PATH + params.ref_data_hmf_bundle_path = Constants.HMF_REFERENCE_DATA_38_BUNDLE_PATH } else { assert false : "Got a bad genome version: ${params.ref_data_genome_version}" } diff --git a/nextflow_schema.json b/nextflow_schema.json index 1147cc8b..8ee91c2c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -143,7 +143,7 @@ "description": "Path to reference genome GRIDSS index file.", "fa_icon": "far fa-file-code" }, - "ref_data_hmf_bundle": { + "ref_data_hmf_bundle_path": { "type": "string", "format": "directory-path", "description": "Path to HMF reference data bundle.", diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index fae052c0..d36634a5 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -102,9 +102,9 @@ workflow PREPARE_REFERENCE { // Set HMF reference paths / stage, unpack if required // // NOTE(SW): requiring all HMF reference data for now - if (params.ref_data_hmf_bundle.endsWith('.tar.gz')) { + if (params.ref_data_hmf_bundle_path.endsWith('.tar.gz')) { // Decompress and set paths - EXTRACT_TARBALL_HMF_BUNDLE([[id: 'hmf_bundle'], file(params.ref_data_hmf_bundle)]) + EXTRACT_TARBALL_HMF_BUNDLE([[id: 'hmf_bundle'], file(params.ref_data_hmf_bundle_path)]) // Obtain paths and convert queue channel to value channel // NOTE(SW): any relevant HMF reference file parameter explicitly set in config will take priority @@ -114,9 +114,9 @@ workflow PREPARE_REFERENCE { assert dir_list.size() == 1 return createHmfDataMap(dir_list[0], false /* params_only */) } - } else if (params.ref_data_hmf_bundle) { + } else if (params.ref_data_hmf_bundle_path) { // If provided as path to directory, set paths - ch_hmf_data = createHmfDataMap(params.ref_data_hmf_bundle, false /* params_only */) + ch_hmf_data = createHmfDataMap(params.ref_data_hmf_bundle_path, false /* params_only */) } else { // If no HMF data bundle is supplied we construct from *only* params ch_hmf_data = createHmfDataMap(null, true /* params_only */) From 1cc3803bb83445261507353e62cead189452a3d4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 9 Dec 2022 17:30:13 +1100 Subject: [PATCH 021/562] Remove tag from EXTRACT_TARBALL --- modules/local/custom/extract_tarball/main.nf | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/local/custom/extract_tarball/main.nf b/modules/local/custom/extract_tarball/main.nf index 5c70b2a2..208c2d32 100644 --- a/modules/local/custom/extract_tarball/main.nf +++ b/modules/local/custom/extract_tarball/main.nf @@ -1,5 +1,4 @@ process EXTRACT_TARBALL { - tag "${meta.id}" label 'process_single' container 'public.ecr.aws/ubuntu/ubuntu:20.04_stable' From 2fd106074cf9249e7f0a075e9bfa15dd1732580a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 9 Dec 2022 17:30:41 +1100 Subject: [PATCH 022/562] Correct variable name --- subworkflows/local/prepare_input.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf index a5e532a1..13c30505 100644 --- a/subworkflows/local/prepare_input.nf +++ b/subworkflows/local/prepare_input.nf @@ -62,9 +62,9 @@ workflow PREPARE_INPUT { ] def index_ext - if (filetype_bai.contains(filetype)) { + if (filetype_bai.contains(filetype_enum)) { index_ext = 'bai' - } else if (filetype_tbi.contains(filetype)) { + } else if (filetype_tbi.contains(filetype_enum)) { index_ext = 'tbi' } else { return From f16efd314ad462344796f46c5e35ed2443b5afcd Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 9 Dec 2022 17:32:40 +1100 Subject: [PATCH 023/562] Execute Docker contains with current user --- nextflow.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nextflow.config b/nextflow.config index 5cad486d..cbff5b61 100644 --- a/nextflow.config +++ b/nextflow.config @@ -6,6 +6,10 @@ ---------------------------------------------------------------------------------------- */ +// NOTE(SW): required for some Docker containers in certain execution envs, +// leaving here until better place decided +docker.runOptions = '-u $(id -u):$(id -g)' + // Global default params, used in configs params { From e123ac1cb38087665cb09316af0b851efc512ea9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 12 Dec 2022 16:10:10 +1100 Subject: [PATCH 024/562] Fix some outputs and ids --- conf/modules.config | 12 ++++++------ subworkflows/local/lilac.nf | 5 +++-- workflows/oncoanalyser.nf | 18 +++++++++++------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index adff181c..735c6286 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -107,7 +107,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/germline_annotations/" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/germline_annotations/" }, ] } @@ -115,7 +115,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic_annotations/" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/somatic_annotations/" }, ] } @@ -124,7 +124,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/linx/somatic_plots/" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/somatic_plots/" }, ] } @@ -132,7 +132,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } @@ -212,7 +212,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } @@ -222,7 +222,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index f03dccb0..16007d7e 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -1,6 +1,7 @@ // // LILAC is a WGS tool for HLA typing and somatic CNV and SNV calling // +import Constants include { EXTRACT_AND_INDEX_CONTIG } from '../../modules/local/custom/lilac_extract_and_index_contig/main' include { REALIGN_READS } from '../../modules/local/custom/lilac_realign_reads_lilac/main' @@ -91,8 +92,8 @@ workflow LILAC { def meta_lilac = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', 'tumor']), - normal_id: meta.get(['sample_name', 'normal']), + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), ] return [meta_lilac, *it[1..-1]] } diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 365dde17..68428edf 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -151,7 +151,8 @@ workflow ONCOANALYSER { // channel: [meta_isofox, tumor_bam_wts] ch_isofox_inputs = ch_inputs_wts.present .map { meta -> - return [[key: meta.id, id: meta.id], meta.get([Constants.FileType.BAM_WTS, Constants.DataType.TUMOR])] + def meta_isofox = [key: meta.id, id: meta.get(['sample_name', Constants.DataType.TUMOR])] + return [meta_isofox, meta.get([Constants.FileType.BAM_WTS, Constants.DataType.TUMOR])] } // Run process @@ -483,7 +484,7 @@ workflow ONCOANALYSER { ] return [pave_meta, sage_vcf] } - ch_pave_somatic_inputs = ch_pave_germline_inputs_source + ch_pave_somatic_inputs = ch_pave_somatic_inputs_source .map { meta, sage_vcf -> def pave_meta = [ key: meta.id, @@ -655,8 +656,8 @@ workflow ONCOANALYSER { ch_bams_and_indices, run.collectwgsmetrics ? ch_cwm_output.tumor : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COLLECTWGSMETRICS, Constants.DataType.TUMOR]), run.collectwgsmetrics ? ch_cwm_output.normal : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COLLECTWGSMETRICS, Constants.DataType.NORMAL]), - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COBALT_DIR, Constants.DataType.TUMOR_NORMAL]), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), ) // Create inputs and create process-specific meta @@ -763,7 +764,7 @@ workflow ONCOANALYSER { def meta = it[0] def meta_virus = [ key: meta.id, - id: meta.id, + id: meta.get(['sample_name', Constants.DataType.TUMOR]), ] return [meta_virus, *it[1..-1]] } @@ -803,7 +804,7 @@ workflow ONCOANALYSER { def meta = it[0] def meta_linx = [ key: meta.id, - id: meta.id, + id: meta.get(['sample_name', Constants.DataType.NORMAL]), ] return [meta_linx, it[1..-1]] } @@ -813,7 +814,7 @@ workflow ONCOANALYSER { def meta = it[0] def meta_linx = [ key: meta.id, - id: meta.id, + id: meta.get(['sample_name', Constants.DataType.TUMOR]), ] return [meta_linx, it[1..-1]] } @@ -841,7 +842,10 @@ workflow ONCOANALYSER { // channel: [meta(meta_linx_report), anno_dir, vis_dir] ch_linx_report_inputs = ch_linx_somatic_out .map { meta, anno_dir, vis_dir -> - def meta_linx_report = [id: meta.id] + def meta_linx_report = [ + key: meta.id, + id: meta.get(['sample_name', Constants.DataType.TUMOR]), + ] return [meta_linx_report, anno_dir, vis_dir] } From ef519fd60b42222bbe5add1224ab421253339e11 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 12 Dec 2022 16:11:33 +1100 Subject: [PATCH 025/562] Add CUPPA report to CUPPA visualiser --- conf/modules.config | 3 ++- modules/local/cuppa/Dockerfile | 30 ++++++++++++++++++-------- modules/local/cuppa/visualiser/main.nf | 10 ++++++--- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 735c6286..a9363a4a 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -236,7 +236,8 @@ process { } withName: 'CUPPA_VISUALISER' { - ext.pythonPath = '/opt/cuppa/chart/cuppa-chart.py' + ext.chartScriptPath = '/opt/cuppa/chart/cuppa-chart.py' + ext.reportScriptPath = '/opt/cuppa/report/CupGenerateReport_pipeline.R' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, diff --git a/modules/local/cuppa/Dockerfile b/modules/local/cuppa/Dockerfile index b697f5c9..03a85743 100644 --- a/modules/local/cuppa/Dockerfile +++ b/modules/local/cuppa/Dockerfile @@ -4,7 +4,7 @@ USER root RUN \ apt-get update && \ - apt-get install -y procps wget && \ + apt-get install -y patch procps wget && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -12,14 +12,20 @@ RUN \ mkdir -p /opt/cuppa/ && \ wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.7/cuppa_v1.7.jar' -ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.7/cuppa/src/main/resources/cuppa-chart -ARG DIR_BASE=/opt/cuppa/chart +ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.7/cuppa/src/main/resources +ARG DIR_BASE=/opt/cuppa RUN \ - mkdir -p ${DIR_BASE}/ && \ - wget -P ${DIR_BASE}/ ${URL_BASE}/requirements.txt && \ - wget -P ${DIR_BASE}/ ${URL_BASE}/cuppa-chart.py && \ - wget -P ${DIR_BASE}/main/ ${URL_BASE}/main/create_chart.py && \ - wget -P ${DIR_BASE}/main/ ${URL_BASE}/main/prepare_data.py + mkdir -p ${DIR_BASE}/{chart,report} && \ + wget -P ${DIR_BASE}/chart/ ${URL_BASE}/cuppa-chart/requirements.txt && \ + wget -P ${DIR_BASE}/chart/ ${URL_BASE}/cuppa-chart/cuppa-chart.py && \ + wget -P ${DIR_BASE}/chart/main/ ${URL_BASE}/cuppa-chart/main/create_chart.py && \ + wget -P ${DIR_BASE}/chart/main/ ${URL_BASE}/cuppa-chart/main/prepare_data.py && \ + wget -P ${DIR_BASE}/report/ ${URL_BASE}/r/CupGenerateReport_pipeline.R + +COPY assets/CupGenerateReport_pipeline.R.patch /tmp/ +RUN \ + patch -p1 ${DIR_BASE}/report/CupGenerateReport_pipeline.R /tmp/CupGenerateReport_pipeline.R.patch && \ + rm /tmp/CupGenerateReport_pipeline.R.patch USER mambauser @@ -30,7 +36,13 @@ RUN \ 'openjdk >=8' \ 'pandas >=1.1,<2' \ 'scipy >=1,<2' \ - 'seaborn >=0.11,<1' && \ + 'seaborn >=0.11,<1' \ + 'r-base ==4.2.2' \ + 'r-cowplot' \ + 'r-ggplot2' \ + 'r-gridextra' \ + 'r-stringi' \ + 'r-tidyr' && \ micromamba clean --all --yes ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf index 4088bd52..22d40e22 100644 --- a/modules/local/cuppa/visualiser/main.nf +++ b/modules/local/cuppa/visualiser/main.nf @@ -8,8 +8,11 @@ process CUPPA_VISUALISER { tuple val(meta), path(cuppa_csv) output: - path '*png' - path '*txt' + path '*chart.png' + path '*conclusion.txt' + path '*report.features.png' + path '*report.summary.png' + path '*cup_report.pdf' path 'versions.yml' , emit: versions when: @@ -19,10 +22,11 @@ process CUPPA_VISUALISER { def args = task.ext.args ?: '' """ - python ${task.ext.pythonPath} \\ + python ${task.ext.chartScriptPath} \\ -sample ${meta.id} \\ -sample_data ${cuppa_csv} \\ -output_dir ./ + Rscript ${task.ext.reportScriptPath} ${meta.id} ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml From 9781aa101c3e147c2185bce27e807d6b7856e6b7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 12 Dec 2022 16:16:34 +1100 Subject: [PATCH 026/562] Fix Sigs --- modules/local/chord/Dockerfile | 6 ++++-- .../chord/assets/extractSigPredictHRD.R.patch | 14 +++++++++++--- modules/local/sigs/main.nf | 3 +++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/modules/local/chord/Dockerfile b/modules/local/chord/Dockerfile index 747c73f5..e87e6e8c 100644 --- a/modules/local/chord/Dockerfile +++ b/modules/local/chord/Dockerfile @@ -31,6 +31,8 @@ RUN \ ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}:/opt/chord/" +# NOTE(SW): mutSigExtractor must be installed second as the process to install +# CHORD can upgrade mutSigExtractor to an incompatible version RUN \ - R -e "devtools::install_github('https://github.com/UMCUGenetics/mutSigExtractor', ref='1.14')" && \ - R -e "devtools::install_github('https://github.com/UMCUGenetics/CHORD', ref='2.00')" + R -e "devtools::install_github('https://github.com/UMCUGenetics/CHORD', ref='2.00')" && \ + R -e "devtools::install_github('https://github.com/UMCUGenetics/mutSigExtractor', ref='1.14')" diff --git a/modules/local/chord/assets/extractSigPredictHRD.R.patch b/modules/local/chord/assets/extractSigPredictHRD.R.patch index b4dc9508..74a8e8c9 100644 --- a/modules/local/chord/assets/extractSigPredictHRD.R.patch +++ b/modules/local/chord/assets/extractSigPredictHRD.R.patch @@ -1,6 +1,10 @@ --- a/extractSigPredictHRD.R +++ b/extractSigPredictHRD.R -@@ -4,12 +4,11 @@ options(stringsAsFactors=F) # to avoid invalid factor level warning +@@ -1,15 +1,14 @@ +-#!/usr/bin/Rscript ++#!/usr/bin/env Rscript + + options(stringsAsFactors=F) # to avoid invalid factor level warning args <- commandArgs(TRUE) @@ -29,7 +33,7 @@ cat("[INFO] Package NamespaceVersions after loading:\n") for (pkgName in c("mutSigExtractor", "CHORD")){ -@@ -28,14 +27,14 @@ for (pkgName in c("mutSigExtractor", "CHORD")){ +@@ -28,18 +27,17 @@ for (pkgName in c("mutSigExtractor", "CHORD")){ } ## Convert genome name to BSGenome name @@ -47,7 +51,11 @@ } cat("[INFO] CHORD Settings:\n") -@@ -73,4 +72,4 @@ write.table(signatures, file=sigOutTxt, sep="\t") +-cat("[INFO] Chord dir:", chordToolDir, "\n") + cat("[INFO] Working dir:", workingDir, "\n") + cat("[INFO] Sample name:", sampleName, "\n") + cat("[INFO] Somatic SNV/IND vcf:", snvIndVcf, "\n") +@@ -73,4 +71,4 @@ write.table(signatures, file=sigOutTxt, sep="\t") cat("[INFO] Writing output file:", prdOutTxt,"\n") write.table(prediction, file=prdOutTxt, sep="\t", quote=FALSE, row.names=FALSE) diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 413f7871..28e93176 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -19,10 +19,13 @@ process SIGS { def args = task.ext.args ?: '' """ + mkdir -p sigs/ + java \\ -Xmx${task.memory.giga}g \\ -jar ${task.ext.jarPath} \\ -sample ${meta.id} \\ + -somatic_vcf_file ${smlv_vcf} \\ -signatures_file ${signatures_file} \\ -output_dir ./sigs/ From e59aaa05a3a026435abebb5c501ec3a930c76eb2 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 12 Dec 2022 16:17:02 +1100 Subject: [PATCH 027/562] Fix PAVE somatic --- modules/local/pave/somatic/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index c4627e60..e4e12e03 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -38,7 +38,7 @@ process PAVE_SOMATIC { -ensembl_data_dir ${ensembl_data_dir} \\ -driver_gene_panel ${driver_gene_panel} \\ -pon_file ${sage_pon_file} \\ - -pon_filters ${pon_filters} \\ + -pon_filters "${pon_filters}" \\ -mappability_bed ${mappability_bed} \\ -vcf_file ${sage_vcf} \\ -read_pass_only \\ From 258c450033190f6b9a97521bea811698234110f4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 14 Dec 2022 10:18:02 +1100 Subject: [PATCH 028/562] Stop on null params.genome value --- lib/WorkflowOncoanalyser.groovy | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 050dee04..70068561 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -16,10 +16,17 @@ class WorkflowOncoanalyser { // public static void initialise(params, workflow, log) { - if (params.genomes && ! params.genomes.containsKey(params.genome)) { + if (!params.genome) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome must be set using the --genome CLI argument or in a configuration file.\n" + + " Currently, the available genome are:\n" + + " ${params.genomes.keySet().join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } else if (!params.genomes.containsKey(params.genome)) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + - " Currently, the available genome keys are:\n" + + " Currently, the available genome are:\n" + " ${params.genomes.keySet().join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) From 1b24d8d6e05aa60551aca1945a91280270a6415b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 14 Dec 2022 10:18:44 +1100 Subject: [PATCH 029/562] Bump required minimum version of Nextflow --- nextflow.config | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index cbff5b61..d7722d61 100644 --- a/nextflow.config +++ b/nextflow.config @@ -195,7 +195,8 @@ manifest { homePage = 'https://github.com/nf-core/oncoanalyser' description = 'A comprehensive cancer NGS analysis and reporting pipeline' mainScript = 'main.nf' - nextflowVersion = '!>=21.10.3' + // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release + nextflowVersion = '!>=22.10.4' version = '0.0.1' doi = '' } From 7d58d038a426586a37bb708e66ce0fcca1526404 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 10:19:39 +1100 Subject: [PATCH 030/562] Remove check samplesheet script --- bin/check_samplesheet.py | 248 --------------------------------------- 1 file changed, 248 deletions(-) delete mode 100755 bin/check_samplesheet.py diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py deleted file mode 100755 index c937b7d2..00000000 --- a/bin/check_samplesheet.py +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/env python3 -import argparse -import collections -import enum -import pathlib -import sys - - -HEADER_COLS = ( - 'id', - 'subject_name', - 'sample_name', - 'sample_type', - 'filetype', - 'filepath', -) - - -class FileType(enum.Enum): - - BAM_WGS = 'bam_wgs' - BAM_WTS = 'bam_wts' - VCF_SV = 'vcf_sv' - SMLV_VCF = 'vcf_smlv' - VCF_SV_GRIPSS_SOFT = 'vcf_sv_gripss_soft' - VCF_SV_GRIPSS_HARD = 'vcf_sv_gripss_hard' - AMBER_DIR = 'amber_dir' - COBALT_DIR = 'cobalt_dir' - PURPLE_DIR = 'purple_dir' - - def __repr__(self): - return self.value - - -class SampleType(enum.Enum): - - TUMOR = 'tumor' - NORMAL = 'normal' - - def __repr__(self): - return self.value - - -FILETYPES_EXPECTED = { - 'full': { - 'required': [ - (SampleType.TUMOR, FileType.BAM_WGS), - (SampleType.NORMAL, FileType.BAM_WGS), - ], - 'optional': [ - (SampleType.TUMOR, FileType.BAM_WTS), - (SampleType.TUMOR, FileType.VCF_SV), - (SampleType.NORMAL, FileType.VCF_SV), - ], - }, - 'gridss_purple_linx': { - 'required': [ - (SampleType.TUMOR, FileType.BAM_WGS), - (SampleType.NORMAL, FileType.BAM_WGS), - ], - 'optional': [ - (SampleType.TUMOR, FileType.VCF_SV), - (SampleType.NORMAL, FileType.VCF_SV), - (SampleType.TUMOR, FileType.SMLV_VCF), - (SampleType.NORMAL, FileType.SMLV_VCF) - ], - }, - 'gridss': { - 'required': [ - (SampleType.TUMOR, FileType.BAM_WGS), - (SampleType.NORMAL, FileType.BAM_WGS), - ], - 'optional': [ - (SampleType.TUMOR, FileType.VCF_SV), - (SampleType.NORMAL, FileType.VCF_SV), - ], - }, - 'purple': { - 'required': [ - (SampleType.TUMOR, FileType.AMBER_DIR), - (SampleType.TUMOR, FileType.COBALT_DIR), - (SampleType.TUMOR, FileType.VCF_SV_GRIPSS_HARD), - (SampleType.TUMOR, FileType.VCF_SV_GRIPSS_SOFT), - ], - 'optional': [ - (SampleType.TUMOR, FileType.SMLV_VCF), - (SampleType.NORMAL, FileType.SMLV_VCF), - ], - }, - # NOTE(SW): expectation that we always at least want to run LINX somatic - 'linx': { - 'required': [ - (SampleType.TUMOR, FileType.PURPLE_DIR), - ], - 'optional': [ - (SampleType.NORMAL, FileType.VCF_SV_GRIPSS_HARD), - ], - }, - 'lilac': { - 'required': [ - (SampleType.TUMOR, FileType.BAM_WGS), - (SampleType.NORMAL, FileType.BAM_WGS), - (SampleType.TUMOR, FileType.PURPLE_DIR), - ], - 'optional': [], - }, - 'teal': { - 'required': [ - (SampleType.TUMOR, FileType.BAM_WGS), - (SampleType.NORMAL, FileType.BAM_WGS), - (SampleType.TUMOR, FileType.COBALT_DIR), - (SampleType.TUMOR, FileType.PURPLE_DIR), - ], - 'optional': [], - }, -} - - -def get_arguments(): - parser = argparse.ArgumentParser() - parser.add_argument( - '--input_fp', - required=True, - type=pathlib.Path, - help='Input samplesheet filepath', - ) - parser.add_argument( - '--mode', - required=True, - type=str, - choices=FILETYPES_EXPECTED.keys(), - help='Pipeline execution mode', - ) - args = parser.parse_args() - if not args.input_fp.exists(): - parser.error(f'Input file {args.input_fp} does not exist') - return args - - -def main(): - # Get commandline arguments - args = get_arguments() - - # Read data - runs = collections.defaultdict(list) - with args.input_fp.open('r') as fh: - line_token_gen = (line.rstrip().split('\t') for line in fh) - header_tokens = next(line_token_gen) - check_header(header_tokens, HEADER_COLS) - for lts in line_token_gen: - record = {k: v for k, v in zip(header_tokens, lts)} - record['sample_type_enum'] = get_enum(record, 'sample_type', SampleType) - record['filetype_enum'] = get_enum(record, 'filetype', FileType) - runs[record['id']].append(record) - - # Validate data - for rid, records in runs.items(): - input_types = {(r['sample_type_enum'], r['filetype_enum']) for r in records} - check_input_types( - input_types, - FILETYPES_EXPECTED[args.mode]['required'], - FILETYPES_EXPECTED[args.mode]['optional'], - ) - check_subject_names(rid, records) - check_bam_sample_names(records, FileType.BAM_WGS) - check_bam_sample_names(records, FileType.BAM_WTS) - check_sample_type_sample_names(rid, records) - - -def get_enum(record, name, enum_class): - value = record[name] - try: - return enum_class(value) - except ValueError: - print(f'Got invalid {name} for {record["id"]}: {value}', file=sys.stderr) - sys.exit(1) - - -def check_subject_names(rid, records): - subject_names = {r['subject_name'] for r in records} - if len(subject_names) > 1: - subject_names_str = ', '.join(subject_names) - msg = f'Got multiple subject names for {rid}: {subject_names_str}' - print(msg, file=sys.stderr) - sys.exit(1) - - -def check_bam_sample_names(records, bam_filetype): - record_tumor_bam = None - record_normal_bam = None - for record in records: - if record['filetype_enum'] != bam_filetype: - continue - if record['sample_type_enum'] == SampleType.TUMOR: - record_tumor_bam = record - elif record['sample_type_enum'] == SampleType.NORMAL: - record_normal_bam = record - - if record_tumor_bam is None or record_normal_bam is None: - return - - if record_tumor_bam['sample_name'] == record_normal_bam['sample_name']: - sample_name = record_tumor_bam['sample_name'] - print(f'Got identical sample names for \'{repr(bam_filetype)}\' BAMs: {sample_name}', file=sys.stderr) - sys.exit(1) - - -def check_sample_type_sample_names(rid, records): - sample_names_tumor = set() - sample_names_normal = set() - for record in records: - if record['sample_type_enum'] == SampleType.TUMOR: - sample_names_tumor.add(record['sample_name']) - elif record['sample_type_enum'] == SampleType.NORMAL: - sample_names_normal.add(record['sample_name']) - else: - assert False - if len(sample_names_tumor) > 1: - sn_tumor_str = ', '.join(sample_names_tumor) - print(f'Got mismatch sample names for {rid} tumor: {sn_tumor_str}', file=sys.stderr) - sys.exit(1) - if len(sample_names_normal) > 1: - sn_normal_str = ', '.join(sample_names_normal) - print(f'Got mismatch sample names for {rid} normal: {sn_normal_str}', file=sys.stderr) - sys.exit(1) - - -def check_header(header_tokens, required_cols): - check_set_difference(header_tokens, required_cols, 'Found unknown header column') - check_set_difference(required_cols, header_tokens, 'Missing required column') - - -def check_input_types(input_types, required, optional): - check_set_difference(input_types, required + optional, 'Found unknown input type') - check_set_difference(required, input_types, 'Missing required input type') - - -def check_set_difference(a, b, message_base): - d = set(a).difference(b) - if d : - d_str = ', '.join(str(e) for e in d) - plurality = 's' if len(d) > 1 else '' - print(f'{message_base}{plurality}: {d_str}', file=sys.stderr) - sys.exit(1) - - -if __name__ == '__main__': - main() From cce34f3666c515c98b9aa29be122198518d2440a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 10:24:21 +1100 Subject: [PATCH 031/562] Restrict, reorganise genome validation --- lib/Constants.groovy | 4 ++-- lib/WorkflowOncoanalyser.groovy | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 022124b2..dbbdd5cf 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -2,8 +2,8 @@ class Constants { // NOTE(SW): the HMF reference data files are incompatible with hg19 due to different contig naming static List GENOMES_VERSION_37 = ['GRCh37_hmf', 'GRCh37'] - static List GENOMES_VERSION_38 = ['GRCh38', 'hg38'] - static List GENOMES_VERSION_38_NOALT = ['GRCh38_hmf'] + static List GENOMES_VERSION_38 = ['GRCh38_hmf', 'GRCh38', 'hg38'] + static List GENOMES_ALT = ['GRCh38', 'hg38'] static String HMF_REFERENCE_DATA_37_BUNDLE_PATH = 's3://umccr-research-dev/stephen/hmftools_reference_data/2_repack/gcloud_vm_v5.23/hmf_data_bundle_5.23_37_0.0.1.tar.gz' static String HMF_REFERENCE_DATA_38_BUNDLE_PATH = 's3://umccr-research-dev/stephen/hmftools_reference_data/2_repack/gcloud_vm_v5.23/hmf_data_bundle_5.23_38_0.0.1.tar.gz' diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 70068561..b97e10e7 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -16,6 +16,15 @@ class WorkflowOncoanalyser { // public static void initialise(params, workflow, log) { + // NOTE(SW): restricting allowable genome values to GRCh37_hmf for now + if (params.genome != 'GRCh37_hmf') { + log.error "ERROR: currently only the GRCh37_hmf genome is supported but got \"${params.genome}\"" + + ", please adjust the --genome argument accordingly." + System.exit(1) + } + + // TODO(SW): allow users to set all appropriate reference genomes manually in config or CLI, including version and type (see below) + if (!params.genome) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome must be set using the --genome CLI argument or in a configuration file.\n" + @@ -34,13 +43,8 @@ class WorkflowOncoanalyser { if (Constants.GENOMES_VERSION_37.contains(params.genome)) { params.ref_data_genome_version = '37' - params.ref_data_genome_type = 'no_alt' } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { params.ref_data_genome_version = '38' - params.ref_data_genome_type = 'alt' - } else if (Constants.GENOMES_VERSION_38_NOALT.contains(params.genome)) { - params.ref_data_genome_version = '38' - params.ref_data_genome_type = 'no_alt' } else { def genome_version_list_all = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + @@ -51,6 +55,13 @@ class WorkflowOncoanalyser { System.exit(1) } + // TODO(SW): when allowing user to set custom genome, require this to be explicitly set + if (Constants.GENOMES_ALT.contains(params.genome)) { + params.ref_data_genome_type = 'alt' + } else { + params.ref_data_genome_type = 'no_alt' + } + if (!params.containsKey('ref_data_hmf_bundle_path')) { if (params.ref_data_genome_version == '37') { params.ref_data_hmf_bundle_path = Constants.HMF_REFERENCE_DATA_37_BUNDLE_PATH From 5923ca052891a211252e769ccd9ebf8697d3b7f8 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 10:24:39 +1100 Subject: [PATCH 032/562] Temporary adjustments for local stub testing --- conf/test.config | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/conf/test.config b/conf/test.config index ff055aac..5c603278 100644 --- a/conf/test.config +++ b/conf/test.config @@ -11,6 +11,7 @@ */ process { + cups = 1 memory = 16.GB withName: 'SAGE_GERMLINE' { @@ -37,10 +38,22 @@ params { schema_ignore_params = 'genomes,ref_data_wgsmetrics_intervals_url' // Limit resources so that this can run on GitHub Actions - max_cpus = 2 + max_cpus = 1 max_memory = '6.GB' max_time = '6.h' // Input data - input = '/Users/stephen/repos/nextflow_testdata/hmftools/input_tsv/samplesheet.tsv' + input = '/Users/stephen/repos/oncoanalyser/temp/samplesheet.csv' + + ref_data_hmf_bundle_path = '/Users/stephen/repos/oncoanalyser/temp/hmf_bundle.tar.gz' + ref_data_virusbreakenddb_path = '/Users/stephen/repos/oncoanalyser/temp/virusbreakenddb_20210401.tar.gz' + + genome = 'GRCh37_hmf' + ref_data_genome_fasta = '/Users/stephen/repos/oncoanalyser/temp/GRCh38.fasta' + ref_data_genome_fai = '/Users/stephen/repos/oncoanalyser/temp/GRCh38.fai' + ref_data_genome_dict = '/Users/stephen/repos/oncoanalyser/temp/GRCh38.dict' + ref_data_genome_bwa_index = '/Users/stephen/repos/oncoanalyser/temp/GRCh38_bwa/' + ref_data_genome_bwa_index_image = '/Users/stephen/repos/oncoanalyser/temp/GRCh38.img' + ref_data_genome_gridss_index = '/Users/stephen/repos/oncoanalyser/temp/GRCh38.gridsscache' + } From 2cfcc95ae66c5fa6c25eb26d6bd8268909f95fc6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 14 Dec 2022 10:17:27 +1100 Subject: [PATCH 033/562] Align tool versions with Pipeline5 v5.29 --- modules/local/cuppa/Dockerfile | 3 ++- modules/local/cuppa/classifier/main.nf | 4 ++-- modules/local/cuppa/visualiser/main.nf | 4 ++-- modules/local/gripss/Dockerfile | 2 +- modules/local/gripss/germline/main.nf | 4 ++-- modules/local/gripss/somatic/main.nf | 4 ++-- modules/local/lilac/Dockerfile | 2 +- modules/local/lilac/main.nf | 4 ++-- modules/local/linx/Dockerfile | 2 +- modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 2 +- modules/local/pave/Dockerfile | 2 +- modules/local/pave/germline/main.nf | 4 ++-- modules/local/pave/somatic/main.nf | 4 ++-- modules/local/purple/Dockerfile | 2 +- modules/local/purple/main.nf | 2 +- modules/local/sage/Dockerfile | 2 +- modules/local/sage/germline/main.nf | 2 +- modules/local/sage/somatic/main.nf | 2 +- modules/local/sigs/Dockerfile | 2 +- modules/local/sigs/main.nf | 4 ++-- 22 files changed, 31 insertions(+), 30 deletions(-) diff --git a/modules/local/cuppa/Dockerfile b/modules/local/cuppa/Dockerfile index 03a85743..9b9a13fe 100644 --- a/modules/local/cuppa/Dockerfile +++ b/modules/local/cuppa/Dockerfile @@ -10,8 +10,9 @@ RUN \ RUN \ mkdir -p /opt/cuppa/ && \ - wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.7/cuppa_v1.7.jar' + wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.6/cuppa_v1.6.jar' +# NOTE(SW): required plotting scripts aren't available under the cuppa-v1.6 tag ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.7/cuppa/src/main/resources ARG DIR_BASE=/opt/cuppa RUN \ diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index a5d43677..e763b294 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -2,7 +2,7 @@ process CUPPA_CLASSIFIER { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.7--0' + container 'docker.io/scwatts/cuppa:1.6--0' input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) @@ -37,7 +37,7 @@ process CUPPA_CLASSIFIER { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - cuppa: 1.7 + cuppa: 1.6 END_VERSIONS """ diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf index 22d40e22..cbb19571 100644 --- a/modules/local/cuppa/visualiser/main.nf +++ b/modules/local/cuppa/visualiser/main.nf @@ -2,7 +2,7 @@ process CUPPA_VISUALISER { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.7--0' + container 'docker.io/scwatts/cuppa:1.6--0' input: tuple val(meta), path(cuppa_csv) @@ -31,7 +31,7 @@ process CUPPA_VISUALISER { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - cuppa: 1.7 + cuppa: 1.6 END_VERSIONS """ diff --git a/modules/local/gripss/Dockerfile b/modules/local/gripss/Dockerfile index fee84c90..19fedbdd 100644 --- a/modules/local/gripss/Dockerfile +++ b/modules/local/gripss/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/gripss/ && \ - wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.3.1/gripss_v2.3.1.jar' + wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.1/gripss_v2.1.jar' USER mambauser diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index b62db6e9..a6203d4c 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -2,7 +2,7 @@ process GRIPSS_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.3.1--0' + container 'docker.io/scwatts/gripss:2.1--0' input: tuple val(meta), path(gridss_vcf) @@ -44,7 +44,7 @@ process GRIPSS_GERMLINE { # NOTE(SW): hard coded since there is no reliable way to obtain version information cat <<-END_VERSIONS > versions.yml "${task.process}": - gripss: 2.3.1 + gripss: 2.1 END_VERSIONS """ diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index 326764c0..1f5f16e7 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -2,7 +2,7 @@ process GRIPSS_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.3.1--0' + container 'docker.io/scwatts/gripss:2.1--0' input: tuple val(meta), path(gridss_vcf) @@ -45,7 +45,7 @@ process GRIPSS_SOMATIC { # NOTE(SW): hard coded since there is no reliable way to obtain version information cat <<-END_VERSIONS > versions.yml "${task.process}": - gripss: 2.3.1 + gripss: 2.1 END_VERSIONS """ diff --git a/modules/local/lilac/Dockerfile b/modules/local/lilac/Dockerfile index b0d3891b..e2d5e079 100644 --- a/modules/local/lilac/Dockerfile +++ b/modules/local/lilac/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/lilac/ && \ - wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.4/lilac_v1.4.1.jar' + wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.1/lilac.jar' USER mambauser diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 79103baa..a22cb49f 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -2,7 +2,7 @@ process LILAC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/lilac:1.4.1--0' + container 'docker.io/scwatts/lilac:1.1--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumour_bai), path(normal_bai), path(purple_dir) @@ -44,7 +44,7 @@ process LILAC { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - lilac: 1.4.1 + lilac: 1.1 END_VERSIONS """ diff --git a/modules/local/linx/Dockerfile b/modules/local/linx/Dockerfile index 846feb27..8a763aba 100644 --- a/modules/local/linx/Dockerfile +++ b/modules/local/linx/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/linx/ && \ - wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.22/linx_v1.22.jar' + wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.19.1/linx_v1.19_rc1.jar' USER mambauser diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index b95b907a..2328dda1 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -2,7 +2,7 @@ process LINX_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.22--0' + container 'docker.io/scwatts/linx:1.19.1--0' input: tuple val(meta), path(gripss_sv) diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index e9c3618d..fae07ff3 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,7 +2,7 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.22--0' + container 'docker.io/scwatts/linx:1.19.1--0' input: tuple val(meta), path(purple_dir) diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index cfffa8a0..283c63e8 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,7 +2,7 @@ process VISUALISER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/linx:1.22--0' + container 'docker.io/scwatts/linx:1.19.1--0' // Lenient caching is required here as the hash of the LINX_SOMATIC // 'annotation_dir' output changes between runs even when the LINX_SOMATIC diff --git a/modules/local/pave/Dockerfile b/modules/local/pave/Dockerfile index d2cbefa9..9245681e 100644 --- a/modules/local/pave/Dockerfile +++ b/modules/local/pave/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/pave/ && \ - wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.4/pave_v1.4.jar' + wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.2.2/pave_v1.2.rc2.jar' USER mambauser diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 42e3eb3b..4b31d673 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -8,7 +8,7 @@ process PAVE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.4--0' + container 'docker.io/scwatts/pave:1.2.2--0' input: tuple val(meta), path(sage_vcf) @@ -54,7 +54,7 @@ process PAVE_GERMLINE { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: 1.4 + pave: 1.2.2 END_VERSIONS """ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index e4e12e03..ae168f4e 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -4,7 +4,7 @@ process PAVE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.4--0' + container 'docker.io/scwatts/pave:1.2.2--0' input: tuple val(meta), path(sage_vcf) @@ -47,7 +47,7 @@ process PAVE_SOMATIC { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: 1.4 + pave: 1.2.2 END_VERSIONS """ diff --git a/modules/local/purple/Dockerfile b/modules/local/purple/Dockerfile index d00dd84a..411117d2 100644 --- a/modules/local/purple/Dockerfile +++ b/modules/local/purple/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/purple/ && \ - wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.7/purple_v3.7.1.jar' + wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.4.3/purple_v3.4.3.jar' USER mambauser diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 4c597cd0..5fbd05d5 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -2,7 +2,7 @@ process PURPLE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/purple:3.6--4' + container 'docker.io/scwatts/purple:3.4.3--0' input: tuple val(meta), path(amber), path(cobalt), path(sv_hard_vcf), path(sv_hard_vcf_index), path(sv_soft_vcf), path(sv_soft_vcf_index), path(smlv_tumor_vcf), path(smlv_normal_vcf) diff --git a/modules/local/sage/Dockerfile b/modules/local/sage/Dockerfile index b2b738b4..069a5bf0 100644 --- a/modules/local/sage/Dockerfile +++ b/modules/local/sage/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/sage/ && \ - wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.2/sage_v3.2.jar' + wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.0.3/sage_v3.0_rc3.jar' USER mambauser diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 3c1068af..d86622d9 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -2,7 +2,7 @@ process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.2--0' + container 'docker.io/scwatts/sage:3.0.3--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index ca3a5e16..e5b4d3d7 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -2,7 +2,7 @@ process SAGE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.2--0' + container 'docker.io/scwatts/sage:3.0.3--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/sigs/Dockerfile b/modules/local/sigs/Dockerfile index 10014b84..5b079be6 100644 --- a/modules/local/sigs/Dockerfile +++ b/modules/local/sigs/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/sigs/ && \ - wget -O /opt/sigs/sigs.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sigs-v1.1/sigs_v1.1.jar' + wget -O /opt/sigs/sigs.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sigs-v1.0/sigs_v1.0.jar' USER mambauser diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 28e93176..53971956 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -2,7 +2,7 @@ process SIGS { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/sigs:1.1--0' + container 'docker.io/scwatts/sigs:1.0--0' input: tuple val(meta), path(smlv_vcf) @@ -32,7 +32,7 @@ process SIGS { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - sigs: 1.1 + sigs: 1.0 END_VERSIONS """ From c3c36c231a8439697746defb9fd64dff20ea2925 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 14 Dec 2022 12:57:05 +1100 Subject: [PATCH 034/562] Add new CUPPA visualiser outputs to stub --- modules/local/cuppa/visualiser/main.nf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf index cbb19571..96269167 100644 --- a/modules/local/cuppa/visualiser/main.nf +++ b/modules/local/cuppa/visualiser/main.nf @@ -39,6 +39,10 @@ process CUPPA_VISUALISER { """ touch ${meta.id}.cuppa.chart.png touch ${meta.id}.cuppa.conclusion.txt + touch ${meta.id}.cuppa.conclusion.txt + touch ${meta.id}_cup_report.pdf + touch ${meta.id}.cup.report.features.png + touch ${meta.id}.cup.report.summary.png echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } From 5576c0157471dc7ca9e256bb15ff7ad208fc45a2 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 10:17:03 +1100 Subject: [PATCH 035/562] Remove SV Prep --- conf/base.config | 3 - conf/modules.config | 12 - lib/Constants.groovy | 2 - lib/Processes.groovy | 2 - modules/local/svprep/Dockerfile | 15 - modules/local/svprep/assemble/main.nf | 92 --- modules/local/svprep/assets/gridss.svprep | 825 ------------------- modules/local/svprep/call/main.nf | 97 --- modules/local/svprep/depth_annotator/main.nf | 50 -- modules/local/svprep/preprocess/main.nf | 57 -- modules/local/svprep/svprep/main.nf | 61 -- nextflow_schema.json | 7 - subworkflows/local/gridss_svprep.nf | 226 ----- subworkflows/local/prepare_reference.nf | 2 - workflows/oncoanalyser.nf | 58 +- 15 files changed, 19 insertions(+), 1490 deletions(-) delete mode 100644 modules/local/svprep/Dockerfile delete mode 100644 modules/local/svprep/assemble/main.nf delete mode 100644 modules/local/svprep/assets/gridss.svprep delete mode 100644 modules/local/svprep/call/main.nf delete mode 100644 modules/local/svprep/depth_annotator/main.nf delete mode 100644 modules/local/svprep/preprocess/main.nf delete mode 100644 modules/local/svprep/svprep/main.nf delete mode 100644 subworkflows/local/gridss_svprep.nf diff --git a/conf/base.config b/conf/base.config index 91edae56..32de85a6 100644 --- a/conf/base.config +++ b/conf/base.config @@ -74,9 +74,6 @@ process { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 1.GB, 'memory' ) } } - withName:'SVPREP.*' { - memory = { check_max( 12.GB, 'memory' ) } - } withName:'.*:GRIDSS:.*' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 30.GB, 'memory' ) } diff --git a/conf/modules.config b/conf/modules.config index a9363a4a..4d71d6ae 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -37,10 +37,6 @@ process { ] } - withName:'.*:(? filename.equals('versions.yml') ? null : "${meta.id}/gridss/sv.vcf.gz" } - ] - } - withName: 'GRIPSS.*' { ext.jarPath = '/opt/gripss/gripss.jar' } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index dbbdd5cf..37ddea03 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -32,7 +32,6 @@ class Constants { PURPLE, SAGE, SIGS, - SVPREP, TEAL, VIRUSINTERPRETER, } @@ -66,7 +65,6 @@ class Constants { AMBER_LOCI: 'amber/GermlineHetPon.vcf.gz', COBALT_GC_PROFILE: 'cobalt/DiploidRegions.bed.gz', CUPPA: 'cuppa/', - SV_PREP_BLACKLIST: 'svprep/sv_prep_blacklist.bed', GRIDSS_BLACKLIST: 'gridss/ENCFF356LFX.bed.gz', GRIDSS_BREAKEND_PON: 'gridss/gridss_pon_single_breakend.bed.gz', GRIDSS_BREAKPOINT_PON: 'gridss/gridss_pon_breakpoint.bedpe.gz', diff --git a/lib/Processes.groovy b/lib/Processes.groovy index 7284ce4c..1277c10c 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -27,7 +27,6 @@ class Processes { Constants.Process.GRIPSS, Constants.Process.LINX, Constants.Process.PURPLE, - Constants.Process.SVPREP, ] break case Constants.PipelineMode.CUPPA: @@ -41,7 +40,6 @@ class Processes { Constants.Process.ISOFOX, Constants.Process.LINX, Constants.Process.PURPLE, - Constants.Process.SVPREP, Constants.Process.VIRUSINTERPRETER, ] break diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile deleted file mode 100644 index 742d4390..00000000 --- a/modules/local/svprep/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM docker.io/scwatts/gridss:2.13.2--3 - -ARG GH_BASE_URL='https://github.com/hartwigmedical/hmftools' -USER root - -RUN \ - mkdir -p /opt/svprep/ && \ - wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.1/sv-prep_v1.1_beta.jar' - -COPY assets/gridss.svprep /opt/svprep/gridss_svprep -RUN \ - chmod 755 /opt/svprep/gridss_svprep && \ - ln -s /opt/svprep/gridss_svprep /usr/local/bin/ - -USER mambauser diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf deleted file mode 100644 index 030f1cb3..00000000 --- a/modules/local/svprep/assemble/main.nf +++ /dev/null @@ -1,92 +0,0 @@ -process ASSEMBLE { - tag "${meta.id}" - label 'process_medium' - - container 'docker.io/scwatts/svprep:1.1--0' - - input: - tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) - path gridss_config - path genome_fasta - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - path blacklist - - output: - tuple val(meta), path('gridss_assemble/'), emit: assemble_dir - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - def output_dirname = 'gridss_assemble' - def labels_arg = labels.join(',') - // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below - def bams_list = bams instanceof List ? bams : [bams] - def bams_arg = "--bams ${bams_list.join(',')}" - def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] - def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" - - """ - # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation - # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present - shadow_input_directory() { - src=\${1} - dst="${output_dirname}/work/\${src##*/}" - for filepath_src in \$(find -L \${src} ! -type d); do - # Get destination location for symlink - filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) - filepath_dst=\${dst%/}/\${filepath_src_rel} - # Create directory for symlink - mkdir -p \${filepath_dst%/*}; - # Get path for symlink source file, then create it - # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only - # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers - symlinkpath=\$(realpath \${filepath_src}) - ln -s \${symlinkpath} \${filepath_dst}; - done - if [[ -L "\${src##*/}" ]]; then - rm "\${src}" - fi - } - for preprocess_dir in ${preprocess_dirs}; do - shadow_input_directory \${preprocess_dir}; - done - - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - - # Run - gridss_svprep \\ - ${args} \\ - --jvmheap ${task.memory.giga}g \\ - --jar ${task.ext.jarPath} \\ - --steps assemble \\ - --labels ${labels_arg} \\ - --reference ${genome_fasta} \\ - --blacklist ${blacklist} \\ - --workingdir ${output_dirname}/work \\ - --assembly ${output_dirname}/sv_assemblies.bam \\ - --threads ${task.cpus} \\ - ${config_arg} \\ - ${bams_arg} \\ - ${bams_filtered_arg} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ - - stub: - """ - mkdir -p gridss_assemble/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/svprep/assets/gridss.svprep b/modules/local/svprep/assets/gridss.svprep deleted file mode 100644 index d1b1f3e8..00000000 --- a/modules/local/svprep/assets/gridss.svprep +++ /dev/null @@ -1,825 +0,0 @@ -#!/bin/bash -# GRIDSS execution script using SvPrep BAMs - -getopt --test -if [[ ${PIPESTATUS[0]} -ne 4 ]]; then - echo 'WARNING: "getopt --test"` failed in this environment.' 1>&2 - echo "WARNING: The version of getopt(1) installed on this system might not be compatible with the GRIDSS driver script." 1>&2 -fi -unset DISPLAY # Prevents errors attempting to connecting to an X server when starting the R plotting device -ulimit -n $(ulimit -Hn 2>/dev/null) 2>/dev/null # Reduce likelihood of running out of open file handles -set -o errexit -o pipefail -o noclobber -o nounset -last_command="" -current_command="" -trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG -trap 'echo "\"${last_command}\" command completed with exit code $?."' EXIT -#253 forcing C locale for everything -export LC_ALL=C - -EX_USAGE=64 -EX_NOINPUT=66 -EX_CANTCREAT=73 -EX_CONFIG=78 - -workingdir="." -reference="" -output_vcf="" -assembly="" -threads=8 -jvmheap="30g" -otherjvmheap="4g" -blacklist="" -metricsrecords=10000000 -maxcoverage=50000 -config_file="" -labels="" -bams="" -filtered_bams="" -full_bams="" -keepTempFiles="false" - -steps="all" -do_preprocess=false -do_assemble=false -do_call=false - -USAGE_MESSAGE=" -Usage: gridss [options] -r -o -a input1.bam [input2.bam [...]] - - -r/--reference: reference genome to use. - -o/--output: output VCF. - -a/--assembly: location of the GRIDSS assembly BAM. This file will be - created by GRIDSS. - -t/--threads: number of threads to use. (Default: $threads) - -j/--jar: location of GRIDSS jar - -w/--workingdir: directory to place GRIDSS intermediate and temporary files - .gridss.working subdirectories will be created. (Default: $workingdir) - -s/--steps: processing steps to run. Defaults to all steps. - Multiple steps are specified using comma separators. Possible steps are: - preprocess, assemble, call, all - -e/--blacklist: BED file containing regions to ignore - -c/--configuration: configuration file use to override default GRIDSS - settings. - -l/--labels: comma separated labels to use in the output VCF for the input - files. Supporting read counts for input files with the same label are - aggregated (useful for multiple sequencing runs of the same sample). - Labels default to input filenames, unless a single read group with a - non-empty sample name exists in which case the read group sample name - is used (which can be disabled by \"useReadGroupSampleNameCategoryLabel=false\" - in the configuration file). If labels are specified, they must be - specified for all input files. - -b/bams: comma separated full-path BAM files - -f/filtered_bams: comma separated full-path filtered BAM files - --jvmheap: size of JVM heap for the high-memory component of assembly and variant calling. (Default: $jvmheap) - " - -OPTIONS=r:o:a:t:j:w:e:s:c:l:b:f: -LONGOPTS=reference:,output:,assembly:,threads:,jar:,workingdir:,jvmheap:,blacklist:,steps:,configuration:,labels:,bams:,filtered_bams: -! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") -if [[ ${PIPESTATUS[0]} -ne 0 ]]; then - # e.g. return value is 1 - # then getopt has complained about wrong arguments to stdout - echo "$USAGE_MESSAGE" 1>&2 - exit $EX_USAGE -fi -eval set -- "$PARSED" - -POSITIONAL_ARGS=() - -#while true; do -while [[ $# -gt 0 ]]; do - case "$1" in - -r|--reference) - reference="$2" - shift 2 - ;; - -l|--labels) - labels="$2" - shift 2 - ;; - -b|--bams) - bams="$2" - shift 2 - ;; - -f|--filtered_bams) - filtered_bams="$2" - shift 2 - ;; - -s|--steps) - steps="$2" - shift 2 - ;; - -w|--workingdir) - workingdir="$2" - shift 2 - ;; - -o|--output) - output_vcf="$2" - shift 2 - ;; - -a|--assembly) - if [[ "$assembly" == "" ]] ; then - assembly="$2" - else - assembly="$assembly $2" - fi - # TODO: support multiple assembly files - shift 2 - ;; - -e|--blacklist) - blacklist="$2" - shift 2 - ;; - -j|--jar) - GRIDSS_JAR="$2" - shift 2 - ;; - --jvmheap) - jvmheap="$2" - shift 2 - ;; - -t|--threads) - printf -v threads '%d\n' "$2" 2>/dev/null - printf -v threads '%d' "$2" 2>/dev/null - shift 2 - ;; - -c|--configuration) - config_file=$2 - shift 2 - ;; - *) - POSITIONAL_ARGS+=("$1") # save positional arg - # echo "Unparsed param" - shift - ;; - esac -done - -##### --workingdir -echo "Using working directory \"$workingdir\"" 1>&2 -if [[ "$workingdir" == "" ]] ; then - echo "$USAGE_MESSAGE" 1>&2 - echo "Working directory must be specified. Specify using the --workingdir command line argument" 1>&2 - exit $EX_USAGE -fi -if [[ "$(tr -d ' \n' <<< "$workingdir")" != "$workingdir" ]] ; then - echo "workingdir cannot contain whitespace" 1>&2 - exit $EX_USAGE - fi -if [[ ! -d $workingdir ]] ; then - mkdir -p $workingdir - if [[ ! -d $workingdir ]] ; then - echo Unable to create working directory $workingdir 1>&2 - exit $EX_CANTCREAT - fi -fi -workingdir=$(dirname $workingdir/placeholder) -timestamp=$(date +%Y%m%d_%H%M%S) -# Logging -logfile=$workingdir/gridss.full.$timestamp.$HOSTNAME.$$.log -# $1 is message to write -write_status() { - echo "$(date): $1" | tee -a $logfile 1>&2 -} -write_status "Full log file is: $logfile" -trap 'echo "\"${last_command}\" command completed with exit code $?. -***** -The underlying error message can be found in $logfile -*****"' EXIT -# Timing instrumentation -timinglogfile=$workingdir/gridss.timing.$timestamp.$HOSTNAME.$$.log -if which /usr/bin/time >/dev/null ; then - timecmd="/usr/bin/time" - write_status "Found /usr/bin/time" -else - timecmd="" - write_status "Not found /usr/bin/time" -fi -if [[ "$timecmd" != "" ]] ; then - timecmd="/usr/bin/time --verbose -a -o $timinglogfile" - if ! $timecmd echo 2>&1 > /dev/null; then - timecmd="/usr/bin/time -a -o $timinglogfile" - fi - if ! $timecmd echo 2>&1 > /dev/null ; then - timecmd="" - write_status "Unexpected /usr/bin/time version. Not logging timing information." - fi - # We don't need timing info of the echo - rm -f $timinglogfile -fi - -### Find the jars -find_jar() { - env_name=$1 - if [[ -f "${!env_name:-}" ]] ; then - echo "${!env_name}" - else - write_status "Unable to find $2 jar. Specify using the environment variant $env_name, or the --jar command line parameter." - exit $EX_NOINPUT - fi -} -gridss_jar=$(find_jar GRIDSS_JAR gridss) -write_status "Using GRIDSS jar $gridss_jar" - -# Check all key inputs: - -if [[ "$labels" == "" ]] ; then - write_status "Labels must be specified" - exit $EX_USAGE -fi - -if [[ "$bams" == "" ]] ; then - write_status "Full BAMs must be specified" - exit $EX_USAGE -fi - -if [[ "$filtered_bams" == "" ]] ; then - write_status "Filtered BAMs must be specified" - exit $EX_USAGE -fi - -##### --reference -if [[ "$reference" == "" ]] ; then - write_status "$USAGE_MESSAGE" - write_status "Reference genome must be specified. Specify using the --reference command line argument" - exit $EX_USAGE -fi - -if [ ! -f $reference ] ; then - write_status "$USAGE_MESSAGE" - write_status "Missing reference genome $reference. Specify reference location using the --reference command line argument" - exit $EX_USAGE -fi -write_status "Using reference genome \"$reference\"" - -##### --output -if [[ $do_call == "true" ]] ; then - if [[ "$output_vcf" == "" ]] ; then - write_status "$USAGE_MESSAGE" - write_status "Output VCF not specified. Use --output to specify output file." - exit $EX_USAGE - fi - mkdir -p $(dirname $output_vcf) - if [[ ! -d $(dirname $output_vcf) ]] ; then - write_status "Unable to create directory for $output_vcf for output VCF." - exit $EX_CANTCREAT - fi - write_status "Using output VCF $output_vcf" -fi -write_status "Using output VCF $output_vcf" - -##### --assembly -if [[ $do_assemble == "true" ]] || [[ $do_call == "true" ]]; then - if [[ "$assembly" == "" ]] ; then - if [[ "$output_vcf" == "" ]] ; then - write_status "Either the assembly output file must explicitly specified with -a, or the output VCF specified with -o" - exit $EX_USAGE - fi - assembly=$output_vcf.assembly.bam - fi - write_status "Using assembly bam $assembly" - if [[ $do_assemble == "true" ]] ; then - mkdir -p $(dirname $assembly) - if [[ ! -d $(dirname $assembly) ]] ; then - write_status "Unable to parent create directory for $assembly" - exit $EX_CANTCREAT - fi - else - if [[ ! -f $assembly ]] ; then - write_status "Missing assembly file $assembly" - write_status "Ensure the GRIDSS assembly step has been run" - exit $EX_NOINPUT - fi - fi -fi - -##### --threads -if [[ "$threads" -lt 1 ]] ; then - write_status "$USAGE_MESSAGE" - write_status "Illegal thread count: $threads. Specify an integer thread count using the --threads command line argument" - exit $EX_USAGE -fi -if [[ "$threads" -gt 8 ]] ; then - write_status "WARNING: GRIDSS scales sub-linearly at high thread count. Up to 8 threads is the recommended level of parallelism." -fi -write_status "Using $threads worker threads." - -if [[ "$blacklist" == "" ]] ; then - blacklist_arg="" - write_status "Using no blacklist bed. The encode DAC blacklist is recommended for hg19." -elif [[ ! -f $blacklist ]] ; then - write_status "$USAGE_MESSAGE" - write_status "Missing blacklist file $blacklist" - exit $EX_NOINPUT -else - blacklist_arg="BLACKLIST=$blacklist" - write_status "Using blacklist $blacklist" - if [[ "$(tr -d ' \n' <<< "$blacklist_arg")" != "$blacklist_arg" ]] ; then - write_status "blacklist cannot contain whitespace" - exit $EX_USAGE - fi -fi - -if [[ "$jvmheap" == "" ]] ; then - if [[ $threads -gt 8 ]] ; then - write_status "Warning: GRIDSS assembly may stall and run out of memory. with $threads and $jvmheap heap size." - fi -fi - -write_status "Using JVM maximum heap size of $jvmheap for assembly and variant calling." - -config_args="" -if [[ "$config_file" != "" ]] ; then - if [[ ! -f $config_file ]] ; then - write_status "Configuration file $config_file does not exist" - exit $EX_NOINPUT - fi - config_args="CONFIGURATION_FILE=$config_file" -fi - -input_args="" -input_filtered_args="" - -# no longer read in the BAM file list from the end of the arguments list - -nows_labels=$(tr -d ' \n' <<< "$labels") -if [[ "$nows_labels" != "$labels" ]] ; then - write_status "input labels cannot contain whitespace" - exit $EX_USAGE -fi -IFS=',' read -ra LABEL_ARRAY <<< "$nows_labels" -label_count=${#LABEL_ARRAY[@]} - -for label in "${LABEL_ARRAY[@]}" ; do - input_args="$input_args INPUT_LABEL=$label" - input_filtered_args="$input_filtered_args INPUT_LABEL=$label" - #write_status "label is $label" -done - -nows_bams=$(tr -d ' \n' <<< "$bams") -if [[ "$nows_bams" != "$bams" ]] ; then - write_status "input filtered BAMs cannot contain whitespace" - exit $EX_USAGE -fi -IFS=',' read -ra BAM_ARRAY <<< "$nows_bams" -for bam_file in "${BAM_ARRAY[@]}" ; do - - if [[ "$(basename $bam_file)" == "$(basename $assembly)" ]] ; then - write_status "assembly and input filtered bam files must have different filenames" - exit $EX_USAGE - fi - - input_args="$input_args INPUT=$bam_file" - # write_status "full bam file is $bam_file" -done - -nows_bams=$(tr -d ' \n' <<< "$filtered_bams") -if [[ "$nows_bams" != "$filtered_bams" ]] ; then - write_status "input filtered BAMs cannot contain whitespace" - exit $EX_USAGE -fi -IFS=',' read -ra FILT_BAM_ARRAY <<< "$nows_bams" -for filtered_bam_file in "${FILT_BAM_ARRAY[@]}" ; do - - if [[ "$(basename $filtered_bam_file)" == "$(basename $assembly)" ]] ; then - write_status "assembly and input filtered bam files must have different filenames" - exit $EX_USAGE - fi - - input_filtered_args="$input_filtered_args INPUT=$filtered_bam_file" - # write_status "filtered bam file is $filtered_bam_file" -done - -for (( i=0; i < $label_count; ++i )) -do - write_status "Label $i: name=${LABEL_ARRAY[$i]} full-bam=${BAM_ARRAY[$i]} filtered-bam=${FILT_BAM_ARRAY[$i]}" -done - -write_status "Full BAM args: $input_args" -write_status "Filtered BAM args: $input_filtered_args" - - -# Validate tools exist on path -for tool in Rscript samtools java bwa ; do #minimap2 - if ! which $tool >/dev/null; then - write_status "Error: unable to find $tool on \$PATH" - exit $EX_CONFIG - fi - write_status "Found $(which $tool)" -done -if $(samtools --version-only >/dev/null) ; then - write_status "samtools version: $(samtools --version-only 2>&1)" -else - write_status "Your samtools version does not support --version-only. Update samtools." - exit $EX_CONFIG -fi -if [[ "$(samtools --version-only)" =~ ^([0-9]+)[.]([0-9]+) ]] ; then - samtools_major_version=${BASH_REMATCH[1]} - samtools_minor_version=${BASH_REMATCH[2]} - if [[ "$samtools_major_version" -le 1 ]] && [[ "$samtools_minor_version" -lt 10 ]] ; then - write_status "samtools 1.13 or later is required." - exit $EX_CONFIG - fi -else - write_status "Unable to determine samtools version" - exit $EX_CONFIG -fi - -# write_status "R version: $(Rscript --version 2>&1)" - -write_status "bwa $(bwa 2>&1 | grep Version || echo -n)" - -if [[ "$timecmd" != "" ]] ; then - if which /usr/bin/time >/dev/null ; then - write_status "time version: $(/usr/bin/time --version 2>&1)" - fi -fi -write_status "bash version: $(/bin/bash --version 2>&1 | head -1)" - -# check java version is ok using the gridss.Echo entry point -if java -cp $gridss_jar gridss.Echo ; then - write_status "java version: $(java -version 2>&1 | tr '\n' '\t')" -else - write_status "Unable to run GRIDSS jar - requires java 1.8 or later" - write_status "java version: $(java -version 2>&1)" - exit $EX_CONFIG -fi - -if ! java -Xms$jvmheap -cp $gridss_jar gridss.Echo ; then - write_status "Failure invoking java with --jvmheap parameter of \"$jvmheap\". Specify a JVM heap size (e.g. \"31g\") that is valid for this machine." - exit 1 -fi - -write_status "Max file handles: $(ulimit -n)" 1>&2 - -steps_message="Running GRIDSS steps:" - -for step in $(echo $steps | tr ',' ' ' ) ; do - if [[ "$step" == "all" ]] ; then - do_preprocess=true - do_assemble=true - do_call=true - steps_message="$steps_message all" - elif [[ "$step" == "preprocess" ]] ; then - do_preprocess=true - steps_message="$steps_message pre-process" - elif [[ "$step" == "assemble" ]] ; then - do_assemble=true - steps_message="$steps_message assembly" - elif [[ "$step" == "call" ]] ; then - do_call=true - steps_message="$steps_message call" - else - write_status "Unknown step \"$step\"" - exit $EX_USAGE - fi -done - -write_status "$steps_message" - -# don't keep files -if [[ $keepTempFiles == "true" ]] ; then - rmcmd="echo rm disabled:" - jvm_args="-Dgridss.keepTempFiles=true" -else - rmcmd="rm" - jvm_args="" -fi - -jvm_args="$jvm_args \ - -XX:ParallelGCThreads=$threads \ - -Dsamjdk.reference_fasta=$reference \ - -Dsamjdk.use_async_io_read_samtools=true \ - -Dsamjdk.use_async_io_write_samtools=true \ - -Dsamjdk.use_async_io_write_tribble=true \ - -Dsamjdk.buffer_size=4194304 \ - -Dsamjdk.async_io_read_threads=$threads" - -aligner_args=' - ALIGNER_COMMAND_LINE=null - ALIGNER_COMMAND_LINE=bwa - ALIGNER_COMMAND_LINE=mem - ALIGNER_COMMAND_LINE=-K - ALIGNER_COMMAND_LINE=10000000 - ALIGNER_COMMAND_LINE=-L - ALIGNER_COMMAND_LINE=0,0 - ALIGNER_COMMAND_LINE=-t - ALIGNER_COMMAND_LINE=%3$d - ALIGNER_COMMAND_LINE=%2$s - ALIGNER_COMMAND_LINE=%1$s' - -samtools_sort="samtools sort --no-PG -@ $threads" - -readpairing_args="READ_PAIR_CONCORDANT_PERCENT=null" - - -# set-up reference has been removed since can assume to exist - -#### -# Pre-process for each filtered BAM file -#### - -if [[ $do_preprocess == true ]] ; then - write_status "*** PRE-PROCESS ***" - - for (( i=0; i < $label_count; ++i )) - do - label=${LABEL_ARRAY[$i]} - bam_file=${FILT_BAM_ARRAY[$i]} - write_status "Processing: sample ${LABEL_ARRAY[$i]}, filtered-bam ${FILT_BAM_ARRAY[$i]}" - - dir=$workingdir/$(basename $bam_file).gridss.working - prefix=$dir/$(basename $bam_file) - write_status "Start pre-processing: $bam_file, working dir: $dir, prefix: $prefix" - - tmp_prefix=$workingdir/$(basename $bam_file).gridss.working/tmp.$(basename $bam_file) - mkdir -p $dir - if [[ ! -d $dir ]] ; then - write_status "Unable to create directory $dir" - exit $EX_CANTCREAT - fi - - name_sorted_bam=$tmp_prefix.namedsorted.bam - write_status "Creating name-sorted BAM from $bam_file, writing to $name_sorted_bam" - - $timecmd $samtools_sort -l 1 -n \ - -T $tmp_prefix.namedsorted-tmp \ - -Obam \ - -o ${name_sorted_bam} \ - ${bam_file} - - write_status "Running ComputeSamTags|samtools: $bam_file" - - rm -f $tmp_prefix.coordinate-tmp* - - { $timecmd java -Xmx$otherjvmheap $jvm_args \ - -cp $gridss_jar gridss.ComputeSamTags \ - TMP_DIR=$dir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - COMPRESSION_LEVEL=0 \ - I=$name_sorted_bam \ - O=/dev/stdout \ - WORKER_THREADS=$threads \ - ASSUME_SORTED=true \ - REMOVE_TAGS=aa \ - MODIFICATION_SUMMARY_FILE=$prefix.computesamtags.changes.tsv \ - | $timecmd $samtools_sort \ - -l 1 \ - -T $tmp_prefix.coordinate-tmp \ - -Obam \ - -o $tmp_prefix.coordinate.bam \ - /dev/stdin \ - ; } 1>&2 2>> $logfile - - write_status "Removing name-sorted bam: $tmp_prefix.namedsorted.bam" - $rmcmd $tmp_prefix.namedsorted.bam - - write_status "Running SoftClipsToSplitReads: sample $label, input: $tmp_prefix.coordinate.bam, output: $tmp_prefix.sc2sr.primary.sv.bam" - rm -f $tmp_prefix.sc2sr.suppsorted.sv-tmp* - { $timecmd java -Xmx$otherjvmheap $jvm_args \ - -Dsamjdk.create_index=false \ - -cp $gridss_jar gridss.SoftClipsToSplitReads \ - TMP_DIR=$workingdir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - I=$tmp_prefix.coordinate.bam \ - O=$tmp_prefix.sc2sr.primary.sv.bam \ - COMPRESSION_LEVEL=1 \ - OUTPUT_UNORDERED_RECORDS=$tmp_prefix.sc2sr.supp.sv.bam \ - WORKER_THREADS=$threads \ - $aligner_args \ - && $rmcmd $tmp_prefix.coordinate.bam \ - && $timecmd $samtools_sort \ - -l 1 \ - -T $tmp_prefix.sc2sr.suppsorted.sv-tmp \ - -Obam \ - -o $tmp_prefix.sc2sr.suppsorted.sv.bam \ - $tmp_prefix.sc2sr.supp.sv.bam \ - && $rmcmd $tmp_prefix.sc2sr.supp.sv.bam \ - && $rmcmd -f $prefix.sv.tmp.bam $prefix.sv.tmp.bam.bai \ - && $timecmd samtools merge \ - -c \ - -p \ - --write-index \ - -@ $threads \ - $prefix.sv.tmp.bam \ - $tmp_prefix.sc2sr.primary.sv.bam \ - $tmp_prefix.sc2sr.suppsorted.sv.bam \ - && $rmcmd $tmp_prefix.sc2sr.primary.sv.bam \ - && $rmcmd $tmp_prefix.sc2sr.suppsorted.sv.bam \ - && mv $prefix.sv.tmp.bam $prefix.sv.bam \ - && mv $prefix.sv.tmp.bam.csi $prefix.sv.bam.csi \ - ; } 1>&2 2>> $logfile - - write_status "Produced SV bam:: $prefix.sv.bam" - - # create metrics on the full BAM and then copy these over the metrics made from the filtered BAMs - full_bam_file=${BAM_ARRAY[$i]} - write_status "Running CollectGridssMetrics on $label full BAM $full_bam_file" - - # test_prefix=$prefix.cp - - { $timecmd java -Xmx$otherjvmheap $jvm_args \ - -cp $gridss_jar gridss.analysis.CollectGridssMetrics \ - REFERENCE_SEQUENCE=$reference \ - TMP_DIR=$dir \ - ASSUME_SORTED=true \ - I=$full_bam_file \ - O=$prefix \ - THRESHOLD_COVERAGE=$maxcoverage \ - FILE_EXTENSION=null \ - GRIDSS_PROGRAM=null \ - GRIDSS_PROGRAM=CollectCigarMetrics \ - GRIDSS_PROGRAM=CollectMapqMetrics \ - GRIDSS_PROGRAM=CollectTagMetrics \ - GRIDSS_PROGRAM=CollectIdsvMetrics \ - PROGRAM=null \ - PROGRAM=CollectInsertSizeMetrics \ - STOP_AFTER=$metricsrecords \ - ; } 1>&2 2>> $logfile - - write_status "Complete pre-processing sample: $label" - done - - write_status "*** PRE-PROCESS COMPLETE ***" -fi - -##### -# ASSEMBLY -#### - -assembly_args="ASSEMBLY=$assembly" - -if [[ $do_assemble == true ]] ; then - - write_status "*** ASSEMBLY ***" - write_status "Running AssembleBreakends: writing output to dir $assembly" - { $timecmd java -Xmx$jvmheap $jvm_args \ - -Dgridss.output_to_temp_file=true \ - -cp $gridss_jar gridss.AssembleBreakends \ - JOB_INDEX=0 \ - JOB_NODES=1 \ - TMP_DIR=$workingdir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - WORKER_THREADS=$threads \ - $input_filtered_args \ - $blacklist_arg \ - $config_args \ - $readpairing_args \ - O=$assembly \ - ; } 1>&2 2>> $logfile - - write_status "AssemblyBreakends complete" - - dir=$workingdir/$(basename $assembly).gridss.working/ - prefix=$dir/$(basename $assembly) - tmp_prefix=$dir/tmp.$(basename $assembly) - - write_status "RunningSoftClipsToSplitReads: running on assembly output dir $assembly" - rm -f $tmp_prefix.sc2sr.suppsorted.sv-tmp* - { $timecmd java -Xmx$otherjvmheap $jvm_args \ - -Dgridss.async.buffersize=16 \ - -Dsamjdk.create_index=false \ - -Dgridss.output_to_temp_file=true \ - -cp $gridss_jar gridss.SoftClipsToSplitReads \ - TMP_DIR=$dir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - WORKER_THREADS=$threads \ - I=$assembly \ - O=$tmp_prefix.sc2sr.primary.sv.bam \ - OUTPUT_UNORDERED_RECORDS=$tmp_prefix.sc2sr.supp.sv.bam \ - REALIGN_ENTIRE_READ=true \ - READJUST_PRIMARY_ALIGNMENT_POSITION=true \ - $aligner_args \ - && $timecmd $samtools_sort \ - -T $tmp_prefix.sc2sr.suppsorted.sv-tmp \ - -Obam \ - -o $tmp_prefix.sc2sr.suppsorted.sv.bam \ - $tmp_prefix.sc2sr.supp.sv.bam \ - && $rmcmd $tmp_prefix.sc2sr.supp.sv.bam \ - && $rmcmd -f $prefix.sv.tmp.bam $prefix.sv.tmp.bam.bai \ - && $timecmd samtools merge \ - -c \ - -p \ - -@ $threads \ - $prefix.sv.tmp.bam \ - $tmp_prefix.sc2sr.primary.sv.bam \ - $tmp_prefix.sc2sr.suppsorted.sv.bam \ - && $timecmd samtools index $prefix.sv.tmp.bam \ - && $rmcmd $tmp_prefix.sc2sr.primary.sv.bam \ - && $rmcmd $tmp_prefix.sc2sr.suppsorted.sv.bam \ - && mv $prefix.sv.tmp.bam $prefix.sv.bam \ - && mv $prefix.sv.tmp.bam.bai $prefix.sv.bam.bai \ - ; } 1>&2 2>> $logfile - - write_status "Produced assembly BAM: $prefix.sv.bam" - - write_status "Complete Assembly" - - # no idea why this is a for loop, could just be: ASSEMBLY=$assembly - #assembly_args="" - #for ass in $assembly ; do - # assembly_args="$assembly_args ASSEMBLY=$ass" - #done - write_status "Assembly args: $assembly_args" - - write_status "*** ASSEMBLY COMPLETE ***" -fi - -#### -# VARIANT CALLING -#### - -if [[ $do_call == true ]] ; then - write_status "*** VARIANT CALLING ***" - - write_status "Creating variant VCF: $output_vcf" - - dir=$workingdir/$(basename $output_vcf).gridss.working - prefix=$dir/$(basename $output_vcf) - mkdir -p $dir - if [[ ! -d $dir ]] ; then - write_status "Unable to create directory $dir" - exit $EX_CANTCREAT - fi - - # create symbolic links to the full BAM as though they were produced by the pre-process step - # eg: ./gridss_02/COLO829R.bam.gridss.working/COLO829R.bam.sv.bam - for (( i=0; i < $label_count; ++i )) - do - bam_file=${BAM_ARRAY[$i]} - bam_dir=$workingdir/$(basename $bam_file).gridss.working - - if [[ ! -d $bam_dir ]] ; then - mkdir -p $bam_dir - fi - - sv_bam_file=$bam_dir/$(basename $bam_file).sv.bam - # write_status "Making soft-link to ${sv_bam_file}" - #ln -sfr ${bam_file} ${sv_bam_file} - #ln -sfr ${bam_file}.bai ${sv_bam_file}.bai - done - - write_status "Running IdentifyVariants" - { $timecmd java -Xmx$jvmheap $jvm_args \ - -Dgridss.output_to_temp_file=true \ - -cp $gridss_jar gridss.IdentifyVariants \ - TMP_DIR=$workingdir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - WORKER_THREADS=$threads \ - $input_filtered_args \ - $blacklist_arg \ - $config_args \ - $assembly_args \ - OUTPUT_VCF=$prefix.unallocated.vcf \ - $readpairing_args \ - ; } 1>&2 2>> $logfile - write_status "IdentifyVariants complete, produced $prefix.unallocated.vcf" - - write_status "Running AnnotateVariants" - { $timecmd java -Xmx$jvmheap $jvm_args \ - -Dgridss.output_to_temp_file=true \ - -Dgridss.async.buffersize=2048 \ - -cp $gridss_jar gridss.AnnotateVariants \ - TMP_DIR=$workingdir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - WORKER_THREADS=$threads \ - $input_filtered_args \ - $blacklist_arg \ - $config_args \ - $assembly_args \ - INPUT_VCF=$prefix.unallocated.vcf \ - OUTPUT_VCF=$prefix.allocated.vcf \ - $readpairing_args \ - ; } 1>&2 2>> $logfile - $rmcmd $prefix.unallocated.vcf - write_status "AnnotateVariants complete, produced $prefix.allocated.vcf" - - write_status "Running AnnotateInsertedSequence" - - { $timecmd java -Xmx$otherjvmheap $jvm_args \ - -Dgridss.output_to_temp_file=true \ - -cp $gridss_jar gridss.AnnotateInsertedSequence \ - TMP_DIR=$workingdir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - WORKER_THREADS=$threads \ - INPUT=$prefix.allocated.vcf \ - OUTPUT=$output_vcf \ - && $rmcmd $prefix.allocated.vcf \ - ; } 1>&2 2>> $logfile - write_status "AnnotateInsertedSequence complete, produced $output_vcf" - - write_status "*** VARIANT CALLING COMPLETE ***" -fi - -if [[ -f $logfile ]] ; then - write_status "Run complete with $(grep WARNING $logfile | wc -l) warnings and $(grep ERROR $logfile | wc -l) errors." -fi -trap - EXIT -exit 0 # success! diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf deleted file mode 100644 index aa7e8bc9..00000000 --- a/modules/local/svprep/call/main.nf +++ /dev/null @@ -1,97 +0,0 @@ -process CALL { - tag "${meta.id}" - label 'process_medium' - - container 'docker.io/scwatts/svprep:1.1--0' - - input: - tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) - path gridss_config - path genome_fasta - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - path blacklist - - output: - tuple val(meta), path('gridss_call/sv.svprep.gridss.vcf.gz'), emit: vcf - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - def output_dirname = 'gridss_call' - def labels_arg = labels.join(',') - // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below - def bams_list = bams instanceof List ? bams : [bams] - def bams_arg = "--bams ${bams_list.join(',')}" - def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] - def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" - - """ - # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation - # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present - shadow_input_directory() { - src=\${1} - dst="${output_dirname}/" - for filepath_src in \$(find -L \${src} ! -type d); do - # Get destination location for symlink - filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) - filepath_dst=\${dst%/}/\${filepath_src_rel} - # Create directory for symlink - mkdir -p \${filepath_dst%/*}; - # Get path for symlink source file, then create it - # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only - # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers - symlinkpath=\$(realpath \${filepath_src}) - ln -s \${symlinkpath} \${filepath_dst}; - done - if [[ -L "\${src##*/}" ]]; then - rm "\${src}" - fi - } - shadow_input_directory ${assemble_dir} - - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - - # Run - gridss_svprep \\ - ${args} \\ - --jvmheap ${task.memory.giga}g \\ - --jar ${task.ext.jarPath} \\ - --steps call \\ - --labels ${labels_arg} \\ - --reference ${genome_fasta} \\ - --blacklist ${blacklist} \\ - --workingdir ${output_dirname}/work/ \\ - --assembly ${output_dirname}/sv_assemblies.bam \\ - --output ${output_dirname}/sv.svprep.gridss.vcf.gz \\ - --threads ${task.cpus} \\ - ${config_arg} \\ - ${bams_arg} \\ - ${bams_filtered_arg} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ - - stub: - """ - mkdir -p gridss_call/ - cat < gridss_call/sv.svprep.gridss.vcf.gz - ##fileformat=VCFv4.1 - ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . - EOF - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf deleted file mode 100644 index 06f267bf..00000000 --- a/modules/local/svprep/depth_annotator/main.nf +++ /dev/null @@ -1,50 +0,0 @@ -process DEPTH_ANNOTATOR { - tag "${meta.id}" - label 'process_medium' - - container 'docker.io/scwatts/svprep:1.1--0' - - input: - tuple val(meta), path(bams), path(bais), path(vcf), val(labels) - path genome_fasta - val genome_ver - - output: - tuple val(meta), path("*.vcf.gz"), emit: vcf - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def labels_arg = labels.join(',') - // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below - def bams_list = bams instanceof List ? bams : [bams] - def bams_arg = "${bams_list.join(',')}" - - """ - java \\ - -Xmx${task.memory.giga}g \\ - -cp ${task.ext.jarPath} com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ - ${args} \\ - -input_vcf ${vcf} \\ - -output_vcf sv.svprep.gridss.depths.vcf.gz \\ - -samples ${labels_arg} \\ - -bam_files ${bams_arg} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -threads ${task.cpus} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - svprep: \$(java -jar ${task.ext.jarPath} 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') - END_VERSIONS - """ - - stub: - """ - touch sv_vcf.depths.vcf.gz - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf deleted file mode 100644 index bb388ead..00000000 --- a/modules/local/svprep/preprocess/main.nf +++ /dev/null @@ -1,57 +0,0 @@ -process PREPROCESS { - tag "${meta.id}" - label 'process_medium' - - container 'docker.io/scwatts/svprep:1.1--0' - - input: - tuple val(meta), path(bam), path(bam_filtered) - path gridss_config - path genome_fasta - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - - output: - tuple val(meta), path("gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/"), emit: preprocess_dir - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - - """ - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - - gridss_svprep \\ - ${args} \\ - --jvmheap ${task.memory.giga}g \\ - --jar ${task.ext.jarPath} \\ - --steps preprocess \\ - --reference ${genome_fasta} \\ - --workingdir gridss_preprocess/ \\ - --threads ${task.cpus} \\ - ${config_arg} \\ - --labels ${meta.id} \\ - --bams ${bam} \\ - --filtered_bams ${bam_filtered} \\ - --output placeholder - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ - - stub: - """ - mkdir -p gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf deleted file mode 100644 index 2068f3cd..00000000 --- a/modules/local/svprep/svprep/main.nf +++ /dev/null @@ -1,61 +0,0 @@ -process SVPREP { - tag "${meta.id}" - label 'process_medium' - - container 'docker.io/scwatts/svprep:1.1--0' - - input: - tuple val(meta), path(bam), path(bai), path(junctions) - path genome_fasta - val genome_ver - path sv_blacklist - path known_fusions - val write_types - val calc_fragment_length - - output: - tuple val(meta), path("*.sorted.bam") , emit: bam - tuple val(meta), path("*.sv_prep.junctions.csv"), emit: junctions - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def write_types_arg = write_types ? "-write_types \'${write_types}\'" : '' - def existing_juction_file_arg = junctions ? "-existing_junction_file ${junctions}" : "" - def calc_fragment_length_arg = calc_fragment_length ? "-calc_fragment_length" : "" - - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -sample ${meta.id} \\ - -bam_file ${bam} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -blacklist_bed ${sv_blacklist} \\ - -known_fusion_bed ${known_fusions} \\ - ${write_types_arg} \\ - ${existing_juction_file_arg} \\ - ${calc_fragment_length_arg} \\ - -threads ${task.cpus} \\ - -output_dir ./ - - samtools sort -O bam "${meta.id}.sv_prep.bam" -o "${meta.id}.sv_prep.sorted.bam" - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - sage: \$(java -jar ${task.ext.jarPath} 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') - END_VERSIONS - """ - - stub: - """ - touch "${meta.id}.sv_prep.sorted.bam" - touch "${meta.id}.sv_prep.junctions.csv" - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/nextflow_schema.json b/nextflow_schema.json index 8ee91c2c..072eeb44 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -175,13 +175,6 @@ "description": "Path to CUPPA reference file directory.", "fa_icon": "far fa-file-code" }, - "ref_data_sv_prep_blacklist": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed$", - "description": "Path to SV Prep blacklist file.", - "fa_icon": "far fa-file-code" - }, "ref_data_gridss_blacklist": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep.nf deleted file mode 100644 index cfa426fb..00000000 --- a/subworkflows/local/gridss_svprep.nf +++ /dev/null @@ -1,226 +0,0 @@ -// -// SV Prep is a BAM filter designed to select only reads relevant to SV events run prior to GRIDSS. -// GRIDSS is a software suite containing tools useful for the detection of genomic rearrangements. -// -import Constants - -include { ASSEMBLE as GRIDSS_ASSEMBLE } from '../../modules/local/svprep/assemble/main' -include { CALL as GRIDSS_CALL } from '../../modules/local/svprep/call/main' -include { PREPROCESS as GRIDSS_PREPROCESS } from '../../modules/local/svprep/preprocess/main' -include { SVPREP as SVPREP_NORMAL } from '../../modules/local/svprep/svprep/main' -include { SVPREP as SVPREP_TUMOR } from '../../modules/local/svprep/svprep/main' -include { DEPTH_ANNOTATOR as SVPREP_DEPTH_ANNOTATOR } from '../../modules/local/svprep/depth_annotator/main' - -workflow GRIDSS_SVPREP { - take: - ch_inputs // channel: [val(meta)] - gridss_config // file: /path/to/gridss_config (optional) - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_version // val: genome version - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_dict // file: /path/to/genome_dict - ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ - ref_data_genome_bwa_index_image // file: /path/to/genome_bwa_index_image - ref_data_genome_gridss_index // file: /path/to/genome_gridss_index - ref_data_gridss_blacklist // val: /path/to/gridss_blacklist - ref_data_sv_prep_blacklist // file: /path/to/sv_prep_blacklist - ref_data_known_fusions // file: /path/to/known_fusions - - main: - // Channel for version.yml files - ch_versions = Channel.empty() - - // Prepare tumor sample inputs - // channel: [val(meta_svprep), bam_tumor, bai_tumor, []] - ch_svprep_tumor_inputs = ch_inputs - .map { meta -> - def meta_svprep = [ - key: meta.id, - id: meta.get(['sample_name', Constants.DataType.TUMOR]), - sample_type: 'tumor', - ] - def bam_tumor = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) - return [meta_svprep, bam_tumor, "${bam_tumor}.bai", []] - } - - // Filter tumor BAM - SVPREP_TUMOR( - ch_svprep_tumor_inputs, - ref_data_genome_fasta, - ref_data_genome_version, - ref_data_sv_prep_blacklist, - ref_data_known_fusions, - 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument switch and value - false, // -calc_fragment_length argument switch - ) - ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) - - // Prepare normal sample inputs - // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] - ch_svprep_normal_inputs = WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs) - .map { meta, junctions_tumor -> - def meta_svprep = [ - key: meta.id, - id: meta.get(['sample_name', Constants.DataType.NORMAL]), - sample_type: 'normal', - ] - def bam_normal = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) - return [meta_svprep, bam_normal, "${bam_normal}.bai", junctions_tumor] - } - - SVPREP_NORMAL( - ch_svprep_normal_inputs, - ref_data_genome_fasta, - ref_data_genome_version, - ref_data_sv_prep_blacklist, - ref_data_known_fusions, - false, // -write_types argument switch and value - true, // -calc_fragment_length argument switch - ) - ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) - - // channel: [val(meta_gridss), bam_tumor, bam_tumor_filtered] - ch_preprocess_inputs_tumor = WorkflowOncoanalyser.groupByMeta( - SVPREP_TUMOR.out.bam, - ch_svprep_tumor_inputs, - ) - .map { meta_svprep, bam_filtered, bam, bai -> - return [meta_svprep, bam, bam_filtered] - } - - // channel: [val(meta_gridss), bam_normal, bam_normal_filtered] - ch_preprocess_inputs_normal = WorkflowOncoanalyser.groupByMeta( - SVPREP_NORMAL.out.bam, - ch_svprep_normal_inputs, - ) - .map { meta_svprep, bam_filtered, bam, bai, junctions -> - return [meta_svprep, bam, bam_filtered] - } - - // channel: [val(meta_gridss), bam, bam_filtered] - ch_preprocess_inputs = Channel.empty() - .mix( - ch_preprocess_inputs_tumor, - ch_preprocess_inputs_normal, - ) - - // Preprocess reads - GRIDSS_PREPROCESS( - ch_preprocess_inputs, - gridss_config, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ) - ch_versions = ch_versions.mix(GRIDSS_PREPROCESS.out.versions) - - // Gather BAMs and outputs from preprocessing for each tumor/normal set - // channel: [key, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] - ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( - ch_preprocess_inputs, - GRIDSS_PREPROCESS.out.preprocess_dir, - ) - .map { [it[0].key, it] } - .groupTuple(size: 2) - - // Order and organise inputs for assembly - // channel: [val(meta_gridss), [bams], [bams_filtered], [preprocess_dirs], [labels]] - ch_assemble_inputs = ch_bams_and_preprocess - .map { key, entries -> - def (tmeta, tbam, tbam_filtered, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } - def (nmeta, nbam, nbam_filtered, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } - def meta_gridss = [id: tmeta.key] - return [ - meta_gridss, - [nbam, tbam], - [nbam_filtered, tbam_filtered], - [npreprocess, tpreprocess], - [nmeta.id, tmeta.id], - ] - } - - // Assemble variants - GRIDSS_ASSEMBLE( - ch_assemble_inputs, - gridss_config, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ) - ch_versions = ch_versions.mix(GRIDSS_ASSEMBLE.out.versions) - - // Prepare inputs for variant calling - // channel: [val(meta_gridss), [bams], [bams_filtered], assemble_dir, [labels]] - ch_call_inputs = WorkflowOncoanalyser.groupByMeta( - ch_assemble_inputs, - GRIDSS_ASSEMBLE.out.assemble_dir, - flatten: false, - ) - .map { data -> - def meta = data[0] - def (bams, bams_filtered, preprocess_dirs, labels) = data[1] - def (assemble_dir) = data[2] - return [meta, bams, bams_filtered, assemble_dir, labels] - } - - // Call variants - GRIDSS_CALL( - ch_call_inputs, - gridss_config, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ) - ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) - - // Prepare inputs for depth annotation, restore original meta - // channel: [val(meta_svprep), [bams], [bais], vcf, [labels]] - ch_depth_inputs = WorkflowOncoanalyser.groupByMeta( - ch_inputs.map { meta -> [meta.id, meta] }, - GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, - ) - .map { id, meta, vcf -> - def tbam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) - def nbam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) - def meta_svprep = [id: meta.id] - return [ - meta_svprep, - [nbam, tbam], - ["${nbam}.bai", "${tbam}.bai"], - vcf, - [meta.get(['sample_name', Constants.DataType.NORMAL]), meta.get(['sample_name', Constants.DataType.TUMOR])], - ] - } - - // Add depth annotations to SVs - SVPREP_DEPTH_ANNOTATOR( - ch_depth_inputs, - ref_data_genome_fasta, - ref_data_genome_version, - ) - - // Reunite final VCF with the corresponding input meta object - ch_out = Channel.empty() - .concat( - ch_inputs.map { meta -> [meta.id, meta] }, - SVPREP_DEPTH_ANNOTATOR.out.vcf.map { meta, vcf -> [meta.id, vcf] }, - ) - .groupTuple(size: 2) - .map { id, other -> other.flatten() } - - emit: - results = ch_out // channel: [val(meta), vcf] - - versions = ch_versions // channel: [versions.yml] -} diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index d36634a5..dcbaf9be 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -145,8 +145,6 @@ def createHmfDataMap(hmf_bundle_dir, params_only) { 'cobalt_gc_profile': getHmfDataFileObject('ref_data_cobalt_gc_profile', 'COBALT_GC_PROFILE', hmf_bundle_dir, params_only), // CUPPA 'cuppa': getHmfDataFileObject('ref_data_cuppa', 'CUPPA', hmf_bundle_dir, params_only), - // SVPREP - 'sv_prep_blacklist': getHmfDataFileObject('ref_data_sv_prep_blacklist', 'SV_PREP_BLACKLIST', hmf_bundle_dir, params_only), // GRIDSS, GRIPSS 'gridss_blacklist': getHmfDataFileObject('ref_data_gridss_blacklist', 'GRIDSS_BLACKLIST', hmf_bundle_dir, params_only), 'gridss_breakend_pon': getHmfDataFileObject('ref_data_gridss_breakend_pon', 'GRIDSS_BREAKEND_PON', hmf_bundle_dir, params_only), diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 68428edf..c7976172 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -73,7 +73,6 @@ include { VIRUSINTERPRETER } from '../modules/local/virusinterpreter/main' // SUBWORKFLOWS // include { GRIDSS } from '../subworkflows/local/gridss' -include { GRIDSS_SVPREP } from '../subworkflows/local/gridss_svprep' include { GRIPSS } from '../subworkflows/local/gripss' include { LILAC } from '../subworkflows/local/lilac' include { LINX } from '../subworkflows/local/linx' @@ -326,44 +325,25 @@ workflow ONCOANALYSER { // channel: [val(meta), gridss_vcf] ch_gridss_out = Channel.empty() if (run.gridss) { - if (run.svprep) { - GRIDSS_SVPREP( - ch_inputs, - gridss_config, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_version, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_bwa_index, - PREPARE_REFERENCE.out.genome_bwa_index_image, - PREPARE_REFERENCE.out.genome_gridss_index, - hmf_data.gridss_blacklist, - hmf_data.sv_prep_blacklist, - hmf_data.known_fusions, - ) - ch_versions = ch_versions.mix(GRIDSS_SVPREP.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP.out.results) - } else { - ch_gridss_inputs = ch_inputs - .map { meta -> - def tumor_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) - def normal_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) - [meta, tumor_bam, normal_bam] - } - GRIDSS( - ch_gridss_inputs, - gridss_config, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_bwa_index, - PREPARE_REFERENCE.out.genome_bwa_index_image, - PREPARE_REFERENCE.out.genome_gridss_index, - hmf_data.gridss_blacklist, - ) - ch_versions = ch_versions.mix(GRIDSS.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS.out.results) - } + ch_gridss_inputs = ch_inputs + .map { meta -> + def tumor_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) + def normal_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) + [meta, tumor_bam, normal_bam] + } + GRIDSS( + ch_gridss_inputs, + gridss_config, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_bwa_index, + PREPARE_REFERENCE.out.genome_bwa_index_image, + PREPARE_REFERENCE.out.genome_gridss_index, + hmf_data.gridss_blacklist, + ) + ch_versions = ch_versions.mix(GRIDSS.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS.out.results) } // From 55beb93070ae9593cfee699a2c0d679be3f7977e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 10:17:40 +1100 Subject: [PATCH 036/562] Remove RepeatMasker file previously used in GRIPSS --- lib/Constants.groovy | 1 - modules/local/gripss/germline/main.nf | 3 --- modules/local/gripss/somatic/main.nf | 3 --- nextflow_schema.json | 7 ------- subworkflows/local/gripss.nf | 3 --- subworkflows/local/prepare_reference.nf | 1 - workflows/oncoanalyser.nf | 1 - 7 files changed, 19 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 37ddea03..1c5afe8d 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -68,7 +68,6 @@ class Constants { GRIDSS_BLACKLIST: 'gridss/ENCFF356LFX.bed.gz', GRIDSS_BREAKEND_PON: 'gridss/gridss_pon_single_breakend.bed.gz', GRIDSS_BREAKPOINT_PON: 'gridss/gridss_pon_breakpoint.bedpe.gz', - REPEAT_MASKER_FILE: 'gridss/repeat_masker.fa.out.gz', ISOFOX_EXP_COUNTS: 'isofox/read_151_exp_counts.csv', ISOFOX_EXP_GC_RATIOS: 'isofox/read_100_exp_gc_ratios.csv', LINX_FRAGILE_SITES: 'linx/fragile_sites_hmf.csv', diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index a6203d4c..fbbc1797 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -12,7 +12,6 @@ process GRIPSS_GERMLINE { path breakend_pon path breakpoint_pon path known_fusions - path repeat_mask_file output: tuple val(meta), path('*.gripss.filtered.vcf.gz'), path('*.gripss.filtered.vcf.gz.tbi'), emit: vcf_hard @@ -24,7 +23,6 @@ process GRIPSS_GERMLINE { script: def args = task.ext.args ?: '' - def repeat_mask_file_arg = repeat_mask_file ? "-repeat_mask_file ${repeat_mask_file}" : '' """ java \\ @@ -38,7 +36,6 @@ process GRIPSS_GERMLINE { -pon_sv_file ${breakpoint_pon} \\ -known_hotspot_file ${known_fusions} \\ -vcf ${gridss_vcf} \\ - ${repeat_mask_file_arg} \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index 1f5f16e7..129280b9 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -12,7 +12,6 @@ process GRIPSS_SOMATIC { path breakend_pon path breakpoint_pon path known_fusions - path repeat_mask_file output: tuple val(meta), path('*.gripss.filtered.vcf.gz'), path('*.gripss.filtered.vcf.gz.tbi'), emit: vcf_hard @@ -24,7 +23,6 @@ process GRIPSS_SOMATIC { script: def args = task.ext.args ?: '' - def repeat_mask_file_arg = repeat_mask_file ? "-repeat_mask_file ${repeat_mask_file}" : '' """ java \\ @@ -39,7 +37,6 @@ process GRIPSS_SOMATIC { -pon_sv_file ${breakpoint_pon} \\ -known_hotspot_file ${known_fusions} \\ -vcf ${gridss_vcf} \\ - ${repeat_mask_file_arg} \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information diff --git a/nextflow_schema.json b/nextflow_schema.json index 072eeb44..6dc55bdb 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -196,13 +196,6 @@ "description": "Path to GRIDSS breakpoint PON file.", "fa_icon": "far fa-file-code" }, - "ref_data_repeat_masker_file": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.fa(\\.out)?\\.gz$", - "description": "Path to RepeatMasker file.", - "fa_icon": "far fa-file-code" - }, "ref_data_isofox_exp_counts": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/gripss.nf b/subworkflows/local/gripss.nf index dd4e8426..1166be98 100644 --- a/subworkflows/local/gripss.nf +++ b/subworkflows/local/gripss.nf @@ -14,7 +14,6 @@ workflow GRIPSS { breakend_pon // file: /path/to/breakend_pon breakpoint_pon // file: /path/to/breakpoint_pon known_fusions // file: /path/to/known_fusions - repeat_masker_file // file: /path/to/repeat_masker_file main: // Channel for version.yml files @@ -29,7 +28,6 @@ workflow GRIPSS { breakend_pon, breakpoint_pon, known_fusions, - repeat_masker_file, ) ch_versions = ch_versions.mix(GRIPSS_GERMLINE.out.versions) @@ -42,7 +40,6 @@ workflow GRIPSS { breakend_pon, breakpoint_pon, known_fusions, - repeat_masker_file, ) ch_versions = ch_versions.mix(GRIPSS_SOMATIC.out.versions) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index dcbaf9be..f65ee6ae 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -149,7 +149,6 @@ def createHmfDataMap(hmf_bundle_dir, params_only) { 'gridss_blacklist': getHmfDataFileObject('ref_data_gridss_blacklist', 'GRIDSS_BLACKLIST', hmf_bundle_dir, params_only), 'gridss_breakend_pon': getHmfDataFileObject('ref_data_gridss_breakend_pon', 'GRIDSS_BREAKEND_PON', hmf_bundle_dir, params_only), 'gridss_breakpoint_pon': getHmfDataFileObject('ref_data_gridss_breakpoint_pon', 'GRIDSS_BREAKPOINT_PON', hmf_bundle_dir, params_only), - 'repeat_masker_file': getHmfDataFileObject('ref_data_repeat_masker_file', 'REPEAT_MASKER_FILE', hmf_bundle_dir, params_only), // Isofox 'isofox_exp_counts': getHmfDataFileObject('ref_data_isofox_exp_counts', 'ISOFOX_EXP_COUNTS', hmf_bundle_dir, params_only), 'isofox_exp_gc_ratios': getHmfDataFileObject('ref_data_isofox_exp_gc_ratios', 'ISOFOX_EXP_GC_RATIOS', hmf_bundle_dir, params_only), diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index c7976172..a18992d2 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -384,7 +384,6 @@ workflow ONCOANALYSER { hmf_data.gridss_breakend_pon, hmf_data.gridss_breakpoint_pon, hmf_data.known_fusions, - hmf_data.repeat_masker_file, ) // Set outputs, restoring original meta From 9944f5e9cd9442847f355b37b5174a08106f3920 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 10:18:22 +1100 Subject: [PATCH 037/562] Run GRIDSS annotation stage --- modules/local/gridss/annotate/main.nf | 41 +++++++++++++++++++++++++++ subworkflows/local/gridss.nf | 8 +++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 modules/local/gridss/annotate/main.nf diff --git a/modules/local/gridss/annotate/main.nf b/modules/local/gridss/annotate/main.nf new file mode 100644 index 00000000..7a7c18f0 --- /dev/null +++ b/modules/local/gridss/annotate/main.nf @@ -0,0 +1,41 @@ +process ANNOTATE { + tag "${meta.id}" + label 'process_single' + + container 'docker.io/scwatts/gridss:2.13.2--3' + + input: + tuple val(meta), path(gridss_vcf) + + output: + tuple val(meta), path('gridss_annotate/*.gridss.annotated.vcf.gz'), emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + gridss_annotate_vcf_repeatmasker \\ + ${args} \\ + --jar ${task.ext.jarPath} \\ + --output gridss_annotate/${meta.id}.gridss.annotated.vcf.gz \\ + --workingdir gridss_annotate/work/ \\ + --threads ${task.cpus} \\ + ${gridss_vcf} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_annotate/ + touch gridss_annotate/${meta.id}.gridss.annotated.vcf.gz + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/subworkflows/local/gridss.nf b/subworkflows/local/gridss.nf index 2c0c88ad..6bf7fca6 100644 --- a/subworkflows/local/gridss.nf +++ b/subworkflows/local/gridss.nf @@ -4,6 +4,7 @@ import Constants import Utils +include { ANNOTATE } from '../../modules/local/gridss/annotate/main' include { ASSEMBLE } from '../../modules/local/gridss/assemble/main' include { CALL } from '../../modules/local/gridss/call/main' include { PREPROCESS } from '../../modules/local/gridss/preprocess/main' @@ -123,11 +124,16 @@ workflow GRIDSS { ) ch_versions = ch_versions.mix(CALL.out.versions) + // Annotate variants with RepeatMasker + ANNOTATE( + CALL.out.vcf, + ) + // Reunite final VCF with the corresponding input meta object ch_out = Channel.empty() .concat( ch_inputs.map { meta, tbam, nbam -> [meta.id, meta] }, - CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + ANNOTATE.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .groupTuple(size: 2) .map { id, other -> other.flatten() } From 6ff00a2e02c92a522d33246795b5cf0b8c7c0572 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 09:53:16 +1100 Subject: [PATCH 038/562] Switch to open directory for HMF data --- conf/hmfdata.config | 45 ++++++++++++ conf/test.config | 4 +- lib/Constants.groovy | 36 +--------- lib/WorkflowOncoanalyser.groovy | 4 +- modules/local/cuppa/classifier/main.nf | 4 +- modules/local/isofox/main.nf | 4 +- modules/local/linx/germline/main.nf | 4 +- modules/local/linx/somatic/main.nf | 4 +- modules/local/linx/visualiser/main.nf | 4 +- modules/local/pave/germline/main.nf | 20 +++--- modules/local/pave/somatic/main.nf | 12 ++-- modules/local/purple/main.nf | 4 +- modules/local/sage/germline/main.nf | 8 +-- modules/local/sage/somatic/main.nf | 8 +-- nextflow.config | 8 ++- nextflow_schema.json | 4 +- subworkflows/local/linx.nf | 26 +++---- subworkflows/local/pave.nf | 40 +++++------ subworkflows/local/prepare_reference.nf | 95 +++++++++++-------------- subworkflows/local/sage.nf | 16 ++--- workflows/oncoanalyser.nf | 48 ++++++------- 21 files changed, 202 insertions(+), 196 deletions(-) create mode 100644 conf/hmfdata.config diff --git a/conf/hmfdata.config b/conf/hmfdata.config new file mode 100644 index 00000000..d2d76896 --- /dev/null +++ b/conf/hmfdata.config @@ -0,0 +1,45 @@ +params { + hmfdata_paths { + '37' { + // AMBER + heterozygous_sites = 'amber/GermlineHetPon.37.vcf.gz' + // COBALT + gc_profile = 'gc_profiles/GC_profile.1000bp.37.cnp' + // CUPPA + cuppa_resources = 'cuppa/' + // GRIDSS + gridss_region_blocklist = 'gridss_repeatmasker_db/ENCFF001TDO.37.bed' + gridss_pon_breakends = 'gridss_pon/gridss_pon_single_breakend.37.bed.gz' + gridss_pon_breakpoints = 'gridss_pon/gridss_pon_breakpoint.37.bedpe.gz' + // Isofox + isofox_counts = 'isofox/read_151_exp_counts.csv' + isofox_gc_ratios = 'isofox/read_100_exp_gc_ratios.csv' + // LINX + linx_fragile_regions = 'linx/fragile_sites_hmf.37.csv' + linx_lines = 'linx/line_elements.37.csv' + // SAGE + sage_blocklist_regions = 'sage/KnownBlacklist.germline.37.bed' + sage_blocklist_sites = 'sage/KnownBlacklist.germline.37.vcf.gz' + sage_coding_panel = 'sage/ActionableCodingPanel.37.bed.gz' + sage_highconf_regions = 'giab_high_conf/NA12878_GIAB_highconf_IllFB-IllGATKHC-CG-Ion-Solid_ALLCHROM_v3.2.2_highconf.bed.gz' + sage_known_hotspots_germline = 'sage/KnownHotspots.germline.37.vcf.gz' + sage_known_hotspots_somatic = 'sage/KnownHotspots.somatic.37.vcf.gz' + sage_pon = 'sage/SageGermlinePon.1000x.37.tsv.gz' + clinvar_annotations = 'sage/clinvar.37.vcf.gz' + // SIGS + sigs_signatures = 'sigs/snv_cosmic_signatures.csv' + // LILAC + lilac_resources = 'lilac/' + // Virus Interpreter + virus_taxonomy = 'virus_interpreter/taxonomy_db.tsv' + virus_reporting = 'virus_interpreter/virus_reporting_db.tsv' + // Misc + purple_germline_del = 'purple/cohort_germline_del_freq.37.csv' + driver_gene_panel = 'gene_panel/DriverGenePanel.37.tsv' + ensembl_data_resources = 'ensembl_data_cache/' + known_fusion_data = 'fusions/known_fusion_data.37.csv' + known_fusions = 'fusions/known_fusions.37.bedpe' + segment_mappability = 'mappability/mappability_150.37.bed.gz' + } + } +} diff --git a/conf/test.config b/conf/test.config index 5c603278..dfa7d563 100644 --- a/conf/test.config +++ b/conf/test.config @@ -35,7 +35,7 @@ params { // Defined here to be accessible within a workflow script; downloaded manually prior to process // execution. ref_data_wgsmetrics_intervals_url = 'https://raw.githubusercontent.com/scwatts/nextflow_testdata/main/hmftools/collectwgsmetrics/intervals.interval_list' - schema_ignore_params = 'genomes,ref_data_wgsmetrics_intervals_url' + schema_ignore_params = 'genomes,hmfdata_paths,ref_data_wgsmetrics_intervals_url' // Limit resources so that this can run on GitHub Actions max_cpus = 1 @@ -45,7 +45,7 @@ params { // Input data input = '/Users/stephen/repos/oncoanalyser/temp/samplesheet.csv' - ref_data_hmf_bundle_path = '/Users/stephen/repos/oncoanalyser/temp/hmf_bundle.tar.gz' + ref_data_hmf_data_base = '/Users/stephen/repos/oncoanalyser/temp/hmf_bundle' ref_data_virusbreakenddb_path = '/Users/stephen/repos/oncoanalyser/temp/virusbreakenddb_20210401.tar.gz' genome = 'GRCh37_hmf' diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 1c5afe8d..d25fc0c0 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -5,8 +5,8 @@ class Constants { static List GENOMES_VERSION_38 = ['GRCh38_hmf', 'GRCh38', 'hg38'] static List GENOMES_ALT = ['GRCh38', 'hg38'] - static String HMF_REFERENCE_DATA_37_BUNDLE_PATH = 's3://umccr-research-dev/stephen/hmftools_reference_data/2_repack/gcloud_vm_v5.23/hmf_data_bundle_5.23_37_0.0.1.tar.gz' - static String HMF_REFERENCE_DATA_38_BUNDLE_PATH = 's3://umccr-research-dev/stephen/hmftools_reference_data/2_repack/gcloud_vm_v5.23/hmf_data_bundle_5.23_38_0.0.1.tar.gz' + static String HMF_DATA_37_BASE = 's3://umccr-research-dev/stephen/hmf_reference_data/2_repacked/hmf_data_bundle_5.29_37_0.0.1/' + static String HMF_DATA_38_BASE = 's3://umccr-research-dev/stephen/hmf_reference_data/2_repacked/hmf_data_bundle_5.29_38_0.0.1/' static String VIRUSBREAKENDDB_PATH = 's3://virusbreakend/virusbreakenddb_20210401.tar.gz' @@ -60,36 +60,4 @@ class Constants { SAGE_VCF, VIRUSINTERPRETER, } - - static public java.util.Map HMF_DATA_PATHS = [ - AMBER_LOCI: 'amber/GermlineHetPon.vcf.gz', - COBALT_GC_PROFILE: 'cobalt/DiploidRegions.bed.gz', - CUPPA: 'cuppa/', - GRIDSS_BLACKLIST: 'gridss/ENCFF356LFX.bed.gz', - GRIDSS_BREAKEND_PON: 'gridss/gridss_pon_single_breakend.bed.gz', - GRIDSS_BREAKPOINT_PON: 'gridss/gridss_pon_breakpoint.bedpe.gz', - ISOFOX_EXP_COUNTS: 'isofox/read_151_exp_counts.csv', - ISOFOX_EXP_GC_RATIOS: 'isofox/read_100_exp_gc_ratios.csv', - LINX_FRAGILE_SITES: 'linx/fragile_sites_hmf.csv', - LINX_LINES: 'linx/line_elements.csv', - SAGE_BLACKLIST_BED: 'sage/KnownBlacklist.germline.bed', - SAGE_BLACKLIST_VCF: 'sage/KnownHotspots.somatic.vcf.gz', - SAGE_CODING_PANEL: 'sage/ActionableCodingPanel.bed.gz', - SAGE_HIGH_CONFIDENCE: 'sage/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz', - SAGE_KNOWN_HOTSPOTS_GERMLINE: 'sage/KnownBlacklist.germline.vcf.gz', - SAGE_KNOWN_HOTSPOTS_SOMATIC: 'sage/KnownHotspots.somatic.vcf.gz', - SAGE_PON_FILE: 'sage/SageGermlinePon.98x.tsv.gz', - CLINVAR_VCF: 'sage/clinvar.vcf.gz', - SIGS_SIGNATURES: 'sigs/snv_cosmic_signatures.csv', - LILAC_RESOURCE_DIR: 'lilac/', - VIRUSBREAKENDDB: 'virusbreakend/', - VIRUSINTERPRETER_TAXONOMY: 'virusinterpreter/taxonomy_db.tsv', - VIRUSINTERPRETER_REPORTING: 'virusinterpreter/virus_reporting_db.tsv', - PURPLE_GERMLINE_DEL: 'purple/cohort_germline_del_freq.csv', - DRIVER_GENE_PANEL: 'gene_panel/DriverGenePanel.tsv', - ENSEMBL_DATA_DIR: 'ensembl_data_cache/', - KNOWN_FUSION_DATA: 'known_fusions/known_fusion_data.csv', - KNOWN_FUSIONS: 'known_fusions/known_fusions.bedpe', - MAPPABILITY_BED: 'mappability/mappability_150.bed.gz', - ] } diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index b97e10e7..57cba85b 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -64,9 +64,9 @@ class WorkflowOncoanalyser { if (!params.containsKey('ref_data_hmf_bundle_path')) { if (params.ref_data_genome_version == '37') { - params.ref_data_hmf_bundle_path = Constants.HMF_REFERENCE_DATA_37_BUNDLE_PATH + params.ref_data_hmf_data_base = Constants.HMF_DATA_37_BASE } else if (params.ref_data_genome_version == '38') { - params.ref_data_hmf_bundle_path = Constants.HMF_REFERENCE_DATA_38_BUNDLE_PATH + params.ref_data_hmf_data_base = Constants.HMF_DATA_38_BASE } else { assert false : "Got a bad genome version: ${params.ref_data_genome_version}" } diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index e763b294..54c1bc1c 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -6,7 +6,7 @@ process CUPPA_CLASSIFIER { input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) - path reference_data + path cuppa_resources output: tuple val(meta), path('*csv'), emit: csv @@ -29,7 +29,7 @@ process CUPPA_CLASSIFIER { -Xmx${task.memory.giga}g \\ -jar ${task.ext.jarPath} \\ -categories ${categories_arg} \\ - -ref_data_dir ${reference_data} \\ + -ref_data_dir ${cuppa_resources} \\ -sample_data ${meta.id} \\ -sample_data_dir sample_data/ \\ -output_dir ./ diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index bb368418..4e0d7627 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -9,7 +9,7 @@ process ISOFOX { path genome_fasta path genome_fai val genome_ver - path ensembl_data_dir + path ensembl_data_resources path exp_counts path exp_gc_ratios @@ -34,7 +34,7 @@ process ISOFOX { -bam_file ${bam} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ - -ensembl_data_dir ${ensembl_data_dir} \\ + -ensembl_data_resources ${ensembl_data_resources} \\ -exp_counts_file ${exp_counts} \\ -exp_gc_ratios_file ${exp_gc_ratios} \\ -output_dir ./isofox/ \\ diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 2328dda1..1a048656 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -9,7 +9,7 @@ process LINX_GERMLINE { val genome_ver path fragile_sites path lines - path ensembl_data_dir + path ensembl_data_resources path driver_gene_panel output: @@ -33,7 +33,7 @@ process LINX_GERMLINE { -sv_vcf ${gripss_sv} \\ -fragile_site_file ${fragile_sites} \\ -line_element_file ${lines} \\ - -ensembl_data_dir ${ensembl_data_dir} \\ + -ensembl_data_resources ${ensembl_data_resources} \\ -check_drivers \\ -driver_gene_panel ${driver_gene_panel} \\ -output_dir linx_germline/ diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index fae07ff3..6b82f05d 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -9,7 +9,7 @@ process LINX_SOMATIC { val genome_ver path fragile_sites path lines - path ensembl_data_dir + path ensembl_data_resources path known_fusion_data path driver_gene_panel @@ -34,7 +34,7 @@ process LINX_SOMATIC { -purple_dir ${purple_dir} \\ -fragile_site_file ${fragile_sites} \\ -line_element_file ${lines} \\ - -ensembl_data_dir ${ensembl_data_dir} \\ + -ensembl_data_resources ${ensembl_data_resources} \\ -check_fusions \\ -known_fusion_file ${known_fusion_data} \\ -check_drivers \\ diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 283c63e8..11ab3d5a 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -12,7 +12,7 @@ process VISUALISER { input: tuple val(meta), path(linx) val genome_ver - path ensembl_data_dir + path ensembl_data_resources output: tuple val(meta), path('linx_visualiser/plot/'), emit: visualiser_dir @@ -32,7 +32,7 @@ process VISUALISER { ${args} \\ -sample ${meta.id} \\ -ref_genome_version ${genome_ver} \\ - -ensembl_data_dir ${ensembl_data_dir} \\ + -ensembl_data_resources ${ensembl_data_resources} \\ -plot_out linx_visualiser/plot \\ -data_out linx_visualiser/data \\ -vis_file_dir ${linx} \\ diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 4b31d673..c2638024 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -15,12 +15,12 @@ process PAVE_GERMLINE { path genome_fasta path genome_fai val genome_ver - path sage_blacklist_bed - path sage_blacklist_vcf - path clinvar_vcf - path mappability_bed + path sage_blocklist_regions + path sage_blocklist_sites + path clinvar_annotations + path segment_mappability path driver_gene_panel - path ensembl_data_dir + path ensembl_data_resources output: tuple val(meta), path("*.vcf.gz") , emit: vcf @@ -41,12 +41,12 @@ process PAVE_GERMLINE { -sample ${meta.id} \\ -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ - -ensembl_data_dir ${ensembl_data_dir} \\ + -ensembl_data_resources ${ensembl_data_resources} \\ -driver_gene_panel ${driver_gene_panel} \\ - -clinvar_vcf ${clinvar_vcf} \\ - -blacklist_bed ${sage_blacklist_bed} \\ - -blacklist_vcf ${sage_blacklist_vcf} \\ - -mappability_bed ${mappability_bed} \\ + -clinvar_annotations ${clinvar_annotations} \\ + -blacklist_bed ${sage_blocklist_regions} \\ + -blacklist_vcf ${sage_blocklist_sites} \\ + -segment_mappability ${segment_mappability} \\ -vcf_file ${sage_vcf} \\ -read_pass_only \\ -output_dir ./ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index ae168f4e..9890200d 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -11,10 +11,10 @@ process PAVE_SOMATIC { path genome_fasta path genome_fai val genome_ver - path sage_pon_file - path mappability_bed + path sage_pon + path segment_mappability path driver_gene_panel - path ensembl_data_dir + path ensembl_data_resources output: tuple val(meta), path("*.vcf.gz") , emit: vcf @@ -35,11 +35,11 @@ process PAVE_SOMATIC { -sample ${meta.id} \\ -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ - -ensembl_data_dir ${ensembl_data_dir} \\ + -ensembl_data_resources ${ensembl_data_resources} \\ -driver_gene_panel ${driver_gene_panel} \\ - -pon_file ${sage_pon_file} \\ + -pon_file ${sage_pon} \\ -pon_filters "${pon_filters}" \\ - -mappability_bed ${mappability_bed} \\ + -segment_mappability ${segment_mappability} \\ -vcf_file ${sage_vcf} \\ -read_pass_only \\ -output_dir ./ diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 5fbd05d5..76571e4e 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -14,7 +14,7 @@ process PURPLE { path sage_known_hotspots_somatic path sage_known_hotspots_germline path driver_gene_panel - path ensembl_data_dir + path ensembl_data_resources path germline_del_freq output: @@ -62,7 +62,7 @@ process PURPLE { -gc_profile ${gc_profile} \\ -run_drivers \\ -driver_gene_panel ${driver_gene_panel} \\ - -ensembl_data_dir ${ensembl_data_dir} \\ + -ensembl_data_resources ${ensembl_data_resources} \\ -somatic_hotspots ${sage_known_hotspots_somatic} \\ -germline_hotspots ${sage_known_hotspots_germline} \\ ${germline_del_freq_arg} \\ diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index d86622d9..32180fb8 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -12,8 +12,8 @@ process SAGE_GERMLINE { val genome_ver path sage_known_hotspots_germline path sage_coding_panel - path sage_high_confidence - path ensembl_data_dir + path sage_highconf_regions + path ensembl_data_resources output: tuple val(meta), path("${meta.tumor_id}.sage_germline.vcf.gz"), emit: vcf @@ -38,8 +38,8 @@ process SAGE_GERMLINE { -ref_genome ${genome_fasta} \\ -hotspots ${sage_known_hotspots_germline} \\ -panel_bed ${sage_coding_panel} \\ - -high_confidence_bed ${sage_high_confidence} \\ - -ensembl_data_dir ${ensembl_data_dir} \\ + -high_confidence_bed ${sage_highconf_regions} \\ + -ensembl_data_resources ${ensembl_data_resources} \\ -hotspot_min_tumor_qual 50 \\ -panel_min_tumor_qual 75 \\ -hotspot_max_germline_vaf 100 \\ diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index e5b4d3d7..12bfd051 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -12,8 +12,8 @@ process SAGE_SOMATIC { val genome_ver path sage_known_hotspots_somatic path sage_coding_panel - path sage_high_confidence - path ensembl_data_dir + path sage_highconf_regions + path ensembl_data_resources output: tuple val(meta), path("${meta.tumor_id}.sage_somatic.vcf.gz"), emit: vcf @@ -38,8 +38,8 @@ process SAGE_SOMATIC { -ref_genome ${genome_fasta} \\ -hotspots ${sage_known_hotspots_somatic} \\ -panel_bed ${sage_coding_panel} \\ - -high_confidence_bed ${sage_high_confidence} \\ - -ensembl_data_dir ${ensembl_data_dir} \\ + -high_confidence_bed ${sage_highconf_regions} \\ + -ensembl_data_resources ${ensembl_data_resources} \\ -threads ${task.cpus} \\ -out ${meta.tumor_id}.sage_somatic.vcf.gz diff --git a/nextflow.config b/nextflow.config index d7722d61..ba80c240 100644 --- a/nextflow.config +++ b/nextflow.config @@ -28,6 +28,9 @@ params { igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false + // HMF data paths + ref_data_hmf_data_base = null + // Boilerplate options outdir = null tracedir = "${params.outdir}/pipeline_info" @@ -40,7 +43,7 @@ params { help = false validate_params = true show_hidden_params = false - schema_ignore_params = 'genomes' + schema_ignore_params = 'genomes,hmfdata_paths' enable_conda = false gridss_config = null @@ -153,7 +156,8 @@ if (!params.igenomes_ignore) { params.genomes = [:] } -// Load hmfgenomes.config +// Load hmfdata.config and hmfgenomes.config +includeConfig 'conf/hmfdata.config' includeConfig 'conf/hmfgenomes.config' diff --git a/nextflow_schema.json b/nextflow_schema.json index 6dc55bdb..cf60d8e8 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -143,10 +143,10 @@ "description": "Path to reference genome GRIDSS index file.", "fa_icon": "far fa-file-code" }, - "ref_data_hmf_bundle_path": { + "ref_data_hmf_data_base": { "type": "string", "format": "directory-path", - "description": "Path to HMF reference data bundle.", + "description": "Path to HMF data base directory or URL.", "fa_icon": "far fa-file-code" }, "ref_data_virusbreakenddb_path": { diff --git a/subworkflows/local/linx.nf b/subworkflows/local/linx.nf index ee0a99dc..defafc98 100644 --- a/subworkflows/local/linx.nf +++ b/subworkflows/local/linx.nf @@ -8,14 +8,14 @@ include { VISUALISER } from '../../modules/local/linx/visualiser/main' workflow LINX { take: - ch_linx_germline_inputs // channel: [val(meta), gripss_hard_vcf] - ch_linx_somatic_inputs // channel: [val(meta), purple_dir] - ref_data_genome_version // val: genome version - ref_data_linx_fragile_sites // file: /path/to/linx_fragile_sites - ref_data_linx_lines // file: /path/to/linx_lines - ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ - ref_data_known_fusion_data // file: /path/to/known_fusion_data - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + ch_linx_germline_inputs // channel: [val(meta), gripss_hard_vcf] + ch_linx_somatic_inputs // channel: [val(meta), purple_dir] + ref_data_genome_version // val: genome version + ref_data_linx_fragile_regions // file: /path/to/linx_fragile_regions + ref_data_linx_lines // file: /path/to/linx_lines + ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + ref_data_known_fusion_data // file: /path/to/known_fusion_data + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel main: // Channel for versions.yml files @@ -25,9 +25,9 @@ workflow LINX { LINX_GERMLINE( ch_linx_germline_inputs, ref_data_genome_version, - ref_data_linx_fragile_sites, + ref_data_linx_fragile_regions, ref_data_linx_lines, - ref_data_ensembl_data_dir, + ref_data_ensembl_data_resources, ref_data_driver_gene_panel, ) ch_versions = ch_versions.mix(LINX_GERMLINE.out.versions) @@ -36,9 +36,9 @@ workflow LINX { LINX_SOMATIC( ch_linx_somatic_inputs, ref_data_genome_version, - ref_data_linx_fragile_sites, + ref_data_linx_fragile_regions, ref_data_linx_lines, - ref_data_ensembl_data_dir, + ref_data_ensembl_data_resources, ref_data_known_fusion_data, ref_data_driver_gene_panel, ) @@ -47,7 +47,7 @@ workflow LINX { VISUALISER( LINX_SOMATIC.out.annotation_dir, ref_data_genome_version, - ref_data_ensembl_data_dir, + ref_data_ensembl_data_resources, ) ch_versions = ch_versions.mix(VISUALISER.out.versions) diff --git a/subworkflows/local/pave.nf b/subworkflows/local/pave.nf index 2b79b705..c434ba7e 100644 --- a/subworkflows/local/pave.nf +++ b/subworkflows/local/pave.nf @@ -7,18 +7,18 @@ include { PAVE_SOMATIC } from '../../modules/local/pave/somatic/main' workflow PAVE { take: - ch_inputs_germline // channel: [val(meta), sage_germline_vcf] - ch_inputs_somatic // channel: [val(meta), sage_somatic_vcf] - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_version // val: genome version - ref_data_sage_pon_file // file: /path/to/sage_pon_file - ref_data_sage_blacklist_bed // file: /path/to/sage_blacklist_bed - ref_data_sage_blacklist_vcf // file: /path/to/sage_black_list_vcf - ref_data_clinvar_vcf // file: /path/to/clinvar_vcf - ref_data_mappability_bed // file: /path/to/mappability_bed - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ + ch_inputs_germline // channel: [val(meta), sage_germline_vcf] + ch_inputs_somatic // channel: [val(meta), sage_somatic_vcf] + ref_data_genome_fasta // file: /path/to/genome_fasta + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_version // val: genome version + ref_data_sage_pon // file: /path/to/sage_pon + ref_data_sage_blocklist_regions // file: /path/to/sage_blocklist_regions + ref_data_sage_blocklist_sites // file: /path/to/sage_black_list_vcf + ref_data_clinvar_annotations // file: /path/to/clinvar_annotations + ref_data_segment_mappability // file: /path/to/segment_mappability + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ main: // Channel for version.yml files @@ -30,12 +30,12 @@ workflow PAVE { ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_version, - ref_data_sage_blacklist_bed, - ref_data_sage_blacklist_vcf, - ref_data_clinvar_vcf, - ref_data_mappability_bed, + ref_data_sage_blocklist_regions, + ref_data_sage_blocklist_sites, + ref_data_clinvar_annotations, + ref_data_segment_mappability, ref_data_driver_gene_panel, - ref_data_ensembl_data_dir, + ref_data_ensembl_data_resources, ) ch_versions = ch_versions.mix(PAVE_GERMLINE.out.versions) @@ -45,10 +45,10 @@ workflow PAVE { ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_version, - ref_data_sage_pon_file, - ref_data_mappability_bed, + ref_data_sage_pon, + ref_data_segment_mappability, ref_data_driver_gene_panel, - ref_data_ensembl_data_dir, + ref_data_ensembl_data_resources, ) ch_versions = ch_versions.mix(PAVE_SOMATIC.out.versions) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index f65ee6ae..2472efe1 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -6,7 +6,6 @@ include { SAMTOOLS_FAIDX } from '../../modules/nf-core/samtools/faidx/ma include { SAMTOOLS_DICT } from '../../modules/nf-core/samtools/dict/main' include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' -include { EXTRACT_TARBALL as EXTRACT_TARBALL_HMF_BUNDLE } from '../../modules/local/custom/extract_tarball/main' include { EXTRACT_TARBALL as EXTRACT_TARBALL_VIRUSBREAKENDDB } from '../../modules/local/custom/extract_tarball/main' include { INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' include { INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' @@ -99,24 +98,10 @@ workflow PREPARE_REFERENCE { } // - // Set HMF reference paths / stage, unpack if required + // Set HMF reference paths // - // NOTE(SW): requiring all HMF reference data for now - if (params.ref_data_hmf_bundle_path.endsWith('.tar.gz')) { - // Decompress and set paths - EXTRACT_TARBALL_HMF_BUNDLE([[id: 'hmf_bundle'], file(params.ref_data_hmf_bundle_path)]) - - // Obtain paths and convert queue channel to value channel - // NOTE(SW): any relevant HMF reference file parameter explicitly set in config will take priority - ch_hmf_data = EXTRACT_TARBALL_HMF_BUNDLE.out.dir - .collect() - .map { dir_list -> - assert dir_list.size() == 1 - return createHmfDataMap(dir_list[0], false /* params_only */) - } - } else if (params.ref_data_hmf_bundle_path) { - // If provided as path to directory, set paths - ch_hmf_data = createHmfDataMap(params.ref_data_hmf_bundle_path, false /* params_only */) + if (params.ref_data_hmf_data_base) { + ch_hmf_data = createHmfDataMap(params.ref_data_hmf_data_base, false /* params_only */) } else { // If no HMF data bundle is supplied we construct from *only* params ch_hmf_data = createHmfDataMap(null, true /* params_only */) @@ -137,59 +122,63 @@ workflow PREPARE_REFERENCE { versions = ch_versions // channel: [versions.yml] } -def createHmfDataMap(hmf_bundle_dir, params_only) { - return [ +def createHmfDataMap(hmf_data_base, params_only) { + def params_mapping = [ // AMBER - 'amber_loci': getHmfDataFileObject('ref_data_amber_loci', 'AMBER_LOCI', hmf_bundle_dir, params_only), + heterozygous_sites: 'ref_data_amber_loci', // COBALT - 'cobalt_gc_profile': getHmfDataFileObject('ref_data_cobalt_gc_profile', 'COBALT_GC_PROFILE', hmf_bundle_dir, params_only), + gc_profile: 'ref_data_gc_profile', // CUPPA - 'cuppa': getHmfDataFileObject('ref_data_cuppa', 'CUPPA', hmf_bundle_dir, params_only), - // GRIDSS, GRIPSS - 'gridss_blacklist': getHmfDataFileObject('ref_data_gridss_blacklist', 'GRIDSS_BLACKLIST', hmf_bundle_dir, params_only), - 'gridss_breakend_pon': getHmfDataFileObject('ref_data_gridss_breakend_pon', 'GRIDSS_BREAKEND_PON', hmf_bundle_dir, params_only), - 'gridss_breakpoint_pon': getHmfDataFileObject('ref_data_gridss_breakpoint_pon', 'GRIDSS_BREAKPOINT_PON', hmf_bundle_dir, params_only), + cuppa_resources: 'ref_data_cuppa_resource_dir', + // GRIDSS + gridss_region_blocklist: 'ref_data_gridss_blacklist', + gridss_pon_breakends: 'ref_data_gridss_breakend_pon', + gridss_pon_breakpoints: 'ref_data_gridss_breakpoint_pon', // Isofox - 'isofox_exp_counts': getHmfDataFileObject('ref_data_isofox_exp_counts', 'ISOFOX_EXP_COUNTS', hmf_bundle_dir, params_only), - 'isofox_exp_gc_ratios': getHmfDataFileObject('ref_data_isofox_exp_gc_ratios', 'ISOFOX_EXP_GC_RATIOS', hmf_bundle_dir, params_only), + isofox_counts: 'ref_data_isofox_exp_counts', + isofox_gc_ratios: 'ref_data_isofox_exp_gc_ratios', // LINX - 'linx_fragile_sites': getHmfDataFileObject('ref_data_linx_fragile_sites', 'LINX_FRAGILE_SITES', hmf_bundle_dir, params_only), - 'linx_lines': getHmfDataFileObject('ref_data_linx_lines', 'LINX_LINES', hmf_bundle_dir, params_only), - // SAGE, PAVE - 'sage_blacklist_bed': getHmfDataFileObject('ref_data_sage_blacklist_bed', 'SAGE_BLACKLIST_BED', hmf_bundle_dir, params_only), - 'sage_blacklist_vcf': getHmfDataFileObject('ref_data_sage_blacklist_vcf', 'SAGE_BLACKLIST_VCF', hmf_bundle_dir, params_only), - 'sage_coding_panel': getHmfDataFileObject('ref_data_sage_coding_panel', 'SAGE_CODING_PANEL', hmf_bundle_dir, params_only), - 'sage_high_confidence': getHmfDataFileObject('ref_data_sage_high_confidence', 'SAGE_HIGH_CONFIDENCE', hmf_bundle_dir, params_only), - 'sage_known_hotspots_germline': getHmfDataFileObject('ref_data_sage_known_hotspots_germline', 'SAGE_KNOWN_HOTSPOTS_GERMLINE', hmf_bundle_dir, params_only), - 'sage_known_hotspots_somatic': getHmfDataFileObject('ref_data_sage_known_hotspots_somatic', 'SAGE_KNOWN_HOTSPOTS_SOMATIC', hmf_bundle_dir, params_only), - 'sage_pon_file': getHmfDataFileObject('ref_data_sage_pon_file', 'SAGE_PON_FILE', hmf_bundle_dir, params_only), - 'clinvar_vcf': getHmfDataFileObject('ref_data_clinvar_vcf', 'CLINVAR_VCF', hmf_bundle_dir, params_only), + linx_fragile_regions: 'ref_data_linx_fragile_sites', + linx_lines: 'ref_data_linx_lines', + // SAGE + sage_blocklist_regions: 'ref_data_sage_blacklist_bed', + sage_blocklist_sites: 'ref_data_sage_blacklist_vcf', + sage_coding_panel: 'ref_data_sage_coding_panel', + sage_highconf_regions: 'ref_data_sage_high_confidence', + sage_known_hotspots_germline: 'ref_data_sage_known_hotspots_germline', + sage_known_hotspots_somatic: 'ref_data_sage_known_hotspots_somatic', + sage_pon: 'ref_data_sage_pon_file', + clinvar_annotations: 'ref_data_clinvar_vcf', // SIGS - 'sigs_signatures': getHmfDataFileObject('ref_data_sigs_signatures', 'SIGS_SIGNATURES', hmf_bundle_dir, params_only), + sigs_signatures: 'ref_data_sigs_signatures', // LILAC - 'lilac_resource_dir': getHmfDataFileObject('ref_data_lilac_resource_dir', 'LILAC_RESOURCE_DIR', hmf_bundle_dir, params_only), + lilac_resources: 'ref_data_lilac_resource_dir', // Virus Interpreter - 'virus_taxonomy': getHmfDataFileObject('ref_data_virus_taxonomy', 'VIRUSINTERPRETER_TAXONOMY', hmf_bundle_dir, params_only), - 'virus_reporting': getHmfDataFileObject('ref_data_virus_reporting', 'VIRUSINTERPRETER_REPORTING', hmf_bundle_dir, params_only), + virus_taxonomy: 'ref_data_virus_taxonomy', + virus_reporting: 'ref_data_virus_reporting', // Misc - 'purple_germline_del': getHmfDataFileObject('ref_data_purple_germline_del', 'PURPLE_GERMLINE_DEL', hmf_bundle_dir, params_only), - 'driver_gene_panel': getHmfDataFileObject('ref_data_driver_gene_panel', 'DRIVER_GENE_PANEL', hmf_bundle_dir, params_only), - 'ensembl_data_dir': getHmfDataFileObject('ref_data_ensembl_data_dir', 'ENSEMBL_DATA_DIR', hmf_bundle_dir, params_only), - 'known_fusion_data': getHmfDataFileObject('ref_data_known_fusion_data', 'KNOWN_FUSION_DATA', hmf_bundle_dir, params_only), - 'known_fusions': getHmfDataFileObject('ref_data_known_fusions', 'KNOWN_FUSIONS', hmf_bundle_dir, params_only), - 'mappability_bed': getHmfDataFileObject('ref_data_mappability_bed', 'MAPPABILITY_BED', hmf_bundle_dir, params_only), + purple_germline_del: 'ref_data_purple_germline_del', + driver_gene_panel: 'ref_data_driver_gene_panel', + ensembl_data_resources: 'ref_data_ensembl_data_dir', + known_fusion_data: 'ref_data_known_fusion_data', + known_fusions: 'ref_data_known_fusions', + segment_mappability: 'ref_data_mappability_bed', ] + params_mapping.collectEntries { k, v -> + [k, getHmfDataFileObject(v, k, hmf_data_base, params_only)] + } } def getHmfDataFileObject(pk, hk, base_dir, params_only) { + def hmfdata_paths = params.hmfdata_paths.getAt(params.ref_data_genome_version) if (params.containsKey(pk)) { return file(params.getAt(pk), checkIfExists: true) } else if (params_only) { assert false : "TODO(SW): more helpful message about missing param ${pk}" - } else if (!Constants.HMF_DATA_PATHS.containsKey(hk)) { - assert false : "bad key for Constants.HMF_DATA_PATHS ${hk}" + } else if (!hmfdata_paths.containsKey(hk)) { + assert false : "bad key for params.hmfdata_paths.${params.genome_version}: ${hk}" } else { def base_dir_noslash = base_dir.toString().replaceAll('/$', '') - return file("${base_dir_noslash}/${Constants.HMF_DATA_PATHS.getAt(hk)}", checkIfExists: true) + return file("${base_dir_noslash}/${hmfdata_paths.getAt(hk)}", checkIfExists: true) } } diff --git a/subworkflows/local/sage.nf b/subworkflows/local/sage.nf index 9391e684..9b1655e0 100644 --- a/subworkflows/local/sage.nf +++ b/subworkflows/local/sage.nf @@ -15,11 +15,11 @@ workflow SAGE { ref_data_sage_known_hotspots_germline // file: /path/to/sage_known_hotspots_germline ref_data_sage_known_hotspots_somatic // file: /path/to/sage_known_hotspots_somatic ref_data_sage_coding_panel // file: /path/to/sage_coding_panel - ref_data_sage_high_confidence // file: /path/to/sage_high_confidence - ref_data_sage_pon_file // file: /path/to/sage_pon - ref_data_mappability_bed // file: /path/to/mappability_bed + ref_data_sage_highconf_regions // file: /path/to/sage_highconf_regions + ref_data_sage_pon // file: /path/to/sage_pon + ref_data_segment_mappability // file: /path/to/segment_mappability ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - ref_data_ensembl_data_dir // file: /path/to/ensembl_data_dir/ + ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ main: // Channel for version.yml files @@ -34,8 +34,8 @@ workflow SAGE { ref_data_genome_version, ref_data_sage_known_hotspots_germline, ref_data_sage_coding_panel, - ref_data_sage_high_confidence, - ref_data_ensembl_data_dir, + ref_data_sage_highconf_regions, + ref_data_ensembl_data_resources, ) ch_versions = ch_versions.mix(SAGE_GERMLINE.out.versions) @@ -48,8 +48,8 @@ workflow SAGE { ref_data_genome_version, ref_data_sage_known_hotspots_somatic, ref_data_sage_coding_panel, - ref_data_sage_high_confidence, - ref_data_ensembl_data_dir, + ref_data_sage_highconf_regions, + ref_data_ensembl_data_resources, ) ch_versions = ch_versions.mix(SAGE_SOMATIC.out.versions) diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index a18992d2..d283faa3 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -160,9 +160,9 @@ workflow ONCOANALYSER { PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, PREPARE_REFERENCE.out.genome_version, - hmf_data.ensembl_data_dir, - hmf_data.isofox_exp_counts, - hmf_data.isofox_exp_gc_ratios, + hmf_data.ensembl_data_resources, + hmf_data.isofox_counts, + hmf_data.isofox_gc_ratios, ) // Set outputs, restoring original meta @@ -279,7 +279,7 @@ workflow ONCOANALYSER { AMBER( ch_amber_inputs, PREPARE_REFERENCE.out.genome_version, - hmf_data.amber_loci, + hmf_data.heterozygous_sites, ) // Set outputs, restoring original meta @@ -311,7 +311,7 @@ workflow ONCOANALYSER { // Run process COBALT( ch_cobalt_inputs, - hmf_data.cobalt_gc_profile, + hmf_data.gc_profile, ) // Set outputs, restoring original meta @@ -340,7 +340,7 @@ workflow ONCOANALYSER { PREPARE_REFERENCE.out.genome_bwa_index, PREPARE_REFERENCE.out.genome_bwa_index_image, PREPARE_REFERENCE.out.genome_gridss_index, - hmf_data.gridss_blacklist, + hmf_data.gridss_region_blocklist, ) ch_versions = ch_versions.mix(GRIDSS.out.versions) ch_gridss_out = ch_gridss_out.mix(GRIDSS.out.results) @@ -381,8 +381,8 @@ workflow ONCOANALYSER { PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, PREPARE_REFERENCE.out.genome_version, - hmf_data.gridss_breakend_pon, - hmf_data.gridss_breakpoint_pon, + hmf_data.gridss_pon_breakends, + hmf_data.gridss_pon_breakpoints, hmf_data.known_fusions, ) @@ -422,11 +422,11 @@ workflow ONCOANALYSER { hmf_data.sage_known_hotspots_germline, hmf_data.sage_known_hotspots_somatic, hmf_data.sage_coding_panel, - hmf_data.sage_high_confidence, - hmf_data.sage_pon_file, - hmf_data.mappability_bed, + hmf_data.sage_highconf_regions, + hmf_data.sage_pon, + hmf_data.segment_mappability, hmf_data.driver_gene_panel, - hmf_data.ensembl_data_dir, + hmf_data.ensembl_data_resources, ) // Set outputs, restoring original meta @@ -479,13 +479,13 @@ workflow ONCOANALYSER { PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, PREPARE_REFERENCE.out.genome_version, - hmf_data.sage_pon_file, - hmf_data.sage_blacklist_bed, - hmf_data.sage_blacklist_vcf, - hmf_data.clinvar_vcf, - hmf_data.mappability_bed, + hmf_data.sage_pon, + hmf_data.sage_blocklist_regions, + hmf_data.sage_blocklist_sites, + hmf_data.clinvar_annotations, + hmf_data.segment_mappability, hmf_data.driver_gene_panel, - hmf_data.ensembl_data_dir, + hmf_data.ensembl_data_resources, ) // Set outputs, restoring original meta @@ -548,11 +548,11 @@ workflow ONCOANALYSER { PREPARE_REFERENCE.out.genome_fai, PREPARE_REFERENCE.out.genome_dict, PREPARE_REFERENCE.out.genome_version, - hmf_data.cobalt_gc_profile, + hmf_data.gc_profile, hmf_data.sage_known_hotspots_somatic, hmf_data.sage_known_hotspots_germline, hmf_data.driver_gene_panel, - hmf_data.ensembl_data_dir, + hmf_data.ensembl_data_resources, hmf_data.purple_germline_del, ) @@ -680,7 +680,7 @@ workflow ONCOANALYSER { run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput([Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, - hmf_data.lilac_resource_dir, + hmf_data.lilac_resources, ) // Set outputs @@ -803,9 +803,9 @@ workflow ONCOANALYSER { ch_linx_inputs_germline, ch_linx_inputs_somatic, PREPARE_REFERENCE.out.genome_version, - hmf_data.linx_fragile_sites, + hmf_data.linx_fragile_regions, hmf_data.linx_lines, - hmf_data.ensembl_data_dir, + hmf_data.ensembl_data_resources, hmf_data.known_fusion_data, hmf_data.driver_gene_panel, ) @@ -889,7 +889,7 @@ workflow ONCOANALYSER { // Run process CUPPA_CLASSIFIER( ch_cuppa_inputs, - hmf_data.cuppa, + hmf_data.cuppa_resources, ) // Set outputs From 5b9385dc540051278ac4a240a181ed2aef1f443a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 15:56:14 +1100 Subject: [PATCH 039/562] Update selection of BED for LILAC slice process --- subworkflows/local/lilac.nf | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index 16007d7e..eb609a6a 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -24,8 +24,12 @@ workflow LILAC { // Slice HLA regions ch_slice_bed = ref_data_lilac_resource_dir .map { lilac_dir -> - def genome_ver = params.ref_data_genome_version - def filename = genome_ver == '38' ? 'hla.38.alt.umccr.bed' : "hla.${genome_ver}.bed" + def filename + if (params.ref_data_genome_type == 'no_alt') { + filename = "hla.${params.ref_data_genome_version}.bed" + } else { + filename = "hla.38.alt.umccr.bed" + } return file("${lilac_dir}/${filename}", checkIfExists: true) } // NOTE(SW): here I remove duplicate files so that we only process each input once From 0e79adcea11a95b1465b6dd3870c7af8af185742 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 15:56:46 +1100 Subject: [PATCH 040/562] Correct variable name for HMF data --- lib/WorkflowOncoanalyser.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 57cba85b..19fd3ce9 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -62,7 +62,7 @@ class WorkflowOncoanalyser { params.ref_data_genome_type = 'no_alt' } - if (!params.containsKey('ref_data_hmf_bundle_path')) { + if (!params.containsKey('ref_data_hmf_data_base')) { if (params.ref_data_genome_version == '37') { params.ref_data_hmf_data_base = Constants.HMF_DATA_37_BASE } else if (params.ref_data_genome_version == '38') { From 25810e1d61277d9ac51ac833416d6e6689ebacbd Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 15:57:16 +1100 Subject: [PATCH 041/562] Add check for null params, remove HMF data base --- lib/WorkflowOncoanalyser.groovy | 14 +++++++++++--- nextflow.config | 3 --- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 19fd3ce9..dbf7d45a 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -76,9 +76,17 @@ class WorkflowOncoanalyser { params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH } - if (!params.ref_data_genome_fasta) { - log.error "Genome fasta file not specified with e.g. '--ref_data_genome_fasta genome.fa' or via a detectable config file." - System.exit(1) + def null_check = [ + 'ref_data_genome_fasta', + 'ref_data_genome_type', + 'ref_data_genome_version', + 'ref_data_virusbreakenddb_path', + ] + null_check.each { k -> + if (!params[k]) { + log.error "ERROR: '${k}' cannot be set to null in any configuration and must be adjusted or removed to proceed." + System.exit(1) + } } // Download region file for collectwgsmetrics if in test mode diff --git a/nextflow.config b/nextflow.config index ba80c240..7f5027f4 100644 --- a/nextflow.config +++ b/nextflow.config @@ -28,9 +28,6 @@ params { igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false - // HMF data paths - ref_data_hmf_data_base = null - // Boilerplate options outdir = null tracedir = "${params.outdir}/pipeline_info" From c77ec17c35b76efa9e61e80ed6e383013c8bbfbd Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 15:57:54 +1100 Subject: [PATCH 042/562] Slightly improve message for missing HMF data --- subworkflows/local/prepare_reference.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 2472efe1..d3f4d39b 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -174,7 +174,8 @@ def getHmfDataFileObject(pk, hk, base_dir, params_only) { if (params.containsKey(pk)) { return file(params.getAt(pk), checkIfExists: true) } else if (params_only) { - assert false : "TODO(SW): more helpful message about missing param ${pk}" + log.error "ERROR: no entry for ${pk} found in params but is required as no HMF data base path provided" + System.exit(1) } else if (!hmfdata_paths.containsKey(hk)) { assert false : "bad key for params.hmfdata_paths.${params.genome_version}: ${hk}" } else { From 23abe417e652912e60be270a9b3147b472d3bb1f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 15:59:10 +1100 Subject: [PATCH 043/562] Fix ensembl data cache arguments --- modules/local/isofox/main.nf | 2 +- modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 2 +- modules/local/pave/germline/main.nf | 2 +- modules/local/pave/somatic/main.nf | 2 +- modules/local/purple/main.nf | 2 +- modules/local/sage/germline/main.nf | 2 +- modules/local/sage/somatic/main.nf | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 4e0d7627..d228bbec 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -34,7 +34,7 @@ process ISOFOX { -bam_file ${bam} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ - -ensembl_data_resources ${ensembl_data_resources} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ -exp_counts_file ${exp_counts} \\ -exp_gc_ratios_file ${exp_gc_ratios} \\ -output_dir ./isofox/ \\ diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 1a048656..99e8bddd 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -33,7 +33,7 @@ process LINX_GERMLINE { -sv_vcf ${gripss_sv} \\ -fragile_site_file ${fragile_sites} \\ -line_element_file ${lines} \\ - -ensembl_data_resources ${ensembl_data_resources} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ -check_drivers \\ -driver_gene_panel ${driver_gene_panel} \\ -output_dir linx_germline/ diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 6b82f05d..12c6615a 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -34,7 +34,7 @@ process LINX_SOMATIC { -purple_dir ${purple_dir} \\ -fragile_site_file ${fragile_sites} \\ -line_element_file ${lines} \\ - -ensembl_data_resources ${ensembl_data_resources} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ -check_fusions \\ -known_fusion_file ${known_fusion_data} \\ -check_drivers \\ diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 11ab3d5a..f1c2baf7 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -32,7 +32,7 @@ process VISUALISER { ${args} \\ -sample ${meta.id} \\ -ref_genome_version ${genome_ver} \\ - -ensembl_data_resources ${ensembl_data_resources} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ -plot_out linx_visualiser/plot \\ -data_out linx_visualiser/data \\ -vis_file_dir ${linx} \\ diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index c2638024..d392641c 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -41,7 +41,7 @@ process PAVE_GERMLINE { -sample ${meta.id} \\ -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ - -ensembl_data_resources ${ensembl_data_resources} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ -driver_gene_panel ${driver_gene_panel} \\ -clinvar_annotations ${clinvar_annotations} \\ -blacklist_bed ${sage_blocklist_regions} \\ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 9890200d..7cc8d5ee 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -35,7 +35,7 @@ process PAVE_SOMATIC { -sample ${meta.id} \\ -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ - -ensembl_data_resources ${ensembl_data_resources} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ -driver_gene_panel ${driver_gene_panel} \\ -pon_file ${sage_pon} \\ -pon_filters "${pon_filters}" \\ diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 76571e4e..593c39f6 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -62,7 +62,7 @@ process PURPLE { -gc_profile ${gc_profile} \\ -run_drivers \\ -driver_gene_panel ${driver_gene_panel} \\ - -ensembl_data_resources ${ensembl_data_resources} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ -somatic_hotspots ${sage_known_hotspots_somatic} \\ -germline_hotspots ${sage_known_hotspots_germline} \\ ${germline_del_freq_arg} \\ diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 32180fb8..d0547147 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -39,7 +39,7 @@ process SAGE_GERMLINE { -hotspots ${sage_known_hotspots_germline} \\ -panel_bed ${sage_coding_panel} \\ -high_confidence_bed ${sage_highconf_regions} \\ - -ensembl_data_resources ${ensembl_data_resources} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ -hotspot_min_tumor_qual 50 \\ -panel_min_tumor_qual 75 \\ -hotspot_max_germline_vaf 100 \\ diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 12bfd051..030b9854 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -39,7 +39,7 @@ process SAGE_SOMATIC { -hotspots ${sage_known_hotspots_somatic} \\ -panel_bed ${sage_coding_panel} \\ -high_confidence_bed ${sage_highconf_regions} \\ - -ensembl_data_resources ${ensembl_data_resources} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ -threads ${task.cpus} \\ -out ${meta.tumor_id}.sage_somatic.vcf.gz From fe005e08ed5f415e3db57ab1d4c0c2a7ba4e8d74 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 16:42:16 +1100 Subject: [PATCH 044/562] Fix URI for LILAC slice BED if required --- subworkflows/local/lilac.nf | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index eb609a6a..1b9e72c6 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -30,7 +30,14 @@ workflow LILAC { } else { filename = "hla.38.alt.umccr.bed" } - return file("${lilac_dir}/${filename}", checkIfExists: true) + + def filepath = lilac_dir.resolve(filename).toUri().toString() + // NOTE(SW): S3Path.toUri() includes an extra forward slash in the URI or path, + // which is removed here. Unsure whether this occurs in other URIs types + if (filepath.startsWith('s3:///')) { + filepath = filepath.replaceFirst(/^s3:\/\/\//, 's3://') + } + return file(filepath, checkIfExists: true) } // NOTE(SW): here I remove duplicate files so that we only process each input once // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used From eb85fed58547bc173e1f691d9258b0bae2697b02 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 17:55:35 +1100 Subject: [PATCH 045/562] Fix SAGE somatic module tumor id variable --- modules/local/sage/somatic/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 030b9854..cf017143 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -32,7 +32,7 @@ process SAGE_SOMATIC { ${args} \\ -reference ${meta.normal_id} \\ -reference_bam ${normal_bam} \\ - -tumor ${meta.tumor_id}} \\ + -tumor ${meta.tumor_id} \\ -tumor_bam ${tumor_bam} \\ -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ From 4816dd3e8400027c00d8724c0ec68257091a45a7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 19:53:13 +1100 Subject: [PATCH 046/562] Rename more HMF data resource variables --- conf/hmfdata.config | 4 +- modules/local/gridss/assemble/main.nf | 4 +- modules/local/gridss/call/main.nf | 4 +- modules/local/gripss/germline/main.nf | 8 ++-- modules/local/gripss/somatic/main.nf | 8 ++-- modules/local/lilac/main.nf | 4 +- modules/local/linx/germline/main.nf | 4 +- modules/local/linx/somatic/main.nf | 4 +- modules/local/purple/main.nf | 6 +-- modules/local/sigs/main.nf | 4 +- modules/local/virusinterpreter/main.nf | 8 ++-- nextflow_schema.json | 62 ++++++++++++------------- subworkflows/local/pave.nf | 2 +- subworkflows/local/prepare_reference.nf | 36 +++++++------- workflows/oncoanalyser.nf | 4 +- 15 files changed, 81 insertions(+), 81 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index d2d76896..19918f02 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -31,8 +31,8 @@ params { // LILAC lilac_resources = 'lilac/' // Virus Interpreter - virus_taxonomy = 'virus_interpreter/taxonomy_db.tsv' - virus_reporting = 'virus_interpreter/virus_reporting_db.tsv' + virus_taxonomy_db = 'virus_interpreter/taxonomy_db.tsv' + virus_reporting_db = 'virus_interpreter/virus_reporting_db.tsv' // Misc purple_germline_del = 'purple/cohort_germline_del_freq.37.csv' driver_gene_panel = 'gene_panel/DriverGenePanel.37.tsv' diff --git a/modules/local/gridss/assemble/main.nf b/modules/local/gridss/assemble/main.nf index 49eee518..04ad5f02 100644 --- a/modules/local/gridss/assemble/main.nf +++ b/modules/local/gridss/assemble/main.nf @@ -13,7 +13,7 @@ process ASSEMBLE { path genome_bwa_index_dir, stageAs: 'bwa_index' path genome_bwa_index_image path genome_gridss_index - path blacklist + path blocklist output: tuple val(meta), path('gridss_assemble/'), emit: assemble_dir @@ -69,7 +69,7 @@ process ASSEMBLE { --steps assemble \\ --labels ${labels_arg} \\ --reference ${genome_fasta} \\ - --blacklist ${blacklist} \\ + --blacklist ${blocklist} \\ --workingdir ${output_dirname}/work \\ --assembly ${output_dirname}/sv_assemblies.bam \\ --threads ${task.cpus} \\ diff --git a/modules/local/gridss/call/main.nf b/modules/local/gridss/call/main.nf index ccf37224..b86d67da 100644 --- a/modules/local/gridss/call/main.nf +++ b/modules/local/gridss/call/main.nf @@ -13,7 +13,7 @@ process CALL { path genome_bwa_index_dir, stageAs: 'bwa_index' path genome_bwa_index_image path genome_gridss_index - path blacklist + path blocklist output: tuple val(meta), path('gridss_call/sv_vcf.vcf.gz'), emit: vcf @@ -67,7 +67,7 @@ process CALL { --steps call \\ --labels ${labels_arg} \\ --reference ${genome_fasta} \\ - --blacklist ${blacklist} \\ + --blacklist ${blocklist} \\ --workingdir ${output_dirname}/work/ \\ --assembly ${output_dirname}/sv_assemblies.bam \\ --output ${output_dirname}/sv_vcf.vcf.gz \\ diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index fbbc1797..c1504bca 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -9,8 +9,8 @@ process GRIPSS_GERMLINE { path genome_fasta path genome_fai val genome_ver - path breakend_pon - path breakpoint_pon + path pon_breakends + path pon_breakpoints path known_fusions output: @@ -32,8 +32,8 @@ process GRIPSS_GERMLINE { -sample ${meta.normal_id} \\ -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ - -pon_sgl_file ${breakend_pon} \\ - -pon_sv_file ${breakpoint_pon} \\ + -pon_sgl_file ${pon_breakends} \\ + -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ -vcf ${gridss_vcf} \\ -output_dir ./ diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index 129280b9..ac85deec 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -9,8 +9,8 @@ process GRIPSS_SOMATIC { path genome_fasta path genome_fai val genome_ver - path breakend_pon - path breakpoint_pon + path pon_breakends + path pon_breakpoints path known_fusions output: @@ -33,8 +33,8 @@ process GRIPSS_SOMATIC { -reference ${meta.normal_id} \\ -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ - -pon_sgl_file ${breakend_pon} \\ - -pon_sv_file ${breakpoint_pon} \\ + -pon_sgl_file ${pon_breakends} \\ + -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ -vcf ${gridss_vcf} \\ -output_dir ./ diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index a22cb49f..31944e1c 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -8,7 +8,7 @@ process LILAC { tuple val(meta), path(tumor_bam), path(normal_bam), path(tumour_bai), path(normal_bai), path(purple_dir) path genome_fasta val genome_ver - path lilac_resource_dir, stageAs: 'lilac_resource_dir' + path lilac_resources, stageAs: 'lilac_resources' output: tuple val(meta), path('lilac/'), emit: lilac_dir @@ -36,7 +36,7 @@ process LILAC { -reference_bam ${normal_bam} \\ -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ - -resource_dir ${lilac_resource_dir} \\ + -resource_dir ${lilac_resources} \\ ${purple_args.replaceAll('\\n', '')} \\ -threads ${task.cpus} \\ -output_dir lilac/ diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 99e8bddd..ccad0f1b 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -7,7 +7,7 @@ process LINX_GERMLINE { input: tuple val(meta), path(gripss_sv) val genome_ver - path fragile_sites + path fragile_regions path lines path ensembl_data_resources path driver_gene_panel @@ -31,7 +31,7 @@ process LINX_GERMLINE { -germline \\ -ref_genome_version ${genome_ver} \\ -sv_vcf ${gripss_sv} \\ - -fragile_site_file ${fragile_sites} \\ + -fragile_site_file ${fragile_regions} \\ -line_element_file ${lines} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -check_drivers \\ diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 12c6615a..33958b45 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -7,7 +7,7 @@ process LINX_SOMATIC { input: tuple val(meta), path(purple_dir) val genome_ver - path fragile_sites + path fragile_regions path lines path ensembl_data_resources path known_fusion_data @@ -32,7 +32,7 @@ process LINX_SOMATIC { -ref_genome_version ${genome_ver} \\ -sv_vcf ${purple_dir}/${meta.id}.purple.sv.vcf.gz \\ -purple_dir ${purple_dir} \\ - -fragile_site_file ${fragile_sites} \\ + -fragile_site_file ${fragile_regions} \\ -line_element_file ${lines} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -check_fusions \\ diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 593c39f6..81168a0b 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -15,7 +15,7 @@ process PURPLE { path sage_known_hotspots_germline path driver_gene_panel path ensembl_data_resources - path germline_del_freq + path germline_del output: tuple val(meta), path('purple/'), emit: purple_dir @@ -28,7 +28,7 @@ process PURPLE { def args = task.ext.args ?: '' def smlv_tumor_vcf_fp = smlv_tumor_vcf ?: '' def smlv_normal_vcf_fp = smlv_normal_vcf ?: '' - def germline_del_freq_arg = germline_del_freq ? "-germline_del_freq_file ${germline_del_freq}" : '' + def germline_del_arg = germline_del ? "-germline_del_file ${germline_del}" : '' """ # For provided smlv VCFs, filter records that do not contain the required FORMAT/AD field and @@ -65,7 +65,7 @@ process PURPLE { -ensembl_data_dir ${ensembl_data_resources} \\ -somatic_hotspots ${sage_known_hotspots_somatic} \\ -germline_hotspots ${sage_known_hotspots_germline} \\ - ${germline_del_freq_arg} \\ + ${germline_del_arg} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -threads ${task.cpus} \\ diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 53971956..aec67448 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -6,7 +6,7 @@ process SIGS { input: tuple val(meta), path(smlv_vcf) - path signatures_file + path signatures output: tuple val(meta), path('sigs/'), emit: sigs_dir @@ -26,7 +26,7 @@ process SIGS { -jar ${task.ext.jarPath} \\ -sample ${meta.id} \\ -somatic_vcf_file ${smlv_vcf} \\ - -signatures_file ${signatures_file} \\ + -signatures_file ${signatures} \\ -output_dir ./sigs/ # NOTE(SW): hard coded since there is no reliable way to obtain version information. diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index 884c1b01..7cc4ac95 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -6,8 +6,8 @@ process VIRUSINTERPRETER { input: tuple val(meta), path(virus_tsv), path(purple_purity), path(purple_qc), path(wgs_metrics) - path taxonomy - path virus_reporting + path taxonomy_db + path reporting_db output: tuple val(meta), path('virusinterpreter'), emit: virusinterpreter_dir @@ -30,8 +30,8 @@ process VIRUSINTERPRETER { -purple_qc_file ${purple_qc} \\ -tumor_sample_wgs_metrics_file ${wgs_metrics} \\ -virus_breakend_tsv ${virus_tsv} \\ - -taxonomy_db_tsv ${taxonomy} \\ - -virus_reporting_db_tsv ${virus_reporting} \\ + -taxonomy_db_tsv ${taxonomy_db} \\ + -virus_reporting_db_tsv ${reporting_db} \\ -output_dir ./virusinterpreter/ cat <<-END_VERSIONS > versions.yml diff --git a/nextflow_schema.json b/nextflow_schema.json index cf60d8e8..46d9adc1 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -155,7 +155,7 @@ "description": "Path to VIRUSBreakend database.", "fa_icon": "far fa-file-code" }, - "ref_data_amber_loci": { + "ref_data_heterozygous_sites": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.vcf\\.gz$", @@ -169,48 +169,48 @@ "description": "Path to COBALT GC profile file.", "fa_icon": "far fa-file-code" }, - "ref_data_cuppa": { + "ref_data_cuppa_resource_dir": { "type": "string", "format": "directory-path", "description": "Path to CUPPA reference file directory.", "fa_icon": "far fa-file-code" }, - "ref_data_gridss_blacklist": { + "ref_data_gridss_region_blocklist": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed.gz$", - "description": "Path to GRIDSS blacklist file.", + "description": "Path to GRIDSS blocklist file.", "fa_icon": "far fa-file-code" }, - "ref_data_gridss_breakend_pon": { + "ref_data_gridss_pon_breakends": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed\\.gz", "description": "Path to GRIDSS breakend PON file.", "fa_icon": "far fa-file-code" }, - "ref_data_gridss_breakpoint_pon": { + "ref_data_gridss_pon_breakpoints": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bedpe\\.gz$", "description": "Path to GRIDSS breakpoint PON file.", "fa_icon": "far fa-file-code" }, - "ref_data_isofox_exp_counts": { + "ref_data_isofox_counts": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", "description": "Path to Isofox expected read counts file.", "fa_icon": "far fa-file-code" }, - "ref_data_isofox_exp_gc_ratios": { + "ref_data_isofox_gc_ratios": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", "description": "Path to Isofox expected GC ratios file.", "fa_icon": "far fa-file-code" }, - "ref_data_linx_fragile_sites": { + "ref_data_linx_fragile_regions": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", @@ -227,90 +227,90 @@ "ref_data_ensembl_data_dir": { "type": "string", "format": "directory-path", - "description": "Path to HMF Ensembl Data Cache directory.", + "description": "Path to HMF Ensembl data cache directory.", "fa_icon": "far fa-file-code" }, - "ref_data_lilac_resource_dir": { + "ref_data_lilac_resources": { "type": "string", "format": "directory-path", "description": "Path to LILAC resource directory.", "fa_icon": "far fa-folder-open" }, - "ref_data_virusinterpreter_taxonomy": { + "ref_data_virus_taxonomy_db": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.tsv$", "description": "Path to Virus Interpreter taxonomy file.", "fa_icon": "far fa-file-code" }, - "ref_data_virusinterpreter_reporting": { + "ref_data_virus_reporting_db": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.tsv$", "description": "Path to Virus Interpreter reporting file.", "fa_icon": "far fa-file-code" }, - "ref_data_mappability_bed": { + "ref_data_segment_mappability": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed\\.gz$", "description": "Path to HMF mappability file.", "fa_icon": "far fa-file-code" }, - "ref_data_clinvar_vcf": { + "ref_data_clinvar_annotations": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to HMF ClinVar file.", + "description": "Path to HMF ClinVar annotations VCF file.", "fa_icon": "far fa-file-code" }, - "ref_data_sage_blacklist_vcf": { + "ref_data_sage_blocklist_regions": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to HMF SAGE Known Blacklist VCF file.", + "description": "Path to HMF SAGE known blocklist VCF file.", "fa_icon": "far fa-file-code" }, - "ref_data_sage_blacklist_bed": { + "ref_data_sage_blocklist_sites": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed$", - "description": "Path to HMF SAGE Known Blacklist BED file.", + "description": "Path to HMF SAGE known blocklist BED file.", "fa_icon": "far fa-file-code" }, - "ref_data_sage_pon_file": { + "ref_data_sage_pon": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.tsv\\.gz$", - "description": "Path to HMF SAGE Panel of Normals file.", + "description": "Path to HMF SAGE panel of normals file.", "fa_icon": "far fa-file-code" }, - "ref_data_sage_high_confidence": { + "ref_data_sage_highconf_regions": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to HMF distributed High Confidence regions file.", + "description": "Path to HMF distributed high confidence regions file.", "fa_icon": "far fa-file-code" }, "ref_data_sage_coding_panel": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to somatic SAGE Coding Panel file.", + "description": "Path to somatic SAGE coding panel file.", "fa_icon": "far fa-file-code" }, "ref_data_sage_known_hotspots_germline": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to germline SAGE Known Hotspots file.", + "description": "Path to germline SAGE known hotspots file.", "fa_icon": "far fa-file-code" }, "ref_data_sage_known_hotspots_somatic": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to somatic SAGE Known Hotspots file.", + "description": "Path to somatic SAGE known hotspots file.", "fa_icon": "far fa-file-code" }, "ref_data_sigs_signatures": { @@ -324,28 +324,28 @@ "type": "string", "format": "file-path", "pattern": "^\\S+\\.bedpe$", - "description": "Path to HMF Known Fusions file.", + "description": "Path to HMF known fusions file.", "fa_icon": "far fa-file-code" }, "ref_data_known_fusion_data": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", - "description": "Path to HMF Known Fusions Data file.", + "description": "Path to HMF known fusions Data file.", "fa_icon": "far fa-file-code" }, "ref_data_purple_germline_del": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", - "description": "Path to HMF PURPLE Germline Cohort Deletion Frequency file.", + "description": "Path to HMF PURPLE germline cohort deletion frequency file.", "fa_icon": "far fa-file-code" }, "ref_data_driver_gene_panel": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.tsv$", - "description": "Path to HMF Driver Gene Panel file.", + "description": "Path to HMF driver gene panel file.", "fa_icon": "far fa-file-code" } } diff --git a/subworkflows/local/pave.nf b/subworkflows/local/pave.nf index c434ba7e..f1eab61c 100644 --- a/subworkflows/local/pave.nf +++ b/subworkflows/local/pave.nf @@ -14,7 +14,7 @@ workflow PAVE { ref_data_genome_version // val: genome version ref_data_sage_pon // file: /path/to/sage_pon ref_data_sage_blocklist_regions // file: /path/to/sage_blocklist_regions - ref_data_sage_blocklist_sites // file: /path/to/sage_black_list_vcf + ref_data_sage_blocklist_sites // file: /path/to/sage_blocklist_sites ref_data_clinvar_annotations // file: /path/to/clinvar_annotations ref_data_segment_mappability // file: /path/to/segment_mappability ref_data_driver_gene_panel // file: /path/to/driver_gene_panel diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index d3f4d39b..2ef9750c 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -125,44 +125,44 @@ workflow PREPARE_REFERENCE { def createHmfDataMap(hmf_data_base, params_only) { def params_mapping = [ // AMBER - heterozygous_sites: 'ref_data_amber_loci', + heterozygous_sites: 'ref_data_heterozygous_sites', // COBALT gc_profile: 'ref_data_gc_profile', // CUPPA - cuppa_resources: 'ref_data_cuppa_resource_dir', + cuppa_resources: 'ref_data_cuppa_resources', // GRIDSS - gridss_region_blocklist: 'ref_data_gridss_blacklist', - gridss_pon_breakends: 'ref_data_gridss_breakend_pon', - gridss_pon_breakpoints: 'ref_data_gridss_breakpoint_pon', + gridss_region_blocklist: 'ref_data_gridss_region_blocklist', + gridss_pon_breakends: 'ref_data_gridss_pon_breakends', + gridss_pon_breakpoints: 'ref_data_gridss_pon_breakpoints', // Isofox - isofox_counts: 'ref_data_isofox_exp_counts', - isofox_gc_ratios: 'ref_data_isofox_exp_gc_ratios', + isofox_counts: 'ref_data_isofox_counts', + isofox_gc_ratios: 'ref_data_isofox_gc_ratios', // LINX - linx_fragile_regions: 'ref_data_linx_fragile_sites', + linx_fragile_regions: 'ref_data_linx_fragile_regions', linx_lines: 'ref_data_linx_lines', // SAGE - sage_blocklist_regions: 'ref_data_sage_blacklist_bed', - sage_blocklist_sites: 'ref_data_sage_blacklist_vcf', + sage_blocklist_regions: 'ref_data_sage_blocklist_regions', + sage_blocklist_sites: 'ref_data_sage_blocklist_sites', sage_coding_panel: 'ref_data_sage_coding_panel', - sage_highconf_regions: 'ref_data_sage_high_confidence', + sage_highconf_regions: 'ref_data_sage_highconf_regions', sage_known_hotspots_germline: 'ref_data_sage_known_hotspots_germline', sage_known_hotspots_somatic: 'ref_data_sage_known_hotspots_somatic', - sage_pon: 'ref_data_sage_pon_file', - clinvar_annotations: 'ref_data_clinvar_vcf', + sage_pon: 'ref_data_sage_pon', + clinvar_annotations: 'ref_data_clinvar_annotations', // SIGS sigs_signatures: 'ref_data_sigs_signatures', // LILAC - lilac_resources: 'ref_data_lilac_resource_dir', + lilac_resources: 'ref_data_lilac_resources', // Virus Interpreter - virus_taxonomy: 'ref_data_virus_taxonomy', - virus_reporting: 'ref_data_virus_reporting', + virus_taxonomy_db: 'ref_data_virus_taxonomy_db', + virus_reporting_db: 'ref_data_virus_reporting_db', // Misc purple_germline_del: 'ref_data_purple_germline_del', driver_gene_panel: 'ref_data_driver_gene_panel', - ensembl_data_resources: 'ref_data_ensembl_data_dir', + ensembl_data_resources: 'ref_data_ensembl_data_resources', known_fusion_data: 'ref_data_known_fusion_data', known_fusions: 'ref_data_known_fusions', - segment_mappability: 'ref_data_mappability_bed', + segment_mappability: 'ref_data_segment_mappability', ] params_mapping.collectEntries { k, v -> [k, getHmfDataFileObject(v, k, hmf_data_base, params_only)] diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index d283faa3..6546b8e2 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -751,8 +751,8 @@ workflow ONCOANALYSER { // Run process VIRUSINTERPRETER( ch_virusinterpreter_inputs, - hmf_data.virus_taxonomy, - hmf_data.virus_reporting, + hmf_data.virus_taxonomy_db, + hmf_data.virus_reporting_db, ) // Set outputs, restoring original meta From 7b75f513a92bff6b395929ff84dafbf7d56306a3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Dec 2022 22:52:18 +1100 Subject: [PATCH 047/562] Fix PAVE arguments --- modules/local/pave/germline/main.nf | 4 ++-- modules/local/pave/somatic/main.nf | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index d392641c..536e52cf 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -43,10 +43,10 @@ process PAVE_GERMLINE { -ref_genome ${genome_fasta} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -driver_gene_panel ${driver_gene_panel} \\ - -clinvar_annotations ${clinvar_annotations} \\ + -clinvar_vcf ${clinvar_annotations} \\ -blacklist_bed ${sage_blocklist_regions} \\ -blacklist_vcf ${sage_blocklist_sites} \\ - -segment_mappability ${segment_mappability} \\ + -mappability_bed ${segment_mappability} \\ -vcf_file ${sage_vcf} \\ -read_pass_only \\ -output_dir ./ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 7cc8d5ee..23edf378 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -39,7 +39,7 @@ process PAVE_SOMATIC { -driver_gene_panel ${driver_gene_panel} \\ -pon_file ${sage_pon} \\ -pon_filters "${pon_filters}" \\ - -segment_mappability ${segment_mappability} \\ + -mappability_bed ${segment_mappability} \\ -vcf_file ${sage_vcf} \\ -read_pass_only \\ -output_dir ./ From 986eefe1c96900931da26fe25e46d330fb9a6012 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 16 Dec 2022 01:33:32 +1100 Subject: [PATCH 048/562] Adjust GRIPSS genome version argument --- modules/local/gripss/germline/main.nf | 2 +- modules/local/gripss/somatic/main.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index c1504bca..7652c8a7 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -30,7 +30,7 @@ process GRIPSS_GERMLINE { -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.normal_id} \\ - -ref_genome_version ${genome_ver} \\ + -ref_genome_version V${genome_ver} \\ -ref_genome ${genome_fasta} \\ -pon_sgl_file ${pon_breakends} \\ -pon_sv_file ${pon_breakpoints} \\ diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index ac85deec..d8517911 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -31,7 +31,7 @@ process GRIPSS_SOMATIC { ${args} \\ -sample ${meta.tumor_id} \\ -reference ${meta.normal_id} \\ - -ref_genome_version ${genome_ver} \\ + -ref_genome_version V${genome_ver} \\ -ref_genome ${genome_fasta} \\ -pon_sgl_file ${pon_breakends} \\ -pon_sv_file ${pon_breakpoints} \\ From d071b92abc6aba69207565e14a516487062dae44 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 16 Dec 2022 01:57:29 +1100 Subject: [PATCH 049/562] Use correct identifier for Sigs --- modules/local/sigs/main.nf | 2 +- workflows/oncoanalyser.nf | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index aec67448..d094961a 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -24,7 +24,7 @@ process SIGS { java \\ -Xmx${task.memory.giga}g \\ -jar ${task.ext.jarPath} \\ - -sample ${meta.id} \\ + -sample ${meta.tumor_id} \\ -somatic_vcf_file ${smlv_vcf} \\ -signatures_file ${signatures} \\ -output_dir ./sigs/ diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 6546b8e2..62896617 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -578,7 +578,10 @@ workflow ONCOANALYSER { ch_sigs_inputs = ch_sigs_inputs_source .map { meta, purple_dir -> def smlv_vcf = file(purple_dir).resolve("${meta.get(['sample_name', Constants.DataType.TUMOR])}.purple.somatic.vcf.gz") - def meta_sigs = [id: meta.id] + def meta_sigs = [ + id: meta.id, + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + ] return [meta_sigs, smlv_vcf] } From 67f79333e6d708ec6d88a1b5cec358190c2e3e96 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 16 Dec 2022 11:57:35 +1100 Subject: [PATCH 050/562] Downgrade to gpgr v1.3.0 for LINX compatibility --- modules/local/gpgr/linx_report/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/gpgr/linx_report/main.nf b/modules/local/gpgr/linx_report/main.nf index 4098089f..f35dbe4a 100644 --- a/modules/local/gpgr/linx_report/main.nf +++ b/modules/local/gpgr/linx_report/main.nf @@ -2,7 +2,7 @@ process LINX_REPORT { tag "${meta.id}" label 'process_single' - container 'ghcr.io/umccr/gpgr:1.4.1' + container 'ghcr.io/umccr/gpgr:1.3.0' input: tuple val(meta), path(linx_annotation), path(linx_visualiser) From 53c698a66cc1b477b042d2da5f4545d00681268a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 16 Dec 2022 12:52:48 +1100 Subject: [PATCH 051/562] Update CUPPA arguments --- modules/local/cuppa/classifier/main.nf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index 54c1bc1c..41c90db2 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -18,6 +18,7 @@ process CUPPA_CLASSIFIER { script: def args = task.ext.args ?: '' def categories_arg = isofox_dir ? 'ALL' : 'DNA' + def gene_exp_arg = isofox_dir ? "-sample_gene_exp_file sample_data/${meta.id}.isf.gene_data.csv" : '' """ # Symlink input files into a single directory @@ -32,6 +33,9 @@ process CUPPA_CLASSIFIER { -ref_data_dir ${cuppa_resources} \\ -sample_data ${meta.id} \\ -sample_data_dir sample_data/ \\ + -sample_sv_file sample_data/${meta.id}.purple.sv.vcf.gz \\ + -sample_somatic_vcf sample_data/${meta.id}.purple.somatic.vcf.gz \\ + ${gene_exp_arg} \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information. From f68314dcfd36f99b39e01dec089b2022655b3eee Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 17 Dec 2022 11:25:18 +1100 Subject: [PATCH 052/562] Require BAI for Isofox process --- modules/local/isofox/main.nf | 2 +- workflows/oncoanalyser.nf | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index d228bbec..103402aa 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -5,7 +5,7 @@ process ISOFOX { container 'docker.io/scwatts/isofox:1.5--0' input: - tuple val(meta), path(bam) + tuple val(meta), path(bam), path(bai) path genome_fasta path genome_fai val genome_ver diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 62896617..c883aec7 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -150,8 +150,9 @@ workflow ONCOANALYSER { // channel: [meta_isofox, tumor_bam_wts] ch_isofox_inputs = ch_inputs_wts.present .map { meta -> + def bam = meta.get([Constants.FileType.BAM_WTS, Constants.DataType.TUMOR]) def meta_isofox = [key: meta.id, id: meta.get(['sample_name', Constants.DataType.TUMOR])] - return [meta_isofox, meta.get([Constants.FileType.BAM_WTS, Constants.DataType.TUMOR])] + return [meta_isofox, bam, "${bam}.bai"] } // Run process From 9231665a5914c72893a7b24ba2c3ea4e80ffedec Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 17 Dec 2022 11:25:25 +1100 Subject: [PATCH 053/562] Update LILAC arguments --- modules/local/lilac/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 31944e1c..5de4834f 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -22,8 +22,8 @@ process LILAC { def sample_name = getSampleName(meta, tumor_bam, normal_bam) def tumor_bam_arg = tumor_bam ? "-tumor_bam ${tumor_bam}" : '' def purple_args = purple_dir ? """ - -gene_copy_number ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ - -somatic_vcf ${purple_dir}/${sample_name}.purple.sv.vcf.gz \\ + -gene_copy_number_file ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ + -somatic_variants_file ${purple_dir}/${sample_name}.purple.sv.vcf.gz \\ """ : '' """ From 69d007096890eed813f123417574e31908cf927f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 17 Dec 2022 10:55:48 +1100 Subject: [PATCH 054/562] Add missing patch for CUPPA report script --- .../assets/CupGenerateReport_pipeline.R.patch | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch diff --git a/modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch b/modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch new file mode 100644 index 00000000..4e165976 --- /dev/null +++ b/modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch @@ -0,0 +1,31 @@ +--- a/CupGenerateReport_pipeline.R ++++ b/CupGenerateReport_pipeline.R +@@ -165,10 +165,10 @@ if (featureCount > featureLimit) + } + + # Generating PNG files +-outputFileSummary = paste0(cuppaDir, sampleId, '.cup.report.summary.png') ++outputFileSummary = paste0(sampleId, '.cup.report.summary.png') + if (separateFeaturePlot) + { +- outputFileFeatures = paste0(cuppaDir, sampleId, '.cup.report.features.png') ++ outputFileFeatures = paste0(sampleId, '.cup.report.features.png') + print(paste0("Writing output to png file: ", outputFileSummary)) + png(file = outputFileSummary, res = 140, height = 2200, width = 4000) + grid.arrange(plot_grid(summaryPlot, genderPlot, sigPlot, svTraitsPlot, +@@ -192,7 +192,7 @@ dev.off() + + # Generate PDF report with disclaimer + +-outputFile = paste0(cuppaDir, sampleId, '_cup_report.pdf') ++outputFile = paste0(sampleId, '_cup_report.pdf') + print(paste0("writing output to pdf file: ", outputFile)) + + pdf(file = outputFile, height = 14, width = 20) +@@ -214,4 +214,4 @@ if (separateFeaturePlot) + ncol = 1, nrow = 8, rel_heights = plotHeightsDisclaimer, align = 'v', axis = 'l') + } + +-dev.off() +\ No newline at end of file ++dev.off() From 3a1e41a5fa16de95cfdacde784939337d62cb5d4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 17 Dec 2022 10:56:03 +1100 Subject: [PATCH 055/562] Retrieve correct CUPPA chart scripts --- modules/local/cuppa/Dockerfile | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/modules/local/cuppa/Dockerfile b/modules/local/cuppa/Dockerfile index 9b9a13fe..a789d03f 100644 --- a/modules/local/cuppa/Dockerfile +++ b/modules/local/cuppa/Dockerfile @@ -12,16 +12,18 @@ RUN \ mkdir -p /opt/cuppa/ && \ wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.6/cuppa_v1.6.jar' -# NOTE(SW): required plotting scripts aren't available under the cuppa-v1.6 tag -ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.7/cuppa/src/main/resources +# NOTE(SW): required report script is only available from the cuppa-v1.7 tag and later +ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools +ARG URL_BASE_CHART=${URL_BASE}/cuppa-v1.6/cuppa/src/main/resources/cuppa-chart +ARG URL_BASE_REPORT=${URL_BASE}/cuppa-v1.7/cuppa/src/main/resources/r ARG DIR_BASE=/opt/cuppa RUN \ mkdir -p ${DIR_BASE}/{chart,report} && \ - wget -P ${DIR_BASE}/chart/ ${URL_BASE}/cuppa-chart/requirements.txt && \ - wget -P ${DIR_BASE}/chart/ ${URL_BASE}/cuppa-chart/cuppa-chart.py && \ - wget -P ${DIR_BASE}/chart/main/ ${URL_BASE}/cuppa-chart/main/create_chart.py && \ - wget -P ${DIR_BASE}/chart/main/ ${URL_BASE}/cuppa-chart/main/prepare_data.py && \ - wget -P ${DIR_BASE}/report/ ${URL_BASE}/r/CupGenerateReport_pipeline.R + wget -P ${DIR_BASE}/chart/ ${URL_BASE_CHART}/requirements.txt && \ + wget -P ${DIR_BASE}/chart/ ${URL_BASE_CHART}/cuppa-chart.py && \ + wget -P ${DIR_BASE}/chart/main/ ${URL_BASE_CHART}/main/create_chart.py && \ + wget -P ${DIR_BASE}/chart/main/ ${URL_BASE_CHART}/main/prepare_data.py && \ + wget -P ${DIR_BASE}/report/ ${URL_BASE_REPORT}/CupGenerateReport_pipeline.R COPY assets/CupGenerateReport_pipeline.R.patch /tmp/ RUN \ From b06f65075aa3506d64af6c8847a56b08776cdb1d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 17 Dec 2022 11:16:33 +1100 Subject: [PATCH 056/562] Remove TEAL --- conf/base.config | 4 - conf/modules.config | 9 -- lib/Constants.groovy | 1 - modules/local/teal/Dockerfile | 22 ----- modules/local/teal/main.nf | 54 ------------ modules/local/teal/meta.yml | 65 --------------- workflows/oncoanalyser.nf | 152 ++++++---------------------------- 7 files changed, 27 insertions(+), 280 deletions(-) delete mode 100644 modules/local/teal/Dockerfile delete mode 100644 modules/local/teal/main.nf delete mode 100644 modules/local/teal/meta.yml diff --git a/conf/base.config b/conf/base.config index 32de85a6..b9f0f574 100644 --- a/conf/base.config +++ b/conf/base.config @@ -129,10 +129,6 @@ process { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'TEAL' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } withName:'COLLECTWGSMETRICS' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } diff --git a/conf/modules.config b/conf/modules.config index 4d71d6ae..d4e6d9a3 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -177,15 +177,6 @@ process { ] } - withName: 'TEAL' { - ext.jarPath = '/opt/teal/teal.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, - ] - } - withName: 'VIRUSBREAKEND' { ext.jarPath = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' publishDir = [ diff --git a/lib/Constants.groovy b/lib/Constants.groovy index d25fc0c0..02bd2762 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -32,7 +32,6 @@ class Constants { PURPLE, SAGE, SIGS, - TEAL, VIRUSINTERPRETER, } diff --git a/modules/local/teal/Dockerfile b/modules/local/teal/Dockerfile deleted file mode 100644 index 79715d2c..00000000 --- a/modules/local/teal/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/teal/ && \ - wget -O /opt/teal/teal.jar 'https://github.com/hartwigmedical/hmftools/releases/download/teal-v1.0.1/teal-1.0.1.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - picard && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/teal/main.nf b/modules/local/teal/main.nf deleted file mode 100644 index 6f0cb586..00000000 --- a/modules/local/teal/main.nf +++ /dev/null @@ -1,54 +0,0 @@ -process TEAL { - tag "${meta.id}" - label 'process_medium' - - container 'docker.io/scwatts/teal:1.0.1--2' - - input: - tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai), path(tumor_wgs_metrics), path(normal_wgs_metrics), path(cobalt_dir), path(purple_dir) - - output: - tuple val(meta), path('teal/'), emit: teal_dir - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def tumor_args = normal_bam ? """ - -tumor ${meta.tumor_id} - -tumor_bam ${tumor_bam} - -tumor_wgs_metrics ${tumor_wgs_metrics} - """ : '' - def reference_args = normal_bam ? """ - -reference ${meta.normal_id} - -reference_bam ${normal_bam} - -reference_wgs_metrics ${normal_wgs_metrics} - """ : '' - - """ - java \\ - -Xmx${task.memory.giga}g \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - ${tumor_args.replaceAll('\n', '')} \\ - ${reference_args.replaceAll('\n', '')} \\ - -cobalt ${cobalt_dir} \\ - -purple ${purple_dir} \\ - -threads ${task.cpus} \\ - -output_dir teal/ - - # NOTE(SW): hard coded since there is no reliable way to obtain version information. - cat <<-END_VERSIONS > versions.yml - "${task.process}": - teal: 1.0.1 - END_VERSIONS - """ - - stub: - """ - mkdir -p teal/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/teal/meta.yml b/modules/local/teal/meta.yml deleted file mode 100644 index 74234dba..00000000 --- a/modules/local/teal/meta.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: "TEAL" -description: TEAL measures telomere content, and estimates telomeric length based on WGS read data -keywords: - - teal - - telomere -tools: - - "TEAL": - description: "TEAL measures telomere content, and estimates telomeric length based on WGS read data." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/teal" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/teal" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/teal" - doi: "" - licence: "['GPL v3']" - -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] - - tumor_bam: - type: file - description: Optional tumor BAM file - pattern: "*.{bam}" - - normal_bam: - type: file - description: Optional normal BAM file - pattern: "*.{bam}" - - tumor_bai: - type: file - description: Tumor BAI file - pattern: "*.{bai}" - - normal_bai: - type: file - description: Normal BAI file - pattern: "*.{bai}" - - tumor_wgs_metrics: - type: file - description: Optional tumor WGS metrics file - - normal_wgs_metrics: - type: file - description: Optional normal WGS metrics file - - cobalt_dir: - type: directory - description: COBALT output directory - - purple_dir: - type: directory - description: PURPLE output directory - -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] - - teal_dir: - type: directory - description: TEAL output directory - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - -authors: - - "@scwatts" diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index c883aec7..fd546596 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -65,7 +65,6 @@ include { ISOFOX } from '../modules/local/isofox/main' include { LINX_REPORT } from '../modules/local/gpgr/linx_report/main' include { PURPLE } from '../modules/local/purple/main' include { SIGS } from '../modules/local/sigs/main' -include { TEAL } from '../modules/local/teal/main' include { VIRUSBREAKEND } from '../modules/local/virusbreakend/main' include { VIRUSINTERPRETER } from '../modules/local/virusinterpreter/main' @@ -119,7 +118,7 @@ workflow ONCOANALYSER { hmf_data = PREPARE_REFERENCE.out.hmf_data // Set up channel with common inputs for several processes - if (run.amber || run.cobalt || run.pave || run.lilac || run.teal) { + if (run.amber || run.cobalt || run.pave || run.lilac) { // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] ch_bams_and_indices = ch_inputs .map { meta -> @@ -171,90 +170,6 @@ workflow ONCOANALYSER { ch_isofox_out = ch_isofox_out.mix(WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs)) } - // - // MODULE: Run COLLECTWGSMETRICS to generate stats required for downstream processes - // - if (run.virusinterpreter || run.teal) { - // Create inputs and create process-specific meta - // NOTE(SW): CUPPA only requires collectwgsmetrics for the tumor sample in the upstream - // process Virus Interpreter but TEAL currently requires collectwgsmetrics for both tumor - // and normal sample - // channel: [val(meta_cwm), bam] - ch_cwm_inputs_all = ch_inputs - .flatMap { meta -> - def sample_types = run.teal ? [Constants.DataType.TUMOR, Constants.DataType.NORMAL] : [Constants.DataType.TUMOR] - return sample_types - .collect { sample_type -> - def bam = meta.get([Constants.FileType.BAM_WGS, sample_type]) - def sample_name = meta.get(['sample_name', sample_type]) - def meta_cwm = [ - key: meta.id, - id: sample_name, - // NOTE(SW): must use string representation for caching purposes - sample_type: sample_type.name(), - ] - return [meta_cwm, bam] - } - } - - // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples - // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent - // on any process - // channel: [val(meta_cwm), bam] - ch_cwm_inputs = ch_cwm_inputs_all - .map { [it[1..-1], it[0]] } - .groupTuple() - .map { filepaths, meta_cwm -> - def (keys, sample_names, sample_types) = meta_cwm - .collect { - [it.key, it.id, it.sample_type] - } - .transpose() - - def sample_types_unique = sample_types.unique(false) - assert sample_types_unique.size() == 1 - def sample_type = sample_types_unique[0] - - def meta_cwm_new = [ - keys: keys, - id: sample_names.join('__'), - id_simple: keys.join('__'), - sample_type: sample_type, - ] - return [meta_cwm_new, *filepaths] - } - - // Run process - COLLECTWGSMETRICS( - ch_cwm_inputs, - PREPARE_REFERENCE.out.genome_fasta, - ) - - // Set outputs, process outputs and restore original meta - ch_versions = ch_versions.mix(COLLECTWGSMETRICS.out.versions) - - // Replicate outputs to reverse unique operation - // channel: [val(meta_cwm_individual), sample_type, metrics] - ch_cwm_output_individual = COLLECTWGSMETRICS.out.metrics - .flatMap { meta_cwm_shared, metrics -> - meta_cwm_shared.keys.collect { key -> - return [meta_cwm_shared + [key: key], meta_cwm_shared.sample_type, metrics] - } - } - - // Match outputs to original meta and set output - // channel (tumor): [val(meta), metrics] - // channel (normal): [val(meta), metrics] - ch_cwm_output = WorkflowOncoanalyser.restoreMeta(ch_cwm_output_individual, ch_inputs) - .branch { meta, sample_type_str, metrics -> - def sample_type = Utils.getEnumFromString(sample_type_str, Constants.DataType) - tumor: sample_type == Constants.DataType.TUMOR - return [meta, metrics] - normal: sample_type == Constants.DataType.NORMAL - return [meta, metrics] - } - } - // // MODULE: Run AMBER to obtain b-allele frequencies // @@ -628,44 +543,6 @@ workflow ONCOANALYSER { ch_versions = ch_versions.mix(CHORD.out.versions) } - // - // MODULE: Run TEAL to characterise teleomeres - // - if (run.teal) { - // Select input sources - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, tumor_wgs_metrics, normal_wgs_metrics, cobalt_dir, purple_dir] - // NOTE(SW): assuming here that TEAL is being run in tumor/normal mode and so we expect a tumor metrics file and normal metrics file - ch_teal_inputs_source = WorkflowOncoanalyser.groupByMeta( - ch_bams_and_indices, - run.collectwgsmetrics ? ch_cwm_output.tumor : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COLLECTWGSMETRICS, Constants.DataType.TUMOR]), - run.collectwgsmetrics ? ch_cwm_output.normal : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COLLECTWGSMETRICS, Constants.DataType.NORMAL]), - run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COBALT_DIR, Constants.DataType.TUMOR_NORMAL]), - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), - ) - - // Create inputs and create process-specific meta - // channel: [val(meta_teal), tumor_bam, normal_bam, tumor_bai, normal_bai, tumor_wgs_metrics, normal_wgs_metrics, cobalt_dir, purple_dir] - ch_teal_inputs = ch_teal_inputs_source - .map { - def meta = it[0] - def other = it[1..-1] - def meta_teal = [ - id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), - normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), - ] - return [meta_teal, *other] - } - - // Run process - TEAL( - ch_teal_inputs, - ) - - // Set outputs - ch_versions = ch_versions.mix(TEAL.out.versions) - } - // // SUBWORKFLOW: Run LILAC for HLA typing and somatic CNV and SNV calling // @@ -697,6 +574,30 @@ workflow ONCOANALYSER { // NOTE(SW): kept separate from CUPPA conditional block since we'll allow users to run this independently ch_virusinterpreter_out = Channel.empty() if (run.virusinterpreter) { + // collectwgsmetrics + // Create inputs and create process-specific meta + // channel: [val(meta_cwm), bam] + ch_cwm_inputs = ch_inputs + .map { meta -> + def bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) + def meta_cwm = [ + key: meta.id, + id: meta.get(['sample_name', Constants.DataType.TUMOR]), + ] + return [meta_cwm, bam] + } + + // Run process + COLLECTWGSMETRICS( + ch_cwm_inputs, + PREPARE_REFERENCE.out.genome_fasta, + ) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix(COLLECTWGSMETRICS.out.versions) + ch_cwm_out = WorkflowOncoanalyser.restoreMeta(COLLECTWGSMETRICS.out.metrics, ch_inputs) + + // VIRUSBreakend // Create inputs and create process-specific meta // channel: [val(meta_virus), tumor_bam] ch_virusbreakend_inputs = ch_inputs @@ -737,9 +638,10 @@ workflow ONCOANALYSER { ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), ch_virusinterpreter_inputs_purple, - ch_cwm_output.tumor, + ch_cwm_out, ) + // Virus Interpreter // Create inputs and create process-specific meta // channel: [val(meta_virus), virus_tsv, purple_purity, purple_qc, wgs_metrics] ch_virusinterpreter_inputs = ch_virusinterpreter_inputs_full From cbbef8748d74a811eb62b6a7f239681c142560e0 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 17 Dec 2022 18:45:47 +1100 Subject: [PATCH 057/562] Write SAGE BQR data and use coverage panels --- conf/hmfdata.config | 1 + modules/local/sage/germline/main.nf | 8 +++++++- modules/local/sage/somatic/main.nf | 7 ++++++- nextflow_schema.json | 7 +++++++ subworkflows/local/prepare_reference.nf | 1 + subworkflows/local/sage.nf | 2 ++ workflows/oncoanalyser.nf | 1 + 7 files changed, 25 insertions(+), 2 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 19918f02..f52bb088 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -21,6 +21,7 @@ params { sage_blocklist_regions = 'sage/KnownBlacklist.germline.37.bed' sage_blocklist_sites = 'sage/KnownBlacklist.germline.37.vcf.gz' sage_coding_panel = 'sage/ActionableCodingPanel.37.bed.gz' + sage_coverage_panel_germline = 'sage/CoverageCodingPanel.germline.37.bed.gz' sage_highconf_regions = 'giab_high_conf/NA12878_GIAB_highconf_IllFB-IllGATKHC-CG-Ion-Solid_ALLCHROM_v3.2.2_highconf.bed.gz' sage_known_hotspots_germline = 'sage/KnownHotspots.germline.37.vcf.gz' sage_known_hotspots_somatic = 'sage/KnownHotspots.somatic.37.vcf.gz' diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index d0547147..b18f7147 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -1,3 +1,5 @@ +// NOTE(SW): 3.0.3 logic that determines BQR outputs assumes '-out' is a path that includes at least one directory + process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' @@ -12,6 +14,7 @@ process SAGE_GERMLINE { val genome_ver path sage_known_hotspots_germline path sage_coding_panel + path sage_coverage_panel_germline path sage_highconf_regions path ensembl_data_resources @@ -38,6 +41,7 @@ process SAGE_GERMLINE { -ref_genome ${genome_fasta} \\ -hotspots ${sage_known_hotspots_germline} \\ -panel_bed ${sage_coding_panel} \\ + -coverage_bed ${sage_coverage_panel_germline} \\ -high_confidence_bed ${sage_highconf_regions} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -hotspot_min_tumor_qual 50 \\ @@ -48,8 +52,10 @@ process SAGE_GERMLINE { -panel_max_germline_rel_raw_base_qual 100 \\ -mnv_filter_enabled false \\ -panel_only \\ + -write_bqr_data \\ + -write_bqr_plot \\ -threads ${task.cpus} \\ - -out ${meta.tumor_id}.sage_germline.vcf.gz + -out ./${meta.tumor_id}.sage_germline.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index cf017143..5e542d7b 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -1,3 +1,5 @@ +// NOTE(SW): logic that determines BQR outputs assumes '-out' is a path that includes at least one directory + process SAGE_SOMATIC { tag "${meta.id}" label 'process_medium' @@ -38,10 +40,13 @@ process SAGE_SOMATIC { -ref_genome ${genome_fasta} \\ -hotspots ${sage_known_hotspots_somatic} \\ -panel_bed ${sage_coding_panel} \\ + -coverage_bed ${sage_coding_panel} \\ -high_confidence_bed ${sage_highconf_regions} \\ -ensembl_data_dir ${ensembl_data_resources} \\ + -write_bqr_data \\ + -write_bqr_plot \\ -threads ${task.cpus} \\ - -out ${meta.tumor_id}.sage_somatic.vcf.gz + -out ./${meta.tumor_id}.sage_somatic.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/nextflow_schema.json b/nextflow_schema.json index 46d9adc1..0aa1a156 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -285,6 +285,13 @@ "description": "Path to HMF SAGE panel of normals file.", "fa_icon": "far fa-file-code" }, + "ref_data_sage_coverage_panel_germline": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed\\.gz$", + "description": "Path to HMF SAGE germline coverage panel file.", + "fa_icon": "far fa-file-code" + }, "ref_data_sage_highconf_regions": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 2ef9750c..d8fd6d52 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -144,6 +144,7 @@ def createHmfDataMap(hmf_data_base, params_only) { sage_blocklist_regions: 'ref_data_sage_blocklist_regions', sage_blocklist_sites: 'ref_data_sage_blocklist_sites', sage_coding_panel: 'ref_data_sage_coding_panel', + sage_coverage_panel_germline: 'ref_data_sage_coverage_panel_germline', sage_highconf_regions: 'ref_data_sage_highconf_regions', sage_known_hotspots_germline: 'ref_data_sage_known_hotspots_germline', sage_known_hotspots_somatic: 'ref_data_sage_known_hotspots_somatic', diff --git a/subworkflows/local/sage.nf b/subworkflows/local/sage.nf index 9b1655e0..740d2c9d 100644 --- a/subworkflows/local/sage.nf +++ b/subworkflows/local/sage.nf @@ -15,6 +15,7 @@ workflow SAGE { ref_data_sage_known_hotspots_germline // file: /path/to/sage_known_hotspots_germline ref_data_sage_known_hotspots_somatic // file: /path/to/sage_known_hotspots_somatic ref_data_sage_coding_panel // file: /path/to/sage_coding_panel + ref_data_sage_coverage_panel_germline // file: /path/to/sage_coverage_panel_germline ref_data_sage_highconf_regions // file: /path/to/sage_highconf_regions ref_data_sage_pon // file: /path/to/sage_pon ref_data_segment_mappability // file: /path/to/segment_mappability @@ -34,6 +35,7 @@ workflow SAGE { ref_data_genome_version, ref_data_sage_known_hotspots_germline, ref_data_sage_coding_panel, + ref_data_sage_coverage_panel_germline, ref_data_sage_highconf_regions, ref_data_ensembl_data_resources, ) diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index fd546596..0a303818 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -338,6 +338,7 @@ workflow ONCOANALYSER { hmf_data.sage_known_hotspots_germline, hmf_data.sage_known_hotspots_somatic, hmf_data.sage_coding_panel, + hmf_data.sage_coverage_panel_germline, hmf_data.sage_highconf_regions, hmf_data.sage_pon, hmf_data.segment_mappability, From f80e030d538482d39e78d6d0995db4a3d81a23e1 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 18 Dec 2022 12:34:57 +1100 Subject: [PATCH 058/562] Correct PURPLE germline del freq file --- modules/local/purple/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 81168a0b..02864d85 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -28,7 +28,7 @@ process PURPLE { def args = task.ext.args ?: '' def smlv_tumor_vcf_fp = smlv_tumor_vcf ?: '' def smlv_normal_vcf_fp = smlv_normal_vcf ?: '' - def germline_del_arg = germline_del ? "-germline_del_file ${germline_del}" : '' + def germline_del_arg = germline_del ? "-germline_del_freq_file ${germline_del}" : '' """ # For provided smlv VCFs, filter records that do not contain the required FORMAT/AD field and From 6fdf1de72a275d3967c76cbb601de03133dcb12e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 18 Dec 2022 13:04:16 +1100 Subject: [PATCH 059/562] Update collectwgsmetrics output directory --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index d4e6d9a3..37db0892 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -137,7 +137,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/wgs_metrics/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/wgs_metrics/${filename}" }, ] } From cb176ae675c7d2b4355b25bd6aab92d4cb9d177b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 18 Dec 2022 16:20:30 +1100 Subject: [PATCH 060/562] Add SAGE optional outputs, reorganise output dirs --- conf/modules.config | 13 +++++++++++-- modules/local/sage/germline/main.nf | 5 ++++- modules/local/sage/somatic/main.nf | 5 ++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 37db0892..4a20cbfd 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -151,12 +151,21 @@ process { ] } - withName: 'SAGE.*' { + withName: 'SAGE_GERMLINE' { ext.jarPath = '/opt/sage/sage.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/germline/${filename}" }, + ] + } + + withName: 'SAGE_SOMATIC' { + ext.jarPath = '/opt/sage/sage.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/somatic/${filename}" }, ] } diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index b18f7147..58cd1740 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -20,7 +20,10 @@ process SAGE_GERMLINE { output: tuple val(meta), path("${meta.tumor_id}.sage_germline.vcf.gz"), emit: vcf - path 'versions.yml' , emit: versions + path '*gene.coverage.tsv' , emit: gene_coverage, optional: true + path '*sage.bqr.png' , emit: bqr_png, optional: true + path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 5e542d7b..30a52b25 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -19,7 +19,10 @@ process SAGE_SOMATIC { output: tuple val(meta), path("${meta.tumor_id}.sage_somatic.vcf.gz"), emit: vcf - path 'versions.yml' , emit: versions + path '*gene.coverage.tsv' , emit: gene_coverage, optional: true + path '*sage.bqr.png' , emit: bqr_png, optional: true + path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when From e9bd36a77d5cadd1343975bf461228446e4dcaf4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 20:13:57 +1100 Subject: [PATCH 061/562] Add PEACH --- conf/base.config | 4 +++ conf/hmfdata.config | 2 ++ conf/modules.config | 9 +++++ lib/Constants.groovy | 1 + modules/local/peach/Dockerfile | 37 ++++++++++++++++++++ modules/local/peach/main.nf | 46 +++++++++++++++++++++++++ nextflow_schema.json | 7 ++++ subworkflows/local/prepare_reference.nf | 2 ++ workflows/oncoanalyser.nf | 42 ++++++++++++++++++++++ 9 files changed, 150 insertions(+) create mode 100644 modules/local/peach/Dockerfile create mode 100644 modules/local/peach/main.nf diff --git a/conf/base.config b/conf/base.config index b9f0f574..7831a4ff 100644 --- a/conf/base.config +++ b/conf/base.config @@ -147,4 +147,8 @@ process { withName:'CUPPA.*' { memory = { check_max( 12.GB, 'memory' ) } } + withName:'PEACH' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } } diff --git a/conf/hmfdata.config b/conf/hmfdata.config index f52bb088..df0052de 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -27,6 +27,8 @@ params { sage_known_hotspots_somatic = 'sage/KnownHotspots.somatic.37.vcf.gz' sage_pon = 'sage/SageGermlinePon.1000x.37.tsv.gz' clinvar_annotations = 'sage/clinvar.37.vcf.gz' + // PEACH + peach_panel = 'peach/min_DPYD.json' // SIGS sigs_signatures = 'sigs/snv_cosmic_signatures.csv' // LILAC diff --git a/conf/modules.config b/conf/modules.config index 4a20cbfd..fb0b857d 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -232,4 +232,13 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/cuppa/${filename}" }, ] } + + withName: 'PEACH' { + ext.scriptPath = '/opt/peach/src/main.py' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/peach/${filename}" }, + ] + } } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 02bd2762..f0ad4457 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -29,6 +29,7 @@ class Constants { LILAC, LINX, PAVE, + PEACH, PURPLE, SAGE, SIGS, diff --git a/modules/local/peach/Dockerfile b/modules/local/peach/Dockerfile new file mode 100644 index 00000000..00ceee56 --- /dev/null +++ b/modules/local/peach/Dockerfile @@ -0,0 +1,37 @@ +FROM mambaorg/micromamba:0.24.0 + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + chardet \ + cython \ + dask \ + mypy \ + numpy \ + 'openjdk >=8' \ + pandas \ + scikit-allel \ + zlib && \ + micromamba clean --all --yes + +USER root + +RUN \ + apt-get update && \ + apt-get install -y build-essential git procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" + +RUN \ + pip install 'TransVar==2.5.8.20190813' + +RUN \ + git clone https://github.com/hartwigmedical/peach.git -b v1.6 /opt/peach/ + +RUN \ + apt-get remove -y build-essential git && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +USER mambauser diff --git a/modules/local/peach/main.nf b/modules/local/peach/main.nf new file mode 100644 index 00000000..a7379449 --- /dev/null +++ b/modules/local/peach/main.nf @@ -0,0 +1,46 @@ +process PEACH { + tag "${meta.id}" + label 'process_single' + + container 'docker.io/scwatts/peach:1.6--0' + + input: + tuple val(meta), path(germline_vcf) + val genome_ver + path panel + + output: + tuple val(meta), path('*.genotype.tsv'), emit: genotype + path '*.calls.tsv' , emit: calls + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def tool_version = '1.6' + + """ + python ${task.ext.scriptPath} \\ + --sample_t_id ${meta.tumor_id} \\ + --sample_r_id ${meta.normal_id} \\ + --vcf ${germline_vcf} \\ + --vcf_reference_assembly_version V${genome_ver} \\ + --panel ${panel} \\ + --tool_version ${tool_version} \\ + --outputdir ./ + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + peach: ${tool_version} + END_VERSIONS + """ + + stub: + """ + touch "${meta.tumor_id}.peach.calls.tsv" + touch "${meta.tumor_id}.peach.genotype.tsv" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/nextflow_schema.json b/nextflow_schema.json index 0aa1a156..46d6eef5 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -320,6 +320,13 @@ "description": "Path to somatic SAGE known hotspots file.", "fa_icon": "far fa-file-code" }, + "ref_data_peach_panel": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.json$", + "description": "Path to PEACH panel file.", + "fa_icon": "far fa-file-code" + }, "ref_data_sigs_signatures": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index d8fd6d52..3c738205 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -150,6 +150,8 @@ def createHmfDataMap(hmf_data_base, params_only) { sage_known_hotspots_somatic: 'ref_data_sage_known_hotspots_somatic', sage_pon: 'ref_data_sage_pon', clinvar_annotations: 'ref_data_clinvar_annotations', + // PEACH + peach_panel: 'ref_data_peach_panel', // SIGS sigs_signatures: 'ref_data_sigs_signatures', // LILAC diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 0a303818..df0da6d3 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -63,6 +63,7 @@ include { CUPPA_CLASSIFIER } from '../modules/local/cuppa/classifier/main' include { CUPPA_VISUALISER } from '../modules/local/cuppa/visualiser/main' include { ISOFOX } from '../modules/local/isofox/main' include { LINX_REPORT } from '../modules/local/gpgr/linx_report/main' +include { PEACH } from '../modules/local/peach/main' include { PURPLE } from '../modules/local/purple/main' include { SIGS } from '../modules/local/sigs/main' include { VIRUSBREAKEND } from '../modules/local/virusbreakend/main' @@ -744,6 +745,47 @@ workflow ONCOANALYSER { ch_versions = ch_versions.mix(LINX_REPORT.out.versions) } + // + // MODULE: Run PEACH to match germline SNVs with pharmacogenetic evidence + // + // channel: [val(meta), peach_genotype] + ch_peach_out = Channel.empty() + if (run.peach) { + // Select input sources + // channel: [val(meta), purple_dir] + if (run.purple) { + ch_peach_inputs_source = ch_purple_out + } else { + ch_peach_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) + } + + // Create inputs and create process-specific meta + // channel: [meta_peach, purple_germline_vcf] + ch_peach_inputs = ch_peach_inputs_source + .map { meta, purple_dir -> + def meta_peach = [ + key: meta.id, + id: meta.id, + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + ] + def purple_germline_vcf = file(purple_dir).resolve("${meta.get(['sample_name', Constants.DataType.TUMOR])}.purple.germline.vcf.gz") + file(purple_germline_vcf, checkIfExists: true) + return [meta_peach, purple_germline_vcf] + } + + // Run process + PEACH( + ch_peach_inputs, + PREPARE_REFERENCE.out.genome_version, + hmf_data.peach_panel, + ) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix(PEACH.out.versions) + ch_peach_out = ch_peach_out.mix(WorkflowOncoanalyser.restoreMeta(PEACH.out.genotype, ch_inputs)) + } + // // MODULE: Run CUPPA predict tissue of origin // From e5d78ea252ec8864bb8adc1eb1876713d296dd31 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 20:16:00 +1100 Subject: [PATCH 062/562] Selectively run collectwgsmetrics for normal --- conf/base.config | 2 +- conf/modules.config | 4 +- conf/test.config | 2 +- workflows/oncoanalyser.nf | 111 +++++++++++++++++++++++++++++--------- 4 files changed, 90 insertions(+), 29 deletions(-) diff --git a/conf/base.config b/conf/base.config index 7831a4ff..910cdcb7 100644 --- a/conf/base.config +++ b/conf/base.config @@ -129,7 +129,7 @@ process { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'COLLECTWGSMETRICS' { + withName:'PICARD_COLLECTWGSMETRICS' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } time = { check_max( 24.h , 'time' ) } diff --git a/conf/modules.config b/conf/modules.config index fb0b857d..9c3103af 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -133,11 +133,11 @@ process { ] } - withName: 'COLLECTWGSMETRICS' { + withName: 'PICARD_COLLECTWGSMETRICS' { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/wgs_metrics/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/wgs_metrics/${filename}" }, ] } diff --git a/conf/test.config b/conf/test.config index dfa7d563..53ec948b 100644 --- a/conf/test.config +++ b/conf/test.config @@ -22,7 +22,7 @@ process { ext.args = '-specific_regions \'chr10:87736200:88056500;chr17:59748500:59828700\'' } - withName: 'COLLECTWGSMETRICS' { + withName: 'PICARD_COLLECTWGSMETRICS' { // NOTE(SW): wrapped by a closure to delay eval until process creation/execution ext.args = { "--INTERVALS ${params.ref_data_wgsmetrics_intervals_local}" } } diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index df0da6d3..0bc9cc5a 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -91,7 +91,7 @@ include { SAGE } from '../subworkflows/local/sage' // MODULES // include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' -include { PICARD_COLLECTWGSMETRICS as COLLECTWGSMETRICS } from '../modules/nf-core/picard/collectwgsmetrics/main' +include { PICARD_COLLECTWGSMETRICS } from '../modules/nf-core/picard/collectwgsmetrics/main' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -171,6 +171,90 @@ workflow ONCOANALYSER { ch_isofox_out = ch_isofox_out.mix(WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs)) } + // + // MODULE: Run PICARD_COLLECTWGSMETRICS to generate stats required for downstream processes + // + if (run.virusinterpreter || run.orange) { + // Create inputs and create process-specific meta + // NOTE(SW): CUPPA only requires collectwgsmetrics for the tumor sample in the upstream + // process Virus Interpreter but ORANGE currently requires collectwgsmetrics for both tumor + // and normal sample + // channel: [val(meta_cwm), bam] + ch_cwm_inputs_all = ch_inputs + .flatMap { meta -> + def sample_types = run.orange ? [Constants.DataType.TUMOR, Constants.DataType.NORMAL] : [Constants.DataType.TUMOR] + return sample_types + .collect { sample_type -> + def bam = meta.get([Constants.FileType.BAM_WGS, sample_type]) + def sample_name = meta.get(['sample_name', sample_type]) + def meta_cwm = [ + key: meta.id, + id: sample_name, + // NOTE(SW): must use string representation for caching purposes + sample_type_str: sample_type.name(), + ] + return [meta_cwm, bam] + } + } + + // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples + // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent + // on any process + // channel: [val(meta_cwm), bam] + ch_cwm_inputs = ch_cwm_inputs_all + .map { [it[1..-1], it[0]] } + .groupTuple() + .map { filepaths, meta_cwm -> + def (keys, sample_names, sample_type_strs) = meta_cwm + .collect { + [it.key, it.id, it.sample_type_str] + } + .transpose() + + def sample_type_strs_unique = sample_type_strs.unique(false) + assert sample_type_strs_unique.size() == 1 + def sample_type_str = sample_type_strs_unique[0] + + def meta_cwm_new = [ + keys: keys, + id: sample_names.join('__'), + id_simple: keys.join('__'), + sample_type_str: sample_type_str, + ] + return [meta_cwm_new, *filepaths] + } + + // Run process + PICARD_COLLECTWGSMETRICS( + ch_cwm_inputs, + PREPARE_REFERENCE.out.genome_fasta, + ) + + // Set outputs, process outputs and restore original meta + ch_versions = ch_versions.mix(PICARD_COLLECTWGSMETRICS.out.versions) + + // Replicate outputs to reverse unique operation + // channel: [val(meta_cwm_individual), sample_type_str, metrics] + ch_cwm_out_individual = PICARD_COLLECTWGSMETRICS.out.metrics + .flatMap { meta_cwm_shared, metrics -> + meta_cwm_shared.keys.collect { key -> + return [meta_cwm_shared + [key: key], meta_cwm_shared.sample_type_str, metrics] + } + } + + // Match outputs to original meta and set output + // channel (tumor): [val(meta), metrics] + // channel (normal): [val(meta), metrics] + ch_cwm_out = WorkflowOncoanalyser.restoreMeta(ch_cwm_out_individual, ch_inputs) + .branch { meta, sample_type_str, metrics -> + def sample_type = Utils.getEnumFromString(sample_type_str, Constants.DataType) + somatic: sample_type == Constants.DataType.TUMOR + return [meta, metrics] + germline: sample_type == Constants.DataType.NORMAL + return [meta, metrics] + } + } + // // MODULE: Run AMBER to obtain b-allele frequencies // @@ -576,29 +660,6 @@ workflow ONCOANALYSER { // NOTE(SW): kept separate from CUPPA conditional block since we'll allow users to run this independently ch_virusinterpreter_out = Channel.empty() if (run.virusinterpreter) { - // collectwgsmetrics - // Create inputs and create process-specific meta - // channel: [val(meta_cwm), bam] - ch_cwm_inputs = ch_inputs - .map { meta -> - def bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) - def meta_cwm = [ - key: meta.id, - id: meta.get(['sample_name', Constants.DataType.TUMOR]), - ] - return [meta_cwm, bam] - } - - // Run process - COLLECTWGSMETRICS( - ch_cwm_inputs, - PREPARE_REFERENCE.out.genome_fasta, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(COLLECTWGSMETRICS.out.versions) - ch_cwm_out = WorkflowOncoanalyser.restoreMeta(COLLECTWGSMETRICS.out.metrics, ch_inputs) - // VIRUSBreakend // Create inputs and create process-specific meta // channel: [val(meta_virus), tumor_bam] @@ -640,7 +701,7 @@ workflow ONCOANALYSER { ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), ch_virusinterpreter_inputs_purple, - ch_cwm_out, + ch_cwm_out.somatic, ) // Virus Interpreter From 425338947141c17f103ecf08f5df51e26d221cf9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 20:17:33 +1100 Subject: [PATCH 063/562] Add PROTECT --- conf/base.config | 4 ++ conf/hmfdata.config | 2 + conf/modules.config | 9 ++++ lib/Constants.groovy | 1 + modules/local/protect/Dockerfile | 22 ++++++++++ modules/local/protect/main.nf | 58 +++++++++++++++++++++++++ nextflow_schema.json | 6 +++ subworkflows/local/prepare_reference.nf | 2 + workflows/oncoanalyser.nf | 47 ++++++++++++++++++++ 9 files changed, 151 insertions(+) create mode 100644 modules/local/protect/Dockerfile create mode 100644 modules/local/protect/main.nf diff --git a/conf/base.config b/conf/base.config index 910cdcb7..f5061a15 100644 --- a/conf/base.config +++ b/conf/base.config @@ -151,4 +151,8 @@ process { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } + withName:'PROTECT' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } } diff --git a/conf/hmfdata.config b/conf/hmfdata.config index df0052de..857b718a 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -29,6 +29,8 @@ params { clinvar_annotations = 'sage/clinvar.37.vcf.gz' // PEACH peach_panel = 'peach/min_DPYD.json' + // PROTECT + serve_resources = 'serve/' // SIGS sigs_signatures = 'sigs/snv_cosmic_signatures.csv' // LILAC diff --git a/conf/modules.config b/conf/modules.config index 9c3103af..3d5343b2 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -233,6 +233,15 @@ process { ] } + withName: 'PROTECT' { + ext.jarPath = '/opt/protect/protect.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/protect/${filename}" }, + ] + } + withName: 'PEACH' { ext.scriptPath = '/opt/peach/src/main.py' publishDir = [ diff --git a/lib/Constants.groovy b/lib/Constants.groovy index f0ad4457..5e672569 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -30,6 +30,7 @@ class Constants { LINX, PAVE, PEACH, + PROTECT, PURPLE, SAGE, SIGS, diff --git a/modules/local/protect/Dockerfile b/modules/local/protect/Dockerfile new file mode 100644 index 00000000..e78e4db2 --- /dev/null +++ b/modules/local/protect/Dockerfile @@ -0,0 +1,22 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/protect/ && \ + wget -O /opt/protect/protect.jar 'https://github.com/hartwigmedical/hmftools/releases/download/protect-v2.2/protect.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'openjdk >=8' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/protect/main.nf b/modules/local/protect/main.nf new file mode 100644 index 00000000..c9216041 --- /dev/null +++ b/modules/local/protect/main.nf @@ -0,0 +1,58 @@ +process PROTECT { + tag "${meta.id}" + label 'process_single' + + container 'docker.io/scwatts/protect:2.2--0' + + input: + tuple val(meta), path(chord_prediction), path(purple_dir), path(linx_dir), path(virusinterpreter) + val genome_ver + path serve_resources + path disease_ontology + + output: + tuple val(meta), path('*.protect.tsv'), emit: tsv + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar ${task.ext.jarPath} \\ + -tumor_sample_id ${meta.tumor_id} \\ + -reference_sample_id ${meta.normal_id} \\ + -primary_tumor_doids '' \\ + -output_dir ./ \\ + -serve_actionability_dir ${serve_resources} \\ + -ref_genome_version ${genome_ver} \\ + -doid_json ${disease_ontology} \\ + -chord_prediction_txt ${chord_prediction} \\ + -purple_purity_tsv ${purple_dir}/${meta.tumor_id}.purple.purity.tsv \\ + -purple_qc_file ${purple_dir}/${meta.tumor_id}.purple.qc \\ + -purple_gene_copy_number_tsv ${purple_dir}/${meta.tumor_id}.purple.cnv.gene.tsv \\ + -purple_somatic_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.purple.driver.catalog.somatic.tsv \\ + -purple_germline_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.purple.driver.catalog.germline.tsv \\ + -purple_somatic_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.somatic.vcf.gz \\ + -purple_germline_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.germline.vcf.gz \\ + -linx_fusion_tsv ${linx_dir}/${meta.tumor_id}.linx.fusion.tsv \\ + -linx_breakend_tsv ${linx_dir}/${meta.tumor_id}.linx.breakend.tsv \\ + -linx_driver_catalog_tsv ${linx_dir}/${meta.tumor_id}.linx.driver.catalog.tsv \\ + -annotated_virus_tsv ${virusinterpreter} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + protect: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*PROTECT v//') + END_VERSIONS + """ + + stub: + """ + touch "${meta.tumor_id}.protect.tsv" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/nextflow_schema.json b/nextflow_schema.json index 46d6eef5..2e0d0e1b 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -327,6 +327,12 @@ "description": "Path to PEACH panel file.", "fa_icon": "far fa-file-code" }, + "ref_data_serve_resources": { + "type": "string", + "format": "directory-path", + "description": "Path to SERVE resource directory.", + "fa_icon": "far fa-folder-open" + }, "ref_data_sigs_signatures": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 3c738205..7a0cb610 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -152,6 +152,8 @@ def createHmfDataMap(hmf_data_base, params_only) { clinvar_annotations: 'ref_data_clinvar_annotations', // PEACH peach_panel: 'ref_data_peach_panel', + // PROTECT + serve_resources: 'ref_data_serve_resources', // SIGS sigs_signatures: 'ref_data_sigs_signatures', // LILAC diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 0bc9cc5a..10991ded 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -64,6 +64,7 @@ include { CUPPA_VISUALISER } from '../modules/local/cuppa/visualiser/main' include { ISOFOX } from '../modules/local/isofox/main' include { LINX_REPORT } from '../modules/local/gpgr/linx_report/main' include { PEACH } from '../modules/local/peach/main' +include { PROTECT } from '../modules/local/protect/main' include { PURPLE } from '../modules/local/purple/main' include { SIGS } from '../modules/local/sigs/main' include { VIRUSBREAKEND } from '../modules/local/virusbreakend/main' @@ -806,6 +807,52 @@ workflow ONCOANALYSER { ch_versions = ch_versions.mix(LINX_REPORT.out.versions) } + // + // MODULE: Run PROTECT to match somatic genomic features with treatment evidence + // + // channel: [val(meta), protect] + ch_protect_out = Channel.empty() + if (run.protect) { + // Select input sources + // channel: [val(meta), linx_somatic_annotation_dir] + ch_linx_anno = ch_linx_somatic_out.map { meta, anno_dir, vis_dir -> [meta, anno_dir]} + + // channel: [val(meta), chord_prediction, purple_dir, linx_dir, virusinterpreter_dir] + ch_protect_inputs_source = WorkflowOncoanalyser.groupByMeta( + run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CHORD_PREDICTION, Constants.DataType.TUMOR]), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), + run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.TUMOR_NORMAL]), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.VIRUSINTERPRETER_TSV, Constants.DataType.TUMOR]), + ) + + // Create process-specific meta + // channel: [val(meta_protect), chord_prediction, purple_dir, linx_dir, virusinterpreter_dir] + ch_protect_inputs = ch_protect_inputs_source + .map { + def meta = it[0] + def other = it[1..-1] + def meta_protect = [ + key: meta.id, + id: meta.id, + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + ] + return [meta_protect, *other] + } + + // Run process + PROTECT( + ch_protect_inputs, + PREPARE_REFERENCE.out.genome_version, + hmf_data.serve_resources, + hmf_data.disease_ontology, + ) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix(PROTECT.out.versions) + ch_protect_out = ch_protect_out.mix(WorkflowOncoanalyser.restoreMeta(PROTECT.out.tsv, ch_inputs)) + } + // // MODULE: Run PEACH to match germline SNVs with pharmacogenetic evidence // From 4ef38fffc863e089a586033d47cb1a3799030690 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 20:19:02 +1100 Subject: [PATCH 064/562] Add ORANGE --- conf/base.config | 4 + conf/hmfdata.config | 4 + conf/modules.config | 17 ++ lib/Constants.groovy | 17 +- modules.json | 4 + modules/local/chord/main.nf | 6 +- modules/local/cuppa/visualiser/main.nf | 6 +- modules/local/orange/Dockerfile | 22 +++ modules/local/orange/main.nf | 103 ++++++++++ modules/local/purple/main.nf | 14 +- modules/local/sage/Dockerfile | 1 - modules/local/sage/germline/main.nf | 9 +- modules/local/sage/somatic/main.nf | 5 +- modules/nf-core/samtools/flagstat/main.nf | 35 ++++ modules/nf-core/samtools/flagstat/meta.yml | 49 +++++ nextflow_schema.json | 21 ++ subworkflows/local/prepare_reference.nf | 4 + subworkflows/local/sage.nf | 9 +- workflows/oncoanalyser.nf | 212 +++++++++++++++++++-- 19 files changed, 498 insertions(+), 44 deletions(-) create mode 100644 modules/local/orange/Dockerfile create mode 100644 modules/local/orange/main.nf create mode 100644 modules/nf-core/samtools/flagstat/main.nf create mode 100644 modules/nf-core/samtools/flagstat/meta.yml diff --git a/conf/base.config b/conf/base.config index f5061a15..dff496e0 100644 --- a/conf/base.config +++ b/conf/base.config @@ -155,4 +155,8 @@ process { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } + withName:'ORANGE' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } } diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 857b718a..7c0dc4b0 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -38,7 +38,11 @@ params { // Virus Interpreter virus_taxonomy_db = 'virus_interpreter/taxonomy_db.tsv' virus_reporting_db = 'virus_interpreter/virus_reporting_db.tsv' + // ORANGE + cohort_mapping = 'orange/cohort_mapping.tsv' + cohort_percentiles = 'orange/cohort_percentiles.tsv' // Misc + disease_ontology = 'disease_ontology/201015_doid.json' purple_germline_del = 'purple/cohort_germline_del_freq.37.csv' driver_gene_panel = 'gene_panel/DriverGenePanel.37.tsv' ensembl_data_resources = 'ensembl_data_cache/' diff --git a/conf/modules.config b/conf/modules.config index 3d5343b2..c9f76ae1 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -250,4 +250,21 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/peach/${filename}" }, ] } + + withName: 'ORANGE' { + ext.jarPath = '/opt/orange/orange.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/orange/${filename}" }, + ] + } + + withName: 'SAMTOOLS_FLAGSTAT' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/flagstats/${filename}" }, + ] + } } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 5e672569..a37c9f74 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -28,6 +28,7 @@ class Constants { ISOFOX, LILAC, LINX, + ORANGE, PAVE, PEACH, PROTECT, @@ -55,10 +56,22 @@ class Constants { GRIPSS_HARD_VCF, GRIPSS_SOFT_VCF, ISOFOX_DIR, - LINX_DIR, + LINX_ANNO_DIR, + LILAC_DIR, PAVE_VCF, PURPLE_DIR, SAGE_VCF, - VIRUSINTERPRETER, + VIRUSINTERPRETER_TSV, + // ORANGE specific + CHORD_PREDICTION, + CUPPA_CSV, + CUPPA_FEATURE_PLOT, + CUPPA_SUMMARY_PLOT, + FLAGSTAT, + LINX_PLOT_DIR, + PEACH_TSV, + PROTECT_TSV, + SAGE_BQR, + SAGE_COVERAGE, } } diff --git a/modules.json b/modules.json index 1b2686bc..9885925d 100644 --- a/modules.json +++ b/modules.json @@ -24,6 +24,10 @@ "samtools/faidx": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01" + }, + "samtools/flagstat": { + "branch": "master", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c" } } } diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf index 851c2742..5bd2abb3 100644 --- a/modules/local/chord/main.nf +++ b/modules/local/chord/main.nf @@ -9,9 +9,9 @@ process CHORD { val genome_ver output: - path '*_chord_signatures.txt', emit: signatures - path '*_chord_prediction.txt', emit: prediction - path 'versions.yml' , emit: versions + tuple val(meta), path('*_chord_prediction.txt'), emit: prediction + path '*_chord_signatures.txt' , emit: signatures + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf index 96269167..488040e5 100644 --- a/modules/local/cuppa/visualiser/main.nf +++ b/modules/local/cuppa/visualiser/main.nf @@ -8,12 +8,12 @@ process CUPPA_VISUALISER { tuple val(meta), path(cuppa_csv) output: + tuple val(meta), path('*report.summary.png') , emit: summary_plot + tuple val(meta), path('*report.features.png'), emit: feature_plot path '*chart.png' path '*conclusion.txt' - path '*report.features.png' - path '*report.summary.png' path '*cup_report.pdf' - path 'versions.yml' , emit: versions + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/orange/Dockerfile b/modules/local/orange/Dockerfile new file mode 100644 index 00000000..de6ef93f --- /dev/null +++ b/modules/local/orange/Dockerfile @@ -0,0 +1,22 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/orange/ && \ + wget -O /opt/orange/orange.jar 'https://github.com/hartwigmedical/hmftools/releases/download/orange-v1.10/orange.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'openjdk >=8' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf new file mode 100644 index 00000000..f8b3d336 --- /dev/null +++ b/modules/local/orange/main.nf @@ -0,0 +1,103 @@ +process ORANGE { + tag "${meta.id}" + label 'process_single' + + container 'docker.io/scwatts/orange:1.10--0' + + input: + tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(chord_prediction), path(lilac_dir), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(linx_anno_dir), path(linx_plot_dir), path(protect), path(peach_genotype), path(cuppa), path(cuppa_summary_plot), path(cuppa_feature_plot), path(virusinterpreter) + val genome_ver + path disease_ontology + path known_fusion_data + path driver_gene_panel + path cohort_mapping + path cohort_percentiles + val pipeline_version + + output: + path '*.orange.json' + path '*.orange.pdf' + path 'versions.yml', emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def pipeline_version_str = pipeline_version ?: 'not specified' + + """ + echo "${pipeline_version_str}" > pipeline_version.txt + + java \\ + -Xmx${task.memory.giga}g \\ + -jar ${task.ext.jarPath} \\ + \\ + -tumor_sample_id ${meta.tumor_id} \\ + -reference_sample_id ${meta.normal_id} \\ + \\ + -pipeline_version_file pipeline_version.txt \\ + -ref_genome_version ${genome_ver} \\ + -primary_tumor_doids "" \\ + -max_evidence_level C \\ + \\ + -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ + -ref_sample_wgs_metrics_file ${bam_metrics_germline} \\ + -tumor_sample_flagstat_file ${flagstat_somatic} \\ + -ref_sample_flagstat_file ${flagstat_germline} \\ + \\ + -chord_prediction_txt ${chord_prediction} \\ + -lilac_result_csv ${lilac_dir}/${meta.tumor_id}.lilac.csv \\ + -lilac_qc_csv ${lilac_dir}/${meta.tumor_id}.lilac.qc.csv \\ + \\ + -sage_somatic_tumor_sample_bqr_plot ${sage_somatic_bqr} \\ + -sage_somatic_ref_sample_bqr_plot ${sage_germline_bqr} \\ + -sage_germline_gene_coverage_tsv ${sage_germlien_coverage} \\ + \\ + -purple_qc_file ${purple_dir}/${meta.tumor_id}.purple.qc \\ + -purple_purity_tsv ${purple_dir}/${meta.tumor_id}.purple.purity.tsv \\ + -purple_gene_copy_number_tsv ${purple_dir}/${meta.tumor_id}.purple.cnv.gene.tsv \\ + -purple_somatic_copy_number_tsv ${purple_dir}/${meta.tumor_id}.purple.cnv.somatic.tsv \\ + -purple_somatic_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.somatic.tsv \\ + -purple_somatic_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.somatic.vcf.gz \\ + -purple_germline_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.germline.tsv \\ + -purple_germline_deletion_tsv ${purple_dir}/${meta.tumor_id}.purple.germline.deletion.tsv \\ + -purple_germline_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.germline.vcf.gz \\ + -purple_plot_directory ${purple_dir}/plot/ \\ + \\ + -linx_breakend_tsv ${linx_anno_dir}/${meta.tumor_id}.linx.breakend.tsv \\ + -linx_structural_variant_tsv ${linx_anno_dir}/${meta.tumor_id}.linx.svs.tsv \\ + -linx_driver_tsv ${linx_anno_dir}/${meta.tumor_id}.linx.drivers.tsv \\ + -linx_driver_catalog_tsv ${linx_anno_dir}/${meta.tumor_id}.linx.driver.catalog.tsv \\ + -linx_fusion_tsv ${linx_anno_dir}/${meta.tumor_id}.linx.fusion.tsv \\ + -linx_germline_disruption_tsv ${linx_anno_dir}/${meta.normal_id}.linx.germline.disruption.tsv \\ + -linx_plot_directory ${linx_plot_dir} \\ + \\ + -cuppa_result_csv ${cuppa} \\ + -cuppa_feature_plot ${cuppa_summary_plot} \\ + -cuppa_summary_plot ${cuppa_feature_plot} \\ + \\ + -peach_genotype_tsv ${peach_genotype} \\ + -protect_evidence_tsv ${protect} \\ + -annotated_virus_tsv ${virusinterpreter} \\ + \\ + -doid_json ${disease_ontology} \\ + -known_fusion_file ${known_fusion_data} \\ + -driver_gene_panel_tsv ${driver_gene_panel} \\ + -cohort_mapping_tsv ${cohort_mapping} \\ + -cohort_percentiles_tsv ${cohort_percentiles} \\ + -output_dir ./ + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + orange: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*ORANGE v//') + END_VERSIONS + """ + + stub: + """ + touch "${meta.tumor_id}.orange.json" + touch "${meta.tumor_id}.orange.pdf" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 02864d85..2601c92d 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -85,12 +85,14 @@ process PURPLE { stub: """ mkdir purple/ - cat < purple/${meta.tumor_id}.purple.sv.vcf.gz - ##fileformat=VCFv4.1 - ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . - EOF + touch purple/${meta.tumor_id}.purple.cnv.gene.tsv + touch purple/${meta.tumor_id}.purple.driver.catalog.germline.tsv + touch purple/${meta.tumor_id}.purple.driver.catalog.somatic.tsv + touch purple/${meta.tumor_id}.purple.germline.vcf.gz + touch purple/${meta.tumor_id}.purple.purity.tsv + touch purple/${meta.tumor_id}.purple.qc + touch purple/${meta.tumor_id}.purple.somatic.vcf.gz + touch purple/${meta.tumor_id}.purple.sv.vcf.gz echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sage/Dockerfile b/modules/local/sage/Dockerfile index 069a5bf0..518f774a 100644 --- a/modules/local/sage/Dockerfile +++ b/modules/local/sage/Dockerfile @@ -28,4 +28,3 @@ RUN \ micromamba clean --all --yes ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" - diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 58cd1740..645f284c 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -1,5 +1,3 @@ -// NOTE(SW): 3.0.3 logic that determines BQR outputs assumes '-out' is a path that includes at least one directory - process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' @@ -20,9 +18,7 @@ process SAGE_GERMLINE { output: tuple val(meta), path("${meta.tumor_id}.sage_germline.vcf.gz"), emit: vcf - path '*gene.coverage.tsv' , emit: gene_coverage, optional: true - path '*sage.bqr.png' , emit: bqr_png, optional: true - path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true + tuple val(meta), path('*gene.coverage.tsv') , emit: gene_coverage, optional: true path 'versions.yml' , emit: versions when: @@ -55,8 +51,6 @@ process SAGE_GERMLINE { -panel_max_germline_rel_raw_base_qual 100 \\ -mnv_filter_enabled false \\ -panel_only \\ - -write_bqr_data \\ - -write_bqr_plot \\ -threads ${task.cpus} \\ -out ./${meta.tumor_id}.sage_germline.vcf.gz @@ -69,6 +63,7 @@ process SAGE_GERMLINE { stub: """ touch "${meta.tumor_id}.sage_germline.vcf.gz" + touch "${meta.tumor_id}.gene.coverage.tsv" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 30a52b25..443acb44 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -19,8 +19,9 @@ process SAGE_SOMATIC { output: tuple val(meta), path("${meta.tumor_id}.sage_somatic.vcf.gz"), emit: vcf + tuple val(meta), path("${meta.tumor_id}.sage.bqr.png") , emit: tumor_bqr_png, optional: true + tuple val(meta), path("${meta.normal_id}.sage.bqr.png") , emit: normal_bqr_png, optional: true path '*gene.coverage.tsv' , emit: gene_coverage, optional: true - path '*sage.bqr.png' , emit: bqr_png, optional: true path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true path 'versions.yml' , emit: versions @@ -60,6 +61,8 @@ process SAGE_SOMATIC { stub: """ touch "${meta.tumor_id}.sage_somatic.vcf.gz" + touch "${meta.tumor_id}.sage.bqr.png" + touch "${meta.normal_id}.sage.bqr.png" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/nf-core/samtools/flagstat/main.nf b/modules/nf-core/samtools/flagstat/main.nf new file mode 100644 index 00000000..2120cd7d --- /dev/null +++ b/modules/nf-core/samtools/flagstat/main.nf @@ -0,0 +1,35 @@ +process SAMTOOLS_FLAGSTAT { + tag "$meta.id" + label 'process_single' + + conda "bioconda::samtools=1.16.1" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + + input: + tuple val(meta), path(bam), path(bai) + + output: + tuple val(meta), path("*.flagstat"), emit: flagstat + 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}" + """ + samtools \\ + flagstat \\ + --threads ${task.cpus} \\ + $bam \\ + > ${prefix}.flagstat + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/samtools/flagstat/meta.yml b/modules/nf-core/samtools/flagstat/meta.yml new file mode 100644 index 00000000..95269063 --- /dev/null +++ b/modules/nf-core/samtools/flagstat/meta.yml @@ -0,0 +1,49 @@ +name: samtools_flagstat +description: Counts the number of alignments in a BAM/CRAM/SAM file for each FLAG type +keywords: + - stats + - mapping + - counts + - bam + - sam + - cram +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: hhttp://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + - bai: + type: file + description: Index for BAM/CRAM/SAM file + pattern: "*.{bai,crai,sai}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - flagstat: + type: file + description: File containing samtools flagstat output + pattern: "*.{flagstat}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" diff --git a/nextflow_schema.json b/nextflow_schema.json index 2e0d0e1b..4135b5c1 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -250,6 +250,20 @@ "description": "Path to Virus Interpreter reporting file.", "fa_icon": "far fa-file-code" }, + "ref_data_cohort_mapping": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv$", + "description": "Path to ORANGE cohort mapping file.", + "fa_icon": "far fa-file-code" + }, + "ref_data_cohort_percentiles": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv$", + "description": "Path to ORANGE cohort percentiles file.", + "fa_icon": "far fa-file-code" + }, "ref_data_segment_mappability": { "type": "string", "format": "file-path", @@ -354,6 +368,13 @@ "description": "Path to HMF known fusions Data file.", "fa_icon": "far fa-file-code" }, + "ref_data_disease_ontology": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.json$", + "description": "Path to disease ontology file.", + "fa_icon": "far fa-file-code" + }, "ref_data_purple_germline_del": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 7a0cb610..2a39e3f8 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -161,7 +161,11 @@ def createHmfDataMap(hmf_data_base, params_only) { // Virus Interpreter virus_taxonomy_db: 'ref_data_virus_taxonomy_db', virus_reporting_db: 'ref_data_virus_reporting_db', + // ORANGE + cohort_mapping: 'ref_data_cohort_mapping', + cohort_percentiles: 'ref_data_cohort_percentiles', // Misc + disease_ontology: 'ref_data_disease_ontology', purple_germline_del: 'ref_data_purple_germline_del', driver_gene_panel: 'ref_data_driver_gene_panel', ensembl_data_resources: 'ref_data_ensembl_data_resources', diff --git a/subworkflows/local/sage.nf b/subworkflows/local/sage.nf index 740d2c9d..68260406 100644 --- a/subworkflows/local/sage.nf +++ b/subworkflows/local/sage.nf @@ -56,8 +56,11 @@ workflow SAGE { ch_versions = ch_versions.mix(SAGE_SOMATIC.out.versions) emit: - germline = SAGE_GERMLINE.out.vcf // channel: [val(meta), sage_vcf] - somatic = SAGE_SOMATIC.out.vcf // channel: [val(meta), sage_vcf] + germline_vcf = SAGE_GERMLINE.out.vcf // channel: [val(meta), sage_vcf] + germline_coverage = SAGE_GERMLINE.out.gene_coverage // channel: [val(meta), sage_coverage] + somatic_vcf = SAGE_SOMATIC.out.vcf // channel: [val(meta), sage_vcf] + somatic_tumor_bqr = SAGE_SOMATIC.out.tumor_bqr_png // channel: [val(meta), sage_bqr_plot] + somatic_normal_bqr = SAGE_SOMATIC.out.normal_bqr_png // channel: [val(meta), sage_brq_plot] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 10991ded..38c5581a 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -63,6 +63,7 @@ include { CUPPA_CLASSIFIER } from '../modules/local/cuppa/classifier/main' include { CUPPA_VISUALISER } from '../modules/local/cuppa/visualiser/main' include { ISOFOX } from '../modules/local/isofox/main' include { LINX_REPORT } from '../modules/local/gpgr/linx_report/main' +include { ORANGE } from '../modules/local/orange/main' include { PEACH } from '../modules/local/peach/main' include { PROTECT } from '../modules/local/protect/main' include { PURPLE } from '../modules/local/purple/main' @@ -93,6 +94,7 @@ include { SAGE } from '../subworkflows/local/sage' // include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' include { PICARD_COLLECTWGSMETRICS } from '../modules/nf-core/picard/collectwgsmetrics/main' +include { SAMTOOLS_FLAGSTAT } from '../modules/nf-core/samtools/flagstat/main' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -101,7 +103,7 @@ include { PICARD_COLLECTWGSMETRICS } from '../modules/nf-core/picard/collectw */ // Get absolute file paths -samplesheet = Utils.getFileObject(params.input) +samplesheet = Utils.getFileObject(params.input) gridss_config = Utils.getFileObject(params.gridss_config) workflow ONCOANALYSER { @@ -151,7 +153,7 @@ workflow ONCOANALYSER { // channel: [meta_isofox, tumor_bam_wts] ch_isofox_inputs = ch_inputs_wts.present .map { meta -> - def bam = meta.get([Constants.FileType.BAM_WTS, Constants.DataType.TUMOR]) + def bam = meta.get([Constants.FileType.BAM_WTS, Constants.DataType.TUMOR]) def meta_isofox = [key: meta.id, id: meta.get(['sample_name', Constants.DataType.TUMOR])] return [meta_isofox, bam, "${bam}.bai"] } @@ -398,9 +400,15 @@ workflow ONCOANALYSER { // SUBWORKFLOW: call SNV, MNV, and small INDELS with SAGE // // channel: [val(meta), sage_vcf] - ch_sage_germline_out = Channel.empty() + ch_sage_germline_vcf_out = Channel.empty() + // channel: [val(meta), sage_coverage] + ch_sage_germline_coverage_out = Channel.empty() // channel: [val(meta), sage_vcf] - ch_sage_somatic_out = Channel.empty() + ch_sage_somatic_vcf_out = Channel.empty() + // channel: [val(meta), bqr_plot] + ch_sage_somatic_tumor_bqr_out = Channel.empty() + // channel: [val(meta), bqr_plot] + ch_sage_somatic_normal_bqr_out = Channel.empty() if (run.sage) { // Create inputs and create process-specific meta ch_sage_inputs = ch_bams_and_indices @@ -434,8 +442,11 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(SAGE.out.versions) - ch_sage_germline_out = ch_sage_germline_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.germline, ch_inputs)) - ch_sage_somatic_out = ch_sage_somatic_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.somatic, ch_inputs)) + ch_sage_germline_vcf_out = ch_sage_germline_vcf_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.germline_vcf, ch_inputs)) + ch_sage_germline_coverage_out = ch_sage_germline_coverage_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.germline_coverage, ch_inputs)) + ch_sage_somatic_vcf_out = ch_sage_somatic_vcf_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.somatic_vcf, ch_inputs)) + ch_sage_somatic_tumor_bqr_out = ch_sage_somatic_tumor_bqr_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.somatic_tumor_bqr, ch_inputs)) + ch_sage_somatic_normal_bqr_out = ch_sage_somatic_normal_bqr_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.somatic_normal_bqr, ch_inputs)) } // @@ -449,8 +460,8 @@ workflow ONCOANALYSER { // Select input sources // channel: [meta, sage_vcf] if (run.sage) { - ch_pave_germline_inputs_source = ch_sage_germline_out - ch_pave_somatic_inputs_source = ch_sage_somatic_out + ch_pave_germline_inputs_source = ch_sage_germline_vcf_out + ch_pave_somatic_inputs_source = ch_sage_somatic_vcf_out } else { ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_VCF, Constants.DataType.NORMAL]) ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_VCF, Constants.DataType.TUMOR]) @@ -523,7 +534,7 @@ workflow ONCOANALYSER { } // channel: [val(meta), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] - ch_purple_inputs_sources = WorkflowOncoanalyser.groupByMeta( + ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( run.amber ? ch_amber_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.AMBER_DIR, Constants.DataType.TUMOR_NORMAL]), run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COBALT_DIR, Constants.DataType.TUMOR_NORMAL]), ch_purple_inputs_sv, @@ -531,8 +542,9 @@ workflow ONCOANALYSER { run.pave ? ch_pave_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PAVE_VCF, Constants.DataType.NORMAL]), ) + // Create process-specific meta // channel: [val(meta_purple), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] - ch_purple_inputs = ch_purple_inputs_sources + ch_purple_inputs = ch_purple_inputs_source .map { def meta = it[0] def other = it[1..-1] @@ -600,6 +612,8 @@ workflow ONCOANALYSER { // // MODULE: Run CHORD to predict HR deficiency status // + // channel: [val(meta), chord_prediction] + ch_chord_out = Channel.empty() if (run.chord) { // Select input sources // channel: [val(meta), purple_dir] @@ -616,7 +630,7 @@ workflow ONCOANALYSER { def tumor_id = meta.get(['sample_name', Constants.DataType.TUMOR]) def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") - def meta_chord = [id: meta.id] + def meta_chord = [key: meta.id, id: meta.id] return [meta_chord, smlv_vcf, sv_vcf] } @@ -626,13 +640,16 @@ workflow ONCOANALYSER { PREPARE_REFERENCE.out.genome_version, ) - // Set outputs + // Set outputs, restoring original meta ch_versions = ch_versions.mix(CHORD.out.versions) + ch_chord_out = ch_chord_out.mix(WorkflowOncoanalyser.restoreMeta(CHORD.out.prediction, ch_inputs)) } // // SUBWORKFLOW: Run LILAC for HLA typing and somatic CNV and SNV calling // + // channel: [val(meta), lilac_dir] + ch_lilac_out = Channel.empty() if (run.lilac) { // Select input sources // channel: [val(meta), purple_dir] @@ -651,14 +668,14 @@ workflow ONCOANALYSER { hmf_data.lilac_resources, ) - // Set outputs + // Set outputs, restoring original meta ch_versions = ch_versions.mix(LILAC.out.versions) + ch_lilac_out = ch_lilac_out.mix(WorkflowOncoanalyser.restoreMeta(LILAC.out.results, ch_inputs)) } // // MODULE: Run VIRUSBreakend and Virus Interpreter to quantify viral content // - // NOTE(SW): kept separate from CUPPA conditional block since we'll allow users to run this independently ch_virusinterpreter_out = Channel.empty() if (run.virusinterpreter) { // VIRUSBreakend @@ -897,6 +914,12 @@ workflow ONCOANALYSER { // // MODULE: Run CUPPA predict tissue of origin // + // channel: [val(meta), cuppa_results] + ch_cuppa_out = Channel.empty() + // channel: [val(meta), cuppa_summary_plot] + ch_cuppa_summary_plot_out = Channel.empty() + // channel: [val(meta), cuppa_feature_plot] + ch_cuppa_feature_plot_out = Channel.empty() if (run.cuppa) { // Select input sources // channel: [val(meta), isofox_dir] @@ -921,8 +944,8 @@ workflow ONCOANALYSER { ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), - run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_DIR, Constants.DataType.TUMOR_NORMAL]), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.VIRUSINTERPRETER, Constants.DataType.TUMOR]), + run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.TUMOR_NORMAL]), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.VIRUSINTERPRETER_TSV, Constants.DataType.TUMOR]), flatten: false, ) .map { data -> @@ -949,16 +972,169 @@ workflow ONCOANALYSER { hmf_data.cuppa_resources, ) - // Set outputs + // Set outputs, restoring original meta ch_versions = ch_versions.mix(CUPPA_CLASSIFIER.out.versions) + ch_cuppa_out = ch_cuppa_out.mix(WorkflowOncoanalyser.restoreMeta(CUPPA_CLASSIFIER.out.csv, ch_inputs)) // Run process CUPPA_VISUALISER( CUPPA_CLASSIFIER.out.csv, ) - // Set outputs + // Set outputs, restoring original meta ch_versions = ch_versions.mix(CUPPA_VISUALISER.out.versions) + ch_cuppa_summary_plot_out = ch_cuppa_summary_plot_out.mix(WorkflowOncoanalyser.restoreMeta(CUPPA_VISUALISER.out.summary_plot, ch_inputs)) + ch_cuppa_feature_plot_out = ch_cuppa_feature_plot_out.mix(WorkflowOncoanalyser.restoreMeta(CUPPA_VISUALISER.out.feature_plot, ch_inputs)) + } + + // + // MODULE: Run ORANGE to generate static PDF report + // + if (run.orange) { + // SAMtools flagstat + // Select input source + // channel (present): [val(meta), sample_type, flagstat] + // channel (absent): [val(meta)] + ch_inputs_flagstat = ch_inputs + .flatMap { meta -> [Constants.DataType.TUMOR, Constants.DataType.NORMAL].collect { [meta, it] } } + .branch { meta, sample_type -> + def key = [Constants.FileType.FLAGSTAT, sample_type] + present: meta.containsKey(key) + return [meta, sample_type, meta.get(key)] + absent: ! meta.containsKey(key) + } + + // Create inputs and create process-specific meta + // channel: [val(meta_flagstat), bam, bai] + ch_flagstat_inputs_all = ch_inputs_flagstat.absent + .map { meta, sample_type -> + def bam = meta.get([Constants.FileType.BAM_WGS, sample_type]) + def meta_flagstat = [ + key: meta.id, + id: meta.get(['sample_name', sample_type]), + // NOTE(SW): must use string representation for caching purposes + sample_type_str: sample_type.name(), + ] + return [meta_flagstat, bam, "${bam}.bai"] + } + + // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples + // channel: [val(meta_flagstat_shared), bam, bai] + ch_flagstat_inputs = ch_flagstat_inputs_all + .map { [it[1..-1], it[0]] } + .groupTuple() + .map { filepaths, meta_flagstat -> + def (keys, sample_names, sample_type_strs) = meta_flagstat + .collect { + [it.key, it.id, it.sample_type_str] + } + .transpose() + + def sample_type_strs_unique = sample_type_strs.unique(false) + assert sample_type_strs_unique.size() == 1 + def sample_type_str = sample_type_strs_unique[0] + + def meta_flagstat_new = [ + keys: keys, + id: sample_names.join('__'), + id_simple: keys.join('__'), + sample_type_str: sample_type_str, + ] + return [meta_flagstat_new, *filepaths] + } + + // Run process + SAMTOOLS_FLAGSTAT( + ch_flagstat_inputs, + ) + + // Set version + ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) + + // Replicate outputs to reverse unique operation + // channel: [val(meta_flagstat_individual), flagstat] + ch_flagstat_out = SAMTOOLS_FLAGSTAT.out.flagstat + .flatMap { meta_flagstat_shared, flagstat -> + def sample_type = Utils.getEnumFromString(meta_flagstat_shared.sample_type_str, Constants.DataType) + meta_flagstat_shared.keys.collect { key -> + return [meta_flagstat_shared + [key: key], sample_type, flagstat] + } + } + + // Combine input flagstat channels, restoring original meta where required, split by sample type + // channel (somatic): [val(meta), flagstat] + // channel (germline): [val(meta), flagstat] + ch_orange_inputs_flagstat = Channel.empty() + .concat( + ch_inputs_flagstat.present, + WorkflowOncoanalyser.restoreMeta(ch_flagstat_out, ch_inputs), + ) + .branch { meta, sample_type, flagstat -> + somatic: sample_type == Constants.DataType.TUMOR + return [meta, flagstat] + germline: sample_type == Constants.DataType.NORMAL + return [meta, flagstat] + } + + // ORANGE + // Split LINX channel + // channel (anno): [val(meta), anno_dir] + // channel (plot): [val(meta), plot_dir] + ch_orange_inputs_linx = ch_linx_somatic_out + .multiMap { meta, anno_dir, plot_dir -> + anno: [meta, anno_dir] + plot: [meta, plot_dir] + } + + // Select input source + // NOTE(SW): we could consider not allowing inputs from the samplesheet here since this nothing follows + ch_orange_inputs_source = WorkflowOncoanalyser.groupByMeta( + ch_cwm_out.somatic, + ch_cwm_out.germline, + ch_orange_inputs_flagstat.somatic, + ch_orange_inputs_flagstat.germline, + run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CHORD_PREDICTION, Constants.DataType.TUMOR]), + run.lilac ? ch_lilac_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LILAC_DIR, Constants.DataType.NORMAL]), + run.sage ? ch_sage_somatic_tumor_bqr_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_BQR, Constants.DataType.TUMOR]), + run.sage ? ch_sage_somatic_normal_bqr_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_BQR, Constants.DataType.NORMAL]), + run.sage ? ch_sage_germline_coverage_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_COVERAGE, Constants.DataType.NORMAL]), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput([Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), + run.linx ? ch_orange_inputs_linx.anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.TUMOR_NORMAL]), + run.linx ? ch_orange_inputs_linx.plot : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_PLOT_DIR, Constants.DataType.TUMOR_NORMAL]), + run.protect ? ch_protect_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PROTECT_TSV, Constants.DataType.TUMOR]), + run.peach ? ch_peach_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PEACH_TSV, Constants.DataType.NORMAL]), + run.cuppa ? ch_cuppa_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CUPPA_CSV, Constants.DataType.TUMOR]), + run.cuppa ? ch_cuppa_feature_plot_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CUPPA_FEATURE_PLOT, Constants.DataType.TUMOR]), + run.cuppa ? ch_cuppa_summary_plot_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CUPPA_SUMMARY_PLOT, Constants.DataType.TUMOR]), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.VIRUSINTERPRETER_TSV, Constants.DataType.TUMOR]), + ) + + ch_orange_inputs = ch_orange_inputs_source + .map { + def meta = it[0] + def meta_orange = [ + key: meta.id, + id: meta.id, + tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + ] + return [meta_orange, *it[1..-1]] + } + + // Run process + ORANGE( + ch_orange_inputs, + PREPARE_REFERENCE.out.genome_version, + hmf_data.disease_ontology, + hmf_data.known_fusion_data, + hmf_data.driver_gene_panel, + hmf_data.cohort_mapping, + hmf_data.cohort_percentiles, + "5.23 (oncoanalyser 0.0.1dev)", + ) + + // Set outputs + ch_versions = ch_versions.mix(ORANGE.out.versions) } // From 22ba34ede0062775c5c923b9755015a30737923b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 20:19:26 +1100 Subject: [PATCH 065/562] Add extra resource config for some processes --- conf/base.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conf/base.config b/conf/base.config index dff496e0..a6f94345 100644 --- a/conf/base.config +++ b/conf/base.config @@ -139,12 +139,15 @@ process { memory = { check_max( 64.GB, 'memory' ) } } withName:'VIRUSINTERPRETER' { + cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } withName:'ISOFOX' { + cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } withName:'CUPPA.*' { + cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } withName:'PEACH' { From bd749415a9052cb5f82e813405f18337159c8a40 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 09:16:31 +1100 Subject: [PATCH 066/562] Fix typo in known fusions data file description --- nextflow_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 4135b5c1..0350af59 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -365,7 +365,7 @@ "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", - "description": "Path to HMF known fusions Data file.", + "description": "Path to HMF known fusions data file.", "fa_icon": "far fa-file-code" }, "ref_data_disease_ontology": { From d55fde4db29d967f57ef968344e849bd320806fb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 10:23:32 +1100 Subject: [PATCH 067/562] Reorganise HMF data params, listings, etc --- conf/hmfdata.config | 26 +- nextflow_schema.json | 308 ++++++++++++++---------- subworkflows/local/prepare_reference.nf | 28 ++- 3 files changed, 208 insertions(+), 154 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 7c0dc4b0..7b3191a2 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -8,16 +8,26 @@ params { // CUPPA cuppa_resources = 'cuppa/' // GRIDSS - gridss_region_blocklist = 'gridss_repeatmasker_db/ENCFF001TDO.37.bed' gridss_pon_breakends = 'gridss_pon/gridss_pon_single_breakend.37.bed.gz' gridss_pon_breakpoints = 'gridss_pon/gridss_pon_breakpoint.37.bedpe.gz' + gridss_region_blocklist = 'gridss_repeatmasker_db/ENCFF001TDO.37.bed' // Isofox isofox_counts = 'isofox/read_151_exp_counts.csv' isofox_gc_ratios = 'isofox/read_100_exp_gc_ratios.csv' + // LILAC + lilac_resources = 'lilac/' // LINX linx_fragile_regions = 'linx/fragile_sites_hmf.37.csv' linx_lines = 'linx/line_elements.37.csv' + // ORANGE + cohort_mapping = 'orange/cohort_mapping.tsv' + cohort_percentiles = 'orange/cohort_percentiles.tsv' + // PEACH + peach_panel = 'peach/min_DPYD.json' + // PROTECT + serve_resources = 'serve/' // SAGE + clinvar_annotations = 'sage/clinvar.37.vcf.gz' sage_blocklist_regions = 'sage/KnownBlacklist.germline.37.bed' sage_blocklist_sites = 'sage/KnownBlacklist.germline.37.vcf.gz' sage_coding_panel = 'sage/ActionableCodingPanel.37.bed.gz' @@ -26,28 +36,18 @@ params { sage_known_hotspots_germline = 'sage/KnownHotspots.germline.37.vcf.gz' sage_known_hotspots_somatic = 'sage/KnownHotspots.somatic.37.vcf.gz' sage_pon = 'sage/SageGermlinePon.1000x.37.tsv.gz' - clinvar_annotations = 'sage/clinvar.37.vcf.gz' - // PEACH - peach_panel = 'peach/min_DPYD.json' - // PROTECT - serve_resources = 'serve/' // SIGS sigs_signatures = 'sigs/snv_cosmic_signatures.csv' - // LILAC - lilac_resources = 'lilac/' // Virus Interpreter - virus_taxonomy_db = 'virus_interpreter/taxonomy_db.tsv' virus_reporting_db = 'virus_interpreter/virus_reporting_db.tsv' - // ORANGE - cohort_mapping = 'orange/cohort_mapping.tsv' - cohort_percentiles = 'orange/cohort_percentiles.tsv' + virus_taxonomy_db = 'virus_interpreter/taxonomy_db.tsv' // Misc disease_ontology = 'disease_ontology/201015_doid.json' - purple_germline_del = 'purple/cohort_germline_del_freq.37.csv' driver_gene_panel = 'gene_panel/DriverGenePanel.37.tsv' ensembl_data_resources = 'ensembl_data_cache/' known_fusion_data = 'fusions/known_fusion_data.37.csv' known_fusions = 'fusions/known_fusions.37.bedpe' + purple_germline_del = 'purple/cohort_germline_del_freq.37.csv' segment_mappability = 'mappability/mappability_150.37.bed.gz' } } diff --git a/nextflow_schema.json b/nextflow_schema.json index 0350af59..fe40ceb1 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,7 +10,10 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": ["input", "outdir"], + "required": [ + "input", + "outdir" + ], "properties": { "input": { "type": "string", @@ -73,28 +76,19 @@ "description": "Reference data files and options required for the workflow.", "properties": { "genome": { - "type": "string", + "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", - "mimetype": "text/plain", - "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", - "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", + "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.", @@ -102,292 +96,340 @@ "hidden": true, "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe c lashes between custom parameters and those supplied in `igenomes.config`." }, + "ref_data_hmf_data_base": { + "type": "string", + "format": "directory-path", + "description": "Path to HMF data base directory or URL.", + "fa_icon": "far fa-folder-open" + }, + "ref_data_virusbreakenddb_path": { + "type": "string", + "format": "directory-path", + "description": "Path to VIRUSBreakend database.", + "fa_icon": "far fa-file-code" + }, "ref_data_genome_fasta": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", "description": "Path to reference genome FASTA file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_genome_fai": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.fai$", "description": "Path to reference genome FAI file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_genome_dict": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.dict$", "description": "Path to reference genome sequence dictionary file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_genome_bwa_index": { "type": "string", "format": "directory-path", "description": "Path to directory containing reference genome BWA indices.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_genome_bwa_index_image": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.img$", "description": "Path to reference genome BWA indices image file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_genome_gridss_index": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.gridsscache$", "description": "Path to reference genome GRIDSS index file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_hmf_data_base": { - "type": "string", - "format": "directory-path", - "description": "Path to HMF data base directory or URL.", - "fa_icon": "far fa-file-code" - }, - "ref_data_virusbreakenddb_path": { - "type": "string", - "format": "directory-path", - "description": "Path to VIRUSBreakend database.", - "fa_icon": "far fa-file-code" - }, + "fa_icon": "far fa-file-code", + "hidden": true + } + } + }, + "hmf_data_options": { + "title": "HMF data options", + "type": "object", + "fa_icon": "fas fa-dna", + "description": "HMF data files for the workflow.", + "properties": { "ref_data_heterozygous_sites": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.vcf\\.gz$", "description": "Path to AMBER loci file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, - "ref_data_cobalt_gc_profile": { + "ref_data_gc_profile": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.cnp", "description": "Path to COBALT GC profile file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, - "ref_data_cuppa_resource_dir": { + "ref_data_cuppa_resources": { "type": "string", "format": "directory-path", "description": "Path to CUPPA reference file directory.", - "fa_icon": "far fa-file-code" - }, - "ref_data_gridss_region_blocklist": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed.gz$", - "description": "Path to GRIDSS blocklist file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-folder-open", + "hidden": true }, "ref_data_gridss_pon_breakends": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed\\.gz", "description": "Path to GRIDSS breakend PON file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_gridss_pon_breakpoints": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bedpe\\.gz$", "description": "Path to GRIDSS breakpoint PON file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true + }, + "ref_data_gridss_region_blocklist": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed.gz$", + "description": "Path to GRIDSS blocklist file.", + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_isofox_counts": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", "description": "Path to Isofox expected read counts file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_isofox_gc_ratios": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", "description": "Path to Isofox expected GC ratios file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true + }, + "ref_data_lilac_resources": { + "type": "string", + "format": "directory-path", + "description": "Path to LILAC resource directory.", + "fa_icon": "far fa-folder-open", + "hidden": true }, "ref_data_linx_fragile_regions": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", "description": "Path to LINX fragile sites file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_linx_lines": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", "description": "Path to LINX LINEs file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_ensembl_data_dir": { - "type": "string", - "format": "directory-path", - "description": "Path to HMF Ensembl data cache directory.", - "fa_icon": "far fa-file-code" - }, - "ref_data_lilac_resources": { - "type": "string", - "format": "directory-path", - "description": "Path to LILAC resource directory.", - "fa_icon": "far fa-folder-open" - }, - "ref_data_virus_taxonomy_db": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to Virus Interpreter taxonomy file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_virus_reporting_db": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to Virus Interpreter reporting file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_cohort_mapping": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.tsv$", "description": "Path to ORANGE cohort mapping file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_cohort_percentiles": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.tsv$", "description": "Path to ORANGE cohort percentiles file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, - "ref_data_segment_mappability": { + "ref_data_peach_panel": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to HMF mappability file.", - "fa_icon": "far fa-file-code" + "pattern": "^\\S+\\.json$", + "description": "Path to PEACH panel file.", + "fa_icon": "far fa-file-code", + "hidden": true + }, + "ref_data_serve_resources": { + "type": "string", + "format": "directory-path", + "description": "Path to SERVE resource directory.", + "fa_icon": "far fa-folder-open", + "hidden": true }, "ref_data_clinvar_annotations": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.vcf\\.gz$", "description": "Path to HMF ClinVar annotations VCF file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_sage_blocklist_regions": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.vcf\\.gz$", "description": "Path to HMF SAGE known blocklist VCF file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_sage_blocklist_sites": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed$", "description": "Path to HMF SAGE known blocklist BED file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, - "ref_data_sage_pon": { + "ref_data_sage_coding_panel": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.tsv\\.gz$", - "description": "Path to HMF SAGE panel of normals file.", - "fa_icon": "far fa-file-code" + "pattern": "^\\S+\\.bed\\.gz$", + "description": "Path to somatic SAGE coding panel file.", + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_sage_coverage_panel_germline": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed\\.gz$", "description": "Path to HMF SAGE germline coverage panel file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_sage_highconf_regions": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed\\.gz$", "description": "Path to HMF distributed high confidence regions file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_sage_coding_panel": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to somatic SAGE coding panel file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_sage_known_hotspots_germline": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.vcf\\.gz$", "description": "Path to germline SAGE known hotspots file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_sage_known_hotspots_somatic": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.vcf\\.gz$", "description": "Path to somatic SAGE known hotspots file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, - "ref_data_peach_panel": { + "ref_data_sage_pon": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.json$", - "description": "Path to PEACH panel file.", - "fa_icon": "far fa-file-code" - }, - "ref_data_serve_resources": { - "type": "string", - "format": "directory-path", - "description": "Path to SERVE resource directory.", - "fa_icon": "far fa-folder-open" + "pattern": "^\\S+\\.tsv\\.gz$", + "description": "Path to HMF SAGE panel of normals file.", + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_sigs_signatures": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", "description": "Path to signature definition file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, - "ref_data_known_fusions": { + "ref_data_virus_reporting_db": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.bedpe$", - "description": "Path to HMF known fusions file.", - "fa_icon": "far fa-file-code" + "pattern": "^\\S+\\.tsv$", + "description": "Path to Virus Interpreter reporting file.", + "fa_icon": "far fa-file-code", + "hidden": true }, - "ref_data_known_fusion_data": { + "ref_data_virus_taxonomy_db": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to HMF known fusions data file.", - "fa_icon": "far fa-file-code" + "pattern": "^\\S+\\.tsv$", + "description": "Path to Virus Interpreter taxonomy file.", + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_disease_ontology": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.json$", "description": "Path to disease ontology file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true + }, + "ref_data_driver_gene_panel": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.tsv$", + "description": "Path to HMF driver gene panel file.", + "fa_icon": "far fa-file-code", + "hidden": true + }, + "ref_data_ensembl_data_dir": { + "type": "string", + "format": "directory-path", + "description": "Path to HMF Ensembl data cache directory.", + "fa_icon": "far fa-folder-open", + "hidden": true + }, + "ref_data_known_fusion_data": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.csv$", + "description": "Path to HMF known fusions data file.", + "fa_icon": "far fa-file-code", + "hidden": true + }, + "ref_data_known_fusions": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bedpe$", + "description": "Path to HMF known fusions file.", + "fa_icon": "far fa-file-code", + "hidden": true }, "ref_data_purple_germline_del": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.csv$", "description": "Path to HMF PURPLE germline cohort deletion frequency file.", - "fa_icon": "far fa-file-code" + "fa_icon": "far fa-file-code", + "hidden": true }, - "ref_data_driver_gene_panel": { + "ref_data_segment_mappability": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to HMF driver gene panel file.", - "fa_icon": "far fa-file-code" + "pattern": "^\\S+\\.bed\\.gz$", + "description": "Path to HMF mappability file.", + "fa_icon": "far fa-file-code", + "hidden": true } } }, @@ -493,7 +535,14 @@ "description": "Method used to save pipeline results to output directory.", "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", "fa_icon": "fas fa-copy", - "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], + "enum": [ + "symlink", + "rellink", + "link", + "copy", + "copyNoFollow", + "move" + ], "hidden": true }, "email_on_fail": { @@ -571,6 +620,9 @@ { "$ref": "#/definitions/reference_data_options" }, + { + "$ref": "#/definitions/hmf_data_options" + }, { "$ref": "#/definitions/institutional_config_options" }, diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 2a39e3f8..1c58317d 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -123,6 +123,8 @@ workflow PREPARE_REFERENCE { } def createHmfDataMap(hmf_data_base, params_only) { + // NOTE(SW): this code provides an explicit mapping between user exposed HMF data params and + // their corresponding internal representation def params_mapping = [ // AMBER heterozygous_sites: 'ref_data_heterozygous_sites', @@ -131,16 +133,26 @@ def createHmfDataMap(hmf_data_base, params_only) { // CUPPA cuppa_resources: 'ref_data_cuppa_resources', // GRIDSS - gridss_region_blocklist: 'ref_data_gridss_region_blocklist', gridss_pon_breakends: 'ref_data_gridss_pon_breakends', gridss_pon_breakpoints: 'ref_data_gridss_pon_breakpoints', + gridss_region_blocklist: 'ref_data_gridss_region_blocklist', // Isofox isofox_counts: 'ref_data_isofox_counts', isofox_gc_ratios: 'ref_data_isofox_gc_ratios', + // LILAC + lilac_resources: 'ref_data_lilac_resources', // LINX linx_fragile_regions: 'ref_data_linx_fragile_regions', linx_lines: 'ref_data_linx_lines', + // ORANGE + cohort_mapping: 'ref_data_cohort_mapping', + cohort_percentiles: 'ref_data_cohort_percentiles', + // PEACH + peach_panel: 'ref_data_peach_panel', + // PROTECT + serve_resources: 'ref_data_serve_resources', // SAGE + clinvar_annotations: 'ref_data_clinvar_annotations', sage_blocklist_regions: 'ref_data_sage_blocklist_regions', sage_blocklist_sites: 'ref_data_sage_blocklist_sites', sage_coding_panel: 'ref_data_sage_coding_panel', @@ -149,28 +161,18 @@ def createHmfDataMap(hmf_data_base, params_only) { sage_known_hotspots_germline: 'ref_data_sage_known_hotspots_germline', sage_known_hotspots_somatic: 'ref_data_sage_known_hotspots_somatic', sage_pon: 'ref_data_sage_pon', - clinvar_annotations: 'ref_data_clinvar_annotations', - // PEACH - peach_panel: 'ref_data_peach_panel', - // PROTECT - serve_resources: 'ref_data_serve_resources', // SIGS sigs_signatures: 'ref_data_sigs_signatures', - // LILAC - lilac_resources: 'ref_data_lilac_resources', // Virus Interpreter - virus_taxonomy_db: 'ref_data_virus_taxonomy_db', virus_reporting_db: 'ref_data_virus_reporting_db', - // ORANGE - cohort_mapping: 'ref_data_cohort_mapping', - cohort_percentiles: 'ref_data_cohort_percentiles', + virus_taxonomy_db: 'ref_data_virus_taxonomy_db', // Misc disease_ontology: 'ref_data_disease_ontology', - purple_germline_del: 'ref_data_purple_germline_del', driver_gene_panel: 'ref_data_driver_gene_panel', ensembl_data_resources: 'ref_data_ensembl_data_resources', known_fusion_data: 'ref_data_known_fusion_data', known_fusions: 'ref_data_known_fusions', + purple_germline_del: 'ref_data_purple_germline_del', segment_mappability: 'ref_data_segment_mappability', ] params_mapping.collectEntries { k, v -> From 98b186129da1479fa484cd4b10bbc5cac5bfc9d1 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 10:40:10 +1100 Subject: [PATCH 068/562] Update input schema and example input samplesheet --- assets/samplesheet.csv | 11 ++++++++--- assets/schema_input.json | 41 ++++++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 5f653ab7..e2a94197 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,8 @@ -sample,fastq_1,fastq_2 -SAMPLE_PAIRED_END,/path/to/fastq/files/AEG588A1_S1_L002_R1_001.fastq.gz,/path/to/fastq/files/AEG588A1_S1_L002_R2_001.fastq.gz -SAMPLE_SINGLE_END,/path/to/fastq/files/AEG588A4_S4_L003_R1_001.fastq.gz, +id,subject_name,sample_name,sample_type,filetype,filepath +SONE_1,SUBJECT_ONE,SAMPLE_ONE_TUMOR,tumor,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_one_tumor.bam +SONE_1,SUBJECT_ONE,SAMPLE_ONE_NORMAL,normal,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_one_normal.bam +STWO_1,SUBJECT_TWO,SAMPLE_TWO_TUMOR_1,tumor,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_two_tumor_one.bam +STWO_1,SUBJECT_TWO,SAMPLE_TWO_TUMOR_1,tumor,bam_wts,/Users/stephen/repos/hmftools_pipeline/sample_two_tumor_one.rna.bam +STWO_1,SUBJECT_TWO,SAMPLE_TWO_NORMAL,normal,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_two_normal.bam +STWO_2,SUBJECT_TWO,SAMPLE_TWO_TUMOR_2,tumor,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_two_tumor_two.bam +STWO_2,SUBJECT_TWO,SAMPLE_TWO_NORMAL,normal,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_two_normal.bam diff --git a/assets/schema_input.json b/assets/schema_input.json index 20402902..01796d58 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -7,30 +7,31 @@ "items": { "type": "object", "properties": { - "sample": { + "id": { "type": "string", "pattern": "^\\S+$", - "errorMessage": "Sample name must be provided and cannot contain spaces" + "errorMessage": "id must be provided and cannot contain spaces" }, - "fastq_1": { - "type": "string", - "pattern": "^\\S+\\.f(ast)?q\\.gz$", - "errorMessage": "FastQ file for reads 1 must be provided, cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" + "subject_name": { + "pattern": "^\\S+$", + "errorMessage": "subject_name must be provided and cannot contain spaces" }, - "fastq_2": { - "errorMessage": "FastQ file for reads 2 cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'", - "anyOf": [ - { - "type": "string", - "pattern": "^\\S+\\.f(ast)?q\\.gz$" - }, - { - "type": "string", - "maxLength": 0 - } - ] + "sample_name": { + "pattern": "^\\S+$", + "errorMessage": "subject_name must be provided and cannot contain spaces" + }, + "sample_type": { + "pattern": "^\\S+$", + "errorMessage": "sample_type must be provided and cannot contain spaces" + }, + "filetype": { + "pattern": "^\\S+$", + "errorMessage": "filetype must be provided and cannot contain spaces" + }, + "filepath": { + "pattern": "^\\S+$", + "errorMessage": "filepath must be provided and cannot contain spaces" } - }, - "required": ["sample", "fastq_1"] + } } } From 3f70ff1dd40aefdd8f8f86e2347e0e8dd6b829d7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 10:50:50 +1100 Subject: [PATCH 069/562] Remove template MultiQC config --- assets/multiqc_config.yml | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 assets/multiqc_config.yml diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml deleted file mode 100644 index dfb73cca..00000000 --- a/assets/multiqc_config.yml +++ /dev/null @@ -1,13 +0,0 @@ -report_comment: > - This report has been generated by the nf-core/oncoanalyser - analysis pipeline. For information about how to interpret these results, please see the - documentation. -report_section_order: - "nf-core-oncoanalyser-methods-description": - order: -1000 - software_versions: - order: -1001 - "nf-core-oncoanalyser-summary": - order: -1002 - -export_plots: true From add613234cd2adf2e057d406796c18eeeac14c84 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 18:38:53 +1100 Subject: [PATCH 070/562] Add generic fn to join channels on meta attributes --- lib/WorkflowOncoanalyser.groovy | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index dbf7d45a..da297be2 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -148,17 +148,30 @@ class WorkflowOncoanalyser { return ch.map { meta -> [meta, meta.getAt(key)] } } + public static joinMeta(Map named_args, ch_a, ch_b) { + // NOTE(SW): the cross operator is used to allow many-to-one relationship between ch_output + // and ch_metas + def key_a = named_args.get('key_a', 'id') + def key_b = named_args.get('key_b', 'key') + def ch_ready_a = ch_a.map { [it[0].get(key_b), it[1..-1]] } + def ch_ready_b = ch_b.map { meta -> [meta.get(key_a), meta] } + return ch_ready_b + .cross(ch_ready_a) + .map { b, a -> + def (ka, values) = a + def (kb, meta) = b + return [meta, *values] + } + } + + // NOTE(SW): function signature required to catch where no named arguments are passed + public static joinMeta(ch_output, ch_metas) { + joinMeta([:], ch_output, ch_metas) + } + public static restoreMeta(ch_output, ch_metas) { // NOTE(SW): ch_output must contain a Map in the first position with a key named 'key' that // contains the corresponding meta.id value, for example: [val(meta_process), *process_outputs] - def ch_source = ch_metas.map { meta -> [meta.id, meta] } - def ch_target = ch_output.map { [it[0].key, it[1..-1]] } - return ch_source - .cross(ch_target) - .map { d_meta, d_outputs -> - def (skey, meta) = d_meta - def (dkey, outputs) = d_outputs - return [meta, *outputs] - } + joinMeta([:], ch_output, ch_metas) } } From 644963b665a92e7564a237106477bb249156c30c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 18:41:13 +1100 Subject: [PATCH 071/562] Add support for LILAC WTS --- lib/WorkflowLilac.groovy | 86 +++++++++++---------- modules/local/custom/lilac_slice/main.nf | 7 +- modules/local/lilac/main.nf | 12 +-- subworkflows/local/lilac.nf | 98 ++++++++++++++++-------- workflows/oncoanalyser.nf | 30 +++++++- 5 files changed, 152 insertions(+), 81 deletions(-) diff --git a/lib/WorkflowLilac.groovy b/lib/WorkflowLilac.groovy index 310c4985..e1aacb31 100755 --- a/lib/WorkflowLilac.groovy +++ b/lib/WorkflowLilac.groovy @@ -1,6 +1,8 @@ // // This file holds several functions specific to the subworkflows/lilac.nf in the nf-core/oncoanalyser pipeline // +import nextflow.Nextflow + import Constants import Utils @@ -10,26 +12,25 @@ class WorkflowLilac { public static getSliceInputs(ch, ch_slice_bed) { // channel: [val(meta_lilac), bam, bai] def d = ch - .flatMap { meta, tbam, nbam, tbai, nbai -> - def sample_types = [Constants.DataType.TUMOR, Constants.DataType.NORMAL] - sample_types - .collect { sample_type -> - def fps - if (sample_type == Constants.DataType.TUMOR) { - fps = [tbam, tbai] - } else if (sample_type == Constants.DataType.NORMAL) { - fps = [nbam, nbai] - } else { - assert false : "got bad sample type" - } + .flatMap { meta, nbam_wgs, nbai_wgs, tbam_wgs, tbai_wgs, tbam_wts, tbai_wts -> + def data = [ + [nbam_wgs, nbai_wgs, Constants.FileType.BAM_WGS, Constants.DataType.NORMAL], + [tbam_wgs, tbai_wgs, Constants.FileType.BAM_WGS, Constants.DataType.TUMOR], + [tbam_wts, tbai_wts, Constants.FileType.BAM_WTS, Constants.DataType.TUMOR], + ] + def data_present = data.findAll { it[0] } + data_present + .collect { bam, bai, filetype, sample_type -> def sample_name = meta.get(['sample_name', sample_type]) def meta_lilac = [ key: meta.id, id: sample_name, // NOTE(SW): must use string representation for caching purposes sample_type_str: sample_type.name(), + filetype_str: filetype.name(), + count: data_present.size(), ] - return [meta_lilac, *fps] + return [meta_lilac, bam, bai] } } // channel: [val(meta_lilac), bam, bai, bed] @@ -42,21 +43,19 @@ class WorkflowLilac { .map { [it[1..-1], it[0]] } .groupTuple() .map { filepaths, meta_lilac -> - def (keys, sample_names, sample_type_strs) = meta_lilac - .collect { - [it.key, it.id, it.sample_type_str] - } + // NOTE(SW): pattern needs to be generalised + def (keys, sample_names, filetype_strs, sample_type_strs) = meta_lilac + .collect { [it.key, it.id, it.filetype_str, it.sample_type_str] } .transpose() - - def sample_type_strs_unique = sample_type_strs.unique(false) - assert sample_type_strs_unique.size() == 1 - def sample_type_str = sample_type_strs_unique[0] + def sample_type_str = getValue(sample_type_strs) + def filetype_str = getValue(filetype_strs) def key = keys.join('__') def meta_lilac_new = [ keys: keys, id: sample_names.join('__'), id_simple: keys.join('__'), + filetype_str: filetype_str, sample_type_str: sample_type_str, ] return [meta_lilac_new, *filepaths] @@ -65,32 +64,39 @@ class WorkflowLilac { } public static sortSlices(ch) { - // Collect T/N pairs into single channel element - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] + // Gather and order files from same grouping using non-blocked groupTuple via provided file counts + // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] def d = ch - .flatMap{ data -> - def meta_lilac = data[0] - def fps = data[1..-1] - meta_lilac.keys.collect { key -> - return [key, [meta_lilac.sample_type_str, *fps]] - } + .map { meta, data -> + return [nextflow.Nextflow.groupKey(meta.key, meta.count), meta, data] } - .groupTuple(size: 2) - .map { key, other -> + .groupTuple() + .map { gk, metas, values -> + assert metas.unique().size() == 1 + def meta = metas[0] def data = [:] - other.each { sample_type_str, bam, bai -> + values.each { filetype_str, sample_type_str, bam, bai -> def sample_type = Utils.getEnumFromString(sample_type_str, Constants.DataType) - data[[sample_type, 'bam']] = bam - data[[sample_type, 'bai']] = bai + def filetype = Utils.getEnumFromString(filetype_str, Constants.FileType) + data[[sample_type, filetype, 'bam']] = bam + data[[sample_type, filetype, 'bai']] = bai } - [ - [key: key], - data.get([Constants.DataType.TUMOR, 'bam']), - data.get([Constants.DataType.NORMAL, 'bam']), - data.get([Constants.DataType.TUMOR, 'bai']), - data.get([Constants.DataType.NORMAL, 'bai']), + return [ + meta, + data.get([Constants.DataType.NORMAL, Constants.FileType.BAM_WGS, 'bam'], []), + data.get([Constants.DataType.NORMAL, Constants.FileType.BAM_WGS, 'bai'], []), + data.get([Constants.DataType.TUMOR, Constants.FileType.BAM_WGS, 'bam'], []), + data.get([Constants.DataType.TUMOR, Constants.FileType.BAM_WGS, 'bai'], []), + data.get([Constants.DataType.TUMOR, Constants.FileType.BAM_WTS, 'bam'], []), + data.get([Constants.DataType.TUMOR, Constants.FileType.BAM_WTS, 'bai'], []), ] } return d } + + public static getValue(l) { + def u = l.unique(false) + assert u.size() == 1 + return u[0] + } } diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index 3a70b216..fa8ccd8c 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -16,6 +16,7 @@ process SLICE { script: def args = task.ext.args ?: '' + def bam_name = bam.name - ~/\.bam$/ """ samtools view \\ @@ -24,7 +25,7 @@ process SLICE { -@${task.cpus} \\ -Obam \\ ${bam} | \\ - samtools sort -T tmp -o ${bam.simpleName}.sliced.bam + samtools sort -T tmp -o ${bam_name}.sliced.bam samtools index "${bam.simpleName}.sliced.bam" @@ -35,8 +36,10 @@ process SLICE { """ stub: + def bam_name = bam.name - ~/\.bam$/ + """ - touch ${bam.simpleName}.sliced.bam ${bam.simpleName}.sliced.bam.bai + touch ${bam_name}.sliced.bam ${bam_name}.sliced.bam.bai echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 5de4834f..0c269f5e 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -5,7 +5,7 @@ process LILAC { container 'docker.io/scwatts/lilac:1.1--0' input: - tuple val(meta), path(tumor_bam), path(normal_bam), path(tumour_bai), path(normal_bai), path(purple_dir) + tuple val(meta), path(normal_wgs_bam), path(normal_wts_bam), path(tumor_wgs_bam), path(tumor_wgs_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(purple_dir) path genome_fasta val genome_ver path lilac_resources, stageAs: 'lilac_resources' @@ -19,8 +19,9 @@ process LILAC { script: def args = task.ext.args ?: '' - def sample_name = getSampleName(meta, tumor_bam, normal_bam) - def tumor_bam_arg = tumor_bam ? "-tumor_bam ${tumor_bam}" : '' + def sample_name = getSampleName(meta, tumor_wgs_bam, normal_wgs_bam) + def tumor_wgs_bam_arg = tumor_wgs_bam ? "-tumor_wgs_bam ${tumor_wgs_bam}" : '' + def tumor_wts_bam_arg = tumor_wts_bam ? "-rna_bam ${tumor_wts_bam}" : '' def purple_args = purple_dir ? """ -gene_copy_number_file ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ -somatic_variants_file ${purple_dir}/${sample_name}.purple.sv.vcf.gz \\ @@ -32,8 +33,9 @@ process LILAC { -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${sample_name} \\ - ${tumor_bam_arg} \\ - -reference_bam ${normal_bam} \\ + ${tumor_wgs_bam_arg} \\ + ${tumor_wts_bam_arg} \\ + -reference_bam ${normal_wgs_bam} \\ -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ -resource_dir ${lilac_resources} \\ diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index 1b9e72c6..64df43ab 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -11,8 +11,8 @@ include { LILAC as LILAC_PROCESS } from '../../modules/local/lila workflow LILAC { take: - ch_inputs_bams // channel: [val(meta_lilac), tumor_bam, normal_bam, tumor_bai, normal_bai] - ch_inputs_purple_dir // channel: [val(meta_lilac), purple_dir] + ch_bams // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] + ch_purple_dir // channel: [val(meta), purple_dir] ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_lilac_resource_dir // file: /path/to/lilac_resource_dir/ @@ -43,17 +43,24 @@ workflow LILAC { // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used // in Pipeline5, see LilacBamSlicer.java#L115 // channel: [val(meta_lilac), bam, bai, bed] - ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_inputs_bams, ch_slice_bed) + ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_bams, ch_slice_bed) + // Isolate meta containing expected file count to use for non-blocking groupTuple later + ch_slice_meta_individual = ch_slice_inputs + .map { + def meta_lilac = it[0] + return [key: meta_lilac.key, count: meta_lilac.count] + } + // Apply slicing to unique files only // channel: [val(meta_lilac), bam, bai, bed] - ch_slice_inputs = WorkflowLilac.getUniqueInputFiles(ch_slice_inputs) + ch_slice_inputs_unique = WorkflowLilac.getUniqueInputFiles(ch_slice_inputs) SLICE( - ch_slice_inputs, + ch_slice_inputs_unique, ) ch_versions = ch_versions.mix(SLICE.out.versions) // Realign contigs if using 38 (use of ALT contigs implied) - // channel: [val(meta)] - ch_metas = ch_inputs_bams.map { return it[0] } + // channel: [val(meta_lilac), bam, bai] + ch_slices_out = SLICE.out.bam if (params.ref_data_genome_type == 'alt') { // Align reads with chr6 // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them @@ -64,39 +71,64 @@ workflow LILAC { ref_data_genome_fasta, ref_data_genome_fai, ) + ch_versions = ch_versions.mix(EXTRACT_AND_INDEX_CONTIG.out.versions) + REALIGN_READS( SLICE.out.bam, EXTRACT_AND_INDEX_CONTIG.out.contig, EXTRACT_AND_INDEX_CONTIG.out.bwa_indices, ) - - // Create input channel for LILAC - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] - ch_lilac_inputs_slices = WorkflowOncoanalyser.restoreMeta( - WorkflowLilac.sortSlices(REALIGN_READS.out.bam), - ch_metas, - ) - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] - ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( - ch_lilac_inputs_slices, - ch_inputs_purple_dir, - ) - } else { - // Create input channel for LILAC - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] - ch_lilac_inputs_slices = WorkflowOncoanalyser.restoreMeta( - WorkflowLilac.sortSlices(SLICE.out.bam), - ch_metas, - ) - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] - ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( - ch_lilac_inputs_slices, - ch_inputs_purple_dir, - ) + ch_slices_out = REALIGN_READS.out.bam + ch_versions = ch_versions.mix(REALIGN_READS.out.versions) } + + // Re-replicate and flow expected file count into meta + // channel: [val(meta_lilac), [filetype_str, sample_type_str, bam, bai]] + ch_slices_out_individual = ch_slices_out + .flatMap{ data -> + def meta_lilac = data[0] + def fps = data[1..-1] + meta_lilac.keys.collect { key -> + return [[key: key], [meta_lilac.filetype_str, meta_lilac.sample_type_str, *fps]] + } + } + // Adding expected file count + // channel: [val(meta_lilac), [filetype_str, sample_type_str, bam, bai]] + ch_slices_ready = WorkflowOncoanalyser.joinMeta( + ch_slices_out_individual, + ch_slice_meta_individual, + key_a: 'key', + ) + + // Gather and order files from same grouping using non-blocked groupTuple via provided file counts + // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] + ch_slices_organised = WorkflowLilac.sortSlices(ch_slices_ready) + + // Restore original meta so we can join with PURPLE directory + // channel: [val(meta)] + ch_metas = ch_bams.map { return it[0] } + // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] + ch_lilac_inputs_slices = WorkflowOncoanalyser.restoreMeta( + ch_slices_organised, + ch_metas, + ) + + // Add PURPLE output to finalise LILAC input channel + // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai, purple_dir] + ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( + ch_lilac_inputs_slices, + ch_purple_dir, + flatten: false, + ) + .map { data -> + def meta = data[0] + def inputs = data[1..-1].collectMany { it } + return [meta, *inputs] + } + // Run LILAC - // channel: [val(meta_lilac), tumor_bam, normal_bam, tumor_bai, normal_bai, purple_dir] + // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai, purple_dir] ch_lilac_inputs = ch_lilac_inputs_full .map { def meta = it[0] @@ -117,7 +149,7 @@ workflow LILAC { ch_versions = ch_versions.mix(LILAC_PROCESS.out.versions) emit: - results = LILAC_PROCESS.out.lilac_dir // channel: [val(meta), lilac_dir] + results = LILAC_PROCESS.out.lilac_dir // channel: [val(meta_lilac), lilac_dir] versions = ch_versions // channel: [versions.yml] } diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 38c5581a..976ccf92 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -659,9 +659,37 @@ workflow ONCOANALYSER { ch_lilac_inputs_source = WorkflowOncoanalyser.getInput([Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) } + // Create channel with all available input BAMs + // First obtain WTS BAMs + // channel: [val(meta), wts_bam, wts_bai] + ch_lilac_bams_wts = Channel.empty() + .mix( + ch_inputs_wts_bams = ch_inputs_wts.present.map { meta -> + def bam = meta.get([Constants.FileType.BAM_WTS, Constants.DataType.TUMOR]) + [meta, bam, "${bam}.bai"] + }, + ch_inputs_wts.absent.map { meta -> [meta, [], []] }, + ) + + // Combine WGS and WTS BAMs + // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] + // WorkflowOncoanalyser.groupByMeta removes optional Isofox input; flattening done manually below to preserve + ch_lilac_bams = WorkflowOncoanalyser.groupByMeta( + ch_lilac_bams_wts, + ch_bams_and_indices, + flatten: false, + ) + .map { data -> + def meta = data[0] + def inputs = data[1..-1].collectMany { it } + // Manually reorder channel + def (tbam_wts, tbai_wts, tbam_wgs, nbam_wgs, tbai_wgs, nbai_wgs) = inputs + return [meta, nbam_wgs, nbai_wgs, tbam_wgs, tbai_wgs, tbam_wts, tbai_wts] + } + // Call subworkflow to run processes LILAC( - ch_bams_and_indices, + ch_lilac_bams, run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput([Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, From 98069a9c89c0f6d86e2e12acb69d3f74fcb690bf Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 20 Dec 2022 18:41:48 +1100 Subject: [PATCH 072/562] Slightly simplify manual flattening of groupByMeta --- workflows/oncoanalyser.nf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 976ccf92..747f4925 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -967,8 +967,7 @@ workflow ONCOANALYSER { // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter_dir] // NOTE(SW): the Groovy Collection.flatten method used in - // WorkflowOncoanalyser.groupByMeta removes optional Isofox input; flattening - // done manually below to preserve + // WorkflowOncoanalyser.groupByMeta removes optional Isofox input; flattening done manually below to preserve ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), @@ -978,7 +977,7 @@ workflow ONCOANALYSER { ) .map { data -> def meta = data[0] - def inputs = data[1..-1].collect { it[0] } + def inputs = data[1..-1].collectMany { it } return [meta, *inputs] } From 226bcf4f78550f16901ace5436c5013417cb10f9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 21 Dec 2022 10:36:41 +1100 Subject: [PATCH 073/562] Preserve empty lists during .groupByMeta flatten --- lib/WorkflowOncoanalyser.groovy | 15 ++++++++++++++- subworkflows/local/lilac.nf | 7 +------ workflows/oncoanalyser.nf | 16 +++------------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index da297be2..233606cc 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -134,8 +134,21 @@ class WorkflowOncoanalyser { } if (named_args.get('flatten', true)) { - r = r.map { it.flatten() } + def flatten_mode = named_args.get('flatten_mode', 'recursive') + if (flatten_mode == 'recursive') { + r = r.map { it.flatten() } + } else if (flatten_mode == 'nonrecursive') { + r = r.map { data -> + def meta = data[0] + def inputs = data[1..-1].collectMany { it } + return [meta, *inputs] + } + } else { + System.err.println "ERROR: got bad flatten_mode: ${flatten_mode}" + System.exit(1) + } } + return r } diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index 64df43ab..7c995cb7 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -119,13 +119,8 @@ workflow LILAC { ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( ch_lilac_inputs_slices, ch_purple_dir, - flatten: false, + flatten_mode: 'nonrecursive', ) - .map { data -> - def meta = data[0] - def inputs = data[1..-1].collectMany { it } - return [meta, *inputs] - } // Run LILAC // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai, purple_dir] diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 747f4925..a0f32563 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -673,17 +673,14 @@ workflow ONCOANALYSER { // Combine WGS and WTS BAMs // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] - // WorkflowOncoanalyser.groupByMeta removes optional Isofox input; flattening done manually below to preserve ch_lilac_bams = WorkflowOncoanalyser.groupByMeta( ch_lilac_bams_wts, ch_bams_and_indices, - flatten: false, + flatten_mode: 'nonrecursive', ) .map { data -> def meta = data[0] - def inputs = data[1..-1].collectMany { it } - // Manually reorder channel - def (tbam_wts, tbai_wts, tbam_wgs, nbam_wgs, tbai_wgs, nbai_wgs) = inputs + def (tbam_wts, tbai_wts, tbam_wgs, nbam_wgs, tbai_wgs, nbai_wgs) = data[1..-1] return [meta, nbam_wgs, nbai_wgs, tbam_wgs, tbai_wgs, tbam_wts, tbai_wts] } @@ -966,20 +963,13 @@ workflow ONCOANALYSER { ch_linx_anno = ch_linx_somatic_out.map { meta, anno_dir, vis_dir -> [meta, anno_dir]} // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter_dir] - // NOTE(SW): the Groovy Collection.flatten method used in - // WorkflowOncoanalyser.groupByMeta removes optional Isofox input; flattening done manually below to preserve ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.TUMOR_NORMAL]), run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.VIRUSINTERPRETER_TSV, Constants.DataType.TUMOR]), - flatten: false, + flatten_mode: 'nonrecursive', ) - .map { data -> - def meta = data[0] - def inputs = data[1..-1].collectMany { it } - return [meta, *inputs] - } // Create inputs and create process-specific meta // channel: [val(meta_cuppa), isofox_dir, purple_dir, linx_dir, virusinterpreter_dir] From 2d57a61f9a2b27c8aa44aee0f7fb4e7884084444 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 21 Dec 2022 10:38:25 +1100 Subject: [PATCH 074/562] Handle Virus Interpreter output as file not dir --- conf/modules.config | 2 +- modules/local/cuppa/classifier/main.nf | 6 +++--- modules/local/virusinterpreter/main.nf | 8 ++++---- workflows/oncoanalyser.nf | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index c9f76ae1..6dbcf123 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -200,7 +200,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/virusinterpreter/${filename}" }, ] } diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index 41c90db2..15554e99 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -5,7 +5,7 @@ process CUPPA_CLASSIFIER { container 'docker.io/scwatts/cuppa:1.6--0' input: - tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) + tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter) path cuppa_resources output: @@ -23,8 +23,8 @@ process CUPPA_CLASSIFIER { """ # Symlink input files into a single directory mkdir sample_data/ - input_dirs="${isofox_dir} ${purple_dir} ${linx_dir} ${virusinterpreter_dir}" - find -L \${input_dirs} -maxdepth 1 -type f -exec ln -s ../{} sample_data/ \\; + inputs="${isofox_dir} ${purple_dir} ${linx_dir} ${virusinterpreter}" + find -L \${inputs} -maxdepth 1 -type f -exec ln -s ../{} sample_data/ \\; java \\ -Xmx${task.memory.giga}g \\ diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index 7cc4ac95..96b9c821 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -10,8 +10,8 @@ process VIRUSINTERPRETER { path reporting_db output: - tuple val(meta), path('virusinterpreter'), emit: virusinterpreter_dir - path 'versions.yml' , emit: versions + tuple val(meta), path("${meta.id}.virus.annotated.tsv"), emit: virusinterpreter + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -32,7 +32,7 @@ process VIRUSINTERPRETER { -virus_breakend_tsv ${virus_tsv} \\ -taxonomy_db_tsv ${taxonomy_db} \\ -virus_reporting_db_tsv ${reporting_db} \\ - -output_dir ./virusinterpreter/ + -output_dir ./ cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -42,7 +42,7 @@ process VIRUSINTERPRETER { stub: """ - mkdir virusinterpreter/ + touch ${meta.id}.virus.annotated.tsv echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index a0f32563..dccc63a3 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -769,7 +769,7 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) - ch_virusinterpreter_out = ch_virusinterpreter_out.mix(WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter_dir, ch_inputs)) + ch_virusinterpreter_out = ch_virusinterpreter_out.mix(WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter, ch_inputs)) } // @@ -859,7 +859,7 @@ workflow ONCOANALYSER { // channel: [val(meta), linx_somatic_annotation_dir] ch_linx_anno = ch_linx_somatic_out.map { meta, anno_dir, vis_dir -> [meta, anno_dir]} - // channel: [val(meta), chord_prediction, purple_dir, linx_dir, virusinterpreter_dir] + // channel: [val(meta), chord_prediction, purple_dir, linx_dir, virusinterpreter] ch_protect_inputs_source = WorkflowOncoanalyser.groupByMeta( run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CHORD_PREDICTION, Constants.DataType.TUMOR]), run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), @@ -868,7 +868,7 @@ workflow ONCOANALYSER { ) // Create process-specific meta - // channel: [val(meta_protect), chord_prediction, purple_dir, linx_dir, virusinterpreter_dir] + // channel: [val(meta_protect), chord_prediction, purple_dir, linx_dir, virusinterpreter] ch_protect_inputs = ch_protect_inputs_source .map { def meta = it[0] @@ -962,7 +962,7 @@ workflow ONCOANALYSER { // channel: [val(meta), linx_somatic_annotation_dir] ch_linx_anno = ch_linx_somatic_out.map { meta, anno_dir, vis_dir -> [meta, anno_dir]} - // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter_dir] + // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter] ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), @@ -972,7 +972,7 @@ workflow ONCOANALYSER { ) // Create inputs and create process-specific meta - // channel: [val(meta_cuppa), isofox_dir, purple_dir, linx_dir, virusinterpreter_dir] + // channel: [val(meta_cuppa), isofox_dir, purple_dir, linx_dir, virusinterpreter] ch_cuppa_inputs = ch_cuppa_inputs_source .map { def meta = it[0] From 5d94f8e029b8a6255b176d95621ac700efc68967 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 21 Dec 2022 10:39:14 +1100 Subject: [PATCH 075/562] Resolve ORANGE error when writing out JSON --- modules/local/orange/main.nf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index f8b3d336..24ed007a 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -29,7 +29,11 @@ process ORANGE { """ echo "${pipeline_version_str}" > pipeline_version.txt + # NOTE(SW): '--add-opens java.base/java.time=ALL-UNNAMED' resolves issue writing JSON, see: + # https://stackoverflow.com/questions/70412805/what-does-this-error-mean-java-lang-reflect-inaccessibleobjectexception-unable/70878195#70878195 + java \\ + --add-opens java.base/java.time=ALL-UNNAMED \\ -Xmx${task.memory.giga}g \\ -jar ${task.ext.jarPath} \\ \\ From 64ddeb789d343c37c6fd8084f8d14ff0816de9c1 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 21 Dec 2022 10:39:57 +1100 Subject: [PATCH 076/562] Correct ORANGE input variable name --- modules/local/orange/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 24ed007a..e7fbbb5f 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -56,7 +56,7 @@ process ORANGE { \\ -sage_somatic_tumor_sample_bqr_plot ${sage_somatic_bqr} \\ -sage_somatic_ref_sample_bqr_plot ${sage_germline_bqr} \\ - -sage_germline_gene_coverage_tsv ${sage_germlien_coverage} \\ + -sage_germline_gene_coverage_tsv ${sage_germline_coverage} \\ \\ -purple_qc_file ${purple_dir}/${meta.tumor_id}.purple.qc \\ -purple_purity_tsv ${purple_dir}/${meta.tumor_id}.purple.purity.tsv \\ From 69cc60ec101c59a85a3d476ff9438eb414162c8e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 21 Dec 2022 10:40:40 +1100 Subject: [PATCH 077/562] Provide LINX germline to ORANGE --- modules/local/orange/main.nf | 16 ++++++++-------- modules/local/protect/main.nf | 4 ++-- workflows/oncoanalyser.nf | 10 +++++++--- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index e7fbbb5f..a11fa35d 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -5,7 +5,7 @@ process ORANGE { container 'docker.io/scwatts/orange:1.10--0' input: - tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(chord_prediction), path(lilac_dir), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(linx_anno_dir), path(linx_plot_dir), path(protect), path(peach_genotype), path(cuppa), path(cuppa_summary_plot), path(cuppa_feature_plot), path(virusinterpreter) + tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(chord_prediction), path(lilac_dir), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(protect), path(peach_genotype), path(cuppa), path(cuppa_summary_plot), path(cuppa_feature_plot), path(virusinterpreter) val genome_ver path disease_ontology path known_fusion_data @@ -69,13 +69,13 @@ process ORANGE { -purple_germline_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.germline.vcf.gz \\ -purple_plot_directory ${purple_dir}/plot/ \\ \\ - -linx_breakend_tsv ${linx_anno_dir}/${meta.tumor_id}.linx.breakend.tsv \\ - -linx_structural_variant_tsv ${linx_anno_dir}/${meta.tumor_id}.linx.svs.tsv \\ - -linx_driver_tsv ${linx_anno_dir}/${meta.tumor_id}.linx.drivers.tsv \\ - -linx_driver_catalog_tsv ${linx_anno_dir}/${meta.tumor_id}.linx.driver.catalog.tsv \\ - -linx_fusion_tsv ${linx_anno_dir}/${meta.tumor_id}.linx.fusion.tsv \\ - -linx_germline_disruption_tsv ${linx_anno_dir}/${meta.normal_id}.linx.germline.disruption.tsv \\ - -linx_plot_directory ${linx_plot_dir} \\ + -linx_breakend_tsv ${linx_somatic_anno_dir}/${meta.tumor_id}.linx.breakend.tsv \\ + -linx_structural_variant_tsv ${linx_somatic_anno_dir}/${meta.tumor_id}.linx.svs.tsv \\ + -linx_driver_tsv ${linx_somatic_anno_dir}/${meta.tumor_id}.linx.drivers.tsv \\ + -linx_driver_catalog_tsv ${linx_somatic_anno_dir}/${meta.tumor_id}.linx.driver.catalog.tsv \\ + -linx_fusion_tsv ${linx_somatic_anno_dir}/${meta.tumor_id}.linx.fusion.tsv \\ + -linx_germline_disruption_tsv ${linx_germline_anno_dir}/${meta.normal_id}.linx.germline.disruption.tsv \\ + -linx_plot_directory ${linx_somatic_plot_dir} \\ \\ -cuppa_result_csv ${cuppa} \\ -cuppa_feature_plot ${cuppa_summary_plot} \\ diff --git a/modules/local/protect/main.nf b/modules/local/protect/main.nf index c9216041..55450f8d 100644 --- a/modules/local/protect/main.nf +++ b/modules/local/protect/main.nf @@ -35,8 +35,8 @@ process PROTECT { -purple_purity_tsv ${purple_dir}/${meta.tumor_id}.purple.purity.tsv \\ -purple_qc_file ${purple_dir}/${meta.tumor_id}.purple.qc \\ -purple_gene_copy_number_tsv ${purple_dir}/${meta.tumor_id}.purple.cnv.gene.tsv \\ - -purple_somatic_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.purple.driver.catalog.somatic.tsv \\ - -purple_germline_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.purple.driver.catalog.germline.tsv \\ + -purple_somatic_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.somatic.tsv \\ + -purple_germline_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.germline.tsv \\ -purple_somatic_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.somatic.vcf.gz \\ -purple_germline_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.germline.vcf.gz \\ -linx_fusion_tsv ${linx_dir}/${meta.tumor_id}.linx.fusion.tsv \\ diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index dccc63a3..c55a8841 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -777,6 +777,8 @@ workflow ONCOANALYSER { // // channel: [val(meta), linx_annotation_dir, linx_visuliaser_dir] ch_linx_somatic_out = Channel.empty() + // channel: [val(meta), linx_annotation_dir] + ch_linx_germline_out = Channel.empty() if (run.linx) { // Select input sources // channel: [val(meta), vcf] @@ -825,6 +827,7 @@ workflow ONCOANALYSER { // Set outputs, restoring original meta ch_versions = ch_versions.mix(LINX.out.versions) ch_linx_somatic_out = ch_linx_somatic_out.mix(WorkflowOncoanalyser.restoreMeta(LINX.out.somatic, ch_inputs)) + ch_linx_germline_out = ch_linx_germline_out.mix(WorkflowOncoanalyser.restoreMeta(LINX.out.germline, ch_inputs)) // // MODULE: Run gpgr to generate a LINX report @@ -1097,7 +1100,7 @@ workflow ONCOANALYSER { // Split LINX channel // channel (anno): [val(meta), anno_dir] // channel (plot): [val(meta), plot_dir] - ch_orange_inputs_linx = ch_linx_somatic_out + ch_orange_inputs_linx_somatic = ch_linx_somatic_out .multiMap { meta, anno_dir, plot_dir -> anno: [meta, anno_dir] plot: [meta, plot_dir] @@ -1116,8 +1119,9 @@ workflow ONCOANALYSER { run.sage ? ch_sage_somatic_normal_bqr_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_BQR, Constants.DataType.NORMAL]), run.sage ? ch_sage_germline_coverage_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_COVERAGE, Constants.DataType.NORMAL]), run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput([Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), - run.linx ? ch_orange_inputs_linx.anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.TUMOR_NORMAL]), - run.linx ? ch_orange_inputs_linx.plot : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_PLOT_DIR, Constants.DataType.TUMOR_NORMAL]), + run.linx ? ch_orange_inputs_linx_somatic.anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.TUMOR_NORMAL]), + run.linx ? ch_orange_inputs_linx_somatic.plot : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_PLOT_DIR, Constants.DataType.TUMOR_NORMAL]), + run.linx ? ch_linx_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.NORMAL]), run.protect ? ch_protect_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PROTECT_TSV, Constants.DataType.TUMOR]), run.peach ? ch_peach_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PEACH_TSV, Constants.DataType.NORMAL]), run.cuppa ? ch_cuppa_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CUPPA_CSV, Constants.DataType.TUMOR]), From b098a2bbc7358c1c190bbe93b379cb56e5ba71e7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 21 Dec 2022 10:41:25 +1100 Subject: [PATCH 078/562] Use samtools 1.12 for ORANGE compatibility --- conf/modules.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conf/modules.config b/conf/modules.config index 6dbcf123..47a28140 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -261,6 +261,9 @@ process { } withName: 'SAMTOOLS_FLAGSTAT' { + container = { "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.12--h9aed4be_1' : + 'quay.io/biocontainers/samtools:1.12--h9aed4be_1' }" } publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, From 89e33728ae63bd58826594ffebd1763dd6d4be9e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 21 Dec 2022 16:54:19 +1100 Subject: [PATCH 079/562] Remove check samplesheet module --- conf/base.config | 4 --- modules/local/check_samplesheet/main.nf | 33 ------------------------- workflows/oncoanalyser.nf | 2 -- 3 files changed, 39 deletions(-) delete mode 100644 modules/local/check_samplesheet/main.nf diff --git a/conf/base.config b/conf/base.config index a6f94345..5a78b041 100644 --- a/conf/base.config +++ b/conf/base.config @@ -57,10 +57,6 @@ process { errorStrategy = 'retry' maxRetries = 2 } - withName:'CHECK_SAMPLESHEET' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 1.GB, 'memory' ) } - } withName:'AMBER' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } diff --git a/modules/local/check_samplesheet/main.nf b/modules/local/check_samplesheet/main.nf deleted file mode 100644 index 3bafa9f1..00000000 --- a/modules/local/check_samplesheet/main.nf +++ /dev/null @@ -1,33 +0,0 @@ -process CHECK_SAMPLESHEET { - conda (params.enable_conda ? "conda-forge::python=3.9.5" : null) - container 'quay.io/biocontainers/python:3.9--1' - - input: - path samplesheet - val mode - - output: - path samplesheet - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - check_samplesheet.py \\ - --input_fp "${samplesheet}" \\ - --mode "${mode}" - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - python: \$(python --version | sed 's/Python //g') - END_VERSIONS - """ - - stub: - """ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index c55a8841..77474830 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -54,8 +54,6 @@ if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input sample // // MODULES // -include { CHECK_SAMPLESHEET } from '../modules/local/check_samplesheet/main' - include { AMBER } from '../modules/local/amber/main' include { CHORD } from '../modules/local/chord/main' include { COBALT } from '../modules/local/cobalt/main' From d9d8d6cefb89d4c2c57b52875ebb4896caf15818 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 21 Dec 2022 16:55:35 +1100 Subject: [PATCH 080/562] Update meta.yml and adjust some module names --- conf/base.config | 10 +- conf/modules.config | 6 +- modules/local/amber/meta.yml | 25 ++-- modules/local/chord/meta.yml | 48 +++++++ modules/local/cobalt/meta.yml | 21 ++- modules/local/cuppa/classifier/meta.yml | 50 +++++++ modules/local/cuppa/visualiser/main.nf | 11 +- modules/local/cuppa/visualiser/meta.yml | 54 ++++++++ modules/local/custom/extract_tarball/main.nf | 2 +- .../lilac_extract_and_index_contig/main.nf | 2 +- .../lilac_extract_and_index_contig/meta.yml | 40 ------ .../custom/lilac_realign_reads_lilac/main.nf | 2 +- .../custom/lilac_realign_reads_lilac/meta.yml | 57 -------- modules/local/custom/lilac_slice/main.nf | 2 +- modules/local/custom/lilac_slice/meta.yml | 49 ------- .../local/gpgr/{linx_report => linx}/main.nf | 2 +- .../local/gpgr/{linx_report => linx}/meta.yml | 27 ++-- modules/local/gridss/annotate/main.nf | 2 +- modules/local/gridss/annotate/meta.yml | 37 +++++ modules/local/gridss/assemble/main.nf | 2 +- modules/local/gridss/assemble/meta.yml | 24 ++-- modules/local/gridss/call/main.nf | 2 +- modules/local/gridss/call/meta.yml | 26 ++-- modules/local/gridss/index/main.nf | 2 +- modules/local/gridss/index/meta.yml | 58 ++++++++ modules/local/gridss/preprocess/main.nf | 2 +- modules/local/gridss/preprocess/meta.yml | 26 ++-- modules/local/gripss/germline/meta.yml | 35 ++--- modules/local/gripss/somatic/meta.yml | 37 ++--- modules/local/isofox/meta.yml | 62 +++++++++ modules/local/lilac/main.nf | 2 +- modules/local/lilac/meta.yml | 57 ++++---- modules/local/linx/germline/meta.yml | 34 ++--- modules/local/linx/somatic/meta.yml | 34 ++--- modules/local/linx/visualiser/main.nf | 2 +- modules/local/linx/visualiser/meta.yml | 26 ++-- modules/local/orange/main.nf | 6 +- modules/local/orange/meta.yml | 129 ++++++++++++++++++ modules/local/pave/germline/meta.yml | 49 +++---- modules/local/pave/somatic/meta.yml | 38 +++--- modules/local/peach/meta.yml | 45 ++++++ modules/local/protect/meta.yml | 44 ++++++ modules/local/purple/meta.yml | 38 +++--- modules/local/sage/germline/meta.yml | 46 +++---- modules/local/sage/somatic/meta.yml | 52 ++++--- modules/local/sigs/meta.yml | 40 ++++++ modules/local/virusbreakend/meta.yml | 70 ++++++++++ modules/local/virusinterpreter/meta.yml | 58 ++++++++ subworkflows/local/gridss.nf | 30 ++-- subworkflows/local/lilac.nf | 30 ++-- subworkflows/local/linx.nf | 12 +- subworkflows/local/prepare_reference.nf | 10 +- workflows/oncoanalyser.nf | 16 +-- 53 files changed, 1035 insertions(+), 556 deletions(-) create mode 100644 modules/local/chord/meta.yml create mode 100644 modules/local/cuppa/classifier/meta.yml create mode 100644 modules/local/cuppa/visualiser/meta.yml delete mode 100644 modules/local/custom/lilac_extract_and_index_contig/meta.yml delete mode 100644 modules/local/custom/lilac_realign_reads_lilac/meta.yml delete mode 100644 modules/local/custom/lilac_slice/meta.yml rename modules/local/gpgr/{linx_report => linx}/main.nf (97%) rename modules/local/gpgr/{linx_report => linx}/meta.yml (58%) create mode 100644 modules/local/gridss/annotate/meta.yml create mode 100644 modules/local/gridss/index/meta.yml create mode 100644 modules/local/isofox/meta.yml create mode 100644 modules/local/orange/meta.yml create mode 100644 modules/local/peach/meta.yml create mode 100644 modules/local/protect/meta.yml create mode 100644 modules/local/sigs/meta.yml create mode 100644 modules/local/virusbreakend/meta.yml create mode 100644 modules/local/virusinterpreter/meta.yml diff --git a/conf/base.config b/conf/base.config index 5a78b041..67c192d2 100644 --- a/conf/base.config +++ b/conf/base.config @@ -82,15 +82,15 @@ process { cpus = { check_max( 4, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName: '.*LILAC:REALIGN_READS' { + withName: '.*LILAC:CUSTOM_REALIGNREADS' { cpus = { check_max( 4, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName: '.*LILAC:SLICE' { + withName: '.*LILAC:CUSTOM_SLICE' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 6.GB, 'memory' ) } } - withName: '.*LILAC:EXTRACT_AND_INDEX_CONTIG' { + withName: '.*LILAC:CUSTOM_EXTRACTCONTIG' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 6.GB, 'memory' ) } } @@ -98,7 +98,7 @@ process { cpus = { check_max( 4, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'LINX_REPORT' { + withName:'GPGR_LINX' { memory = { check_max( 12.GB, 'memory' ) } } withName:'.*PAVE.*' { @@ -121,7 +121,7 @@ process { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 4.GB, 'memory' ) } } - withName:'SLICE' { + withName:'CUSTOM_SLICE' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } diff --git a/conf/modules.config b/conf/modules.config index 47a28140..c7d7ab48 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -42,7 +42,7 @@ process { ext.otherJvmHeap = 4.GB } - withName: '.*:GRIDSS:CALL' { + withName: '.*:GRIDSS:GRIDSS_CALL' { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -107,7 +107,7 @@ process { ] } - withName: '.*LINX:VISUALISER' { + withName: '.*LINX:LINX_VISUALISER' { ext.path_circos = 'circos' publishDir = [ path: { "${params.outdir}" }, @@ -116,7 +116,7 @@ process { ] } - withName: 'LINX_REPORT' { + withName: 'GPGR_LINX' { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, diff --git a/modules/local/amber/meta.yml b/modules/local/amber/meta.yml index 08075526..dfa92a3e 100644 --- a/modules/local/amber/meta.yml +++ b/modules/local/amber/meta.yml @@ -1,24 +1,20 @@ -name: "AMBER" +name: amber description: Generate a tumor BAF file for PURPLE copy number fit keywords: - - amber - baf - cnv tools: - - "AMBER": - description: "Generate a tumor BAF file for PURPLE copy number fit." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/amber" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/amber" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/amber" - doi: "" - licence: "['GPL v3']" - + - amber: + description: Generate a tumor BAF file for PURPLE copy number fit. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/amber + documentation: https://github.com/hartwigmedical/hmftools/tree/master/amber + licence: ["GPL v3"] input: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - tumor_bam: type: file description: Tumor BAM file @@ -35,17 +31,19 @@ input: type: file description: Normal BAI file pattern: "*.{bai}" + - genome_ver: + type: string + description: Reference genome version - loci: type: file description: AMBER loci file pattern: "*.{vcf.gz}" - output: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - amber_dir: type: directory description: AMBER output directory @@ -53,6 +51,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/chord/meta.yml b/modules/local/chord/meta.yml new file mode 100644 index 00000000..d6d02374 --- /dev/null +++ b/modules/local/chord/meta.yml @@ -0,0 +1,48 @@ +name: chord +description: Predict HR deficiency from mutation contexts +keywords: + - hrd + - mutational signatures +tools: + - chord: + description: Prediction of HR deficiency from mutation contexts. + homepage: https://github.com/UMCUGenetics/CHORD + documentation: https://github.com/UMCUGenetics/CHORD + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - smlv_vcf: + type: file + description: Tumor small variant VCF file + pattern: "*.{vcf.gz}" + - sv_vcf: + type: file + description: GRIPSS structural variant VCF file with PURPLE annotations + pattern: "*.{vcf.gz}" + - genome_ver: + type: string + description: Reference genome version +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - prediction: + type: file + description: HRD prediction + pattern: "*.{txt}" + - signatures: + type: file + description: Mutation signatures + pattern: "*.{txt}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/cobalt/meta.yml b/modules/local/cobalt/meta.yml index fc577f07..cedfc27d 100644 --- a/modules/local/cobalt/meta.yml +++ b/modules/local/cobalt/meta.yml @@ -1,24 +1,21 @@ -name: "COBALT" +name: cobalt description: Count bam lines determines the read depth ratios of the supplied tumor and reference genomes keywords: - cobalt - read depth ratios - cnv tools: - - "COBALT": - description: "Count bam lines determines the read depth ratios of the supplied tumor and reference genomes." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/cobalt" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/cobalt" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/cobalt" - doi: "" - licence: "['GPL v3']" - + - cobalt: + description: Count bam lines determines the read depth ratios of the supplied tumor and reference genomes. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/cobalt + documentation: https://github.com/hartwigmedical/hmftools/tree/master/cobalt + licence: ["GPL v3"] input: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - tumor_bam: type: file description: Tumor BAM file @@ -39,13 +36,12 @@ input: type: file description: COBALT GC Profile file pattern: "*.{cnp}" - output: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - cobalt: type: directory description: COBALT output directory @@ -53,6 +49,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/cuppa/classifier/meta.yml b/modules/local/cuppa/classifier/meta.yml new file mode 100644 index 00000000..4b4b4fdb --- /dev/null +++ b/modules/local/cuppa/classifier/meta.yml @@ -0,0 +1,50 @@ +name: cuppa_classifier +description: Predict tumor sample tissue of origin +keywords: + - cup + - tumor + - classification +tools: + - cuppa: + description: Prediction of tumor sample tissue of origin + homepage: https://github.com/hartwigmedical/hmftools/tree/master/cuppa + documentation: https://github.com/hartwigmedical/hmftools/tree/master/cuppa + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - isofox_dir: + type: directory + description: Isofox output directory (optional) + - purple_dir: + type: directory + description: PURPLE output directory + - linx_dir: + type: directory + description: LINX output directory + - virusinterpreter: + type: file + description: Virus Interpreter annotations file + pattern: "*.{tsv}" + - cuppa_resources: + type: directory + description: CUPPA resource directory +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - csv: + type: file + description: CUPPA classification output file + pattern: "*.{csv}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf index 488040e5..ade9a0aa 100644 --- a/modules/local/cuppa/visualiser/main.nf +++ b/modules/local/cuppa/visualiser/main.nf @@ -8,11 +8,11 @@ process CUPPA_VISUALISER { tuple val(meta), path(cuppa_csv) output: + tuple val(meta), path('*conclusion.txt') , emit: conclusion + tuple val(meta), path('*cup_report.pdf') , emit: report tuple val(meta), path('*report.summary.png') , emit: summary_plot tuple val(meta), path('*report.features.png'), emit: feature_plot - path '*chart.png' - path '*conclusion.txt' - path '*cup_report.pdf' + tuple val(meta), path('*chart.png') , emit: chart_plot path 'versions.yml' , emit: versions when: @@ -37,12 +37,11 @@ process CUPPA_VISUALISER { stub: """ - touch ${meta.id}.cuppa.chart.png - touch ${meta.id}.cuppa.conclusion.txt touch ${meta.id}.cuppa.conclusion.txt touch ${meta.id}_cup_report.pdf - touch ${meta.id}.cup.report.features.png touch ${meta.id}.cup.report.summary.png + touch ${meta.id}.cup.report.features.png + touch ${meta.id}.cuppa.chart.png echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/cuppa/visualiser/meta.yml b/modules/local/cuppa/visualiser/meta.yml new file mode 100644 index 00000000..0794bbe9 --- /dev/null +++ b/modules/local/cuppa/visualiser/meta.yml @@ -0,0 +1,54 @@ +name: cuppa_visualiser +description: Visualise tissue of origin predictions +keywords: + - cup + - tumor + - classification +tools: + - cuppa: + description: Prediction of tumor sample tissue of origin + homepage: https://github.com/hartwigmedical/hmftools/tree/master/cuppa + documentation: https://github.com/hartwigmedical/hmftools/tree/master/cuppa + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - csv: + type: file + description: CUPPA classification output file + pattern: "*.{csv}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - conclusion: + type: file + description: Conclusion file + pattern: "*.{txt}" + - report: + type: file + description: Report PDF file + pattern: "*.{pdf}" + - summary_plot: + type: file + description: Summary plot file + pattern: "*.{png}" + - feature_plot: + type: file + description: Feature plot file + pattern: "*.{png}" + - chart_plot: + type: file + description: Chart plot file + pattern: "*.{png}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/custom/extract_tarball/main.nf b/modules/local/custom/extract_tarball/main.nf index 208c2d32..20e6d039 100644 --- a/modules/local/custom/extract_tarball/main.nf +++ b/modules/local/custom/extract_tarball/main.nf @@ -1,4 +1,4 @@ -process EXTRACT_TARBALL { +process CUSTOM_EXTRACTTARBALL { label 'process_single' container 'public.ecr.aws/ubuntu/ubuntu:20.04_stable' diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index 39077940..d0af2900 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -1,4 +1,4 @@ -process EXTRACT_AND_INDEX_CONTIG { +process CUSTOM_EXTRACTCONTIG { tag "${contig_name}" label 'process_single' diff --git a/modules/local/custom/lilac_extract_and_index_contig/meta.yml b/modules/local/custom/lilac_extract_and_index_contig/meta.yml deleted file mode 100644 index 1125a44f..00000000 --- a/modules/local/custom/lilac_extract_and_index_contig/meta.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: "lilac_extract_and_index_contig" -description: Extract a contig FASTA record from a reference genome and index with BWA -keywords: - - reference - - contig - - extract -tools: - - custom: - description: "Extract and index contig" - homepage: "https://github.com/umccr/hmftools" - documentation: "https://github.com/umccr/hmftools" - doi: "" - licence: "['GPL v3']" - -input: - - contig_name: - type: string - description: Contig name - - ref_data_genome_dir: - type: directory - description: Directory containing reference genome - - ref_data_genome_fn: - type: string - description: Reference genome filename - -output: - - contig: - type: file - description: FASTA containing extracted contig - pattern: "*.{fa}" - - bwa_indices: - type: list - description: BWA indices for extracted contig - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - -authors: - - "@scwatts" diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf index c569a73b..442bcfd3 100644 --- a/modules/local/custom/lilac_realign_reads_lilac/main.nf +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -1,4 +1,4 @@ -process REALIGN_READS { +process CUSTOM_REALIGNREADS { tag "${meta.id}" label 'process_low' diff --git a/modules/local/custom/lilac_realign_reads_lilac/meta.yml b/modules/local/custom/lilac_realign_reads_lilac/meta.yml deleted file mode 100644 index 524152b5..00000000 --- a/modules/local/custom/lilac_realign_reads_lilac/meta.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: "lilac_realign_reads_lilac" -description: Realign reads for LILAC -keywords: - - alignment - - lilac - - preprocessing -tools: - - custom: - description: "Realign reads for LILAC" - homepage: "https://github.com/umccr/hmftools" - documentation: "https://github.com/umccr/hmftools" - doi: "" - licence: "['GPL v3']" - -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. ['id': 'sample_name'] - - bam: - type: file - description: BAM file - pattern: "*.{bam}" - - bai: - type: file - description: BAI file - pattern: "*.{bai}" - - reference: - type: path - description: Reference FASTA file - pattern: "*.{fa}" - - reference_indices: - type: list - description: BWA indices for reference FASTA file - -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. ['id': 'sample_name'] - - bam: - type: list - description: BAM file - pattern: "*.{bam}" - - bai: - type: list - description: BAI file - pattern: "*.{bai}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - -authors: - - "@scwatts" diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index fa8ccd8c..58f59c2c 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -1,4 +1,4 @@ -process SLICE { +process CUSTOM_SLICE { tag "${meta.id}" label 'process_single' diff --git a/modules/local/custom/lilac_slice/meta.yml b/modules/local/custom/lilac_slice/meta.yml deleted file mode 100644 index f1c5076c..00000000 --- a/modules/local/custom/lilac_slice/meta.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: "lilac_slice" -description: Slice BAM for LILAC -keywords: - - samtools - - slice -tools: - - custom: - description: "Slice BAM for LILAC" - homepage: "https://github.com/umccr/hmftools" - documentation: "https://github.com/umccr/hmftools" - doi: "" - licence: "['GPL v3']" - -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - bam: - type: file - description: BAM file - pattern: "*.{bam}" - - bai: - type: file - description: BAI file - pattern: "*.{bai}" - - bed: - type: file - description: Optional slice regions BED file - pattern: "*.{bed}" - -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - bam: - type: file - description: Sliced BAM file - pattern: "*.{bam}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - -authors: - - "@scwatts" diff --git a/modules/local/gpgr/linx_report/main.nf b/modules/local/gpgr/linx/main.nf similarity index 97% rename from modules/local/gpgr/linx_report/main.nf rename to modules/local/gpgr/linx/main.nf index f35dbe4a..a2b45add 100644 --- a/modules/local/gpgr/linx_report/main.nf +++ b/modules/local/gpgr/linx/main.nf @@ -1,4 +1,4 @@ -process LINX_REPORT { +process GPGR_LINX { tag "${meta.id}" label 'process_single' diff --git a/modules/local/gpgr/linx_report/meta.yml b/modules/local/gpgr/linx/meta.yml similarity index 58% rename from modules/local/gpgr/linx_report/meta.yml rename to modules/local/gpgr/linx/meta.yml index 16e4dabb..dbb21a04 100644 --- a/modules/local/gpgr/linx_report/meta.yml +++ b/modules/local/gpgr/linx/meta.yml @@ -1,38 +1,34 @@ -name: "LINX_REPORT" -description: Read and process output files from somatic LINX +name: gpgr_linx +description: Create an interactive report for LINX keywords: - - gpgr - - linx report + - report + - linx - sv - cnv tools: - - "gpgr": - description: "Read and process output files from LINX." - homepage: "https://github.com/umccr/gpgr" - documentation: "https://github.com/umccr/gpgr" - tool_dev_url: "https://github.com/umccr/gpgr" - doi: "" - licence: "['MIT']" - + - gpgr: + description: Create interactive reports from genomic data + homepage: https://github.com/umccr/gpgr + documentation: https://github.com/umccr/gpgr + licence: ["MIT"] input: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor'] + e.g. [id: 'sample_id'] - linx_annotation: type: directory description: Somatic LINX annotation output directory - linx_visualiser: type: directory description: Somatic LINX visualiser output directory - output: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor'] + e.g. [id: 'sample_id'] - html: type: file description: gpgr LINX report file @@ -41,6 +37,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/gridss/annotate/main.nf b/modules/local/gridss/annotate/main.nf index 7a7c18f0..6981bffb 100644 --- a/modules/local/gridss/annotate/main.nf +++ b/modules/local/gridss/annotate/main.nf @@ -1,4 +1,4 @@ -process ANNOTATE { +process GRIDSS_ANNOTATE { tag "${meta.id}" label 'process_single' diff --git a/modules/local/gridss/annotate/meta.yml b/modules/local/gridss/annotate/meta.yml new file mode 100644 index 00000000..2a935710 --- /dev/null +++ b/modules/local/gridss/annotate/meta.yml @@ -0,0 +1,37 @@ +name: gridss_annotate +description: Annotate SVs called with GRIDSS +keywords: + - annotate + - sv +tools: + - gridss: + description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. + homepage: https://github.com/PapenfussLab/gridss + documentation: https://github.com/PapenfussLab/gridss + licence: ["GPL >=3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - gridss_vcf: + type: file + description: GRIDSS structural variant VCF file + pattern: "*.{bam}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - vcf: + type: file + description: Annotated structural variant VCF file + pattern: "*.{vcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/gridss/assemble/main.nf b/modules/local/gridss/assemble/main.nf index 04ad5f02..c49abf4d 100644 --- a/modules/local/gridss/assemble/main.nf +++ b/modules/local/gridss/assemble/main.nf @@ -1,4 +1,4 @@ -process ASSEMBLE { +process GRIDSS_ASSEMBLE { tag "${meta.id}" label 'process_medium' diff --git a/modules/local/gridss/assemble/meta.yml b/modules/local/gridss/assemble/meta.yml index f49fb610..b93ae838 100644 --- a/modules/local/gridss/assemble/meta.yml +++ b/modules/local/gridss/assemble/meta.yml @@ -1,18 +1,14 @@ -name: "ASSEMBLE" +name: gridss_assemble description: Assemble SVs with GRIDSS keywords: - - gridss - assemble - sv tools: - - "gridss": - description: "GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements." - homepage: "https://github.com/PapenfussLab/gridss" - documentation: "https://github.com/PapenfussLab/gridss" - tool_dev_url: "https://github.com/PapenfussLab/gridss" - doi: "" - licence: "['GPL >=3']" - + - gridss: + description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. + homepage: https://github.com/PapenfussLab/gridss + documentation: https://github.com/PapenfussLab/gridss + licence: ["GPL >=3"] input: - meta: type: map @@ -31,7 +27,7 @@ input: description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - gridss_config: type: file - description: Optional GRIDSS configuration file + description: Optional GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly fa file @@ -55,11 +51,10 @@ input: type: file description: Reference genome assembly GRIDSS index file pattern: "*.{gridsscache}" - - blacklist: + - blocklist: type: file - description: GRIDSS blacklist file + description: GRIDSS blocklist file pattern: "*.{bed.gz}" - output: - meta: type: map @@ -73,6 +68,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/gridss/call/main.nf b/modules/local/gridss/call/main.nf index b86d67da..7e5d312b 100644 --- a/modules/local/gridss/call/main.nf +++ b/modules/local/gridss/call/main.nf @@ -1,4 +1,4 @@ -process CALL { +process GRIDSS_CALL { tag "${meta.id}" label 'process_medium' diff --git a/modules/local/gridss/call/meta.yml b/modules/local/gridss/call/meta.yml index 04b037e4..db407d72 100644 --- a/modules/local/gridss/call/meta.yml +++ b/modules/local/gridss/call/meta.yml @@ -1,18 +1,14 @@ -name: "CALL" +name: gridss_call description: Call SVs with GRIDSS keywords: - - gridss - - variant calling + - calling - sv tools: - - "gridss": - description: "GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements." - homepage: "https://github.com/PapenfussLab/gridss" - documentation: "https://github.com/PapenfussLab/gridss" - tool_dev_url: "https://github.com/PapenfussLab/gridss" - doi: "" - licence: "['GPL >=3']" - + - gridss: + description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. + homepage: https://github.com/PapenfussLab/gridss + documentation: https://github.com/PapenfussLab/gridss + licence: ["GPL >=3"] input: - meta: type: map @@ -31,7 +27,7 @@ input: description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - gridss_config: type: file - description: Optional GRIDSS configuration file + description: Optional GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly fa file @@ -55,11 +51,10 @@ input: type: file description: Reference genome assembly GRIDSS index file pattern: "*.{gridsscache}" - - blacklist: + - blocklist: type: file - description: GRIDSS blacklist file + description: GRIDSS blocklist file pattern: "*.{bed.gz}" - output: - meta: type: map @@ -74,6 +69,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 63e31b85..5933769b 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -1,4 +1,4 @@ -process INDEX { +process GRIDSS_INDEX { tag "${genome_fasta.name}" label 'process_single' diff --git a/modules/local/gridss/index/meta.yml b/modules/local/gridss/index/meta.yml new file mode 100644 index 00000000..6f6c51c5 --- /dev/null +++ b/modules/local/gridss/index/meta.yml @@ -0,0 +1,58 @@ +name: gridss_index +description: Create GRIDSS indices +keywords: + - index + - sv +tools: + - gridss: + description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. + homepage: https://github.com/PapenfussLab/gridss + documentation: https://github.com/PapenfussLab/gridss + licence: ["GPL >=3"] +input: + - genome_fasta: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file (optional) + pattern: "*.{dict}" + - genome_bwa_index_dir: + type: directory + description: Directory containing reference genome assembly BWA index (optional) + - genome_bwa_index_image: + type: file + description: Reference genome assembly BWA index img file (optional) + pattern: "*.{img}" + - indices: + type: string + description: List of indices to create +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - dict: + type: file + description: Reference genome dictionary file + pattern: "*.{dict}" + - img: + type: file + description: Reference genome BWA index image file + pattern: "*.{img}" + - index: + type: file + description: Reference genome GRIDSS index file + pattern: "*.{gridsscache}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/gridss/preprocess/main.nf b/modules/local/gridss/preprocess/main.nf index fd8af8fa..ddbbae12 100644 --- a/modules/local/gridss/preprocess/main.nf +++ b/modules/local/gridss/preprocess/main.nf @@ -1,4 +1,4 @@ -process PREPROCESS { +process GRIDSS_PREPROCESS { tag "${meta.id}" label 'process_medium' diff --git a/modules/local/gridss/preprocess/meta.yml b/modules/local/gridss/preprocess/meta.yml index 3eef6890..fdba777e 100644 --- a/modules/local/gridss/preprocess/meta.yml +++ b/modules/local/gridss/preprocess/meta.yml @@ -1,18 +1,14 @@ -name: "PREPROCESS" +name: gridss_preprocess description: Preprocess reads for GRIDSS keywords: - - gridss - - read processing + - preprocessing - sv tools: - - "gridss": - description: "GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements." - homepage: "https://github.com/PapenfussLab/gridss" - documentation: "https://github.com/PapenfussLab/gridss" - tool_dev_url: "https://github.com/PapenfussLab/gridss" - doi: "" - licence: "['GPL >=3']" - + - gridss: + description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. + homepage: https://github.com/PapenfussLab/gridss + documentation: https://github.com/PapenfussLab/gridss + licence: ["GPL >=3"] input: - meta: type: map @@ -25,7 +21,7 @@ input: pattern: "*.{bam}" - gridss_config: type: file - description: Optional GRIDSS configuration file + description: Optional GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly fa file @@ -49,7 +45,6 @@ input: type: file description: Reference genome assembly GRIDSS index file pattern: "*.{gridsscache}" - output: - meta: type: map @@ -59,6 +54,9 @@ output: - preprocess_dir: type: directory description: GRIDSS preprocess output directory - + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@scwatts" diff --git a/modules/local/gripss/germline/meta.yml b/modules/local/gripss/germline/meta.yml index 6666ef77..1081597a 100644 --- a/modules/local/gripss/germline/meta.yml +++ b/modules/local/gripss/germline/meta.yml @@ -1,24 +1,21 @@ -name: "GRIPSS_germline" -description: GRIPSS applies a set of filtering and post processing steps on GRIDSS SVs +name: gripss_germline +description: Filter and process GRIDSS germline structural variants keywords: - - gripss - - sv filtering + - sv + - filtering - germline tools: - - "GRIPSS": - description: "GRIPSS applies a set of filtering and post processing steps on GRIDSS SVs." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" - doi: "" - licence: "['GPL v3']" - + - gripss: + description: Apply filtering and post-processing to GRIDSS structural variants. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/gripss + documentation: https://github.com/hartwigmedical/hmftools/tree/master/gripss + licence: ["GPL v3"] input: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'normal']: 'sample_normal'] + e.g. [id: 'sample_id', normal_id: 'normal_name'] - gridss_vcf: type: file description: VCF file @@ -34,11 +31,11 @@ input: - genome_ver: type: string description: Reference genome version - - breakend_pon: + - pon_breakends: type: file description: GRIDSS breakend PON file pattern: "*.{bed.gz}" - - breakpoint_pon: + - pon_breakpoints: type: file description: GRIDSS breakpoint PON file pattern: "*.{bedpe.gz}" @@ -46,17 +43,12 @@ input: type: file description: HMF Known Fusions file pattern: "*.{bedpe}" - - repeat_mask_file: - type: file - description: RepeatMasker resource file (optional) - pattern: "*.{fa.out.gz}" - output: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'normal']: 'sample_normal'] + e.g. [id: 'sample_id', normal_id: 'normal_name'] - vcf_hard: type: list description: Hard filtered VCF file and index file @@ -69,6 +61,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/gripss/somatic/meta.yml b/modules/local/gripss/somatic/meta.yml index 826c74af..fbe5018a 100644 --- a/modules/local/gripss/somatic/meta.yml +++ b/modules/local/gripss/somatic/meta.yml @@ -1,24 +1,21 @@ -name: "GRIPSS_somatic" -description: GRIPSS applies a set of filtering and post processing steps on GRIDSS SVs +name: gripss_somatic +description: Filter and process GRIDSS somatic structural variants keywords: - - gripss - - sv filtering - - germline + - sv + - filtering + - somatic tools: - - "GRIPSS": - description: "GRIPSS applies a set of filtering and post processing steps on GRIDSS SVs." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/gripss" - doi: "" - licence: "['GPL v3']" - + - gripss: + description: Apply filtering and post-processing to GRIDSS structural variants. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/gripss + documentation: https://github.com/hartwigmedical/hmftools/tree/master/gripss + licence: ["GPL v3"] input: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'somatic']: 'sample_somatic'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - gridss_vcf: type: file description: VCF file @@ -34,11 +31,11 @@ input: - genome_ver: type: string description: Reference genome version - - breakend_pon: + - pon_breakend: type: file description: GRIDSS breakend PON file pattern: "*.{bed.gz}" - - breakpoint_pon: + - pon_breakpoints: type: file description: GRIDSS breakpoint PON file pattern: "*.{bedpe.gz}" @@ -46,17 +43,12 @@ input: type: file description: HMF Known Fusions file pattern: "*.{bedpe}" - - repeat_mask_file: - type: file - description: RepeatMasker resource file (optional) - pattern: "*.{fa.out.gz}" - output: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'somatic']: 'sample_somatic'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - vcf_hard: type: list description: Hard filtered VCF file and index file @@ -69,6 +61,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/isofox/meta.yml b/modules/local/isofox/meta.yml new file mode 100644 index 00000000..41bf9132 --- /dev/null +++ b/modules/local/isofox/meta.yml @@ -0,0 +1,62 @@ +name: isofox +description: Characterise and count gene, transcript features +keywords: + - rna + - rnaseq +tools: + - isofox: + description: Characterises and counts gene, transcript features + homepage: https://github.com/hartwigmedical/hmftools/tree/master/isofox + documentation: https://github.com/hartwigmedical/hmftools/tree/master/isofox + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - bai: + type: file + description: BAI file + pattern: "*.{bai}" + - genome_fasta: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_ver: + type: string + description: Reference genome version + - ensembl_data_resources: + type: directory + description: HMF ensembl data resources directory + - exp_counts: + type: file + description: Isofox expected counts file + pattern: "*.{csv}" + - exp_gc_ratios: + type: file + description: Isofox expected GC ratio counts file + pattern: "*.{csv}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - isofox_dir: + type: directory + description: Isofox output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 0c269f5e..25ba5a5e 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -5,7 +5,7 @@ process LILAC { container 'docker.io/scwatts/lilac:1.1--0' input: - tuple val(meta), path(normal_wgs_bam), path(normal_wts_bam), path(tumor_wgs_bam), path(tumor_wgs_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(purple_dir) + tuple val(meta), path(normal_wgs_bam), path(normal_wgs_bai), path(tumor_wgs_bam), path(tumor_wgs_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(purple_dir) path genome_fasta val genome_ver path lilac_resources, stageAs: 'lilac_resources' diff --git a/modules/local/lilac/meta.yml b/modules/local/lilac/meta.yml index 083812cd..8d717839 100644 --- a/modules/local/lilac/meta.yml +++ b/modules/local/lilac/meta.yml @@ -1,41 +1,48 @@ -name: "LILAC" -description: LILAC is a WGS tool for HLA typing and somatic CNV and SNV calling +name: lilac +description: Type HLA alleles and call somatic structural variants keywords: - - lilac + - hla + - typing + - sv tools: - - "LILAC": - description: "LILAC is a WGS tool for HLA typing and somatic CNV and SNV calling." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/lilac" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/lilac" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/lilac" - doi: "" - licence: "['GPL v3']" - + - lilac: + description: Performs HLA typing and calls somatic structural variants + homepage: https://github.com/hartwigmedical/hmftools/tree/master/lilac + documentation: https://github.com/hartwigmedical/hmftools/tree/master/lilac + licence: ["GPL v3"] input: - meta: type: map description: | Groovy Map containing sample information - e.g. ['subject_name': 'subject', ['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] - - tumor_bam: + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - normal_wgs_bam: type: file - description: Optional tumor BAM file + description: Normal WGS BAM file pattern: "*.{bam}" - - normal_bam: + - normal_wgs_bai: type: file - description: Normal BAM file + description: Normal WGS BAI file + pattern: "*.{bai}" + - tumor_wgs_bam: + type: file + description: Normal WGS BAM file (optional) pattern: "*.{bam}" - - tumor_bai: + - tumor_wgs_bai: type: file - description: Optional tumor BAI file + description: Tumor WGS BAI file (optional) pattern: "*.{bai}" - - normal_bai: + - tumor_wts_bam: + type: file + description: Normal WTS BAM file (optional) + pattern: "*.{bam}" + - tumor_wts_bai: type: file - description: Normal BAI file + description: Tumor WTS BAI file (optional) pattern: "*.{bai}" - purple_dir: type: directory - description: Optional PURPLE output directory + description: PURPLE output directory (optional) - genome_fasta: type: file description: Reference genome assembly fa file @@ -43,16 +50,15 @@ input: - genome_ver: type: string description: Reference genome version - - lilac_resource_dir: + - lilac_resources: type: directory - description: LILAC resource directory - + description: LILAC resources directory output: - meta: type: map description: | Groovy Map containing sample information - e.g. ['subject_name': 'subject', ['sample_name', 'tumor']: 'sample_tumor', [['sample_name', 'normal']]: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - lilac_dir: type: file description: LILAC output directory @@ -60,6 +66,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/linx/germline/meta.yml b/modules/local/linx/germline/meta.yml index 335b3de4..f4a5bbd6 100644 --- a/modules/local/linx/germline/meta.yml +++ b/modules/local/linx/germline/meta.yml @@ -1,54 +1,49 @@ -name: "LINX_germline" +name: linx_germline description: Generate LINX germline annotation data keywords: - - linx - germline - sv - annotation tools: - - "LINX": - description: "LINX is an annotation, interpretation and visualisation tool for structural variants." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/linx" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/linx" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/linx" - doi: "" - licence: "['GPL v3']" - + - linx: + description: An annotation, interpretation and visualisation tool for structural variants. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/linx + documentation: https://github.com/hartwigmedical/hmftools/tree/master/linx + licence: ["GPL v3"] input: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'normal']: 'sample_normal'] + e.g. [id: 'sample_id'] - gridss_sv: type: file - description: GRIPSS hard filtered VCF + description: GRIPSS hard filtered VCF file pattern: "*.{vcf.gz}" - genome_ver: type: string description: Reference genome version - - fragile_sites: + - fragile_regions: type: file - description: LINX fragile sites file + description: LINX fragile regions file pattern: "*.{csv}" - lines: type: file description: LINEs file pattern: "*.{csv}" - - ensembl_data_dir: + - ensembl_data_resources: type: directory - description: HMF Ensembl Data Cache directory + description: HMF ensembl data resources directory - driver_gene_panel: type: file - description: HMF Driver Gene Panel file + description: Driver gene panel file pattern: "*.{csv}" - output: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'normal']: 'sample_normal'] + e.g. [id: 'sample_id'] - annotation_dir: type: directory description: LINX annotation output directory @@ -56,6 +51,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/linx/somatic/meta.yml b/modules/local/linx/somatic/meta.yml index b620c8d1..6b9b41ae 100644 --- a/modules/local/linx/somatic/meta.yml +++ b/modules/local/linx/somatic/meta.yml @@ -1,57 +1,52 @@ -name: "LINX_somatic" +name: linx_somatic description: Generate LINX somatic annotation data keywords: - - linx - somatic - sv - annotation tools: - - "LINX": - description: "LINX is an annotation, interpretation and visualisation tool for structural variants." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/linx" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/linx" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/linx" - doi: "" - licence: "['GPL v3']" - + - linx: + description: An annotation, interpretation and visualisation tool for structural variants. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/linx + documentation: https://github.com/hartwigmedical/hmftools/tree/master/linx + licence: ["GPL v3"] input: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor'] + e.g. [id: 'sample_id'] - purple_dir: type: directory description: PURPLE output directory - genome_ver: type: string description: Reference genome version - - fragile_sites: + - fragile_regions: type: file - description: LINX fragile sites file + description: LINX fragile regions file pattern: "*.{csv}" - lines: type: file description: LINEs file pattern: "*.{csv}" - - ensembl_data_dir: + - ensembl_data_resources: type: directory - description: HMF Ensembl Data Cache directory + description: HMF ensembl data resources directory - known_fusion_data: type: file - description: HMF Known Fusions Data file + description: Known susions data file pattern: "*.{bedpe}" - driver_gene_panel: type: file - description: HMF Driver Gene Panel file + description: Driver Gene Panel file pattern: "*.{csv}" - output: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor'] + e.g. [id: 'sample_id'] - annotation_dir: type: directory description: LINX annotation output directory @@ -59,6 +54,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index f1c2baf7..b2d6e65a 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -1,4 +1,4 @@ -process VISUALISER { +process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' diff --git a/modules/local/linx/visualiser/meta.yml b/modules/local/linx/visualiser/meta.yml index 725e21d8..43012afc 100644 --- a/modules/local/linx/visualiser/meta.yml +++ b/modules/local/linx/visualiser/meta.yml @@ -1,42 +1,37 @@ -name: "VISUALISER" +name: linx_visualiser description: Visualise LINX somatic annotations keywords: - - linx - somatic - sv - annotation - visualisation tools: - - "LINX": - description: "LINX is an annotation, interpretation and visualisation tool for structural variants." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/linx" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/linx" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/linx" - doi: "" - licence: "['GPL v3']" - + - linx: + description: An annotation, interpretation and visualisation tool for structural variants. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/linx + documentation: https://github.com/hartwigmedical/hmftools/tree/master/linx + licence: ["GPL v3"] input: - meta: type: map description: | Groovy Map containing sample information - e.g. ['subject_name': 'subject', ['sample_name', 'tumor']: 'sample', ['tumor', 'bam']: 'path/to/bam'] + e.g. [id: 'sample_id'] - genome_ver: type: string description: Reference genome version - linx: type: directory description: LINX somatic annotation output directory - - ensembl_data_dir: + - ensembl_data_resources: type: directory - description: HMF Ensembl Data Cache directory - + description: HMF ensembl data resources directory output: - meta: type: map description: | Groovy Map containing sample information - e.g. ['subject_name': 'subject', ['sample_name', 'tumor']: 'sample', ['tumor', 'bam']: 'path/to/bam'] + e.g. [id: 'sample_id'] - visualiser_dir: type: directory description: LINX visualiser output directory @@ -44,6 +39,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index a11fa35d..03ef3bd9 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -15,9 +15,9 @@ process ORANGE { val pipeline_version output: - path '*.orange.json' - path '*.orange.pdf' - path 'versions.yml', emit: versions + tuple val(meta), path('*.orange.pdf') , emit: pdf + tuple val(meta), path('*.orange.json'), emit: json + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/orange/meta.yml b/modules/local/orange/meta.yml new file mode 100644 index 00000000..2206ed7f --- /dev/null +++ b/modules/local/orange/meta.yml @@ -0,0 +1,129 @@ +name: orange +description: Summarise key outputs of the HMF toolkit +keywords: + - cancer report +tools: + - orange: + description: Summarises key outputs of the HMF toolkit + homepage: https://github.com/hartwigmedical/hmftools/tree/master/orange + documentation: https://github.com/hartwigmedical/hmftools/tree/master/orange + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - bam_metrics_somatic: + type: file + description: Somatic collectwgsmetrics file + - bam_metrics_germline: + type: file + description: Germline collectwgsmetrics file + - flagstat_somatic: + type: file + description: Somatic SAMtools flagstat output file + - flagstat_germline: + type: file + description: Somatic SAMtools flagstat output file + - chord_prediction: + type: file + description: CHORD prediction file + pattern: "*.{txt}" + - lilac_dir: + type: directory + description: LILAC output directory + - sage_somatic_bqr: + type: file + description: SAGE somatic tumor BQR plot file + pattern: "*.{png}" + - sage_germline_bqr: + type: file + description: SAGE somatic normal BQR plot file + pattern: "*.{png}" + - sage_germline_coverage: + type: file + description: SAGE germline coverage file + pattern: "*.{tsv}" + - purple_dir: + type: directory + description: PURPLE output directory + - linx_somatic_anno_dir: + type: directory + description: LINX somatic annotation output directory + - linx_somatic_plot_dir: + type: directory + description: LINX somatic plot output directory + - linx_germline_anno_dir: + type: directory + description: LINX germline annotation output directory + - protect: + type: file + description: PROTECT output file + pattern: "*.{tsv}" + - peach_genotype: + type: file + description: PEACH genotype file + pattern: "*.{tsv}" + - cuppa: + type: file + description: CUPPA classification file + pattern: "*.{csv}" + - cuppa_summary_plot: + type: file + description: CUPPA summary plot file + pattern: "*.{png}" + - cuppa_feature_plot: + type: file + description: CUPPA feature plot file + pattern: "*.{png}" + - virusinterpreter: + type: file + description: Virus Interpreter annotations file + pattern: "*.{tsv}" + - genome_ver: + type: string + description: Reference genome version + - disease_ontology: + type: string + description: Disease ontology file + pattern: "*.{json}" + - known_fusion_data: + type: file + description: Known susions data file + pattern: "*.{bedpe}" + - driver_gene_panel: + type: file + description: Driver gene panel file + pattern: "*.{csv}" + - cohort_mapping: + type: file + description: HMF cohort mapping file + pattern: "*.{tsv}" + - cohort_percentiles: + type: file + description: HMF cohort percentiles file + pattern: "*.{tsv}" + - pipeline_version: + type: string + description: Pipeline version to display in report +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - pdf: + type: file + description: Report file + pattern: "*.{pdf}" + - json: + type: directory + description: Compiled JSON output file + pattern: "*.{json}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/pave/germline/meta.yml b/modules/local/pave/germline/meta.yml index 662b1088..8b68e820 100644 --- a/modules/local/pave/germline/meta.yml +++ b/modules/local/pave/germline/meta.yml @@ -1,30 +1,26 @@ -name: "PAVE_germline" -description: PAVE annotates a somatic variant VCF with gene and transcript coding and protein effects +name: pave_germline +description: Annotate small variant VCF with gene, transcript coding and protein effects keywords: - - pave - annotation - gene - transcript - protein - vcf tools: - - "PAVE": - description: "PAVE annotates a somatic variant VCF with gene and transcript coding and protein effects." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/pave" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/pave" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/pave" - doi: "" - licence: "['GPL v3']" - + - pave: + description: Annotates small variant VCF with gene, transcript coding and protein effects. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/pave + documentation: https://github.com/hartwigmedical/hmftools/tree/master/pave + licence: ['GPL v3'] input: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor'] + e.g. [id: 'sample_id'] - sage_vcf: type: file - description: SAGE VCF + description: SAGE VCF file pattern: "*.{vcf.gz}" - genome_fasta: type: file @@ -37,37 +33,35 @@ input: - genome_ver: type: string description: Reference genome version - - sage_blacklist_bed: + - sage_blocklist_regions: type: file - description: SAGE blacklist BED + description: SAGE regions blocklist file pattern: "*.{bed}" - - sage_blacklist_vcf: + - sage_blocklist_sites: type: file - description: SAGE blacklist VCF + description: SAGE sites blocklist file pattern: "*.{vcf.gz}" - - clinvar_vcf: + - clinvar_annotations: type: file - description: HMF ClinVar VCF + description: ClinVar annotations VCF file pattern: "*.{vcf.gz}" - - mappability_bed: + - segment_mappability: type: file - description: HMF mappability BED + description: Segment mappability file pattern: "*.{bed.gz}" - driver_gene_panel: type: file - description: HMF Driver Gene Panel file + description: Driver gene panel file pattern: "*.{tsv}" - - ensembl_data_dir: + - ensembl_data_resources: type: directory - description: HMF Ensembl Data Cache directory - pattern: "*.{tsv}" - + description: HMF ensembl data resources directory output: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor'] + e.g. [id: 'sample_id'] - vcf: type: file description: PAVE VCF file @@ -80,6 +74,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/pave/somatic/meta.yml b/modules/local/pave/somatic/meta.yml index 53f6b87c..78d2b18d 100644 --- a/modules/local/pave/somatic/meta.yml +++ b/modules/local/pave/somatic/meta.yml @@ -1,5 +1,5 @@ -name: "PAVE_somatic" -description: PAVE annotates a somatic variant VCF with gene and transcript coding and protein effects +name: pave_somatic +description: Annotate small variant VCF with gene, transcript coding and protein effects keywords: - pave - annotation @@ -8,23 +8,20 @@ keywords: - protein - vcf tools: - - "PAVE": - description: "PAVE annotates a somatic variant VCF with gene and transcript coding and protein effects." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/pave" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/pave" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/pave" - doi: "" - licence: "['GPL v3']" - + - pave: + description: Annotates small variant VCF with gene, transcript coding and protein effects. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/pave + documentation: https://github.com/hartwigmedical/hmftools/tree/master/pave + licence: ['GPL v3'] input: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor'] + e.g. [id: 'sample_id'] - sage_vcf: type: file - description: SAGE VCF + description: SAGE VCF file pattern: "*.{vcf.gz}" - genome_fasta: type: file @@ -37,29 +34,27 @@ input: - genome_ver: type: string description: Reference genome version - - sage_pon_file: + - sage_pong: type: file description: SAGE PON file pattern: "*.{tsv.gz}" - - mappability_bed: + - segment_mappability: type: file - description: HMF mappability BED + description: Segment mappability file pattern: "*.{bed.gz}" - driver_gene_panel: type: file - description: HMF Driver Gene Panel file + description: Driver gene panel file pattern: "*.{tsv}" - - ensembl_data_dir: + - ensembl_data_resources: type: directory - description: HMF Ensembl Data Cache directory - pattern: "*.{tsv}" - + description: HMF ensembl data resources directory output: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor'] + e.g. [id: 'sample_id'] - vcf: type: file description: PAVE VCF file @@ -72,6 +67,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/peach/meta.yml b/modules/local/peach/meta.yml new file mode 100644 index 00000000..d4ee9dc0 --- /dev/null +++ b/modules/local/peach/meta.yml @@ -0,0 +1,45 @@ +name: peach +description: Match germline small variants with pharmacogenetic evidence +keywords: + - pharmacogenetic + - variant + - annotation + - germline +tools: + - peach: + description: Matches germline small variants with pharmacogenetic evidence. + homepage: https://github.com/hartwigmedical/peach + documentation: https://github.com/hartwigmedical/peach +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - genome_ver: + type: string + description: Reference genome version + - panel: + type: file + description: PEACH panel file + pattern: "*.{json}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - genotype: + type: file + description: Genotypes file + pattern: "*.{tsv}" + - calls: + type: file + description: Haplotype calls file + pattern: "*.{tsv}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/protect/meta.yml b/modules/local/protect/meta.yml new file mode 100644 index 00000000..01cdee94 --- /dev/null +++ b/modules/local/protect/meta.yml @@ -0,0 +1,44 @@ +name: protect +description: Match somatic variants with treatment evidence +keywords: + - treatment + - variant + - annotation + - somatic +tools: + - protect: + description: Matches somatic variants with treatment evidence. + homepage: https://github.com/hartwigmedical/oncoact/tree/master/protect + documentation: https://github.com/hartwigmedical/oncoact/tree/master/protect +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - genome_ver: + type: string + description: Reference genome version + - serve_resources: + type: directory + description: SERVE resources directory + - disease_ontology: + type: file + description: Disease ontology file + pattern: "*.{json}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - tsv: + type: file + description: PROTECT output file + pattern: "*.{tsv}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/purple/meta.yml b/modules/local/purple/meta.yml index 8c0a815c..6c2c7611 100644 --- a/modules/local/purple/meta.yml +++ b/modules/local/purple/meta.yml @@ -1,27 +1,23 @@ -name: "PURPLE" -description: PURPLE is a purity ploidy estimator for whole genome sequenced data +name: purple +description: Estimate purity and ploidy from WGS data keywords: - - purple - variant caller - ploidy - purity - cnv - sv tools: - - "PURPLE": - description: "PURPLE is a purity ploidy estimator for whole genome sequenced data." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/purple" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/purple" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/purple" - doi: "" - licence: "['GPL v3']" - + - purple: + description: Estimates purity and ploidy from WGS data + homepage: https://github.com/hartwigmedical/hmftools/tree/master/purple + documentation: https://github.com/hartwigmedical/hmftools/tree/master/purple + licence: ["GPL v3"] input: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - amber: type: directory description: AMBER output directory @@ -69,34 +65,33 @@ input: description: Reference genome version - gc_profile: type: file - description: COBALT GC Profile file + description: COBALT GC profile file pattern: "*.{cnp}" - sage_known_hotspots_somatic: type: file - description: SAGE somatic Known Hotspots file + description: SAGE somatic known hotspots file pattern: "*.{vcf.gz}" - sage_known_hotspots_germline: type: file - description: SAGE germline Known Hotspots file + description: SAGE germline known hotspots file pattern: "*.{vcf.gz}" - driver_gene_panel: type: file - description: HMF Driver Gene Panel file + description: Driver gene panel file pattern: "*.{csv}" - - ensembl_data_dir: + - ensembl_data_resources: type: directory - description: HMF Ensembl Data Cache directory - - germline_del_freq: + description: HMF ensembl data resources directory + - germline_del: type: file description: Cohort frequency for germline deletions pattern: "*.{csv}" - output: - meta: type: map description: | Groovy Map containing sample information - e.g. [['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - purple_dir: type: directory description: PURPLE output directory @@ -104,6 +99,5 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/sage/germline/meta.yml b/modules/local/sage/germline/meta.yml index 86cfefb0..8b2a9fc2 100644 --- a/modules/local/sage/germline/meta.yml +++ b/modules/local/sage/germline/meta.yml @@ -1,27 +1,22 @@ -name: "SAGE_germline" +name: sage_germline description: A precise and highly sensitive somatic SNV, MNV and small INDEL caller keywords: - - sage - germline - variant caller - snv - mnv - - small indel tools: - - "SAGE": - description: "A precise and highly sensitive somatic SNV, MNV and small INDEL caller." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/sage" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/sage" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/sage" - doi: "" - licence: "['GPL v3']" - + - sage: + description: A precise and highly sensitive somatic SNV, MNV and small INDEL caller. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/sage + documentation: https://github.com/hartwigmedical/hmftools/tree/master/sage + licence: ['GPL v3'] input: - meta: type: map description: | Groovy Map containing sample informatio - e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - tumor_bam: type: file description: Tumor BAM file @@ -55,35 +50,40 @@ input: description: Reference genome version - sage_known_hotspots_germline: type: file - description: SAGE germline Known Hotspots file + description: SAGE germline known hotspots file pattern: "*.{vcf.gz}" - sage_coding_panel: type: file - description: SAGE Coding Panel file + description: SAGE coding panel file pattern: "*.{bed.gz}" - - sage_high_confidence: + - sage_coverage_panel_germline: type: file - description: SAGE High Confidence file + description: SAGE germline coverage ene panel file pattern: "*.{bed.gz}" - - ensembl_data_dir: + - sage_highconf_regions: + type: file + description: SAGE high confidence regions file + pattern: "*.{bed.gz}" + - ensembl_data_resources: type: directory - description: HMF Ensembl Data Cache directory - pattern: "*.{tsv}" - + description: HMF ensembl data resources directory output: - meta: type: map description: | Groovy Map containing sample information - e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - vcf: type: file - description: SAGE VCF file + description: VCF file pattern: "*.{vcf.gz}" + - gene_coverage: + type: file + description: Gene coverage file + pattern: "*.{tsv}" - versions: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/sage/somatic/meta.yml b/modules/local/sage/somatic/meta.yml index 692be7cf..cc8f3f6c 100644 --- a/modules/local/sage/somatic/meta.yml +++ b/modules/local/sage/somatic/meta.yml @@ -1,27 +1,22 @@ -name: "SAGE_somatic" +name: sage_somatic description: A precise and highly sensitive somatic SNV, MNV and small INDEL caller keywords: - - sage - somatic - variant caller - snv - mnv - - small indel tools: - - "SAGE": - description: "A precise and highly sensitive somatic SNV, MNV and small INDEL caller." - homepage: "https://github.com/hartwigmedical/hmftools/tree/master/sage" - documentation: "https://github.com/hartwigmedical/hmftools/tree/master/sage" - tool_dev_url: "https://github.com/hartwigmedical/hmftools/tree/master/sage" - doi: "" - licence: "['GPL v3']" - + - sage: + description: A precise and highly sensitive somatic SNV, MNV and small INDEL caller. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/sage + documentation: https://github.com/hartwigmedical/hmftools/tree/master/sage + licence: ['GPL v3'] input: - meta: type: map description: | Groovy Map containing sample informatio - e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - tumor_bam: type: file description: Tumor BAM file @@ -55,35 +50,48 @@ input: description: Reference genome version - sage_known_hotspots_somatic: type: file - description: SAGE somatic Known Hotspots file + description: SAGE somatic known hotspots file pattern: "*.{vcf.gz}" - sage_coding_panel: type: file - description: SAGE Coding Panel file + description: SAGE coding gene panel file pattern: "*.{bed.gz}" - - sage_high_confidence: + - sage_highconf_regions: type: file - description: SAGE High Confidence file + description: SAGE high confidence regions file pattern: "*.{bed.gz}" - - ensembl_data_dir: + - ensembl_data_resources: type: directory - description: HMF Ensembl Data Cache directory - pattern: "*.{tsv}" - + description: HMF ensembl data resources directory output: - meta: type: map description: | Groovy Map containing sample information - e.g. [subject_name: 'subject', ['sample_name', 'tumor']: 'sample_tumor', ['sample_name', 'normal']: 'sample_normal'] + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - vcf: type: file description: SAGE VCF file pattern: "*.{vcf.gz}" + - tumor_bqr_png: + type: file + description: Tumor BQR plot file + pattern: "*.{png}" + - normal_bqr_png: + type: file + description: Normal BQR plot file + pattern: "*.{png}" + - gene_coverage: + type: file + description: Gene coverage output file + pattern: "*.{tsv}" + - bqr_tsv: + type: file + description: BQR data files + pattern: "*.{tsv}" - versions: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@scwatts" diff --git a/modules/local/sigs/meta.yml b/modules/local/sigs/meta.yml new file mode 100644 index 00000000..08d6db55 --- /dev/null +++ b/modules/local/sigs/meta.yml @@ -0,0 +1,40 @@ +name: sigs +description: Fit somatic small variants to signature definitions +keywords: + - signatures + - variants +tools: + - sigs: + description: Fits somatic small variants to signature definitions. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/sigs + documentation: https://github.com/hartwigmedical/hmftools/tree/master/sigs + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name'] + - smlv_vcf: + type: file + description: Tumor small variant VCF file + pattern: "*.{vcf.gz}" + - signatures: + type: file + description: Signatures file + pattern: "*.{csv}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - sigs_dir: + type: directory + description: Sigs output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/virusbreakend/meta.yml b/modules/local/virusbreakend/meta.yml new file mode 100644 index 00000000..d8fafb0c --- /dev/null +++ b/modules/local/virusbreakend/meta.yml @@ -0,0 +1,70 @@ +name: virusbreakend +description: Detect viral integration from WGS data +keywords: + - viral + - integration +tools: + - virusbreakend: + description: Performs detection of viral intergation from WGS data + homepage: https://github.com/PapenfussLab/gridss/blob/master/VIRUSBreakend_Readme.md + documentation: https://github.com/PapenfussLab/gridss/blob/master/VIRUSBreakend_Readme.md + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - gridss_config: + type: file + description: Optional GRIDSS configuration file (optional) + - genome_fasta: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_bwa_index_dir: + type: directory + description: Directory containing reference genome assembly BWA index + - genome_bwa_index_image: + type: file + description: Reference genome assembly BWA index img file + pattern: "*.{img}" + - genome_gridss_index: + type: file + description: Reference genome assembly GRIDSS index file + pattern: "*.{gridsscache}" + - virusbreakenddb: + type: directory + description: VIRUSBreakend database directory +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - tsv: + type: file + description: Summary file + pattern: "*.{tsv}" + - vcf: + type: file + description: VCF file + pattern: "*.{vcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/virusinterpreter/meta.yml b/modules/local/virusinterpreter/meta.yml new file mode 100644 index 00000000..df59f4e8 --- /dev/null +++ b/modules/local/virusinterpreter/meta.yml @@ -0,0 +1,58 @@ +name: virusinterpreter +description: Filters and annotates VIRUSBreakend calls +keywords: + - viral + - integration + - annotation + - filtering +tools: + - virusinterpreter: + description: Performs filtering and annotation of VIRUSBreakend calls + homepage: https://github.com/hartwigmedical/hmftools/tree/master/virus-interpreter + documentation: https://github.com/hartwigmedical/hmftools/tree/master/virus-interpreter + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - virus_tsv: + type: file + description: VIRUSBreakend summary file + pattern: "*.{tsv}" + - purple_purity: + type: file + description: PURPLE purity file + pattern: "*.{tsv}" + - purple_qc: + type: file + description: PURPLE QC file + pattern: "*.{qc}" + - wgs_metrics: + type: file + description: Somatic collectwgsmetrics file + - taxonomy_db: + type: file + description: Virus Interpreter taxonomy database file + pattern: "*.{tsv}" + - reporting_db: + type: file + description: Virus Interpreter reporting database file + pattern: "*.{tsv}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - virusinterpreter: + type: file + description: Virus Interpreter output file + pattern: "*.{tsv}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/subworkflows/local/gridss.nf b/subworkflows/local/gridss.nf index 6bf7fca6..b8ee66f3 100644 --- a/subworkflows/local/gridss.nf +++ b/subworkflows/local/gridss.nf @@ -4,10 +4,10 @@ import Constants import Utils -include { ANNOTATE } from '../../modules/local/gridss/annotate/main' -include { ASSEMBLE } from '../../modules/local/gridss/assemble/main' -include { CALL } from '../../modules/local/gridss/call/main' -include { PREPROCESS } from '../../modules/local/gridss/preprocess/main' +include { GRIDSS_ANNOTATE } from '../../modules/local/gridss/annotate/main' +include { GRIDSS_ASSEMBLE } from '../../modules/local/gridss/assemble/main' +include { GRIDSS_CALL } from '../../modules/local/gridss/call/main' +include { GRIDSS_PREPROCESS } from '../../modules/local/gridss/preprocess/main' workflow GRIDSS { take: @@ -51,7 +51,7 @@ workflow GRIDSS { } // Preprocess reads - PREPROCESS( + GRIDSS_PREPROCESS( ch_preprocess_inputs, gridss_config, ref_data_genome_fasta, @@ -61,13 +61,13 @@ workflow GRIDSS { ref_data_genome_bwa_index_image, ref_data_genome_gridss_index, ) - ch_versions = ch_versions.mix(PREPROCESS.out.versions) + ch_versions = ch_versions.mix(GRIDSS_PREPROCESS.out.versions) // Gather BAMs and outputs from preprocessing for each tumor/normal set // channel: [subject_id, [[val(meta_gridss), bam, preprocess_dir], ...]] ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( ch_preprocess_inputs, - PREPROCESS.out.preprocess_dir, + GRIDSS_PREPROCESS.out.preprocess_dir, ) .map { [it[0].subject_id, it] } .groupTuple(size: 2) @@ -83,7 +83,7 @@ workflow GRIDSS { } // Assemble variants - ASSEMBLE( + GRIDSS_ASSEMBLE( ch_assemble_inputs, gridss_config, ref_data_genome_fasta, @@ -94,13 +94,13 @@ workflow GRIDSS { ref_data_genome_gridss_index, ref_data_gridss_blacklist, ) - ch_versions = ch_versions.mix(ASSEMBLE.out.versions) + ch_versions = ch_versions.mix(GRIDSS_ASSEMBLE.out.versions) // Prepare inputs for variant calling // channel: [val(meta_gridss), [bams], assemble_dir, [labels]] ch_call_inputs = WorkflowOncoanalyser.groupByMeta( ch_assemble_inputs, - ASSEMBLE.out.assemble_dir, + GRIDSS_ASSEMBLE.out.assemble_dir, flatten: false, ) .map { data -> @@ -111,7 +111,7 @@ workflow GRIDSS { } // Call variants - CALL( + GRIDSS_CALL( ch_call_inputs, gridss_config, ref_data_genome_fasta, @@ -122,18 +122,18 @@ workflow GRIDSS { ref_data_genome_gridss_index, ref_data_gridss_blacklist, ) - ch_versions = ch_versions.mix(CALL.out.versions) + ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) // Annotate variants with RepeatMasker - ANNOTATE( - CALL.out.vcf, + GRIDSS_ANNOTATE( + GRIDSS_CALL.out.vcf, ) // Reunite final VCF with the corresponding input meta object ch_out = Channel.empty() .concat( ch_inputs.map { meta, tbam, nbam -> [meta.id, meta] }, - ANNOTATE.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + GRIDSS_ANNOTATE.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .groupTuple(size: 2) .map { id, other -> other.flatten() } diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index 7c995cb7..10e79b97 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -3,11 +3,11 @@ // import Constants -include { EXTRACT_AND_INDEX_CONTIG } from '../../modules/local/custom/lilac_extract_and_index_contig/main' -include { REALIGN_READS } from '../../modules/local/custom/lilac_realign_reads_lilac/main' -include { SLICE } from '../../modules/local/custom/lilac_slice/main' +include { CUSTOM_EXTRACTCONTIG } from '../../modules/local/custom/lilac_extract_and_index_contig/main' +include { CUSTOM_REALIGNREADS } from '../../modules/local/custom/lilac_realign_reads_lilac/main' +include { CUSTOM_SLICE } from '../../modules/local/custom/lilac_slice/main' -include { LILAC as LILAC_PROCESS } from '../../modules/local/lilac/main' +include { LILAC as LILAC_PROCESS } from '../../modules/local/lilac/main' workflow LILAC { take: @@ -53,33 +53,33 @@ workflow LILAC { // Apply slicing to unique files only // channel: [val(meta_lilac), bam, bai, bed] ch_slice_inputs_unique = WorkflowLilac.getUniqueInputFiles(ch_slice_inputs) - SLICE( + CUSTOM_SLICE( ch_slice_inputs_unique, ) - ch_versions = ch_versions.mix(SLICE.out.versions) + ch_versions = ch_versions.mix(CUSTOM_SLICE.out.versions) // Realign contigs if using 38 (use of ALT contigs implied) // channel: [val(meta_lilac), bam, bai] - ch_slices_out = SLICE.out.bam + ch_slices_out = CUSTOM_SLICE.out.bam if (params.ref_data_genome_type == 'alt') { // Align reads with chr6 // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them // to the three relevant HLA genes on chr6. All reads including those previously mapped to chr6 // are realigned for consistency. - EXTRACT_AND_INDEX_CONTIG( + CUSTOM_EXTRACTCONTIG( 'chr6', ref_data_genome_fasta, ref_data_genome_fai, ) - ch_versions = ch_versions.mix(EXTRACT_AND_INDEX_CONTIG.out.versions) + ch_versions = ch_versions.mix(CUSTOM_EXTRACTCONTIG.out.versions) - REALIGN_READS( - SLICE.out.bam, - EXTRACT_AND_INDEX_CONTIG.out.contig, - EXTRACT_AND_INDEX_CONTIG.out.bwa_indices, + CUSTOM_REALIGNREADS( + CUSTOM_SLICE.out.bam, + CUSTOM_EXTRACTCONTIG.out.contig, + CUSTOM_EXTRACTCONTIG.out.bwa_indices, ) - ch_slices_out = REALIGN_READS.out.bam - ch_versions = ch_versions.mix(REALIGN_READS.out.versions) + ch_slices_out = CUSTOM_REALIGNREADS.out.bam + ch_versions = ch_versions.mix(CUSTOM_REALIGNREADS.out.versions) } diff --git a/subworkflows/local/linx.nf b/subworkflows/local/linx.nf index defafc98..ffe82d7b 100644 --- a/subworkflows/local/linx.nf +++ b/subworkflows/local/linx.nf @@ -2,9 +2,9 @@ // Linx is an annotation, interpretation and visualisation tool for structural variants. // -include { LINX_GERMLINE } from '../../modules/local/linx/germline/main' -include { LINX_SOMATIC } from '../../modules/local/linx/somatic/main' -include { VISUALISER } from '../../modules/local/linx/visualiser/main' +include { LINX_GERMLINE } from '../../modules/local/linx/germline/main' +include { LINX_SOMATIC } from '../../modules/local/linx/somatic/main' +include { LINX_VISUALISER } from '../../modules/local/linx/visualiser/main' workflow LINX { take: @@ -44,17 +44,17 @@ workflow LINX { ) ch_versions = ch_versions.mix(LINX_SOMATIC.out.versions) - VISUALISER( + LINX_VISUALISER( LINX_SOMATIC.out.annotation_dir, ref_data_genome_version, ref_data_ensembl_data_resources, ) - ch_versions = ch_versions.mix(VISUALISER.out.versions) + ch_versions = ch_versions.mix(LINX_VISUALISER.out.versions) // channel: [val(meta), linx_annotation_dir, linx_visualiser_dir] ch_linx_somatic_out = WorkflowOncoanalyser.groupByMeta( LINX_SOMATIC.out.annotation_dir, - VISUALISER.out.visualiser_dir, + LINX_VISUALISER.out.visualiser_dir, ) emit: diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 1c58317d..ad501efb 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -6,9 +6,9 @@ include { SAMTOOLS_FAIDX } from '../../modules/nf-core/samtools/faidx/ma include { SAMTOOLS_DICT } from '../../modules/nf-core/samtools/dict/main' include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' -include { EXTRACT_TARBALL as EXTRACT_TARBALL_VIRUSBREAKENDDB } from '../../modules/local/custom/extract_tarball/main' -include { INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' -include { INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' +include { CUSTOM_EXTRACTTARBALL } from '../../modules/local/custom/extract_tarball/main' +include { GRIDSS_INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' +include { GRIDSS_INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' workflow PREPARE_REFERENCE { take: @@ -90,8 +90,8 @@ workflow PREPARE_REFERENCE { [id: 'virusbreakenddb'], file(params.ref_data_virusbreakenddb_path), ] - EXTRACT_TARBALL_VIRUSBREAKENDDB(ch_virusbreakenddb_inputs) - ch_virusbreakenddb = EXTRACT_TARBALL_VIRUSBREAKENDDB.out.dir + CUSTOM_EXTRACTTARBALL(ch_virusbreakenddb_inputs) + ch_virusbreakenddb = CUSTOM_EXTRACTTARBALL.out.dir } else { ch_virusbreakenddb = file(params.ref_data_virusbreakenddb_path) } diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 77474830..174bb144 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -59,8 +59,8 @@ include { CHORD } from '../modules/local/chord/main' include { COBALT } from '../modules/local/cobalt/main' include { CUPPA_CLASSIFIER } from '../modules/local/cuppa/classifier/main' include { CUPPA_VISUALISER } from '../modules/local/cuppa/visualiser/main' +include { GPGR_LINX } from '../modules/local/gpgr/linx/main' include { ISOFOX } from '../modules/local/isofox/main' -include { LINX_REPORT } from '../modules/local/gpgr/linx_report/main' include { ORANGE } from '../modules/local/orange/main' include { PEACH } from '../modules/local/peach/main' include { PROTECT } from '../modules/local/protect/main' @@ -831,23 +831,23 @@ workflow ONCOANALYSER { // MODULE: Run gpgr to generate a LINX report // // Create inputs and create process-specific meta - // channel: [meta(meta_linx_report), anno_dir, vis_dir] - ch_linx_report_inputs = ch_linx_somatic_out + // channel: [meta(meta_gpgr_linx), anno_dir, vis_dir] + ch_gpgr_linx_inputs = ch_linx_somatic_out .map { meta, anno_dir, vis_dir -> - def meta_linx_report = [ + def meta_gpgr_linx = [ key: meta.id, id: meta.get(['sample_name', Constants.DataType.TUMOR]), ] - return [meta_linx_report, anno_dir, vis_dir] + return [meta_gpgr_linx, anno_dir, vis_dir] } // Run process - LINX_REPORT( - ch_linx_report_inputs, + GPGR_LINX( + ch_gpgr_linx_inputs, ) // Set outputs - ch_versions = ch_versions.mix(LINX_REPORT.out.versions) + ch_versions = ch_versions.mix(GPGR_LINX.out.versions) } // From 6cb267d2547f451ae3c99fe6b49c1bbd5326146a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 21 Dec 2022 16:56:08 +1100 Subject: [PATCH 081/562] Adjust ORANGE pipeline version due to length limit --- workflows/oncoanalyser.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 174bb144..280c7045 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -1149,7 +1149,7 @@ workflow ONCOANALYSER { hmf_data.driver_gene_panel, hmf_data.cohort_mapping, hmf_data.cohort_percentiles, - "5.23 (oncoanalyser 0.0.1dev)", + "5.23 [oncoanalyser]", ) // Set outputs From c133c609e39da829a9603b9f82ad97e7f1160797 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 22 Dec 2022 15:54:55 +1100 Subject: [PATCH 082/562] Correct LILAC tumor WGS BAM argument --- modules/local/lilac/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 25ba5a5e..288308ce 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -20,7 +20,7 @@ process LILAC { script: def args = task.ext.args ?: '' def sample_name = getSampleName(meta, tumor_wgs_bam, normal_wgs_bam) - def tumor_wgs_bam_arg = tumor_wgs_bam ? "-tumor_wgs_bam ${tumor_wgs_bam}" : '' + def tumor_wgs_bam_arg = tumor_wgs_bam ? "-tumor_bam ${tumor_wgs_bam}" : '' def tumor_wts_bam_arg = tumor_wts_bam ? "-rna_bam ${tumor_wts_bam}" : '' def purple_args = purple_dir ? """ -gene_copy_number_file ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ From a5c6279c5cb67bd64f421380f8c11b594747b296 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 28 Nov 2022 12:18:14 +1100 Subject: [PATCH 083/562] initial template build from nf-core/tools, version 2.6 --- .editorconfig | 24 + .gitattributes | 3 + .github/.dockstore.yml | 6 + .github/CONTRIBUTING.md | 103 ++++ .github/ISSUE_TEMPLATE/bug_report.yml | 50 ++ .github/ISSUE_TEMPLATE/config.yml | 7 + .github/ISSUE_TEMPLATE/feature_request.yml | 11 + .github/PULL_REQUEST_TEMPLATE.md | 24 + .github/workflows/awsfulltest.yml | 34 ++ .github/workflows/awstest.yml | 29 + .github/workflows/branch.yml | 44 ++ .github/workflows/ci.yml | 39 ++ .github/workflows/fix-linting.yml | 55 ++ .github/workflows/linting.yml | 106 ++++ .github/workflows/linting_comment.yml | 28 + .gitignore | 8 + .gitpod.yml | 14 + .nf-core.yml | 1 + .prettierignore | 10 + .prettierrc.yml | 1 + CHANGELOG.md | 16 + CITATION.cff | 56 ++ CITATIONS.md | 35 ++ CODE_OF_CONDUCT.md | 111 ++++ LICENSE | 21 + README.md | 92 +++ assets/adaptivecard.json | 67 +++ assets/email_template.html | 53 ++ assets/email_template.txt | 39 ++ assets/methods_description_template.yml | 25 + assets/multiqc_config.yml | 13 + assets/nf-core-oncoanalyser_logo_light.png | Bin 0 -> 11358 bytes assets/samplesheet.csv | 3 + assets/schema_input.json | 36 ++ assets/sendmail_template.txt | 53 ++ bin/check_samplesheet.py | 262 +++++++++ conf/base.config | 65 +++ conf/igenomes.config | 432 ++++++++++++++ conf/modules.config | 41 ++ conf/test.config | 29 + conf/test_full.config | 24 + docs/README.md | 10 + docs/images/mqc_fastqc_adapter.png | Bin 0 -> 23458 bytes docs/images/mqc_fastqc_counts.png | Bin 0 -> 33918 bytes docs/images/mqc_fastqc_quality.png | Bin 0 -> 55769 bytes .../images/nf-core-oncoanalyser_logo_dark.png | Bin 0 -> 87060 bytes .../nf-core-oncoanalyser_logo_light.png | Bin 0 -> 86949 bytes docs/output.md | 68 +++ docs/usage.md | 264 +++++++++ lib/NfcoreSchema.groovy | 529 ++++++++++++++++++ lib/NfcoreTemplate.groovy | 313 +++++++++++ lib/Utils.groovy | 47 ++ lib/WorkflowMain.groovy | 93 +++ lib/WorkflowOncoanalyser.groovy | 77 +++ lib/nfcore_external_java_deps.jar | Bin 0 -> 2291171 bytes main.nf | 64 +++ modules.json | 24 + modules/local/samplesheet_check.nf | 27 + .../custom/dumpsoftwareversions/main.nf | 24 + .../custom/dumpsoftwareversions/meta.yml | 34 ++ .../templates/dumpsoftwareversions.py | 91 +++ modules/nf-core/fastqc/main.nf | 59 ++ modules/nf-core/fastqc/meta.yml | 52 ++ modules/nf-core/multiqc/main.nf | 53 ++ modules/nf-core/multiqc/meta.yml | 55 ++ nextflow.config | 231 ++++++++ nextflow_schema.json | 287 ++++++++++ pyproject.toml | 10 + subworkflows/local/input_check.nf | 44 ++ workflows/oncoanalyser.nf | 133 +++++ 70 files changed, 4659 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/.dockstore.yml create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/awsfulltest.yml create mode 100644 .github/workflows/awstest.yml create mode 100644 .github/workflows/branch.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/fix-linting.yml create mode 100644 .github/workflows/linting.yml create mode 100644 .github/workflows/linting_comment.yml create mode 100644 .gitignore create mode 100644 .gitpod.yml create mode 100644 .nf-core.yml create mode 100644 .prettierignore create mode 100644 .prettierrc.yml create mode 100644 CHANGELOG.md create mode 100644 CITATION.cff create mode 100644 CITATIONS.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 assets/adaptivecard.json create mode 100644 assets/email_template.html create mode 100644 assets/email_template.txt create mode 100644 assets/methods_description_template.yml create mode 100644 assets/multiqc_config.yml create mode 100644 assets/nf-core-oncoanalyser_logo_light.png create mode 100644 assets/samplesheet.csv create mode 100644 assets/schema_input.json create mode 100644 assets/sendmail_template.txt create mode 100755 bin/check_samplesheet.py create mode 100644 conf/base.config create mode 100644 conf/igenomes.config create mode 100644 conf/modules.config create mode 100644 conf/test.config create mode 100644 conf/test_full.config create mode 100644 docs/README.md create mode 100755 docs/images/mqc_fastqc_adapter.png create mode 100755 docs/images/mqc_fastqc_counts.png create mode 100755 docs/images/mqc_fastqc_quality.png create mode 100644 docs/images/nf-core-oncoanalyser_logo_dark.png create mode 100644 docs/images/nf-core-oncoanalyser_logo_light.png create mode 100644 docs/output.md create mode 100644 docs/usage.md create mode 100755 lib/NfcoreSchema.groovy create mode 100755 lib/NfcoreTemplate.groovy create mode 100644 lib/Utils.groovy create mode 100755 lib/WorkflowMain.groovy create mode 100755 lib/WorkflowOncoanalyser.groovy create mode 100644 lib/nfcore_external_java_deps.jar create mode 100644 main.nf create mode 100644 modules.json create mode 100644 modules/local/samplesheet_check.nf create mode 100644 modules/nf-core/custom/dumpsoftwareversions/main.nf create mode 100644 modules/nf-core/custom/dumpsoftwareversions/meta.yml create mode 100644 modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py create mode 100644 modules/nf-core/fastqc/main.nf create mode 100644 modules/nf-core/fastqc/meta.yml create mode 100644 modules/nf-core/multiqc/main.nf create mode 100644 modules/nf-core/multiqc/meta.yml create mode 100644 nextflow.config create mode 100644 nextflow_schema.json create mode 100644 pyproject.toml create mode 100644 subworkflows/local/input_check.nf create mode 100644 workflows/oncoanalyser.nf diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..b78de6e6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,24 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_size = 4 +indent_style = space + +[*.{md,yml,yaml,html,css,scss,js,cff}] +indent_size = 2 + +# These files are edited and tested upstream in nf-core/modules +[/modules/nf-core/**] +charset = unset +end_of_line = unset +insert_final_newline = unset +trim_trailing_whitespace = unset +indent_style = unset +indent_size = unset + +[/assets/email*] +indent_size = unset diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..050bb120 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.config linguist-language=nextflow +modules/nf-core/** linguist-generated +subworkflows/nf-core/** linguist-generated diff --git a/.github/.dockstore.yml b/.github/.dockstore.yml new file mode 100644 index 00000000..191fabd2 --- /dev/null +++ b/.github/.dockstore.yml @@ -0,0 +1,6 @@ +# Dockstore config version, not pipeline version +version: 1.2 +workflows: + - subclass: nfl + primaryDescriptorPath: /nextflow.config + publish: True diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..c54ec775 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,103 @@ +# nf-core/oncoanalyser: Contributing Guidelines + +Hi there! +Many thanks for taking an interest in improving nf-core/oncoanalyser. + +We try to manage the required tasks for nf-core/oncoanalyser using GitHub issues, you probably came to this page when creating one. +Please use the pre-filled template to save time. + +However, don't be put off by this template - other more general issues and suggestions are welcome! +Contributions to the code are even more welcome ;) + +> If you need help using or modifying nf-core/oncoanalyser then the best place to ask is on the nf-core Slack [#oncoanalyser](https://nfcore.slack.com/channels/oncoanalyser) channel ([join our Slack here](https://nf-co.re/join/slack)). + +## Contribution workflow + +If you'd like to write some code for nf-core/oncoanalyser, the standard workflow is as follows: + +1. Check that there isn't already an issue about your idea in the [nf-core/oncoanalyser issues](https://github.com/nf-core/oncoanalyser/issues) to avoid duplicating work. If there isn't one already, please create one so that others know you're working on this +2. [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the [nf-core/oncoanalyser repository](https://github.com/nf-core/oncoanalyser) to your GitHub account +3. Make the necessary changes / additions within your forked repository following [Pipeline conventions](#pipeline-contribution-conventions) +4. Use `nf-core schema build` and add any new parameters to the pipeline JSON schema (requires [nf-core tools](https://github.com/nf-core/tools) >= 1.10). +5. Submit a Pull Request against the `dev` branch and wait for the code to be reviewed and merged + +If you're not used to this workflow with git, you can start with some [docs from GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests) or even their [excellent `git` resources](https://try.github.io/). + +## Tests + +When you create a pull request with changes, [GitHub Actions](https://github.com/features/actions) will run automatic tests. +Typically, pull-requests are only fully reviewed when these tests are passing, though of course we can help out before then. + +There are typically two types of tests that run: + +### Lint tests + +`nf-core` has a [set of guidelines](https://nf-co.re/developers/guidelines) which all pipelines must adhere to. +To enforce these and ensure that all pipelines stay in sync, we have developed a helper tool which runs checks on the pipeline code. This is in the [nf-core/tools repository](https://github.com/nf-core/tools) and once installed can be run locally with the `nf-core lint ` command. + +If any failures or warnings are encountered, please follow the listed URL for more documentation. + +### Pipeline tests + +Each `nf-core` pipeline should be set up with a minimal set of test-data. +`GitHub Actions` then runs the pipeline on this data to ensure that it exits successfully. +If there are any failures then the automated tests fail. +These tests are run both with the latest available version of `Nextflow` and also the minimum required version that is stated in the pipeline code. + +## Patch + +:warning: Only in the unlikely and regretful event of a release happening with a bug. + +- On your own fork, make a new branch `patch` based on `upstream/master`. +- Fix the bug, and bump version (X.Y.Z+1). +- A PR should be made on `master` from patch to directly this particular bug. + +## Getting help + +For further information/help, please consult the [nf-core/oncoanalyser documentation](https://nf-co.re/oncoanalyser/usage) and don't hesitate to get in touch on the nf-core Slack [#oncoanalyser](https://nfcore.slack.com/channels/oncoanalyser) channel ([join our Slack here](https://nf-co.re/join/slack)). + +## Pipeline contribution conventions + +To make the nf-core/oncoanalyser code and processing logic more understandable for new contributors and to ensure quality, we semi-standardise the way the code and other contributions are written. + +### Adding a new step + +If you wish to contribute a new step, please use the following coding standards: + +1. Define the corresponding input channel into your new process from the expected previous process channel +2. Write the process block (see below). +3. Define the output channel if needed (see below). +4. Add any new parameters to `nextflow.config` with a default (see below). +5. Add any new parameters to `nextflow_schema.json` with help text (via the `nf-core schema build` tool). +6. Add sanity checks and validation for all relevant parameters. +7. Perform local tests to validate that the new code works as expected. +8. If applicable, add a new test command in `.github/workflow/ci.yml`. +9. Update MultiQC config `assets/multiqc_config.yml` so relevant suffixes, file name clean up and module plots are in the appropriate order. If applicable, add a [MultiQC](https://https://multiqc.info/) module. +10. Add a description of the output files and if relevant any appropriate images from the MultiQC report to `docs/output.md`. + +### Default values + +Parameters should be initialised / defined with default values in `nextflow.config` under the `params` scope. + +Once there, use `nf-core schema build` to add to `nextflow_schema.json`. + +### Default processes resource requirements + +Sensible defaults for process resource requirements (CPUs / memory / time) for a process should be defined in `conf/base.config`. These should generally be specified generic with `withLabel:` selectors so they can be shared across multiple processes/steps of the pipeline. A nf-core standard set of labels that should be followed where possible can be seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/master/nf_core/pipeline-template/conf/base.config), which has the default process as a single core-process, and then different levels of multi-core configurations for increasingly large memory requirements defined with standardised labels. + +The process resources can be passed on to the tool dynamically within the process with the `${task.cpu}` and `${task.memory}` variables in the `script:` block. + +### Naming schemes + +Please use the following naming schemes, to make it easy to understand what is going where. + +- initial process channel: `ch_output_from_` +- intermediate and terminal channels: `ch__for_` + +### Nextflow version bumping + +If you are using a new feature from core Nextflow, you may bump the minimum required version of nextflow in the pipeline with: `nf-core bump-version --nextflow . [min-nf-version]` + +### Images and figures + +For overview images and other documents we follow the nf-core [style guidelines and examples](https://nf-co.re/developers/design_guidelines). diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..3ed51a88 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,50 @@ +name: Bug report +description: Report something that is broken or incorrect +labels: bug +body: + - type: markdown + attributes: + value: | + Before you post this issue, please check the documentation: + + - [nf-core website: troubleshooting](https://nf-co.re/usage/troubleshooting) + - [nf-core/oncoanalyser pipeline documentation](https://nf-co.re/oncoanalyser/usage) + + - type: textarea + id: description + attributes: + label: Description of the bug + description: A clear and concise description of what the bug is. + validations: + required: true + + - type: textarea + id: command_used + attributes: + label: Command used and terminal output + description: Steps to reproduce the behaviour. Please paste the command you used to launch the pipeline and the output from your terminal. + render: console + placeholder: | + $ nextflow run ... + + Some output where something broke + + - type: textarea + id: files + attributes: + label: Relevant files + description: | + Please drag and drop the relevant files here. Create a `.zip` archive if the extension is not allowed. + Your verbose log file `.nextflow.log` is often useful _(this is a hidden file in the directory where you launched the pipeline)_ as well as custom Nextflow configuration files. + + - type: textarea + id: system + attributes: + label: System information + description: | + * Nextflow version _(eg. 21.10.3)_ + * Hardware _(eg. HPC, Desktop, Cloud)_ + * Executor _(eg. slurm, local, awsbatch)_ + * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter or Charliecloud)_ + * OS _(eg. CentOS Linux, macOS, Linux Mint)_ + * Version of nf-core/oncoanalyser _(eg. 1.1, 1.5, 1.8.2)_ diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..22b326cb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +contact_links: + - name: Join nf-core + url: https://nf-co.re/join + about: Please join the nf-core community here + - name: "Slack #oncoanalyser channel" + url: https://nfcore.slack.com/channels/oncoanalyser + about: Discussion about the nf-core/oncoanalyser pipeline diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..1903b19a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,11 @@ +name: Feature request +description: Suggest an idea for the nf-core/oncoanalyser pipeline +labels: enhancement +body: + - type: textarea + id: description + attributes: + label: Description of feature + description: Please describe your suggestion for a new feature. It might help to describe a problem or use case, plus any alternatives that you have considered. + validations: + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..045d9396 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,24 @@ + + +## PR checklist + +- [ ] This comment contains a description of changes (with reason). +- [ ] If you've fixed a bug or added code that should be tested, add tests! +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/oncoanalyser/tree/master/.github/CONTRIBUTING.md)- [ ] If necessary, also make a PR on the nf-core/oncoanalyser _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. +- [ ] Make sure your code lints (`nf-core lint`). +- [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). +- [ ] Usage Documentation in `docs/usage.md` is updated. +- [ ] Output Documentation in `docs/output.md` is updated. +- [ ] `CHANGELOG.md` is updated. +- [ ] `README.md` is updated (including new tool citations and authors/contributors). diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml new file mode 100644 index 00000000..f32fa1b6 --- /dev/null +++ b/.github/workflows/awsfulltest.yml @@ -0,0 +1,34 @@ +name: nf-core AWS full size tests +# This workflow is triggered on published releases. +# It can be additionally triggered manually with GitHub actions workflow dispatch button. +# It runs the -profile 'test_full' on AWS batch + +on: + release: + types: [published] + workflow_dispatch: +jobs: + run-tower: + name: Run AWS full tests + if: github.repository == 'nf-core/oncoanalyser' + runs-on: ubuntu-latest + steps: + - name: Launch workflow via tower + uses: nf-core/tower-action@v3 + # TODO nf-core: You can customise AWS full pipeline tests as required + # Add full size test data (but still relatively small datasets for few samples) + # on the `test_full.config` test runs with only one set of parameters + with: + workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} + access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} + compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/oncoanalyser/work-${{ github.sha }} + parameters: | + { + "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/oncoanalyser/results-${{ github.sha }}" + } + profiles: test_full,aws_tower + - uses: actions/upload-artifact@v3 + with: + name: Tower debug log file + path: tower_action_*.log diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml new file mode 100644 index 00000000..9a4ec76d --- /dev/null +++ b/.github/workflows/awstest.yml @@ -0,0 +1,29 @@ +name: nf-core AWS test +# This workflow can be triggered manually with the GitHub actions workflow dispatch button. +# It runs the -profile 'test' on AWS batch + +on: + workflow_dispatch: +jobs: + run-tower: + name: Run AWS tests + if: github.repository == 'nf-core/oncoanalyser' + runs-on: ubuntu-latest + steps: + # Launch workflow using Tower CLI tool action + - name: Launch workflow via tower + uses: nf-core/tower-action@v3 + with: + workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} + access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} + compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/oncoanalyser/work-${{ github.sha }} + parameters: | + { + "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/oncoanalyser/results-test-${{ github.sha }}" + } + profiles: test,aws_tower + - uses: actions/upload-artifact@v3 + with: + name: Tower debug log file + path: tower_action_*.log diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml new file mode 100644 index 00000000..0a1cdd32 --- /dev/null +++ b/.github/workflows/branch.yml @@ -0,0 +1,44 @@ +name: nf-core branch protection +# This workflow is triggered on PRs to master branch on the repository +# It fails when someone tries to make a PR against the nf-core `master` branch instead of `dev` +on: + pull_request_target: + branches: [master] + +jobs: + test: + runs-on: ubuntu-latest + steps: + # PRs to the nf-core repo master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches + - name: Check PRs + if: github.repository == 'nf-core/oncoanalyser' + run: | + { [[ ${{github.event.pull_request.head.repo.full_name }} == nf-core/oncoanalyser ]] && [[ $GITHUB_HEAD_REF = "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] + + # If the above check failed, post a comment on the PR explaining the failure + # NOTE - this doesn't currently work if the PR is coming from a fork, due to limitations in GitHub actions secrets + - name: Post PR comment + if: failure() + uses: mshick/add-pr-comment@v1 + with: + message: | + ## This PR is against the `master` branch :x: + + * Do not close this PR + * Click _Edit_ and change the `base` to `dev` + * This CI test will remain failed until you push a new commit + + --- + + Hi @${{ github.event.pull_request.user.login }}, + + It looks like this pull-request is has been made against the [${{github.event.pull_request.head.repo.full_name }}](https://github.com/${{github.event.pull_request.head.repo.full_name }}) `master` branch. + The `master` branch on nf-core repositories should always contain code from the latest release. + Because of this, PRs to `master` are only allowed if they come from the [${{github.event.pull_request.head.repo.full_name }}](https://github.com/${{github.event.pull_request.head.repo.full_name }}) `dev` branch. + + You do not need to close this PR, you can change the target branch to `dev` by clicking the _"Edit"_ button at the top of this page. + Note that even after this, the test will continue to show as failing until you push a new commit. + + Thanks again for your contribution! + repo-token: ${{ secrets.GITHUB_TOKEN }} + allow-repeats: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..e1f80dbd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,39 @@ +name: nf-core CI +# This workflow runs the pipeline with the minimal test dataset to check that it completes without any syntax errors +on: + push: + branches: + - dev + pull_request: + release: + types: [published] + +env: + NXF_ANSI_LOG: false + +jobs: + test: + name: Run pipeline with test data + # Only run on push if this is the nf-core dev branch (merged PRs) + if: "${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/oncoanalyser') }}" + runs-on: ubuntu-latest + strategy: + matrix: + NXF_VER: + - "21.10.3" + - "latest-everything" + steps: + - name: Check out pipeline code + uses: actions/checkout@v2 + + - name: Install Nextflow + uses: nf-core/setup-nextflow@v1 + with: + version: "${{ matrix.NXF_VER }}" + + - name: Run pipeline with test data + # TODO nf-core: You can customise CI pipeline run tests as required + # For example: adding multiple test runs with different parameters + # Remember that you can parallelise this by using strategy.matrix + run: | + nextflow run ${GITHUB_WORKSPACE} -profile test,docker --outdir ./results diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix-linting.yml new file mode 100644 index 00000000..50f455de --- /dev/null +++ b/.github/workflows/fix-linting.yml @@ -0,0 +1,55 @@ +name: Fix linting from a comment +on: + issue_comment: + types: [created] + +jobs: + deploy: + # Only run if comment is on a PR with the main repo, and if it contains the magic keywords + if: > + contains(github.event.comment.html_url, '/pull/') && + contains(github.event.comment.body, '@nf-core-bot fix linting') && + github.repository == 'nf-core/oncoanalyser' + runs-on: ubuntu-latest + steps: + # Use the @nf-core-bot token to check out so we can push later + - uses: actions/checkout@v3 + with: + token: ${{ secrets.nf_core_bot_auth_token }} + + # Action runs on the issue comment, so we don't get the PR by default + # Use the gh cli to check out the PR + - name: Checkout Pull Request + run: gh pr checkout ${{ github.event.issue.number }} + env: + GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} + + - uses: actions/setup-node@v2 + + - name: Install Prettier + run: npm install -g prettier @prettier/plugin-php + + # Check that we actually need to fix something + - name: Run 'prettier --check' + id: prettier_status + run: | + if prettier --check ${GITHUB_WORKSPACE}; then + echo "::set-output name=result::pass" + else + echo "::set-output name=result::fail" + fi + + - name: Run 'prettier --write' + if: steps.prettier_status.outputs.result == 'fail' + run: prettier --write ${GITHUB_WORKSPACE} + + - name: Commit & push changes + if: steps.prettier_status.outputs.result == 'fail' + run: | + git config user.email "core@nf-co.re" + git config user.name "nf-core-bot" + git config push.default upstream + git add . + git status + git commit -m "[automated] Fix linting with Prettier" + git push diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml new file mode 100644 index 00000000..8a5ce69b --- /dev/null +++ b/.github/workflows/linting.yml @@ -0,0 +1,106 @@ +name: nf-core linting +# This workflow is triggered on pushes and PRs to the repository. +# It runs the `nf-core lint` and markdown lint tests to ensure +# that the code meets the nf-core guidelines. +on: + push: + pull_request: + release: + types: [published] + +jobs: + EditorConfig: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2 + + - name: Install editorconfig-checker + run: npm install -g editorconfig-checker + + - name: Run ECLint check + run: editorconfig-checker -exclude README.md $(find .* -type f | grep -v '.git\|.py\|.md\|json\|yml\|yaml\|html\|css\|work\|.nextflow\|build\|nf_core.egg-info\|log.txt\|Makefile') + + Prettier: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2 + + - name: Install Prettier + run: npm install -g prettier + + - name: Run Prettier --check + run: prettier --check ${GITHUB_WORKSPACE} + + PythonBlack: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Check code lints with Black + uses: psf/black@stable + + # If the above check failed, post a comment on the PR explaining the failure + - name: Post PR comment + if: failure() + uses: mshick/add-pr-comment@v1 + with: + message: | + ## Python linting (`black`) is failing + + To keep the code consistent with lots of contributors, we run automated code consistency checks. + To fix this CI test, please run: + + * Install [`black`](https://black.readthedocs.io/en/stable/): `pip install black` + * Fix formatting errors in your pipeline: `black .` + + Once you push these changes the test should pass, and you can hide this comment :+1: + + We highly recommend setting up Black in your code editor so that this formatting is done automatically on save. Ask about it on Slack for help! + + Thanks again for your contribution! + repo-token: ${{ secrets.GITHUB_TOKEN }} + allow-repeats: false + + nf-core: + runs-on: ubuntu-latest + steps: + - name: Check out pipeline code + uses: actions/checkout@v2 + + - name: Install Nextflow + uses: nf-core/setup-nextflow@v1 + + - uses: actions/setup-python@v3 + with: + python-version: "3.7" + architecture: "x64" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install nf-core + + - name: Run nf-core lint + env: + GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_PR_COMMIT: ${{ github.event.pull_request.head.sha }} + run: nf-core -l lint_log.txt lint --dir ${GITHUB_WORKSPACE} --markdown lint_results.md + + - name: Save PR number + if: ${{ always() }} + run: echo ${{ github.event.pull_request.number }} > PR_number.txt + + - name: Upload linting log file artifact + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: linting-logs + path: | + lint_log.txt + lint_results.md + PR_number.txt diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml new file mode 100644 index 00000000..04758f61 --- /dev/null +++ b/.github/workflows/linting_comment.yml @@ -0,0 +1,28 @@ +name: nf-core linting comment +# This workflow is triggered after the linting action is complete +# It posts an automated comment to the PR, even if the PR is coming from a fork + +on: + workflow_run: + workflows: ["nf-core linting"] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Download lint results + uses: dawidd6/action-download-artifact@v2 + with: + workflow: linting.yml + workflow_conclusion: completed + + - name: Get PR number + id: pr_number + run: echo "::set-output name=pr_number::$(cat linting-logs/PR_number.txt)" + + - name: Post PR comment + uses: marocchino/sticky-pull-request-comment@v2 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + number: ${{ steps.pr_number.outputs.pr_number }} + path: linting-logs/lint_results.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5124c9ac --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.nextflow* +work/ +data/ +results/ +.DS_Store +testing/ +testing* +*.pyc diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 00000000..85d95ecc --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,14 @@ +image: nfcore/gitpod:latest + +vscode: + extensions: # based on nf-core.nf-core-extensionpack + - codezombiech.gitignore # Language support for .gitignore files + # - cssho.vscode-svgviewer # SVG viewer + - esbenp.prettier-vscode # Markdown/CommonMark linting and style checking for Visual Studio Code + - eamodio.gitlens # Quickly glimpse into whom, why, and when a line or code block was changed + - EditorConfig.EditorConfig # override user/workspace settings with settings found in .editorconfig files + - Gruntfuggly.todo-tree # Display TODO and FIXME in a tree view in the activity bar + - mechatroner.rainbow-csv # Highlight columns in csv files in different colors + # - nextflow.nextflow # Nextflow syntax highlighting + - oderwat.indent-rainbow # Highlight indentation level + - streetsidesoftware.code-spell-checker # Spelling checker for source code diff --git a/.nf-core.yml b/.nf-core.yml new file mode 100644 index 00000000..3805dc81 --- /dev/null +++ b/.nf-core.yml @@ -0,0 +1 @@ +repository_type: pipeline diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..eb74a574 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,10 @@ +email_template.html +adaptivecard.json +.nextflow* +work/ +data/ +results/ +.DS_Store +testing/ +testing* +*.pyc diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 00000000..c81f9a76 --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1 @@ +printWidth: 120 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..f5b610f4 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# nf-core/oncoanalyser: Changelog + +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). + +## v1.0dev - [date] + +Initial release of nf-core/oncoanalyser, created with the [nf-core](https://nf-co.re/) template. + +### `Added` + +### `Fixed` + +### `Dependencies` + +### `Deprecated` diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 00000000..017666c0 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,56 @@ +cff-version: 1.2.0 +message: "If you use `nf-core tools` in your work, please cite the `nf-core` publication" +authors: + - family-names: Ewels + given-names: Philip + - family-names: Peltzer + given-names: Alexander + - family-names: Fillinger + given-names: Sven + - family-names: Patel + given-names: Harshil + - family-names: Alneberg + given-names: Johannes + - family-names: Wilm + given-names: Andreas + - family-names: Garcia + given-names: Maxime Ulysse + - family-names: Di Tommaso + given-names: Paolo + - family-names: Nahnsen + given-names: Sven +title: "The nf-core framework for community-curated bioinformatics pipelines." +version: 2.4.1 +doi: 10.1038/s41587-020-0439-x +date-released: 2022-05-16 +url: https://github.com/nf-core/tools +prefered-citation: + type: article + authors: + - family-names: Ewels + given-names: Philip + - family-names: Peltzer + given-names: Alexander + - family-names: Fillinger + given-names: Sven + - family-names: Patel + given-names: Harshil + - family-names: Alneberg + given-names: Johannes + - family-names: Wilm + given-names: Andreas + - family-names: Garcia + given-names: Maxime Ulysse + - family-names: Di Tommaso + given-names: Paolo + - family-names: Nahnsen + given-names: Sven + doi: 10.1038/s41587-020-0439-x + journal: nature biotechnology + start: 276 + end: 278 + title: "The nf-core framework for community-curated bioinformatics pipelines." + issue: 3 + volume: 38 + year: 2020 + url: https://dx.doi.org/10.1038/s41587-020-0439-x diff --git a/CITATIONS.md b/CITATIONS.md new file mode 100644 index 00000000..dfebcc85 --- /dev/null +++ b/CITATIONS.md @@ -0,0 +1,35 @@ +# nf-core/oncoanalyser: Citations + +## [nf-core](https://pubmed.ncbi.nlm.nih.gov/32055031/) + +> Ewels PA, Peltzer A, Fillinger S, Patel H, Alneberg J, Wilm A, Garcia MU, Di Tommaso P, Nahnsen S. The nf-core framework for community-curated bioinformatics pipelines. Nat Biotechnol. 2020 Mar;38(3):276-278. doi: 10.1038/s41587-020-0439-x. PubMed PMID: 32055031. + +## [Nextflow](https://pubmed.ncbi.nlm.nih.gov/28398311/) + +> Di Tommaso P, Chatzou M, Floden EW, Barja PP, Palumbo E, Notredame C. Nextflow enables reproducible computational workflows. Nat Biotechnol. 2017 Apr 11;35(4):316-319. doi: 10.1038/nbt.3820. PubMed PMID: 28398311. + +## Pipeline tools + +- [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) + +- [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) + > Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. + +## Software packaging/containerisation tools + +- [Anaconda](https://anaconda.com) + + > Anaconda Software Distribution. Computer software. Vers. 2-2.4.0. Anaconda, Nov. 2016. Web. + +- [Bioconda](https://pubmed.ncbi.nlm.nih.gov/29967506/) + + > Grüning B, Dale R, Sjödin A, Chapman BA, Rowe J, Tomkins-Tinch CH, Valieris R, Köster J; Bioconda Team. Bioconda: sustainable and comprehensive software distribution for the life sciences. Nat Methods. 2018 Jul;15(7):475-476. doi: 10.1038/s41592-018-0046-7. PubMed PMID: 29967506. + +- [BioContainers](https://pubmed.ncbi.nlm.nih.gov/28379341/) + + > da Veiga Leprevost F, Grüning B, Aflitos SA, Röst HL, Uszkoreit J, Barsnes H, Vaudel M, Moreno P, Gatto L, Weber J, Bai M, Jimenez RC, Sachsenberg T, Pfeuffer J, Alvarez RV, Griss J, Nesvizhskii AI, Perez-Riverol Y. BioContainers: an open-source and community-driven framework for software standardization. Bioinformatics. 2017 Aug 15;33(16):2580-2582. doi: 10.1093/bioinformatics/btx192. PubMed PMID: 28379341; PubMed Central PMCID: PMC5870671. + +- [Docker](https://dl.acm.org/doi/10.5555/2600239.2600241) + +- [Singularity](https://pubmed.ncbi.nlm.nih.gov/28494014/) + > Kurtzer GM, Sochat V, Bauer MW. Singularity: Scientific containers for mobility of compute. PLoS One. 2017 May 11;12(5):e0177459. doi: 10.1371/journal.pone.0177459. eCollection 2017. PubMed PMID: 28494014; PubMed Central PMCID: PMC5426675. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..f4fd052f --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,111 @@ +# Code of Conduct at nf-core (v1.0) + +## Our Pledge + +In the interest of fostering an open, collaborative, and welcoming environment, we as contributors and maintainers of nf-core, pledge to making participation in our projects and community a harassment-free experience for everyone, regardless of: + +- Age +- Body size +- Familial status +- Gender identity and expression +- Geographical location +- Level of experience +- Nationality and national origins +- Native language +- Physical and neurological ability +- Race or ethnicity +- Religion +- Sexual identity and orientation +- Socioeconomic status + +Please note that the list above is alphabetised and is therefore not ranked in any order of preference or importance. + +## Preamble + +> Note: This Code of Conduct (CoC) has been drafted by the nf-core Safety Officer and been edited after input from members of the nf-core team and others. "We", in this document, refers to the Safety Officer and members of the nf-core core team, both of whom are deemed to be members of the nf-core community and are therefore required to abide by this Code of Conduct. This document will amended periodically to keep it up-to-date, and in case of any dispute, the most current version will apply. + +An up-to-date list of members of the nf-core core team can be found [here](https://nf-co.re/about). Our current safety officer is Renuka Kudva. + +nf-core is a young and growing community that welcomes contributions from anyone with a shared vision for [Open Science Policies](https://www.fosteropenscience.eu/taxonomy/term/8). Open science policies encompass inclusive behaviours and we strive to build and maintain a safe and inclusive environment for all individuals. + +We have therefore adopted this code of conduct (CoC), which we require all members of our community and attendees in nf-core events to adhere to in all our workspaces at all times. Workspaces include but are not limited to Slack, meetings on Zoom, Jitsi, YouTube live etc. + +Our CoC will be strictly enforced and the nf-core team reserve the right to exclude participants who do not comply with our guidelines from our workspaces and future nf-core activities. + +We ask all members of our community to help maintain a supportive and productive workspace and to avoid behaviours that can make individuals feel unsafe or unwelcome. Please help us maintain and uphold this CoC. + +Questions, concerns or ideas on what we can include? Contact safety [at] nf-co [dot] re + +## Our Responsibilities + +The safety officer is responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behaviour. + +The safety officer in consultation with the nf-core core team have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +Members of the core team or the safety officer who violate the CoC will be required to recuse themselves pending investigation. They will not have access to any reports of the violations and be subject to the same actions as others in violation of the CoC. + +## When are where does this Code of Conduct apply? + +Participation in the nf-core community is contingent on following these guidelines in all our workspaces and events. This includes but is not limited to the following listed alphabetically and therefore in no order of preference: + +- Communicating with an official project email address. +- Communicating with community members within the nf-core Slack channel. +- Participating in hackathons organised by nf-core (both online and in-person events). +- Participating in collaborative work on GitHub, Google Suite, community calls, mentorship meetings, email correspondence. +- Participating in workshops, training, and seminar series organised by nf-core (both online and in-person events). This applies to events hosted on web-based platforms such as Zoom, Jitsi, YouTube live etc. +- Representing nf-core on social media. This includes both official and personal accounts. + +## nf-core cares 😊 + +nf-core's CoC and expectations of respectful behaviours for all participants (including organisers and the nf-core team) include but are not limited to the following (listed in alphabetical order): + +- Ask for consent before sharing another community member’s personal information (including photographs) on social media. +- Be respectful of differing viewpoints and experiences. We are all here to learn from one another and a difference in opinion can present a good learning opportunity. +- Celebrate your accomplishments at events! (Get creative with your use of emojis 🎉 🥳 💯 🙌 !) +- Demonstrate empathy towards other community members. (We don’t all have the same amount of time to dedicate to nf-core. If tasks are pending, don’t hesitate to gently remind members of your team. If you are leading a task, ask for help if you feel overwhelmed.) +- Engage with and enquire after others. (This is especially important given the geographically remote nature of the nf-core community, so let’s do this the best we can) +- Focus on what is best for the team and the community. (When in doubt, ask) +- Graciously accept constructive criticism, yet be unafraid to question, deliberate, and learn. +- Introduce yourself to members of the community. (We’ve all been outsiders and we know that talking to strangers can be hard for some, but remember we’re interested in getting to know you and your visions for open science!) +- Show appreciation and **provide clear feedback**. (This is especially important because we don’t see each other in person and it can be harder to interpret subtleties. Also remember that not everyone understands a certain language to the same extent as you do, so **be clear in your communications to be kind.**) +- Take breaks when you feel like you need them. +- Using welcoming and inclusive language. (Participants are encouraged to display their chosen pronouns on Zoom or in communication on Slack.) + +## nf-core frowns on 😕 + +The following behaviours from any participants within the nf-core community (including the organisers) will be considered unacceptable under this code of conduct. Engaging or advocating for any of the following could result in expulsion from nf-core workspaces. + +- Deliberate intimidation, stalking or following and sustained disruption of communication among participants of the community. This includes hijacking shared screens through actions such as using the annotate tool in conferencing software such as Zoom. +- “Doxing” i.e. posting (or threatening to post) another person’s personal identifying information online. +- Spamming or trolling of individuals on social media. +- Use of sexual or discriminatory imagery, comments, or jokes and unwelcome sexual attention. +- Verbal and text comments that reinforce social structures of domination related to gender, gender identity and expression, sexual orientation, ability, physical appearance, body size, race, age, religion or work experience. + +### Online Trolling + +The majority of nf-core interactions and events are held online. Unfortunately, holding events online comes with the added issue of online trolling. This is unacceptable, reports of such behaviour will be taken very seriously, and perpetrators will be excluded from activities immediately. + +All community members are required to ask members of the group they are working within for explicit consent prior to taking screenshots of individuals during video calls. + +## Procedures for Reporting CoC violations + +If someone makes you feel uncomfortable through their behaviours or actions, report it as soon as possible. + +You can reach out to members of the [nf-core core team](https://nf-co.re/about) and they will forward your concerns to the safety officer(s). + +Issues directly concerning members of the core team will be dealt with by other members of the core team and the safety manager, and possible conflicts of interest will be taken into account. nf-core is also in discussions about having an ombudsperson, and details will be shared in due course. + +All reports will be handled with utmost discretion and confidentially. + +## Attribution and Acknowledgements + +- The [Contributor Covenant, version 1.4](http://contributor-covenant.org/version/1/4) +- The [OpenCon 2017 Code of Conduct](http://www.opencon2017.org/code_of_conduct) (CC BY 4.0 OpenCon organisers, SPARC and Right to Research Coalition) +- The [eLife innovation sprint 2020 Code of Conduct](https://sprint.elifesciences.org/code-of-conduct/) +- The [Mozilla Community Participation Guidelines v3.1](https://www.mozilla.org/en-US/about/governance/policies/participation/) (version 3.1, CC BY-SA 3.0 Mozilla) + +## Changelog + +### v1.0 - March 12th, 2021 + +- Complete rewrite from original [Contributor Covenant](http://contributor-covenant.org/) CoC. diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f92ae0c3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Stephen Watts + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..95bace73 --- /dev/null +++ b/README.md @@ -0,0 +1,92 @@ +# ![nf-core/oncoanalyser](docs/images/nf-core-oncoanalyser_logo_light.png#gh-light-mode-only) ![nf-core/oncoanalyser](docs/images/nf-core-oncoanalyser_logo_dark.png#gh-dark-mode-only) + +[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/oncoanalyser/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) + +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg)](https://www.nextflow.io/) +[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) +[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) +[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) +[![Launch on Nextflow Tower](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/oncoanalyser) + +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23oncoanalyser-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/oncoanalyser)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) + +## Introduction + + + +**nf-core/oncoanalyser** is a comprehensive cancer WGS/WTS analysis and reporting pipeline. + +The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. Where possible, these processes have been submitted to and installed from [nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to everyone within the Nextflow community! + + + +On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources.The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/oncoanalyser/results). + +## Pipeline summary + + + +1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) +2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) + +## Quick Start + +1. Install [`Nextflow`](https://www.nextflow.io/docs/latest/getstarted.html#installation) (`>=21.10.3`) + +2. Install any of [`Docker`](https://docs.docker.com/engine/installation/), [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/) (you can follow [this tutorial](https://singularity-tutorial.github.io/01-installation/)), [`Podman`](https://podman.io/), [`Shifter`](https://nersc.gitlab.io/development/shifter/how-to-use/) or [`Charliecloud`](https://hpc.github.io/charliecloud/) for full pipeline reproducibility _(you can use [`Conda`](https://conda.io/miniconda.html) both to install Nextflow itself and also to manage software within pipelines. Please only use it within pipelines as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles))_. + +3. Download the pipeline and test it on a minimal dataset with a single command: + + ```bash + nextflow run nf-core/oncoanalyser -profile test,YOURPROFILE --outdir + ``` + + Note that some form of configuration will be needed so that Nextflow knows how to fetch the required software. This is usually done in the form of a config profile (`YOURPROFILE` in the example command above). You can chain multiple config profiles in a comma-separated string. + + > - The pipeline comes with config profiles called `docker`, `singularity`, `podman`, `shifter`, `charliecloud` and `conda` which instruct the pipeline to use the named tool for software management. For example, `-profile test,docker`. + > - Please check [nf-core/configs](https://github.com/nf-core/configs#documentation) to see if a custom config file to run nf-core pipelines already exists for your Institute. If so, you can simply use `-profile ` in your command. This will enable either `docker` or `singularity` and set the appropriate execution settings for your local compute environment. + > - If you are using `singularity`, please use the [`nf-core download`](https://nf-co.re/tools/#downloading-pipelines-for-offline-use) command to download images first, before running the pipeline. Setting the [`NXF_SINGULARITY_CACHEDIR` or `singularity.cacheDir`](https://www.nextflow.io/docs/latest/singularity.html?#singularity-docker-hub) Nextflow options enables you to store and re-use the images from a central location for future pipeline runs. + > - If you are using `conda`, it is highly recommended to use the [`NXF_CONDA_CACHEDIR` or `conda.cacheDir`](https://www.nextflow.io/docs/latest/conda.html) settings to store the environments in a central location for future pipeline runs. + +4. Start running your own analysis! + + + + ```bash + nextflow run nf-core/oncoanalyser --input samplesheet.csv --outdir --genome GRCh37 -profile + ``` + +## Documentation + +The nf-core/oncoanalyser pipeline comes with documentation about the pipeline [usage](https://nf-co.re/oncoanalyser/usage), [parameters](https://nf-co.re/oncoanalyser/parameters) and [output](https://nf-co.re/oncoanalyser/output). + +## Credits + +nf-core/oncoanalyser was originally written by Stephen Watts. + +We thank the following people for their extensive assistance in the development of this pipeline: + + + +## Contributions and Support + +If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). + +For further information or help, don't hesitate to get in touch on the [Slack `#oncoanalyser` channel](https://nfcore.slack.com/channels/oncoanalyser) (you can join with [this invite](https://nf-co.re/join/slack)). + +## Citations + + + + + + +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: + +> **The nf-core framework for community-curated bioinformatics pipelines.** +> +> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen. +> +> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). diff --git a/assets/adaptivecard.json b/assets/adaptivecard.json new file mode 100644 index 00000000..345c580f --- /dev/null +++ b/assets/adaptivecard.json @@ -0,0 +1,67 @@ +{ + "type": "message", + "attachments": [ + { + "contentType": "application/vnd.microsoft.card.adaptive", + "contentUrl": null, + "content": { + "\$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "msteams": { + "width": "Full" + }, + "type": "AdaptiveCard", + "version": "1.2", + "body": [ + { + "type": "TextBlock", + "size": "Large", + "weight": "Bolder", + "color": "<% if (success) { %>Good<% } else { %>Attention<%} %>", + "text": "nf-core/oncoanalyser v${version} - ${runName}", + "wrap": true + }, + { + "type": "TextBlock", + "spacing": "None", + "text": "Completed at ${dateComplete} (duration: ${duration})", + "isSubtle": true, + "wrap": true + }, + { + "type": "TextBlock", + "text": "<% if (success) { %>Pipeline completed successfully!<% } else { %>Pipeline completed with errors. The full error message was: ${errorReport}.<% } %>", + "wrap": true + }, + { + "type": "TextBlock", + "text": "The command used to launch the workflow was as follows:", + "wrap": true + }, + { + "type": "TextBlock", + "text": "${commandLine}", + "isSubtle": true, + "wrap": true + } + ], + "actions": [ + { + "type": "Action.ShowCard", + "title": "Pipeline Configuration", + "card": { + "type": "AdaptiveCard", + "\$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "body": [ + { + "type": "FactSet", + "facts": [<% out << summary.collect{ k,v -> "{\"title\": \"$k\", \"value\" : \"$v\"}"}.join(",\n") %> + ] + } + ] + } + } + ] + } + } + ] +} diff --git a/assets/email_template.html b/assets/email_template.html new file mode 100644 index 00000000..098117ff --- /dev/null +++ b/assets/email_template.html @@ -0,0 +1,53 @@ + + + + + + + + nf-core/oncoanalyser Pipeline Report + + +
    + + + +

    nf-core/oncoanalyser v${version}

    +

    Run Name: $runName

    + +<% if (!success){ + out << """ +
    +

    nf-core/oncoanalyser execution completed unsuccessfully!

    +

    The exit status of the task that caused the workflow execution to fail was: $exitStatus.

    +

    The full error message was:

    +
    ${errorReport}
    +
    + """ +} else { + out << """ +
    + nf-core/oncoanalyser execution completed successfully! +
    + """ +} +%> + +

    The workflow was completed at $dateComplete (duration: $duration)

    +

    The command used to launch the workflow was as follows:

    +
    $commandLine
    + +

    Pipeline Configuration:

    + + + <% out << summary.collect{ k,v -> "" }.join("\n") %> + +
    $k
    $v
    + +

    nf-core/oncoanalyser

    +

    https://github.com/nf-core/oncoanalyser

    + +
    + + + diff --git a/assets/email_template.txt b/assets/email_template.txt new file mode 100644 index 00000000..9058d515 --- /dev/null +++ b/assets/email_template.txt @@ -0,0 +1,39 @@ +---------------------------------------------------- + ,--./,-. + ___ __ __ __ ___ /,-._.--~\\ + |\\ | |__ __ / ` / \\ |__) |__ } { + | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-, + `._,._,' + nf-core/oncoanalyser v${version} +---------------------------------------------------- +Run Name: $runName + +<% if (success){ + out << "## nf-core/oncoanalyser execution completed successfully! ##" +} else { + out << """#################################################### +## nf-core/oncoanalyser execution completed unsuccessfully! ## +#################################################### +The exit status of the task that caused the workflow execution to fail was: $exitStatus. +The full error message was: + +${errorReport} +""" +} %> + + +The workflow was completed at $dateComplete (duration: $duration) + +The command used to launch the workflow was as follows: + + $commandLine + + + +Pipeline Configuration: +----------------------- +<% out << summary.collect{ k,v -> " - $k: $v" }.join("\n") %> + +-- +nf-core/oncoanalyser +https://github.com/nf-core/oncoanalyser diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml new file mode 100644 index 00000000..5e1aba5b --- /dev/null +++ b/assets/methods_description_template.yml @@ -0,0 +1,25 @@ +id: "nf-core-oncoanalyser-methods-description" +description: "Suggested text and references to use when describing pipeline usage within the methods section of a publication." +section_name: "nf-core/oncoanalyser Methods Description" +section_href: "https://github.com/nf-core/oncoanalyser" +plot_type: "html" +## TODO nf-core: Update the HTML below to your prefered methods description, e.g. add publication citation for this pipeline +## You inject any metadata in the Nextflow '${workflow}' object +data: | +

    Methods

    +

    Data was processed using nf-core/oncoanalyser v${workflow.manifest.version} ${doi_text} of the nf-core collection of workflows (Ewels et al., 2020).

    +

    The pipeline was executed with Nextflow v${workflow.nextflow.version} (Di Tommaso et al., 2017) with the following command:

    +
    ${workflow.commandLine}
    +

    References

    +
      +
    • Di Tommaso, P., Chatzou, M., Floden, E. W., Barja, P. P., Palumbo, E., & Notredame, C. (2017). Nextflow enables reproducible computational workflows. Nature Biotechnology, 35(4), 316-319. https://doi.org/10.1038/nbt.3820
    • +
    • Ewels, P. A., Peltzer, A., Fillinger, S., Patel, H., Alneberg, J., Wilm, A., Garcia, M. U., Di Tommaso, P., & Nahnsen, S. (2020). The nf-core framework for community-curated bioinformatics pipelines. Nature Biotechnology, 38(3), 276-278. https://doi.org/10.1038/s41587-020-0439-x
    • +
    +
    +
    Notes:
    +
      + ${nodoi_text} +
    • The command above does not include parameters contained in any configs or profiles that may have been used. Ensure the config file is also uploaded with your publication!
    • +
    • You should also cite all software used within this run. Check the "Software Versions" of this report to get version information.
    • +
    +
    diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml new file mode 100644 index 00000000..dfb73cca --- /dev/null +++ b/assets/multiqc_config.yml @@ -0,0 +1,13 @@ +report_comment: > + This report has been generated by the nf-core/oncoanalyser + analysis pipeline. For information about how to interpret these results, please see the + documentation. +report_section_order: + "nf-core-oncoanalyser-methods-description": + order: -1000 + software_versions: + order: -1001 + "nf-core-oncoanalyser-summary": + order: -1002 + +export_plots: true diff --git a/assets/nf-core-oncoanalyser_logo_light.png b/assets/nf-core-oncoanalyser_logo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..72327aa5792d50d626ec3be3aeb73dd9309e4213 GIT binary patch literal 11358 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 aVr_2|SZrswIRFm~gOugfU{x +Content-Disposition: inline; filename="nf-core-oncoanalyser_logo_light.png" + +<% out << new File("$projectDir/assets/nf-core-oncoanalyser_logo_light.png"). + bytes. + encodeBase64(). + toString(). + tokenize( '\n' )*. + toList()*. + collate( 76 )*. + collect { it.join() }. + flatten(). + join( '\n' ) %> + +<% +if (mqcFile){ +def mqcFileObj = new File("$mqcFile") +if (mqcFileObj.length() < mqcMaxSize){ +out << """ +--nfcoremimeboundary +Content-Type: text/html; name=\"multiqc_report\" +Content-Transfer-Encoding: base64 +Content-ID: +Content-Disposition: attachment; filename=\"${mqcFileObj.getName()}\" + +${mqcFileObj. + bytes. + encodeBase64(). + toString(). + tokenize( '\n' )*. + toList()*. + collate( 76 )*. + collect { it.join() }. + flatten(). + join( '\n' )} +""" +}} +%> + +--nfcoremimeboundary-- diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py new file mode 100755 index 00000000..11b15572 --- /dev/null +++ b/bin/check_samplesheet.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python + + +"""Provide a command line tool to validate and transform tabular samplesheets.""" + + +import argparse +import csv +import logging +import sys +from collections import Counter +from pathlib import Path + +logger = logging.getLogger() + + +class RowChecker: + """ + Define a service that can validate and transform each given row. + + Attributes: + modified (list): A list of dicts, where each dict corresponds to a previously + validated and transformed row. The order of rows is maintained. + + """ + + VALID_FORMATS = ( + ".fq.gz", + ".fastq.gz", + ) + + def __init__( + self, + sample_col="sample", + first_col="fastq_1", + second_col="fastq_2", + single_col="single_end", + **kwargs, + ): + """ + Initialize the row checker with the expected column names. + + 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"). + + """ + super().__init__(**kwargs) + self._sample_col = sample_col + self._first_col = first_col + self._second_col = second_col + self._single_col = single_col + self._seen = set() + self.modified = [] + + def validate_and_transform(self, row): + """ + Perform all validations on the given row and insert the read pairing status. + + Args: + row (dict): A mapping from column headers (keys) to elements of that row + (values). + + """ + self._validate_sample(row) + self._validate_first(row) + self._validate_second(row) + self._validate_pair(row) + self._seen.add((row[self._sample_col], row[self._first_col])) + self.modified.append(row) + + def _validate_sample(self, row): + """Assert that the sample name exists and convert spaces to underscores.""" + if len(row[self._sample_col]) <= 0: + raise AssertionError("Sample input is required.") + # Sanitize samples slightly. + 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.""" + 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]) + + 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]) + + 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_fastq_format(self, filename): + """Assert that a given filename has one of the expected FASTQ extensions.""" + 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"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. + + 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. + + """ + if len(self._seen) != len(self.modified): + raise AssertionError("The pair of sample name and FASTQ 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]}" + + +def read_head(handle, num_lines=10): + """Read the specified number of lines from the current position in the file.""" + lines = [] + for idx, line in enumerate(handle): + if idx == num_lines: + break + lines.append(line) + return "".join(lines) + + +def sniff_format(handle): + """ + Detect the tabular format. + + Args: + handle (text file): A handle to a `text file`_ object. The read position is + expected to be at the beginning (index 0). + + Returns: + csv.Dialect: The detected tabular format. + + .. _text file: + https://docs.python.org/3/glossary.html#term-text-file + + """ + peek = read_head(handle) + handle.seek(0) + sniffer = csv.Sniffer() + if not sniffer.has_header(peek): + logger.critical("The given sample sheet does not appear to contain a header.") + sys.exit(1) + dialect = sniffer.sniff(peek) + return dialect + + +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. + + Args: + file_in (pathlib.Path): The given tabular samplesheet. The format can be either + CSV, TSV, or any other format automatically recognized by ``csv.Sniffer``. + file_out (pathlib.Path): Where the validated and transformed samplesheet should + be created; always in CSV format. + + Example: + 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, + + .. _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"} + # 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)) + # Validate the existence of the expected header columns. + if not required_columns.issubset(reader.fieldnames): + req_cols = ", ".join(required_columns) + logger.critical(f"The sample sheet **must** contain these column headers: {req_cols}.") + sys.exit(1) + # Validate each row. + checker = RowChecker() + for i, row in enumerate(reader): + try: + checker.validate_and_transform(row) + except AssertionError as error: + logger.critical(f"{str(error)} On line {i + 2}.") + sys.exit(1) + checker.validate_unique_samples() + header = list(reader.fieldnames) + 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=",") + writer.writeheader() + for row in checker.modified: + writer.writerow(row) + + +def parse_args(argv=None): + """Define and immediately parse command line arguments.""" + parser = argparse.ArgumentParser( + description="Validate and transform a tabular samplesheet.", + epilog="Example: python check_samplesheet.py samplesheet.csv samplesheet.valid.csv", + ) + parser.add_argument( + "file_in", + metavar="FILE_IN", + type=Path, + help="Tabular input samplesheet in CSV or TSV format.", + ) + parser.add_argument( + "file_out", + metavar="FILE_OUT", + type=Path, + help="Transformed output samplesheet in CSV format.", + ) + parser.add_argument( + "-l", + "--log-level", + help="The desired log level (default WARNING).", + choices=("CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"), + default="WARNING", + ) + return parser.parse_args(argv) + + +def main(argv=None): + """Coordinate argument parsing and program execution.""" + args = parse_args(argv) + logging.basicConfig(level=args.log_level, format="[%(levelname)s] %(message)s") + if not args.file_in.is_file(): + logger.error(f"The given input file {args.file_in} was not found!") + sys.exit(2) + args.file_out.parent.mkdir(parents=True, exist_ok=True) + check_samplesheet(args.file_in, args.file_out) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/conf/base.config b/conf/base.config new file mode 100644 index 00000000..05eac721 --- /dev/null +++ b/conf/base.config @@ -0,0 +1,65 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + nf-core/oncoanalyser Nextflow base config file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + A 'blank slate' config file, appropriate for general use on most high performance + compute environments. Assumes that all software is installed and available on + the PATH. Runs in `local` mode - all jobs will be run on the logged in environment. +---------------------------------------------------------------------------------------- +*/ + +process { + + // TODO nf-core: Check the defaults for all processes + cpus = { check_max( 1 * task.attempt, 'cpus' ) } + memory = { check_max( 6.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } + + errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } + maxRetries = 1 + maxErrors = '-1' + + // Process-specific resource requirements + // NOTE - Please try and re-use the labels below as much as possible. + // These labels are used and recognised by default in DSL2 files hosted on nf-core/modules. + // If possible, it would be nice to keep the same label naming convention when + // adding in your local modules too. + // TODO nf-core: Customise requirements for specific processes. + // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors + withLabel:process_single { + cpus = { check_max( 1 , 'cpus' ) } + memory = { check_max( 6.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } + } + withLabel:process_low { + cpus = { check_max( 2 * task.attempt, 'cpus' ) } + memory = { check_max( 12.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } + } + withLabel:process_medium { + cpus = { check_max( 6 * task.attempt, 'cpus' ) } + memory = { check_max( 36.GB * task.attempt, 'memory' ) } + time = { check_max( 8.h * task.attempt, 'time' ) } + } + withLabel:process_high { + cpus = { check_max( 12 * task.attempt, 'cpus' ) } + memory = { check_max( 72.GB * task.attempt, 'memory' ) } + time = { check_max( 16.h * task.attempt, 'time' ) } + } + withLabel:process_long { + time = { check_max( 20.h * task.attempt, 'time' ) } + } + withLabel:process_high_memory { + memory = { check_max( 200.GB * task.attempt, 'memory' ) } + } + withLabel:error_ignore { + errorStrategy = 'ignore' + } + withLabel:error_retry { + errorStrategy = 'retry' + maxRetries = 2 + } + withName:CUSTOM_DUMPSOFTWAREVERSIONS { + cache = false + } +} diff --git a/conf/igenomes.config b/conf/igenomes.config new file mode 100644 index 00000000..7a1b3ac6 --- /dev/null +++ b/conf/igenomes.config @@ -0,0 +1,432 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for iGenomes paths +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines reference genomes using iGenome paths. + Can be used by any config that customises the base path using: + $params.igenomes_base / --igenomes_base +---------------------------------------------------------------------------------------- +*/ + +params { + // illumina iGenomes reference file paths + genomes { + 'GRCh37' { + fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/GRCh37-blacklist.bed" + } + 'GRCh38' { + fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" + } + 'GRCm38' { + fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "1.87e9" + blacklist = "${projectDir}/assets/blacklists/GRCm38-blacklist.bed" + } + 'TAIR10' { + fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" + mito_name = "Mt" + } + 'EB2' { + fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" + } + 'UMD3.1' { + fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" + mito_name = "MT" + } + 'WBcel235' { + fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" + mito_name = "MtDNA" + macs_gsize = "9e7" + } + 'CanFam3.1' { + fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" + mito_name = "MT" + } + 'GRCz10' { + fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'BDGP6' { + fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" + mito_name = "M" + macs_gsize = "1.2e8" + } + 'EquCab2' { + fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" + mito_name = "MT" + } + 'EB1' { + fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" + } + 'Galgal4' { + fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'Gm01' { + fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" + } + 'Mmul_1' { + fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" + mito_name = "MT" + } + 'IRGSP-1.0' { + fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" + mito_name = "Mt" + } + 'CHIMP2.1.4' { + fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" + mito_name = "MT" + } + 'Rnor_5.0' { + fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'Rnor_6.0' { + fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" + mito_name = "MT" + } + 'R64-1-1' { + fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" + mito_name = "MT" + macs_gsize = "1.2e7" + } + 'EF2' { + fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "1.21e7" + } + 'Sbi1' { + fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" + } + 'Sscrofa10.2' { + fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" + mito_name = "MT" + } + 'AGPv3' { + fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" + mito_name = "Mt" + } + 'hg38' { + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" + } + 'hg19' { + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${projectDir}/assets/blacklists/hg19-blacklist.bed" + } + 'mm10' { + fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "1.87e9" + blacklist = "${projectDir}/assets/blacklists/mm10-blacklist.bed" + } + 'bosTau8' { + fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" + mito_name = "chrM" + } + 'ce10' { + fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "9e7" + } + 'canFam3' { + fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" + mito_name = "chrM" + } + 'danRer10' { + fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "1.37e9" + } + 'dm6' { + fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "1.2e8" + } + 'equCab2' { + fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" + mito_name = "chrM" + } + 'galGal4' { + fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" + mito_name = "chrM" + } + 'panTro4' { + fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" + mito_name = "chrM" + } + 'rn6' { + fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" + mito_name = "chrM" + } + 'sacCer3' { + fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" + readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "1.2e7" + } + 'susScr3' { + fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/" + bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" + mito_name = "chrM" + } + } +} diff --git a/conf/modules.config b/conf/modules.config new file mode 100644 index 00000000..da58a5d8 --- /dev/null +++ b/conf/modules.config @@ -0,0 +1,41 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Config file for defining DSL2 per module options and publishing paths +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Available keys to override module options: + ext.args = Additional arguments appended to command in module. + ext.args2 = Second set of arguments appended to command in module (multi-tool modules). + ext.args3 = Third set of arguments appended to command in module (multi-tool modules). + ext.prefix = File name prefix for output files. +---------------------------------------------------------------------------------------- +*/ + +process { + + publishDir = [ + path: { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + + withName: SAMPLESHEET_CHECK { + publishDir = [ + path: { "${params.outdir}/pipeline_info" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + + withName: FASTQC { + ext.args = '--quiet' + } + + withName: CUSTOM_DUMPSOFTWAREVERSIONS { + publishDir = [ + path: { "${params.outdir}/pipeline_info" }, + mode: params.publish_dir_mode, + pattern: '*_versions.yml' + ] + } + +} diff --git a/conf/test.config b/conf/test.config new file mode 100644 index 00000000..42f23058 --- /dev/null +++ b/conf/test.config @@ -0,0 +1,29 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running minimal tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a fast and simple pipeline test. + + Use as follows: + nextflow run nf-core/oncoanalyser -profile test, --outdir + +---------------------------------------------------------------------------------------- +*/ + +params { + config_profile_name = 'Test profile' + config_profile_description = 'Minimal test dataset to check pipeline function' + + // Limit resources so that this can run on GitHub Actions + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' + + // Input data + // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets + // TODO nf-core: Give any required params for the test so that command line flags are not needed + input = 'https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv' + + // Genome references + genome = 'R64-1-1' +} diff --git a/conf/test_full.config b/conf/test_full.config new file mode 100644 index 00000000..3a0c73e0 --- /dev/null +++ b/conf/test_full.config @@ -0,0 +1,24 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running full-size tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a full size pipeline test. + + Use as follows: + nextflow run nf-core/oncoanalyser -profile test_full, --outdir + +---------------------------------------------------------------------------------------- +*/ + +params { + config_profile_name = 'Full test profile' + config_profile_description = 'Full test dataset to check pipeline function' + + // Input data for full size test + // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) + // TODO nf-core: Give any required params for the test so that command line flags are not needed + input = 'https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_full_illumina_amplicon.csv' + + // Genome references + genome = 'R64-1-1' +} diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..a4e57f5c --- /dev/null +++ b/docs/README.md @@ -0,0 +1,10 @@ +# nf-core/oncoanalyser: Documentation + +The nf-core/oncoanalyser documentation is split into the following pages: + +- [Usage](usage.md) + - An overview of how the pipeline works, how to run it and a description of all of the different command-line flags. +- [Output](output.md) + - An overview of the different results produced by the pipeline and how to interpret them. + +You can find a lot more documentation about installing, configuring and running nf-core pipelines on the website: [https://nf-co.re](https://nf-co.re) diff --git a/docs/images/mqc_fastqc_adapter.png b/docs/images/mqc_fastqc_adapter.png new file mode 100755 index 0000000000000000000000000000000000000000..361d0e47acfb424dea1f326590d1eb2f6dfa26b5 GIT binary patch literal 23458 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 literal 0 HcmV?d00001 diff --git a/docs/images/mqc_fastqc_quality.png b/docs/images/mqc_fastqc_quality.png new file mode 100755 index 0000000000000000000000000000000000000000..a4b89bf56ab2ba88cab87841916eb680a816deae GIT binary patch literal 55769 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�)v~C(0C)c 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 M)78&qol`;+0Fu7JivR!s literal 0 HcmV?d00001 diff --git a/docs/images/nf-core-oncoanalyser_logo_dark.png b/docs/images/nf-core-oncoanalyser_logo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6e9f66c1e81c97da2504f06623d225734ffe5197 GIT binary patch literal 87060 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 R{3Q7n*<-((^%M2i{{oi35HA1# literal 0 HcmV?d00001 diff --git a/docs/images/nf-core-oncoanalyser_logo_light.png b/docs/images/nf-core-oncoanalyser_logo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..5d6f1c71ba0d76002047ae721880d6a65df8286d GIT binary patch literal 86949 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%0DdkSBkTJ0jfo-uX{!snR7# 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 PIuv4Kcd%f;*AM> + +## Pipeline overview + +The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: + +- [FastQC](#fastqc) - Raw read QC +- [MultiQC](#multiqc) - Aggregate report describing results and QC from the whole pipeline +- [Pipeline information](#pipeline-information) - Report metrics generated during the workflow execution + +### FastQC + +
    +Output files + +- `fastqc/` + - `*_fastqc.html`: FastQC report containing quality metrics. + - `*_fastqc.zip`: Zip archive containing the FastQC report, tab-delimited data file and plot images. + +
    + +[FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your sequenced reads. It provides information about the quality score distribution across your reads, per base sequence content (%A/T/G/C), adapter contamination and overrepresented sequences. For further reading and documentation see the [FastQC help pages](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). + +![MultiQC - FastQC sequence counts plot](images/mqc_fastqc_counts.png) + +![MultiQC - FastQC mean quality scores plot](images/mqc_fastqc_quality.png) + +![MultiQC - FastQC adapter content plot](images/mqc_fastqc_adapter.png) + +> **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. + +### MultiQC + +
    +Output files + +- `multiqc/` + - `multiqc_report.html`: a standalone HTML file that can be viewed in your web browser. + - `multiqc_data/`: directory containing parsed statistics from the different tools used in the pipeline. + - `multiqc_plots/`: directory containing static images from the report in various formats. + +
    + +[MultiQC](http://multiqc.info) is a visualization tool that generates a single HTML report summarising all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in the report data directory. + +Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQC. The pipeline has special steps which also allow the software versions to be reported in the MultiQC output for future traceability. For more information about how to use MultiQC reports, see . + +### Pipeline information + +
    +Output files + +- `pipeline_info/` + - Reports generated by Nextflow: `execution_report.html`, `execution_timeline.html`, `execution_trace.txt` and `pipeline_dag.dot`/`pipeline_dag.svg`. + - Reports generated by the pipeline: `pipeline_report.html`, `pipeline_report.txt` and `software_versions.yml`. The `pipeline_report*` files will only be present if the `--email` / `--email_on_fail` parameter's are used when running the pipeline. + - Reformatted samplesheet files used as input to the pipeline: `samplesheet.valid.csv`. + +
    + +[Nextflow](https://www.nextflow.io/docs/latest/tracing.html) provides excellent functionality for generating various reports relevant to the running and execution of the pipeline. This will allow you to troubleshoot errors with the running of the pipeline, and also provide you with other information such as launch commands, run times and resource usage. diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 00000000..8d291b27 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,264 @@ +# nf-core/oncoanalyser: Usage + +## :warning: Please read this documentation on the nf-core website: [https://nf-co.re/oncoanalyser/usage](https://nf-co.re/oncoanalyser/usage) + +> _Documentation of pipeline parameters is generated automatically from the pipeline schema and can no longer be found in markdown files._ + +## Introduction + + + +## Samplesheet input + +You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row as shown in the examples below. + +```bash +--input '[path to samplesheet file]' +``` + +### Multiple runs of the same sample + +The `sample` identifiers have to be the same when you have re-sequenced the same sample more than once e.g. to increase sequencing depth. The pipeline will concatenate the raw reads before performing any downstream analysis. Below is an example for the same sample sequenced across 3 lanes: + +```console +sample,fastq_1,fastq_2 +CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz +CONTROL_REP1,AEG588A1_S1_L003_R1_001.fastq.gz,AEG588A1_S1_L003_R2_001.fastq.gz +CONTROL_REP1,AEG588A1_S1_L004_R1_001.fastq.gz,AEG588A1_S1_L004_R2_001.fastq.gz +``` + +### Full samplesheet + +The pipeline will auto-detect whether a sample is single- or paired-end using the information provided in the samplesheet. The samplesheet can have as many columns as you desire, however, there is a strict requirement for the first 3 columns to match those defined in the table below. + +A final samplesheet file consisting of both single- and paired-end data may look something like the one below. This is for 6 samples, where `TREATMENT_REP3` has been sequenced twice. + +```console +sample,fastq_1,fastq_2 +CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz +CONTROL_REP2,AEG588A2_S2_L002_R1_001.fastq.gz,AEG588A2_S2_L002_R2_001.fastq.gz +CONTROL_REP3,AEG588A3_S3_L002_R1_001.fastq.gz,AEG588A3_S3_L002_R2_001.fastq.gz +TREATMENT_REP1,AEG588A4_S4_L003_R1_001.fastq.gz, +TREATMENT_REP2,AEG588A5_S5_L003_R1_001.fastq.gz, +TREATMENT_REP3,AEG588A6_S6_L003_R1_001.fastq.gz, +TREATMENT_REP3,AEG588A6_S6_L004_R1_001.fastq.gz, +``` + +| Column | Description | +| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `sample` | Custom sample name. This entry will be identical for multiple sequencing libraries/runs from the same sample. Spaces in sample names are automatically converted to underscores (`_`). | +| `fastq_1` | Full path to FastQ file for Illumina short reads 1. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". | +| `fastq_2` | Full path to FastQ file for Illumina short reads 2. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". | + +An [example samplesheet](../assets/samplesheet.csv) has been provided with the pipeline. + +## Running the pipeline + +The typical command for running the pipeline is as follows: + +```bash +nextflow run nf-core/oncoanalyser --input samplesheet.csv --outdir --genome GRCh37 -profile docker +``` + +This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. + +Note that the pipeline will create the following files in your working directory: + +```bash +work # Directory containing the nextflow working files + # Finished results in specified location (defined with --outdir) +.nextflow_log # Log file from Nextflow +# Other nextflow hidden files, eg. history of pipeline runs and old logs. +``` + +### Updating the pipeline + +When you run the above command, Nextflow automatically pulls the pipeline code from GitHub and stores it as a cached version. When running the pipeline after this, it will always use the cached version if available - even if the pipeline has been updated since. To make sure that you're running the latest version of the pipeline, make sure that you regularly update the cached version of the pipeline: + +```bash +nextflow pull nf-core/oncoanalyser +``` + +### Reproducibility + +It is a good idea to specify a pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. + +First, go to the [nf-core/oncoanalyser releases page](https://github.com/nf-core/oncoanalyser/releases) and find the latest version number - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. + +This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. + +## Core Nextflow arguments + +> **NB:** These options are part of Nextflow and use a _single_ hyphen (pipeline parameters use a double-hyphen). + +### `-profile` + +Use this parameter to choose a configuration profile. Profiles can give configuration presets for different compute environments. + +Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Conda) - see below. When using Biocontainers, most of these software packaging methods pull Docker containers from quay.io e.g [FastQC](https://quay.io/repository/biocontainers/fastqc) except for Singularity which directly downloads Singularity images via https hosted by the [Galaxy project](https://depot.galaxyproject.org/singularity/) and Conda which downloads and installs software locally from [Bioconda](https://bioconda.github.io/). + +> We highly recommend the use of Docker or Singularity containers for full pipeline reproducibility, however when this is not possible, Conda is also supported. + +The pipeline also dynamically loads configurations from [https://github.com/nf-core/configs](https://github.com/nf-core/configs) when it runs, making multiple config profiles for various institutional clusters available at run time. For more information and to see if your system is available in these configs please see the [nf-core/configs documentation](https://github.com/nf-core/configs#documentation). + +Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! +They are loaded in sequence, so later profiles can overwrite earlier profiles. + +If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended. + +- `docker` + - A generic configuration profile to be used with [Docker](https://docker.com/) +- `singularity` + - A generic configuration profile to be used with [Singularity](https://sylabs.io/docs/) +- `podman` + - A generic configuration profile to be used with [Podman](https://podman.io/) +- `shifter` + - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) +- `charliecloud` + - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) +- `conda` + - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter or Charliecloud. +- `test` + - A profile with a complete configuration for automated testing + - Includes links to test data so needs no other parameters + +### `-resume` + +Specify this when restarting a pipeline. Nextflow will use cached results from any pipeline steps where the inputs are the same, continuing from where it got to previously. For input to be considered the same, not only the names must be identical but the files' contents as well. For more info about this parameter, see [this blog post](https://www.nextflow.io/blog/2019/demystifying-nextflow-resume.html). + +You can also supply a run name to resume a specific run: `-resume [run-name]`. Use the `nextflow log` command to show previous run names. + +### `-c` + +Specify the path to a specific config file (this is a core Nextflow command). See the [nf-core website documentation](https://nf-co.re/usage/configuration) for more information. + +## Custom configuration + +### Resource requests + +Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the steps in the pipeline, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher requests (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. + +For example, if the nf-core/rnaseq pipeline is failing after multiple re-submissions of the `STAR_ALIGN` process due to an exit code of `137` this would indicate that there is an out of memory issue: + +```console +[62/149eb0] NOTE: Process `NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN (WT_REP1)` terminated with an error exit status (137) -- Execution is retried (1) +Error executing process > 'NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN (WT_REP1)' + +Caused by: + Process `NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN (WT_REP1)` terminated with an error exit status (137) + +Command executed: + STAR \ + --genomeDir star \ + --readFilesIn WT_REP1_trimmed.fq.gz \ + --runThreadN 2 \ + --outFileNamePrefix WT_REP1. \ + + +Command exit status: + 137 + +Command output: + (empty) + +Command error: + .command.sh: line 9: 30 Killed STAR --genomeDir star --readFilesIn WT_REP1_trimmed.fq.gz --runThreadN 2 --outFileNamePrefix WT_REP1. +Work dir: + /home/pipelinetest/work/9d/172ca5881234073e8d76f2a19c88fb + +Tip: you can replicate the issue by changing to the process work dir and entering the command `bash .command.run` +``` + +To bypass this error you would need to find exactly which resources are set by the `STAR_ALIGN` process. The quickest way is to search for `process STAR_ALIGN` in the [nf-core/rnaseq Github repo](https://github.com/nf-core/rnaseq/search?q=process+STAR_ALIGN). +We have standardised the structure of Nextflow DSL2 pipelines such that all module files will be present in the `modules/` directory and so, based on the search results, the file we want is `modules/nf-core/software/star/align/main.nf`. +If you click on the link to that file you will notice that there is a `label` directive at the top of the module that is set to [`label process_high`](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/modules/nf-core/software/star/align/main.nf#L9). +The [Nextflow `label`](https://www.nextflow.io/docs/latest/process.html#label) directive allows us to organise workflow processes in separate groups which can be referenced in a configuration file to select and configure subset of processes having similar computing requirements. +The default values for the `process_high` label are set in the pipeline's [`base.config`](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L33-L37) which in this case is defined as 72GB. +Providing you haven't set any other standard nf-core parameters to **cap** the [maximum resources](https://nf-co.re/usage/configuration#max-resources) used by the pipeline then we can try and bypass the `STAR_ALIGN` process failure by creating a custom config file that sets at least 72GB of memory, in this case increased to 100GB. +The custom config below can then be provided to the pipeline via the [`-c`](#-c) parameter as highlighted in previous sections. + +```nextflow +process { + withName: 'NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN' { + memory = 100.GB + } +} +``` + +> **NB:** We specify the full process name i.e. `NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN` in the config file because this takes priority over the short name (`STAR_ALIGN`) and allows existing configuration using the full process name to be correctly overridden. +> +> If you get a warning suggesting that the process selector isn't recognised check that the process name has been specified correctly. + +### Updating containers + +The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. If for some reason you need to use a different version of a particular tool with the pipeline then you just need to identify the `process` name and override the Nextflow `container` definition for that process using the `withName` declaration. For example, in the [nf-core/viralrecon](https://nf-co.re/viralrecon) pipeline a tool called [Pangolin](https://github.com/cov-lineages/pangolin) has been used during the COVID-19 pandemic to assign lineages to SARS-CoV-2 genome sequenced samples. Given that the lineage assignments change quite frequently it doesn't make sense to re-release the nf-core/viralrecon everytime a new version of Pangolin has been released. However, you can override the default container used by the pipeline by creating a custom config file and passing it as a command-line argument via `-c custom.config`. + +1. Check the default version used by the pipeline in the module file for [Pangolin](https://github.com/nf-core/viralrecon/blob/a85d5969f9025409e3618d6c280ef15ce417df65/modules/nf-core/software/pangolin/main.nf#L14-L19) +2. Find the latest version of the Biocontainer available on [Quay.io](https://quay.io/repository/biocontainers/pangolin?tag=latest&tab=tags) +3. Create the custom config accordingly: + + - For Docker: + + ```nextflow + process { + withName: PANGOLIN { + container = 'quay.io/biocontainers/pangolin:3.0.5--pyhdfd78af_0' + } + } + ``` + + - For Singularity: + + ```nextflow + process { + withName: PANGOLIN { + container = 'https://depot.galaxyproject.org/singularity/pangolin:3.0.5--pyhdfd78af_0' + } + } + ``` + + - For Conda: + + ```nextflow + process { + withName: PANGOLIN { + conda = 'bioconda::pangolin=3.0.5' + } + } + ``` + +> **NB:** If you wish to periodically update individual tool-specific results (e.g. Pangolin) generated by the pipeline then you must ensure to keep the `work/` directory otherwise the `-resume` ability of the pipeline will be compromised and it will restart from scratch. + +### nf-core/configs + +In most cases, you will only need to create a custom config as a one-off but if you and others within your organisation are likely to be running nf-core pipelines regularly and need to use the same settings regularly it may be a good idea to request that your custom config file is uploaded to the `nf-core/configs` git repository. Before you do this please can you test that the config file works with your pipeline of choice using the `-c` parameter. You can then create a pull request to the `nf-core/configs` repository with the addition of your config file, associated documentation file (see examples in [`nf-core/configs/docs`](https://github.com/nf-core/configs/tree/master/docs)), and amending [`nfcore_custom.config`](https://github.com/nf-core/configs/blob/master/nfcore_custom.config) to include your custom profile. + +See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for more information about creating your own configuration files. + +If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack) on the [`#configs` channel](https://nfcore.slack.com/channels/configs). + +## Azure Resource Requests + +To be used with the `azurebatch` profile by specifying the `-profile azurebatch`. +We recommend providing a compute `params.vm_type` of `Standard_D16_v3` VMs by default but these options can be changed if required. + +Note that the choice of VM size depends on your quota and the overall workload during the analysis. +For a thorough list, please refer the [Azure Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/sizes). + +## Running in the background + +Nextflow handles job submissions and supervises the running jobs. The Nextflow process must run until the pipeline is finished. + +The Nextflow `-bg` flag launches Nextflow in the background, detached from your terminal so that the workflow does not stop if you log out of your session. The logs are saved to a file. + +Alternatively, you can use `screen` / `tmux` or similar tool to create a detached session which you can log back into at a later time. +Some HPC setups also allow you to run nextflow within a cluster job submitted your job scheduler (from where it submits more jobs). + +## Nextflow memory requirements + +In some cases, the Nextflow Java virtual machines can start to request a large amount of memory. +We recommend adding the following line to your environment to limit this (typically in `~/.bashrc` or `~./bash_profile`): + +```bash +NXF_OPTS='-Xms1g -Xmx4g' +``` diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy new file mode 100755 index 00000000..b3d092f8 --- /dev/null +++ b/lib/NfcoreSchema.groovy @@ -0,0 +1,529 @@ +// +// This file holds several functions used to perform JSON parameter validation, help and summary rendering for the nf-core pipeline template. +// + +import org.everit.json.schema.Schema +import org.everit.json.schema.loader.SchemaLoader +import org.everit.json.schema.ValidationException +import org.json.JSONObject +import org.json.JSONTokener +import org.json.JSONArray +import groovy.json.JsonSlurper +import groovy.json.JsonBuilder + +class NfcoreSchema { + + // + // Resolve Schema path relative to main workflow directory + // + public static String getSchemaPath(workflow, schema_filename='nextflow_schema.json') { + return "${workflow.projectDir}/${schema_filename}" + } + + // + // Function to loop over all parameters defined in schema and check + // whether the given parameters adhere to the specifications + // + /* groovylint-disable-next-line UnusedPrivateMethodParameter */ + public static void validateParameters(workflow, params, log, schema_filename='nextflow_schema.json') { + def has_error = false + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Check for nextflow core params and unexpected params + def json = new File(getSchemaPath(workflow, schema_filename=schema_filename)).text + def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions') + def nf_params = [ + // Options for base `nextflow` command + 'bg', + 'c', + 'C', + 'config', + 'd', + 'D', + 'dockerize', + 'h', + 'log', + 'q', + 'quiet', + 'syslog', + 'v', + 'version', + + // Options for `nextflow run` command + 'ansi', + 'ansi-log', + 'bg', + 'bucket-dir', + 'c', + 'cache', + 'config', + 'dsl2', + 'dump-channels', + 'dump-hashes', + 'E', + 'entry', + 'latest', + 'lib', + 'main-script', + 'N', + 'name', + 'offline', + 'params-file', + 'pi', + 'plugins', + 'poll-interval', + 'pool-size', + 'profile', + 'ps', + 'qs', + 'queue-size', + 'r', + 'resume', + 'revision', + 'stdin', + 'stub', + 'stub-run', + 'test', + 'w', + 'with-charliecloud', + 'with-conda', + 'with-dag', + 'with-docker', + 'with-mpi', + 'with-notification', + 'with-podman', + 'with-report', + 'with-singularity', + 'with-timeline', + 'with-tower', + 'with-trace', + 'with-weblog', + 'without-docker', + 'without-podman', + 'work-dir' + ] + def unexpectedParams = [] + + // Collect expected parameters from the schema + def expectedParams = [] + def enums = [:] + for (group in schemaParams) { + for (p in group.value['properties']) { + expectedParams.push(p.key) + if (group.value['properties'][p.key].containsKey('enum')) { + enums[p.key] = group.value['properties'][p.key]['enum'] + } + } + } + + for (specifiedParam in params.keySet()) { + // nextflow params + if (nf_params.contains(specifiedParam)) { + log.error "ERROR: You used a core Nextflow option with two hyphens: '--${specifiedParam}'. Please resubmit with '-${specifiedParam}'" + has_error = true + } + // unexpected params + def params_ignore = params.schema_ignore_params.split(',') + 'schema_ignore_params' + def expectedParamsLowerCase = expectedParams.collect{ it.replace("-", "").toLowerCase() } + def specifiedParamLowerCase = specifiedParam.replace("-", "").toLowerCase() + def isCamelCaseBug = (specifiedParam.contains("-") && !expectedParams.contains(specifiedParam) && expectedParamsLowerCase.contains(specifiedParamLowerCase)) + if (!expectedParams.contains(specifiedParam) && !params_ignore.contains(specifiedParam) && !isCamelCaseBug) { + // Temporarily remove camelCase/camel-case params #1035 + def unexpectedParamsLowerCase = unexpectedParams.collect{ it.replace("-", "").toLowerCase()} + if (!unexpectedParamsLowerCase.contains(specifiedParamLowerCase)){ + unexpectedParams.push(specifiedParam) + } + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + // Validate parameters against the schema + InputStream input_stream = new File(getSchemaPath(workflow, schema_filename=schema_filename)).newInputStream() + JSONObject raw_schema = new JSONObject(new JSONTokener(input_stream)) + + // Remove anything that's in params.schema_ignore_params + raw_schema = removeIgnoredParams(raw_schema, params) + + Schema schema = SchemaLoader.load(raw_schema) + + // Clean the parameters + def cleanedParams = cleanParameters(params) + + // Convert to JSONObject + def jsonParams = new JsonBuilder(cleanedParams) + JSONObject params_json = new JSONObject(jsonParams.toString()) + + // Validate + try { + schema.validate(params_json) + } catch (ValidationException e) { + println '' + log.error 'ERROR: Validation of pipeline parameters failed!' + JSONObject exceptionJSON = e.toJSON() + printExceptions(exceptionJSON, params_json, log, enums) + println '' + has_error = true + } + + // Check for unexpected parameters + if (unexpectedParams.size() > 0) { + Map colors = NfcoreTemplate.logColours(params.monochrome_logs) + println '' + def warn_msg = 'Found unexpected parameters:' + for (unexpectedParam in unexpectedParams) { + warn_msg = warn_msg + "\n* --${unexpectedParam}: ${params[unexpectedParam].toString()}" + } + log.warn warn_msg + log.info "- ${colors.dim}Ignore this warning: params.schema_ignore_params = \"${unexpectedParams.join(',')}\" ${colors.reset}" + println '' + } + + if (has_error) { + System.exit(1) + } + } + + // + // Beautify parameters for --help + // + public static String paramsHelp(workflow, params, command, schema_filename='nextflow_schema.json') { + Map colors = NfcoreTemplate.logColours(params.monochrome_logs) + Integer num_hidden = 0 + String output = '' + output += 'Typical pipeline command:\n\n' + output += " ${colors.cyan}${command}${colors.reset}\n\n" + Map params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) + Integer max_chars = paramsMaxChars(params_map) + 1 + Integer desc_indent = max_chars + 14 + Integer dec_linewidth = 160 - desc_indent + for (group in params_map.keySet()) { + Integer num_params = 0 + String group_output = colors.underlined + colors.bold + group + colors.reset + '\n' + def group_params = params_map.get(group) // This gets the parameters of that particular group + for (param in group_params.keySet()) { + if (group_params.get(param).hidden && !params.show_hidden_params) { + num_hidden += 1 + continue; + } + def type = '[' + group_params.get(param).type + ']' + def description = group_params.get(param).description + def defaultValue = group_params.get(param).default != null ? " [default: " + group_params.get(param).default.toString() + "]" : '' + def description_default = description + colors.dim + defaultValue + colors.reset + // Wrap long description texts + // Loosely based on https://dzone.com/articles/groovy-plain-text-word-wrap + if (description_default.length() > dec_linewidth){ + List olines = [] + String oline = "" // " " * indent + description_default.split(" ").each() { wrd -> + if ((oline.size() + wrd.size()) <= dec_linewidth) { + oline += wrd + " " + } else { + olines += oline + oline = wrd + " " + } + } + olines += oline + description_default = olines.join("\n" + " " * desc_indent) + } + group_output += " --" + param.padRight(max_chars) + colors.dim + type.padRight(10) + colors.reset + description_default + '\n' + num_params += 1 + } + group_output += '\n' + if (num_params > 0){ + output += group_output + } + } + if (num_hidden > 0){ + output += colors.dim + "!! Hiding $num_hidden params, use --show_hidden_params to show them !!\n" + colors.reset + } + output += NfcoreTemplate.dashedLine(params.monochrome_logs) + return output + } + + // + // Groovy Map summarising parameters/workflow options used by the pipeline + // + public static LinkedHashMap paramsSummaryMap(workflow, params, schema_filename='nextflow_schema.json') { + // Get a selection of core Nextflow workflow options + def Map workflow_summary = [:] + if (workflow.revision) { + workflow_summary['revision'] = workflow.revision + } + workflow_summary['runName'] = workflow.runName + if (workflow.containerEngine) { + workflow_summary['containerEngine'] = workflow.containerEngine + } + if (workflow.container) { + workflow_summary['container'] = workflow.container + } + workflow_summary['launchDir'] = workflow.launchDir + workflow_summary['workDir'] = workflow.workDir + workflow_summary['projectDir'] = workflow.projectDir + workflow_summary['userName'] = workflow.userName + workflow_summary['profile'] = workflow.profile + workflow_summary['configFiles'] = workflow.configFiles.join(', ') + + // Get pipeline parameters defined in JSON Schema + def Map params_summary = [:] + def params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) + for (group in params_map.keySet()) { + def sub_params = new LinkedHashMap() + def group_params = params_map.get(group) // This gets the parameters of that particular group + for (param in group_params.keySet()) { + if (params.containsKey(param)) { + def params_value = params.get(param) + def schema_value = group_params.get(param).default + def param_type = group_params.get(param).type + if (schema_value != null) { + if (param_type == 'string') { + if (schema_value.contains('$projectDir') || schema_value.contains('${projectDir}')) { + def sub_string = schema_value.replace('\$projectDir', '') + sub_string = sub_string.replace('\${projectDir}', '') + if (params_value.contains(sub_string)) { + schema_value = params_value + } + } + if (schema_value.contains('$params.outdir') || schema_value.contains('${params.outdir}')) { + def sub_string = schema_value.replace('\$params.outdir', '') + sub_string = sub_string.replace('\${params.outdir}', '') + if ("${params.outdir}${sub_string}" == params_value) { + schema_value = params_value + } + } + } + } + + // We have a default in the schema, and this isn't it + if (schema_value != null && params_value != schema_value) { + sub_params.put(param, params_value) + } + // No default in the schema, and this isn't empty + else if (schema_value == null && params_value != "" && params_value != null && params_value != false) { + sub_params.put(param, params_value) + } + } + } + params_summary.put(group, sub_params) + } + return [ 'Core Nextflow options' : workflow_summary ] << params_summary + } + + // + // Beautify parameters for summary and return as string + // + public static String paramsSummaryLog(workflow, params) { + Map colors = NfcoreTemplate.logColours(params.monochrome_logs) + String output = '' + def params_map = paramsSummaryMap(workflow, params) + def max_chars = paramsMaxChars(params_map) + for (group in params_map.keySet()) { + def group_params = params_map.get(group) // This gets the parameters of that particular group + if (group_params) { + output += colors.bold + group + colors.reset + '\n' + for (param in group_params.keySet()) { + output += " " + colors.blue + param.padRight(max_chars) + ": " + colors.green + group_params.get(param) + colors.reset + '\n' + } + output += '\n' + } + } + output += "!! Only displaying parameters that differ from the pipeline defaults !!\n" + output += NfcoreTemplate.dashedLine(params.monochrome_logs) + return output + } + + // + // Loop over nested exceptions and print the causingException + // + private static void printExceptions(ex_json, params_json, log, enums, limit=5) { + def causingExceptions = ex_json['causingExceptions'] + if (causingExceptions.length() == 0) { + def m = ex_json['message'] =~ /required key \[([^\]]+)\] not found/ + // Missing required param + if (m.matches()) { + log.error "* Missing required parameter: --${m[0][1]}" + } + // Other base-level error + else if (ex_json['pointerToViolation'] == '#') { + log.error "* ${ex_json['message']}" + } + // Error with specific param + else { + def param = ex_json['pointerToViolation'] - ~/^#\// + def param_val = params_json[param].toString() + if (enums.containsKey(param)) { + def error_msg = "* --${param}: '${param_val}' is not a valid choice (Available choices" + if (enums[param].size() > limit) { + log.error "${error_msg} (${limit} of ${enums[param].size()}): ${enums[param][0..limit-1].join(', ')}, ... )" + } else { + log.error "${error_msg}: ${enums[param].join(', ')})" + } + } else { + log.error "* --${param}: ${ex_json['message']} (${param_val})" + } + } + } + for (ex in causingExceptions) { + printExceptions(ex, params_json, log, enums) + } + } + + // + // Remove an element from a JSONArray + // + private static JSONArray removeElement(json_array, element) { + def list = [] + int len = json_array.length() + for (int i=0;i + if(raw_schema.keySet().contains('definitions')){ + raw_schema.definitions.each { definition -> + for (key in definition.keySet()){ + if (definition[key].get("properties").keySet().contains(ignore_param)){ + // Remove the param to ignore + definition[key].get("properties").remove(ignore_param) + // If the param was required, change this + if (definition[key].has("required")) { + def cleaned_required = removeElement(definition[key].required, ignore_param) + definition[key].put("required", cleaned_required) + } + } + } + } + } + if(raw_schema.keySet().contains('properties') && raw_schema.get('properties').keySet().contains(ignore_param)) { + raw_schema.get("properties").remove(ignore_param) + } + if(raw_schema.keySet().contains('required') && raw_schema.required.contains(ignore_param)) { + def cleaned_required = removeElement(raw_schema.required, ignore_param) + raw_schema.put("required", cleaned_required) + } + } + return raw_schema + } + + // + // Clean and check parameters relative to Nextflow native classes + // + private static Map cleanParameters(params) { + def new_params = params.getClass().newInstance(params) + for (p in params) { + // remove anything evaluating to false + if (!p['value']) { + new_params.remove(p.key) + } + // Cast MemoryUnit to String + if (p['value'].getClass() == nextflow.util.MemoryUnit) { + new_params.replace(p.key, p['value'].toString()) + } + // Cast Duration to String + if (p['value'].getClass() == nextflow.util.Duration) { + new_params.replace(p.key, p['value'].toString().replaceFirst(/d(?!\S)/, "day")) + } + // Cast LinkedHashMap to String + if (p['value'].getClass() == LinkedHashMap) { + new_params.replace(p.key, p['value'].toString()) + } + } + return new_params + } + + // + // This function tries to read a JSON params file + // + private static LinkedHashMap paramsLoad(String json_schema) { + def params_map = new LinkedHashMap() + try { + params_map = paramsRead(json_schema) + } catch (Exception e) { + println "Could not read parameters settings from JSON. $e" + params_map = new LinkedHashMap() + } + return params_map + } + + // + // Method to actually read in JSON file using Groovy. + // Group (as Key), values are all parameters + // - Parameter1 as Key, Description as Value + // - Parameter2 as Key, Description as Value + // .... + // Group + // - + private static LinkedHashMap paramsRead(String json_schema) throws Exception { + def json = new File(json_schema).text + def Map schema_definitions = (Map) new JsonSlurper().parseText(json).get('definitions') + def Map schema_properties = (Map) new JsonSlurper().parseText(json).get('properties') + /* Tree looks like this in nf-core schema + * definitions <- this is what the first get('definitions') gets us + group 1 + title + description + properties + parameter 1 + type + description + parameter 2 + type + description + group 2 + title + description + properties + parameter 1 + type + description + * properties <- parameters can also be ungrouped, outside of definitions + parameter 1 + type + description + */ + + // Grouped params + def params_map = new LinkedHashMap() + schema_definitions.each { key, val -> + def Map group = schema_definitions."$key".properties // Gets the property object of the group + def title = schema_definitions."$key".title + def sub_params = new LinkedHashMap() + group.each { innerkey, value -> + sub_params.put(innerkey, value) + } + params_map.put(title, sub_params) + } + + // Ungrouped params + def ungrouped_params = new LinkedHashMap() + schema_properties.each { innerkey, value -> + ungrouped_params.put(innerkey, value) + } + params_map.put("Other parameters", ungrouped_params) + + return params_map + } + + // + // Get maximum number of characters across all parameter names + // + private static Integer paramsMaxChars(params_map) { + Integer max_chars = 0 + for (group in params_map.keySet()) { + def group_params = params_map.get(group) // This gets the parameters of that particular group + for (param in group_params.keySet()) { + if (param.size() > max_chars) { + max_chars = param.size() + } + } + } + return max_chars + } +} diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy new file mode 100755 index 00000000..27feb009 --- /dev/null +++ b/lib/NfcoreTemplate.groovy @@ -0,0 +1,313 @@ +// +// This file holds several functions used within the nf-core pipeline template. +// + +import org.yaml.snakeyaml.Yaml + +class NfcoreTemplate { + + // + // Check AWS Batch related parameters have been specified correctly + // + public static void awsBatch(workflow, params) { + if (workflow.profile.contains('awsbatch')) { + // Check params.awsqueue and params.awsregion have been set if running on AWSBatch + assert (params.awsqueue && params.awsregion) : "Specify correct --awsqueue and --awsregion parameters on AWSBatch!" + // Check outdir paths to be S3 buckets if running on AWSBatch + assert params.outdir.startsWith('s3:') : "Outdir not on S3 - specify S3 Bucket to run on AWSBatch!" + } + } + + // + // Warn if a -profile or Nextflow config has not been provided to run the pipeline + // + public static void checkConfigProvided(workflow, log) { + if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { + log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + + "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + + " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + + " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + + " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + + "Please refer to the quick start section and usage docs for the pipeline.\n " + } + } + + // + // Construct and send completion email + // + public static void email(workflow, params, summary_params, projectDir, log, multiqc_report=[]) { + + // Set up the e-mail variables + def subject = "[$workflow.manifest.name] Successful: $workflow.runName" + if (!workflow.success) { + subject = "[$workflow.manifest.name] FAILED: $workflow.runName" + } + + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['Date Started'] = workflow.start + misc_fields['Date Completed'] = workflow.complete + misc_fields['Pipeline script file path'] = workflow.scriptFile + misc_fields['Pipeline script hash ID'] = workflow.scriptId + if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository + if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId + if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision + misc_fields['Nextflow Version'] = workflow.nextflow.version + misc_fields['Nextflow Build'] = workflow.nextflow.build + misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp + + def email_fields = [:] + email_fields['version'] = workflow.manifest.version + email_fields['runName'] = workflow.runName + email_fields['success'] = workflow.success + email_fields['dateComplete'] = workflow.complete + email_fields['duration'] = workflow.duration + email_fields['exitStatus'] = workflow.exitStatus + email_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + email_fields['errorReport'] = (workflow.errorReport ?: 'None') + email_fields['commandLine'] = workflow.commandLine + email_fields['projectDir'] = workflow.projectDir + email_fields['summary'] = summary << misc_fields + + // On success try attach the multiqc report + def mqc_report = null + try { + if (workflow.success) { + mqc_report = multiqc_report.getVal() + if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { + if (mqc_report.size() > 1) { + log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" + } + mqc_report = mqc_report[0] + } + } + } catch (all) { + if (multiqc_report) { + log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" + } + } + + // Check if we are only sending emails on failure + def email_address = params.email + if (!params.email && params.email_on_fail && !workflow.success) { + email_address = params.email_on_fail + } + + // Render the TXT template + def engine = new groovy.text.GStringTemplateEngine() + def tf = new File("$projectDir/assets/email_template.txt") + def txt_template = engine.createTemplate(tf).make(email_fields) + def email_txt = txt_template.toString() + + // Render the HTML template + def hf = new File("$projectDir/assets/email_template.html") + def html_template = engine.createTemplate(hf).make(email_fields) + def email_html = html_template.toString() + + // Render the sendmail template + def max_multiqc_email_size = params.max_multiqc_email_size as nextflow.util.MemoryUnit + def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] + def sf = new File("$projectDir/assets/sendmail_template.txt") + def sendmail_template = engine.createTemplate(sf).make(smail_fields) + def sendmail_html = sendmail_template.toString() + + // Send the HTML e-mail + Map colors = logColours(params.monochrome_logs) + if (email_address) { + try { + if (params.plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } + // Try to send HTML e-mail using sendmail + [ 'sendmail', '-t' ].execute() << sendmail_html + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" + } catch (all) { + // Catch failures and try with plaintext + def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] + if ( mqc_report.size() <= max_multiqc_email_size.toBytes() ) { + mail_cmd += [ '-A', mqc_report ] + } + mail_cmd.execute() << email_html + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" + } + } + + // Write summary e-mail HTML to a file + def output_d = new File("${params.outdir}/pipeline_info/") + if (!output_d.exists()) { + output_d.mkdirs() + } + def output_hf = new File(output_d, "pipeline_report.html") + output_hf.withWriter { w -> w << email_html } + def output_tf = new File(output_d, "pipeline_report.txt") + output_tf.withWriter { w -> w << email_txt } + } + + // + // Construct and send adaptive card + // https://adaptivecards.io + // + public static void adaptivecard(workflow, params, summary_params, projectDir, log) { + def hook_url = params.hook_url + + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['start'] = workflow.start + misc_fields['complete'] = workflow.complete + misc_fields['scriptfile'] = workflow.scriptFile + misc_fields['scriptid'] = workflow.scriptId + if (workflow.repository) misc_fields['repository'] = workflow.repository + if (workflow.commitId) misc_fields['commitid'] = workflow.commitId + if (workflow.revision) misc_fields['revision'] = workflow.revision + misc_fields['nxf_version'] = workflow.nextflow.version + misc_fields['nxf_build'] = workflow.nextflow.build + misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp + + def msg_fields = [:] + msg_fields['version'] = workflow.manifest.version + msg_fields['runName'] = workflow.runName + msg_fields['success'] = workflow.success + msg_fields['dateComplete'] = workflow.complete + msg_fields['duration'] = workflow.duration + msg_fields['exitStatus'] = workflow.exitStatus + msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + msg_fields['errorReport'] = (workflow.errorReport ?: 'None') + msg_fields['commandLine'] = workflow.commandLine + msg_fields['projectDir'] = workflow.projectDir + msg_fields['summary'] = summary << misc_fields + + // Render the JSON template + def engine = new groovy.text.GStringTemplateEngine() + def hf = new File("$projectDir/assets/adaptivecard.json") + def json_template = engine.createTemplate(hf).make(msg_fields) + def json_message = json_template.toString() + + // POST + def post = new URL(hook_url).openConnection(); + post.setRequestMethod("POST") + post.setDoOutput(true) + post.setRequestProperty("Content-Type", "application/json") + post.getOutputStream().write(json_message.getBytes("UTF-8")); + def postRC = post.getResponseCode(); + if (! postRC.equals(200)) { + log.warn(post.getErrorStream().getText()); + } + } + + // + // Print pipeline summary on completion + // + public static void summary(workflow, params, log) { + Map colors = logColours(params.monochrome_logs) + if (workflow.success) { + if (workflow.stats.ignoredCount == 0) { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" + } else { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" + } + } else { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" + } + } + + // + // ANSII Colours used for terminal logging + // + public static Map logColours(Boolean monochrome_logs) { + Map colorcodes = [:] + + // Reset / Meta + colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" + colorcodes['bold'] = monochrome_logs ? '' : "\033[1m" + colorcodes['dim'] = monochrome_logs ? '' : "\033[2m" + colorcodes['underlined'] = monochrome_logs ? '' : "\033[4m" + colorcodes['blink'] = monochrome_logs ? '' : "\033[5m" + colorcodes['reverse'] = monochrome_logs ? '' : "\033[7m" + colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" + + // Regular Colors + colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" + colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" + colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" + colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" + colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" + colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" + colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" + colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" + + // Bold + colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" + colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" + colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" + colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" + colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" + colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" + colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" + colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" + + // Underline + colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" + colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" + colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" + colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" + colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" + colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" + colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" + colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" + + // High Intensity + colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" + colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" + colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" + colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" + colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" + colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" + colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" + colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" + + // Bold High Intensity + colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" + colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" + colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" + colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" + colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" + colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" + colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" + colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" + + return colorcodes + } + + // + // Does what is says on the tin + // + public static String dashedLine(monochrome_logs) { + Map colors = logColours(monochrome_logs) + return "-${colors.dim}----------------------------------------------------${colors.reset}-" + } + + // + // nf-core logo + // + public static String logo(workflow, monochrome_logs) { + Map colors = logColours(monochrome_logs) + String.format( + """\n + ${dashedLine(monochrome_logs)} + ${colors.green},--.${colors.black}/${colors.green},-.${colors.reset} + ${colors.blue} ___ __ __ __ ___ ${colors.green}/,-._.--~\'${colors.reset} + ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} + ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} + ${colors.green}`._,._,\'${colors.reset} + ${colors.purple} ${workflow.manifest.name} v${workflow.manifest.version}${colors.reset} + ${dashedLine(monochrome_logs)} + """.stripIndent() + ) + } +} diff --git a/lib/Utils.groovy b/lib/Utils.groovy new file mode 100644 index 00000000..8d030f4e --- /dev/null +++ b/lib/Utils.groovy @@ -0,0 +1,47 @@ +// +// This file holds several Groovy functions that could be useful for any Nextflow pipeline +// + +import org.yaml.snakeyaml.Yaml + +class Utils { + + // + // When running with -profile conda, warn if channels have not been set-up appropriately + // + public static void checkCondaChannels(log) { + Yaml parser = new Yaml() + def channels = [] + try { + def config = parser.load("conda config --show channels".execute().text) + channels = config.channels + } catch(NullPointerException | IOException e) { + log.warn "Could not verify conda channel configuration." + return + } + + // Check that all channels are present + // This channel list is ordered by required channel priority. + def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] + def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean + + // Check that they are in the right order + def channel_priority_violation = false + def n = required_channels_in_order.size() + for (int i = 0; i < n - 1; i++) { + channel_priority_violation |= !(channels.indexOf(required_channels_in_order[i]) < channels.indexOf(required_channels_in_order[i+1])) + } + + if (channels_missing | channel_priority_violation) { + log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " There is a problem with your Conda configuration!\n\n" + + " You will need to set-up the conda-forge and bioconda channels correctly.\n" + + " Please refer to https://bioconda.github.io/\n" + + " The observed channel order is \n" + + " ${channels}\n" + + " but the following channel order is required:\n" + + " ${required_channels_in_order}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + } + } +} diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy new file mode 100755 index 00000000..07f95372 --- /dev/null +++ b/lib/WorkflowMain.groovy @@ -0,0 +1,93 @@ +// +// This file holds several functions specific to the main.nf workflow in the nf-core/oncoanalyser pipeline +// + +class WorkflowMain { + + // + // Citation string for pipeline + // + public static String citation(workflow) { + return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + + // TODO nf-core: Add Zenodo DOI for pipeline after first release + //"* The pipeline\n" + + //" https://doi.org/10.5281/zenodo.XXXXXXX\n\n" + + "* The nf-core framework\n" + + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + + "* Software dependencies\n" + + " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" + } + + // + // Print help to screen if required + // + public static String help(workflow, params, log) { + def command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh37 -profile docker" + def help_string = '' + help_string += NfcoreTemplate.logo(workflow, params.monochrome_logs) + help_string += NfcoreSchema.paramsHelp(workflow, params, command) + help_string += '\n' + citation(workflow) + '\n' + help_string += NfcoreTemplate.dashedLine(params.monochrome_logs) + return help_string + } + + // + // Print parameter summary log to screen + // + public static String paramsSummaryLog(workflow, params, log) { + def summary_log = '' + summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) + summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) + summary_log += '\n' + citation(workflow) + '\n' + summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) + return summary_log + } + + // + // Validate parameters and print summary to screen + // + public static void initialise(workflow, params, log) { + // Print help to screen if required + if (params.help) { + log.info help(workflow, params, log) + System.exit(0) + } + + // Validate workflow parameters via the JSON schema + if (params.validate_params) { + NfcoreSchema.validateParameters(workflow, params, log) + } + + // Print parameter summary log to screen + + log.info paramsSummaryLog(workflow, params, log) + + // Check that a -profile or Nextflow config has been provided to run the pipeline + NfcoreTemplate.checkConfigProvided(workflow, log) + + // Check that conda channels are set-up correctly + if (params.enable_conda) { + Utils.checkCondaChannels(log) + } + + // Check AWS batch settings + NfcoreTemplate.awsBatch(workflow, params) + + // Check input has been provided + if (!params.input) { + log.error "Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'" + System.exit(1) + } + } + // + // 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)) { + return params.genomes[ params.genome ][ attribute ] + } + } + return null + } +} diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy new file mode 100755 index 00000000..ae6958ad --- /dev/null +++ b/lib/WorkflowOncoanalyser.groovy @@ -0,0 +1,77 @@ +// +// This file holds several functions specific to the workflow/oncoanalyser.nf in the nf-core/oncoanalyser pipeline +// + +import groovy.text.SimpleTemplateEngine + +class WorkflowOncoanalyser { + + // + // Check and validate parameters + // + public static void initialise(params, log) { + genomeExistsError(params, log) + + + if (!params.fasta) { + log.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." + System.exit(1) + } + } + + // + // Get workflow summary for MultiQC + // + public static String paramsSummaryMultiqc(workflow, summary) { + String summary_section = '' + for (group in summary.keySet()) { + def group_params = summary.get(group) // This gets the parameters of that particular group + if (group_params) { + summary_section += "

    $group

    \n" + summary_section += "
    \n" + } + } + + String yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" + yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" + yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" + yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" + yaml_file_text += "plot_type: 'html'\n" + yaml_file_text += "data: |\n" + yaml_file_text += "${summary_section}" + return yaml_file_text + } + + public static String methodsDescriptionText(run_workflow, mqc_methods_yaml) { + // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file + def meta = [:] + meta.workflow = run_workflow.toMap() + meta["manifest_map"] = run_workflow.manifest.toMap() + + meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" + meta["nodoi_text"] = meta.manifest_map.doi ? "": "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " + + def methods_text = mqc_methods_yaml.text + + def engine = new SimpleTemplateEngine() + def description_html = engine.createTemplate(methods_text).make(meta) + + return description_html + }// + // Exit pipeline if incorrect --genome key provided + // + private static void genomeExistsError(params, log) { + if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + + " Currently, the available genome keys are:\n" + + " ${params.genomes.keySet().join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + } +} diff --git a/lib/nfcore_external_java_deps.jar b/lib/nfcore_external_java_deps.jar new file mode 100644 index 0000000000000000000000000000000000000000..805c8bb5e4fd43a12a5891eea5a68788309629b0 GIT binary patch literal 2291171 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�tYW?&}i=k!VP!s3Fsl9>uU$+h>+D#gpmDc5f7BEy3^#*-?IO zHn3@wd7E!YZ1-fYplF}xqRgw#^f5k=)F~ysENJ>SCkzufdAZCGUaSfj=Cu?^HgRTy z{(kdh)H7N~{;X@U^`5a=fyHXI8j%-`*@$X;-r*NGD-OU_kqJz*(6JDY8HWu`cHst8 zrQ)JSm{=u!37tJ&M-k0x+8LW3Z9hiOWS9$?nAjyc>bK`cxVkfCJz|=)qiNup3xtZ^ zq3a#C5PFTxS!txrleVIiN>^uP^F)F>-$ddBU1ZCN7WlfiDYLV(#!I4sAi*{F?##;O zYm~FIoh^%9Q2Tp%q0Z?Bm?mwKH63lAJ@+#nG1|fah}-=n;WT4{7k%da!0lb*&UiAF zLheR+2gNRUTezIpal_`~MuwGV3|Xpi&+6Jwv%m+mvQSzU!DQ3RieQnS42Y&U;uF0$ zviotyupQgOPFsBIms&+yZ(kEYQPZv-|O5H@zMql09G3l0IiE3o`lpW)a%2DlpE zfSixyfng6TVAycLUSs(5DXm~c0E({|E#wnBdff^HUo74jpoWOki1CI@_c72SM-)kO zdYNuX)WS;Zv~Wha904q4jwOOB^Ar{|FgXD7aLo~BG~P*c@^B?{S?OAV-cU7vs+?-tt<$l!WxVzG_-3xr1GaF^N3{Te6h=JCxrm+lLj9D6)~&BOLHchuRCZ;{~@q!uc@5GuVsn_H^!A?q^4 zT4lbSJe?j&MxETi{2L;eD-^J2#Oym4&BT%Gd`~#A_G|YE+1A0`>Bv3W{u?&K7fiz! zPQw>a!xvJ+7gWiu8@v5FhYk*!EVloPvv-KHZR@smSC}ho+qP}nSYg|?ZQHhO+qR7r z#*6)*d&?{Do_luUWkzO<)GTGTUVCd_s}-h)1iA+wx`!CLhY-4l6xs(5+J~sD3mqC3 z0kr)$+N42`WBezH?5wP^uF4nOvdka(7+q_UI#;Zt3rN!1LQ*Gcp;t4dL=+Nv_ULk_ zZ3WtylxvE=*$*D|XeoV?3%rU~pCI0Ms!9<(dHf&Pn1j5vnjeU)VLo}fADa4I^ifUJ z*fkg?JQxz%;!3h{acf!``@Dx|*i=a0#57*ghE(PE`N00lYmX)M@@o4$BCJ`80!zKb zaY9iC#}puP$f$O23{HP(sCB&i_2xuTBIr;*(Zn>VWL>aXluujL#t1P4HQS_1s<`$#a9YglnliL4*EOW=7A4Wc;$~p8r_hfp!yLHCejqi0!x#D2Q z(nj%7&Dr(L^NW|-%%0a+`j7NXXR)1@Q#F^x{EWO}J`y67L*i$tg5@H4WYCvhq4uT> z%xiB}U;D_eGj@#!jzx^V;+BJ2M-cz=1aK8+xN>BkPB-Y3sQgq^xJrs!sWOpj z`30I5$Ou$D-}npCIDTu=fTO5&pXHItq^k9R^ASuuTOxVHFTcHdGMS{IrLvKeE*G`} zN7ONFP#=eFf0G}&-YWs8&y4EhKRS)pY0ZZl;@2-yKlFvFk&%V0@jp+u zANWG(zpJz;m7RZRuP^I*d?Ix`IfW)GF>%FFSczId<%N9WREczyKqONOr{u$Untwd@ zrQvfvNj+_c?XceS8953XUv_bKeRgwp8)$jTPG}@CP$bf%y1P84pR+us+e}zr5B{04 z-jd)1(TA1M>8HZz!L9VWV%~tevhsO9st3SL`}P@ z9U3Xl!%UxB)k7;oGbZdYTTJS#VsYy}ez|W5FIv{Qg@o2#QPyrUL6bOJ5a+6FOD=jukYAUc>3F$?3W-x7P}o- zaIIP6qq{gGv;!}Old!X;aJ6~)_8;)H&azVXEX0BsmUcmA7ES3AqeM{+qTSV`8O}>_ z8?fY71=KQHiehO|dARz;3NhFd*zt=<9fnCGc`rO|=MVS!e~y0 z=>q{c7b7Y>aszmB^b~pm10_C2i z(2BG?%B>iU*B`(sBp#5bdrvxSjZysZ-}a?<_j$90F}cG)({Z`p z?)618(0HC@jmEzxGG&J0_43`mbf~Q}xixa=>HlU_N27u4IGD=AG${NT$LSGiU)5Ip zHuCY~t%EuXX|9Z@?q%+m6l;5oa713V=HC(CC57$a6Prnzz~S$erlJp}IYMtg>;G9Y zGKLVJPq{ zHsIT^K{)ynNOGtcUcg3Q(@Kwt)F6qaV+|`GjQ-t-l(4^}&xD%rGPHrY-EWW%k_5S(yJHhIk0!dk#dN@u$BUEo0TV~{ zS8taba8BIjrkSh*;_cn`QY`B(dXZ&M+2m{I?LWn(?QaLgKftNbL)Kkg%IM1rB;=}^MGa=bVx*S)J^B{RJBs^M$W9*cWvK+ zH9U*xAt4+E;5@6(UqD`SKEm844blUk8o_&;9y71gYd0UQth8UB5467!y3r}R0btQjp+jp7WpuuWJ$6{b+lQyz_MGHb7<1;kVjp0DG>&ujrEg zS|!gZ1=&!kF7lV2o?TYmsv>5|F-bv&w%W$RC_@1PH7Zzr`JN-iWVFmtW=nfhjqdzO zMW(35Kavc^(9<^pe>0^nR1aMeE$$9PM19r{JqRwGL8X?$0Q_fl ztA0n-wbz#!Jq7(Oc4)zmUrEJ1V+*dOpf)Qd$eLx-WM-nuFM2hV!^ zN%(EA?+_G*P}Rsme5rL{>BLc5{DB=f`E9cH;uf?(+9R2e+F1PiFlv%}+lu?rD>zXw zu+qUtT3he<6s7%6F+-wj8k8+BFVTvtl%vt-r!!qoWq=CQlbo?3y{O}*#-#D#G8~T8 z!gv%-o)z+1Rzjd$Q9t2aXV|-9 zc)EX#9A-p?v-W4_BHm-4T}3mp zyXw3$-9C!|0@+9mH}i0g!Zx+bFS+0NGe)S9ut4on`f%t^^PMQ|LK^@Tzak68=5pjD z$ma3gz3>=h=@XO+l}L7HfRpgh4}tU=Y8Hwvo<3?dCVg6nJ~-?m5UR#u&3Rc_jS;`=`?+8Kjc>>xU4F`PU-z zKk}oZ692}jCn;MgZiv8n!$1!U(AeZPierZ)5;cRT7P^^16#-x&bjaiaXBNjYg*Z76 zjv^3FNTvN4NCPn}OgG9DUrAq40yHui3NMoHK3C)q|IWb_?!+o`8NvyJkd6Rb9OOErIpq+rVWg8mAYem$aw( zR6TS@7VYHM7kp1;mXfqmt7TFUiwY;~cNl-cl|IhOeYQ~SKM8my#nS$`0ZdV!K|pR- zoJu_#!9-q4sz_xR(WiDOPkLb>dmYSPBjnOhTsUS_DKS&hJdMHv6?92bB&l%Ssa!=N z%Z`jpLi9dL|1MB)$ib}9*_Q+zdjs&dYP%9_gzpJ@1lalYK+}23AtSoYvZLCi6@Z4h zmYRH`na!wQ(aDUxm_VdQ)Tp{F*y2Y17TtU@dNYANqdi%3ZCf5Wr#+9`K0_yHIw&K( zUDY$cutlNkV$6V)Wh&0j@|5hLE}E%(A+G^BH?(-?jJvjB5oyEyv(zZ!YhEWPm!Dp&7VXW>LI^03`C@gF@56P1#Ny zU_3H*p@huQ%O_<$Zq=tDy0_%!oC1SyOY23q-G>!O(tF>F1}v-R-ta($m5HINQNMCjhmak>_m${X@q*^`qonJFTvCh*uH7{lr%?ql- z76o_D0374>3M*J$l?k^{7Xx*aQKrGnaRJElk5qTCYY@%B`OWE95)~lo8jkDlM?D1b zc?{&hFuG(1aE$lJo!Kpc%M@oNn?E`DL~Fs98;Rs12cdHUvh6|JuZuIGBMQf!=egKy zSaQ~Q{QlDMIw800ZemY*@ezk6!6-!HO>jQw>W(zKCL13(?%TH`nx_%>H*gqP52X1Y zp1nEHuPOZ>;>WVy49pl7{1H!kJosDlGQ@vzgAB;2}ZxD5XTwy!#1^RpK$UOuaNeAKdig~RBzl-~;U?$ch2K2rvaBD_K z&P^6ahop^Y{7TX@B%ld8taQ}mgY)E$@(iQxuZE9{A7`)|klZ7hyXH}O-PoNaT(^ez3V9tTs+%Mdr5Q!wKts+2FXls=CFy-K8H~C%Y zkcQwP++<0M&FM1>61RTgYX!9_qIqa}jY)R)uXHT~bB>NOn+uIKW+`gQ`}VPfu=0t; zs{H2t^f^A4`%@!;Am3g&FoWtJVysIsa;-^oTVT4Hx8vhEu1V0`Ag70@zTeVVzn zq;cXK$WmHmZlB~Qv1546IQL9kk0Z?y%udlzLkuNew(PFA+;|m6?Feu)-R?ANXnW| zr^7Zk(_U3Z9hkyv1CA-Dg>_n2+Fv5kC7eh#JTn7ebNbP0JA^V|qUzz3mOX*lJ?FdHP}!7(!wCE?43- z%WE5ODV|wAAgKIuNV5(`ar$x^P%;XG10M6TH(@#eCj-_;N^$y#`Ve`E4!yD)PtuiD z{{)%;bvQE?{iiYbx+YJMn%X*+TXW2qWI`D5n&YsL-P|40TZ%KpDg2>*);RDD%M zbV2&25=BWC20%uFRg%N!pVy>Rg5qbw=!Mkpa}Y;SgT~ynEPS-?a$jl2X=-WGurjN_ zgCJzY=3FStnts$hf9#S5j*s=F=JkBoYPosqw7~WGba+<%6+;jYg~>texaTX>67bSr@RpmXR#E3Ounl6DV?Tf=b0T--GsV^jOZ>R_wTPo8-kvOq8` zR@$!)Z&Md=II-axVsjJjD$A#mfqssH*WskitmRFNrW61O>0h2l{sprHZVup;(;@F$ zE6LYQnF}T@%*u)6BR19jYN9uDC+)#f>nf?~;T2)=9_MvM1Av_EJ9lvj`+`(b_PbQZ zCI@~NNXA98Vxs*OsB54J&{8L5|4I==$^9(}F`UuR+`EJ|*F!Kk@4R?{*=ef`_&q&| zKYq+=!QE*H8l7mFSGKMl*aZVw(W*pJl~2{;UFU7PHLR{8q=s+RjMnRjPd;blm;SNOz`DR}4)< z&%hXv$}G+@0v^4(2L>(EL^}Y~S7-6z5;jq6^byKjBKrE@_)|BEzmv~m?a*`X?%E=0 zYbAp-Vrb`x_9@YI4=~RMT|?a2@~1_v0*@8FVC$`d)CZB#clOIeZw$2toLFwTcS7w2 zhowL84n!ltYiEk>YB+LDIbM-V6o+Nyg?S&Y$|H5@2o6*doil8NEQWBxx%*J)DGt~# zk!$s?$y9Dr4VVoUTOTqo2(Cw6K@S-ETT_wJ7LCYyUt^IebD5lU<-_JuO_e+nV|S2h zDatet(qjb#H@Py6$=}x?+x1m+)m5 z*caT=EB!_Bg{d&iG8ouO&v^haDHBAM?ia)Vs!-3!skX1Iah+loBx5B0+~3p3MJ4_? zQk2ZtOP9yrC?OX#nRMh0I-&fo2GcctV=9!hvWvg2XR6r<0UPsJlT?R9A4tXrI3l;O zmndeLdZspak@;;sy>!o{)!1xX@e3NIqGS0NEhP(_!3ji|2{&PT@B9UxfFg z&c=t5|Lx7h#5M^k zX;`dKtdeW6eK0LR=f7x;QnAECEOLd82~YucAMZ_gl*-X)Pq_z6K5atjf?=>Xi?$&i zXUVV3)%}{l2(pdv2H}z{naXE@H~B;|QIAy2>bfw;sG zPUeoh^r&^idX}e$&?HrFl;w-W8yT>{);pZPI6mi%)xNTmy3mzP_mi1l4Z^}2B)}4Y zfI<8O=jRD8$%T`{^(#oiGw#W(G^uTH4uSJ?^pHq1jB~Q*;7hy;wBvvg2xo&{XanLj z$lMSEx*)R?%5%d4rn=#%ziPpby52G+-S56+! zT^T%=B1_Q2=nsMv8w3K@PgV+35PK7HiX$>NxhiCpNs5g+IxH-4O{}yakr1?H8n(tJ zNVmF2!%#~WIaHu#k6jflj-&`FK~me;i`rLjm&k$TB8M@2Z&#VyLdp4hhZ9a(OW|K{ zSD7tdn8S>yhROfRMo~PVDbdWwsl;<7TVWUURnsoZVtTIff-J$1UP}!&gXb2tc3&iKvv~5*EOclX^~}Fr`jO^^?vK z?BB`LQB-k%Dkh-eLpsdTI5J2vid#IMPw;u2*HbwL zKVrfi5VNds1TWH_o;uGRvcUM;F*KZvJvTeClu)u1m$DR-v3BQt`lKu;jW9rN^%h+3 zNzR4UV6Eq$^9@D32reA-*Do*Ff9tvbxLE$Ou{WVLw=vYCbu_awqBStJx3RXNm2k2& z)3g3RkGLdNZCk_@1zWOjs;a z)@h(~{)Q08o03h4<(-e6EzTP<0}AsSbhh(noRT`*aeSMdeym$alPSrP!Fihv;WBi; zt|l0(zl6`8yXHReKG}5Waky@~*zs~YAn~<1U<80bg(lKQ8-hSZ8xEKEw?oD0d)8ud zPmCbdUJV`r=Azj}!sWr=6$g-oV7uyv%(UA#`}*SX;Tpi5X_pH>2_GAI*c^e?as{Am zzs2UE=#%`gTMkOOgTzgXQGGpNhH=Y^nMUsWFd#h6H9g?Jh}Vwkg;$?A#$y`DbC{9DpG!3z9Qi#Bpw4CQjbh1*5EYti2hE*OpeO^nX=An<^9ZyFc6;03wQgByS=dH z;+osg6vJg`=HJDgw*@_&+e6Ac@u6k8m4hJcBkNPzRMPcuyDi5#&;m%$eU2F|Oq7!s zIof?2i?g8LeO*{CrqMxOT6gLS6+pO26BJ?yD*HzbBgs=-P~K}V6-DN}y%N3q>Cv_& z5e-tpuAcl_H9y^u$cbSAl4&CjQ9i_Q6dwaC)XaWj03^600);k#U|=ke9#7I;Rq7_? zH)zL*uB_wgh5>xIsW9K%VfNvuygID7sPcTGh|z$}JWjH-`#JYt5JaVTqsiGbb#vSx zk1LJ&m>yfvXzcJ}v<|fE@xQ4c4fcf+8jC9)j%qNNjr~09=`@mYKLdV6Q8SAqp>aU0 z09yh2V5#LzD76gKumm8t7w8R}h$1%~6@)D;Y$bwp1Z)QX@Nx=>^^%dB=amHrd#C82 zqgMWq@J1S9_}C&gTF?q;7`nw^V&+VxG0~KK($O{78$2-2tFVDqTn(~P)8w+L0jNbOBc-s>xaParFtmXzH@Uu4V`%!y1I4>m9Lxq| zji_l?DlVp-ZE|9SdvN7CUtB~8?eIzwgpXE>^vaeB&*VYsHqVmtB4#73F}cn@`?>yy zn@xBX#U()xf}jfCj!XJP)2{!_q00XR0fZ?r?l!vT}t5xkZQSVKm zT+10u?qD1G;?(hCBT{B#e2SVDO9f-_=Z5OJOXzYvd6XKB)Mcgc>L;3!jEk>L^5V(_ zPK4nqsBy!HPLDW;OKL6x$uZ0;VK2XM??(zlD_V!Asv};&aUbNxdXY?wH3p%dB7W}H zfYza@P2e7KLaaD&cXTk}Y=Hv=!FklX2C*jtD?UgVLV;wRN>m z(!HIYE#eTwo<1(Ywg3*$-5Zr6!A-C4LG0KVF^cT#BU1w{-u#FfzD4_FGZOj6qw;A~ zLGn6TT>;P)r9i+ac%zrS`d*X=oDGItmVM-ZJjMUOA!JS8=qzw{rd$S6xr&l{~>|d|S5@rQJf@jtBG`L1Y z>;lh<{WWQ-OM;7-r{ii=;1hnzv`v!86x2(e?;dqhQyzY-&N@t(TLoneP6jYUSVV^`|-++&VLv#sg6NQFCA=bxp42`&Qj zz+wv^U{SuzOQ>>+UN}h&e}EX(RJegK4Hjx=vOp`kC%*ysVzVnIX+Q8TPw{!XN(FE? z!ShlNw-aSs&fsfx1?LRc=QU2?@Sh9goRHwZ9j1HnC;3K&MWr7D$R9BT9I6H~U_CYm zpVZZwllC2BpTeI}z^`0)F*3Kwk$gZ^Wf!O`$q{*k#bH%hr1^=g8oI{6EZBZpxYEo| zqsP0z=jm4sWZ0=g;eKX`%89ah`NohgQhD|mlqVQAc{OIaYhRR5GW#kw%$4nd_v(qz zbSjKdONWK&j?73_u@;zJjI9gldn!?%%1<+-a`Re3H|6Z7H;>T-CUDBJNb073mDvS-tP!t_KELZ zlfk{xzE0dhICO|FR_>su_kMSVLAgTREFgXmNY8cosnk6jx?*Bjl*l_VV+T!0Z2%)* zc`&UFC;stf4^zQ;xTi4p-?%plx2*kP6>w#J@46D$82cvvZ z*S&fq?!h7rnRup*2p=dg3WqEJYuJS{M~{Sp za?btf$TWCYeZ$UMR70U~+f(l7D%MJkymZv{J$1$+cQ;%Crr3PER{-!n;KC}gn)E70 zxJX=QR3K&{+qkT_Oj;!~A3XX zN9t&Xl(i21F3=@{t>r;|A^tRkE`Bh|Qh}Vzm{?UkUYicEoaASi-jU-uEY>1Aksb@_ zq(nU!Znc8=pISD8OsD|2v#Ep zZU!Wv49QT=jk_bk6y$0eOjgP$IBt(}AA7p6ofpql=#0*fEKzv4bd+!ZNUXN5XSZ&) z#3npWGjO!`5h7Oj>+_GyVS4~6i2muVG5)KA49))}b42ZpOl<7`uS!SL5_1HZn~*0t z-&9ipX#&A4q!vW5xNuhdYH)6VTv(h1JKmmXjXsO%KD;A;S>u{vq6o*0jkZHPqfmOG zF)9g33=xlF9nBV-kAYy7{w>rumk$?Lcq69yRMhW@kSshO_tVtFBqfO~9HkJ%+4wrk z;bwDXlbH8?W`q@BGoYmcpYL8^xHUxuT}H-r4o0}w4Isg@400557WhYo%Z^e5NMf zCMWc_(ee;kn-lrM;14NUv#=AjO?bMSh7wf$MGiBs>tBI`!xCstggRF)7B2UCA5*3! zTy%op#F>MC><`%lwRMS@x!hy3=i>V2JaAgS@yw#=T@mUG<;N33Gs$VZ>JD$kh|sTa zxtS4+z=xa&5qWAP^;ebZ?b*2XPSbICj7QP4q?Yngs?O8aXh2;!D2ho9gO^|2>?EL3 zrG$T%I8kfUL8~(k%q1P!(euW^IS?swR~j4n|3$s#d;1l=-z!f7q z^oLvg(bif~+u!561{jE=9x|^&q0dQaK=J`V9qRxPRw?45HJ46^DjjzT<5KeGqZf(G zuWc-E7*d%V!hWK7ZKXO^s5h0{)-(W{X1J7zFmKO|_X7%#V|^c7>$8IqBP%aIv_jkZ zLyIgZFlQ+*df}%QM?Ae+DMCP?SdVXPsCi##S?Me8y<_$Co=7enU$ngzXO^X>3Zf*i zG6@mfs_=xU7s{eHI_&BKHChMX>y$pms!Hu&FC6can0Mb<<0I@Ztcr8fU4y<** zH{m)K!UO#>8-;_bGpvfX-fW9s=3t3(F`#+}xu`P1@b#1IN!(}Dx6|07bR%YVf&}245^$r8K`*>jGjsx{Q7}jPt!_!HtH-n33=YDS^^!*mQ5V-Sb zz=+fGlLuOVH3U9Wf3>GgMXWa*{sQ?y;%zl-$rU2i0NkeT5nU-<;u6 z-KA$mOOt|JAfc`5Vnb+XT0Vg?weD_IEjzQxy`N)}1i5WUOJqWj|1!IG%@I!Hvbte-C-+FVzn^{ySDC}Uz82z#CAa-G4nyYs` zOJCbn-i2wcORLhmZNdZTL+P30+~(n1;U@)FVk05azIo`+kDCB=bMU@w+407PVYav% zD09YQ3wA$9Uxx`2NGE)jL-JcTF4{zVVj;26#1?dBkDf~w<0p%ZRv!UX{2swhH$P^2 zVo^=E&*cuoTa3FkoON5jRr3^yR92?6%Ilfn`eQB}S%=aprR?(96nP*le-KX|CVhi! zp7Vf-=?VB45B$Lv)O|gekC?G75a!0^=13d2G;S|)`?@psR7F2$-?zS}6d0{MlT9uP>sX|w&_YR3 zX=OpFCFZkP8khn6*OHuN3)UBT(7ws7UfS{_KSj8A9@+VG2koR@Nsr3-RNk=eh)#*R zt%4F3ZZi8ldRNJvn7kit- zT9wZgpE7`sB)(7WdEz<%{-g16c8^h|UDU%@+OlzPLA_7vrvsNoK5yBT57O}l+k((3>{O1%x-WF>C5JL<0 zd)&up6@lRKxbJ*OHc^*B5gZDZ;$Y&&g{zyF&=hTMst}7Xwv_cr~yw8k81qWgb(@GMg{MGJHh`y^DrehTO%SxM?GspJ$u9d_U6C( z^GV4NmPkfOBi}nKRw>pkN1y=k?1?x6X6%qEZR5&RO5`EC?3XedRxJ&5oKQ&ea`N)> z@Nz#-c(`ztB02U5{rut5J255^gGhOUNDPBedQh+LE$S_8xyG^Y=c)H?kDX4pcjI{% z8C(v~TyRouGJa)}dHR%8(McBrKd=bfEU=XW(0!48l6~WTJQPHpe%VwZW_iIy1c3bL zQc`~*AU$||eTcfm+OS&8XfRa#{`zG2i7;d#!n*j@AT{AliA|A8l4ZCSL>D+01dFha z(2g*VP^ZDJL9fBjL3dUhxl;s|D_{6boAo`u(R5WFVg4zlQ5q<9y^-3?R}nh>;_tsJ zWr_heW$l`Iin;SoU{r);b_vJ~Ko6C^j4gIQSYs`L;R@1n(1%DKqA49ziIC+$oL~va zWNr?A5oC5R)<8ME0R*}#Fp*nle^VQ>(=bB;9a(oj#R!ZVb5X*K$GRKP{V`?hxPW(? z@=3U_(R4Hu70XrI@IIc4xl{=^vC8!BX6N@UFgFqH8}!&1`tf`yJT&E_lxOnzkW=vt z`IIJ6R0VT?Q=R_2{lmDCAWS$;B^?dx(XdgI^C%>UAahia$&w-4u~u7Xu>`kzv)Ri@ z>Yki!8rGIz_Fm@&XzjeE3 z(pcil?+u@1(Y%?Sm(HVPqje*GLM)aeV%O1#->$1sQ973W#ig{aV0T<~39G`FBszFce;NdCqLY&}qs=BNpy-}5x^jdh87Ic@3YN`Wa83fIG9X30A@~GqPIuyDWE;@lF;@Q+4k|i8g@!=#FDbTTS=sCPKqqlQdX2OtY0uv zlj^e$PhF-~P&Jd=&|8h&Vj|Shxo0iG)n~3dPayuC+)ox*IVx7qu@@+L;ts;nQBk2~ zYk=oWZbnkD0In!_LK2*>w>TOqtIUSqP&z$^3ikX@) zN<>+fykDpho?uRnLQ0eD11oWe3x@ipPc_WHXJ5x8F&CvP(Y8GrW8|2Hq`j3tMwT#2 zZqKZvzhHEgq-zUD@!gMd`k_ZHHgR)c?ss8yM}5yza;OvNbjgJGN;%S=7Lc? zGILH_5zox+!#kfoQ)q0fn1wXWW>QMY{Ai`eZageVStvk#5&PkvCFa76oXPiQa7rE4 zp8NZ(-ZEsP397oWxUo3VeJ918*H_ak6zeZMXqoJwM^Yvlr<-r)1i>Z^PIEqaQRGa} zPc=cQJU=k{(3%a8ge18H`0kE02Ivz0n@^k{YFcF4WLkBqGZ&CAonMttDm)YJ9OkOp z{OWsJTPpone2P8yo*yHegN)_dp*|ZnO2j3EvPWDWhLz7a7j!D&NZ5|Z9hxollgVfY zFc)$v`AA4Z^u~%iEDQy!-+RX>U6ue5@Fv0W#*Fp%H^x#+tF%`P=Mt=1iFe}nl6Swz zU#R9%-8$*dV3S4iOQjxznm3@SbJ@ny1vVmVu4-l(bJXo+bXQrIe$n*+*(OxoQ!LM_ zj$O_zZ4B+Oii4;e6x^g|4)^F5gmj!p)-CudxGIFIFjns@(=O8hQ-{vi4WSKTPN9wi z-e07)J*CQyL|=rNmP12RRcK@wL>N>U1nokOWu~QMs)?lIsK}u-h`$kkqaufkgoXPGS0_dkswaQ}+N2}O3NQ#q5Y6@eYn$O>_4|8?<~&T=+rwKAes zIcAWB8)L%>!uiy0wMufXutumM+xOEQLBk0>`n1e+VWDW|$W>A|$mOr)*%|X3?En^4 z;u4|DNy>qS>lf%h_sL>opicaswzVb?)7* zf`Y4q;~Qdv_7ho|Gyj416T%ma2MiOZP8tj8mYTDhIzKU{C*a0@ zN;AR^bL0ib`lRblf78znAVg?!w>Fg1E+rH~3dI0&Wu0C-vV(qr_c^o`^*O8+SJd?e z004IVF4p%3%2jPp0SoyyG!%DN9v~*nwD%x$50T*QuF$un^{C`^Hv}*nz7BFG`~^Py zfRPvF77^aUHVT`Un&6$6a#-SHGy3G}B?$Y+14dQrb;bE(I2!fxr3$;J;Xs&Er~csC zxzlol(z$ay?3=&WBIxS98i%+huhwh8FC<1Tgz~%Ywh;Bt2jU&+hkCEB(BnP^fX@+d z=_jV((sEv2X#R7lpD)H5%JNew5Ah_PQ;>i}DQdRiA%@%-Drf>D`5VcNt)e(h!2s-sF3)Fr%!f8vM!K1n7aVUha;wF`N?zCj zQ){gO_&tIT@KFpg5*uNlU`e(;TxhvzkP(ootS&aCjtQz~ha6IQb}~&RDMPjxj@5BB98orLIoCye_q7UN$)9b18NnP!nfhZYEh)-P7fEJSZsRT2?lwn zF`g(gl)muT6cntWO7Qx?g!^eS@%M7%hy!155!nI|oT{0!jWb+)FAf#JLh`hHB(vywW}oeG@?oBHsr8gadE|wh(0od_%crY20@9emNq!99yEwmnW)DfO(|oC z=(EzVB{hSNP+_QC=VoxU+_x33imKK$cwCF&j*pQ4fxss)h~NLA-% z$up!o-V|$#PLsR}s3OUq5t~UM8vMHqHU-i$Z}5DTAZ)2&= z@9mA5$41PfwULSBN=d-O6>Z%edXI&sG7^GY!%)>@v<5hmtG=p1S6_0CA@~*I`%y%Y z3pjq$k+>RR)jq81&-8OE+!}>maIrxt899qR+8^7lZ*xi%V`B}4(dzOTV(mVH9)y~f z@~kyQH3hMua0#%op;`CC*vpe-l;P|&B!lGC>{z!3$hPV-j5^@!!6+6ss!4S<`EKzf zkErs2t)&*`Hf!~3sT$DwD#GF>bST9^r#4EGU_g@=d8wJ4Pl!COY}Ww@h5>zzDMpuO zhTv_`YoHvgCnLgag_}tME|s;(b7RV>ISVBD8I{N!EN#OSmRfOTK*N^pHD*j71L2EG zd@F$4@QxG$!s(%O-Ndt$LlAXa#lLPtX6|O<){AKJ znVJbT{A%csawyIj;2(G<33D}k%#EU$_|>FD8T1RT;pi6S^bQnu5sKsD;ldd?-{BSZ z#>y0T=6&+)m5m{uUY={=RKWGCCHc)9dX<7uw^z5i>4~KUdAY|wf*OZcUfg{4MJ79g2_3-6+gni=)D!9=Wb;+or-l%s|MG_H`yPjvV4lw-(&~1^S8iuL- z^=E)f$6vlCL)Cb3`Xq)14YVu=j5g}QZBK+zkf|Y6L&VC@0^t(oobDxxcl&UzB`LWX z9&d^M?#OKz*CiYV-v)yvcw?U;2y~jf(UUdr1bsq#7^_bj{~HbxhLBb-Kd}|?^KlF2 z3#<|z<0yfO51c=c3Yc}uF2N{}E}-A9T^wBf59rxNQ8z7!NW_3;{hxF2;%d_!Z!war z0J1E9vFQ|z5ntQA7CG(Waovg|-d-Zgt8 z{;pU!9#O3xUr4P$bFIukihF`}0d0%PxMd^>mX7HBP3C}k0MRv~aZyTU9xmeS0w1(EMN!JKB;_Y#nM40b2`CT6TKP`c0Ov>*2urJUlLNiI2;MZ z1#lUY@(mC>3z@z)cyhaT`VYY9?g&S&kjkzYP`A)1d+Jnu4#8=4Sd%A*`d2->3+fyB=jx~7F<_`+qpLxflnw=J0yt? zw$(xV^)xwXq%7I)NKyhklzv%BaocWeydB$}Qe8oXs-o_H3ta$svb1fyi*=yR+Qe;` z&%8i$njTd&>=Xrle2}@!Q4EECbA~Cc6vSHLEkTj@N-s%@4`=O$=|*XIGpCL?>r?Mh z86sI#Xg4jCP7EZk1C^??`w5H6k7qzEvTpeUZd5U;Nde6Sxn1sZ#+>Y6v~2q8pJ($Y zyW}N~k(mUP8tG6O@vx=&H(7#PNePoqxirA*Ke@F#lQd*G269noP|WSB#rx1E!>m%& zRoVbfa7#xHQ-WI3V6eyJ>TNOx1OrIK9nxKg603y|9|{_u%nNhGTxQGmc>=7pg;qDY zMYU*-<=w%hlgxSoQ?e$|nwQMhrx~YO0A7ERi6ayX6Lz2waPn<*z`!_jyIq1-{$bTT z`#@m$D{NnHRz5V21|yKsM{E1{Z#q_$KZObg;I*n0{kuEI8 z(wRM)GcZQxz!g)*iCsqQyhi%Gg=4+gHh-dS+FaJYl6Bp=Vr%!5Ze6Bg>vYwyku-z4 zPRjC~Em6+Jzuy)?*%I=vCC1dHb)_DoWBT)~*)|kx2khsicjk2TEbRms+#lFsZG!t8 zhh=A(#{HW9rA4kFMX7eMxSk^zgA|0V+v>ysE(zWqTw!#NK>ss(sC&qJhEJLXz>>IS zyV3Y|$@1AMC-#cnyY1}bT~z$q6frAYVgp61w7AJxfr#J(yQk?Gte*| zf-7e1f%@dT=kvYgb=L=V8?+WQ=coWUI@g;Y$o~mqo%Yl>*8{{$aF!LsOLErB{~Fa% zZng!4JNF=#-+i?=;3e9R_5lCYQ*Fcr>J}V_`Iei@c-Ib#o(@VD%@sj5Y;ghPg~uE3 z6rKK|(hqmP)bHfBa}oyya|HSWoEFU$e&pz3q(2Mpy3n@7vD5GmhsO9eu=$f#)x`A?4%BG*BJc#30ntg)t4yVY2&SkD zdFL4(qe4hpOVAJgzW@25mZfe`1EW5Xuwg+eGCOTA3=M@N z|De-Ui_Q+-=IkXXtmQ5mt-bI-8?k4wM(RUD4y}p9+hCttYxzzSQNA(5759pR2M);P z;$?PF^kr2D>|EN@UshVJ{}Tq6F>{ha^?BniH7Wk(X3uZgaR2!wAeuM*1@UVVfZ~ZD z?|_!%E4(M|h4U*9pN_ul$#fl38L?^h&!$4fhIS(cijD!8ZCq1Kw%t|ELuALXb;1>c z&-%gSR*Yu5;+POa_9X}1l6NNur6kh;spf`+afrc4Tg$SsF_VmoMuS8BR9*f8E~OHU zKBRfx(#Bou6%Nt{X$XhT#8k)d^<|@iN`8RV*l)`nn!oGs>^C8n3+7&>(Nw8l*1IAm zrqnQ3W@H(eovL>1jpV2@bSXwF4n;BB)CH7(-LFw-&&5M}OMizcbpeq$*?z$1#MzcG z;T5j$Qe$#sUp1EN)1L_t5im0t7V>8eUuO-{D-NG;4P;#O<6d1f5WOoalEfPwObn1X zgabf}Aw*?i7>^wog%`M;BZz8XjHsr8#ATsJ6r-v9QMjn*X@Y!SlW|F48lhHmI>x|q zA=W98=joPw=>{>@uigYbJRT3qJ#~-SKA+p*YVRvZ!r3~Vlg8=VD#+m0IGQt$vA#2n z$~Urirff&v$i)}%25o+D%BFPz5ykjrMQ=X}aFfyn`RWlO=P6g$iLu!u2ps1orv3|u z_z*4{&NHwCqAkz_!n^+gIO~=GKgKpbR+g8RJL(A7%RaqLzYsfApWMwT(%I=8 z0{Snh(?NR212%VCNW0ER;QxoRZwj(4+LAqG+qP}nwr$(CZQHhO+qO>CDZA=ay}Gx% zUqpAmdn4Y@o@?#B|3<`|Idf!=oXv*|59mM{K|5tLmMNWD9K3tCOL%~Ps+ZLIF$r8BaO6V zTw&;(v2RM#ws>fKP5jaNK(g0#G?Zl`#-^zp7(S{L)!64A@*)a*39#wfS(s0b~69lgrG z%~IMhx|FVQ&Bd#l^@^O*0o1XXGvCsK{U`KK1>IAo{61~aiPGyO!S%ozPl)B*9%88) zp(GvuOHL@=S+uu!W0@!zBjCB&C{TLEpEGmrt{$U|XIbNhmtTKy3VXmfCe`ZNx>ge; z1)=B+N3IQkr7R3fvbHH5OR6G5;U}fn)vD#xbs9PbPbpUEtRtujsCH2%l)9;s>R!D^up-%z_3~cQ1r;X zFJvO=6hARX(Bk$@ulotM9butrb3s?Qh5S{z`2^EvTAI?$b|rV~FJJX$uv!Az&T)6M zbGm7ix(RNMYF@$Z2F=`|a`$mwF>iQdm>i#rzv2FYY)qsjt`mQhFce7t4%z%nO8Xzk zM%vEEz*_l7`uiWOWsW9_hA7)hsE!XaY?_F_cGac z>D;`o^z^$?R5Yy(Qae{PwE7{DhYgAqL9niD?c+kk^2WiV;)OrQhG=QG?i7+G>G&hU zTo!(-Zooy;BPZMvkrT9$i)4Tr3gb%dl~5uj%4HqyoO9&BhAGHQINVbEW?k;Eb18

    A$B3k~{RycObG@6y| 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 $@vz03z8Z`qI{ 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

    =%>>2|D73@_9Fx}<*!s;{SFX;r+XReUC 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 z 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

    qm4Wk) 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 z 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�!!ybUdR4n8i&a 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≻pfc-p+kq>A@&EZJ32ii;nzX4TDQYlf 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
    gy>fqEPDaO`QF}o` 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%0AO0^D-A)i$ldleqyk}TE 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 z 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

    tyv*0yP}nk-pv4zbBt@DbR|3V7ZQ73LXi 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 kF-h#lNtCW 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 literal 0 HcmV?d00001 diff --git a/main.nf b/main.nf new file mode 100644 index 00000000..5fa2e2fb --- /dev/null +++ b/main.nf @@ -0,0 +1,64 @@ +#!/usr/bin/env nextflow +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + nf-core/oncoanalyser +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Github : https://github.com/nf-core/oncoanalyser + + Website: https://nf-co.re/oncoanalyser + Slack : https://nfcore.slack.com/channels/oncoanalyser +---------------------------------------------------------------------------------------- +*/ + +nextflow.enable.dsl = 2 + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + GENOME PARAMETER VALUES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +params.fasta = WorkflowMain.getGenomeAttribute(params, 'fasta') + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + VALIDATE & PRINT PARAMETER SUMMARY +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +WorkflowMain.initialise(workflow, params, log) + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + NAMED WORKFLOW FOR PIPELINE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +include { ONCOANALYSER } from './workflows/oncoanalyser' + +// +// WORKFLOW: Run main nf-core/oncoanalyser analysis pipeline +// +workflow NFCORE_ONCOANALYSER { + ONCOANALYSER () +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + RUN ALL WORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// +// WORKFLOW: Execute a single named workflow for the pipeline +// See: https://github.com/nf-core/rnaseq/issues/619 +// +workflow { + NFCORE_ONCOANALYSER () +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + THE END +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ diff --git a/modules.json b/modules.json new file mode 100644 index 00000000..4ce9f998 --- /dev/null +++ b/modules.json @@ -0,0 +1,24 @@ +{ + "name": "nf-core/oncoanalyser", + "homePage": "https://github.com/nf-core/oncoanalyser", + "repos": { + "https://github.com/nf-core/modules.git": { + "modules": { + "nf-core": { + "custom/dumpsoftwareversions": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "fastqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "multiqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + } + } + } + } + } +} diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf new file mode 100644 index 00000000..6df76a07 --- /dev/null +++ b/modules/local/samplesheet_check.nf @@ -0,0 +1,27 @@ +process SAMPLESHEET_CHECK { + tag "$samplesheet" + + conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/python:3.8.3' : + 'quay.io/biocontainers/python:3.8.3' }" + + input: + path samplesheet + + output: + path '*.csv' , emit: csv + path "versions.yml", emit: versions + + script: // This script is bundled with the pipeline, in nf-core/oncoanalyser/bin/ + """ + check_samplesheet.py \\ + $samplesheet \\ + samplesheet.valid.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ +} diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf new file mode 100644 index 00000000..cebb6e05 --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -0,0 +1,24 @@ +process CUSTOM_DUMPSOFTWAREVERSIONS { + label 'process_single' + + // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container + conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" + + input: + path versions + + output: + path "software_versions.yml" , emit: yml + path "software_versions_mqc.yml", emit: mqc_yml + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + template 'dumpsoftwareversions.py' +} diff --git a/modules/nf-core/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/custom/dumpsoftwareversions/meta.yml new file mode 100644 index 00000000..60b546a0 --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/meta.yml @@ -0,0 +1,34 @@ +name: custom_dumpsoftwareversions +description: Custom module used to dump software versions within the nf-core pipeline template +keywords: + - custom + - version +tools: + - custom: + description: Custom module used to dump software versions within the nf-core pipeline template + homepage: https://github.com/nf-core/tools + documentation: https://github.com/nf-core/tools + licence: ["MIT"] +input: + - versions: + type: file + description: YML file containing software versions + pattern: "*.yml" + +output: + - yml: + type: file + description: Standard YML file containing software versions + pattern: "software_versions.yml" + - mqc_yml: + type: file + description: MultiQC custom content YML file containing software versions + pattern: "software_versions_mqc.yml" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@drpatelh" + - "@grst" diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py new file mode 100644 index 00000000..787bdb7b --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python + +import platform +from textwrap import dedent + +import yaml + + +def _make_versions_html(versions): + html = [ + dedent( + """\\ + + + + + + + + + + """ + ) + ] + for process, tmp_versions in sorted(versions.items()): + html.append("") + for i, (tool, version) in enumerate(sorted(tmp_versions.items())): + html.append( + dedent( + f"""\\ + + + + + + """ + ) + ) + html.append("") + html.append("
    Process Name Software Version
    {process if (i == 0) else ''}{tool}{version}
    ") + return "\\n".join(html) + + +versions_this_module = {} +versions_this_module["${task.process}"] = { + "python": platform.python_version(), + "yaml": yaml.__version__, +} + +with open("$versions") as f: + versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module + +# aggregate versions by the module name (derived from fully-qualified process name) +versions_by_module = {} +for process, process_versions in versions_by_process.items(): + module = process.split(":")[-1] + try: + if versions_by_module[module] != process_versions: + raise AssertionError( + "We assume that software versions are the same between all modules. " + "If you see this error-message it means you discovered an edge-case " + "and should open an issue in nf-core/tools. " + ) + except KeyError: + versions_by_module[module] = process_versions + +versions_by_module["Workflow"] = { + "Nextflow": "$workflow.nextflow.version", + "$workflow.manifest.name": "$workflow.manifest.version", +} + +versions_mqc = { + "id": "software_versions", + "section_name": "${workflow.manifest.name} Software Versions", + "section_href": "https://github.com/${workflow.manifest.name}", + "plot_type": "html", + "description": "are collected at run time from the software output.", + "data": _make_versions_html(versions_by_module), +} + +with open("software_versions.yml", "w") as f: + yaml.dump(versions_by_module, f, default_flow_style=False) +with open("software_versions_mqc.yml", "w") as f: + yaml.dump(versions_mqc, f, default_flow_style=False) + +with open("versions.yml", "w") as f: + yaml.dump(versions_this_module, f, default_flow_style=False) diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf new file mode 100644 index 00000000..05730368 --- /dev/null +++ b/modules/nf-core/fastqc/main.nf @@ -0,0 +1,59 @@ +process FASTQC { + tag "$meta.id" + label 'process_medium' + + conda (params.enable_conda ? "bioconda::fastqc=0.11.9" : null) + 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 ?: '' + // Add soft-links to original FastQs for consistent naming in pipeline + def prefix = task.ext.prefix ?: "${meta.id}" + if (meta.single_end) { + """ + [ ! -f ${prefix}.fastq.gz ] && ln -s $reads ${prefix}.fastq.gz + fastqc $args --threads $task.cpus ${prefix}.fastq.gz + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) + END_VERSIONS + """ + } else { + """ + [ ! -f ${prefix}_1.fastq.gz ] && ln -s ${reads[0]} ${prefix}_1.fastq.gz + [ ! -f ${prefix}_2.fastq.gz ] && ln -s ${reads[1]} ${prefix}_2.fastq.gz + fastqc $args --threads $task.cpus ${prefix}_1.fastq.gz ${prefix}_2.fastq.gz + + 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 new file mode 100644 index 00000000..4da5bb5a --- /dev/null +++ b/modules/nf-core/fastqc/meta.yml @@ -0,0 +1,52 @@ +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/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf new file mode 100644 index 00000000..a8159a57 --- /dev/null +++ b/modules/nf-core/multiqc/main.nf @@ -0,0 +1,53 @@ +process MULTIQC { + label 'process_single' + + conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" + + input: + path multiqc_files, stageAs: "?/*" + path(multiqc_config) + path(extra_multiqc_config) + path(multiqc_logo) + + output: + path "*multiqc_report.html", emit: report + path "*_data" , emit: data + path "*_plots" , optional:true, emit: plots + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config = multiqc_config ? "--config $multiqc_config" : '' + def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + """ + multiqc \\ + --force \\ + $args \\ + $config \\ + $extra_config \\ + . + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) + END_VERSIONS + """ + + stub: + """ + touch multiqc_data + touch multiqc_plots + touch multiqc_report.html + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) + END_VERSIONS + """ +} diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml new file mode 100644 index 00000000..ebc29b27 --- /dev/null +++ b/modules/nf-core/multiqc/meta.yml @@ -0,0 +1,55 @@ +name: MultiQC +description: Aggregate results from bioinformatics analyses across many samples into a single report +keywords: + - QC + - bioinformatics tools + - Beautiful stand-alone HTML report +tools: + - multiqc: + description: | + MultiQC searches a given directory for analysis logs and compiles a HTML report. + It's a general use tool, perfect for summarising the output from numerous bioinformatics tools. + homepage: https://multiqc.info/ + documentation: https://multiqc.info/docs/ + licence: ["GPL-3.0-or-later"] + +input: + - multiqc_files: + type: file + description: | + List of reports / files recognised by MultiQC, for example the html and zip output of FastQC + - multiqc_config: + type: file + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + - extra_multiqc_config: + type: file + description: Second optional config yml for MultiQC. Will override common sections in multiqc_config. + pattern: "*.{yml,yaml}" + - multiqc_logo: + type: file + description: Optional logo file for MultiQC + pattern: "*.{png}" + +output: + - report: + type: file + description: MultiQC report file + pattern: "multiqc_report.html" + - data: + type: dir + description: MultiQC data dir + pattern: "multiqc_data" + - plots: + type: file + description: Plots created by MultiQC + pattern: "*_data" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@abhi18av" + - "@bunop" + - "@drpatelh" + - "@jfy133" diff --git a/nextflow.config b/nextflow.config new file mode 100644 index 00000000..0eef462b --- /dev/null +++ b/nextflow.config @@ -0,0 +1,231 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + nf-core/oncoanalyser Nextflow config file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Default config options for all compute environments +---------------------------------------------------------------------------------------- +*/ + +// Global default params, used in configs +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 + // MultiQC options + multiqc_config = null + multiqc_title = null + multiqc_logo = null + max_multiqc_email_size = '25.MB' + multiqc_methods_description = null + + // Boilerplate options + outdir = null + tracedir = "${params.outdir}/pipeline_info" + publish_dir_mode = 'copy' + email = null + email_on_fail = null + plaintext_email = false + monochrome_logs = false + hook_url = null + help = false + validate_params = true + show_hidden_params = false + schema_ignore_params = 'genomes' + enable_conda = false + + + // Config options + custom_config_version = 'master' + custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" + config_profile_description = null + config_profile_contact = null + config_profile_url = null + config_profile_name = null + + + // Max resource options + // Defaults only, expecting to be overwritten + max_memory = '128.GB' + max_cpus = 16 + max_time = '240.h' + +} + +// Load base.config by default for all pipelines +includeConfig 'conf/base.config' + +// Load nf-core custom profiles from different Institutions +try { + includeConfig "${params.custom_config_base}/nfcore_custom.config" +} catch (Exception e) { + System.err.println("WARNING: Could not load nf-core/config profiles: ${params.custom_config_base}/nfcore_custom.config") +} + +// Load nf-core/oncoanalyser custom profiles from different institutions. +// Warning: Uncomment only if a pipeline-specific instititutional config already exists on nf-core/configs! +// try { +// includeConfig "${params.custom_config_base}/pipeline/oncoanalyser.config" +// } catch (Exception e) { +// System.err.println("WARNING: Could not load nf-core/config/oncoanalyser profiles: ${params.custom_config_base}/pipeline/oncoanalyser.config") +// } + + +profiles { + debug { process.beforeScript = 'echo $HOSTNAME' } + conda { + params.enable_conda = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + mamba { + params.enable_conda = true + conda.useMamba = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + docker { + docker.enabled = true + docker.userEmulation = true + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + singularity { + singularity.enabled = true + singularity.autoMounts = true + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + podman { + podman.enabled = true + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + shifter { + shifter.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false + } + charliecloud { + charliecloud.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + } + gitpod { + executor.name = 'local' + executor.cpus = 16 + executor.memory = 60.GB + } + test { includeConfig 'conf/test.config' } + test_full { includeConfig 'conf/test_full.config' } +} + + +// 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. + +env { + PYTHONNOUSERSITE = 1 + R_PROFILE_USER = "/.Rprofile" + R_ENVIRON_USER = "/.Renviron" + JULIA_DEPOT_PATH = "/usr/local/share/julia" +} + +// Capture exit codes from upstream processes when piping +process.shell = ['/bin/bash', '-euo', 'pipefail'] + +def trace_timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') +timeline { + enabled = true + file = "${params.tracedir}/execution_timeline_${trace_timestamp}.html" +} +report { + enabled = true + file = "${params.tracedir}/execution_report_${trace_timestamp}.html" +} +trace { + enabled = true + file = "${params.tracedir}/execution_trace_${trace_timestamp}.txt" +} +dag { + enabled = true + file = "${params.tracedir}/pipeline_dag_${trace_timestamp}.html" +} + +manifest { + name = 'nf-core/oncoanalyser' + author = 'Stephen Watts' + homePage = 'https://github.com/nf-core/oncoanalyser' + description = 'A comprehensive cancer WGS/WTS analysis and reporting pipeline' + mainScript = 'main.nf' + nextflowVersion = '!>=21.10.3' + version = '1.0dev' + doi = '' +} + +// Load modules.config for DSL2 module specific options +includeConfig 'conf/modules.config' + +// Function to ensure that resource requirements don't go beyond +// a maximum limit +def check_max(obj, type) { + if (type == 'memory') { + try { + if (obj.compareTo(params.max_memory as nextflow.util.MemoryUnit) == 1) + return params.max_memory as nextflow.util.MemoryUnit + else + return obj + } catch (all) { + println " ### ERROR ### Max memory '${params.max_memory}' is not valid! Using default value: $obj" + return obj + } + } else if (type == 'time') { + try { + if (obj.compareTo(params.max_time as nextflow.util.Duration) == 1) + return params.max_time as nextflow.util.Duration + else + return obj + } catch (all) { + println " ### ERROR ### Max time '${params.max_time}' is not valid! Using default value: $obj" + return obj + } + } else if (type == 'cpus') { + try { + return Math.min( obj, params.max_cpus as int ) + } catch (all) { + println " ### ERROR ### Max cpus '${params.max_cpus}' is not valid! Using default value: $obj" + return obj + } + } +} diff --git a/nextflow_schema.json b/nextflow_schema.json new file mode 100644 index 00000000..d570597b --- /dev/null +++ b/nextflow_schema.json @@ -0,0 +1,287 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "https://raw.githubusercontent.com/nf-core/oncoanalyser/master/nextflow_schema.json", + "title": "nf-core/oncoanalyser pipeline parameters", + "description": "A comprehensive cancer WGS/WTS analysis and reporting pipeline", + "type": "object", + "definitions": { + "input_output_options": { + "title": "Input/output options", + "type": "object", + "fa_icon": "fas fa-terminal", + "description": "Define where the pipeline should find input data and save output data.", + "required": ["input", "outdir"], + "properties": { + "input": { + "type": "string", + "format": "file-path", + "mimetype": "text/csv", + "pattern": "^\\S+\\.csv$", + "schema": "assets/schema_input.json", + "description": "Path to comma-separated file containing information about the samples in the experiment.", + "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/oncoanalyser/usage#samplesheet-input).", + "fa_icon": "fas fa-file-csv" + }, + "outdir": { + "type": "string", + "format": "directory-path", + "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", + "fa_icon": "fas fa-folder-open" + }, + "email": { + "type": "string", + "description": "Email address for completion summary.", + "fa_icon": "fas fa-envelope", + "help_text": "Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run.", + "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" + }, + "multiqc_title": { + "type": "string", + "description": "MultiQC report title. Printed as page header, used for filename if not otherwise specified.", + "fa_icon": "fas fa-file-signature" + } + } + }, + "reference_genome_options": { + "title": "Reference genome options", + "type": "object", + "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", + "mimetype": "text/plain", + "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", + "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`." + } + } + }, + "institutional_config_options": { + "title": "Institutional config options", + "type": "object", + "fa_icon": "fas fa-university", + "description": "Parameters used to describe centralised config profiles. These should not be edited.", + "help_text": "The centralised nf-core configuration profiles use a handful of pipeline parameters to describe themselves. This information is then printed to the Nextflow log when you run a pipeline. You should not need to change these values when you run a pipeline.", + "properties": { + "custom_config_version": { + "type": "string", + "description": "Git commit id for Institutional configs.", + "default": "master", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "custom_config_base": { + "type": "string", + "description": "Base directory for Institutional configs.", + "default": "https://raw.githubusercontent.com/nf-core/configs/master", + "hidden": true, + "help_text": "If you're running offline, Nextflow will not be able to fetch the institutional config files from the internet. If you don't need them, then this is not a problem. If you do need them, you should download the files from the repo and tell Nextflow where to find them with this parameter.", + "fa_icon": "fas fa-users-cog" + }, + "config_profile_name": { + "type": "string", + "description": "Institutional config name.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_description": { + "type": "string", + "description": "Institutional config description.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_contact": { + "type": "string", + "description": "Institutional config contact information.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_url": { + "type": "string", + "description": "Institutional config URL link.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + } + } + }, + "max_job_request_options": { + "title": "Max job request options", + "type": "object", + "fa_icon": "fab fa-acquisitions-incorporated", + "description": "Set the top limit for requested resources for any single job.", + "help_text": "If you are running on a smaller system, a pipeline step requesting more resources than are available may cause the Nextflow to stop the run with an error. These options allow you to cap the maximum resources requested by any single job so that the pipeline will run on your system.\n\nNote that you can not _increase_ the resources requested by any job using these options. For that you will need your own configuration file. See [the nf-core website](https://nf-co.re/usage/configuration) for details.", + "properties": { + "max_cpus": { + "type": "integer", + "description": "Maximum number of CPUs that can be requested for any single job.", + "default": 16, + "fa_icon": "fas fa-microchip", + "hidden": true, + "help_text": "Use to set an upper-limit for the CPU requirement for each process. Should be an integer e.g. `--max_cpus 1`" + }, + "max_memory": { + "type": "string", + "description": "Maximum amount of memory that can be requested for any single job.", + "default": "128.GB", + "fa_icon": "fas fa-memory", + "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", + "hidden": true, + "help_text": "Use to set an upper-limit for the memory requirement for each process. Should be a string in the format integer-unit e.g. `--max_memory '8.GB'`" + }, + "max_time": { + "type": "string", + "description": "Maximum amount of time that can be requested for any single job.", + "default": "240.h", + "fa_icon": "far fa-clock", + "pattern": "^(\\d+\\.?\\s*(s|m|h|day)\\s*)+$", + "hidden": true, + "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" + } + } + }, + "generic_options": { + "title": "Generic options", + "type": "object", + "fa_icon": "fas fa-file-import", + "description": "Less common options for the pipeline, typically set in a config file.", + "help_text": "These options are common to all nf-core pipelines and allow you to customise some of the core preferences for how the pipeline runs.\n\nTypically these options would be set in a Nextflow config file loaded for all pipeline runs, such as `~/.nextflow/config`.", + "properties": { + "help": { + "type": "boolean", + "description": "Display help text.", + "fa_icon": "fas fa-question-circle", + "hidden": true + }, + "publish_dir_mode": { + "type": "string", + "default": "copy", + "description": "Method used to save pipeline results to output directory.", + "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", + "fa_icon": "fas fa-copy", + "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], + "hidden": true + }, + "email_on_fail": { + "type": "string", + "description": "Email address for completion summary, only when pipeline fails.", + "fa_icon": "fas fa-exclamation-triangle", + "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$", + "help_text": "An email address to send a summary email to when the pipeline is completed - ONLY sent if the pipeline does not exit successfully.", + "hidden": true + }, + "plaintext_email": { + "type": "boolean", + "description": "Send plain-text email instead of HTML.", + "fa_icon": "fas fa-remove-format", + "hidden": true + }, + "max_multiqc_email_size": { + "type": "string", + "description": "File size limit when attaching MultiQC reports to summary emails.", + "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", + "default": "25.MB", + "fa_icon": "fas fa-file-upload", + "hidden": true + }, + "monochrome_logs": { + "type": "boolean", + "description": "Do not use coloured log outputs.", + "fa_icon": "fas fa-palette", + "hidden": true + }, + "hook_url": { + "type": "string", + "description": "Incoming hook URL for messaging service", + "fa_icon": "fas fa-people-group", + "help_text": "Incoming hook URL for messaging service. Currently, only MS Teams is supported.", + "hidden": true + }, + "multiqc_config": { + "type": "string", + "description": "Custom config file to supply to MultiQC.", + "fa_icon": "fas fa-cog", + "hidden": true + }, + "multiqc_logo": { + "type": "string", + "description": "Custom logo file to supply to MultiQC. File name must also be set in the MultiQC config file", + "fa_icon": "fas fa-image", + "hidden": true + }, + "multiqc_methods_description": { + "type": "string", + "description": "Custom MultiQC yaml file containing HTML including a methods description.", + "fa_icon": "fas fa-cog" + }, + "tracedir": { + "type": "string", + "description": "Directory to keep pipeline Nextflow logs and reports.", + "default": "${params.outdir}/pipeline_info", + "fa_icon": "fas fa-cogs", + "hidden": true + }, + "validate_params": { + "type": "boolean", + "description": "Boolean whether to validate parameters against the schema at runtime", + "default": true, + "fa_icon": "fas fa-check-square", + "hidden": true + }, + "show_hidden_params": { + "type": "boolean", + "fa_icon": "far fa-eye-slash", + "description": "Show all params when using `--help`", + "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." + }, + "enable_conda": { + "type": "boolean", + "description": "Run this workflow with Conda. You can also use '-profile conda' instead of providing this parameter.", + "hidden": true, + "fa_icon": "fas fa-bacon" + } + } + } + }, + "allOf": [ + { + "$ref": "#/definitions/input_output_options" + }, + { + "$ref": "#/definitions/reference_genome_options" + }, + { + "$ref": "#/definitions/institutional_config_options" + }, + { + "$ref": "#/definitions/max_job_request_options" + }, + { + "$ref": "#/definitions/generic_options" + } + ] +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..0d62beb6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +# Config file for Python. Mostly used to configure linting of bin/check_samplesheet.py with Black. +# Should be kept the same as nf-core/tools to avoid fighting with template synchronisation. +[tool.black] +line-length = 120 +target_version = ["py37", "py38", "py39", "py310"] + +[tool.isort] +profile = "black" +known_first_party = ["nf_core"] +multi_line_output = 3 diff --git a/subworkflows/local/input_check.nf b/subworkflows/local/input_check.nf new file mode 100644 index 00000000..0aecf87f --- /dev/null +++ b/subworkflows/local/input_check.nf @@ -0,0 +1,44 @@ +// +// Check input samplesheet and get read channels +// + +include { SAMPLESHEET_CHECK } from '../../modules/local/samplesheet_check' + +workflow INPUT_CHECK { + take: + samplesheet // file: /path/to/samplesheet.csv + + main: + SAMPLESHEET_CHECK ( samplesheet ) + .csv + .splitCsv ( header:true, sep:',' ) + .map { create_fastq_channel(it) } + .set { reads } + + emit: + reads // channel: [ val(meta), [ reads ] ] + versions = SAMPLESHEET_CHECK.out.versions // channel: [ versions.yml ] +} + +// Function to get list of [ meta, [ fastq_1, fastq_2 ] ] +def create_fastq_channel(LinkedHashMap row) { + // create meta map + def meta = [:] + meta.id = row.sample + meta.single_end = 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) ] ] + } + return fastq_meta +} diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf new file mode 100644 index 00000000..50bc12ad --- /dev/null +++ b/workflows/oncoanalyser.nf @@ -0,0 +1,133 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + VALIDATE INPUTS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) + +// Validate input parameters +WorkflowOncoanalyser.initialise(params, log) + +// TODO nf-core: Add all file path parameters for the pipeline to the list below +// Check input path parameters to see if they exist +def checkPathParamList = [ params.input, params.multiqc_config, params.fasta ] +for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } + +// Check mandatory parameters +if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CONFIG FILES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) +ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath( params.multiqc_config, checkIfExists: true ) : Channel.empty() +ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath( params.multiqc_logo, checkIfExists: true ) : Channel.empty() +ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT LOCAL MODULES/SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// +// SUBWORKFLOW: Consisting of a mix of local and nf-core/modules +// +include { INPUT_CHECK } from '../subworkflows/local/input_check' + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT NF-CORE MODULES/SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// +// 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' + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + RUN MAIN WORKFLOW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// Info required for completion email and summary +def multiqc_report = [] + +workflow ONCOANALYSER { + + ch_versions = Channel.empty() + + // + // SUBWORKFLOW: Read in samplesheet, validate and stage input files + // + INPUT_CHECK ( + ch_input + ) + ch_versions = ch_versions.mix(INPUT_CHECK.out.versions) + + // + // 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') + ) + + // + // MODULE: MultiQC + // + workflow_summary = WorkflowOncoanalyser.paramsSummaryMultiqc(workflow, summary_params) + ch_workflow_summary = Channel.value(workflow_summary) + + methods_description = WorkflowOncoanalyser.methodsDescriptionText(workflow, ch_multiqc_custom_methods_description) + ch_methods_description = Channel.value(methods_description) + + ch_multiqc_files = Channel.empty() + 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(), + ch_multiqc_config.collect().ifEmpty([]), + ch_multiqc_custom_config.collect().ifEmpty([]), + ch_multiqc_logo.collect().ifEmpty([]) + ) + multiqc_report = MULTIQC.out.report.toList() + ch_versions = ch_versions.mix(MULTIQC.out.versions) +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + COMPLETION EMAIL AND SUMMARY +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +workflow.onComplete { + if (params.email || params.email_on_fail) { + NfcoreTemplate.email(workflow, params, summary_params, projectDir, log, multiqc_report) + } + NfcoreTemplate.summary(workflow, params, log) + if (params.hook_url) { + NfcoreTemplate.adaptivecard(workflow, params, summary_params, projectDir, log) + } +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + THE END +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ From bff33eb9d1c2a6840da36a2e1826ea77686a79bc Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:31:07 +1100 Subject: [PATCH 084/562] Reduce VIRUSBreakend default memory to 60 GB --- conf/base.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/base.config b/conf/base.config index 67c192d2..60d20dca 100644 --- a/conf/base.config +++ b/conf/base.config @@ -132,7 +132,7 @@ process { } withName:'VIRUSBREAKEND' { cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 64.GB, 'memory' ) } + memory = { check_max( 60.GB, 'memory' ) } } withName:'VIRUSINTERPRETER' { cpus = { check_max( 1, 'cpus' ) } From 9b60e78979ecf3433631b9d0a5baa32c7667b284 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:34:08 +1100 Subject: [PATCH 085/562] Enable PAVE gnomAD annotations, update PON filters --- conf/hmfdata.config | 1 + modules/local/pave/somatic/main.nf | 15 ++++++++++++++- nextflow_schema.json | 7 +++++++ subworkflows/local/pave.nf | 2 ++ subworkflows/local/prepare_reference.nf | 1 + workflows/oncoanalyser.nf | 1 + 6 files changed, 26 insertions(+), 1 deletion(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 7b3191a2..04b95d5b 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -45,6 +45,7 @@ params { disease_ontology = 'disease_ontology/201015_doid.json' driver_gene_panel = 'gene_panel/DriverGenePanel.37.tsv' ensembl_data_resources = 'ensembl_data_cache/' + gnomad_pon_dir = 'gnomad/' known_fusion_data = 'fusions/known_fusion_data.37.csv' known_fusions = 'fusions/known_fusions.37.bedpe' purple_germline_del = 'purple/cohort_germline_del_freq.37.csv' diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 23edf378..f3e1d807 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -15,6 +15,7 @@ process PAVE_SOMATIC { path segment_mappability path driver_gene_panel path ensembl_data_resources + path gnomad_pon_dir output: tuple val(meta), path("*.vcf.gz") , emit: vcf @@ -26,7 +27,18 @@ process PAVE_SOMATIC { script: def args = task.ext.args ?: '' - def pon_filters = "HOTSPOT:5:5;PANEL:2:5;UNKNOWN:2:0" + def pon_filters + def gnomad_args + if (genome_ver == '37') { + pon_filters = 'HOTSPOT:10:5;PANEL:6:5;UNKNOWN:6:0' + gnomad_args = '' + } else if (genome_ver == '38') { + pon_filters = 'HOTSPOT:5:5;PANEL:2:5;UNKNOWN:2:0' + gnomad_args = "-gnomad_freq_dir \"${gnomad_pon_dir}\" -gnomad_load_chr_on_demand" + } else { + log.error "got bad genome version: ${genome_ver}" + System.exit(1) + } """ java \\ @@ -42,6 +54,7 @@ process PAVE_SOMATIC { -mappability_bed ${segment_mappability} \\ -vcf_file ${sage_vcf} \\ -read_pass_only \\ + ${gnomad_args} \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information. diff --git a/nextflow_schema.json b/nextflow_schema.json index fe40ceb1..8a13ef81 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -399,6 +399,13 @@ "fa_icon": "far fa-folder-open", "hidden": true }, + "ref_data_gnomad_pon_dir": { + "type": "string", + "format": "directory-path", + "description": "Path to HMF gnomAD PON directory.", + "fa_icon": "far fa-folder-open", + "hidden": true + }, "ref_data_known_fusion_data": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/pave.nf b/subworkflows/local/pave.nf index f1eab61c..a5100f71 100644 --- a/subworkflows/local/pave.nf +++ b/subworkflows/local/pave.nf @@ -19,6 +19,7 @@ workflow PAVE { ref_data_segment_mappability // file: /path/to/segment_mappability ref_data_driver_gene_panel // file: /path/to/driver_gene_panel ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + ref_data_gnomad_pon_dir // file: /path/to/gnomad_pon_dir/ main: // Channel for version.yml files @@ -49,6 +50,7 @@ workflow PAVE { ref_data_segment_mappability, ref_data_driver_gene_panel, ref_data_ensembl_data_resources, + ref_data_gnomad_pon_dir, ) ch_versions = ch_versions.mix(PAVE_SOMATIC.out.versions) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index ad501efb..adc8191b 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -170,6 +170,7 @@ def createHmfDataMap(hmf_data_base, params_only) { disease_ontology: 'ref_data_disease_ontology', driver_gene_panel: 'ref_data_driver_gene_panel', ensembl_data_resources: 'ref_data_ensembl_data_resources', + gnomad_pon_dir: 'ref_data_gnomad_pon_dir', known_fusion_data: 'ref_data_known_fusion_data', known_fusions: 'ref_data_known_fusions', purple_germline_del: 'ref_data_purple_germline_del', diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 280c7045..09d205d5 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -498,6 +498,7 @@ workflow ONCOANALYSER { hmf_data.segment_mappability, hmf_data.driver_gene_panel, hmf_data.ensembl_data_resources, + hmf_data.gnomad_pon_dir, ) // Set outputs, restoring original meta From a1051b601af0c4b088231be76b19ec39081a3018 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:35:00 +1100 Subject: [PATCH 086/562] Move GRCh37_hmf genome check/restriction --- lib/WorkflowOncoanalyser.groovy | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 233606cc..9f5eb91c 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -16,13 +16,6 @@ class WorkflowOncoanalyser { // public static void initialise(params, workflow, log) { - // NOTE(SW): restricting allowable genome values to GRCh37_hmf for now - if (params.genome != 'GRCh37_hmf') { - log.error "ERROR: currently only the GRCh37_hmf genome is supported but got \"${params.genome}\"" + - ", please adjust the --genome argument accordingly." - System.exit(1) - } - // TODO(SW): allow users to set all appropriate reference genomes manually in config or CLI, including version and type (see below) if (!params.genome) { @@ -41,6 +34,13 @@ class WorkflowOncoanalyser { System.exit(1) } + // NOTE(SW): restricting allowable genome values to GRCh37_hmf for now + if (params.genome != 'GRCh37_hmf') { + log.error "ERROR: currently only the GRCh37_hmf genome is supported but got \"${params.genome}\"" + + ", please adjust the --genome argument accordingly." + System.exit(1) + } + if (Constants.GENOMES_VERSION_37.contains(params.genome)) { params.ref_data_genome_version = '37' } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { From 38be34e3ebce9649fe4e29d5be1ef7ccb698fbfa Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:36:14 +1100 Subject: [PATCH 087/562] Provide PON to germline LINX --- modules/local/linx/germline/main.nf | 4 ++++ subworkflows/local/linx.nf | 4 ++++ workflows/oncoanalyser.nf | 2 ++ 3 files changed, 10 insertions(+) diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index ccad0f1b..32e4644d 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -11,6 +11,8 @@ process LINX_GERMLINE { path lines path ensembl_data_resources path driver_gene_panel + path pon_breakends + path pon_breakpoints output: tuple val(meta), path('linx_germline/'), emit: annotation_dir @@ -36,6 +38,8 @@ process LINX_GERMLINE { -ensembl_data_dir ${ensembl_data_resources} \\ -check_drivers \\ -driver_gene_panel ${driver_gene_panel} \\ + -germine_pon_sgl_file ${pon_breakends} \\ + -germine_pon_sv_file ${pon_breakpoints} \\ -output_dir linx_germline/ cat <<-END_VERSIONS > versions.yml diff --git a/subworkflows/local/linx.nf b/subworkflows/local/linx.nf index ffe82d7b..96db9483 100644 --- a/subworkflows/local/linx.nf +++ b/subworkflows/local/linx.nf @@ -16,6 +16,8 @@ workflow LINX { ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ ref_data_known_fusion_data // file: /path/to/known_fusion_data ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + ref_data_gridss_pon_breakends // file: /path/to/gridss_pon_breakends + ref_data_gridss_pon_breakpoints // file: /path/to/gridss_pon_breakpoints main: // Channel for versions.yml files @@ -29,6 +31,8 @@ workflow LINX { ref_data_linx_lines, ref_data_ensembl_data_resources, ref_data_driver_gene_panel, + ref_data_gridss_pon_breakends, + ref_data_gridss_pon_breakpoints, ) ch_versions = ch_versions.mix(LINX_GERMLINE.out.versions) diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 09d205d5..2b77cfce 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -821,6 +821,8 @@ workflow ONCOANALYSER { hmf_data.ensembl_data_resources, hmf_data.known_fusion_data, hmf_data.driver_gene_panel, + hmf_data.gridss_pon_breakends, + hmf_data.gridss_pon_breakpoints, ) // Set outputs, restoring original meta From 13d0e21d1a28a35b1711db513aba9d71435da1f7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:36:56 +1100 Subject: [PATCH 088/562] Remove check_drivers flag from LINX germline --- modules/local/linx/germline/main.nf | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 32e4644d..761a3289 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -36,7 +36,6 @@ process LINX_GERMLINE { -fragile_site_file ${fragile_regions} \\ -line_element_file ${lines} \\ -ensembl_data_dir ${ensembl_data_resources} \\ - -check_drivers \\ -driver_gene_panel ${driver_gene_panel} \\ -germine_pon_sgl_file ${pon_breakends} \\ -germine_pon_sv_file ${pon_breakpoints} \\ From 9b49055b5b32b7443e10c5a35062751354054838 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:37:15 +1100 Subject: [PATCH 089/562] Use write_vis_data in LINX somatic command --- modules/local/linx/somatic/main.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 33958b45..1db11f4a 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -39,6 +39,7 @@ process LINX_SOMATIC { -known_fusion_file ${known_fusion_data} \\ -check_drivers \\ -driver_gene_panel ${driver_gene_panel} \\ + -write_vis_data \\ -output_dir linx_somatic/ cat <<-END_VERSIONS > versions.yml From 83881b99f31249485b706a50cc3c1217554f6c57 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:37:52 +1100 Subject: [PATCH 090/562] Set PAVE to write only passing variants --- modules/local/pave/germline/main.nf | 1 + modules/local/pave/somatic/main.nf | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 536e52cf..e4fb5f29 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -49,6 +49,7 @@ process PAVE_GERMLINE { -mappability_bed ${segment_mappability} \\ -vcf_file ${sage_vcf} \\ -read_pass_only \\ + -write_pass_only \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information. diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index f3e1d807..972144ab 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -54,6 +54,7 @@ process PAVE_SOMATIC { -mappability_bed ${segment_mappability} \\ -vcf_file ${sage_vcf} \\ -read_pass_only \\ + -write_pass_only \\ ${gnomad_args} \\ -output_dir ./ From d27f84de1c53e2893f49a7ba2ca2956e7d1440f8 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:39:02 +1100 Subject: [PATCH 091/562] Create hard filtered SAGE VCF --- modules/local/sage/germline/main.nf | 14 +++++++++----- modules/local/sage/somatic/main.nf | 20 ++++++++++++-------- subworkflows/local/sage.nf | 4 ++-- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 645f284c..f53b49ce 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -17,9 +17,10 @@ process SAGE_GERMLINE { path ensembl_data_resources output: - tuple val(meta), path("${meta.tumor_id}.sage_germline.vcf.gz"), emit: vcf - tuple val(meta), path('*gene.coverage.tsv') , emit: gene_coverage, optional: true - path 'versions.yml' , emit: versions + tuple val(meta), path("${meta.tumor_id}.sage.germline.vcf.gz") , emit: vcf + tuple val(meta), path("${meta.tumor_id}.sage.germline.filtered.vcf.gz"), emit: vcf_filtered + tuple val(meta), path('*gene.coverage.tsv') , emit: gene_coverage, optional: true + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -52,7 +53,9 @@ process SAGE_GERMLINE { -mnv_filter_enabled false \\ -panel_only \\ -threads ${task.cpus} \\ - -out ./${meta.tumor_id}.sage_germline.vcf.gz + -out ./${meta.tumor_id}.sage.germline.vcf.gz + + bcftools view -f 'PASS' -o ${meta.tumor_id}.sage.germline.filtered.vcf.gz ${meta.tumor_id}.sage.germline.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -62,7 +65,8 @@ process SAGE_GERMLINE { stub: """ - touch "${meta.tumor_id}.sage_germline.vcf.gz" + touch "${meta.tumor_id}.sage.germline.vcf.gz" + touch "${meta.tumor_id}.sage.germline.filtered.vcf.gz" touch "${meta.tumor_id}.gene.coverage.tsv" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 443acb44..87c05188 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -18,12 +18,13 @@ process SAGE_SOMATIC { path ensembl_data_resources output: - tuple val(meta), path("${meta.tumor_id}.sage_somatic.vcf.gz"), emit: vcf - tuple val(meta), path("${meta.tumor_id}.sage.bqr.png") , emit: tumor_bqr_png, optional: true - tuple val(meta), path("${meta.normal_id}.sage.bqr.png") , emit: normal_bqr_png, optional: true - path '*gene.coverage.tsv' , emit: gene_coverage, optional: true - path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true - path 'versions.yml' , emit: versions + tuple val(meta), path("${meta.tumor_id}.sage.somatic.vcf.gz") , emit: vcf + tuple val(meta), path("${meta.tumor_id}.sage.somatic.filtered.vcf.gz"), emit: vcf_filtered + tuple val(meta), path("${meta.tumor_id}.sage.bqr.png") , emit: tumor_bqr_png, optional: true + tuple val(meta), path("${meta.normal_id}.sage.bqr.png") , emit: normal_bqr_png, optional: true + path '*gene.coverage.tsv' , emit: gene_coverage, optional: true + path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -50,7 +51,9 @@ process SAGE_SOMATIC { -write_bqr_data \\ -write_bqr_plot \\ -threads ${task.cpus} \\ - -out ./${meta.tumor_id}.sage_somatic.vcf.gz + -out ./${meta.tumor_id}.sage.somatic.vcf.gz + + bcftools view -f 'PASS' -o ${meta.tumor_id}.sage.somatic.filtered.vcf.gz ${meta.tumor_id}.sage.somatic.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -60,7 +63,8 @@ process SAGE_SOMATIC { stub: """ - touch "${meta.tumor_id}.sage_somatic.vcf.gz" + touch "${meta.tumor_id}.sage.somatic.vcf.gz" + touch "${meta.tumor_id}.sage.somatic.filtered.vcf.gz" touch "${meta.tumor_id}.sage.bqr.png" touch "${meta.normal_id}.sage.bqr.png" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml diff --git a/subworkflows/local/sage.nf b/subworkflows/local/sage.nf index 68260406..b18ef1d0 100644 --- a/subworkflows/local/sage.nf +++ b/subworkflows/local/sage.nf @@ -56,9 +56,9 @@ workflow SAGE { ch_versions = ch_versions.mix(SAGE_SOMATIC.out.versions) emit: - germline_vcf = SAGE_GERMLINE.out.vcf // channel: [val(meta), sage_vcf] + germline_vcf = SAGE_GERMLINE.out.vcf_filtered // channel: [val(meta), sage_vcf] germline_coverage = SAGE_GERMLINE.out.gene_coverage // channel: [val(meta), sage_coverage] - somatic_vcf = SAGE_SOMATIC.out.vcf // channel: [val(meta), sage_vcf] + somatic_vcf = SAGE_SOMATIC.out.vcf_filtered // channel: [val(meta), sage_vcf] somatic_tumor_bqr = SAGE_SOMATIC.out.tumor_bqr_png // channel: [val(meta), sage_bqr_plot] somatic_normal_bqr = SAGE_SOMATIC.out.normal_bqr_png // channel: [val(meta), sage_brq_plot] From 065315131f06551bc9d059b4f287ca460f283de7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:39:22 +1100 Subject: [PATCH 092/562] Realign long comment --- modules/local/sage/somatic/main.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 87c05188..4fc18c16 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -1,4 +1,5 @@ -// NOTE(SW): logic that determines BQR outputs assumes '-out' is a path that includes at least one directory +// NOTE(SW): logic that determines BQR outputs assumes '-out' is a path that includes at least +// leading one directory process SAGE_SOMATIC { tag "${meta.id}" From ab6a9fa131eb9d20749d14bcf82d22d29718f06d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:39:43 +1100 Subject: [PATCH 093/562] Correct NF schema argument name --- nextflow_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 8a13ef81..a8f0d54a 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -392,7 +392,7 @@ "fa_icon": "far fa-file-code", "hidden": true }, - "ref_data_ensembl_data_dir": { + "ref_data_ensembl_data_resources": { "type": "string", "format": "directory-path", "description": "Path to HMF Ensembl data cache directory.", From e0f85f6afc05a7714e08ca3124d66eb398ac9285 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:41:00 +1100 Subject: [PATCH 094/562] Bug fix for common input channel conditional --- workflows/oncoanalyser.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 2b77cfce..566c3302 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -120,7 +120,7 @@ workflow ONCOANALYSER { hmf_data = PREPARE_REFERENCE.out.hmf_data // Set up channel with common inputs for several processes - if (run.amber || run.cobalt || run.pave || run.lilac) { + if (run.amber || run.cobalt || run.sage || run.lilac) { // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] ch_bams_and_indices = ch_inputs .map { meta -> From 1e98563a7e42fea4a73d95ea3c382f34cb7b2ac0 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 19 Jan 2023 09:41:31 +1100 Subject: [PATCH 095/562] Add note regarding PAVE germline naming convention --- workflows/oncoanalyser.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 566c3302..3d1b9eeb 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -471,6 +471,7 @@ workflow ONCOANALYSER { .map { meta, sage_vcf -> def pave_meta = [ key: meta.id, + // NOTE(SW): use of tumor sample name for PAVE germline is correct id: meta.get(['sample_name', Constants.DataType.TUMOR]), ] return [pave_meta, sage_vcf] From 503d5c81346dfc8946a4a1b03f6d2bead1655a46 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 28 Dec 2022 14:28:13 +1100 Subject: [PATCH 096/562] Reinstate SV Prep --- conf/base.config | 3 + conf/hmfdata.config | 2 + conf/modules.config | 12 + lib/Constants.groovy | 1 + lib/Processes.groovy | 2 + modules/local/svprep/Dockerfile | 15 + modules/local/svprep/assemble/main.nf | 92 +++ modules/local/svprep/assets/gridss.svprep | 825 +++++++++++++++++++ modules/local/svprep/call/main.nf | 97 +++ modules/local/svprep/depth_annotator/main.nf | 50 ++ modules/local/svprep/preprocess/main.nf | 57 ++ modules/local/svprep/svprep/main.nf | 61 ++ nextflow_schema.json | 8 + subworkflows/local/gridss_svprep.nf | 226 +++++ subworkflows/local/prepare_reference.nf | 2 + workflows/oncoanalyser.nf | 58 +- 16 files changed, 1492 insertions(+), 19 deletions(-) create mode 100644 modules/local/svprep/Dockerfile create mode 100644 modules/local/svprep/assemble/main.nf create mode 100644 modules/local/svprep/assets/gridss.svprep create mode 100644 modules/local/svprep/call/main.nf create mode 100644 modules/local/svprep/depth_annotator/main.nf create mode 100644 modules/local/svprep/preprocess/main.nf create mode 100644 modules/local/svprep/svprep/main.nf create mode 100644 subworkflows/local/gridss_svprep.nf diff --git a/conf/base.config b/conf/base.config index 60d20dca..bf3f7683 100644 --- a/conf/base.config +++ b/conf/base.config @@ -70,6 +70,9 @@ process { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 1.GB, 'memory' ) } } + withName:'SVPREP.*' { + memory = { check_max( 12.GB, 'memory' ) } + } withName:'.*:GRIDSS:.*' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 30.GB, 'memory' ) } diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 04b95d5b..247e0ade 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -7,6 +7,8 @@ params { gc_profile = 'gc_profiles/GC_profile.1000bp.37.cnp' // CUPPA cuppa_resources = 'cuppa/' + // SV Prep + sv_prep_blocklist = 'svprep/sv_prep_blacklist.37.bed' // GRIDSS gridss_pon_breakends = 'gridss_pon/gridss_pon_single_breakend.37.bed.gz' gridss_pon_breakpoints = 'gridss_pon/gridss_pon_breakpoint.37.bedpe.gz' diff --git a/conf/modules.config b/conf/modules.config index c7d7ab48..0f7aecbb 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -37,6 +37,10 @@ process { ] } + withName:'.*:(? filename.equals('versions.yml') ? null : "${meta.id}/gridss/sv.vcf.gz" } + ] + } + withName: 'GRIPSS.*' { ext.jarPath = '/opt/gripss/gripss.jar' } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index a37c9f74..78af1318 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -35,6 +35,7 @@ class Constants { PURPLE, SAGE, SIGS, + SVPREP, VIRUSINTERPRETER, } diff --git a/lib/Processes.groovy b/lib/Processes.groovy index 1277c10c..7284ce4c 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -27,6 +27,7 @@ class Processes { Constants.Process.GRIPSS, Constants.Process.LINX, Constants.Process.PURPLE, + Constants.Process.SVPREP, ] break case Constants.PipelineMode.CUPPA: @@ -40,6 +41,7 @@ class Processes { Constants.Process.ISOFOX, Constants.Process.LINX, Constants.Process.PURPLE, + Constants.Process.SVPREP, Constants.Process.VIRUSINTERPRETER, ] break diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile new file mode 100644 index 00000000..742d4390 --- /dev/null +++ b/modules/local/svprep/Dockerfile @@ -0,0 +1,15 @@ +FROM docker.io/scwatts/gridss:2.13.2--3 + +ARG GH_BASE_URL='https://github.com/hartwigmedical/hmftools' +USER root + +RUN \ + mkdir -p /opt/svprep/ && \ + wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.1/sv-prep_v1.1_beta.jar' + +COPY assets/gridss.svprep /opt/svprep/gridss_svprep +RUN \ + chmod 755 /opt/svprep/gridss_svprep && \ + ln -s /opt/svprep/gridss_svprep /usr/local/bin/ + +USER mambauser diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf new file mode 100644 index 00000000..bcd32a66 --- /dev/null +++ b/modules/local/svprep/assemble/main.nf @@ -0,0 +1,92 @@ +process ASSEMBLE { + tag "${meta.id}" + label 'process_medium' + + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) + path gridss_config + path genome_fasta + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + path blocklist + + output: + tuple val(meta), path('gridss_assemble/'), emit: assemble_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + def output_dirname = 'gridss_assemble' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = "--bams ${bams_list.join(',')}" + def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] + def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" + + """ + # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation + # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + shadow_input_directory() { + src=\${1} + dst="${output_dirname}/work/\${src##*/}" + for filepath_src in \$(find -L \${src} ! -type d); do + # Get destination location for symlink + filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) + filepath_dst=\${dst%/}/\${filepath_src_rel} + # Create directory for symlink + mkdir -p \${filepath_dst%/*}; + # Get path for symlink source file, then create it + # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only + # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers + symlinkpath=\$(realpath \${filepath_src}) + ln -s \${symlinkpath} \${filepath_dst}; + done + if [[ -L "\${src##*/}" ]]; then + rm "\${src}" + fi + } + for preprocess_dir in ${preprocess_dirs}; do + shadow_input_directory \${preprocess_dir}; + done + + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + # Run + gridss_svprep \\ + ${args} \\ + --jvmheap ${task.memory.giga}g \\ + --jar ${task.ext.jarPath} \\ + --steps assemble \\ + --labels ${labels_arg} \\ + --reference ${genome_fasta} \\ + --blacklist ${blocklist} \\ + --workingdir ${output_dirname}/work \\ + --assembly ${output_dirname}/sv_assemblies.bam \\ + --threads ${task.cpus} \\ + ${config_arg} \\ + ${bams_arg} \\ + ${bams_filtered_arg} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_assemble/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/svprep/assets/gridss.svprep b/modules/local/svprep/assets/gridss.svprep new file mode 100644 index 00000000..d1b1f3e8 --- /dev/null +++ b/modules/local/svprep/assets/gridss.svprep @@ -0,0 +1,825 @@ +#!/bin/bash +# GRIDSS execution script using SvPrep BAMs + +getopt --test +if [[ ${PIPESTATUS[0]} -ne 4 ]]; then + echo 'WARNING: "getopt --test"` failed in this environment.' 1>&2 + echo "WARNING: The version of getopt(1) installed on this system might not be compatible with the GRIDSS driver script." 1>&2 +fi +unset DISPLAY # Prevents errors attempting to connecting to an X server when starting the R plotting device +ulimit -n $(ulimit -Hn 2>/dev/null) 2>/dev/null # Reduce likelihood of running out of open file handles +set -o errexit -o pipefail -o noclobber -o nounset +last_command="" +current_command="" +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'echo "\"${last_command}\" command completed with exit code $?."' EXIT +#253 forcing C locale for everything +export LC_ALL=C + +EX_USAGE=64 +EX_NOINPUT=66 +EX_CANTCREAT=73 +EX_CONFIG=78 + +workingdir="." +reference="" +output_vcf="" +assembly="" +threads=8 +jvmheap="30g" +otherjvmheap="4g" +blacklist="" +metricsrecords=10000000 +maxcoverage=50000 +config_file="" +labels="" +bams="" +filtered_bams="" +full_bams="" +keepTempFiles="false" + +steps="all" +do_preprocess=false +do_assemble=false +do_call=false + +USAGE_MESSAGE=" +Usage: gridss [options] -r -o -a input1.bam [input2.bam [...]] + + -r/--reference: reference genome to use. + -o/--output: output VCF. + -a/--assembly: location of the GRIDSS assembly BAM. This file will be + created by GRIDSS. + -t/--threads: number of threads to use. (Default: $threads) + -j/--jar: location of GRIDSS jar + -w/--workingdir: directory to place GRIDSS intermediate and temporary files + .gridss.working subdirectories will be created. (Default: $workingdir) + -s/--steps: processing steps to run. Defaults to all steps. + Multiple steps are specified using comma separators. Possible steps are: + preprocess, assemble, call, all + -e/--blacklist: BED file containing regions to ignore + -c/--configuration: configuration file use to override default GRIDSS + settings. + -l/--labels: comma separated labels to use in the output VCF for the input + files. Supporting read counts for input files with the same label are + aggregated (useful for multiple sequencing runs of the same sample). + Labels default to input filenames, unless a single read group with a + non-empty sample name exists in which case the read group sample name + is used (which can be disabled by \"useReadGroupSampleNameCategoryLabel=false\" + in the configuration file). If labels are specified, they must be + specified for all input files. + -b/bams: comma separated full-path BAM files + -f/filtered_bams: comma separated full-path filtered BAM files + --jvmheap: size of JVM heap for the high-memory component of assembly and variant calling. (Default: $jvmheap) + " + +OPTIONS=r:o:a:t:j:w:e:s:c:l:b:f: +LONGOPTS=reference:,output:,assembly:,threads:,jar:,workingdir:,jvmheap:,blacklist:,steps:,configuration:,labels:,bams:,filtered_bams: +! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") +if [[ ${PIPESTATUS[0]} -ne 0 ]]; then + # e.g. return value is 1 + # then getopt has complained about wrong arguments to stdout + echo "$USAGE_MESSAGE" 1>&2 + exit $EX_USAGE +fi +eval set -- "$PARSED" + +POSITIONAL_ARGS=() + +#while true; do +while [[ $# -gt 0 ]]; do + case "$1" in + -r|--reference) + reference="$2" + shift 2 + ;; + -l|--labels) + labels="$2" + shift 2 + ;; + -b|--bams) + bams="$2" + shift 2 + ;; + -f|--filtered_bams) + filtered_bams="$2" + shift 2 + ;; + -s|--steps) + steps="$2" + shift 2 + ;; + -w|--workingdir) + workingdir="$2" + shift 2 + ;; + -o|--output) + output_vcf="$2" + shift 2 + ;; + -a|--assembly) + if [[ "$assembly" == "" ]] ; then + assembly="$2" + else + assembly="$assembly $2" + fi + # TODO: support multiple assembly files + shift 2 + ;; + -e|--blacklist) + blacklist="$2" + shift 2 + ;; + -j|--jar) + GRIDSS_JAR="$2" + shift 2 + ;; + --jvmheap) + jvmheap="$2" + shift 2 + ;; + -t|--threads) + printf -v threads '%d\n' "$2" 2>/dev/null + printf -v threads '%d' "$2" 2>/dev/null + shift 2 + ;; + -c|--configuration) + config_file=$2 + shift 2 + ;; + *) + POSITIONAL_ARGS+=("$1") # save positional arg + # echo "Unparsed param" + shift + ;; + esac +done + +##### --workingdir +echo "Using working directory \"$workingdir\"" 1>&2 +if [[ "$workingdir" == "" ]] ; then + echo "$USAGE_MESSAGE" 1>&2 + echo "Working directory must be specified. Specify using the --workingdir command line argument" 1>&2 + exit $EX_USAGE +fi +if [[ "$(tr -d ' \n' <<< "$workingdir")" != "$workingdir" ]] ; then + echo "workingdir cannot contain whitespace" 1>&2 + exit $EX_USAGE + fi +if [[ ! -d $workingdir ]] ; then + mkdir -p $workingdir + if [[ ! -d $workingdir ]] ; then + echo Unable to create working directory $workingdir 1>&2 + exit $EX_CANTCREAT + fi +fi +workingdir=$(dirname $workingdir/placeholder) +timestamp=$(date +%Y%m%d_%H%M%S) +# Logging +logfile=$workingdir/gridss.full.$timestamp.$HOSTNAME.$$.log +# $1 is message to write +write_status() { + echo "$(date): $1" | tee -a $logfile 1>&2 +} +write_status "Full log file is: $logfile" +trap 'echo "\"${last_command}\" command completed with exit code $?. +***** +The underlying error message can be found in $logfile +*****"' EXIT +# Timing instrumentation +timinglogfile=$workingdir/gridss.timing.$timestamp.$HOSTNAME.$$.log +if which /usr/bin/time >/dev/null ; then + timecmd="/usr/bin/time" + write_status "Found /usr/bin/time" +else + timecmd="" + write_status "Not found /usr/bin/time" +fi +if [[ "$timecmd" != "" ]] ; then + timecmd="/usr/bin/time --verbose -a -o $timinglogfile" + if ! $timecmd echo 2>&1 > /dev/null; then + timecmd="/usr/bin/time -a -o $timinglogfile" + fi + if ! $timecmd echo 2>&1 > /dev/null ; then + timecmd="" + write_status "Unexpected /usr/bin/time version. Not logging timing information." + fi + # We don't need timing info of the echo + rm -f $timinglogfile +fi + +### Find the jars +find_jar() { + env_name=$1 + if [[ -f "${!env_name:-}" ]] ; then + echo "${!env_name}" + else + write_status "Unable to find $2 jar. Specify using the environment variant $env_name, or the --jar command line parameter." + exit $EX_NOINPUT + fi +} +gridss_jar=$(find_jar GRIDSS_JAR gridss) +write_status "Using GRIDSS jar $gridss_jar" + +# Check all key inputs: + +if [[ "$labels" == "" ]] ; then + write_status "Labels must be specified" + exit $EX_USAGE +fi + +if [[ "$bams" == "" ]] ; then + write_status "Full BAMs must be specified" + exit $EX_USAGE +fi + +if [[ "$filtered_bams" == "" ]] ; then + write_status "Filtered BAMs must be specified" + exit $EX_USAGE +fi + +##### --reference +if [[ "$reference" == "" ]] ; then + write_status "$USAGE_MESSAGE" + write_status "Reference genome must be specified. Specify using the --reference command line argument" + exit $EX_USAGE +fi + +if [ ! -f $reference ] ; then + write_status "$USAGE_MESSAGE" + write_status "Missing reference genome $reference. Specify reference location using the --reference command line argument" + exit $EX_USAGE +fi +write_status "Using reference genome \"$reference\"" + +##### --output +if [[ $do_call == "true" ]] ; then + if [[ "$output_vcf" == "" ]] ; then + write_status "$USAGE_MESSAGE" + write_status "Output VCF not specified. Use --output to specify output file." + exit $EX_USAGE + fi + mkdir -p $(dirname $output_vcf) + if [[ ! -d $(dirname $output_vcf) ]] ; then + write_status "Unable to create directory for $output_vcf for output VCF." + exit $EX_CANTCREAT + fi + write_status "Using output VCF $output_vcf" +fi +write_status "Using output VCF $output_vcf" + +##### --assembly +if [[ $do_assemble == "true" ]] || [[ $do_call == "true" ]]; then + if [[ "$assembly" == "" ]] ; then + if [[ "$output_vcf" == "" ]] ; then + write_status "Either the assembly output file must explicitly specified with -a, or the output VCF specified with -o" + exit $EX_USAGE + fi + assembly=$output_vcf.assembly.bam + fi + write_status "Using assembly bam $assembly" + if [[ $do_assemble == "true" ]] ; then + mkdir -p $(dirname $assembly) + if [[ ! -d $(dirname $assembly) ]] ; then + write_status "Unable to parent create directory for $assembly" + exit $EX_CANTCREAT + fi + else + if [[ ! -f $assembly ]] ; then + write_status "Missing assembly file $assembly" + write_status "Ensure the GRIDSS assembly step has been run" + exit $EX_NOINPUT + fi + fi +fi + +##### --threads +if [[ "$threads" -lt 1 ]] ; then + write_status "$USAGE_MESSAGE" + write_status "Illegal thread count: $threads. Specify an integer thread count using the --threads command line argument" + exit $EX_USAGE +fi +if [[ "$threads" -gt 8 ]] ; then + write_status "WARNING: GRIDSS scales sub-linearly at high thread count. Up to 8 threads is the recommended level of parallelism." +fi +write_status "Using $threads worker threads." + +if [[ "$blacklist" == "" ]] ; then + blacklist_arg="" + write_status "Using no blacklist bed. The encode DAC blacklist is recommended for hg19." +elif [[ ! -f $blacklist ]] ; then + write_status "$USAGE_MESSAGE" + write_status "Missing blacklist file $blacklist" + exit $EX_NOINPUT +else + blacklist_arg="BLACKLIST=$blacklist" + write_status "Using blacklist $blacklist" + if [[ "$(tr -d ' \n' <<< "$blacklist_arg")" != "$blacklist_arg" ]] ; then + write_status "blacklist cannot contain whitespace" + exit $EX_USAGE + fi +fi + +if [[ "$jvmheap" == "" ]] ; then + if [[ $threads -gt 8 ]] ; then + write_status "Warning: GRIDSS assembly may stall and run out of memory. with $threads and $jvmheap heap size." + fi +fi + +write_status "Using JVM maximum heap size of $jvmheap for assembly and variant calling." + +config_args="" +if [[ "$config_file" != "" ]] ; then + if [[ ! -f $config_file ]] ; then + write_status "Configuration file $config_file does not exist" + exit $EX_NOINPUT + fi + config_args="CONFIGURATION_FILE=$config_file" +fi + +input_args="" +input_filtered_args="" + +# no longer read in the BAM file list from the end of the arguments list + +nows_labels=$(tr -d ' \n' <<< "$labels") +if [[ "$nows_labels" != "$labels" ]] ; then + write_status "input labels cannot contain whitespace" + exit $EX_USAGE +fi +IFS=',' read -ra LABEL_ARRAY <<< "$nows_labels" +label_count=${#LABEL_ARRAY[@]} + +for label in "${LABEL_ARRAY[@]}" ; do + input_args="$input_args INPUT_LABEL=$label" + input_filtered_args="$input_filtered_args INPUT_LABEL=$label" + #write_status "label is $label" +done + +nows_bams=$(tr -d ' \n' <<< "$bams") +if [[ "$nows_bams" != "$bams" ]] ; then + write_status "input filtered BAMs cannot contain whitespace" + exit $EX_USAGE +fi +IFS=',' read -ra BAM_ARRAY <<< "$nows_bams" +for bam_file in "${BAM_ARRAY[@]}" ; do + + if [[ "$(basename $bam_file)" == "$(basename $assembly)" ]] ; then + write_status "assembly and input filtered bam files must have different filenames" + exit $EX_USAGE + fi + + input_args="$input_args INPUT=$bam_file" + # write_status "full bam file is $bam_file" +done + +nows_bams=$(tr -d ' \n' <<< "$filtered_bams") +if [[ "$nows_bams" != "$filtered_bams" ]] ; then + write_status "input filtered BAMs cannot contain whitespace" + exit $EX_USAGE +fi +IFS=',' read -ra FILT_BAM_ARRAY <<< "$nows_bams" +for filtered_bam_file in "${FILT_BAM_ARRAY[@]}" ; do + + if [[ "$(basename $filtered_bam_file)" == "$(basename $assembly)" ]] ; then + write_status "assembly and input filtered bam files must have different filenames" + exit $EX_USAGE + fi + + input_filtered_args="$input_filtered_args INPUT=$filtered_bam_file" + # write_status "filtered bam file is $filtered_bam_file" +done + +for (( i=0; i < $label_count; ++i )) +do + write_status "Label $i: name=${LABEL_ARRAY[$i]} full-bam=${BAM_ARRAY[$i]} filtered-bam=${FILT_BAM_ARRAY[$i]}" +done + +write_status "Full BAM args: $input_args" +write_status "Filtered BAM args: $input_filtered_args" + + +# Validate tools exist on path +for tool in Rscript samtools java bwa ; do #minimap2 + if ! which $tool >/dev/null; then + write_status "Error: unable to find $tool on \$PATH" + exit $EX_CONFIG + fi + write_status "Found $(which $tool)" +done +if $(samtools --version-only >/dev/null) ; then + write_status "samtools version: $(samtools --version-only 2>&1)" +else + write_status "Your samtools version does not support --version-only. Update samtools." + exit $EX_CONFIG +fi +if [[ "$(samtools --version-only)" =~ ^([0-9]+)[.]([0-9]+) ]] ; then + samtools_major_version=${BASH_REMATCH[1]} + samtools_minor_version=${BASH_REMATCH[2]} + if [[ "$samtools_major_version" -le 1 ]] && [[ "$samtools_minor_version" -lt 10 ]] ; then + write_status "samtools 1.13 or later is required." + exit $EX_CONFIG + fi +else + write_status "Unable to determine samtools version" + exit $EX_CONFIG +fi + +# write_status "R version: $(Rscript --version 2>&1)" + +write_status "bwa $(bwa 2>&1 | grep Version || echo -n)" + +if [[ "$timecmd" != "" ]] ; then + if which /usr/bin/time >/dev/null ; then + write_status "time version: $(/usr/bin/time --version 2>&1)" + fi +fi +write_status "bash version: $(/bin/bash --version 2>&1 | head -1)" + +# check java version is ok using the gridss.Echo entry point +if java -cp $gridss_jar gridss.Echo ; then + write_status "java version: $(java -version 2>&1 | tr '\n' '\t')" +else + write_status "Unable to run GRIDSS jar - requires java 1.8 or later" + write_status "java version: $(java -version 2>&1)" + exit $EX_CONFIG +fi + +if ! java -Xms$jvmheap -cp $gridss_jar gridss.Echo ; then + write_status "Failure invoking java with --jvmheap parameter of \"$jvmheap\". Specify a JVM heap size (e.g. \"31g\") that is valid for this machine." + exit 1 +fi + +write_status "Max file handles: $(ulimit -n)" 1>&2 + +steps_message="Running GRIDSS steps:" + +for step in $(echo $steps | tr ',' ' ' ) ; do + if [[ "$step" == "all" ]] ; then + do_preprocess=true + do_assemble=true + do_call=true + steps_message="$steps_message all" + elif [[ "$step" == "preprocess" ]] ; then + do_preprocess=true + steps_message="$steps_message pre-process" + elif [[ "$step" == "assemble" ]] ; then + do_assemble=true + steps_message="$steps_message assembly" + elif [[ "$step" == "call" ]] ; then + do_call=true + steps_message="$steps_message call" + else + write_status "Unknown step \"$step\"" + exit $EX_USAGE + fi +done + +write_status "$steps_message" + +# don't keep files +if [[ $keepTempFiles == "true" ]] ; then + rmcmd="echo rm disabled:" + jvm_args="-Dgridss.keepTempFiles=true" +else + rmcmd="rm" + jvm_args="" +fi + +jvm_args="$jvm_args \ + -XX:ParallelGCThreads=$threads \ + -Dsamjdk.reference_fasta=$reference \ + -Dsamjdk.use_async_io_read_samtools=true \ + -Dsamjdk.use_async_io_write_samtools=true \ + -Dsamjdk.use_async_io_write_tribble=true \ + -Dsamjdk.buffer_size=4194304 \ + -Dsamjdk.async_io_read_threads=$threads" + +aligner_args=' + ALIGNER_COMMAND_LINE=null + ALIGNER_COMMAND_LINE=bwa + ALIGNER_COMMAND_LINE=mem + ALIGNER_COMMAND_LINE=-K + ALIGNER_COMMAND_LINE=10000000 + ALIGNER_COMMAND_LINE=-L + ALIGNER_COMMAND_LINE=0,0 + ALIGNER_COMMAND_LINE=-t + ALIGNER_COMMAND_LINE=%3$d + ALIGNER_COMMAND_LINE=%2$s + ALIGNER_COMMAND_LINE=%1$s' + +samtools_sort="samtools sort --no-PG -@ $threads" + +readpairing_args="READ_PAIR_CONCORDANT_PERCENT=null" + + +# set-up reference has been removed since can assume to exist + +#### +# Pre-process for each filtered BAM file +#### + +if [[ $do_preprocess == true ]] ; then + write_status "*** PRE-PROCESS ***" + + for (( i=0; i < $label_count; ++i )) + do + label=${LABEL_ARRAY[$i]} + bam_file=${FILT_BAM_ARRAY[$i]} + write_status "Processing: sample ${LABEL_ARRAY[$i]}, filtered-bam ${FILT_BAM_ARRAY[$i]}" + + dir=$workingdir/$(basename $bam_file).gridss.working + prefix=$dir/$(basename $bam_file) + write_status "Start pre-processing: $bam_file, working dir: $dir, prefix: $prefix" + + tmp_prefix=$workingdir/$(basename $bam_file).gridss.working/tmp.$(basename $bam_file) + mkdir -p $dir + if [[ ! -d $dir ]] ; then + write_status "Unable to create directory $dir" + exit $EX_CANTCREAT + fi + + name_sorted_bam=$tmp_prefix.namedsorted.bam + write_status "Creating name-sorted BAM from $bam_file, writing to $name_sorted_bam" + + $timecmd $samtools_sort -l 1 -n \ + -T $tmp_prefix.namedsorted-tmp \ + -Obam \ + -o ${name_sorted_bam} \ + ${bam_file} + + write_status "Running ComputeSamTags|samtools: $bam_file" + + rm -f $tmp_prefix.coordinate-tmp* + + { $timecmd java -Xmx$otherjvmheap $jvm_args \ + -cp $gridss_jar gridss.ComputeSamTags \ + TMP_DIR=$dir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + COMPRESSION_LEVEL=0 \ + I=$name_sorted_bam \ + O=/dev/stdout \ + WORKER_THREADS=$threads \ + ASSUME_SORTED=true \ + REMOVE_TAGS=aa \ + MODIFICATION_SUMMARY_FILE=$prefix.computesamtags.changes.tsv \ + | $timecmd $samtools_sort \ + -l 1 \ + -T $tmp_prefix.coordinate-tmp \ + -Obam \ + -o $tmp_prefix.coordinate.bam \ + /dev/stdin \ + ; } 1>&2 2>> $logfile + + write_status "Removing name-sorted bam: $tmp_prefix.namedsorted.bam" + $rmcmd $tmp_prefix.namedsorted.bam + + write_status "Running SoftClipsToSplitReads: sample $label, input: $tmp_prefix.coordinate.bam, output: $tmp_prefix.sc2sr.primary.sv.bam" + rm -f $tmp_prefix.sc2sr.suppsorted.sv-tmp* + { $timecmd java -Xmx$otherjvmheap $jvm_args \ + -Dsamjdk.create_index=false \ + -cp $gridss_jar gridss.SoftClipsToSplitReads \ + TMP_DIR=$workingdir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + I=$tmp_prefix.coordinate.bam \ + O=$tmp_prefix.sc2sr.primary.sv.bam \ + COMPRESSION_LEVEL=1 \ + OUTPUT_UNORDERED_RECORDS=$tmp_prefix.sc2sr.supp.sv.bam \ + WORKER_THREADS=$threads \ + $aligner_args \ + && $rmcmd $tmp_prefix.coordinate.bam \ + && $timecmd $samtools_sort \ + -l 1 \ + -T $tmp_prefix.sc2sr.suppsorted.sv-tmp \ + -Obam \ + -o $tmp_prefix.sc2sr.suppsorted.sv.bam \ + $tmp_prefix.sc2sr.supp.sv.bam \ + && $rmcmd $tmp_prefix.sc2sr.supp.sv.bam \ + && $rmcmd -f $prefix.sv.tmp.bam $prefix.sv.tmp.bam.bai \ + && $timecmd samtools merge \ + -c \ + -p \ + --write-index \ + -@ $threads \ + $prefix.sv.tmp.bam \ + $tmp_prefix.sc2sr.primary.sv.bam \ + $tmp_prefix.sc2sr.suppsorted.sv.bam \ + && $rmcmd $tmp_prefix.sc2sr.primary.sv.bam \ + && $rmcmd $tmp_prefix.sc2sr.suppsorted.sv.bam \ + && mv $prefix.sv.tmp.bam $prefix.sv.bam \ + && mv $prefix.sv.tmp.bam.csi $prefix.sv.bam.csi \ + ; } 1>&2 2>> $logfile + + write_status "Produced SV bam:: $prefix.sv.bam" + + # create metrics on the full BAM and then copy these over the metrics made from the filtered BAMs + full_bam_file=${BAM_ARRAY[$i]} + write_status "Running CollectGridssMetrics on $label full BAM $full_bam_file" + + # test_prefix=$prefix.cp + + { $timecmd java -Xmx$otherjvmheap $jvm_args \ + -cp $gridss_jar gridss.analysis.CollectGridssMetrics \ + REFERENCE_SEQUENCE=$reference \ + TMP_DIR=$dir \ + ASSUME_SORTED=true \ + I=$full_bam_file \ + O=$prefix \ + THRESHOLD_COVERAGE=$maxcoverage \ + FILE_EXTENSION=null \ + GRIDSS_PROGRAM=null \ + GRIDSS_PROGRAM=CollectCigarMetrics \ + GRIDSS_PROGRAM=CollectMapqMetrics \ + GRIDSS_PROGRAM=CollectTagMetrics \ + GRIDSS_PROGRAM=CollectIdsvMetrics \ + PROGRAM=null \ + PROGRAM=CollectInsertSizeMetrics \ + STOP_AFTER=$metricsrecords \ + ; } 1>&2 2>> $logfile + + write_status "Complete pre-processing sample: $label" + done + + write_status "*** PRE-PROCESS COMPLETE ***" +fi + +##### +# ASSEMBLY +#### + +assembly_args="ASSEMBLY=$assembly" + +if [[ $do_assemble == true ]] ; then + + write_status "*** ASSEMBLY ***" + write_status "Running AssembleBreakends: writing output to dir $assembly" + { $timecmd java -Xmx$jvmheap $jvm_args \ + -Dgridss.output_to_temp_file=true \ + -cp $gridss_jar gridss.AssembleBreakends \ + JOB_INDEX=0 \ + JOB_NODES=1 \ + TMP_DIR=$workingdir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + WORKER_THREADS=$threads \ + $input_filtered_args \ + $blacklist_arg \ + $config_args \ + $readpairing_args \ + O=$assembly \ + ; } 1>&2 2>> $logfile + + write_status "AssemblyBreakends complete" + + dir=$workingdir/$(basename $assembly).gridss.working/ + prefix=$dir/$(basename $assembly) + tmp_prefix=$dir/tmp.$(basename $assembly) + + write_status "RunningSoftClipsToSplitReads: running on assembly output dir $assembly" + rm -f $tmp_prefix.sc2sr.suppsorted.sv-tmp* + { $timecmd java -Xmx$otherjvmheap $jvm_args \ + -Dgridss.async.buffersize=16 \ + -Dsamjdk.create_index=false \ + -Dgridss.output_to_temp_file=true \ + -cp $gridss_jar gridss.SoftClipsToSplitReads \ + TMP_DIR=$dir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + WORKER_THREADS=$threads \ + I=$assembly \ + O=$tmp_prefix.sc2sr.primary.sv.bam \ + OUTPUT_UNORDERED_RECORDS=$tmp_prefix.sc2sr.supp.sv.bam \ + REALIGN_ENTIRE_READ=true \ + READJUST_PRIMARY_ALIGNMENT_POSITION=true \ + $aligner_args \ + && $timecmd $samtools_sort \ + -T $tmp_prefix.sc2sr.suppsorted.sv-tmp \ + -Obam \ + -o $tmp_prefix.sc2sr.suppsorted.sv.bam \ + $tmp_prefix.sc2sr.supp.sv.bam \ + && $rmcmd $tmp_prefix.sc2sr.supp.sv.bam \ + && $rmcmd -f $prefix.sv.tmp.bam $prefix.sv.tmp.bam.bai \ + && $timecmd samtools merge \ + -c \ + -p \ + -@ $threads \ + $prefix.sv.tmp.bam \ + $tmp_prefix.sc2sr.primary.sv.bam \ + $tmp_prefix.sc2sr.suppsorted.sv.bam \ + && $timecmd samtools index $prefix.sv.tmp.bam \ + && $rmcmd $tmp_prefix.sc2sr.primary.sv.bam \ + && $rmcmd $tmp_prefix.sc2sr.suppsorted.sv.bam \ + && mv $prefix.sv.tmp.bam $prefix.sv.bam \ + && mv $prefix.sv.tmp.bam.bai $prefix.sv.bam.bai \ + ; } 1>&2 2>> $logfile + + write_status "Produced assembly BAM: $prefix.sv.bam" + + write_status "Complete Assembly" + + # no idea why this is a for loop, could just be: ASSEMBLY=$assembly + #assembly_args="" + #for ass in $assembly ; do + # assembly_args="$assembly_args ASSEMBLY=$ass" + #done + write_status "Assembly args: $assembly_args" + + write_status "*** ASSEMBLY COMPLETE ***" +fi + +#### +# VARIANT CALLING +#### + +if [[ $do_call == true ]] ; then + write_status "*** VARIANT CALLING ***" + + write_status "Creating variant VCF: $output_vcf" + + dir=$workingdir/$(basename $output_vcf).gridss.working + prefix=$dir/$(basename $output_vcf) + mkdir -p $dir + if [[ ! -d $dir ]] ; then + write_status "Unable to create directory $dir" + exit $EX_CANTCREAT + fi + + # create symbolic links to the full BAM as though they were produced by the pre-process step + # eg: ./gridss_02/COLO829R.bam.gridss.working/COLO829R.bam.sv.bam + for (( i=0; i < $label_count; ++i )) + do + bam_file=${BAM_ARRAY[$i]} + bam_dir=$workingdir/$(basename $bam_file).gridss.working + + if [[ ! -d $bam_dir ]] ; then + mkdir -p $bam_dir + fi + + sv_bam_file=$bam_dir/$(basename $bam_file).sv.bam + # write_status "Making soft-link to ${sv_bam_file}" + #ln -sfr ${bam_file} ${sv_bam_file} + #ln -sfr ${bam_file}.bai ${sv_bam_file}.bai + done + + write_status "Running IdentifyVariants" + { $timecmd java -Xmx$jvmheap $jvm_args \ + -Dgridss.output_to_temp_file=true \ + -cp $gridss_jar gridss.IdentifyVariants \ + TMP_DIR=$workingdir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + WORKER_THREADS=$threads \ + $input_filtered_args \ + $blacklist_arg \ + $config_args \ + $assembly_args \ + OUTPUT_VCF=$prefix.unallocated.vcf \ + $readpairing_args \ + ; } 1>&2 2>> $logfile + write_status "IdentifyVariants complete, produced $prefix.unallocated.vcf" + + write_status "Running AnnotateVariants" + { $timecmd java -Xmx$jvmheap $jvm_args \ + -Dgridss.output_to_temp_file=true \ + -Dgridss.async.buffersize=2048 \ + -cp $gridss_jar gridss.AnnotateVariants \ + TMP_DIR=$workingdir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + WORKER_THREADS=$threads \ + $input_filtered_args \ + $blacklist_arg \ + $config_args \ + $assembly_args \ + INPUT_VCF=$prefix.unallocated.vcf \ + OUTPUT_VCF=$prefix.allocated.vcf \ + $readpairing_args \ + ; } 1>&2 2>> $logfile + $rmcmd $prefix.unallocated.vcf + write_status "AnnotateVariants complete, produced $prefix.allocated.vcf" + + write_status "Running AnnotateInsertedSequence" + + { $timecmd java -Xmx$otherjvmheap $jvm_args \ + -Dgridss.output_to_temp_file=true \ + -cp $gridss_jar gridss.AnnotateInsertedSequence \ + TMP_DIR=$workingdir \ + WORKING_DIR=$workingdir \ + REFERENCE_SEQUENCE=$reference \ + WORKER_THREADS=$threads \ + INPUT=$prefix.allocated.vcf \ + OUTPUT=$output_vcf \ + && $rmcmd $prefix.allocated.vcf \ + ; } 1>&2 2>> $logfile + write_status "AnnotateInsertedSequence complete, produced $output_vcf" + + write_status "*** VARIANT CALLING COMPLETE ***" +fi + +if [[ -f $logfile ]] ; then + write_status "Run complete with $(grep WARNING $logfile | wc -l) warnings and $(grep ERROR $logfile | wc -l) errors." +fi +trap - EXIT +exit 0 # success! diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf new file mode 100644 index 00000000..f1ce2a1c --- /dev/null +++ b/modules/local/svprep/call/main.nf @@ -0,0 +1,97 @@ +process CALL { + tag "${meta.id}" + label 'process_medium' + + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) + path gridss_config + path genome_fasta + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + path blocklist + + output: + tuple val(meta), path('gridss_call/sv.svprep.gridss.vcf.gz'), emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + def output_dirname = 'gridss_call' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = "--bams ${bams_list.join(',')}" + def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] + def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" + + """ + # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation + # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + shadow_input_directory() { + src=\${1} + dst="${output_dirname}/" + for filepath_src in \$(find -L \${src} ! -type d); do + # Get destination location for symlink + filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) + filepath_dst=\${dst%/}/\${filepath_src_rel} + # Create directory for symlink + mkdir -p \${filepath_dst%/*}; + # Get path for symlink source file, then create it + # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only + # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers + symlinkpath=\$(realpath \${filepath_src}) + ln -s \${symlinkpath} \${filepath_dst}; + done + if [[ -L "\${src##*/}" ]]; then + rm "\${src}" + fi + } + shadow_input_directory ${assemble_dir} + + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + # Run + gridss_svprep \\ + ${args} \\ + --jvmheap ${task.memory.giga}g \\ + --jar ${task.ext.jarPath} \\ + --steps call \\ + --labels ${labels_arg} \\ + --reference ${genome_fasta} \\ + --blacklist ${blocklist} \\ + --workingdir ${output_dirname}/work/ \\ + --assembly ${output_dirname}/sv_assemblies.bam \\ + --output ${output_dirname}/sv.svprep.gridss.vcf.gz \\ + --threads ${task.cpus} \\ + ${config_arg} \\ + ${bams_arg} \\ + ${bams_filtered_arg} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_call/ + cat < gridss_call/sv.svprep.gridss.vcf.gz + ##fileformat=VCFv4.1 + ##contig= + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . + EOF + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf new file mode 100644 index 00000000..06f267bf --- /dev/null +++ b/modules/local/svprep/depth_annotator/main.nf @@ -0,0 +1,50 @@ +process DEPTH_ANNOTATOR { + tag "${meta.id}" + label 'process_medium' + + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bams), path(bais), path(vcf), val(labels) + path genome_fasta + val genome_ver + + output: + tuple val(meta), path("*.vcf.gz"), emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def labels_arg = labels.join(',') + // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below + def bams_list = bams instanceof List ? bams : [bams] + def bams_arg = "${bams_list.join(',')}" + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -cp ${task.ext.jarPath} com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ + ${args} \\ + -input_vcf ${vcf} \\ + -output_vcf sv.svprep.gridss.depths.vcf.gz \\ + -samples ${labels_arg} \\ + -bam_files ${bams_arg} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -threads ${task.cpus} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + svprep: \$(java -jar ${task.ext.jarPath} 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + END_VERSIONS + """ + + stub: + """ + touch sv_vcf.depths.vcf.gz + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf new file mode 100644 index 00000000..bb388ead --- /dev/null +++ b/modules/local/svprep/preprocess/main.nf @@ -0,0 +1,57 @@ +process PREPROCESS { + tag "${meta.id}" + label 'process_medium' + + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bam), path(bam_filtered) + path gridss_config + path genome_fasta + path genome_fai + path genome_dict + path genome_bwa_index_dir, stageAs: 'bwa_index' + path genome_bwa_index_image + path genome_gridss_index + + output: + tuple val(meta), path("gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/"), emit: preprocess_dir + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' + + """ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + + gridss_svprep \\ + ${args} \\ + --jvmheap ${task.memory.giga}g \\ + --jar ${task.ext.jarPath} \\ + --steps preprocess \\ + --reference ${genome_fasta} \\ + --workingdir gridss_preprocess/ \\ + --threads ${task.cpus} \\ + ${config_arg} \\ + --labels ${meta.id} \\ + --bams ${bam} \\ + --filtered_bams ${bam_filtered} \\ + --output placeholder + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + END_VERSIONS + """ + + stub: + """ + mkdir -p gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf new file mode 100644 index 00000000..424c33ba --- /dev/null +++ b/modules/local/svprep/svprep/main.nf @@ -0,0 +1,61 @@ +process SVPREP { + tag "${meta.id}" + label 'process_medium' + + container 'docker.io/scwatts/svprep:1.1--0' + + input: + tuple val(meta), path(bam), path(bai), path(junctions) + path genome_fasta + val genome_ver + path sv_blocklist + path known_fusions + val write_types + val calc_fragment_length + + output: + tuple val(meta), path("*.sorted.bam") , emit: bam + tuple val(meta), path("*.sv_prep.junctions.csv"), emit: junctions + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def write_types_arg = write_types ? "-write_types \'${write_types}\'" : '' + def existing_juction_file_arg = junctions ? "-existing_junction_file ${junctions}" : "" + def calc_fragment_length_arg = calc_fragment_length ? "-calc_fragment_length" : "" + + """ + java \\ + -Xmx${task.memory.giga}g \\ + -jar ${task.ext.jarPath} \\ + ${args} \\ + -sample ${meta.id} \\ + -bam_file ${bam} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -blacklist_bed ${sv_blocklist} \\ + -known_fusion_bed ${known_fusions} \\ + ${write_types_arg} \\ + ${existing_juction_file_arg} \\ + ${calc_fragment_length_arg} \\ + -threads ${task.cpus} \\ + -output_dir ./ + + samtools sort -O bam "${meta.id}.sv_prep.bam" -o "${meta.id}.sv_prep.sorted.bam" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sage: \$(java -jar ${task.ext.jarPath} 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + END_VERSIONS + """ + + stub: + """ + touch "${meta.id}.sv_prep.sorted.bam" + touch "${meta.id}.sv_prep.junctions.csv" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/nextflow_schema.json b/nextflow_schema.json index a8f0d54a..beabf533 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -186,6 +186,14 @@ "fa_icon": "far fa-folder-open", "hidden": true }, + "ref_data_sv_prep_blocklist": { + "type": "string", + "format": "file-path", + "pattern": "^\\S+\\.bed$", + "description": "Path to SV Prep blocklist file.", + "fa_icon": "far fa-file-code", + "hidden": true + }, "ref_data_gridss_pon_breakends": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep.nf new file mode 100644 index 00000000..fa0b9250 --- /dev/null +++ b/subworkflows/local/gridss_svprep.nf @@ -0,0 +1,226 @@ +// +// SV Prep is a BAM filter designed to select only reads relevant to SV events run prior to GRIDSS. +// GRIDSS is a software suite containing tools useful for the detection of genomic rearrangements. +// +import Constants + +include { ASSEMBLE as GRIDSS_ASSEMBLE } from '../../modules/local/svprep/assemble/main' +include { CALL as GRIDSS_CALL } from '../../modules/local/svprep/call/main' +include { PREPROCESS as GRIDSS_PREPROCESS } from '../../modules/local/svprep/preprocess/main' +include { SVPREP as SVPREP_NORMAL } from '../../modules/local/svprep/svprep/main' +include { SVPREP as SVPREP_TUMOR } from '../../modules/local/svprep/svprep/main' +include { DEPTH_ANNOTATOR as SVPREP_DEPTH_ANNOTATOR } from '../../modules/local/svprep/depth_annotator/main' + +workflow GRIDSS_SVPREP { + take: + ch_inputs // channel: [val(meta)] + gridss_config // file: /path/to/gridss_config (optional) + ref_data_genome_fasta // file: /path/to/genome_fasta + ref_data_genome_version // val: genome version + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_dict // file: /path/to/genome_dict + ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ + ref_data_genome_bwa_index_image // file: /path/to/genome_bwa_index_image + ref_data_genome_gridss_index // file: /path/to/genome_gridss_index + ref_data_gridss_blocklist // val: /path/to/gridss_blocklist + ref_data_sv_prep_blocklist // file: /path/to/sv_prep_blocklist + ref_data_known_fusions // file: /path/to/known_fusions + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Prepare tumor sample inputs + // channel: [val(meta_svprep), bam_tumor, bai_tumor, []] + ch_svprep_tumor_inputs = ch_inputs + .map { meta -> + def meta_svprep = [ + key: meta.id, + id: meta.get(['sample_name', Constants.DataType.TUMOR]), + sample_type: 'tumor', + ] + def bam_tumor = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) + return [meta_svprep, bam_tumor, "${bam_tumor}.bai", []] + } + + // Filter tumor BAM + SVPREP_TUMOR( + ch_svprep_tumor_inputs, + ref_data_genome_fasta, + ref_data_genome_version, + ref_data_sv_prep_blocklist, + ref_data_known_fusions, + 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument switch and value + false, // -calc_fragment_length argument switch + ) + ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) + + // Prepare normal sample inputs + // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] + ch_svprep_normal_inputs = WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs) + .map { meta, junctions_tumor -> + def meta_svprep = [ + key: meta.id, + id: meta.get(['sample_name', Constants.DataType.NORMAL]), + sample_type: 'normal', + ] + def bam_normal = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) + return [meta_svprep, bam_normal, "${bam_normal}.bai", junctions_tumor] + } + + SVPREP_NORMAL( + ch_svprep_normal_inputs, + ref_data_genome_fasta, + ref_data_genome_version, + ref_data_sv_prep_blocklist, + ref_data_known_fusions, + false, // -write_types argument switch and value + true, // -calc_fragment_length argument switch + ) + ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) + + // channel: [val(meta_gridss), bam_tumor, bam_tumor_filtered] + ch_preprocess_inputs_tumor = WorkflowOncoanalyser.groupByMeta( + SVPREP_TUMOR.out.bam, + ch_svprep_tumor_inputs, + ) + .map { meta_svprep, bam_filtered, bam, bai -> + return [meta_svprep, bam, bam_filtered] + } + + // channel: [val(meta_gridss), bam_normal, bam_normal_filtered] + ch_preprocess_inputs_normal = WorkflowOncoanalyser.groupByMeta( + SVPREP_NORMAL.out.bam, + ch_svprep_normal_inputs, + ) + .map { meta_svprep, bam_filtered, bam, bai, junctions -> + return [meta_svprep, bam, bam_filtered] + } + + // channel: [val(meta_gridss), bam, bam_filtered] + ch_preprocess_inputs = Channel.empty() + .mix( + ch_preprocess_inputs_tumor, + ch_preprocess_inputs_normal, + ) + + // Preprocess reads + GRIDSS_PREPROCESS( + ch_preprocess_inputs, + gridss_config, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ) + ch_versions = ch_versions.mix(GRIDSS_PREPROCESS.out.versions) + + // Gather BAMs and outputs from preprocessing for each tumor/normal set + // channel: [key, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] + ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( + ch_preprocess_inputs, + GRIDSS_PREPROCESS.out.preprocess_dir, + ) + .map { [it[0].key, it] } + .groupTuple(size: 2) + + // Order and organise inputs for assembly + // channel: [val(meta_gridss), [bams], [bams_filtered], [preprocess_dirs], [labels]] + ch_assemble_inputs = ch_bams_and_preprocess + .map { key, entries -> + def (tmeta, tbam, tbam_filtered, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } + def (nmeta, nbam, nbam_filtered, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } + def meta_gridss = [id: tmeta.key] + return [ + meta_gridss, + [nbam, tbam], + [nbam_filtered, tbam_filtered], + [npreprocess, tpreprocess], + [nmeta.id, tmeta.id], + ] + } + + // Assemble variants + GRIDSS_ASSEMBLE( + ch_assemble_inputs, + gridss_config, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blocklist, + ) + ch_versions = ch_versions.mix(GRIDSS_ASSEMBLE.out.versions) + + // Prepare inputs for variant calling + // channel: [val(meta_gridss), [bams], [bams_filtered], assemble_dir, [labels]] + ch_call_inputs = WorkflowOncoanalyser.groupByMeta( + ch_assemble_inputs, + GRIDSS_ASSEMBLE.out.assemble_dir, + flatten: false, + ) + .map { data -> + def meta = data[0] + def (bams, bams_filtered, preprocess_dirs, labels) = data[1] + def (assemble_dir) = data[2] + return [meta, bams, bams_filtered, assemble_dir, labels] + } + + // Call variants + GRIDSS_CALL( + ch_call_inputs, + gridss_config, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_gridss_blocklist, + ) + ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) + + // Prepare inputs for depth annotation, restore original meta + // channel: [val(meta_svprep), [bams], [bais], vcf, [labels]] + ch_depth_inputs = WorkflowOncoanalyser.groupByMeta( + ch_inputs.map { meta -> [meta.id, meta] }, + GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + ) + .map { id, meta, vcf -> + def tbam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) + def nbam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) + def meta_svprep = [id: meta.id] + return [ + meta_svprep, + [nbam, tbam], + ["${nbam}.bai", "${tbam}.bai"], + vcf, + [meta.get(['sample_name', Constants.DataType.NORMAL]), meta.get(['sample_name', Constants.DataType.TUMOR])], + ] + } + + // Add depth annotations to SVs + SVPREP_DEPTH_ANNOTATOR( + ch_depth_inputs, + ref_data_genome_fasta, + ref_data_genome_version, + ) + + // Reunite final VCF with the corresponding input meta object + ch_out = Channel.empty() + .concat( + ch_inputs.map { meta -> [meta.id, meta] }, + SVPREP_DEPTH_ANNOTATOR.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + ) + .groupTuple(size: 2) + .map { id, other -> other.flatten() } + + emit: + results = ch_out // channel: [val(meta), vcf] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index adc8191b..65a488e6 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -132,6 +132,8 @@ def createHmfDataMap(hmf_data_base, params_only) { gc_profile: 'ref_data_gc_profile', // CUPPA cuppa_resources: 'ref_data_cuppa_resources', + // SVPREP + 'sv_prep_blocklist': 'ref_data_sv_prep_blocklist', // GRIDSS gridss_pon_breakends: 'ref_data_gridss_pon_breakends', gridss_pon_breakpoints: 'ref_data_gridss_pon_breakpoints', diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 3d1b9eeb..8776c1dc 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -73,6 +73,7 @@ include { VIRUSINTERPRETER } from '../modules/local/virusinterpreter/main' // SUBWORKFLOWS // include { GRIDSS } from '../subworkflows/local/gridss' +include { GRIDSS_SVPREP } from '../subworkflows/local/gridss_svprep' include { GRIPSS } from '../subworkflows/local/gripss' include { LILAC } from '../subworkflows/local/lilac' include { LINX } from '../subworkflows/local/linx' @@ -327,25 +328,44 @@ workflow ONCOANALYSER { // channel: [val(meta), gridss_vcf] ch_gridss_out = Channel.empty() if (run.gridss) { - ch_gridss_inputs = ch_inputs - .map { meta -> - def tumor_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) - def normal_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) - [meta, tumor_bam, normal_bam] - } - GRIDSS( - ch_gridss_inputs, - gridss_config, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_bwa_index, - PREPARE_REFERENCE.out.genome_bwa_index_image, - PREPARE_REFERENCE.out.genome_gridss_index, - hmf_data.gridss_region_blocklist, - ) - ch_versions = ch_versions.mix(GRIDSS.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS.out.results) + if (run.svprep) { + GRIDSS_SVPREP( + ch_inputs, + gridss_config, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_version, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_bwa_index, + PREPARE_REFERENCE.out.genome_bwa_index_image, + PREPARE_REFERENCE.out.genome_gridss_index, + hmf_data.gridss_region_blocklist, + hmf_data.sv_prep_blocklist, + hmf_data.known_fusions, + ) + ch_versions = ch_versions.mix(GRIDSS_SVPREP.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP.out.results) + } else { + ch_gridss_inputs = ch_inputs + .map { meta -> + def tumor_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) + def normal_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) + [meta, tumor_bam, normal_bam] + } + GRIDSS( + ch_gridss_inputs, + gridss_config, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_bwa_index, + PREPARE_REFERENCE.out.genome_bwa_index_image, + PREPARE_REFERENCE.out.genome_gridss_index, + hmf_data.gridss_region_blocklist, + ) + ch_versions = ch_versions.mix(GRIDSS.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS.out.results) + } } // From 50452dc58434dcf052f87a179cb2c5015d2dbf3e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 28 Dec 2022 15:30:18 +1100 Subject: [PATCH 097/562] Add meta.yml for SV prep modules --- modules/local/svprep/assemble/meta.yml | 76 ++++++++++++++++++ modules/local/svprep/call/meta.yml | 77 +++++++++++++++++++ modules/local/svprep/depth_annotator/meta.yml | 56 ++++++++++++++ modules/local/svprep/preprocess/meta.yml | 66 ++++++++++++++++ modules/local/svprep/svprep/meta.yml | 68 ++++++++++++++++ 5 files changed, 343 insertions(+) create mode 100644 modules/local/svprep/assemble/meta.yml create mode 100644 modules/local/svprep/call/meta.yml create mode 100644 modules/local/svprep/depth_annotator/meta.yml create mode 100644 modules/local/svprep/preprocess/meta.yml create mode 100644 modules/local/svprep/svprep/meta.yml diff --git a/modules/local/svprep/assemble/meta.yml b/modules/local/svprep/assemble/meta.yml new file mode 100644 index 00000000..c275af3f --- /dev/null +++ b/modules/local/svprep/assemble/meta.yml @@ -0,0 +1,76 @@ +name: gridss_assemble +description: Assemble SVs with GRIDSS +keywords: + - assemble + - sv +tools: + - gridss: + description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. + homepage: https://github.com/PapenfussLab/gridss + documentation: https://github.com/PapenfussLab/gridss + licence: ["GPL >=3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bams: + type: list + description: List of BAM files + pattern: "*.{bam}" + - bams_filtered: + type: list + description: List of filtered BAM files + pattern: "*.{bam}" + - preprocess_dirs: + type: list + description: List of GRIDSS preprocess output directories + - labels: + type: list + description: List of labels corresponding to BAMs and GRIDSS preprocess output directories + - gridss_config: + type: file + description: Optional GRIDSS configuration file (optional) + - genome_fasta: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_bwa_index_dir: + type: directory + description: Directory containing reference genome assembly BWA index + - genome_bwa_index_image: + type: file + description: Reference genome assembly BWA index img file + pattern: "*.{img}" + - genome_gridss_index: + type: file + description: Reference genome assembly GRIDSS index file + pattern: "*.{gridsscache}" + - blocklist: + type: file + description: GRIDSS blocklist file + pattern: "*.{bed.gz}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - assembly_dir: + type: directory + description: GRIDSS assemble output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/svprep/call/meta.yml b/modules/local/svprep/call/meta.yml new file mode 100644 index 00000000..9352c818 --- /dev/null +++ b/modules/local/svprep/call/meta.yml @@ -0,0 +1,77 @@ +name: gridss_call +description: Call SVs with GRIDSS +keywords: + - calling + - sv +tools: + - gridss: + description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. + homepage: https://github.com/PapenfussLab/gridss + documentation: https://github.com/PapenfussLab/gridss + licence: ["GPL >=3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bams: + type: list + description: List of BAM files + pattern: "*.{bam}" + - bams_filtered: + type: list + description: List of filtered BAM files + pattern: "*.{bam}" + - assemble_dir: + type: directory + description: GRIDSS assemble output directory + - labels: + type: list + description: List of labels corresponding to BAMs and GRIDSS preprocess output directories + - gridss_config: + type: file + description: Optional GRIDSS configuration file (optional) + - genome_fasta: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_bwa_index_dir: + type: directory + description: Directory containing reference genome assembly BWA index + - genome_bwa_index_image: + type: file + description: Reference genome assembly BWA index img file + pattern: "*.{img}" + - genome_gridss_index: + type: file + description: Reference genome assembly GRIDSS index file + pattern: "*.{gridsscache}" + - blocklist: + type: file + description: GRIDSS blocklist file + pattern: "*.{bed.gz}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - vcf: + type: file + description: GRIDSS SV VCF file + pattern: "*.{vcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/svprep/depth_annotator/meta.yml b/modules/local/svprep/depth_annotator/meta.yml new file mode 100644 index 00000000..22198296 --- /dev/null +++ b/modules/local/svprep/depth_annotator/meta.yml @@ -0,0 +1,56 @@ +name: depth_annotator +description: Annotate GRIDSS BAM with depth information +keywords: + - depth + - annotation + - sv +tools: + - svprep: + description: Selects reads associated with SV events for input to GRIDSS + homepage: https://github.com/hartwigmedical/hmftools/tree/master/sv-prep + documentation: https://github.com/hartwigmedical/hmftools/tree/master/sv-prep + licence: ["GPL >=3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bams: + type: list + description: BAM files + pattern: "*.{bam}" + - bai: + type: list + description: BAI files + pattern: "*.{bai}" + - vcf: + type: file + description: VCF file + pattern: "*.{vcf.gz}" + - labels: + type: list + description: List of labels corresponding to BAMs and GRIDSS preprocess output directories + - genome_fasta: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - vcf: + type: file + description: VCF file + pattern: "*.{vcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/svprep/preprocess/meta.yml b/modules/local/svprep/preprocess/meta.yml new file mode 100644 index 00000000..4941f31e --- /dev/null +++ b/modules/local/svprep/preprocess/meta.yml @@ -0,0 +1,66 @@ +name: gridss_preprocess +description: Preprocess reads for GRIDSS +keywords: + - preprocessing + - sv +tools: + - gridss: + description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. + homepage: https://github.com/PapenfussLab/gridss + documentation: https://github.com/PapenfussLab/gridss + licence: ["GPL >=3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - bam_filtered: + type: file + description: Filtered BAM file + pattern: "*.{bam}" + - gridss_config: + type: file + description: Optional GRIDSS configuration file (optional) + - genome_fasta: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - genome_bwa_index_dir: + type: directory + description: Directory containing reference genome assembly BWA index + - genome_bwa_index_image: + type: file + description: Reference genome assembly BWA index img file + pattern: "*.{img}" + - genome_gridss_index: + type: file + description: Reference genome assembly GRIDSS index file + pattern: "*.{gridsscache}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - preprocess_dir: + type: directory + description: GRIDSS preprocess output directory + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/local/svprep/svprep/meta.yml b/modules/local/svprep/svprep/meta.yml new file mode 100644 index 00000000..24aadfe3 --- /dev/null +++ b/modules/local/svprep/svprep/meta.yml @@ -0,0 +1,68 @@ +name: svprep +description: Select reads associated with SV events +keywords: + - filtering + - reads + - sv +tools: + - svprep: + description: Selects reads associated with SV events for input to GRIDSS + homepage: https://github.com/hartwigmedical/hmftools/tree/master/sv-prep + documentation: https://github.com/hartwigmedical/hmftools/tree/master/sv-prep + licence: ["GPL >=3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - bai: + type: file + description: BAI file + pattern: "*.{bai}" + - junctions: + type: file + description: Optional existing candidate SV junctions file + pattern: "*.{csv}" + - genome_fasta: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version + - sv_blocklist: + type: file + description: SV Prep blocklist file + pattern: "*.{bed}" + - known_fusions: + type: file + description: Known fusions file + pattern: "*.{bedpe}" + - write_types: + type: string + description: Type of output files to write +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bam: + type: file + description: BAM file containing selected reads + pattern: "*.{bam}" + - junctions: + type: file + description: Candidate SV junctions file + pattern: "*.{csv}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" From dd6c1c725567e6c79fb807da0eb5f75f35c488ef Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 28 Dec 2022 15:29:58 +1100 Subject: [PATCH 098/562] Remove superfluous SV Prep argument --- modules/local/svprep/svprep/main.nf | 3 --- subworkflows/local/gridss_svprep.nf | 2 -- 2 files changed, 5 deletions(-) diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 424c33ba..36bd6d80 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -11,7 +11,6 @@ process SVPREP { path sv_blocklist path known_fusions val write_types - val calc_fragment_length output: tuple val(meta), path("*.sorted.bam") , emit: bam @@ -25,7 +24,6 @@ process SVPREP { def args = task.ext.args ?: '' def write_types_arg = write_types ? "-write_types \'${write_types}\'" : '' def existing_juction_file_arg = junctions ? "-existing_junction_file ${junctions}" : "" - def calc_fragment_length_arg = calc_fragment_length ? "-calc_fragment_length" : "" """ java \\ @@ -40,7 +38,6 @@ process SVPREP { -known_fusion_bed ${known_fusions} \\ ${write_types_arg} \\ ${existing_juction_file_arg} \\ - ${calc_fragment_length_arg} \\ -threads ${task.cpus} \\ -output_dir ./ diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep.nf index fa0b9250..b7870895 100644 --- a/subworkflows/local/gridss_svprep.nf +++ b/subworkflows/local/gridss_svprep.nf @@ -51,7 +51,6 @@ workflow GRIDSS_SVPREP { ref_data_sv_prep_blocklist, ref_data_known_fusions, 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument switch and value - false, // -calc_fragment_length argument switch ) ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) @@ -75,7 +74,6 @@ workflow GRIDSS_SVPREP { ref_data_sv_prep_blocklist, ref_data_known_fusions, false, // -write_types argument switch and value - true, // -calc_fragment_length argument switch ) ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) From a1e386a63dab63f81db4713387d82c054896c254 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 28 Dec 2022 15:04:24 +1100 Subject: [PATCH 099/562] Remove GRIDSS annotate --- modules/local/gridss/annotate/main.nf | 41 -------------------------- modules/local/gridss/annotate/meta.yml | 37 ----------------------- subworkflows/local/gridss.nf | 8 +---- 3 files changed, 1 insertion(+), 85 deletions(-) delete mode 100644 modules/local/gridss/annotate/main.nf delete mode 100644 modules/local/gridss/annotate/meta.yml diff --git a/modules/local/gridss/annotate/main.nf b/modules/local/gridss/annotate/main.nf deleted file mode 100644 index 6981bffb..00000000 --- a/modules/local/gridss/annotate/main.nf +++ /dev/null @@ -1,41 +0,0 @@ -process GRIDSS_ANNOTATE { - tag "${meta.id}" - label 'process_single' - - container 'docker.io/scwatts/gridss:2.13.2--3' - - input: - tuple val(meta), path(gridss_vcf) - - output: - tuple val(meta), path('gridss_annotate/*.gridss.annotated.vcf.gz'), emit: vcf - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - gridss_annotate_vcf_repeatmasker \\ - ${args} \\ - --jar ${task.ext.jarPath} \\ - --output gridss_annotate/${meta.id}.gridss.annotated.vcf.gz \\ - --workingdir gridss_annotate/work/ \\ - --threads ${task.cpus} \\ - ${gridss_vcf} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ - - stub: - """ - mkdir -p gridss_annotate/ - touch gridss_annotate/${meta.id}.gridss.annotated.vcf.gz - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/gridss/annotate/meta.yml b/modules/local/gridss/annotate/meta.yml deleted file mode 100644 index 2a935710..00000000 --- a/modules/local/gridss/annotate/meta.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: gridss_annotate -description: Annotate SVs called with GRIDSS -keywords: - - annotate - - sv -tools: - - gridss: - description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. - homepage: https://github.com/PapenfussLab/gridss - documentation: https://github.com/PapenfussLab/gridss - licence: ["GPL >=3"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - gridss_vcf: - type: file - description: GRIDSS structural variant VCF file - pattern: "*.{bam}" -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - vcf: - type: file - description: Annotated structural variant VCF file - pattern: "*.{vcf.gz}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@scwatts" diff --git a/subworkflows/local/gridss.nf b/subworkflows/local/gridss.nf index b8ee66f3..dfb5dc2d 100644 --- a/subworkflows/local/gridss.nf +++ b/subworkflows/local/gridss.nf @@ -4,7 +4,6 @@ import Constants import Utils -include { GRIDSS_ANNOTATE } from '../../modules/local/gridss/annotate/main' include { GRIDSS_ASSEMBLE } from '../../modules/local/gridss/assemble/main' include { GRIDSS_CALL } from '../../modules/local/gridss/call/main' include { GRIDSS_PREPROCESS } from '../../modules/local/gridss/preprocess/main' @@ -124,16 +123,11 @@ workflow GRIDSS { ) ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) - // Annotate variants with RepeatMasker - GRIDSS_ANNOTATE( - GRIDSS_CALL.out.vcf, - ) - // Reunite final VCF with the corresponding input meta object ch_out = Channel.empty() .concat( ch_inputs.map { meta, tbam, nbam -> [meta.id, meta] }, - GRIDSS_ANNOTATE.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .groupTuple(size: 2) .map { id, other -> other.flatten() } From 23cb7c7ad17ec54532e304d2db5e06ceb0fb66a7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 23 Jan 2023 15:20:13 +1100 Subject: [PATCH 100/562] Align with Pipeline5 v5.31 --- conf/hmfdata.config | 19 ++++++++++--------- modules/local/cuppa/Dockerfile | 9 ++++----- modules/local/cuppa/classifier/main.nf | 8 ++------ modules/local/cuppa/visualiser/main.nf | 4 ++-- modules/local/gpgr/linx/main.nf | 2 +- modules/local/gripss/Dockerfile | 2 +- modules/local/gripss/germline/main.nf | 15 +++++++++------ modules/local/gripss/germline/meta.yml | 3 +++ modules/local/gripss/somatic/main.nf | 15 +++++++++------ modules/local/gripss/somatic/meta.yml | 3 +++ modules/local/lilac/Dockerfile | 2 +- modules/local/lilac/main.nf | 8 ++++---- modules/local/linx/Dockerfile | 2 +- modules/local/linx/germline/main.nf | 8 +------- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 7 +------ modules/local/orange/Dockerfile | 2 +- modules/local/orange/main.nf | 8 +++++--- modules/local/pave/Dockerfile | 2 +- modules/local/pave/germline/main.nf | 7 ++----- modules/local/pave/somatic/main.nf | 7 ++----- modules/local/pave/somatic/meta.yml | 2 +- modules/local/peach/Dockerfile | 2 +- modules/local/peach/main.nf | 4 ++-- modules/local/protect/Dockerfile | 2 +- modules/local/protect/main.nf | 20 +++++++++++++++----- modules/local/protect/meta.yml | 17 +++++++++++++++++ modules/local/purple/Dockerfile | 2 +- modules/local/purple/main.nf | 2 +- modules/local/sage/Dockerfile | 3 ++- modules/local/sage/germline/main.nf | 16 ++++++++-------- modules/local/sage/germline/meta.yml | 8 ++++---- modules/local/sage/somatic/main.nf | 8 ++++---- modules/local/sage/somatic/meta.yml | 4 ++-- modules/local/sigs/Dockerfile | 2 +- modules/local/sigs/main.nf | 4 ++-- modules/local/svprep/Dockerfile | 2 +- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/depth_annotator/main.nf | 2 +- modules/local/svprep/preprocess/main.nf | 2 +- modules/local/svprep/svprep/main.nf | 4 ++-- nextflow_schema.json | 17 ++++++++++++----- subworkflows/local/gripss.nf | 17 ++++++++++------- subworkflows/local/linx.nf | 5 ----- subworkflows/local/prepare_reference.nf | 14 +++++++++++--- subworkflows/local/sage.nf | 10 +++++----- workflows/oncoanalyser.nf | 11 ++++++----- 48 files changed, 177 insertions(+), 142 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 247e0ade..bfffbc47 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -8,11 +8,12 @@ params { // CUPPA cuppa_resources = 'cuppa/' // SV Prep - sv_prep_blocklist = 'svprep/sv_prep_blacklist.37.bed' - // GRIDSS - gridss_pon_breakends = 'gridss_pon/gridss_pon_single_breakend.37.bed.gz' - gridss_pon_breakpoints = 'gridss_pon/gridss_pon_breakpoint.37.bedpe.gz' - gridss_region_blocklist = 'gridss_repeatmasker_db/ENCFF001TDO.37.bed' + sv_prep_blocklist = 'gridss/sv_prep_blacklist.37.bed' + // GRIDSS, GRIPSS + gridss_pon_breakends = 'gridss/sgl_pon.37.bed.gz' + gridss_pon_breakpoints = 'gridss/sv_pon.37.bedpe.gz' + gridss_region_blocklist = 'gridss/gridss_blacklist.37.bed.gz' + repeatmasker_annotations = 'gridss/repeat_mask_data.37.fa.gz' // Isofox isofox_counts = 'isofox/read_151_exp_counts.csv' isofox_gc_ratios = 'isofox/read_100_exp_gc_ratios.csv' @@ -25,15 +26,15 @@ params { cohort_mapping = 'orange/cohort_mapping.tsv' cohort_percentiles = 'orange/cohort_percentiles.tsv' // PEACH - peach_panel = 'peach/min_DPYD.json' + peach_panel = 'peach/peach.json' // PROTECT serve_resources = 'serve/' // SAGE clinvar_annotations = 'sage/clinvar.37.vcf.gz' sage_blocklist_regions = 'sage/KnownBlacklist.germline.37.bed' sage_blocklist_sites = 'sage/KnownBlacklist.germline.37.vcf.gz' - sage_coding_panel = 'sage/ActionableCodingPanel.37.bed.gz' - sage_coverage_panel_germline = 'sage/CoverageCodingPanel.germline.37.bed.gz' + sage_actionable_panel = 'sage/ActionableCodingPanel.37.bed.gz' + sage_coverage_panel = 'sage/CoverageCodingPanel.37.bed.gz' sage_highconf_regions = 'giab_high_conf/NA12878_GIAB_highconf_IllFB-IllGATKHC-CG-Ion-Solid_ALLCHROM_v3.2.2_highconf.bed.gz' sage_known_hotspots_germline = 'sage/KnownHotspots.germline.37.vcf.gz' sage_known_hotspots_somatic = 'sage/KnownHotspots.somatic.37.vcf.gz' @@ -47,7 +48,7 @@ params { disease_ontology = 'disease_ontology/201015_doid.json' driver_gene_panel = 'gene_panel/DriverGenePanel.37.tsv' ensembl_data_resources = 'ensembl_data_cache/' - gnomad_pon_dir = 'gnomad/' + gnomad_pon_dir = [] known_fusion_data = 'fusions/known_fusion_data.37.csv' known_fusions = 'fusions/known_fusions.37.bedpe' purple_germline_del = 'purple/cohort_germline_del_freq.37.csv' diff --git a/modules/local/cuppa/Dockerfile b/modules/local/cuppa/Dockerfile index a789d03f..1b89e1ce 100644 --- a/modules/local/cuppa/Dockerfile +++ b/modules/local/cuppa/Dockerfile @@ -10,12 +10,11 @@ RUN \ RUN \ mkdir -p /opt/cuppa/ && \ - wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.6/cuppa_v1.6.jar' + wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.7.1/cuppa.jar' -# NOTE(SW): required report script is only available from the cuppa-v1.7 tag and later -ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools -ARG URL_BASE_CHART=${URL_BASE}/cuppa-v1.6/cuppa/src/main/resources/cuppa-chart -ARG URL_BASE_REPORT=${URL_BASE}/cuppa-v1.7/cuppa/src/main/resources/r +ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.7.1 +ARG URL_BASE_CHART=${URL_BASE}/cuppa/src/main/resources/cuppa-chart +ARG URL_BASE_REPORT=${URL_BASE}/cuppa/src/main/resources/r ARG DIR_BASE=/opt/cuppa RUN \ mkdir -p ${DIR_BASE}/{chart,report} && \ diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index 15554e99..3ba9d2ba 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -2,7 +2,7 @@ process CUPPA_CLASSIFIER { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.6--0' + container 'docker.io/scwatts/cuppa:1.7.1--0' input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter) @@ -18,7 +18,6 @@ process CUPPA_CLASSIFIER { script: def args = task.ext.args ?: '' def categories_arg = isofox_dir ? 'ALL' : 'DNA' - def gene_exp_arg = isofox_dir ? "-sample_gene_exp_file sample_data/${meta.id}.isf.gene_data.csv" : '' """ # Symlink input files into a single directory @@ -33,15 +32,12 @@ process CUPPA_CLASSIFIER { -ref_data_dir ${cuppa_resources} \\ -sample_data ${meta.id} \\ -sample_data_dir sample_data/ \\ - -sample_sv_file sample_data/${meta.id}.purple.sv.vcf.gz \\ - -sample_somatic_vcf sample_data/${meta.id}.purple.somatic.vcf.gz \\ - ${gene_exp_arg} \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - cuppa: 1.6 + cuppa: 1.7.1 END_VERSIONS """ diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf index ade9a0aa..7c411bfe 100644 --- a/modules/local/cuppa/visualiser/main.nf +++ b/modules/local/cuppa/visualiser/main.nf @@ -2,7 +2,7 @@ process CUPPA_VISUALISER { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.6--0' + container 'docker.io/scwatts/cuppa:1.7.1--0' input: tuple val(meta), path(cuppa_csv) @@ -31,7 +31,7 @@ process CUPPA_VISUALISER { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - cuppa: 1.6 + cuppa: 1.7.1 END_VERSIONS """ diff --git a/modules/local/gpgr/linx/main.nf b/modules/local/gpgr/linx/main.nf index a2b45add..e96d11d5 100644 --- a/modules/local/gpgr/linx/main.nf +++ b/modules/local/gpgr/linx/main.nf @@ -2,7 +2,7 @@ process GPGR_LINX { tag "${meta.id}" label 'process_single' - container 'ghcr.io/umccr/gpgr:1.3.0' + container 'ghcr.io/umccr/gpgr:1.4.1' input: tuple val(meta), path(linx_annotation), path(linx_visualiser) diff --git a/modules/local/gripss/Dockerfile b/modules/local/gripss/Dockerfile index 19fedbdd..da5d319b 100644 --- a/modules/local/gripss/Dockerfile +++ b/modules/local/gripss/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/gripss/ && \ - wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.1/gripss_v2.1.jar' + wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.3.2/gripss_v2.3.2.jar' USER mambauser diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 7652c8a7..2f180165 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -2,7 +2,7 @@ process GRIPSS_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.1--0' + container 'docker.io/scwatts/gripss:2.3.2--0' input: tuple val(meta), path(gridss_vcf) @@ -12,11 +12,12 @@ process GRIPSS_GERMLINE { path pon_breakends path pon_breakpoints path known_fusions + path repeatmasker_annotations output: - tuple val(meta), path('*.gripss.filtered.vcf.gz'), path('*.gripss.filtered.vcf.gz.tbi'), emit: vcf_hard - tuple val(meta), path('*.gripss.vcf.gz'), path('*.gripss.vcf.gz.tbi') , emit: vcf_soft - path 'versions.yml' , emit: versions + tuple val(meta), path('*gripss.filtered.germline.vcf.gz'), path('*gripss.filtered.germline.vcf.gz.tbi'), emit: vcf_hard + tuple val(meta), path('*.gripss.germline.vcf.gz'), path('*.gripss.germline.vcf.gz.tbi') , emit: vcf_soft + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -30,18 +31,20 @@ process GRIPSS_GERMLINE { -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.normal_id} \\ - -ref_genome_version V${genome_ver} \\ + -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ -pon_sgl_file ${pon_breakends} \\ -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ + -repeat_mask_file ${repeatmasker_annotations} \\ -vcf ${gridss_vcf} \\ + -output_id germline \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information cat <<-END_VERSIONS > versions.yml "${task.process}": - gripss: 2.1 + gripss: 2.3.2 END_VERSIONS """ diff --git a/modules/local/gripss/germline/meta.yml b/modules/local/gripss/germline/meta.yml index 1081597a..6febcdb0 100644 --- a/modules/local/gripss/germline/meta.yml +++ b/modules/local/gripss/germline/meta.yml @@ -43,6 +43,9 @@ input: type: file description: HMF Known Fusions file pattern: "*.{bedpe}" + - repeatmasker_annotations: + type: file + description: RepeatMasker annotations file output: - meta: type: map diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index d8517911..d48e5abd 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -2,7 +2,7 @@ process GRIPSS_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.1--0' + container 'docker.io/scwatts/gripss:2.3.2--0' input: tuple val(meta), path(gridss_vcf) @@ -12,11 +12,12 @@ process GRIPSS_SOMATIC { path pon_breakends path pon_breakpoints path known_fusions + path repeatmasker_annotations output: - tuple val(meta), path('*.gripss.filtered.vcf.gz'), path('*.gripss.filtered.vcf.gz.tbi'), emit: vcf_hard - tuple val(meta), path('*.gripss.vcf.gz'), path('*.gripss.vcf.gz.tbi') , emit: vcf_soft - path 'versions.yml' , emit: versions + tuple val(meta), path('*.gripss.filtered.somatic.vcf.gz'), path('*.gripss.filtered.somatic.vcf.gz.tbi'), emit: vcf_hard + tuple val(meta), path('*.gripss.somatic.vcf.gz'), path('*.gripss.somatic.vcf.gz.tbi') , emit: vcf_soft + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -31,18 +32,20 @@ process GRIPSS_SOMATIC { ${args} \\ -sample ${meta.tumor_id} \\ -reference ${meta.normal_id} \\ - -ref_genome_version V${genome_ver} \\ + -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ -pon_sgl_file ${pon_breakends} \\ -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ + -repeat_mask_file ${repeatmasker_annotations} \\ -vcf ${gridss_vcf} \\ + -output_id somatic \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information cat <<-END_VERSIONS > versions.yml "${task.process}": - gripss: 2.1 + gripss: 2.3.2 END_VERSIONS """ diff --git a/modules/local/gripss/somatic/meta.yml b/modules/local/gripss/somatic/meta.yml index fbe5018a..76d968dd 100644 --- a/modules/local/gripss/somatic/meta.yml +++ b/modules/local/gripss/somatic/meta.yml @@ -43,6 +43,9 @@ input: type: file description: HMF Known Fusions file pattern: "*.{bedpe}" + - repeatmasker_annotations: + type: file + description: RepeatMasker annotations file output: - meta: type: map diff --git a/modules/local/lilac/Dockerfile b/modules/local/lilac/Dockerfile index e2d5e079..b7dfe9b9 100644 --- a/modules/local/lilac/Dockerfile +++ b/modules/local/lilac/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/lilac/ && \ - wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.1/lilac.jar' + wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.4.2/lilac_v1.4.2.jar' USER mambauser diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 288308ce..c5c7d237 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -2,7 +2,7 @@ process LILAC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/lilac:1.1--0' + container 'docker.io/scwatts/lilac:1.4.2--0' input: tuple val(meta), path(normal_wgs_bam), path(normal_wgs_bai), path(tumor_wgs_bam), path(tumor_wgs_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(purple_dir) @@ -23,8 +23,8 @@ process LILAC { def tumor_wgs_bam_arg = tumor_wgs_bam ? "-tumor_bam ${tumor_wgs_bam}" : '' def tumor_wts_bam_arg = tumor_wts_bam ? "-rna_bam ${tumor_wts_bam}" : '' def purple_args = purple_dir ? """ - -gene_copy_number_file ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ - -somatic_variants_file ${purple_dir}/${sample_name}.purple.sv.vcf.gz \\ + -gene_copy_number ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ + -somatic_vcf ${purple_dir}/${sample_name}.purple.sv.vcf.gz \\ """ : '' """ @@ -46,7 +46,7 @@ process LILAC { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - lilac: 1.1 + lilac: 1.4.2 END_VERSIONS """ diff --git a/modules/local/linx/Dockerfile b/modules/local/linx/Dockerfile index 8a763aba..846feb27 100644 --- a/modules/local/linx/Dockerfile +++ b/modules/local/linx/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/linx/ && \ - wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.19.1/linx_v1.19_rc1.jar' + wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.22/linx_v1.22.jar' USER mambauser diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 761a3289..56ff2272 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -2,17 +2,14 @@ process LINX_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.19.1--0' + container 'docker.io/scwatts/linx:1.22--0' input: tuple val(meta), path(gripss_sv) val genome_ver - path fragile_regions path lines path ensembl_data_resources path driver_gene_panel - path pon_breakends - path pon_breakpoints output: tuple val(meta), path('linx_germline/'), emit: annotation_dir @@ -33,12 +30,9 @@ process LINX_GERMLINE { -germline \\ -ref_genome_version ${genome_ver} \\ -sv_vcf ${gripss_sv} \\ - -fragile_site_file ${fragile_regions} \\ -line_element_file ${lines} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -driver_gene_panel ${driver_gene_panel} \\ - -germine_pon_sgl_file ${pon_breakends} \\ - -germine_pon_sv_file ${pon_breakpoints} \\ -output_dir linx_germline/ cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 1db11f4a..383464f7 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,7 +2,7 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.19.1--0' + container 'docker.io/scwatts/linx:1.22--0' input: tuple val(meta), path(purple_dir) diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index b2d6e65a..3ca314f8 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,12 +2,7 @@ process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/linx:1.19.1--0' - - // Lenient caching is required here as the hash of the LINX_SOMATIC - // 'annotation_dir' output changes between runs even when the LINX_SOMATIC - // process itself is cached. - cache = 'lenient' + container 'docker.io/scwatts/linx:1.22--0' input: tuple val(meta), path(linx) diff --git a/modules/local/orange/Dockerfile b/modules/local/orange/Dockerfile index de6ef93f..560b1adc 100644 --- a/modules/local/orange/Dockerfile +++ b/modules/local/orange/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/orange/ && \ - wget -O /opt/orange/orange.jar 'https://github.com/hartwigmedical/hmftools/releases/download/orange-v1.10/orange.jar' + wget -O /opt/orange/orange.jar 'https://github.com/hartwigmedical/hmftools/releases/download/orange-v1.10.2/orange_v1.10.2.jar' USER mambauser diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 03ef3bd9..a4d68898 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -1,8 +1,10 @@ +// NOTE(SW): reference files for Isfox aren't currently available (-isofox_gene_distribution_csv, -isofox_alt_sj_cohort_csv) + process ORANGE { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/orange:1.10--0' + container 'docker.io/scwatts/orange:1.10.2--0' input: tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(chord_prediction), path(lilac_dir), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(protect), path(peach_genotype), path(cuppa), path(cuppa_summary_plot), path(cuppa_feature_plot), path(virusinterpreter) @@ -78,8 +80,8 @@ process ORANGE { -linx_plot_directory ${linx_somatic_plot_dir} \\ \\ -cuppa_result_csv ${cuppa} \\ - -cuppa_feature_plot ${cuppa_summary_plot} \\ - -cuppa_summary_plot ${cuppa_feature_plot} \\ + -cuppa_feature_plot ${cuppa_feature_plot} \\ + -cuppa_summary_plot ${cuppa_summary_plot} \\ \\ -peach_genotype_tsv ${peach_genotype} \\ -protect_evidence_tsv ${protect} \\ diff --git a/modules/local/pave/Dockerfile b/modules/local/pave/Dockerfile index 9245681e..d2cbefa9 100644 --- a/modules/local/pave/Dockerfile +++ b/modules/local/pave/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/pave/ && \ - wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.2.2/pave_v1.2.rc2.jar' + wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.4/pave_v1.4.jar' USER mambauser diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index e4fb5f29..088a9015 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -1,5 +1,3 @@ -// NOTE(SW): PAVE gnomad filtering is not yet documented but is used in Pipeline5: -// - cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L27-L28 // NOTE(SW): use of tumor sample name here is consistent with pipeline5 // - cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveGermline.java#L35-L39 // - cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L34-L44 @@ -8,7 +6,7 @@ process PAVE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.2.2--0' + container 'docker.io/scwatts/pave:1.4--0' input: tuple val(meta), path(sage_vcf) @@ -49,13 +47,12 @@ process PAVE_GERMLINE { -mappability_bed ${segment_mappability} \\ -vcf_file ${sage_vcf} \\ -read_pass_only \\ - -write_pass_only \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: 1.2.2 + pave: 1.4 END_VERSIONS """ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 972144ab..b947ae0b 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -1,10 +1,8 @@ -// NOTE(SW): PAVE gnomad filtering is not yet documented but is used in Pipeline5 https://github.com/hartwigmedical/pipeline5/blob/master/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L27-L28 - process PAVE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.2.2--0' + container 'docker.io/scwatts/pave:1.4--0' input: tuple val(meta), path(sage_vcf) @@ -54,14 +52,13 @@ process PAVE_SOMATIC { -mappability_bed ${segment_mappability} \\ -vcf_file ${sage_vcf} \\ -read_pass_only \\ - -write_pass_only \\ ${gnomad_args} \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: 1.2.2 + pave: 1.4 END_VERSIONS """ diff --git a/modules/local/pave/somatic/meta.yml b/modules/local/pave/somatic/meta.yml index 78d2b18d..ce1da31c 100644 --- a/modules/local/pave/somatic/meta.yml +++ b/modules/local/pave/somatic/meta.yml @@ -34,7 +34,7 @@ input: - genome_ver: type: string description: Reference genome version - - sage_pong: + - sage_pon: type: file description: SAGE PON file pattern: "*.{tsv.gz}" diff --git a/modules/local/peach/Dockerfile b/modules/local/peach/Dockerfile index 00ceee56..25926009 100644 --- a/modules/local/peach/Dockerfile +++ b/modules/local/peach/Dockerfile @@ -27,7 +27,7 @@ RUN \ pip install 'TransVar==2.5.8.20190813' RUN \ - git clone https://github.com/hartwigmedical/peach.git -b v1.6 /opt/peach/ + git clone https://github.com/hartwigmedical/peach.git -b v1.7 /opt/peach/ RUN \ apt-get remove -y build-essential git && \ diff --git a/modules/local/peach/main.nf b/modules/local/peach/main.nf index a7379449..34d6ba37 100644 --- a/modules/local/peach/main.nf +++ b/modules/local/peach/main.nf @@ -2,7 +2,7 @@ process PEACH { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/peach:1.6--0' + container 'docker.io/scwatts/peach:1.7--0' input: tuple val(meta), path(germline_vcf) @@ -19,7 +19,7 @@ process PEACH { script: def args = task.ext.args ?: '' - def tool_version = '1.6' + def tool_version = '1.7' """ python ${task.ext.scriptPath} \\ diff --git a/modules/local/protect/Dockerfile b/modules/local/protect/Dockerfile index e78e4db2..870f3e2a 100644 --- a/modules/local/protect/Dockerfile +++ b/modules/local/protect/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/protect/ && \ - wget -O /opt/protect/protect.jar 'https://github.com/hartwigmedical/hmftools/releases/download/protect-v2.2/protect.jar' + wget -O /opt/protect/protect.jar 'https://github.com/hartwigmedical/hmftools/releases/download/protect-v2.3/protect.jar' USER mambauser diff --git a/modules/local/protect/main.nf b/modules/local/protect/main.nf index 55450f8d..5335839a 100644 --- a/modules/local/protect/main.nf +++ b/modules/local/protect/main.nf @@ -2,12 +2,13 @@ process PROTECT { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/protect:2.2--0' + container 'docker.io/scwatts/protect:2.3--0' input: - tuple val(meta), path(chord_prediction), path(purple_dir), path(linx_dir), path(virusinterpreter) + tuple val(meta), path(chord_prediction), path(purple_dir), path(linx_dir), path(lilac_dir), path(virusinterpreter) val genome_ver path serve_resources + path driver_gene_panel path disease_ontology output: @@ -28,20 +29,29 @@ process PROTECT { -reference_sample_id ${meta.normal_id} \\ -primary_tumor_doids '' \\ -output_dir ./ \\ + \\ -serve_actionability_dir ${serve_resources} \\ -ref_genome_version ${genome_ver} \\ + -driver_gene_tsv ${driver_gene_panel} \\ -doid_json ${disease_ontology} \\ + \\ -chord_prediction_txt ${chord_prediction} \\ - -purple_purity_tsv ${purple_dir}/${meta.tumor_id}.purple.purity.tsv \\ + \\ -purple_qc_file ${purple_dir}/${meta.tumor_id}.purple.qc \\ + -purple_purity_tsv ${purple_dir}/${meta.tumor_id}.purple.purity.tsv \\ -purple_gene_copy_number_tsv ${purple_dir}/${meta.tumor_id}.purple.cnv.gene.tsv \\ -purple_somatic_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.somatic.tsv \\ - -purple_germline_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.germline.tsv \\ -purple_somatic_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.somatic.vcf.gz \\ + -purple_germline_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.germline.tsv \\ -purple_germline_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.germline.vcf.gz \\ - -linx_fusion_tsv ${linx_dir}/${meta.tumor_id}.linx.fusion.tsv \\ + \\ -linx_breakend_tsv ${linx_dir}/${meta.tumor_id}.linx.breakend.tsv \\ -linx_driver_catalog_tsv ${linx_dir}/${meta.tumor_id}.linx.driver.catalog.tsv \\ + -linx_fusion_tsv ${linx_dir}/${meta.tumor_id}.linx.fusion.tsv \\ + \\ + -lilac_qc_csv ${lilac_dir}/${meta.tumor_id}.lilac.qc.csv \\ + -lilac_result_csv ${lilac_dir}/${meta.tumor_id}.lilac.csv \\ + \\ -annotated_virus_tsv ${virusinterpreter} cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/protect/meta.yml b/modules/local/protect/meta.yml index 01cdee94..3ed42132 100644 --- a/modules/local/protect/meta.yml +++ b/modules/local/protect/meta.yml @@ -16,6 +16,23 @@ input: description: | Groovy Map containing sample information e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - chord_prediction: + type: file + description: CHORD prediction file + pattern: "*.{txt}" + - purple_dir: + type: directory + description: PURPLE output directory + - linx_dir: + type: directory + description: LINX somatic annotation output directory + - lilac_dir: + type: directory + description: LILAC output directory + - virusinterpreter: + type: file + description: Virus Interpreter annotations file + pattern: "*.{tsv}" - genome_ver: type: string description: Reference genome version diff --git a/modules/local/purple/Dockerfile b/modules/local/purple/Dockerfile index 411117d2..d00dd84a 100644 --- a/modules/local/purple/Dockerfile +++ b/modules/local/purple/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/purple/ && \ - wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.4.3/purple_v3.4.3.jar' + wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.7/purple_v3.7.1.jar' USER mambauser diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 2601c92d..d9d65a1f 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -2,7 +2,7 @@ process PURPLE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/purple:3.4.3--0' + container 'docker.io/scwatts/purple:3.7.1--0' input: tuple val(meta), path(amber), path(cobalt), path(sv_hard_vcf), path(sv_hard_vcf_index), path(sv_soft_vcf), path(sv_soft_vcf_index), path(smlv_tumor_vcf), path(smlv_normal_vcf) diff --git a/modules/local/sage/Dockerfile b/modules/local/sage/Dockerfile index 518f774a..5db4d918 100644 --- a/modules/local/sage/Dockerfile +++ b/modules/local/sage/Dockerfile @@ -10,12 +10,13 @@ RUN \ RUN \ mkdir -p /opt/sage/ && \ - wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.0.3/sage_v3.0_rc3.jar' + wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.2.3/sage_v3.2.3.jar' USER mambauser RUN \ micromamba install -y -n base -c bioconda -c conda-forge \ + 'bcftools ==1.16' \ bioconductor-genomicranges \ bioconductor-variantannotation \ font-ttf-dejavu \ diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index f53b49ce..f6fb998d 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -2,7 +2,7 @@ process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.0.3--0' + container 'docker.io/scwatts/sage:3.2.3--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -11,8 +11,8 @@ process SAGE_GERMLINE { path genome_dict val genome_ver path sage_known_hotspots_germline - path sage_coding_panel - path sage_coverage_panel_germline + path sage_actionable_panel + path sage_coverage_panel path sage_highconf_regions path ensembl_data_resources @@ -33,15 +33,15 @@ process SAGE_GERMLINE { -Xmx${task.memory.giga}g \\ -jar ${task.ext.jarPath} \\ ${args} \\ - -reference ${meta.tumor_id} \\ - -reference_bam ${tumor_bam} \\ -tumor ${meta.normal_id} \\ -tumor_bam ${normal_bam} \\ + -reference ${meta.tumor_id} \\ + -reference_bam ${tumor_bam} \\ -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ -hotspots ${sage_known_hotspots_germline} \\ - -panel_bed ${sage_coding_panel} \\ - -coverage_bed ${sage_coverage_panel_germline} \\ + -panel_bed ${sage_actionable_panel} \\ + -coverage_bed ${sage_coverage_panel} \\ -high_confidence_bed ${sage_highconf_regions} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -hotspot_min_tumor_qual 50 \\ @@ -50,7 +50,7 @@ process SAGE_GERMLINE { -hotspot_max_germline_rel_raw_base_qual 100 \\ -panel_max_germline_vaf 100 \\ -panel_max_germline_rel_raw_base_qual 100 \\ - -mnv_filter_enabled false \\ + -ref_sample_count 0 \\ -panel_only \\ -threads ${task.cpus} \\ -out ./${meta.tumor_id}.sage.germline.vcf.gz diff --git a/modules/local/sage/germline/meta.yml b/modules/local/sage/germline/meta.yml index 8b2a9fc2..ccc46270 100644 --- a/modules/local/sage/germline/meta.yml +++ b/modules/local/sage/germline/meta.yml @@ -52,13 +52,13 @@ input: type: file description: SAGE germline known hotspots file pattern: "*.{vcf.gz}" - - sage_coding_panel: + - sage_actionable_panel: type: file - description: SAGE coding panel file + description: SAGE actionable panel file pattern: "*.{bed.gz}" - - sage_coverage_panel_germline: + - sage_coverage_panel: type: file - description: SAGE germline coverage ene panel file + description: SAGE coverage gene panel file pattern: "*.{bed.gz}" - sage_highconf_regions: type: file diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 4fc18c16..cb43244f 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -5,7 +5,7 @@ process SAGE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.0.3--0' + container 'docker.io/scwatts/sage:3.2.3--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -14,7 +14,7 @@ process SAGE_SOMATIC { path genome_dict val genome_ver path sage_known_hotspots_somatic - path sage_coding_panel + path sage_actionable_panel path sage_highconf_regions path ensembl_data_resources @@ -45,8 +45,8 @@ process SAGE_SOMATIC { -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ -hotspots ${sage_known_hotspots_somatic} \\ - -panel_bed ${sage_coding_panel} \\ - -coverage_bed ${sage_coding_panel} \\ + -panel_bed ${sage_actionable_panel} \\ + -coverage_bed ${sage_actionable_panel} \\ -high_confidence_bed ${sage_highconf_regions} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -write_bqr_data \\ diff --git a/modules/local/sage/somatic/meta.yml b/modules/local/sage/somatic/meta.yml index cc8f3f6c..172d7ad9 100644 --- a/modules/local/sage/somatic/meta.yml +++ b/modules/local/sage/somatic/meta.yml @@ -52,9 +52,9 @@ input: type: file description: SAGE somatic known hotspots file pattern: "*.{vcf.gz}" - - sage_coding_panel: + - sage_actionable_panel: type: file - description: SAGE coding gene panel file + description: SAGE actionable gene panel file pattern: "*.{bed.gz}" - sage_highconf_regions: type: file diff --git a/modules/local/sigs/Dockerfile b/modules/local/sigs/Dockerfile index 5b079be6..6e0fb67b 100644 --- a/modules/local/sigs/Dockerfile +++ b/modules/local/sigs/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/sigs/ && \ - wget -O /opt/sigs/sigs.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sigs-v1.0/sigs_v1.0.jar' + wget -O /opt/sigs/sigs.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sigs-v1.1/sigs_v1.1.jar USER mambauser diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index d094961a..8fe3a772 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -2,7 +2,7 @@ process SIGS { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/sigs:1.0--0' + container 'docker.io/scwatts/sigs:1.1--0' input: tuple val(meta), path(smlv_vcf) @@ -32,7 +32,7 @@ process SIGS { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - sigs: 1.0 + sigs: 1.1 END_VERSIONS """ diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile index 742d4390..f0ed272f 100644 --- a/modules/local/svprep/Dockerfile +++ b/modules/local/svprep/Dockerfile @@ -5,7 +5,7 @@ USER root RUN \ mkdir -p /opt/svprep/ && \ - wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.1/sv-prep_v1.1_beta.jar' + wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.0.1/sv-prep_v1.0.1.jar' COPY assets/gridss.svprep /opt/svprep/gridss_svprep RUN \ diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index bcd32a66..9f2a3321 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -2,7 +2,7 @@ process ASSEMBLE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.0.1--0' input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index f1ce2a1c..d31f3c21 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -2,7 +2,7 @@ process CALL { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.0.1--0' input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 06f267bf..495959b5 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -2,7 +2,7 @@ process DEPTH_ANNOTATOR { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.0.1--0' input: tuple val(meta), path(bams), path(bais), path(vcf), val(labels) diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index bb388ead..641aafae 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -2,7 +2,7 @@ process PREPROCESS { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.0.1--0' input: tuple val(meta), path(bam), path(bam_filtered) diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 36bd6d80..442496f5 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -2,7 +2,7 @@ process SVPREP { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.0.1--0' input: tuple val(meta), path(bam), path(bai), path(junctions) @@ -45,7 +45,7 @@ process SVPREP { cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: \$(java -jar ${task.ext.jarPath} 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + svprep: \$(java -jar ${task.ext.jarPath} 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') END_VERSIONS """ diff --git a/nextflow_schema.json b/nextflow_schema.json index beabf533..62926d1a 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -213,11 +213,18 @@ "ref_data_gridss_region_blocklist": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.bed.gz$", + "pattern": "^\\S+\\.bed\\.gz$", "description": "Path to GRIDSS blocklist file.", "fa_icon": "far fa-file-code", "hidden": true }, + "ref_data_repeatmasker_annotations": { + "type": "string", + "format": "file-path", + "description": "Path to RepeastMasker annotations file.", + "fa_icon": "far fa-file-code", + "hidden": true + }, "ref_data_isofox_counts": { "type": "string", "format": "file-path", @@ -312,19 +319,19 @@ "fa_icon": "far fa-file-code", "hidden": true }, - "ref_data_sage_coding_panel": { + "ref_data_sage_actionable_panel": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to somatic SAGE coding panel file.", + "description": "Path to somatic SAGE actionable panel file.", "fa_icon": "far fa-file-code", "hidden": true }, - "ref_data_sage_coverage_panel_germline": { + "ref_data_sage_coverage_panel": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to HMF SAGE germline coverage panel file.", + "description": "Path to HMF SAGE coverage panel file.", "fa_icon": "far fa-file-code", "hidden": true }, diff --git a/subworkflows/local/gripss.nf b/subworkflows/local/gripss.nf index 1166be98..6a80f822 100644 --- a/subworkflows/local/gripss.nf +++ b/subworkflows/local/gripss.nf @@ -7,13 +7,14 @@ include { GRIPSS_SOMATIC } from '../../modules/local/gripss/somatic/main' workflow GRIPSS { take: - ch_inputs // channel: [val(meta_gripss), gridss_vcf] - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_version // val: genome version - breakend_pon // file: /path/to/breakend_pon - breakpoint_pon // file: /path/to/breakpoint_pon - known_fusions // file: /path/to/known_fusions + ch_inputs // channel: [val(meta_gripss), gridss_vcf] + ref_data_genome_fasta // file: /path/to/genome_fasta + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_version // val: genome version + breakend_pon // file: /path/to/breakend_pon + breakpoint_pon // file: /path/to/breakpoint_pon + known_fusions // file: /path/to/known_fusions + repeatmasker_annotations // file: /path/to/repeatmasker_annotations main: // Channel for version.yml files @@ -28,6 +29,7 @@ workflow GRIPSS { breakend_pon, breakpoint_pon, known_fusions, + repeatmasker_annotations, ) ch_versions = ch_versions.mix(GRIPSS_GERMLINE.out.versions) @@ -40,6 +42,7 @@ workflow GRIPSS { breakend_pon, breakpoint_pon, known_fusions, + repeatmasker_annotations, ) ch_versions = ch_versions.mix(GRIPSS_SOMATIC.out.versions) diff --git a/subworkflows/local/linx.nf b/subworkflows/local/linx.nf index 96db9483..35899026 100644 --- a/subworkflows/local/linx.nf +++ b/subworkflows/local/linx.nf @@ -16,8 +16,6 @@ workflow LINX { ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ ref_data_known_fusion_data // file: /path/to/known_fusion_data ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - ref_data_gridss_pon_breakends // file: /path/to/gridss_pon_breakends - ref_data_gridss_pon_breakpoints // file: /path/to/gridss_pon_breakpoints main: // Channel for versions.yml files @@ -27,12 +25,9 @@ workflow LINX { LINX_GERMLINE( ch_linx_germline_inputs, ref_data_genome_version, - ref_data_linx_fragile_regions, ref_data_linx_lines, ref_data_ensembl_data_resources, ref_data_driver_gene_panel, - ref_data_gridss_pon_breakends, - ref_data_gridss_pon_breakpoints, ) ch_versions = ch_versions.mix(LINX_GERMLINE.out.versions) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 65a488e6..387d7fd1 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -134,10 +134,11 @@ def createHmfDataMap(hmf_data_base, params_only) { cuppa_resources: 'ref_data_cuppa_resources', // SVPREP 'sv_prep_blocklist': 'ref_data_sv_prep_blocklist', - // GRIDSS + // GRIDSS, GRIPSS gridss_pon_breakends: 'ref_data_gridss_pon_breakends', gridss_pon_breakpoints: 'ref_data_gridss_pon_breakpoints', gridss_region_blocklist: 'ref_data_gridss_region_blocklist', + repeatmasker_annotations: 'ref_data_repeatmasker_annotations', // Isofox isofox_counts: 'ref_data_isofox_counts', isofox_gc_ratios: 'ref_data_isofox_gc_ratios', @@ -157,8 +158,8 @@ def createHmfDataMap(hmf_data_base, params_only) { clinvar_annotations: 'ref_data_clinvar_annotations', sage_blocklist_regions: 'ref_data_sage_blocklist_regions', sage_blocklist_sites: 'ref_data_sage_blocklist_sites', - sage_coding_panel: 'ref_data_sage_coding_panel', - sage_coverage_panel_germline: 'ref_data_sage_coverage_panel_germline', + sage_actionable_panel: 'ref_data_sage_actionable_panel', + sage_coverage_panel: 'ref_data_sage_coverage_panel', sage_highconf_regions: 'ref_data_sage_highconf_regions', sage_known_hotspots_germline: 'ref_data_sage_known_hotspots_germline', sage_known_hotspots_somatic: 'ref_data_sage_known_hotspots_somatic', @@ -193,6 +194,13 @@ def getHmfDataFileObject(pk, hk, base_dir, params_only) { } else if (!hmfdata_paths.containsKey(hk)) { assert false : "bad key for params.hmfdata_paths.${params.genome_version}: ${hk}" } else { + + // NOTE(SW): allow paths to optionally set by checking for and returning '[]' values + def value = hmfdata_paths.getAt(hk) + if (value == []) { + return value + } + def base_dir_noslash = base_dir.toString().replaceAll('/$', '') return file("${base_dir_noslash}/${hmfdata_paths.getAt(hk)}", checkIfExists: true) } diff --git a/subworkflows/local/sage.nf b/subworkflows/local/sage.nf index b18ef1d0..72a75834 100644 --- a/subworkflows/local/sage.nf +++ b/subworkflows/local/sage.nf @@ -14,8 +14,8 @@ workflow SAGE { ref_data_genome_version // val: genome version ref_data_sage_known_hotspots_germline // file: /path/to/sage_known_hotspots_germline ref_data_sage_known_hotspots_somatic // file: /path/to/sage_known_hotspots_somatic - ref_data_sage_coding_panel // file: /path/to/sage_coding_panel - ref_data_sage_coverage_panel_germline // file: /path/to/sage_coverage_panel_germline + ref_data_sage_actionable_panel // file: /path/to/sage_actionable_panel + ref_data_sage_coverage_panel // file: /path/to/sage_coverage_panel ref_data_sage_highconf_regions // file: /path/to/sage_highconf_regions ref_data_sage_pon // file: /path/to/sage_pon ref_data_segment_mappability // file: /path/to/segment_mappability @@ -34,8 +34,8 @@ workflow SAGE { ref_data_genome_dict, ref_data_genome_version, ref_data_sage_known_hotspots_germline, - ref_data_sage_coding_panel, - ref_data_sage_coverage_panel_germline, + ref_data_sage_actionable_panel, + ref_data_sage_coverage_panel, ref_data_sage_highconf_regions, ref_data_ensembl_data_resources, ) @@ -49,7 +49,7 @@ workflow SAGE { ref_data_genome_dict, ref_data_genome_version, ref_data_sage_known_hotspots_somatic, - ref_data_sage_coding_panel, + ref_data_sage_actionable_panel, ref_data_sage_highconf_regions, ref_data_ensembl_data_resources, ) diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 8776c1dc..ab779593 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -406,6 +406,7 @@ workflow ONCOANALYSER { hmf_data.gridss_pon_breakends, hmf_data.gridss_pon_breakpoints, hmf_data.known_fusions, + hmf_data.repeatmasker_annotations, ) // Set outputs, restoring original meta @@ -449,8 +450,8 @@ workflow ONCOANALYSER { PREPARE_REFERENCE.out.genome_version, hmf_data.sage_known_hotspots_germline, hmf_data.sage_known_hotspots_somatic, - hmf_data.sage_coding_panel, - hmf_data.sage_coverage_panel_germline, + hmf_data.sage_actionable_panel, + hmf_data.sage_coverage_panel, hmf_data.sage_highconf_regions, hmf_data.sage_pon, hmf_data.segment_mappability, @@ -842,8 +843,6 @@ workflow ONCOANALYSER { hmf_data.ensembl_data_resources, hmf_data.known_fusion_data, hmf_data.driver_gene_panel, - hmf_data.gridss_pon_breakends, - hmf_data.gridss_pon_breakpoints, ) // Set outputs, restoring original meta @@ -889,6 +888,7 @@ workflow ONCOANALYSER { run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CHORD_PREDICTION, Constants.DataType.TUMOR]), run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.TUMOR_NORMAL]), + run.lilac ? ch_lilac_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LILAC_DIR, Constants.DataType.NORMAL]), run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.VIRUSINTERPRETER_TSV, Constants.DataType.TUMOR]), ) @@ -912,6 +912,7 @@ workflow ONCOANALYSER { ch_protect_inputs, PREPARE_REFERENCE.out.genome_version, hmf_data.serve_resources, + hmf_data.driver_gene_panel, hmf_data.disease_ontology, ) @@ -1173,7 +1174,7 @@ workflow ONCOANALYSER { hmf_data.driver_gene_panel, hmf_data.cohort_mapping, hmf_data.cohort_percentiles, - "5.23 [oncoanalyser]", + "5.31 [oncoanalyser]", ) // Set outputs From 86d57d15a86f7a2ebdf068d83caeb9eb4b82d1ab Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 23 Jan 2023 15:20:58 +1100 Subject: [PATCH 101/562] Update process resources, tags --- conf/base.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/base.config b/conf/base.config index bf3f7683..eca7f37f 100644 --- a/conf/base.config +++ b/conf/base.config @@ -71,9 +71,9 @@ process { memory = { check_max( 1.GB, 'memory' ) } } withName:'SVPREP.*' { - memory = { check_max( 12.GB, 'memory' ) } + memory = { check_max( 16.GB, 'memory' ) } } - withName:'.*:GRIDSS:.*' { + withName: '.*:GRIDSS(?!_SVPREP).*' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 30.GB, 'memory' ) } } From 5d948c43cdd65aeee8ce2206fced46de3718b102 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 23 Jan 2023 15:21:29 +1100 Subject: [PATCH 102/562] Prevent SV Prep crashing by enforcing memory buffer --- modules/local/svprep/assemble/main.nf | 3 ++- modules/local/svprep/assets/gridss.svprep | 10 +++++++++- modules/local/svprep/call/main.nf | 3 ++- modules/local/svprep/svprep/main.nf | 5 ++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 9f2a3321..4df53457 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -65,7 +65,8 @@ process ASSEMBLE { # Run gridss_svprep \\ ${args} \\ - --jvmheap ${task.memory.giga}g \\ + --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ + --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ --jar ${task.ext.jarPath} \\ --steps assemble \\ --labels ${labels_arg} \\ diff --git a/modules/local/svprep/assets/gridss.svprep b/modules/local/svprep/assets/gridss.svprep index d1b1f3e8..60e8375a 100644 --- a/modules/local/svprep/assets/gridss.svprep +++ b/modules/local/svprep/assets/gridss.svprep @@ -71,10 +71,14 @@ Usage: gridss [options] -r -o -a i -b/bams: comma separated full-path BAM files -f/filtered_bams: comma separated full-path filtered BAM files --jvmheap: size of JVM heap for the high-memory component of assembly and variant calling. (Default: $jvmheap) + --otherjvmheap: size of JVM heap for everything else. Useful to prevent + java out of memory errors when using large (>4Gb) reference genomes. + Note that some parts of assembly and variant calling use this heap + size. (Default: $otherjvmheap) " OPTIONS=r:o:a:t:j:w:e:s:c:l:b:f: -LONGOPTS=reference:,output:,assembly:,threads:,jar:,workingdir:,jvmheap:,blacklist:,steps:,configuration:,labels:,bams:,filtered_bams: +LONGOPTS=reference:,output:,assembly:,threads:,jar:,workingdir:,jvmheap:,otherjvmheap:,blacklist:,steps:,configuration:,labels:,bams:,filtered_bams: ! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") if [[ ${PIPESTATUS[0]} -ne 0 ]]; then # e.g. return value is 1 @@ -138,6 +142,10 @@ while [[ $# -gt 0 ]]; do jvmheap="$2" shift 2 ;; + --otherjvmheap) + otherjvmheap="$2" + shift 2 + ;; -t|--threads) printf -v threads '%d\n' "$2" 2>/dev/null printf -v threads '%d' "$2" 2>/dev/null diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index d31f3c21..d9c24998 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -63,7 +63,8 @@ process CALL { # Run gridss_svprep \\ ${args} \\ - --jvmheap ${task.memory.giga}g \\ + --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ + --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ --jar ${task.ext.jarPath} \\ --steps call \\ --labels ${labels_arg} \\ diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 442496f5..9b19f962 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -1,3 +1,6 @@ +// NOTE(SW): providing a 1GB memory buffer since SV Prep v1.0.1 is often killed due to exceeding +// allocated memory + process SVPREP { tag "${meta.id}" label 'process_medium' @@ -27,7 +30,7 @@ process SVPREP { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${task.memory.giga - 1}g \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ From 920c261b7685481bd3ee9b6ee94173ade44247ac Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 20 Jan 2023 09:43:00 +1100 Subject: [PATCH 103/562] Fix CUPPA report script patch --- .../assets/CupGenerateReport_pipeline.R.patch | 97 +++++++++++++++---- 1 file changed, 79 insertions(+), 18 deletions(-) diff --git a/modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch b/modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch index 4e165976..2bf7310e 100644 --- a/modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch +++ b/modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch @@ -1,31 +1,92 @@ --- a/CupGenerateReport_pipeline.R +++ b/CupGenerateReport_pipeline.R -@@ -165,10 +165,10 @@ if (featureCount > featureLimit) - } - +@@ -150,49 +150,30 @@ titleHeight = 10 + disclaimer1Height = 12 + disclaimer2Height = 14 + +-if (featureCount > featureLimit) +-{ +- separateFeaturePlot = T +- print(sprintf('Features(%d) print separately', featureCount)) +- plotHeights = c(summaryHeight, genderHeight, sigHeight, percHeight) +- plotHeightsDisclaimer = c(titleHeight, disclaimer1Height, disclaimer2Height, summaryHeight, genderHeight, sigHeight, percHeight) +-} else +-{ +- separateFeaturePlot = F +- featureHeight = 45 + (featureCount - 1) * 10 +- plotHeights = c(summaryHeight, genderHeight, sigHeight, percHeight, featureHeight) +- plotHeightsDisclaimer = c(titleHeight, disclaimer1Height, disclaimer2Height, summaryHeight, genderHeight, sigHeight, percHeight, featureHeight) +-} ++print(sprintf('Features(%d) print separately', featureCount)) ++plotHeights = c(summaryHeight, genderHeight, sigHeight, percHeight) ++plotHeightsDisclaimer = c(titleHeight, disclaimer1Height, disclaimer2Height, summaryHeight, genderHeight, sigHeight, percHeight) + # Generating PNG files -outputFileSummary = paste0(cuppaDir, sampleId, '.cup.report.summary.png') -+outputFileSummary = paste0(sampleId, '.cup.report.summary.png') - if (separateFeaturePlot) - { +-if (separateFeaturePlot) +-{ - outputFileFeatures = paste0(cuppaDir, sampleId, '.cup.report.features.png') -+ outputFileFeatures = paste0(sampleId, '.cup.report.features.png') - print(paste0("Writing output to png file: ", outputFileSummary)) - png(file = outputFileSummary, res = 140, height = 2200, width = 4000) - grid.arrange(plot_grid(summaryPlot, genderPlot, sigPlot, svTraitsPlot, -@@ -192,7 +192,7 @@ dev.off() - +- print(paste0("Writing output to png file: ", outputFileSummary)) +- png(file = outputFileSummary, res = 140, height = 2200, width = 4000) +- grid.arrange(plot_grid(summaryPlot, genderPlot, sigPlot, svTraitsPlot, +- ncol = 1, nrow = 4, rel_heights = plotHeights, align = 'v', axis = 'l')) +- +- print(paste0("Writing output to png file: ", outputFileFeatures)) +- png(file = outputFileFeatures, res = 140, height = 2200, width = 4000) +- featurePlot = featurePlot + +- scale_x_discrete(position = "top") + +- theme(axis.text.x.top = element_text(angle = 90, hjust = 0, size = 10, face = 'bold', family = font)) +- grid.arrange(plot_grid(featurePlot, ncol = 1, nrow = 1), newpage = T) +-} else +-{ +- print(paste0("Writing output to png file: ", outputFileSummary)) +- png(file = outputFileSummary, res = 140, height = 2200, width = 4000) +- plot_grid(summaryPlot, genderPlot, sigPlot, svTraitsPlot, featurePlot, +- ncol = 1, nrow = 5, rel_heights = plotHeights, align = 'v', axis = 'l') +-} ++outputFileSummary = paste0(sampleId, '.cup.report.summary.png') ++outputFileFeatures = paste0(sampleId, '.cup.report.features.png') ++print(paste0("Writing output to png file: ", outputFileSummary)) ++png(file = outputFileSummary, res = 140, height = 2200, width = 4000) ++grid.arrange(plot_grid(summaryPlot, genderPlot, sigPlot, svTraitsPlot, ++ ncol = 1, nrow = 4, rel_heights = plotHeights, align = 'v', axis = 'l')) ++ ++print(paste0("Writing output to png file: ", outputFileFeatures)) ++png(file = outputFileFeatures, res = 140, height = 2200, width = 4000) ++featurePlot = featurePlot + ++ scale_x_discrete(position = "top") + ++ theme(axis.text.x.top = element_text(angle = 90, hjust = 0, size = 10, face = 'bold', family = font)) ++grid.arrange(plot_grid(featurePlot, ncol = 1, nrow = 1), newpage = T) + + dev.off() + # Generate PDF report with disclaimer - + -outputFile = paste0(cuppaDir, sampleId, '_cup_report.pdf') +outputFile = paste0(sampleId, '_cup_report.pdf') print(paste0("writing output to pdf file: ", outputFile)) - + pdf(file = outputFile, height = 14, width = 20) -@@ -214,4 +214,4 @@ if (separateFeaturePlot) - ncol = 1, nrow = 8, rel_heights = plotHeightsDisclaimer, align = 'v', axis = 'l') - } - +@@ -202,16 +183,9 @@ title = textGrob(paste0(sampleId, ' CUP Report'), gp = gpar(fontface = "bold", f + disclaimer1 = textGrob(paste('All results and data described in this report are for research-use-only and have not been generated using a clinically validated and controlled procedure.'), gp = gpar(fontface = "bold", fontsize = 13)) + disclaimer2 = textGrob(paste('These results should not be used for clinical decision making.'), gp = gpar(fontface = "bold", fontsize = 13)) + +-if (separateFeaturePlot) +- { +- grid.arrange(plot_grid(title, disclaimer1, disclaimer2, summaryPlot, genderPlot, sigPlot, svTraitsPlot, +- ncol = 1, nrow = 7, rel_heights = plotHeightsDisclaimer, align = 'v', axis = 'l')) +- +- grid.arrange(plot_grid(featurePlot, ncol = 1, nrow = 1), newpage = T) +-} else +-{ +- plot_grid(title, disclaimer1, disclaimer2, summaryPlot, genderPlot, sigPlot, svTraitsPlot, featurePlot, +- ncol = 1, nrow = 8, rel_heights = plotHeightsDisclaimer, align = 'v', axis = 'l') +-} ++grid.arrange(plot_grid(title, disclaimer1, disclaimer2, summaryPlot, genderPlot, sigPlot, svTraitsPlot, ++ ncol = 1, nrow = 7, rel_heights = plotHeightsDisclaimer, align = 'v', axis = 'l')) ++ ++grid.arrange(plot_grid(featurePlot, ncol = 1, nrow = 1), newpage = T) + -dev.off() \ No newline at end of file +dev.off() From f0578ee73fa32de6bf8ccf63c6e011d0e6c9a37c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 20 Jan 2023 15:01:06 +1100 Subject: [PATCH 104/562] Accept BWA indices, HMF data as tarballs --- conf/test.config | 2 +- lib/Constants.groovy | 4 +-- lib/WorkflowOncoanalyser.groovy | 6 ++-- subworkflows/local/prepare_reference.nf | 48 +++++++++++++++++++------ 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/conf/test.config b/conf/test.config index 53ec948b..fd22da6e 100644 --- a/conf/test.config +++ b/conf/test.config @@ -45,7 +45,7 @@ params { // Input data input = '/Users/stephen/repos/oncoanalyser/temp/samplesheet.csv' - ref_data_hmf_data_base = '/Users/stephen/repos/oncoanalyser/temp/hmf_bundle' + ref_data_hmf_data_path = '/Users/stephen/repos/oncoanalyser/temp/hmf_bundle' ref_data_virusbreakenddb_path = '/Users/stephen/repos/oncoanalyser/temp/virusbreakenddb_20210401.tar.gz' genome = 'GRCh37_hmf' diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 78af1318..9ec61acb 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -5,8 +5,8 @@ class Constants { static List GENOMES_VERSION_38 = ['GRCh38_hmf', 'GRCh38', 'hg38'] static List GENOMES_ALT = ['GRCh38', 'hg38'] - static String HMF_DATA_37_BASE = 's3://umccr-research-dev/stephen/hmf_reference_data/2_repacked/hmf_data_bundle_5.29_37_0.0.1/' - static String HMF_DATA_38_BASE = 's3://umccr-research-dev/stephen/hmf_reference_data/2_repacked/hmf_data_bundle_5.29_38_0.0.1/' + static String HMF_DATA_37_PATH = 's3://umccr-research-dev/stephen/hmf_reference_data/2_repacked/hmf_data_bundle_5.29_37_0.0.1/' + static String HMF_DATA_38_PATH = 's3://umccr-research-dev/stephen/hmf_reference_data/2_repacked/hmf_data_bundle_5.29_38_0.0.1/' static String VIRUSBREAKENDDB_PATH = 's3://virusbreakend/virusbreakenddb_20210401.tar.gz' diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 9f5eb91c..5f097538 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -62,11 +62,11 @@ class WorkflowOncoanalyser { params.ref_data_genome_type = 'no_alt' } - if (!params.containsKey('ref_data_hmf_data_base')) { + if (!params.containsKey('ref_data_hmf_data_path')) { if (params.ref_data_genome_version == '37') { - params.ref_data_hmf_data_base = Constants.HMF_DATA_37_BASE + params.ref_data_hmf_data_path = Constants.HMF_DATA_37_PATH } else if (params.ref_data_genome_version == '38') { - params.ref_data_hmf_data_base = Constants.HMF_DATA_38_BASE + params.ref_data_hmf_data_path = Constants.HMF_DATA_38_PATH } else { assert false : "Got a bad genome version: ${params.ref_data_genome_version}" } diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 387d7fd1..8de73349 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -6,9 +6,11 @@ include { SAMTOOLS_FAIDX } from '../../modules/nf-core/samtools/faidx/ma include { SAMTOOLS_DICT } from '../../modules/nf-core/samtools/dict/main' include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' -include { CUSTOM_EXTRACTTARBALL } from '../../modules/local/custom/extract_tarball/main' -include { GRIDSS_INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' -include { GRIDSS_INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' +include { CUSTOM_EXTRACTTARBALL as DECOMP_BWA_INDEX } from '../../modules/local/custom/extract_tarball/main' +include { CUSTOM_EXTRACTTARBALL as DECOMP_HMF_DATA } from '../../modules/local/custom/extract_tarball/main' +include { CUSTOM_EXTRACTTARBALL as DECOMP_VIRUSBREAKEND_DB } from '../../modules/local/custom/extract_tarball/main' +include { GRIDSS_INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' +include { GRIDSS_INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' workflow PREPARE_REFERENCE { take: @@ -49,11 +51,20 @@ workflow PREPARE_REFERENCE { ch_genome_bwa_index_image = file(params.ref_data_genome_bwa_index_image) ch_genome_gridss_index = file(params.ref_data_genome_gridss_index) if (run.gridss || run.virusinterpreter) { + // NOTE(SW): the BWA index directory can be provided as a compressed tarball if (!params.ref_data_genome_bwa_index) { BWA_INDEX([[:], ch_genome_fasta]) ch_genome_bwa_index = BWA_INDEX.out.index.map { it[1] } ch_versions = ch_versions.mix(BWA_INDEX.out.versions) + } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { + ch_genome_bwa_index_inputs = [ + [id: 'bwa_index'], + file(params.ref_data_genome_bwa_index), + ] + DECOMP_BWA_INDEX(ch_genome_bwa_index_inputs) + ch_genome_bwa_index = DECOMP_BWA_INDEX.out.dir } + if (!params.ref_data_genome_bwa_index_image) { GRIDSS_BWA_INDEX_IMAGE( ch_genome_fasta, @@ -81,7 +92,7 @@ workflow PREPARE_REFERENCE { } // - // Set VIRUSBreakend database paths / stage, unpack if required + // Set VIRUSBreakend database path / stage, unpack if required // ch_virusbreakenddb = Channel.empty() if (run.virusinterpreter) { @@ -90,18 +101,33 @@ workflow PREPARE_REFERENCE { [id: 'virusbreakenddb'], file(params.ref_data_virusbreakenddb_path), ] - CUSTOM_EXTRACTTARBALL(ch_virusbreakenddb_inputs) - ch_virusbreakenddb = CUSTOM_EXTRACTTARBALL.out.dir + DECOMP_VIRUSBREAKEND_DB(ch_virusbreakenddb_inputs) + ch_virusbreakenddb = DECOMP_VIRUSBREAKEND_DB.out.dir } else { ch_virusbreakenddb = file(params.ref_data_virusbreakenddb_path) } } // - // Set HMF reference paths + // Set HMF reference paths / stage, unpack if required // - if (params.ref_data_hmf_data_base) { - ch_hmf_data = createHmfDataMap(params.ref_data_hmf_data_base, false /* params_only */) + if (params.ref_data_hmf_data_path.endsWith('tar.gz')) { + // Decompress and set paths + ch_hmf_data_inputs = [ + [id: 'hmf_data'], + file(params.ref_data_hmf_data_path), + ] + DECOMP_HMF_DATA(ch_hmf_data_inputs) + + ch_hmf_data = DECOMP_HMF_DATA.out.dir + .collect() + .map { dir_list -> + assert dir_list.size() == 1 + return createHmfDataMap(dir_list[0], false /* params_only */) + } + } else if (params.ref_data_hmf_data_path) { + // If provided as path to directory, set paths + ch_hmf_data = createHmfDataMap(params.ref_data_hmf_data_path, false /* params_only */) } else { // If no HMF data bundle is supplied we construct from *only* params ch_hmf_data = createHmfDataMap(null, true /* params_only */) @@ -122,7 +148,7 @@ workflow PREPARE_REFERENCE { versions = ch_versions // channel: [versions.yml] } -def createHmfDataMap(hmf_data_base, params_only) { +def createHmfDataMap(hmf_data_path, params_only) { // NOTE(SW): this code provides an explicit mapping between user exposed HMF data params and // their corresponding internal representation def params_mapping = [ @@ -180,7 +206,7 @@ def createHmfDataMap(hmf_data_base, params_only) { segment_mappability: 'ref_data_segment_mappability', ] params_mapping.collectEntries { k, v -> - [k, getHmfDataFileObject(v, k, hmf_data_base, params_only)] + [k, getHmfDataFileObject(v, k, hmf_data_path, params_only)] } } From 4944033b39a74822ee64845c91ab549c0451fa5f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 20 Jan 2023 15:03:53 +1100 Subject: [PATCH 105/562] Clean up reference data paths, use data on R2 --- conf/hmfgenomes.config | 20 ++++++-------------- lib/Constants.groovy | 6 +++--- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/conf/hmfgenomes.config b/conf/hmfgenomes.config index a99c225c..c4de9fc8 100644 --- a/conf/hmfgenomes.config +++ b/conf/hmfgenomes.config @@ -10,20 +10,12 @@ params { genomes { 'GRCh37_hmf' { - fasta = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/Homo_sapiens.GRCh37.GATK.illumina.fasta" - fai = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" - dict = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" - bwa_index = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/bwa_index/" - bwa_index_image = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" - gridss_index = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh37/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" - } - 'GRCh38_hmf' { - fasta = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" - fai = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" - dict = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwa_index = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/bwa_index/" - bwa_index_image = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" - gridss_index = "s3://umccr-research-dev/stephen/hmf_reference_genomes/GRCh38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" + fasta = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/Homo_sapiens.GRCh37.GATK.illumina.fasta" + fai = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" + dict = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" + bwa_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/0.7.17-r1188.tar.gz" + bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" + gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" } } } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 9ec61acb..afc5fbec 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -5,10 +5,10 @@ class Constants { static List GENOMES_VERSION_38 = ['GRCh38_hmf', 'GRCh38', 'hg38'] static List GENOMES_ALT = ['GRCh38', 'hg38'] - static String HMF_DATA_37_PATH = 's3://umccr-research-dev/stephen/hmf_reference_data/2_repacked/hmf_data_bundle_5.29_37_0.0.1/' - static String HMF_DATA_38_PATH = 's3://umccr-research-dev/stephen/hmf_reference_data/2_repacked/hmf_data_bundle_5.29_38_0.0.1/' + static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.31_37_0.0.1.tar.gz' + static String HMF_DATA_38_PATH = null - static String VIRUSBREAKENDDB_PATH = 's3://virusbreakend/virusbreakenddb_20210401.tar.gz' + static String VIRUSBREAKENDDB_PATH = 'https://virusbreakend.s3.us-east-2.amazonaws.com/virusbreakenddb_20210401.tar.gz' static enum PipelineMode { FULL, From 4df591f8f7710c40222e6fc21baf8379f4dd4827 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 23 Jan 2023 15:21:58 +1100 Subject: [PATCH 106/562] Require 22.10.5 to avoid issues staging from R2 --- nextflow.config | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index 7f5027f4..312bb58e 100644 --- a/nextflow.config +++ b/nextflow.config @@ -197,7 +197,8 @@ manifest { description = 'A comprehensive cancer NGS analysis and reporting pipeline' mainScript = 'main.nf' // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release - nextflowVersion = '!>=22.10.4' + // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release + nextflowVersion = '!>=22.10.5' version = '0.0.1' doi = '' } From 4af780f2f758ce8104cb194780d5a5218d3eb238 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 20 Jan 2023 20:14:38 +1100 Subject: [PATCH 107/562] Fix CUSTOM_SLICE samtools index command --- modules/local/custom/lilac_slice/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index 58f59c2c..eed55288 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -27,7 +27,7 @@ process CUSTOM_SLICE { ${bam} | \\ samtools sort -T tmp -o ${bam_name}.sliced.bam - samtools index "${bam.simpleName}.sliced.bam" + samtools index ${bam_name}.sliced.bam cat <<-END_VERSIONS > versions.yml "${task.process}": From e94e25f4a5b08948d38dc72f64ab14beb38bd13e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 9 Feb 2023 11:23:52 +1100 Subject: [PATCH 108/562] Symlink BWA index files for VIRUSBreakend as required --- modules/local/virusbreakend/main.nf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 7b5e39b0..a2e326d1 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -29,6 +29,9 @@ process VIRUSBREAKEND { def args = task.ext.args ?: '' """ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + virusbreakend \\ --jar ${task.ext.jarPath} \\ --gridssargs "--jvmheap ${task.memory.giga}g" \\ From 32d3dd8ddd27d7ca58d1d784feed7fc06913d576 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 9 Feb 2023 11:26:50 +1100 Subject: [PATCH 109/562] Fix groupTuple with empty tuple return in getInput --- lib/WorkflowOncoanalyser.groovy | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 5f097538..f48f7d33 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -158,7 +158,13 @@ class WorkflowOncoanalyser { } public static getInput(ch, key) { - return ch.map { meta -> [meta, meta.getAt(key)] } + return ch.map { meta -> + if (meta.containsKey(key)) { + return [meta, meta.getAt(key)] + } else { + return [:] + } + } } public static joinMeta(Map named_args, ch_a, ch_b) { From f66dc60a1bc3c8ad9485b7d6061042b656f459fa Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 9 Feb 2023 11:29:14 +1100 Subject: [PATCH 110/562] Update GRIPSS somatic and germline stubs --- modules/local/gripss/germline/main.nf | 12 ++++++------ modules/local/gripss/somatic/main.nf | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 2f180165..99bd73fb 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -50,15 +50,15 @@ process GRIPSS_GERMLINE { stub: """ - cat < ${meta.normal_id}.gripss.filtered.vcf.gz + cat < ${meta.normal_id}.gripss.filtered.germline.vcf.gz ##fileformat=VCFv4.1 ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . + #CHROM POS ID REF ALT QUAL FILTER INFO + . . . . . . . EOF - touch ${meta.normal_id}.gripss.filtered.vcf.gz.tbi - touch ${meta.normal_id}.gripss.vcf.gz - touch ${meta.normal_id}.gripss.vcf.gz.tbi + touch ${meta.normal_id}.gripss.filtered.germline.vcf.gz.tbi + touch ${meta.normal_id}.gripss.germline.vcf.gz + touch ${meta.normal_id}.gripss.germline.vcf.gz.tbi echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index d48e5abd..cbfdc4cf 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -51,15 +51,15 @@ process GRIPSS_SOMATIC { stub: """ - cat < ${meta.tumor_id}.gripss.filtered.vcf.gz + cat < ${meta.tumor_id}.gripss.filtered.somatic.vcf.gz ##fileformat=VCFv4.1 ##contig= #CHROM POS ID REF ALT QUAL FILTER INFO . . . . . . . EOF - touch ${meta.tumor_id}.gripss.filtered.vcf.gz.tbi - touch ${meta.tumor_id}.gripss.vcf.gz - touch ${meta.tumor_id}.gripss.vcf.gz.tbi + touch ${meta.tumor_id}.gripss.filtered.somatic.vcf.gz.tbi + touch ${meta.tumor_id}.gripss.somatic.vcf.gz + touch ${meta.tumor_id}.gripss.somatic.vcf.gz.tbi echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } From 33fa4f21e369b162ae327328115736b1589ebbe9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 9 Feb 2023 11:30:03 +1100 Subject: [PATCH 111/562] Correct param name in pipeline schema --- nextflow_schema.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 62926d1a..eeddb792 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -96,10 +96,9 @@ "hidden": true, "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe c lashes between custom parameters and those supplied in `igenomes.config`." }, - "ref_data_hmf_data_base": { + "ref_data_hmf_data_path": { "type": "string", - "format": "directory-path", - "description": "Path to HMF data base directory or URL.", + "description": "Path to HMF data.", "fa_icon": "far fa-folder-open" }, "ref_data_virusbreakenddb_path": { From 10494d802f8f75d7fa24454591b6ad91a366f1d6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 9 Feb 2023 11:30:48 +1100 Subject: [PATCH 112/562] Patch virusbreakend script to enforce GRIDSS args Added for testing purposes. --- modules/local/gridss/Dockerfile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/local/gridss/Dockerfile b/modules/local/gridss/Dockerfile index b270f82c..6373cf84 100644 --- a/modules/local/gridss/Dockerfile +++ b/modules/local/gridss/Dockerfile @@ -15,11 +15,20 @@ RUN \ 'gridss==2.13.2' && \ micromamba clean --all --yes +# NOTE(SW): required to correctly check SAMtools version built by Conda RUN \ sed -i \ -e '209s/grep samtools/head -n1 | grep samtools/' \ /opt/conda/share/gridss-2.13.2-1/gridss_extract_overlapping_fragments +# NOTE(SW): required to run tests on compute with low resources; without the +# change this GRIDSS invoke will attempt to allocate the default 30 GB of +# memory even when `--gridssargs` is set +RUN \ + sed -i \ + -e '779a \\t\t$gridssargs \\' \ + /opt/conda/share/gridss-2.13.2-1/virusbreakend + RUN \ ln -sf \ /opt/conda/pkgs/gridss-2.13.2-h20b1175_1/share/gridss-2.13.2-1/gridss \ From 02a2c7057167e46f3d9c3365b58267a11fe52ea5 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 9 Feb 2023 11:31:47 +1100 Subject: [PATCH 113/562] Support optional somatic LINX gene_id_file input Added for testing purposes. --- modules/local/linx/somatic/main.nf | 3 +++ modules/local/linx/somatic/meta.yml | 4 ++++ nextflow.config | 3 +++ nextflow_schema.json | 5 +++++ subworkflows/local/linx.nf | 2 ++ workflows/oncoanalyser.nf | 5 +++++ 6 files changed, 22 insertions(+) diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 383464f7..f3d8a43b 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -12,6 +12,7 @@ process LINX_SOMATIC { path ensembl_data_resources path known_fusion_data path driver_gene_panel + path gene_id_file output: tuple val(meta), path('linx_somatic/'), emit: annotation_dir @@ -22,6 +23,7 @@ process LINX_SOMATIC { script: def args = task.ext.args ?: '' + def gene_id_file_arg = gene_id_file ? "-gene_id_file ${gene_id_file}" : '' """ java \\ @@ -32,6 +34,7 @@ process LINX_SOMATIC { -ref_genome_version ${genome_ver} \\ -sv_vcf ${purple_dir}/${meta.id}.purple.sv.vcf.gz \\ -purple_dir ${purple_dir} \\ + ${gene_id_file_arg} \\ -fragile_site_file ${fragile_regions} \\ -line_element_file ${lines} \\ -ensembl_data_dir ${ensembl_data_resources} \\ diff --git a/modules/local/linx/somatic/meta.yml b/modules/local/linx/somatic/meta.yml index 6b9b41ae..bc2ed58b 100644 --- a/modules/local/linx/somatic/meta.yml +++ b/modules/local/linx/somatic/meta.yml @@ -41,6 +41,10 @@ input: type: file description: Driver Gene Panel file pattern: "*.{csv}" + - gene_id_file: + type: file + description: Ensembl gene ID file + pattern: "*.{csv}" output: - meta: type: map diff --git a/nextflow.config b/nextflow.config index 312bb58e..ac5c0af1 100644 --- a/nextflow.config +++ b/nextflow.config @@ -42,7 +42,10 @@ params { show_hidden_params = false schema_ignore_params = 'genomes,hmfdata_paths' enable_conda = false + + // Other workflow inputs gridss_config = null + linx_gene_id_file = null // Config options custom_config_version = 'master' diff --git a/nextflow_schema.json b/nextflow_schema.json index eeddb792..2b448058 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -66,6 +66,11 @@ "type": "string", "description": "Path to GRIDSS configuration file.", "fa_icon": "fas fa-cog" + }, + "linx_gene_id_file": { + "type": "string", + "description": "Path to LINX gene ID file.", + "fa_icon": "fas fa-cog" } } }, diff --git a/subworkflows/local/linx.nf b/subworkflows/local/linx.nf index 35899026..320f67fa 100644 --- a/subworkflows/local/linx.nf +++ b/subworkflows/local/linx.nf @@ -16,6 +16,7 @@ workflow LINX { ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ ref_data_known_fusion_data // file: /path/to/known_fusion_data ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + gene_id_file // file: /path/to/linx_gene_id_file main: // Channel for versions.yml files @@ -40,6 +41,7 @@ workflow LINX { ref_data_ensembl_data_resources, ref_data_known_fusion_data, ref_data_driver_gene_panel, + gene_id_file, ) ch_versions = ch_versions.mix(LINX_SOMATIC.out.versions) diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index ab779593..1c8f9088 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -31,6 +31,7 @@ run = Constants.Process def checkPathParamList = [ params.input, params.gridss_config, + params.linx_gene_id_file, ] for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } @@ -38,6 +39,9 @@ for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true // Check mandatory parameters if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } +// Create Path objects for some input files +linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : [] + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CONFIG FILES @@ -843,6 +847,7 @@ workflow ONCOANALYSER { hmf_data.ensembl_data_resources, hmf_data.known_fusion_data, hmf_data.driver_gene_panel, + linx_gene_id_file, ) // Set outputs, restoring original meta From c70ca42dc7caa756710c0fac44b022890ae50b5a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 10 Feb 2023 15:30:03 +1100 Subject: [PATCH 114/562] Remove collectwgsmetrics interval file for tests --- conf/test.config | 7 +------ lib/WorkflowOncoanalyser.groovy | 13 ------------- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/conf/test.config b/conf/test.config index fd22da6e..ad3c99dd 100644 --- a/conf/test.config +++ b/conf/test.config @@ -22,10 +22,6 @@ process { ext.args = '-specific_regions \'chr10:87736200:88056500;chr17:59748500:59828700\'' } - withName: 'PICARD_COLLECTWGSMETRICS' { - // NOTE(SW): wrapped by a closure to delay eval until process creation/execution - ext.args = { "--INTERVALS ${params.ref_data_wgsmetrics_intervals_local}" } - } } params { @@ -34,8 +30,7 @@ params { // Defined here to be accessible within a workflow script; downloaded manually prior to process // execution. - ref_data_wgsmetrics_intervals_url = 'https://raw.githubusercontent.com/scwatts/nextflow_testdata/main/hmftools/collectwgsmetrics/intervals.interval_list' - schema_ignore_params = 'genomes,hmfdata_paths,ref_data_wgsmetrics_intervals_url' + schema_ignore_params = 'genomes,hmfdata_paths' // Limit resources so that this can run on GitHub Actions max_cpus = 1 diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index f48f7d33..6df07735 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -88,19 +88,6 @@ class WorkflowOncoanalyser { System.exit(1) } } - - // Download region file for collectwgsmetrics if in test mode - // NOTE(SW): this will be removed as part of the overhaul for testing - if (workflow.profile.contains('test')) { - def stage_dir = new File(workflow.workDir.toString(), 'stage/manual/') - def interval_file = new File(stage_dir, 'collectwgsmetrics.interval_list') - if (! interval_file.exists()) { - stage_dir.mkdirs() - interval_file.createNewFile() - interval_file << new URL (params.ref_data_wgsmetrics_intervals_url).getText() - } - params.ref_data_wgsmetrics_intervals_local = interval_file - } } public static groupByMeta(Map named_args, ... channels) { From 0722aceec69f762ea0cb17e9db2d8e6dbb4f2257 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 10 Feb 2023 15:32:28 +1100 Subject: [PATCH 115/562] Use simulated test data and config from R2 --- conf/test.config | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/conf/test.config b/conf/test.config index ad3c99dd..1d76eac0 100644 --- a/conf/test.config +++ b/conf/test.config @@ -11,15 +11,20 @@ */ process { - cups = 1 - memory = 16.GB + withName: 'ISOFOX' { + ext.args = '-specific_chr 19' + } + + withName: 'SAGE.*' { + ext.args = '-specific_chr 19' + } - withName: 'SAGE_GERMLINE' { - ext.args = '-specific_regions \'chr10:87864102:87966988\'' + withName: 'PURPLE' { + ext.args = '-min_ploidy 2 -max_ploidy 2 -min_purity 1 -max_purity 1' } - withName: 'SAGE_SOMATIC' { - ext.args = '-specific_regions \'chr10:87736200:88056500;chr17:59748500:59828700\'' + withName: 'LINX_SOMATIC' { + ext.args = '-write_all_vis_fusions' } } @@ -38,17 +43,12 @@ params { max_time = '6.h' // Input data - input = '/Users/stephen/repos/oncoanalyser/temp/samplesheet.csv' - - ref_data_hmf_data_path = '/Users/stephen/repos/oncoanalyser/temp/hmf_bundle' - ref_data_virusbreakenddb_path = '/Users/stephen/repos/oncoanalyser/temp/virusbreakenddb_20210401.tar.gz' + input = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/samplesheet.csv' genome = 'GRCh37_hmf' - ref_data_genome_fasta = '/Users/stephen/repos/oncoanalyser/temp/GRCh38.fasta' - ref_data_genome_fai = '/Users/stephen/repos/oncoanalyser/temp/GRCh38.fai' - ref_data_genome_dict = '/Users/stephen/repos/oncoanalyser/temp/GRCh38.dict' - ref_data_genome_bwa_index = '/Users/stephen/repos/oncoanalyser/temp/GRCh38_bwa/' - ref_data_genome_bwa_index_image = '/Users/stephen/repos/oncoanalyser/temp/GRCh38.img' - ref_data_genome_gridss_index = '/Users/stephen/repos/oncoanalyser/temp/GRCh38.gridsscache' + ref_data_virusbreakenddb_path = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/reference_data/virusbreakend/virusbreakenddb_test.tar.gz' + ref_data_known_fusion_data = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/known_fusion_data_custom.csv' + + linx_gene_id_file = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/fusion_genes.csv' } From fdfa64fc5fc027eda44850657f41da4f8c703984 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 10 Feb 2023 16:26:49 +1100 Subject: [PATCH 116/562] Move Isofox functions from ext.args to params --- conf/modules.config | 1 - modules/local/isofox/main.nf | 3 +++ nextflow.config | 3 ++- nextflow_schema.json | 6 ++++++ workflows/oncoanalyser.nf | 1 + 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 0f7aecbb..f811a9d0 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -218,7 +218,6 @@ process { withName: 'ISOFOX' { ext.jarPath = '/opt/isofox/isofox.jar' - ext.args = '-functions "TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS"' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 103402aa..2cb45638 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -6,6 +6,7 @@ process ISOFOX { input: tuple val(meta), path(bam), path(bai) + val functions path genome_fasta path genome_fai val genome_ver @@ -22,6 +23,7 @@ process ISOFOX { script: def args = task.ext.args ?: '' + def functions_arg = functions ? "-functions \'${functions}\'" : '' """ mkdir -p isofox/ @@ -32,6 +34,7 @@ process ISOFOX { ${args} \\ -sample ${meta.id} \\ -bam_file ${bam} \\ + ${functions_arg} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ diff --git a/nextflow.config b/nextflow.config index ac5c0af1..79bd61f0 100644 --- a/nextflow.config +++ b/nextflow.config @@ -43,9 +43,10 @@ params { schema_ignore_params = 'genomes,hmfdata_paths' enable_conda = false - // Other workflow inputs + // Other workflow inputs and options gridss_config = null linx_gene_id_file = null + isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' // Config options custom_config_version = 'master' diff --git a/nextflow_schema.json b/nextflow_schema.json index 2b448058..48965671 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -71,6 +71,12 @@ "type": "string", "description": "Path to LINX gene ID file.", "fa_icon": "fas fa-cog" + }, + "isofox_functions": { + "type": "string", + "description": "Semicolon-separated list of Isofox functions to run", + "default": "TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS", + "fa_icon": "fas fa-cog" } } }, diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 1c8f9088..a95f7789 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -164,6 +164,7 @@ workflow ONCOANALYSER { // Run process ISOFOX( ch_isofox_inputs, + params.isofox_functions, PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, PREPARE_REFERENCE.out.genome_version, From e74d85773e21ef118769e9a3451fed099172aa29 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 10 Feb 2023 17:38:40 +1100 Subject: [PATCH 117/562] Increase maximum test memory for GRIDSS --- conf/test.config | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conf/test.config b/conf/test.config index 1d76eac0..6d6db9e8 100644 --- a/conf/test.config +++ b/conf/test.config @@ -39,7 +39,8 @@ params { // Limit resources so that this can run on GitHub Actions max_cpus = 1 - max_memory = '6.GB' + // NOTE(SW): increased from 6GB to 8GB as required for GRIDSS + max_memory = '8.GB' max_time = '6.h' // Input data From eb839a8d4a945cf2b4e70e25870ebb59b8d90606 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 10 Feb 2023 18:05:47 +1100 Subject: [PATCH 118/562] Handle S3 URI for decompressed HMF data directory --- subworkflows/local/prepare_reference.nf | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 8de73349..0f3518f3 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -123,7 +123,17 @@ workflow PREPARE_REFERENCE { .collect() .map { dir_list -> assert dir_list.size() == 1 - return createHmfDataMap(dir_list[0], false /* params_only */) + + // NOTE(SW): use of toString() in getHmfDataFileObject() fails to parse S3 URIs, + // so must handle here (encountered with workDir set as S3 e.g. in NF Tower) + def dirpath = dir_list[0].toUri().toString() + // NOTE(SW): S3Path.toUri() includes an extra forward slash in the URI or path, + // which is removed here. Unsure whether this occurs in other URIs types. + if (dirpath.startsWith('s3:///')) { + dirpath = dirpath.replaceFirst(/^s3:\/\/\//, 's3://') + } + + return createHmfDataMap(dirpath, false /* params_only */) } } else if (params.ref_data_hmf_data_path) { // If provided as path to directory, set paths From fbc063abc36eca2524b256e4944c9be65077c54a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 22 Feb 2023 15:38:42 +1100 Subject: [PATCH 119/562] Use VIRUSBreakend database hosted on R2 rather than from S3 --- lib/Constants.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index afc5fbec..a26d12af 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -8,7 +8,7 @@ class Constants { static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.31_37_0.0.1.tar.gz' static String HMF_DATA_38_PATH = null - static String VIRUSBREAKENDDB_PATH = 'https://virusbreakend.s3.us-east-2.amazonaws.com/virusbreakenddb_20210401.tar.gz' + static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' static enum PipelineMode { FULL, From 95d49e2750916cdca4d366263396bc5e8d128c2c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 23 Feb 2023 12:13:50 +1100 Subject: [PATCH 120/562] Generate Isofox expected counts as default --- conf/test.config | 1 + modules/local/isofox/main.nf | 6 ++++-- modules/local/isofox/meta.yml | 4 ++-- nextflow.config | 7 ++++--- nextflow_schema.json | 6 ++++++ workflows/oncoanalyser.nf | 12 +++++++++++- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/conf/test.config b/conf/test.config index 6d6db9e8..03427988 100644 --- a/conf/test.config +++ b/conf/test.config @@ -52,4 +52,5 @@ params { ref_data_known_fusion_data = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/known_fusion_data_custom.csv' linx_gene_id_file = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/fusion_genes.csv' + use_isofox_exp_counts_cache = true } diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 2cb45638..abd52c6c 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -24,6 +24,8 @@ process ISOFOX { script: def args = task.ext.args ?: '' def functions_arg = functions ? "-functions \'${functions}\'" : '' + def exp_counts_arg = exp_counts ? "-exp_counts_file ${exp_counts}" : '' + def exp_gc_ratios_arg = exp_gc_ratios ? "-exp_gc_ratios_file ${exp_gc_ratios}" : '' """ mkdir -p isofox/ @@ -38,8 +40,8 @@ process ISOFOX { -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ - -exp_counts_file ${exp_counts} \\ - -exp_gc_ratios_file ${exp_gc_ratios} \\ + ${exp_counts_arg} \\ + ${exp_gc_ratios_arg} \\ -output_dir ./isofox/ \\ -threads ${task.cpus} diff --git a/modules/local/isofox/meta.yml b/modules/local/isofox/meta.yml index 41bf9132..3e9e1381 100644 --- a/modules/local/isofox/meta.yml +++ b/modules/local/isofox/meta.yml @@ -39,11 +39,11 @@ input: description: HMF ensembl data resources directory - exp_counts: type: file - description: Isofox expected counts file + description: Isofox expected counts file (optional) pattern: "*.{csv}" - exp_gc_ratios: type: file - description: Isofox expected GC ratio counts file + description: Isofox expected GC ratio counts file (optional) pattern: "*.{csv}" output: - meta: diff --git a/nextflow.config b/nextflow.config index 79bd61f0..f7eace0a 100644 --- a/nextflow.config +++ b/nextflow.config @@ -44,9 +44,10 @@ params { enable_conda = false // Other workflow inputs and options - gridss_config = null - linx_gene_id_file = null - isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' + gridss_config = null + linx_gene_id_file = null + isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' + use_isofox_exp_counts_cache = false // Config options custom_config_version = 'master' diff --git a/nextflow_schema.json b/nextflow_schema.json index 48965671..b1076071 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -77,6 +77,12 @@ "description": "Semicolon-separated list of Isofox functions to run", "default": "TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS", "fa_icon": "fas fa-cog" + }, + "use_isofox_exp_counts_cache": { + "type": "boolean", + "description": "Use the 151 bp read expected counts provided by the HMF bundle for Isofox", + "default": false, + "fa_icon": "fas fa-cog" } } }, diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index a95f7789..db6a4a98 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -161,6 +161,16 @@ workflow ONCOANALYSER { return [meta_isofox, bam, "${bam}.bai"] } + // Set Isofox cache files + // NOTE(SW): the Isofox expected count file is read length dependent so required users to explicitly use expect + // counts generated for 151 bp reads that is available in the HMF reference bundle. When not specifying an + // expected count file, Isofox will automatically create one for the computed read length. However, doing so + // greatly increases runtime. + // NOTE(SW): consider alternative approaches for using the expected count file e.g. generate once at runtime, + // then use for all samples; generate all possible read lengths outside of pipeline and store on a remote for + // retrieval at runtime (requires inference of read length) + isofox_counts = params.use_isofox_exp_counts_cache ? hmf_data.isofox_counts : [] + // Run process ISOFOX( ch_isofox_inputs, @@ -169,7 +179,7 @@ workflow ONCOANALYSER { PREPARE_REFERENCE.out.genome_fai, PREPARE_REFERENCE.out.genome_version, hmf_data.ensembl_data_resources, - hmf_data.isofox_counts, + isofox_counts, hmf_data.isofox_gc_ratios, ) From 3df85fba0b14955435b454a5cbcd192fd5f2a1ae Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 23 Feb 2023 12:16:58 +1100 Subject: [PATCH 121/562] =?UTF-8?q?Bump=20Isofox=20version:=201.5=20?= =?UTF-8?q?=E2=86=92=201.6.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/isofox/Dockerfile | 2 +- modules/local/isofox/main.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/isofox/Dockerfile b/modules/local/isofox/Dockerfile index 6e4b5b11..489084eb 100644 --- a/modules/local/isofox/Dockerfile +++ b/modules/local/isofox/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/isofox/ && \ - wget -O /opt/isofox/isofox.jar 'https://github.com/hartwigmedical/hmftools/releases/download/isofox-v1.5/isofox_v1.5_rc3.jar' + wget -O /opt/isofox/isofox.jar 'https://github.com/hartwigmedical/hmftools/releases/download/isofox-v1.6.1/isofox_v1.6.1.jar' USER mambauser diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index abd52c6c..a2f51498 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -2,7 +2,7 @@ process ISOFOX { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/isofox:1.5--0' + container 'docker.io/scwatts/isofox:1.6.1--0' input: tuple val(meta), path(bam), path(bai) From 116c59a4da172bd30a5bcf2b981afee438c3f7bc Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 23 Feb 2023 12:17:57 +1100 Subject: [PATCH 122/562] Adjust terminology for optional input in meta.yml --- modules/local/gridss/assemble/meta.yml | 2 +- modules/local/gridss/call/meta.yml | 2 +- modules/local/gridss/preprocess/meta.yml | 2 +- modules/local/purple/meta.yml | 4 ++-- modules/local/svprep/assemble/meta.yml | 2 +- modules/local/svprep/call/meta.yml | 2 +- modules/local/svprep/preprocess/meta.yml | 2 +- modules/local/svprep/svprep/meta.yml | 2 +- modules/local/virusbreakend/meta.yml | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/local/gridss/assemble/meta.yml b/modules/local/gridss/assemble/meta.yml index b93ae838..929eb0bb 100644 --- a/modules/local/gridss/assemble/meta.yml +++ b/modules/local/gridss/assemble/meta.yml @@ -27,7 +27,7 @@ input: description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - gridss_config: type: file - description: Optional GRIDSS configuration file (optional) + description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly fa file diff --git a/modules/local/gridss/call/meta.yml b/modules/local/gridss/call/meta.yml index db407d72..8fc76340 100644 --- a/modules/local/gridss/call/meta.yml +++ b/modules/local/gridss/call/meta.yml @@ -27,7 +27,7 @@ input: description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - gridss_config: type: file - description: Optional GRIDSS configuration file (optional) + description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly fa file diff --git a/modules/local/gridss/preprocess/meta.yml b/modules/local/gridss/preprocess/meta.yml index fdba777e..39fe570c 100644 --- a/modules/local/gridss/preprocess/meta.yml +++ b/modules/local/gridss/preprocess/meta.yml @@ -21,7 +21,7 @@ input: pattern: "*.{bam}" - gridss_config: type: file - description: Optional GRIDSS configuration file (optional) + description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly fa file diff --git a/modules/local/purple/meta.yml b/modules/local/purple/meta.yml index 6c2c7611..6df54e8e 100644 --- a/modules/local/purple/meta.yml +++ b/modules/local/purple/meta.yml @@ -42,11 +42,11 @@ input: pattern: "*.{vcf.gz.tbi}" - smlv_tumor_vcf: type: file - description: Optional small variant tumor VCF file + description: Small variant tumor VCF file (optional) pattern: "*.{vcf.gz}" - smlv_normal_vcf: type: file - description: Optional small variant normal VCF file + description: Small variant normal VCF file (optional) pattern: "*.{vcf.gz}" - genome_fasta: type: file diff --git a/modules/local/svprep/assemble/meta.yml b/modules/local/svprep/assemble/meta.yml index c275af3f..a54c7fa9 100644 --- a/modules/local/svprep/assemble/meta.yml +++ b/modules/local/svprep/assemble/meta.yml @@ -31,7 +31,7 @@ input: description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - gridss_config: type: file - description: Optional GRIDSS configuration file (optional) + description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly fa file diff --git a/modules/local/svprep/call/meta.yml b/modules/local/svprep/call/meta.yml index 9352c818..e3a1a69d 100644 --- a/modules/local/svprep/call/meta.yml +++ b/modules/local/svprep/call/meta.yml @@ -31,7 +31,7 @@ input: description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - gridss_config: type: file - description: Optional GRIDSS configuration file (optional) + description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly fa file diff --git a/modules/local/svprep/preprocess/meta.yml b/modules/local/svprep/preprocess/meta.yml index 4941f31e..c792bda5 100644 --- a/modules/local/svprep/preprocess/meta.yml +++ b/modules/local/svprep/preprocess/meta.yml @@ -25,7 +25,7 @@ input: pattern: "*.{bam}" - gridss_config: type: file - description: Optional GRIDSS configuration file (optional) + description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly fa file diff --git a/modules/local/svprep/svprep/meta.yml b/modules/local/svprep/svprep/meta.yml index 24aadfe3..e25a0202 100644 --- a/modules/local/svprep/svprep/meta.yml +++ b/modules/local/svprep/svprep/meta.yml @@ -26,7 +26,7 @@ input: pattern: "*.{bai}" - junctions: type: file - description: Optional existing candidate SV junctions file + description: Existing candidate SV junctions file (optional) pattern: "*.{csv}" - genome_fasta: type: file diff --git a/modules/local/virusbreakend/meta.yml b/modules/local/virusbreakend/meta.yml index d8fafb0c..ae9641d9 100644 --- a/modules/local/virusbreakend/meta.yml +++ b/modules/local/virusbreakend/meta.yml @@ -21,7 +21,7 @@ input: pattern: "*.{bam}" - gridss_config: type: file - description: Optional GRIDSS configuration file (optional) + description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly fa file From e1fe6f868306b6e8d5ccef111d22b2b8d79c3816 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 26 Feb 2023 16:04:49 +1100 Subject: [PATCH 123/562] Add config for limited use of GRCh38_hmf ref data --- conf/hmfdata.config | 54 +++++++++++++++++++++++++++++++++ conf/hmfgenomes.config | 8 +++++ lib/Constants.groovy | 16 +--------- lib/Processes.groovy | 15 --------- lib/WorkflowOncoanalyser.groovy | 4 +-- 5 files changed, 65 insertions(+), 32 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index bfffbc47..a7777846 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -54,5 +54,59 @@ params { purple_germline_del = 'purple/cohort_germline_del_freq.37.csv' segment_mappability = 'mappability/mappability_150.37.bed.gz' } + '38' { + // AMBER + heterozygous_sites = 'amber/GermlineHetPon.38.vcf.gz' + // COBALT + gc_profile = 'gc_profiles/GC_profile.1000bp.38.cnp' + // CUPPA + cuppa_resources = [] + // SV Prep + sv_prep_blocklist = 'gridss/sv_prep_blacklist.38.bed' + // GRIDSS, GRIPSS + gridss_pon_breakends = 'gridss/sgl_pon.38.bed.gz' + gridss_pon_breakpoints = 'gridss/sv_pon.38.bedpe.gz' + gridss_region_blocklist = 'gridss/gridss_blacklist.38.bed.gz' + repeatmasker_annotations = 'gridss/repeat_mask_data.38.fa.gz' + // Isofox + isofox_counts = 'isofox/read_151_exp_counts.csv' + isofox_gc_ratios = 'isofox/read_100_exp_gc_ratios.csv' + // LILAC + lilac_resources = 'lilac/' + // LINX + linx_fragile_regions = 'linx/fragile_sites_hmf.38.csv' + linx_lines = 'linx/line_elements.38.csv' + // ORANGE + cohort_mapping = 'orange/cohort_mapping.tsv' + cohort_percentiles = 'orange/cohort_percentiles.tsv' + // PEACH + peach_panel = 'peach/peach.json' + // PROTECT + serve_resources = 'serve/' + // SAGE + clinvar_annotations = 'sage/clinvar.38.vcf.gz' + sage_blocklist_regions = 'sage/KnownBlacklist.germline.38.bed' + sage_blocklist_sites = 'sage/KnownBlacklist.germline.38.vcf.gz' + sage_actionable_panel = 'sage/ActionableCodingPanel.38.bed.gz' + sage_coverage_panel = 'sage/CoverageCodingPanel.38.bed.gz' + sage_highconf_regions = 'giab_high_conf/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz' + sage_known_hotspots_germline = 'sage/KnownHotspots.germline.38.vcf.gz' + sage_known_hotspots_somatic = 'sage/KnownHotspots.somatic.38.vcf.gz' + sage_pon = 'sage/SageGermlinePon.98x.38.tsv.gz' + // SIGS + sigs_signatures = 'sigs/snv_cosmic_signatures.csv' + // Virus Interpreter + virus_reporting_db = 'virus_interpreter/virus_reporting_db.tsv' + virus_taxonomy_db = 'virus_interpreter/taxonomy_db.tsv' + // Misc + disease_ontology = 'disease_ontology/201015_doid.json' + driver_gene_panel = 'gene_panel/DriverGenePanel.38.tsv' + ensembl_data_resources = 'ensembl_data_cache/' + gnomad_pon_dir = 'gnomad/' + known_fusion_data = 'fusions/known_fusion_data.38.csv' + known_fusions = 'fusions/known_fusions.38.bedpe' + purple_germline_del = 'purple/cohort_germline_del_freq.38.csv' + segment_mappability = 'mappability/mappability_150.38.bed.gz' + } } } diff --git a/conf/hmfgenomes.config b/conf/hmfgenomes.config index c4de9fc8..147d4274 100644 --- a/conf/hmfgenomes.config +++ b/conf/hmfgenomes.config @@ -17,5 +17,13 @@ params { bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" } + 'GRCh38_hmf' { + fasta = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" + fai = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" + dict = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" + bwa_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz" + bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" + gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" + } } } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index a26d12af..4462facf 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -6,7 +6,7 @@ class Constants { static List GENOMES_ALT = ['GRCh38', 'hg38'] static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.31_37_0.0.1.tar.gz' - static String HMF_DATA_38_PATH = null + static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.31_38_0.0.1.tar.gz' static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' @@ -14,7 +14,6 @@ class Constants { FULL, MANUAL, GRIDSS_PURPLE_LINX, - CUPPA, } static enum Process { @@ -22,13 +21,11 @@ class Constants { CHORD, COBALT, COLLECTWGSMETRICS, - CUPPA, GRIDSS, GRIPSS, ISOFOX, LILAC, LINX, - ORANGE, PAVE, PEACH, PROTECT, @@ -63,16 +60,5 @@ class Constants { PURPLE_DIR, SAGE_VCF, VIRUSINTERPRETER_TSV, - // ORANGE specific - CHORD_PREDICTION, - CUPPA_CSV, - CUPPA_FEATURE_PLOT, - CUPPA_SUMMARY_PLOT, - FLAGSTAT, - LINX_PLOT_DIR, - PEACH_TSV, - PROTECT_TSV, - SAGE_BQR, - SAGE_COVERAGE, } } diff --git a/lib/Processes.groovy b/lib/Processes.groovy index 7284ce4c..f0546291 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -30,21 +30,6 @@ class Processes { Constants.Process.SVPREP, ] break - case Constants.PipelineMode.CUPPA: - processes = [ - Constants.Process.AMBER, - Constants.Process.COBALT, - Constants.Process.COLLECTWGSMETRICS, - Constants.Process.CUPPA, - Constants.Process.GRIDSS, - Constants.Process.GRIPSS, - Constants.Process.ISOFOX, - Constants.Process.LINX, - Constants.Process.PURPLE, - Constants.Process.SVPREP, - Constants.Process.VIRUSINTERPRETER, - ] - break default: log.error "\nERROR: we should never have come here" System.exit(1) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 6df07735..61737214 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -35,8 +35,8 @@ class WorkflowOncoanalyser { } // NOTE(SW): restricting allowable genome values to GRCh37_hmf for now - if (params.genome != 'GRCh37_hmf') { - log.error "ERROR: currently only the GRCh37_hmf genome is supported but got \"${params.genome}\"" + + if (params.genome != 'GRCh37_hmf' or params.genome != 'GRCh38_hmf') { + log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmd genomes are supported but got \"${params.genome}\"" + ", please adjust the --genome argument accordingly." System.exit(1) } From 7fb27598e951061652f988ad823a920499ae2c29 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 7 Mar 2023 17:32:56 +1100 Subject: [PATCH 124/562] Correct 'or' logic conditional syntax --- lib/WorkflowOncoanalyser.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 61737214..a3142a12 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -35,8 +35,8 @@ class WorkflowOncoanalyser { } // NOTE(SW): restricting allowable genome values to GRCh37_hmf for now - if (params.genome != 'GRCh37_hmf' or params.genome != 'GRCh38_hmf') { - log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmd genomes are supported but got \"${params.genome}\"" + + if (params.genome != 'GRCh37_hmf' && params.genome != 'GRCh38_hmf') { + log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got \"${params.genome}\"" + ", please adjust the --genome argument accordingly." System.exit(1) } From 7d500007ac3502eb13ed1139b3db884a876c98c6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 7 Mar 2023 17:56:07 +1100 Subject: [PATCH 125/562] Restore CUPPA configuration, add path for GRCh38 --- conf/hmfdata.config | 2 +- lib/Constants.groovy | 16 +++++++++++++++- lib/Processes.groovy | 15 +++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index a7777846..8683dc92 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -60,7 +60,7 @@ params { // COBALT gc_profile = 'gc_profiles/GC_profile.1000bp.38.cnp' // CUPPA - cuppa_resources = [] + cuppa_resources = 'cuppa/' // SV Prep sv_prep_blocklist = 'gridss/sv_prep_blacklist.38.bed' // GRIDSS, GRIPSS diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 4462facf..36a26079 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -6,7 +6,7 @@ class Constants { static List GENOMES_ALT = ['GRCh38', 'hg38'] static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.31_37_0.0.1.tar.gz' - static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.31_38_0.0.1.tar.gz' + static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32+dev1_38_0.0.1.tar.gz' static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' @@ -14,6 +14,7 @@ class Constants { FULL, MANUAL, GRIDSS_PURPLE_LINX, + CUPPA, } static enum Process { @@ -21,11 +22,13 @@ class Constants { CHORD, COBALT, COLLECTWGSMETRICS, + CUPPA, GRIDSS, GRIPSS, ISOFOX, LILAC, LINX, + ORANGE, PAVE, PEACH, PROTECT, @@ -60,5 +63,16 @@ class Constants { PURPLE_DIR, SAGE_VCF, VIRUSINTERPRETER_TSV, + // ORANGE specific + CHORD_PREDICTION, + CUPPA_CSV, + CUPPA_FEATURE_PLOT, + CUPPA_SUMMARY_PLOT, + FLAGSTAT, + LINX_PLOT_DIR, + PEACH_TSV, + PROTECT_TSV, + SAGE_BQR, + SAGE_COVERAGE, } } diff --git a/lib/Processes.groovy b/lib/Processes.groovy index f0546291..7284ce4c 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -30,6 +30,21 @@ class Processes { Constants.Process.SVPREP, ] break + case Constants.PipelineMode.CUPPA: + processes = [ + Constants.Process.AMBER, + Constants.Process.COBALT, + Constants.Process.COLLECTWGSMETRICS, + Constants.Process.CUPPA, + Constants.Process.GRIDSS, + Constants.Process.GRIPSS, + Constants.Process.ISOFOX, + Constants.Process.LINX, + Constants.Process.PURPLE, + Constants.Process.SVPREP, + Constants.Process.VIRUSINTERPRETER, + ] + break default: log.error "\nERROR: we should never have come here" System.exit(1) From 1d0470a25c200c2b922825fb5cf19b710919dd06 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 7 Mar 2023 17:56:22 +1100 Subject: [PATCH 126/562] Adjust SV Prep memory --- conf/base.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conf/base.config b/conf/base.config index eca7f37f..5095b3b8 100644 --- a/conf/base.config +++ b/conf/base.config @@ -73,6 +73,9 @@ process { withName:'SVPREP.*' { memory = { check_max( 16.GB, 'memory' ) } } + withName:'SVPREP_DEPTH_ANNOTATOR' { + memory = { check_max( 30.GB, 'memory' ) } + } withName: '.*:GRIDSS(?!_SVPREP).*' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 30.GB, 'memory' ) } From f9986b6b29f831eb781a38a3b0e8cb2a2a4dd044 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 7 Mar 2023 19:14:33 +1100 Subject: [PATCH 127/562] =?UTF-8?q?Bump=20CUPPA=20version:=201.7.1=20?= =?UTF-8?q?=E2=86=92=201.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/cuppa/Dockerfile | 4 ++-- modules/local/cuppa/classifier/main.nf | 6 ++++-- modules/local/cuppa/visualiser/main.nf | 4 ++-- workflows/oncoanalyser.nf | 1 + 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/modules/local/cuppa/Dockerfile b/modules/local/cuppa/Dockerfile index 1b89e1ce..9a3fe074 100644 --- a/modules/local/cuppa/Dockerfile +++ b/modules/local/cuppa/Dockerfile @@ -10,9 +10,9 @@ RUN \ RUN \ mkdir -p /opt/cuppa/ && \ - wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.7.1/cuppa.jar' + wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.8/cuppa_v1.8.jar' -ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.7.1 +ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.8 ARG URL_BASE_CHART=${URL_BASE}/cuppa/src/main/resources/cuppa-chart ARG URL_BASE_REPORT=${URL_BASE}/cuppa/src/main/resources/r ARG DIR_BASE=/opt/cuppa diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index 3ba9d2ba..2a5693ce 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -2,10 +2,11 @@ process CUPPA_CLASSIFIER { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.7.1--0' + container 'docker.io/scwatts/cuppa:1.8--0' input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter) + val ref_genome_ver path cuppa_resources output: @@ -32,12 +33,13 @@ process CUPPA_CLASSIFIER { -ref_data_dir ${cuppa_resources} \\ -sample_data ${meta.id} \\ -sample_data_dir sample_data/ \\ + -ref_genome_version ${ref_genome_ver} \\ -output_dir ./ # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - cuppa: 1.7.1 + cuppa: 1.8 END_VERSIONS """ diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf index 7c411bfe..3a5e6985 100644 --- a/modules/local/cuppa/visualiser/main.nf +++ b/modules/local/cuppa/visualiser/main.nf @@ -2,7 +2,7 @@ process CUPPA_VISUALISER { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.7.1--0' + container 'docker.io/scwatts/cuppa:1.8--0' input: tuple val(meta), path(cuppa_csv) @@ -31,7 +31,7 @@ process CUPPA_VISUALISER { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - cuppa: 1.7.1 + cuppa: 1.8 END_VERSIONS """ diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index db6a4a98..ca2ed3c3 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -1028,6 +1028,7 @@ workflow ONCOANALYSER { // Run process CUPPA_CLASSIFIER( ch_cuppa_inputs, + PREPARE_REFERENCE.out.genome_version, hmf_data.cuppa_resources, ) From 553911744a4b096aef8549b5ca02551643014b03 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 7 Mar 2023 19:59:29 +1100 Subject: [PATCH 128/562] Restore the FLAGSTAT filetype --- lib/Constants.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 36a26079..a0673625 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -53,6 +53,7 @@ class Constants { AMBER_DIR, COBALT_DIR, COLLECTWGSMETRICS, + FLAGSTAT, GRIDSS_VCF, GRIPSS_HARD_VCF, GRIPSS_SOFT_VCF, From 6fd2f03b83a3197e736e4740c47f670e96c779f4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 9 Mar 2023 09:56:09 +1100 Subject: [PATCH 129/562] Rebuild Docker images with new CUPPA v1.8 release --- modules/local/cuppa/classifier/main.nf | 2 +- modules/local/cuppa/visualiser/main.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index 2a5693ce..78bc42b7 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -2,7 +2,7 @@ process CUPPA_CLASSIFIER { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.8--0' + container 'docker.io/scwatts/cuppa:1.8--1' input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter) diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf index 3a5e6985..b723dc20 100644 --- a/modules/local/cuppa/visualiser/main.nf +++ b/modules/local/cuppa/visualiser/main.nf @@ -2,7 +2,7 @@ process CUPPA_VISUALISER { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.8--0' + container 'docker.io/scwatts/cuppa:1.8--1' input: tuple val(meta), path(cuppa_csv) From 465e500ff3917ae181f0ab47e439e9044240bc58 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 28 Mar 2023 11:56:36 +1100 Subject: [PATCH 130/562] Improve optional inputs, add sequence type --- assets/schema_input.json | 4 + lib/Constants.groovy | 67 +++++- lib/Utils.groovy | 37 +++ lib/WorkflowLilac.groovy | 42 ++-- lib/WorkflowOncoanalyser.groovy | 32 ++- modules/local/lilac/main.nf | 11 +- modules/local/lilac/meta.yml | 11 +- modules/local/purple/main.nf | 9 +- subworkflows/local/gridss.nf | 16 +- subworkflows/local/gridss_svprep.nf | 20 +- subworkflows/local/lilac.nf | 59 ++++- subworkflows/local/prepare_input.nf | 76 ++++-- workflows/oncoanalyser.nf | 359 +++++++++++++++++----------- 13 files changed, 502 insertions(+), 241 deletions(-) diff --git a/assets/schema_input.json b/assets/schema_input.json index 01796d58..aa8e460d 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -24,6 +24,10 @@ "pattern": "^\\S+$", "errorMessage": "sample_type must be provided and cannot contain spaces" }, + "sequence_type": { + "pattern": "^\\S+$", + "errorMessage": "sequence_type must be provided and cannot contain spaces" + }, "filetype": { "pattern": "^\\S+$", "errorMessage": "filetype must be provided and cannot contain spaces" diff --git a/lib/Constants.groovy b/lib/Constants.groovy index a0673625..43daf43f 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -39,21 +39,13 @@ class Constants { VIRUSINTERPRETER, } - static enum DataType { - TUMOR, - NORMAL, - TUMOR_NORMAL, - } - static enum FileType { // Generic - BAM_WGS, - BAM_WTS, + BAM, // Process AMBER_DIR, COBALT_DIR, COLLECTWGSMETRICS, - FLAGSTAT, GRIDSS_VCF, GRIPSS_HARD_VCF, GRIPSS_SOFT_VCF, @@ -76,4 +68,61 @@ class Constants { SAGE_BQR, SAGE_COVERAGE, } + + static enum SampleType { + TUMOR, + NORMAL, + TUMOR_NORMAL, + } + + static enum SequenceType { + WGS, + WGTS, + WTS, + } + + static Map META_PLACEHOLDER = [meta_placeholder: null] + + static Map INPUT = [ + ISOFOX_DIR: [FileType.ISOFOX_DIR, SampleType.TUMOR, SequenceType.WTS], + + AMBER_DIR: [FileType.AMBER_DIR, SampleType.TUMOR_NORMAL, SequenceType.WGS], + COBALT_DIR: [FileType.COBALT_DIR, SampleType.TUMOR_NORMAL, SequenceType.WGS], + + BAMTOOLS_TXT_TUMOR: [FileType.BAMTOOLS_TXT, SampleType.TUMOR, SequenceType.WGS], + BAMTOOLS_TXT_NORMAL: [FileType.BAMTOOLS_TXT, SampleType.NORMAL, SequenceType.WGS], + + SAGE_VCF_TUMOR: [FileType.SAGE_VCF, SampleType.TUMOR, SequenceType.WGS], + SAGE_VCF_NORMAL: [FileType.SAGE_VCF, SampleType.NORMAL, SequenceType.WGS], + SAGE_BQR_TUMOR: [FileType.SAGE_BQR, SampleType.TUMOR, SequenceType.WGS], + SAGE_BQR_NORMAL: [FileType.SAGE_BQR, SampleType.NORMAL, SequenceType.WGS], + SAGE_COVERAGE: [FileType.SAGE_COVERAGE, SampleType.NORMAL, SequenceType.WGS], + + PAVE_VCF_TUMOR: [FileType.PAVE_VCF, SampleType.TUMOR, SequenceType.WGS], + PAVE_VCF_NORMAL: [FileType.PAVE_VCF, SampleType.NORMAL, SequenceType.WGS], + + GRIDSS_VCF: [FileType.GRIDSS_VCF, SampleType.TUMOR_NORMAL, SequenceType.WGS], + + GRIPSS_HARD_VCF_TUMOR: [FileType.GRIPSS_HARD_VCF, SampleType.TUMOR, SequenceType.WGS], + GRIPSS_SOFT_VCF_TUMOR: [FileType.GRIPSS_SOFT_VCF, SampleType.TUMOR, SequenceType.WGS], + GRIPSS_HARD_VCF_NORMAL: [FileType.GRIPSS_HARD_VCF, SampleType.NORMAL, SequenceType.WGS], + GRIPSS_SOFT_VCF_NORMAL: [FileType.GRIPSS_SOFT_VCF, SampleType.NORMAL, SequenceType.WGS], + + PURPLE_DIR: [FileType.PURPLE_DIR, SampleType.TUMOR_NORMAL, SequenceType.WGS], + + LINX_PLOT_DIR_TUMOR: [FileType.LINX_PLOT_DIR, SampleType.TUMOR, SequenceType.WGS], + LINX_ANNO_DIR_TUMOR: [FileType.LINX_ANNO_DIR, SampleType.TUMOR, SequenceType.WGS], + LINX_ANNO_DIR_NORMAL: [FileType.LINX_ANNO_DIR, SampleType.NORMAL, SequenceType.WGS], + + CHORD_PREDICTION: [FileType.CHORD_PREDICTION, SampleType.TUMOR, SequenceType.WGS], + LILAC_DIR: [FileType.LILAC_DIR, SampleType.NORMAL, SequenceType.WGS], + PEACH_TSV: [FileType.PEACH_TSV, SampleType.NORMAL, SequenceType.WGS], + PROTECT_TSV: [FileType.PROTECT_TSV, SampleType.TUMOR, SequenceType.WGS], + + VIRUSINTERPRETER_TSV: [FileType.VIRUSINTERPRETER_TSV, SampleType.TUMOR, SequenceType.WGS], + + CUPPA_CSV: [FileType.CUPPA_CSV, SampleType.TUMOR, SequenceType.WGTS], + CUPPA_FEATURE_PLOT: [FileType.CUPPA_FEATURE_PLOT, SampleType.TUMOR, SequenceType.WGTS], + CUPPA_SUMMARY_PLOT: [FileType.CUPPA_SUMMARY_PLOT, SampleType.TUMOR, SequenceType.WGTS], + ] } diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 6b54c65c..9bc7c6e7 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -66,4 +66,41 @@ class Utils { static public getFileObject(path) { return path ? Nextflow.file(path) : [] } + + + // Sample names + static public getTumorWgsSampleName(meta) { + return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) + } + + static public getTumorWtsSampleName(meta) { + return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + } + + static public getNormalWgsSampleName(meta) { + return getMetaEntry(meta, ['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.WGS]) + } + + + // Files + static public getTumorWgsBam(meta) { + return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) + } + + static public getNormalWgsBam(meta) { + return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.WGS]) + } + + static public getTumorWtsBam(meta) { + return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + } + + + static public getMetaEntry(meta, key) { + if (! meta.containsKey(key)) { + System.err.println "\nERROR: meta does not contain key ${key}: ${meta}" + System.exit(1) + } + return meta.getAt(key) + } } diff --git a/lib/WorkflowLilac.groovy b/lib/WorkflowLilac.groovy index e1aacb31..dc18425f 100755 --- a/lib/WorkflowLilac.groovy +++ b/lib/WorkflowLilac.groovy @@ -14,20 +14,20 @@ class WorkflowLilac { def d = ch .flatMap { meta, nbam_wgs, nbai_wgs, tbam_wgs, tbai_wgs, tbam_wts, tbai_wts -> def data = [ - [nbam_wgs, nbai_wgs, Constants.FileType.BAM_WGS, Constants.DataType.NORMAL], - [tbam_wgs, tbai_wgs, Constants.FileType.BAM_WGS, Constants.DataType.TUMOR], - [tbam_wts, tbai_wts, Constants.FileType.BAM_WTS, Constants.DataType.TUMOR], + [nbam_wgs, nbai_wgs, Constants.SequenceType.WGS, Constants.SampleType.NORMAL], + [tbam_wgs, tbai_wgs, Constants.SequenceType.WGS, Constants.SampleType.TUMOR], + [tbam_wts, tbai_wts, Constants.SequenceType.WTS, Constants.SampleType.TUMOR], ] def data_present = data.findAll { it[0] } data_present - .collect { bam, bai, filetype, sample_type -> - def sample_name = meta.get(['sample_name', sample_type]) + .collect { bam, bai, sequence_type, sample_type -> + def sample_name = meta.getAt(['sample_name', sample_type, sequence_type]) def meta_lilac = [ key: meta.id, id: sample_name, // NOTE(SW): must use string representation for caching purposes sample_type_str: sample_type.name(), - filetype_str: filetype.name(), + sequence_type_str: sequence_type.name(), count: data_present.size(), ] return [meta_lilac, bam, bai] @@ -44,18 +44,18 @@ class WorkflowLilac { .groupTuple() .map { filepaths, meta_lilac -> // NOTE(SW): pattern needs to be generalised - def (keys, sample_names, filetype_strs, sample_type_strs) = meta_lilac - .collect { [it.key, it.id, it.filetype_str, it.sample_type_str] } + def (keys, sample_names, sequence_type_strs, sample_type_strs) = meta_lilac + .collect { [it.key, it.id, it.sequence_type_str, it.sample_type_str] } .transpose() def sample_type_str = getValue(sample_type_strs) - def filetype_str = getValue(filetype_strs) + def sequence_type_str = getValue(sequence_type_strs) def key = keys.join('__') def meta_lilac_new = [ keys: keys, id: sample_names.join('__'), id_simple: keys.join('__'), - filetype_str: filetype_str, + sequence_type_str: sequence_type_str, sample_type_str: sample_type_str, ] return [meta_lilac_new, *filepaths] @@ -75,20 +75,20 @@ class WorkflowLilac { assert metas.unique().size() == 1 def meta = metas[0] def data = [:] - values.each { filetype_str, sample_type_str, bam, bai -> - def sample_type = Utils.getEnumFromString(sample_type_str, Constants.DataType) - def filetype = Utils.getEnumFromString(filetype_str, Constants.FileType) - data[[sample_type, filetype, 'bam']] = bam - data[[sample_type, filetype, 'bai']] = bai + values.each { sequence_type_str, sample_type_str, bam, bai -> + def sample_type = Utils.getEnumFromString(sample_type_str, Constants.SampleType) + def sequence_type = Utils.getEnumFromString(sequence_type_str, Constants.SequenceType) + data[[sample_type, sequence_type, 'bam']] = bam + data[[sample_type, sequence_type, 'bai']] = bai } return [ meta, - data.get([Constants.DataType.NORMAL, Constants.FileType.BAM_WGS, 'bam'], []), - data.get([Constants.DataType.NORMAL, Constants.FileType.BAM_WGS, 'bai'], []), - data.get([Constants.DataType.TUMOR, Constants.FileType.BAM_WGS, 'bam'], []), - data.get([Constants.DataType.TUMOR, Constants.FileType.BAM_WGS, 'bai'], []), - data.get([Constants.DataType.TUMOR, Constants.FileType.BAM_WTS, 'bam'], []), - data.get([Constants.DataType.TUMOR, Constants.FileType.BAM_WTS, 'bai'], []), + data.get([Constants.SampleType.NORMAL, Constants.SequenceType.WGS, 'bam'], []), + data.get([Constants.SampleType.NORMAL, Constants.SequenceType.WGS, 'bai'], []), + data.get([Constants.SampleType.TUMOR, Constants.SequenceType.WGS, 'bam'], []), + data.get([Constants.SampleType.TUMOR, Constants.SequenceType.WGS, 'bai'], []), + data.get([Constants.SampleType.TUMOR, Constants.SequenceType.WTS, 'bam'], []), + data.get([Constants.SampleType.TUMOR, Constants.SequenceType.WTS, 'bai'], []), ] } return d diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index a3142a12..4fc1ddfe 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -108,6 +108,10 @@ class WorkflowOncoanalyser { } r = Channel.empty().mix(*r) + + // NOTE(SW): As of Nextflow 22.10.6, groupTuple requires a matching meta /and/ an additional element to complete without error, these placeholders are filtered in the groupByMeta function + r = r.filter { it[0] != Constants.META_PLACEHOLDER } + r = r .groupTuple(size: channels.size()) .map { data -> @@ -120,8 +124,8 @@ class WorkflowOncoanalyser { return [meta, *values_list] } - if (named_args.get('flatten', true)) { - def flatten_mode = named_args.get('flatten_mode', 'recursive') + if (named_args.getOrDefault('flatten', true)) { + def flatten_mode = named_args.getOrDefault('flatten_mode', 'recursive') if (flatten_mode == 'recursive') { r = r.map { it.flatten() } } else if (flatten_mode == 'nonrecursive') { @@ -144,23 +148,35 @@ class WorkflowOncoanalyser { return groupByMeta([:], *channels) } - public static getInput(ch, key) { + public static getInput(Map named_args, ch, key) { + def input_type = named_args.getOrDefault('type', 'required') return ch.map { meta -> if (meta.containsKey(key)) { return [meta, meta.getAt(key)] + } else if (input_type == 'required') { + return [Constants.META_PLACEHOLDER, null] + } else if (input_type == 'optional') { + return [meta, []] } else { - return [:] + System.err.println "ERROR: got bad input type: ${input_type}" + System.exit(1) } } } + // NOTE(SW): function signature required to catch where no named arguments are passed + public static getInput(ch, key) { + return getInput([:], ch, key) + } + + public static joinMeta(Map named_args, ch_a, ch_b) { // NOTE(SW): the cross operator is used to allow many-to-one relationship between ch_output // and ch_metas - def key_a = named_args.get('key_a', 'id') - def key_b = named_args.get('key_b', 'key') - def ch_ready_a = ch_a.map { [it[0].get(key_b), it[1..-1]] } - def ch_ready_b = ch_b.map { meta -> [meta.get(key_a), meta] } + def key_a = named_args.getOrDefault('key_a', 'id') + def key_b = named_args.getOrDefault('key_b', 'key') + def ch_ready_a = ch_a.map { [it[0].getAt(key_b), it[1..-1]] } + def ch_ready_b = ch_b.map { meta -> [meta.getAt(key_a), meta] } return ch_ready_b .cross(ch_ready_a) .map { b, a -> diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index c5c7d237..c925c3a6 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -5,7 +5,7 @@ process LILAC { container 'docker.io/scwatts/lilac:1.4.2--0' input: - tuple val(meta), path(normal_wgs_bam), path(normal_wgs_bai), path(tumor_wgs_bam), path(tumor_wgs_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(purple_dir) + tuple val(meta), path(normal_wgs_bam), path(normal_wgs_bai), path(tumor_wgs_bam), path(tumor_wgs_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(gene_cn), path(smlv_vcf) path genome_fasta val genome_ver path lilac_resources, stageAs: 'lilac_resources' @@ -22,10 +22,8 @@ process LILAC { def sample_name = getSampleName(meta, tumor_wgs_bam, normal_wgs_bam) def tumor_wgs_bam_arg = tumor_wgs_bam ? "-tumor_bam ${tumor_wgs_bam}" : '' def tumor_wts_bam_arg = tumor_wts_bam ? "-rna_bam ${tumor_wts_bam}" : '' - def purple_args = purple_dir ? """ - -gene_copy_number ${purple_dir}/${sample_name}.purple.cnv.gene.tsv \\ - -somatic_vcf ${purple_dir}/${sample_name}.purple.sv.vcf.gz \\ - """ : '' + def gene_cn_arg = gene_cn ? "-gene_copy_number ${gene_cn}" : '' + def smlv_vcf_arg = smlv_vcf ? "-somatic_vcf ${smlv_vcf}" : '' """ java \\ @@ -39,7 +37,8 @@ process LILAC { -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ -resource_dir ${lilac_resources} \\ - ${purple_args.replaceAll('\\n', '')} \\ + ${gene_cn_arg} \\ + ${smlv_vcf_arg} \\ -threads ${task.cpus} \\ -output_dir lilac/ diff --git a/modules/local/lilac/meta.yml b/modules/local/lilac/meta.yml index 8d717839..acaaaf88 100644 --- a/modules/local/lilac/meta.yml +++ b/modules/local/lilac/meta.yml @@ -40,9 +40,14 @@ input: type: file description: Tumor WTS BAI file (optional) pattern: "*.{bai}" - - purple_dir: - type: directory - description: PURPLE output directory (optional) + - gene_cn: + type: file + description: PURPLE somatic gene copy number file (optional) + pattern: "*.{tsv}" + - smlv_vcf: + type: file + description: PURPLE somatic small variant VCF file (optional) + pattern: "*.{vcf.gz}" - genome_fasta: type: file description: Reference genome assembly fa file diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index d9d65a1f..a78dc6cb 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -26,8 +26,13 @@ process PURPLE { script: def args = task.ext.args ?: '' + + def sv_vcf_arg = sv_hard_vcf ? "-structural_vcf ${sv_hard_vcf}" : '' + def sv_lowconf_vcf_fp = sv_soft_vcf ? "-sv_recovery_vcf ${sv_soft_vcf}" : '' + def smlv_tumor_vcf_fp = smlv_tumor_vcf ?: '' def smlv_normal_vcf_fp = smlv_normal_vcf ?: '' + def germline_del_arg = germline_del ? "-germline_del_freq_file ${germline_del}" : '' """ @@ -52,8 +57,8 @@ process PURPLE { ${args} \\ -tumor ${meta.tumor_id} \\ -reference ${meta.normal_id} \\ - -sv_recovery_vcf ${sv_soft_vcf} \\ - -structural_vcf ${sv_hard_vcf} \\ + ${sv_vcf_arg} \\ + ${sv_lowconf_vcf_fp} \\ \${smlv_tumor_vcf_arg} \\ \${smlv_normal_vcf_arg} \\ -amber ${amber} \\ diff --git a/subworkflows/local/gridss.nf b/subworkflows/local/gridss.nf index dfb5dc2d..d4d71371 100644 --- a/subworkflows/local/gridss.nf +++ b/subworkflows/local/gridss.nf @@ -10,7 +10,7 @@ include { GRIDSS_PREPROCESS } from '../../modules/local/gridss/preprocess workflow GRIDSS { take: - ch_inputs // channel: [val(meta), bam_tumor, bam_normal] + ch_inputs // channel: [val(meta), tumor_bam, normal_bam] gridss_config // file: /path/to/gridss_config (optional) ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai @@ -28,19 +28,19 @@ workflow GRIDSS { // channel: [val(meta_gridss), bam] ch_preprocess_inputs = ch_inputs .flatMap { meta, tbam, nbam -> - def sample_types = [Constants.DataType.TUMOR, Constants.DataType.NORMAL] + def sample_types = [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL] sample_types .collect { sample_type -> def bam_fp - if (sample_type == Constants.DataType.TUMOR) { + if (sample_type == Constants.SampleType.TUMOR) { bam_fp = tbam - } else if (sample_type == Constants.DataType.NORMAL) { + } else if (sample_type == Constants.SampleType.NORMAL) { bam_fp = nbam } else { assert false : "got bad sample type" } def meta_gridss = [ - id: meta.get(['sample_name', sample_type]), + id: meta.get(['sample_name', sample_type, Constants.SequenceType.WGS]), // NOTE(SW): must use string representation for caching purposes sample_type_str: sample_type.name(), subject_id: meta.id, @@ -75,8 +75,8 @@ workflow GRIDSS { // channel: [val(meta_gridss), [bams], [preprocess_dirs], [labels]] ch_assemble_inputs = ch_bams_and_preprocess .map { subject_id, entries -> - def (tmeta, tbam, tpreprocess) = get_sample_type_entry(entries, Constants.DataType.TUMOR) - def (nmeta, nbam, npreprocess) = get_sample_type_entry(entries, Constants.DataType.NORMAL) + def (tmeta, tbam, tpreprocess) = get_sample_type_entry(entries, Constants.SampleType.TUMOR) + def (nmeta, nbam, npreprocess) = get_sample_type_entry(entries, Constants.SampleType.NORMAL) def meta_gridss = [id: tmeta.subject_id] return [meta_gridss, [nbam, tbam], [npreprocess, tpreprocess], [nmeta.id, tmeta.id]] } @@ -141,6 +141,6 @@ workflow GRIDSS { def get_sample_type_entry(entries, sample_type) { entries.find { e -> def meta = e[0] - return Utils.getEnumFromString(meta.sample_type_str, Constants.DataType) == sample_type + return Utils.getEnumFromString(meta.sample_type_str, Constants.SampleType) == sample_type } } diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep.nf index b7870895..10d85355 100644 --- a/subworkflows/local/gridss_svprep.nf +++ b/subworkflows/local/gridss_svprep.nf @@ -2,7 +2,7 @@ // SV Prep is a BAM filter designed to select only reads relevant to SV events run prior to GRIDSS. // GRIDSS is a software suite containing tools useful for the detection of genomic rearrangements. // -import Constants +import Utils include { ASSEMBLE as GRIDSS_ASSEMBLE } from '../../modules/local/svprep/assemble/main' include { CALL as GRIDSS_CALL } from '../../modules/local/svprep/call/main' @@ -36,11 +36,11 @@ workflow GRIDSS_SVPREP { .map { meta -> def meta_svprep = [ key: meta.id, - id: meta.get(['sample_name', Constants.DataType.TUMOR]), + id: Utils.getTumorWgsSampleName(meta), sample_type: 'tumor', ] - def bam_tumor = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) - return [meta_svprep, bam_tumor, "${bam_tumor}.bai", []] + def tumor_bam = Utils.getTumorWgsBam(meta) + return [meta_svprep, tumor_bam, "${tumor_bam}.bai", []] } // Filter tumor BAM @@ -60,11 +60,11 @@ workflow GRIDSS_SVPREP { .map { meta, junctions_tumor -> def meta_svprep = [ key: meta.id, - id: meta.get(['sample_name', Constants.DataType.NORMAL]), + id: Utils.getNormalWgsSampleName(meta), sample_type: 'normal', ] - def bam_normal = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) - return [meta_svprep, bam_normal, "${bam_normal}.bai", junctions_tumor] + def normal_bam = Utils.getNormalWgsBam(meta) + return [meta_svprep, normal_bam, "${normal_bam}.bai", junctions_tumor] } SVPREP_NORMAL( @@ -189,15 +189,15 @@ workflow GRIDSS_SVPREP { GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .map { id, meta, vcf -> - def tbam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) - def nbam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) + def tbam = Utils.getTumorWgsBam(meta) + def nbam = Utils.getNormalWgsBam(meta) def meta_svprep = [id: meta.id] return [ meta_svprep, [nbam, tbam], ["${nbam}.bai", "${tbam}.bai"], vcf, - [meta.get(['sample_name', Constants.DataType.NORMAL]), meta.get(['sample_name', Constants.DataType.TUMOR])], + [Utils.getNormalWgsSampleName(meta), Utils.getTumorWgsSampleName(meta)], ] } diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac.nf index 10e79b97..03ee581d 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac.nf @@ -2,6 +2,7 @@ // LILAC is a WGS tool for HLA typing and somatic CNV and SNV calling // import Constants +import Utils include { CUSTOM_EXTRACTCONTIG } from '../../modules/local/custom/lilac_extract_and_index_contig/main' include { CUSTOM_REALIGNREADS } from '../../modules/local/custom/lilac_realign_reads_lilac/main' @@ -84,17 +85,17 @@ workflow LILAC { // Re-replicate and flow expected file count into meta - // channel: [val(meta_lilac), [filetype_str, sample_type_str, bam, bai]] + // channel: [val(meta_lilac), [sequence_type_str, sample_type_str, bam, bai]] ch_slices_out_individual = ch_slices_out .flatMap{ data -> def meta_lilac = data[0] def fps = data[1..-1] meta_lilac.keys.collect { key -> - return [[key: key], [meta_lilac.filetype_str, meta_lilac.sample_type_str, *fps]] + return [[key: key], [meta_lilac.sequence_type_str, meta_lilac.sample_type_str, *fps]] } } // Adding expected file count - // channel: [val(meta_lilac), [filetype_str, sample_type_str, bam, bai]] + // channel: [val(meta_lilac), [sequence_type_str, sample_type_str, bam, bai]] ch_slices_ready = WorkflowOncoanalyser.joinMeta( ch_slices_out_individual, ch_slice_meta_individual, @@ -114,27 +115,65 @@ workflow LILAC { ch_metas, ) - // Add PURPLE output to finalise LILAC input channel + // Get inputs from PURPLE + // channel: [val(meta), gene_cn] + ch_lilac_inputs_gene_cn = ch_purple_dir + .map { meta, purple_dir -> + if (purple_dir == []) { + return [meta, []] + } + + def tumor_id = Utils.getTumorWgsSampleName(meta) + def gene_cn = file(purple_dir).resolve("${tumor_id}.purple.cnv.gene.tsv") + return gene_cn.exists() ? [meta, gene_cn] : [meta, []] + } + + // channel: [val(meta), smlv_vcf] + ch_lilac_inputs_smlv_vcf = ch_purple_dir + .map { meta, purple_dir -> + if (purple_dir == []) { + return [meta, []] + } + + def tumor_id = Utils.getTumorWgsSampleName(meta) + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + return smlv_vcf.exists() ? [meta, smlv_vcf] : [meta, []] + } + // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai, purple_dir] ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( ch_lilac_inputs_slices, - ch_purple_dir, + ch_lilac_inputs_gene_cn, + ch_lilac_inputs_smlv_vcf, flatten_mode: 'nonrecursive', ) - // Run LILAC - // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai, purple_dir] + // Create final input channel for LILAC, remove samples with only WTS BAMs + // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai, gene_cn, smlv_vcf]] ch_lilac_inputs = ch_lilac_inputs_full .map { def meta = it[0] + def fps = it[1..-1] + + // LILAC requires either tumor or normal WGS BAM + if (fps[0] == [] && fps[2] == []) { + return Constants.META_PLACEHOLDER + } + + def tumor_id_key = ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS] + def normal_id_key = ['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.WGS] + def meta_lilac = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), - normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + tumor_id: meta.containsKey(tumor_id_key) ? meta.getAt(tumor_id_key) : '', + normal_id: meta.containsKey(normal_id_key) ? meta.getAt(normal_id_key) : '', ] - return [meta_lilac, *it[1..-1]] + return [meta_lilac, *fps] } + .filter { it != Constants.META_PLACEHOLDER } + + // Run LILAC LILAC_PROCESS( ch_lilac_inputs, ref_data_genome_fasta, diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf index 13c30505..a63ea438 100644 --- a/subworkflows/local/prepare_input.nf +++ b/subworkflows/local/prepare_input.nf @@ -26,13 +26,21 @@ workflow PREPARE_INPUT { } // Sample type - def sample_type_enum = Utils.getEnumFromString(it.sample_type, Constants.DataType) + def sample_type_enum = Utils.getEnumFromString(it.sample_type, Constants.SampleType) if (!sample_type_enum) { - def sample_type_str = Utils.getEnumNames(Constants.DataType).join('\n - ') + def sample_type_str = Utils.getEnumNames(Constants.SampleType).join('\n - ') log.error "\nERROR: recieved invalid sample type: '${it.sample_type}'. Valid options are:\n - ${sample_type_str}" System.exit(1) } + // Sequence type + def sequence_type_enum = Utils.getEnumFromString(it.sequence_type, Constants.SequenceType) + if (!sequence_type_enum) { + def sequence_type_str = Utils.getEnumNames(Constants.SequenceType).join('\n - ') + log.error "\nERROR: recieved invalid sequence type: '${it.sequence_type}'. Valid options are:\n - ${sequence_type_str}" + System.exit(1) + } + // Filetype def filetype_enum = Utils.getEnumFromString(it.filetype, Constants.FileType) if (!filetype_enum) { @@ -42,17 +50,17 @@ workflow PREPARE_INPUT { } // Check whether this input type already exists - if (input_types_seen.contains([sample_type_enum, filetype_enum])) { + def key_input_type = [sample_type_enum, sequence_type_enum, filetype_enum] + if (input_types_seen.contains(key_input_type)) { log.error "\nERROR: got duplicate inputs for ${key}: ${sample_type_enum}/${filetype_enum}" System.exit(1) } - input_types_seen.push([sample_type_enum, filetype_enum]) + input_types_seen.push(key_input_type) // Check for relevant indices if (!workflow.stubRun) { def filetype_bai = [ - Constants.FileType.BAM_WGS, - Constants.FileType.BAM_WTS, + Constants.FileType.BAM, ] def filetype_tbi = [ @@ -66,29 +74,50 @@ workflow PREPARE_INPUT { index_ext = 'bai' } else if (filetype_tbi.contains(filetype_enum)) { index_ext = 'tbi' - } else { - return } - def index_fp_str = "${it.filepath}.${index_ext}".toString() - def index_fp = file(index_fp_str) - if (! index_fp.exists()) { - log.error "\nERROR: No index found for ${it.filepath}" - System.exit(1) + if (index_ext) { + def index_fp_str = "${it.filepath}.${index_ext}".toString() + def index_fp = file(index_fp_str) + if (! index_fp.exists()) { + log.error "\nERROR: No index found for ${it.filepath}" + System.exit(1) + } } } // Sample name - def key_sample_name = ['sample_name', sample_type_enum] - if (meta.containsKey(key_sample_name) && meta[key_sample_name] != it.sample_name) { - log.error "\nERROR: got unexpected sample name for ${key}/${meta[key_sample_name]}: ${it.sample_name}" - System.exit(1) + def key_sample_name + if (sample_type_enum == Constants.SampleType.TUMOR_NORMAL) { + if (it.sample_name.contains(';')) { + def sample_name_tokens = it.sample_name.split(';') + if (sample_name_tokens.size() != 2) { + log.error "\nERROR: expected two sample names but got ${sample_name_tokens.size()}" + System.exit(1) + } + + def sample_name_and_types = [ + [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL], + sample_name_tokens, + ] + sample_name_and_types + .transpose() + .each { st, sn -> + key_sample_name = ['sample_name', st, sequence_type_enum] + meta[key_sample_name] = process_sample_name(sn, key_sample_name, meta) + } + } else { + key_sample_name = ['sample_name', Constants.SampleType.TUMOR, sequence_type_enum] + meta[key_sample_name] = process_sample_name(it.sample_name, key_sample_name, meta) + } } else { - meta[key_sample_name] = it.sample_name + key_sample_name = ['sample_name', sample_type_enum, sequence_type_enum] + meta[key_sample_name] = process_sample_name(it.sample_name, key_sample_name, meta) } + // Filepath - def key_file = [filetype_enum, sample_type_enum] + def key_file = [filetype_enum, sample_type_enum, sequence_type_enum] if (meta.containsKey(key_file)) { log.error "\nERROR: got duplicate file for ${key}: ${filetype_enum}/${sample_type_enum}" System.exit(1) @@ -102,3 +131,12 @@ workflow PREPARE_INPUT { emit: data = ch_inputs } + + +def process_sample_name(sample_name, key_sample_name, meta) { + if (meta.containsKey(key_sample_name) && meta[key_sample_name] != sample_name) { + log.error "\nERROR: got unexpected sample name for ${key}/${meta[key_sample_name]}: ${sample_name}" + System.exit(1) + } + return sample_name +} diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index ca2ed3c3..a95df036 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -115,37 +115,42 @@ workflow ONCOANALYSER { ch_versions = Channel.empty() // Get inputs from samplesheet + // channel: [val(meta)] PREPARE_INPUT( samplesheet, ) ch_inputs = PREPARE_INPUT.out.data - // Set up reference data and unpack HMF data map for convenience - PREPARE_REFERENCE(run) - hmf_data = PREPARE_REFERENCE.out.hmf_data + // Split inputs WTS and WGS + // NOTE(SW): assuming there are only t/n pairs i.e. no tumor-only or normal-only - // Set up channel with common inputs for several processes - if (run.amber || run.cobalt || run.sage || run.lilac) { - // channel: [val(meta), tumor_bam, normal_bam, tumor_bai, normal_bai] - ch_bams_and_indices = ch_inputs - .map { meta -> - def tumor_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) - def normal_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) - [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] - } - } + // channel (present): [val(meta)] + // channel (absent): [val(meta)] + ch_inputs_wgs = ch_inputs + .branch { meta -> + def key_tumor = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS] + def key_normal = [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.WGS] + present: meta.containsKey(key_tumor) && meta.containsKey(key_normal) + return meta + absent: true + return meta + } // channel (present): [val(meta)] // channel (absent): [val(meta)] ch_inputs_wts = ch_inputs .branch { meta -> - def key = [Constants.FileType.BAM_WTS, Constants.DataType.TUMOR] + def key = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WTS] present: meta.containsKey(key) return meta absent: ! meta.containsKey(key) return meta } + // Set up reference data and unpack HMF data map for convenience + PREPARE_REFERENCE(run) + hmf_data = PREPARE_REFERENCE.out.hmf_data + // // MODULE: Run Isofox to analyse WTS data // @@ -156,8 +161,8 @@ workflow ONCOANALYSER { // channel: [meta_isofox, tumor_bam_wts] ch_isofox_inputs = ch_inputs_wts.present .map { meta -> - def bam = meta.get([Constants.FileType.BAM_WTS, Constants.DataType.TUMOR]) - def meta_isofox = [key: meta.id, id: meta.get(['sample_name', Constants.DataType.TUMOR])] + def bam = Utils.getTumorWtsBam(meta) + def meta_isofox = [key: meta.id, id: Utils.getTumorWtsSampleName(meta)] return [meta_isofox, bam, "${bam}.bai"] } @@ -196,14 +201,14 @@ workflow ONCOANALYSER { // NOTE(SW): CUPPA only requires collectwgsmetrics for the tumor sample in the upstream // process Virus Interpreter but ORANGE currently requires collectwgsmetrics for both tumor // and normal sample - // channel: [val(meta_cwm), bam] - ch_cwm_inputs_all = ch_inputs + // channel: [val(meta_cwm), bam_wgs] + ch_cwm_inputs_all = ch_inputs_wgs.present .flatMap { meta -> - def sample_types = run.orange ? [Constants.DataType.TUMOR, Constants.DataType.NORMAL] : [Constants.DataType.TUMOR] + def sample_types = run.orange ? [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL] : [Constants.SampleType.TUMOR] return sample_types .collect { sample_type -> - def bam = meta.get([Constants.FileType.BAM_WGS, sample_type]) - def sample_name = meta.get(['sample_name', sample_type]) + def bam = meta.getAt([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) + def sample_name = meta.getAt(['sample_name', sample_type, Constants.SequenceType.WGS]) def meta_cwm = [ key: meta.id, id: sample_name, @@ -217,7 +222,7 @@ workflow ONCOANALYSER { // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent // on any process - // channel: [val(meta_cwm), bam] + // channel: [val(meta_cwm), bam_wgs] ch_cwm_inputs = ch_cwm_inputs_all .map { [it[1..-1], it[0]] } .groupTuple() @@ -264,10 +269,10 @@ workflow ONCOANALYSER { // channel (normal): [val(meta), metrics] ch_cwm_out = WorkflowOncoanalyser.restoreMeta(ch_cwm_out_individual, ch_inputs) .branch { meta, sample_type_str, metrics -> - def sample_type = Utils.getEnumFromString(sample_type_str, Constants.DataType) - somatic: sample_type == Constants.DataType.TUMOR + def sample_type = Utils.getEnumFromString(sample_type_str, Constants.SampleType) + somatic: sample_type == Constants.SampleType.TUMOR return [meta, metrics] - germline: sample_type == Constants.DataType.NORMAL + germline: sample_type == Constants.SampleType.NORMAL return [meta, metrics] } } @@ -279,18 +284,18 @@ workflow ONCOANALYSER { ch_amber_out = Channel.empty() if (run.amber) { // Create inputs and create process-specific meta - // channel: [val(meta_amber), tumor_bam, normal_bam, tumor_bai, normal_bai] - ch_amber_inputs = ch_bams_and_indices - .map { - def meta = it[0] - def fps = it[1..-1] + // channel: [val(meta_amber), tumor_bam_wgs, normal_bam_wgs, tumor_bai_wgs, normal_bai_wgs] + ch_amber_inputs = ch_inputs_wgs.present + .map { meta -> def meta_amber = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), - normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), ] - return [meta_amber, *fps] + def tumor_bam = Utils.getTumorWgsBam(meta) + def normal_bam = Utils.getNormalWgsBam(meta) + [meta_amber, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] } // Run process @@ -312,18 +317,18 @@ workflow ONCOANALYSER { ch_cobalt_out = Channel.empty() if (run.cobalt) { // Create inputs and create process-specific meta - // channel: [meta_cobalt, tbam, nbam, tbai, nbai] - ch_cobalt_inputs = ch_bams_and_indices - .map { - def meta = it[0] - def fps = it[1..-1] + // channel: [meta_cobalt, tumor_bam_wgs, normal_bam_wgs, tumor_bai_wgs, normal_bai_wgs] + ch_cobalt_inputs = ch_inputs_wgs.present + .map { meta -> def meta_cobalt = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), - normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), ] - return [meta_cobalt, *fps] + def tumor_bam = Utils.getTumorWgsBam(meta) + def normal_bam = Utils.getNormalWgsBam(meta) + return [meta_cobalt, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] } // Run process @@ -345,7 +350,7 @@ workflow ONCOANALYSER { if (run.gridss) { if (run.svprep) { GRIDSS_SVPREP( - ch_inputs, + ch_inputs_wgs.present, gridss_config, PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_version, @@ -361,10 +366,10 @@ workflow ONCOANALYSER { ch_versions = ch_versions.mix(GRIDSS_SVPREP.out.versions) ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP.out.results) } else { - ch_gridss_inputs = ch_inputs + ch_gridss_inputs = ch_inputs_wgs.present .map { meta -> - def tumor_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR]) - def normal_bam = meta.get([Constants.FileType.BAM_WGS, Constants.DataType.NORMAL]) + def tumor_bam = Utils.getTumorWgsBam(meta) + def normal_bam = Utils.getNormalWgsBam(meta) [meta, tumor_bam, normal_bam] } GRIDSS( @@ -396,7 +401,8 @@ workflow ONCOANALYSER { if (run.gridss) { ch_gripss_inputs_source = ch_gridss_out } else { - ch_gripss_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.GRIDSS_VCF, Constants.DataType.TUMOR_NORMAL]) + ch_gripss_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIDSS_VCF) + .filter { it[0] != Constants.META_PLACEHOLDER } } // Create inputs and create process-specific meta @@ -406,8 +412,8 @@ workflow ONCOANALYSER { def meta_gripss = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), - normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), ] return [meta_gripss, gridss_vcf] } @@ -445,15 +451,17 @@ workflow ONCOANALYSER { ch_sage_somatic_normal_bqr_out = Channel.empty() if (run.sage) { // Create inputs and create process-specific meta - ch_sage_inputs = ch_bams_and_indices - .map { meta, tbam, nbam, tbai, nbai -> + ch_sage_inputs = ch_inputs_wgs.present + .map { meta -> def meta_sage = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), - normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), ] - return [meta_sage, tbam, nbam, tbai, nbai] + def tumor_bam = Utils.getTumorWgsBam(meta) + def normal_bam = Utils.getNormalWgsBam(meta) + return [meta_sage, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] } // Call subworkflow to run processes @@ -497,8 +505,10 @@ workflow ONCOANALYSER { ch_pave_germline_inputs_source = ch_sage_germline_vcf_out ch_pave_somatic_inputs_source = ch_sage_somatic_vcf_out } else { - ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_VCF, Constants.DataType.NORMAL]) - ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_VCF, Constants.DataType.TUMOR]) + ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_TUMOR) + .filter { it[0] != Constants.META_PLACEHOLDER } + ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_NORMAL) + .filter { it[0] != Constants.META_PLACEHOLDER } } // Create inputs and create process-specific meta @@ -508,7 +518,7 @@ workflow ONCOANALYSER { def pave_meta = [ key: meta.id, // NOTE(SW): use of tumor sample name for PAVE germline is correct - id: meta.get(['sample_name', Constants.DataType.TUMOR]), + id: Utils.getTumorWgsSampleName(meta), ] return [pave_meta, sage_vcf] } @@ -516,7 +526,7 @@ workflow ONCOANALYSER { .map { meta, sage_vcf -> def pave_meta = [ key: meta.id, - id: meta.get(['sample_name', Constants.DataType.TUMOR]), + id: Utils.getTumorWgsSampleName(meta), ] return [pave_meta, sage_vcf] } @@ -552,30 +562,33 @@ workflow ONCOANALYSER { if (run.purple) { // Select input sources // channel: [val(meta), sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi] + ch_purple_inputs_sv = Channel.empty() if (run.gripss) { + // NOTE(SW): GRIPSS will be run for all WGS entries, so no optionals here ch_purple_inputs_sv = ch_gripss_somatic_out } else { - ch_purple_inputs_sv = ch_inputs - .map { meta -> - def sv_hard_vcf = meta[[Constants.FileType.GRIPSS_HARD_VCF, Constants.DataType.TUMOR]] - def sv_soft_vcf = meta[[Constants.FileType.GRIPSS_SOFT_VCF, Constants.DataType.TUMOR]] - return [ - meta, - sv_hard_vcf, - "${sv_hard_vcf}.tbi", - sv_soft_vcf, - "${sv_soft_vcf}.tbi", - ] - } + ch_purple_inputs_sv = WorkflowOncoanalyser.groupByMeta( + WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_HARD_VCF_TUMOR, type: 'optional'), + WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_SOFT_VCF_TUMOR, type: 'optional'), + flatten_mode: 'nonrecursive', + ) + .map { meta, vcf_hard, vcf_soft -> + def tbi_hard = vcf_hard == [] ? [] : "${vcf_hard}.tbi" + def tbi_soft = vcf_soft == [] ? [] : "${vcf_soft}.tbi" + return [meta, vcf_hard, tbi_hard, vcf_soft, tbi_soft] + } } // channel: [val(meta), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( - run.amber ? ch_amber_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.AMBER_DIR, Constants.DataType.TUMOR_NORMAL]), - run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.COBALT_DIR, Constants.DataType.TUMOR_NORMAL]), + // Required inputs + run.amber ? ch_amber_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.AMBER_DIR), + run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.COBALT_DIR), + // Optional inputs ch_purple_inputs_sv, - run.pave ? ch_pave_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PAVE_VCF, Constants.DataType.TUMOR]), - run.pave ? ch_pave_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PAVE_VCF, Constants.DataType.NORMAL]), + run.pave ? ch_pave_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_TUMOR, type: 'optional'), + run.pave ? ch_pave_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_NORMAL, type: 'optional'), + flatten_mode: 'nonrecursive', ) // Create process-specific meta @@ -587,8 +600,8 @@ workflow ONCOANALYSER { def meta_purple = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), - normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), ] return [meta_purple, *other] } @@ -621,20 +634,28 @@ workflow ONCOANALYSER { if (run.purple) { ch_sigs_inputs_source = ch_purple_out } else { - ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) + ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) } // Create inputs and create process-specific meta // channel: [val(meta_sigs), smlv_vcf] ch_sigs_inputs = ch_sigs_inputs_source .map { meta, purple_dir -> - def smlv_vcf = file(purple_dir).resolve("${meta.get(['sample_name', Constants.DataType.TUMOR])}.purple.somatic.vcf.gz") + def tumor_id = Utils.getTumorWgsSampleName(meta) + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + + // Require smlv VCF from the PURPLE directory + if (!smlv_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + def meta_sigs = [ id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), + tumor_id: meta.getAt(['sample_name', Constants.SampleType.TUMOR]), ] return [meta_sigs, smlv_vcf] } + .filter { it[0] != Constants.META_PLACEHOLDER } SIGS( ch_sigs_inputs, @@ -656,19 +677,26 @@ workflow ONCOANALYSER { if (run.purple) { ch_chord_inputs_source = ch_purple_out } else { - ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) + ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) } // Create inputs and create process-specific meta // channel: [val(meta), smlv_vcf, sv_vcf] ch_chord_inputs = ch_chord_inputs_source .map { meta, purple_dir -> - def tumor_id = meta.get(['sample_name', Constants.DataType.TUMOR]) + def tumor_id = Utils.getTumorWgsSampleName(meta) def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") + + // Require both SV and smlv VCF from the PURPLE directory + if (!smlv_vcf.exists() || !sv_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + def meta_chord = [key: meta.id, id: meta.id] return [meta_chord, smlv_vcf, sv_vcf] } + .filter { it[0] != Constants.META_PLACEHOLDER } // Run process CHORD( @@ -690,9 +718,13 @@ workflow ONCOANALYSER { // Select input sources // channel: [val(meta), purple_dir] if (run.purple) { - ch_lilac_inputs_source = ch_purple_out + ch_lilac_inputs_purple = Channel.empty() + .mix( + ch_purple_out, + ch_inputs_wgs.absent.map { meta -> [meta, []] }, + ) } else { - ch_lilac_inputs_source = WorkflowOncoanalyser.getInput([Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) + ch_lilac_inputs_purple = WorkflowOncoanalyser.getInput(meta, Constants.INPUT.PURPLE_DIR, type: 'optional') } // Create channel with all available input BAMs @@ -700,18 +732,28 @@ workflow ONCOANALYSER { // channel: [val(meta), wts_bam, wts_bai] ch_lilac_bams_wts = Channel.empty() .mix( - ch_inputs_wts_bams = ch_inputs_wts.present.map { meta -> - def bam = meta.get([Constants.FileType.BAM_WTS, Constants.DataType.TUMOR]) + ch_inputs_wts.present.map { meta -> + def bam = Utils.getTumorWtsBam(meta) [meta, bam, "${bam}.bai"] }, ch_inputs_wts.absent.map { meta -> [meta, [], []] }, ) + ch_lilac_bams_wgs = Channel.empty() + .mix( + ch_inputs_wgs.present.map { meta -> + def tumor_bam = Utils.getTumorWgsBam(meta) + def normal_bam = Utils.getNormalWgsBam(meta) + [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] + }, + ch_inputs_wgs.absent.map { meta -> [meta, [], [], [], []] }, + ) + // Combine WGS and WTS BAMs // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] ch_lilac_bams = WorkflowOncoanalyser.groupByMeta( ch_lilac_bams_wts, - ch_bams_and_indices, + ch_lilac_bams_wgs, flatten_mode: 'nonrecursive', ) .map { data -> @@ -723,7 +765,7 @@ workflow ONCOANALYSER { // Call subworkflow to run processes LILAC( ch_lilac_bams, - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput([Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), + ch_lilac_inputs_purple, PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, hmf_data.lilac_resources, @@ -742,13 +784,13 @@ workflow ONCOANALYSER { // VIRUSBreakend // Create inputs and create process-specific meta // channel: [val(meta_virus), tumor_bam] - ch_virusbreakend_inputs = ch_inputs + ch_virusbreakend_inputs = ch_inputs_wgs.present .map { meta -> def meta_virus = [ key: meta.id, id: meta.id, ] - return [meta_virus, meta.get([Constants.FileType.BAM_WGS, Constants.DataType.TUMOR])] + return [meta_virus, Utils.getTumorWgsBam(meta)] } // Run process @@ -768,18 +810,32 @@ workflow ONCOANALYSER { ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) // Create inputs and create process-specific meta - // channel: [val(meta), purple_purity, purple_qc] - ch_virusinterpreter_inputs_purple = ch_purple_out + if (run.purple) { + ch_virusinterpreter_inputs_purple = ch_purple_out + } else { + ch_virusinterpreter_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + } + + // channel: [val(meta), purple_qc, wgs_metrics] + ch_virusinterpreter_inputs_purple_files = ch_virusinterpreter_inputs_purple + .filter { it[0] != Constants.META_PLACEHOLDER } .map { meta, purple_dir -> - def purple_purity = file(purple_dir).resolve("${meta.get(['sample_name', Constants.DataType.TUMOR])}.purple.purity.tsv") - def purple_qc = file(purple_dir).resolve("${meta.get(['sample_name', Constants.DataType.TUMOR])}.purple.qc") + def tumor_id = Utils.getTumorWgsSampleName(meta) + def purple_purity = file(purple_dir).resolve("${tumor_id}.purple.purity.tsv") + def purple_qc = file(purple_dir).resolve("${tumor_id}.purple.qc") + + // Require both purity and QC files from the PURPLE directory + if (!purple_purity.exists() || !purple_qc.exists()) { + return Constants.META_PLACEHOLDER + } return [meta, purple_purity, purple_qc] } + // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), - ch_virusinterpreter_inputs_purple, + ch_virusinterpreter_inputs_purple_files, ch_cwm_out.somatic, ) @@ -791,7 +847,7 @@ workflow ONCOANALYSER { def meta = it[0] def meta_virus = [ key: meta.id, - id: meta.get(['sample_name', Constants.DataType.TUMOR]), + id: Utils.getTumorWgsSampleName(meta), ] return [meta_virus, *it[1..-1]] } @@ -821,10 +877,11 @@ workflow ONCOANALYSER { if (run.gripss) { ch_linx_inputs_germline_source = ch_gripss_germline_out.map { meta, h, hi, s, si -> [meta, h] } } else { - ch_linx_inputs_germline_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.GRIPSS_HARD_VCF, Constants.DataType.NORMAL]) + ch_linx_inputs_germline_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_HARD_VCF_TUMOR) } + // channel: [val(meta), sv_vcf, purple_dir] - ch_linx_inputs_somatic_source = run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) + ch_linx_inputs_somatic_source = run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) // Create inputs and create process-specific meta // channel: [val(meta_linx), sv_vcf] @@ -833,17 +890,18 @@ workflow ONCOANALYSER { def meta = it[0] def meta_linx = [ key: meta.id, - id: meta.get(['sample_name', Constants.DataType.NORMAL]), + id: Utils.getNormalWgsSampleName(meta), ] return [meta_linx, it[1..-1]] } + // channel: [val(meta_linx), purple_dir] ch_linx_inputs_somatic = ch_linx_inputs_somatic_source .map { def meta = it[0] def meta_linx = [ key: meta.id, - id: meta.get(['sample_name', Constants.DataType.TUMOR]), + id: Utils.getTumorWgsSampleName(meta), ] return [meta_linx, it[1..-1]] } @@ -875,7 +933,7 @@ workflow ONCOANALYSER { .map { meta, anno_dir, vis_dir -> def meta_gpgr_linx = [ key: meta.id, - id: meta.get(['sample_name', Constants.DataType.TUMOR]), + id: Utils.getTumorWgsSampleName(meta), ] return [meta_gpgr_linx, anno_dir, vis_dir] } @@ -896,16 +954,17 @@ workflow ONCOANALYSER { ch_protect_out = Channel.empty() if (run.protect) { // Select input sources + // channel: [val(meta), linx_somatic_annotation_dir] ch_linx_anno = ch_linx_somatic_out.map { meta, anno_dir, vis_dir -> [meta, anno_dir]} // channel: [val(meta), chord_prediction, purple_dir, linx_dir, virusinterpreter] ch_protect_inputs_source = WorkflowOncoanalyser.groupByMeta( - run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CHORD_PREDICTION, Constants.DataType.TUMOR]), - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), - run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.TUMOR_NORMAL]), - run.lilac ? ch_lilac_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LILAC_DIR, Constants.DataType.NORMAL]), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.VIRUSINTERPRETER_TSV, Constants.DataType.TUMOR]), + run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_PREDICTION), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), + run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + run.lilac ? ch_lilac_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV), ) // Create process-specific meta @@ -917,8 +976,8 @@ workflow ONCOANALYSER { def meta_protect = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), - normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), ] return [meta_protect, *other] } @@ -948,7 +1007,7 @@ workflow ONCOANALYSER { if (run.purple) { ch_peach_inputs_source = ch_purple_out } else { - ch_peach_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]) + ch_peach_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) } // Create inputs and create process-specific meta @@ -958,13 +1017,19 @@ workflow ONCOANALYSER { def meta_peach = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), - normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), ] - def purple_germline_vcf = file(purple_dir).resolve("${meta.get(['sample_name', Constants.DataType.TUMOR])}.purple.germline.vcf.gz") - file(purple_germline_vcf, checkIfExists: true) + def tumor_id = Utils.getTumorWgsSampleName(meta) + def purple_germline_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") + + if (!purple_germline_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + return [meta_peach, purple_germline_vcf] } + .filter { it[0] != Constants.META_PLACEHOLDER } // Run process PEACH( @@ -990,15 +1055,16 @@ workflow ONCOANALYSER { if (run.cuppa) { // Select input sources // channel: [val(meta), isofox_dir] + ch_cuppa_inputs_isofox = Channel.empty() if (run.isofox) { - ch_cuppa_inputs_isofox = Channel.empty() + // Take Isofox output and supplement with placeholders for missing; i.e. allow optional + ch_cuppa_inputs_isofox = ch_cuppa_inputs_isofox .mix( - ch_inputs_wts.absent.map { meta -> [meta, []] }, ch_isofox_out, + ch_inputs_wts.absent.map { meta -> [meta, []] }, ) } else { - ch_cuppa_inputs_isofox = ch_inputs - .map { meta -> [meta, meta.get([Constants.FileType.ISOFOX_DIR, Constants.DataType.TUMOR], [])] } + ch_cuppa_inputs_isofox = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX, type: 'optional') } // channel: [val(meta), linx_somatic_annotation_dir] @@ -1007,9 +1073,9 @@ workflow ONCOANALYSER { // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter] ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), - run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.TUMOR_NORMAL]), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.VIRUSINTERPRETER_TSV, Constants.DataType.TUMOR]), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), + run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV), flatten_mode: 'nonrecursive', ) @@ -1020,7 +1086,7 @@ workflow ONCOANALYSER { def meta = it[0] def meta_cuppa = [ key: meta.id, - id: meta.get(['sample_name', Constants.DataType.TUMOR]), + id: Utils.getTumorWgsSampleName(meta), ] return [meta_cuppa, *it[1..-1]] } @@ -1055,12 +1121,12 @@ workflow ONCOANALYSER { // Select input source // channel (present): [val(meta), sample_type, flagstat] // channel (absent): [val(meta)] - ch_inputs_flagstat = ch_inputs - .flatMap { meta -> [Constants.DataType.TUMOR, Constants.DataType.NORMAL].collect { [meta, it] } } + ch_inputs_flagstat = ch_inputs_wgs.present + .flatMap { meta -> [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL].collect { [meta, it] } } .branch { meta, sample_type -> - def key = [Constants.FileType.FLAGSTAT, sample_type] + def key = [Constants.FileType.FLAGSTAT, sample_type, Constants.SequenceType.WGS] present: meta.containsKey(key) - return [meta, sample_type, meta.get(key)] + return [meta, sample_type, meta.getAt(key)] absent: ! meta.containsKey(key) } @@ -1068,10 +1134,11 @@ workflow ONCOANALYSER { // channel: [val(meta_flagstat), bam, bai] ch_flagstat_inputs_all = ch_inputs_flagstat.absent .map { meta, sample_type -> - def bam = meta.get([Constants.FileType.BAM_WGS, sample_type]) + def bam = meta.getAt([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) + def sample_name = meta.getAt(['sample_name', sample_type, Constants.SequenceType.WGS]) def meta_flagstat = [ key: meta.id, - id: meta.get(['sample_name', sample_type]), + id: sample_name, // NOTE(SW): must use string representation for caching purposes sample_type_str: sample_type.name(), ] @@ -1115,7 +1182,7 @@ workflow ONCOANALYSER { // channel: [val(meta_flagstat_individual), flagstat] ch_flagstat_out = SAMTOOLS_FLAGSTAT.out.flagstat .flatMap { meta_flagstat_shared, flagstat -> - def sample_type = Utils.getEnumFromString(meta_flagstat_shared.sample_type_str, Constants.DataType) + def sample_type = Utils.getEnumFromString(meta_flagstat_shared.sample_type_str, Constants.SampleType) meta_flagstat_shared.keys.collect { key -> return [meta_flagstat_shared + [key: key], sample_type, flagstat] } @@ -1130,9 +1197,9 @@ workflow ONCOANALYSER { WorkflowOncoanalyser.restoreMeta(ch_flagstat_out, ch_inputs), ) .branch { meta, sample_type, flagstat -> - somatic: sample_type == Constants.DataType.TUMOR + somatic: sample_type == Constants.SampleType.TUMOR return [meta, flagstat] - germline: sample_type == Constants.DataType.NORMAL + germline: sample_type == Constants.SampleType.NORMAL return [meta, flagstat] } @@ -1146,6 +1213,8 @@ workflow ONCOANALYSER { plot: [meta, plot_dir] } + // TODO(SW): handle CUPPA WTS, WGS, WGS + // Select input source // NOTE(SW): we could consider not allowing inputs from the samplesheet here since this nothing follows ch_orange_inputs_source = WorkflowOncoanalyser.groupByMeta( @@ -1153,21 +1222,21 @@ workflow ONCOANALYSER { ch_cwm_out.germline, ch_orange_inputs_flagstat.somatic, ch_orange_inputs_flagstat.germline, - run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CHORD_PREDICTION, Constants.DataType.TUMOR]), - run.lilac ? ch_lilac_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LILAC_DIR, Constants.DataType.NORMAL]), - run.sage ? ch_sage_somatic_tumor_bqr_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_BQR, Constants.DataType.TUMOR]), - run.sage ? ch_sage_somatic_normal_bqr_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_BQR, Constants.DataType.NORMAL]), - run.sage ? ch_sage_germline_coverage_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.SAGE_COVERAGE, Constants.DataType.NORMAL]), - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput([Constants.FileType.PURPLE_DIR, Constants.DataType.TUMOR_NORMAL]), - run.linx ? ch_orange_inputs_linx_somatic.anno : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.TUMOR_NORMAL]), - run.linx ? ch_orange_inputs_linx_somatic.plot : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_PLOT_DIR, Constants.DataType.TUMOR_NORMAL]), - run.linx ? ch_linx_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.LINX_ANNO_DIR, Constants.DataType.NORMAL]), - run.protect ? ch_protect_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PROTECT_TSV, Constants.DataType.TUMOR]), - run.peach ? ch_peach_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.PEACH_TSV, Constants.DataType.NORMAL]), - run.cuppa ? ch_cuppa_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CUPPA_CSV, Constants.DataType.TUMOR]), - run.cuppa ? ch_cuppa_feature_plot_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CUPPA_FEATURE_PLOT, Constants.DataType.TUMOR]), - run.cuppa ? ch_cuppa_summary_plot_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.CUPPA_SUMMARY_PLOT, Constants.DataType.TUMOR]), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, [Constants.FileType.VIRUSINTERPRETER_TSV, Constants.DataType.TUMOR]), + run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD), + run.lilac ? ch_lilac_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), + run.sage ? ch_sage_somatic_tumor_bqr_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_TUMOR), + run.sage ? ch_sage_somatic_normal_bqr_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_NORMAL), + run.sage ? ch_sage_germline_coverage_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_COVERAGE), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), + run.linx ? ch_orange_inputs_linx_somatic.anno : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + run.linx ? ch_orange_inputs_linx_somatic.plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_TUMOR), + run.linx ? ch_linx_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_NORMAL), + run.protect ? ch_protect_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PROTECT_TSV), + run.peach ? ch_peach_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PEACH_TSV), + run.cuppa ? ch_cuppa_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUTS_CUPPA_CSV), + run.cuppa ? ch_cuppa_feature_plot_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_FEATURE_PLOT), + run.cuppa ? ch_cuppa_summary_plot_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_SUMMARY_PLOT), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV), ) ch_orange_inputs = ch_orange_inputs_source @@ -1176,8 +1245,8 @@ workflow ONCOANALYSER { def meta_orange = [ key: meta.id, id: meta.id, - tumor_id: meta.get(['sample_name', Constants.DataType.TUMOR]), - normal_id: meta.get(['sample_name', Constants.DataType.NORMAL]), + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), ] return [meta_orange, *it[1..-1]] } From 0ed2189c64878b6c9c638e2b60174a586022cf4d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 28 Mar 2023 17:39:28 +1100 Subject: [PATCH 131/562] Replace collectwgsmetrics with Bam Tools --- conf/base.config | 5 -- conf/modules.config | 5 +- lib/Constants.groovy | 6 +- modules.json | 4 -- modules/local/bamtools/Dockerfile | 22 +++++++ modules/local/bamtools/main.nf | 46 +++++++++++++++ modules/local/bamtools/meta.yml | 46 +++++++++++++++ .../nf-core/picard/collectwgsmetrics/main.nf | 56 ------------------ .../nf-core/picard/collectwgsmetrics/meta.yml | 47 --------------- workflows/oncoanalyser.nf | 59 ++++++++++--------- 10 files changed, 150 insertions(+), 146 deletions(-) create mode 100644 modules/local/bamtools/Dockerfile create mode 100644 modules/local/bamtools/main.nf create mode 100644 modules/local/bamtools/meta.yml delete mode 100644 modules/nf-core/picard/collectwgsmetrics/main.nf delete mode 100644 modules/nf-core/picard/collectwgsmetrics/meta.yml diff --git a/conf/base.config b/conf/base.config index 5095b3b8..06a36de3 100644 --- a/conf/base.config +++ b/conf/base.config @@ -131,11 +131,6 @@ process { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'PICARD_COLLECTWGSMETRICS' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - time = { check_max( 24.h , 'time' ) } - } withName:'VIRUSBREAKEND' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 60.GB, 'memory' ) } diff --git a/conf/modules.config b/conf/modules.config index f811a9d0..5f5da099 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -145,11 +145,12 @@ process { ] } - withName: 'PICARD_COLLECTWGSMETRICS' { + withName: 'BAMTOOLS' { + ext.jarPath = '/opt/bamtools/bamtools.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/wgs_metrics/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/bamtools/${filename}" }, ] } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 43daf43f..ffdf34a1 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -19,9 +19,9 @@ class Constants { static enum Process { AMBER, + BAMTOOLS, CHORD, COBALT, - COLLECTWGSMETRICS, CUPPA, GRIDSS, GRIPSS, @@ -44,14 +44,14 @@ class Constants { BAM, // Process AMBER_DIR, + BAMTOOLS_TXT, COBALT_DIR, - COLLECTWGSMETRICS, GRIDSS_VCF, GRIPSS_HARD_VCF, GRIPSS_SOFT_VCF, ISOFOX_DIR, - LINX_ANNO_DIR, LILAC_DIR, + LINX_ANNO_DIR, PAVE_VCF, PURPLE_DIR, SAGE_VCF, diff --git a/modules.json b/modules.json index 9885925d..2133cd50 100644 --- a/modules.json +++ b/modules.json @@ -13,10 +13,6 @@ "branch": "master", "git_sha": "8022c68e7403eecbd8ba9c49496f69f8c49d50f0" }, - "picard/collectwgsmetrics": { - "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" - }, "samtools/dict": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01" diff --git a/modules/local/bamtools/Dockerfile b/modules/local/bamtools/Dockerfile new file mode 100644 index 00000000..e850f9ce --- /dev/null +++ b/modules/local/bamtools/Dockerfile @@ -0,0 +1,22 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN \ + mkdir -p /opt/bamtools/ && \ + wget -O /opt/bamtools/bamtools.jar 'https://github.com/hartwigmedical/hmftools/releases/download/bam-tools-v1.0.1/bam-tools_v1.0.1.jar' + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'openjdk >=8' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf new file mode 100644 index 00000000..4400b34e --- /dev/null +++ b/modules/local/bamtools/main.nf @@ -0,0 +1,46 @@ +process BAMTOOLS { + tag "${meta.id}" + label 'process_medium' + + container 'docker.io/scwatts/bamtools:1.0.1--0' + + input: + tuple val(meta), path(bam), path(bai) + path genome_fasta + val genome_ver + + output: + tuple val(meta), path('*wgsmetrics'), emit: metrics + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + -cp ${task.ext.jarPath} \\ + com.hartwig.hmftools.bamtools.metrics.BamMetrics \\ + -sample ${meta.id} \\ + -bam_file ${bam} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -threads ${task.cpus} \\ + -write_old_style \\ + -output_dir ./ + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bamtools: \$(java -jar bam-tools_v1.0.jar 2>&1 | sed -n '1s/^.*BamTools version: //p') + END_VERSIONS + """ + + stub: + """ + mkdir -p ${meta.id}.wgsmetrics + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/bamtools/meta.yml b/modules/local/bamtools/meta.yml new file mode 100644 index 00000000..1a257f7c --- /dev/null +++ b/modules/local/bamtools/meta.yml @@ -0,0 +1,46 @@ +name: bamtools +description: Rapidly process BAMs for various tasks +keywords: + - bam +tools: + - bamtools: + description: Performs rapid processing of BAM files + homepage: https://github.com/hartwigmedical/hmftools/tree/master/bam-tools + documentation: https://github.com/hartwigmedical/hmftools/tree/master/bam-tools + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - bai: + type: file + description: BAI file + pattern: "*.{bai}" + - genome_fasta: + type: file + description: Reference genome assembly fa file + pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id'] + - metrics: + description: BAM metrics file + pattern: "*.{wgsmetrics}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" diff --git a/modules/nf-core/picard/collectwgsmetrics/main.nf b/modules/nf-core/picard/collectwgsmetrics/main.nf deleted file mode 100644 index 2b0aeefe..00000000 --- a/modules/nf-core/picard/collectwgsmetrics/main.nf +++ /dev/null @@ -1,56 +0,0 @@ -process PICARD_COLLECTWGSMETRICS { - tag "$meta.id" - label 'process_medium' - - conda (params.enable_conda ? "bioconda::picard=2.27.4 r::r-base" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/picard:2.27.4--hdfd78af_0' : - 'quay.io/biocontainers/picard:2.27.4--hdfd78af_0' }" - - input: - tuple val(meta), path(bam) - path fasta - - output: - tuple val(meta), path("*_metrics"), emit: metrics - 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 avail_mem = 3 - if (!task.memory) { - log.info '[Picard CollectWgsMetrics] Available memory not known - defaulting to 3GB. Specify process memory requirements to change this.' - } else { - avail_mem = task.memory.giga - } - """ - picard \\ - -Xmx${avail_mem}g \\ - CollectWgsMetrics \\ - $args \\ - --INPUT $bam \\ - --OUTPUT ${prefix}.CollectWgsMetrics.coverage_metrics \\ - --REFERENCE_SEQUENCE ${fasta} - - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - picard: \$(picard CollectWgsMetrics --version 2>&1 | grep -o 'Version.*' | cut -f2- -d:) - END_VERSIONS - """ - - stub: - def prefix = task.ext.prefix ?: "${meta.id}" - """ - touch ${prefix}.CollectWgsMetrics.coverage_metrics - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - picard: \$(picard CollectWgsMetrics --version 2>&1 | grep -o 'Version.*' | cut -f2- -d:) - END_VERSIONS - """ -} diff --git a/modules/nf-core/picard/collectwgsmetrics/meta.yml b/modules/nf-core/picard/collectwgsmetrics/meta.yml deleted file mode 100644 index d6c3d012..00000000 --- a/modules/nf-core/picard/collectwgsmetrics/meta.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: picard_collectwgsmetrics -description: Collect metrics about coverage and performance of whole genome sequencing (WGS) experiments. -keywords: - - alignment - - metrics - - statistics - - quality - - bam -tools: - - picard: - description: | - A set of command line tools (in Java) for manipulating high-throughput sequencing (HTS) - data and formats such as SAM/BAM/CRAM and VCF. - homepage: https://broadinstitute.github.io/picard/ - documentation: https://broadinstitute.github.io/picard/ - licence: ["MIT"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - bam: - type: file - description: BAM file - pattern: "*.{bam}" - - fasta: - type: file - description: Genome fasta file -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - metrics: - type: file - description: Alignment metrics files generated by picard - pattern: "*_{metrics}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@drpatelh" - - "@flowuenne" - - "@lassefolkersen" diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index a95df036..d3ed6305 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -59,6 +59,7 @@ linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : // MODULES // include { AMBER } from '../modules/local/amber/main' +include { BAMTOOLS } from '../modules/local/bamtools/main' include { CHORD } from '../modules/local/chord/main' include { COBALT } from '../modules/local/cobalt/main' include { CUPPA_CLASSIFIER } from '../modules/local/cuppa/classifier/main' @@ -96,7 +97,6 @@ include { SAGE } from '../subworkflows/local/sage' // MODULES // include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' -include { PICARD_COLLECTWGSMETRICS } from '../modules/nf-core/picard/collectwgsmetrics/main' include { SAMTOOLS_FLAGSTAT } from '../modules/nf-core/samtools/flagstat/main' /* @@ -194,40 +194,40 @@ workflow ONCOANALYSER { } // - // MODULE: Run PICARD_COLLECTWGSMETRICS to generate stats required for downstream processes + // MODULE: Run Bam Tools to generate stats required for downstream processes // - if (run.virusinterpreter || run.orange) { + if (run.bamtools) { // Create inputs and create process-specific meta - // NOTE(SW): CUPPA only requires collectwgsmetrics for the tumor sample in the upstream - // process Virus Interpreter but ORANGE currently requires collectwgsmetrics for both tumor + // NOTE(SW): CUPPA only requires metrics for the tumor sample in the upstream + // process Virus Interpreter but ORANGE currently requires metrics for both tumor // and normal sample - // channel: [val(meta_cwm), bam_wgs] - ch_cwm_inputs_all = ch_inputs_wgs.present + // channel: [val(meta_bamtools), bam, bai] + ch_bamtools_inputs_all = ch_inputs_wgs.present .flatMap { meta -> def sample_types = run.orange ? [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL] : [Constants.SampleType.TUMOR] return sample_types .collect { sample_type -> - def bam = meta.getAt([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) - def sample_name = meta.getAt(['sample_name', sample_type, Constants.SequenceType.WGS]) - def meta_cwm = [ + def bam = meta.get([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) + def sample_name = meta.get(['sample_name', sample_type, Constants.SequenceType.WGS]) + def meta_bamtools = [ key: meta.id, id: sample_name, // NOTE(SW): must use string representation for caching purposes sample_type_str: sample_type.name(), ] - return [meta_cwm, bam] + return [meta_bamtools, bam, "${bam}.bai"] } } // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent // on any process - // channel: [val(meta_cwm), bam_wgs] - ch_cwm_inputs = ch_cwm_inputs_all + // channel: [val(meta_bamtools), bam, bai] + ch_bamtools_inputs = ch_bamtools_inputs_all .map { [it[1..-1], it[0]] } .groupTuple() - .map { filepaths, meta_cwm -> - def (keys, sample_names, sample_type_strs) = meta_cwm + .map { filepaths, meta_bamtools -> + def (keys, sample_names, sample_type_strs) = meta_bamtools .collect { [it.key, it.id, it.sample_type_str] } @@ -237,37 +237,38 @@ workflow ONCOANALYSER { assert sample_type_strs_unique.size() == 1 def sample_type_str = sample_type_strs_unique[0] - def meta_cwm_new = [ + def meta_bamtools_new = [ keys: keys, id: sample_names.join('__'), id_simple: keys.join('__'), sample_type_str: sample_type_str, ] - return [meta_cwm_new, *filepaths] + return [meta_bamtools_new, *filepaths] } // Run process - PICARD_COLLECTWGSMETRICS( - ch_cwm_inputs, + BAMTOOLS( + ch_bamtools_inputs, PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_version, ) // Set outputs, process outputs and restore original meta - ch_versions = ch_versions.mix(PICARD_COLLECTWGSMETRICS.out.versions) + ch_versions = ch_versions.mix(BAMTOOLS.out.versions) // Replicate outputs to reverse unique operation - // channel: [val(meta_cwm_individual), sample_type_str, metrics] - ch_cwm_out_individual = PICARD_COLLECTWGSMETRICS.out.metrics - .flatMap { meta_cwm_shared, metrics -> - meta_cwm_shared.keys.collect { key -> - return [meta_cwm_shared + [key: key], meta_cwm_shared.sample_type_str, metrics] + // channel: [val(meta_bamtools_individual), sample_type_str, metrics] + ch_bamtools_out_individual = BAMTOOLS.out.metrics + .flatMap { meta_bamtools_shared, metrics -> + meta_bamtools_shared.keys.collect { key -> + return [meta_bamtools_shared + [key: key], meta_bamtools_shared.sample_type_str, metrics] } } // Match outputs to original meta and set output // channel (tumor): [val(meta), metrics] // channel (normal): [val(meta), metrics] - ch_cwm_out = WorkflowOncoanalyser.restoreMeta(ch_cwm_out_individual, ch_inputs) + ch_bamtools_out = WorkflowOncoanalyser.restoreMeta(ch_bamtools_out_individual, ch_inputs) .branch { meta, sample_type_str, metrics -> def sample_type = Utils.getEnumFromString(sample_type_str, Constants.SampleType) somatic: sample_type == Constants.SampleType.TUMOR @@ -836,7 +837,7 @@ workflow ONCOANALYSER { ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), ch_virusinterpreter_inputs_purple_files, - ch_cwm_out.somatic, + run.bamtools ? ch_bamtools_out.somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_TUMOR), ) // Virus Interpreter @@ -1218,8 +1219,8 @@ workflow ONCOANALYSER { // Select input source // NOTE(SW): we could consider not allowing inputs from the samplesheet here since this nothing follows ch_orange_inputs_source = WorkflowOncoanalyser.groupByMeta( - ch_cwm_out.somatic, - ch_cwm_out.germline, + run.bamtools ? ch_bamtools_out.somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_TUMOR), + run.bamtools ? ch_bamtools_out.germline: WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_NORMAL), ch_orange_inputs_flagstat.somatic, ch_orange_inputs_flagstat.germline, run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD), From 644f31c03b8e26f8de4f8115a58ca69127f22e44 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 28 Mar 2023 21:24:16 +1100 Subject: [PATCH 132/562] Support DNA, RNA, and ALL CUPPA classifiers --- modules/local/cuppa/classifier/main.nf | 39 +++++++++++++++++++++---- modules/local/cuppa/classifier/meta.yml | 6 ++-- workflows/oncoanalyser.nf | 33 ++++++++++++++------- 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index 78bc42b7..3d6ebdac 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -18,18 +18,47 @@ process CUPPA_CLASSIFIER { script: def args = task.ext.args ?: '' - def categories_arg = isofox_dir ? 'ALL' : 'DNA' + + def has_rna = isofox_dir + def has_dna = purple_dir || linx_dir + if (has_dna && (!purple_dir || !linx_dir)) { + exit 1, "ERROR: CUPPA_CLASSIFIER: DNA classification requires both PURPLE and LINX inputs" + } + + def categories_val + if (has_dna && has_rna) { + categories_val = 'ALL' + } else if (has_dna) { + categories_val = 'DNA' + } else if (has_rna) { + categories_val = 'RNA' + } else { + exit 1, "ERROR: CUPPA_CLASSIFIER: either PURPLE and LINX inputs or Isofox inputs are required" + } """ # Symlink input files into a single directory - mkdir sample_data/ - inputs="${isofox_dir} ${purple_dir} ${linx_dir} ${virusinterpreter}" - find -L \${inputs} -maxdepth 1 -type f -exec ln -s ../{} sample_data/ \\; + mkdir -p sample_data/ + if [[ ${categories_val} == 'DNA' || ${categories_val} == 'ALL' ]]; then + find -L ${purple_dir} ${linx_dir} ${virusinterpreter} -mindepth 1 -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; + fi + + if [[ ${categories_val} == 'RNA' ]]; then + find -L ${isofox_dir} -mindepth 1 -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; + elif [[ ${categories_val} == 'ALL' ]]; then + # NOTE(SW): CUPPA requires that the WTS sample name matches the WGS sample name + for fp in \$(find -L ${isofox_dir} -mindepth 1 -maxdepth 1 -type f); do + fn_out=\$(sed 's/^${meta.id_wts}/${meta.id}/' <<< \${fp##*/}); + cp \${fp} sample_data/\${fn_out} + done; + # Rename identifier in the summary file + sed -i 's/^${meta.id_wts}/${meta.id}/g' sample_data/${meta.id}.isf.summary.csv + fi; java \\ -Xmx${task.memory.giga}g \\ -jar ${task.ext.jarPath} \\ - -categories ${categories_arg} \\ + -categories ${categories_val} \\ -ref_data_dir ${cuppa_resources} \\ -sample_data ${meta.id} \\ -sample_data_dir sample_data/ \\ diff --git a/modules/local/cuppa/classifier/meta.yml b/modules/local/cuppa/classifier/meta.yml index 4b4b4fdb..8ed4e73e 100644 --- a/modules/local/cuppa/classifier/meta.yml +++ b/modules/local/cuppa/classifier/meta.yml @@ -21,13 +21,13 @@ input: description: Isofox output directory (optional) - purple_dir: type: directory - description: PURPLE output directory + description: PURPLE output directory (optional) - linx_dir: type: directory - description: LINX output directory + description: LINX output directory (optional) - virusinterpreter: type: file - description: Virus Interpreter annotations file + description: Virus Interpreter annotations file (optional) pattern: "*.{tsv}" - cuppa_resources: type: directory diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index d3ed6305..128f3591 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -1074,22 +1074,35 @@ workflow ONCOANALYSER { // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter] ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), - run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional'), + run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR, type: 'optional'), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), flatten_mode: 'nonrecursive', ) // Create inputs and create process-specific meta // channel: [val(meta_cuppa), isofox_dir, purple_dir, linx_dir, virusinterpreter] ch_cuppa_inputs = ch_cuppa_inputs_source - .map { - def meta = it[0] - def meta_cuppa = [ - key: meta.id, - id: Utils.getTumorWgsSampleName(meta), - ] - return [meta_cuppa, *it[1..-1]] + .map { data -> + def meta = data[0] + def meta_cuppa = [key: meta.id] + + def sample_name_wgs = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) + def sample_name_wts = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + + if (sample_name_wgs && sample_name_wts) { + meta_cuppa.id = sample_name_wgs + meta_cuppa.id_wts = sample_name_wts + } else if (sample_name_wgs) { + meta_cuppa.id = sample_name_wgs + } else if (sample_name_wts) { + meta_cuppa.id = sample_name_wts + } else { + log.error "ERROR: no sample name for: ${meta}" + System.exit(1) + } + + return [meta_cuppa, *data[1..-1]] } // Run process From 8528a07c66e73a5c4e4d9b1cb2a648b9ab3c3cc4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 31 Mar 2023 09:03:52 +1100 Subject: [PATCH 133/562] Add samtools/flagstat stub as module patch --- modules.json | 4 +++- modules/nf-core/samtools/flagstat/main.nf | 7 +++++++ .../samtools/flagstat/samtools-flagstat.diff | 17 +++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 modules/nf-core/samtools/flagstat/samtools-flagstat.diff diff --git a/modules.json b/modules.json index 2133cd50..1d2c2c13 100644 --- a/modules.json +++ b/modules.json @@ -23,7 +23,9 @@ }, "samtools/flagstat": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c" + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "installed_by": ["modules"], + "patch": "modules/nf-core/samtools/flagstat/samtools-flagstat.diff" } } } diff --git a/modules/nf-core/samtools/flagstat/main.nf b/modules/nf-core/samtools/flagstat/main.nf index 2120cd7d..8d8d91dd 100644 --- a/modules/nf-core/samtools/flagstat/main.nf +++ b/modules/nf-core/samtools/flagstat/main.nf @@ -32,4 +32,11 @@ process SAMTOOLS_FLAGSTAT { samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') END_VERSIONS """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.flagstat + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/nf-core/samtools/flagstat/samtools-flagstat.diff b/modules/nf-core/samtools/flagstat/samtools-flagstat.diff new file mode 100644 index 00000000..52c43355 --- /dev/null +++ b/modules/nf-core/samtools/flagstat/samtools-flagstat.diff @@ -0,0 +1,17 @@ +Changes in module 'nf-core/samtools/flagstat' +--- modules/nf-core/samtools/flagstat/main.nf ++++ modules/nf-core/samtools/flagstat/main.nf +@@ -32,4 +32,11 @@ + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ ++ ++ stub: ++ def prefix = task.ext.prefix ?: "${meta.id}" ++ """ ++ touch ${prefix}.flagstat ++ echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml ++ """ + } + +************************************************************ From fb54113036d2ad1b38a0f8b8e03b29a457c30d94 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 31 Mar 2023 09:06:03 +1100 Subject: [PATCH 134/562] Enforce small memory buffer for Java applications This change is required for execution models where Nextflow requests compute with the specified task memory. In this scenario, the memory is shared between the system and the user application. Hence, the JVM should not be allocated all available memory to avoid crashing the compute. --- modules/local/amber/main.nf | 2 +- modules/local/cobalt/main.nf | 2 +- modules/local/cuppa/classifier/main.nf | 2 +- modules/local/gridss/assemble/main.nf | 4 ++-- modules/local/gridss/call/main.nf | 4 ++-- modules/local/gridss/index/main.nf | 2 +- modules/local/gridss/preprocess/main.nf | 2 +- modules/local/gripss/germline/main.nf | 2 +- modules/local/gripss/somatic/main.nf | 2 +- modules/local/isofox/main.nf | 2 +- modules/local/lilac/main.nf | 2 +- modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 2 +- modules/local/orange/main.nf | 2 +- modules/local/pave/germline/main.nf | 2 +- modules/local/pave/somatic/main.nf | 2 +- modules/local/protect/main.nf | 2 +- modules/local/purple/main.nf | 2 +- modules/local/sage/germline/main.nf | 2 +- modules/local/sage/somatic/main.nf | 2 +- modules/local/sigs/main.nf | 2 +- modules/local/svprep/assemble/main.nf | 4 ++-- modules/local/svprep/call/main.nf | 4 ++-- modules/local/svprep/depth_annotator/main.nf | 2 +- modules/local/svprep/preprocess/main.nf | 2 +- modules/local/svprep/svprep/main.nf | 5 +---- modules/local/virusbreakend/main.nf | 2 +- modules/local/virusinterpreter/main.nf | 2 +- 29 files changed, 33 insertions(+), 36 deletions(-) diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index da3f0acd..7272fee5 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -21,7 +21,7 @@ process AMBER { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -tumor ${meta.tumor_id} \\ diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index 4c91e657..1b2a3563 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -20,7 +20,7 @@ process COBALT { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -tumor ${meta.tumor_id} \\ diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/classifier/main.nf index 3d6ebdac..660c3fba 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/classifier/main.nf @@ -56,7 +56,7 @@ process CUPPA_CLASSIFIER { fi; java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ -categories ${categories_val} \\ -ref_data_dir ${cuppa_resources} \\ diff --git a/modules/local/gridss/assemble/main.nf b/modules/local/gridss/assemble/main.nf index c49abf4d..f8e6192a 100644 --- a/modules/local/gridss/assemble/main.nf +++ b/modules/local/gridss/assemble/main.nf @@ -63,8 +63,8 @@ process GRIDSS_ASSEMBLE { # Run gridss \\ ${args} \\ - --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ - --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ + --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ + --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ --jar ${task.ext.jarPath} \\ --steps assemble \\ --labels ${labels_arg} \\ diff --git a/modules/local/gridss/call/main.nf b/modules/local/gridss/call/main.nf index 7e5d312b..f35a54d7 100644 --- a/modules/local/gridss/call/main.nf +++ b/modules/local/gridss/call/main.nf @@ -61,8 +61,8 @@ process GRIDSS_CALL { # Run gridss \\ ${args} \\ - --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ - --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ + --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ + --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ --jar ${task.ext.jarPath} \\ --steps call \\ --labels ${labels_arg} \\ diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 5933769b..f22bb4fd 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -32,7 +32,7 @@ process GRIDSS_INDEX { ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ # Run - java -Xmx${task.memory.giga}g \\ + java -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -XX:ParallelGCThreads=${task.cpus} \\ -Dsamjdk.reference_fasta=${genome_fasta} \\ -Dsamjdk.use_async_io_read_samtools=true \\ diff --git a/modules/local/gridss/preprocess/main.nf b/modules/local/gridss/preprocess/main.nf index ddbbae12..264ab3ff 100644 --- a/modules/local/gridss/preprocess/main.nf +++ b/modules/local/gridss/preprocess/main.nf @@ -31,7 +31,7 @@ process GRIDSS_PREPROCESS { gridss \\ ${args} \\ - --jvmheap ${task.memory.giga}g \\ + --jvmheap ${Math.round(task.memory.bytes * 0.95)} \\ --jar ${task.ext.jarPath} \\ --steps preprocess \\ --reference ${genome_fasta} \\ diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 99bd73fb..457bcec1 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -27,7 +27,7 @@ process GRIPSS_GERMLINE { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.normal_id} \\ diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index cbfdc4cf..a4bbf255 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -27,7 +27,7 @@ process GRIPSS_SOMATIC { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.tumor_id} \\ diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index a2f51498..23febca5 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -31,7 +31,7 @@ process ISOFOX { mkdir -p isofox/ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index c925c3a6..19b47aad 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -27,7 +27,7 @@ process LILAC { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${sample_name} \\ diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 56ff2272..b5494c6d 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -23,7 +23,7 @@ process LINX_GERMLINE { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index f3d8a43b..cb402482 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -27,7 +27,7 @@ process LINX_SOMATIC { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 3ca314f8..4d5e6b24 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -21,7 +21,7 @@ process LINX_VISUALISER { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -cp ${task.ext.jarPath} \\ com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ ${args} \\ diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index a4d68898..4720e8b2 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -36,7 +36,7 @@ process ORANGE { java \\ --add-opens java.base/java.time=ALL-UNNAMED \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ \\ -tumor_sample_id ${meta.tumor_id} \\ diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 088a9015..13d26c3f 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -33,7 +33,7 @@ process PAVE_GERMLINE { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index b947ae0b..da0ea55d 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -40,7 +40,7 @@ process PAVE_SOMATIC { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ -sample ${meta.id} \\ -ref_genome_version ${genome_ver} \\ diff --git a/modules/local/protect/main.nf b/modules/local/protect/main.nf index 5335839a..5158382b 100644 --- a/modules/local/protect/main.nf +++ b/modules/local/protect/main.nf @@ -23,7 +23,7 @@ process PROTECT { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ -tumor_sample_id ${meta.tumor_id} \\ -reference_sample_id ${meta.normal_id} \\ diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index a78dc6cb..268882ba 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -52,7 +52,7 @@ process PURPLE { # Run PURPLE java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -tumor ${meta.tumor_id} \\ diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index f6fb998d..cab41d6a 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -30,7 +30,7 @@ process SAGE_GERMLINE { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -tumor ${meta.normal_id} \\ diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index cb43244f..60f14ae0 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -35,7 +35,7 @@ process SAGE_SOMATIC { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -reference ${meta.normal_id} \\ diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 8fe3a772..ecf0bf7a 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -22,7 +22,7 @@ process SIGS { mkdir -p sigs/ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ -sample ${meta.tumor_id} \\ -somatic_vcf_file ${smlv_vcf} \\ diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 4df53457..01cd029b 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -65,8 +65,8 @@ process ASSEMBLE { # Run gridss_svprep \\ ${args} \\ - --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ - --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ + --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ + --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ --jar ${task.ext.jarPath} \\ --steps assemble \\ --labels ${labels_arg} \\ diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index d9c24998..1592685f 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -63,8 +63,8 @@ process CALL { # Run gridss_svprep \\ ${args} \\ - --jvmheap ${task.memory.giga - task.ext.otherJvmHeap.giga}g \\ - --otherjvmheap ${task.ext.otherJvmHeap.giga}g \\ + --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ + --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ --jar ${task.ext.jarPath} \\ --steps call \\ --labels ${labels_arg} \\ diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 495959b5..164eef05 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -25,7 +25,7 @@ process DEPTH_ANNOTATOR { """ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -cp ${task.ext.jarPath} com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ ${args} \\ -input_vcf ${vcf} \\ diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 641aafae..5bfcf361 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -31,7 +31,7 @@ process PREPROCESS { gridss_svprep \\ ${args} \\ - --jvmheap ${task.memory.giga}g \\ + --jvmheap ${Math.round(task.memory.bytes * 0.95)} \\ --jar ${task.ext.jarPath} \\ --steps preprocess \\ --reference ${genome_fasta} \\ diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 9b19f962..fbadcf37 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -1,6 +1,3 @@ -// NOTE(SW): providing a 1GB memory buffer since SV Prep v1.0.1 is often killed due to exceeding -// allocated memory - process SVPREP { tag "${meta.id}" label 'process_medium' @@ -30,7 +27,7 @@ process SVPREP { """ java \\ - -Xmx${task.memory.giga - 1}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index a2e326d1..96a05f76 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -34,7 +34,7 @@ process VIRUSBREAKEND { virusbreakend \\ --jar ${task.ext.jarPath} \\ - --gridssargs "--jvmheap ${task.memory.giga}g" \\ + --gridssargs "--jvmheap ${Math.round(task.memory.bytes * 0.95)}" \\ --threads ${task.cpus} \\ --db ${virusbreakenddb.toString().replaceAll("/\$", "")}/ \\ --output ${meta.id}.virusbreakend.vcf \\ diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index 96b9c821..d8280233 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -23,7 +23,7 @@ process VIRUSINTERPRETER { mkdir -p virusinterpreter/ java \\ - -Xmx${task.memory.giga}g \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ -sample_id ${meta.id} \\ -purple_purity_tsv ${purple_purity} \\ From b55a5425259da3ee0bfa8744c3fd1cbe8c7a1978 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 31 Mar 2023 09:08:01 +1100 Subject: [PATCH 135/562] Use consistent formatting in gridss/index module --- modules/local/gridss/index/main.nf | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index f22bb4fd..0c90de86 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -32,19 +32,20 @@ process GRIDSS_INDEX { ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ # Run - java -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -XX:ParallelGCThreads=${task.cpus} \\ - -Dsamjdk.reference_fasta=${genome_fasta} \\ - -Dsamjdk.use_async_io_read_samtools=true \\ - -Dsamjdk.use_async_io_write_samtools=true \\ - -Dsamjdk.use_async_io_write_tribble=true \\ - -Dsamjdk.buffer_size=4194304 \\ - -Dsamjdk.async_io_read_threads=${task.cpus} \\ - -cp ${task.ext.jarPath} \\ - REFERENCE_SEQUENCE=${genome_fasta} \\ - CREATE_SEQUENCE_DICTIONARY=${sequence_dict_arg} \\ - CREATE_BWA_INDEX_IMAGE=${bwa_index_image_arg} \\ - CREATE_GRIDSS_REFERENCE_CACHE=${gridss_index_arg} + java \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + -XX:ParallelGCThreads=${task.cpus} \\ + -Dsamjdk.reference_fasta=${genome_fasta} \\ + -Dsamjdk.use_async_io_read_samtools=true \\ + -Dsamjdk.use_async_io_write_samtools=true \\ + -Dsamjdk.use_async_io_write_tribble=true \\ + -Dsamjdk.buffer_size=4194304 \\ + -Dsamjdk.async_io_read_threads=${task.cpus} \\ + -cp ${task.ext.jarPath} \\ + REFERENCE_SEQUENCE=${genome_fasta} \\ + CREATE_SEQUENCE_DICTIONARY=${sequence_dict_arg} \\ + CREATE_BWA_INDEX_IMAGE=${bwa_index_image_arg} \\ + CREATE_GRIDSS_REFERENCE_CACHE=${gridss_index_arg} cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -60,4 +61,3 @@ process GRIDSS_INDEX { echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } - From 29f5fc19ecbc172ba9d12dd0fd48b75f2b2d0846 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 31 Mar 2023 09:08:44 +1100 Subject: [PATCH 136/562] Improve BAM naming in modules --- modules/local/custom/lilac_realign_reads_lilac/main.nf | 6 +++--- modules/local/custom/lilac_slice/main.nf | 7 ++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf index 442bcfd3..a76778ee 100644 --- a/modules/local/custom/lilac_realign_reads_lilac/main.nf +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -33,8 +33,8 @@ process CUSTOM_REALIGNREADS { ${reference} \\ ${meta.id}_R1.fastq.gz \\ ${meta.id}_R2.fastq.gz | \\ - samtools sort -T tmp -o ${meta.id}_realigned.bam - samtools index ${meta.id}_realigned.bam + samtools sort -T tmp -o ${bam.baseName}.realigned.bam + samtools index ${bam.baseName}.realigned.bam cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -46,7 +46,7 @@ process CUSTOM_REALIGNREADS { stub: """ - touch ${meta.id}_realigned.bam ${meta.id}_realigned.bam.bai + touch ${bam.baseName}.realigned.bam ${bam.baseName}.realigned.bam.bai echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index eed55288..9a0f7280 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -16,7 +16,6 @@ process CUSTOM_SLICE { script: def args = task.ext.args ?: '' - def bam_name = bam.name - ~/\.bam$/ """ samtools view \\ @@ -25,7 +24,7 @@ process CUSTOM_SLICE { -@${task.cpus} \\ -Obam \\ ${bam} | \\ - samtools sort -T tmp -o ${bam_name}.sliced.bam + samtools sort -T tmp -o ${bam.baseName}.sliced.bam samtools index ${bam_name}.sliced.bam @@ -36,10 +35,8 @@ process CUSTOM_SLICE { """ stub: - def bam_name = bam.name - ~/\.bam$/ - """ - touch ${bam_name}.sliced.bam ${bam_name}.sliced.bam.bai + touch ${bam.baseName}.sliced.bam ${bam.baseName}.sliced.bam.bai echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } From e51d9b5ca5142bc85f218a42802a27f0167d8f01 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 31 Mar 2023 14:23:24 +1100 Subject: [PATCH 137/562] Format svprep/call module file --- modules/local/svprep/call/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 1592685f..1c860421 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -17,7 +17,7 @@ process CALL { output: tuple val(meta), path('gridss_call/sv.svprep.gridss.vcf.gz'), emit: vcf - path 'versions.yml' , emit: versions + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when From 95cee1f4a9b00a41779ceb1009e201aec16a1d89 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 3 Apr 2023 15:34:01 +1000 Subject: [PATCH 138/562] Remove MultiQC from email --- lib/NfcoreTemplate.groovy | 26 ++------------------------ nextflow_schema.json | 8 -------- workflows/oncoanalyser.nf | 2 +- 3 files changed, 3 insertions(+), 33 deletions(-) diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 27feb009..cfd8608a 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -35,7 +35,7 @@ class NfcoreTemplate { // // Construct and send completion email // - public static void email(workflow, params, summary_params, projectDir, log, multiqc_report=[]) { + public static void email(workflow, params, summary_params, projectDir, log) { // Set up the e-mail variables def subject = "[$workflow.manifest.name] Successful: $workflow.runName" @@ -73,24 +73,6 @@ class NfcoreTemplate { email_fields['projectDir'] = workflow.projectDir email_fields['summary'] = summary << misc_fields - // On success try attach the multiqc report - def mqc_report = null - try { - if (workflow.success) { - mqc_report = multiqc_report.getVal() - if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { - if (mqc_report.size() > 1) { - log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" - } - mqc_report = mqc_report[0] - } - } - } catch (all) { - if (multiqc_report) { - log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" - } - } - // Check if we are only sending emails on failure def email_address = params.email if (!params.email && params.email_on_fail && !workflow.success) { @@ -109,8 +91,7 @@ class NfcoreTemplate { def email_html = html_template.toString() // Render the sendmail template - def max_multiqc_email_size = params.max_multiqc_email_size as nextflow.util.MemoryUnit - def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] + def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir" ] def sf = new File("$projectDir/assets/sendmail_template.txt") def sendmail_template = engine.createTemplate(sf).make(smail_fields) def sendmail_html = sendmail_template.toString() @@ -126,9 +107,6 @@ class NfcoreTemplate { } catch (all) { // Catch failures and try with plaintext def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] - if ( mqc_report.size() <= max_multiqc_email_size.toBytes() ) { - mail_cmd += [ '-A', mqc_report ] - } mail_cmd.execute() << email_html log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" } diff --git a/nextflow_schema.json b/nextflow_schema.json index b1076071..425045dc 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -597,14 +597,6 @@ "fa_icon": "fas fa-remove-format", "hidden": true }, - "max_multiqc_email_size": { - "type": "string", - "description": "File size limit when attaching MultiQC reports to summary emails.", - "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", - "default": "25.MB", - "fa_icon": "fas fa-file-upload", - "hidden": true - }, "monochrome_logs": { "type": "boolean", "description": "Do not use coloured log outputs.", diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 128f3591..fd7a3a50 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -1298,7 +1298,7 @@ workflow ONCOANALYSER { workflow.onComplete { if (params.email || params.email_on_fail) { - NfcoreTemplate.email(workflow, params, summary_params, projectDir, log, multiqc_report) + NfcoreTemplate.email(workflow, params, summary_params, projectDir, log) } NfcoreTemplate.summary(workflow, params, log) if (params.hook_url) { From d049c5c3d4caef9b81597bf2084d6aa1c0e2ab02 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 8 Apr 2023 12:26:04 +1000 Subject: [PATCH 139/562] Resolve LILAC workflow bugs --- modules/local/custom/lilac_slice/main.nf | 2 +- workflows/oncoanalyser.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index 9a0f7280..b7565497 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -26,7 +26,7 @@ process CUSTOM_SLICE { ${bam} | \\ samtools sort -T tmp -o ${bam.baseName}.sliced.bam - samtools index ${bam_name}.sliced.bam + samtools index ${bam.baseName}.sliced.bam cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index fd7a3a50..0fbd21e3 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -725,7 +725,7 @@ workflow ONCOANALYSER { ch_inputs_wgs.absent.map { meta -> [meta, []] }, ) } else { - ch_lilac_inputs_purple = WorkflowOncoanalyser.getInput(meta, Constants.INPUT.PURPLE_DIR, type: 'optional') + ch_lilac_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional') } // Create channel with all available input BAMs From 8494ce6b6ed8f813cb1f5f4e5602d0698bc7f169 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 18 Apr 2023 11:39:37 +1000 Subject: [PATCH 140/562] Force use of Isofox exp count cache file for now --- workflows/oncoanalyser.nf | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 0fbd21e3..550af628 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -174,7 +174,13 @@ workflow ONCOANALYSER { // NOTE(SW): consider alternative approaches for using the expected count file e.g. generate once at runtime, // then use for all samples; generate all possible read lengths outside of pipeline and store on a remote for // retrieval at runtime (requires inference of read length) - isofox_counts = params.use_isofox_exp_counts_cache ? hmf_data.isofox_counts : [] + + // TODO(SW): this must be improved to allow users to set input file, use cache, or generate at runtime; + // currently does not update functions + // NOTE(SW): forcing use of cache for now since this feature is incomplete + + //isofox_counts = params.use_isofox_exp_counts_cache ? hmf_data.isofox_counts : [] + isofox_counts = hmf_data.isofox_counts // Run process ISOFOX( From e4c4237c5bff931e3fbc6f8d3da3957e4fab14ed Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 31 Mar 2023 18:44:00 +1100 Subject: [PATCH 141/562] Small syntax fix in conf/modules.config --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 5f5da099..d44cb941 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -52,7 +52,7 @@ process { mode: params.publish_dir_mode, // NOTE(SW): java.io.File and Nextflow's file do not work here, resorting to string splitting saveAs: { filename -> - if(filename.equals('versions.yml')) { + if (filename.equals('versions.yml')) { return null } else { def tokens = filename.split('[/]') From 45131d81e829ffcd89ffb93cee0242a8e29f158d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 1 Apr 2023 13:30:42 +1100 Subject: [PATCH 142/562] Reduce SV Prep memory in attempt to avoid crashes --- modules/local/svprep/svprep/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index fbadcf37..54dd0144 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -27,7 +27,7 @@ process SVPREP { """ java \\ - -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + -Xmx${Math.round(task.memory.bytes * 0.75)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ From fd31923c899a0fcd34e0625d520500707f3e9905 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 26 Apr 2023 13:12:06 +1000 Subject: [PATCH 143/562] Index SAGE VCFs --- modules/local/sage/germline/main.nf | 13 +++++++++---- modules/local/sage/somatic/main.nf | 19 ++++++++++++------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index cab41d6a..e4f9fa15 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -17,10 +17,10 @@ process SAGE_GERMLINE { path ensembl_data_resources output: - tuple val(meta), path("${meta.tumor_id}.sage.germline.vcf.gz") , emit: vcf - tuple val(meta), path("${meta.tumor_id}.sage.germline.filtered.vcf.gz"), emit: vcf_filtered - tuple val(meta), path('*gene.coverage.tsv') , emit: gene_coverage, optional: true - path 'versions.yml' , emit: versions + tuple val(meta), path('*.sage.germline.vcf.gz'), path('*.sage.germline.vcf.gz.tbi') , emit: vcf + tuple val(meta), path('*.sage.germline.filtered.vcf.gz'), path('*.sage.germline.filtered.vcf.gz.tbi'), emit: vcf_filtered + tuple val(meta), path('*gene.coverage.tsv') , emit: gene_coverage, optional: true + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -57,6 +57,9 @@ process SAGE_GERMLINE { bcftools view -f 'PASS' -o ${meta.tumor_id}.sage.germline.filtered.vcf.gz ${meta.tumor_id}.sage.germline.vcf.gz + bcftools index -t ${meta.tumor_id}.sage.germline.vcf.gz + bcftools index -t ${meta.tumor_id}.sage.germline.filtered.vcf.gz + cat <<-END_VERSIONS > versions.yml "${task.process}": sage: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*Sage version: //') @@ -66,7 +69,9 @@ process SAGE_GERMLINE { stub: """ touch "${meta.tumor_id}.sage.germline.vcf.gz" + touch "${meta.tumor_id}.sage.germline.vcf.gz.tbi" touch "${meta.tumor_id}.sage.germline.filtered.vcf.gz" + touch "${meta.tumor_id}.sage.germline.filtered.vcf.gz.tbi" touch "${meta.tumor_id}.gene.coverage.tsv" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 60f14ae0..94f57ead 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -19,13 +19,13 @@ process SAGE_SOMATIC { path ensembl_data_resources output: - tuple val(meta), path("${meta.tumor_id}.sage.somatic.vcf.gz") , emit: vcf - tuple val(meta), path("${meta.tumor_id}.sage.somatic.filtered.vcf.gz"), emit: vcf_filtered - tuple val(meta), path("${meta.tumor_id}.sage.bqr.png") , emit: tumor_bqr_png, optional: true - tuple val(meta), path("${meta.normal_id}.sage.bqr.png") , emit: normal_bqr_png, optional: true - path '*gene.coverage.tsv' , emit: gene_coverage, optional: true - path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true - path 'versions.yml' , emit: versions + tuple val(meta), path('*.sage.somatic.vcf.gz'), path('*.sage.somatic.vcf.gz.tbi') , emit: vcf + tuple val(meta), path('*.sage.somatic.filtered.vcf.gz'), path('*.sage.somatic.filtered.vcf.gz.tbi'), emit: vcf_filtered + tuple val(meta), path("${meta.tumor_id}.sage.bqr.png") , emit: tumor_bqr_png, optional: true + tuple val(meta), path("${meta.normal_id}.sage.bqr.png") , emit: normal_bqr_png, optional: true + path '*gene.coverage.tsv' , emit: gene_coverage, optional: true + path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -56,6 +56,9 @@ process SAGE_SOMATIC { bcftools view -f 'PASS' -o ${meta.tumor_id}.sage.somatic.filtered.vcf.gz ${meta.tumor_id}.sage.somatic.vcf.gz + bcftools index -t ${meta.tumor_id}.sage.somatic.vcf.gz + bcftools index -t ${meta.tumor_id}.sage.somatic.filtered.vcf.gz + cat <<-END_VERSIONS > versions.yml "${task.process}": sage: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*Sage version: //') @@ -65,7 +68,9 @@ process SAGE_SOMATIC { stub: """ touch "${meta.tumor_id}.sage.somatic.vcf.gz" + touch "${meta.tumor_id}.sage.somatic.vcf.gz.tbi" touch "${meta.tumor_id}.sage.somatic.filtered.vcf.gz" + touch "${meta.tumor_id}.sage.somatic.filtered.vcf.gz.tbi" touch "${meta.tumor_id}.sage.bqr.png" touch "${meta.normal_id}.sage.bqr.png" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml From 6553d2b6a4e8ca41cdd5e7b5ca6bfcc899eaaac6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 26 Apr 2023 13:14:23 +1000 Subject: [PATCH 144/562] =?UTF-8?q?Bump=20SV=20Prep=20version:=201.0.1=20?= =?UTF-8?q?=E2=86=92=201.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/svprep/Dockerfile | 2 +- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/depth_annotator/main.nf | 2 +- modules/local/svprep/preprocess/main.nf | 2 +- modules/local/svprep/svprep/main.nf | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile index f0ed272f..bd69fcc1 100644 --- a/modules/local/svprep/Dockerfile +++ b/modules/local/svprep/Dockerfile @@ -5,7 +5,7 @@ USER root RUN \ mkdir -p /opt/svprep/ && \ - wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.0.1/sv-prep_v1.0.1.jar' + wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.1/sv-prep_v1.1.jar' COPY assets/gridss.svprep /opt/svprep/gridss_svprep RUN \ diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 01cd029b..e9771f73 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -2,7 +2,7 @@ process ASSEMBLE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.0.1--0' + container 'docker.io/scwatts/svprep:1.1--0' input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 1c860421..7882d6e1 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -2,7 +2,7 @@ process CALL { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.0.1--0' + container 'docker.io/scwatts/svprep:1.1--0' input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 164eef05..03185365 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -2,7 +2,7 @@ process DEPTH_ANNOTATOR { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.0.1--0' + container 'docker.io/scwatts/svprep:1.1--0' input: tuple val(meta), path(bams), path(bais), path(vcf), val(labels) diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 5bfcf361..7043a5a8 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -2,7 +2,7 @@ process PREPROCESS { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.0.1--0' + container 'docker.io/scwatts/svprep:1.1--0' input: tuple val(meta), path(bam), path(bam_filtered) diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 54dd0144..d21dbfa1 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -2,7 +2,7 @@ process SVPREP { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.0.1--0' + container 'docker.io/scwatts/svprep:1.1--0' input: tuple val(meta), path(bam), path(bai), path(junctions) From 3782d95a0d84820410f86b0c41251fc02eb00e16 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 26 Apr 2023 13:26:18 +1000 Subject: [PATCH 145/562] Refactor into subworkflows --- lib/Constants.groovy | 12 +- main.nf | 4 +- modules/local/gripss/germline/main.nf | 4 +- modules/local/gripss/germline/meta.yml | 8 +- modules/local/gripss/somatic/main.nf | 4 +- modules/local/gripss/somatic/meta.yml | 6 +- modules/local/purple/main.nf | 7 +- modules/local/purple/meta.yml | 16 +- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/depth_annotator/main.nf | 2 +- modules/local/svprep/preprocess/main.nf | 2 +- subworkflows/local/amber_profiling.nf | 51 + subworkflows/local/bamtools_metrics.nf | 117 ++ subworkflows/local/cobalt_profiling.nf | 49 + subworkflows/local/cuppa_prediction.nf | 103 ++ .../local/{gridss.nf => gridss_calling.nf} | 39 +- ...dss_svprep.nf => gridss_svprep_calling.nf} | 38 +- subworkflows/local/gripss.nf | 66 - subworkflows/local/gripss_filtering.nf | 87 ++ .../local/{lilac.nf => lilac_calling.nf} | 85 +- subworkflows/local/linx.nf | 66 - subworkflows/local/linx_annotation.nf | 101 ++ subworkflows/local/linx_plotting.nf | 69 + subworkflows/local/orange_reporting.nf | 189 +++ subworkflows/local/pave.nf | 62 - subworkflows/local/pave_annotation.nf | 107 ++ subworkflows/local/purple_calling.nf | 107 ++ subworkflows/local/sage.nf | 66 - subworkflows/local/sage_calling.nf | 87 ++ subworkflows/local/virusbreakend_calling.nf | 121 ++ workflows/oncoanalyser.nf | 1319 ----------------- workflows/wgts.nf | 789 ++++++++++ 33 files changed, 2126 insertions(+), 1661 deletions(-) create mode 100644 subworkflows/local/amber_profiling.nf create mode 100644 subworkflows/local/bamtools_metrics.nf create mode 100644 subworkflows/local/cobalt_profiling.nf create mode 100644 subworkflows/local/cuppa_prediction.nf rename subworkflows/local/{gridss.nf => gridss_calling.nf} (81%) rename subworkflows/local/{gridss_svprep.nf => gridss_svprep_calling.nf} (89%) delete mode 100644 subworkflows/local/gripss.nf create mode 100644 subworkflows/local/gripss_filtering.nf rename subworkflows/local/{lilac.nf => lilac_calling.nf} (72%) delete mode 100644 subworkflows/local/linx.nf create mode 100644 subworkflows/local/linx_annotation.nf create mode 100644 subworkflows/local/linx_plotting.nf create mode 100644 subworkflows/local/orange_reporting.nf delete mode 100644 subworkflows/local/pave.nf create mode 100644 subworkflows/local/pave_annotation.nf create mode 100644 subworkflows/local/purple_calling.nf delete mode 100644 subworkflows/local/sage.nf create mode 100644 subworkflows/local/sage_calling.nf create mode 100644 subworkflows/local/virusbreakend_calling.nf delete mode 100644 workflows/oncoanalyser.nf create mode 100644 workflows/wgts.nf diff --git a/lib/Constants.groovy b/lib/Constants.groovy index ffdf34a1..c8f91a71 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -47,8 +47,8 @@ class Constants { BAMTOOLS_TXT, COBALT_DIR, GRIDSS_VCF, - GRIPSS_HARD_VCF, - GRIPSS_SOFT_VCF, + GRIPSS_VCF, + GRIPSS_UNFILTERED_VCF, ISOFOX_DIR, LILAC_DIR, LINX_ANNO_DIR, @@ -103,10 +103,10 @@ class Constants { GRIDSS_VCF: [FileType.GRIDSS_VCF, SampleType.TUMOR_NORMAL, SequenceType.WGS], - GRIPSS_HARD_VCF_TUMOR: [FileType.GRIPSS_HARD_VCF, SampleType.TUMOR, SequenceType.WGS], - GRIPSS_SOFT_VCF_TUMOR: [FileType.GRIPSS_SOFT_VCF, SampleType.TUMOR, SequenceType.WGS], - GRIPSS_HARD_VCF_NORMAL: [FileType.GRIPSS_HARD_VCF, SampleType.NORMAL, SequenceType.WGS], - GRIPSS_SOFT_VCF_NORMAL: [FileType.GRIPSS_SOFT_VCF, SampleType.NORMAL, SequenceType.WGS], + GRIPSS_VCF_TUMOR: [FileType.GRIPSS_VCF, SampleType.TUMOR, SequenceType.WGS], + GRIPSS_VCF_NORMAL: [FileType.GRIPSS_VCF, SampleType.NORMAL, SequenceType.WGS], + GRIPSS_UNFILTERED_VCF_TUMOR: [FileType.GRIPSS_UNFILTERED_VCF, SampleType.TUMOR, SequenceType.WGS], + GRIPSS_UNFILTERED_VCF_NORMAL: [FileType.GRIPSS_UNFILTERED_VCF, SampleType.NORMAL, SequenceType.WGS], PURPLE_DIR: [FileType.PURPLE_DIR, SampleType.TUMOR_NORMAL, SequenceType.WGS], diff --git a/main.nf b/main.nf index d653bb03..76e85b33 100644 --- a/main.nf +++ b/main.nf @@ -39,13 +39,13 @@ WorkflowMain.initialise(workflow, params, log) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { ONCOANALYSER } from './workflows/oncoanalyser' +include { WGTS } from './workflows/wgts' // // WORKFLOW: Run main nf-core/oncoanalyser analysis pipeline // workflow NFCORE_ONCOANALYSER { - ONCOANALYSER() + WGTS() } /* diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 457bcec1..b10df71f 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -15,8 +15,8 @@ process GRIPSS_GERMLINE { path repeatmasker_annotations output: - tuple val(meta), path('*gripss.filtered.germline.vcf.gz'), path('*gripss.filtered.germline.vcf.gz.tbi'), emit: vcf_hard - tuple val(meta), path('*.gripss.germline.vcf.gz'), path('*.gripss.germline.vcf.gz.tbi') , emit: vcf_soft + tuple val(meta), path('*gripss.filtered.germline.vcf.gz'), path('*gripss.filtered.germline.vcf.gz.tbi'), emit: vcf + tuple val(meta), path('*.gripss.germline.vcf.gz'), path('*.gripss.germline.vcf.gz.tbi') , emit: vcf_unfiltered path 'versions.yml' , emit: versions when: diff --git a/modules/local/gripss/germline/meta.yml b/modules/local/gripss/germline/meta.yml index 6febcdb0..bca56b20 100644 --- a/modules/local/gripss/germline/meta.yml +++ b/modules/local/gripss/germline/meta.yml @@ -52,13 +52,13 @@ output: description: | Groovy Map containing sample information e.g. [id: 'sample_id', normal_id: 'normal_name'] - - vcf_hard: + - vcf: type: list - description: Hard filtered VCF file and index file + description: Filtered VCF file and index file pattern: "*.{vcf.gz,vcf.gz.tbi}" - - vcf_soft: + - vcf_unfiltered: type: list - description: Soft filtered VCF file and index file + description: Unfiltered VCF file and index file pattern: "*.{vcf.gz,vcf.gz.tbi}" - versions: type: file diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index a4bbf255..a3746e28 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -15,8 +15,8 @@ process GRIPSS_SOMATIC { path repeatmasker_annotations output: - tuple val(meta), path('*.gripss.filtered.somatic.vcf.gz'), path('*.gripss.filtered.somatic.vcf.gz.tbi'), emit: vcf_hard - tuple val(meta), path('*.gripss.somatic.vcf.gz'), path('*.gripss.somatic.vcf.gz.tbi') , emit: vcf_soft + tuple val(meta), path('*.gripss.filtered.somatic.vcf.gz'), path('*.gripss.filtered.somatic.vcf.gz.tbi'), emit: vcf + tuple val(meta), path('*.gripss.somatic.vcf.gz'), path('*.gripss.somatic.vcf.gz.tbi') , emit: vcf_unfiltered path 'versions.yml' , emit: versions when: diff --git a/modules/local/gripss/somatic/meta.yml b/modules/local/gripss/somatic/meta.yml index 76d968dd..a6ff96b7 100644 --- a/modules/local/gripss/somatic/meta.yml +++ b/modules/local/gripss/somatic/meta.yml @@ -52,13 +52,13 @@ output: description: | Groovy Map containing sample information e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - - vcf_hard: + - vcf: type: list description: Hard filtered VCF file and index file pattern: "*.{vcf.gz,vcf.gz.tbi}" - - vcf_soft: + - vcf_unfiltered: type: list - description: Soft filtered VCF file and index file + description: Unfiltered VCF file and index file pattern: "*.{vcf.gz,vcf.gz.tbi}" - versions: type: file diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 268882ba..3238da3c 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -5,7 +5,7 @@ process PURPLE { container 'docker.io/scwatts/purple:3.7.1--0' input: - tuple val(meta), path(amber), path(cobalt), path(sv_hard_vcf), path(sv_hard_vcf_index), path(sv_soft_vcf), path(sv_soft_vcf_index), path(smlv_tumor_vcf), path(smlv_normal_vcf) + tuple val(meta), path(amber), path(cobalt), path(sv_vcf), path(sv_vcf_index), path(sv_unfiltered_vcf), path(sv_unfiltered_vcf_index), path(smlv_tumor_vcf), path(smlv_normal_vcf) path genome_fasta path genome_fai path genome_dict @@ -27,8 +27,8 @@ process PURPLE { script: def args = task.ext.args ?: '' - def sv_vcf_arg = sv_hard_vcf ? "-structural_vcf ${sv_hard_vcf}" : '' - def sv_lowconf_vcf_fp = sv_soft_vcf ? "-sv_recovery_vcf ${sv_soft_vcf}" : '' + def sv_vcf_arg = sv_vcf ? "-structural_vcf ${sv_vcf}" : '' + def sv_lowconf_vcf_fp = sv_unfiltered_vcf ? "-sv_recovery_vcf ${sv_unfiltered_vcf}" : '' def smlv_tumor_vcf_fp = smlv_tumor_vcf ?: '' def smlv_normal_vcf_fp = smlv_normal_vcf ?: '' @@ -91,6 +91,7 @@ process PURPLE { """ mkdir purple/ touch purple/${meta.tumor_id}.purple.cnv.gene.tsv + touch purple/${meta.tumor_id}.purple.cnv.somatic.tsv touch purple/${meta.tumor_id}.purple.driver.catalog.germline.tsv touch purple/${meta.tumor_id}.purple.driver.catalog.somatic.tsv touch purple/${meta.tumor_id}.purple.germline.vcf.gz diff --git a/modules/local/purple/meta.yml b/modules/local/purple/meta.yml index 6df54e8e..e88b0327 100644 --- a/modules/local/purple/meta.yml +++ b/modules/local/purple/meta.yml @@ -24,21 +24,21 @@ input: - cobalt: type: directory description: COBALT output directory - - sv_hard_vcf: + - sv_vcf: type: file - description: GRIPSS hard filtered VCF file + description: GRIPSS VCF file pattern: "*.{vcf.gz}" - - sv_hard_vcf_index: + - sv_vcf_index: type: file - description: GRIPSS hard filtered VCF index file + description: GRIPSS VCF index file pattern: "*.{vcf.gz.tbi}" - - sv_soft_vcf: + - sv_unfiltered_vcf: type: file - description: GRIPSS soft filtered VCF file + description: GRIPSS unfiltered VCF file pattern: "*.{vcf.gz}" - - sv_soft_vcf_index: + - sv_unfiltered_vcf_index: type: file - description: GRIPSS soft filtered VCF index file + description: GRIPSS unfiltered VCF index file pattern: "*.{vcf.gz.tbi}" - smlv_tumor_vcf: type: file diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index e9771f73..4bd813e7 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -1,4 +1,4 @@ -process ASSEMBLE { +process GRIDSS_ASSEMBLE { tag "${meta.id}" label 'process_medium' diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 7882d6e1..f99b6e98 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -1,4 +1,4 @@ -process CALL { +process GRIDSS_CALL { tag "${meta.id}" label 'process_medium' diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 03185365..3a104e09 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -1,4 +1,4 @@ -process DEPTH_ANNOTATOR { +process SVPREP_DEPTH_ANNOTATOR { tag "${meta.id}" label 'process_medium' diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 7043a5a8..512e13c5 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -1,4 +1,4 @@ -process PREPROCESS { +process GRIDSS_PREPROCESS { tag "${meta.id}" label 'process_medium' diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf new file mode 100644 index 00000000..0248a0ca --- /dev/null +++ b/subworkflows/local/amber_profiling.nf @@ -0,0 +1,51 @@ +// +// XXX +// +import Utils + +include { AMBER } from '../../modules/local/amber/main' + +workflow AMBER_PROFILING { + take: + // Sample data + ch_inputs + + // Reference data + ref_data_genome_version + ref_data_heterozygous_sites + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Select input sources + // channel: [val(meta_amber), tumor_bam_wgs, normal_bam_wgs, tumor_bai_wgs, normal_bai_wgs] + ch_amber_inputs = ch_inputs + .map { meta -> + def meta_amber = [ + key: meta.id, + id: meta.id, + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), + ] + def tumor_bam = Utils.getTumorWgsBam(meta) + def normal_bam = Utils.getNormalWgsBam(meta) + [meta_amber, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] + } + + // Run process + AMBER( + ch_amber_inputs, + ref_data_genome_version, + ref_data_heterozygous_sites, + ) + + // Set outputs, restoring original meta + ch_outputs = WorkflowOncoanalyser.restoreMeta(AMBER.out.amber_dir, ch_inputs) + ch_versions = ch_versions.mix(AMBER.out.versions) + + emit: + amber_dir = ch_outputs // channel: [val(meta), amber_dir] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/bamtools_metrics.nf b/subworkflows/local/bamtools_metrics.nf new file mode 100644 index 00000000..0769a57a --- /dev/null +++ b/subworkflows/local/bamtools_metrics.nf @@ -0,0 +1,117 @@ +// +// XXX +// +import Constants +import Utils + +include { BAMTOOLS } from '../../modules/local/bamtools/main' + +workflow BAMTOOLS_METRICS { + take: + // Sample data + ch_inputs + + // Reference data + ref_data_genome_fasta + ref_data_genome_version + + // Params + run + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Select input sources + // NOTE(SW): CUPPA only requires metrics for the tumor sample in the upstream + // process Virus Interpreter but ORANGE currently requires metrics for both tumor + // and normal sample + // channel: [val(meta_bamtools), bam, bai] + ch_bamtools_inputs_all = ch_inputs + .flatMap { meta -> + def sample_types + if (run.orange) { + sample_types = [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL] + } else { + sample_types = [Constants.SampleType.TUMOR] + } + + return sample_types + .collect { sample_type -> + def bam = meta.get([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) + def sample_name = meta.get(['sample_name', sample_type, Constants.SequenceType.WGS]) + def meta_bamtools = [ + key: meta.id, + id: sample_name, + // NOTE(SW): must use string representation for caching purposes + sample_type_str: sample_type.name(), + ] + return [meta_bamtools, bam, "${bam}.bai"] + } + } + + // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples + // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent + // on any process + // channel: [val(meta_bamtools), bam, bai] + ch_bamtools_inputs = ch_bamtools_inputs_all + .map { [it[1..-1], it[0]] } + .groupTuple() + .map { filepaths, meta_bamtools -> + def (keys, sample_names, sample_type_strs) = meta_bamtools + .collect { + [it.key, it.id, it.sample_type_str] + } + .transpose() + + def sample_type_strs_unique = sample_type_strs.unique(false) + assert sample_type_strs_unique.size() == 1 + def sample_type_str = sample_type_strs_unique[0] + + def meta_bamtools_new = [ + keys: keys, + id: sample_names.join('__'), + id_simple: keys.join('__'), + sample_type_str: sample_type_str, + ] + return [meta_bamtools_new, *filepaths] + } + + // Run process + BAMTOOLS( + ch_bamtools_inputs, + ref_data_genome_fasta, + ref_data_genome_version, + ) + + // Set outputs, process outputs and restore original meta + ch_versions = ch_versions.mix(BAMTOOLS.out.versions) + + // Replicate outputs to reverse unique operation + // channel: [val(meta_bamtools_individual), sample_type_str, metrics] + ch_bamtools_out_individual = BAMTOOLS.out.metrics + .flatMap { meta_bamtools_shared, metrics -> + meta_bamtools_shared.keys.collect { key -> + return [meta_bamtools_shared + [key: key], meta_bamtools_shared.sample_type_str, metrics] + } + } + + // Set outputs + // channel (somatic): [val(meta), metrics] + // channel (germline): [val(meta), metrics] + ch_outputs = WorkflowOncoanalyser.restoreMeta(ch_bamtools_out_individual, ch_inputs) + .branch { meta, sample_type_str, metrics -> + def sample_type = Utils.getEnumFromString(sample_type_str, Constants.SampleType) + somatic: sample_type == Constants.SampleType.TUMOR + return [meta, metrics] + germline: sample_type == Constants.SampleType.NORMAL + return [meta, metrics] + } + ch_versions = ch_versions.mix(BAMTOOLS.out.versions) + + emit: + somatic = ch_outputs.somatic // channel: [val(meta), metrics] + germline = ch_outputs.germline // channel: [val(meta), metrics] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf new file mode 100644 index 00000000..132671c1 --- /dev/null +++ b/subworkflows/local/cobalt_profiling.nf @@ -0,0 +1,49 @@ +// +// XXX +// +import Utils + +include { COBALT } from '../../modules/local/cobalt/main' + +workflow COBALT_PROFILING { + take: + // Sample data + ch_inputs + + // Reference data + ref_data_gc_profile + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Select input sources + // channel: [meta_cobalt, tumor_bam_wgs, normal_bam_wgs, tumor_bai_wgs, normal_bai_wgs] + ch_cobalt_inputs = ch_inputs + .map { meta -> + def meta_cobalt = [ + key: meta.id, + id: meta.id, + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), + ] + def tumor_bam = Utils.getTumorWgsBam(meta) + def normal_bam = Utils.getNormalWgsBam(meta) + return [meta_cobalt, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] + } + + // Run process + COBALT( + ch_cobalt_inputs, + ref_data_gc_profile, + ) + + // Set outputs, restoring original meta + ch_outputs = WorkflowOncoanalyser.restoreMeta(COBALT.out.cobalt_dir, ch_inputs) + ch_versions = ch_versions.mix(COBALT.out.versions) + + emit: + cobalt_dir = ch_outputs // channel: [val(meta), cobalt_dir] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf new file mode 100644 index 00000000..4a15b9b5 --- /dev/null +++ b/subworkflows/local/cuppa_prediction.nf @@ -0,0 +1,103 @@ +// +// XXX +// +import Constants + +include { CUPPA_CLASSIFIER as CLASSIFIER } from '../../modules/local/cuppa/classifier/main' +include { CUPPA_VISUALISER as VISUALISER } from '../../modules/local/cuppa/visualiser/main' + +workflow CUPPA_PREDICTION { + take: + // Sample data + ch_inputs + ch_inputs_wts_absent + ch_isofox + ch_purple + ch_linx + ch_virusinterpreter + + // Reference data + ref_data_genome_version + ref_data_cuppa_resources + + // Parameters + run + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Select input sources + // channel: [val(meta), isofox_dir] + ch_cuppa_inputs_isofox = Channel.empty() + if (run.isofox) { + // Take Isofox output and supplement with placeholders for missing; i.e. allow optional + ch_cuppa_inputs_isofox = ch_cuppa_inputs_isofox + .mix( + ch_isofox, + ch_inputs_wts_absent.map { meta -> [meta, []] }, + ) + } else { + ch_cuppa_inputs_isofox = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX, type: 'optional') + } + + // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter] + ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( + ch_cuppa_inputs_isofox, + run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional'), + run.linx ? ch_linx : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR, type: 'optional'), + run.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), + flatten_mode: 'nonrecursive', + ) + + // Create inputs and create process-specific meta + // channel: [val(meta_cuppa), isofox_dir, purple_dir, linx_dir, virusinterpreter] + ch_cuppa_inputs = ch_cuppa_inputs_source + .map { data -> + def meta = data[0] + def meta_cuppa = [key: meta.id] + + def sample_name_wgs = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) + def sample_name_wts = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + + if (sample_name_wgs && sample_name_wts) { + meta_cuppa.id = sample_name_wgs + meta_cuppa.id_wts = sample_name_wts + } else if (sample_name_wgs) { + meta_cuppa.id = sample_name_wgs + } else if (sample_name_wts) { + meta_cuppa.id = sample_name_wts + } else { + log.error "ERROR: no sample name for: ${meta}" + System.exit(1) + } + + return [meta_cuppa, *data[1..-1]] + } + + CLASSIFIER( + ch_cuppa_inputs, + ref_data_genome_version, + ref_data_cuppa_resources, + ) + + VISUALISER( + CLASSIFIER.out.csv, + ) + + // Set outputs, restoring original meta + ch_csv = WorkflowOncoanalyser.restoreMeta(CLASSIFIER.out.csv, ch_inputs) + ch_summary_plot = WorkflowOncoanalyser.restoreMeta(VISUALISER.out.summary_plot, ch_inputs) + ch_feature_plot = WorkflowOncoanalyser.restoreMeta(VISUALISER.out.feature_plot, ch_inputs) + ch_versions = ch_versions.mix( + VISUALISER.out.versions, + CLASSIFIER.out.versions, + ) + + emit: + csv = ch_csv + summary_plot = ch_summary_plot + feature_plot = ch_feature_plot + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/gridss.nf b/subworkflows/local/gridss_calling.nf similarity index 81% rename from subworkflows/local/gridss.nf rename to subworkflows/local/gridss_calling.nf index d4d71371..b6a1da96 100644 --- a/subworkflows/local/gridss.nf +++ b/subworkflows/local/gridss_calling.nf @@ -4,13 +4,13 @@ import Constants import Utils -include { GRIDSS_ASSEMBLE } from '../../modules/local/gridss/assemble/main' -include { GRIDSS_CALL } from '../../modules/local/gridss/call/main' -include { GRIDSS_PREPROCESS } from '../../modules/local/gridss/preprocess/main' +include { GRIDSS_ASSEMBLE as ASSEMBLE } from '../../modules/local/gridss/assemble/main' +include { GRIDSS_CALL as CALL } from '../../modules/local/gridss/call/main' +include { GRIDSS_PREPROCESS as PREPROCESS } from '../../modules/local/gridss/preprocess/main' -workflow GRIDSS { +workflow GRIDSS_CALLING { take: - ch_inputs // channel: [val(meta), tumor_bam, normal_bam] + ch_inputs // channel: [val(meta)] gridss_config // file: /path/to/gridss_config (optional) ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai @@ -24,9 +24,16 @@ workflow GRIDSS { // Channel for version.yml files ch_versions = Channel.empty() + ch_inputs_bam_bai = ch_inputs + .map { meta -> + def tumor_bam = Utils.getTumorWgsBam(meta) + def normal_bam = Utils.getNormalWgsBam(meta) + [meta, tumor_bam, normal_bam] + } + // Build a channel of individual BAMs for preprocessing // channel: [val(meta_gridss), bam] - ch_preprocess_inputs = ch_inputs + ch_preprocess_inputs = ch_inputs_bam_bai .flatMap { meta, tbam, nbam -> def sample_types = [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL] sample_types @@ -50,7 +57,7 @@ workflow GRIDSS { } // Preprocess reads - GRIDSS_PREPROCESS( + PREPROCESS( ch_preprocess_inputs, gridss_config, ref_data_genome_fasta, @@ -60,13 +67,13 @@ workflow GRIDSS { ref_data_genome_bwa_index_image, ref_data_genome_gridss_index, ) - ch_versions = ch_versions.mix(GRIDSS_PREPROCESS.out.versions) + ch_versions = ch_versions.mix(PREPROCESS.out.versions) // Gather BAMs and outputs from preprocessing for each tumor/normal set // channel: [subject_id, [[val(meta_gridss), bam, preprocess_dir], ...]] ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( ch_preprocess_inputs, - GRIDSS_PREPROCESS.out.preprocess_dir, + PREPROCESS.out.preprocess_dir, ) .map { [it[0].subject_id, it] } .groupTuple(size: 2) @@ -82,7 +89,7 @@ workflow GRIDSS { } // Assemble variants - GRIDSS_ASSEMBLE( + ASSEMBLE( ch_assemble_inputs, gridss_config, ref_data_genome_fasta, @@ -93,13 +100,13 @@ workflow GRIDSS { ref_data_genome_gridss_index, ref_data_gridss_blacklist, ) - ch_versions = ch_versions.mix(GRIDSS_ASSEMBLE.out.versions) + ch_versions = ch_versions.mix(ASSEMBLE.out.versions) // Prepare inputs for variant calling // channel: [val(meta_gridss), [bams], assemble_dir, [labels]] ch_call_inputs = WorkflowOncoanalyser.groupByMeta( ch_assemble_inputs, - GRIDSS_ASSEMBLE.out.assemble_dir, + ASSEMBLE.out.assemble_dir, flatten: false, ) .map { data -> @@ -110,7 +117,7 @@ workflow GRIDSS { } // Call variants - GRIDSS_CALL( + CALL( ch_call_inputs, gridss_config, ref_data_genome_fasta, @@ -121,13 +128,13 @@ workflow GRIDSS { ref_data_genome_gridss_index, ref_data_gridss_blacklist, ) - ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) + ch_versions = ch_versions.mix(CALL.out.versions) // Reunite final VCF with the corresponding input meta object ch_out = Channel.empty() .concat( - ch_inputs.map { meta, tbam, nbam -> [meta.id, meta] }, - GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + ch_inputs_bam_bai.map { meta, tbam, nbam -> [meta.id, meta] }, + CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .groupTuple(size: 2) .map { id, other -> other.flatten() } diff --git a/subworkflows/local/gridss_svprep.nf b/subworkflows/local/gridss_svprep_calling.nf similarity index 89% rename from subworkflows/local/gridss_svprep.nf rename to subworkflows/local/gridss_svprep_calling.nf index 10d85355..6eb980bd 100644 --- a/subworkflows/local/gridss_svprep.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -4,14 +4,14 @@ // import Utils -include { ASSEMBLE as GRIDSS_ASSEMBLE } from '../../modules/local/svprep/assemble/main' -include { CALL as GRIDSS_CALL } from '../../modules/local/svprep/call/main' -include { PREPROCESS as GRIDSS_PREPROCESS } from '../../modules/local/svprep/preprocess/main' -include { SVPREP as SVPREP_NORMAL } from '../../modules/local/svprep/svprep/main' -include { SVPREP as SVPREP_TUMOR } from '../../modules/local/svprep/svprep/main' -include { DEPTH_ANNOTATOR as SVPREP_DEPTH_ANNOTATOR } from '../../modules/local/svprep/depth_annotator/main' - -workflow GRIDSS_SVPREP { +include { GRIDSS_ASSEMBLE as ASSEMBLE } from '../../modules/local/svprep/assemble/main' +include { GRIDSS_CALL as CALL } from '../../modules/local/svprep/call/main' +include { SVPREP_DEPTH_ANNOTATOR as DEPTH_ANNOTATOR } from '../../modules/local/svprep/depth_annotator/main' +include { GRIDSS_PREPROCESS as PREPROCESS } from '../../modules/local/svprep/preprocess/main' +include { SVPREP as SVPREP_NORMAL } from '../../modules/local/svprep/svprep/main' +include { SVPREP as SVPREP_TUMOR } from '../../modules/local/svprep/svprep/main' + +workflow GRIDSS_SVPREP_CALLING { take: ch_inputs // channel: [val(meta)] gridss_config // file: /path/to/gridss_config (optional) @@ -103,7 +103,7 @@ workflow GRIDSS_SVPREP { ) // Preprocess reads - GRIDSS_PREPROCESS( + PREPROCESS( ch_preprocess_inputs, gridss_config, ref_data_genome_fasta, @@ -113,13 +113,13 @@ workflow GRIDSS_SVPREP { ref_data_genome_bwa_index_image, ref_data_genome_gridss_index, ) - ch_versions = ch_versions.mix(GRIDSS_PREPROCESS.out.versions) + ch_versions = ch_versions.mix(PREPROCESS.out.versions) // Gather BAMs and outputs from preprocessing for each tumor/normal set // channel: [key, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( ch_preprocess_inputs, - GRIDSS_PREPROCESS.out.preprocess_dir, + PREPROCESS.out.preprocess_dir, ) .map { [it[0].key, it] } .groupTuple(size: 2) @@ -141,7 +141,7 @@ workflow GRIDSS_SVPREP { } // Assemble variants - GRIDSS_ASSEMBLE( + ASSEMBLE( ch_assemble_inputs, gridss_config, ref_data_genome_fasta, @@ -152,13 +152,13 @@ workflow GRIDSS_SVPREP { ref_data_genome_gridss_index, ref_data_gridss_blocklist, ) - ch_versions = ch_versions.mix(GRIDSS_ASSEMBLE.out.versions) + ch_versions = ch_versions.mix(ASSEMBLE.out.versions) // Prepare inputs for variant calling // channel: [val(meta_gridss), [bams], [bams_filtered], assemble_dir, [labels]] ch_call_inputs = WorkflowOncoanalyser.groupByMeta( ch_assemble_inputs, - GRIDSS_ASSEMBLE.out.assemble_dir, + ASSEMBLE.out.assemble_dir, flatten: false, ) .map { data -> @@ -169,7 +169,7 @@ workflow GRIDSS_SVPREP { } // Call variants - GRIDSS_CALL( + CALL( ch_call_inputs, gridss_config, ref_data_genome_fasta, @@ -180,13 +180,13 @@ workflow GRIDSS_SVPREP { ref_data_genome_gridss_index, ref_data_gridss_blocklist, ) - ch_versions = ch_versions.mix(GRIDSS_CALL.out.versions) + ch_versions = ch_versions.mix(CALL.out.versions) // Prepare inputs for depth annotation, restore original meta // channel: [val(meta_svprep), [bams], [bais], vcf, [labels]] ch_depth_inputs = WorkflowOncoanalyser.groupByMeta( ch_inputs.map { meta -> [meta.id, meta] }, - GRIDSS_CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .map { id, meta, vcf -> def tbam = Utils.getTumorWgsBam(meta) @@ -202,7 +202,7 @@ workflow GRIDSS_SVPREP { } // Add depth annotations to SVs - SVPREP_DEPTH_ANNOTATOR( + DEPTH_ANNOTATOR( ch_depth_inputs, ref_data_genome_fasta, ref_data_genome_version, @@ -212,7 +212,7 @@ workflow GRIDSS_SVPREP { ch_out = Channel.empty() .concat( ch_inputs.map { meta -> [meta.id, meta] }, - SVPREP_DEPTH_ANNOTATOR.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + DEPTH_ANNOTATOR.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .groupTuple(size: 2) .map { id, other -> other.flatten() } diff --git a/subworkflows/local/gripss.nf b/subworkflows/local/gripss.nf deleted file mode 100644 index 6a80f822..00000000 --- a/subworkflows/local/gripss.nf +++ /dev/null @@ -1,66 +0,0 @@ -// -// GRIPSS performs SV filtering. -// - -include { GRIPSS_GERMLINE } from '../../modules/local/gripss/germline/main' -include { GRIPSS_SOMATIC } from '../../modules/local/gripss/somatic/main' - -workflow GRIPSS { - take: - ch_inputs // channel: [val(meta_gripss), gridss_vcf] - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_version // val: genome version - breakend_pon // file: /path/to/breakend_pon - breakpoint_pon // file: /path/to/breakpoint_pon - known_fusions // file: /path/to/known_fusions - repeatmasker_annotations // file: /path/to/repeatmasker_annotations - - main: - // Channel for version.yml files - ch_versions = Channel.empty() - - // Germline; set correct ID in meta - GRIPSS_GERMLINE( - ch_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, - breakend_pon, - breakpoint_pon, - known_fusions, - repeatmasker_annotations, - ) - ch_versions = ch_versions.mix(GRIPSS_GERMLINE.out.versions) - - // Somatic - GRIPSS_SOMATIC( - ch_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, - breakend_pon, - breakpoint_pon, - known_fusions, - repeatmasker_annotations, - ) - ch_versions = ch_versions.mix(GRIPSS_SOMATIC.out.versions) - - // Pack output - // channel: [val(meta_gripss), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - ch_germline_out = WorkflowOncoanalyser.groupByMeta( - GRIPSS_GERMLINE.out.vcf_hard, - GRIPSS_GERMLINE.out.vcf_soft, - ) - // channel: [val(meta_gripss), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - ch_somatic_out = WorkflowOncoanalyser.groupByMeta( - GRIPSS_SOMATIC.out.vcf_hard, - GRIPSS_SOMATIC.out.vcf_soft, - ) - - emit: - germline = ch_germline_out // channel: [val(meta_gripss), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - somatic = ch_somatic_out // channel: [val(meta_gripss), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - - versions = ch_versions // channel: [versions.yml] -} diff --git a/subworkflows/local/gripss_filtering.nf b/subworkflows/local/gripss_filtering.nf new file mode 100644 index 00000000..715e09f5 --- /dev/null +++ b/subworkflows/local/gripss_filtering.nf @@ -0,0 +1,87 @@ +// +// GRIPSS performs SV filtering. +// + +include { GRIPSS_GERMLINE as GERMLINE } from '../../modules/local/gripss/germline/main' +include { GRIPSS_SOMATIC as SOMATIC } from '../../modules/local/gripss/somatic/main' + +workflow GRIPSS_FILTERING { + take: + // Sample inputs + ch_inputs // channel: [val(meta)] + ch_gridss // channel: [val(meta), gridss_vcf] + + // Reference data + ref_data_genome_fasta // file: /path/to/genome_fasta + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_version // val: genome version + breakend_pon // file: /path/to/breakend_pon + breakpoint_pon // file: /path/to/breakpoint_pon + known_fusions // file: /path/to/known_fusions + repeatmasker_annotations // file: /path/to/repeatmasker_annotations + + // Parameters + run + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Select input source + // channel: [val(meta), gridss_vcf] + ch_gripss_inputs_source = run.gridss ? ch_gridss : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIDSS_VCF) + + // Create inputs and create process-specific meta + // channel: [val(meta_gripss), gridss_vcf] + ch_gripss_inputs = ch_gripss_inputs_source + .filter { it[0] != Constants.META_PLACEHOLDER } + .map { meta, gridss_vcf -> + def meta_gripss = [ + key: meta.id, + id: meta.id, + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), + ] + return [meta_gripss, gridss_vcf] + } + + GERMLINE( + ch_gripss_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_version, + breakend_pon, + breakpoint_pon, + known_fusions, + repeatmasker_annotations, + ) + + SOMATIC( + ch_gripss_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_version, + breakend_pon, + breakpoint_pon, + known_fusions, + repeatmasker_annotations, + ) + + ch_versions = ch_versions.mix( + GERMLINE.out.versions, + SOMATIC.out.versions, + ) + + ch_somatic_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs) + ch_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) + ch_somatic_unfiltered_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_unfiltered, ch_inputs) + ch_germline_unfiltered_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_unfiltered, ch_inputs) + + emit: + somatic = ch_somatic_out // channel: [val(meta), vcf, tbi] + germline = ch_germline_out // channel: [val(meta), vcf, tbi] + somatic_unfiltered = ch_somatic_unfiltered_out // channel: [val(meta), vcf, tbi] + germline_unfiltered = ch_germline_unfiltered_out // channel: [val(meta), vcf, tbi] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/lilac.nf b/subworkflows/local/lilac_calling.nf similarity index 72% rename from subworkflows/local/lilac.nf rename to subworkflows/local/lilac_calling.nf index 03ee581d..6e9af982 100644 --- a/subworkflows/local/lilac.nf +++ b/subworkflows/local/lilac_calling.nf @@ -7,21 +7,77 @@ import Utils include { CUSTOM_EXTRACTCONTIG } from '../../modules/local/custom/lilac_extract_and_index_contig/main' include { CUSTOM_REALIGNREADS } from '../../modules/local/custom/lilac_realign_reads_lilac/main' include { CUSTOM_SLICE } from '../../modules/local/custom/lilac_slice/main' +include { LILAC } from '../../modules/local/lilac/main' -include { LILAC as LILAC_PROCESS } from '../../modules/local/lilac/main' - -workflow LILAC { +workflow LILAC_CALLING { take: - ch_bams // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] - ch_purple_dir // channel: [val(meta), purple_dir] + // Sample data + ch_inputs + ch_inputs_wgs_present + ch_inputs_wgs_absent + ch_inputs_wts_present + ch_inputs_wts_absent + ch_purple + + // Reference data ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_lilac_resource_dir // file: /path/to/lilac_resource_dir/ + // Params + run + main: // Channel for version.yml files ch_versions = Channel.empty() + // Select input sources + // channel: [val(meta), purple_dir] + if (run.purple) { + ch_lilac_inputs_purple = Channel.empty() + .mix( + ch_purple, + ch_inputs_wgs_absent.map { meta -> [meta, []] }, + ) + } else { + ch_lilac_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional') + } + + // Create channel with all available input BAMs + // First obtain WTS BAMs + // channel: [val(meta), wts_bam, wts_bai] + ch_lilac_bams_wts = Channel.empty() + .mix( + ch_inputs_wts_present.map { meta -> + def bam = Utils.getTumorWtsBam(meta) + return [meta, bam, "${bam}.bai"] + }, + ch_inputs_wts_absent.map { meta -> [meta, [], []] }, + ) + + ch_lilac_bams_wgs = Channel.empty() + .mix( + ch_inputs_wgs_present.map { meta -> + def tumor_bam = Utils.getTumorWgsBam(meta) + def normal_bam = Utils.getNormalWgsBam(meta) + [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] + }, + ch_inputs_wgs_absent.map { meta -> [meta, [], [], [], []] }, + ) + + // Combine WGS and WTS BAMs + // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] + ch_lilac_bams = WorkflowOncoanalyser.groupByMeta( + ch_lilac_bams_wts, + ch_lilac_bams_wgs, + flatten_mode: 'nonrecursive', + ) + .map { data -> + def meta = data[0] + def (tbam_wts, tbai_wts, tbam_wgs, nbam_wgs, tbai_wgs, nbai_wgs) = data[1..-1] + return [meta, nbam_wgs, nbai_wgs, tbam_wgs, tbai_wgs, tbam_wts, tbai_wts] + } + // Slice HLA regions ch_slice_bed = ref_data_lilac_resource_dir .map { lilac_dir -> @@ -44,7 +100,7 @@ workflow LILAC { // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used // in Pipeline5, see LilacBamSlicer.java#L115 // channel: [val(meta_lilac), bam, bai, bed] - ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_bams, ch_slice_bed) + ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_lilac_bams, ch_slice_bed) // Isolate meta containing expected file count to use for non-blocking groupTuple later ch_slice_meta_individual = ch_slice_inputs .map { @@ -108,7 +164,7 @@ workflow LILAC { // Restore original meta so we can join with PURPLE directory // channel: [val(meta)] - ch_metas = ch_bams.map { return it[0] } + ch_metas = ch_lilac_bams.map { return it[0] } // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] ch_lilac_inputs_slices = WorkflowOncoanalyser.restoreMeta( ch_slices_organised, @@ -117,7 +173,7 @@ workflow LILAC { // Get inputs from PURPLE // channel: [val(meta), gene_cn] - ch_lilac_inputs_gene_cn = ch_purple_dir + ch_lilac_inputs_gene_cn = ch_purple .map { meta, purple_dir -> if (purple_dir == []) { return [meta, []] @@ -129,7 +185,7 @@ workflow LILAC { } // channel: [val(meta), smlv_vcf] - ch_lilac_inputs_smlv_vcf = ch_purple_dir + ch_lilac_inputs_smlv_vcf = ch_purple .map { meta, purple_dir -> if (purple_dir == []) { return [meta, []] @@ -174,16 +230,19 @@ workflow LILAC { .filter { it != Constants.META_PLACEHOLDER } // Run LILAC - LILAC_PROCESS( + LILAC( ch_lilac_inputs, ref_data_genome_fasta, params.ref_data_genome_version, ref_data_lilac_resource_dir, ) - ch_versions = ch_versions.mix(LILAC_PROCESS.out.versions) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix(LILAC.out.versions) + ch_outputs = WorkflowOncoanalyser.restoreMeta(LILAC.out.lilac_dir, ch_inputs) emit: - results = LILAC_PROCESS.out.lilac_dir // channel: [val(meta_lilac), lilac_dir] + lilac_dir = ch_outputs // channel: [val(meta), lilac_dir] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/linx.nf b/subworkflows/local/linx.nf deleted file mode 100644 index 320f67fa..00000000 --- a/subworkflows/local/linx.nf +++ /dev/null @@ -1,66 +0,0 @@ -// -// Linx is an annotation, interpretation and visualisation tool for structural variants. -// - -include { LINX_GERMLINE } from '../../modules/local/linx/germline/main' -include { LINX_SOMATIC } from '../../modules/local/linx/somatic/main' -include { LINX_VISUALISER } from '../../modules/local/linx/visualiser/main' - -workflow LINX { - take: - ch_linx_germline_inputs // channel: [val(meta), gripss_hard_vcf] - ch_linx_somatic_inputs // channel: [val(meta), purple_dir] - ref_data_genome_version // val: genome version - ref_data_linx_fragile_regions // file: /path/to/linx_fragile_regions - ref_data_linx_lines // file: /path/to/linx_lines - ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ - ref_data_known_fusion_data // file: /path/to/known_fusion_data - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - gene_id_file // file: /path/to/linx_gene_id_file - - main: - // Channel for versions.yml files - ch_versions = Channel.empty() - - // Germline - LINX_GERMLINE( - ch_linx_germline_inputs, - ref_data_genome_version, - ref_data_linx_lines, - ref_data_ensembl_data_resources, - ref_data_driver_gene_panel, - ) - ch_versions = ch_versions.mix(LINX_GERMLINE.out.versions) - - // Somatic - LINX_SOMATIC( - ch_linx_somatic_inputs, - ref_data_genome_version, - ref_data_linx_fragile_regions, - ref_data_linx_lines, - ref_data_ensembl_data_resources, - ref_data_known_fusion_data, - ref_data_driver_gene_panel, - gene_id_file, - ) - ch_versions = ch_versions.mix(LINX_SOMATIC.out.versions) - - LINX_VISUALISER( - LINX_SOMATIC.out.annotation_dir, - ref_data_genome_version, - ref_data_ensembl_data_resources, - ) - ch_versions = ch_versions.mix(LINX_VISUALISER.out.versions) - - // channel: [val(meta), linx_annotation_dir, linx_visualiser_dir] - ch_linx_somatic_out = WorkflowOncoanalyser.groupByMeta( - LINX_SOMATIC.out.annotation_dir, - LINX_VISUALISER.out.visualiser_dir, - ) - - emit: - somatic = ch_linx_somatic_out // channel: [val(meta), linx_annotation_dir, linx_visualiser_dir] - germline = LINX_GERMLINE.out.annotation_dir // channel: [val(meta), linx_annotation_dir] - - versions = ch_versions // channel: [versions.yml] -} diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf new file mode 100644 index 00000000..26eb3325 --- /dev/null +++ b/subworkflows/local/linx_annotation.nf @@ -0,0 +1,101 @@ +// +// Linx is an annotation, interpretation and visualisation tool for structural variants. +// +import Constants +import Utils + +include { LINX_GERMLINE as GERMLINE } from '../../modules/local/linx/germline/main' +include { LINX_SOMATIC as SOMATIC } from '../../modules/local/linx/somatic/main' + +workflow LINX_ANNOTATION { + take: + // Sample data + ch_inputs // channel: [val(meta)] + ch_gripss_germline // channel: [val(meta), vcf] + ch_purple // channel: [val(meta), purple_dir] + + // Reference data + ref_data_genome_version // val: genome version + ref_data_linx_fragile_regions // file: /path/to/linx_fragile_regions + ref_data_linx_lines // file: /path/to/linx_lines + ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + ref_data_known_fusion_data // file: /path/to/known_fusion_data + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + gene_id_file // file: /path/to/linx_gene_id_file + + // Parameters + run + + main: + // Channel for versions.yml files + ch_versions = Channel.empty() + + // Select input sources + // channel: [val(meta), sv_vcf] + if (run.gripss) { + ch_linx_inputs_germline_source = ch_gripss_germline.map { meta, vcf, tbi -> [meta, vcf] } + } else { + ch_linx_inputs_germline_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_TUMOR) + } + + // channel: [val(meta), sv_vcf, purple_dir] + ch_linx_inputs_somatic_source = run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + + // Create inputs and create process-specific meta + // channel: [val(meta_linx), sv_vcf] + ch_linx_inputs_germline = ch_linx_inputs_germline_source + .map { + def meta = it[0] + def meta_linx = [ + key: meta.id, + id: Utils.getNormalWgsSampleName(meta), + ] + return [meta_linx, it[1..-1]] + } + + // channel: [val(meta_linx), purple_dir] + ch_linx_inputs_somatic = ch_linx_inputs_somatic_source + .map { + def meta = it[0] + def meta_linx = [ + key: meta.id, + id: Utils.getTumorWgsSampleName(meta), + ] + return [meta_linx, it[1..-1]] + } + + GERMLINE( + ch_linx_inputs_germline, + ref_data_genome_version, + ref_data_linx_lines, + ref_data_ensembl_data_resources, + ref_data_driver_gene_panel, + ) + + SOMATIC( + ch_linx_inputs_somatic, + ref_data_genome_version, + ref_data_linx_fragile_regions, + ref_data_linx_lines, + ref_data_ensembl_data_resources, + ref_data_known_fusion_data, + ref_data_driver_gene_panel, + gene_id_file, + ) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix( + SOMATIC.out.versions, + GERMLINE.out.versions, + ) + + // channel: [val(meta), linx_annotation_dir] + ch_linx_somatic_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.annotation_dir, ch_inputs) + ch_linx_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.annotation_dir, ch_inputs) + + emit: + somatic = ch_linx_somatic_out // channel: [val(meta), linx_annotation_dir] + germline = ch_linx_germline_out // channel: [val(meta), linx_annotation_dir] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/linx_plotting.nf b/subworkflows/local/linx_plotting.nf new file mode 100644 index 00000000..b407d095 --- /dev/null +++ b/subworkflows/local/linx_plotting.nf @@ -0,0 +1,69 @@ +// +// XXX +// +import Utils + +include { GPGR_LINX as GPGR } from '../../modules/local/gpgr/linx/main' +include { LINX_VISUALISER as VISUALISER } from '../../modules/local/linx/visualiser/main' + +workflow LINX_PLOTTING { + take: + // Sample data + ch_inputs + ch_annotations + + // Reference data + ref_data_genome_version // val: genome version + ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + + main: + // Channel for versions.yml files + ch_versions = Channel.empty() + + // Select input sources + // channel: [val(meta_linx), anno_dir] + ch_linx_visualiser_inputs = ch_annotations + .map { meta, anno_dir -> + def meta_linx = [ + key: meta.id, + id: Utils.getTumorWgsSampleName(meta), + ] + return [meta_linx, anno_dir] + } + + VISUALISER( + ch_linx_visualiser_inputs, + ref_data_genome_version, + ref_data_ensembl_data_resources, + ) + + // Set outputs, restoring original meta + ch_visualiser_out = WorkflowOncoanalyser.restoreMeta(VISUALISER.out.visualiser_dir, ch_inputs) + ch_versions = ch_versions.mix(VISUALISER.out.versions) + + + // Create inputs and create process-specific meta + // channel: [meta(meta_gpgr_linx), anno_dir, vis_dir] + ch_gpgr_linx_inputs = WorkflowOncoanalyser.groupByMeta( + ch_annotations, + ch_visualiser_out, + ) + .map { meta, anno_dir, vis_dir -> + def meta_gpgr_linx = [ + key: meta.id, + id: Utils.getTumorWgsSampleName(meta), + ] + return [meta_gpgr_linx, anno_dir, vis_dir] + } + + GPGR( + ch_gpgr_linx_inputs, + ) + + ch_versions = ch_versions.mix(GPGR.out.versions) + + emit: + visualiser_dir = ch_visualiser_out // channel: [val(meta), visualiser_dir] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf new file mode 100644 index 00000000..2d6d400c --- /dev/null +++ b/subworkflows/local/orange_reporting.nf @@ -0,0 +1,189 @@ +// +// XXX +// +import Constants +import Utils + +include { ORANGE } from '../../modules/local/orange/main' +include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/samtools/flagstat/main' + +workflow ORANGE_REPORTING { + take: + // Sample data + ch_inputs + ch_inputs_wgs + ch_bamtools_somatic + ch_bamtools_germline + ch_chord + ch_lilac + ch_sage_somatic_tumor_bqr + ch_sage_somatic_normal_bqr + ch_sage_germline_coverage + ch_purple + ch_linx_somatic_annotation + ch_linx_somatic_plot + ch_linx_germline_annotation + ch_protect + ch_peach + ch_cuppa + ch_cuppa_feature_plot + ch_cuppa_summary_plot + ch_virusinterpreter + + // Reference data + ref_data_genome_version + ref_data_disease_ontology + ref_data_known_fusion_data + ref_data_driver_gene_panel + ref_data_cohort_mapping + ref_data_cohort_percentiles + + // Parameters + run + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // SAMtools flagstat + // Select input source + // channel (present): [val(meta), sample_type, flagstat] + // channel (absent): [val(meta)] + ch_inputs_flagstat = ch_inputs_wgs + .flatMap { meta -> [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL].collect { [meta, it] } } + .branch { meta, sample_type -> + def key = [Constants.FileType.FLAGSTAT, sample_type, Constants.SequenceType.WGS] + present: meta.containsKey(key) + return [meta, sample_type, meta.getAt(key)] + absent: ! meta.containsKey(key) + } + + // Create inputs and create process-specific meta + // channel: [val(meta_flagstat), bam, bai] + ch_flagstat_inputs_all = ch_inputs_flagstat.absent + .map { meta, sample_type -> + def bam = meta.getAt([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) + def sample_name = meta.getAt(['sample_name', sample_type, Constants.SequenceType.WGS]) + def meta_flagstat = [ + key: meta.id, + id: sample_name, + // NOTE(SW): must use string representation for caching purposes + sample_type_str: sample_type.name(), + ] + return [meta_flagstat, bam, "${bam}.bai"] + } + + // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples + // channel: [val(meta_flagstat_shared), bam, bai] + ch_flagstat_inputs = ch_flagstat_inputs_all + .map { [it[1..-1], it[0]] } + .groupTuple() + .map { filepaths, meta_flagstat -> + def (keys, sample_names, sample_type_strs) = meta_flagstat + .collect { + [it.key, it.id, it.sample_type_str] + } + .transpose() + + def sample_type_strs_unique = sample_type_strs.unique(false) + assert sample_type_strs_unique.size() == 1 + def sample_type_str = sample_type_strs_unique[0] + + def meta_flagstat_new = [ + keys: keys, + id: sample_names.join('__'), + id_simple: keys.join('__'), + sample_type_str: sample_type_str, + ] + return [meta_flagstat_new, *filepaths] + } + + // Run process + SAMTOOLS_FLAGSTAT( + ch_flagstat_inputs, + ) + + // Set version + ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) + + // Replicate outputs to reverse unique operation + // channel: [val(meta_flagstat_individual), flagstat] + ch_flagstat_out = SAMTOOLS_FLAGSTAT.out.flagstat + .flatMap { meta_flagstat_shared, flagstat -> + def sample_type = Utils.getEnumFromString(meta_flagstat_shared.sample_type_str, Constants.SampleType) + meta_flagstat_shared.keys.collect { key -> + return [meta_flagstat_shared + [key: key], sample_type, flagstat] + } + } + + // Combine input flagstat channels, restoring original meta where required, split by sample type + // channel (somatic): [val(meta), flagstat] + // channel (germline): [val(meta), flagstat] + ch_orange_inputs_flagstat = Channel.empty() + .concat( + ch_inputs_flagstat.present, + WorkflowOncoanalyser.restoreMeta(ch_flagstat_out, ch_inputs), + ) + .branch { meta, sample_type, flagstat -> + somatic: sample_type == Constants.SampleType.TUMOR + return [meta, flagstat] + germline: sample_type == Constants.SampleType.NORMAL + return [meta, flagstat] + } + + // TODO(SW): handle CUPPA WTS, WGS, WGS + + // Select input source + // NOTE(SW): we could consider not allowing inputs from the samplesheet here since this nothing follows + ch_orange_inputs_source = WorkflowOncoanalyser.groupByMeta( + run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_TUMOR), + run.bamtools ? ch_bamtools_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_NORMAL), + ch_orange_inputs_flagstat.somatic, + ch_orange_inputs_flagstat.germline, + run.chord ? ch_chord : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD), + run.lilac ? ch_lilac : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), + run.sage ? ch_sage_somatic_tumor_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_TUMOR), + run.sage ? ch_sage_somatic_normal_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_NORMAL), + run.sage ? ch_sage_germline_coverage : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_COVERAGE), + run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), + run.linx ? ch_linx_somatic_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + run.linx ? ch_linx_somatic_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_TUMOR), + run.linx ? ch_linx_germline_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_NORMAL), + run.protect ? ch_protect : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PROTECT_TSV), + run.peach ? ch_peach : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PEACH_TSV), + run.cuppa ? ch_cuppa : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUTS_CUPPA_CSV), + run.cuppa ? ch_cuppa_feature_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_FEATURE_PLOT), + run.cuppa ? ch_cuppa_summary_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_SUMMARY_PLOT), + run.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV), + ) + + ch_orange_inputs = ch_orange_inputs_source + .map { + def meta = it[0] + def meta_orange = [ + key: meta.id, + id: meta.id, + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), + ] + return [meta_orange, *it[1..-1]] + } + + // Run process + ORANGE( + ch_orange_inputs, + ref_data_genome_version, + ref_data_disease_ontology, + ref_data_known_fusion_data, + ref_data_driver_gene_panel, + ref_data_cohort_mapping, + ref_data_cohort_percentiles, + "5.31 [oncoanalyser]", + ) + + // Set outputs + ch_versions = ch_versions.mix(ORANGE.out.versions) + + emit: + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/pave.nf b/subworkflows/local/pave.nf deleted file mode 100644 index a5100f71..00000000 --- a/subworkflows/local/pave.nf +++ /dev/null @@ -1,62 +0,0 @@ -// -// PAVE annotates somatic and germline variant VCFs with gene and transcript coding and protein effects. -// - -include { PAVE_GERMLINE } from '../../modules/local/pave/germline/main' -include { PAVE_SOMATIC } from '../../modules/local/pave/somatic/main' - -workflow PAVE { - take: - ch_inputs_germline // channel: [val(meta), sage_germline_vcf] - ch_inputs_somatic // channel: [val(meta), sage_somatic_vcf] - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_version // val: genome version - ref_data_sage_pon // file: /path/to/sage_pon - ref_data_sage_blocklist_regions // file: /path/to/sage_blocklist_regions - ref_data_sage_blocklist_sites // file: /path/to/sage_blocklist_sites - ref_data_clinvar_annotations // file: /path/to/clinvar_annotations - ref_data_segment_mappability // file: /path/to/segment_mappability - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ - ref_data_gnomad_pon_dir // file: /path/to/gnomad_pon_dir/ - - main: - // Channel for version.yml files - ch_versions = Channel.empty() - - // Germline - PAVE_GERMLINE( - ch_inputs_germline, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_sage_blocklist_regions, - ref_data_sage_blocklist_sites, - ref_data_clinvar_annotations, - ref_data_segment_mappability, - ref_data_driver_gene_panel, - ref_data_ensembl_data_resources, - ) - ch_versions = ch_versions.mix(PAVE_GERMLINE.out.versions) - - // Somatic - PAVE_SOMATIC( - ch_inputs_somatic, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_sage_pon, - ref_data_segment_mappability, - ref_data_driver_gene_panel, - ref_data_ensembl_data_resources, - ref_data_gnomad_pon_dir, - ) - ch_versions = ch_versions.mix(PAVE_SOMATIC.out.versions) - - emit: - germline = PAVE_GERMLINE.out.vcf // channel: [val(meta), pave_vcf] - somatic = PAVE_SOMATIC.out.vcf // channel: [val(meta), pave_vcf] - - versions = ch_versions // channel: [versions.yml] -} diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf new file mode 100644 index 00000000..1322d2d8 --- /dev/null +++ b/subworkflows/local/pave_annotation.nf @@ -0,0 +1,107 @@ +// +// PAVE annotates somatic and germline variant VCFs with gene and transcript coding and protein effects. +// + +include { PAVE_GERMLINE as GERMLINE } from '../../modules/local/pave/germline/main' +include { PAVE_SOMATIC as SOMATIC } from '../../modules/local/pave/somatic/main' + +workflow PAVE_ANNOTATION { + take: + + // Sample data + ch_inputs // channel: [val(meta)] + ch_sage_germline_vcf // channel: [val(meta), sage_germline_vcf] + ch_sage_somatic_vcf // channel: [val(meta), sage_somatic_vcf] + + // Reference data + ref_data_genome_fasta // file: /path/to/genome_fasta + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_version // val: genome version + ref_data_sage_pon // file: /path/to/sage_pon + ref_data_sage_blocklist_regions // file: /path/to/sage_blocklist_regions + ref_data_sage_blocklist_sites // file: /path/to/sage_blocklist_sites + ref_data_clinvar_annotations // file: /path/to/clinvar_annotations + ref_data_segment_mappability // file: /path/to/segment_mappability + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + ref_data_gnomad_pon_dir // file: /path/to/gnomad_pon_dir/ + + // Params + run + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Select input sources + // channel: [meta, sage_vcf, sage_tbi] + if (run.sage) { + ch_pave_germline_inputs_source = ch_sage_germline_vcf + ch_pave_somatic_inputs_source = ch_sage_somatic_vcf + } else { + ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_TUMOR) + .filter { it[0] != Constants.META_PLACEHOLDER } + ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_NORMAL) + .filter { it[0] != Constants.META_PLACEHOLDER } + } + + // Create inputs and create process-specific meta + // channel: [val(meta_pave), sage_vcf] + ch_pave_germline_inputs = ch_pave_germline_inputs_source + .map { meta, sage_vcf, sage_tbi -> + def pave_meta = [ + key: meta.id, + // NOTE(SW): use of tumor sample name for PAVE germline is correct + id: Utils.getTumorWgsSampleName(meta), + ] + return [pave_meta, sage_vcf] + } + + ch_pave_somatic_inputs = ch_pave_somatic_inputs_source + .map { meta, sage_vcf, sage_tbi -> + def pave_meta = [ + key: meta.id, + id: Utils.getTumorWgsSampleName(meta), + ] + return [pave_meta, sage_vcf] + } + + GERMLINE( + ch_pave_germline_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_sage_blocklist_regions, + ref_data_sage_blocklist_sites, + ref_data_clinvar_annotations, + ref_data_segment_mappability, + ref_data_driver_gene_panel, + ref_data_ensembl_data_resources, + ) + + SOMATIC( + ch_pave_somatic_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_sage_pon, + ref_data_segment_mappability, + ref_data_driver_gene_panel, + ref_data_ensembl_data_resources, + ref_data_gnomad_pon_dir, + ) + + // Set outputs + ch_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) + ch_somatic_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs) + ch_versions = ch_versions.mix( + GERMLINE.out.versions, + SOMATIC.out.versions, + ) + + emit: + germline = ch_germline_out // channel: [val(meta), pave_vcf] + somatic = ch_somatic_out // channel: [val(meta), pave_vcf] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/purple_calling.nf b/subworkflows/local/purple_calling.nf new file mode 100644 index 00000000..159e6bb6 --- /dev/null +++ b/subworkflows/local/purple_calling.nf @@ -0,0 +1,107 @@ +// +// PURPLE is a CNV caller that infers purity/ploidy and recovers low-confidence SVs +// + +include { PURPLE } from '../../modules/local/purple/main' + +workflow PURPLE_CALLING { + take: + // Sample data + ch_inputs + ch_amber + ch_cobalt + ch_smlv_somatic + ch_smlv_germline + ch_sv_somatic + ch_sv_somatic_recovery + + // Reference data + ref_data_genome_fasta + ref_data_genome_fai + ref_data_genome_dict + ref_data_genome_version + gc_profile + sage_known_hotspots_somatic + sage_known_hotspots_germline + driver_gene_panel + ensembl_data_resources + purple_germline_del + + // Params + run + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Select input sources + // channel: [val(meta), sv_vcf, sv_tbi, sv_recovery_vcf, sv_recovery_tbi] + ch_purple_inputs_sv = Channel.empty() + if (run.gripss) { + // NOTE(SW): GRIPSS will be run for all WGS entries, so no optionals here + ch_purple_inputs_sv = WorkflowOncoanalyser.groupByMeta( + ch_sv_somatic, + ch_sv_somatic_recovery, + ) + } else { + ch_purple_inputs_sv = WorkflowOncoanalyser.groupByMeta( + WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_TUMOR, type: 'optional'), + WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR, type: 'optional'), + flatten_mode: 'nonrecursive', + ) + .map { meta, vcf, vcf_unfiltered-> + def tbi = vcf == [] ? [] : "${vcf}.tbi" + def tbi_unfiltered = vcf_unfiltered == [] ? [] : "${vcf_unfiltered}.tbi" + return [meta, vcf, tbi, vcf_unfiltered, tbi_unfiltered] + } + } + + // channel: [val(meta), amber_dir, cobalt_dir, sv_vcf, sv_tbi, sv_recovery_vcf, sv_recovery_tbi, smlv_tumor_vcf, smlv_normal_vcf] + ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( + // Required inputs + run.amber ? ch_amber: WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.AMBER_DIR), + run.cobalt ? ch_cobalt: WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.COBALT_DIR), + // Optional inputs + ch_purple_inputs_sv, + run.pave ? ch_smlv_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_TUMOR, type: 'optional'), + run.pave ? ch_smlv_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_NORMAL, type: 'optional'), + flatten_mode: 'nonrecursive', + ) + + // Create process-specific meta + // channel: [val(meta_purple), amber_dir, cobalt_dir, sv_vcf, sv_tbi, sv_recovery_vcf, sv_recovery_tbi, smlv_tumor_vcf, smlv_normal_vcf] + ch_purple_inputs = ch_purple_inputs_source + .map { + def meta = it[0] + def other = it[1..-1] + def meta_purple = [ + key: meta.id, + id: meta.id, + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), + ] + return [meta_purple, *other] + } + + PURPLE( + ch_purple_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + gc_profile, + sage_known_hotspots_somatic, + sage_known_hotspots_germline, + driver_gene_panel, + ensembl_data_resources, + purple_germline_del, + ) + + ch_outputs = WorkflowOncoanalyser.restoreMeta(PURPLE.out.purple_dir, ch_inputs) + ch_versions = ch_versions.mix(PURPLE.out.versions) + + emit: + purple_dir = ch_outputs // channel: [val(meta), purple_dir] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/sage.nf b/subworkflows/local/sage.nf deleted file mode 100644 index 72a75834..00000000 --- a/subworkflows/local/sage.nf +++ /dev/null @@ -1,66 +0,0 @@ -// -// SAGE is a precise and highly sensitive somatic SNV, MNV and small INDEL caller. -// - -include { SAGE_GERMLINE } from '../../modules/local/sage/germline/main' -include { SAGE_SOMATIC } from '../../modules/local/sage/somatic/main' - -workflow SAGE { - take: - ch_inputs // channel: [meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai] - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_dict // file: /path/to/genome_dict - ref_data_genome_version // val: genome version - ref_data_sage_known_hotspots_germline // file: /path/to/sage_known_hotspots_germline - ref_data_sage_known_hotspots_somatic // file: /path/to/sage_known_hotspots_somatic - ref_data_sage_actionable_panel // file: /path/to/sage_actionable_panel - ref_data_sage_coverage_panel // file: /path/to/sage_coverage_panel - ref_data_sage_highconf_regions // file: /path/to/sage_highconf_regions - ref_data_sage_pon // file: /path/to/sage_pon - ref_data_segment_mappability // file: /path/to/segment_mappability - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ - - main: - // Channel for version.yml files - ch_versions = Channel.empty() - - // Germline - SAGE_GERMLINE( - ch_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_sage_known_hotspots_germline, - ref_data_sage_actionable_panel, - ref_data_sage_coverage_panel, - ref_data_sage_highconf_regions, - ref_data_ensembl_data_resources, - ) - ch_versions = ch_versions.mix(SAGE_GERMLINE.out.versions) - - // Somatic - SAGE_SOMATIC( - ch_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_sage_known_hotspots_somatic, - ref_data_sage_actionable_panel, - ref_data_sage_highconf_regions, - ref_data_ensembl_data_resources, - ) - ch_versions = ch_versions.mix(SAGE_SOMATIC.out.versions) - - emit: - germline_vcf = SAGE_GERMLINE.out.vcf_filtered // channel: [val(meta), sage_vcf] - germline_coverage = SAGE_GERMLINE.out.gene_coverage // channel: [val(meta), sage_coverage] - somatic_vcf = SAGE_SOMATIC.out.vcf_filtered // channel: [val(meta), sage_vcf] - somatic_tumor_bqr = SAGE_SOMATIC.out.tumor_bqr_png // channel: [val(meta), sage_bqr_plot] - somatic_normal_bqr = SAGE_SOMATIC.out.normal_bqr_png // channel: [val(meta), sage_brq_plot] - - versions = ch_versions // channel: [versions.yml] -} diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf new file mode 100644 index 00000000..e4c70293 --- /dev/null +++ b/subworkflows/local/sage_calling.nf @@ -0,0 +1,87 @@ +// +// SAGE is a precise and highly sensitive somatic SNV, MNV and small INDEL caller. +// + +include { SAGE_GERMLINE as GERMLINE } from '../../modules/local/sage/germline/main' +include { SAGE_SOMATIC as SOMATIC } from '../../modules/local/sage/somatic/main' + +workflow SAGE_CALLING { + take: + ch_inputs // channel: [val(meta)] + ref_data_genome_fasta // file: /path/to/genome_fasta + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_dict // file: /path/to/genome_dict + ref_data_genome_version // val: genome version + ref_data_sage_known_hotspots_germline // file: /path/to/sage_known_hotspots_germline + ref_data_sage_known_hotspots_somatic // file: /path/to/sage_known_hotspots_somatic + ref_data_sage_actionable_panel // file: /path/to/sage_actionable_panel + ref_data_sage_coverage_panel // file: /path/to/sage_coverage_panel + ref_data_sage_highconf_regions // file: /path/to/sage_highconf_regions + ref_data_sage_pon // file: /path/to/sage_pon + ref_data_segment_mappability // file: /path/to/segment_mappability + ref_data_driver_gene_panel // file: /path/to/driver_gene_panel + ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Get inputs + ch_sage_inputs = ch_inputs + .map { meta -> + def meta_sage = [ + key: meta.id, + id: meta.id, + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), + ] + def tumor_bam = Utils.getTumorWgsBam(meta) + def normal_bam = Utils.getNormalWgsBam(meta) + return [meta_sage, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] + } + + GERMLINE( + ch_sage_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_sage_known_hotspots_germline, + ref_data_sage_actionable_panel, + ref_data_sage_coverage_panel, + ref_data_sage_highconf_regions, + ref_data_ensembl_data_resources, + ) + + SOMATIC( + ch_sage_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_sage_known_hotspots_somatic, + ref_data_sage_actionable_panel, + ref_data_sage_highconf_regions, + ref_data_ensembl_data_resources, + ) + + ch_versions = ch_versions.mix( + GERMLINE.out.versions, + SOMATIC.out.versions, + ) + + ch_germline_vcf_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_filtered, ch_inputs) + ch_germline_coverage_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.gene_coverage, ch_inputs) + ch_somatic_vcf_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_filtered, ch_inputs) + ch_somatic_tumor_bqr_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.tumor_bqr_png, ch_inputs) + ch_somatic_normal_bqr_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.normal_bqr_png, ch_inputs) + + emit: + germline_vcf = ch_germline_vcf_out // channel: [val(meta), sage_vcf, sage_tbi] + germline_coverage = ch_germline_coverage_out // channel: [val(meta), sage_coverage] + somatic_vcf = ch_somatic_vcf_out // channel: [val(meta), sage_vcf, sage_tbi] + somatic_tumor_bqr = ch_somatic_tumor_bqr_out // channel: [val(meta), sage_bqr_plot] + somatic_normal_bqr = ch_somatic_normal_bqr_out // channel: [val(meta), sage_brq_plot] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf new file mode 100644 index 00000000..644c59b2 --- /dev/null +++ b/subworkflows/local/virusbreakend_calling.nf @@ -0,0 +1,121 @@ +// +// XXX +// +import Constants +import Utils + +include { VIRUSBREAKEND } from '../../modules/local/virusbreakend/main' +include { VIRUSINTERPRETER } from '../../modules/local/virusinterpreter/main' + +workflow VIRUSBREAKEND_CALLING { + take: + // Sample data + ch_inputs + ch_purple + ch_bamtools_somatic + + // Reference data + ref_data_genome_fasta + ref_data_genome_fai + ref_data_genome_dict + ref_data_genome_bwa_index + ref_data_genome_bwa_index_image + ref_data_genome_gridss_index + ref_data_virusbreakenddb + ref_data_virus_taxonomy_db + ref_data_virus_reporting_db + + // Parameters + run + gridss_config + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // VIRUSBreakend + // Create inputs and create process-specific meta + // channel: [val(meta_virus), tumor_bam] + ch_virusbreakend_inputs = ch_inputs + .map { meta -> + def meta_virus = [ + key: meta.id, + id: meta.id, + ] + return [meta_virus, Utils.getTumorWgsBam(meta)] + } + + // Run process + VIRUSBREAKEND( + ch_virusbreakend_inputs, + gridss_config, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_bwa_index, + ref_data_genome_bwa_index_image, + ref_data_genome_gridss_index, + ref_data_virusbreakenddb, + ) + + // Create inputs and create process-specific meta + if (run.purple) { + ch_virusinterpreter_inputs_purple = ch_purple + } else { + ch_virusinterpreter_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + } + + // channel: [val(meta), purple_qc, wgs_metrics] + ch_virusinterpreter_inputs_purple_files = ch_virusinterpreter_inputs_purple + .filter { it[0] != Constants.META_PLACEHOLDER } + .map { meta, purple_dir -> + def tumor_id = Utils.getTumorWgsSampleName(meta) + def purple_purity = file(purple_dir).resolve("${tumor_id}.purple.purity.tsv") + def purple_qc = file(purple_dir).resolve("${tumor_id}.purple.qc") + + // Require both purity and QC files from the PURPLE directory + if (!purple_purity.exists() || !purple_qc.exists()) { + return Constants.META_PLACEHOLDER + } + return [meta, purple_purity, purple_qc] + } + + // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] + ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( + WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), + ch_virusinterpreter_inputs_purple_files, + run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_TUMOR), + ) + + // Virus Interpreter + // Create inputs and create process-specific meta + // channel: [val(meta_virus), virus_tsv, purple_purity, purple_qc, wgs_metrics] + ch_virusinterpreter_inputs = ch_virusinterpreter_inputs_full + .map { + def meta = it[0] + def meta_virus = [ + key: meta.id, + id: Utils.getTumorWgsSampleName(meta), + ] + return [meta_virus, *it[1..-1]] + } + + // Run process + VIRUSINTERPRETER( + ch_virusinterpreter_inputs, + ref_data_virus_taxonomy_db, + ref_data_virus_reporting_db, + ) + + // Set outputs, restoring original meta + ch_outputs = WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter, ch_inputs) + ch_versions = ch_versions.mix( + VIRUSINTERPRETER.out.versions, + VIRUSBREAKEND.out.versions, + ) + + emit: + virusinterpreter = ch_outputs // channel: [val(meta), virusinterpreter] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf deleted file mode 100644 index 550af628..00000000 --- a/workflows/oncoanalyser.nf +++ /dev/null @@ -1,1319 +0,0 @@ -import Constants -import Processes -import Utils - - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - VALIDATE INPUTS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) - -// Validate input parameters -WorkflowOncoanalyser.initialise(params, workflow, log) - -// Set processes to run -processes = Processes.setProcesses(params.mode, log) -processes_include = Processes.getProcessList(params.processes_include, log) -processes_exclude = Processes.getProcessList(params.processes_exclude, log) -Processes.checkIncludeExcludeList(processes_include, processes_exclude, log) - -processes.addAll(processes_include) -processes.removeAll(processes_exclude) - -run = Constants.Process - .values() - .collectEntries { p -> [p.name().toLowerCase(), p in processes] } - -// Check input path parameters to see if they exist -def checkPathParamList = [ - params.input, - params.gridss_config, - params.linx_gene_id_file, -] - -for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } - -// Check mandatory parameters -if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } - -// Create Path objects for some input files -linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : [] - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - CONFIG FILES -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - IMPORT LOCAL MODULES/SUBWORKFLOWS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -// -// MODULES -// -include { AMBER } from '../modules/local/amber/main' -include { BAMTOOLS } from '../modules/local/bamtools/main' -include { CHORD } from '../modules/local/chord/main' -include { COBALT } from '../modules/local/cobalt/main' -include { CUPPA_CLASSIFIER } from '../modules/local/cuppa/classifier/main' -include { CUPPA_VISUALISER } from '../modules/local/cuppa/visualiser/main' -include { GPGR_LINX } from '../modules/local/gpgr/linx/main' -include { ISOFOX } from '../modules/local/isofox/main' -include { ORANGE } from '../modules/local/orange/main' -include { PEACH } from '../modules/local/peach/main' -include { PROTECT } from '../modules/local/protect/main' -include { PURPLE } from '../modules/local/purple/main' -include { SIGS } from '../modules/local/sigs/main' -include { VIRUSBREAKEND } from '../modules/local/virusbreakend/main' -include { VIRUSINTERPRETER } from '../modules/local/virusinterpreter/main' - -// -// SUBWORKFLOWS -// -include { GRIDSS } from '../subworkflows/local/gridss' -include { GRIDSS_SVPREP } from '../subworkflows/local/gridss_svprep' -include { GRIPSS } from '../subworkflows/local/gripss' -include { LILAC } from '../subworkflows/local/lilac' -include { LINX } from '../subworkflows/local/linx' -include { PAVE } from '../subworkflows/local/pave' -include { PREPARE_INPUT } from '../subworkflows/local/prepare_input' -include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' -include { SAGE } from '../subworkflows/local/sage' - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - IMPORT NF-CORE MODULES/SUBWORKFLOWS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -// -// MODULES -// -include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' -include { SAMTOOLS_FLAGSTAT } from '../modules/nf-core/samtools/flagstat/main' - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - RUN MAIN WORKFLOW -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -// Get absolute file paths -samplesheet = Utils.getFileObject(params.input) -gridss_config = Utils.getFileObject(params.gridss_config) - -workflow ONCOANALYSER { - // Create channel for versions - // channel: [versions.yml] - ch_versions = Channel.empty() - - // Get inputs from samplesheet - // channel: [val(meta)] - PREPARE_INPUT( - samplesheet, - ) - ch_inputs = PREPARE_INPUT.out.data - - // Split inputs WTS and WGS - // NOTE(SW): assuming there are only t/n pairs i.e. no tumor-only or normal-only - - // channel (present): [val(meta)] - // channel (absent): [val(meta)] - ch_inputs_wgs = ch_inputs - .branch { meta -> - def key_tumor = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS] - def key_normal = [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.WGS] - present: meta.containsKey(key_tumor) && meta.containsKey(key_normal) - return meta - absent: true - return meta - } - - // channel (present): [val(meta)] - // channel (absent): [val(meta)] - ch_inputs_wts = ch_inputs - .branch { meta -> - def key = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WTS] - present: meta.containsKey(key) - return meta - absent: ! meta.containsKey(key) - return meta - } - - // Set up reference data and unpack HMF data map for convenience - PREPARE_REFERENCE(run) - hmf_data = PREPARE_REFERENCE.out.hmf_data - - // - // MODULE: Run Isofox to analyse WTS data - // - // channel: [meta, isofox_dir] - ch_isofox_out = Channel.empty() - if (run.isofox) { - // Create inputs and create process-specific meta - // channel: [meta_isofox, tumor_bam_wts] - ch_isofox_inputs = ch_inputs_wts.present - .map { meta -> - def bam = Utils.getTumorWtsBam(meta) - def meta_isofox = [key: meta.id, id: Utils.getTumorWtsSampleName(meta)] - return [meta_isofox, bam, "${bam}.bai"] - } - - // Set Isofox cache files - // NOTE(SW): the Isofox expected count file is read length dependent so required users to explicitly use expect - // counts generated for 151 bp reads that is available in the HMF reference bundle. When not specifying an - // expected count file, Isofox will automatically create one for the computed read length. However, doing so - // greatly increases runtime. - // NOTE(SW): consider alternative approaches for using the expected count file e.g. generate once at runtime, - // then use for all samples; generate all possible read lengths outside of pipeline and store on a remote for - // retrieval at runtime (requires inference of read length) - - // TODO(SW): this must be improved to allow users to set input file, use cache, or generate at runtime; - // currently does not update functions - // NOTE(SW): forcing use of cache for now since this feature is incomplete - - //isofox_counts = params.use_isofox_exp_counts_cache ? hmf_data.isofox_counts : [] - isofox_counts = hmf_data.isofox_counts - - // Run process - ISOFOX( - ch_isofox_inputs, - params.isofox_functions, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_version, - hmf_data.ensembl_data_resources, - isofox_counts, - hmf_data.isofox_gc_ratios, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(ISOFOX.out.versions) - ch_isofox_out = ch_isofox_out.mix(WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs)) - } - - // - // MODULE: Run Bam Tools to generate stats required for downstream processes - // - if (run.bamtools) { - // Create inputs and create process-specific meta - // NOTE(SW): CUPPA only requires metrics for the tumor sample in the upstream - // process Virus Interpreter but ORANGE currently requires metrics for both tumor - // and normal sample - // channel: [val(meta_bamtools), bam, bai] - ch_bamtools_inputs_all = ch_inputs_wgs.present - .flatMap { meta -> - def sample_types = run.orange ? [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL] : [Constants.SampleType.TUMOR] - return sample_types - .collect { sample_type -> - def bam = meta.get([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) - def sample_name = meta.get(['sample_name', sample_type, Constants.SequenceType.WGS]) - def meta_bamtools = [ - key: meta.id, - id: sample_name, - // NOTE(SW): must use string representation for caching purposes - sample_type_str: sample_type.name(), - ] - return [meta_bamtools, bam, "${bam}.bai"] - } - } - - // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples - // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent - // on any process - // channel: [val(meta_bamtools), bam, bai] - ch_bamtools_inputs = ch_bamtools_inputs_all - .map { [it[1..-1], it[0]] } - .groupTuple() - .map { filepaths, meta_bamtools -> - def (keys, sample_names, sample_type_strs) = meta_bamtools - .collect { - [it.key, it.id, it.sample_type_str] - } - .transpose() - - def sample_type_strs_unique = sample_type_strs.unique(false) - assert sample_type_strs_unique.size() == 1 - def sample_type_str = sample_type_strs_unique[0] - - def meta_bamtools_new = [ - keys: keys, - id: sample_names.join('__'), - id_simple: keys.join('__'), - sample_type_str: sample_type_str, - ] - return [meta_bamtools_new, *filepaths] - } - - // Run process - BAMTOOLS( - ch_bamtools_inputs, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_version, - ) - - // Set outputs, process outputs and restore original meta - ch_versions = ch_versions.mix(BAMTOOLS.out.versions) - - // Replicate outputs to reverse unique operation - // channel: [val(meta_bamtools_individual), sample_type_str, metrics] - ch_bamtools_out_individual = BAMTOOLS.out.metrics - .flatMap { meta_bamtools_shared, metrics -> - meta_bamtools_shared.keys.collect { key -> - return [meta_bamtools_shared + [key: key], meta_bamtools_shared.sample_type_str, metrics] - } - } - - // Match outputs to original meta and set output - // channel (tumor): [val(meta), metrics] - // channel (normal): [val(meta), metrics] - ch_bamtools_out = WorkflowOncoanalyser.restoreMeta(ch_bamtools_out_individual, ch_inputs) - .branch { meta, sample_type_str, metrics -> - def sample_type = Utils.getEnumFromString(sample_type_str, Constants.SampleType) - somatic: sample_type == Constants.SampleType.TUMOR - return [meta, metrics] - germline: sample_type == Constants.SampleType.NORMAL - return [meta, metrics] - } - } - - // - // MODULE: Run AMBER to obtain b-allele frequencies - // - // channel: [val(meta), amber_dir] - ch_amber_out = Channel.empty() - if (run.amber) { - // Create inputs and create process-specific meta - // channel: [val(meta_amber), tumor_bam_wgs, normal_bam_wgs, tumor_bai_wgs, normal_bai_wgs] - ch_amber_inputs = ch_inputs_wgs.present - .map { meta -> - def meta_amber = [ - key: meta.id, - id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - def tumor_bam = Utils.getTumorWgsBam(meta) - def normal_bam = Utils.getNormalWgsBam(meta) - [meta_amber, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] - } - - // Run process - AMBER( - ch_amber_inputs, - PREPARE_REFERENCE.out.genome_version, - hmf_data.heterozygous_sites, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(AMBER.out.versions) - ch_amber_out = ch_amber_out.mix(WorkflowOncoanalyser.restoreMeta(AMBER.out.amber_dir, ch_inputs)) - } - - // - // MODULE: Run COBALT to obtain read ratios - // - // channel: [val(meta), cobalt_dir] - ch_cobalt_out = Channel.empty() - if (run.cobalt) { - // Create inputs and create process-specific meta - // channel: [meta_cobalt, tumor_bam_wgs, normal_bam_wgs, tumor_bai_wgs, normal_bai_wgs] - ch_cobalt_inputs = ch_inputs_wgs.present - .map { meta -> - def meta_cobalt = [ - key: meta.id, - id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - def tumor_bam = Utils.getTumorWgsBam(meta) - def normal_bam = Utils.getNormalWgsBam(meta) - return [meta_cobalt, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] - } - - // Run process - COBALT( - ch_cobalt_inputs, - hmf_data.gc_profile, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(COBALT.out.versions) - ch_cobalt_out = ch_cobalt_out.mix(WorkflowOncoanalyser.restoreMeta(COBALT.out.cobalt_dir, ch_inputs)) - } - - // - // SUBWORKFLOW: Call structural variants with GRIDSS - // - // channel: [val(meta), gridss_vcf] - ch_gridss_out = Channel.empty() - if (run.gridss) { - if (run.svprep) { - GRIDSS_SVPREP( - ch_inputs_wgs.present, - gridss_config, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_version, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_bwa_index, - PREPARE_REFERENCE.out.genome_bwa_index_image, - PREPARE_REFERENCE.out.genome_gridss_index, - hmf_data.gridss_region_blocklist, - hmf_data.sv_prep_blocklist, - hmf_data.known_fusions, - ) - ch_versions = ch_versions.mix(GRIDSS_SVPREP.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP.out.results) - } else { - ch_gridss_inputs = ch_inputs_wgs.present - .map { meta -> - def tumor_bam = Utils.getTumorWgsBam(meta) - def normal_bam = Utils.getNormalWgsBam(meta) - [meta, tumor_bam, normal_bam] - } - GRIDSS( - ch_gridss_inputs, - gridss_config, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_bwa_index, - PREPARE_REFERENCE.out.genome_bwa_index_image, - PREPARE_REFERENCE.out.genome_gridss_index, - hmf_data.gridss_region_blocklist, - ) - ch_versions = ch_versions.mix(GRIDSS.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS.out.results) - } - } - - // - // MODULE: Run GRIPSS to filter GRIDSS SV calls - // - // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - ch_gripss_germline_out = Channel.empty() - // channel: [val(meta), hard_vcf, hard_tbi, soft_vcf, soft_tbi] - ch_gripss_somatic_out = Channel.empty() - if (run.gripss) { - // Select input source - // channel: [val(meta), gridss_vcf] - if (run.gridss) { - ch_gripss_inputs_source = ch_gridss_out - } else { - ch_gripss_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIDSS_VCF) - .filter { it[0] != Constants.META_PLACEHOLDER } - } - - // Create inputs and create process-specific meta - // channel: [val(meta_gripss), gridss_vcf] - ch_gripss_inputs = ch_gripss_inputs_source - .map { meta, gridss_vcf -> - def meta_gripss = [ - key: meta.id, - id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - return [meta_gripss, gridss_vcf] - } - - // Call subworkflow to run processes - GRIPSS( - ch_gripss_inputs, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_version, - hmf_data.gridss_pon_breakends, - hmf_data.gridss_pon_breakpoints, - hmf_data.known_fusions, - hmf_data.repeatmasker_annotations, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(GRIPSS.out.versions) - ch_gripss_germline_out = ch_gripss_germline_out.mix(WorkflowOncoanalyser.restoreMeta(GRIPSS.out.germline, ch_inputs)) - ch_gripss_somatic_out = ch_gripss_somatic_out.mix(WorkflowOncoanalyser.restoreMeta(GRIPSS.out.somatic, ch_inputs)) - } - - // - // SUBWORKFLOW: call SNV, MNV, and small INDELS with SAGE - // - // channel: [val(meta), sage_vcf] - ch_sage_germline_vcf_out = Channel.empty() - // channel: [val(meta), sage_coverage] - ch_sage_germline_coverage_out = Channel.empty() - // channel: [val(meta), sage_vcf] - ch_sage_somatic_vcf_out = Channel.empty() - // channel: [val(meta), bqr_plot] - ch_sage_somatic_tumor_bqr_out = Channel.empty() - // channel: [val(meta), bqr_plot] - ch_sage_somatic_normal_bqr_out = Channel.empty() - if (run.sage) { - // Create inputs and create process-specific meta - ch_sage_inputs = ch_inputs_wgs.present - .map { meta -> - def meta_sage = [ - key: meta.id, - id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - def tumor_bam = Utils.getTumorWgsBam(meta) - def normal_bam = Utils.getNormalWgsBam(meta) - return [meta_sage, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] - } - - // Call subworkflow to run processes - SAGE( - ch_sage_inputs, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_version, - hmf_data.sage_known_hotspots_germline, - hmf_data.sage_known_hotspots_somatic, - hmf_data.sage_actionable_panel, - hmf_data.sage_coverage_panel, - hmf_data.sage_highconf_regions, - hmf_data.sage_pon, - hmf_data.segment_mappability, - hmf_data.driver_gene_panel, - hmf_data.ensembl_data_resources, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(SAGE.out.versions) - ch_sage_germline_vcf_out = ch_sage_germline_vcf_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.germline_vcf, ch_inputs)) - ch_sage_germline_coverage_out = ch_sage_germline_coverage_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.germline_coverage, ch_inputs)) - ch_sage_somatic_vcf_out = ch_sage_somatic_vcf_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.somatic_vcf, ch_inputs)) - ch_sage_somatic_tumor_bqr_out = ch_sage_somatic_tumor_bqr_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.somatic_tumor_bqr, ch_inputs)) - ch_sage_somatic_normal_bqr_out = ch_sage_somatic_normal_bqr_out.mix(WorkflowOncoanalyser.restoreMeta(SAGE.out.somatic_normal_bqr, ch_inputs)) - } - - // - // SUBWORKFLOW: Annotate variants with PAVE - // - // channel: [val(meta), pave_vcf] - ch_pave_germline_out = Channel.empty() - // channel: [val(meta), pave_vcf] - ch_pave_somatic_out = Channel.empty() - if (run.pave) { - // Select input sources - // channel: [meta, sage_vcf] - if (run.sage) { - ch_pave_germline_inputs_source = ch_sage_germline_vcf_out - ch_pave_somatic_inputs_source = ch_sage_somatic_vcf_out - } else { - ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_TUMOR) - .filter { it[0] != Constants.META_PLACEHOLDER } - ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_NORMAL) - .filter { it[0] != Constants.META_PLACEHOLDER } - } - - // Create inputs and create process-specific meta - // channel: [val(meta_pave), sage_vcf] - ch_pave_germline_inputs = ch_pave_germline_inputs_source - .map { meta, sage_vcf -> - def pave_meta = [ - key: meta.id, - // NOTE(SW): use of tumor sample name for PAVE germline is correct - id: Utils.getTumorWgsSampleName(meta), - ] - return [pave_meta, sage_vcf] - } - ch_pave_somatic_inputs = ch_pave_somatic_inputs_source - .map { meta, sage_vcf -> - def pave_meta = [ - key: meta.id, - id: Utils.getTumorWgsSampleName(meta), - ] - return [pave_meta, sage_vcf] - } - - // Call subworkflow to run processes - PAVE( - ch_pave_germline_inputs, - ch_pave_somatic_inputs, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_version, - hmf_data.sage_pon, - hmf_data.sage_blocklist_regions, - hmf_data.sage_blocklist_sites, - hmf_data.clinvar_annotations, - hmf_data.segment_mappability, - hmf_data.driver_gene_panel, - hmf_data.ensembl_data_resources, - hmf_data.gnomad_pon_dir, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(PAVE.out.versions) - ch_pave_germline_out = ch_pave_germline_out.mix(WorkflowOncoanalyser.restoreMeta(PAVE.out.germline, ch_inputs)) - ch_pave_somatic_out = ch_pave_somatic_out.mix(WorkflowOncoanalyser.restoreMeta(PAVE.out.somatic, ch_inputs)) - } - - // - // MODULE: Run PURPLE for CNV calling, purity and ploidy inference, SV recovery - // - // channel: [val(meta), purple_dir] - ch_purple_out = Channel.empty() - if (run.purple) { - // Select input sources - // channel: [val(meta), sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi] - ch_purple_inputs_sv = Channel.empty() - if (run.gripss) { - // NOTE(SW): GRIPSS will be run for all WGS entries, so no optionals here - ch_purple_inputs_sv = ch_gripss_somatic_out - } else { - ch_purple_inputs_sv = WorkflowOncoanalyser.groupByMeta( - WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_HARD_VCF_TUMOR, type: 'optional'), - WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_SOFT_VCF_TUMOR, type: 'optional'), - flatten_mode: 'nonrecursive', - ) - .map { meta, vcf_hard, vcf_soft -> - def tbi_hard = vcf_hard == [] ? [] : "${vcf_hard}.tbi" - def tbi_soft = vcf_soft == [] ? [] : "${vcf_soft}.tbi" - return [meta, vcf_hard, tbi_hard, vcf_soft, tbi_soft] - } - } - - // channel: [val(meta), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] - ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( - // Required inputs - run.amber ? ch_amber_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.AMBER_DIR), - run.cobalt ? ch_cobalt_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.COBALT_DIR), - // Optional inputs - ch_purple_inputs_sv, - run.pave ? ch_pave_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_TUMOR, type: 'optional'), - run.pave ? ch_pave_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_NORMAL, type: 'optional'), - flatten_mode: 'nonrecursive', - ) - - // Create process-specific meta - // channel: [val(meta_purple), amber_dir, cobalt_dir, sv_hard_vcf, sv_hard_tbi, sv_soft_vcf, sv_soft_tbi, smlv_tumor_vcf, smlv_normal_vcf] - ch_purple_inputs = ch_purple_inputs_source - .map { - def meta = it[0] - def other = it[1..-1] - def meta_purple = [ - key: meta.id, - id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - return [meta_purple, *other] - } - - PURPLE( - ch_purple_inputs, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_version, - hmf_data.gc_profile, - hmf_data.sage_known_hotspots_somatic, - hmf_data.sage_known_hotspots_germline, - hmf_data.driver_gene_panel, - hmf_data.ensembl_data_resources, - hmf_data.purple_germline_del, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(PURPLE.out.versions) - ch_purple_out = ch_purple_out.mix(WorkflowOncoanalyser.restoreMeta(PURPLE.out.purple_dir, ch_inputs)) - } - - // - // MODULE: Run Sigs to fit somatic smlv to signature definitions - // - if (run.sigs) { - // Select input sources - // channel: [val(meta), purple_dir] - if (run.purple) { - ch_sigs_inputs_source = ch_purple_out - } else { - ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - } - - // Create inputs and create process-specific meta - // channel: [val(meta_sigs), smlv_vcf] - ch_sigs_inputs = ch_sigs_inputs_source - .map { meta, purple_dir -> - def tumor_id = Utils.getTumorWgsSampleName(meta) - def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - - // Require smlv VCF from the PURPLE directory - if (!smlv_vcf.exists()) { - return Constants.META_PLACEHOLDER - } - - def meta_sigs = [ - id: meta.id, - tumor_id: meta.getAt(['sample_name', Constants.SampleType.TUMOR]), - ] - return [meta_sigs, smlv_vcf] - } - .filter { it[0] != Constants.META_PLACEHOLDER } - - SIGS( - ch_sigs_inputs, - hmf_data.sigs_signatures, - ) - - // Set outputs - ch_versions = ch_versions.mix(SIGS.out.versions) - } - - // - // MODULE: Run CHORD to predict HR deficiency status - // - // channel: [val(meta), chord_prediction] - ch_chord_out = Channel.empty() - if (run.chord) { - // Select input sources - // channel: [val(meta), purple_dir] - if (run.purple) { - ch_chord_inputs_source = ch_purple_out - } else { - ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - } - - // Create inputs and create process-specific meta - // channel: [val(meta), smlv_vcf, sv_vcf] - ch_chord_inputs = ch_chord_inputs_source - .map { meta, purple_dir -> - def tumor_id = Utils.getTumorWgsSampleName(meta) - def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") - - // Require both SV and smlv VCF from the PURPLE directory - if (!smlv_vcf.exists() || !sv_vcf.exists()) { - return Constants.META_PLACEHOLDER - } - - def meta_chord = [key: meta.id, id: meta.id] - return [meta_chord, smlv_vcf, sv_vcf] - } - .filter { it[0] != Constants.META_PLACEHOLDER } - - // Run process - CHORD( - ch_chord_inputs, - PREPARE_REFERENCE.out.genome_version, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(CHORD.out.versions) - ch_chord_out = ch_chord_out.mix(WorkflowOncoanalyser.restoreMeta(CHORD.out.prediction, ch_inputs)) - } - - // - // SUBWORKFLOW: Run LILAC for HLA typing and somatic CNV and SNV calling - // - // channel: [val(meta), lilac_dir] - ch_lilac_out = Channel.empty() - if (run.lilac) { - // Select input sources - // channel: [val(meta), purple_dir] - if (run.purple) { - ch_lilac_inputs_purple = Channel.empty() - .mix( - ch_purple_out, - ch_inputs_wgs.absent.map { meta -> [meta, []] }, - ) - } else { - ch_lilac_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional') - } - - // Create channel with all available input BAMs - // First obtain WTS BAMs - // channel: [val(meta), wts_bam, wts_bai] - ch_lilac_bams_wts = Channel.empty() - .mix( - ch_inputs_wts.present.map { meta -> - def bam = Utils.getTumorWtsBam(meta) - [meta, bam, "${bam}.bai"] - }, - ch_inputs_wts.absent.map { meta -> [meta, [], []] }, - ) - - ch_lilac_bams_wgs = Channel.empty() - .mix( - ch_inputs_wgs.present.map { meta -> - def tumor_bam = Utils.getTumorWgsBam(meta) - def normal_bam = Utils.getNormalWgsBam(meta) - [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] - }, - ch_inputs_wgs.absent.map { meta -> [meta, [], [], [], []] }, - ) - - // Combine WGS and WTS BAMs - // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] - ch_lilac_bams = WorkflowOncoanalyser.groupByMeta( - ch_lilac_bams_wts, - ch_lilac_bams_wgs, - flatten_mode: 'nonrecursive', - ) - .map { data -> - def meta = data[0] - def (tbam_wts, tbai_wts, tbam_wgs, nbam_wgs, tbai_wgs, nbai_wgs) = data[1..-1] - return [meta, nbam_wgs, nbai_wgs, tbam_wgs, tbai_wgs, tbam_wts, tbai_wts] - } - - // Call subworkflow to run processes - LILAC( - ch_lilac_bams, - ch_lilac_inputs_purple, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - hmf_data.lilac_resources, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(LILAC.out.versions) - ch_lilac_out = ch_lilac_out.mix(WorkflowOncoanalyser.restoreMeta(LILAC.out.results, ch_inputs)) - } - - // - // MODULE: Run VIRUSBreakend and Virus Interpreter to quantify viral content - // - ch_virusinterpreter_out = Channel.empty() - if (run.virusinterpreter) { - // VIRUSBreakend - // Create inputs and create process-specific meta - // channel: [val(meta_virus), tumor_bam] - ch_virusbreakend_inputs = ch_inputs_wgs.present - .map { meta -> - def meta_virus = [ - key: meta.id, - id: meta.id, - ] - return [meta_virus, Utils.getTumorWgsBam(meta)] - } - - // Run process - VIRUSBREAKEND( - ch_virusbreakend_inputs, - gridss_config, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_bwa_index, - PREPARE_REFERENCE.out.genome_bwa_index_image, - PREPARE_REFERENCE.out.genome_gridss_index, - PREPARE_REFERENCE.out.virusbreakenddb, - ) - - // Set outputs - ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) - - // Create inputs and create process-specific meta - if (run.purple) { - ch_virusinterpreter_inputs_purple = ch_purple_out - } else { - ch_virusinterpreter_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - } - - // channel: [val(meta), purple_qc, wgs_metrics] - ch_virusinterpreter_inputs_purple_files = ch_virusinterpreter_inputs_purple - .filter { it[0] != Constants.META_PLACEHOLDER } - .map { meta, purple_dir -> - def tumor_id = Utils.getTumorWgsSampleName(meta) - def purple_purity = file(purple_dir).resolve("${tumor_id}.purple.purity.tsv") - def purple_qc = file(purple_dir).resolve("${tumor_id}.purple.qc") - - // Require both purity and QC files from the PURPLE directory - if (!purple_purity.exists() || !purple_qc.exists()) { - return Constants.META_PLACEHOLDER - } - return [meta, purple_purity, purple_qc] - } - - - // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] - ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( - WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), - ch_virusinterpreter_inputs_purple_files, - run.bamtools ? ch_bamtools_out.somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_TUMOR), - ) - - // Virus Interpreter - // Create inputs and create process-specific meta - // channel: [val(meta_virus), virus_tsv, purple_purity, purple_qc, wgs_metrics] - ch_virusinterpreter_inputs = ch_virusinterpreter_inputs_full - .map { - def meta = it[0] - def meta_virus = [ - key: meta.id, - id: Utils.getTumorWgsSampleName(meta), - ] - return [meta_virus, *it[1..-1]] - } - - // Run process - VIRUSINTERPRETER( - ch_virusinterpreter_inputs, - hmf_data.virus_taxonomy_db, - hmf_data.virus_reporting_db, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) - ch_virusinterpreter_out = ch_virusinterpreter_out.mix(WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter, ch_inputs)) - } - - // - // SUBWORKFLOW: Group structural variants into higher order events with LINX - // - // channel: [val(meta), linx_annotation_dir, linx_visuliaser_dir] - ch_linx_somatic_out = Channel.empty() - // channel: [val(meta), linx_annotation_dir] - ch_linx_germline_out = Channel.empty() - if (run.linx) { - // Select input sources - // channel: [val(meta), vcf] - if (run.gripss) { - ch_linx_inputs_germline_source = ch_gripss_germline_out.map { meta, h, hi, s, si -> [meta, h] } - } else { - ch_linx_inputs_germline_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_HARD_VCF_TUMOR) - } - - // channel: [val(meta), sv_vcf, purple_dir] - ch_linx_inputs_somatic_source = run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - - // Create inputs and create process-specific meta - // channel: [val(meta_linx), sv_vcf] - ch_linx_inputs_germline = ch_linx_inputs_germline_source - .map { - def meta = it[0] - def meta_linx = [ - key: meta.id, - id: Utils.getNormalWgsSampleName(meta), - ] - return [meta_linx, it[1..-1]] - } - - // channel: [val(meta_linx), purple_dir] - ch_linx_inputs_somatic = ch_linx_inputs_somatic_source - .map { - def meta = it[0] - def meta_linx = [ - key: meta.id, - id: Utils.getTumorWgsSampleName(meta), - ] - return [meta_linx, it[1..-1]] - } - - // Run process - LINX( - ch_linx_inputs_germline, - ch_linx_inputs_somatic, - PREPARE_REFERENCE.out.genome_version, - hmf_data.linx_fragile_regions, - hmf_data.linx_lines, - hmf_data.ensembl_data_resources, - hmf_data.known_fusion_data, - hmf_data.driver_gene_panel, - linx_gene_id_file, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(LINX.out.versions) - ch_linx_somatic_out = ch_linx_somatic_out.mix(WorkflowOncoanalyser.restoreMeta(LINX.out.somatic, ch_inputs)) - ch_linx_germline_out = ch_linx_germline_out.mix(WorkflowOncoanalyser.restoreMeta(LINX.out.germline, ch_inputs)) - - // - // MODULE: Run gpgr to generate a LINX report - // - // Create inputs and create process-specific meta - // channel: [meta(meta_gpgr_linx), anno_dir, vis_dir] - ch_gpgr_linx_inputs = ch_linx_somatic_out - .map { meta, anno_dir, vis_dir -> - def meta_gpgr_linx = [ - key: meta.id, - id: Utils.getTumorWgsSampleName(meta), - ] - return [meta_gpgr_linx, anno_dir, vis_dir] - } - - // Run process - GPGR_LINX( - ch_gpgr_linx_inputs, - ) - - // Set outputs - ch_versions = ch_versions.mix(GPGR_LINX.out.versions) - } - - // - // MODULE: Run PROTECT to match somatic genomic features with treatment evidence - // - // channel: [val(meta), protect] - ch_protect_out = Channel.empty() - if (run.protect) { - // Select input sources - - // channel: [val(meta), linx_somatic_annotation_dir] - ch_linx_anno = ch_linx_somatic_out.map { meta, anno_dir, vis_dir -> [meta, anno_dir]} - - // channel: [val(meta), chord_prediction, purple_dir, linx_dir, virusinterpreter] - ch_protect_inputs_source = WorkflowOncoanalyser.groupByMeta( - run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_PREDICTION), - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), - run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), - run.lilac ? ch_lilac_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV), - ) - - // Create process-specific meta - // channel: [val(meta_protect), chord_prediction, purple_dir, linx_dir, virusinterpreter] - ch_protect_inputs = ch_protect_inputs_source - .map { - def meta = it[0] - def other = it[1..-1] - def meta_protect = [ - key: meta.id, - id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - return [meta_protect, *other] - } - - // Run process - PROTECT( - ch_protect_inputs, - PREPARE_REFERENCE.out.genome_version, - hmf_data.serve_resources, - hmf_data.driver_gene_panel, - hmf_data.disease_ontology, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(PROTECT.out.versions) - ch_protect_out = ch_protect_out.mix(WorkflowOncoanalyser.restoreMeta(PROTECT.out.tsv, ch_inputs)) - } - - // - // MODULE: Run PEACH to match germline SNVs with pharmacogenetic evidence - // - // channel: [val(meta), peach_genotype] - ch_peach_out = Channel.empty() - if (run.peach) { - // Select input sources - // channel: [val(meta), purple_dir] - if (run.purple) { - ch_peach_inputs_source = ch_purple_out - } else { - ch_peach_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - } - - // Create inputs and create process-specific meta - // channel: [meta_peach, purple_germline_vcf] - ch_peach_inputs = ch_peach_inputs_source - .map { meta, purple_dir -> - def meta_peach = [ - key: meta.id, - id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - def tumor_id = Utils.getTumorWgsSampleName(meta) - def purple_germline_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") - - if (!purple_germline_vcf.exists()) { - return Constants.META_PLACEHOLDER - } - - return [meta_peach, purple_germline_vcf] - } - .filter { it[0] != Constants.META_PLACEHOLDER } - - // Run process - PEACH( - ch_peach_inputs, - PREPARE_REFERENCE.out.genome_version, - hmf_data.peach_panel, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(PEACH.out.versions) - ch_peach_out = ch_peach_out.mix(WorkflowOncoanalyser.restoreMeta(PEACH.out.genotype, ch_inputs)) - } - - // - // MODULE: Run CUPPA predict tissue of origin - // - // channel: [val(meta), cuppa_results] - ch_cuppa_out = Channel.empty() - // channel: [val(meta), cuppa_summary_plot] - ch_cuppa_summary_plot_out = Channel.empty() - // channel: [val(meta), cuppa_feature_plot] - ch_cuppa_feature_plot_out = Channel.empty() - if (run.cuppa) { - // Select input sources - // channel: [val(meta), isofox_dir] - ch_cuppa_inputs_isofox = Channel.empty() - if (run.isofox) { - // Take Isofox output and supplement with placeholders for missing; i.e. allow optional - ch_cuppa_inputs_isofox = ch_cuppa_inputs_isofox - .mix( - ch_isofox_out, - ch_inputs_wts.absent.map { meta -> [meta, []] }, - ) - } else { - ch_cuppa_inputs_isofox = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX, type: 'optional') - } - - // channel: [val(meta), linx_somatic_annotation_dir] - ch_linx_anno = ch_linx_somatic_out.map { meta, anno_dir, vis_dir -> [meta, anno_dir]} - - // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter] - ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( - ch_cuppa_inputs_isofox, - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional'), - run.linx ? ch_linx_anno : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR, type: 'optional'), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), - flatten_mode: 'nonrecursive', - ) - - // Create inputs and create process-specific meta - // channel: [val(meta_cuppa), isofox_dir, purple_dir, linx_dir, virusinterpreter] - ch_cuppa_inputs = ch_cuppa_inputs_source - .map { data -> - def meta = data[0] - def meta_cuppa = [key: meta.id] - - def sample_name_wgs = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) - def sample_name_wts = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) - - if (sample_name_wgs && sample_name_wts) { - meta_cuppa.id = sample_name_wgs - meta_cuppa.id_wts = sample_name_wts - } else if (sample_name_wgs) { - meta_cuppa.id = sample_name_wgs - } else if (sample_name_wts) { - meta_cuppa.id = sample_name_wts - } else { - log.error "ERROR: no sample name for: ${meta}" - System.exit(1) - } - - return [meta_cuppa, *data[1..-1]] - } - - // Run process - CUPPA_CLASSIFIER( - ch_cuppa_inputs, - PREPARE_REFERENCE.out.genome_version, - hmf_data.cuppa_resources, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(CUPPA_CLASSIFIER.out.versions) - ch_cuppa_out = ch_cuppa_out.mix(WorkflowOncoanalyser.restoreMeta(CUPPA_CLASSIFIER.out.csv, ch_inputs)) - - // Run process - CUPPA_VISUALISER( - CUPPA_CLASSIFIER.out.csv, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(CUPPA_VISUALISER.out.versions) - ch_cuppa_summary_plot_out = ch_cuppa_summary_plot_out.mix(WorkflowOncoanalyser.restoreMeta(CUPPA_VISUALISER.out.summary_plot, ch_inputs)) - ch_cuppa_feature_plot_out = ch_cuppa_feature_plot_out.mix(WorkflowOncoanalyser.restoreMeta(CUPPA_VISUALISER.out.feature_plot, ch_inputs)) - } - - // - // MODULE: Run ORANGE to generate static PDF report - // - if (run.orange) { - // SAMtools flagstat - // Select input source - // channel (present): [val(meta), sample_type, flagstat] - // channel (absent): [val(meta)] - ch_inputs_flagstat = ch_inputs_wgs.present - .flatMap { meta -> [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL].collect { [meta, it] } } - .branch { meta, sample_type -> - def key = [Constants.FileType.FLAGSTAT, sample_type, Constants.SequenceType.WGS] - present: meta.containsKey(key) - return [meta, sample_type, meta.getAt(key)] - absent: ! meta.containsKey(key) - } - - // Create inputs and create process-specific meta - // channel: [val(meta_flagstat), bam, bai] - ch_flagstat_inputs_all = ch_inputs_flagstat.absent - .map { meta, sample_type -> - def bam = meta.getAt([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) - def sample_name = meta.getAt(['sample_name', sample_type, Constants.SequenceType.WGS]) - def meta_flagstat = [ - key: meta.id, - id: sample_name, - // NOTE(SW): must use string representation for caching purposes - sample_type_str: sample_type.name(), - ] - return [meta_flagstat, bam, "${bam}.bai"] - } - - // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples - // channel: [val(meta_flagstat_shared), bam, bai] - ch_flagstat_inputs = ch_flagstat_inputs_all - .map { [it[1..-1], it[0]] } - .groupTuple() - .map { filepaths, meta_flagstat -> - def (keys, sample_names, sample_type_strs) = meta_flagstat - .collect { - [it.key, it.id, it.sample_type_str] - } - .transpose() - - def sample_type_strs_unique = sample_type_strs.unique(false) - assert sample_type_strs_unique.size() == 1 - def sample_type_str = sample_type_strs_unique[0] - - def meta_flagstat_new = [ - keys: keys, - id: sample_names.join('__'), - id_simple: keys.join('__'), - sample_type_str: sample_type_str, - ] - return [meta_flagstat_new, *filepaths] - } - - // Run process - SAMTOOLS_FLAGSTAT( - ch_flagstat_inputs, - ) - - // Set version - ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) - - // Replicate outputs to reverse unique operation - // channel: [val(meta_flagstat_individual), flagstat] - ch_flagstat_out = SAMTOOLS_FLAGSTAT.out.flagstat - .flatMap { meta_flagstat_shared, flagstat -> - def sample_type = Utils.getEnumFromString(meta_flagstat_shared.sample_type_str, Constants.SampleType) - meta_flagstat_shared.keys.collect { key -> - return [meta_flagstat_shared + [key: key], sample_type, flagstat] - } - } - - // Combine input flagstat channels, restoring original meta where required, split by sample type - // channel (somatic): [val(meta), flagstat] - // channel (germline): [val(meta), flagstat] - ch_orange_inputs_flagstat = Channel.empty() - .concat( - ch_inputs_flagstat.present, - WorkflowOncoanalyser.restoreMeta(ch_flagstat_out, ch_inputs), - ) - .branch { meta, sample_type, flagstat -> - somatic: sample_type == Constants.SampleType.TUMOR - return [meta, flagstat] - germline: sample_type == Constants.SampleType.NORMAL - return [meta, flagstat] - } - - // ORANGE - // Split LINX channel - // channel (anno): [val(meta), anno_dir] - // channel (plot): [val(meta), plot_dir] - ch_orange_inputs_linx_somatic = ch_linx_somatic_out - .multiMap { meta, anno_dir, plot_dir -> - anno: [meta, anno_dir] - plot: [meta, plot_dir] - } - - // TODO(SW): handle CUPPA WTS, WGS, WGS - - // Select input source - // NOTE(SW): we could consider not allowing inputs from the samplesheet here since this nothing follows - ch_orange_inputs_source = WorkflowOncoanalyser.groupByMeta( - run.bamtools ? ch_bamtools_out.somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_TUMOR), - run.bamtools ? ch_bamtools_out.germline: WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_NORMAL), - ch_orange_inputs_flagstat.somatic, - ch_orange_inputs_flagstat.germline, - run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD), - run.lilac ? ch_lilac_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), - run.sage ? ch_sage_somatic_tumor_bqr_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_TUMOR), - run.sage ? ch_sage_somatic_normal_bqr_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_NORMAL), - run.sage ? ch_sage_germline_coverage_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_COVERAGE), - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), - run.linx ? ch_orange_inputs_linx_somatic.anno : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), - run.linx ? ch_orange_inputs_linx_somatic.plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_TUMOR), - run.linx ? ch_linx_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_NORMAL), - run.protect ? ch_protect_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PROTECT_TSV), - run.peach ? ch_peach_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PEACH_TSV), - run.cuppa ? ch_cuppa_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUTS_CUPPA_CSV), - run.cuppa ? ch_cuppa_feature_plot_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_FEATURE_PLOT), - run.cuppa ? ch_cuppa_summary_plot_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_SUMMARY_PLOT), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV), - ) - - ch_orange_inputs = ch_orange_inputs_source - .map { - def meta = it[0] - def meta_orange = [ - key: meta.id, - id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - return [meta_orange, *it[1..-1]] - } - - // Run process - ORANGE( - ch_orange_inputs, - PREPARE_REFERENCE.out.genome_version, - hmf_data.disease_ontology, - hmf_data.known_fusion_data, - hmf_data.driver_gene_panel, - hmf_data.cohort_mapping, - hmf_data.cohort_percentiles, - "5.31 [oncoanalyser]", - ) - - // Set outputs - ch_versions = ch_versions.mix(ORANGE.out.versions) - } - - // - // MODULE: Pipeline reporting - // - // Run process - CUSTOM_DUMPSOFTWAREVERSIONS( - ch_versions.unique().collectFile(name: 'collated_versions.yml') - ) -} - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - COMPLETION EMAIL AND SUMMARY -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -workflow.onComplete { - if (params.email || params.email_on_fail) { - NfcoreTemplate.email(workflow, params, summary_params, projectDir, log) - } - NfcoreTemplate.summary(workflow, params, log) - if (params.hook_url) { - NfcoreTemplate.adaptivecard(workflow, params, summary_params, projectDir, log) - } -} - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - THE END -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ diff --git a/workflows/wgts.nf b/workflows/wgts.nf new file mode 100644 index 00000000..aa33eab0 --- /dev/null +++ b/workflows/wgts.nf @@ -0,0 +1,789 @@ +import Constants +import Processes +import Utils + + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + VALIDATE INPUTS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) + +// Validate input parameters +WorkflowOncoanalyser.initialise(params, workflow, log) + +// Set processes to run +processes = Processes.setProcesses(params.mode, log) +processes_include = Processes.getProcessList(params.processes_include, log) +processes_exclude = Processes.getProcessList(params.processes_exclude, log) +Processes.checkIncludeExcludeList(processes_include, processes_exclude, log) + +processes.addAll(processes_include) +processes.removeAll(processes_exclude) + +run = Constants.Process + .values() + .collectEntries { p -> [p.name().toLowerCase(), p in processes] } + +// Check input path parameters to see if they exist +def checkPathParamList = [ + params.input, + params.gridss_config, + params.linx_gene_id_file, +] + +for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } + +// Check mandatory parameters +if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } + +// Create Path objects for some input files +linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : [] + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CONFIG FILES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT LOCAL MODULES/SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// +// MODULES +// +include { CHORD } from '../modules/local/chord/main' +include { ISOFOX } from '../modules/local/isofox/main' +include { PEACH } from '../modules/local/peach/main' +include { PROTECT } from '../modules/local/protect/main' +include { SIGS } from '../modules/local/sigs/main' + +// +// SUBWORKFLOWS +// +include { AMBER_PROFILING } from '../subworkflows/local/amber_profiling' +include { BAMTOOLS_METRICS } from '../subworkflows/local/bamtools_metrics' +include { COBALT_PROFILING } from '../subworkflows/local/cobalt_profiling' +include { CUPPA_PREDICTION } from '../subworkflows/local/cuppa_prediction' +include { GRIDSS_CALLING } from '../subworkflows/local/gridss_calling' +include { GRIDSS_SVPREP_CALLING } from '../subworkflows/local/gridss_svprep_calling' +include { GRIPSS_FILTERING } from '../subworkflows/local/gripss_filtering' +include { LILAC_CALLING } from '../subworkflows/local/lilac_calling' +include { LINX_ANNOTATION } from '../subworkflows/local/linx_annotation' +include { LINX_PLOTTING } from '../subworkflows/local/linx_plotting' +include { ORANGE_REPORTING } from '../subworkflows/local/orange_reporting' +include { PAVE_ANNOTATION } from '../subworkflows/local/pave_annotation' +include { PREPARE_INPUT } from '../subworkflows/local/prepare_input' +include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' +include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' +include { SAGE_CALLING } from '../subworkflows/local/sage_calling' +include { VIRUSBREAKEND_CALLING } from '../subworkflows/local/virusbreakend_calling' + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT NF-CORE MODULES/SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// +// MODULES +// +include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + RUN MAIN WORKFLOW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// Get absolute file paths +samplesheet = Utils.getFileObject(params.input) +gridss_config = Utils.getFileObject(params.gridss_config) + +workflow WGTS { + // Create channel for versions + // channel: [versions.yml] + ch_versions = Channel.empty() + + // Get inputs from samplesheet + // channel: [val(meta)] + PREPARE_INPUT( + samplesheet, + ) + ch_inputs = PREPARE_INPUT.out.data + + // Split inputs WTS and WGS + // NOTE(SW): assuming there are only t/n pairs i.e. no tumor-only or normal-only + + // channel (present): [val(meta)] + // channel (absent): [val(meta)] + ch_inputs_wgs = ch_inputs + .branch { meta -> + def key_tumor = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS] + def key_normal = [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.WGS] + present: meta.containsKey(key_tumor) && meta.containsKey(key_normal) + return meta + absent: true + return meta + } + + // channel (present): [val(meta)] + // channel (absent): [val(meta)] + ch_inputs_wts = ch_inputs + .branch { meta -> + def key = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WTS] + present: meta.containsKey(key) + return meta + absent: ! meta.containsKey(key) + return meta + } + + // Set up reference data and unpack HMF data map for convenience + PREPARE_REFERENCE(run) + hmf_data = PREPARE_REFERENCE.out.hmf_data + + // + // MODULE: Run Isofox to analyse WTS data + // + // channel: [meta, isofox_dir] + ch_isofox_out = Channel.empty() + if (run.isofox) { + // Create inputs and create process-specific meta + // channel: [meta_isofox, tumor_bam_wts] + ch_isofox_inputs = ch_inputs_wts.present + .map { meta -> + def bam = Utils.getTumorWtsBam(meta) + def meta_isofox = [key: meta.id, id: Utils.getTumorWtsSampleName(meta)] + return [meta_isofox, bam, "${bam}.bai"] + } + + // Set Isofox cache files + // NOTE(SW): the Isofox expected count file is read length dependent so required users to explicitly use expect + // counts generated for 151 bp reads that is available in the HMF reference bundle. When not specifying an + // expected count file, Isofox will automatically create one for the computed read length. However, doing so + // greatly increases runtime. + // NOTE(SW): consider alternative approaches for using the expected count file e.g. generate once at runtime, + // then use for all samples; generate all possible read lengths outside of pipeline and store on a remote for + // retrieval at runtime (requires inference of read length) + + // TODO(SW): this must be improved to allow users to set input file, use cache, or generate at runtime; + // currently does not update functions + // NOTE(SW): forcing use of cache for now since this feature is incomplete + + //isofox_counts = params.use_isofox_exp_counts_cache ? hmf_data.isofox_counts : [] + isofox_counts = hmf_data.isofox_counts + + // Run process + ISOFOX( + ch_isofox_inputs, + params.isofox_functions, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_version, + hmf_data.ensembl_data_resources, + isofox_counts, + hmf_data.isofox_gc_ratios, + ) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix(ISOFOX.out.versions) + ch_isofox_out = ch_isofox_out.mix(WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs)) + } + + // + // MODULE: Run Bam Tools to generate stats required for downstream processes + // + // channel: [val(meta), metrics] + ch_bamtools_somatic_out = Channel.empty() + ch_bamtools_germline_out = Channel.empty() + if (run.bamtools) { + + BAMTOOLS_METRICS( + ch_inputs_wgs.present, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_version, + run, + ) + + ch_versions = ch_versions.mix(BAMTOOLS_METRICS.out.versions) + ch_bamtools_somatic_out = ch_bamtools_somatic_out.mix(BAMTOOLS_METRICS.out.somatic) + ch_bamtools_germline_out = ch_bamtools_germline_out.mix(BAMTOOLS_METRICS.out.germline) + } + + // + // MODULE: Run AMBER to obtain b-allele frequencies + // + // channel: [val(meta), amber_dir] + ch_amber_out = Channel.empty() + if (run.amber) { + + AMBER_PROFILING( + ch_inputs_wgs.present, + PREPARE_REFERENCE.out.genome_version, + hmf_data.heterozygous_sites, + ) + + ch_versions = ch_versions.mix(AMBER_PROFILING.out.versions) + ch_amber_out = ch_amber_out.mix(AMBER_PROFILING.out.amber_dir) + } + + // + // MODULE: Run COBALT to obtain read ratios + // + // channel: [val(meta), cobalt_dir] + ch_cobalt_out = Channel.empty() + if (run.cobalt) { + + COBALT_PROFILING( + ch_inputs_wgs.present, + hmf_data.gc_profile, + ) + + ch_versions = ch_versions.mix(COBALT_PROFILING.out.versions) + ch_cobalt_out = ch_cobalt_out.mix(COBALT_PROFILING.out.cobalt_dir) + } + + // + // SUBWORKFLOW: Call structural variants with GRIDSS + // + // channel: [val(meta), gridss_vcf] + ch_gridss_out = Channel.empty() + if (run.gridss) { + if (run.svprep) { + + GRIDSS_SVPREP_CALLING( + ch_inputs_wgs.present, + gridss_config, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_version, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_bwa_index, + PREPARE_REFERENCE.out.genome_bwa_index_image, + PREPARE_REFERENCE.out.genome_gridss_index, + hmf_data.gridss_region_blocklist, + hmf_data.sv_prep_blocklist, + hmf_data.known_fusions, + ) + + ch_versions = ch_versions.mix(GRIDSS_SVPREP_CALLING.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP_CALLING.out.results) + + } else { + + GRIDSS_CALLING( + ch_inputs_wgs.present, + gridss_config, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_bwa_index, + PREPARE_REFERENCE.out.genome_bwa_index_image, + PREPARE_REFERENCE.out.genome_gridss_index, + hmf_data.gridss_region_blocklist, + ) + + ch_versions = ch_versions.mix(GRIDSS_CALLING.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS_CALLING.out.results) + } + } + + // + // MODULE: Run GRIPSS to filter GRIDSS SV calls + // + // channel: [val(meta), vcf, tbi] + ch_gripss_somatic_out = Channel.empty() + ch_gripss_somatic_unfiltered_out = Channel.empty() + ch_gripss_germline_out = Channel.empty() + if (run.gripss) { + + GRIPSS_FILTERING( + ch_inputs, + ch_gridss_out, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_version, + hmf_data.gridss_pon_breakends, + hmf_data.gridss_pon_breakpoints, + hmf_data.known_fusions, + hmf_data.repeatmasker_annotations, + run, + ) + + ch_versions = ch_versions.mix(GRIPSS_FILTERING.out.versions) + ch_gripss_somatic_out = ch_gripss_somatic_out.mix(GRIPSS_FILTERING.out.somatic) + ch_gripss_somatic_unfiltered_out = ch_gripss_somatic_unfiltered_out.mix(GRIPSS_FILTERING.out.somatic_unfiltered) + ch_gripss_germline_out = ch_gripss_germline_out.mix(GRIPSS_FILTERING.out.germline) + } + + // + // SUBWORKFLOW: call SNV, MNV, and small INDELS with SAGE + // + // channel: [val(meta), sage_vcf, sage_tbi] + ch_sage_germline_vcf_out = Channel.empty() + ch_sage_somatic_vcf_out = Channel.empty() + // channel: [val(meta), sage_coverage] + ch_sage_germline_coverage_out = Channel.empty() + // channel: [val(meta), bqr_plot] + ch_sage_somatic_tumor_bqr_out = Channel.empty() + ch_sage_somatic_normal_bqr_out = Channel.empty() + if (run.sage) { + + SAGE_CALLING( + ch_inputs_wgs.present, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_version, + hmf_data.sage_known_hotspots_germline, + hmf_data.sage_known_hotspots_somatic, + hmf_data.sage_actionable_panel, + hmf_data.sage_coverage_panel, + hmf_data.sage_highconf_regions, + hmf_data.sage_pon, + hmf_data.segment_mappability, + hmf_data.driver_gene_panel, + hmf_data.ensembl_data_resources, + ) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix(SAGE_CALLING.out.versions) + ch_sage_germline_vcf_out = ch_sage_germline_vcf_out.mix(SAGE_CALLING.out.germline_vcf) + ch_sage_germline_coverage_out = ch_sage_germline_coverage_out.mix(SAGE_CALLING.out.germline_coverage) + ch_sage_somatic_vcf_out = ch_sage_somatic_vcf_out.mix(SAGE_CALLING.out.somatic_vcf) + ch_sage_somatic_tumor_bqr_out = ch_sage_somatic_tumor_bqr_out.mix(SAGE_CALLING.out.somatic_tumor_bqr) + ch_sage_somatic_normal_bqr_out = ch_sage_somatic_normal_bqr_out.mix(SAGE_CALLING.out.somatic_normal_bqr) + } + + // + // SUBWORKFLOW: Annotate variants with PAVE + // + // channel: [val(meta), pave_vcf] + ch_pave_germline_out = Channel.empty() + ch_pave_somatic_out = Channel.empty() + if (run.pave) { + + PAVE_ANNOTATION( + ch_inputs, + ch_sage_germline_vcf_out, + ch_sage_somatic_vcf_out, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_version, + hmf_data.sage_pon, + hmf_data.sage_blocklist_regions, + hmf_data.sage_blocklist_sites, + hmf_data.clinvar_annotations, + hmf_data.segment_mappability, + hmf_data.driver_gene_panel, + hmf_data.ensembl_data_resources, + hmf_data.gnomad_pon_dir, + run, + ) + + ch_versions = ch_versions.mix(PAVE_ANNOTATION.out.versions) + ch_pave_germline_out = ch_pave_germline_out.mix(PAVE_ANNOTATION.out.germline) + ch_pave_somatic_out = ch_pave_somatic_out.mix(PAVE_ANNOTATION.out.somatic) + } + + // + // SUBWORKFLOW: Call CNVs, infer purity and ploidy, and recover low quality SVs with PURPLE + // + // channel: [val(meta), purple_dir] + ch_purple_out = Channel.empty() + if (run.purple) { + + PURPLE_CALLING( + ch_inputs, + ch_amber_out, + ch_cobalt_out, + ch_pave_somatic_out, + ch_pave_germline_out, + ch_gripss_somatic_out, + ch_gripss_somatic_unfiltered_out, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_version, + hmf_data.gc_profile, + hmf_data.sage_known_hotspots_somatic, + hmf_data.sage_known_hotspots_germline, + hmf_data.driver_gene_panel, + hmf_data.ensembl_data_resources, + hmf_data.purple_germline_del, + run, + ) + + ch_versions = ch_versions.mix(PURPLE_CALLING.out.versions) + ch_purple_out = ch_purple_out.mix(PURPLE_CALLING.out.purple_dir) + } + + // + // MODULE: Run Sigs to fit somatic smlv to signature definitions + // + if (run.sigs) { + // Select input sources + // channel: [val(meta), purple_dir] + if (run.purple) { + ch_sigs_inputs_source = ch_purple_out + } else { + ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + } + + // Create inputs and create process-specific meta + // channel: [val(meta_sigs), smlv_vcf] + ch_sigs_inputs = ch_sigs_inputs_source + .map { meta, purple_dir -> + def tumor_id = Utils.getTumorWgsSampleName(meta) + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + + // Require smlv VCF from the PURPLE directory + if (!smlv_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + + def meta_sigs = [ + id: meta.id, + tumor_id: meta.getAt(['sample_name', Constants.SampleType.TUMOR]), + ] + return [meta_sigs, smlv_vcf] + } + .filter { it[0] != Constants.META_PLACEHOLDER } + + SIGS( + ch_sigs_inputs, + hmf_data.sigs_signatures, + ) + + // Set outputs + ch_versions = ch_versions.mix(SIGS.out.versions) + } + + // + // MODULE: Run CHORD to predict HR deficiency status + // + // channel: [val(meta), chord_prediction] + ch_chord_out = Channel.empty() + if (run.chord) { + // Select input sources + // channel: [val(meta), purple_dir] + if (run.purple) { + ch_chord_inputs_source = ch_purple_out + } else { + ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + } + + // Create inputs and create process-specific meta + // channel: [val(meta), smlv_vcf, sv_vcf] + ch_chord_inputs = ch_chord_inputs_source + .map { meta, purple_dir -> + def tumor_id = Utils.getTumorWgsSampleName(meta) + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") + + // Require both SV and smlv VCF from the PURPLE directory + if (!smlv_vcf.exists() || !sv_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + + def meta_chord = [key: meta.id, id: meta.id] + return [meta_chord, smlv_vcf, sv_vcf] + } + .filter { it[0] != Constants.META_PLACEHOLDER } + + // Run process + CHORD( + ch_chord_inputs, + PREPARE_REFERENCE.out.genome_version, + ) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix(CHORD.out.versions) + ch_chord_out = ch_chord_out.mix(WorkflowOncoanalyser.restoreMeta(CHORD.out.prediction, ch_inputs)) + } + + // + // SUBWORKFLOW: Run LILAC for HLA typing and somatic CNV and SNV calling + // + // channel: [val(meta), lilac_dir] + ch_lilac_out = Channel.empty() + if (run.lilac) { + + // TODO(SW): improve interface here + LILAC_CALLING( + ch_inputs, + ch_inputs_wgs.present, + ch_inputs_wgs.absent, + ch_inputs_wts.present, + ch_inputs_wts.absent, + ch_purple_out, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + hmf_data.lilac_resources, + run, + ) + + ch_versions = ch_versions.mix(LILAC_CALLING.out.versions) + ch_lilac_out = ch_lilac_out.mix(LILAC_CALLING.out.lilac_dir) + } + + // + // SUBWORKFLOW: Run VIRUSBreakend and Virus Interpreter to quantify viral content + // + ch_virusinterpreter_out = Channel.empty() + if (run.virusinterpreter) { + + VIRUSBREAKEND_CALLING( + ch_inputs_wgs.present, + ch_purple_out, + ch_bamtools_somatic_out, + PREPARE_REFERENCE.out.genome_fasta, + PREPARE_REFERENCE.out.genome_fai, + PREPARE_REFERENCE.out.genome_dict, + PREPARE_REFERENCE.out.genome_bwa_index, + PREPARE_REFERENCE.out.genome_bwa_index_image, + PREPARE_REFERENCE.out.genome_gridss_index, + PREPARE_REFERENCE.out.virusbreakenddb, + hmf_data.virus_taxonomy_db, + hmf_data.virus_reporting_db, + run, + gridss_config, + ) + + ch_versions = ch_versions.mix(VIRUSBREAKEND_CALLING.out.versions) + ch_virusinterpreter_out = ch_virusinterpreter_out.mix(VIRUSBREAKEND_CALLING.out.virusinterpreter) + } + + // + // SUBWORKFLOW: Group structural variants into higher order events with LINX + // + // channel: [val(meta), linx_annotation_dir] + ch_linx_somatic_out = Channel.empty() + ch_linx_germline_out = Channel.empty() + // channel: [val(meta), linx_visualiser_dir] + ch_linx_somatic_plot_out = Channel.empty() + if (run.linx) { + + LINX_ANNOTATION( + ch_inputs, + ch_gripss_germline_out, + ch_purple_out, + PREPARE_REFERENCE.out.genome_version, + hmf_data.linx_fragile_regions, + hmf_data.linx_lines, + hmf_data.ensembl_data_resources, + hmf_data.known_fusion_data, + hmf_data.driver_gene_panel, + linx_gene_id_file, + run, + ) + + ch_versions = ch_versions.mix(LINX_ANNOTATION.out.versions) + ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX_ANNOTATION.out.somatic) + ch_linx_germline_out = ch_linx_germline_out.mix(LINX_ANNOTATION.out.germline) + + LINX_PLOTTING( + ch_inputs, + ch_linx_somatic_out, + PREPARE_REFERENCE.out.genome_version, + hmf_data.ensembl_data_resources, + ) + + ch_versions = ch_versions.mix(LINX_PLOTTING.out.versions) + ch_linx_somatic_plot_out = ch_linx_somatic_plot_out.mix(LINX_PLOTTING.out.visualiser_dir) + } + + // + // MODULE: Run PROTECT to match somatic genomic features with treatment evidence + // + // channel: [val(meta), protect] + ch_protect_out = Channel.empty() + if (run.protect) { + // Select input sources + // channel: [val(meta), chord_prediction, purple_dir, linx_dir, virusinterpreter] + ch_protect_inputs_source = WorkflowOncoanalyser.groupByMeta( + run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_PREDICTION), + run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), + run.linx ? ch_linx_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + run.lilac ? ch_lilac_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), + run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV), + ) + + // Create process-specific meta + // channel: [val(meta_protect), chord_prediction, purple_dir, linx_dir, virusinterpreter] + ch_protect_inputs = ch_protect_inputs_source + .map { + def meta = it[0] + def other = it[1..-1] + def meta_protect = [ + key: meta.id, + id: meta.id, + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), + ] + return [meta_protect, *other] + } + + // Run process + PROTECT( + ch_protect_inputs, + PREPARE_REFERENCE.out.genome_version, + hmf_data.serve_resources, + hmf_data.driver_gene_panel, + hmf_data.disease_ontology, + ) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix(PROTECT.out.versions) + ch_protect_out = ch_protect_out.mix(WorkflowOncoanalyser.restoreMeta(PROTECT.out.tsv, ch_inputs)) + } + + // + // MODULE: Run PEACH to match germline SNVs with pharmacogenetic evidence + // + // channel: [val(meta), peach_genotype] + ch_peach_out = Channel.empty() + if (run.peach) { + // Select input sources + // channel: [val(meta), purple_dir] + if (run.purple) { + ch_peach_inputs_source = ch_purple_out + } else { + ch_peach_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + } + + // Create inputs and create process-specific meta + // channel: [meta_peach, purple_germline_vcf] + ch_peach_inputs = ch_peach_inputs_source + .map { meta, purple_dir -> + def meta_peach = [ + key: meta.id, + id: meta.id, + tumor_id: Utils.getTumorWgsSampleName(meta), + normal_id: Utils.getNormalWgsSampleName(meta), + ] + def tumor_id = Utils.getTumorWgsSampleName(meta) + def purple_germline_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") + + if (!purple_germline_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + + return [meta_peach, purple_germline_vcf] + } + .filter { it[0] != Constants.META_PLACEHOLDER } + + // Run process + PEACH( + ch_peach_inputs, + PREPARE_REFERENCE.out.genome_version, + hmf_data.peach_panel, + ) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix(PEACH.out.versions) + ch_peach_out = ch_peach_out.mix(WorkflowOncoanalyser.restoreMeta(PEACH.out.genotype, ch_inputs)) + } + + // + // SUBWORKFLOW: Run CUPPA predict tissue of origin + // + // channel: [val(meta), cuppa_results] + ch_cuppa_out = Channel.empty() + // channel: [val(meta), cuppa_summary_plot] + ch_cuppa_summary_plot_out = Channel.empty() + // channel: [val(meta), cuppa_feature_plot] + ch_cuppa_feature_plot_out = Channel.empty() + if (run.cuppa) { + + CUPPA_PREDICTION( + ch_inputs, + ch_inputs_wts.absent, + ch_isofox_out, + ch_purple_out, + ch_linx_somatic_out, + ch_virusinterpreter_out, + PREPARE_REFERENCE.out.genome_version, + hmf_data.cuppa_resources, + run, + ) + + ch_versions = ch_versions.mix(CUPPA_PREDICTION.out.versions) + ch_cuppa_out = ch_cuppa_out.mix(CUPPA_PREDICTION.out.csv) + ch_cuppa_summary_plot_out = ch_cuppa_summary_plot_out.mix(CUPPA_PREDICTION.out.summary_plot) + ch_cuppa_feature_plot_out = ch_cuppa_feature_plot_out.mix(CUPPA_PREDICTION.out.feature_plot) + } + + // + // SUBWORKFLOW: Run ORANGE to generate static PDF report + // + if (run.orange) { + + ORANGE_REPORTING( + ch_inputs, + ch_inputs_wgs.present, + ch_bamtools_somatic_out, + ch_bamtools_germline_out, + ch_chord_out, + ch_lilac_out, + ch_sage_somatic_tumor_bqr_out, + ch_sage_somatic_normal_bqr_out, + ch_sage_germline_coverage_out, + ch_purple_out, + ch_linx_somatic_out, + ch_linx_somatic_plot_out, + ch_linx_germline_out, + ch_protect_out, + ch_peach_out, + ch_cuppa_out, + ch_cuppa_feature_plot_out, + ch_cuppa_summary_plot_out, + ch_virusinterpreter_out, + PREPARE_REFERENCE.out.genome_version, + hmf_data.disease_ontology, + hmf_data.known_fusion_data, + hmf_data.driver_gene_panel, + hmf_data.cohort_mapping, + hmf_data.cohort_percentiles, + run, + ) + + ch_versions = ch_versions.mix(ORANGE_REPORTING.out.versions) + } + + // + // MODULE: Pipeline reporting + // + // Run process + CUSTOM_DUMPSOFTWAREVERSIONS( + ch_versions.unique().collectFile(name: 'collated_versions.yml') + ) +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + COMPLETION EMAIL AND SUMMARY +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +workflow.onComplete { + if (params.email || params.email_on_fail) { + NfcoreTemplate.email(workflow, params, summary_params, projectDir, log) + } + NfcoreTemplate.summary(workflow, params, log) + if (params.hook_url) { + NfcoreTemplate.adaptivecard(workflow, params, summary_params, projectDir, log) + } +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + THE END +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ From 07d809989e6fb6d5efaad232fea0c9002298b876 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 28 Apr 2023 17:28:26 +1000 Subject: [PATCH 146/562] Improve handling of S3 URIs when resolving paths Thanks to folks at DNAnexus for the suggestion --- subworkflows/local/lilac_calling.nf | 8 +------- subworkflows/local/prepare_reference.nf | 11 +---------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index 6e9af982..d0c9d9ca 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -87,13 +87,7 @@ workflow LILAC_CALLING { } else { filename = "hla.38.alt.umccr.bed" } - - def filepath = lilac_dir.resolve(filename).toUri().toString() - // NOTE(SW): S3Path.toUri() includes an extra forward slash in the URI or path, - // which is removed here. Unsure whether this occurs in other URIs types - if (filepath.startsWith('s3:///')) { - filepath = filepath.replaceFirst(/^s3:\/\/\//, 's3://') - } + def filepath = lilac_dir.resolve(filename).toUriString() return file(filepath, checkIfExists: true) } // NOTE(SW): here I remove duplicate files so that we only process each input once diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 0f3518f3..0fed641c 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -123,16 +123,7 @@ workflow PREPARE_REFERENCE { .collect() .map { dir_list -> assert dir_list.size() == 1 - - // NOTE(SW): use of toString() in getHmfDataFileObject() fails to parse S3 URIs, - // so must handle here (encountered with workDir set as S3 e.g. in NF Tower) - def dirpath = dir_list[0].toUri().toString() - // NOTE(SW): S3Path.toUri() includes an extra forward slash in the URI or path, - // which is removed here. Unsure whether this occurs in other URIs types. - if (dirpath.startsWith('s3:///')) { - dirpath = dirpath.replaceFirst(/^s3:\/\/\//, 's3://') - } - + def dirpath = dir_list[0].toUriString() return createHmfDataMap(dirpath, false /* params_only */) } } else if (params.ref_data_hmf_data_path) { From e67d67385af235bb0bff1325ae2ce661c30f5927 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 3 May 2023 16:02:54 +1000 Subject: [PATCH 147/562] Complete initial Pipeline5 v5.32 alignment --- conf/hmfdata.config | 18 +- lib/Constants.groovy | 20 +- lib/Processes.groovy | 2 +- modules/local/amber/main.nf | 4 +- modules/local/bamtools/main.nf | 15 +- modules/local/cuppa/Dockerfile | 13 +- .../assets/CupGenerateReport_pipeline.R.patch | 92 -- modules/local/cuppa/{classifier => }/main.nf | 25 +- modules/local/cuppa/{classifier => }/meta.yml | 22 +- modules/local/cuppa/visualiser/main.nf | 47 - modules/local/cuppa/visualiser/meta.yml | 54 -- modules/local/gripss/Dockerfile | 2 +- modules/local/gripss/germline/main.nf | 24 +- modules/local/gripss/somatic/main.nf | 22 +- modules/local/isofox/Dockerfile | 2 +- modules/local/lilac/main.nf | 8 +- modules/local/linx/Dockerfile | 2 +- modules/local/linx/germline/main.nf | 8 +- modules/local/linx/germline/meta.yml | 11 +- modules/local/linx/somatic/main.nf | 8 +- modules/local/linx/visualiser/main.nf | 10 +- modules/local/orange/Dockerfile | 2 +- modules/local/orange/main.nf | 117 +-- modules/local/pave/Dockerfile | 2 +- modules/local/pave/germline/main.nf | 21 +- modules/local/pave/somatic/main.nf | 15 +- modules/local/peach/Dockerfile | 37 - modules/local/peach/main.nf | 46 - modules/local/peach/meta.yml | 45 - modules/local/protect/Dockerfile | 22 - modules/local/protect/main.nf | 68 -- modules/local/protect/meta.yml | 61 -- modules/local/purple/Dockerfile | 2 +- modules/local/purple/main.nf | 45 +- modules/local/sage/Dockerfile | 2 +- modules/local/sage/germline/main.nf | 23 +- modules/local/sage/somatic/main.nf | 12 +- modules/local/svprep/Dockerfile | 12 +- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/assets/gridss.svprep | 833 ------------------ .../local/svprep/assets/gridss_svprep.patch | 139 +++ modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/depth_annotator/main.nf | 6 +- modules/local/svprep/preprocess/main.nf | 2 +- modules/local/svprep/svprep/main.nf | 11 +- nextflow_schema.json | 31 +- subworkflows/local/bamtools_metrics.nf | 1 - subworkflows/local/chord_prediction.nf | 66 ++ subworkflows/local/cuppa_prediction.nf | 23 +- subworkflows/local/flagstat_metrics.nf | 107 +++ subworkflows/local/isofox_quantification.nf | 74 ++ subworkflows/local/linx_annotation.nf | 40 +- subworkflows/local/orange_reporting.nf | 178 ++-- subworkflows/local/prepare_reference.nf | 9 +- subworkflows/local/purple_calling.nf | 31 +- subworkflows/local/sigs_fitting.nf | 68 ++ workflows/wgts.nf | 347 ++------ 57 files changed, 913 insertions(+), 1998 deletions(-) delete mode 100644 modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch rename modules/local/cuppa/{classifier => }/main.nf (80%) rename modules/local/cuppa/{classifier => }/meta.yml (72%) delete mode 100644 modules/local/cuppa/visualiser/main.nf delete mode 100644 modules/local/cuppa/visualiser/meta.yml delete mode 100644 modules/local/peach/Dockerfile delete mode 100644 modules/local/peach/main.nf delete mode 100644 modules/local/peach/meta.yml delete mode 100644 modules/local/protect/Dockerfile delete mode 100644 modules/local/protect/main.nf delete mode 100644 modules/local/protect/meta.yml delete mode 100644 modules/local/svprep/assets/gridss.svprep create mode 100644 modules/local/svprep/assets/gridss_svprep.patch create mode 100644 subworkflows/local/chord_prediction.nf create mode 100644 subworkflows/local/flagstat_metrics.nf create mode 100644 subworkflows/local/isofox_quantification.nf create mode 100644 subworkflows/local/sigs_fitting.nf diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 8683dc92..43fef51e 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -19,16 +19,11 @@ params { isofox_gc_ratios = 'isofox/read_100_exp_gc_ratios.csv' // LILAC lilac_resources = 'lilac/' - // LINX - linx_fragile_regions = 'linx/fragile_sites_hmf.37.csv' - linx_lines = 'linx/line_elements.37.csv' // ORANGE cohort_mapping = 'orange/cohort_mapping.tsv' cohort_percentiles = 'orange/cohort_percentiles.tsv' - // PEACH - peach_panel = 'peach/peach.json' - // PROTECT - serve_resources = 'serve/' + alt_sj_distribution = 'cuppa/cup_ref_alt_sj_sample.csv.gz' + gene_exp_distribution = 'cuppa/cup_ref_gene_exp_sample.csv.gz' // SAGE clinvar_annotations = 'sage/clinvar.37.vcf.gz' sage_blocklist_regions = 'sage/KnownBlacklist.germline.37.bed' @@ -73,16 +68,11 @@ params { isofox_gc_ratios = 'isofox/read_100_exp_gc_ratios.csv' // LILAC lilac_resources = 'lilac/' - // LINX - linx_fragile_regions = 'linx/fragile_sites_hmf.38.csv' - linx_lines = 'linx/line_elements.38.csv' // ORANGE cohort_mapping = 'orange/cohort_mapping.tsv' cohort_percentiles = 'orange/cohort_percentiles.tsv' - // PEACH - peach_panel = 'peach/peach.json' - // PROTECT - serve_resources = 'serve/' + alt_sj_distribution = 'cuppa/cup_ref_alt_sj_sample.csv.gz' + gene_exp_distribution = 'cuppa/cup_ref_gene_exp_sample.csv.gz' // SAGE clinvar_annotations = 'sage/clinvar.38.vcf.gz' sage_blocklist_regions = 'sage/KnownBlacklist.germline.38.bed' diff --git a/lib/Constants.groovy b/lib/Constants.groovy index c8f91a71..ae9629a9 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -23,6 +23,7 @@ class Constants { CHORD, COBALT, CUPPA, + FLAGSTAT, GRIDSS, GRIPSS, ISOFOX, @@ -30,8 +31,6 @@ class Constants { LINX, ORANGE, PAVE, - PEACH, - PROTECT, PURPLE, SAGE, SIGS, @@ -58,13 +57,10 @@ class Constants { VIRUSINTERPRETER_TSV, // ORANGE specific CHORD_PREDICTION, - CUPPA_CSV, - CUPPA_FEATURE_PLOT, - CUPPA_SUMMARY_PLOT, + SIGS, + CUPPA_DIR, FLAGSTAT, LINX_PLOT_DIR, - PEACH_TSV, - PROTECT_TSV, SAGE_BQR, SAGE_COVERAGE, } @@ -92,6 +88,9 @@ class Constants { BAMTOOLS_TXT_TUMOR: [FileType.BAMTOOLS_TXT, SampleType.TUMOR, SequenceType.WGS], BAMTOOLS_TXT_NORMAL: [FileType.BAMTOOLS_TXT, SampleType.NORMAL, SequenceType.WGS], + FLAGSTAT_TUMOR: [FileType.FLAGSTAT, SampleType.TUMOR, SequenceType.WGS], + FLAGSTAT_NORMAL: [FileType.FLAGSTAT, SampleType.NORMAL, SequenceType.WGS], + SAGE_VCF_TUMOR: [FileType.SAGE_VCF, SampleType.TUMOR, SequenceType.WGS], SAGE_VCF_NORMAL: [FileType.SAGE_VCF, SampleType.NORMAL, SequenceType.WGS], SAGE_BQR_TUMOR: [FileType.SAGE_BQR, SampleType.TUMOR, SequenceType.WGS], @@ -115,14 +114,11 @@ class Constants { LINX_ANNO_DIR_NORMAL: [FileType.LINX_ANNO_DIR, SampleType.NORMAL, SequenceType.WGS], CHORD_PREDICTION: [FileType.CHORD_PREDICTION, SampleType.TUMOR, SequenceType.WGS], + SIGS: [FileType.SIGS, SampleType.TUMOR, SequenceType.WGS], LILAC_DIR: [FileType.LILAC_DIR, SampleType.NORMAL, SequenceType.WGS], - PEACH_TSV: [FileType.PEACH_TSV, SampleType.NORMAL, SequenceType.WGS], - PROTECT_TSV: [FileType.PROTECT_TSV, SampleType.TUMOR, SequenceType.WGS], VIRUSINTERPRETER_TSV: [FileType.VIRUSINTERPRETER_TSV, SampleType.TUMOR, SequenceType.WGS], - CUPPA_CSV: [FileType.CUPPA_CSV, SampleType.TUMOR, SequenceType.WGTS], - CUPPA_FEATURE_PLOT: [FileType.CUPPA_FEATURE_PLOT, SampleType.TUMOR, SequenceType.WGTS], - CUPPA_SUMMARY_PLOT: [FileType.CUPPA_SUMMARY_PLOT, SampleType.TUMOR, SequenceType.WGTS], + CUPPA_DIR: [FileType.CUPPA_DIR, SampleType.TUMOR, SequenceType.WGTS], ] } diff --git a/lib/Processes.groovy b/lib/Processes.groovy index 7284ce4c..dbf2fcaf 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -33,8 +33,8 @@ class Processes { case Constants.PipelineMode.CUPPA: processes = [ Constants.Process.AMBER, + Constants.Process.BAMTOOLS, Constants.Process.COBALT, - Constants.Process.COLLECTWGSMETRICS, Constants.Process.CUPPA, Constants.Process.GRIDSS, Constants.Process.GRIPSS, diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index 7272fee5..bae69c57 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -29,9 +29,9 @@ process AMBER { -reference ${meta.normal_id} \\ -reference_bam ${normal_bam} \\ -ref_genome_version ${ref_genome_ver} \\ - -output_dir amber/ \\ + -loci ${loci} \\ -threads ${task.cpus} \\ - -loci ${loci} + -output_dir amber/ # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf index 4400b34e..efa073a2 100644 --- a/modules/local/bamtools/main.nf +++ b/modules/local/bamtools/main.nf @@ -24,13 +24,14 @@ process BAMTOOLS { -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -cp ${task.ext.jarPath} \\ com.hartwig.hmftools.bamtools.metrics.BamMetrics \\ - -sample ${meta.id} \\ - -bam_file ${bam} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -threads ${task.cpus} \\ - -write_old_style \\ - -output_dir ./ + -sample ${meta.id} \\ + -bam_file ${bam} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -threads ${task.cpus} \\ + -write_old_style \\ + -log_level INFO \\ + -output_dir ./ cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/cuppa/Dockerfile b/modules/local/cuppa/Dockerfile index 9a3fe074..1b84453b 100644 --- a/modules/local/cuppa/Dockerfile +++ b/modules/local/cuppa/Dockerfile @@ -4,7 +4,7 @@ USER root RUN \ apt-get update && \ - apt-get install -y patch procps wget && \ + apt-get install -y procps wget && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -14,22 +14,13 @@ RUN \ ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.8 ARG URL_BASE_CHART=${URL_BASE}/cuppa/src/main/resources/cuppa-chart -ARG URL_BASE_REPORT=${URL_BASE}/cuppa/src/main/resources/r ARG DIR_BASE=/opt/cuppa RUN \ mkdir -p ${DIR_BASE}/{chart,report} && \ wget -P ${DIR_BASE}/chart/ ${URL_BASE_CHART}/requirements.txt && \ wget -P ${DIR_BASE}/chart/ ${URL_BASE_CHART}/cuppa-chart.py && \ wget -P ${DIR_BASE}/chart/main/ ${URL_BASE_CHART}/main/create_chart.py && \ - wget -P ${DIR_BASE}/chart/main/ ${URL_BASE_CHART}/main/prepare_data.py && \ - wget -P ${DIR_BASE}/report/ ${URL_BASE_REPORT}/CupGenerateReport_pipeline.R - -COPY assets/CupGenerateReport_pipeline.R.patch /tmp/ -RUN \ - patch -p1 ${DIR_BASE}/report/CupGenerateReport_pipeline.R /tmp/CupGenerateReport_pipeline.R.patch && \ - rm /tmp/CupGenerateReport_pipeline.R.patch - -USER mambauser + wget -P ${DIR_BASE}/chart/main/ ${URL_BASE_CHART}/main/prepare_data.py RUN \ micromamba install -y -n base -c bioconda -c conda-forge \ diff --git a/modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch b/modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch deleted file mode 100644 index 2bf7310e..00000000 --- a/modules/local/cuppa/assets/CupGenerateReport_pipeline.R.patch +++ /dev/null @@ -1,92 +0,0 @@ ---- a/CupGenerateReport_pipeline.R -+++ b/CupGenerateReport_pipeline.R -@@ -150,49 +150,30 @@ titleHeight = 10 - disclaimer1Height = 12 - disclaimer2Height = 14 - --if (featureCount > featureLimit) --{ -- separateFeaturePlot = T -- print(sprintf('Features(%d) print separately', featureCount)) -- plotHeights = c(summaryHeight, genderHeight, sigHeight, percHeight) -- plotHeightsDisclaimer = c(titleHeight, disclaimer1Height, disclaimer2Height, summaryHeight, genderHeight, sigHeight, percHeight) --} else --{ -- separateFeaturePlot = F -- featureHeight = 45 + (featureCount - 1) * 10 -- plotHeights = c(summaryHeight, genderHeight, sigHeight, percHeight, featureHeight) -- plotHeightsDisclaimer = c(titleHeight, disclaimer1Height, disclaimer2Height, summaryHeight, genderHeight, sigHeight, percHeight, featureHeight) --} -+print(sprintf('Features(%d) print separately', featureCount)) -+plotHeights = c(summaryHeight, genderHeight, sigHeight, percHeight) -+plotHeightsDisclaimer = c(titleHeight, disclaimer1Height, disclaimer2Height, summaryHeight, genderHeight, sigHeight, percHeight) - - # Generating PNG files --outputFileSummary = paste0(cuppaDir, sampleId, '.cup.report.summary.png') --if (separateFeaturePlot) --{ -- outputFileFeatures = paste0(cuppaDir, sampleId, '.cup.report.features.png') -- print(paste0("Writing output to png file: ", outputFileSummary)) -- png(file = outputFileSummary, res = 140, height = 2200, width = 4000) -- grid.arrange(plot_grid(summaryPlot, genderPlot, sigPlot, svTraitsPlot, -- ncol = 1, nrow = 4, rel_heights = plotHeights, align = 'v', axis = 'l')) -- -- print(paste0("Writing output to png file: ", outputFileFeatures)) -- png(file = outputFileFeatures, res = 140, height = 2200, width = 4000) -- featurePlot = featurePlot + -- scale_x_discrete(position = "top") + -- theme(axis.text.x.top = element_text(angle = 90, hjust = 0, size = 10, face = 'bold', family = font)) -- grid.arrange(plot_grid(featurePlot, ncol = 1, nrow = 1), newpage = T) --} else --{ -- print(paste0("Writing output to png file: ", outputFileSummary)) -- png(file = outputFileSummary, res = 140, height = 2200, width = 4000) -- plot_grid(summaryPlot, genderPlot, sigPlot, svTraitsPlot, featurePlot, -- ncol = 1, nrow = 5, rel_heights = plotHeights, align = 'v', axis = 'l') --} -+outputFileSummary = paste0(sampleId, '.cup.report.summary.png') -+outputFileFeatures = paste0(sampleId, '.cup.report.features.png') -+print(paste0("Writing output to png file: ", outputFileSummary)) -+png(file = outputFileSummary, res = 140, height = 2200, width = 4000) -+grid.arrange(plot_grid(summaryPlot, genderPlot, sigPlot, svTraitsPlot, -+ ncol = 1, nrow = 4, rel_heights = plotHeights, align = 'v', axis = 'l')) -+ -+print(paste0("Writing output to png file: ", outputFileFeatures)) -+png(file = outputFileFeatures, res = 140, height = 2200, width = 4000) -+featurePlot = featurePlot + -+ scale_x_discrete(position = "top") + -+ theme(axis.text.x.top = element_text(angle = 90, hjust = 0, size = 10, face = 'bold', family = font)) -+grid.arrange(plot_grid(featurePlot, ncol = 1, nrow = 1), newpage = T) - - dev.off() - - # Generate PDF report with disclaimer - --outputFile = paste0(cuppaDir, sampleId, '_cup_report.pdf') -+outputFile = paste0(sampleId, '_cup_report.pdf') - print(paste0("writing output to pdf file: ", outputFile)) - - pdf(file = outputFile, height = 14, width = 20) -@@ -202,16 +183,9 @@ title = textGrob(paste0(sampleId, ' CUP Report'), gp = gpar(fontface = "bold", f - disclaimer1 = textGrob(paste('All results and data described in this report are for research-use-only and have not been generated using a clinically validated and controlled procedure.'), gp = gpar(fontface = "bold", fontsize = 13)) - disclaimer2 = textGrob(paste('These results should not be used for clinical decision making.'), gp = gpar(fontface = "bold", fontsize = 13)) - --if (separateFeaturePlot) -- { -- grid.arrange(plot_grid(title, disclaimer1, disclaimer2, summaryPlot, genderPlot, sigPlot, svTraitsPlot, -- ncol = 1, nrow = 7, rel_heights = plotHeightsDisclaimer, align = 'v', axis = 'l')) -- -- grid.arrange(plot_grid(featurePlot, ncol = 1, nrow = 1), newpage = T) --} else --{ -- plot_grid(title, disclaimer1, disclaimer2, summaryPlot, genderPlot, sigPlot, svTraitsPlot, featurePlot, -- ncol = 1, nrow = 8, rel_heights = plotHeightsDisclaimer, align = 'v', axis = 'l') --} -+grid.arrange(plot_grid(title, disclaimer1, disclaimer2, summaryPlot, genderPlot, sigPlot, svTraitsPlot, -+ ncol = 1, nrow = 7, rel_heights = plotHeightsDisclaimer, align = 'v', axis = 'l')) -+ -+grid.arrange(plot_grid(featurePlot, ncol = 1, nrow = 1), newpage = T) - --dev.off() -\ No newline at end of file -+dev.off() diff --git a/modules/local/cuppa/classifier/main.nf b/modules/local/cuppa/main.nf similarity index 80% rename from modules/local/cuppa/classifier/main.nf rename to modules/local/cuppa/main.nf index 660c3fba..66c24599 100644 --- a/modules/local/cuppa/classifier/main.nf +++ b/modules/local/cuppa/main.nf @@ -1,8 +1,8 @@ -process CUPPA_CLASSIFIER { +process CUPPA { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.8--1' + container 'docker.io/scwatts/cuppa:1.8--2' input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter) @@ -10,8 +10,8 @@ process CUPPA_CLASSIFIER { path cuppa_resources output: - tuple val(meta), path('*csv'), emit: csv - path 'versions.yml' , emit: versions + tuple val(meta), path('cuppa/'), emit: cuppa_dir + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -58,12 +58,18 @@ process CUPPA_CLASSIFIER { java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ - -categories ${categories_val} \\ - -ref_data_dir ${cuppa_resources} \\ -sample_data ${meta.id} \\ -sample_data_dir sample_data/ \\ + -categories ${categories_val} \\ + -ref_data_dir ${cuppa_resources} \\ -ref_genome_version ${ref_genome_ver} \\ - -output_dir ./ + -create_pdf \\ + -output_dir ./cuppa/ + + python ${task.ext.chartScriptPath} \\ + -sample ${meta.id} \\ + -sample_data cuppa/${meta.id}.cup.data.csv \\ + -output_dir ./cuppa/ # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml @@ -75,6 +81,11 @@ process CUPPA_CLASSIFIER { stub: """ touch ${meta.id}.cup.data.csv + touch ${meta.id}.cuppa.conclusion.txt + touch ${meta.id}_cup_report.pdf + touch ${meta.id}.cup.report.summary.png + touch ${meta.id}.cup.report.features.png + touch ${meta.id}.cuppa.chart.png echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/cuppa/classifier/meta.yml b/modules/local/cuppa/meta.yml similarity index 72% rename from modules/local/cuppa/classifier/meta.yml rename to modules/local/cuppa/meta.yml index 8ed4e73e..5fc0a714 100644 --- a/modules/local/cuppa/classifier/meta.yml +++ b/modules/local/cuppa/meta.yml @@ -40,8 +40,28 @@ output: e.g. [id: 'sample_id'] - csv: type: file - description: CUPPA classification output file + description: Classification file pattern: "*.{csv}" + - conclusion: + type: file + description: Conclusion file + pattern: "*.{txt}" + - report: + type: file + description: Report PDF file + pattern: "*.{pdf}" + - summary_plot: + type: file + description: Summary plot file + pattern: "*.{png}" + - feature_plot: + type: file + description: Feature plot file + pattern: "*.{png}" + - chart_plot: + type: file + description: Chart plot file + pattern: "*.{png}" - versions: type: file description: File containing software versions diff --git a/modules/local/cuppa/visualiser/main.nf b/modules/local/cuppa/visualiser/main.nf deleted file mode 100644 index b723dc20..00000000 --- a/modules/local/cuppa/visualiser/main.nf +++ /dev/null @@ -1,47 +0,0 @@ -process CUPPA_VISUALISER { - tag "${meta.id}" - label 'process_low' - - container 'docker.io/scwatts/cuppa:1.8--1' - - input: - tuple val(meta), path(cuppa_csv) - - output: - tuple val(meta), path('*conclusion.txt') , emit: conclusion - tuple val(meta), path('*cup_report.pdf') , emit: report - tuple val(meta), path('*report.summary.png') , emit: summary_plot - tuple val(meta), path('*report.features.png'), emit: feature_plot - tuple val(meta), path('*chart.png') , emit: chart_plot - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - python ${task.ext.chartScriptPath} \\ - -sample ${meta.id} \\ - -sample_data ${cuppa_csv} \\ - -output_dir ./ - Rscript ${task.ext.reportScriptPath} ${meta.id} ./ - - # NOTE(SW): hard coded since there is no reliable way to obtain version information. - cat <<-END_VERSIONS > versions.yml - "${task.process}": - cuppa: 1.8 - END_VERSIONS - """ - - stub: - """ - touch ${meta.id}.cuppa.conclusion.txt - touch ${meta.id}_cup_report.pdf - touch ${meta.id}.cup.report.summary.png - touch ${meta.id}.cup.report.features.png - touch ${meta.id}.cuppa.chart.png - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/cuppa/visualiser/meta.yml b/modules/local/cuppa/visualiser/meta.yml deleted file mode 100644 index 0794bbe9..00000000 --- a/modules/local/cuppa/visualiser/meta.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: cuppa_visualiser -description: Visualise tissue of origin predictions -keywords: - - cup - - tumor - - classification -tools: - - cuppa: - description: Prediction of tumor sample tissue of origin - homepage: https://github.com/hartwigmedical/hmftools/tree/master/cuppa - documentation: https://github.com/hartwigmedical/hmftools/tree/master/cuppa - licence: ["GPL v3"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - csv: - type: file - description: CUPPA classification output file - pattern: "*.{csv}" -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - conclusion: - type: file - description: Conclusion file - pattern: "*.{txt}" - - report: - type: file - description: Report PDF file - pattern: "*.{pdf}" - - summary_plot: - type: file - description: Summary plot file - pattern: "*.{png}" - - feature_plot: - type: file - description: Feature plot file - pattern: "*.{png}" - - chart_plot: - type: file - description: Chart plot file - pattern: "*.{png}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@scwatts" diff --git a/modules/local/gripss/Dockerfile b/modules/local/gripss/Dockerfile index da5d319b..69a2d666 100644 --- a/modules/local/gripss/Dockerfile +++ b/modules/local/gripss/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/gripss/ && \ - wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.3.2/gripss_v2.3.2.jar' + wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.3.5/gripss_v2.3.5.jar' USER mambauser diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index b10df71f..705c2b55 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -2,7 +2,7 @@ process GRIPSS_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.3.2--0' + container 'docker.io/scwatts/gripss:2.3.5--0' input: tuple val(meta), path(gridss_vcf) @@ -15,9 +15,9 @@ process GRIPSS_GERMLINE { path repeatmasker_annotations output: - tuple val(meta), path('*gripss.filtered.germline.vcf.gz'), path('*gripss.filtered.germline.vcf.gz.tbi'), emit: vcf - tuple val(meta), path('*.gripss.germline.vcf.gz'), path('*.gripss.germline.vcf.gz.tbi') , emit: vcf_unfiltered - path 'versions.yml' , emit: versions + tuple val(meta), path('*.filtered.germline.vcf.gz'), path('*.filtered.germline.vcf.gz.tbi'), emit: vcf + tuple val(meta), path('*gripss.germline.vcf.gz'), path('*gripss.germline.vcf.gz.tbi') , emit: vcf_unfiltered + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -31,31 +31,27 @@ process GRIPSS_GERMLINE { -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.normal_id} \\ - -ref_genome_version ${genome_ver} \\ + -reference ${meta.tumor_id} \\ + -vcf ${gridss_vcf} \\ + -germline \\ -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ -pon_sgl_file ${pon_breakends} \\ -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ -repeat_mask_file ${repeatmasker_annotations} \\ - -vcf ${gridss_vcf} \\ -output_id germline \\ -output_dir ./ - # NOTE(SW): hard coded since there is no reliable way to obtain version information cat <<-END_VERSIONS > versions.yml "${task.process}": - gripss: 2.3.2 + gripss: \$(java -jar ${task.ext.jarPath} | sed -n '1s/^.*version: //p') END_VERSIONS """ stub: """ - cat < ${meta.normal_id}.gripss.filtered.germline.vcf.gz - ##fileformat=VCFv4.1 - ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . - EOF + touch ${meta.normal_id}.gripss.filtered.germline.vcf.gz touch ${meta.normal_id}.gripss.filtered.germline.vcf.gz.tbi touch ${meta.normal_id}.gripss.germline.vcf.gz touch ${meta.normal_id}.gripss.germline.vcf.gz.tbi diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index a3746e28..ab1c6728 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -2,7 +2,7 @@ process GRIPSS_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.3.2--0' + container 'docker.io/scwatts/gripss:2.3.5--0' input: tuple val(meta), path(gridss_vcf) @@ -15,9 +15,9 @@ process GRIPSS_SOMATIC { path repeatmasker_annotations output: - tuple val(meta), path('*.gripss.filtered.somatic.vcf.gz'), path('*.gripss.filtered.somatic.vcf.gz.tbi'), emit: vcf - tuple val(meta), path('*.gripss.somatic.vcf.gz'), path('*.gripss.somatic.vcf.gz.tbi') , emit: vcf_unfiltered - path 'versions.yml' , emit: versions + tuple val(meta), path('*.filtered.somatic.vcf.gz'), path('*.filtered.somatic.vcf.gz.tbi'), emit: vcf + tuple val(meta), path('*.gripss.somatic.vcf.gz'), path('*.gripss.somatic.vcf.gz.tbi') , emit: vcf_unfiltered + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -32,31 +32,25 @@ process GRIPSS_SOMATIC { ${args} \\ -sample ${meta.tumor_id} \\ -reference ${meta.normal_id} \\ - -ref_genome_version ${genome_ver} \\ + -vcf ${gridss_vcf} \\ -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ -pon_sgl_file ${pon_breakends} \\ -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ -repeat_mask_file ${repeatmasker_annotations} \\ - -vcf ${gridss_vcf} \\ -output_id somatic \\ -output_dir ./ - # NOTE(SW): hard coded since there is no reliable way to obtain version information cat <<-END_VERSIONS > versions.yml "${task.process}": - gripss: 2.3.2 + gripss: \$(java -jar ${task.ext.jarPath} | sed -n '1s/^.*version: //p') END_VERSIONS """ stub: """ - cat < ${meta.tumor_id}.gripss.filtered.somatic.vcf.gz - ##fileformat=VCFv4.1 - ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . - EOF + touch ${meta.tumor_id}.gripss.filtered.somatic.vcf.gz touch ${meta.tumor_id}.gripss.filtered.somatic.vcf.gz.tbi touch ${meta.tumor_id}.gripss.somatic.vcf.gz touch ${meta.tumor_id}.gripss.somatic.vcf.gz.tbi diff --git a/modules/local/isofox/Dockerfile b/modules/local/isofox/Dockerfile index 489084eb..9f6986d2 100644 --- a/modules/local/isofox/Dockerfile +++ b/modules/local/isofox/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/isofox/ && \ - wget -O /opt/isofox/isofox.jar 'https://github.com/hartwigmedical/hmftools/releases/download/isofox-v1.6.1/isofox_v1.6.1.jar' + wget -O /opt/isofox/isofox.jar 'https://github.com/hartwigmedical/hmftools/releases/download/isofox-v1.6.2/isofox_v1.6.2.jar' USER mambauser diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 19b47aad..54855c39 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -31,14 +31,14 @@ process LILAC { -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${sample_name} \\ + -reference_bam ${normal_wgs_bam} \\ ${tumor_wgs_bam_arg} \\ ${tumor_wts_bam_arg} \\ - -reference_bam ${normal_wgs_bam} \\ - -ref_genome_version ${genome_ver} \\ + ${smlv_vcf_arg} \\ + ${gene_cn_arg} \\ -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ -resource_dir ${lilac_resources} \\ - ${gene_cn_arg} \\ - ${smlv_vcf_arg} \\ -threads ${task.cpus} \\ -output_dir lilac/ diff --git a/modules/local/linx/Dockerfile b/modules/local/linx/Dockerfile index 846feb27..322ce3d1 100644 --- a/modules/local/linx/Dockerfile +++ b/modules/local/linx/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/linx/ && \ - wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.22/linx_v1.22.jar' + wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.23.2/linx_v1.23.2.jar' USER mambauser diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index b5494c6d..709d3266 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -2,12 +2,11 @@ process LINX_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.22--0' + container 'docker.io/scwatts/linx:1.23.2--0' input: - tuple val(meta), path(gripss_sv) + tuple val(meta), path(sv_vcf) val genome_ver - path lines path ensembl_data_resources path driver_gene_panel @@ -27,10 +26,9 @@ process LINX_GERMLINE { -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ + -sv_vcf ${purple_dir}/${meta.id}.purple.sv.germline.vcf.gz \\ -germline \\ -ref_genome_version ${genome_ver} \\ - -sv_vcf ${gripss_sv} \\ - -line_element_file ${lines} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -driver_gene_panel ${driver_gene_panel} \\ -output_dir linx_germline/ diff --git a/modules/local/linx/germline/meta.yml b/modules/local/linx/germline/meta.yml index f4a5bbd6..57c411e7 100644 --- a/modules/local/linx/germline/meta.yml +++ b/modules/local/linx/germline/meta.yml @@ -16,10 +16,9 @@ input: description: | Groovy Map containing sample information e.g. [id: 'sample_id'] - - gridss_sv: - type: file - description: GRIPSS hard filtered VCF file - pattern: "*.{vcf.gz}" + - purple_dir: + type: directory + description: PURPLE output directory - genome_ver: type: string description: Reference genome version @@ -27,10 +26,6 @@ input: type: file description: LINX fragile regions file pattern: "*.{csv}" - - lines: - type: file - description: LINEs file - pattern: "*.{csv}" - ensembl_data_resources: type: directory description: HMF ensembl data resources directory diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index cb402482..00952de6 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,13 +2,11 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.22--0' + container 'docker.io/scwatts/linx:1.23.2--0' input: tuple val(meta), path(purple_dir) val genome_ver - path fragile_regions - path lines path ensembl_data_resources path known_fusion_data path driver_gene_panel @@ -31,12 +29,10 @@ process LINX_SOMATIC { -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ - -ref_genome_version ${genome_ver} \\ -sv_vcf ${purple_dir}/${meta.id}.purple.sv.vcf.gz \\ -purple_dir ${purple_dir} \\ ${gene_id_file_arg} \\ - -fragile_site_file ${fragile_regions} \\ - -line_element_file ${lines} \\ + -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -check_fusions \\ -known_fusion_file ${known_fusion_data} \\ diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 4d5e6b24..700894e9 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,7 +2,7 @@ process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/linx:1.22--0' + container 'docker.io/scwatts/linx:1.23.2--0' input: tuple val(meta), path(linx) @@ -26,13 +26,13 @@ process LINX_VISUALISER { com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ ${args} \\ -sample ${meta.id} \\ + -vis_file_dir ${linx} \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ - -plot_out linx_visualiser/plot \\ - -data_out linx_visualiser/data \\ - -vis_file_dir ${linx} \\ -circos ${task.ext.path_circos} \\ - -threads ${task.cpus} + -threads ${task.cpus} \\ + -plot_out linx_visualiser/plot \\ + -data_out linx_visualiser/data cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/orange/Dockerfile b/modules/local/orange/Dockerfile index 560b1adc..0581b863 100644 --- a/modules/local/orange/Dockerfile +++ b/modules/local/orange/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/orange/ && \ - wget -O /opt/orange/orange.jar 'https://github.com/hartwigmedical/hmftools/releases/download/orange-v1.10.2/orange_v1.10.2.jar' + wget -O /opt/orange/orange.jar 'https://github.com/hartwigmedical/hmftools/releases/download/orange-v2.3/orange_v2.3.jar' USER mambauser diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 4720e8b2..7739c5d3 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -1,19 +1,20 @@ -// NOTE(SW): reference files for Isfox aren't currently available (-isofox_gene_distribution_csv, -isofox_alt_sj_cohort_csv) - process ORANGE { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/orange:1.10.2--0' + container 'docker.io/scwatts/orange:2.3--0' input: - tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(chord_prediction), path(lilac_dir), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(protect), path(peach_genotype), path(cuppa), path(cuppa_summary_plot), path(cuppa_feature_plot), path(virusinterpreter) + tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter), path(chord_prediction), path(sigs_tsv), path(lilac_dir), path(cuppa_dir), path(isofox_dir) val genome_ver path disease_ontology - path known_fusion_data - path driver_gene_panel path cohort_mapping path cohort_percentiles + path known_fusion_data + path driver_gene_panel + path ensembl_data_resources + path isofox_alt_sj + path isofox_gene_distribution val pipeline_version output: @@ -28,70 +29,80 @@ process ORANGE { def args = task.ext.args ?: '' def pipeline_version_str = pipeline_version ?: 'not specified' + def virusinterpreter_arg = virusinterpreter ? "-annotated_virus_tsv ${virusinterpreter}" : '' + def chord_arg = chord_prediction ? "-chord_prediction_txt ${chord_prediction}" : '' + def sigs_arg = sigs_tsv ? "-sigs_allocation_tsv ${sigs_tsv}" : '' + def cuppa_csv_arg = cuppa_dir ? "-cuppa_result_csv ${cuppa_dir}/${meta.tumor_wgs_id}.cup.data.csv" : '' + def cuppa_feature_arg = cuppa_dir ? "-cuppa_feature_plot ${cuppa_dir}/${meta.tumor_wgs_id}.cup.report.features.png" : '' + def cuppa_summary_arg = cuppa_dir ? "-cuppa_summary_plot ${cuppa_dir}/${meta.tumor_wgs_id}.cup.report.summary.png" : '' + + def normal_id_arg = meta.containsKey('normal_wgs_id') ? "-reference_sample_id ${meta.normal_wgs_id}" : '' + def normal_metrics_arg = bam_metrics_germline ? "-ref_sample_wgs_metrics_file ${bam_metrics_germline}" : '' + def normal_flagstat_arg = flagstat_germline ? "-ref_sample_flagstat_file ${flagstat_germline}" : '' + def normal_sage_somatic_bqr_arg = sage_somatic_normal_bqr ? "-sage_somatic_ref_sample_bqr_plot ${sage_somatic_normal_bqr}" : '' + def normal_sage_coverage_arg = sage_germline_coverage ? "-sage_germline_gene_coverage_tsv ${sage_germline_coverage}" : '' + def normal_linx_arg = linx_germline_anno_dir ? "-linx_germline_data_directory ${linx_germline_anno_dir}" : '' + + def rna_id_arg = meta.containsKey('tumor_wts_id') ? "-reference_sample_id ${meta.tumor_wts_id}" : '' + def isofox_summary_csv_arg = isofox_dir ? "-isofox_summary_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.summary.csv" : '' + def isofox_gene_csv_arg = isofox_dir ? "-isofox_summary_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.gene_data.csv" : '' + def isofox_fusion_csv_arg = isofox_dir ? "-isofox_gene_data_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.fusions.csv" : '' + def isofox_alt_sj_csv_arg = isofox_dir ? "-isofox_fusion_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.alt_splice_junc.csv" : '' + + def isofox_gene_distribution_arg = isofox_gene_distribution ? "-isofox_gene_distribution_csv ${isofox_gene_distribution}" : '' + def isofox_alt_sj_arg = isofox_alt_sj ? "-isofox_alt_sj_cohort_csv ${isofox_alt_sj}" : '' + """ echo "${pipeline_version_str}" > pipeline_version.txt - # NOTE(SW): '--add-opens java.base/java.time=ALL-UNNAMED' resolves issue writing JSON, see: - # https://stackoverflow.com/questions/70412805/what-does-this-error-mean-java-lang-reflect-inaccessibleobjectexception-unable/70878195#70878195 - java \\ - --add-opens java.base/java.time=ALL-UNNAMED \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ \\ - -tumor_sample_id ${meta.tumor_id} \\ - -reference_sample_id ${meta.normal_id} \\ - \\ + -experiment_date \$(date +%y%m%d) \\ -pipeline_version_file pipeline_version.txt \\ - -ref_genome_version ${genome_ver} \\ - -primary_tumor_doids "" \\ - -max_evidence_level C \\ + -add_disclaimer \\ \\ + -tumor_sample_id ${meta.tumor_wgs_id} \\ + -primary_tumor_doids "" \\ -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ - -ref_sample_wgs_metrics_file ${bam_metrics_germline} \\ -tumor_sample_flagstat_file ${flagstat_somatic} \\ - -ref_sample_flagstat_file ${flagstat_germline} \\ - \\ - -chord_prediction_txt ${chord_prediction} \\ - -lilac_result_csv ${lilac_dir}/${meta.tumor_id}.lilac.csv \\ - -lilac_qc_csv ${lilac_dir}/${meta.tumor_id}.lilac.qc.csv \\ - \\ - -sage_somatic_tumor_sample_bqr_plot ${sage_somatic_bqr} \\ - -sage_somatic_ref_sample_bqr_plot ${sage_germline_bqr} \\ - -sage_germline_gene_coverage_tsv ${sage_germline_coverage} \\ - \\ - -purple_qc_file ${purple_dir}/${meta.tumor_id}.purple.qc \\ - -purple_purity_tsv ${purple_dir}/${meta.tumor_id}.purple.purity.tsv \\ - -purple_gene_copy_number_tsv ${purple_dir}/${meta.tumor_id}.purple.cnv.gene.tsv \\ - -purple_somatic_copy_number_tsv ${purple_dir}/${meta.tumor_id}.purple.cnv.somatic.tsv \\ - -purple_somatic_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.somatic.tsv \\ - -purple_somatic_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.somatic.vcf.gz \\ - -purple_germline_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.germline.tsv \\ - -purple_germline_deletion_tsv ${purple_dir}/${meta.tumor_id}.purple.germline.deletion.tsv \\ - -purple_germline_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.germline.vcf.gz \\ + -sage_somatic_tumor_sample_bqr_plot ${sage_somatic_tumor_bqr} \\ + -purple_data_directory ${purple_dir} \\ -purple_plot_directory ${purple_dir}/plot/ \\ - \\ - -linx_breakend_tsv ${linx_somatic_anno_dir}/${meta.tumor_id}.linx.breakend.tsv \\ - -linx_structural_variant_tsv ${linx_somatic_anno_dir}/${meta.tumor_id}.linx.svs.tsv \\ - -linx_driver_tsv ${linx_somatic_anno_dir}/${meta.tumor_id}.linx.drivers.tsv \\ - -linx_driver_catalog_tsv ${linx_somatic_anno_dir}/${meta.tumor_id}.linx.driver.catalog.tsv \\ - -linx_fusion_tsv ${linx_somatic_anno_dir}/${meta.tumor_id}.linx.fusion.tsv \\ - -linx_germline_disruption_tsv ${linx_germline_anno_dir}/${meta.normal_id}.linx.germline.disruption.tsv \\ + -linx_somatic_data_directory ${linx_somatic_anno_dir} \\ -linx_plot_directory ${linx_somatic_plot_dir} \\ + -lilac_result_csv ${lilac_dir}/${meta.tumor_wgs_id}.lilac.csv \\ + -lilac_qc_csv ${lilac_dir}/${meta.tumor_wgs_id}.lilac.qc.csv \\ + ${virusinterpreter_arg} \\ + ${chord_arg} \\ + ${sigs_tsv} \\ + ${cuppa_csv_arg} \\ + ${cuppa_feature_arg} \\ + ${cuppa_summary_arg} \\ \\ - -cuppa_result_csv ${cuppa} \\ - -cuppa_feature_plot ${cuppa_feature_plot} \\ - -cuppa_summary_plot ${cuppa_summary_plot} \\ + ${normal_id_arg} \\ + ${normal_metrics_arg} \\ + ${normal_flagstat_arg} \\ + ${normal_sage_somatic_bqr_arg} \\ + ${normal_sage_coverage_arg} \\ + ${normal_linx_arg} \\ \\ - -peach_genotype_tsv ${peach_genotype} \\ - -protect_evidence_tsv ${protect} \\ - -annotated_virus_tsv ${virusinterpreter} \\ + ${rna_id_arg} \\ + ${isofox_summary_csv_arg} \\ + ${isofox_gene_csv_arg} \\ + ${isofox_fusion_csv_arg} \\ + ${isofox_alt_sj_csv_arg} \\ \\ + -ref_genome_version ${genome_ver} \\ -doid_json ${disease_ontology} \\ - -known_fusion_file ${known_fusion_data} \\ - -driver_gene_panel_tsv ${driver_gene_panel} \\ -cohort_mapping_tsv ${cohort_mapping} \\ -cohort_percentiles_tsv ${cohort_percentiles} \\ + -known_fusion_file ${known_fusion_data} \\ + -driver_gene_panel_tsv ${driver_gene_panel} \\ + -ensembl_data_directory ${ensembl_data_resources} \\ + ${isofox_gene_distribution_arg} \\ + ${isofox_alt_sj_arg} \\ -output_dir ./ cat <<-END_VERSIONS > versions.yml @@ -102,8 +113,8 @@ process ORANGE { stub: """ - touch "${meta.tumor_id}.orange.json" - touch "${meta.tumor_id}.orange.pdf" + touch "${meta.tumor_wgs_id}.orange.json" + touch "${meta.tumor_wgs_id}.orange.pdf" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/pave/Dockerfile b/modules/local/pave/Dockerfile index d2cbefa9..297aba7b 100644 --- a/modules/local/pave/Dockerfile +++ b/modules/local/pave/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/pave/ && \ - wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.4/pave_v1.4.jar' + wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.4.3/pave_v1.4.3.jar' USER mambauser diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 13d26c3f..1d71f7e2 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -1,12 +1,12 @@ -// NOTE(SW): use of tumor sample name here is consistent with pipeline5 -// - cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveGermline.java#L35-L39 -// - cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L34-L44 +// NOTE(SW): use of tumor sample name here is consistent with Pipeline5 +// - https://github.com/hartwigmedical/pipeline5/blob/v5.32/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveGermline.java#L35-L39 +// - https://github.com/hartwigmedical/pipeline5/blob/v5.32/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L34-L44 process PAVE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.4--0' + container 'docker.io/scwatts/pave:1.4.3--0' input: tuple val(meta), path(sage_vcf) @@ -37,22 +37,21 @@ process PAVE_GERMLINE { -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ - -ref_genome_version ${genome_ver} \\ + -vcf_file ${sage_vcf} \\ -ref_genome ${genome_fasta} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - -driver_gene_panel ${driver_gene_panel} \\ + -ref_genome_version ${genome_ver} \\ -clinvar_vcf ${clinvar_annotations} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -mappability_bed ${segment_mappability} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ -blacklist_bed ${sage_blocklist_regions} \\ -blacklist_vcf ${sage_blocklist_sites} \\ - -mappability_bed ${segment_mappability} \\ - -vcf_file ${sage_vcf} \\ -read_pass_only \\ -output_dir ./ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: 1.4 + pave: \$(java -jar ${task.ext.jarPath} 2>&1 | sed -n 's/^.*version: //p') END_VERSIONS """ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index da0ea55d..7fc8dedb 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -2,7 +2,7 @@ process PAVE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.4--0' + container 'docker.io/scwatts/pave:1.4.3--0' input: tuple val(meta), path(sage_vcf) @@ -43,22 +43,21 @@ process PAVE_SOMATIC { -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ -sample ${meta.id} \\ - -ref_genome_version ${genome_ver} \\ + -vcf_file ${sage_vcf} \\ -ref_genome ${genome_fasta} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - -driver_gene_panel ${driver_gene_panel} \\ + -ref_genome_version ${genome_ver} \\ -pon_file ${sage_pon} \\ -pon_filters "${pon_filters}" \\ + -driver_gene_panel ${driver_gene_panel} \\ -mappability_bed ${segment_mappability} \\ - -vcf_file ${sage_vcf} \\ - -read_pass_only \\ + -ensembl_data_dir ${ensembl_data_resources} \\ ${gnomad_args} \\ + -read_pass_only \\ -output_dir ./ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: 1.4 + pave: \$(java -jar ${task.ext.jarPath} 2>&1 | sed -n 's/^.*version: //p') END_VERSIONS """ diff --git a/modules/local/peach/Dockerfile b/modules/local/peach/Dockerfile deleted file mode 100644 index 25926009..00000000 --- a/modules/local/peach/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - chardet \ - cython \ - dask \ - mypy \ - numpy \ - 'openjdk >=8' \ - pandas \ - scikit-allel \ - zlib && \ - micromamba clean --all --yes - -USER root - -RUN \ - apt-get update && \ - apt-get install -y build-essential git procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" - -RUN \ - pip install 'TransVar==2.5.8.20190813' - -RUN \ - git clone https://github.com/hartwigmedical/peach.git -b v1.7 /opt/peach/ - -RUN \ - apt-get remove -y build-essential git && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -USER mambauser diff --git a/modules/local/peach/main.nf b/modules/local/peach/main.nf deleted file mode 100644 index 34d6ba37..00000000 --- a/modules/local/peach/main.nf +++ /dev/null @@ -1,46 +0,0 @@ -process PEACH { - tag "${meta.id}" - label 'process_single' - - container 'docker.io/scwatts/peach:1.7--0' - - input: - tuple val(meta), path(germline_vcf) - val genome_ver - path panel - - output: - tuple val(meta), path('*.genotype.tsv'), emit: genotype - path '*.calls.tsv' , emit: calls - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def tool_version = '1.7' - - """ - python ${task.ext.scriptPath} \\ - --sample_t_id ${meta.tumor_id} \\ - --sample_r_id ${meta.normal_id} \\ - --vcf ${germline_vcf} \\ - --vcf_reference_assembly_version V${genome_ver} \\ - --panel ${panel} \\ - --tool_version ${tool_version} \\ - --outputdir ./ - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - peach: ${tool_version} - END_VERSIONS - """ - - stub: - """ - touch "${meta.tumor_id}.peach.calls.tsv" - touch "${meta.tumor_id}.peach.genotype.tsv" - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/peach/meta.yml b/modules/local/peach/meta.yml deleted file mode 100644 index d4ee9dc0..00000000 --- a/modules/local/peach/meta.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: peach -description: Match germline small variants with pharmacogenetic evidence -keywords: - - pharmacogenetic - - variant - - annotation - - germline -tools: - - peach: - description: Matches germline small variants with pharmacogenetic evidence. - homepage: https://github.com/hartwigmedical/peach - documentation: https://github.com/hartwigmedical/peach -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - - genome_ver: - type: string - description: Reference genome version - - panel: - type: file - description: PEACH panel file - pattern: "*.{json}" -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - - genotype: - type: file - description: Genotypes file - pattern: "*.{tsv}" - - calls: - type: file - description: Haplotype calls file - pattern: "*.{tsv}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@scwatts" diff --git a/modules/local/protect/Dockerfile b/modules/local/protect/Dockerfile deleted file mode 100644 index 870f3e2a..00000000 --- a/modules/local/protect/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/protect/ && \ - wget -O /opt/protect/protect.jar 'https://github.com/hartwigmedical/hmftools/releases/download/protect-v2.3/protect.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'openjdk >=8' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/protect/main.nf b/modules/local/protect/main.nf deleted file mode 100644 index 5158382b..00000000 --- a/modules/local/protect/main.nf +++ /dev/null @@ -1,68 +0,0 @@ -process PROTECT { - tag "${meta.id}" - label 'process_single' - - container 'docker.io/scwatts/protect:2.3--0' - - input: - tuple val(meta), path(chord_prediction), path(purple_dir), path(linx_dir), path(lilac_dir), path(virusinterpreter) - val genome_ver - path serve_resources - path driver_gene_panel - path disease_ontology - - output: - tuple val(meta), path('*.protect.tsv'), emit: tsv - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - - """ - java \\ - -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - -tumor_sample_id ${meta.tumor_id} \\ - -reference_sample_id ${meta.normal_id} \\ - -primary_tumor_doids '' \\ - -output_dir ./ \\ - \\ - -serve_actionability_dir ${serve_resources} \\ - -ref_genome_version ${genome_ver} \\ - -driver_gene_tsv ${driver_gene_panel} \\ - -doid_json ${disease_ontology} \\ - \\ - -chord_prediction_txt ${chord_prediction} \\ - \\ - -purple_qc_file ${purple_dir}/${meta.tumor_id}.purple.qc \\ - -purple_purity_tsv ${purple_dir}/${meta.tumor_id}.purple.purity.tsv \\ - -purple_gene_copy_number_tsv ${purple_dir}/${meta.tumor_id}.purple.cnv.gene.tsv \\ - -purple_somatic_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.somatic.tsv \\ - -purple_somatic_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.somatic.vcf.gz \\ - -purple_germline_driver_catalog_tsv ${purple_dir}/${meta.tumor_id}.driver.catalog.germline.tsv \\ - -purple_germline_variant_vcf ${purple_dir}/${meta.tumor_id}.purple.germline.vcf.gz \\ - \\ - -linx_breakend_tsv ${linx_dir}/${meta.tumor_id}.linx.breakend.tsv \\ - -linx_driver_catalog_tsv ${linx_dir}/${meta.tumor_id}.linx.driver.catalog.tsv \\ - -linx_fusion_tsv ${linx_dir}/${meta.tumor_id}.linx.fusion.tsv \\ - \\ - -lilac_qc_csv ${lilac_dir}/${meta.tumor_id}.lilac.qc.csv \\ - -lilac_result_csv ${lilac_dir}/${meta.tumor_id}.lilac.csv \\ - \\ - -annotated_virus_tsv ${virusinterpreter} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - protect: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*PROTECT v//') - END_VERSIONS - """ - - stub: - """ - touch "${meta.tumor_id}.protect.tsv" - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/protect/meta.yml b/modules/local/protect/meta.yml deleted file mode 100644 index 3ed42132..00000000 --- a/modules/local/protect/meta.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: protect -description: Match somatic variants with treatment evidence -keywords: - - treatment - - variant - - annotation - - somatic -tools: - - protect: - description: Matches somatic variants with treatment evidence. - homepage: https://github.com/hartwigmedical/oncoact/tree/master/protect - documentation: https://github.com/hartwigmedical/oncoact/tree/master/protect -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - - chord_prediction: - type: file - description: CHORD prediction file - pattern: "*.{txt}" - - purple_dir: - type: directory - description: PURPLE output directory - - linx_dir: - type: directory - description: LINX somatic annotation output directory - - lilac_dir: - type: directory - description: LILAC output directory - - virusinterpreter: - type: file - description: Virus Interpreter annotations file - pattern: "*.{tsv}" - - genome_ver: - type: string - description: Reference genome version - - serve_resources: - type: directory - description: SERVE resources directory - - disease_ontology: - type: file - description: Disease ontology file - pattern: "*.{json}" -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - - tsv: - type: file - description: PROTECT output file - pattern: "*.{tsv}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@scwatts" diff --git a/modules/local/purple/Dockerfile b/modules/local/purple/Dockerfile index d00dd84a..1253714e 100644 --- a/modules/local/purple/Dockerfile +++ b/modules/local/purple/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/purple/ && \ - wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.7/purple_v3.7.1.jar' + wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.8.2/purple_v3.8.2.jar' USER mambauser diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 3238da3c..d8dc7cf7 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -2,10 +2,10 @@ process PURPLE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/purple:3.7.1--0' + container 'docker.io/scwatts/purple:3.8.2--0' input: - tuple val(meta), path(amber), path(cobalt), path(sv_vcf), path(sv_vcf_index), path(sv_unfiltered_vcf), path(sv_unfiltered_vcf_index), path(smlv_tumor_vcf), path(smlv_normal_vcf) + tuple val(meta), path(amber), path(cobalt), path(sv_tumor_vcf), path(sv_tumor_tbi), path(sv_tumor_unfiltered_vcf), path(sv_tumor_unfiltered_tbi), path(sv_normal_vcf), path(sv_normal_tbi), path(smlv_tumor_vcf), path(smlv_normal_vcf) path genome_fasta path genome_fai path genome_dict @@ -27,8 +27,10 @@ process PURPLE { script: def args = task.ext.args ?: '' - def sv_vcf_arg = sv_vcf ? "-structural_vcf ${sv_vcf}" : '' - def sv_lowconf_vcf_fp = sv_unfiltered_vcf ? "-sv_recovery_vcf ${sv_unfiltered_vcf}" : '' + def sv_tumor_vcf_arg = sv_tumor_vcf ? "-somatic_sv_vcf ${sv_tumor_vcf}" : '' + def sv_normal_vcf_arg = sv_normal_vcf ? "-germline_sv_vcf ${sv_normal_vcf}" : '' + + def sv_tumor_recovery_vcf_arg = sv_tumor_unfiltered_vcf ? "-sv_recovery_vcf ${sv_tumor_unfiltered_vcf}" : '' def smlv_tumor_vcf_fp = smlv_tumor_vcf ?: '' def smlv_normal_vcf_fp = smlv_normal_vcf ?: '' @@ -42,13 +44,13 @@ process PURPLE { fp=\${1} fn=\${fp##*/} if [[ "\${fp}" != '' ]]; then - fp_out="prepared__\${2}__\${fn}" - bcftools filter -Oz -e 'FORMAT/AD[*]="."' "\${fp}" > \${fp_out} + fp_out=prepared__\${2}__\${fn} + bcftools view -e 'FORMAT/AD[*]="."' -o \${fp_out} \${fp} echo "-\${2} \${fp_out}" fi } - smlv_tumor_vcf_arg=\$(get_smlv_arg "${smlv_tumor_vcf_fp}" somatic_vcf) - smlv_normal_vcf_arg=\$(get_smlv_arg "${smlv_normal_vcf_fp}" germline_vcf) + smlv_tumor_vcf_arg=\$(get_smlv_arg ${smlv_tumor_vcf_fp} somatic_vcf) + smlv_normal_vcf_arg=\$(get_smlv_arg ${smlv_normal_vcf_fp} germline_vcf) # Run PURPLE java \\ @@ -57,29 +59,24 @@ process PURPLE { ${args} \\ -tumor ${meta.tumor_id} \\ -reference ${meta.normal_id} \\ - ${sv_vcf_arg} \\ - ${sv_lowconf_vcf_fp} \\ - \${smlv_tumor_vcf_arg} \\ - \${smlv_normal_vcf_arg} \\ -amber ${amber} \\ -cobalt ${cobalt} \\ - -output_dir purple/ \\ - -gc_profile ${gc_profile} \\ - -run_drivers \\ + ${sv_tumor_vcf} \\ + ${sv_normal_vcf} \\ + ${sv_tumor_recovery_vcf_arg} \\ + \${smlv_tumor_vcf_arg} \\ + \${smlv_normal_vcf_arg} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ -driver_gene_panel ${driver_gene_panel} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -somatic_hotspots ${sage_known_hotspots_somatic} \\ -germline_hotspots ${sage_known_hotspots_germline} \\ ${germline_del_arg} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ + -gc_profile ${gc_profile} \\ + -circos ${task.ext.circosPath} \\ -threads ${task.cpus} \\ - -circos ${task.ext.circosPath} - - # PURPLE can fail silently, check that at least the PURPLE SV VCF is created - if [[ ! -s "purple/${meta.tumor_id}.purple.sv.vcf.gz" ]]; then - exit 1; - fi + -output_dir purple/ cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -95,9 +92,11 @@ process PURPLE { touch purple/${meta.tumor_id}.purple.driver.catalog.germline.tsv touch purple/${meta.tumor_id}.purple.driver.catalog.somatic.tsv touch purple/${meta.tumor_id}.purple.germline.vcf.gz + touch purple/${meta.tumor_id}.purple.germline.vcf.gz touch purple/${meta.tumor_id}.purple.purity.tsv touch purple/${meta.tumor_id}.purple.qc touch purple/${meta.tumor_id}.purple.somatic.vcf.gz + touch purple/${meta.tumor_id}.purple.sv.germline.vcf.gz touch purple/${meta.tumor_id}.purple.sv.vcf.gz echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ diff --git a/modules/local/sage/Dockerfile b/modules/local/sage/Dockerfile index 5db4d918..a18f34d7 100644 --- a/modules/local/sage/Dockerfile +++ b/modules/local/sage/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/sage/ && \ - wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.2.3/sage_v3.2.3.jar' + wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.2.5/sage_v3.2.5.jar' USER mambauser diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index e4f9fa15..05a6507e 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -1,8 +1,16 @@ +// NOTE(SW): use of tumor and normal sample names here is consistent with Pipeline5 +// - https://github.com/hartwigmedical/pipeline5/blob/v5.32/cluster/src/main/java/com/hartwig/pipeline/calling/sage/SageCommandBuilder.java#L95-L96 +// - https://github.com/hartwigmedical/pipeline5/blob/v5.32/cluster/src/main/java/com/hartwig/pipeline/calling/sage/SageCommandBuilder.java#L112-L118 + +// NOTE(SW): logic that determines BQR outputs assumes '-out' is a path that includes at least leading one directory + +// TODO(SW): check whether intentional sample name switch for germline also affects BQR outputs + process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.2.3--0' + container 'docker.io/scwatts/sage:3.2.5--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -19,7 +27,10 @@ process SAGE_GERMLINE { output: tuple val(meta), path('*.sage.germline.vcf.gz'), path('*.sage.germline.vcf.gz.tbi') , emit: vcf tuple val(meta), path('*.sage.germline.filtered.vcf.gz'), path('*.sage.germline.filtered.vcf.gz.tbi'), emit: vcf_filtered + tuple val(meta), path("${meta.tumor_id}.sage.bqr.png") , emit: tumor_bqr_png, optional: true + tuple val(meta), path("${meta.normal_id}.sage.bqr.png") , emit: normal_bqr_png, optional: true tuple val(meta), path('*gene.coverage.tsv') , emit: gene_coverage, optional: true + path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true path 'versions.yml' , emit: versions when: @@ -37,8 +48,8 @@ process SAGE_GERMLINE { -tumor_bam ${normal_bam} \\ -reference ${meta.tumor_id} \\ -reference_bam ${tumor_bam} \\ - -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ -hotspots ${sage_known_hotspots_germline} \\ -panel_bed ${sage_actionable_panel} \\ -coverage_bed ${sage_coverage_panel} \\ @@ -52,6 +63,8 @@ process SAGE_GERMLINE { -panel_max_germline_rel_raw_base_qual 100 \\ -ref_sample_count 0 \\ -panel_only \\ + -write_bqr_data \\ + -write_bqr_plot \\ -threads ${task.cpus} \\ -out ./${meta.tumor_id}.sage.germline.vcf.gz @@ -72,7 +85,11 @@ process SAGE_GERMLINE { touch "${meta.tumor_id}.sage.germline.vcf.gz.tbi" touch "${meta.tumor_id}.sage.germline.filtered.vcf.gz" touch "${meta.tumor_id}.sage.germline.filtered.vcf.gz.tbi" - touch "${meta.tumor_id}.gene.coverage.tsv" + touch "${meta.tumor_id}.sage.bqr.png" + touch "${meta.tumor_id}.sage.bqr.tsv" + touch "${meta.normal_id}.sage.bqr.png" + touch "${meta.normal_id}.sage.bqr.tsv" + touch "${meta.normal_id}.gene.coverage.tsv" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 94f57ead..e0018cea 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -1,11 +1,10 @@ -// NOTE(SW): logic that determines BQR outputs assumes '-out' is a path that includes at least -// leading one directory +// NOTE(SW): logic that determines BQR outputs assumes '-out' is a path that includes at least leading one directory process SAGE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.2.3--0' + container 'docker.io/scwatts/sage:3.2.5--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -23,7 +22,7 @@ process SAGE_SOMATIC { tuple val(meta), path('*.sage.somatic.filtered.vcf.gz'), path('*.sage.somatic.filtered.vcf.gz.tbi'), emit: vcf_filtered tuple val(meta), path("${meta.tumor_id}.sage.bqr.png") , emit: tumor_bqr_png, optional: true tuple val(meta), path("${meta.normal_id}.sage.bqr.png") , emit: normal_bqr_png, optional: true - path '*gene.coverage.tsv' , emit: gene_coverage, optional: true + tuple val(meta), path('*gene.coverage.tsv') , emit: gene_coverage, optional: true path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true path 'versions.yml' , emit: versions @@ -42,8 +41,8 @@ process SAGE_SOMATIC { -reference_bam ${normal_bam} \\ -tumor ${meta.tumor_id} \\ -tumor_bam ${tumor_bam} \\ - -ref_genome_version ${genome_ver} \\ -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ -hotspots ${sage_known_hotspots_somatic} \\ -panel_bed ${sage_actionable_panel} \\ -coverage_bed ${sage_actionable_panel} \\ @@ -71,8 +70,11 @@ process SAGE_SOMATIC { touch "${meta.tumor_id}.sage.somatic.vcf.gz.tbi" touch "${meta.tumor_id}.sage.somatic.filtered.vcf.gz" touch "${meta.tumor_id}.sage.somatic.filtered.vcf.gz.tbi" + touch "${meta.tumor_id}.gene.coverage.tsv" touch "${meta.tumor_id}.sage.bqr.png" + touch "${meta.tumor_id}.sage.bqr.tsv" touch "${meta.normal_id}.sage.bqr.png" + touch "${meta.normal_id}.sage.bqr.tsv" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile index bd69fcc1..8c2b669d 100644 --- a/modules/local/svprep/Dockerfile +++ b/modules/local/svprep/Dockerfile @@ -3,12 +3,20 @@ FROM docker.io/scwatts/gridss:2.13.2--3 ARG GH_BASE_URL='https://github.com/hartwigmedical/hmftools' USER root +RUN \ + apt-get update && \ + apt-get install -y patch && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + RUN \ mkdir -p /opt/svprep/ && \ - wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.1/sv-prep_v1.1.jar' + wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.1/sv-prep_v1.1.jar' && \ + wget -O /opt/svprep/gridss_svprep 'https://raw.githubusercontent.com/hartwigmedical/hmftools/sv-prep-v1.1/sv-prep/src/main/resources/gridss/gridss.run.sh' -COPY assets/gridss.svprep /opt/svprep/gridss_svprep +COPY assets/gridss_svprep.patch /tmp/ RUN \ + patch -lp1 -d /opt/svprep/ /tmp/gridss_svprep.patch && \ chmod 755 /opt/svprep/gridss_svprep && \ ln -s /opt/svprep/gridss_svprep /usr/local/bin/ diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 4bd813e7..5929fb86 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -2,7 +2,7 @@ process GRIDSS_ASSEMBLE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.1--1' input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) diff --git a/modules/local/svprep/assets/gridss.svprep b/modules/local/svprep/assets/gridss.svprep deleted file mode 100644 index 60e8375a..00000000 --- a/modules/local/svprep/assets/gridss.svprep +++ /dev/null @@ -1,833 +0,0 @@ -#!/bin/bash -# GRIDSS execution script using SvPrep BAMs - -getopt --test -if [[ ${PIPESTATUS[0]} -ne 4 ]]; then - echo 'WARNING: "getopt --test"` failed in this environment.' 1>&2 - echo "WARNING: The version of getopt(1) installed on this system might not be compatible with the GRIDSS driver script." 1>&2 -fi -unset DISPLAY # Prevents errors attempting to connecting to an X server when starting the R plotting device -ulimit -n $(ulimit -Hn 2>/dev/null) 2>/dev/null # Reduce likelihood of running out of open file handles -set -o errexit -o pipefail -o noclobber -o nounset -last_command="" -current_command="" -trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG -trap 'echo "\"${last_command}\" command completed with exit code $?."' EXIT -#253 forcing C locale for everything -export LC_ALL=C - -EX_USAGE=64 -EX_NOINPUT=66 -EX_CANTCREAT=73 -EX_CONFIG=78 - -workingdir="." -reference="" -output_vcf="" -assembly="" -threads=8 -jvmheap="30g" -otherjvmheap="4g" -blacklist="" -metricsrecords=10000000 -maxcoverage=50000 -config_file="" -labels="" -bams="" -filtered_bams="" -full_bams="" -keepTempFiles="false" - -steps="all" -do_preprocess=false -do_assemble=false -do_call=false - -USAGE_MESSAGE=" -Usage: gridss [options] -r -o -a input1.bam [input2.bam [...]] - - -r/--reference: reference genome to use. - -o/--output: output VCF. - -a/--assembly: location of the GRIDSS assembly BAM. This file will be - created by GRIDSS. - -t/--threads: number of threads to use. (Default: $threads) - -j/--jar: location of GRIDSS jar - -w/--workingdir: directory to place GRIDSS intermediate and temporary files - .gridss.working subdirectories will be created. (Default: $workingdir) - -s/--steps: processing steps to run. Defaults to all steps. - Multiple steps are specified using comma separators. Possible steps are: - preprocess, assemble, call, all - -e/--blacklist: BED file containing regions to ignore - -c/--configuration: configuration file use to override default GRIDSS - settings. - -l/--labels: comma separated labels to use in the output VCF for the input - files. Supporting read counts for input files with the same label are - aggregated (useful for multiple sequencing runs of the same sample). - Labels default to input filenames, unless a single read group with a - non-empty sample name exists in which case the read group sample name - is used (which can be disabled by \"useReadGroupSampleNameCategoryLabel=false\" - in the configuration file). If labels are specified, they must be - specified for all input files. - -b/bams: comma separated full-path BAM files - -f/filtered_bams: comma separated full-path filtered BAM files - --jvmheap: size of JVM heap for the high-memory component of assembly and variant calling. (Default: $jvmheap) - --otherjvmheap: size of JVM heap for everything else. Useful to prevent - java out of memory errors when using large (>4Gb) reference genomes. - Note that some parts of assembly and variant calling use this heap - size. (Default: $otherjvmheap) - " - -OPTIONS=r:o:a:t:j:w:e:s:c:l:b:f: -LONGOPTS=reference:,output:,assembly:,threads:,jar:,workingdir:,jvmheap:,otherjvmheap:,blacklist:,steps:,configuration:,labels:,bams:,filtered_bams: -! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") -if [[ ${PIPESTATUS[0]} -ne 0 ]]; then - # e.g. return value is 1 - # then getopt has complained about wrong arguments to stdout - echo "$USAGE_MESSAGE" 1>&2 - exit $EX_USAGE -fi -eval set -- "$PARSED" - -POSITIONAL_ARGS=() - -#while true; do -while [[ $# -gt 0 ]]; do - case "$1" in - -r|--reference) - reference="$2" - shift 2 - ;; - -l|--labels) - labels="$2" - shift 2 - ;; - -b|--bams) - bams="$2" - shift 2 - ;; - -f|--filtered_bams) - filtered_bams="$2" - shift 2 - ;; - -s|--steps) - steps="$2" - shift 2 - ;; - -w|--workingdir) - workingdir="$2" - shift 2 - ;; - -o|--output) - output_vcf="$2" - shift 2 - ;; - -a|--assembly) - if [[ "$assembly" == "" ]] ; then - assembly="$2" - else - assembly="$assembly $2" - fi - # TODO: support multiple assembly files - shift 2 - ;; - -e|--blacklist) - blacklist="$2" - shift 2 - ;; - -j|--jar) - GRIDSS_JAR="$2" - shift 2 - ;; - --jvmheap) - jvmheap="$2" - shift 2 - ;; - --otherjvmheap) - otherjvmheap="$2" - shift 2 - ;; - -t|--threads) - printf -v threads '%d\n' "$2" 2>/dev/null - printf -v threads '%d' "$2" 2>/dev/null - shift 2 - ;; - -c|--configuration) - config_file=$2 - shift 2 - ;; - *) - POSITIONAL_ARGS+=("$1") # save positional arg - # echo "Unparsed param" - shift - ;; - esac -done - -##### --workingdir -echo "Using working directory \"$workingdir\"" 1>&2 -if [[ "$workingdir" == "" ]] ; then - echo "$USAGE_MESSAGE" 1>&2 - echo "Working directory must be specified. Specify using the --workingdir command line argument" 1>&2 - exit $EX_USAGE -fi -if [[ "$(tr -d ' \n' <<< "$workingdir")" != "$workingdir" ]] ; then - echo "workingdir cannot contain whitespace" 1>&2 - exit $EX_USAGE - fi -if [[ ! -d $workingdir ]] ; then - mkdir -p $workingdir - if [[ ! -d $workingdir ]] ; then - echo Unable to create working directory $workingdir 1>&2 - exit $EX_CANTCREAT - fi -fi -workingdir=$(dirname $workingdir/placeholder) -timestamp=$(date +%Y%m%d_%H%M%S) -# Logging -logfile=$workingdir/gridss.full.$timestamp.$HOSTNAME.$$.log -# $1 is message to write -write_status() { - echo "$(date): $1" | tee -a $logfile 1>&2 -} -write_status "Full log file is: $logfile" -trap 'echo "\"${last_command}\" command completed with exit code $?. -***** -The underlying error message can be found in $logfile -*****"' EXIT -# Timing instrumentation -timinglogfile=$workingdir/gridss.timing.$timestamp.$HOSTNAME.$$.log -if which /usr/bin/time >/dev/null ; then - timecmd="/usr/bin/time" - write_status "Found /usr/bin/time" -else - timecmd="" - write_status "Not found /usr/bin/time" -fi -if [[ "$timecmd" != "" ]] ; then - timecmd="/usr/bin/time --verbose -a -o $timinglogfile" - if ! $timecmd echo 2>&1 > /dev/null; then - timecmd="/usr/bin/time -a -o $timinglogfile" - fi - if ! $timecmd echo 2>&1 > /dev/null ; then - timecmd="" - write_status "Unexpected /usr/bin/time version. Not logging timing information." - fi - # We don't need timing info of the echo - rm -f $timinglogfile -fi - -### Find the jars -find_jar() { - env_name=$1 - if [[ -f "${!env_name:-}" ]] ; then - echo "${!env_name}" - else - write_status "Unable to find $2 jar. Specify using the environment variant $env_name, or the --jar command line parameter." - exit $EX_NOINPUT - fi -} -gridss_jar=$(find_jar GRIDSS_JAR gridss) -write_status "Using GRIDSS jar $gridss_jar" - -# Check all key inputs: - -if [[ "$labels" == "" ]] ; then - write_status "Labels must be specified" - exit $EX_USAGE -fi - -if [[ "$bams" == "" ]] ; then - write_status "Full BAMs must be specified" - exit $EX_USAGE -fi - -if [[ "$filtered_bams" == "" ]] ; then - write_status "Filtered BAMs must be specified" - exit $EX_USAGE -fi - -##### --reference -if [[ "$reference" == "" ]] ; then - write_status "$USAGE_MESSAGE" - write_status "Reference genome must be specified. Specify using the --reference command line argument" - exit $EX_USAGE -fi - -if [ ! -f $reference ] ; then - write_status "$USAGE_MESSAGE" - write_status "Missing reference genome $reference. Specify reference location using the --reference command line argument" - exit $EX_USAGE -fi -write_status "Using reference genome \"$reference\"" - -##### --output -if [[ $do_call == "true" ]] ; then - if [[ "$output_vcf" == "" ]] ; then - write_status "$USAGE_MESSAGE" - write_status "Output VCF not specified. Use --output to specify output file." - exit $EX_USAGE - fi - mkdir -p $(dirname $output_vcf) - if [[ ! -d $(dirname $output_vcf) ]] ; then - write_status "Unable to create directory for $output_vcf for output VCF." - exit $EX_CANTCREAT - fi - write_status "Using output VCF $output_vcf" -fi -write_status "Using output VCF $output_vcf" - -##### --assembly -if [[ $do_assemble == "true" ]] || [[ $do_call == "true" ]]; then - if [[ "$assembly" == "" ]] ; then - if [[ "$output_vcf" == "" ]] ; then - write_status "Either the assembly output file must explicitly specified with -a, or the output VCF specified with -o" - exit $EX_USAGE - fi - assembly=$output_vcf.assembly.bam - fi - write_status "Using assembly bam $assembly" - if [[ $do_assemble == "true" ]] ; then - mkdir -p $(dirname $assembly) - if [[ ! -d $(dirname $assembly) ]] ; then - write_status "Unable to parent create directory for $assembly" - exit $EX_CANTCREAT - fi - else - if [[ ! -f $assembly ]] ; then - write_status "Missing assembly file $assembly" - write_status "Ensure the GRIDSS assembly step has been run" - exit $EX_NOINPUT - fi - fi -fi - -##### --threads -if [[ "$threads" -lt 1 ]] ; then - write_status "$USAGE_MESSAGE" - write_status "Illegal thread count: $threads. Specify an integer thread count using the --threads command line argument" - exit $EX_USAGE -fi -if [[ "$threads" -gt 8 ]] ; then - write_status "WARNING: GRIDSS scales sub-linearly at high thread count. Up to 8 threads is the recommended level of parallelism." -fi -write_status "Using $threads worker threads." - -if [[ "$blacklist" == "" ]] ; then - blacklist_arg="" - write_status "Using no blacklist bed. The encode DAC blacklist is recommended for hg19." -elif [[ ! -f $blacklist ]] ; then - write_status "$USAGE_MESSAGE" - write_status "Missing blacklist file $blacklist" - exit $EX_NOINPUT -else - blacklist_arg="BLACKLIST=$blacklist" - write_status "Using blacklist $blacklist" - if [[ "$(tr -d ' \n' <<< "$blacklist_arg")" != "$blacklist_arg" ]] ; then - write_status "blacklist cannot contain whitespace" - exit $EX_USAGE - fi -fi - -if [[ "$jvmheap" == "" ]] ; then - if [[ $threads -gt 8 ]] ; then - write_status "Warning: GRIDSS assembly may stall and run out of memory. with $threads and $jvmheap heap size." - fi -fi - -write_status "Using JVM maximum heap size of $jvmheap for assembly and variant calling." - -config_args="" -if [[ "$config_file" != "" ]] ; then - if [[ ! -f $config_file ]] ; then - write_status "Configuration file $config_file does not exist" - exit $EX_NOINPUT - fi - config_args="CONFIGURATION_FILE=$config_file" -fi - -input_args="" -input_filtered_args="" - -# no longer read in the BAM file list from the end of the arguments list - -nows_labels=$(tr -d ' \n' <<< "$labels") -if [[ "$nows_labels" != "$labels" ]] ; then - write_status "input labels cannot contain whitespace" - exit $EX_USAGE -fi -IFS=',' read -ra LABEL_ARRAY <<< "$nows_labels" -label_count=${#LABEL_ARRAY[@]} - -for label in "${LABEL_ARRAY[@]}" ; do - input_args="$input_args INPUT_LABEL=$label" - input_filtered_args="$input_filtered_args INPUT_LABEL=$label" - #write_status "label is $label" -done - -nows_bams=$(tr -d ' \n' <<< "$bams") -if [[ "$nows_bams" != "$bams" ]] ; then - write_status "input filtered BAMs cannot contain whitespace" - exit $EX_USAGE -fi -IFS=',' read -ra BAM_ARRAY <<< "$nows_bams" -for bam_file in "${BAM_ARRAY[@]}" ; do - - if [[ "$(basename $bam_file)" == "$(basename $assembly)" ]] ; then - write_status "assembly and input filtered bam files must have different filenames" - exit $EX_USAGE - fi - - input_args="$input_args INPUT=$bam_file" - # write_status "full bam file is $bam_file" -done - -nows_bams=$(tr -d ' \n' <<< "$filtered_bams") -if [[ "$nows_bams" != "$filtered_bams" ]] ; then - write_status "input filtered BAMs cannot contain whitespace" - exit $EX_USAGE -fi -IFS=',' read -ra FILT_BAM_ARRAY <<< "$nows_bams" -for filtered_bam_file in "${FILT_BAM_ARRAY[@]}" ; do - - if [[ "$(basename $filtered_bam_file)" == "$(basename $assembly)" ]] ; then - write_status "assembly and input filtered bam files must have different filenames" - exit $EX_USAGE - fi - - input_filtered_args="$input_filtered_args INPUT=$filtered_bam_file" - # write_status "filtered bam file is $filtered_bam_file" -done - -for (( i=0; i < $label_count; ++i )) -do - write_status "Label $i: name=${LABEL_ARRAY[$i]} full-bam=${BAM_ARRAY[$i]} filtered-bam=${FILT_BAM_ARRAY[$i]}" -done - -write_status "Full BAM args: $input_args" -write_status "Filtered BAM args: $input_filtered_args" - - -# Validate tools exist on path -for tool in Rscript samtools java bwa ; do #minimap2 - if ! which $tool >/dev/null; then - write_status "Error: unable to find $tool on \$PATH" - exit $EX_CONFIG - fi - write_status "Found $(which $tool)" -done -if $(samtools --version-only >/dev/null) ; then - write_status "samtools version: $(samtools --version-only 2>&1)" -else - write_status "Your samtools version does not support --version-only. Update samtools." - exit $EX_CONFIG -fi -if [[ "$(samtools --version-only)" =~ ^([0-9]+)[.]([0-9]+) ]] ; then - samtools_major_version=${BASH_REMATCH[1]} - samtools_minor_version=${BASH_REMATCH[2]} - if [[ "$samtools_major_version" -le 1 ]] && [[ "$samtools_minor_version" -lt 10 ]] ; then - write_status "samtools 1.13 or later is required." - exit $EX_CONFIG - fi -else - write_status "Unable to determine samtools version" - exit $EX_CONFIG -fi - -# write_status "R version: $(Rscript --version 2>&1)" - -write_status "bwa $(bwa 2>&1 | grep Version || echo -n)" - -if [[ "$timecmd" != "" ]] ; then - if which /usr/bin/time >/dev/null ; then - write_status "time version: $(/usr/bin/time --version 2>&1)" - fi -fi -write_status "bash version: $(/bin/bash --version 2>&1 | head -1)" - -# check java version is ok using the gridss.Echo entry point -if java -cp $gridss_jar gridss.Echo ; then - write_status "java version: $(java -version 2>&1 | tr '\n' '\t')" -else - write_status "Unable to run GRIDSS jar - requires java 1.8 or later" - write_status "java version: $(java -version 2>&1)" - exit $EX_CONFIG -fi - -if ! java -Xms$jvmheap -cp $gridss_jar gridss.Echo ; then - write_status "Failure invoking java with --jvmheap parameter of \"$jvmheap\". Specify a JVM heap size (e.g. \"31g\") that is valid for this machine." - exit 1 -fi - -write_status "Max file handles: $(ulimit -n)" 1>&2 - -steps_message="Running GRIDSS steps:" - -for step in $(echo $steps | tr ',' ' ' ) ; do - if [[ "$step" == "all" ]] ; then - do_preprocess=true - do_assemble=true - do_call=true - steps_message="$steps_message all" - elif [[ "$step" == "preprocess" ]] ; then - do_preprocess=true - steps_message="$steps_message pre-process" - elif [[ "$step" == "assemble" ]] ; then - do_assemble=true - steps_message="$steps_message assembly" - elif [[ "$step" == "call" ]] ; then - do_call=true - steps_message="$steps_message call" - else - write_status "Unknown step \"$step\"" - exit $EX_USAGE - fi -done - -write_status "$steps_message" - -# don't keep files -if [[ $keepTempFiles == "true" ]] ; then - rmcmd="echo rm disabled:" - jvm_args="-Dgridss.keepTempFiles=true" -else - rmcmd="rm" - jvm_args="" -fi - -jvm_args="$jvm_args \ - -XX:ParallelGCThreads=$threads \ - -Dsamjdk.reference_fasta=$reference \ - -Dsamjdk.use_async_io_read_samtools=true \ - -Dsamjdk.use_async_io_write_samtools=true \ - -Dsamjdk.use_async_io_write_tribble=true \ - -Dsamjdk.buffer_size=4194304 \ - -Dsamjdk.async_io_read_threads=$threads" - -aligner_args=' - ALIGNER_COMMAND_LINE=null - ALIGNER_COMMAND_LINE=bwa - ALIGNER_COMMAND_LINE=mem - ALIGNER_COMMAND_LINE=-K - ALIGNER_COMMAND_LINE=10000000 - ALIGNER_COMMAND_LINE=-L - ALIGNER_COMMAND_LINE=0,0 - ALIGNER_COMMAND_LINE=-t - ALIGNER_COMMAND_LINE=%3$d - ALIGNER_COMMAND_LINE=%2$s - ALIGNER_COMMAND_LINE=%1$s' - -samtools_sort="samtools sort --no-PG -@ $threads" - -readpairing_args="READ_PAIR_CONCORDANT_PERCENT=null" - - -# set-up reference has been removed since can assume to exist - -#### -# Pre-process for each filtered BAM file -#### - -if [[ $do_preprocess == true ]] ; then - write_status "*** PRE-PROCESS ***" - - for (( i=0; i < $label_count; ++i )) - do - label=${LABEL_ARRAY[$i]} - bam_file=${FILT_BAM_ARRAY[$i]} - write_status "Processing: sample ${LABEL_ARRAY[$i]}, filtered-bam ${FILT_BAM_ARRAY[$i]}" - - dir=$workingdir/$(basename $bam_file).gridss.working - prefix=$dir/$(basename $bam_file) - write_status "Start pre-processing: $bam_file, working dir: $dir, prefix: $prefix" - - tmp_prefix=$workingdir/$(basename $bam_file).gridss.working/tmp.$(basename $bam_file) - mkdir -p $dir - if [[ ! -d $dir ]] ; then - write_status "Unable to create directory $dir" - exit $EX_CANTCREAT - fi - - name_sorted_bam=$tmp_prefix.namedsorted.bam - write_status "Creating name-sorted BAM from $bam_file, writing to $name_sorted_bam" - - $timecmd $samtools_sort -l 1 -n \ - -T $tmp_prefix.namedsorted-tmp \ - -Obam \ - -o ${name_sorted_bam} \ - ${bam_file} - - write_status "Running ComputeSamTags|samtools: $bam_file" - - rm -f $tmp_prefix.coordinate-tmp* - - { $timecmd java -Xmx$otherjvmheap $jvm_args \ - -cp $gridss_jar gridss.ComputeSamTags \ - TMP_DIR=$dir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - COMPRESSION_LEVEL=0 \ - I=$name_sorted_bam \ - O=/dev/stdout \ - WORKER_THREADS=$threads \ - ASSUME_SORTED=true \ - REMOVE_TAGS=aa \ - MODIFICATION_SUMMARY_FILE=$prefix.computesamtags.changes.tsv \ - | $timecmd $samtools_sort \ - -l 1 \ - -T $tmp_prefix.coordinate-tmp \ - -Obam \ - -o $tmp_prefix.coordinate.bam \ - /dev/stdin \ - ; } 1>&2 2>> $logfile - - write_status "Removing name-sorted bam: $tmp_prefix.namedsorted.bam" - $rmcmd $tmp_prefix.namedsorted.bam - - write_status "Running SoftClipsToSplitReads: sample $label, input: $tmp_prefix.coordinate.bam, output: $tmp_prefix.sc2sr.primary.sv.bam" - rm -f $tmp_prefix.sc2sr.suppsorted.sv-tmp* - { $timecmd java -Xmx$otherjvmheap $jvm_args \ - -Dsamjdk.create_index=false \ - -cp $gridss_jar gridss.SoftClipsToSplitReads \ - TMP_DIR=$workingdir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - I=$tmp_prefix.coordinate.bam \ - O=$tmp_prefix.sc2sr.primary.sv.bam \ - COMPRESSION_LEVEL=1 \ - OUTPUT_UNORDERED_RECORDS=$tmp_prefix.sc2sr.supp.sv.bam \ - WORKER_THREADS=$threads \ - $aligner_args \ - && $rmcmd $tmp_prefix.coordinate.bam \ - && $timecmd $samtools_sort \ - -l 1 \ - -T $tmp_prefix.sc2sr.suppsorted.sv-tmp \ - -Obam \ - -o $tmp_prefix.sc2sr.suppsorted.sv.bam \ - $tmp_prefix.sc2sr.supp.sv.bam \ - && $rmcmd $tmp_prefix.sc2sr.supp.sv.bam \ - && $rmcmd -f $prefix.sv.tmp.bam $prefix.sv.tmp.bam.bai \ - && $timecmd samtools merge \ - -c \ - -p \ - --write-index \ - -@ $threads \ - $prefix.sv.tmp.bam \ - $tmp_prefix.sc2sr.primary.sv.bam \ - $tmp_prefix.sc2sr.suppsorted.sv.bam \ - && $rmcmd $tmp_prefix.sc2sr.primary.sv.bam \ - && $rmcmd $tmp_prefix.sc2sr.suppsorted.sv.bam \ - && mv $prefix.sv.tmp.bam $prefix.sv.bam \ - && mv $prefix.sv.tmp.bam.csi $prefix.sv.bam.csi \ - ; } 1>&2 2>> $logfile - - write_status "Produced SV bam:: $prefix.sv.bam" - - # create metrics on the full BAM and then copy these over the metrics made from the filtered BAMs - full_bam_file=${BAM_ARRAY[$i]} - write_status "Running CollectGridssMetrics on $label full BAM $full_bam_file" - - # test_prefix=$prefix.cp - - { $timecmd java -Xmx$otherjvmheap $jvm_args \ - -cp $gridss_jar gridss.analysis.CollectGridssMetrics \ - REFERENCE_SEQUENCE=$reference \ - TMP_DIR=$dir \ - ASSUME_SORTED=true \ - I=$full_bam_file \ - O=$prefix \ - THRESHOLD_COVERAGE=$maxcoverage \ - FILE_EXTENSION=null \ - GRIDSS_PROGRAM=null \ - GRIDSS_PROGRAM=CollectCigarMetrics \ - GRIDSS_PROGRAM=CollectMapqMetrics \ - GRIDSS_PROGRAM=CollectTagMetrics \ - GRIDSS_PROGRAM=CollectIdsvMetrics \ - PROGRAM=null \ - PROGRAM=CollectInsertSizeMetrics \ - STOP_AFTER=$metricsrecords \ - ; } 1>&2 2>> $logfile - - write_status "Complete pre-processing sample: $label" - done - - write_status "*** PRE-PROCESS COMPLETE ***" -fi - -##### -# ASSEMBLY -#### - -assembly_args="ASSEMBLY=$assembly" - -if [[ $do_assemble == true ]] ; then - - write_status "*** ASSEMBLY ***" - write_status "Running AssembleBreakends: writing output to dir $assembly" - { $timecmd java -Xmx$jvmheap $jvm_args \ - -Dgridss.output_to_temp_file=true \ - -cp $gridss_jar gridss.AssembleBreakends \ - JOB_INDEX=0 \ - JOB_NODES=1 \ - TMP_DIR=$workingdir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - WORKER_THREADS=$threads \ - $input_filtered_args \ - $blacklist_arg \ - $config_args \ - $readpairing_args \ - O=$assembly \ - ; } 1>&2 2>> $logfile - - write_status "AssemblyBreakends complete" - - dir=$workingdir/$(basename $assembly).gridss.working/ - prefix=$dir/$(basename $assembly) - tmp_prefix=$dir/tmp.$(basename $assembly) - - write_status "RunningSoftClipsToSplitReads: running on assembly output dir $assembly" - rm -f $tmp_prefix.sc2sr.suppsorted.sv-tmp* - { $timecmd java -Xmx$otherjvmheap $jvm_args \ - -Dgridss.async.buffersize=16 \ - -Dsamjdk.create_index=false \ - -Dgridss.output_to_temp_file=true \ - -cp $gridss_jar gridss.SoftClipsToSplitReads \ - TMP_DIR=$dir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - WORKER_THREADS=$threads \ - I=$assembly \ - O=$tmp_prefix.sc2sr.primary.sv.bam \ - OUTPUT_UNORDERED_RECORDS=$tmp_prefix.sc2sr.supp.sv.bam \ - REALIGN_ENTIRE_READ=true \ - READJUST_PRIMARY_ALIGNMENT_POSITION=true \ - $aligner_args \ - && $timecmd $samtools_sort \ - -T $tmp_prefix.sc2sr.suppsorted.sv-tmp \ - -Obam \ - -o $tmp_prefix.sc2sr.suppsorted.sv.bam \ - $tmp_prefix.sc2sr.supp.sv.bam \ - && $rmcmd $tmp_prefix.sc2sr.supp.sv.bam \ - && $rmcmd -f $prefix.sv.tmp.bam $prefix.sv.tmp.bam.bai \ - && $timecmd samtools merge \ - -c \ - -p \ - -@ $threads \ - $prefix.sv.tmp.bam \ - $tmp_prefix.sc2sr.primary.sv.bam \ - $tmp_prefix.sc2sr.suppsorted.sv.bam \ - && $timecmd samtools index $prefix.sv.tmp.bam \ - && $rmcmd $tmp_prefix.sc2sr.primary.sv.bam \ - && $rmcmd $tmp_prefix.sc2sr.suppsorted.sv.bam \ - && mv $prefix.sv.tmp.bam $prefix.sv.bam \ - && mv $prefix.sv.tmp.bam.bai $prefix.sv.bam.bai \ - ; } 1>&2 2>> $logfile - - write_status "Produced assembly BAM: $prefix.sv.bam" - - write_status "Complete Assembly" - - # no idea why this is a for loop, could just be: ASSEMBLY=$assembly - #assembly_args="" - #for ass in $assembly ; do - # assembly_args="$assembly_args ASSEMBLY=$ass" - #done - write_status "Assembly args: $assembly_args" - - write_status "*** ASSEMBLY COMPLETE ***" -fi - -#### -# VARIANT CALLING -#### - -if [[ $do_call == true ]] ; then - write_status "*** VARIANT CALLING ***" - - write_status "Creating variant VCF: $output_vcf" - - dir=$workingdir/$(basename $output_vcf).gridss.working - prefix=$dir/$(basename $output_vcf) - mkdir -p $dir - if [[ ! -d $dir ]] ; then - write_status "Unable to create directory $dir" - exit $EX_CANTCREAT - fi - - # create symbolic links to the full BAM as though they were produced by the pre-process step - # eg: ./gridss_02/COLO829R.bam.gridss.working/COLO829R.bam.sv.bam - for (( i=0; i < $label_count; ++i )) - do - bam_file=${BAM_ARRAY[$i]} - bam_dir=$workingdir/$(basename $bam_file).gridss.working - - if [[ ! -d $bam_dir ]] ; then - mkdir -p $bam_dir - fi - - sv_bam_file=$bam_dir/$(basename $bam_file).sv.bam - # write_status "Making soft-link to ${sv_bam_file}" - #ln -sfr ${bam_file} ${sv_bam_file} - #ln -sfr ${bam_file}.bai ${sv_bam_file}.bai - done - - write_status "Running IdentifyVariants" - { $timecmd java -Xmx$jvmheap $jvm_args \ - -Dgridss.output_to_temp_file=true \ - -cp $gridss_jar gridss.IdentifyVariants \ - TMP_DIR=$workingdir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - WORKER_THREADS=$threads \ - $input_filtered_args \ - $blacklist_arg \ - $config_args \ - $assembly_args \ - OUTPUT_VCF=$prefix.unallocated.vcf \ - $readpairing_args \ - ; } 1>&2 2>> $logfile - write_status "IdentifyVariants complete, produced $prefix.unallocated.vcf" - - write_status "Running AnnotateVariants" - { $timecmd java -Xmx$jvmheap $jvm_args \ - -Dgridss.output_to_temp_file=true \ - -Dgridss.async.buffersize=2048 \ - -cp $gridss_jar gridss.AnnotateVariants \ - TMP_DIR=$workingdir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - WORKER_THREADS=$threads \ - $input_filtered_args \ - $blacklist_arg \ - $config_args \ - $assembly_args \ - INPUT_VCF=$prefix.unallocated.vcf \ - OUTPUT_VCF=$prefix.allocated.vcf \ - $readpairing_args \ - ; } 1>&2 2>> $logfile - $rmcmd $prefix.unallocated.vcf - write_status "AnnotateVariants complete, produced $prefix.allocated.vcf" - - write_status "Running AnnotateInsertedSequence" - - { $timecmd java -Xmx$otherjvmheap $jvm_args \ - -Dgridss.output_to_temp_file=true \ - -cp $gridss_jar gridss.AnnotateInsertedSequence \ - TMP_DIR=$workingdir \ - WORKING_DIR=$workingdir \ - REFERENCE_SEQUENCE=$reference \ - WORKER_THREADS=$threads \ - INPUT=$prefix.allocated.vcf \ - OUTPUT=$output_vcf \ - && $rmcmd $prefix.allocated.vcf \ - ; } 1>&2 2>> $logfile - write_status "AnnotateInsertedSequence complete, produced $output_vcf" - - write_status "*** VARIANT CALLING COMPLETE ***" -fi - -if [[ -f $logfile ]] ; then - write_status "Run complete with $(grep WARNING $logfile | wc -l) warnings and $(grep ERROR $logfile | wc -l) errors." -fi -trap - EXIT -exit 0 # success! diff --git a/modules/local/svprep/assets/gridss_svprep.patch b/modules/local/svprep/assets/gridss_svprep.patch new file mode 100644 index 00000000..e8e1cb7e --- /dev/null +++ b/modules/local/svprep/assets/gridss_svprep.patch @@ -0,0 +1,139 @@ +--- a/gridss.run.sh 2023-05-02 11:27:25 ++++ b/gridss.run.sh 2023-05-02 11:30:08 +@@ -48,13 +48,15 @@ + + -r/--reference: reference genome to use. + -o/--output: output VCF. ++ -a/--assembly: location of the GRIDSS assembly BAM. This file will be ++ created by GRIDSS. + -t/--threads: number of threads to use. (Default: $threads) + -j/--jar: location of GRIDSS jar + -w/--workingdir: directory to place GRIDSS intermediate and temporary files + .gridss.working subdirectories will be created. (Default: $workingdir) + -s/--steps: processing steps to run. Defaults to all steps. + Multiple steps are specified using comma separators. Possible steps are: +- preprocess, assemble, calling, all ++ preprocess, assemble, call, all + -e/--blacklist: BED file containing regions to ignore + -c/--configuration: configuration file use to override default GRIDSS + settings. +@@ -69,10 +71,14 @@ + -b/bams: comma separated full-path BAM files + -f/filtered_bams: comma separated full-path filtered BAM files + --jvmheap: size of JVM heap for the high-memory component of assembly and variant calling. (Default: $jvmheap) ++ --otherjvmheap: size of JVM heap for everything else. Useful to prevent ++ java out of memory errors when using large (>4Gb) reference genomes. ++ Note that some parts of assembly and variant calling use this heap ++ size. (Default: $otherjvmheap) + " + +-OPTIONS=r:o:t:j:w:e:s:c:l:b:f: +-LONGOPTS=reference:,output:,threads:,jar:,workingdir:,jvmheap:,blacklist:,steps:,configuration:,labels:,bams:,filtered_bams: ++OPTIONS=r:o:a:t:j:w:e:s:c:l:b:f: ++LONGOPTS=reference:,output:,assembly:,threads:,jar:,workingdir:,jvmheap:,otherjvmheap:,blacklist:,steps:,configuration:,labels:,bams:,filtered_bams: + ! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") + if [[ ${PIPESTATUS[0]} -ne 0 ]]; then + # e.g. return value is 1 +@@ -115,6 +121,15 @@ + output_vcf="$2" + shift 2 + ;; ++ -a|--assembly) ++ if [[ "$assembly" == "" ]] ; then ++ assembly="$2" ++ else ++ assembly="$assembly $2" ++ fi ++ # TODO: support multiple assembly files ++ shift 2 ++ ;; + -e|--blacklist) + blacklist="$2" + shift 2 +@@ -127,6 +142,10 @@ + jvmheap="$2" + shift 2 + ;; ++ --otherjvmheap) ++ otherjvmheap="$2" ++ shift 2 ++ ;; + -t|--threads) + printf -v threads '%d\n' "$2" 2>/dev/null + printf -v threads '%d' "$2" 2>/dev/null +@@ -242,25 +261,43 @@ + write_status "Using reference genome \"$reference\"" + + ##### --output +-if [[ "$output_vcf" == "" ]] ; then +- write_status "$USAGE_MESSAGE" +- write_status "Output VCF not specified. Use --output to specify output file." +- exit $EX_USAGE ++if [[ $do_call == "true" ]] ; then ++ if [[ "$output_vcf" == "" ]] ; then ++ write_status "$USAGE_MESSAGE" ++ write_status "Output VCF not specified. Use --output to specify output file." ++ exit $EX_USAGE ++ fi ++ mkdir -p $(dirname $output_vcf) ++ if [[ ! -d $(dirname $output_vcf) ]] ; then ++ write_status "Unable to create directory for $output_vcf for output VCF." ++ exit $EX_CANTCREAT ++ fi ++ write_status "Using output VCF $output_vcf" + fi +-mkdir -p $(dirname $output_vcf) +-if [[ ! -d $(dirname $output_vcf) ]] ; then +- write_status "Unable to create directory for $output_vcf for output VCF." +- exit $EX_CANTCREAT +-fi +-write_status "Using output VCF $output_vcf" + + ##### --assembly +-assembly=$output_vcf.assembly.bam +-write_status "Using assembly bam $assembly" +-mkdir -p $(dirname $assembly) +-if [[ ! -d $(dirname $assembly) ]] ; then +- write_status "Unable to parent create directory for $assembly" +- exit $EX_CANTCREAT ++if [[ $do_assemble == "true" ]] || [[ $do_call == "true" ]]; then ++ if [[ "$assembly" == "" ]] ; then ++ if [[ "$output_vcf" == "" ]] ; then ++ write_status "Either the assembly output file must explicitly specified with -a, or the output VCF specified with -o" ++ exit $EX_USAGE ++ fi ++ assembly=$output_vcf.assembly.bam ++ fi ++ write_status "Using assembly bam $assembly" ++ if [[ $do_assemble == "true" ]] ; then ++ mkdir -p $(dirname $assembly) ++ if [[ ! -d $(dirname $assembly) ]] ; then ++ write_status "Unable to parent create directory for $assembly" ++ exit $EX_CANTCREAT ++ fi ++ else ++ if [[ ! -f $assembly ]] ; then ++ write_status "Missing assembly file $assembly" ++ write_status "Ensure the GRIDSS assembly step has been run" ++ exit $EX_NOINPUT ++ fi ++ fi + fi + + ##### --threads +@@ -433,12 +470,12 @@ + elif [[ "$step" == "preprocess" ]] ; then + do_preprocess=true + steps_message="$steps_message pre-process" +- elif [[ "$step" == "assembly" ]] ; then ++ elif [[ "$step" == "assemble" ]] ; then + do_assemble=true + steps_message="$steps_message assembly" +- elif [[ "$step" == "calling" ]] ; then ++ elif [[ "$step" == "call" ]] ; then + do_call=true +- steps_message="$steps_message calling" ++ steps_message="$steps_message call" + else + write_status "Unknown step \"$step\"" + exit $EX_USAGE diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index f99b6e98..a85669ae 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -2,7 +2,7 @@ process GRIDSS_CALL { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.1--1' input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 3a104e09..74608189 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -2,7 +2,7 @@ process SVPREP_DEPTH_ANNOTATOR { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.1--1' input: tuple val(meta), path(bams), path(bais), path(vcf), val(labels) @@ -29,12 +29,12 @@ process SVPREP_DEPTH_ANNOTATOR { -cp ${task.ext.jarPath} com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ ${args} \\ -input_vcf ${vcf} \\ - -output_vcf sv.svprep.gridss.depths.vcf.gz \\ -samples ${labels_arg} \\ -bam_files ${bams_arg} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ - -threads ${task.cpus} + -threads ${task.cpus} \\ + -output_vcf sv.svprep.gridss.depths.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 512e13c5..a766531a 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -2,7 +2,7 @@ process GRIDSS_PREPROCESS { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.1--1' input: tuple val(meta), path(bam), path(bam_filtered) diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index d21dbfa1..faa545fd 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -2,7 +2,7 @@ process SVPREP { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--0' + container 'docker.io/scwatts/svprep:1.1--1' input: tuple val(meta), path(bam), path(bai), path(junctions) @@ -23,7 +23,7 @@ process SVPREP { script: def args = task.ext.args ?: '' def write_types_arg = write_types ? "-write_types \'${write_types}\'" : '' - def existing_juction_file_arg = junctions ? "-existing_junction_file ${junctions}" : "" + def existing_juction_file_arg = junctions ? "-existing_junction_file ${junctions}" : '' """ java \\ @@ -41,7 +41,12 @@ process SVPREP { -threads ${task.cpus} \\ -output_dir ./ - samtools sort -O bam "${meta.id}.sv_prep.bam" -o "${meta.id}.sv_prep.sorted.bam" + samtools sort \\ + -@ ${task.cpus} \\ + -m ${min(Math.round(task.memory.mega * 0.95), 4096)}K \\ + -T ${meta.id}.sv_prep.tmp \\ + -o ${meta.id}.sv_prep.sorted.bam \\ + ${meta.id}.sv_prep.bam cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/nextflow_schema.json b/nextflow_schema.json index 425045dc..3eec8eee 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -264,22 +264,6 @@ "fa_icon": "far fa-folder-open", "hidden": true }, - "ref_data_linx_fragile_regions": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to LINX fragile sites file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_linx_lines": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to LINX LINEs file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, "ref_data_cohort_mapping": { "type": "string", "format": "file-path", @@ -296,19 +280,20 @@ "fa_icon": "far fa-file-code", "hidden": true }, - "ref_data_peach_panel": { + "ref_data_alt_sj_distribution": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.json$", - "description": "Path to PEACH panel file.", + "pattern": "^\\S+\\.csv.gz$", + "description": "Path to ORANGE alternative splice junction distribution file.", "fa_icon": "far fa-file-code", "hidden": true }, - "ref_data_serve_resources": { + "ref_data_gene_exp_distribution": { "type": "string", - "format": "directory-path", - "description": "Path to SERVE resource directory.", - "fa_icon": "far fa-folder-open", + "format": "file-path", + "pattern": "^\\S+\\.csv.gz$", + "description": "Path to ORANGE gene expression distribution file.", + "fa_icon": "far fa-file-code", "hidden": true }, "ref_data_clinvar_annotations": { diff --git a/subworkflows/local/bamtools_metrics.nf b/subworkflows/local/bamtools_metrics.nf index 0769a57a..d1bd831c 100644 --- a/subworkflows/local/bamtools_metrics.nf +++ b/subworkflows/local/bamtools_metrics.nf @@ -107,7 +107,6 @@ workflow BAMTOOLS_METRICS { germline: sample_type == Constants.SampleType.NORMAL return [meta, metrics] } - ch_versions = ch_versions.mix(BAMTOOLS.out.versions) emit: somatic = ch_outputs.somatic // channel: [val(meta), metrics] diff --git a/subworkflows/local/chord_prediction.nf b/subworkflows/local/chord_prediction.nf new file mode 100644 index 00000000..15cde711 --- /dev/null +++ b/subworkflows/local/chord_prediction.nf @@ -0,0 +1,66 @@ +// +// XXX +// +import Constants +import Utils + +include { CHORD } from '../../modules/local/chord/main' + +workflow CHORD_PREDICTION { + take: + // Sample data + ch_inputs + ch_purple + + // Reference data + ref_data_genome_version + + // Parameters + run + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Select input sources + // channel: [val(meta), purple_dir] + if (run.purple) { + ch_chord_inputs_source = ch_purple + } else { + ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + } + + // Create inputs and create process-specific meta + // channel: [val(meta), smlv_vcf, sv_vcf] + ch_chord_inputs = ch_chord_inputs_source + .map { meta, purple_dir -> + def tumor_id = Utils.getTumorWgsSampleName(meta) + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") + + // Require both SV and smlv VCF from the PURPLE directory + if (!smlv_vcf.exists() || !sv_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + + def meta_chord = [key: meta.id, id: meta.id] + return [meta_chord, smlv_vcf, sv_vcf] + } + .filter { it[0] != Constants.META_PLACEHOLDER } + + // Run process + CHORD( + ch_chord_inputs, + ref_data_genome_version, + ) + + // Set outputs, restoring original meta + ch_outputs = WorkflowOncoanalyser.restoreMeta(CHORD.out.prediction, ch_inputs) + ch_versions = ch_versions.mix(CHORD.out.versions) + + emit: + prediction = ch_outputs // channel: [val(meta), prediction] + + versions = ch_versions // channel: [versions.yml] +} + diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index 4a15b9b5..d6d60d73 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -3,8 +3,7 @@ // import Constants -include { CUPPA_CLASSIFIER as CLASSIFIER } from '../../modules/local/cuppa/classifier/main' -include { CUPPA_VISUALISER as VISUALISER } from '../../modules/local/cuppa/visualiser/main' +include { CUPPA } from '../../modules/local/cuppa/main' workflow CUPPA_PREDICTION { take: @@ -75,29 +74,17 @@ workflow CUPPA_PREDICTION { return [meta_cuppa, *data[1..-1]] } - CLASSIFIER( + CUPPA( ch_cuppa_inputs, ref_data_genome_version, ref_data_cuppa_resources, ) - VISUALISER( - CLASSIFIER.out.csv, - ) - // Set outputs, restoring original meta - ch_csv = WorkflowOncoanalyser.restoreMeta(CLASSIFIER.out.csv, ch_inputs) - ch_summary_plot = WorkflowOncoanalyser.restoreMeta(VISUALISER.out.summary_plot, ch_inputs) - ch_feature_plot = WorkflowOncoanalyser.restoreMeta(VISUALISER.out.feature_plot, ch_inputs) - ch_versions = ch_versions.mix( - VISUALISER.out.versions, - CLASSIFIER.out.versions, - ) + ch_output = WorkflowOncoanalyser.restoreMeta(CUPPA.out.cuppa_dir, ch_inputs) emit: - csv = ch_csv - summary_plot = ch_summary_plot - feature_plot = ch_feature_plot + cuppa_dir = ch_output - versions = ch_versions // channel: [versions.yml] + versions = CUPPA.out.versions // channel: [versions.yml] } diff --git a/subworkflows/local/flagstat_metrics.nf b/subworkflows/local/flagstat_metrics.nf new file mode 100644 index 00000000..18d6364c --- /dev/null +++ b/subworkflows/local/flagstat_metrics.nf @@ -0,0 +1,107 @@ +// +// XXX +// +import Constants +import Utils + +include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/samtools/flagstat/main' + +workflow FLAGSTAT_METRICS { + take: + ch_inputs + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Select input source + // channel (present): [val(meta), sample_type, flagstat] + // channel (absent): [val(meta)] + ch_inputs_flagstat = ch_inputs + .flatMap { meta -> [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL].collect { [meta, it] } } + .branch { meta, sample_type -> + def key = [Constants.FileType.FLAGSTAT, sample_type, Constants.SequenceType.WGS] + present: meta.containsKey(key) + return [meta, sample_type, meta.getAt(key)] + absent: ! meta.containsKey(key) + } + + // Create inputs and create process-specific meta + // channel: [val(meta_flagstat), bam, bai] + ch_flagstat_inputs_all = ch_inputs_flagstat.absent + .map { meta, sample_type -> + def bam = meta.getAt([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) + def sample_name = meta.getAt(['sample_name', sample_type, Constants.SequenceType.WGS]) + def meta_flagstat = [ + key: meta.id, + id: sample_name, + // NOTE(SW): must use string representation for caching purposes + sample_type_str: sample_type.name(), + ] + return [meta_flagstat, bam, "${bam}.bai"] + } + + // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples + // channel: [val(meta_flagstat_shared), bam, bai] + ch_flagstat_inputs = ch_flagstat_inputs_all + .map { [it[1..-1], it[0]] } + .groupTuple() + .map { filepaths, meta_flagstat -> + def (keys, sample_names, sample_type_strs) = meta_flagstat + .collect { + [it.key, it.id, it.sample_type_str] + } + .transpose() + + def sample_type_strs_unique = sample_type_strs.unique(false) + assert sample_type_strs_unique.size() == 1 + def sample_type_str = sample_type_strs_unique[0] + + def meta_flagstat_new = [ + keys: keys, + id: sample_names.join('__'), + id_simple: keys.join('__'), + sample_type_str: sample_type_str, + ] + return [meta_flagstat_new, *filepaths] + } + + // Run process + SAMTOOLS_FLAGSTAT( + ch_flagstat_inputs, + ) + + // Set version + + // Replicate outputs to reverse unique operation + // channel: [val(meta_flagstat_individual), flagstat] + ch_flagstat_out = SAMTOOLS_FLAGSTAT.out.flagstat + .flatMap { meta_flagstat_shared, flagstat -> + def sample_type = Utils.getEnumFromString(meta_flagstat_shared.sample_type_str, Constants.SampleType) + meta_flagstat_shared.keys.collect { key -> + return [meta_flagstat_shared + [key: key], sample_type, flagstat] + } + } + + // Combine input flagstat channels, restoring original meta where required, split by sample type + // channel (somatic): [val(meta), flagstat] + // channel (germline): [val(meta), flagstat] + ch_outputs = Channel.empty() + .concat( + ch_inputs_flagstat.present, + WorkflowOncoanalyser.restoreMeta(ch_flagstat_out, ch_inputs), + ) + .branch { meta, sample_type, flagstat -> + somatic: sample_type == Constants.SampleType.TUMOR + return [meta, flagstat] + germline: sample_type == Constants.SampleType.NORMAL + return [meta, flagstat] + } + ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) + + emit: + somatic = ch_outputs.somatic // channel: [val(meta), metrics] + germline = ch_outputs.germline // channel: [val(meta), metrics] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf new file mode 100644 index 00000000..2f0edcc9 --- /dev/null +++ b/subworkflows/local/isofox_quantification.nf @@ -0,0 +1,74 @@ +// +// XXX +// +import Utils + +include { ISOFOX } from '../../modules/local/isofox/main' + +workflow ISOFOX_QUANTIFICATION { + take: + // Sample data + ch_inputs + + // Reference data + ref_data_genome_fasta + ref_data_genome_fai + ref_data_genome_version + ref_data_ensembl_data_resources + ref_data_isofox_counts + ref_data_isofox_gc_ratios + + // Parameters + isofox_functions + //use_isofox_exp_counts_cache + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Create inputs and create process-specific meta + // channel: [meta_isofox, tumor_bam_wts] + ch_isofox_inputs = ch_inputs + .map { meta -> + def bam = Utils.getTumorWtsBam(meta) + def meta_isofox = [key: meta.id, id: Utils.getTumorWtsSampleName(meta)] + return [meta_isofox, bam, "${bam}.bai"] + } + + // Set Isofox cache files + // NOTE(SW): the Isofox expected count file is read length dependent so required users to explicitly use expect + // counts generated for 151 bp reads that is available in the HMF reference bundle. When not specifying an + // expected count file, Isofox will automatically create one for the computed read length. However, doing so + // greatly increases runtime. + // NOTE(SW): consider alternative approaches for using the expected count file e.g. generate once at runtime, + // then use for all samples; generate all possible read lengths outside of pipeline and store on a remote for + // retrieval at runtime (requires inference of read length) + + // TODO(SW): this must be improved to allow users to set input file, use cache, or generate at runtime; + // currently does not update functions + // NOTE(SW): forcing use of cache for now since this feature is incomplete + + //isofox_counts = params.use_isofox_exp_counts_cache ? ref_data_isofox_counts : [] + isofox_counts = ref_data_isofox_counts + + // Run process + ISOFOX( + ch_isofox_inputs, + isofox_functions, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_ensembl_data_resources, + isofox_counts, + ref_data_isofox_gc_ratios, + ) + + // Set outputs, restoring original meta + ch_outputs = WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs) + ch_versions = ch_versions.mix(ISOFOX.out.versions) + + emit: + isofox_dir = ch_outputs // channel: [val(meta), isofox_dir] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf index 26eb3325..d4121e36 100644 --- a/subworkflows/local/linx_annotation.nf +++ b/subworkflows/local/linx_annotation.nf @@ -11,13 +11,10 @@ workflow LINX_ANNOTATION { take: // Sample data ch_inputs // channel: [val(meta)] - ch_gripss_germline // channel: [val(meta), vcf] ch_purple // channel: [val(meta), purple_dir] // Reference data ref_data_genome_version // val: genome version - ref_data_linx_fragile_regions // file: /path/to/linx_fragile_regions - ref_data_linx_lines // file: /path/to/linx_lines ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ ref_data_known_fusion_data // file: /path/to/known_fusion_data ref_data_driver_gene_panel // file: /path/to/driver_gene_panel @@ -31,43 +28,42 @@ workflow LINX_ANNOTATION { ch_versions = Channel.empty() // Select input sources - // channel: [val(meta), sv_vcf] - if (run.gripss) { - ch_linx_inputs_germline_source = ch_gripss_germline.map { meta, vcf, tbi -> [meta, vcf] } - } else { - ch_linx_inputs_germline_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_TUMOR) - } - - // channel: [val(meta), sv_vcf, purple_dir] - ch_linx_inputs_somatic_source = run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + // channel: [val(meta), purple_dir] + ch_linx_inputs_source = run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) // Create inputs and create process-specific meta // channel: [val(meta_linx), sv_vcf] - ch_linx_inputs_germline = ch_linx_inputs_germline_source - .map { - def meta = it[0] + ch_linx_inputs_germline = ch_linx_inputs_source + .map { meta, purple_dir -> + + def tumor_id = Utils.getTumorWgsSampleName(meta) + def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") + + if (!sv_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + def meta_linx = [ key: meta.id, id: Utils.getNormalWgsSampleName(meta), ] - return [meta_linx, it[1..-1]] + + return [meta_linx, sv_vcf] } // channel: [val(meta_linx), purple_dir] - ch_linx_inputs_somatic = ch_linx_inputs_somatic_source - .map { - def meta = it[0] + ch_linx_inputs_somatic = ch_linx_inputs_source + .map { meta, purple_dir -> def meta_linx = [ key: meta.id, id: Utils.getTumorWgsSampleName(meta), ] - return [meta_linx, it[1..-1]] + return [meta_linx, purple_dir] } GERMLINE( ch_linx_inputs_germline, ref_data_genome_version, - ref_data_linx_lines, ref_data_ensembl_data_resources, ref_data_driver_gene_panel, ) @@ -75,8 +71,6 @@ workflow LINX_ANNOTATION { SOMATIC( ch_linx_inputs_somatic, ref_data_genome_version, - ref_data_linx_fragile_regions, - ref_data_linx_lines, ref_data_ensembl_data_resources, ref_data_known_fusion_data, ref_data_driver_gene_panel, diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 2d6d400c..78350405 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -5,7 +5,8 @@ import Constants import Utils include { ORANGE } from '../../modules/local/orange/main' -include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/samtools/flagstat/main' + +include { FLAGSTAT_METRICS } from './flagstat_metrics' workflow ORANGE_REPORTING { take: @@ -14,8 +15,6 @@ workflow ORANGE_REPORTING { ch_inputs_wgs ch_bamtools_somatic ch_bamtools_germline - ch_chord - ch_lilac ch_sage_somatic_tumor_bqr ch_sage_somatic_normal_bqr ch_sage_germline_coverage @@ -23,20 +22,23 @@ workflow ORANGE_REPORTING { ch_linx_somatic_annotation ch_linx_somatic_plot ch_linx_germline_annotation - ch_protect - ch_peach - ch_cuppa - ch_cuppa_feature_plot - ch_cuppa_summary_plot ch_virusinterpreter + ch_chord + ch_sigs + ch_lilac + ch_cuppa + ch_isofox // Reference data ref_data_genome_version ref_data_disease_ontology - ref_data_known_fusion_data - ref_data_driver_gene_panel ref_data_cohort_mapping ref_data_cohort_percentiles + ref_data_known_fusion_data + ref_data_driver_gene_panel + ref_data_ensembl_data_resources + ref_data_isofox_alt_sj + ref_data_isofox_gene_distribution // Parameters run @@ -45,127 +47,70 @@ workflow ORANGE_REPORTING { // Channel for version.yml files ch_versions = Channel.empty() - // SAMtools flagstat - // Select input source - // channel (present): [val(meta), sample_type, flagstat] - // channel (absent): [val(meta)] - ch_inputs_flagstat = ch_inputs_wgs - .flatMap { meta -> [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL].collect { [meta, it] } } - .branch { meta, sample_type -> - def key = [Constants.FileType.FLAGSTAT, sample_type, Constants.SequenceType.WGS] - present: meta.containsKey(key) - return [meta, sample_type, meta.getAt(key)] - absent: ! meta.containsKey(key) - } - - // Create inputs and create process-specific meta - // channel: [val(meta_flagstat), bam, bai] - ch_flagstat_inputs_all = ch_inputs_flagstat.absent - .map { meta, sample_type -> - def bam = meta.getAt([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) - def sample_name = meta.getAt(['sample_name', sample_type, Constants.SequenceType.WGS]) - def meta_flagstat = [ - key: meta.id, - id: sample_name, - // NOTE(SW): must use string representation for caching purposes - sample_type_str: sample_type.name(), - ] - return [meta_flagstat, bam, "${bam}.bai"] - } - - // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples - // channel: [val(meta_flagstat_shared), bam, bai] - ch_flagstat_inputs = ch_flagstat_inputs_all - .map { [it[1..-1], it[0]] } - .groupTuple() - .map { filepaths, meta_flagstat -> - def (keys, sample_names, sample_type_strs) = meta_flagstat - .collect { - [it.key, it.id, it.sample_type_str] - } - .transpose() - - def sample_type_strs_unique = sample_type_strs.unique(false) - assert sample_type_strs_unique.size() == 1 - def sample_type_str = sample_type_strs_unique[0] - - def meta_flagstat_new = [ - keys: keys, - id: sample_names.join('__'), - id_simple: keys.join('__'), - sample_type_str: sample_type_str, - ] - return [meta_flagstat_new, *filepaths] - } - - // Run process - SAMTOOLS_FLAGSTAT( - ch_flagstat_inputs, - ) - - // Set version - ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) - - // Replicate outputs to reverse unique operation - // channel: [val(meta_flagstat_individual), flagstat] - ch_flagstat_out = SAMTOOLS_FLAGSTAT.out.flagstat - .flatMap { meta_flagstat_shared, flagstat -> - def sample_type = Utils.getEnumFromString(meta_flagstat_shared.sample_type_str, Constants.SampleType) - meta_flagstat_shared.keys.collect { key -> - return [meta_flagstat_shared + [key: key], sample_type, flagstat] - } - } + // + // SUBWORKFLOW: Run SAMtools flagstat to generate stats required for ORANGE + // + // channel: [val(meta), metrics] + ch_flagstat_somatic_out = Channel.empty() + ch_flagstat_germline_out = Channel.empty() + if (run.flagstat) { - // Combine input flagstat channels, restoring original meta where required, split by sample type - // channel (somatic): [val(meta), flagstat] - // channel (germline): [val(meta), flagstat] - ch_orange_inputs_flagstat = Channel.empty() - .concat( - ch_inputs_flagstat.present, - WorkflowOncoanalyser.restoreMeta(ch_flagstat_out, ch_inputs), + FLAGSTAT_METRICS( + ch_inputs_wgs, ) - .branch { meta, sample_type, flagstat -> - somatic: sample_type == Constants.SampleType.TUMOR - return [meta, flagstat] - germline: sample_type == Constants.SampleType.NORMAL - return [meta, flagstat] - } - // TODO(SW): handle CUPPA WTS, WGS, WGS + ch_versions = ch_versions.mix(FLAGSTAT_METRICS.out.versions) + ch_flagstat_somatic_out = ch_flagstat_somatic_out.mix(FLAGSTAT_METRICS.out.somatic) + ch_flagstat_germline_out = ch_flagstat_germline_out.mix(FLAGSTAT_METRICS.out.germline) + } + // + // MODULE: Run ORANGE + // // Select input source - // NOTE(SW): we could consider not allowing inputs from the samplesheet here since this nothing follows ch_orange_inputs_source = WorkflowOncoanalyser.groupByMeta( - run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_TUMOR), - run.bamtools ? ch_bamtools_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_NORMAL), - ch_orange_inputs_flagstat.somatic, - ch_orange_inputs_flagstat.germline, - run.chord ? ch_chord : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD), - run.lilac ? ch_lilac : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), + run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_TXT_TUMOR), + run.bamtools ? ch_bamtools_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_TXT_NORMAL, type: 'optional'), + run.flagstat ? ch_flagstat_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_TUMOR), + run.flagstat ? ch_flagstat_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_NORMAL, type: 'optional'), run.sage ? ch_sage_somatic_tumor_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_TUMOR), - run.sage ? ch_sage_somatic_normal_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_NORMAL), - run.sage ? ch_sage_germline_coverage : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_COVERAGE), + run.sage ? ch_sage_somatic_normal_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_NORMAL, type: 'optional'), + run.sage ? ch_sage_germline_coverage : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_COVERAGE, type: 'optional'), run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), run.linx ? ch_linx_somatic_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), run.linx ? ch_linx_somatic_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_TUMOR), - run.linx ? ch_linx_germline_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_NORMAL), - run.protect ? ch_protect : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PROTECT_TSV), - run.peach ? ch_peach : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PEACH_TSV), - run.cuppa ? ch_cuppa : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUTS_CUPPA_CSV), - run.cuppa ? ch_cuppa_feature_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_FEATURE_PLOT), - run.cuppa ? ch_cuppa_summary_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_SUMMARY_PLOT), - run.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV), + run.linx ? ch_linx_germline_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_NORMAL, type: 'optional'), + run.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), + run.chord ? ch_chord : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_PREDICITION, type: 'optional'), + run.sigs ? ch_sigs : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SIGS, type: 'optional'), + run.lilac ? ch_lilac : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), + run.cuppa ? ch_cuppa : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_DIR, type: 'optional'), + run.isofox ? ch_isofox : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional'), + flatten_mode: 'nonrecursive', ) ch_orange_inputs = ch_orange_inputs_source .map { def meta = it[0] + + // NOTE(SW): these attributes are optional + def normal_wgs_id = meta.getAt(['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.WGS]) + def tumor_wts_id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + def meta_orange = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), + tumor_wgs_id: Utils.getTumorWgsSampleName(meta), ] + + // Add optional identifiers to meta + if (normal_wgs_id) { + meta_orange.normal_wgs_id = normal_wgs_id + } + if (tumor_wts_id) { + meta_orange.tumor_wts_id = tumor_wts_id + } + return [meta_orange, *it[1..-1]] } @@ -174,11 +119,14 @@ workflow ORANGE_REPORTING { ch_orange_inputs, ref_data_genome_version, ref_data_disease_ontology, - ref_data_known_fusion_data, - ref_data_driver_gene_panel, ref_data_cohort_mapping, ref_data_cohort_percentiles, - "5.31 [oncoanalyser]", + ref_data_known_fusion_data, + ref_data_driver_gene_panel, + ref_data_ensembl_data_resources, + ref_data_isofox_alt_sj, + ref_data_isofox_gene_distribution, + "5.32 [oncoanalyser]", ) // Set outputs diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 0fed641c..3eb34e19 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -171,16 +171,11 @@ def createHmfDataMap(hmf_data_path, params_only) { isofox_gc_ratios: 'ref_data_isofox_gc_ratios', // LILAC lilac_resources: 'ref_data_lilac_resources', - // LINX - linx_fragile_regions: 'ref_data_linx_fragile_regions', - linx_lines: 'ref_data_linx_lines', // ORANGE cohort_mapping: 'ref_data_cohort_mapping', cohort_percentiles: 'ref_data_cohort_percentiles', - // PEACH - peach_panel: 'ref_data_peach_panel', - // PROTECT - serve_resources: 'ref_data_serve_resources', + alt_sj_distribution: 'ref_data_alt_sj_distribution', + gene_exp_distribution: 'ref_data_gene_exp_distribution', // SAGE clinvar_annotations: 'ref_data_clinvar_annotations', sage_blocklist_regions: 'ref_data_sage_blocklist_regions', diff --git a/subworkflows/local/purple_calling.nf b/subworkflows/local/purple_calling.nf index 159e6bb6..e74bd5b2 100644 --- a/subworkflows/local/purple_calling.nf +++ b/subworkflows/local/purple_calling.nf @@ -13,7 +13,8 @@ workflow PURPLE_CALLING { ch_smlv_somatic ch_smlv_germline ch_sv_somatic - ch_sv_somatic_recovery + ch_sv_germline + ch_sv_somatic_unfiltered // Reference data ref_data_genome_fasta @@ -35,28 +36,37 @@ workflow PURPLE_CALLING { ch_versions = Channel.empty() // Select input sources - // channel: [val(meta), sv_vcf, sv_tbi, sv_recovery_vcf, sv_recovery_tbi] + // channel: [val(meta), sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi] ch_purple_inputs_sv = Channel.empty() if (run.gripss) { // NOTE(SW): GRIPSS will be run for all WGS entries, so no optionals here ch_purple_inputs_sv = WorkflowOncoanalyser.groupByMeta( ch_sv_somatic, - ch_sv_somatic_recovery, + ch_sv_somatic_unfiltered, + ch_sv_germline, ) } else { ch_purple_inputs_sv = WorkflowOncoanalyser.groupByMeta( WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_TUMOR, type: 'optional'), WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR, type: 'optional'), + WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_NORMAL, type: 'optional'), flatten_mode: 'nonrecursive', ) - .map { meta, vcf, vcf_unfiltered-> - def tbi = vcf == [] ? [] : "${vcf}.tbi" - def tbi_unfiltered = vcf_unfiltered == [] ? [] : "${vcf_unfiltered}.tbi" - return [meta, vcf, tbi, vcf_unfiltered, tbi_unfiltered] + .map { + + def meta = it[0] + def vcfs = it[1..-1] + + def files = vcfs.collectMany { vcf -> + def tbi = vcf == [] ? [] : "${vcf}.tbi" + return [vcf, tbi] + } + + return [meta, *files] } } - // channel: [val(meta), amber_dir, cobalt_dir, sv_vcf, sv_tbi, sv_recovery_vcf, sv_recovery_tbi, smlv_tumor_vcf, smlv_normal_vcf] + // channel: [val(meta), amber_dir, cobalt_dir, sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi, smlv_tumor_vcf, smlv_normal_vcf] ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( // Required inputs run.amber ? ch_amber: WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.AMBER_DIR), @@ -69,18 +79,17 @@ workflow PURPLE_CALLING { ) // Create process-specific meta - // channel: [val(meta_purple), amber_dir, cobalt_dir, sv_vcf, sv_tbi, sv_recovery_vcf, sv_recovery_tbi, smlv_tumor_vcf, smlv_normal_vcf] + // channel: [val(meta_purple), amber_dir, cobalt_dir, sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi, smlv_tumor_vcf, smlv_normal_vcf] ch_purple_inputs = ch_purple_inputs_source .map { def meta = it[0] - def other = it[1..-1] def meta_purple = [ key: meta.id, id: meta.id, tumor_id: Utils.getTumorWgsSampleName(meta), normal_id: Utils.getNormalWgsSampleName(meta), ] - return [meta_purple, *other] + return [meta_purple, *it[1..-1]] } PURPLE( diff --git a/subworkflows/local/sigs_fitting.nf b/subworkflows/local/sigs_fitting.nf new file mode 100644 index 00000000..d48473f0 --- /dev/null +++ b/subworkflows/local/sigs_fitting.nf @@ -0,0 +1,68 @@ +// +// XXX +// +import Constants +import Utils + +include { SIGS } from '../../modules/local/sigs/main' + +workflow SIGS_FITTING { + take: + // Sample data + ch_inputs + ch_purple + + // Reference data + ref_data_sigs_signatures + + // Parameters + run + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Select input sources + // channel: [val(meta), purple_dir] + if (run.purple) { + ch_sigs_inputs_source = ch_purple + } else { + ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + } + + // Create inputs and create process-specific meta + // channel: [val(meta_sigs), smlv_vcf] + ch_sigs_inputs = ch_sigs_inputs_source + .map { meta, purple_dir -> + + def tumor_id = Utils.getTumorWgsSampleName(meta) + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + + // Require smlv VCF from the PURPLE directory + if (!smlv_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + + def meta_sigs = [ + key: meta.id, + id: meta.id, + tumor_id: tumor_id, + ] + return [meta_sigs, smlv_vcf] + } + .filter { it[0] != Constants.META_PLACEHOLDER } + + SIGS( + ch_sigs_inputs, + ref_data_sigs_signatures, + ) + + // Set outputs, restoring original meta + ch_outputs = WorkflowOncoanalyser.restoreMeta(SIGS.out.sigs_dir, ch_inputs) + ch_versions = ch_versions.mix(SIGS.out.versions) + + emit: + sigs_dir = ch_outputs // channel: [val(meta), sigs_dir] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/workflows/wgts.nf b/workflows/wgts.nf index aa33eab0..2c2caa23 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -55,25 +55,18 @@ linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -// -// MODULES -// -include { CHORD } from '../modules/local/chord/main' -include { ISOFOX } from '../modules/local/isofox/main' -include { PEACH } from '../modules/local/peach/main' -include { PROTECT } from '../modules/local/protect/main' -include { SIGS } from '../modules/local/sigs/main' - // // SUBWORKFLOWS // include { AMBER_PROFILING } from '../subworkflows/local/amber_profiling' include { BAMTOOLS_METRICS } from '../subworkflows/local/bamtools_metrics' +include { CHORD_PREDICTION } from '../subworkflows/local/chord_prediction' include { COBALT_PROFILING } from '../subworkflows/local/cobalt_profiling' include { CUPPA_PREDICTION } from '../subworkflows/local/cuppa_prediction' include { GRIDSS_CALLING } from '../subworkflows/local/gridss_calling' include { GRIDSS_SVPREP_CALLING } from '../subworkflows/local/gridss_svprep_calling' include { GRIPSS_FILTERING } from '../subworkflows/local/gripss_filtering' +include { ISOFOX_QUANTIFICATION } from '../subworkflows/local/isofox_quantification' include { LILAC_CALLING } from '../subworkflows/local/lilac_calling' include { LINX_ANNOTATION } from '../subworkflows/local/linx_annotation' include { LINX_PLOTTING } from '../subworkflows/local/linx_plotting' @@ -83,6 +76,7 @@ include { PREPARE_INPUT } from '../subworkflows/local/prepare_input' include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' include { SAGE_CALLING } from '../subworkflows/local/sage_calling' +include { SIGS_FITTING } from '../subworkflows/local/sigs_fitting' include { VIRUSBREAKEND_CALLING } from '../subworkflows/local/virusbreakend_calling' /* @@ -154,50 +148,24 @@ workflow WGTS { // channel: [meta, isofox_dir] ch_isofox_out = Channel.empty() if (run.isofox) { - // Create inputs and create process-specific meta - // channel: [meta_isofox, tumor_bam_wts] - ch_isofox_inputs = ch_inputs_wts.present - .map { meta -> - def bam = Utils.getTumorWtsBam(meta) - def meta_isofox = [key: meta.id, id: Utils.getTumorWtsSampleName(meta)] - return [meta_isofox, bam, "${bam}.bai"] - } - - // Set Isofox cache files - // NOTE(SW): the Isofox expected count file is read length dependent so required users to explicitly use expect - // counts generated for 151 bp reads that is available in the HMF reference bundle. When not specifying an - // expected count file, Isofox will automatically create one for the computed read length. However, doing so - // greatly increases runtime. - // NOTE(SW): consider alternative approaches for using the expected count file e.g. generate once at runtime, - // then use for all samples; generate all possible read lengths outside of pipeline and store on a remote for - // retrieval at runtime (requires inference of read length) - - // TODO(SW): this must be improved to allow users to set input file, use cache, or generate at runtime; - // currently does not update functions - // NOTE(SW): forcing use of cache for now since this feature is incomplete - - //isofox_counts = params.use_isofox_exp_counts_cache ? hmf_data.isofox_counts : [] - isofox_counts = hmf_data.isofox_counts - - // Run process - ISOFOX( - ch_isofox_inputs, - params.isofox_functions, + + ISOFOX_QUANTIFICATION( + ch_inputs_wts.present, PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, PREPARE_REFERENCE.out.genome_version, hmf_data.ensembl_data_resources, - isofox_counts, + hmf_data.isofox_counts, hmf_data.isofox_gc_ratios, + params.isofox_functions, ) - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(ISOFOX.out.versions) - ch_isofox_out = ch_isofox_out.mix(WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs)) + ch_versions = ch_versions.mix(ISOFOX_QUANTIFICATION.out.versions) + ch_isofox_out = ch_isofox_out.mix(ISOFOX_QUANTIFICATION.out.isofox_dir) } // - // MODULE: Run Bam Tools to generate stats required for downstream processes + // SUBWORKFLOW: Run Bam Tools to generate stats required for downstream processes // // channel: [val(meta), metrics] ch_bamtools_somatic_out = Channel.empty() @@ -217,7 +185,7 @@ workflow WGTS { } // - // MODULE: Run AMBER to obtain b-allele frequencies + // SUBWORKFLOW: Run AMBER to obtain b-allele frequencies // // channel: [val(meta), amber_dir] ch_amber_out = Channel.empty() @@ -234,7 +202,7 @@ workflow WGTS { } // - // MODULE: Run COBALT to obtain read ratios + // SUBWORKFLOW: Run COBALT to obtain read ratios // // channel: [val(meta), cobalt_dir] ch_cobalt_out = Channel.empty() @@ -295,12 +263,12 @@ workflow WGTS { } // - // MODULE: Run GRIPSS to filter GRIDSS SV calls + // SUBWORKFLOW: Run GRIPSS to filter GRIDSS SV calls // // channel: [val(meta), vcf, tbi] ch_gripss_somatic_out = Channel.empty() - ch_gripss_somatic_unfiltered_out = Channel.empty() ch_gripss_germline_out = Channel.empty() + ch_gripss_somatic_unfiltered_out = Channel.empty() if (run.gripss) { GRIPSS_FILTERING( @@ -318,8 +286,8 @@ workflow WGTS { ch_versions = ch_versions.mix(GRIPSS_FILTERING.out.versions) ch_gripss_somatic_out = ch_gripss_somatic_out.mix(GRIPSS_FILTERING.out.somatic) - ch_gripss_somatic_unfiltered_out = ch_gripss_somatic_unfiltered_out.mix(GRIPSS_FILTERING.out.somatic_unfiltered) ch_gripss_germline_out = ch_gripss_germline_out.mix(GRIPSS_FILTERING.out.germline) + ch_gripss_somatic_unfiltered_out = ch_gripss_somatic_unfiltered_out.mix(GRIPSS_FILTERING.out.somatic_unfiltered) } // @@ -406,6 +374,7 @@ workflow WGTS { ch_pave_somatic_out, ch_pave_germline_out, ch_gripss_somatic_out, + ch_gripss_germline_out, ch_gripss_somatic_unfiltered_out, PREPARE_REFERENCE.out.genome_fasta, PREPARE_REFERENCE.out.genome_fai, @@ -425,87 +394,75 @@ workflow WGTS { } // - // MODULE: Run Sigs to fit somatic smlv to signature definitions + // SUBWORKFLOW: Group structural variants into higher order events with LINX + // + // channel: [val(meta), linx_annotation_dir] + ch_linx_somatic_out = Channel.empty() + ch_linx_germline_out = Channel.empty() + // channel: [val(meta), linx_visualiser_dir] + ch_linx_somatic_plot_out = Channel.empty() + if (run.linx) { + + LINX_ANNOTATION( + ch_inputs, + ch_purple_out, + PREPARE_REFERENCE.out.genome_version, + hmf_data.ensembl_data_resources, + hmf_data.known_fusion_data, + hmf_data.driver_gene_panel, + linx_gene_id_file, + run, + ) + + ch_versions = ch_versions.mix(LINX_ANNOTATION.out.versions) + ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX_ANNOTATION.out.somatic) + ch_linx_germline_out = ch_linx_germline_out.mix(LINX_ANNOTATION.out.germline) + + LINX_PLOTTING( + ch_inputs, + ch_linx_somatic_out, + PREPARE_REFERENCE.out.genome_version, + hmf_data.ensembl_data_resources, + ) + + ch_versions = ch_versions.mix(LINX_PLOTTING.out.versions) + ch_linx_somatic_plot_out = ch_linx_somatic_plot_out.mix(LINX_PLOTTING.out.visualiser_dir) + } + + // + // SUBWORKFLOW: Run Sigs to fit somatic smlv to signature definitions // + // channel: [val(meta), sigs_dir] + ch_sigs_out = Channel.empty() if (run.sigs) { - // Select input sources - // channel: [val(meta), purple_dir] - if (run.purple) { - ch_sigs_inputs_source = ch_purple_out - } else { - ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - } - // Create inputs and create process-specific meta - // channel: [val(meta_sigs), smlv_vcf] - ch_sigs_inputs = ch_sigs_inputs_source - .map { meta, purple_dir -> - def tumor_id = Utils.getTumorWgsSampleName(meta) - def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - - // Require smlv VCF from the PURPLE directory - if (!smlv_vcf.exists()) { - return Constants.META_PLACEHOLDER - } - - def meta_sigs = [ - id: meta.id, - tumor_id: meta.getAt(['sample_name', Constants.SampleType.TUMOR]), - ] - return [meta_sigs, smlv_vcf] - } - .filter { it[0] != Constants.META_PLACEHOLDER } - - SIGS( - ch_sigs_inputs, - hmf_data.sigs_signatures, + SIGS_FITTING( + ch_inputs, + ch_purple_out, + hmf_data.sigs_signatures, + run, ) - // Set outputs - ch_versions = ch_versions.mix(SIGS.out.versions) + ch_versions = ch_versions.mix(SIGS_FITTING.out.versions) + ch_sigs_out = ch_sigs_out.mix(SIGS_FITTING.out.sigs_dir) } // - // MODULE: Run CHORD to predict HR deficiency status + // SUBWORKFLOW: Run CHORD to predict HR deficiency status // // channel: [val(meta), chord_prediction] ch_chord_out = Channel.empty() if (run.chord) { - // Select input sources - // channel: [val(meta), purple_dir] - if (run.purple) { - ch_chord_inputs_source = ch_purple_out - } else { - ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - } - // Create inputs and create process-specific meta - // channel: [val(meta), smlv_vcf, sv_vcf] - ch_chord_inputs = ch_chord_inputs_source - .map { meta, purple_dir -> - def tumor_id = Utils.getTumorWgsSampleName(meta) - def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") - - // Require both SV and smlv VCF from the PURPLE directory - if (!smlv_vcf.exists() || !sv_vcf.exists()) { - return Constants.META_PLACEHOLDER - } - - def meta_chord = [key: meta.id, id: meta.id] - return [meta_chord, smlv_vcf, sv_vcf] - } - .filter { it[0] != Constants.META_PLACEHOLDER } - - // Run process - CHORD( - ch_chord_inputs, - PREPARE_REFERENCE.out.genome_version, + CHORD_PREDICTION( + ch_inputs, + ch_purple_out, + PREPARE_REFERENCE.out.genome_version, + run, ) - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(CHORD.out.versions) - ch_chord_out = ch_chord_out.mix(WorkflowOncoanalyser.restoreMeta(CHORD.out.prediction, ch_inputs)) + ch_versions = ch_versions.mix(CHORD_PREDICTION.out.versions) + ch_chord_out = ch_chord_out.mix(CHORD_PREDICTION.out.prediction) } // @@ -536,6 +493,7 @@ workflow WGTS { // // SUBWORKFLOW: Run VIRUSBreakend and Virus Interpreter to quantify viral content // + // channel: [val(meta), virusinterpreter] ch_virusinterpreter_out = Channel.empty() if (run.virusinterpreter) { @@ -560,146 +518,11 @@ workflow WGTS { ch_virusinterpreter_out = ch_virusinterpreter_out.mix(VIRUSBREAKEND_CALLING.out.virusinterpreter) } - // - // SUBWORKFLOW: Group structural variants into higher order events with LINX - // - // channel: [val(meta), linx_annotation_dir] - ch_linx_somatic_out = Channel.empty() - ch_linx_germline_out = Channel.empty() - // channel: [val(meta), linx_visualiser_dir] - ch_linx_somatic_plot_out = Channel.empty() - if (run.linx) { - - LINX_ANNOTATION( - ch_inputs, - ch_gripss_germline_out, - ch_purple_out, - PREPARE_REFERENCE.out.genome_version, - hmf_data.linx_fragile_regions, - hmf_data.linx_lines, - hmf_data.ensembl_data_resources, - hmf_data.known_fusion_data, - hmf_data.driver_gene_panel, - linx_gene_id_file, - run, - ) - - ch_versions = ch_versions.mix(LINX_ANNOTATION.out.versions) - ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX_ANNOTATION.out.somatic) - ch_linx_germline_out = ch_linx_germline_out.mix(LINX_ANNOTATION.out.germline) - - LINX_PLOTTING( - ch_inputs, - ch_linx_somatic_out, - PREPARE_REFERENCE.out.genome_version, - hmf_data.ensembl_data_resources, - ) - - ch_versions = ch_versions.mix(LINX_PLOTTING.out.versions) - ch_linx_somatic_plot_out = ch_linx_somatic_plot_out.mix(LINX_PLOTTING.out.visualiser_dir) - } - - // - // MODULE: Run PROTECT to match somatic genomic features with treatment evidence - // - // channel: [val(meta), protect] - ch_protect_out = Channel.empty() - if (run.protect) { - // Select input sources - // channel: [val(meta), chord_prediction, purple_dir, linx_dir, virusinterpreter] - ch_protect_inputs_source = WorkflowOncoanalyser.groupByMeta( - run.chord ? ch_chord_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_PREDICTION), - run.purple ? ch_purple_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), - run.linx ? ch_linx_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), - run.lilac ? ch_lilac_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), - run.virusinterpreter ? ch_virusinterpreter_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV), - ) - - // Create process-specific meta - // channel: [val(meta_protect), chord_prediction, purple_dir, linx_dir, virusinterpreter] - ch_protect_inputs = ch_protect_inputs_source - .map { - def meta = it[0] - def other = it[1..-1] - def meta_protect = [ - key: meta.id, - id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - return [meta_protect, *other] - } - - // Run process - PROTECT( - ch_protect_inputs, - PREPARE_REFERENCE.out.genome_version, - hmf_data.serve_resources, - hmf_data.driver_gene_panel, - hmf_data.disease_ontology, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(PROTECT.out.versions) - ch_protect_out = ch_protect_out.mix(WorkflowOncoanalyser.restoreMeta(PROTECT.out.tsv, ch_inputs)) - } - - // - // MODULE: Run PEACH to match germline SNVs with pharmacogenetic evidence - // - // channel: [val(meta), peach_genotype] - ch_peach_out = Channel.empty() - if (run.peach) { - // Select input sources - // channel: [val(meta), purple_dir] - if (run.purple) { - ch_peach_inputs_source = ch_purple_out - } else { - ch_peach_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - } - - // Create inputs and create process-specific meta - // channel: [meta_peach, purple_germline_vcf] - ch_peach_inputs = ch_peach_inputs_source - .map { meta, purple_dir -> - def meta_peach = [ - key: meta.id, - id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - def tumor_id = Utils.getTumorWgsSampleName(meta) - def purple_germline_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") - - if (!purple_germline_vcf.exists()) { - return Constants.META_PLACEHOLDER - } - - return [meta_peach, purple_germline_vcf] - } - .filter { it[0] != Constants.META_PLACEHOLDER } - - // Run process - PEACH( - ch_peach_inputs, - PREPARE_REFERENCE.out.genome_version, - hmf_data.peach_panel, - ) - - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(PEACH.out.versions) - ch_peach_out = ch_peach_out.mix(WorkflowOncoanalyser.restoreMeta(PEACH.out.genotype, ch_inputs)) - } - // // SUBWORKFLOW: Run CUPPA predict tissue of origin // - // channel: [val(meta), cuppa_results] + // channel: [val(meta), cuppa_dir] ch_cuppa_out = Channel.empty() - // channel: [val(meta), cuppa_summary_plot] - ch_cuppa_summary_plot_out = Channel.empty() - // channel: [val(meta), cuppa_feature_plot] - ch_cuppa_feature_plot_out = Channel.empty() if (run.cuppa) { CUPPA_PREDICTION( @@ -715,9 +538,7 @@ workflow WGTS { ) ch_versions = ch_versions.mix(CUPPA_PREDICTION.out.versions) - ch_cuppa_out = ch_cuppa_out.mix(CUPPA_PREDICTION.out.csv) - ch_cuppa_summary_plot_out = ch_cuppa_summary_plot_out.mix(CUPPA_PREDICTION.out.summary_plot) - ch_cuppa_feature_plot_out = ch_cuppa_feature_plot_out.mix(CUPPA_PREDICTION.out.feature_plot) + ch_cuppa_out = ch_cuppa_out.mix(CUPPA_PREDICTION.out.cuppa_dir) } // @@ -730,8 +551,6 @@ workflow WGTS { ch_inputs_wgs.present, ch_bamtools_somatic_out, ch_bamtools_germline_out, - ch_chord_out, - ch_lilac_out, ch_sage_somatic_tumor_bqr_out, ch_sage_somatic_normal_bqr_out, ch_sage_germline_coverage_out, @@ -739,18 +558,21 @@ workflow WGTS { ch_linx_somatic_out, ch_linx_somatic_plot_out, ch_linx_germline_out, - ch_protect_out, - ch_peach_out, - ch_cuppa_out, - ch_cuppa_feature_plot_out, - ch_cuppa_summary_plot_out, ch_virusinterpreter_out, + ch_chord_out, + ch_sigs_out, + ch_lilac_out, + ch_cuppa_out, + ch_isofox_out, PREPARE_REFERENCE.out.genome_version, hmf_data.disease_ontology, - hmf_data.known_fusion_data, - hmf_data.driver_gene_panel, hmf_data.cohort_mapping, hmf_data.cohort_percentiles, + hmf_data.known_fusion_data, + hmf_data.driver_gene_panel, + hmf_data.ensembl_data_resources, + hmf_data.alt_sj_distribution, + hmf_data.gene_exp_distribution, run, ) @@ -760,7 +582,6 @@ workflow WGTS { // // MODULE: Pipeline reporting // - // Run process CUSTOM_DUMPSOFTWAREVERSIONS( ch_versions.unique().collectFile(name: 'collated_versions.yml') ) From 1264041bd363c2bae66948f497c294fb08fb718e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 3 May 2023 16:40:06 +1000 Subject: [PATCH 148/562] Simplify reference data and meta object handling --- subworkflows/local/amber_profiling.nf | 9 +- subworkflows/local/bamtools_metrics.nf | 9 +- subworkflows/local/channel_group_inputs.nf | 38 +++++ subworkflows/local/cobalt_profiling.nf | 9 +- subworkflows/local/cuppa_prediction.nf | 10 +- subworkflows/local/gridss_calling.nf | 10 +- subworkflows/local/gridss_svprep_calling.nf | 13 +- subworkflows/local/isofox_quantification.nf | 9 +- subworkflows/local/lilac_calling.nf | 21 +-- subworkflows/local/orange_reporting.nf | 11 +- subworkflows/local/sage_calling.nf | 9 +- subworkflows/local/virusbreakend_calling.nf | 9 +- workflows/wgts.nf | 152 ++++++++------------ 13 files changed, 194 insertions(+), 115 deletions(-) create mode 100644 subworkflows/local/channel_group_inputs.nf diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index 0248a0ca..000d5601 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -5,6 +5,8 @@ import Utils include { AMBER } from '../../modules/local/amber/main' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + workflow AMBER_PROFILING { take: // Sample data @@ -18,9 +20,14 @@ workflow AMBER_PROFILING { // Channel for version.yml files ch_versions = Channel.empty() + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + // Select input sources // channel: [val(meta_amber), tumor_bam_wgs, normal_bam_wgs, tumor_bai_wgs, normal_bai_wgs] - ch_amber_inputs = ch_inputs + ch_amber_inputs = CHANNEL_GROUP_INPUTS.out.wgs_present .map { meta -> def meta_amber = [ key: meta.id, diff --git a/subworkflows/local/bamtools_metrics.nf b/subworkflows/local/bamtools_metrics.nf index d1bd831c..6da8bdc4 100644 --- a/subworkflows/local/bamtools_metrics.nf +++ b/subworkflows/local/bamtools_metrics.nf @@ -6,6 +6,8 @@ import Utils include { BAMTOOLS } from '../../modules/local/bamtools/main' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + workflow BAMTOOLS_METRICS { take: // Sample data @@ -22,12 +24,17 @@ workflow BAMTOOLS_METRICS { // Channel for version.yml files ch_versions = Channel.empty() + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + // Select input sources // NOTE(SW): CUPPA only requires metrics for the tumor sample in the upstream // process Virus Interpreter but ORANGE currently requires metrics for both tumor // and normal sample // channel: [val(meta_bamtools), bam, bai] - ch_bamtools_inputs_all = ch_inputs + ch_bamtools_inputs_all = CHANNEL_GROUP_INPUTS.out.wgs_present .flatMap { meta -> def sample_types if (run.orange) { diff --git a/subworkflows/local/channel_group_inputs.nf b/subworkflows/local/channel_group_inputs.nf new file mode 100644 index 00000000..adb3f0a3 --- /dev/null +++ b/subworkflows/local/channel_group_inputs.nf @@ -0,0 +1,38 @@ +import Constants +import Utils + +workflow CHANNEL_GROUP_INPUTS { + take: + ch_inputs + + main: + // channel (present): [val(meta)] + // channel (absent): [val(meta)] + ch_inputs_wgs = ch_inputs + .branch { meta -> + def key_tumor = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS] + def key_normal = [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.WGS] + present: meta.containsKey(key_tumor) && meta.containsKey(key_normal) + return meta + absent: true + return meta + } + + // channel (present): [val(meta)] + // channel (absent): [val(meta)] + ch_inputs_wts = ch_inputs + .branch { meta -> + def key = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WTS] + present: meta.containsKey(key) + return meta + absent: ! meta.containsKey(key) + return meta + } + + emit: + wgs_present = ch_inputs_wgs.present + wgs_absent = ch_inputs_wgs.absent + + wts_present = ch_inputs_wts.present + wts_absent = ch_inputs_wts.absent +} diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index 132671c1..577ed344 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -5,6 +5,8 @@ import Utils include { COBALT } from '../../modules/local/cobalt/main' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + workflow COBALT_PROFILING { take: // Sample data @@ -17,9 +19,14 @@ workflow COBALT_PROFILING { // Channel for version.yml files ch_versions = Channel.empty() + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + // Select input sources // channel: [meta_cobalt, tumor_bam_wgs, normal_bam_wgs, tumor_bai_wgs, normal_bai_wgs] - ch_cobalt_inputs = ch_inputs + ch_cobalt_inputs = CHANNEL_GROUP_INPUTS.out.wgs_present .map { meta -> def meta_cobalt = [ key: meta.id, diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index d6d60d73..0e400560 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -5,11 +5,12 @@ import Constants include { CUPPA } from '../../modules/local/cuppa/main' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + workflow CUPPA_PREDICTION { take: // Sample data ch_inputs - ch_inputs_wts_absent ch_isofox ch_purple ch_linx @@ -26,6 +27,11 @@ workflow CUPPA_PREDICTION { // Channel for version.yml files ch_versions = Channel.empty() + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + // Select input sources // channel: [val(meta), isofox_dir] ch_cuppa_inputs_isofox = Channel.empty() @@ -34,7 +40,7 @@ workflow CUPPA_PREDICTION { ch_cuppa_inputs_isofox = ch_cuppa_inputs_isofox .mix( ch_isofox, - ch_inputs_wts_absent.map { meta -> [meta, []] }, + CHANNEL_GROUP_INPUTS.out.wts_absent.map { meta -> [meta, []] }, ) } else { ch_cuppa_inputs_isofox = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX, type: 'optional') diff --git a/subworkflows/local/gridss_calling.nf b/subworkflows/local/gridss_calling.nf index b6a1da96..b8021dc7 100644 --- a/subworkflows/local/gridss_calling.nf +++ b/subworkflows/local/gridss_calling.nf @@ -8,6 +8,8 @@ include { GRIDSS_ASSEMBLE as ASSEMBLE } from '../../modules/local/gridss/ass include { GRIDSS_CALL as CALL } from '../../modules/local/gridss/call/main' include { GRIDSS_PREPROCESS as PREPROCESS } from '../../modules/local/gridss/preprocess/main' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + workflow GRIDSS_CALLING { take: ch_inputs // channel: [val(meta)] @@ -24,7 +26,13 @@ workflow GRIDSS_CALLING { // Channel for version.yml files ch_versions = Channel.empty() - ch_inputs_bam_bai = ch_inputs + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + + // Gather BAMs and BAIs + ch_inputs_bam_bai = CHANNEL_GROUP_INPUTS.out.wgs_present .map { meta -> def tumor_bam = Utils.getTumorWgsBam(meta) def normal_bam = Utils.getNormalWgsBam(meta) diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index 6eb980bd..d8df944d 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -11,6 +11,8 @@ include { GRIDSS_PREPROCESS as PREPROCESS } from '../../modules/local/ include { SVPREP as SVPREP_NORMAL } from '../../modules/local/svprep/svprep/main' include { SVPREP as SVPREP_TUMOR } from '../../modules/local/svprep/svprep/main' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + workflow GRIDSS_SVPREP_CALLING { take: ch_inputs // channel: [val(meta)] @@ -30,9 +32,14 @@ workflow GRIDSS_SVPREP_CALLING { // Channel for version.yml files ch_versions = Channel.empty() + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + // Prepare tumor sample inputs // channel: [val(meta_svprep), bam_tumor, bai_tumor, []] - ch_svprep_tumor_inputs = ch_inputs + ch_svprep_tumor_inputs = CHANNEL_GROUP_INPUTS.out.wgs_present .map { meta -> def meta_svprep = [ key: meta.id, @@ -185,7 +192,7 @@ workflow GRIDSS_SVPREP_CALLING { // Prepare inputs for depth annotation, restore original meta // channel: [val(meta_svprep), [bams], [bais], vcf, [labels]] ch_depth_inputs = WorkflowOncoanalyser.groupByMeta( - ch_inputs.map { meta -> [meta.id, meta] }, + CHANNEL_GROUP_INPUTS.out.wgs_present.map { meta -> [meta.id, meta] }, CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .map { id, meta, vcf -> @@ -211,7 +218,7 @@ workflow GRIDSS_SVPREP_CALLING { // Reunite final VCF with the corresponding input meta object ch_out = Channel.empty() .concat( - ch_inputs.map { meta -> [meta.id, meta] }, + CHANNEL_GROUP_INPUTS.out.wgs_present.map { meta -> [meta.id, meta] }, DEPTH_ANNOTATOR.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .groupTuple(size: 2) diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf index 2f0edcc9..1eca9c88 100644 --- a/subworkflows/local/isofox_quantification.nf +++ b/subworkflows/local/isofox_quantification.nf @@ -5,6 +5,8 @@ import Utils include { ISOFOX } from '../../modules/local/isofox/main' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + workflow ISOFOX_QUANTIFICATION { take: // Sample data @@ -26,9 +28,14 @@ workflow ISOFOX_QUANTIFICATION { // Channel for version.yml files ch_versions = Channel.empty() + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + // Create inputs and create process-specific meta // channel: [meta_isofox, tumor_bam_wts] - ch_isofox_inputs = ch_inputs + ch_isofox_inputs = CHANNEL_GROUP_INPUTS.out.wts_present .map { meta -> def bam = Utils.getTumorWtsBam(meta) def meta_isofox = [key: meta.id, id: Utils.getTumorWtsSampleName(meta)] diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index d0c9d9ca..cb0ad069 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -9,14 +9,12 @@ include { CUSTOM_REALIGNREADS } from '../../modules/local/custom/lilac_realig include { CUSTOM_SLICE } from '../../modules/local/custom/lilac_slice/main' include { LILAC } from '../../modules/local/lilac/main' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + workflow LILAC_CALLING { take: // Sample data ch_inputs - ch_inputs_wgs_present - ch_inputs_wgs_absent - ch_inputs_wts_present - ch_inputs_wts_absent ch_purple // Reference data @@ -31,13 +29,18 @@ workflow LILAC_CALLING { // Channel for version.yml files ch_versions = Channel.empty() + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + // Select input sources // channel: [val(meta), purple_dir] if (run.purple) { ch_lilac_inputs_purple = Channel.empty() .mix( ch_purple, - ch_inputs_wgs_absent.map { meta -> [meta, []] }, + CHANNEL_GROUP_INPUTS.out.wgs_absent.map { meta -> [meta, []] }, ) } else { ch_lilac_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional') @@ -48,21 +51,21 @@ workflow LILAC_CALLING { // channel: [val(meta), wts_bam, wts_bai] ch_lilac_bams_wts = Channel.empty() .mix( - ch_inputs_wts_present.map { meta -> + CHANNEL_GROUP_INPUTS.out.wts_present.map { meta -> def bam = Utils.getTumorWtsBam(meta) return [meta, bam, "${bam}.bai"] }, - ch_inputs_wts_absent.map { meta -> [meta, [], []] }, + CHANNEL_GROUP_INPUTS.out.wts_absent.map { meta -> [meta, [], []] }, ) ch_lilac_bams_wgs = Channel.empty() .mix( - ch_inputs_wgs_present.map { meta -> + CHANNEL_GROUP_INPUTS.out.wgs_present.map { meta -> def tumor_bam = Utils.getTumorWgsBam(meta) def normal_bam = Utils.getNormalWgsBam(meta) [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] }, - ch_inputs_wgs_absent.map { meta -> [meta, [], [], [], []] }, + CHANNEL_GROUP_INPUTS.out.wgs_absent.map { meta -> [meta, [], [], [], []] }, ) // Combine WGS and WTS BAMs diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 78350405..0f9ad1bc 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -6,13 +6,13 @@ import Utils include { ORANGE } from '../../modules/local/orange/main' -include { FLAGSTAT_METRICS } from './flagstat_metrics' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' +include { FLAGSTAT_METRICS } from './flagstat_metrics' workflow ORANGE_REPORTING { take: // Sample data ch_inputs - ch_inputs_wgs ch_bamtools_somatic ch_bamtools_germline ch_sage_somatic_tumor_bqr @@ -47,6 +47,11 @@ workflow ORANGE_REPORTING { // Channel for version.yml files ch_versions = Channel.empty() + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + // // SUBWORKFLOW: Run SAMtools flagstat to generate stats required for ORANGE // @@ -56,7 +61,7 @@ workflow ORANGE_REPORTING { if (run.flagstat) { FLAGSTAT_METRICS( - ch_inputs_wgs, + CHANNEL_GROUP_INPUTS.out.wgs_present, ) ch_versions = ch_versions.mix(FLAGSTAT_METRICS.out.versions) diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index e4c70293..c28b1e16 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -5,6 +5,8 @@ include { SAGE_GERMLINE as GERMLINE } from '../../modules/local/sage/germline/main' include { SAGE_SOMATIC as SOMATIC } from '../../modules/local/sage/somatic/main' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + workflow SAGE_CALLING { take: ch_inputs // channel: [val(meta)] @@ -26,8 +28,13 @@ workflow SAGE_CALLING { // Channel for version.yml files ch_versions = Channel.empty() + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + // Get inputs - ch_sage_inputs = ch_inputs + ch_sage_inputs = CHANNEL_GROUP_INPUTS.out.wgs_present .map { meta -> def meta_sage = [ key: meta.id, diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index 644c59b2..7ca3d4b1 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -7,6 +7,8 @@ import Utils include { VIRUSBREAKEND } from '../../modules/local/virusbreakend/main' include { VIRUSINTERPRETER } from '../../modules/local/virusinterpreter/main' +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + workflow VIRUSBREAKEND_CALLING { take: // Sample data @@ -33,10 +35,15 @@ workflow VIRUSBREAKEND_CALLING { // Channel for version.yml files ch_versions = Channel.empty() + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + // VIRUSBreakend // Create inputs and create process-specific meta // channel: [val(meta_virus), tumor_bam] - ch_virusbreakend_inputs = ch_inputs + ch_virusbreakend_inputs = CHANNEL_GROUP_INPUTS.out.wgs_present .map { meta -> def meta_virus = [ key: meta.id, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 2c2caa23..c78c3e4a 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -105,41 +105,18 @@ workflow WGTS { // channel: [versions.yml] ch_versions = Channel.empty() - // Get inputs from samplesheet + // Get inputs from samplesheet, assign more human readable variable // channel: [val(meta)] PREPARE_INPUT( samplesheet, ) ch_inputs = PREPARE_INPUT.out.data - // Split inputs WTS and WGS - // NOTE(SW): assuming there are only t/n pairs i.e. no tumor-only or normal-only - - // channel (present): [val(meta)] - // channel (absent): [val(meta)] - ch_inputs_wgs = ch_inputs - .branch { meta -> - def key_tumor = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS] - def key_normal = [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.WGS] - present: meta.containsKey(key_tumor) && meta.containsKey(key_normal) - return meta - absent: true - return meta - } - - // channel (present): [val(meta)] - // channel (absent): [val(meta)] - ch_inputs_wts = ch_inputs - .branch { meta -> - def key = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WTS] - present: meta.containsKey(key) - return meta - absent: ! meta.containsKey(key) - return meta - } - - // Set up reference data and unpack HMF data map for convenience - PREPARE_REFERENCE(run) + // Set up reference data, assign more human readable variables + PREPARE_REFERENCE( + run, + ) + ref_data = PREPARE_REFERENCE.out hmf_data = PREPARE_REFERENCE.out.hmf_data // @@ -150,10 +127,10 @@ workflow WGTS { if (run.isofox) { ISOFOX_QUANTIFICATION( - ch_inputs_wts.present, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_version, + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_version, hmf_data.ensembl_data_resources, hmf_data.isofox_counts, hmf_data.isofox_gc_ratios, @@ -173,9 +150,9 @@ workflow WGTS { if (run.bamtools) { BAMTOOLS_METRICS( - ch_inputs_wgs.present, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_version, + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_version, run, ) @@ -192,8 +169,8 @@ workflow WGTS { if (run.amber) { AMBER_PROFILING( - ch_inputs_wgs.present, - PREPARE_REFERENCE.out.genome_version, + ch_inputs, + ref_data.genome_version, hmf_data.heterozygous_sites, ) @@ -209,7 +186,7 @@ workflow WGTS { if (run.cobalt) { COBALT_PROFILING( - ch_inputs_wgs.present, + ch_inputs, hmf_data.gc_profile, ) @@ -226,15 +203,15 @@ workflow WGTS { if (run.svprep) { GRIDSS_SVPREP_CALLING( - ch_inputs_wgs.present, + ch_inputs, gridss_config, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_version, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_bwa_index, - PREPARE_REFERENCE.out.genome_bwa_index_image, - PREPARE_REFERENCE.out.genome_gridss_index, + ref_data.genome_fasta, + ref_data.genome_version, + ref_data.genome_fai, + ref_data.genome_dict, + ref_data.genome_bwa_index, + ref_data.genome_bwa_index_image, + ref_data.genome_gridss_index, hmf_data.gridss_region_blocklist, hmf_data.sv_prep_blocklist, hmf_data.known_fusions, @@ -246,14 +223,14 @@ workflow WGTS { } else { GRIDSS_CALLING( - ch_inputs_wgs.present, + ch_inputs, gridss_config, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_bwa_index, - PREPARE_REFERENCE.out.genome_bwa_index_image, - PREPARE_REFERENCE.out.genome_gridss_index, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_dict, + ref_data.genome_bwa_index, + ref_data.genome_bwa_index_image, + ref_data.genome_gridss_index, hmf_data.gridss_region_blocklist, ) @@ -274,9 +251,9 @@ workflow WGTS { GRIPSS_FILTERING( ch_inputs, ch_gridss_out, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_version, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_version, hmf_data.gridss_pon_breakends, hmf_data.gridss_pon_breakpoints, hmf_data.known_fusions, @@ -304,11 +281,11 @@ workflow WGTS { if (run.sage) { SAGE_CALLING( - ch_inputs_wgs.present, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_version, + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_dict, + ref_data.genome_version, hmf_data.sage_known_hotspots_germline, hmf_data.sage_known_hotspots_somatic, hmf_data.sage_actionable_panel, @@ -341,9 +318,9 @@ workflow WGTS { ch_inputs, ch_sage_germline_vcf_out, ch_sage_somatic_vcf_out, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_version, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_version, hmf_data.sage_pon, hmf_data.sage_blocklist_regions, hmf_data.sage_blocklist_sites, @@ -376,10 +353,10 @@ workflow WGTS { ch_gripss_somatic_out, ch_gripss_germline_out, ch_gripss_somatic_unfiltered_out, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_version, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_dict, + ref_data.genome_version, hmf_data.gc_profile, hmf_data.sage_known_hotspots_somatic, hmf_data.sage_known_hotspots_germline, @@ -406,7 +383,7 @@ workflow WGTS { LINX_ANNOTATION( ch_inputs, ch_purple_out, - PREPARE_REFERENCE.out.genome_version, + ref_data.genome_version, hmf_data.ensembl_data_resources, hmf_data.known_fusion_data, hmf_data.driver_gene_panel, @@ -421,7 +398,7 @@ workflow WGTS { LINX_PLOTTING( ch_inputs, ch_linx_somatic_out, - PREPARE_REFERENCE.out.genome_version, + ref_data.genome_version, hmf_data.ensembl_data_resources, ) @@ -457,7 +434,7 @@ workflow WGTS { CHORD_PREDICTION( ch_inputs, ch_purple_out, - PREPARE_REFERENCE.out.genome_version, + ref_data.genome_version, run, ) @@ -472,16 +449,11 @@ workflow WGTS { ch_lilac_out = Channel.empty() if (run.lilac) { - // TODO(SW): improve interface here LILAC_CALLING( ch_inputs, - ch_inputs_wgs.present, - ch_inputs_wgs.absent, - ch_inputs_wts.present, - ch_inputs_wts.absent, ch_purple_out, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, + ref_data.genome_fasta, + ref_data.genome_fai, hmf_data.lilac_resources, run, ) @@ -498,16 +470,16 @@ workflow WGTS { if (run.virusinterpreter) { VIRUSBREAKEND_CALLING( - ch_inputs_wgs.present, + ch_inputs, ch_purple_out, ch_bamtools_somatic_out, - PREPARE_REFERENCE.out.genome_fasta, - PREPARE_REFERENCE.out.genome_fai, - PREPARE_REFERENCE.out.genome_dict, - PREPARE_REFERENCE.out.genome_bwa_index, - PREPARE_REFERENCE.out.genome_bwa_index_image, - PREPARE_REFERENCE.out.genome_gridss_index, - PREPARE_REFERENCE.out.virusbreakenddb, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_dict, + ref_data.genome_bwa_index, + ref_data.genome_bwa_index_image, + ref_data.genome_gridss_index, + ref_data.virusbreakenddb, hmf_data.virus_taxonomy_db, hmf_data.virus_reporting_db, run, @@ -527,12 +499,11 @@ workflow WGTS { CUPPA_PREDICTION( ch_inputs, - ch_inputs_wts.absent, ch_isofox_out, ch_purple_out, ch_linx_somatic_out, ch_virusinterpreter_out, - PREPARE_REFERENCE.out.genome_version, + ref_data.genome_version, hmf_data.cuppa_resources, run, ) @@ -548,7 +519,6 @@ workflow WGTS { ORANGE_REPORTING( ch_inputs, - ch_inputs_wgs.present, ch_bamtools_somatic_out, ch_bamtools_germline_out, ch_sage_somatic_tumor_bqr_out, @@ -564,7 +534,7 @@ workflow WGTS { ch_lilac_out, ch_cuppa_out, ch_isofox_out, - PREPARE_REFERENCE.out.genome_version, + ref_data.genome_version, hmf_data.disease_ontology, hmf_data.cohort_mapping, hmf_data.cohort_percentiles, From 85d6433e77dc50f17778f55d0d08e4e8168d17ce Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 4 May 2023 11:53:22 +1000 Subject: [PATCH 149/562] Update HMF reference data structure --- conf/hmfdata.config | 126 ++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 43fef51e..f4c0d08c 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -2,101 +2,101 @@ params { hmfdata_paths { '37' { // AMBER - heterozygous_sites = 'amber/GermlineHetPon.37.vcf.gz' + heterozygous_sites = 'dna_pipeline/copy_number/GermlineHetPon.37.vcf.gz' // COBALT - gc_profile = 'gc_profiles/GC_profile.1000bp.37.cnp' + gc_profile = 'dna_pipeline/copy_number/GC_profile.1000bp.37.cnp' // CUPPA cuppa_resources = 'cuppa/' // SV Prep - sv_prep_blocklist = 'gridss/sv_prep_blacklist.37.bed' + sv_prep_blocklist = 'dna_pipeline/sv/sv_prep_blacklist.37.bed' // GRIDSS, GRIPSS - gridss_pon_breakends = 'gridss/sgl_pon.37.bed.gz' - gridss_pon_breakpoints = 'gridss/sv_pon.37.bedpe.gz' - gridss_region_blocklist = 'gridss/gridss_blacklist.37.bed.gz' - repeatmasker_annotations = 'gridss/repeat_mask_data.37.fa.gz' + gridss_pon_breakends = 'dna_pipeline/sv/sgl_pon.37.bed.gz' + gridss_pon_breakpoints = 'dna_pipeline/sv/sv_pon.37.bedpe.gz' + gridss_region_blocklist = 'dna_pipeline/sv/gridss_blacklist.37.bed.gz' + repeatmasker_annotations = 'dna_pipeline/sv/repeat_mask_data.37.fa.gz' // Isofox - isofox_counts = 'isofox/read_151_exp_counts.csv' - isofox_gc_ratios = 'isofox/read_100_exp_gc_ratios.csv' + isofox_counts = 'rna_pipeline/read_151_exp_counts.csv' + isofox_gc_ratios = 'rna_pipeline/read_100_exp_gc_ratios.csv' // LILAC - lilac_resources = 'lilac/' + lilac_resources = 'dna_pipeline/immune/' // ORANGE - cohort_mapping = 'orange/cohort_mapping.tsv' - cohort_percentiles = 'orange/cohort_percentiles.tsv' + cohort_mapping = 'missing/orange/cohort_mapping.tsv' + cohort_percentiles = 'missing/orange/cohort_percentiles.tsv' alt_sj_distribution = 'cuppa/cup_ref_alt_sj_sample.csv.gz' gene_exp_distribution = 'cuppa/cup_ref_gene_exp_sample.csv.gz' // SAGE - clinvar_annotations = 'sage/clinvar.37.vcf.gz' - sage_blocklist_regions = 'sage/KnownBlacklist.germline.37.bed' - sage_blocklist_sites = 'sage/KnownBlacklist.germline.37.vcf.gz' - sage_actionable_panel = 'sage/ActionableCodingPanel.37.bed.gz' - sage_coverage_panel = 'sage/CoverageCodingPanel.37.bed.gz' - sage_highconf_regions = 'giab_high_conf/NA12878_GIAB_highconf_IllFB-IllGATKHC-CG-Ion-Solid_ALLCHROM_v3.2.2_highconf.bed.gz' - sage_known_hotspots_germline = 'sage/KnownHotspots.germline.37.vcf.gz' - sage_known_hotspots_somatic = 'sage/KnownHotspots.somatic.37.vcf.gz' - sage_pon = 'sage/SageGermlinePon.1000x.37.tsv.gz' + clinvar_annotations = 'dna_pipeline/variants/clinvar.37.vcf.gz' + sage_blocklist_regions = 'dna_pipeline/variants/KnownBlacklist.germline.37.bed' + sage_blocklist_sites = 'dna_pipeline/variants/KnownBlacklist.germline.37.vcf.gz' + sage_actionable_panel = 'dna_pipeline/variants/ActionableCodingPanel.37.bed.gz' + sage_coverage_panel = 'dna_pipeline/variants/ActionableCodingPanel.37.bed.gz' + sage_highconf_regions = 'dna_pipeline/variants/NA12878_GIAB_highconf_IllFB-IllGATKHC-CG-Ion-Solid_ALLCHROM_v3.2.2_highconf.bed.gz' + sage_known_hotspots_germline = 'dna_pipeline/variants/KnownHotspots.germline.37.vcf.gz' + sage_known_hotspots_somatic = 'dna_pipeline/variants/KnownHotspots.somatic.37.vcf.gz' + sage_pon = 'dna_pipeline/variants/SageGermlinePon.1000x.37.tsv.gz' // SIGS - sigs_signatures = 'sigs/snv_cosmic_signatures.csv' + sigs_signatures = 'missing/sigs/snv_cosmic_signatures.csv' // Virus Interpreter - virus_reporting_db = 'virus_interpreter/virus_reporting_db.tsv' - virus_taxonomy_db = 'virus_interpreter/taxonomy_db.tsv' + virus_reporting_db = 'missing/viral/virus_reporting_db.tsv' + virus_taxonomy_db = 'missing/viral/taxonomy_db.tsv' // Misc - disease_ontology = 'disease_ontology/201015_doid.json' - driver_gene_panel = 'gene_panel/DriverGenePanel.37.tsv' - ensembl_data_resources = 'ensembl_data_cache/' + disease_ontology = 'missing/orange/201015_doid.json' + driver_gene_panel = 'dna_pipeline/common/DriverGenePanel.37.tsv' + ensembl_data_resources = 'dna_pipeline/common/ensembl_data/' gnomad_pon_dir = [] - known_fusion_data = 'fusions/known_fusion_data.37.csv' - known_fusions = 'fusions/known_fusions.37.bedpe' - purple_germline_del = 'purple/cohort_germline_del_freq.37.csv' - segment_mappability = 'mappability/mappability_150.37.bed.gz' + known_fusion_data = 'dna_pipeline/sv/known_fusion_data.37.csv' + known_fusions = 'dna_pipeline/sv/known_fusions.37.bedpe' + purple_germline_del = 'dna_pipeline/copy_number/cohort_germline_del_freq.37.csv' + segment_mappability = 'dna_pipeline/variants/mappability_150.37.bed.gz' } '38' { // AMBER - heterozygous_sites = 'amber/GermlineHetPon.38.vcf.gz' + heterozygous_sites = 'dna_pipeline/copy_number/GermlineHetPon.38.vcf.gz' // COBALT - gc_profile = 'gc_profiles/GC_profile.1000bp.38.cnp' + gc_profile = 'dna_pipeline/copy_number/GC_profile.1000bp.38.cnp' // CUPPA cuppa_resources = 'cuppa/' // SV Prep - sv_prep_blocklist = 'gridss/sv_prep_blacklist.38.bed' + sv_prep_blocklist = 'dna_pipeline/sv/sv_prep_blacklist.38.bed' // GRIDSS, GRIPSS - gridss_pon_breakends = 'gridss/sgl_pon.38.bed.gz' - gridss_pon_breakpoints = 'gridss/sv_pon.38.bedpe.gz' - gridss_region_blocklist = 'gridss/gridss_blacklist.38.bed.gz' - repeatmasker_annotations = 'gridss/repeat_mask_data.38.fa.gz' + gridss_pon_breakends = 'dna_pipeline/sv/sgl_pon.38.bed.gz' + gridss_pon_breakpoints = 'dna_pipeline/sv/sv_pon.38.bedpe.gz' + gridss_region_blocklist = 'dna_pipeline/sv/gridss_blacklist.38.bed.gz' + repeatmasker_annotations = 'dna_pipeline/sv/repeat_mask_data.38.fa.gz' // Isofox - isofox_counts = 'isofox/read_151_exp_counts.csv' - isofox_gc_ratios = 'isofox/read_100_exp_gc_ratios.csv' + isofox_counts = 'rna_pipeline/read_151_exp_counts.csv' + isofox_gc_ratios = 'rna_pipeline/read_100_exp_gc_ratios.csv' // LILAC - lilac_resources = 'lilac/' + lilac_resources = 'dna_pipeline/immune/' // ORANGE - cohort_mapping = 'orange/cohort_mapping.tsv' - cohort_percentiles = 'orange/cohort_percentiles.tsv' + cohort_mapping = 'missing/orange/cohort_mapping.tsv' + cohort_percentiles = 'missing/orange/cohort_percentiles.tsv' alt_sj_distribution = 'cuppa/cup_ref_alt_sj_sample.csv.gz' gene_exp_distribution = 'cuppa/cup_ref_gene_exp_sample.csv.gz' // SAGE - clinvar_annotations = 'sage/clinvar.38.vcf.gz' - sage_blocklist_regions = 'sage/KnownBlacklist.germline.38.bed' - sage_blocklist_sites = 'sage/KnownBlacklist.germline.38.vcf.gz' - sage_actionable_panel = 'sage/ActionableCodingPanel.38.bed.gz' - sage_coverage_panel = 'sage/CoverageCodingPanel.38.bed.gz' - sage_highconf_regions = 'giab_high_conf/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz' - sage_known_hotspots_germline = 'sage/KnownHotspots.germline.38.vcf.gz' - sage_known_hotspots_somatic = 'sage/KnownHotspots.somatic.38.vcf.gz' - sage_pon = 'sage/SageGermlinePon.98x.38.tsv.gz' + clinvar_annotations = 'dna_pipeline/variants/clinvar.38.vcf.gz' + sage_blocklist_regions = 'dna_pipeline/variants/KnownBlacklist.germline.38.bed' + sage_blocklist_sites = 'dna_pipeline/variants/KnownBlacklist.germline.38.vcf.gz' + sage_actionable_panel = 'dna_pipeline/variants/ActionableCodingPanel.38.bed.gz' + sage_coverage_panel = 'dna_pipeline/variants/CoverageCodingPanel.38.bed.gz' + sage_highconf_regions = 'dna_pipeline/variants/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticde' + sage_known_hotspots_germline = 'dna_pipeline/variants/KnownHotspots.germline.38.vcf.gz' + sage_known_hotspots_somatic = 'dna_pipeline/variants/KnownHotspots.somatic.38.vcf.gz' + sage_pon = 'dna_pipeline/variants/SageGermlinePon.98x.38.tsv.gz' // SIGS - sigs_signatures = 'sigs/snv_cosmic_signatures.csv' + sigs_signatures = 'missing/sigs/snv_cosmic_signatures.csv' // Virus Interpreter - virus_reporting_db = 'virus_interpreter/virus_reporting_db.tsv' - virus_taxonomy_db = 'virus_interpreter/taxonomy_db.tsv' + virus_reporting_db = 'missing/viral/virus_reporting_db.tsv' + virus_taxonomy_db = 'missing/viral/taxonomy_db.tsv' // Misc - disease_ontology = 'disease_ontology/201015_doid.json' - driver_gene_panel = 'gene_panel/DriverGenePanel.38.tsv' - ensembl_data_resources = 'ensembl_data_cache/' - gnomad_pon_dir = 'gnomad/' - known_fusion_data = 'fusions/known_fusion_data.38.csv' - known_fusions = 'fusions/known_fusions.38.bedpe' - purple_germline_del = 'purple/cohort_germline_del_freq.38.csv' - segment_mappability = 'mappability/mappability_150.38.bed.gz' + disease_ontology = 'missing/orange/201015_doid.json' + driver_gene_panel = 'dna_pipeline/common/DriverGenePanel.38.tsv' + ensembl_data_resources = 'dna_pipeline/common/ensembl_data/' + gnomad_pon_dir = 'dna_pipeline/variants/gnomad/' + known_fusion_data = 'dna_pipeline/sv/known_fusion_data.38.csv' + known_fusions = 'dna_pipeline/sv/known_fusions.38.bedpe' + purple_germline_del = 'dna_pipeline/copy_number/cohort_germline_del_freq.38.csv' + segment_mappability = 'dna_pipeline/variants/mappability_150.38.bed.gz' } } } From 85da0a909c8f4d7bd45adc5f84797c75acd04d68 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 4 May 2023 17:14:26 +1000 Subject: [PATCH 150/562] Allow forcing custom genome, better config support --- lib/Constants.groovy | 10 ++- lib/WorkflowMain.groovy | 3 +- lib/WorkflowOncoanalyser.groovy | 107 ++++++++++++++++++++++---------- nextflow_schema.json | 18 +++++- workflows/wgts.nf | 15 ++++- 5 files changed, 110 insertions(+), 43 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index ae9629a9..7e3149e4 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -1,9 +1,13 @@ class Constants { // NOTE(SW): the HMF reference data files are incompatible with hg19 due to different contig naming - static List GENOMES_VERSION_37 = ['GRCh37_hmf', 'GRCh37'] - static List GENOMES_VERSION_38 = ['GRCh38_hmf', 'GRCh38', 'hg38'] - static List GENOMES_ALT = ['GRCh38', 'hg38'] + static List GENOMES_VERSION_37 = ['GRCh37_hmf', 'GRCh37'] + static List GENOMES_VERSION_38 = ['GRCh38_hmf', 'GRCh38', 'hg38'] + static List GENOMES_ALT = ['GRCh38', 'hg38'] + + static List GENOMES_SUPPORTED = ['GRCh37_hmf', 'GRCh38_hmf'] + static List GENOMES_DEFINED = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 + static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.31_37_0.0.1.tar.gz' static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32+dev1_38_0.0.1.tar.gz' diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index b30cd096..1784de60 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -58,8 +58,9 @@ class WorkflowMain { NfcoreSchema.validateParameters(workflow, params, log) } + // NOTE(SW): this is now deferred until after we set defaults in subworkflows // Print parameter summary log to screen - log.info paramsSummaryLog(workflow, params, log) + //log.info paramsSummaryLog(workflow, params, log) // Check that a -profile or Nextflow config has been provided to run the pipeline NfcoreTemplate.checkConfigProvided(workflow, log) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 4fc1ddfe..33f345a4 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -12,12 +12,48 @@ import Constants class WorkflowOncoanalyser { // - // Check and validate parameters + // Set parameter defaults where required // - public static void initialise(params, workflow, log) { + public static void setParamsDefaults(params, log) { + + if (params.containsKey('genome_version')) { + params.ref_data_genome_version = params.genome_version.toString() + } else if (Constants.GENOMES_VERSION_37.contains(params.genome)) { + params.ref_data_genome_version = '37' + } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { + params.ref_data_genome_version = '38' + } else { + log.error "ERROR: Got a bad genome version: ${params.ref_data_genome_version}" + System.exit(1) + } + + if (params.containsKey('genome_type')) { + params.ref_data_genome_type = params.genome_type + } else if (Constants.GENOMES_ALT.contains(params.genome)) { + params.ref_data_genome_type = 'alt' + } else if (Constants.GENOMES_DEFINED.contains(params.genome)) { + params.ref_data_genome_type = 'no_alt' + } else { + log.error "ERROR: Got a bad genome type: ${params.ref_data_genome_type}" + System.exit(1) + } - // TODO(SW): allow users to set all appropriate reference genomes manually in config or CLI, including version and type (see below) + if (!params.containsKey('ref_data_hmf_data_path')) { + if (params.ref_data_genome_version == '37') { + params.ref_data_hmf_data_path = Constants.HMF_DATA_37_PATH + } else if (params.ref_data_genome_version == '38') { + params.ref_data_hmf_data_path = Constants.HMF_DATA_38_PATH + } + } + if (!params.containsKey('ref_data_virusbreakenddb_path')) { + params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH + } + + // + // Check and validate parameters + // + public static void validateParams(params, log) { if (!params.genome) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome must be set using the --genome CLI argument or in a configuration file.\n" + @@ -34,53 +70,47 @@ class WorkflowOncoanalyser { System.exit(1) } - // NOTE(SW): restricting allowable genome values to GRCh37_hmf for now - if (params.genome != 'GRCh37_hmf' && params.genome != 'GRCh38_hmf') { - log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got \"${params.genome}\"" + - ", please adjust the --genome argument accordingly." - System.exit(1) + if (!Constants.GENOMES_SUPPORTED.contains(params.genome)) { + if (!params.containsKey('force_genome')) { + log.warn "currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but forcing to " + + "proceed with \"${params.genome}\"" + } else { + log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got \"${params.genome}\"" + + ", please adjust the --genome argument accordingly." + System.exit(1) + } } - if (Constants.GENOMES_VERSION_37.contains(params.genome)) { - params.ref_data_genome_version = '37' - } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { - params.ref_data_genome_version = '38' - } else { - def genome_version_list_all = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 + if (!params.ref_data_genome_version) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome '${params.genome}' is not defined in genome version list. \n" + + " Genome version wasn't provided and genome '${params.genome}' is not defined in \n" + + " genome version list.\n" + " Currently, the list of genomes in the version list include:\n" + - " ${genome_version_list_all.join(", ")}\n" + + " ${Constants.GENOMES_DEFINED.join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) } - // TODO(SW): when allowing user to set custom genome, require this to be explicitly set - if (Constants.GENOMES_ALT.contains(params.genome)) { - params.ref_data_genome_type = 'alt' - } else { - params.ref_data_genome_type = 'no_alt' - } - - if (!params.containsKey('ref_data_hmf_data_path')) { - if (params.ref_data_genome_version == '37') { - params.ref_data_hmf_data_path = Constants.HMF_DATA_37_PATH - } else if (params.ref_data_genome_version == '38') { - params.ref_data_hmf_data_path = Constants.HMF_DATA_38_PATH - } else { - assert false : "Got a bad genome version: ${params.ref_data_genome_version}" - } + if (!params.ref_data_genome_type) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome type wasn't provided and genome '${params.genome}' is not defined in \n" + + " genome version list.\n" + + " Currently, the list of genomes in the version list include:\n" + + " ${Constants.GENOMES_DEINFED.join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) } - if (!params.containsKey('ref_data_virusbreakenddb_path')) { - params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH + if (!params.ref_data_hmf_data_path) { + log.error "ERROR: HMF data path wasn't provided" + System.exit(1) } + // NOTE(SW): this could be moved to the wgts.nf where we check that input files exist def null_check = [ 'ref_data_genome_fasta', 'ref_data_genome_type', 'ref_data_genome_version', - 'ref_data_virusbreakenddb_path', ] null_check.each { k -> if (!params[k]) { @@ -90,6 +120,15 @@ class WorkflowOncoanalyser { } } + public static String paramsSummaryLog(workflow, params, log) { + def summary_log = '' + summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) + summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) + summary_log += '\n' + WorkflowMain.citation(workflow) + '\n' + summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) + log.info summary_log + } + public static groupByMeta(Map named_args, ... channels) { def r = channels // Set position; required to use non-blocking .mix operator diff --git a/nextflow_schema.json b/nextflow_schema.json index 3eec8eee..e0ab6767 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -52,6 +52,11 @@ "description": "Pipeline mode to use.", "fa_icon": "fas fa-diagram-project" }, + "force_genome": { + "type": "boolean", + "description": "Skip check for restricted genome.", + "fa_icon": "fas fa-palette" + }, "processes_exclude": { "type": "string", "description": "Pipeline processes to exclude.", @@ -94,9 +99,18 @@ "properties": { "genome": { "type": "string", - "description": "Name of iGenomes reference.", + "description": "Name of genome reference.", + "fa_icon": "fas fa-book" + }, + "genome_version": { + "description": "Reference genome version.", "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." + "hidden": true + }, + "genome_type": { + "description": "Reference genome type.", + "fa_icon": "fas fa-book", + "hidden": true }, "igenomes_base": { "type": "string", diff --git a/workflows/wgts.nf b/workflows/wgts.nf index c78c3e4a..edfdba27 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -9,10 +9,13 @@ import Utils ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) +// Set defaults and validate parameters +WorkflowOncoanalyser.setParamsDefaults(params, log) +WorkflowOncoanalyser.validateParams(params, log) -// Validate input parameters -WorkflowOncoanalyser.initialise(params, workflow, log) +// Get parameter summary and also print to console +def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) +WorkflowOncoanalyser.paramsSummaryLog(workflow, params, log) // Set processes to run processes = Processes.setProcesses(params.mode, log) @@ -34,6 +37,12 @@ def checkPathParamList = [ params.linx_gene_id_file, ] +// Conditional requirements +if (run.virusinterpreter) { + checkPathParamList.add(params.ref_data_virusbreakenddb_path) +} + +// TODO(SW): consider whether we should check for null entries here for errors to be more informative for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } // Check mandatory parameters From d093414da7bd99336c9a3dc38a692e5c648d97fc Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 4 May 2023 17:15:02 +1000 Subject: [PATCH 151/562] Improve selection and config for HLA slice BED --- conf/hmfdata.config | 2 ++ lib/Constants.groovy | 2 ++ lib/WorkflowLilac.groovy | 8 +++----- lib/WorkflowOncoanalyser.groovy | 5 +++++ modules/local/custom/lilac_slice/main.nf | 3 ++- nextflow_schema.json | 6 ++++++ subworkflows/local/lilac_calling.nf | 19 +++++-------------- subworkflows/local/prepare_reference.nf | 1 + workflows/wgts.nf | 14 ++++++++++++++ 9 files changed, 40 insertions(+), 20 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index f4c0d08c..0d154b1e 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -19,6 +19,7 @@ params { isofox_gc_ratios = 'rna_pipeline/read_100_exp_gc_ratios.csv' // LILAC lilac_resources = 'dna_pipeline/immune/' + hla_slice_bed = 'missing/lilac/hla.37.bed' // ORANGE cohort_mapping = 'missing/orange/cohort_mapping.tsv' cohort_percentiles = 'missing/orange/cohort_percentiles.tsv' @@ -68,6 +69,7 @@ params { isofox_gc_ratios = 'rna_pipeline/read_100_exp_gc_ratios.csv' // LILAC lilac_resources = 'dna_pipeline/immune/' + hla_slice_bed = 'missing/lilac/hla.38.bed' // ORANGE cohort_mapping = 'missing/orange/cohort_mapping.tsv' cohort_percentiles = 'missing/orange/cohort_percentiles.tsv' diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 7e3149e4..bfd5f716 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -14,6 +14,8 @@ class Constants { static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' + static String HLA_SLICE_BED_GRCH38_ALT_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/umccr_reference_data/other/hla_slice/grch38_alt.plus_homologous.bed' + static enum PipelineMode { FULL, MANUAL, diff --git a/lib/WorkflowLilac.groovy b/lib/WorkflowLilac.groovy index dc18425f..fe0f4922 100755 --- a/lib/WorkflowLilac.groovy +++ b/lib/WorkflowLilac.groovy @@ -9,9 +9,9 @@ import Utils class WorkflowLilac { - public static getSliceInputs(ch, ch_slice_bed) { + public static getSliceInputs(ch) { // channel: [val(meta_lilac), bam, bai] - def d = ch + return ch .flatMap { meta, nbam_wgs, nbai_wgs, tbam_wgs, tbai_wgs, tbam_wts, tbai_wts -> def data = [ [nbam_wgs, nbai_wgs, Constants.SequenceType.WGS, Constants.SampleType.NORMAL], @@ -33,12 +33,10 @@ class WorkflowLilac { return [meta_lilac, bam, bai] } } - // channel: [val(meta_lilac), bam, bai, bed] - return d.combine(ch_slice_bed) } public static getUniqueInputFiles(ch) { - // channel: [val(meta_lilac), bam, bai, bed] + // channel: [val(meta_lilac), bam, bai] def d = ch .map { [it[1..-1], it[0]] } .groupTuple() diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 33f345a4..c1b16de5 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -50,6 +50,11 @@ class WorkflowOncoanalyser { params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH } + if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && !params.containsKey('ref_data_hla_slice_bed')) { + params.ref_data_hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH + } + } + // // Check and validate parameters // diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index b7565497..e3b371f7 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -5,7 +5,8 @@ process CUSTOM_SLICE { container 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' input: - tuple val(meta), path(bam), path(bai), path(bed) + tuple val(meta), path(bam), path(bai) + path(bed) output: tuple val(meta), path("*sliced.bam"), path("*sliced.bam.bai"), emit: bam diff --git a/nextflow_schema.json b/nextflow_schema.json index e0ab6767..0b088f37 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -138,6 +138,12 @@ "description": "Path to VIRUSBreakend database.", "fa_icon": "far fa-file-code" }, + "ref_data_hla_slice_bed": { + "format": "file-path", + "pattern": "^\\S+\\.bed$", + "description": "Path to HLA slice BED file.", + "fa_icon": "far fa-file-code" + }, "ref_data_genome_fasta": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index cb0ad069..85383570 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -21,6 +21,7 @@ workflow LILAC_CALLING { ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_lilac_resource_dir // file: /path/to/lilac_resource_dir/ + ref_data_hla_slice_bed // Params run @@ -82,22 +83,11 @@ workflow LILAC_CALLING { } // Slice HLA regions - ch_slice_bed = ref_data_lilac_resource_dir - .map { lilac_dir -> - def filename - if (params.ref_data_genome_type == 'no_alt') { - filename = "hla.${params.ref_data_genome_version}.bed" - } else { - filename = "hla.38.alt.umccr.bed" - } - def filepath = lilac_dir.resolve(filename).toUriString() - return file(filepath, checkIfExists: true) - } // NOTE(SW): here I remove duplicate files so that we only process each input once // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used // in Pipeline5, see LilacBamSlicer.java#L115 - // channel: [val(meta_lilac), bam, bai, bed] - ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_lilac_bams, ch_slice_bed) + // channel: [val(meta_lilac), bam, bai] + ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_lilac_bams) // Isolate meta containing expected file count to use for non-blocking groupTuple later ch_slice_meta_individual = ch_slice_inputs .map { @@ -105,10 +95,11 @@ workflow LILAC_CALLING { return [key: meta_lilac.key, count: meta_lilac.count] } // Apply slicing to unique files only - // channel: [val(meta_lilac), bam, bai, bed] + // channel: [val(meta_lilac), bam, bai] ch_slice_inputs_unique = WorkflowLilac.getUniqueInputFiles(ch_slice_inputs) CUSTOM_SLICE( ch_slice_inputs_unique, + ref_data_hla_slice_bed, ) ch_versions = ch_versions.mix(CUSTOM_SLICE.out.versions) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 3eb34e19..b0916bfa 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -171,6 +171,7 @@ def createHmfDataMap(hmf_data_path, params_only) { isofox_gc_ratios: 'ref_data_isofox_gc_ratios', // LILAC lilac_resources: 'ref_data_lilac_resources', + hla_slice_bed: 'ref_data_hla_slice_bed', // ORANGE cohort_mapping: 'ref_data_cohort_mapping', cohort_percentiles: 'ref_data_cohort_percentiles', diff --git a/workflows/wgts.nf b/workflows/wgts.nf index edfdba27..2bd68f45 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -42,6 +42,10 @@ if (run.virusinterpreter) { checkPathParamList.add(params.ref_data_virusbreakenddb_path) } +if (run.lilac && params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt') { + checkPathParamList.add(params.ref_data_hla_slice_bed) +} + // TODO(SW): consider whether we should check for null entries here for errors to be more informative for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } @@ -458,12 +462,22 @@ workflow WGTS { ch_lilac_out = Channel.empty() if (run.lilac) { + // Select HLA slice BED + if (params.ref_data_genome_type == 'no_alt') { + ref_data_hla_slice_bed = hmf_data.hla_slice_bed.collect() + } else if (params.ref_data_genome_type == 'alt' && params.ref_data_genome_version == '38') { + ref_data_hla_slice_bed = params.ref_data_hla_slice_bed + } else { + assert false + } + LILAC_CALLING( ch_inputs, ch_purple_out, ref_data.genome_fasta, ref_data.genome_fai, hmf_data.lilac_resources, + ref_data_hla_slice_bed, run, ) From 8c6141d1ffd32d58e9cdadbe2ca0cbebc2362b1b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 4 May 2023 17:16:47 +1000 Subject: [PATCH 152/562] Add gnomAD annotation for PAVE GRCh37 This is done in the BASH pipeline example hosted on hartwigmedical/hmftools but not in Pipeline5 v5.32. --- conf/hmfdata.config | 4 ++-- modules/local/pave/somatic/main.nf | 6 +++--- modules/local/pave/somatic/meta.yml | 2 ++ nextflow_schema.json | 8 ++++---- subworkflows/local/pave_annotation.nf | 4 ++-- subworkflows/local/prepare_reference.nf | 2 +- workflows/wgts.nf | 2 +- 7 files changed, 15 insertions(+), 13 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 0d154b1e..5ec63800 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -44,7 +44,7 @@ params { disease_ontology = 'missing/orange/201015_doid.json' driver_gene_panel = 'dna_pipeline/common/DriverGenePanel.37.tsv' ensembl_data_resources = 'dna_pipeline/common/ensembl_data/' - gnomad_pon_dir = [] + gnomad_resource = 'dna_pipeline/variants/gnomad_variants_v37.csv.gz' known_fusion_data = 'dna_pipeline/sv/known_fusion_data.37.csv' known_fusions = 'dna_pipeline/sv/known_fusions.37.bedpe' purple_germline_del = 'dna_pipeline/copy_number/cohort_germline_del_freq.37.csv' @@ -94,7 +94,7 @@ params { disease_ontology = 'missing/orange/201015_doid.json' driver_gene_panel = 'dna_pipeline/common/DriverGenePanel.38.tsv' ensembl_data_resources = 'dna_pipeline/common/ensembl_data/' - gnomad_pon_dir = 'dna_pipeline/variants/gnomad/' + gnomad_resource = 'dna_pipeline/variants/gnomad/' known_fusion_data = 'dna_pipeline/sv/known_fusion_data.38.csv' known_fusions = 'dna_pipeline/sv/known_fusions.38.bedpe' purple_germline_del = 'dna_pipeline/copy_number/cohort_germline_del_freq.38.csv' diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 7fc8dedb..394fb50f 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -13,7 +13,7 @@ process PAVE_SOMATIC { path segment_mappability path driver_gene_panel path ensembl_data_resources - path gnomad_pon_dir + path gnomad_resource output: tuple val(meta), path("*.vcf.gz") , emit: vcf @@ -29,10 +29,10 @@ process PAVE_SOMATIC { def gnomad_args if (genome_ver == '37') { pon_filters = 'HOTSPOT:10:5;PANEL:6:5;UNKNOWN:6:0' - gnomad_args = '' + gnomad_args = "-gnomad_freq_file ${gnomad_resource}" } else if (genome_ver == '38') { pon_filters = 'HOTSPOT:5:5;PANEL:2:5;UNKNOWN:2:0' - gnomad_args = "-gnomad_freq_dir \"${gnomad_pon_dir}\" -gnomad_load_chr_on_demand" + gnomad_args = "-gnomad_freq_dir ${gnomad_resource} -gnomad_load_chr_on_demand" } else { log.error "got bad genome version: ${genome_ver}" System.exit(1) diff --git a/modules/local/pave/somatic/meta.yml b/modules/local/pave/somatic/meta.yml index ce1da31c..5e88a0ab 100644 --- a/modules/local/pave/somatic/meta.yml +++ b/modules/local/pave/somatic/meta.yml @@ -49,6 +49,8 @@ input: - ensembl_data_resources: type: directory description: HMF ensembl data resources directory + - gnomad_resource: + description: gnomAD resource output: - meta: type: map diff --git a/nextflow_schema.json b/nextflow_schema.json index 0b088f37..3e87cf6f 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -435,11 +435,11 @@ "fa_icon": "far fa-folder-open", "hidden": true }, - "ref_data_gnomad_pon_dir": { + "ref_data_gnomad_resource": { "type": "string", - "format": "directory-path", - "description": "Path to HMF gnomAD PON directory.", - "fa_icon": "far fa-folder-open", + "format": "file-path", + "description": "Path to HMF gnomAD resource.", + "fa_icon": "far fa-file-code", "hidden": true }, "ref_data_known_fusion_data": { diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf index 1322d2d8..1275d9a8 100644 --- a/subworkflows/local/pave_annotation.nf +++ b/subworkflows/local/pave_annotation.nf @@ -24,7 +24,7 @@ workflow PAVE_ANNOTATION { ref_data_segment_mappability // file: /path/to/segment_mappability ref_data_driver_gene_panel // file: /path/to/driver_gene_panel ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ - ref_data_gnomad_pon_dir // file: /path/to/gnomad_pon_dir/ + ref_data_gnomad_resource // file: /path/to/gnomad_resource // Params run @@ -88,7 +88,7 @@ workflow PAVE_ANNOTATION { ref_data_segment_mappability, ref_data_driver_gene_panel, ref_data_ensembl_data_resources, - ref_data_gnomad_pon_dir, + ref_data_gnomad_resource, ) // Set outputs diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index b0916bfa..9329f334 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -196,7 +196,7 @@ def createHmfDataMap(hmf_data_path, params_only) { disease_ontology: 'ref_data_disease_ontology', driver_gene_panel: 'ref_data_driver_gene_panel', ensembl_data_resources: 'ref_data_ensembl_data_resources', - gnomad_pon_dir: 'ref_data_gnomad_pon_dir', + gnomad_resource: 'ref_data_gnomad_resource', known_fusion_data: 'ref_data_known_fusion_data', known_fusions: 'ref_data_known_fusions', purple_germline_del: 'ref_data_purple_germline_del', diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 2bd68f45..f28ddd36 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -341,7 +341,7 @@ workflow WGTS { hmf_data.segment_mappability, hmf_data.driver_gene_panel, hmf_data.ensembl_data_resources, - hmf_data.gnomad_pon_dir, + hmf_data.gnomad_resource, run, ) From 4903843c5215168b3fe16c7bd7e40fd5e22e4e2b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 5 May 2023 10:04:16 +1000 Subject: [PATCH 153/562] Update process config --- conf/base.config | 113 ++++++++++++++++++++++-------------- conf/modules.config | 137 ++++++++++++++++++-------------------------- 2 files changed, 128 insertions(+), 122 deletions(-) diff --git a/conf/base.config b/conf/base.config index 06a36de3..6a50f738 100644 --- a/conf/base.config +++ b/conf/base.config @@ -57,106 +57,135 @@ process { errorStrategy = 'retry' maxRetries = 2 } - withName:'AMBER' { + + // Process-specific requirements by name + withName: 'AMBER' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'COBALT' { + + withName: 'COBALT' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:CUSTOM_DUMPSOFTWAREVERSIONS { - cache = false - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 1.GB, 'memory' ) } + + withName: '.*:GRIDSS(?:_SVPREP)?_CALLING:(?:PREPROCESS|ASSEMBLE|CALL)' { + cpus = { check_max( 8, 'cpus' ) } + memory = { check_max( 30.GB, 'memory' ) } } - withName:'SVPREP.*' { + + withName: '.*:GRIDSS_SVPREP_CALLING:SVPREP_(?:TUMOR|NORMAL)' { memory = { check_max( 16.GB, 'memory' ) } } - withName:'SVPREP_DEPTH_ANNOTATOR' { + + withName: '.*GRIDSS_SVPREP_CALLING:DEPTH_ANNOTATOR' { memory = { check_max( 30.GB, 'memory' ) } } - withName: '.*:GRIDSS(?!_SVPREP).*' { + + withName: '.*:GRIPSS_FILTERING:(?:GERMLINE|SOMATIC)' { + cpus = { check_max( 4, 'cpus' ) } + memory = { check_max( 12.GB, 'memory' ) } + } + + withName: '.*:SAGE_CALLING:(?:GERMLINE|SOMATIC)' { cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 30.GB, 'memory' ) } + memory = { check_max( 12.GB, 'memory' ) } } - withName:'.*GRIPSS.*' { + + withName: '.*:PAVE_ANNOTATION:(?:GERMLINE|SOMATIC)' { cpus = { check_max( 4, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName: 'LILAC_PROCESS' { - cpus = { check_max( 4, 'cpus' ) } + + withName: 'PURPLE' { + cpus = { check_max( 2, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName: '.*LILAC:CUSTOM_REALIGNREADS' { + + withName: '.*:LINX_ANNOTATION:(?:GERMLINE|SOMATIC)' { cpus = { check_max( 4, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName: '.*LILAC:CUSTOM_SLICE' { + + withName: '.*:LINX_PLOTTING:VISUALISER' { cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 6.GB, 'memory' ) } + memory = { check_max( 12.GB, 'memory' ) } } - withName: '.*LILAC:CUSTOM_EXTRACTCONTIG' { + + withName: '.*:LINX_PLOTTING:GPGR' { cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 6.GB, 'memory' ) } + memory = { check_max( 12.GB, 'memory' ) } } - withName:'.*LINX:.*' { + + withName: 'BAMTOOLS' { cpus = { check_max( 4, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'GPGR_LINX' { - memory = { check_max( 12.GB, 'memory' ) } + + withName: 'CHORD' { + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 4.GB, 'memory' ) } } - withName:'.*PAVE.*' { + + withName: 'LILAC' { cpus = { check_max( 4, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'PURPLE' { - cpus = { check_max( 2, 'cpus' ) } + + withName: '.*:LILAC_CALLING:CUSTOM_REALIGNREADS' { + cpus = { check_max( 4, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'.*SAGE.*' { + + withName: '.*:LILAC_CALLING:CUSTOM_SLICE' { cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } + memory = { check_max( 6.GB, 'memory' ) } } - withName:'SIGS' { + + withName: '.*:LILAC_CALLING:CUSTOM_EXTRACTCONTIG' { cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 4.GB, 'memory' ) } + memory = { check_max( 6.GB, 'memory' ) } } - withName:'CHORD' { + + withName: 'SIGS' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 4.GB, 'memory' ) } } - withName:'CUSTOM_SLICE' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - withName:'VIRUSBREAKEND' { + + withName: 'VIRUSBREAKEND' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 60.GB, 'memory' ) } } - withName:'VIRUSINTERPRETER' { + + withName: 'VIRUSINTERPRETER' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'ISOFOX' { + + withName: 'ISOFOX' { cpus = { check_max( 8, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'CUPPA.*' { + + withName: 'CUPPA' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'PEACH' { + + withName: 'SAMTOOLS_FLAGSTAT' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'PROTECT' { + + withName: 'ORANGE' { cpus = { check_max( 1, 'cpus' ) } memory = { check_max( 12.GB, 'memory' ) } } - withName:'ORANGE' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } + + withName: 'CUSTOM_DUMPSOFTWAREVERSIONS' { + cache = false + cpus = { check_max( 1, 'cpus' ) } + memory = { check_max( 1.GB, 'memory' ) } } + } diff --git a/conf/modules.config b/conf/modules.config index d44cb941..4cae6f49 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -11,6 +11,7 @@ */ process { + withName: 'AMBER' { ext.jarPath = '/opt/conda/share/hmftools-amber-3.9-1/amber.jar' publishDir = [ @@ -29,24 +30,16 @@ process { ] } - withName: 'CUSTOM_DUMPSOFTWAREVERSIONS' { - publishDir = [ - path: { "${params.outdir}/pipeline_info" }, - mode: params.publish_dir_mode, - pattern: '*_versions.yml', - ] - } - - withName:'.*:(? filename.equals('versions.yml') ? null : "${meta.id}/${filename}" } + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/germline/${filename}" }, ] } - withName: '.*LINX:.*' { - ext.jarPath = '/opt/linx/linx.jar' - } - - withName: '.*LINX_GERMLINE' { + withName: '.*:SAGE_CALLING:SOMATIC' { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/germline_annotations/" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/somatic/${filename}" }, ] } - withName: '.*LINX_SOMATIC' { + withName: '.*:PAVE_ANNOTATION:(?:GERMLINE|SOMATIC)' { + ext.jarPath = '/opt/pave/pave.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/somatic_annotations/" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/pave/${filename}" }, ] } - withName: '.*LINX:LINX_VISUALISER' { - ext.path_circos = 'circos' + withName: 'PURPLE' { + ext.jarPath = '/opt/purple/purple.jar' + ext.circosPath = 'circos' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/somatic_plots/" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, ] } - withName: 'GPGR_LINX' { + withName: '.*:LINX_ANNOTATION:(?:GERMLINE|SOMATIC)' { + ext.jarPath = '/opt/linx/linx.jar' + } + + withName: '.*:LINX_ANNOTATION:GERMLINE' { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/germline_annotations/" }, ] } - withName: 'PAVE.*' { - ext.jarPath = '/opt/pave/pave.jar' + withName: '.*:LINX_ANNOTATION:SOMATIC' { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/pave/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/somatic_annotations/" }, ] } - withName: 'BAMTOOLS' { - ext.jarPath = '/opt/bamtools/bamtools.jar' + withName: '.*:LINX_PLOTTING:VISUALISER' { + ext.path_circos = 'circos' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/bamtools/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/somatic_plots/" }, ] } - withName: 'PURPLE' { - ext.jarPath = '/opt/purple/purple.jar' - ext.circosPath = 'circos' + withName: '.*:LINX_PLOTTING:GPGR' { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } - withName: 'SAGE_GERMLINE' { - ext.jarPath = '/opt/sage/sage.jar' + withName: 'BAMTOOLS' { + ext.jarPath = '/opt/bamtools/bamtools.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/germline/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/bamtools/${filename}" }, ] } - withName: 'SAGE_SOMATIC' { - ext.jarPath = '/opt/sage/sage.jar' + withName: 'CHORD' { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/somatic/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/chord/${filename}" }, ] } - withName: 'SIGS' { - ext.jarPath = '/opt/sigs/sigs.jar' + withName: 'LILAC' { + ext.jarPath = '/opt/lilac/lilac.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" } ] } - withName: 'CHORD' { + withName: 'SIGS' { + ext.jarPath = '/opt/sigs/sigs.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/chord/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, ] } @@ -226,18 +221,9 @@ process { ] } - withName: 'CUPPA_CLASSIFIER' { + withName: 'CUPPA' { ext.jarPath = '/opt/cuppa/cuppa.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/cuppa/${filename}" }, - ] - } - - withName: 'CUPPA_VISUALISER' { ext.chartScriptPath = '/opt/cuppa/chart/cuppa-chart.py' - ext.reportScriptPath = '/opt/cuppa/report/CupGenerateReport_pipeline.R' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -245,21 +231,14 @@ process { ] } - withName: 'PROTECT' { - ext.jarPath = '/opt/protect/protect.jar' - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/protect/${filename}" }, - ] - } - - withName: 'PEACH' { - ext.scriptPath = '/opt/peach/src/main.py' + withName: 'SAMTOOLS_FLAGSTAT' { + container = { "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.12--h9aed4be_1' : + 'quay.io/biocontainers/samtools:1.12--h9aed4be_1' }" } publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/peach/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/flagstats/${filename}" }, ] } @@ -272,14 +251,12 @@ process { ] } - withName: 'SAMTOOLS_FLAGSTAT' { - container = { "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.12--h9aed4be_1' : - 'quay.io/biocontainers/samtools:1.12--h9aed4be_1' }" } + withName: 'CUSTOM_DUMPSOFTWAREVERSIONS' { publishDir = [ - path: { "${params.outdir}" }, + path: { "${params.outdir}/pipeline_info" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/flagstats/${filename}" }, + pattern: '*_versions.yml', ] } + } From 943838fcd1188a8db6382952532f0170b44e5633 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 10 May 2023 12:35:58 +1000 Subject: [PATCH 154/562] Various fixes, to be sorted --- conf/hmfdata.config | 2 +- conf/modules.config | 6 ++--- modules/local/bamtools/main.nf | 2 +- modules/local/cuppa/main.nf | 23 +++++++++-------- modules/local/gpgr/linx/main.nf | 4 +-- modules/local/linx/germline/main.nf | 2 +- modules/local/orange/main.nf | 25 ++++++++++--------- modules/local/purple/main.nf | 4 +-- modules/local/sage/germline/main.nf | 2 -- modules/local/sage/somatic/main.nf | 2 -- modules/local/svprep/Dockerfile | 2 +- modules/local/svprep/svprep/main.nf | 2 +- .../templates/dumpsoftwareversions.py | 20 +++------------ subworkflows/local/lilac_calling.nf | 12 ++++++--- subworkflows/local/linx_annotation.nf | 1 + subworkflows/local/prepare_input.nf | 4 +-- 16 files changed, 54 insertions(+), 59 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 5ec63800..49cdaf3e 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -81,7 +81,7 @@ params { sage_blocklist_sites = 'dna_pipeline/variants/KnownBlacklist.germline.38.vcf.gz' sage_actionable_panel = 'dna_pipeline/variants/ActionableCodingPanel.38.bed.gz' sage_coverage_panel = 'dna_pipeline/variants/CoverageCodingPanel.38.bed.gz' - sage_highconf_regions = 'dna_pipeline/variants/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticde' + sage_highconf_regions = 'dna_pipeline/variants/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz' sage_known_hotspots_germline = 'dna_pipeline/variants/KnownHotspots.germline.38.vcf.gz' sage_known_hotspots_somatic = 'dna_pipeline/variants/KnownHotspots.somatic.38.vcf.gz' sage_pon = 'dna_pipeline/variants/SageGermlinePon.98x.38.tsv.gz' diff --git a/conf/modules.config b/conf/modules.config index 4cae6f49..bc7b5765 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -30,7 +30,7 @@ process { ] } - withName: '.*:GRIDSS_SVPREP_CALLING:(?:DEPTH_ANNOTATOR|SVPREP)' { + withName: '.*:GRIDSS_SVPREP_CALLING:(?:DEPTH_ANNOTATOR|SVPREP_TUMOR|SVPREP_NORMAL)' { ext.jarPath = '/opt/svprep/svprep.jar' } @@ -122,7 +122,7 @@ process { ] } - withName: '.*:LINX_ANNOTATION:(?:GERMLINE|SOMATIC)' { + withName: '.*:LINX_ANNOTATION:(?:GERMLINE|SOMATIC)|.*:LINX_PLOTTING:VISUALISER' { ext.jarPath = '/opt/linx/linx.jar' } @@ -227,7 +227,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/cuppa/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf index efa073a2..c0cd0dc3 100644 --- a/modules/local/bamtools/main.nf +++ b/modules/local/bamtools/main.nf @@ -35,7 +35,7 @@ process BAMTOOLS { cat <<-END_VERSIONS > versions.yml "${task.process}": - bamtools: \$(java -jar bam-tools_v1.0.jar 2>&1 | sed -n '1s/^.*BamTools version: //p') + bamtools: \$(java -jar ${task.ext.jarPath} 2>&1 | sed -n '1s/^.*BamTools version: //p') END_VERSIONS """ diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index 66c24599..bec647a4 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -7,7 +7,7 @@ process CUPPA { input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter) val ref_genome_ver - path cuppa_resources + path cuppa_resources, stageAs: 'cuppa_reference_data' output: tuple val(meta), path('cuppa/'), emit: cuppa_dir @@ -40,14 +40,14 @@ process CUPPA { # Symlink input files into a single directory mkdir -p sample_data/ if [[ ${categories_val} == 'DNA' || ${categories_val} == 'ALL' ]]; then - find -L ${purple_dir} ${linx_dir} ${virusinterpreter} -mindepth 1 -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; + find -L ${purple_dir} ${linx_dir} ${virusinterpreter} -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; fi if [[ ${categories_val} == 'RNA' ]]; then - find -L ${isofox_dir} -mindepth 1 -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; + find -L ${isofox_dir} -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; elif [[ ${categories_val} == 'ALL' ]]; then # NOTE(SW): CUPPA requires that the WTS sample name matches the WGS sample name - for fp in \$(find -L ${isofox_dir} -mindepth 1 -maxdepth 1 -type f); do + for fp in \$(find -L ${isofox_dir} -maxdepth 1 -type f); do fn_out=\$(sed 's/^${meta.id_wts}/${meta.id}/' <<< \${fp##*/}); cp \${fp} sample_data/\${fn_out} done; @@ -55,6 +55,8 @@ process CUPPA { sed -i 's/^${meta.id_wts}/${meta.id}/g' sample_data/${meta.id}.isf.summary.csv fi; + mkdir -p cuppa/ + java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ @@ -80,12 +82,13 @@ process CUPPA { stub: """ - touch ${meta.id}.cup.data.csv - touch ${meta.id}.cuppa.conclusion.txt - touch ${meta.id}_cup_report.pdf - touch ${meta.id}.cup.report.summary.png - touch ${meta.id}.cup.report.features.png - touch ${meta.id}.cuppa.chart.png + mkdir -p cuppa/ + touch cuppa/${meta.id}.cup.data.csv + touch cuppa/${meta.id}.cuppa.conclusion.txt + touch cuppa/${meta.id}_cup_report.pdf + touch cuppa/${meta.id}.cup.report.summary.png + touch cuppa/${meta.id}.cup.report.features.png + touch cuppa/${meta.id}.cuppa.chart.png echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/gpgr/linx/main.nf b/modules/local/gpgr/linx/main.nf index e96d11d5..fd6a7ea3 100644 --- a/modules/local/gpgr/linx/main.nf +++ b/modules/local/gpgr/linx/main.nf @@ -2,7 +2,7 @@ process GPGR_LINX { tag "${meta.id}" label 'process_single' - container 'ghcr.io/umccr/gpgr:1.4.1' + container 'docker.io/scwatts/gpgr:1.4.3' input: tuple val(meta), path(linx_annotation), path(linx_visualiser) @@ -23,7 +23,7 @@ process GPGR_LINX { --sample ${meta.id} \\ --plot ${linx_visualiser}/ \\ --table ${linx_annotation}/ \\ - --out ${meta.id}_linx.html; + --out ${meta.id}_linx.html cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 709d3266..3b9c2951 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -26,7 +26,7 @@ process LINX_GERMLINE { -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.id} \\ - -sv_vcf ${purple_dir}/${meta.id}.purple.sv.germline.vcf.gz \\ + -sv_vcf ${sv_vcf} \\ -germline \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 7739c5d3..99e843e0 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -5,7 +5,7 @@ process ORANGE { container 'docker.io/scwatts/orange:2.3--0' input: - tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter), path(chord_prediction), path(sigs_tsv), path(lilac_dir), path(cuppa_dir), path(isofox_dir) + tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter), path(chord_prediction), path(sigs_dir), path(lilac_dir), path(cuppa_dir), path(isofox_dir) val genome_ver path disease_ontology path cohort_mapping @@ -31,23 +31,22 @@ process ORANGE { def virusinterpreter_arg = virusinterpreter ? "-annotated_virus_tsv ${virusinterpreter}" : '' def chord_arg = chord_prediction ? "-chord_prediction_txt ${chord_prediction}" : '' - def sigs_arg = sigs_tsv ? "-sigs_allocation_tsv ${sigs_tsv}" : '' + def sigs_arg = sigs_tsv ? "-sigs_allocation_tsv ${sigs_dir}/${meta.tumor_wgs_id}.sig.allocation.tsv" : '' def cuppa_csv_arg = cuppa_dir ? "-cuppa_result_csv ${cuppa_dir}/${meta.tumor_wgs_id}.cup.data.csv" : '' - def cuppa_feature_arg = cuppa_dir ? "-cuppa_feature_plot ${cuppa_dir}/${meta.tumor_wgs_id}.cup.report.features.png" : '' def cuppa_summary_arg = cuppa_dir ? "-cuppa_summary_plot ${cuppa_dir}/${meta.tumor_wgs_id}.cup.report.summary.png" : '' def normal_id_arg = meta.containsKey('normal_wgs_id') ? "-reference_sample_id ${meta.normal_wgs_id}" : '' def normal_metrics_arg = bam_metrics_germline ? "-ref_sample_wgs_metrics_file ${bam_metrics_germline}" : '' def normal_flagstat_arg = flagstat_germline ? "-ref_sample_flagstat_file ${flagstat_germline}" : '' - def normal_sage_somatic_bqr_arg = sage_somatic_normal_bqr ? "-sage_somatic_ref_sample_bqr_plot ${sage_somatic_normal_bqr}" : '' + def normal_sage_somatic_bqr_arg = sage_germline_bqr ? "-sage_somatic_ref_sample_bqr_plot ${sage_germline_bqr}" : '' def normal_sage_coverage_arg = sage_germline_coverage ? "-sage_germline_gene_coverage_tsv ${sage_germline_coverage}" : '' def normal_linx_arg = linx_germline_anno_dir ? "-linx_germline_data_directory ${linx_germline_anno_dir}" : '' - def rna_id_arg = meta.containsKey('tumor_wts_id') ? "-reference_sample_id ${meta.tumor_wts_id}" : '' + def rna_id_arg = meta.containsKey('tumor_wts_id') ? "-rna_sample_id ${meta.tumor_wts_id}" : '' def isofox_summary_csv_arg = isofox_dir ? "-isofox_summary_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.summary.csv" : '' - def isofox_gene_csv_arg = isofox_dir ? "-isofox_summary_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.gene_data.csv" : '' - def isofox_fusion_csv_arg = isofox_dir ? "-isofox_gene_data_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.fusions.csv" : '' - def isofox_alt_sj_csv_arg = isofox_dir ? "-isofox_fusion_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.alt_splice_junc.csv" : '' + def isofox_gene_csv_arg = isofox_dir ? "-isofox_gene_data_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.gene_data.csv" : '' + def isofox_fusion_csv_arg = isofox_dir ? "-isofox_fusion_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.fusions.csv" : '' + def isofox_alt_sj_csv_arg = isofox_dir ? "-isofox_alt_splice_junction_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.alt_splice_junc.csv" : '' def isofox_gene_distribution_arg = isofox_gene_distribution ? "-isofox_gene_distribution_csv ${isofox_gene_distribution}" : '' def isofox_alt_sj_arg = isofox_alt_sj ? "-isofox_alt_sj_cohort_csv ${isofox_alt_sj}" : '' @@ -55,19 +54,22 @@ process ORANGE { """ echo "${pipeline_version_str}" > pipeline_version.txt + # NOTE(SW): '--add-opens java.base/java.time=ALL-UNNAMED' resolves issue writing JSON, see: + # https://stackoverflow.com/questions/70412805/what-does-this-error-mean-java-lang-reflect-inaccessibleobjectexception-unable/70878195#70878195 + java \\ + --add-opens java.base/java.time=ALL-UNNAMED \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ \\ -experiment_date \$(date +%y%m%d) \\ -pipeline_version_file pipeline_version.txt \\ - -add_disclaimer \\ \\ -tumor_sample_id ${meta.tumor_wgs_id} \\ -primary_tumor_doids "" \\ -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ -tumor_sample_flagstat_file ${flagstat_somatic} \\ - -sage_somatic_tumor_sample_bqr_plot ${sage_somatic_tumor_bqr} \\ + -sage_somatic_tumor_sample_bqr_plot ${sage_somatic_bqr} \\ -purple_data_directory ${purple_dir} \\ -purple_plot_directory ${purple_dir}/plot/ \\ -linx_somatic_data_directory ${linx_somatic_anno_dir} \\ @@ -76,9 +78,8 @@ process ORANGE { -lilac_qc_csv ${lilac_dir}/${meta.tumor_wgs_id}.lilac.qc.csv \\ ${virusinterpreter_arg} \\ ${chord_arg} \\ - ${sigs_tsv} \\ + ${sigs_arg} \\ ${cuppa_csv_arg} \\ - ${cuppa_feature_arg} \\ ${cuppa_summary_arg} \\ \\ ${normal_id_arg} \\ diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index d8dc7cf7..5a1e4067 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -61,8 +61,8 @@ process PURPLE { -reference ${meta.normal_id} \\ -amber ${amber} \\ -cobalt ${cobalt} \\ - ${sv_tumor_vcf} \\ - ${sv_normal_vcf} \\ + ${sv_tumor_vcf_arg} \\ + ${sv_normal_vcf_arg} \\ ${sv_tumor_recovery_vcf_arg} \\ \${smlv_tumor_vcf_arg} \\ \${smlv_normal_vcf_arg} \\ diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 05a6507e..61af8e15 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -69,8 +69,6 @@ process SAGE_GERMLINE { -out ./${meta.tumor_id}.sage.germline.vcf.gz bcftools view -f 'PASS' -o ${meta.tumor_id}.sage.germline.filtered.vcf.gz ${meta.tumor_id}.sage.germline.vcf.gz - - bcftools index -t ${meta.tumor_id}.sage.germline.vcf.gz bcftools index -t ${meta.tumor_id}.sage.germline.filtered.vcf.gz cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index e0018cea..7c024955 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -54,8 +54,6 @@ process SAGE_SOMATIC { -out ./${meta.tumor_id}.sage.somatic.vcf.gz bcftools view -f 'PASS' -o ${meta.tumor_id}.sage.somatic.filtered.vcf.gz ${meta.tumor_id}.sage.somatic.vcf.gz - - bcftools index -t ${meta.tumor_id}.sage.somatic.vcf.gz bcftools index -t ${meta.tumor_id}.sage.somatic.filtered.vcf.gz cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile index 8c2b669d..d3337b83 100644 --- a/modules/local/svprep/Dockerfile +++ b/modules/local/svprep/Dockerfile @@ -16,7 +16,7 @@ RUN \ COPY assets/gridss_svprep.patch /tmp/ RUN \ - patch -lp1 -d /opt/svprep/ /tmp/gridss_svprep.patch && \ + patch -lp1 -i /tmp/gridss_svprep.patch /opt/svprep/gridss_svprep && \ chmod 755 /opt/svprep/gridss_svprep && \ ln -s /opt/svprep/gridss_svprep /usr/local/bin/ diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index faa545fd..274974dc 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -43,7 +43,7 @@ process SVPREP { samtools sort \\ -@ ${task.cpus} \\ - -m ${min(Math.round(task.memory.mega * 0.95), 4096)}K \\ + -m ${Math.min(Math.round(task.memory.mega * 0.95), 4096)}K \\ -T ${meta.id}.sv_prep.tmp \\ -o ${meta.id}.sv_prep.sorted.bam \\ ${meta.id}.sv_prep.bam diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py index d1390392..ad395862 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -53,20 +53,7 @@ def _make_versions_html(versions): with open("$versions") as f: versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module -# aggregate versions by the module name (derived from fully-qualified process name) -versions_by_module = {} -for process, process_versions in versions_by_process.items(): - module = process.split(":")[-1] - try: - assert versions_by_module[module] == process_versions, ( - "We assume that software versions are the same between all modules. " - "If you see this error-message it means you discovered an edge-case " - "and should open an issue in nf-core/tools. " - ) - except KeyError: - versions_by_module[module] = process_versions - -versions_by_module["Workflow"] = { +versions_by_process["Workflow"] = { "Nextflow": "$workflow.nextflow.version", "$workflow.manifest.name": "$workflow.manifest.version", } @@ -77,11 +64,12 @@ def _make_versions_html(versions): "section_href": "https://github.com/${workflow.manifest.name}", "plot_type": "html", "description": "are collected at run time from the software output.", - "data": _make_versions_html(versions_by_module), + "data": _make_versions_html(versions_by_process), } with open("software_versions.yml", "w") as f: - yaml.dump(versions_by_module, f, default_flow_style=False) + yaml.dump(versions_by_process, f, default_flow_style=False) + with open("software_versions_mqc.yml", "w") as f: yaml.dump(versions_mqc, f, default_flow_style=False) diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index 85383570..7fb3ac5c 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -118,16 +118,22 @@ workflow LILAC_CALLING { ) ch_versions = ch_versions.mix(CUSTOM_EXTRACTCONTIG.out.versions) + ch_slice_bams = CUSTOM_SLICE.out.bam + .branch { meta_lilac, bam, bai -> + def sequence_type = Utils.getEnumFromString(meta_lilac.sequence_type_str, Constants.SequenceType) + wgs: sequence_type == Constants.SequenceType.WGS + wts: sequence_type == Constants.SequenceType.WTS + } + CUSTOM_REALIGNREADS( - CUSTOM_SLICE.out.bam, + ch_slice_bams.wgs, CUSTOM_EXTRACTCONTIG.out.contig, CUSTOM_EXTRACTCONTIG.out.bwa_indices, ) - ch_slices_out = CUSTOM_REALIGNREADS.out.bam + ch_slices_out = Channel.empty().mix(CUSTOM_REALIGNREADS.out.bam, ch_slice_bams.wts) ch_versions = ch_versions.mix(CUSTOM_REALIGNREADS.out.versions) } - // Re-replicate and flow expected file count into meta // channel: [val(meta_lilac), [sequence_type_str, sample_type_str, bam, bai]] ch_slices_out_individual = ch_slices_out diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf index d4121e36..1ccc1a8f 100644 --- a/subworkflows/local/linx_annotation.nf +++ b/subworkflows/local/linx_annotation.nf @@ -50,6 +50,7 @@ workflow LINX_ANNOTATION { return [meta_linx, sv_vcf] } + .filter { it != Constants.META_PLACEHOLDER } // channel: [val(meta_linx), purple_dir] ch_linx_inputs_somatic = ch_linx_inputs_source diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf index a63ea438..c1685d90 100644 --- a/subworkflows/local/prepare_input.nf +++ b/subworkflows/local/prepare_input.nf @@ -65,8 +65,8 @@ workflow PREPARE_INPUT { def filetype_tbi = [ Constants.FileType.GRIDSS_VCF, - Constants.FileType.GRIPSS_HARD_VCF, - Constants.FileType.GRIPSS_SOFT_VCF, + Constants.FileType.GRIPSS_VCF, + Constants.FileType.GRIPSS_UNFILTERED_VCF, ] def index_ext From dcc231b5692e68d32965010f9118b63b95323845 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 10 May 2023 12:36:53 +1000 Subject: [PATCH 155/562] Remove process-specific resource config --- conf/base.config | 131 ----------------------------------------------- 1 file changed, 131 deletions(-) diff --git a/conf/base.config b/conf/base.config index 6a50f738..612497db 100644 --- a/conf/base.config +++ b/conf/base.config @@ -57,135 +57,4 @@ process { errorStrategy = 'retry' maxRetries = 2 } - - // Process-specific requirements by name - withName: 'AMBER' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: 'COBALT' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: '.*:GRIDSS(?:_SVPREP)?_CALLING:(?:PREPROCESS|ASSEMBLE|CALL)' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 30.GB, 'memory' ) } - } - - withName: '.*:GRIDSS_SVPREP_CALLING:SVPREP_(?:TUMOR|NORMAL)' { - memory = { check_max( 16.GB, 'memory' ) } - } - - withName: '.*GRIDSS_SVPREP_CALLING:DEPTH_ANNOTATOR' { - memory = { check_max( 30.GB, 'memory' ) } - } - - withName: '.*:GRIPSS_FILTERING:(?:GERMLINE|SOMATIC)' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: '.*:SAGE_CALLING:(?:GERMLINE|SOMATIC)' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: '.*:PAVE_ANNOTATION:(?:GERMLINE|SOMATIC)' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: 'PURPLE' { - cpus = { check_max( 2, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: '.*:LINX_ANNOTATION:(?:GERMLINE|SOMATIC)' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: '.*:LINX_PLOTTING:VISUALISER' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: '.*:LINX_PLOTTING:GPGR' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: 'BAMTOOLS' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: 'CHORD' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 4.GB, 'memory' ) } - } - - withName: 'LILAC' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: '.*:LILAC_CALLING:CUSTOM_REALIGNREADS' { - cpus = { check_max( 4, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: '.*:LILAC_CALLING:CUSTOM_SLICE' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 6.GB, 'memory' ) } - } - - withName: '.*:LILAC_CALLING:CUSTOM_EXTRACTCONTIG' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 6.GB, 'memory' ) } - } - - withName: 'SIGS' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 4.GB, 'memory' ) } - } - - withName: 'VIRUSBREAKEND' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 60.GB, 'memory' ) } - } - - withName: 'VIRUSINTERPRETER' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: 'ISOFOX' { - cpus = { check_max( 8, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: 'CUPPA' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: 'SAMTOOLS_FLAGSTAT' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: 'ORANGE' { - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 12.GB, 'memory' ) } - } - - withName: 'CUSTOM_DUMPSOFTWAREVERSIONS' { - cache = false - cpus = { check_max( 1, 'cpus' ) } - memory = { check_max( 1.GB, 'memory' ) } - } - } From 77a01254ec2b6d7cf56cc632c520226db56417e8 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 12 May 2023 16:39:49 +1000 Subject: [PATCH 156/562] Process LINX germline inputs for ORANGE --- modules/local/orange/main.nf | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 99e843e0..0a6ca89b 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -40,7 +40,8 @@ process ORANGE { def normal_flagstat_arg = flagstat_germline ? "-ref_sample_flagstat_file ${flagstat_germline}" : '' def normal_sage_somatic_bqr_arg = sage_germline_bqr ? "-sage_somatic_ref_sample_bqr_plot ${sage_germline_bqr}" : '' def normal_sage_coverage_arg = sage_germline_coverage ? "-sage_germline_gene_coverage_tsv ${sage_germline_coverage}" : '' - def normal_linx_arg = linx_germline_anno_dir ? "-linx_germline_data_directory ${linx_germline_anno_dir}" : '' + // NOTE(SW): LINX germline outputs are processed below to contain tumor id in the filename as required by ORANGE + def normal_linx_arg = linx_germline_anno_dir ? "-linx_germline_data_directory normal_linx__prepared/" : '' def rna_id_arg = meta.containsKey('tumor_wts_id') ? "-rna_sample_id ${meta.tumor_wts_id}" : '' def isofox_summary_csv_arg = isofox_dir ? "-isofox_summary_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.summary.csv" : '' @@ -54,6 +55,14 @@ process ORANGE { """ echo "${pipeline_version_str}" > pipeline_version.txt + if [[ -n "${normal_linx_arg}" ]]; then + mkdir -p normal_linx__prepared/; + for fp in ${linx_germline_anno_dir}/*; do + fn=\${fp##*/}; + ln -s ../${linx_germline_anno_dir}/\${fn} normal_linx__prepared/\$(sed 's/${meta.normal_wgs_id}/${meta.tumor_wgs_id}/' <<< \${fn}); + done; + fi + # NOTE(SW): '--add-opens java.base/java.time=ALL-UNNAMED' resolves issue writing JSON, see: # https://stackoverflow.com/questions/70412805/what-does-this-error-mean-java-lang-reflect-inaccessibleobjectexception-unable/70878195#70878195 From 1833e1e264b6215dca4dcbae0f3e2d656103aff7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 12 May 2023 16:40:06 +1000 Subject: [PATCH 157/562] Disable WTS in ORANGE --- modules/local/orange/main.nf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 0a6ca89b..50dcdca8 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -98,11 +98,11 @@ process ORANGE { ${normal_sage_coverage_arg} \\ ${normal_linx_arg} \\ \\ - ${rna_id_arg} \\ - ${isofox_summary_csv_arg} \\ - ${isofox_gene_csv_arg} \\ - ${isofox_fusion_csv_arg} \\ - ${isofox_alt_sj_csv_arg} \\ + \\ #${rna_id_arg} \\ + \\ #${isofox_summary_csv_arg} \\ + \\ #${isofox_gene_csv_arg} \\ + \\ #${isofox_fusion_csv_arg} \\ + \\ #${isofox_alt_sj_csv_arg} \\ \\ -ref_genome_version ${genome_ver} \\ -doid_json ${disease_ontology} \\ From b400808cf275eeb1c429482a7ed4b1a893207a88 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 12 May 2023 21:03:36 +1000 Subject: [PATCH 158/562] Correct Sigs input variable names --- lib/Constants.groovy | 4 ++-- modules/local/orange/main.nf | 2 +- subworkflows/local/orange_reporting.nf | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index bfd5f716..68b5bd13 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -63,7 +63,7 @@ class Constants { VIRUSINTERPRETER_TSV, // ORANGE specific CHORD_PREDICTION, - SIGS, + SIGS_DIR, CUPPA_DIR, FLAGSTAT, LINX_PLOT_DIR, @@ -120,7 +120,7 @@ class Constants { LINX_ANNO_DIR_NORMAL: [FileType.LINX_ANNO_DIR, SampleType.NORMAL, SequenceType.WGS], CHORD_PREDICTION: [FileType.CHORD_PREDICTION, SampleType.TUMOR, SequenceType.WGS], - SIGS: [FileType.SIGS, SampleType.TUMOR, SequenceType.WGS], + SIGS_DIR: [FileType.SIGS_DIR, SampleType.TUMOR, SequenceType.WGS], LILAC_DIR: [FileType.LILAC_DIR, SampleType.NORMAL, SequenceType.WGS], VIRUSINTERPRETER_TSV: [FileType.VIRUSINTERPRETER_TSV, SampleType.TUMOR, SequenceType.WGS], diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 50dcdca8..8dc35e90 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -31,7 +31,7 @@ process ORANGE { def virusinterpreter_arg = virusinterpreter ? "-annotated_virus_tsv ${virusinterpreter}" : '' def chord_arg = chord_prediction ? "-chord_prediction_txt ${chord_prediction}" : '' - def sigs_arg = sigs_tsv ? "-sigs_allocation_tsv ${sigs_dir}/${meta.tumor_wgs_id}.sig.allocation.tsv" : '' + def sigs_arg = sigs_dir ? "-sigs_allocation_tsv ${sigs_dir}/${meta.tumor_wgs_id}.sig.allocation.tsv" : '' def cuppa_csv_arg = cuppa_dir ? "-cuppa_result_csv ${cuppa_dir}/${meta.tumor_wgs_id}.cup.data.csv" : '' def cuppa_summary_arg = cuppa_dir ? "-cuppa_summary_plot ${cuppa_dir}/${meta.tumor_wgs_id}.cup.report.summary.png" : '' diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 0f9ad1bc..d060528d 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -87,7 +87,7 @@ workflow ORANGE_REPORTING { run.linx ? ch_linx_germline_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_NORMAL, type: 'optional'), run.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), run.chord ? ch_chord : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_PREDICITION, type: 'optional'), - run.sigs ? ch_sigs : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SIGS, type: 'optional'), + run.sigs ? ch_sigs : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SIGS_DIR, type: 'optional'), run.lilac ? ch_lilac : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), run.cuppa ? ch_cuppa : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_DIR, type: 'optional'), run.isofox ? ch_isofox : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional'), From 6b486fa893a5fcd8ef7f7b72c56d16ab18e120aa Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 12 May 2023 22:45:48 +1000 Subject: [PATCH 159/562] Place ORANGE outputs in subdirectory --- conf/modules.config | 10 +++++++++- modules/local/orange/main.nf | 8 ++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index bc7b5765..9f0633da 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -247,7 +247,15 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/orange/${filename}" }, + // NOTE(SW): java.io.File and Nextflow's file do not work here, resorting to string splitting + saveAs: { filename -> + if (filename.equals('versions.yml')) { + return null + } else { + def tokens = filename.split('[/]') + return "${meta.id}/orange/${tokens[-1]}" + } + } ] } diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 8dc35e90..5a3b8f23 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -18,9 +18,9 @@ process ORANGE { val pipeline_version output: - tuple val(meta), path('*.orange.pdf') , emit: pdf - tuple val(meta), path('*.orange.json'), emit: json - path 'versions.yml' , emit: versions + tuple val(meta), path('output/*.orange.pdf') , emit: pdf + tuple val(meta), path('output/*.orange.json'), emit: json + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -113,7 +113,7 @@ process ORANGE { -ensembl_data_directory ${ensembl_data_resources} \\ ${isofox_gene_distribution_arg} \\ ${isofox_alt_sj_arg} \\ - -output_dir ./ + -output_dir ./output/ cat <<-END_VERSIONS > versions.yml "${task.process}": From 598d338b722cf6dd9befca8c27a03b7e895c52d9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 13 May 2023 11:47:10 +1000 Subject: [PATCH 160/562] Move the gpgr LINX report to the linx output dir --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 9f0633da..f975c83f 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -155,7 +155,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/${filename}" }, ] } From 1ffb8419a2d7d2141ef43a85cd92b7eeca2e6f6c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 14 May 2023 21:57:45 +1000 Subject: [PATCH 161/562] Fix meta placeholder filtering --- subworkflows/local/chord_prediction.nf | 2 +- subworkflows/local/sigs_fitting.nf | 2 +- subworkflows/local/virusbreakend_calling.nf | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/chord_prediction.nf b/subworkflows/local/chord_prediction.nf index 15cde711..7ea60f17 100644 --- a/subworkflows/local/chord_prediction.nf +++ b/subworkflows/local/chord_prediction.nf @@ -46,7 +46,7 @@ workflow CHORD_PREDICTION { def meta_chord = [key: meta.id, id: meta.id] return [meta_chord, smlv_vcf, sv_vcf] } - .filter { it[0] != Constants.META_PLACEHOLDER } + .filter { it != Constants.META_PLACEHOLDER } // Run process CHORD( diff --git a/subworkflows/local/sigs_fitting.nf b/subworkflows/local/sigs_fitting.nf index d48473f0..b81b4f26 100644 --- a/subworkflows/local/sigs_fitting.nf +++ b/subworkflows/local/sigs_fitting.nf @@ -50,7 +50,7 @@ workflow SIGS_FITTING { ] return [meta_sigs, smlv_vcf] } - .filter { it[0] != Constants.META_PLACEHOLDER } + .filter { it != Constants.META_PLACEHOLDER } SIGS( ch_sigs_inputs, diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index 7ca3d4b1..5d27d503 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -86,6 +86,7 @@ workflow VIRUSBREAKEND_CALLING { } return [meta, purple_purity, purple_qc] } + .filter { it != Constants.META_PLACEHOLDER } // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( From 526ede7307cfbc978e40991541b6e179a561d6d6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 14 May 2023 22:12:34 +1000 Subject: [PATCH 162/562] Fix ORANGE stub --- modules/local/orange/main.nf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 5a3b8f23..9eb55ba7 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -123,8 +123,9 @@ process ORANGE { stub: """ - touch "${meta.tumor_wgs_id}.orange.json" - touch "${meta.tumor_wgs_id}.orange.pdf" + mkdir -p output/ + touch output/${meta.tumor_wgs_id}.orange.json + touch output/${meta.tumor_wgs_id}.orange.pdf echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } From 443f652bd48f491de5b4d7fac85e7c31cc62d091 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 14 May 2023 22:30:17 +1000 Subject: [PATCH 163/562] Update default HMF data paths --- lib/Constants.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 68b5bd13..f071c286 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -9,8 +9,8 @@ class Constants { static List GENOMES_DEFINED = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 - static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.31_37_0.0.1.tar.gz' - static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32+dev1_38_0.0.1.tar.gz' + static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32_37_0.0.1.tar.gz' + static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32_38_0.0.1.tar.gz' static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' From 2f5e8990d575f9e9de208447714aa499f1eab30d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 15 May 2023 09:05:01 +1000 Subject: [PATCH 164/562] Fix supported genome check --- lib/WorkflowOncoanalyser.groovy | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index c1b16de5..eb16b2a5 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -76,13 +76,13 @@ class WorkflowOncoanalyser { } if (!Constants.GENOMES_SUPPORTED.contains(params.genome)) { - if (!params.containsKey('force_genome')) { - log.warn "currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but forcing to " + - "proceed with \"${params.genome}\"" + if (!params.containsKey('force_genome') || !params.force_genome) { + log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got \"${params.genome}\"" + + ", please adjust the --genome argument accordingly or override with --force_genome." + System.exit(1) } else { - log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got \"${params.genome}\"" + - ", please adjust the --genome argument accordingly." - System.exit(1) + log.warn "currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but forcing to " + + "proceed with \"${params.genome}\"" } } From 4e680f0bc44a52cfc890e72ecccaf7f2914e4a24 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 15 May 2023 09:05:21 +1000 Subject: [PATCH 165/562] Remove custom module prefix in LILAC subworkflow --- subworkflows/local/lilac_calling.nf | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index 7fb3ac5c..77a33a5a 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -4,10 +4,10 @@ import Constants import Utils -include { CUSTOM_EXTRACTCONTIG } from '../../modules/local/custom/lilac_extract_and_index_contig/main' -include { CUSTOM_REALIGNREADS } from '../../modules/local/custom/lilac_realign_reads_lilac/main' -include { CUSTOM_SLICE } from '../../modules/local/custom/lilac_slice/main' -include { LILAC } from '../../modules/local/lilac/main' +include { CUSTOM_EXTRACTCONTIG as EXTRACTCONTIG } from '../../modules/local/custom/lilac_extract_and_index_contig/main' +include { CUSTOM_REALIGNREADS as REALIGNREADS } from '../../modules/local/custom/lilac_realign_reads_lilac/main' +include { CUSTOM_SLICE as SLICEBAM } from '../../modules/local/custom/lilac_slice/main' +include { LILAC } from '../../modules/local/lilac/main' include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' @@ -97,41 +97,41 @@ workflow LILAC_CALLING { // Apply slicing to unique files only // channel: [val(meta_lilac), bam, bai] ch_slice_inputs_unique = WorkflowLilac.getUniqueInputFiles(ch_slice_inputs) - CUSTOM_SLICE( + SLICEBAM( ch_slice_inputs_unique, ref_data_hla_slice_bed, ) - ch_versions = ch_versions.mix(CUSTOM_SLICE.out.versions) + ch_versions = ch_versions.mix(SLICEBAM.out.versions) // Realign contigs if using 38 (use of ALT contigs implied) // channel: [val(meta_lilac), bam, bai] - ch_slices_out = CUSTOM_SLICE.out.bam + ch_slices_out = SLICEBAM.out.bam if (params.ref_data_genome_type == 'alt') { // Align reads with chr6 // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them // to the three relevant HLA genes on chr6. All reads including those previously mapped to chr6 // are realigned for consistency. - CUSTOM_EXTRACTCONTIG( + EXTRACTCONTIG( 'chr6', ref_data_genome_fasta, ref_data_genome_fai, ) - ch_versions = ch_versions.mix(CUSTOM_EXTRACTCONTIG.out.versions) + ch_versions = ch_versions.mix(EXTRACTCONTIG.out.versions) - ch_slice_bams = CUSTOM_SLICE.out.bam + ch_slice_bams = SLICEBAM.out.bam .branch { meta_lilac, bam, bai -> def sequence_type = Utils.getEnumFromString(meta_lilac.sequence_type_str, Constants.SequenceType) wgs: sequence_type == Constants.SequenceType.WGS wts: sequence_type == Constants.SequenceType.WTS } - CUSTOM_REALIGNREADS( + REALIGNREADS( ch_slice_bams.wgs, - CUSTOM_EXTRACTCONTIG.out.contig, - CUSTOM_EXTRACTCONTIG.out.bwa_indices, + EXTRACTCONTIG.out.contig, + EXTRACTCONTIG.out.bwa_indices, ) - ch_slices_out = Channel.empty().mix(CUSTOM_REALIGNREADS.out.bam, ch_slice_bams.wts) - ch_versions = ch_versions.mix(CUSTOM_REALIGNREADS.out.versions) + ch_slices_out = Channel.empty().mix(REALIGNREADS.out.bam, ch_slice_bams.wts) + ch_versions = ch_versions.mix(REALIGNREADS.out.versions) } // Re-replicate and flow expected file count into meta From 671de8005ca964fe01a6ec8f39c5a009d89a95c5 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 15 May 2023 21:08:49 +1000 Subject: [PATCH 166/562] Correct GRCh37 SAGE coverage panel path --- conf/hmfdata.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 49cdaf3e..1ad4bea0 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -30,7 +30,7 @@ params { sage_blocklist_regions = 'dna_pipeline/variants/KnownBlacklist.germline.37.bed' sage_blocklist_sites = 'dna_pipeline/variants/KnownBlacklist.germline.37.vcf.gz' sage_actionable_panel = 'dna_pipeline/variants/ActionableCodingPanel.37.bed.gz' - sage_coverage_panel = 'dna_pipeline/variants/ActionableCodingPanel.37.bed.gz' + sage_coverage_panel = 'dna_pipeline/variants/CoverageCodingPanel.37.bed.gz' sage_highconf_regions = 'dna_pipeline/variants/NA12878_GIAB_highconf_IllFB-IllGATKHC-CG-Ion-Solid_ALLCHROM_v3.2.2_highconf.bed.gz' sage_known_hotspots_germline = 'dna_pipeline/variants/KnownHotspots.germline.37.vcf.gz' sage_known_hotspots_somatic = 'dna_pipeline/variants/KnownHotspots.somatic.37.vcf.gz' From e28bf8453e2af96ab164c98e43774464afa1d7c5 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 17 May 2023 14:18:59 +1000 Subject: [PATCH 167/562] Do not use ECR Ubuntu Docker image --- modules/local/custom/extract_tarball/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/custom/extract_tarball/main.nf b/modules/local/custom/extract_tarball/main.nf index 20e6d039..d8a5f33c 100644 --- a/modules/local/custom/extract_tarball/main.nf +++ b/modules/local/custom/extract_tarball/main.nf @@ -1,7 +1,7 @@ process CUSTOM_EXTRACTTARBALL { label 'process_single' - container 'public.ecr.aws/ubuntu/ubuntu:20.04_stable' + container 'docker.io/ubuntu:20.04' input: tuple val(meta), path(tarball) From 73f6deed5d95e29c3bb47c862b4badf1a8bb4cb3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 24 May 2023 10:31:26 +1000 Subject: [PATCH 168/562] Rename BamTools input constant --- lib/Constants.groovy | 6 +++--- subworkflows/local/orange_reporting.nf | 4 ++-- subworkflows/local/virusbreakend_calling.nf | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index f071c286..21f53b5e 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -49,7 +49,7 @@ class Constants { BAM, // Process AMBER_DIR, - BAMTOOLS_TXT, + BAMTOOLS, COBALT_DIR, GRIDSS_VCF, GRIPSS_VCF, @@ -91,8 +91,8 @@ class Constants { AMBER_DIR: [FileType.AMBER_DIR, SampleType.TUMOR_NORMAL, SequenceType.WGS], COBALT_DIR: [FileType.COBALT_DIR, SampleType.TUMOR_NORMAL, SequenceType.WGS], - BAMTOOLS_TXT_TUMOR: [FileType.BAMTOOLS_TXT, SampleType.TUMOR, SequenceType.WGS], - BAMTOOLS_TXT_NORMAL: [FileType.BAMTOOLS_TXT, SampleType.NORMAL, SequenceType.WGS], + BAMTOOLS_TUMOR: [FileType.BAMTOOLS, SampleType.TUMOR, SequenceType.WGS], + BAMTOOLS_NORMAL: [FileType.BAMTOOLS, SampleType.NORMAL, SequenceType.WGS], FLAGSTAT_TUMOR: [FileType.FLAGSTAT, SampleType.TUMOR, SequenceType.WGS], FLAGSTAT_NORMAL: [FileType.FLAGSTAT, SampleType.NORMAL, SequenceType.WGS], diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index d060528d..10442222 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -74,8 +74,8 @@ workflow ORANGE_REPORTING { // // Select input source ch_orange_inputs_source = WorkflowOncoanalyser.groupByMeta( - run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_TXT_TUMOR), - run.bamtools ? ch_bamtools_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_TXT_NORMAL, type: 'optional'), + run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_TUMOR), + run.bamtools ? ch_bamtools_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_NORMAL, type: 'optional'), run.flagstat ? ch_flagstat_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_TUMOR), run.flagstat ? ch_flagstat_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_NORMAL, type: 'optional'), run.sage ? ch_sage_somatic_tumor_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_TUMOR), diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index 5d27d503..3c5e857b 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -92,7 +92,7 @@ workflow VIRUSBREAKEND_CALLING { ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), ch_virusinterpreter_inputs_purple_files, - run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TXT_TUMOR), + run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TUMOR), ) // Virus Interpreter From 4ac92e9431069854fd5a8d5f7b372711a2af98df Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 24 May 2023 10:32:59 +1000 Subject: [PATCH 169/562] Update HMF reference data paths --- conf/hmfdata.config | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/conf/hmfdata.config b/conf/hmfdata.config index 1ad4bea0..df577ac6 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -19,10 +19,10 @@ params { isofox_gc_ratios = 'rna_pipeline/read_100_exp_gc_ratios.csv' // LILAC lilac_resources = 'dna_pipeline/immune/' - hla_slice_bed = 'missing/lilac/hla.37.bed' + hla_slice_bed = 'other/lilac/hla.37.bed' // ORANGE - cohort_mapping = 'missing/orange/cohort_mapping.tsv' - cohort_percentiles = 'missing/orange/cohort_percentiles.tsv' + cohort_mapping = 'orange/cohort_mapping.tsv' + cohort_percentiles = 'orange/cohort_percentiles.tsv' alt_sj_distribution = 'cuppa/cup_ref_alt_sj_sample.csv.gz' gene_exp_distribution = 'cuppa/cup_ref_gene_exp_sample.csv.gz' // SAGE @@ -36,12 +36,12 @@ params { sage_known_hotspots_somatic = 'dna_pipeline/variants/KnownHotspots.somatic.37.vcf.gz' sage_pon = 'dna_pipeline/variants/SageGermlinePon.1000x.37.tsv.gz' // SIGS - sigs_signatures = 'missing/sigs/snv_cosmic_signatures.csv' + sigs_signatures = 'sigs/snv_cosmic_signatures.csv' // Virus Interpreter - virus_reporting_db = 'missing/viral/virus_reporting_db.tsv' - virus_taxonomy_db = 'missing/viral/taxonomy_db.tsv' + virus_reporting_db = 'virusinterpreter/virus_reporting_db.tsv' + virus_taxonomy_db = 'virusinterpreter/taxonomy_db.tsv' // Misc - disease_ontology = 'missing/orange/201015_doid.json' + disease_ontology = 'disease_ontology/doid.json' driver_gene_panel = 'dna_pipeline/common/DriverGenePanel.37.tsv' ensembl_data_resources = 'dna_pipeline/common/ensembl_data/' gnomad_resource = 'dna_pipeline/variants/gnomad_variants_v37.csv.gz' @@ -69,10 +69,10 @@ params { isofox_gc_ratios = 'rna_pipeline/read_100_exp_gc_ratios.csv' // LILAC lilac_resources = 'dna_pipeline/immune/' - hla_slice_bed = 'missing/lilac/hla.38.bed' + hla_slice_bed = 'other/lilac/hla.38.bed' // ORANGE - cohort_mapping = 'missing/orange/cohort_mapping.tsv' - cohort_percentiles = 'missing/orange/cohort_percentiles.tsv' + cohort_mapping = 'orange/cohort_mapping.tsv' + cohort_percentiles = 'orange/cohort_percentiles.tsv' alt_sj_distribution = 'cuppa/cup_ref_alt_sj_sample.csv.gz' gene_exp_distribution = 'cuppa/cup_ref_gene_exp_sample.csv.gz' // SAGE @@ -86,12 +86,12 @@ params { sage_known_hotspots_somatic = 'dna_pipeline/variants/KnownHotspots.somatic.38.vcf.gz' sage_pon = 'dna_pipeline/variants/SageGermlinePon.98x.38.tsv.gz' // SIGS - sigs_signatures = 'missing/sigs/snv_cosmic_signatures.csv' + sigs_signatures = 'sigs/snv_cosmic_signatures.csv' // Virus Interpreter - virus_reporting_db = 'missing/viral/virus_reporting_db.tsv' - virus_taxonomy_db = 'missing/viral/taxonomy_db.tsv' + virus_reporting_db = 'virusinterpreter/virus_reporting_db.tsv' + virus_taxonomy_db = 'virusinterpreter/taxonomy_db.tsv' // Misc - disease_ontology = 'missing/orange/201015_doid.json' + disease_ontology = 'disease_ontology/doid.json' driver_gene_panel = 'dna_pipeline/common/DriverGenePanel.38.tsv' ensembl_data_resources = 'dna_pipeline/common/ensembl_data/' gnomad_resource = 'dna_pipeline/variants/gnomad/' From 48265a0a489f6e070cdcbc4fd1eaadc511b054ee Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 24 May 2023 12:58:46 +1000 Subject: [PATCH 170/562] Update unsupported genome error message --- lib/WorkflowOncoanalyser.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index eb16b2a5..8419fc74 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -77,7 +77,7 @@ class WorkflowOncoanalyser { if (!Constants.GENOMES_SUPPORTED.contains(params.genome)) { if (!params.containsKey('force_genome') || !params.force_genome) { - log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got \"${params.genome}\"" + + log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got ${params.genome}" + ", please adjust the --genome argument accordingly or override with --force_genome." System.exit(1) } else { From 402196c1e6eaf9ed520ab503cf1dcc761fdafc8a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 24 May 2023 12:59:37 +1000 Subject: [PATCH 171/562] Syntax cleanup --- subworkflows/local/amber_profiling.nf | 8 ++++---- subworkflows/local/chord_prediction.nf | 2 +- subworkflows/local/cobalt_profiling.nf | 6 +++--- subworkflows/local/gridss_calling.nf | 7 ++++++- subworkflows/local/gridss_svprep_calling.nf | 7 ++++++- subworkflows/local/gripss_filtering.nf | 4 ++-- subworkflows/local/isofox_quantification.nf | 2 +- subworkflows/local/linx_annotation.nf | 2 +- subworkflows/local/orange_reporting.nf | 2 +- subworkflows/local/pave_annotation.nf | 3 +-- subworkflows/local/sage_calling.nf | 3 +++ workflows/wgts.nf | 6 +++--- 12 files changed, 32 insertions(+), 20 deletions(-) diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index 000d5601..a97e0640 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -1,5 +1,5 @@ // -// XXX +// AMBER determines b-allele frequencies for downstream CNV calling // import Utils @@ -10,11 +10,11 @@ include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' workflow AMBER_PROFILING { take: // Sample data - ch_inputs + ch_inputs // channel: [val(meta)] // Reference data - ref_data_genome_version - ref_data_heterozygous_sites + ref_data_genome_version // val: genome version + ref_data_heterozygous_sites // file: /path/to/heterozygous_sites main: // Channel for version.yml files diff --git a/subworkflows/local/chord_prediction.nf b/subworkflows/local/chord_prediction.nf index 7ea60f17..2113e053 100644 --- a/subworkflows/local/chord_prediction.nf +++ b/subworkflows/local/chord_prediction.nf @@ -15,7 +15,7 @@ workflow CHORD_PREDICTION { // Reference data ref_data_genome_version - // Parameters + // Params run main: diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index 577ed344..7b5c0868 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -1,5 +1,5 @@ // -// XXX +// COBALT determines tumor/normal read ratios for downstream CNV calling // import Utils @@ -10,10 +10,10 @@ include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' workflow COBALT_PROFILING { take: // Sample data - ch_inputs + ch_inputs // channel: [val(meta)] // Reference data - ref_data_gc_profile + ref_data_gc_profile // file: /path/to/gc_profile main: // Channel for version.yml files diff --git a/subworkflows/local/gridss_calling.nf b/subworkflows/local/gridss_calling.nf index b8021dc7..71cef0e8 100644 --- a/subworkflows/local/gridss_calling.nf +++ b/subworkflows/local/gridss_calling.nf @@ -12,8 +12,10 @@ include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' workflow GRIDSS_CALLING { take: + // Sample data ch_inputs // channel: [val(meta)] - gridss_config // file: /path/to/gridss_config (optional) + + // Reference data ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_dict // file: /path/to/genome_dict @@ -22,6 +24,9 @@ workflow GRIDSS_CALLING { ref_data_genome_gridss_index // file: /path/to/genome_gridss_index ref_data_gridss_blacklist // val: /path/to/gridss_blacklist + // Params + gridss_config // file: /path/to/gridss_config (optional) + main: // Channel for version.yml files ch_versions = Channel.empty() diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index d8df944d..d5be34a9 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -15,8 +15,10 @@ include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' workflow GRIDSS_SVPREP_CALLING { take: + // Sample data ch_inputs // channel: [val(meta)] - gridss_config // file: /path/to/gridss_config (optional) + + // Reference data ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_version // val: genome version ref_data_genome_fai // file: /path/to/genome_fai @@ -28,6 +30,9 @@ workflow GRIDSS_SVPREP_CALLING { ref_data_sv_prep_blocklist // file: /path/to/sv_prep_blocklist ref_data_known_fusions // file: /path/to/known_fusions + // Params + gridss_config // file: /path/to/gridss_config (optional) + main: // Channel for version.yml files ch_versions = Channel.empty() diff --git a/subworkflows/local/gripss_filtering.nf b/subworkflows/local/gripss_filtering.nf index 715e09f5..7f7cc2c8 100644 --- a/subworkflows/local/gripss_filtering.nf +++ b/subworkflows/local/gripss_filtering.nf @@ -20,7 +20,7 @@ workflow GRIPSS_FILTERING { known_fusions // file: /path/to/known_fusions repeatmasker_annotations // file: /path/to/repeatmasker_annotations - // Parameters + // Params run main: @@ -83,5 +83,5 @@ workflow GRIPSS_FILTERING { somatic_unfiltered = ch_somatic_unfiltered_out // channel: [val(meta), vcf, tbi] germline_unfiltered = ch_germline_unfiltered_out // channel: [val(meta), vcf, tbi] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf index 1eca9c88..caf574cd 100644 --- a/subworkflows/local/isofox_quantification.nf +++ b/subworkflows/local/isofox_quantification.nf @@ -20,7 +20,7 @@ workflow ISOFOX_QUANTIFICATION { ref_data_isofox_counts ref_data_isofox_gc_ratios - // Parameters + // Params isofox_functions //use_isofox_exp_counts_cache diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf index 1ccc1a8f..abe7708c 100644 --- a/subworkflows/local/linx_annotation.nf +++ b/subworkflows/local/linx_annotation.nf @@ -20,7 +20,7 @@ workflow LINX_ANNOTATION { ref_data_driver_gene_panel // file: /path/to/driver_gene_panel gene_id_file // file: /path/to/linx_gene_id_file - // Parameters + // Params run main: diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 10442222..b3f2ff6b 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -40,7 +40,7 @@ workflow ORANGE_REPORTING { ref_data_isofox_alt_sj ref_data_isofox_gene_distribution - // Parameters + // Params run main: diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf index 1275d9a8..36fbb13d 100644 --- a/subworkflows/local/pave_annotation.nf +++ b/subworkflows/local/pave_annotation.nf @@ -7,7 +7,6 @@ include { PAVE_SOMATIC as SOMATIC } from '../../modules/local/pave/somatic/mai workflow PAVE_ANNOTATION { take: - // Sample data ch_inputs // channel: [val(meta)] ch_sage_germline_vcf // channel: [val(meta), sage_germline_vcf] @@ -103,5 +102,5 @@ workflow PAVE_ANNOTATION { germline = ch_germline_out // channel: [val(meta), pave_vcf] somatic = ch_somatic_out // channel: [val(meta), pave_vcf] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [versions.yml] } diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index c28b1e16..44c3174f 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -9,7 +9,10 @@ include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' workflow SAGE_CALLING { take: + // Sample data ch_inputs // channel: [val(meta)] + + // Reference data ref_data_genome_fasta // file: /path/to/genome_fasta ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_dict // file: /path/to/genome_dict diff --git a/workflows/wgts.nf b/workflows/wgts.nf index f28ddd36..d6c64b03 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -217,7 +217,6 @@ workflow WGTS { GRIDSS_SVPREP_CALLING( ch_inputs, - gridss_config, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -228,6 +227,7 @@ workflow WGTS { hmf_data.gridss_region_blocklist, hmf_data.sv_prep_blocklist, hmf_data.known_fusions, + gridss_config, ) ch_versions = ch_versions.mix(GRIDSS_SVPREP_CALLING.out.versions) @@ -237,7 +237,6 @@ workflow WGTS { GRIDSS_CALLING( ch_inputs, - gridss_config, ref_data.genome_fasta, ref_data.genome_fai, ref_data.genome_dict, @@ -245,6 +244,7 @@ workflow WGTS { ref_data.genome_bwa_index_image, ref_data.genome_gridss_index, hmf_data.gridss_region_blocklist, + gridss_config, ) ch_versions = ch_versions.mix(GRIDSS_CALLING.out.versions) @@ -255,7 +255,7 @@ workflow WGTS { // // SUBWORKFLOW: Run GRIPSS to filter GRIDSS SV calls // - // channel: [val(meta), vcf, tbi] + // channel: [val(meta), gripss_vcf, gripss_tbi] ch_gripss_somatic_out = Channel.empty() ch_gripss_germline_out = Channel.empty() ch_gripss_somatic_unfiltered_out = Channel.empty() From c2f46ab1ff12ca75b4c1d6b9e2a120d70e807424 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 24 May 2023 12:59:57 +1000 Subject: [PATCH 172/562] Reindent input channel subworkflow --- subworkflows/local/channel_group_inputs.nf | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/subworkflows/local/channel_group_inputs.nf b/subworkflows/local/channel_group_inputs.nf index adb3f0a3..8da94256 100644 --- a/subworkflows/local/channel_group_inputs.nf +++ b/subworkflows/local/channel_group_inputs.nf @@ -3,31 +3,31 @@ import Utils workflow CHANNEL_GROUP_INPUTS { take: - ch_inputs + ch_inputs main: - // channel (present): [val(meta)] - // channel (absent): [val(meta)] - ch_inputs_wgs = ch_inputs - .branch { meta -> - def key_tumor = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS] - def key_normal = [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.WGS] - present: meta.containsKey(key_tumor) && meta.containsKey(key_normal) - return meta - absent: true - return meta - } + // channel (present): [val(meta)] + // channel (absent): [val(meta)] + ch_inputs_wgs = ch_inputs + .branch { meta -> + def key_tumor = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS] + def key_normal = [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.WGS] + present: meta.containsKey(key_tumor) && meta.containsKey(key_normal) + return meta + absent: true + return meta + } - // channel (present): [val(meta)] - // channel (absent): [val(meta)] - ch_inputs_wts = ch_inputs - .branch { meta -> - def key = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WTS] - present: meta.containsKey(key) - return meta - absent: ! meta.containsKey(key) - return meta - } + // channel (present): [val(meta)] + // channel (absent): [val(meta)] + ch_inputs_wts = ch_inputs + .branch { meta -> + def key = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WTS] + present: meta.containsKey(key) + return meta + absent: ! meta.containsKey(key) + return meta + } emit: wgs_present = ch_inputs_wgs.present From 11ee2a7c98a0eb309351e1ef54e14f4ce36830da Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 24 May 2023 13:00:16 +1000 Subject: [PATCH 173/562] Add PURPLE source selection for LILAC subworkflow --- subworkflows/local/lilac_calling.nf | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index 77a33a5a..74705d3e 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -166,8 +166,11 @@ workflow LILAC_CALLING { ) // Get inputs from PURPLE + // Set PURPLE directory source first + ch_purple_dir_source = run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + // channel: [val(meta), gene_cn] - ch_lilac_inputs_gene_cn = ch_purple + ch_lilac_inputs_gene_cn = ch_purple_dir_source .map { meta, purple_dir -> if (purple_dir == []) { return [meta, []] @@ -179,7 +182,7 @@ workflow LILAC_CALLING { } // channel: [val(meta), smlv_vcf] - ch_lilac_inputs_smlv_vcf = ch_purple + ch_lilac_inputs_smlv_vcf = ch_purple_dir_source .map { meta, purple_dir -> if (purple_dir == []) { return [meta, []] From 986d3be609614ddcb325915798beb208634e8f67 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 24 May 2023 12:55:32 +1000 Subject: [PATCH 174/562] Add SAGE append for ORANGE and Neo --- conf/hmfdata.config | 8 +- conf/modules.config | 9 ++ lib/Constants.groovy | 4 +- modules/local/orange/main.nf | 35 ++++++-- modules/local/sage/append/main.nf | 46 ++++++++++ subworkflows/local/orange_reporting.nf | 41 ++++++++- subworkflows/local/sage_append.nf | 119 +++++++++++++++++++++++++ workflows/wgts.nf | 27 ++++++ 8 files changed, 273 insertions(+), 16 deletions(-) create mode 100644 modules/local/sage/append/main.nf create mode 100644 subworkflows/local/sage_append.nf diff --git a/conf/hmfdata.config b/conf/hmfdata.config index df577ac6..79a4e108 100644 --- a/conf/hmfdata.config +++ b/conf/hmfdata.config @@ -23,8 +23,8 @@ params { // ORANGE cohort_mapping = 'orange/cohort_mapping.tsv' cohort_percentiles = 'orange/cohort_percentiles.tsv' - alt_sj_distribution = 'cuppa/cup_ref_alt_sj_sample.csv.gz' - gene_exp_distribution = 'cuppa/cup_ref_gene_exp_sample.csv.gz' + alt_sj_distribution = 'rna_pipeline/isofox.hmf_3444.alt_sj_cohort.37.csv' + gene_exp_distribution = 'rna_pipeline/isofox.hmf_3444.gene_distribution.37.csv' // SAGE clinvar_annotations = 'dna_pipeline/variants/clinvar.37.vcf.gz' sage_blocklist_regions = 'dna_pipeline/variants/KnownBlacklist.germline.37.bed' @@ -73,8 +73,8 @@ params { // ORANGE cohort_mapping = 'orange/cohort_mapping.tsv' cohort_percentiles = 'orange/cohort_percentiles.tsv' - alt_sj_distribution = 'cuppa/cup_ref_alt_sj_sample.csv.gz' - gene_exp_distribution = 'cuppa/cup_ref_gene_exp_sample.csv.gz' + alt_sj_distribution = 'rna_pipeline/isofox.hmf_3444.alt_sj_cohort.38.csv' + gene_exp_distribution = 'rna_pipeline/isofox.hmf_3444.gene_distribution.38.csv' // SAGE clinvar_annotations = 'dna_pipeline/variants/clinvar.38.vcf.gz' sage_blocklist_regions = 'dna_pipeline/variants/KnownBlacklist.germline.38.bed' diff --git a/conf/modules.config b/conf/modules.config index f975c83f..7daa4bfa 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -103,6 +103,15 @@ process { ] } + withName: '.*:SAGE_APPEND:(?:GERMLINE|SOMATIC)' { + ext.jarPath = '/opt/sage/sage.jar' + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/append/${filename}" }, + ] + } + withName: '.*:PAVE_ANNOTATION:(?:GERMLINE|SOMATIC)' { ext.jarPath = '/opt/pave/pave.jar' publishDir = [ diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 21f53b5e..c613adf1 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -9,8 +9,8 @@ class Constants { static List GENOMES_DEFINED = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 - static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32_37_0.0.1.tar.gz' - static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32_38_0.0.1.tar.gz' + static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32_37_0.0.2.tar.gz' + static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32_38_0.0.2.tar.gz' static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 9eb55ba7..ca84665f 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -5,7 +5,7 @@ process ORANGE { container 'docker.io/scwatts/orange:2.3--0' input: - tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter), path(chord_prediction), path(sigs_dir), path(lilac_dir), path(cuppa_dir), path(isofox_dir) + tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(smlv_somatic_vcf), path(smlv_germline_vcf), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter), path(chord_prediction), path(sigs_dir), path(lilac_dir), path(cuppa_dir), path(isofox_dir) val genome_ver path disease_ontology path cohort_mapping @@ -55,6 +55,7 @@ process ORANGE { """ echo "${pipeline_version_str}" > pipeline_version.txt + # Replace identifiers as required if [[ -n "${normal_linx_arg}" ]]; then mkdir -p normal_linx__prepared/; for fp in ${linx_germline_anno_dir}/*; do @@ -63,9 +64,23 @@ process ORANGE { done; fi + # When WTS data is present, ORANGE expects the somatic SAGE VCF to have appended WTS data; CS indicates this should + # occur after PURPLE. Since ORANGE only collects the somatic SAGE VCF from the PURPLE output directory, we must + # prepare accordingly + purple_dir_local=${purple_dir} + if [[ -n "${rna_id_arg}" ]]; then + purple_dir_local=purple__prepared; + mkdir -p \${purple_dir_local}/; + find -L ${purple_dir} -maxdepth 1 -exec ln -fs ../{} \${purple_dir_local}/ \\; + ln -sf ../${smlv_somatic_vcf} \${purple_dir_local}/${meta.tumor_wgs_id}.purple.somatic.vcf.gz; + ln -sf ../${smlv_germline_vcf} \${purple_dir_local}/${meta.tumor_wgs_id}.purple.germline.vcf.gz; + fi + # NOTE(SW): '--add-opens java.base/java.time=ALL-UNNAMED' resolves issue writing JSON, see: # https://stackoverflow.com/questions/70412805/what-does-this-error-mean-java-lang-reflect-inaccessibleobjectexception-unable/70878195#70878195 + # NOTE(SW): DOID label: 162 [cancer]; Hartwig cohort group: unknown + java \\ --add-opens java.base/java.time=ALL-UNNAMED \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ @@ -75,12 +90,14 @@ process ORANGE { -pipeline_version_file pipeline_version.txt \\ \\ -tumor_sample_id ${meta.tumor_wgs_id} \\ - -primary_tumor_doids "" \\ + \\ + -primary_tumor_doids 162 \\ + \\ -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ -tumor_sample_flagstat_file ${flagstat_somatic} \\ -sage_somatic_tumor_sample_bqr_plot ${sage_somatic_bqr} \\ - -purple_data_directory ${purple_dir} \\ - -purple_plot_directory ${purple_dir}/plot/ \\ + -purple_data_directory \${purple_dir_local} \\ + -purple_plot_directory \${purple_dir_local}/plot/ \\ -linx_somatic_data_directory ${linx_somatic_anno_dir} \\ -linx_plot_directory ${linx_somatic_plot_dir} \\ -lilac_result_csv ${lilac_dir}/${meta.tumor_wgs_id}.lilac.csv \\ @@ -98,11 +115,11 @@ process ORANGE { ${normal_sage_coverage_arg} \\ ${normal_linx_arg} \\ \\ - \\ #${rna_id_arg} \\ - \\ #${isofox_summary_csv_arg} \\ - \\ #${isofox_gene_csv_arg} \\ - \\ #${isofox_fusion_csv_arg} \\ - \\ #${isofox_alt_sj_csv_arg} \\ + ${rna_id_arg} \\ + ${isofox_summary_csv_arg} \\ + ${isofox_gene_csv_arg} \\ + ${isofox_fusion_csv_arg} \\ + ${isofox_alt_sj_csv_arg} \\ \\ -ref_genome_version ${genome_ver} \\ -doid_json ${disease_ontology} \\ diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf new file mode 100644 index 00000000..0c4c5134 --- /dev/null +++ b/modules/local/sage/append/main.nf @@ -0,0 +1,46 @@ +process SAGE_APPEND { + tag "${meta.id}" + label 'process_medium' + + container 'docker.io/scwatts/sage:3.2.5--0' + + input: + tuple val(meta), path(vcf), path(bam), path(bai) + path genome_fasta + path genome_fai + path genome_dict + + output: + tuple val(meta), path('*.append.vcf.gz'), emit: vcf + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + """ + java \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + -cp ${task.ext.jarPath} com.hartwig.hmftools.sage.append.SageAppendApplication \\ + ${args} \\ + -input_vcf ${vcf} \\ + -reference ${meta.tumor_wts_id} \\ + -reference_bam ${bam} \\ + -ref_genome ${genome_fasta} \\ + -threads ${task.cpus} \\ + -out ./${meta.wgs_id}.sage.append.vcf.gz + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sage: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*Sage version: //') + END_VERSIONS + """ + + stub: + """ + touch "${meta.wgs_id}.sage.append.vcf.gz" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index b3f2ff6b..1c3cdc13 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -18,6 +18,8 @@ workflow ORANGE_REPORTING { ch_sage_somatic_tumor_bqr ch_sage_somatic_normal_bqr ch_sage_germline_coverage + ch_sage_somatic_append + ch_sage_germline_append ch_purple ch_linx_somatic_annotation ch_linx_somatic_plot @@ -72,6 +74,42 @@ workflow ORANGE_REPORTING { // // MODULE: Run ORANGE // + // Get PURPLE input source for processing + ch_orange_inputs_purple_dir = run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + + // Get input smlv somatic VCF from either PURPLE or SAGE append + // NOTE(SW): a better test would be WTS or WGTS; this will be implemented as run mode (WGS/WTS/WGTS, + // panel, MRD) along with input type (tumor-only, tumor/normal) + // channel: [meta, smlv_somatic_vcf, smlv_germline_vcf] + ch_orange_inputs_smlv_vcfs_append = WorkflowOncoanalyser.groupByMeta( + ch_sage_somatic_append, + ch_sage_germline_append, + ) + // NOTE(SW): using .join for selection only + .join(CHANNEL_GROUP_INPUTS.out.wts_present) + + // channel: [meta, smlv_somatic_vcf, smlv_germline_vcf] + ch_orange_inputs_smlv_vcfs_purple_dir = CHANNEL_GROUP_INPUTS.out.wts_absent + .join(ch_orange_inputs_purple_dir) + .map { meta, purple_dir -> + def tumor_id = Utils.getTumorWgsSampleName(meta) + def smlv_somatic_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + def smlv_germline_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") + + // Require smlv somatic VCF from the PURPLE directory + if (!smlv_somatic_vcf.exists() || !smlv_germline_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + + return [meta, smlv_somatic_vcf, smlv_germline_vcf] + } + + ch_orange_inputs_smlv_vcfs = Channel.empty() + .mix( + ch_orange_inputs_smlv_vcfs_append, + ch_orange_inputs_smlv_vcfs_purple_dir, + ) + // Select input source ch_orange_inputs_source = WorkflowOncoanalyser.groupByMeta( run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_TUMOR), @@ -81,7 +119,8 @@ workflow ORANGE_REPORTING { run.sage ? ch_sage_somatic_tumor_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_TUMOR), run.sage ? ch_sage_somatic_normal_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_NORMAL, type: 'optional'), run.sage ? ch_sage_germline_coverage : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_COVERAGE, type: 'optional'), - run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), + ch_orange_inputs_purple_dir, + ch_orange_inputs_smlv_vcfs, run.linx ? ch_linx_somatic_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), run.linx ? ch_linx_somatic_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_TUMOR), run.linx ? ch_linx_germline_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_NORMAL, type: 'optional'), diff --git a/subworkflows/local/sage_append.nf b/subworkflows/local/sage_append.nf new file mode 100644 index 00000000..558858ac --- /dev/null +++ b/subworkflows/local/sage_append.nf @@ -0,0 +1,119 @@ +// +// SAGE append adds WTS data to an existing SAGE VCF +// + +include { SAGE_APPEND as SOMATIC } from '../../modules/local/sage/append/main' +include { SAGE_APPEND as GERMLINE } from '../../modules/local/sage/append/main' + +include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' + +workflow SAGE_APPEND { + take: + // Sample data + ch_inputs // channel: [val(meta)] + ch_purple_dir // channel: [val(meta), purple_dir] + + // Reference data + ref_data_genome_fasta // file: /path/to/genome_fasta + ref_data_genome_fai // file: /path/to/genome_fai + ref_data_genome_dict // file: /path/to/genome_dict + + // Params + run + + main: + // Channel for version.yml files + ch_versions = Channel.empty() + + // Get input meta groups + CHANNEL_GROUP_INPUTS( + ch_inputs, + ) + + // Select input sources + // channel: [meta, purple_dir, tumor_wts_bam, tumor_wts_bai] + ch_sage_append_inputs_source = WorkflowOncoanalyser.groupByMeta( + run.purple ? ch_purple_dir : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), + CHANNEL_GROUP_INPUTS.out.wts_present + .map { meta -> + def bam = Utils.getTumorWtsBam(meta) + return [meta, bam, "${bam}.bai"] + }, + ) + + // Create inputs and create process-specific meta + // channel: [sage_meta, purple_somatic_smlv_vcf, tumor_wts_bam] + ch_sage_somatic_append_inputs = ch_sage_append_inputs_source + .map { meta, purple_dir, bam, bai -> + def tumor_id = Utils.getTumorWgsSampleName(meta) + def purple_smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + + // Require both somatic smlv from the PURPLE directory + if (!purple_smlv_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + + def sage_meta = [ + key: meta.id, + id: tumor_id, + tumor_wts_id: Utils.getTumorWtsSampleName(meta), + wgs_id: tumor_id, + ] + return [sage_meta, purple_smlv_vcf, bam, bai] + } + .filter { it != Constants.META_PLACEHOLDER } + + // NOTE(SW): revise to reduce repetition + + // channel: [sage_meta, purple_germline_smlv_vcf, tumor_wts_bam] + ch_sage_germline_append_inputs = ch_sage_append_inputs_source + .map { meta, purple_dir, bam, bai -> + def tumor_id = Utils.getTumorWgsSampleName(meta) + def normal_id = Utils.getNormalWgsSampleName(meta) + + def purple_smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") + + // Require both germline smlv from the PURPLE directory + if (!purple_smlv_vcf.exists()) { + return Constants.META_PLACEHOLDER + } + + def sage_meta = [ + key: meta.id, + id: normal_id, + tumor_wts_id: Utils.getTumorWtsSampleName(meta), + wgs_id: normal_id, + ] + return [sage_meta, purple_smlv_vcf, bam, bai] + } + .filter { it != Constants.META_PLACEHOLDER } + + // Run process + SOMATIC( + ch_sage_somatic_append_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ) + + GERMLINE( + ch_sage_germline_append_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ) + + // Set outputs, restoring original meta + ch_somatic_vcf = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs) + ch_germline_vcf = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) + ch_versions = ch_versions.mix( + GERMLINE.out.versions, + SOMATIC.out.versions, + ) + + emit: + somatic_vcf = ch_somatic_vcf // channel: [val(meta), somatic_vcf] + germline_vcf = ch_germline_vcf // channel: [val(meta), germline_vcf] + + versions = ch_versions // channel: [versions.yml] +} diff --git a/workflows/wgts.nf b/workflows/wgts.nf index d6c64b03..0bf86f45 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -88,6 +88,7 @@ include { PAVE_ANNOTATION } from '../subworkflows/local/pave_annotation' include { PREPARE_INPUT } from '../subworkflows/local/prepare_input' include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' +include { SAGE_APPEND } from '../subworkflows/local/sage_append' include { SAGE_CALLING } from '../subworkflows/local/sage_calling' include { SIGS_FITTING } from '../subworkflows/local/sigs_fitting' include { VIRUSBREAKEND_CALLING } from '../subworkflows/local/virusbreakend_calling' @@ -383,6 +384,30 @@ workflow WGTS { ch_purple_out = ch_purple_out.mix(PURPLE_CALLING.out.purple_dir) } + // + // SUBWORKFLOW: Append WTS data to SAGE VCF + // + // channel: [val(meta), append_vcf] + ch_sage_somatic_append_vcf = Channel.empty() + ch_sage_germline_append_vcf = Channel.empty() + if (run.orange) { + + // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented + + SAGE_APPEND( + ch_inputs, + ch_purple_out, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_dict, + run, + ) + + ch_versions = ch_versions.mix(SAGE_APPEND.out.versions) + ch_sage_somatic_append_vcf = ch_sage_somatic_append_vcf.mix(SAGE_APPEND.out.somatic_vcf) + ch_sage_germline_append_vcf = ch_sage_germline_append_vcf.mix(SAGE_APPEND.out.germline_vcf) + } + // // SUBWORKFLOW: Group structural variants into higher order events with LINX // @@ -547,6 +572,8 @@ workflow WGTS { ch_sage_somatic_tumor_bqr_out, ch_sage_somatic_normal_bqr_out, ch_sage_germline_coverage_out, + ch_sage_somatic_append_vcf, + ch_sage_germline_append_vcf, ch_purple_out, ch_linx_somatic_out, ch_linx_somatic_plot_out, From e01244a1dc45cf1f520a93a5be3ee8269b7109e0 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 29 May 2023 10:33:35 +1000 Subject: [PATCH 175/562] Change SAGE append id to output in same directory --- subworkflows/local/sage_append.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/sage_append.nf b/subworkflows/local/sage_append.nf index 558858ac..41be29ab 100644 --- a/subworkflows/local/sage_append.nf +++ b/subworkflows/local/sage_append.nf @@ -55,7 +55,7 @@ workflow SAGE_APPEND { def sage_meta = [ key: meta.id, - id: tumor_id, + id: meta.id, tumor_wts_id: Utils.getTumorWtsSampleName(meta), wgs_id: tumor_id, ] @@ -80,7 +80,7 @@ workflow SAGE_APPEND { def sage_meta = [ key: meta.id, - id: normal_id, + id: meta.id, tumor_wts_id: Utils.getTumorWtsSampleName(meta), wgs_id: normal_id, ] From b5271fadd7e886c93648cbdbf1366672dab857f2 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 3 Jun 2023 14:47:37 +1000 Subject: [PATCH 176/562] Catch bug when no smlv VCF is passed to PURPLE --- modules/local/purple/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 5a1e4067..bd473a47 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -49,8 +49,8 @@ process PURPLE { echo "-\${2} \${fp_out}" fi } - smlv_tumor_vcf_arg=\$(get_smlv_arg ${smlv_tumor_vcf_fp} somatic_vcf) - smlv_normal_vcf_arg=\$(get_smlv_arg ${smlv_normal_vcf_fp} germline_vcf) + smlv_tumor_vcf_arg=\$(get_smlv_arg "${smlv_tumor_vcf_fp}" somatic_vcf) + smlv_normal_vcf_arg=\$(get_smlv_arg "${smlv_normal_vcf_fp}" germline_vcf) # Run PURPLE java \\ From d5447cdcaa0b1bb6adead7a2241efcfe2caacf68 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 3 Jun 2023 14:47:57 +1000 Subject: [PATCH 177/562] Remove unneeded Docker options --- nextflow.config | 4 ---- 1 file changed, 4 deletions(-) diff --git a/nextflow.config b/nextflow.config index f7eace0a..5b83c018 100644 --- a/nextflow.config +++ b/nextflow.config @@ -6,10 +6,6 @@ ---------------------------------------------------------------------------------------- */ -// NOTE(SW): required for some Docker containers in certain execution envs, -// leaving here until better place decided -docker.runOptions = '-u $(id -u):$(id -g)' - // Global default params, used in configs params { From 7a5e3fddec8330550c0cdcbd143e06725a9d51d6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 3 Jun 2023 14:48:05 +1000 Subject: [PATCH 178/562] Correct syntax --- subworkflows/local/purple_calling.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/purple_calling.nf b/subworkflows/local/purple_calling.nf index e74bd5b2..3542d2cf 100644 --- a/subworkflows/local/purple_calling.nf +++ b/subworkflows/local/purple_calling.nf @@ -69,8 +69,8 @@ workflow PURPLE_CALLING { // channel: [val(meta), amber_dir, cobalt_dir, sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi, smlv_tumor_vcf, smlv_normal_vcf] ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( // Required inputs - run.amber ? ch_amber: WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.AMBER_DIR), - run.cobalt ? ch_cobalt: WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.COBALT_DIR), + run.amber ? ch_amber : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.AMBER_DIR), + run.cobalt ? ch_cobalt : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.COBALT_DIR), // Optional inputs ch_purple_inputs_sv, run.pave ? ch_smlv_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_TUMOR, type: 'optional'), From 71fa3ee6167041d78cf5708f419e510f2993fb42 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 23 May 2023 08:57:45 +1000 Subject: [PATCH 179/562] Prepare for panel workflow --- .gitignore | 2 + conf/{hmfdata.config => hmf_data.config} | 4 +- .../{hmfgenomes.config => hmf_genomes.config} | 0 conf/modules.config | 18 +- conf/test.config | 2 +- lib/Constants.groovy | 213 ++++++++++--- lib/Processes.groovy | 62 +++- lib/Utils.groovy | 40 +++ lib/WorkflowLilac.groovy | 10 +- lib/WorkflowMain.groovy | 2 +- lib/WorkflowOncoanalyser.groovy | 143 +++++++-- main.nf | 16 +- modules/local/amber/main.nf | 11 +- modules/local/cobalt/main.nf | 18 +- modules/local/cuppa/main.nf | 12 +- modules/local/gridss/Dockerfile | 37 --- modules/local/gridss/assemble/main.nf | 90 ------ modules/local/gridss/assemble/meta.yml | 72 ----- modules/local/gridss/call/main.nf | 95 ------ modules/local/gridss/call/meta.yml | 73 ----- modules/local/gridss/preprocess/main.nf | 54 ---- modules/local/gridss/preprocess/meta.yml | 62 ---- modules/local/gripss/somatic/main.nf | 16 +- modules/local/lilac/main.nf | 13 +- modules/local/orange/main.nf | 24 +- modules/local/pave/somatic/main.nf | 5 + modules/local/purple/main.nf | 17 +- modules/local/sage/somatic/main.nf | 10 +- modules/local/svprep/assemble/main.nf | 3 +- modules/local/svprep/call/main.nf | 3 +- modules/local/svprep/depth_annotator/main.nf | 3 +- nextflow.config | 12 +- nextflow_schema.json | 301 +----------------- subworkflows/local/amber_profiling.nf | 45 +-- subworkflows/local/bamtools_metrics.nf | 56 ++-- subworkflows/local/channel_group_inputs.nf | 38 --- subworkflows/local/channel_inputs_purple.nf | 73 +++++ subworkflows/local/chord_prediction.nf | 10 +- subworkflows/local/cobalt_profiling.nf | 51 ++- subworkflows/local/cuppa_prediction.nf | 57 ++-- subworkflows/local/flagstat_metrics.nf | 58 ++-- subworkflows/local/gridss_calling.nf | 166 ---------- subworkflows/local/gridss_svprep_calling.nf | 186 +++++++---- subworkflows/local/gripss_filtering.nf | 61 ++-- subworkflows/local/isofox_quantification.nf | 24 +- subworkflows/local/lilac_calling.nf | 114 ++++--- subworkflows/local/linx_annotation.nf | 76 +++-- subworkflows/local/linx_plotting.nf | 7 +- subworkflows/local/orange_reporting.nf | 118 +++---- subworkflows/local/pave_annotation.nf | 87 ++--- subworkflows/local/prepare_input.nf | 143 ++++++++- subworkflows/local/prepare_reference.nf | 107 ++----- subworkflows/local/purple_calling.nf | 74 ++--- subworkflows/local/sage_append.nf | 102 +++--- subworkflows/local/sage_calling.nf | 85 +++-- subworkflows/local/sigs_fitting.nf | 10 +- subworkflows/local/virusbreakend_calling.nf | 29 +- workflows/mrd.nf | 1 + workflows/panel.nf | 1 + workflows/wgts.nf | 151 ++++----- 60 files changed, 1502 insertions(+), 1871 deletions(-) rename conf/{hmfdata.config => hmf_data.config} (97%) rename conf/{hmfgenomes.config => hmf_genomes.config} (100%) delete mode 100644 modules/local/gridss/Dockerfile delete mode 100644 modules/local/gridss/assemble/main.nf delete mode 100644 modules/local/gridss/assemble/meta.yml delete mode 100644 modules/local/gridss/call/main.nf delete mode 100644 modules/local/gridss/call/meta.yml delete mode 100644 modules/local/gridss/preprocess/main.nf delete mode 100644 modules/local/gridss/preprocess/meta.yml delete mode 100644 subworkflows/local/channel_group_inputs.nf create mode 100644 subworkflows/local/channel_inputs_purple.nf delete mode 100644 subworkflows/local/gridss_calling.nf create mode 100644 workflows/mrd.nf create mode 100644 workflows/panel.nf diff --git a/.gitignore b/.gitignore index 5124c9ac..5b62d021 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +examples/ +*.tar.gz .nextflow* work/ data/ diff --git a/conf/hmfdata.config b/conf/hmf_data.config similarity index 97% rename from conf/hmfdata.config rename to conf/hmf_data.config index 79a4e108..29aff795 100644 --- a/conf/hmfdata.config +++ b/conf/hmf_data.config @@ -1,10 +1,11 @@ params { - hmfdata_paths { + hmf_data_paths { '37' { // AMBER heterozygous_sites = 'dna_pipeline/copy_number/GermlineHetPon.37.vcf.gz' // COBALT gc_profile = 'dna_pipeline/copy_number/GC_profile.1000bp.37.cnp' + diploid_bed = 'dna_pipeline/copy_number/DiploidRegions.37.bed.gz' // CUPPA cuppa_resources = 'cuppa/' // SV Prep @@ -55,6 +56,7 @@ params { heterozygous_sites = 'dna_pipeline/copy_number/GermlineHetPon.38.vcf.gz' // COBALT gc_profile = 'dna_pipeline/copy_number/GC_profile.1000bp.38.cnp' + diploid_bed = 'dna_pipeline/copy_number/DiploidRegions.38.bed.gz' // CUPPA cuppa_resources = 'cuppa/' // SV Prep diff --git a/conf/hmfgenomes.config b/conf/hmf_genomes.config similarity index 100% rename from conf/hmfgenomes.config rename to conf/hmf_genomes.config diff --git a/conf/modules.config b/conf/modules.config index 7daa4bfa..719c5a24 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -34,27 +34,11 @@ process { ext.jarPath = '/opt/svprep/svprep.jar' } - withName: '.*:GRIDSS(?:_SVPREP)?_CALLING:(?:PREPROCESS|ASSEMBLE|CALL)' { + withName: '.*:GRIDSS_SVPREP_CALLING:(?:PREPROCESS|ASSEMBLE|CALL)' { ext.jarPath = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' ext.otherJvmHeap = 4.GB } - withName: '.*:GRIDSS_CALLING:CALL' { - publishDir = [ - path: { "${params.outdir}" }, - mode: params.publish_dir_mode, - // NOTE(SW): java.io.File and Nextflow's file do not work here, resorting to string splitting - saveAs: { filename -> - if (filename.equals('versions.yml')) { - return null - } else { - def tokens = filename.split('[/]') - return "${meta.id}/gridss/${tokens[-1]}" - } - } - ] - } - withName: '.*:GRIDSS_SVPREP_CALLING:DEPTH_ANNOTATOR' { publishDir = [ path: { "${params.outdir}" }, diff --git a/conf/test.config b/conf/test.config index 03427988..2da2c9ee 100644 --- a/conf/test.config +++ b/conf/test.config @@ -35,7 +35,7 @@ params { // Defined here to be accessible within a workflow script; downloaded manually prior to process // execution. - schema_ignore_params = 'genomes,hmfdata_paths' + schema_ignore_params = 'genomes,hmf_data_paths' // Limit resources so that this can run on GitHub Actions max_cpus = 1 diff --git a/lib/Constants.groovy b/lib/Constants.groovy index c613adf1..28bfd26d 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -9,18 +9,23 @@ class Constants { static List GENOMES_DEFINED = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 - static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32_37_0.0.2.tar.gz' - static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/repacks/5.32_38_0.0.2.tar.gz' + static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.32_37_0.0.3.tar.gz' + static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.32_38_0.0.3.tar.gz' + static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' static String HLA_SLICE_BED_GRCH38_ALT_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/umccr_reference_data/other/hla_slice/grch38_alt.plus_homologous.bed' - static enum PipelineMode { - FULL, - MANUAL, - GRIDSS_PURPLE_LINX, - CUPPA, + static enum RunType { + TUMOR_NORMAL, + TUMOR_ONLY, + } + + static enum RunMode { + WGS, + WGTS, + WTS, } static enum Process { @@ -40,7 +45,6 @@ class Constants { PURPLE, SAGE, SIGS, - SVPREP, VIRUSINTERPRETER, } @@ -83,48 +87,163 @@ class Constants { WTS, } - static Map META_PLACEHOLDER = [meta_placeholder: null] + static Map PLACEHOLDER_META = [meta_placeholder: null] + static List PLACEHOLDER_OPTIONAL_CHANNEL = [] static Map INPUT = [ - ISOFOX_DIR: [FileType.ISOFOX_DIR, SampleType.TUMOR, SequenceType.WTS], - - AMBER_DIR: [FileType.AMBER_DIR, SampleType.TUMOR_NORMAL, SequenceType.WGS], - COBALT_DIR: [FileType.COBALT_DIR, SampleType.TUMOR_NORMAL, SequenceType.WGS], - - BAMTOOLS_TUMOR: [FileType.BAMTOOLS, SampleType.TUMOR, SequenceType.WGS], - BAMTOOLS_NORMAL: [FileType.BAMTOOLS, SampleType.NORMAL, SequenceType.WGS], - - FLAGSTAT_TUMOR: [FileType.FLAGSTAT, SampleType.TUMOR, SequenceType.WGS], - FLAGSTAT_NORMAL: [FileType.FLAGSTAT, SampleType.NORMAL, SequenceType.WGS], - - SAGE_VCF_TUMOR: [FileType.SAGE_VCF, SampleType.TUMOR, SequenceType.WGS], - SAGE_VCF_NORMAL: [FileType.SAGE_VCF, SampleType.NORMAL, SequenceType.WGS], - SAGE_BQR_TUMOR: [FileType.SAGE_BQR, SampleType.TUMOR, SequenceType.WGS], - SAGE_BQR_NORMAL: [FileType.SAGE_BQR, SampleType.NORMAL, SequenceType.WGS], - SAGE_COVERAGE: [FileType.SAGE_COVERAGE, SampleType.NORMAL, SequenceType.WGS], - - PAVE_VCF_TUMOR: [FileType.PAVE_VCF, SampleType.TUMOR, SequenceType.WGS], - PAVE_VCF_NORMAL: [FileType.PAVE_VCF, SampleType.NORMAL, SequenceType.WGS], - - GRIDSS_VCF: [FileType.GRIDSS_VCF, SampleType.TUMOR_NORMAL, SequenceType.WGS], - - GRIPSS_VCF_TUMOR: [FileType.GRIPSS_VCF, SampleType.TUMOR, SequenceType.WGS], - GRIPSS_VCF_NORMAL: [FileType.GRIPSS_VCF, SampleType.NORMAL, SequenceType.WGS], - GRIPSS_UNFILTERED_VCF_TUMOR: [FileType.GRIPSS_UNFILTERED_VCF, SampleType.TUMOR, SequenceType.WGS], - GRIPSS_UNFILTERED_VCF_NORMAL: [FileType.GRIPSS_UNFILTERED_VCF, SampleType.NORMAL, SequenceType.WGS], - - PURPLE_DIR: [FileType.PURPLE_DIR, SampleType.TUMOR_NORMAL, SequenceType.WGS], - - LINX_PLOT_DIR_TUMOR: [FileType.LINX_PLOT_DIR, SampleType.TUMOR, SequenceType.WGS], - LINX_ANNO_DIR_TUMOR: [FileType.LINX_ANNO_DIR, SampleType.TUMOR, SequenceType.WGS], - LINX_ANNO_DIR_NORMAL: [FileType.LINX_ANNO_DIR, SampleType.NORMAL, SequenceType.WGS], - - CHORD_PREDICTION: [FileType.CHORD_PREDICTION, SampleType.TUMOR, SequenceType.WGS], - SIGS_DIR: [FileType.SIGS_DIR, SampleType.TUMOR, SequenceType.WGS], - LILAC_DIR: [FileType.LILAC_DIR, SampleType.NORMAL, SequenceType.WGS], - VIRUSINTERPRETER_TSV: [FileType.VIRUSINTERPRETER_TSV, SampleType.TUMOR, SequenceType.WGS], + ISOFOX_DIR: [ + FileType.ISOFOX_DIR, + SampleType.TUMOR, + SequenceType.WTS + ], + + AMBER_DIR: [ + FileType.AMBER_DIR, + [SampleType.TUMOR, SampleType.TUMOR_NORMAL], + SequenceType.WGS, + ], + COBALT_DIR: [ + FileType.COBALT_DIR, + [SampleType.TUMOR, SampleType.TUMOR_NORMAL], + SequenceType.WGS, + ], + + BAMTOOLS_TUMOR: [ + FileType.BAMTOOLS, + SampleType.TUMOR, + SequenceType.WGS, + ], + BAMTOOLS_NORMAL: [ + FileType.BAMTOOLS, + SampleType.NORMAL, + SequenceType.WGS, + ], + + FLAGSTAT_TUMOR: [ + FileType.FLAGSTAT, + SampleType.TUMOR, + SequenceType.WGS, + ], + FLAGSTAT_NORMAL: [ + FileType.FLAGSTAT, + SampleType.NORMAL, + SequenceType.WGS + ], + + SAGE_VCF_TUMOR: [ + FileType.SAGE_VCF, + SampleType.TUMOR, + SequenceType.WGS, + ], + SAGE_VCF_NORMAL: [ + FileType.SAGE_VCF, + SampleType.NORMAL, + SequenceType.WGS + ], + SAGE_BQR_TUMOR: [ + FileType.SAGE_BQR, + SampleType.TUMOR, + SequenceType.WGS, + ], + SAGE_BQR_NORMAL: [ + FileType.SAGE_BQR, + SampleType.NORMAL, + SequenceType.WGS + ], + SAGE_COVERAGE: [ + FileType.SAGE_COVERAGE, + SampleType.NORMAL, + SequenceType.WGS + ], + + PAVE_VCF_TUMOR: [ + FileType.PAVE_VCF, + SampleType.TUMOR, + SequenceType.WGS, + ], + PAVE_VCF_NORMAL: [ + FileType.PAVE_VCF, + SampleType.NORMAL, + SequenceType.WGS + ], + + GRIDSS_VCF: [ + FileType.GRIDSS_VCF, + [SampleType.TUMOR, SampleType.TUMOR_NORMAL], + SequenceType.WGS, + ], + + GRIPSS_VCF_TUMOR: [ + FileType.GRIPSS_VCF, + [SampleType.TUMOR, SampleType.TUMOR_NORMAL], + SequenceType.WGS, + ], + GRIPSS_VCF_NORMAL: [ + FileType.GRIPSS_VCF, + SampleType.NORMAL, + SequenceType.WGS + ], + GRIPSS_UNFILTERED_VCF_TUMOR: [ + FileType.GRIPSS_UNFILTERED_VCF, + [SampleType.TUMOR, SampleType.TUMOR_NORMAL], + SequenceType.WGS, + ], + GRIPSS_UNFILTERED_VCF_NORMAL: [ + FileType.GRIPSS_UNFILTERED_VCF, + SampleType.NORMAL, + SequenceType.WGS + ], + + PURPLE_DIR: [ + FileType.PURPLE_DIR, + [SampleType.TUMOR, SampleType.TUMOR_NORMAL], + SequenceType.WGS, + ], + + LINX_PLOT_DIR_TUMOR: [ + FileType.LINX_PLOT_DIR, + SampleType.TUMOR, + SequenceType.WGS, + ], + LINX_ANNO_DIR_TUMOR: [ + FileType.LINX_ANNO_DIR, + SampleType.TUMOR, + SequenceType.WGS, + ], + LINX_ANNO_DIR_NORMAL: [ + FileType.LINX_ANNO_DIR, + SampleType.NORMAL, + SequenceType.WGS + ], + + CHORD_PREDICTION: [ + FileType.CHORD_PREDICTION, + SampleType.TUMOR, + SequenceType.WGS + ], + SIGS_DIR: [ + FileType.SIGS_DIR, + SampleType.TUMOR, + SequenceType.WGS + ], + LILAC_DIR: [ + FileType.LILAC_DIR, + [SampleType.TUMOR, SampleType.NORMAL, SampleType.TUMOR_NORMAL], + [SequenceType.WGS, SequenceType.WGTS], + ], + + VIRUSINTERPRETER_TSV: [ + FileType.VIRUSINTERPRETER_TSV, + SampleType.TUMOR, + SequenceType.WGS + ], + + CUPPA_DIR: [ + FileType.CUPPA_DIR, + SampleType.TUMOR, + [SequenceType.WGS, SequenceType.WTS, SequenceType.WGTS], + ], - CUPPA_DIR: [FileType.CUPPA_DIR, SampleType.TUMOR, SequenceType.WGTS], ] } diff --git a/lib/Processes.groovy b/lib/Processes.groovy index dbf2fcaf..6cf1863a 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -4,44 +4,58 @@ import Utils class Processes { - public static setProcesses(mode_str, log) { - def mode_enum = Utils.getEnumFromString(mode_str, Constants.PipelineMode) - if (!mode_enum) { - def workflows_str = Utils.getEnumNames(Constants.PipelineMode).join('\n - ') - log.error "\nERROR: recieved invalid pipeline mode: '${mode_str}'. Valid options are:\n - ${workflows_str}" - System.exit(1) + public static setProcesses(run_mode, manual_select, log) { + def processes = [] + + if (manual_select) { + return processes } - def processes = [] - switch(mode_enum) { - case Constants.PipelineMode.FULL: - processes = Constants.Process.values() as List - break - case Constants.PipelineMode.MANUAL: - break - case Constants.PipelineMode.GRIDSS_PURPLE_LINX: + switch(run_mode) { + case Constants.RunMode.WGS: processes = [ Constants.Process.AMBER, + Constants.Process.BAMTOOLS, + Constants.Process.CHORD, Constants.Process.COBALT, + Constants.Process.CUPPA, + Constants.Process.FLAGSTAT, Constants.Process.GRIDSS, Constants.Process.GRIPSS, + Constants.Process.LILAC, Constants.Process.LINX, + Constants.Process.ORANGE, + Constants.Process.PAVE, Constants.Process.PURPLE, - Constants.Process.SVPREP, + Constants.Process.SAGE, + Constants.Process.SIGS, + Constants.Process.VIRUSINTERPRETER, ] break - case Constants.PipelineMode.CUPPA: + case Constants.RunMode.WTS: + processes = [ + Constants.Process.CUPPA, + Constants.Process.ISOFOX, + ] + break + case Constants.RunMode.WGTS: processes = [ Constants.Process.AMBER, Constants.Process.BAMTOOLS, + Constants.Process.CHORD, Constants.Process.COBALT, Constants.Process.CUPPA, + Constants.Process.FLAGSTAT, Constants.Process.GRIDSS, Constants.Process.GRIPSS, Constants.Process.ISOFOX, + Constants.Process.LILAC, Constants.Process.LINX, + Constants.Process.ORANGE, + Constants.Process.PAVE, Constants.Process.PURPLE, - Constants.Process.SVPREP, + Constants.Process.SAGE, + Constants.Process.SIGS, Constants.Process.VIRUSINTERPRETER, ] break @@ -52,6 +66,20 @@ class Processes { return processes } + public static getRunStages(run_mode, include, exclude, manual_select, log) { + def processes = this.setProcesses(run_mode, manual_select, log) + def include_list = this.getProcessList(include, log) + def exclude_list = this.getProcessList(exclude, log) + this.checkIncludeExcludeList(include_list, exclude_list, log) + + processes.addAll(include_list) + processes.removeAll(exclude_list) + + return Constants.Process + .values() + .collectEntries { p -> [p.name().toLowerCase(), p in processes] } + } + public static getProcessList(process_str, log) { if (!process_str) { return [] diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 9bc7c6e7..6e3b37bb 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -69,6 +69,15 @@ class Utils { // Sample names + static public getTumorSampleName(meta, run_mode) { + + // NOTE(SW): this should /only/ be used to get panel or WGS tumor sample name, WTS sample name retrieval is not supported + + def sequence_type = Constants.SequenceType.WGS + + return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, sequence_type]) + } + static public getTumorWgsSampleName(meta) { return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) } @@ -83,6 +92,15 @@ class Utils { // Files + static public getTumorBam(meta, run_mode) { + + // NOTE(SW): this should /only/ be used to get panel or WGS tumor BAM, WTS BAM retrieval is not supported + + def sequence_type = Constants.SequenceType.WGS + + return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, sequence_type]) + } + static public getTumorWgsBam(meta) { return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) } @@ -103,4 +121,26 @@ class Utils { } return meta.getAt(key) } + + + static public getRunMode(run_mode, log) { + def run_mode_enum = Utils.getEnumFromString(run_mode, Constants.RunMode) + if (!run_mode_enum) { + def run_modes_str = Utils.getEnumNames(Constants.RunMode).join('\n - ') + log.error "\nERROR: recieved an invalid run mode: '${run_mode}'. Valid options are:\n - ${run_modes_str}" + System.exit(1) + } + return run_mode_enum + } + + + static public getRunType(run_type, log) { + def run_type_enum = Utils.getEnumFromString(run_type, Constants.RunType) + if (!run_type_enum) { + def run_types_str = Utils.getEnumNames(Constants.RunType).join('\n - ') + log.error "\nERROR: recieved an invalid run type: '${run_type}'. Valid options are:\n - ${run_types_str}" + System.exit(1) + } + return run_type_enum + } } diff --git a/lib/WorkflowLilac.groovy b/lib/WorkflowLilac.groovy index fe0f4922..dc1fa124 100755 --- a/lib/WorkflowLilac.groovy +++ b/lib/WorkflowLilac.groovy @@ -9,13 +9,13 @@ import Utils class WorkflowLilac { - public static getSliceInputs(ch) { + public static getSliceInputs(ch, tumor_sequence_type) { // channel: [val(meta_lilac), bam, bai] return ch .flatMap { meta, nbam_wgs, nbai_wgs, tbam_wgs, tbai_wgs, tbam_wts, tbai_wts -> def data = [ [nbam_wgs, nbai_wgs, Constants.SequenceType.WGS, Constants.SampleType.NORMAL], - [tbam_wgs, tbai_wgs, Constants.SequenceType.WGS, Constants.SampleType.TUMOR], + [tbam_wgs, tbai_wgs, tumor_sequence_type, Constants.SampleType.TUMOR], [tbam_wts, tbai_wts, Constants.SequenceType.WTS, Constants.SampleType.TUMOR], ] def data_present = data.findAll { it[0] } @@ -61,7 +61,7 @@ class WorkflowLilac { return d } - public static sortSlices(ch) { + public static sortSlices(ch, tumor_sequence_type) { // Gather and order files from same grouping using non-blocked groupTuple via provided file counts // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] def d = ch @@ -83,8 +83,8 @@ class WorkflowLilac { meta, data.get([Constants.SampleType.NORMAL, Constants.SequenceType.WGS, 'bam'], []), data.get([Constants.SampleType.NORMAL, Constants.SequenceType.WGS, 'bai'], []), - data.get([Constants.SampleType.TUMOR, Constants.SequenceType.WGS, 'bam'], []), - data.get([Constants.SampleType.TUMOR, Constants.SequenceType.WGS, 'bai'], []), + data.get([Constants.SampleType.TUMOR, tumor_sequence_type, 'bam'], []), + data.get([Constants.SampleType.TUMOR, tumor_sequence_type, 'bai'], []), data.get([Constants.SampleType.TUMOR, Constants.SequenceType.WTS, 'bam'], []), data.get([Constants.SampleType.TUMOR, Constants.SequenceType.WTS, 'bai'], []), ] diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 1784de60..f351b3b4 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -58,7 +58,7 @@ class WorkflowMain { NfcoreSchema.validateParameters(workflow, params, log) } - // NOTE(SW): this is now deferred until after we set defaults in subworkflows + // NOTE(SW): this is now deferred until after we set defaults // Print parameter summary log to screen //log.info paramsSummaryLog(workflow, params, log) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 8419fc74..a272da35 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -8,6 +8,8 @@ import nextflow.Channel import nextflow.Nextflow import Constants +import Processes +import Utils class WorkflowOncoanalyser { @@ -16,6 +18,10 @@ class WorkflowOncoanalyser { // public static void setParamsDefaults(params, log) { + // Set defaults common to all run configuration + + def default_invalid = false + if (params.containsKey('genome_version')) { params.ref_data_genome_version = params.genome_version.toString() } else if (Constants.GENOMES_VERSION_37.contains(params.genome)) { @@ -23,8 +29,7 @@ class WorkflowOncoanalyser { } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { params.ref_data_genome_version = '38' } else { - log.error "ERROR: Got a bad genome version: ${params.ref_data_genome_version}" - System.exit(1) + default_invalid = true } if (params.containsKey('genome_type')) { @@ -34,8 +39,7 @@ class WorkflowOncoanalyser { } else if (Constants.GENOMES_DEFINED.contains(params.genome)) { params.ref_data_genome_type = 'no_alt' } else { - log.error "ERROR: Got a bad genome type: ${params.ref_data_genome_type}" - System.exit(1) + default_invalid = true } if (!params.containsKey('ref_data_hmf_data_path')) { @@ -46,12 +50,45 @@ class WorkflowOncoanalyser { } } - if (!params.containsKey('ref_data_virusbreakenddb_path')) { - params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH + // Bad configuration, catch in validateParams + if (default_invalid) { + return + } + + // Set defaults specific to run configuration without attempting to validate + + def run_mode + if (params.containsKey('run_mode')) { + run_mode = Utils.getRunMode(params.run_mode, log) + } else { + // Bad configuration, catch in validateParams + return + } + + if (run_mode == Constants.RunMode.WTS) { + if (!params.containsKey('run_type')) { + params.run_type = 'tumor_only' + } + } + + def stages = Processes.getRunStages( + run_mode, + params.processes_include, + params.processes_exclude, + params.processes_manual, + log, + ) + + if (stages.virusinterpreter) { + if (!params.containsKey('ref_data_virusbreakenddb_path')) { + params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH + } } - if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && !params.containsKey('ref_data_hla_slice_bed')) { - params.ref_data_hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH + if (stages.lilac) { + if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && !params.containsKey('ref_data_hla_slice_bed')) { + params.ref_data_hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH + } } } @@ -59,15 +96,18 @@ class WorkflowOncoanalyser { // Check and validate parameters // public static void validateParams(params, log) { + + // Common parameters + if (!params.genome) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome must be set using the --genome CLI argument or in a configuration file.\n" + " Currently, the available genome are:\n" + " ${params.genomes.keySet().join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) } else if (!params.genomes.containsKey(params.genome)) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + " Currently, the available genome are:\n" + " ${params.genomes.keySet().join(", ")}\n" + @@ -87,7 +127,7 @@ class WorkflowOncoanalyser { } if (!params.ref_data_genome_version) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome version wasn't provided and genome '${params.genome}' is not defined in \n" + " genome version list.\n" + " Currently, the list of genomes in the version list include:\n" + @@ -97,7 +137,7 @@ class WorkflowOncoanalyser { } if (!params.ref_data_genome_type) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome type wasn't provided and genome '${params.genome}' is not defined in \n" + " genome version list.\n" + " Currently, the list of genomes in the version list include:\n" + @@ -123,6 +163,45 @@ class WorkflowOncoanalyser { System.exit(1) } } + + // Run configuration specific parameters + + if (!params.run_mode) { + def run_modes = Utils.getEnumNames(Constants.RunMode).join('\n - ') + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Run mode must be set using the --run_mode CLI argument or in a configuration \n" + + " file.\n" + + " Currently, the available run modes are:\n" + + " - ${run_modes}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + if (!params.run_type) { + def run_types = Utils.getEnumNames(Constants.RunType).join('\n - ') + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Run type must be set using the --run_type CLI argument or in a configuration \n" + + " file.\n" + + " Currently, the available run types are:\n" + + " - ${run_types}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + def run_mode = Utils.getRunMode(params.run_mode, log) + def run_type = Utils.getRunType(params.run_type, log) + + if (run_mode == Constants.RunMode.WTS) { + if (run_type != Constants.RunType.TUMOR_ONLY) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " The WTS run mode does not support tumor/normal data, please adjust the CLI \n" + + " --run_type option or corresponding configuration file.\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + } + } public static String paramsSummaryLog(workflow, params, log) { @@ -134,6 +213,24 @@ class WorkflowOncoanalyser { log.info summary_log } + public static getRunConfig(params, log) { + def run_mode = Utils.getRunMode(params.run_mode, log) + def run_type = Utils.getRunType(params.run_type, log) + def stages = Processes.getRunStages( + run_mode, + params.processes_include, + params.processes_exclude, + params.processes_manual, + log, + ) + + return [ + mode: run_mode, + type: run_type, + stages: stages, + ] + } + public static groupByMeta(Map named_args, ... channels) { def r = channels // Set position; required to use non-blocking .mix operator @@ -154,7 +251,7 @@ class WorkflowOncoanalyser { r = Channel.empty().mix(*r) // NOTE(SW): As of Nextflow 22.10.6, groupTuple requires a matching meta /and/ an additional element to complete without error, these placeholders are filtered in the groupByMeta function - r = r.filter { it[0] != Constants.META_PLACEHOLDER } + r = r.filter { it[0] != Constants.PLACEHOLDER_META } r = r .groupTuple(size: channels.size()) @@ -169,7 +266,7 @@ class WorkflowOncoanalyser { } if (named_args.getOrDefault('flatten', true)) { - def flatten_mode = named_args.getOrDefault('flatten_mode', 'recursive') + def flatten_mode = named_args.getOrDefault('flatten_mode', 'nonrecursive') if (flatten_mode == 'recursive') { r = r.map { it.flatten() } } else if (flatten_mode == 'nonrecursive') { @@ -195,10 +292,20 @@ class WorkflowOncoanalyser { public static getInput(Map named_args, ch, key) { def input_type = named_args.getOrDefault('type', 'required') return ch.map { meta -> - if (meta.containsKey(key)) { - return [meta, meta.getAt(key)] - } else if (input_type == 'required') { - return [Constants.META_PLACEHOLDER, null] + def result + for (key_combination in key.combinations()) { + if (meta.containsKey(key_combination)) { + result = [meta, meta.getAt(key_combination)] + break + } + } + + if (result) { + return result + } + + if (input_type == 'required') { + return [Constants.PLACEHOLDER_META, null] } else if (input_type == 'optional') { return [meta, []] } else { diff --git a/main.nf b/main.nf index 76e85b33..7eea1d9d 100644 --- a/main.nf +++ b/main.nf @@ -1,4 +1,7 @@ #!/usr/bin/env nextflow +import Utils +import Constants + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nf-core/oncoanalyser @@ -32,6 +35,9 @@ params.ref_data_genome_gridss_index = WorkflowMain.getGenomeAttribute(params, */ WorkflowMain.initialise(workflow, params, log) +WorkflowOncoanalyser.setParamsDefaults(params, log) +WorkflowOncoanalyser.validateParams(params, log) + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -44,8 +50,16 @@ include { WGTS } from './workflows/wgts' // // WORKFLOW: Run main nf-core/oncoanalyser analysis pipeline // + +run_mode = Utils.getRunMode(params.run_mode, log) + workflow NFCORE_ONCOANALYSER { - WGTS() + run_modes_wgts = [Constants.RunMode.WGS, Constants.RunMode.WTS, Constants.RunMode.WGTS] + if (run_modes_wgts.contains(run_mode)) { + WGTS() + } else { + assert false + } } /* diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index bae69c57..2369c7d8 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -7,7 +7,7 @@ process AMBER { input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) val ref_genome_ver - path loci + path heterozygous_sites output: tuple val(meta), path('amber/'), emit: amber_dir @@ -19,6 +19,9 @@ process AMBER { script: def args = task.ext.args ?: '' + def reference_arg = meta.containsKey('normal_id') ? "-reference ${meta.normal_id}" : '' + def reference_bam_arg = normal_bam ? "-reference_bam ${normal_bam}" : '' + """ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ @@ -26,10 +29,10 @@ process AMBER { ${args} \\ -tumor ${meta.tumor_id} \\ -tumor_bam ${tumor_bam} \\ - -reference ${meta.normal_id} \\ - -reference_bam ${normal_bam} \\ + ${reference_arg} \\ + ${reference_bam_arg} \\ -ref_genome_version ${ref_genome_ver} \\ - -loci ${loci} \\ + -loci ${heterozygous_sites} \\ -threads ${task.cpus} \\ -output_dir amber/ diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index 1b2a3563..8476e285 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -7,6 +7,8 @@ process COBALT { input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) path gc_profile + path diploid_regions + path target_region_normalisation output: tuple val(meta), path('cobalt/'), emit: cobalt_dir @@ -18,6 +20,12 @@ process COBALT { script: def args = task.ext.args ?: '' + def reference_arg = meta.containsKey('normal_id') ? "-reference ${meta.normal_id}" : '' + def reference_bam_arg = normal_bam ? "-reference_bam ${normal_bam}" : '' + + def diploid_regions_arg = diploid_regions ? "-tumor_only_diploid_bed ${diploid_regions}" : '' + def target_region_arg = target_region_normalisation ? "-target_region ${target_region_normalisation}" : '' + """ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ @@ -25,11 +33,13 @@ process COBALT { ${args} \\ -tumor ${meta.tumor_id} \\ -tumor_bam ${tumor_bam} \\ - -reference ${meta.normal_id} \\ - -reference_bam ${normal_bam} \\ - -output_dir cobalt/ \\ + ${reference_arg} \\ + ${reference_bam_arg} \\ -threads ${task.cpus} \\ - -gc_profile ${gc_profile} + -gc_profile ${gc_profile} \\ + ${diploid_regions_arg} \\ + ${target_region_arg} \\ + -output_dir cobalt/ # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index bec647a4..72aa5f7f 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -52,7 +52,7 @@ process CUPPA { cp \${fp} sample_data/\${fn_out} done; # Rename identifier in the summary file - sed -i 's/^${meta.id_wts}/${meta.id}/g' sample_data/${meta.id}.isf.summary.csv + sed -i 's/^${meta.id_wts}/${meta.id}/g' sample_data/${meta.id}.isf.summary.csv; fi; mkdir -p cuppa/ @@ -68,10 +68,12 @@ process CUPPA { -create_pdf \\ -output_dir ./cuppa/ - python ${task.ext.chartScriptPath} \\ - -sample ${meta.id} \\ - -sample_data cuppa/${meta.id}.cup.data.csv \\ - -output_dir ./cuppa/ + if [[ ${categories_val} == 'DNA' || ${categories_val} == 'ALL' ]]; then + python ${task.ext.chartScriptPath} \\ + -sample ${meta.id} \\ + -sample_data cuppa/${meta.id}.cup.data.csv \\ + -output_dir ./cuppa/; + fi # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/gridss/Dockerfile b/modules/local/gridss/Dockerfile deleted file mode 100644 index 6373cf84..00000000 --- a/modules/local/gridss/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'gridss==2.13.2' && \ - micromamba clean --all --yes - -# NOTE(SW): required to correctly check SAMtools version built by Conda -RUN \ - sed -i \ - -e '209s/grep samtools/head -n1 | grep samtools/' \ - /opt/conda/share/gridss-2.13.2-1/gridss_extract_overlapping_fragments - -# NOTE(SW): required to run tests on compute with low resources; without the -# change this GRIDSS invoke will attempt to allocate the default 30 GB of -# memory even when `--gridssargs` is set -RUN \ - sed -i \ - -e '779a \\t\t$gridssargs \\' \ - /opt/conda/share/gridss-2.13.2-1/virusbreakend - -RUN \ - ln -sf \ - /opt/conda/pkgs/gridss-2.13.2-h20b1175_1/share/gridss-2.13.2-1/gridss \ - /opt/conda/bin/gridss - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/gridss/assemble/main.nf b/modules/local/gridss/assemble/main.nf deleted file mode 100644 index f8e6192a..00000000 --- a/modules/local/gridss/assemble/main.nf +++ /dev/null @@ -1,90 +0,0 @@ -process GRIDSS_ASSEMBLE { - tag "${meta.id}" - label 'process_medium' - - container 'docker.io/scwatts/gridss:2.13.2--3' - - input: - tuple val(meta), path(bams), path(preprocess_dirs), val(labels) - path gridss_config - path genome_fasta - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - path blocklist - - output: - tuple val(meta), path('gridss_assemble/'), emit: assemble_dir - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - def output_dirname = 'gridss_assemble' - def labels_arg = labels.join(',') - // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below - def bams_list = bams instanceof List ? bams : [bams] - def bams_arg = bams_list.join(' ') - - """ - # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation - # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present - shadow_input_directory() { - src=\${1} - dst="${output_dirname}/work/\${src##*/}" - for filepath_src in \$(find -L \${src} ! -type d); do - # Get destination location for symlink - filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) - filepath_dst=\${dst%/}/\${filepath_src_rel} - # Create directory for symlink - mkdir -p \${filepath_dst%/*}; - # Get path for symlink source file, then create it - # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only - # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers - symlinkpath=\$(realpath \${filepath_src}) - ln -s \${symlinkpath} \${filepath_dst}; - done - if [[ -L "\${src##*/}" ]]; then - rm "\${src}" - fi - } - for preprocess_dir in ${preprocess_dirs}; do - shadow_input_directory \${preprocess_dir}; - done - - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - - # Run - gridss \\ - ${args} \\ - --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ - --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ - --jar ${task.ext.jarPath} \\ - --steps assemble \\ - --labels ${labels_arg} \\ - --reference ${genome_fasta} \\ - --blacklist ${blocklist} \\ - --workingdir ${output_dirname}/work \\ - --assembly ${output_dirname}/sv_assemblies.bam \\ - --threads ${task.cpus} \\ - ${config_arg} \\ - ${bams_arg} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ - - stub: - """ - mkdir -p gridss_assemble/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/gridss/assemble/meta.yml b/modules/local/gridss/assemble/meta.yml deleted file mode 100644 index 929eb0bb..00000000 --- a/modules/local/gridss/assemble/meta.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: gridss_assemble -description: Assemble SVs with GRIDSS -keywords: - - assemble - - sv -tools: - - gridss: - description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. - homepage: https://github.com/PapenfussLab/gridss - documentation: https://github.com/PapenfussLab/gridss - licence: ["GPL >=3"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - bams: - type: list - description: List of BAM files - pattern: "*.{bam}" - - preprocess_dirs: - type: list - description: List of GRIDSS preprocess output directories - - labels: - type: list - description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - - gridss_config: - type: file - description: GRIDSS configuration file (optional) - - genome_fasta: - type: file - description: Reference genome assembly fa file - pattern: "*.{fa,fasta}" - - genome_fai: - type: file - description: Reference genome assembly fai file - pattern: "*.{fai}" - - genome_dict: - type: file - description: Reference genome assembly dict file - pattern: "*.{dict}" - - genome_bwa_index_dir: - type: directory - description: Directory containing reference genome assembly BWA index - - genome_bwa_index_image: - type: file - description: Reference genome assembly BWA index img file - pattern: "*.{img}" - - genome_gridss_index: - type: file - description: Reference genome assembly GRIDSS index file - pattern: "*.{gridsscache}" - - blocklist: - type: file - description: GRIDSS blocklist file - pattern: "*.{bed.gz}" -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - assembly_dir: - type: directory - description: GRIDSS assemble output directory - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@scwatts" diff --git a/modules/local/gridss/call/main.nf b/modules/local/gridss/call/main.nf deleted file mode 100644 index f35a54d7..00000000 --- a/modules/local/gridss/call/main.nf +++ /dev/null @@ -1,95 +0,0 @@ -process GRIDSS_CALL { - tag "${meta.id}" - label 'process_medium' - - container 'docker.io/scwatts/gridss:2.13.2--3' - - input: - tuple val(meta), path(bams), path(assemble_dir), val(labels) - path gridss_config - path genome_fasta - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - path blocklist - - output: - tuple val(meta), path('gridss_call/sv_vcf.vcf.gz'), emit: vcf - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - def output_dirname = 'gridss_call' - def labels_arg = labels.join(',') - // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below - def bams_list = bams instanceof List ? bams : [bams] - def bams_arg = bams_list.join(' ') - - """ - # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation - # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present - shadow_input_directory() { - src=\${1} - dst="${output_dirname}/" - for filepath_src in \$(find -L \${src} ! -type d); do - # Get destination location for symlink - filepath_src_rel=\$(sed 's#^'\${src}'/*##' <<< \${filepath_src}) - filepath_dst=\${dst%/}/\${filepath_src_rel} - # Create directory for symlink - mkdir -p \${filepath_dst%/*}; - # Get path for symlink source file, then create it - # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only - # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers - symlinkpath=\$(realpath \${filepath_src}) - ln -s \${symlinkpath} \${filepath_dst}; - done - if [[ -L "\${src##*/}" ]]; then - rm "\${src}" - fi - } - shadow_input_directory ${assemble_dir} - - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - - # Run - gridss \\ - ${args} \\ - --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ - --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ - --jar ${task.ext.jarPath} \\ - --steps call \\ - --labels ${labels_arg} \\ - --reference ${genome_fasta} \\ - --blacklist ${blocklist} \\ - --workingdir ${output_dirname}/work/ \\ - --assembly ${output_dirname}/sv_assemblies.bam \\ - --output ${output_dirname}/sv_vcf.vcf.gz \\ - --threads ${task.cpus} \\ - ${config_arg} \\ - ${bams_arg} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ - - stub: - """ - mkdir -p gridss_call/ - cat < gridss_call/sv_vcf.vcf.gz - ##fileformat=VCFv4.1 - ##contig= - #CHROM POS ID REF ALT QUAL FILTER INFO - . . . . . . . - EOF - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/gridss/call/meta.yml b/modules/local/gridss/call/meta.yml deleted file mode 100644 index 8fc76340..00000000 --- a/modules/local/gridss/call/meta.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: gridss_call -description: Call SVs with GRIDSS -keywords: - - calling - - sv -tools: - - gridss: - description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. - homepage: https://github.com/PapenfussLab/gridss - documentation: https://github.com/PapenfussLab/gridss - licence: ["GPL >=3"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - bams: - type: list - description: List of BAM files - pattern: "*.{bam}" - - assemble_dir: - type: directory - description: GRIDSS assemble output directory - - labels: - type: list - description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - - gridss_config: - type: file - description: GRIDSS configuration file (optional) - - genome_fasta: - type: file - description: Reference genome assembly fa file - pattern: "*.{fa,fasta}" - - genome_fai: - type: file - description: Reference genome assembly fai file - pattern: "*.{fai}" - - genome_dict: - type: file - description: Reference genome assembly dict file - pattern: "*.{dict}" - - genome_bwa_index_dir: - type: directory - description: Directory containing reference genome assembly BWA index - - genome_bwa_index_image: - type: file - description: Reference genome assembly BWA index img file - pattern: "*.{img}" - - genome_gridss_index: - type: file - description: Reference genome assembly GRIDSS index file - pattern: "*.{gridsscache}" - - blocklist: - type: file - description: GRIDSS blocklist file - pattern: "*.{bed.gz}" -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - vcf: - type: file - description: GRIDSS SV VCF file - pattern: "*.{vcf.gz}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@scwatts" diff --git a/modules/local/gridss/preprocess/main.nf b/modules/local/gridss/preprocess/main.nf deleted file mode 100644 index 264ab3ff..00000000 --- a/modules/local/gridss/preprocess/main.nf +++ /dev/null @@ -1,54 +0,0 @@ -process GRIDSS_PREPROCESS { - tag "${meta.id}" - label 'process_medium' - - container 'docker.io/scwatts/gridss:2.13.2--3' - - input: - tuple val(meta), path(bam) - path gridss_config - path genome_fasta - path genome_fai - path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - path genome_gridss_index - - output: - tuple val(meta), path("gridss_preprocess/${bam.name}.gridss.working/"), emit: preprocess_dir - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' - - """ - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - - gridss \\ - ${args} \\ - --jvmheap ${Math.round(task.memory.bytes * 0.95)} \\ - --jar ${task.ext.jarPath} \\ - --steps preprocess \\ - --reference ${genome_fasta} \\ - --workingdir gridss_preprocess/ \\ - --threads ${task.cpus} \\ - ${config_arg} \\ - ${bam} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - END_VERSIONS - """ - - stub: - """ - mkdir -p gridss_preprocess/${bam.name}.gridss.working/ - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/modules/local/gridss/preprocess/meta.yml b/modules/local/gridss/preprocess/meta.yml deleted file mode 100644 index 39fe570c..00000000 --- a/modules/local/gridss/preprocess/meta.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: gridss_preprocess -description: Preprocess reads for GRIDSS -keywords: - - preprocessing - - sv -tools: - - gridss: - description: GRIDSS is a module software suite containing tools useful for the detection of genomic rearrangements. - homepage: https://github.com/PapenfussLab/gridss - documentation: https://github.com/PapenfussLab/gridss - licence: ["GPL >=3"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - bam: - type: file - description: BAM file - pattern: "*.{bam}" - - gridss_config: - type: file - description: GRIDSS configuration file (optional) - - genome_fasta: - type: file - description: Reference genome assembly fa file - pattern: "*.{fa,fasta}" - - genome_fai: - type: file - description: Reference genome assembly fai file - pattern: "*.{fai}" - - genome_dict: - type: file - description: Reference genome assembly dict file - pattern: "*.{dict}" - - genome_bwa_index_dir: - type: directory - description: Directory containing reference genome assembly BWA index - - genome_bwa_index_image: - type: file - description: Reference genome assembly BWA index img file - pattern: "*.{img}" - - genome_gridss_index: - type: file - description: Reference genome assembly GRIDSS index file - pattern: "*.{gridsscache}" -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [id: 'sample_id'] - - preprocess_dir: - type: directory - description: GRIDSS preprocess output directory - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@scwatts" diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index ab1c6728..16cc48dc 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -13,11 +13,12 @@ process GRIPSS_SOMATIC { path pon_breakpoints path known_fusions path repeatmasker_annotations + path target_regions_bed output: - tuple val(meta), path('*.filtered.somatic.vcf.gz'), path('*.filtered.somatic.vcf.gz.tbi'), emit: vcf - tuple val(meta), path('*.gripss.somatic.vcf.gz'), path('*.gripss.somatic.vcf.gz.tbi') , emit: vcf_unfiltered - path 'versions.yml' , emit: versions + tuple val(meta), path('*.gripss.filtered{,.somatic}.vcf.gz'), path('*.gripss.filtered{,.somatic}.vcf.gz.tbi'), emit: vcf + tuple val(meta), path('*.gripss{,.somatic}.vcf.gz'), path('*.gripss{,.somatic}.vcf.gz.tbi') , emit: vcf_unfiltered + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -25,13 +26,17 @@ process GRIPSS_SOMATIC { script: def args = task.ext.args ?: '' + def reference_arg = meta.containsKey('normal_id') ? "-reference ${meta.normal_id}" : '' + def target_regions_bed_arg = target_regions_bed ? "-target_regions_bed ${target_regions_bed}" : '' + def output_id_arg = meta.containsKey('normal_id') ? '-output_id somatic' : '' + """ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${meta.tumor_id} \\ - -reference ${meta.normal_id} \\ + ${reference_arg} \\ -vcf ${gridss_vcf} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ @@ -39,7 +44,8 @@ process GRIPSS_SOMATIC { -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ -repeat_mask_file ${repeatmasker_annotations} \\ - -output_id somatic \\ + ${target_regions_bed_arg} \\ + ${output_id_arg} \\ -output_dir ./ cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 54855c39..65fdb26f 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -5,7 +5,7 @@ process LILAC { container 'docker.io/scwatts/lilac:1.4.2--0' input: - tuple val(meta), path(normal_wgs_bam), path(normal_wgs_bai), path(tumor_wgs_bam), path(tumor_wgs_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(gene_cn), path(smlv_vcf) + tuple val(meta), path(normal_wgs_bam), path(normal_wgs_bai), path(tumor_bam), path(tumor_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(gene_cn), path(smlv_vcf) path genome_fasta val genome_ver path lilac_resources, stageAs: 'lilac_resources' @@ -19,9 +19,12 @@ process LILAC { script: def args = task.ext.args ?: '' - def sample_name = getSampleName(meta, tumor_wgs_bam, normal_wgs_bam) - def tumor_wgs_bam_arg = tumor_wgs_bam ? "-tumor_bam ${tumor_wgs_bam}" : '' + def sample_name = getSampleName(meta, tumor_bam, normal_wgs_bam) + + def normal_bam_arg = normal_wgs_bam ? "-reference_bam ${normal_wgs_bam}" : '' + def tumor_bam_arg = tumor_bam ? "-tumor_bam ${tumor_bam}" : '' def tumor_wts_bam_arg = tumor_wts_bam ? "-rna_bam ${tumor_wts_bam}" : '' + def gene_cn_arg = gene_cn ? "-gene_copy_number ${gene_cn}" : '' def smlv_vcf_arg = smlv_vcf ? "-somatic_vcf ${smlv_vcf}" : '' @@ -31,8 +34,8 @@ process LILAC { -jar ${task.ext.jarPath} \\ ${args} \\ -sample ${sample_name} \\ - -reference_bam ${normal_wgs_bam} \\ - ${tumor_wgs_bam_arg} \\ + ${normal_bam_arg} \\ + ${tumor_bam_arg} \\ ${tumor_wts_bam_arg} \\ ${smlv_vcf_arg} \\ ${gene_cn_arg} \\ diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index ca84665f..ff9c78a4 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -31,9 +31,9 @@ process ORANGE { def virusinterpreter_arg = virusinterpreter ? "-annotated_virus_tsv ${virusinterpreter}" : '' def chord_arg = chord_prediction ? "-chord_prediction_txt ${chord_prediction}" : '' - def sigs_arg = sigs_dir ? "-sigs_allocation_tsv ${sigs_dir}/${meta.tumor_wgs_id}.sig.allocation.tsv" : '' - def cuppa_csv_arg = cuppa_dir ? "-cuppa_result_csv ${cuppa_dir}/${meta.tumor_wgs_id}.cup.data.csv" : '' - def cuppa_summary_arg = cuppa_dir ? "-cuppa_summary_plot ${cuppa_dir}/${meta.tumor_wgs_id}.cup.report.summary.png" : '' + def sigs_arg = sigs_dir ? "-sigs_allocation_tsv ${sigs_dir}/${meta.tumor_id}.sig.allocation.tsv" : '' + def cuppa_csv_arg = cuppa_dir ? "-cuppa_result_csv ${cuppa_dir}/${meta.tumor_id}.cup.data.csv" : '' + def cuppa_summary_arg = cuppa_dir ? "-cuppa_summary_plot ${cuppa_dir}/${meta.tumor_id}.cup.report.summary.png" : '' def normal_id_arg = meta.containsKey('normal_wgs_id') ? "-reference_sample_id ${meta.normal_wgs_id}" : '' def normal_metrics_arg = bam_metrics_germline ? "-ref_sample_wgs_metrics_file ${bam_metrics_germline}" : '' @@ -60,7 +60,7 @@ process ORANGE { mkdir -p normal_linx__prepared/; for fp in ${linx_germline_anno_dir}/*; do fn=\${fp##*/}; - ln -s ../${linx_germline_anno_dir}/\${fn} normal_linx__prepared/\$(sed 's/${meta.normal_wgs_id}/${meta.tumor_wgs_id}/' <<< \${fn}); + ln -s ../${linx_germline_anno_dir}/\${fn} normal_linx__prepared/\$(sed 's/${meta.normal_wgs_id}/${meta.tumor_id}/' <<< \${fn}); done; fi @@ -72,8 +72,8 @@ process ORANGE { purple_dir_local=purple__prepared; mkdir -p \${purple_dir_local}/; find -L ${purple_dir} -maxdepth 1 -exec ln -fs ../{} \${purple_dir_local}/ \\; - ln -sf ../${smlv_somatic_vcf} \${purple_dir_local}/${meta.tumor_wgs_id}.purple.somatic.vcf.gz; - ln -sf ../${smlv_germline_vcf} \${purple_dir_local}/${meta.tumor_wgs_id}.purple.germline.vcf.gz; + ln -sf ../${smlv_somatic_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.somatic.vcf.gz; + ln -sf ../${smlv_germline_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.germline.vcf.gz; fi # NOTE(SW): '--add-opens java.base/java.time=ALL-UNNAMED' resolves issue writing JSON, see: @@ -89,10 +89,8 @@ process ORANGE { -experiment_date \$(date +%y%m%d) \\ -pipeline_version_file pipeline_version.txt \\ \\ - -tumor_sample_id ${meta.tumor_wgs_id} \\ - \\ + -tumor_sample_id ${meta.tumor_id} \\ -primary_tumor_doids 162 \\ - \\ -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ -tumor_sample_flagstat_file ${flagstat_somatic} \\ -sage_somatic_tumor_sample_bqr_plot ${sage_somatic_bqr} \\ @@ -100,8 +98,8 @@ process ORANGE { -purple_plot_directory \${purple_dir_local}/plot/ \\ -linx_somatic_data_directory ${linx_somatic_anno_dir} \\ -linx_plot_directory ${linx_somatic_plot_dir} \\ - -lilac_result_csv ${lilac_dir}/${meta.tumor_wgs_id}.lilac.csv \\ - -lilac_qc_csv ${lilac_dir}/${meta.tumor_wgs_id}.lilac.qc.csv \\ + -lilac_result_csv ${lilac_dir}/${meta.tumor_id}.lilac.csv \\ + -lilac_qc_csv ${lilac_dir}/${meta.tumor_id}.lilac.qc.csv \\ ${virusinterpreter_arg} \\ ${chord_arg} \\ ${sigs_arg} \\ @@ -141,8 +139,8 @@ process ORANGE { stub: """ mkdir -p output/ - touch output/${meta.tumor_wgs_id}.orange.json - touch output/${meta.tumor_wgs_id}.orange.pdf + touch output/${meta.tumor_id}.orange.json + touch output/${meta.tumor_id}.orange.pdf echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 394fb50f..fbedd7ea 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -10,6 +10,7 @@ process PAVE_SOMATIC { path genome_fai val genome_ver path sage_pon + path sage_pon_artefacts path segment_mappability path driver_gene_panel path ensembl_data_resources @@ -25,6 +26,9 @@ process PAVE_SOMATIC { script: def args = task.ext.args ?: '' + + def pon_artefact_arg = sage_pon_artefacts ? "-pon_artefact_file ${sage_pon_artefacts}" : '' + def pon_filters def gnomad_args if (genome_ver == '37') { @@ -48,6 +52,7 @@ process PAVE_SOMATIC { -ref_genome_version ${genome_ver} \\ -pon_file ${sage_pon} \\ -pon_filters "${pon_filters}" \\ + ${pon_artefact_arg} \\ -driver_gene_panel ${driver_gene_panel} \\ -mappability_bed ${segment_mappability} \\ -ensembl_data_dir ${ensembl_data_resources} \\ diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index bd473a47..0f5b1a49 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -16,6 +16,9 @@ process PURPLE { path driver_gene_panel path ensembl_data_resources path germline_del + path target_region_bed + path target_region_ratios + path target_region_msi_indels output: tuple val(meta), path('purple/'), emit: purple_dir @@ -27,6 +30,8 @@ process PURPLE { script: def args = task.ext.args ?: '' + def reference_arg = meta.containsKey('normal_id') ? "-reference ${meta.normal_id}" : '' + def sv_tumor_vcf_arg = sv_tumor_vcf ? "-somatic_sv_vcf ${sv_tumor_vcf}" : '' def sv_normal_vcf_arg = sv_normal_vcf ? "-germline_sv_vcf ${sv_normal_vcf}" : '' @@ -35,8 +40,13 @@ process PURPLE { def smlv_tumor_vcf_fp = smlv_tumor_vcf ?: '' def smlv_normal_vcf_fp = smlv_normal_vcf ?: '' + def sage_known_hotspots_germline_arg = sage_known_hotspots_germline ? "-germline_hotspots ${sage_known_hotspots_germline}" : '' def germline_del_arg = germline_del ? "-germline_del_freq_file ${germline_del}" : '' + def target_region_bed_arg = target_region_bed ? "-target_regions_bed ${target_region_bed}" : '' + def target_region_ratios_arg = target_region_ratios ? "-target_regions_ratios ${target_region_ratios}" : '' + def target_region_msi_indels_arg = target_region_msi_indels ? "-target_regions_msi_indels ${target_region_msi_indels}" : '' + """ # For provided smlv VCFs, filter records that do not contain the required FORMAT/AD field and # get argument for PURPLE @@ -58,7 +68,7 @@ process PURPLE { -jar ${task.ext.jarPath} \\ ${args} \\ -tumor ${meta.tumor_id} \\ - -reference ${meta.normal_id} \\ + ${reference_arg} \\ -amber ${amber} \\ -cobalt ${cobalt} \\ ${sv_tumor_vcf_arg} \\ @@ -71,7 +81,10 @@ process PURPLE { -driver_gene_panel ${driver_gene_panel} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -somatic_hotspots ${sage_known_hotspots_somatic} \\ - -germline_hotspots ${sage_known_hotspots_germline} \\ + ${sage_known_hotspots_germline_arg} \\ + ${target_region_bed_arg} \\ + ${target_region_ratios_arg} \\ + ${target_region_msi_indels_arg} \\ ${germline_del_arg} \\ -gc_profile ${gc_profile} \\ -circos ${task.ext.circosPath} \\ diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 7c024955..c0ad0c9c 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -14,6 +14,7 @@ process SAGE_SOMATIC { val genome_ver path sage_known_hotspots_somatic path sage_actionable_panel + path sage_coverage_panel path sage_highconf_regions path ensembl_data_resources @@ -32,20 +33,23 @@ process SAGE_SOMATIC { script: def args = task.ext.args ?: '' + def reference_arg = meta.containsKey('normal_id') ? "-reference ${meta.normal_id}" : '' + def reference_bam_arg = normal_bam ? "-reference_bam ${normal_bam}" : '' + """ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ - -reference ${meta.normal_id} \\ - -reference_bam ${normal_bam} \\ + ${reference_arg} \\ + ${reference_bam_arg} \\ -tumor ${meta.tumor_id} \\ -tumor_bam ${tumor_bam} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -hotspots ${sage_known_hotspots_somatic} \\ -panel_bed ${sage_actionable_panel} \\ - -coverage_bed ${sage_actionable_panel} \\ + -coverage_bed ${sage_coverage_panel} \\ -high_confidence_bed ${sage_highconf_regions} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -write_bqr_data \\ diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 5929fb86..ba358a88 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -26,7 +26,8 @@ process GRIDSS_ASSEMBLE { def args = task.ext.args ?: '' def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' def output_dirname = 'gridss_assemble' - def labels_arg = labels.join(',') + def labels_list = labels instanceof List ? labels : [labels] + def labels_arg = labels_list.join(',') // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below def bams_list = bams instanceof List ? bams : [bams] def bams_arg = "--bams ${bams_list.join(',')}" diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index a85669ae..29b2e0dd 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -26,7 +26,8 @@ process GRIDSS_CALL { def args = task.ext.args ?: '' def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' def output_dirname = 'gridss_call' - def labels_arg = labels.join(',') + def labels_list = labels instanceof List ? labels : [labels] + def labels_arg = labels_list.join(',') // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below def bams_list = bams instanceof List ? bams : [bams] def bams_arg = "--bams ${bams_list.join(',')}" diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 74608189..0dbea3b1 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -18,7 +18,8 @@ process SVPREP_DEPTH_ANNOTATOR { script: def args = task.ext.args ?: '' - def labels_arg = labels.join(',') + def labels_list = labels instanceof List ? labels : [labels] + def labels_arg = labels_list.join(',') // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below def bams_list = bams instanceof List ? bams : [bams] def bams_arg = "${bams_list.join(',')}" diff --git a/nextflow.config b/nextflow.config index 5b83c018..c84c0999 100644 --- a/nextflow.config +++ b/nextflow.config @@ -12,8 +12,8 @@ params { // Input options input = null - // Pipeline run type - mode = 'full' + // Pipeline run configuration + processes_manual = false processes_include = null processes_exclude = null @@ -36,7 +36,7 @@ params { help = false validate_params = true show_hidden_params = false - schema_ignore_params = 'genomes,hmfdata_paths' + schema_ignore_params = 'genomes,hmf_data_paths' enable_conda = false // Other workflow inputs and options @@ -154,9 +154,9 @@ if (!params.igenomes_ignore) { params.genomes = [:] } -// Load hmfdata.config and hmfgenomes.config -includeConfig 'conf/hmfdata.config' -includeConfig 'conf/hmfgenomes.config' +// Load data configs +includeConfig 'conf/hmf_data.config' +includeConfig 'conf/hmf_genomes.config' // Export these variables to prevent local Python/R libraries from conflicting with those in the container diff --git a/nextflow_schema.json b/nextflow_schema.json index 3e87cf6f..a75e5af8 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -46,10 +46,14 @@ "help_text": "Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run.", "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" }, - "mode": { + "run_type": { "type": "string", - "default": "full", - "description": "Pipeline mode to use.", + "description": "Pipeline run type.", + "fa_icon": "fas fa-diagram-project" + }, + "run_mode": { + "type": "string", + "description": "Pipeline run mode.", "fa_icon": "fas fa-diagram-project" }, "force_genome": { @@ -57,6 +61,11 @@ "description": "Skip check for restricted genome.", "fa_icon": "fas fa-palette" }, + "processes_manual": { + "type": "boolean", + "description": "Run only processes manually provided in processes_include.", + "fa_icon": "fas fa-diagram-project" + }, "processes_exclude": { "type": "string", "description": "Pipeline processes to exclude.", @@ -193,289 +202,6 @@ } } }, - "hmf_data_options": { - "title": "HMF data options", - "type": "object", - "fa_icon": "fas fa-dna", - "description": "HMF data files for the workflow.", - "properties": { - "ref_data_heterozygous_sites": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to AMBER loci file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_gc_profile": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.cnp", - "description": "Path to COBALT GC profile file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_cuppa_resources": { - "type": "string", - "format": "directory-path", - "description": "Path to CUPPA reference file directory.", - "fa_icon": "far fa-folder-open", - "hidden": true - }, - "ref_data_sv_prep_blocklist": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed$", - "description": "Path to SV Prep blocklist file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_gridss_pon_breakends": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz", - "description": "Path to GRIDSS breakend PON file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_gridss_pon_breakpoints": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bedpe\\.gz$", - "description": "Path to GRIDSS breakpoint PON file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_gridss_region_blocklist": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to GRIDSS blocklist file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_repeatmasker_annotations": { - "type": "string", - "format": "file-path", - "description": "Path to RepeastMasker annotations file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_isofox_counts": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to Isofox expected read counts file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_isofox_gc_ratios": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to Isofox expected GC ratios file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_lilac_resources": { - "type": "string", - "format": "directory-path", - "description": "Path to LILAC resource directory.", - "fa_icon": "far fa-folder-open", - "hidden": true - }, - "ref_data_cohort_mapping": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to ORANGE cohort mapping file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_cohort_percentiles": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to ORANGE cohort percentiles file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_alt_sj_distribution": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv.gz$", - "description": "Path to ORANGE alternative splice junction distribution file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_gene_exp_distribution": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv.gz$", - "description": "Path to ORANGE gene expression distribution file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_clinvar_annotations": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to HMF ClinVar annotations VCF file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_sage_blocklist_regions": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to HMF SAGE known blocklist VCF file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_sage_blocklist_sites": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed$", - "description": "Path to HMF SAGE known blocklist BED file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_sage_actionable_panel": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to somatic SAGE actionable panel file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_sage_coverage_panel": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to HMF SAGE coverage panel file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_sage_highconf_regions": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to HMF distributed high confidence regions file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_sage_known_hotspots_germline": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to germline SAGE known hotspots file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_sage_known_hotspots_somatic": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.vcf\\.gz$", - "description": "Path to somatic SAGE known hotspots file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_sage_pon": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv\\.gz$", - "description": "Path to HMF SAGE panel of normals file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_sigs_signatures": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to signature definition file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_virus_reporting_db": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to Virus Interpreter reporting file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_virus_taxonomy_db": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to Virus Interpreter taxonomy file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_disease_ontology": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.json$", - "description": "Path to disease ontology file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_driver_gene_panel": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.tsv$", - "description": "Path to HMF driver gene panel file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_ensembl_data_resources": { - "type": "string", - "format": "directory-path", - "description": "Path to HMF Ensembl data cache directory.", - "fa_icon": "far fa-folder-open", - "hidden": true - }, - "ref_data_gnomad_resource": { - "type": "string", - "format": "file-path", - "description": "Path to HMF gnomAD resource.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_known_fusion_data": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to HMF known fusions data file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_known_fusions": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bedpe$", - "description": "Path to HMF known fusions file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_purple_germline_del": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.csv$", - "description": "Path to HMF PURPLE germline cohort deletion frequency file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "ref_data_segment_mappability": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.bed\\.gz$", - "description": "Path to HMF mappability file.", - "fa_icon": "far fa-file-code", - "hidden": true - } - } - }, "institutional_config_options": { "title": "Institutional config options", "type": "object", @@ -655,9 +381,6 @@ { "$ref": "#/definitions/reference_data_options" }, - { - "$ref": "#/definitions/hmf_data_options" - }, { "$ref": "#/definitions/institutional_config_options" }, diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index a97e0640..b5571ee2 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -1,50 +1,59 @@ // -// AMBER determines b-allele frequencies for downstream CNV calling +// AMBER determines b-allele frequencies at predetermined positions // import Utils include { AMBER } from '../../modules/local/amber/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - workflow AMBER_PROFILING { take: // Sample data ch_inputs // channel: [val(meta)] // Reference data - ref_data_genome_version // val: genome version - ref_data_heterozygous_sites // file: /path/to/heterozygous_sites + ref_data_genome_version + heterozygous_sites + + // Params + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - // Select input sources - // channel: [val(meta_amber), tumor_bam_wgs, normal_bam_wgs, tumor_bai_wgs, normal_bai_wgs] - ch_amber_inputs = CHANNEL_GROUP_INPUTS.out.wgs_present + // channel: [val(meta_amber), tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_amber_inputs = ch_inputs .map { meta -> def meta_amber = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), + tumor_id: Utils.getTumorSampleName(meta, run_config.mode), ] - def tumor_bam = Utils.getTumorWgsBam(meta) - def normal_bam = Utils.getNormalWgsBam(meta) - [meta_amber, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] + + def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + + def normal_bam = [] + def normal_bai = [] + + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + + assert [Constants.RunMode.WGS, Constants.RunMode.WGTS].contains(run_config.mode) + + meta_amber.normal_id = Utils.getNormalWgsSampleName(meta) + normal_bam = Utils.getNormalWgsBam(meta) + normal_bai = "${normal_bam}.bai" + + } + + [meta_amber, tumor_bam, normal_bam, "${tumor_bam}.bai", normal_bai] } // Run process AMBER( ch_amber_inputs, ref_data_genome_version, - ref_data_heterozygous_sites, + heterozygous_sites, ) // Set outputs, restoring original meta diff --git a/subworkflows/local/bamtools_metrics.nf b/subworkflows/local/bamtools_metrics.nf index 6da8bdc4..9b867e2d 100644 --- a/subworkflows/local/bamtools_metrics.nf +++ b/subworkflows/local/bamtools_metrics.nf @@ -1,13 +1,11 @@ // -// XXX +// Bam Tools calculates summary statistics for BAMs // import Constants import Utils include { BAMTOOLS } from '../../modules/local/bamtools/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - workflow BAMTOOLS_METRICS { take: // Sample data @@ -18,43 +16,39 @@ workflow BAMTOOLS_METRICS { ref_data_genome_version // Params - run + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - // Select input sources - // NOTE(SW): CUPPA only requires metrics for the tumor sample in the upstream - // process Virus Interpreter but ORANGE currently requires metrics for both tumor - // and normal sample // channel: [val(meta_bamtools), bam, bai] - ch_bamtools_inputs_all = CHANNEL_GROUP_INPUTS.out.wgs_present + ch_bamtools_inputs_all = ch_inputs .flatMap { meta -> - def sample_types - if (run.orange) { - sample_types = [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL] - } else { - sample_types = [Constants.SampleType.TUMOR] + def inputs = [] + + def meta_bamtools_tumor = [ + key: meta.id, + id: Utils.getTumorSampleName(meta, run_config.mode), + // NOTE(SW): must use string representation for caching purposes + sample_type_str: Constants.SampleType.TUMOR.name(), + ] + def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + inputs.add([meta_bamtools_tumor, tumor_bam, "${tumor_bam}.bai"]) + + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + def meta_bamtools_normal = [ + key: meta.id, + id: Utils.getNormalWgsSampleName(meta), + // NOTE(SW): must use string representation for caching purposes + sample_type_str: Constants.SampleType.NORMAL.name(), + ] + def normal_bam = Utils.getNormalWgsBam(meta) + inputs.add([meta_bamtools_normal, normal_bam, "${normal_bam}.bai"]) } - return sample_types - .collect { sample_type -> - def bam = meta.get([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) - def sample_name = meta.get(['sample_name', sample_type, Constants.SequenceType.WGS]) - def meta_bamtools = [ - key: meta.id, - id: sample_name, - // NOTE(SW): must use string representation for caching purposes - sample_type_str: sample_type.name(), - ] - return [meta_bamtools, bam, "${bam}.bai"] - } + return inputs } // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples @@ -91,7 +85,7 @@ workflow BAMTOOLS_METRICS { ref_data_genome_version, ) - // Set outputs, process outputs and restore original meta + // Set version ch_versions = ch_versions.mix(BAMTOOLS.out.versions) // Replicate outputs to reverse unique operation diff --git a/subworkflows/local/channel_group_inputs.nf b/subworkflows/local/channel_group_inputs.nf deleted file mode 100644 index 8da94256..00000000 --- a/subworkflows/local/channel_group_inputs.nf +++ /dev/null @@ -1,38 +0,0 @@ -import Constants -import Utils - -workflow CHANNEL_GROUP_INPUTS { - take: - ch_inputs - - main: - // channel (present): [val(meta)] - // channel (absent): [val(meta)] - ch_inputs_wgs = ch_inputs - .branch { meta -> - def key_tumor = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS] - def key_normal = [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.WGS] - present: meta.containsKey(key_tumor) && meta.containsKey(key_normal) - return meta - absent: true - return meta - } - - // channel (present): [val(meta)] - // channel (absent): [val(meta)] - ch_inputs_wts = ch_inputs - .branch { meta -> - def key = [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WTS] - present: meta.containsKey(key) - return meta - absent: ! meta.containsKey(key) - return meta - } - - emit: - wgs_present = ch_inputs_wgs.present - wgs_absent = ch_inputs_wgs.absent - - wts_present = ch_inputs_wts.present - wts_absent = ch_inputs_wts.absent -} diff --git a/subworkflows/local/channel_inputs_purple.nf b/subworkflows/local/channel_inputs_purple.nf new file mode 100644 index 00000000..5d1a2f16 --- /dev/null +++ b/subworkflows/local/channel_inputs_purple.nf @@ -0,0 +1,73 @@ +// +// XXX +// +import Constants + +workflow CHANNEL_INPUTS_PURPLE { + take: + // Sample data + ch_inputs + ch_amber + ch_cobalt + ch_smlv_somatic + ch_smlv_germline + ch_sv_somatic + ch_sv_germline + ch_sv_somatic_unfiltered + + // Params + run_config + + main: + // Set input sources + ch_amber_source = run_config.stages.amber ? ch_amber : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.AMBER_DIR) + ch_cobalt_source = run_config.stages.cobalt ? ch_cobalt : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.COBALT_DIR) + + if (run_config.stages.gripss) { + + ch_sv_somatic_source = ch_sv_somatic + ch_sv_somatic_unfiltered_source = ch_sv_somatic_unfiltered + ch_sv_germline_source = ch_sv_germline + + } else { + + ch_sv_somatic_source = getGripssSampleSheetInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_TUMOR) + ch_sv_somatic_unfiltered_source = getGripssSampleSheetInput(ch_inputs, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR) + ch_sv_germline_source = getGripssSampleSheetInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_NORMAL) + + } + + ch_smlv_somatic_source = run_config.stages.pave ? ch_smlv_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_TUMOR, type: 'optional') + ch_smlv_germline_source = run_config.stages.pave ? ch_smlv_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_NORMAL, type: 'optional') + + // Adjust for run type and mode + if (run_config.type == Constants.RunType.TUMOR_ONLY) { + + ch_sv_germline_source = ch_inputs.map { meta -> [meta, [], []] } + ch_smlv_germline_source = ch_inputs.map { meta -> [meta, []] } + + } + + // Combine into single channel + // channel: [val(meta), amber_dir, cobalt_dir, sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi, smlv_tumor_vcf, smlv_normal_vcf] + ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( + ch_amber_source, + ch_cobalt_source, + ch_sv_somatic_source, + ch_sv_somatic_unfiltered_source, + ch_sv_germline_source, + ch_smlv_somatic_source, + ch_smlv_germline_source, + ) + + emit: + ch_purple_inputs_source +} + +def getGripssSampleSheetInput(ch_inputs, input_type) { + WorkflowOncoanalyser.getInput(ch_inputs, input_type, type: 'optional') + .map { meta, vcf -> + def tbi = vcf == [] ? [] : "${vcf}.tbi" + return [meta, vcf, tbi] + } +} diff --git a/subworkflows/local/chord_prediction.nf b/subworkflows/local/chord_prediction.nf index 2113e053..d8d17e7e 100644 --- a/subworkflows/local/chord_prediction.nf +++ b/subworkflows/local/chord_prediction.nf @@ -1,5 +1,5 @@ // -// XXX +// CHORD predicts HR status // import Constants import Utils @@ -16,7 +16,7 @@ workflow CHORD_PREDICTION { ref_data_genome_version // Params - run + run_config main: // Channel for version.yml files @@ -24,7 +24,7 @@ workflow CHORD_PREDICTION { // Select input sources // channel: [val(meta), purple_dir] - if (run.purple) { + if (run_config.stages.purple) { ch_chord_inputs_source = ch_purple } else { ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) @@ -40,13 +40,13 @@ workflow CHORD_PREDICTION { // Require both SV and smlv VCF from the PURPLE directory if (!smlv_vcf.exists() || !sv_vcf.exists()) { - return Constants.META_PLACEHOLDER + return Constants.PLACEHOLDER_META } def meta_chord = [key: meta.id, id: meta.id] return [meta_chord, smlv_vcf, sv_vcf] } - .filter { it != Constants.META_PLACEHOLDER } + .filter { it != Constants.PLACEHOLDER_META } // Run process CHORD( diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index 7b5c0868..fac67d9d 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -1,48 +1,65 @@ // -// COBALT determines tumor/normal read ratios for downstream CNV calling +// COBALT calculates read ratios between tumor and normal samples // import Utils include { COBALT } from '../../modules/local/cobalt/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - workflow COBALT_PROFILING { take: // Sample data ch_inputs // channel: [val(meta)] // Reference data - ref_data_gc_profile // file: /path/to/gc_profile + gc_profile + diploid_bed + target_region_normalisation + + // Params + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - // Select input sources - // channel: [meta_cobalt, tumor_bam_wgs, normal_bam_wgs, tumor_bai_wgs, normal_bai_wgs] - ch_cobalt_inputs = CHANNEL_GROUP_INPUTS.out.wgs_present + // channel: [meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai] + ch_cobalt_inputs = ch_inputs .map { meta -> def meta_cobalt = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), + tumor_id: Utils.getTumorSampleName(meta, run_config.mode), ] - def tumor_bam = Utils.getTumorWgsBam(meta) - def normal_bam = Utils.getNormalWgsBam(meta) - return [meta_cobalt, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] + def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + + def normal_bam = [] + def normal_bai = [] + + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + + assert [Constants.RunMode.WGS, Constants.RunMode.WGTS].contains(run_config.mode) + + meta_cobalt.normal_id = Utils.getNormalWgsSampleName(meta) + normal_bam = Utils.getNormalWgsBam(meta) + normal_bai = "${normal_bam}.bai" + + } + + return [meta_cobalt, tumor_bam, normal_bam, "${tumor_bam}.bai", normal_bai] } + // Set reference files on run type + if (run_config.type != Constants.RunType.TUMOR_ONLY) { + diploid_bed = [] + } + // Run process COBALT( ch_cobalt_inputs, - ref_data_gc_profile, + gc_profile, + diploid_bed, + target_region_normalisation, ) // Set outputs, restoring original meta diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index 0e400560..c5033950 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -1,12 +1,10 @@ // -// XXX +// CUPPA predicts tissue of origin from molecular profiles // import Constants include { CUPPA } from '../../modules/local/cuppa/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - workflow CUPPA_PREDICTION { take: // Sample data @@ -20,38 +18,23 @@ workflow CUPPA_PREDICTION { ref_data_genome_version ref_data_cuppa_resources - // Parameters - run + // Params + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - // Select input sources // channel: [val(meta), isofox_dir] - ch_cuppa_inputs_isofox = Channel.empty() - if (run.isofox) { - // Take Isofox output and supplement with placeholders for missing; i.e. allow optional - ch_cuppa_inputs_isofox = ch_cuppa_inputs_isofox - .mix( - ch_isofox, - CHANNEL_GROUP_INPUTS.out.wts_absent.map { meta -> [meta, []] }, - ) - } else { - ch_cuppa_inputs_isofox = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX, type: 'optional') - } + ch_cuppa_inputs_isofox = run_config.stages.isofox ? ch_isofox : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional') // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter] ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, - run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional'), - run.linx ? ch_linx : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR, type: 'optional'), - run.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), + run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional'), + run_config.stages.linx ? ch_linx : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR, type: 'optional'), + run_config.stages.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), flatten_mode: 'nonrecursive', ) @@ -62,19 +45,19 @@ workflow CUPPA_PREDICTION { def meta = data[0] def meta_cuppa = [key: meta.id] - def sample_name_wgs = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) - def sample_name_wts = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) - - if (sample_name_wgs && sample_name_wts) { - meta_cuppa.id = sample_name_wgs - meta_cuppa.id_wts = sample_name_wts - } else if (sample_name_wgs) { - meta_cuppa.id = sample_name_wgs - } else if (sample_name_wts) { - meta_cuppa.id = sample_name_wts - } else { - log.error "ERROR: no sample name for: ${meta}" - System.exit(1) + switch (run_config.mode) { + case Constants.RunMode.WGS: + meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) + break + case Constants.RunMode.WTS: + meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + break + case Constants.RunMode.WGTS: + meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) + meta_cuppa.id_wts = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + break + default: + assert false } return [meta_cuppa, *data[1..-1]] diff --git a/subworkflows/local/flagstat_metrics.nf b/subworkflows/local/flagstat_metrics.nf index 18d6364c..8bea6733 100644 --- a/subworkflows/local/flagstat_metrics.nf +++ b/subworkflows/local/flagstat_metrics.nf @@ -8,37 +8,44 @@ include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/samtools/flagstat/main workflow FLAGSTAT_METRICS { take: + // Sample data ch_inputs + // Params + run_config + main: // Channel for version.yml files ch_versions = Channel.empty() // Select input source - // channel (present): [val(meta), sample_type, flagstat] - // channel (absent): [val(meta)] - ch_inputs_flagstat = ch_inputs - .flatMap { meta -> [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL].collect { [meta, it] } } - .branch { meta, sample_type -> - def key = [Constants.FileType.FLAGSTAT, sample_type, Constants.SequenceType.WGS] - present: meta.containsKey(key) - return [meta, sample_type, meta.getAt(key)] - absent: ! meta.containsKey(key) - } - - // Create inputs and create process-specific meta + // Select input sources // channel: [val(meta_flagstat), bam, bai] - ch_flagstat_inputs_all = ch_inputs_flagstat.absent - .map { meta, sample_type -> - def bam = meta.getAt([Constants.FileType.BAM, sample_type, Constants.SequenceType.WGS]) - def sample_name = meta.getAt(['sample_name', sample_type, Constants.SequenceType.WGS]) - def meta_flagstat = [ + ch_flagstat_inputs_all = ch_inputs + .flatMap { meta -> + def inputs = [] + + def meta_flagstat_tumor = [ key: meta.id, - id: sample_name, + id: Utils.getTumorSampleName(meta, run_config.mode), // NOTE(SW): must use string representation for caching purposes - sample_type_str: sample_type.name(), + sample_type_str: Constants.SampleType.TUMOR.name(), ] - return [meta_flagstat, bam, "${bam}.bai"] + def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + inputs.add([meta_flagstat_tumor, tumor_bam, "${tumor_bam}.bai"]) + + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + def meta_flagstat_normal = [ + key: meta.id, + id: Utils.getNormalWgsSampleName(meta), + // NOTE(SW): must use string representation for caching purposes + sample_type_str: Constants.SampleType.NORMAL.name(), + ] + def normal_bam = Utils.getNormalWgsBam(meta) + inputs.add([meta_flagstat_normal, normal_bam, "${normal_bam}.bai"]) + } + + return inputs } // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples @@ -72,10 +79,11 @@ workflow FLAGSTAT_METRICS { ) // Set version + ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) // Replicate outputs to reverse unique operation // channel: [val(meta_flagstat_individual), flagstat] - ch_flagstat_out = SAMTOOLS_FLAGSTAT.out.flagstat + ch_flagstat_out_individual = SAMTOOLS_FLAGSTAT.out.flagstat .flatMap { meta_flagstat_shared, flagstat -> def sample_type = Utils.getEnumFromString(meta_flagstat_shared.sample_type_str, Constants.SampleType) meta_flagstat_shared.keys.collect { key -> @@ -83,14 +91,10 @@ workflow FLAGSTAT_METRICS { } } - // Combine input flagstat channels, restoring original meta where required, split by sample type + // Set outputs // channel (somatic): [val(meta), flagstat] // channel (germline): [val(meta), flagstat] - ch_outputs = Channel.empty() - .concat( - ch_inputs_flagstat.present, - WorkflowOncoanalyser.restoreMeta(ch_flagstat_out, ch_inputs), - ) + ch_outputs = WorkflowOncoanalyser.restoreMeta(ch_flagstat_out_individual, ch_inputs) .branch { meta, sample_type, flagstat -> somatic: sample_type == Constants.SampleType.TUMOR return [meta, flagstat] diff --git a/subworkflows/local/gridss_calling.nf b/subworkflows/local/gridss_calling.nf deleted file mode 100644 index 71cef0e8..00000000 --- a/subworkflows/local/gridss_calling.nf +++ /dev/null @@ -1,166 +0,0 @@ -// -// GRIDSS is a software suite containing tools useful for the detection of genomic rearrangements. -// -import Constants -import Utils - -include { GRIDSS_ASSEMBLE as ASSEMBLE } from '../../modules/local/gridss/assemble/main' -include { GRIDSS_CALL as CALL } from '../../modules/local/gridss/call/main' -include { GRIDSS_PREPROCESS as PREPROCESS } from '../../modules/local/gridss/preprocess/main' - -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - -workflow GRIDSS_CALLING { - take: - // Sample data - ch_inputs // channel: [val(meta)] - - // Reference data - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_dict // file: /path/to/genome_dict - ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ - ref_data_genome_bwa_index_image // file: /path/to/genome_bwa_index_image - ref_data_genome_gridss_index // file: /path/to/genome_gridss_index - ref_data_gridss_blacklist // val: /path/to/gridss_blacklist - - // Params - gridss_config // file: /path/to/gridss_config (optional) - - main: - // Channel for version.yml files - ch_versions = Channel.empty() - - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - - // Gather BAMs and BAIs - ch_inputs_bam_bai = CHANNEL_GROUP_INPUTS.out.wgs_present - .map { meta -> - def tumor_bam = Utils.getTumorWgsBam(meta) - def normal_bam = Utils.getNormalWgsBam(meta) - [meta, tumor_bam, normal_bam] - } - - // Build a channel of individual BAMs for preprocessing - // channel: [val(meta_gridss), bam] - ch_preprocess_inputs = ch_inputs_bam_bai - .flatMap { meta, tbam, nbam -> - def sample_types = [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL] - sample_types - .collect { sample_type -> - def bam_fp - if (sample_type == Constants.SampleType.TUMOR) { - bam_fp = tbam - } else if (sample_type == Constants.SampleType.NORMAL) { - bam_fp = nbam - } else { - assert false : "got bad sample type" - } - def meta_gridss = [ - id: meta.get(['sample_name', sample_type, Constants.SequenceType.WGS]), - // NOTE(SW): must use string representation for caching purposes - sample_type_str: sample_type.name(), - subject_id: meta.id, - ] - return [meta_gridss, bam_fp] - } - } - - // Preprocess reads - PREPROCESS( - ch_preprocess_inputs, - gridss_config, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ) - ch_versions = ch_versions.mix(PREPROCESS.out.versions) - - // Gather BAMs and outputs from preprocessing for each tumor/normal set - // channel: [subject_id, [[val(meta_gridss), bam, preprocess_dir], ...]] - ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( - ch_preprocess_inputs, - PREPROCESS.out.preprocess_dir, - ) - .map { [it[0].subject_id, it] } - .groupTuple(size: 2) - - // Order and organise inputs for assembly - // channel: [val(meta_gridss), [bams], [preprocess_dirs], [labels]] - ch_assemble_inputs = ch_bams_and_preprocess - .map { subject_id, entries -> - def (tmeta, tbam, tpreprocess) = get_sample_type_entry(entries, Constants.SampleType.TUMOR) - def (nmeta, nbam, npreprocess) = get_sample_type_entry(entries, Constants.SampleType.NORMAL) - def meta_gridss = [id: tmeta.subject_id] - return [meta_gridss, [nbam, tbam], [npreprocess, tpreprocess], [nmeta.id, tmeta.id]] - } - - // Assemble variants - ASSEMBLE( - ch_assemble_inputs, - gridss_config, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ) - ch_versions = ch_versions.mix(ASSEMBLE.out.versions) - - // Prepare inputs for variant calling - // channel: [val(meta_gridss), [bams], assemble_dir, [labels]] - ch_call_inputs = WorkflowOncoanalyser.groupByMeta( - ch_assemble_inputs, - ASSEMBLE.out.assemble_dir, - flatten: false, - ) - .map { data -> - def meta = data[0] - def (bams, preprocess_dirs, labels) = data[1] - def (assemble_dir) = data[2] - return [meta, bams, assemble_dir, labels] - } - - // Call variants - CALL( - ch_call_inputs, - gridss_config, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blacklist, - ) - ch_versions = ch_versions.mix(CALL.out.versions) - - // Reunite final VCF with the corresponding input meta object - ch_out = Channel.empty() - .concat( - ch_inputs_bam_bai.map { meta, tbam, nbam -> [meta.id, meta] }, - CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, - ) - .groupTuple(size: 2) - .map { id, other -> other.flatten() } - - emit: - results = ch_out // channel: [val(meta), vcf] - - versions = ch_versions // channel: [versions.yml] -} - -def get_sample_type_entry(entries, sample_type) { - entries.find { e -> - def meta = e[0] - return Utils.getEnumFromString(meta.sample_type_str, Constants.SampleType) == sample_type - } -} diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index d5be34a9..bd334cbc 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -11,12 +11,11 @@ include { GRIDSS_PREPROCESS as PREPROCESS } from '../../modules/local/ include { SVPREP as SVPREP_NORMAL } from '../../modules/local/svprep/svprep/main' include { SVPREP as SVPREP_TUMOR } from '../../modules/local/svprep/svprep/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - workflow GRIDSS_SVPREP_CALLING { take: // Sample data ch_inputs // channel: [val(meta)] + gridss_config // file: /path/to/gridss_config (optional) // Reference data ref_data_genome_fasta // file: /path/to/genome_fasta @@ -31,27 +30,25 @@ workflow GRIDSS_SVPREP_CALLING { ref_data_known_fusions // file: /path/to/known_fusions // Params - gridss_config // file: /path/to/gridss_config (optional) + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - + // + // MODULE: SV Prep (tumor) + // // Prepare tumor sample inputs // channel: [val(meta_svprep), bam_tumor, bai_tumor, []] - ch_svprep_tumor_inputs = CHANNEL_GROUP_INPUTS.out.wgs_present + ch_svprep_tumor_inputs = ch_inputs .map { meta -> def meta_svprep = [ key: meta.id, - id: Utils.getTumorWgsSampleName(meta), + id: Utils.getTumorSampleName(meta, run_config.mode), sample_type: 'tumor', ] - def tumor_bam = Utils.getTumorWgsBam(meta) + def tumor_bam = Utils.getTumorBam(meta, run_config.mode) return [meta_svprep, tumor_bam, "${tumor_bam}.bai", []] } @@ -66,47 +63,60 @@ workflow GRIDSS_SVPREP_CALLING { ) ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) - // Prepare normal sample inputs - // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] - ch_svprep_normal_inputs = WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs) - .map { meta, junctions_tumor -> - def meta_svprep = [ - key: meta.id, - id: Utils.getNormalWgsSampleName(meta), - sample_type: 'normal', - ] - def normal_bam = Utils.getNormalWgsBam(meta) - return [meta_svprep, normal_bam, "${normal_bam}.bai", junctions_tumor] - } - - SVPREP_NORMAL( - ch_svprep_normal_inputs, - ref_data_genome_fasta, - ref_data_genome_version, - ref_data_sv_prep_blocklist, - ref_data_known_fusions, - false, // -write_types argument switch and value - ) - ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) - // channel: [val(meta_gridss), bam_tumor, bam_tumor_filtered] ch_preprocess_inputs_tumor = WorkflowOncoanalyser.groupByMeta( SVPREP_TUMOR.out.bam, ch_svprep_tumor_inputs, ) - .map { meta_svprep, bam_filtered, bam, bai -> + .map { meta_svprep, bam_filtered, bam, bai, jnc_optional -> return [meta_svprep, bam, bam_filtered] } + // + // MODULE: SV Prep (normal) + // // channel: [val(meta_gridss), bam_normal, bam_normal_filtered] - ch_preprocess_inputs_normal = WorkflowOncoanalyser.groupByMeta( - SVPREP_NORMAL.out.bam, - ch_svprep_normal_inputs, - ) - .map { meta_svprep, bam_filtered, bam, bai, junctions -> - return [meta_svprep, bam, bam_filtered] - } + ch_preprocess_inputs_normal = Channel.empty() + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + + assert [Constants.RunMode.WGS, Constants.RunMode.WGTS].contains(run_config.mode) + + // Prepare normal sample inputs + // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] + ch_svprep_normal_inputs = WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs) + .map { meta, junctions_tumor -> + def meta_svprep = [ + key: meta.id, + id: Utils.getNormalWgsSampleName(meta), + sample_type: 'normal', + ] + def normal_bam = Utils.getNormalWgsBam(meta) + return [meta_svprep, normal_bam, "${normal_bam}.bai", junctions_tumor] + } + SVPREP_NORMAL( + ch_svprep_normal_inputs, + ref_data_genome_fasta, + ref_data_genome_version, + ref_data_sv_prep_blocklist, + ref_data_known_fusions, + false, // -write_types argument switch and value + ) + ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) + + // channel: [val(meta_gridss), bam_normal, bam_normal_filtered] + ch_preprocess_inputs_normal = WorkflowOncoanalyser.groupByMeta( + SVPREP_NORMAL.out.bam, + ch_svprep_normal_inputs, + ) + .map { meta_svprep, bam_filtered, bam, bai, junctions -> + return [meta_svprep, bam, bam_filtered] + } + } + + // + // MODULE: GRIDSS preprocess + // // channel: [val(meta_gridss), bam, bam_filtered] ch_preprocess_inputs = Channel.empty() .mix( @@ -129,27 +139,51 @@ workflow GRIDSS_SVPREP_CALLING { // Gather BAMs and outputs from preprocessing for each tumor/normal set // channel: [key, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] + preprocess_group_tuple_size = run_config.type == Constants.RunType.TUMOR_NORMAL ? 2 : 1 ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( ch_preprocess_inputs, PREPROCESS.out.preprocess_dir, ) .map { [it[0].key, it] } - .groupTuple(size: 2) + .groupTuple(size: preprocess_group_tuple_size) + // + // MODULE: GRIDSS assemble + // // Order and organise inputs for assembly // channel: [val(meta_gridss), [bams], [bams_filtered], [preprocess_dirs], [labels]] ch_assemble_inputs = ch_bams_and_preprocess .map { key, entries -> def (tmeta, tbam, tbam_filtered, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } - def (nmeta, nbam, nbam_filtered, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } def meta_gridss = [id: tmeta.key] - return [ - meta_gridss, - [nbam, tbam], - [nbam_filtered, tbam_filtered], - [npreprocess, tpreprocess], - [nmeta.id, tmeta.id], - ] + + def data = [] + if (run_config.type == Constants.RunType.TUMOR_ONLY) { + + data = [ + meta_gridss, + tbam, + tbam_filtered, + tpreprocess, + tmeta.id, + ] + + } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + + def (nmeta, nbam, nbam_filtered, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } + data = [ + meta_gridss, + [nbam, tbam], + [nbam_filtered, tbam_filtered], + [npreprocess, tpreprocess], + [nmeta.id, tmeta.id], + ] + + } else { + assert false + } + + return data } // Assemble variants @@ -166,6 +200,9 @@ workflow GRIDSS_SVPREP_CALLING { ) ch_versions = ch_versions.mix(ASSEMBLE.out.versions) + // + // MODULE: GRIDSS call + // // Prepare inputs for variant calling // channel: [val(meta_gridss), [bams], [bams_filtered], assemble_dir, [labels]] ch_call_inputs = WorkflowOncoanalyser.groupByMeta( @@ -194,23 +231,48 @@ workflow GRIDSS_SVPREP_CALLING { ) ch_versions = ch_versions.mix(CALL.out.versions) + // + // MODULE: SV Prep depth annotation + // // Prepare inputs for depth annotation, restore original meta // channel: [val(meta_svprep), [bams], [bais], vcf, [labels]] ch_depth_inputs = WorkflowOncoanalyser.groupByMeta( - CHANNEL_GROUP_INPUTS.out.wgs_present.map { meta -> [meta.id, meta] }, + ch_inputs.map { meta -> [meta.id, meta] }, CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .map { id, meta, vcf -> - def tbam = Utils.getTumorWgsBam(meta) - def nbam = Utils.getNormalWgsBam(meta) + def tbam = Utils.getTumorBam(meta, run_config.mode) def meta_svprep = [id: meta.id] - return [ - meta_svprep, - [nbam, tbam], - ["${nbam}.bai", "${tbam}.bai"], - vcf, - [Utils.getNormalWgsSampleName(meta), Utils.getTumorWgsSampleName(meta)], - ] + + def data = [] + if (run_config.type == Constants.RunType.TUMOR_ONLY) { + + data = [ + meta_svprep, + tbam, + "${tbam}.bai", + vcf, + Utils.getTumorSampleName(meta, run_config.mode), + ] + + } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + + def nbam = Utils.getNormalWgsBam(meta) + + data = [ + meta_svprep, + [nbam, tbam], + ["${nbam}.bai", "${tbam}.bai"], + vcf, + [Utils.getNormalWgsSampleName(meta), Utils.getTumorWgsSampleName(meta)], + ] + + } else { + assert false + } + + return data + } // Add depth annotations to SVs @@ -223,7 +285,7 @@ workflow GRIDSS_SVPREP_CALLING { // Reunite final VCF with the corresponding input meta object ch_out = Channel.empty() .concat( - CHANNEL_GROUP_INPUTS.out.wgs_present.map { meta -> [meta.id, meta] }, + ch_inputs.map { meta -> [meta.id, meta] }, DEPTH_ANNOTATOR.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .groupTuple(size: 2) diff --git a/subworkflows/local/gripss_filtering.nf b/subworkflows/local/gripss_filtering.nf index 7f7cc2c8..d91c60b4 100644 --- a/subworkflows/local/gripss_filtering.nf +++ b/subworkflows/local/gripss_filtering.nf @@ -19,9 +19,10 @@ workflow GRIPSS_FILTERING { breakpoint_pon // file: /path/to/breakpoint_pon known_fusions // file: /path/to/known_fusions repeatmasker_annotations // file: /path/to/repeatmasker_annotations + target_regions_bed // Params - run + run_config main: // Channel for version.yml files @@ -29,33 +30,54 @@ workflow GRIPSS_FILTERING { // Select input source // channel: [val(meta), gridss_vcf] - ch_gripss_inputs_source = run.gridss ? ch_gridss : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIDSS_VCF) + ch_gripss_inputs_source = run_config.stages.gridss ? ch_gridss : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIDSS_VCF) // Create inputs and create process-specific meta // channel: [val(meta_gripss), gridss_vcf] ch_gripss_inputs = ch_gripss_inputs_source - .filter { it[0] != Constants.META_PLACEHOLDER } + .filter { it[0] != Constants.PLACEHOLDER_META } .map { meta, gridss_vcf -> + def meta_gripss = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), + tumor_id: Utils.getTumorSampleName(meta, run_config.mode), ] + + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + meta_gripss.normal_id = Utils.getNormalWgsSampleName(meta) + } + return [meta_gripss, gridss_vcf] } - GERMLINE( - ch_gripss_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, - breakend_pon, - breakpoint_pon, - known_fusions, - repeatmasker_annotations, - ) + // + // MODULE: GRIPSS germline + // + ch_germline_out = Channel.empty() + ch_germline_unfiltered_out = Channel.empty() + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + + GERMLINE( + ch_gripss_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_version, + breakend_pon, + breakpoint_pon, + known_fusions, + repeatmasker_annotations, + ) + ch_versions = ch_versions.mix(GERMLINE.out.versions) + ch_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) + ch_germline_unfiltered_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_unfiltered, ch_inputs) + + } + + // + // MODULE: GRIPSS somatic + // SOMATIC( ch_gripss_inputs, ref_data_genome_fasta, @@ -65,17 +87,12 @@ workflow GRIPSS_FILTERING { breakpoint_pon, known_fusions, repeatmasker_annotations, + target_regions_bed, ) - ch_versions = ch_versions.mix( - GERMLINE.out.versions, - SOMATIC.out.versions, - ) - + ch_versions = ch_versions.mix(SOMATIC.out.versions) ch_somatic_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs) - ch_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) ch_somatic_unfiltered_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_unfiltered, ch_inputs) - ch_germline_unfiltered_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_unfiltered, ch_inputs) emit: somatic = ch_somatic_out // channel: [val(meta), vcf, tbi] diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf index caf574cd..e9d62f63 100644 --- a/subworkflows/local/isofox_quantification.nf +++ b/subworkflows/local/isofox_quantification.nf @@ -5,8 +5,6 @@ import Utils include { ISOFOX } from '../../modules/local/isofox/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - workflow ISOFOX_QUANTIFICATION { take: // Sample data @@ -23,24 +21,24 @@ workflow ISOFOX_QUANTIFICATION { // Params isofox_functions //use_isofox_exp_counts_cache + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - // Create inputs and create process-specific meta // channel: [meta_isofox, tumor_bam_wts] - ch_isofox_inputs = CHANNEL_GROUP_INPUTS.out.wts_present - .map { meta -> - def bam = Utils.getTumorWtsBam(meta) - def meta_isofox = [key: meta.id, id: Utils.getTumorWtsSampleName(meta)] - return [meta_isofox, bam, "${bam}.bai"] - } + if (run_config.stages.isofox) { + ch_isofox_inputs = ch_inputs + .map { meta -> + def bam = Utils.getTumorWtsBam(meta) + def meta_isofox = [key: meta.id, id: Utils.getTumorWtsSampleName(meta)] + return [meta_isofox, bam, "${bam}.bai"] + } + } else { + ch_isofox_inputs = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional') + } // Set Isofox cache files // NOTE(SW): the Isofox expected count file is read length dependent so required users to explicitly use expect diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index 74705d3e..4ea8d923 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -9,8 +9,6 @@ include { CUSTOM_REALIGNREADS as REALIGNREADS } from '../../modules/local/cust include { CUSTOM_SLICE as SLICEBAM } from '../../modules/local/custom/lilac_slice/main' include { LILAC } from '../../modules/local/lilac/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - workflow LILAC_CALLING { take: // Sample data @@ -24,70 +22,86 @@ workflow LILAC_CALLING { ref_data_hla_slice_bed // Params - run + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - // Select input sources // channel: [val(meta), purple_dir] - if (run.purple) { - ch_lilac_inputs_purple = Channel.empty() - .mix( - ch_purple, - CHANNEL_GROUP_INPUTS.out.wgs_absent.map { meta -> [meta, []] }, - ) + if (run_config.stages.purple) { + ch_lilac_inputs_purple = ch_purple } else { ch_lilac_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional') } // Create channel with all available input BAMs - // First obtain WTS BAMs // channel: [val(meta), wts_bam, wts_bai] ch_lilac_bams_wts = Channel.empty() - .mix( - CHANNEL_GROUP_INPUTS.out.wts_present.map { meta -> + if (run_config.mode == Constants.RunMode.WTS || run_config.mode == Constants.RunMode.WGTS) { + ch_lilac_bams_wts = ch_inputs + .map { meta -> def bam = Utils.getTumorWtsBam(meta) return [meta, bam, "${bam}.bai"] - }, - CHANNEL_GROUP_INPUTS.out.wts_absent.map { meta -> [meta, [], []] }, - ) + } + } else { + ch_lilac_bams_wts = ch_inputs.map { meta -> [meta, [], []] } + } + + // channel: [val(meta), bam, bai] + ch_lilac_bams = Channel.empty() + if (run_config.mode == Constants.RunMode.WGS || run_config.mode == Constants.RunMode.WGTS) { + + ch_lilac_bams = ch_inputs + .map { meta -> - ch_lilac_bams_wgs = Channel.empty() - .mix( - CHANNEL_GROUP_INPUTS.out.wgs_present.map { meta -> def tumor_bam = Utils.getTumorWgsBam(meta) - def normal_bam = Utils.getNormalWgsBam(meta) - [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] - }, - CHANNEL_GROUP_INPUTS.out.wgs_absent.map { meta -> [meta, [], [], [], []] }, - ) - // Combine WGS and WTS BAMs - // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] + def normal_bam = [] + def normal_bai = [] + + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + normal_bam = Utils.getNormalWgsBam(meta) + normal_bai = "${normal_bam}.bai" + } + + [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", normal_bai] + } + + } else { + ch_lilac_bams = ch_inputs.map { meta -> [meta, [], [], [], []] } + } + + // Combine BAMs + // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai] ch_lilac_bams = WorkflowOncoanalyser.groupByMeta( ch_lilac_bams_wts, - ch_lilac_bams_wgs, + ch_lilac_bams, flatten_mode: 'nonrecursive', ) .map { data -> def meta = data[0] - def (tbam_wts, tbai_wts, tbam_wgs, nbam_wgs, tbai_wgs, nbai_wgs) = data[1..-1] - return [meta, nbam_wgs, nbai_wgs, tbam_wgs, tbai_wgs, tbam_wts, tbai_wts] + def (tbam_wts, tbai_wts, tbam, nbam, tbai, nbai) = data[1..-1] + return [meta, nbam, nbai, tbam, tbai, tbam_wts, tbai_wts] } + // Set tumor sequence type for non-WTS input (i.e. WGS or panel) + switch(run_config.mode) { + case Constants.RunMode.WGS: + case Constants.RunMode.WGTS: + tumor_sequence_type = Constants.SequenceType.WGS + break + default: + assert false + } + // Slice HLA regions // NOTE(SW): here I remove duplicate files so that we only process each input once // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used // in Pipeline5, see LilacBamSlicer.java#L115 // channel: [val(meta_lilac), bam, bai] - ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_lilac_bams) + ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_lilac_bams, tumor_sequence_type) // Isolate meta containing expected file count to use for non-blocking groupTuple later ch_slice_meta_individual = ch_slice_inputs .map { @@ -121,12 +135,13 @@ workflow LILAC_CALLING { ch_slice_bams = SLICEBAM.out.bam .branch { meta_lilac, bam, bai -> def sequence_type = Utils.getEnumFromString(meta_lilac.sequence_type_str, Constants.SequenceType) - wgs: sequence_type == Constants.SequenceType.WGS wts: sequence_type == Constants.SequenceType.WTS + // WGS or targetted + non_wts: sequence_type != Constants.SequenceType.WTS } REALIGNREADS( - ch_slice_bams.wgs, + ch_slice_bams.non_wts, EXTRACTCONTIG.out.contig, EXTRACTCONTIG.out.bwa_indices, ) @@ -153,47 +168,44 @@ workflow LILAC_CALLING { ) // Gather and order files from same grouping using non-blocked groupTuple via provided file counts - // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] - ch_slices_organised = WorkflowLilac.sortSlices(ch_slices_ready) + // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai] + ch_slices_organised = WorkflowLilac.sortSlices(ch_slices_ready, tumor_sequence_type) // Restore original meta so we can join with PURPLE directory // channel: [val(meta)] ch_metas = ch_lilac_bams.map { return it[0] } - // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] + // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai] ch_lilac_inputs_slices = WorkflowOncoanalyser.restoreMeta( ch_slices_organised, ch_metas, ) // Get inputs from PURPLE - // Set PURPLE directory source first - ch_purple_dir_source = run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - // channel: [val(meta), gene_cn] - ch_lilac_inputs_gene_cn = ch_purple_dir_source + ch_lilac_inputs_gene_cn = ch_lilac_inputs_purple .map { meta, purple_dir -> if (purple_dir == []) { return [meta, []] } - def tumor_id = Utils.getTumorWgsSampleName(meta) + def tumor_id = Utils.getTumorSampleName(meta, run_config.mode) def gene_cn = file(purple_dir).resolve("${tumor_id}.purple.cnv.gene.tsv") return gene_cn.exists() ? [meta, gene_cn] : [meta, []] } // channel: [val(meta), smlv_vcf] - ch_lilac_inputs_smlv_vcf = ch_purple_dir_source + ch_lilac_inputs_smlv_vcf = ch_lilac_inputs_purple .map { meta, purple_dir -> if (purple_dir == []) { return [meta, []] } - def tumor_id = Utils.getTumorWgsSampleName(meta) + def tumor_id = Utils.getTumorSampleName(meta, run_config.mode) def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") return smlv_vcf.exists() ? [meta, smlv_vcf] : [meta, []] } - // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai, purple_dir] + // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, purple_dir] ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( ch_lilac_inputs_slices, ch_lilac_inputs_gene_cn, @@ -202,7 +214,7 @@ workflow LILAC_CALLING { ) // Create final input channel for LILAC, remove samples with only WTS BAMs - // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai, gene_cn, smlv_vcf]] + // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, gene_cn, smlv_vcf]] ch_lilac_inputs = ch_lilac_inputs_full .map { def meta = it[0] @@ -210,11 +222,11 @@ workflow LILAC_CALLING { // LILAC requires either tumor or normal WGS BAM if (fps[0] == [] && fps[2] == []) { - return Constants.META_PLACEHOLDER + return Constants.PLACEHOLDER_META } - def tumor_id_key = ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS] def normal_id_key = ['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.WGS] + def tumor_id_key = ['sample_name', Constants.SampleType.TUMOR, tumor_sequence_type] def meta_lilac = [ key: meta.id, @@ -224,7 +236,7 @@ workflow LILAC_CALLING { ] return [meta_lilac, *fps] } - .filter { it != Constants.META_PLACEHOLDER } + .filter { it != Constants.PLACEHOLDER_META } // Run LILAC LILAC( diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf index abe7708c..cdce9c8d 100644 --- a/subworkflows/local/linx_annotation.nf +++ b/subworkflows/local/linx_annotation.nf @@ -21,7 +21,7 @@ workflow LINX_ANNOTATION { gene_id_file // file: /path/to/linx_gene_id_file // Params - run + run_config main: // Channel for versions.yml files @@ -29,46 +29,63 @@ workflow LINX_ANNOTATION { // Select input sources // channel: [val(meta), purple_dir] - ch_linx_inputs_source = run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + ch_linx_inputs_source = run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - // Create inputs and create process-specific meta - // channel: [val(meta_linx), sv_vcf] - ch_linx_inputs_germline = ch_linx_inputs_source - .map { meta, purple_dir -> + // + // MODULE: LINX germline annotation + // + ch_linx_germline_out = Channel.empty() + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - def tumor_id = Utils.getTumorWgsSampleName(meta) - def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") + // Create germline inputs and create process-specific meta + // channel: [val(meta_linx), sv_vcf] + ch_linx_inputs_germline = ch_linx_inputs_source + .map { meta, purple_dir -> - if (!sv_vcf.exists()) { - return Constants.META_PLACEHOLDER - } + def tumor_id = Utils.getTumorSampleName(meta, run_config.mode) + def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.germline.vcf.gz") - def meta_linx = [ - key: meta.id, - id: Utils.getNormalWgsSampleName(meta), - ] + if (!sv_vcf.exists()) { + return Constants.PLACEHOLDER_META + } - return [meta_linx, sv_vcf] - } - .filter { it != Constants.META_PLACEHOLDER } + def meta_linx = [ + key: meta.id, + id: Utils.getNormalWgsSampleName(meta), + ] + return [meta_linx, sv_vcf] + } + .filter { it != Constants.PLACEHOLDER_META } + + + GERMLINE( + ch_linx_inputs_germline, + ref_data_genome_version, + ref_data_ensembl_data_resources, + ref_data_driver_gene_panel, + ) + + // Set outputs, restoring original meta + ch_versions = ch_versions.mix(GERMLINE.out.versions) + // channel: [val(meta), linx_annotation_dir] + ch_linx_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.annotation_dir, ch_inputs) + } + + // + // MODULE: LINX somatic annotation + // + // Create somatic inputs and create process-specific meta // channel: [val(meta_linx), purple_dir] ch_linx_inputs_somatic = ch_linx_inputs_source .map { meta, purple_dir -> def meta_linx = [ key: meta.id, - id: Utils.getTumorWgsSampleName(meta), + id: Utils.getTumorSampleName(meta, run_config.mode), ] return [meta_linx, purple_dir] } - GERMLINE( - ch_linx_inputs_germline, - ref_data_genome_version, - ref_data_ensembl_data_resources, - ref_data_driver_gene_panel, - ) - SOMATIC( ch_linx_inputs_somatic, ref_data_genome_version, @@ -79,14 +96,9 @@ workflow LINX_ANNOTATION { ) // Set outputs, restoring original meta - ch_versions = ch_versions.mix( - SOMATIC.out.versions, - GERMLINE.out.versions, - ) - + ch_versions = ch_versions.mix(SOMATIC.out.versions) // channel: [val(meta), linx_annotation_dir] ch_linx_somatic_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.annotation_dir, ch_inputs) - ch_linx_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.annotation_dir, ch_inputs) emit: somatic = ch_linx_somatic_out // channel: [val(meta), linx_annotation_dir] diff --git a/subworkflows/local/linx_plotting.nf b/subworkflows/local/linx_plotting.nf index b407d095..80f6b1fe 100644 --- a/subworkflows/local/linx_plotting.nf +++ b/subworkflows/local/linx_plotting.nf @@ -16,6 +16,9 @@ workflow LINX_PLOTTING { ref_data_genome_version // val: genome version ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + // Params + run_config + main: // Channel for versions.yml files ch_versions = Channel.empty() @@ -26,7 +29,7 @@ workflow LINX_PLOTTING { .map { meta, anno_dir -> def meta_linx = [ key: meta.id, - id: Utils.getTumorWgsSampleName(meta), + id: Utils.getTumorSampleName(meta, run_config.mode), ] return [meta_linx, anno_dir] } @@ -51,7 +54,7 @@ workflow LINX_PLOTTING { .map { meta, anno_dir, vis_dir -> def meta_gpgr_linx = [ key: meta.id, - id: Utils.getTumorWgsSampleName(meta), + id: Utils.getTumorSampleName(meta, run_config.mode), ] return [meta_gpgr_linx, anno_dir, vis_dir] } diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 1c3cdc13..3e5eef62 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -6,8 +6,7 @@ import Utils include { ORANGE } from '../../modules/local/orange/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' -include { FLAGSTAT_METRICS } from './flagstat_metrics' +include { FLAGSTAT_METRICS } from './flagstat_metrics' workflow ORANGE_REPORTING { take: @@ -43,27 +42,23 @@ workflow ORANGE_REPORTING { ref_data_isofox_gene_distribution // Params - run + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - // // SUBWORKFLOW: Run SAMtools flagstat to generate stats required for ORANGE // // channel: [val(meta), metrics] ch_flagstat_somatic_out = Channel.empty() ch_flagstat_germline_out = Channel.empty() - if (run.flagstat) { + if (run_config.stages.flagstat) { FLAGSTAT_METRICS( - CHANNEL_GROUP_INPUTS.out.wgs_present, + ch_inputs, + run_config, ) ch_versions = ch_versions.mix(FLAGSTAT_METRICS.out.versions) @@ -74,62 +69,75 @@ workflow ORANGE_REPORTING { // // MODULE: Run ORANGE // + // Create placeholders for tumor-only + if (run_config.type == Constants.RunType.TUMOR_ONLY) { + ch_bamtools_germline = ch_inputs.map { meta -> [meta, []] } + ch_sage_germline_append = ch_inputs.map { meta -> [meta, []] } + ch_flagstat_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_germline_coverage = ch_inputs.map { meta -> [meta, []] } + ch_linx_germline_annotation = ch_inputs.map { meta -> [meta, []] } + ch_sage_somatic_normal_bqr = ch_inputs.map { meta -> [meta, []] } + } + // Get PURPLE input source for processing - ch_orange_inputs_purple_dir = run.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + ch_orange_inputs_purple_dir = run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) // Get input smlv somatic VCF from either PURPLE or SAGE append - // NOTE(SW): a better test would be WTS or WGTS; this will be implemented as run mode (WGS/WTS/WGTS, - // panel, MRD) along with input type (tumor-only, tumor/normal) - // channel: [meta, smlv_somatic_vcf, smlv_germline_vcf] - ch_orange_inputs_smlv_vcfs_append = WorkflowOncoanalyser.groupByMeta( - ch_sage_somatic_append, - ch_sage_germline_append, - ) - // NOTE(SW): using .join for selection only - .join(CHANNEL_GROUP_INPUTS.out.wts_present) - - // channel: [meta, smlv_somatic_vcf, smlv_germline_vcf] - ch_orange_inputs_smlv_vcfs_purple_dir = CHANNEL_GROUP_INPUTS.out.wts_absent - .join(ch_orange_inputs_purple_dir) - .map { meta, purple_dir -> - def tumor_id = Utils.getTumorWgsSampleName(meta) - def smlv_somatic_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - def smlv_germline_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") - - // Require smlv somatic VCF from the PURPLE directory - if (!smlv_somatic_vcf.exists() || !smlv_germline_vcf.exists()) { - return Constants.META_PLACEHOLDER + if (run_config.mode == Constants.RunMode.WGS) { + + ch_orange_inputs_smlv_vcfs = ch_orange_inputs_purple_dir + .map { meta, purple_dir -> + def tumor_id = Utils.getTumorSampleName(meta, run_config.mode) + + def smlv_somatic_vcf = [] + def smlv_germline_vcf = [] + + def smlv_somatic_vcf_path = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + def smlv_germline_vcf_path = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") + + if (smlv_somatic_vcf_path.exists()) { + smlv_somatic_vcf = smlv_somatic_vcf_path + } + + // NOTE(SW): can only evaluate to true with WGS tumor/normal + if (smlv_germline_vcf_path.exists()) { + smlv_germline_vcf = smlv_germline_vcf_path + } + + return [meta, smlv_somatic_vcf, smlv_germline_vcf] } - return [meta, smlv_somatic_vcf, smlv_germline_vcf] - } + } else if (run_config.mode == Constants.RunMode.WGTS) { - ch_orange_inputs_smlv_vcfs = Channel.empty() - .mix( - ch_orange_inputs_smlv_vcfs_append, - ch_orange_inputs_smlv_vcfs_purple_dir, + ch_orange_inputs_smlv_vcfs = WorkflowOncoanalyser.groupByMeta( + ch_sage_somatic_append, + ch_sage_germline_append, ) + } else { + ch_orange_inputs_smlv_vcfs = ch_inputs.map { meta -> [meta, [], []] } + } + // Select input source ch_orange_inputs_source = WorkflowOncoanalyser.groupByMeta( - run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_TUMOR), - run.bamtools ? ch_bamtools_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_NORMAL, type: 'optional'), - run.flagstat ? ch_flagstat_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_TUMOR), - run.flagstat ? ch_flagstat_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_NORMAL, type: 'optional'), - run.sage ? ch_sage_somatic_tumor_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_TUMOR), - run.sage ? ch_sage_somatic_normal_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_NORMAL, type: 'optional'), - run.sage ? ch_sage_germline_coverage : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_COVERAGE, type: 'optional'), + run_config.stages.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_TUMOR), + run_config.stages.bamtools ? ch_bamtools_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_NORMAL, type: 'optional'), + run_config.stages.flagstat ? ch_flagstat_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_TUMOR), + run_config.stages.flagstat ? ch_flagstat_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_NORMAL, type: 'optional'), + run_config.stages.sage ? ch_sage_somatic_tumor_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_TUMOR), + run_config.stages.sage ? ch_sage_somatic_normal_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_NORMAL, type: 'optional'), + run_config.stages.sage ? ch_sage_germline_coverage : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_COVERAGE, type: 'optional'), ch_orange_inputs_purple_dir, ch_orange_inputs_smlv_vcfs, - run.linx ? ch_linx_somatic_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), - run.linx ? ch_linx_somatic_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_TUMOR), - run.linx ? ch_linx_germline_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_NORMAL, type: 'optional'), - run.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), - run.chord ? ch_chord : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_PREDICITION, type: 'optional'), - run.sigs ? ch_sigs : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SIGS_DIR, type: 'optional'), - run.lilac ? ch_lilac : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), - run.cuppa ? ch_cuppa : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_DIR, type: 'optional'), - run.isofox ? ch_isofox : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional'), + run_config.stages.linx ? ch_linx_somatic_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + run_config.stages.linx ? ch_linx_somatic_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_TUMOR), + run_config.stages.linx ? ch_linx_germline_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_NORMAL, type: 'optional'), + run_config.stages.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), + run_config.stages.chord ? ch_chord : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_PREDICTION, type: 'optional'), + run_config.stages.sigs ? ch_sigs : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SIGS_DIR, type: 'optional'), + run_config.stages.lilac ? ch_lilac : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), + run_config.stages.cuppa ? ch_cuppa : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_DIR, type: 'optional'), + run_config.stages.isofox ? ch_isofox : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional'), flatten_mode: 'nonrecursive', ) @@ -144,7 +152,7 @@ workflow ORANGE_REPORTING { def meta_orange = [ key: meta.id, id: meta.id, - tumor_wgs_id: Utils.getTumorWgsSampleName(meta), + tumor_id: Utils.getTumorSampleName(meta, run_config.mode), ] // Add optional identifiers to meta diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf index 36fbb13d..b823b732 100644 --- a/subworkflows/local/pave_annotation.nf +++ b/subworkflows/local/pave_annotation.nf @@ -17,6 +17,7 @@ workflow PAVE_ANNOTATION { ref_data_genome_fai // file: /path/to/genome_fai ref_data_genome_version // val: genome version ref_data_sage_pon // file: /path/to/sage_pon + ref_data_sage_pon_artefacts // file: /path/to/sage_pon_artefacts ref_data_sage_blocklist_regions // file: /path/to/sage_blocklist_regions ref_data_sage_blocklist_sites // file: /path/to/sage_blocklist_sites ref_data_clinvar_annotations // file: /path/to/clinvar_annotations @@ -26,7 +27,7 @@ workflow PAVE_ANNOTATION { ref_data_gnomad_resource // file: /path/to/gnomad_resource // Params - run + run_config main: // Channel for version.yml files @@ -34,69 +35,83 @@ workflow PAVE_ANNOTATION { // Select input sources // channel: [meta, sage_vcf, sage_tbi] - if (run.sage) { + if (run_config.stages.sage) { ch_pave_germline_inputs_source = ch_sage_germline_vcf ch_pave_somatic_inputs_source = ch_sage_somatic_vcf } else { - ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_TUMOR) - .filter { it[0] != Constants.META_PLACEHOLDER } - ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_NORMAL) - .filter { it[0] != Constants.META_PLACEHOLDER } + ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_NORMAL) + .filter { it[0] != Constants.PLACEHOLDER_META } + .map { meta, vcf -> [meta, vcf, "${vcf}.tbi"] } + ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_TUMOR) + .filter { it[0] != Constants.PLACEHOLDER_META } + .map { meta, vcf -> [meta, vcf, "${vcf}.tbi"] } } + // + // MODULE: PAVE germline + // + ch_germline_out = Channel.empty() + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + + // Create inputs and create process-specific meta + // channel: [val(meta_pave), sage_vcf] + ch_pave_germline_inputs = ch_pave_germline_inputs_source + .map { meta, sage_vcf, sage_tbi -> + def pave_meta = [ + key: meta.id, + // NOTE(SW): use of tumor sample name for PAVE germline is correct + id: Utils.getTumorSampleName(meta, run_config.mode), + ] + return [pave_meta, sage_vcf] + } + + GERMLINE( + ch_pave_germline_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_version, + ref_data_sage_blocklist_regions, + ref_data_sage_blocklist_sites, + ref_data_clinvar_annotations, + ref_data_segment_mappability, + ref_data_driver_gene_panel, + ref_data_ensembl_data_resources, + ) + + ch_versions = ch_versions.mix(GERMLINE.out.versions) + ch_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) + + } + + // + // MODULE: PAVE somatic + // // Create inputs and create process-specific meta // channel: [val(meta_pave), sage_vcf] - ch_pave_germline_inputs = ch_pave_germline_inputs_source - .map { meta, sage_vcf, sage_tbi -> - def pave_meta = [ - key: meta.id, - // NOTE(SW): use of tumor sample name for PAVE germline is correct - id: Utils.getTumorWgsSampleName(meta), - ] - return [pave_meta, sage_vcf] - } - ch_pave_somatic_inputs = ch_pave_somatic_inputs_source .map { meta, sage_vcf, sage_tbi -> def pave_meta = [ key: meta.id, - id: Utils.getTumorWgsSampleName(meta), + id: Utils.getTumorSampleName(meta, run_config.mode), ] return [pave_meta, sage_vcf] } - GERMLINE( - ch_pave_germline_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_sage_blocklist_regions, - ref_data_sage_blocklist_sites, - ref_data_clinvar_annotations, - ref_data_segment_mappability, - ref_data_driver_gene_panel, - ref_data_ensembl_data_resources, - ) - SOMATIC( ch_pave_somatic_inputs, ref_data_genome_fasta, ref_data_genome_fai, ref_data_genome_version, ref_data_sage_pon, + ref_data_sage_pon_artefacts, ref_data_segment_mappability, ref_data_driver_gene_panel, ref_data_ensembl_data_resources, ref_data_gnomad_resource, ) - // Set outputs - ch_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) + ch_versions = ch_versions.mix(SOMATIC.out.versions) ch_somatic_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs) - ch_versions = ch_versions.mix( - GERMLINE.out.versions, - SOMATIC.out.versions, - ) emit: germline = ch_germline_out // channel: [val(meta), pave_vcf] diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf index c1685d90..93b9a50a 100644 --- a/subworkflows/local/prepare_input.nf +++ b/subworkflows/local/prepare_input.nf @@ -4,9 +4,36 @@ import Utils workflow PREPARE_INPUT { take: + // Sample data ch_samplesheet + // Params + run_config + main: + + if (run_config.type == Constants.RunType.TUMOR_ONLY) { + sample_types_allowed = [Constants.SampleType.TUMOR] + } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + sample_types_allowed = [ + Constants.SampleType.TUMOR, + Constants.SampleType.NORMAL, + Constants.SampleType.TUMOR_NORMAL, + ] + } else { + assert false + } + + if (run_config.mode == Constants.RunMode.WGS) { + sequence_types_allowed = [Constants.SequenceType.WGS] + } else if (run_config.mode == Constants.RunMode.WTS) { + sequence_types_allowed = [Constants.SequenceType.WTS] + } else if (run_config.mode == Constants.RunMode.WGTS) { + sequence_types_allowed = [Constants.SequenceType.WGS, Constants.SequenceType.WTS] + } else { + assert false + } + ch_inputs = Channel.of(ch_samplesheet) .splitCsv(header: true) .map { [it.id, it] } @@ -25,27 +52,46 @@ workflow PREPARE_INPUT { meta.subject_name = it.subject_name } + // Sample type def sample_type_enum = Utils.getEnumFromString(it.sample_type, Constants.SampleType) if (!sample_type_enum) { def sample_type_str = Utils.getEnumNames(Constants.SampleType).join('\n - ') - log.error "\nERROR: recieved invalid sample type: '${it.sample_type}'. Valid options are:\n - ${sample_type_str}" + log.error "\nERROR: received invalid sample type: '${it.sample_type}'. Valid options are:\n - ${sample_type_str}" System.exit(1) } + if (!sample_types_allowed.contains(sample_type_enum)) { + def sample_type_str = sample_types_allowed.collect { it.name().toLowerCase() }.join('\n - ') + def run_type_str = run_config.type.name().toLowerCase() + log.error "\nERROR: received invalid sample type for ${run_type_str} " + + "run: '${it.sample_type}'. Valid options are:\n - ${sample_type_str}" + System.exit(1) + } + + // Sequence type def sequence_type_enum = Utils.getEnumFromString(it.sequence_type, Constants.SequenceType) if (!sequence_type_enum) { def sequence_type_str = Utils.getEnumNames(Constants.SequenceType).join('\n - ') - log.error "\nERROR: recieved invalid sequence type: '${it.sequence_type}'. Valid options are:\n - ${sequence_type_str}" + log.error "\nERROR: received invalid sequence type: '${it.sequence_type}'. Valid options are:\n - ${sequence_type_str}" + System.exit(1) + } + + if (!sequence_types_allowed.contains(sequence_type_enum)) { + def sequence_types_str = sequence_types_allowed.collect { it.name().toLowerCase() }.join('\n - ') + def run_mode_str = run_config.mode.name().toLowerCase() + log.error "\nERROR: received invalid sample mode for ${run_mode_str} " + + "run: '${it.sequence_type}'. Valid options are:\n - ${sequence_types_str}" System.exit(1) } + // Filetype def filetype_enum = Utils.getEnumFromString(it.filetype, Constants.FileType) if (!filetype_enum) { def filetype_str = Utils.getEnumNames(Constants.FileType).join('\n - ') - log.error "\nERROR: recieved invalid file type: '${it.filetype}'. Valid options are:\n - ${filetype_str}" + log.error "\nERROR: received invalid file type: '${it.filetype}'. Valid options are:\n - ${filetype_str}" System.exit(1) } @@ -86,6 +132,7 @@ workflow PREPARE_INPUT { } } + // Sample name def key_sample_name if (sample_type_enum == Constants.SampleType.TUMOR_NORMAL) { @@ -128,6 +175,96 @@ workflow PREPARE_INPUT { return meta } + // Check we have the required sample types for the specified run configuration + ch_inputs + .map { meta -> + + def sample_types = [] + for (e in meta) { + if (! e.key instanceof List || e.key[0] != 'sample_name') { + continue + } + sample_types.add(e.key[1..-1]) + } + + def required_sample_types + if (run_config.mode == Constants.RunMode.WGS) { + + if (run_config.type == Constants.RunType.TUMOR_ONLY) { + required_sample_types = [ + [Constants.SampleType.TUMOR, Constants.SequenceType.WGS], + ] + } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + required_sample_types = [ + [Constants.SampleType.TUMOR, Constants.SequenceType.WGS], + [Constants.SampleType.NORMAL, Constants.SequenceType.WGS], + ] + } else { + assert false + } + + } else if (run_config.mode == Constants.RunMode.WTS) { + + required_sample_types = [ + [Constants.SampleType.TUMOR, Constants.SequenceType.WTS], + ] + + } else if (run_config.mode == Constants.RunMode.WGTS) { + + if (run_config.type == Constants.RunType.TUMOR_ONLY) { + required_sample_types = [ + [Constants.SampleType.TUMOR, Constants.SequenceType.WGS], + [Constants.SampleType.TUMOR, Constants.SequenceType.WTS], + ] + } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + required_sample_types = [ + [Constants.SampleType.TUMOR, Constants.SequenceType.WGS], + [Constants.SampleType.TUMOR, Constants.SequenceType.WTS], + [Constants.SampleType.NORMAL, Constants.SequenceType.WGS], + ] + } else { + assert false + } + + } else { + assert false + } + + def sample_types_missing = required_sample_types - sample_types + def sample_types_extra = sample_types - required_sample_types + + + if (sample_types_missing) { + + def sample_type_str = sample_types_missing + .collect { e -> + def (sample, sequence) = e.collect { it.name().toLowerCase() } + return "${sample}/${sequence}" + } + .join('\n - ') + + def run_type_str = run_config.type.name().toLowerCase() + log.error "\nERROR: missing required input for ${run_type_str} run:\n - ${sample_type_str}" + System.exit(1) + } + + // NOTE(SW): this shold never evalutate as true with the above checks in place + if (sample_types_extra) { + + def sample_type_str = sample_types_extra + .collect { e -> + def (sample, sequence) = e.collect { it.name().toLowerCase() } + return "${sample}/${sequence}" + } + .join('\n - ') + + def run_type_str = run_config.type.name().toLowerCase() + log.error "\nERROR: extra input for ${run_type_str} run found:\n - ${sample_type_str}" + System.exit(1) + } + + } + emit: data = ch_inputs } diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 9329f334..3fc39ae9 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -2,9 +2,9 @@ // Prepare reference data as required // -include { SAMTOOLS_FAIDX } from '../../modules/nf-core/samtools/faidx/main' -include { SAMTOOLS_DICT } from '../../modules/nf-core/samtools/dict/main' -include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' +include { SAMTOOLS_FAIDX } from '../../modules/nf-core/samtools/faidx/main' +include { SAMTOOLS_DICT } from '../../modules/nf-core/samtools/dict/main' +include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_BWA_INDEX } from '../../modules/local/custom/extract_tarball/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_HMF_DATA } from '../../modules/local/custom/extract_tarball/main' @@ -14,7 +14,7 @@ include { GRIDSS_INDEX as GRIDSS_INDEX } from '../../modules workflow PREPARE_REFERENCE { take: - run // map: stages to run + run_config // map: run configuration main: // Channel for version.yml files @@ -50,7 +50,7 @@ workflow PREPARE_REFERENCE { ch_genome_bwa_index = file(params.ref_data_genome_bwa_index) ch_genome_bwa_index_image = file(params.ref_data_genome_bwa_index_image) ch_genome_gridss_index = file(params.ref_data_genome_gridss_index) - if (run.gridss || run.virusinterpreter) { + if (run_config.stages.gridss || run_config.stages.virusinterpreter) { // NOTE(SW): the BWA index directory can be provided as a compressed tarball if (!params.ref_data_genome_bwa_index) { BWA_INDEX([[:], ch_genome_fasta]) @@ -95,7 +95,7 @@ workflow PREPARE_REFERENCE { // Set VIRUSBreakend database path / stage, unpack if required // ch_virusbreakenddb = Channel.empty() - if (run.virusinterpreter) { + if (run_config.stages.virusinterpreter) { if (params.ref_data_virusbreakenddb_path.endsWith('.tar.gz')) { ch_virusbreakenddb_inputs = [ [id: 'virusbreakenddb'], @@ -111,8 +111,8 @@ workflow PREPARE_REFERENCE { // // Set HMF reference paths / stage, unpack if required // + hmf_data_paths = params.hmf_data_paths[params.ref_data_genome_version] if (params.ref_data_hmf_data_path.endsWith('tar.gz')) { - // Decompress and set paths ch_hmf_data_inputs = [ [id: 'hmf_data'], file(params.ref_data_hmf_data_path), @@ -124,14 +124,10 @@ workflow PREPARE_REFERENCE { .map { dir_list -> assert dir_list.size() == 1 def dirpath = dir_list[0].toUriString() - return createHmfDataMap(dirpath, false /* params_only */) + return createDataMap(hmf_data_paths, dirpath) } - } else if (params.ref_data_hmf_data_path) { - // If provided as path to directory, set paths - ch_hmf_data = createHmfDataMap(params.ref_data_hmf_data_path, false /* params_only */) } else { - // If no HMF data bundle is supplied we construct from *only* params - ch_hmf_data = createHmfDataMap(null, true /* params_only */) + ch_hmf_data = createDataMap(hmf_data_paths, params.ref_data_hmf_data_path) } emit: @@ -149,82 +145,15 @@ workflow PREPARE_REFERENCE { versions = ch_versions // channel: [versions.yml] } -def createHmfDataMap(hmf_data_path, params_only) { - // NOTE(SW): this code provides an explicit mapping between user exposed HMF data params and - // their corresponding internal representation - def params_mapping = [ - // AMBER - heterozygous_sites: 'ref_data_heterozygous_sites', - // COBALT - gc_profile: 'ref_data_gc_profile', - // CUPPA - cuppa_resources: 'ref_data_cuppa_resources', - // SVPREP - 'sv_prep_blocklist': 'ref_data_sv_prep_blocklist', - // GRIDSS, GRIPSS - gridss_pon_breakends: 'ref_data_gridss_pon_breakends', - gridss_pon_breakpoints: 'ref_data_gridss_pon_breakpoints', - gridss_region_blocklist: 'ref_data_gridss_region_blocklist', - repeatmasker_annotations: 'ref_data_repeatmasker_annotations', - // Isofox - isofox_counts: 'ref_data_isofox_counts', - isofox_gc_ratios: 'ref_data_isofox_gc_ratios', - // LILAC - lilac_resources: 'ref_data_lilac_resources', - hla_slice_bed: 'ref_data_hla_slice_bed', - // ORANGE - cohort_mapping: 'ref_data_cohort_mapping', - cohort_percentiles: 'ref_data_cohort_percentiles', - alt_sj_distribution: 'ref_data_alt_sj_distribution', - gene_exp_distribution: 'ref_data_gene_exp_distribution', - // SAGE - clinvar_annotations: 'ref_data_clinvar_annotations', - sage_blocklist_regions: 'ref_data_sage_blocklist_regions', - sage_blocklist_sites: 'ref_data_sage_blocklist_sites', - sage_actionable_panel: 'ref_data_sage_actionable_panel', - sage_coverage_panel: 'ref_data_sage_coverage_panel', - sage_highconf_regions: 'ref_data_sage_highconf_regions', - sage_known_hotspots_germline: 'ref_data_sage_known_hotspots_germline', - sage_known_hotspots_somatic: 'ref_data_sage_known_hotspots_somatic', - sage_pon: 'ref_data_sage_pon', - // SIGS - sigs_signatures: 'ref_data_sigs_signatures', - // Virus Interpreter - virus_reporting_db: 'ref_data_virus_reporting_db', - virus_taxonomy_db: 'ref_data_virus_taxonomy_db', - // Misc - disease_ontology: 'ref_data_disease_ontology', - driver_gene_panel: 'ref_data_driver_gene_panel', - ensembl_data_resources: 'ref_data_ensembl_data_resources', - gnomad_resource: 'ref_data_gnomad_resource', - known_fusion_data: 'ref_data_known_fusion_data', - known_fusions: 'ref_data_known_fusions', - purple_germline_del: 'ref_data_purple_germline_del', - segment_mappability: 'ref_data_segment_mappability', - ] - params_mapping.collectEntries { k, v -> - [k, getHmfDataFileObject(v, k, hmf_data_path, params_only)] - } +def createDataMap(entries, ref_data_path) { + return entries + .collectEntries { name, path -> + def ref_data_file = getRefdataFile(path, ref_data_path) + return [name, ref_data_file] + } } -def getHmfDataFileObject(pk, hk, base_dir, params_only) { - def hmfdata_paths = params.hmfdata_paths.getAt(params.ref_data_genome_version) - if (params.containsKey(pk)) { - return file(params.getAt(pk), checkIfExists: true) - } else if (params_only) { - log.error "ERROR: no entry for ${pk} found in params but is required as no HMF data base path provided" - System.exit(1) - } else if (!hmfdata_paths.containsKey(hk)) { - assert false : "bad key for params.hmfdata_paths.${params.genome_version}: ${hk}" - } else { - - // NOTE(SW): allow paths to optionally set by checking for and returning '[]' values - def value = hmfdata_paths.getAt(hk) - if (value == []) { - return value - } - - def base_dir_noslash = base_dir.toString().replaceAll('/$', '') - return file("${base_dir_noslash}/${hmfdata_paths.getAt(hk)}", checkIfExists: true) - } +def getRefdataFile(filepath, ref_data_path) { + def data_path_noslash = ref_data_path.toString().replaceAll('/$', '') + return file("${data_path_noslash}/${filepath}", checkIfExists: true) } diff --git a/subworkflows/local/purple_calling.nf b/subworkflows/local/purple_calling.nf index 3542d2cf..931e8600 100644 --- a/subworkflows/local/purple_calling.nf +++ b/subworkflows/local/purple_calling.nf @@ -1,9 +1,12 @@ // // PURPLE is a CNV caller that infers purity/ploidy and recovers low-confidence SVs // +import Constants include { PURPLE } from '../../modules/local/purple/main' +include { CHANNEL_INPUTS_PURPLE } from './channel_inputs_purple' + workflow PURPLE_CALLING { take: // Sample data @@ -27,69 +30,47 @@ workflow PURPLE_CALLING { driver_gene_panel ensembl_data_resources purple_germline_del + target_region_bed + target_region_ratios + target_region_msi_indels // Params - run + run_config main: // Channel for version.yml files ch_versions = Channel.empty() // Select input sources - // channel: [val(meta), sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi] - ch_purple_inputs_sv = Channel.empty() - if (run.gripss) { - // NOTE(SW): GRIPSS will be run for all WGS entries, so no optionals here - ch_purple_inputs_sv = WorkflowOncoanalyser.groupByMeta( - ch_sv_somatic, - ch_sv_somatic_unfiltered, - ch_sv_germline, - ) - } else { - ch_purple_inputs_sv = WorkflowOncoanalyser.groupByMeta( - WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_TUMOR, type: 'optional'), - WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR, type: 'optional'), - WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_NORMAL, type: 'optional'), - flatten_mode: 'nonrecursive', - ) - .map { - - def meta = it[0] - def vcfs = it[1..-1] - - def files = vcfs.collectMany { vcf -> - def tbi = vcf == [] ? [] : "${vcf}.tbi" - return [vcf, tbi] - } - - return [meta, *files] - } - } - // channel: [val(meta), amber_dir, cobalt_dir, sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi, smlv_tumor_vcf, smlv_normal_vcf] - ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( - // Required inputs - run.amber ? ch_amber : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.AMBER_DIR), - run.cobalt ? ch_cobalt : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.COBALT_DIR), - // Optional inputs - ch_purple_inputs_sv, - run.pave ? ch_smlv_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_TUMOR, type: 'optional'), - run.pave ? ch_smlv_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_NORMAL, type: 'optional'), - flatten_mode: 'nonrecursive', + CHANNEL_INPUTS_PURPLE( + ch_inputs, + ch_amber, + ch_cobalt, + ch_smlv_somatic, + ch_smlv_germline, + ch_sv_somatic, + ch_sv_germline, + ch_sv_somatic_unfiltered, + run_config, ) // Create process-specific meta // channel: [val(meta_purple), amber_dir, cobalt_dir, sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi, smlv_tumor_vcf, smlv_normal_vcf] - ch_purple_inputs = ch_purple_inputs_source + ch_purple_inputs = CHANNEL_INPUTS_PURPLE.out .map { def meta = it[0] def meta_purple = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), - ] - return [meta_purple, *it[1..-1]] + tumor_id: Utils.getTumorSampleName(meta, run_config.mode), + ] + + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + meta_purple.normal_id = Utils.getNormalWgsSampleName(meta) + } + + return [meta_purple, *it[1..-1]] } PURPLE( @@ -104,6 +85,9 @@ workflow PURPLE_CALLING { driver_gene_panel, ensembl_data_resources, purple_germline_del, + target_region_bed, + target_region_ratios, + target_region_msi_indels, ) ch_outputs = WorkflowOncoanalyser.restoreMeta(PURPLE.out.purple_dir, ch_inputs) diff --git a/subworkflows/local/sage_append.nf b/subworkflows/local/sage_append.nf index 41be29ab..015aec2b 100644 --- a/subworkflows/local/sage_append.nf +++ b/subworkflows/local/sage_append.nf @@ -1,12 +1,11 @@ // // SAGE append adds WTS data to an existing SAGE VCF // +import Constants include { SAGE_APPEND as SOMATIC } from '../../modules/local/sage/append/main' include { SAGE_APPEND as GERMLINE } from '../../modules/local/sage/append/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - workflow SAGE_APPEND { take: // Sample data @@ -19,28 +18,68 @@ workflow SAGE_APPEND { ref_data_genome_dict // file: /path/to/genome_dict // Params - run + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - // Select input sources // channel: [meta, purple_dir, tumor_wts_bam, tumor_wts_bai] ch_sage_append_inputs_source = WorkflowOncoanalyser.groupByMeta( - run.purple ? ch_purple_dir : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), - CHANNEL_GROUP_INPUTS.out.wts_present + run_config.stages.purple ? ch_purple_dir : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), + ch_inputs .map { meta -> def bam = Utils.getTumorWtsBam(meta) return [meta, bam, "${bam}.bai"] }, ) + // + // MODULE: SAGE append germline + // + ch_germline_vcf = Channel.empty() + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + + // channel: [sage_meta, purple_germline_smlv_vcf, tumor_wts_bam] + ch_sage_germline_append_inputs = ch_sage_append_inputs_source + .map { meta, purple_dir, bam, bai -> + def tumor_id = Utils.getTumorWgsSampleName(meta) + def normal_id = Utils.getNormalWgsSampleName(meta) + + def purple_smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") + + // Require both germline smlv from the PURPLE directory + if (!purple_smlv_vcf.exists()) { + return Constants.PLACEHOLDER_META + } + + def sage_meta = [ + key: meta.id, + id: meta.id, + tumor_wts_id: Utils.getTumorWtsSampleName(meta), + wgs_id: normal_id, + ] + return [sage_meta, purple_smlv_vcf, bam, bai] + } + .filter { it != Constants.PLACEHOLDER_META } + + GERMLINE( + ch_sage_germline_append_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ) + + // Set outputs, restoring original meta + ch_germline_vcf = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) + ch_versions = ch_versions.mix(GERMLINE.out.versions) + } + + // + // MODULE: SAGE append germline + // + // NOTE(SW): revise to reduce repetition // Create inputs and create process-specific meta // channel: [sage_meta, purple_somatic_smlv_vcf, tumor_wts_bam] ch_sage_somatic_append_inputs = ch_sage_append_inputs_source @@ -50,7 +89,7 @@ workflow SAGE_APPEND { // Require both somatic smlv from the PURPLE directory if (!purple_smlv_vcf.exists()) { - return Constants.META_PLACEHOLDER + return Constants.PLACEHOLDER_META } def sage_meta = [ @@ -61,34 +100,8 @@ workflow SAGE_APPEND { ] return [sage_meta, purple_smlv_vcf, bam, bai] } - .filter { it != Constants.META_PLACEHOLDER } - - // NOTE(SW): revise to reduce repetition - - // channel: [sage_meta, purple_germline_smlv_vcf, tumor_wts_bam] - ch_sage_germline_append_inputs = ch_sage_append_inputs_source - .map { meta, purple_dir, bam, bai -> - def tumor_id = Utils.getTumorWgsSampleName(meta) - def normal_id = Utils.getNormalWgsSampleName(meta) - - def purple_smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") - - // Require both germline smlv from the PURPLE directory - if (!purple_smlv_vcf.exists()) { - return Constants.META_PLACEHOLDER - } - - def sage_meta = [ - key: meta.id, - id: meta.id, - tumor_wts_id: Utils.getTumorWtsSampleName(meta), - wgs_id: normal_id, - ] - return [sage_meta, purple_smlv_vcf, bam, bai] - } - .filter { it != Constants.META_PLACEHOLDER } + .filter { it != Constants.PLACEHOLDER_META } - // Run process SOMATIC( ch_sage_somatic_append_inputs, ref_data_genome_fasta, @@ -96,20 +109,9 @@ workflow SAGE_APPEND { ref_data_genome_dict, ) - GERMLINE( - ch_sage_germline_append_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ) - // Set outputs, restoring original meta ch_somatic_vcf = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs) - ch_germline_vcf = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) - ch_versions = ch_versions.mix( - GERMLINE.out.versions, - SOMATIC.out.versions, - ) + ch_versions = ch_versions.mix(SOMATIC.out.versions) emit: somatic_vcf = ch_somatic_vcf // channel: [val(meta), somatic_vcf] diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index 44c3174f..fecb95c8 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -5,8 +5,6 @@ include { SAGE_GERMLINE as GERMLINE } from '../../modules/local/sage/germline/main' include { SAGE_SOMATIC as SOMATIC } from '../../modules/local/sage/somatic/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - workflow SAGE_CALLING { take: // Sample data @@ -22,47 +20,73 @@ workflow SAGE_CALLING { ref_data_sage_actionable_panel // file: /path/to/sage_actionable_panel ref_data_sage_coverage_panel // file: /path/to/sage_coverage_panel ref_data_sage_highconf_regions // file: /path/to/sage_highconf_regions - ref_data_sage_pon // file: /path/to/sage_pon ref_data_segment_mappability // file: /path/to/segment_mappability ref_data_driver_gene_panel // file: /path/to/driver_gene_panel ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + + // Params + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - // Get inputs - ch_sage_inputs = CHANNEL_GROUP_INPUTS.out.wgs_present + ch_sage_inputs = ch_inputs .map { meta -> def meta_sage = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorWgsSampleName(meta), - normal_id: Utils.getNormalWgsSampleName(meta), + tumor_id: Utils.getTumorSampleName(meta, run_config.mode), ] - def tumor_bam = Utils.getTumorWgsBam(meta) - def normal_bam = Utils.getNormalWgsBam(meta) - return [meta_sage, tumor_bam, normal_bam, "${tumor_bam}.bai", "${normal_bam}.bai"] + + def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + + def normal_bam = [] + def normal_bai = [] + + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + + assert [Constants.RunMode.WGS, Constants.RunMode.WGTS].contains(run_config.mode) + + meta_sage.normal_id = Utils.getNormalWgsSampleName(meta) + normal_bam = Utils.getNormalWgsBam(meta) + normal_bai = "${normal_bam}.bai" + + } + + return [meta_sage, tumor_bam, normal_bam, "${tumor_bam}.bai", normal_bai] } - GERMLINE( - ch_sage_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_sage_known_hotspots_germline, - ref_data_sage_actionable_panel, - ref_data_sage_coverage_panel, - ref_data_sage_highconf_regions, - ref_data_ensembl_data_resources, - ) + // + // MODULE: SAGE germline + // + ch_germline_vcf_out = Channel.empty() + ch_germline_coverage_out = Channel.empty() + if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + + GERMLINE( + ch_sage_inputs, + ref_data_genome_fasta, + ref_data_genome_fai, + ref_data_genome_dict, + ref_data_genome_version, + ref_data_sage_known_hotspots_germline, + ref_data_sage_actionable_panel, + ref_data_sage_coverage_panel, + ref_data_sage_highconf_regions, + ref_data_ensembl_data_resources, + ) + + ch_versions = ch_versions.mix(GERMLINE.out.versions) + ch_germline_vcf_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_filtered, ch_inputs) + ch_germline_coverage_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.gene_coverage, ch_inputs) + } + // + // MODULE: SAGE somatic + // SOMATIC( ch_sage_inputs, ref_data_genome_fasta, @@ -71,17 +95,12 @@ workflow SAGE_CALLING { ref_data_genome_version, ref_data_sage_known_hotspots_somatic, ref_data_sage_actionable_panel, + ref_data_sage_coverage_panel, ref_data_sage_highconf_regions, ref_data_ensembl_data_resources, ) - ch_versions = ch_versions.mix( - GERMLINE.out.versions, - SOMATIC.out.versions, - ) - - ch_germline_vcf_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_filtered, ch_inputs) - ch_germline_coverage_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.gene_coverage, ch_inputs) + ch_versions = ch_versions.mix(SOMATIC.out.versions) ch_somatic_vcf_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_filtered, ch_inputs) ch_somatic_tumor_bqr_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.tumor_bqr_png, ch_inputs) ch_somatic_normal_bqr_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.normal_bqr_png, ch_inputs) diff --git a/subworkflows/local/sigs_fitting.nf b/subworkflows/local/sigs_fitting.nf index b81b4f26..323ea3b2 100644 --- a/subworkflows/local/sigs_fitting.nf +++ b/subworkflows/local/sigs_fitting.nf @@ -15,8 +15,8 @@ workflow SIGS_FITTING { // Reference data ref_data_sigs_signatures - // Parameters - run + // Params + run_config main: // Channel for version.yml files @@ -24,7 +24,7 @@ workflow SIGS_FITTING { // Select input sources // channel: [val(meta), purple_dir] - if (run.purple) { + if (run_config.stages.purple) { ch_sigs_inputs_source = ch_purple } else { ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) @@ -40,7 +40,7 @@ workflow SIGS_FITTING { // Require smlv VCF from the PURPLE directory if (!smlv_vcf.exists()) { - return Constants.META_PLACEHOLDER + return Constants.PLACEHOLDER_META } def meta_sigs = [ @@ -50,7 +50,7 @@ workflow SIGS_FITTING { ] return [meta_sigs, smlv_vcf] } - .filter { it != Constants.META_PLACEHOLDER } + .filter { it != Constants.PLACEHOLDER_META } SIGS( ch_sigs_inputs, diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index 3c5e857b..7599295e 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -7,8 +7,6 @@ import Utils include { VIRUSBREAKEND } from '../../modules/local/virusbreakend/main' include { VIRUSINTERPRETER } from '../../modules/local/virusinterpreter/main' -include { CHANNEL_GROUP_INPUTS } from './channel_group_inputs' - workflow VIRUSBREAKEND_CALLING { take: // Sample data @@ -27,29 +25,24 @@ workflow VIRUSBREAKEND_CALLING { ref_data_virus_taxonomy_db ref_data_virus_reporting_db - // Parameters - run + // Params gridss_config + run_config main: // Channel for version.yml files ch_versions = Channel.empty() - // Get input meta groups - CHANNEL_GROUP_INPUTS( - ch_inputs, - ) - // VIRUSBreakend // Create inputs and create process-specific meta // channel: [val(meta_virus), tumor_bam] - ch_virusbreakend_inputs = CHANNEL_GROUP_INPUTS.out.wgs_present + ch_virusbreakend_inputs = ch_inputs .map { meta -> def meta_virus = [ key: meta.id, id: meta.id, ] - return [meta_virus, Utils.getTumorWgsBam(meta)] + return [meta_virus, Utils.getTumorBam(meta, run_config.mode)] } // Run process @@ -66,7 +59,7 @@ workflow VIRUSBREAKEND_CALLING { ) // Create inputs and create process-specific meta - if (run.purple) { + if (run_config.stages.purple) { ch_virusinterpreter_inputs_purple = ch_purple } else { ch_virusinterpreter_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) @@ -74,25 +67,25 @@ workflow VIRUSBREAKEND_CALLING { // channel: [val(meta), purple_qc, wgs_metrics] ch_virusinterpreter_inputs_purple_files = ch_virusinterpreter_inputs_purple - .filter { it[0] != Constants.META_PLACEHOLDER } + .filter { it[0] != Constants.PLACEHOLDER_META } .map { meta, purple_dir -> - def tumor_id = Utils.getTumorWgsSampleName(meta) + def tumor_id = Utils.getTumorSampleName(meta, run_config.mode) def purple_purity = file(purple_dir).resolve("${tumor_id}.purple.purity.tsv") def purple_qc = file(purple_dir).resolve("${tumor_id}.purple.qc") // Require both purity and QC files from the PURPLE directory if (!purple_purity.exists() || !purple_qc.exists()) { - return Constants.META_PLACEHOLDER + return Constants.PLACEHOLDER_META } return [meta, purple_purity, purple_qc] } - .filter { it != Constants.META_PLACEHOLDER } + .filter { it != Constants.PLACEHOLDER_META } // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), ch_virusinterpreter_inputs_purple_files, - run.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TUMOR), + run_config.stages.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TUMOR), ) // Virus Interpreter @@ -103,7 +96,7 @@ workflow VIRUSBREAKEND_CALLING { def meta = it[0] def meta_virus = [ key: meta.id, - id: Utils.getTumorWgsSampleName(meta), + id: Utils.getTumorSampleName(meta, run_config.mode), ] return [meta_virus, *it[1..-1]] } diff --git a/workflows/mrd.nf b/workflows/mrd.nf new file mode 100644 index 00000000..d43b9490 --- /dev/null +++ b/workflows/mrd.nf @@ -0,0 +1 @@ +// PLACEHOLDER diff --git a/workflows/panel.nf b/workflows/panel.nf new file mode 100644 index 00000000..d43b9490 --- /dev/null +++ b/workflows/panel.nf @@ -0,0 +1 @@ +// PLACEHOLDER diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 0bf86f45..822a97b8 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -9,26 +9,12 @@ import Utils ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -// Set defaults and validate parameters -WorkflowOncoanalyser.setParamsDefaults(params, log) -WorkflowOncoanalyser.validateParams(params, log) - // Get parameter summary and also print to console def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) WorkflowOncoanalyser.paramsSummaryLog(workflow, params, log) -// Set processes to run -processes = Processes.setProcesses(params.mode, log) -processes_include = Processes.getProcessList(params.processes_include, log) -processes_exclude = Processes.getProcessList(params.processes_exclude, log) -Processes.checkIncludeExcludeList(processes_include, processes_exclude, log) - -processes.addAll(processes_include) -processes.removeAll(processes_exclude) - -run = Constants.Process - .values() - .collectEntries { p -> [p.name().toLowerCase(), p in processes] } +// Get run config +run_config = WorkflowOncoanalyser.getRunConfig(params, log) // Check input path parameters to see if they exist def checkPathParamList = [ @@ -38,11 +24,11 @@ def checkPathParamList = [ ] // Conditional requirements -if (run.virusinterpreter) { +if (run_config.stages.virusinterpreter) { checkPathParamList.add(params.ref_data_virusbreakenddb_path) } -if (run.lilac && params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt') { +if (run_config.stages.lilac && params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt') { checkPathParamList.add(params.ref_data_hla_slice_bed) } @@ -76,7 +62,6 @@ include { BAMTOOLS_METRICS } from '../subworkflows/local/bamtools_metrics' include { CHORD_PREDICTION } from '../subworkflows/local/chord_prediction' include { COBALT_PROFILING } from '../subworkflows/local/cobalt_profiling' include { CUPPA_PREDICTION } from '../subworkflows/local/cuppa_prediction' -include { GRIDSS_CALLING } from '../subworkflows/local/gridss_calling' include { GRIDSS_SVPREP_CALLING } from '../subworkflows/local/gridss_svprep_calling' include { GRIPSS_FILTERING } from '../subworkflows/local/gripss_filtering' include { ISOFOX_QUANTIFICATION } from '../subworkflows/local/isofox_quantification' @@ -123,12 +108,13 @@ workflow WGTS { // channel: [val(meta)] PREPARE_INPUT( samplesheet, + run_config, ) ch_inputs = PREPARE_INPUT.out.data // Set up reference data, assign more human readable variables PREPARE_REFERENCE( - run, + run_config, ) ref_data = PREPARE_REFERENCE.out hmf_data = PREPARE_REFERENCE.out.hmf_data @@ -138,7 +124,7 @@ workflow WGTS { // // channel: [meta, isofox_dir] ch_isofox_out = Channel.empty() - if (run.isofox) { + if (run_config.stages.isofox) { ISOFOX_QUANTIFICATION( ch_inputs, @@ -149,6 +135,7 @@ workflow WGTS { hmf_data.isofox_counts, hmf_data.isofox_gc_ratios, params.isofox_functions, + run_config, ) ch_versions = ch_versions.mix(ISOFOX_QUANTIFICATION.out.versions) @@ -161,13 +148,13 @@ workflow WGTS { // channel: [val(meta), metrics] ch_bamtools_somatic_out = Channel.empty() ch_bamtools_germline_out = Channel.empty() - if (run.bamtools) { + if (run_config.stages.bamtools) { BAMTOOLS_METRICS( ch_inputs, ref_data.genome_fasta, ref_data.genome_version, - run, + run_config, ) ch_versions = ch_versions.mix(BAMTOOLS_METRICS.out.versions) @@ -180,12 +167,13 @@ workflow WGTS { // // channel: [val(meta), amber_dir] ch_amber_out = Channel.empty() - if (run.amber) { + if (run_config.stages.amber) { AMBER_PROFILING( ch_inputs, ref_data.genome_version, hmf_data.heterozygous_sites, + run_config, ) ch_versions = ch_versions.mix(AMBER_PROFILING.out.versions) @@ -197,11 +185,14 @@ workflow WGTS { // // channel: [val(meta), cobalt_dir] ch_cobalt_out = Channel.empty() - if (run.cobalt) { + if (run_config.stages.cobalt) { COBALT_PROFILING( ch_inputs, hmf_data.gc_profile, + hmf_data.diploid_bed, + [], // panel_target_region_normalisation + run_config, ) ch_versions = ch_versions.mix(COBALT_PROFILING.out.versions) @@ -213,44 +204,27 @@ workflow WGTS { // // channel: [val(meta), gridss_vcf] ch_gridss_out = Channel.empty() - if (run.gridss) { - if (run.svprep) { - - GRIDSS_SVPREP_CALLING( - ch_inputs, - ref_data.genome_fasta, - ref_data.genome_version, - ref_data.genome_fai, - ref_data.genome_dict, - ref_data.genome_bwa_index, - ref_data.genome_bwa_index_image, - ref_data.genome_gridss_index, - hmf_data.gridss_region_blocklist, - hmf_data.sv_prep_blocklist, - hmf_data.known_fusions, - gridss_config, - ) - - ch_versions = ch_versions.mix(GRIDSS_SVPREP_CALLING.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP_CALLING.out.results) + if (run_config.stages.gridss) { - } else { + GRIDSS_SVPREP_CALLING( + ch_inputs, + gridss_config, + ref_data.genome_fasta, + ref_data.genome_version, + ref_data.genome_fai, + ref_data.genome_dict, + ref_data.genome_bwa_index, + ref_data.genome_bwa_index_image, + ref_data.genome_gridss_index, + hmf_data.gridss_region_blocklist, + hmf_data.sv_prep_blocklist, + hmf_data.known_fusions, + run_config, + ) + + ch_versions = ch_versions.mix(GRIDSS_SVPREP_CALLING.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP_CALLING.out.results) - GRIDSS_CALLING( - ch_inputs, - ref_data.genome_fasta, - ref_data.genome_fai, - ref_data.genome_dict, - ref_data.genome_bwa_index, - ref_data.genome_bwa_index_image, - ref_data.genome_gridss_index, - hmf_data.gridss_region_blocklist, - gridss_config, - ) - - ch_versions = ch_versions.mix(GRIDSS_CALLING.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS_CALLING.out.results) - } } // @@ -260,7 +234,7 @@ workflow WGTS { ch_gripss_somatic_out = Channel.empty() ch_gripss_germline_out = Channel.empty() ch_gripss_somatic_unfiltered_out = Channel.empty() - if (run.gripss) { + if (run_config.stages.gripss) { GRIPSS_FILTERING( ch_inputs, @@ -272,7 +246,8 @@ workflow WGTS { hmf_data.gridss_pon_breakpoints, hmf_data.known_fusions, hmf_data.repeatmasker_annotations, - run, + [], + run_config, ) ch_versions = ch_versions.mix(GRIPSS_FILTERING.out.versions) @@ -292,7 +267,7 @@ workflow WGTS { // channel: [val(meta), bqr_plot] ch_sage_somatic_tumor_bqr_out = Channel.empty() ch_sage_somatic_normal_bqr_out = Channel.empty() - if (run.sage) { + if (run_config.stages.sage) { SAGE_CALLING( ch_inputs, @@ -305,13 +280,12 @@ workflow WGTS { hmf_data.sage_actionable_panel, hmf_data.sage_coverage_panel, hmf_data.sage_highconf_regions, - hmf_data.sage_pon, hmf_data.segment_mappability, hmf_data.driver_gene_panel, hmf_data.ensembl_data_resources, + run_config, ) - // Set outputs, restoring original meta ch_versions = ch_versions.mix(SAGE_CALLING.out.versions) ch_sage_germline_vcf_out = ch_sage_germline_vcf_out.mix(SAGE_CALLING.out.germline_vcf) ch_sage_germline_coverage_out = ch_sage_germline_coverage_out.mix(SAGE_CALLING.out.germline_coverage) @@ -326,7 +300,7 @@ workflow WGTS { // channel: [val(meta), pave_vcf] ch_pave_germline_out = Channel.empty() ch_pave_somatic_out = Channel.empty() - if (run.pave) { + if (run_config.stages.pave) { PAVE_ANNOTATION( ch_inputs, @@ -336,6 +310,7 @@ workflow WGTS { ref_data.genome_fai, ref_data.genome_version, hmf_data.sage_pon, + [], // sage_pon_artefacts hmf_data.sage_blocklist_regions, hmf_data.sage_blocklist_sites, hmf_data.clinvar_annotations, @@ -343,7 +318,7 @@ workflow WGTS { hmf_data.driver_gene_panel, hmf_data.ensembl_data_resources, hmf_data.gnomad_resource, - run, + run_config, ) ch_versions = ch_versions.mix(PAVE_ANNOTATION.out.versions) @@ -356,7 +331,7 @@ workflow WGTS { // // channel: [val(meta), purple_dir] ch_purple_out = Channel.empty() - if (run.purple) { + if (run_config.stages.purple) { PURPLE_CALLING( ch_inputs, @@ -377,7 +352,10 @@ workflow WGTS { hmf_data.driver_gene_panel, hmf_data.ensembl_data_resources, hmf_data.purple_germline_del, - run, + [], + [], + [], + run_config, ) ch_versions = ch_versions.mix(PURPLE_CALLING.out.versions) @@ -390,7 +368,7 @@ workflow WGTS { // channel: [val(meta), append_vcf] ch_sage_somatic_append_vcf = Channel.empty() ch_sage_germline_append_vcf = Channel.empty() - if (run.orange) { + if (run_config.mode == Constants.RunMode.WGTS && run_config.stages.orange) { // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented @@ -400,7 +378,7 @@ workflow WGTS { ref_data.genome_fasta, ref_data.genome_fai, ref_data.genome_dict, - run, + run_config, ) ch_versions = ch_versions.mix(SAGE_APPEND.out.versions) @@ -416,7 +394,7 @@ workflow WGTS { ch_linx_germline_out = Channel.empty() // channel: [val(meta), linx_visualiser_dir] ch_linx_somatic_plot_out = Channel.empty() - if (run.linx) { + if (run_config.stages.linx) { LINX_ANNOTATION( ch_inputs, @@ -426,7 +404,7 @@ workflow WGTS { hmf_data.known_fusion_data, hmf_data.driver_gene_panel, linx_gene_id_file, - run, + run_config, ) ch_versions = ch_versions.mix(LINX_ANNOTATION.out.versions) @@ -438,6 +416,7 @@ workflow WGTS { ch_linx_somatic_out, ref_data.genome_version, hmf_data.ensembl_data_resources, + run_config, ) ch_versions = ch_versions.mix(LINX_PLOTTING.out.versions) @@ -449,13 +428,13 @@ workflow WGTS { // // channel: [val(meta), sigs_dir] ch_sigs_out = Channel.empty() - if (run.sigs) { + if (run_config.stages.sigs) { SIGS_FITTING( ch_inputs, ch_purple_out, hmf_data.sigs_signatures, - run, + run_config, ) ch_versions = ch_versions.mix(SIGS_FITTING.out.versions) @@ -467,13 +446,13 @@ workflow WGTS { // // channel: [val(meta), chord_prediction] ch_chord_out = Channel.empty() - if (run.chord) { + if (run_config.stages.chord) { CHORD_PREDICTION( ch_inputs, ch_purple_out, ref_data.genome_version, - run, + run_config, ) ch_versions = ch_versions.mix(CHORD_PREDICTION.out.versions) @@ -485,7 +464,7 @@ workflow WGTS { // // channel: [val(meta), lilac_dir] ch_lilac_out = Channel.empty() - if (run.lilac) { + if (run_config.stages.lilac) { // Select HLA slice BED if (params.ref_data_genome_type == 'no_alt') { @@ -503,7 +482,7 @@ workflow WGTS { ref_data.genome_fai, hmf_data.lilac_resources, ref_data_hla_slice_bed, - run, + run_config, ) ch_versions = ch_versions.mix(LILAC_CALLING.out.versions) @@ -515,7 +494,7 @@ workflow WGTS { // // channel: [val(meta), virusinterpreter] ch_virusinterpreter_out = Channel.empty() - if (run.virusinterpreter) { + if (run_config.stages.virusinterpreter) { VIRUSBREAKEND_CALLING( ch_inputs, @@ -530,8 +509,8 @@ workflow WGTS { ref_data.virusbreakenddb, hmf_data.virus_taxonomy_db, hmf_data.virus_reporting_db, - run, gridss_config, + run_config, ) ch_versions = ch_versions.mix(VIRUSBREAKEND_CALLING.out.versions) @@ -543,7 +522,7 @@ workflow WGTS { // // channel: [val(meta), cuppa_dir] ch_cuppa_out = Channel.empty() - if (run.cuppa) { + if (run_config.stages.cuppa) { CUPPA_PREDICTION( ch_inputs, @@ -553,7 +532,7 @@ workflow WGTS { ch_virusinterpreter_out, ref_data.genome_version, hmf_data.cuppa_resources, - run, + run_config, ) ch_versions = ch_versions.mix(CUPPA_PREDICTION.out.versions) @@ -563,7 +542,7 @@ workflow WGTS { // // SUBWORKFLOW: Run ORANGE to generate static PDF report // - if (run.orange) { + if (run_config.stages.orange) { ORANGE_REPORTING( ch_inputs, @@ -593,7 +572,7 @@ workflow WGTS { hmf_data.ensembl_data_resources, hmf_data.alt_sj_distribution, hmf_data.gene_exp_distribution, - run, + run_config, ) ch_versions = ch_versions.mix(ORANGE_REPORTING.out.versions) From 9d1b4464d718844d0b227ddae22d0e7583838642 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Jun 2023 13:13:04 +1000 Subject: [PATCH 180/562] Reorganise workflow summary and email notification --- lib/WorkflowMain.groovy | 218 +++++++++++++++++++++++++++++++- lib/WorkflowOncoanalyser.groovy | 218 -------------------------------- main.nf | 26 +++- workflows/wgts.nf | 24 +--- 4 files changed, 237 insertions(+), 249 deletions(-) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index f351b3b4..d2ccaca0 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -32,7 +32,7 @@ class WorkflowMain { } // - // Print parameter summary log to screen + // Print parameter summary log // public static String paramsSummaryLog(workflow, params, log) { def summary_log = '' @@ -40,7 +40,7 @@ class WorkflowMain { summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) summary_log += '\n' + citation(workflow) + '\n' summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) - return summary_log + log.info summary_log } // @@ -58,10 +58,6 @@ class WorkflowMain { NfcoreSchema.validateParameters(workflow, params, log) } - // NOTE(SW): this is now deferred until after we set defaults - // Print parameter summary log to screen - //log.info paramsSummaryLog(workflow, params, log) - // Check that a -profile or Nextflow config has been provided to run the pipeline NfcoreTemplate.checkConfigProvided(workflow, log) @@ -90,4 +86,214 @@ class WorkflowMain { } return null } + + + // + // Set parameter defaults where required + // + public static void setParamsDefaults(params, log) { + + // Set defaults common to all run configuration + + def default_invalid = false + + if (params.containsKey('genome_version')) { + params.ref_data_genome_version = params.genome_version.toString() + } else if (Constants.GENOMES_VERSION_37.contains(params.genome)) { + params.ref_data_genome_version = '37' + } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { + params.ref_data_genome_version = '38' + } else { + default_invalid = true + } + + if (params.containsKey('genome_type')) { + params.ref_data_genome_type = params.genome_type + } else if (Constants.GENOMES_ALT.contains(params.genome)) { + params.ref_data_genome_type = 'alt' + } else if (Constants.GENOMES_DEFINED.contains(params.genome)) { + params.ref_data_genome_type = 'no_alt' + } else { + default_invalid = true + } + + if (!params.containsKey('ref_data_hmf_data_path')) { + if (params.ref_data_genome_version == '37') { + params.ref_data_hmf_data_path = Constants.HMF_DATA_37_PATH + } else if (params.ref_data_genome_version == '38') { + params.ref_data_hmf_data_path = Constants.HMF_DATA_38_PATH + } + } + + // Bad configuration, catch in validateParams + if (default_invalid) { + return + } + + // Set defaults specific to run configuration without attempting to validate + + def run_mode + if (params.containsKey('run_mode')) { + run_mode = Utils.getRunMode(params.run_mode, log) + } else { + // Bad configuration, catch in validateParams + return + } + + if (run_mode == Constants.RunMode.WTS) { + if (!params.containsKey('run_type')) { + params.run_type = 'tumor_only' + } + } + + def stages = Processes.getRunStages( + run_mode, + params.processes_include, + params.processes_exclude, + params.processes_manual, + log, + ) + + if (stages.virusinterpreter) { + if (!params.containsKey('ref_data_virusbreakenddb_path')) { + params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH + } + } + + if (stages.lilac) { + if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && !params.containsKey('ref_data_hla_slice_bed')) { + params.ref_data_hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH + } + } + } + + // + // Check and validate parameters + // + public static void validateParams(params, log) { + + // Common parameters + + if (!params.genome) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome must be set using the --genome CLI argument or in a configuration file.\n" + + " Currently, the available genome are:\n" + + " ${params.genomes.keySet().join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } else if (!params.genomes.containsKey(params.genome)) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + + " Currently, the available genome are:\n" + + " ${params.genomes.keySet().join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + if (!Constants.GENOMES_SUPPORTED.contains(params.genome)) { + if (!params.containsKey('force_genome') || !params.force_genome) { + log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got ${params.genome}" + + ", please adjust the --genome argument accordingly or override with --force_genome." + System.exit(1) + } else { + log.warn "currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but forcing to " + + "proceed with \"${params.genome}\"" + } + } + + if (!params.ref_data_genome_version) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome version wasn't provided and genome '${params.genome}' is not defined in \n" + + " genome version list.\n" + + " Currently, the list of genomes in the version list include:\n" + + " ${Constants.GENOMES_DEFINED.join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + if (!params.ref_data_genome_type) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome type wasn't provided and genome '${params.genome}' is not defined in \n" + + " genome version list.\n" + + " Currently, the list of genomes in the version list include:\n" + + " ${Constants.GENOMES_DEINFED.join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + if (!params.ref_data_hmf_data_path) { + log.error "ERROR: HMF data path wasn't provided" + System.exit(1) + } + + // NOTE(SW): this could be moved to the wgts.nf where we check that input files exist + def null_check = [ + 'ref_data_genome_fasta', + 'ref_data_genome_type', + 'ref_data_genome_version', + ] + null_check.each { k -> + if (!params[k]) { + log.error "ERROR: '${k}' cannot be set to null in any configuration and must be adjusted or removed to proceed." + System.exit(1) + } + } + + // Run configuration specific parameters + + if (!params.run_mode) { + def run_modes = Utils.getEnumNames(Constants.RunMode).join('\n - ') + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Run mode must be set using the --run_mode CLI argument or in a configuration \n" + + " file.\n" + + " Currently, the available run modes are:\n" + + " - ${run_modes}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + if (!params.run_type) { + def run_types = Utils.getEnumNames(Constants.RunType).join('\n - ') + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Run type must be set using the --run_type CLI argument or in a configuration \n" + + " file.\n" + + " Currently, the available run types are:\n" + + " - ${run_types}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + def run_mode = Utils.getRunMode(params.run_mode, log) + def run_type = Utils.getRunType(params.run_type, log) + + if (run_mode == Constants.RunMode.WTS) { + if (run_type != Constants.RunType.TUMOR_ONLY) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " The WTS run mode does not support tumor/normal data, please adjust the CLI \n" + + " --run_type option or corresponding configuration file.\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + } + + } + + public static getRunConfig(params, log) { + def run_mode = Utils.getRunMode(params.run_mode, log) + def run_type = Utils.getRunType(params.run_type, log) + def stages = Processes.getRunStages( + run_mode, + params.processes_include, + params.processes_exclude, + params.processes_manual, + log, + ) + + return [ + mode: run_mode, + type: run_type, + stages: stages, + ] + } } diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index a272da35..f62729f5 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -13,224 +13,6 @@ import Utils class WorkflowOncoanalyser { - // - // Set parameter defaults where required - // - public static void setParamsDefaults(params, log) { - - // Set defaults common to all run configuration - - def default_invalid = false - - if (params.containsKey('genome_version')) { - params.ref_data_genome_version = params.genome_version.toString() - } else if (Constants.GENOMES_VERSION_37.contains(params.genome)) { - params.ref_data_genome_version = '37' - } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { - params.ref_data_genome_version = '38' - } else { - default_invalid = true - } - - if (params.containsKey('genome_type')) { - params.ref_data_genome_type = params.genome_type - } else if (Constants.GENOMES_ALT.contains(params.genome)) { - params.ref_data_genome_type = 'alt' - } else if (Constants.GENOMES_DEFINED.contains(params.genome)) { - params.ref_data_genome_type = 'no_alt' - } else { - default_invalid = true - } - - if (!params.containsKey('ref_data_hmf_data_path')) { - if (params.ref_data_genome_version == '37') { - params.ref_data_hmf_data_path = Constants.HMF_DATA_37_PATH - } else if (params.ref_data_genome_version == '38') { - params.ref_data_hmf_data_path = Constants.HMF_DATA_38_PATH - } - } - - // Bad configuration, catch in validateParams - if (default_invalid) { - return - } - - // Set defaults specific to run configuration without attempting to validate - - def run_mode - if (params.containsKey('run_mode')) { - run_mode = Utils.getRunMode(params.run_mode, log) - } else { - // Bad configuration, catch in validateParams - return - } - - if (run_mode == Constants.RunMode.WTS) { - if (!params.containsKey('run_type')) { - params.run_type = 'tumor_only' - } - } - - def stages = Processes.getRunStages( - run_mode, - params.processes_include, - params.processes_exclude, - params.processes_manual, - log, - ) - - if (stages.virusinterpreter) { - if (!params.containsKey('ref_data_virusbreakenddb_path')) { - params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH - } - } - - if (stages.lilac) { - if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && !params.containsKey('ref_data_hla_slice_bed')) { - params.ref_data_hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH - } - } - } - - // - // Check and validate parameters - // - public static void validateParams(params, log) { - - // Common parameters - - if (!params.genome) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome must be set using the --genome CLI argument or in a configuration file.\n" + - " Currently, the available genome are:\n" + - " ${params.genomes.keySet().join(", ")}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } else if (!params.genomes.containsKey(params.genome)) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + - " Currently, the available genome are:\n" + - " ${params.genomes.keySet().join(", ")}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - - if (!Constants.GENOMES_SUPPORTED.contains(params.genome)) { - if (!params.containsKey('force_genome') || !params.force_genome) { - log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got ${params.genome}" + - ", please adjust the --genome argument accordingly or override with --force_genome." - System.exit(1) - } else { - log.warn "currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but forcing to " + - "proceed with \"${params.genome}\"" - } - } - - if (!params.ref_data_genome_version) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome version wasn't provided and genome '${params.genome}' is not defined in \n" + - " genome version list.\n" + - " Currently, the list of genomes in the version list include:\n" + - " ${Constants.GENOMES_DEFINED.join(", ")}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - - if (!params.ref_data_genome_type) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome type wasn't provided and genome '${params.genome}' is not defined in \n" + - " genome version list.\n" + - " Currently, the list of genomes in the version list include:\n" + - " ${Constants.GENOMES_DEINFED.join(", ")}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - - if (!params.ref_data_hmf_data_path) { - log.error "ERROR: HMF data path wasn't provided" - System.exit(1) - } - - // NOTE(SW): this could be moved to the wgts.nf where we check that input files exist - def null_check = [ - 'ref_data_genome_fasta', - 'ref_data_genome_type', - 'ref_data_genome_version', - ] - null_check.each { k -> - if (!params[k]) { - log.error "ERROR: '${k}' cannot be set to null in any configuration and must be adjusted or removed to proceed." - System.exit(1) - } - } - - // Run configuration specific parameters - - if (!params.run_mode) { - def run_modes = Utils.getEnumNames(Constants.RunMode).join('\n - ') - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Run mode must be set using the --run_mode CLI argument or in a configuration \n" + - " file.\n" + - " Currently, the available run modes are:\n" + - " - ${run_modes}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - - if (!params.run_type) { - def run_types = Utils.getEnumNames(Constants.RunType).join('\n - ') - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Run type must be set using the --run_type CLI argument or in a configuration \n" + - " file.\n" + - " Currently, the available run types are:\n" + - " - ${run_types}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - - def run_mode = Utils.getRunMode(params.run_mode, log) - def run_type = Utils.getRunType(params.run_type, log) - - if (run_mode == Constants.RunMode.WTS) { - if (run_type != Constants.RunType.TUMOR_ONLY) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " The WTS run mode does not support tumor/normal data, please adjust the CLI \n" + - " --run_type option or corresponding configuration file.\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - - } - - } - - public static String paramsSummaryLog(workflow, params, log) { - def summary_log = '' - summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) - summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) - summary_log += '\n' + WorkflowMain.citation(workflow) + '\n' - summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) - log.info summary_log - } - - public static getRunConfig(params, log) { - def run_mode = Utils.getRunMode(params.run_mode, log) - def run_type = Utils.getRunType(params.run_type, log) - def stages = Processes.getRunStages( - run_mode, - params.processes_include, - params.processes_exclude, - params.processes_manual, - log, - ) - - return [ - mode: run_mode, - type: run_type, - stages: stages, - ] - } - public static groupByMeta(Map named_args, ... channels) { def r = channels // Set position; required to use non-blocking .mix operator diff --git a/main.nf b/main.nf index 7eea1d9d..fc9c7560 100644 --- a/main.nf +++ b/main.nf @@ -35,9 +35,9 @@ params.ref_data_genome_gridss_index = WorkflowMain.getGenomeAttribute(params, */ WorkflowMain.initialise(workflow, params, log) -WorkflowOncoanalyser.setParamsDefaults(params, log) -WorkflowOncoanalyser.validateParams(params, log) - +WorkflowMain.setParamsDefaults(params, log) +WorkflowMain.validateParams(params, log) +WorkflowMain.paramsSummaryLog(workflow, params, log) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -76,6 +76,26 @@ workflow { NFCORE_ONCOANALYSER() } +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + COMPLETION EMAIL AND SUMMARY +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +workflow.onComplete { + + def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) + + if (params.email || params.email_on_fail) { + NfcoreTemplate.email(workflow, params, summary_params, projectDir, log) + } + + NfcoreTemplate.summary(workflow, params, log) + if (params.hook_url) { + NfcoreTemplate.adaptivecard(workflow, params, summary_params, projectDir, log) + } +} + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ THE END diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 822a97b8..be68f2fa 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -9,12 +9,8 @@ import Utils ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -// Get parameter summary and also print to console -def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) -WorkflowOncoanalyser.paramsSummaryLog(workflow, params, log) - -// Get run config -run_config = WorkflowOncoanalyser.getRunConfig(params, log) +// Get run config and parameter summary +run_config = WorkflowMain.getRunConfig(params, log) // Check input path parameters to see if they exist def checkPathParamList = [ @@ -586,22 +582,6 @@ workflow WGTS { ) } -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - COMPLETION EMAIL AND SUMMARY -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -workflow.onComplete { - if (params.email || params.email_on_fail) { - NfcoreTemplate.email(workflow, params, summary_params, projectDir, log) - } - NfcoreTemplate.summary(workflow, params, log) - if (params.hook_url) { - NfcoreTemplate.adaptivecard(workflow, params, summary_params, projectDir, log) - } -} - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ THE END From acec5a2e97df4fc9dfb66b06bf1b726f06b7c103 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 2 Jul 2023 19:42:58 +1000 Subject: [PATCH 181/562] Change GRIDSS VCF output file name and write index --- conf/modules.config | 2 +- modules/local/svprep/depth_annotator/main.nf | 10 ++++++---- subworkflows/local/gridss_svprep_calling.nf | 5 ++++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 719c5a24..5f21daa6 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -43,7 +43,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gridss/sv.vcf.gz" } + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gridss/${filename}" } ] } diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 0dbea3b1..16b0d700 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -10,8 +10,9 @@ process SVPREP_DEPTH_ANNOTATOR { val genome_ver output: - tuple val(meta), path("*.vcf.gz"), emit: vcf - path 'versions.yml' , emit: versions + tuple val(meta), path("${meta.tumor_id}.gridss.vcf.gz"), emit: vcf + path("${meta.tumor_id}.gridss.vcf.gz.tbi") , emit: tbi + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -35,7 +36,7 @@ process SVPREP_DEPTH_ANNOTATOR { -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -threads ${task.cpus} \\ - -output_vcf sv.svprep.gridss.depths.vcf.gz + -output_vcf ${meta.tumor_id}.gridss.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -45,7 +46,8 @@ process SVPREP_DEPTH_ANNOTATOR { stub: """ - touch sv_vcf.depths.vcf.gz + touch ${meta.tumor_id}.gridss.vcf.gz + touch ${meta.tumor_id}.gridss.vcf.gz.tbi echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index bd334cbc..fe5af79e 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -242,7 +242,10 @@ workflow GRIDSS_SVPREP_CALLING { ) .map { id, meta, vcf -> def tbam = Utils.getTumorBam(meta, run_config.mode) - def meta_svprep = [id: meta.id] + def meta_svprep = [ + id: meta.id, + tumor_id: Utils.getTumorSampleName(meta, run_config.mode), + ] def data = [] if (run_config.type == Constants.RunType.TUMOR_ONLY) { From 8eae01ac7c248f6843f3e291007e5c76e91d6e56 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 7 Jul 2023 11:50:17 +1000 Subject: [PATCH 182/562] Update channel notes, adjust variable naming --- modules/local/gripss/germline/main.nf | 4 +- modules/local/gripss/somatic/main.nf | 4 +- modules/local/isofox/main.nf | 2 +- modules/local/pave/germline/main.nf | 2 +- modules/local/pave/somatic/main.nf | 2 +- modules/local/purple/main.nf | 2 +- modules/local/sage/germline/main.nf | 2 +- modules/local/sage/somatic/main.nf | 2 +- subworkflows/local/amber_profiling.nf | 18 ++-- subworkflows/local/bamtools_metrics.nf | 28 ++--- subworkflows/local/channel_inputs_purple.nf | 24 ++--- subworkflows/local/chord_prediction.nf | 22 ++-- subworkflows/local/cobalt_profiling.nf | 18 ++-- subworkflows/local/cuppa_prediction.nf | 32 +++--- subworkflows/local/flagstat_metrics.nf | 24 +++-- subworkflows/local/gridss_svprep_calling.nf | 114 ++++++++++---------- subworkflows/local/gripss_filtering.nf | 49 ++++----- subworkflows/local/isofox_quantification.nf | 42 ++++---- subworkflows/local/lilac_calling.nf | 61 ++++++----- subworkflows/local/linx_annotation.nf | 49 ++++----- subworkflows/local/linx_plotting.nf | 26 ++--- subworkflows/local/orange_reporting.nf | 83 +++++++------- subworkflows/local/pave_annotation.nf | 70 ++++++------ subworkflows/local/prepare_input.nf | 8 +- subworkflows/local/prepare_reference.nf | 5 +- subworkflows/local/purple_calling.nf | 62 +++++------ subworkflows/local/sage_append.nf | 39 +++---- subworkflows/local/sage_calling.nf | 84 ++++++++------- subworkflows/local/sigs_fitting.nf | 22 ++-- subworkflows/local/virusbreakend_calling.nf | 62 +++++------ workflows/wgts.nf | 55 +++++----- 31 files changed, 530 insertions(+), 487 deletions(-) diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 705c2b55..ed923a47 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -7,8 +7,8 @@ process GRIPSS_GERMLINE { input: tuple val(meta), path(gridss_vcf) path genome_fasta + val genome_version path genome_fai - val genome_ver path pon_breakends path pon_breakpoints path known_fusions @@ -35,7 +35,7 @@ process GRIPSS_GERMLINE { -vcf ${gridss_vcf} \\ -germline \\ -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ + -ref_genome_version ${genome_version} \\ -pon_sgl_file ${pon_breakends} \\ -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index 16cc48dc..ff8289ca 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -7,8 +7,8 @@ process GRIPSS_SOMATIC { input: tuple val(meta), path(gridss_vcf) path genome_fasta + val genome_version path genome_fai - val genome_ver path pon_breakends path pon_breakpoints path known_fusions @@ -39,7 +39,7 @@ process GRIPSS_SOMATIC { ${reference_arg} \\ -vcf ${gridss_vcf} \\ -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ + -ref_genome_version ${genome_version} \\ -pon_sgl_file ${pon_breakends} \\ -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 23febca5..e6aa71be 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -8,8 +8,8 @@ process ISOFOX { tuple val(meta), path(bam), path(bai) val functions path genome_fasta - path genome_fai val genome_ver + path genome_fai path ensembl_data_resources path exp_counts path exp_gc_ratios diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 1d71f7e2..a2417d60 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -11,8 +11,8 @@ process PAVE_GERMLINE { input: tuple val(meta), path(sage_vcf) path genome_fasta - path genome_fai val genome_ver + path genome_fai path sage_blocklist_regions path sage_blocklist_sites path clinvar_annotations diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index fbedd7ea..b0f1f2f4 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -7,8 +7,8 @@ process PAVE_SOMATIC { input: tuple val(meta), path(sage_vcf) path genome_fasta - path genome_fai val genome_ver + path genome_fai path sage_pon path sage_pon_artefacts path segment_mappability diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 0f5b1a49..28bf42fa 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -7,9 +7,9 @@ process PURPLE { input: tuple val(meta), path(amber), path(cobalt), path(sv_tumor_vcf), path(sv_tumor_tbi), path(sv_tumor_unfiltered_vcf), path(sv_tumor_unfiltered_tbi), path(sv_normal_vcf), path(sv_normal_tbi), path(smlv_tumor_vcf), path(smlv_normal_vcf) path genome_fasta + val genome_ver path genome_fai path genome_dict - val genome_ver path gc_profile path sage_known_hotspots_somatic path sage_known_hotspots_germline diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 61af8e15..e96524ee 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -15,9 +15,9 @@ process SAGE_GERMLINE { input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) path genome_fasta + val genome_ver path genome_fai path genome_dict - val genome_ver path sage_known_hotspots_germline path sage_actionable_panel path sage_coverage_panel diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index c0ad0c9c..829ae52e 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -9,9 +9,9 @@ process SAGE_SOMATIC { input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) path genome_fasta + val genome_ver path genome_fai path genome_dict - val genome_ver path sage_known_hotspots_somatic path sage_actionable_panel path sage_coverage_panel diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index b5571ee2..245553d0 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -1,6 +1,7 @@ // // AMBER determines b-allele frequencies at predetermined positions // + import Utils include { AMBER } from '../../modules/local/amber/main' @@ -8,21 +9,22 @@ include { AMBER } from '../../modules/local/amber/main' workflow AMBER_PROFILING { take: // Sample data - ch_inputs // channel: [val(meta)] + ch_inputs // channel: [mandatory] [ meta ] // Reference data - ref_data_genome_version - heterozygous_sites + genome_version // channel: [mandatory] genome version + heterozygous_sites // channel: [optional] /path/to/heterozygous_sites // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [val(meta_amber), tumor_bam, normal_bam, tumor_bai, normal_bai] + // channel: [ meta_amber, tumor_bam, normal_bam, tumor_bai, normal_bai ] ch_amber_inputs = ch_inputs .map { meta -> def meta_amber = [ @@ -52,7 +54,7 @@ workflow AMBER_PROFILING { // Run process AMBER( ch_amber_inputs, - ref_data_genome_version, + genome_version, heterozygous_sites, ) @@ -61,7 +63,7 @@ workflow AMBER_PROFILING { ch_versions = ch_versions.mix(AMBER.out.versions) emit: - amber_dir = ch_outputs // channel: [val(meta), amber_dir] + amber_dir = ch_outputs // channel: [ meta, amber_dir ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/bamtools_metrics.nf b/subworkflows/local/bamtools_metrics.nf index 9b867e2d..6ca8915a 100644 --- a/subworkflows/local/bamtools_metrics.nf +++ b/subworkflows/local/bamtools_metrics.nf @@ -1,6 +1,7 @@ // // Bam Tools calculates summary statistics for BAMs // + import Constants import Utils @@ -9,21 +10,22 @@ include { BAMTOOLS } from '../../modules/local/bamtools/main' workflow BAMTOOLS_METRICS { take: // Sample data - ch_inputs + ch_inputs // channel: [mandatory] [ meta ] // Reference data - ref_data_genome_fasta - ref_data_genome_version + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [val(meta_bamtools), bam, bai] + // channel: [ meta_bamtools, bam, bai ] ch_bamtools_inputs_all = ch_inputs .flatMap { meta -> def inputs = [] @@ -54,7 +56,7 @@ workflow BAMTOOLS_METRICS { // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent // on any process - // channel: [val(meta_bamtools), bam, bai] + // channel: [ meta_bamtools, bam, bai ] ch_bamtools_inputs = ch_bamtools_inputs_all .map { [it[1..-1], it[0]] } .groupTuple() @@ -81,15 +83,15 @@ workflow BAMTOOLS_METRICS { // Run process BAMTOOLS( ch_bamtools_inputs, - ref_data_genome_fasta, - ref_data_genome_version, + genome_fasta, + genome_version, ) // Set version ch_versions = ch_versions.mix(BAMTOOLS.out.versions) // Replicate outputs to reverse unique operation - // channel: [val(meta_bamtools_individual), sample_type_str, metrics] + // channel: [ meta_bamtools_individual, sample_type_str, metrics ] ch_bamtools_out_individual = BAMTOOLS.out.metrics .flatMap { meta_bamtools_shared, metrics -> meta_bamtools_shared.keys.collect { key -> @@ -98,8 +100,6 @@ workflow BAMTOOLS_METRICS { } // Set outputs - // channel (somatic): [val(meta), metrics] - // channel (germline): [val(meta), metrics] ch_outputs = WorkflowOncoanalyser.restoreMeta(ch_bamtools_out_individual, ch_inputs) .branch { meta, sample_type_str, metrics -> def sample_type = Utils.getEnumFromString(sample_type_str, Constants.SampleType) @@ -110,8 +110,8 @@ workflow BAMTOOLS_METRICS { } emit: - somatic = ch_outputs.somatic // channel: [val(meta), metrics] - germline = ch_outputs.germline // channel: [val(meta), metrics] + somatic = ch_outputs.somatic // channel: [ meta, metrics ] + germline = ch_outputs.germline // channel: [ meta, metrics ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/channel_inputs_purple.nf b/subworkflows/local/channel_inputs_purple.nf index 5d1a2f16..42ef14db 100644 --- a/subworkflows/local/channel_inputs_purple.nf +++ b/subworkflows/local/channel_inputs_purple.nf @@ -1,22 +1,23 @@ // -// XXX +// Construct PURPLE input channel // + import Constants workflow CHANNEL_INPUTS_PURPLE { take: // Sample data - ch_inputs - ch_amber - ch_cobalt - ch_smlv_somatic - ch_smlv_germline - ch_sv_somatic - ch_sv_germline - ch_sv_somatic_unfiltered + ch_inputs // channel: [mandatory] [ meta ] + ch_amber // channel: [mandatory] [ meta, amber_dir ] + ch_cobalt // channel: [mandatory] [ meta, cobalt_dir ] + ch_smlv_somatic // channel: [optional] [ meta, pave_vcf ] + ch_smlv_germline // channel: [optional] [ meta, pave_vcf ] + ch_sv_somatic // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] + ch_sv_germline // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] + ch_sv_somatic_unfiltered // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] // Params - run_config + run_config // channel: [mandatory] run configuration main: // Set input sources @@ -49,7 +50,6 @@ workflow CHANNEL_INPUTS_PURPLE { } // Combine into single channel - // channel: [val(meta), amber_dir, cobalt_dir, sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi, smlv_tumor_vcf, smlv_normal_vcf] ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_amber_source, ch_cobalt_source, @@ -61,7 +61,7 @@ workflow CHANNEL_INPUTS_PURPLE { ) emit: - ch_purple_inputs_source + ch_purple_inputs_source // channel: [ meta, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] } def getGripssSampleSheetInput(ch_inputs, input_type) { diff --git a/subworkflows/local/chord_prediction.nf b/subworkflows/local/chord_prediction.nf index d8d17e7e..429251f8 100644 --- a/subworkflows/local/chord_prediction.nf +++ b/subworkflows/local/chord_prediction.nf @@ -1,6 +1,7 @@ // -// CHORD predicts HR status +// CHORD predicts HR status for tumor samples // + import Constants import Utils @@ -9,21 +10,22 @@ include { CHORD } from '../../modules/local/chord/main' workflow CHORD_PREDICTION { take: // Sample data - ch_inputs - ch_purple + ch_inputs // channel: [mandatory] [ meta ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] // Reference data - ref_data_genome_version + genome_version // channel: [mandatory] genome version // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [val(meta), purple_dir] + // channel: [ meta, purple_dir ] if (run_config.stages.purple) { ch_chord_inputs_source = ch_purple } else { @@ -31,7 +33,7 @@ workflow CHORD_PREDICTION { } // Create inputs and create process-specific meta - // channel: [val(meta), smlv_vcf, sv_vcf] + // channel: [ meta, smlv_vcf, sv_vcf ] ch_chord_inputs = ch_chord_inputs_source .map { meta, purple_dir -> def tumor_id = Utils.getTumorWgsSampleName(meta) @@ -51,7 +53,7 @@ workflow CHORD_PREDICTION { // Run process CHORD( ch_chord_inputs, - ref_data_genome_version, + genome_version, ) // Set outputs, restoring original meta @@ -59,8 +61,8 @@ workflow CHORD_PREDICTION { ch_versions = ch_versions.mix(CHORD.out.versions) emit: - prediction = ch_outputs // channel: [val(meta), prediction] + prediction = ch_outputs // channel: [ meta, prediction ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index fac67d9d..995d5907 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -1,6 +1,7 @@ // // COBALT calculates read ratios between tumor and normal samples // + import Utils include { COBALT } from '../../modules/local/cobalt/main' @@ -8,22 +9,23 @@ include { COBALT } from '../../modules/local/cobalt/main' workflow COBALT_PROFILING { take: // Sample data - ch_inputs // channel: [val(meta)] + ch_inputs // channel: [mandatory] [ meta ] // Reference data - gc_profile - diploid_bed - target_region_normalisation + gc_profile // channel: [mandatory] /path/to/gc_profile + diploid_bed // channel: [optional] /path/to/diploid_bed + target_region_normalisation // channel: [optional] /path/to/target_region_normalisation // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai] + // channel: [ meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai ] ch_cobalt_inputs = ch_inputs .map { meta -> def meta_cobalt = [ @@ -67,7 +69,7 @@ workflow COBALT_PROFILING { ch_versions = ch_versions.mix(COBALT.out.versions) emit: - cobalt_dir = ch_outputs // channel: [val(meta), cobalt_dir] + cobalt_dir = ch_outputs // channel: [ meta, cobalt_dir ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index c5033950..ab5da6d7 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -1,6 +1,7 @@ // // CUPPA predicts tissue of origin from molecular profiles // + import Constants include { CUPPA } from '../../modules/local/cuppa/main' @@ -8,28 +9,29 @@ include { CUPPA } from '../../modules/local/cuppa/main' workflow CUPPA_PREDICTION { take: // Sample data - ch_inputs - ch_isofox - ch_purple - ch_linx - ch_virusinterpreter + ch_inputs // channel: [mandatory] [ meta ] + ch_isofox // channel: [optional] [ meta, isofox_dir ] + ch_purple // channel: [optional] [ meta, purple_dir ] + ch_linx // channel: [optional] [ meta, linx_annotation_dir ] + ch_virusinterpreter // channel: [optional] [ meta, virusinterpreter ] // Reference data - ref_data_genome_version - ref_data_cuppa_resources + genome_version // channel: [mandatory] genome version + cuppa_resources // channel: [mandatory] /path/to/cuppa_resources/ // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [val(meta), isofox_dir] + // channel: [ meta, isofox_dir ] ch_cuppa_inputs_isofox = run_config.stages.isofox ? ch_isofox : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional') - // channel: [val(meta), isofox_dir, purple_dir, linx_dir, virusinterpreter] + // channel: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter ] ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional'), @@ -39,7 +41,7 @@ workflow CUPPA_PREDICTION { ) // Create inputs and create process-specific meta - // channel: [val(meta_cuppa), isofox_dir, purple_dir, linx_dir, virusinterpreter] + // channel: [ meta_cuppa, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter ] ch_cuppa_inputs = ch_cuppa_inputs_source .map { data -> def meta = data[0] @@ -65,15 +67,15 @@ workflow CUPPA_PREDICTION { CUPPA( ch_cuppa_inputs, - ref_data_genome_version, - ref_data_cuppa_resources, + genome_version, + cuppa_resources, ) // Set outputs, restoring original meta ch_output = WorkflowOncoanalyser.restoreMeta(CUPPA.out.cuppa_dir, ch_inputs) emit: - cuppa_dir = ch_output + cuppa_dir = ch_output // channel: [ meta, cuppa_dir ] - versions = CUPPA.out.versions // channel: [versions.yml] + versions = CUPPA.out.versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/flagstat_metrics.nf b/subworkflows/local/flagstat_metrics.nf index 8bea6733..91cffacf 100644 --- a/subworkflows/local/flagstat_metrics.nf +++ b/subworkflows/local/flagstat_metrics.nf @@ -1,6 +1,7 @@ // -// XXX +// SAMtools flagstat generates statistics for read alignments from the SAM FLAG field // + import Constants import Utils @@ -9,18 +10,19 @@ include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/samtools/flagstat/main workflow FLAGSTAT_METRICS { take: // Sample data - ch_inputs + ch_inputs // channel: [mandatory] [ meta ] // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input source // Select input sources - // channel: [val(meta_flagstat), bam, bai] + // channel: [ meta_flagstat, bam, bai ] ch_flagstat_inputs_all = ch_inputs .flatMap { meta -> def inputs = [] @@ -49,7 +51,7 @@ workflow FLAGSTAT_METRICS { } // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples - // channel: [val(meta_flagstat_shared), bam, bai] + // channel: [ meta_flagstat_shared, bam, bai ] ch_flagstat_inputs = ch_flagstat_inputs_all .map { [it[1..-1], it[0]] } .groupTuple() @@ -82,7 +84,7 @@ workflow FLAGSTAT_METRICS { ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) // Replicate outputs to reverse unique operation - // channel: [val(meta_flagstat_individual), flagstat] + // channel: [ meta_flagstat_individual, flagstat ] ch_flagstat_out_individual = SAMTOOLS_FLAGSTAT.out.flagstat .flatMap { meta_flagstat_shared, flagstat -> def sample_type = Utils.getEnumFromString(meta_flagstat_shared.sample_type_str, Constants.SampleType) @@ -92,8 +94,8 @@ workflow FLAGSTAT_METRICS { } // Set outputs - // channel (somatic): [val(meta), flagstat] - // channel (germline): [val(meta), flagstat] + // channel (somatic): [ meta, flagstat ] + // channel (germline): [ meta, flagstat ] ch_outputs = WorkflowOncoanalyser.restoreMeta(ch_flagstat_out_individual, ch_inputs) .branch { meta, sample_type, flagstat -> somatic: sample_type == Constants.SampleType.TUMOR @@ -104,8 +106,8 @@ workflow FLAGSTAT_METRICS { ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) emit: - somatic = ch_outputs.somatic // channel: [val(meta), metrics] - germline = ch_outputs.germline // channel: [val(meta), metrics] + somatic = ch_outputs.somatic // channel: [ meta, metrics ] + germline = ch_outputs.germline // channel: [ meta, metrics ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index fe5af79e..ead84d64 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -1,7 +1,8 @@ // -// SV Prep is a BAM filter designed to select only reads relevant to SV events run prior to GRIDSS. -// GRIDSS is a software suite containing tools useful for the detection of genomic rearrangements. +// SV Prep selects only reads relevant to SV events run prior to execution of GRIDSS. +// GRIDSS detects structural variants, and reports breakends and breakpoints. // + import Utils include { GRIDSS_ASSEMBLE as ASSEMBLE } from '../../modules/local/svprep/assemble/main' @@ -14,33 +15,34 @@ include { SVPREP as SVPREP_TUMOR } from '../../modules/local/ workflow GRIDSS_SVPREP_CALLING { take: // Sample data - ch_inputs // channel: [val(meta)] - gridss_config // file: /path/to/gridss_config (optional) + ch_inputs // channel: [mandatory] [ meta ] // Reference data - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_version // val: genome version - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_dict // file: /path/to/genome_dict - ref_data_genome_bwa_index // file: /path/to/genome_bwa_index_dir/ - ref_data_genome_bwa_index_image // file: /path/to/genome_bwa_index_image - ref_data_genome_gridss_index // file: /path/to/genome_gridss_index - ref_data_gridss_blocklist // val: /path/to/gridss_blocklist - ref_data_sv_prep_blocklist // file: /path/to/sv_prep_blocklist - ref_data_known_fusions // file: /path/to/known_fusions + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict + genome_bwa_index // channel: [mandatory] /path/to/genome_bwa_index_dir/ + genome_bwa_index_image // channel: [mandatory] /path/to/genome_bwa_index_image + genome_gridss_index // channel: [mandatory] /path/to/genome_gridss_index + gridss_blocklist // channel: [mandatory] /path/to/gridss_blocklist + sv_prep_blocklist // channel: [mandatory] /path/to/sv_prep_blocklist + known_fusions // channel: [mandatory] /path/to/known_fusions // Params - run_config + gridss_config // channel: [optional] /path/to/gridss_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // // MODULE: SV Prep (tumor) // // Prepare tumor sample inputs - // channel: [val(meta_svprep), bam_tumor, bai_tumor, []] + // channel: [ meta_svprep, bam_tumor, bai_tumor, [] ] ch_svprep_tumor_inputs = ch_inputs .map { meta -> def meta_svprep = [ @@ -55,15 +57,15 @@ workflow GRIDSS_SVPREP_CALLING { // Filter tumor BAM SVPREP_TUMOR( ch_svprep_tumor_inputs, - ref_data_genome_fasta, - ref_data_genome_version, - ref_data_sv_prep_blocklist, - ref_data_known_fusions, + genome_fasta, + genome_version, + sv_prep_blocklist, + known_fusions, 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument switch and value ) ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) - // channel: [val(meta_gridss), bam_tumor, bam_tumor_filtered] + // channel: [ meta_gridss, bam_tumor, bam_tumor_filtered ] ch_preprocess_inputs_tumor = WorkflowOncoanalyser.groupByMeta( SVPREP_TUMOR.out.bam, ch_svprep_tumor_inputs, @@ -75,7 +77,7 @@ workflow GRIDSS_SVPREP_CALLING { // // MODULE: SV Prep (normal) // - // channel: [val(meta_gridss), bam_normal, bam_normal_filtered] + // channel: [ meta_gridss, bam_normal, bam_normal_filtered ] ch_preprocess_inputs_normal = Channel.empty() if (run_config.type == Constants.RunType.TUMOR_NORMAL) { @@ -96,15 +98,15 @@ workflow GRIDSS_SVPREP_CALLING { SVPREP_NORMAL( ch_svprep_normal_inputs, - ref_data_genome_fasta, - ref_data_genome_version, - ref_data_sv_prep_blocklist, - ref_data_known_fusions, + genome_fasta, + genome_version, + sv_prep_blocklist, + known_fusions, false, // -write_types argument switch and value ) ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) - // channel: [val(meta_gridss), bam_normal, bam_normal_filtered] + // channel: [ meta_gridss, bam_normal, bam_normal_filtered ] ch_preprocess_inputs_normal = WorkflowOncoanalyser.groupByMeta( SVPREP_NORMAL.out.bam, ch_svprep_normal_inputs, @@ -117,7 +119,7 @@ workflow GRIDSS_SVPREP_CALLING { // // MODULE: GRIDSS preprocess // - // channel: [val(meta_gridss), bam, bam_filtered] + // channel: [ meta_gridss, bam, bam_filtered ] ch_preprocess_inputs = Channel.empty() .mix( ch_preprocess_inputs_tumor, @@ -128,17 +130,17 @@ workflow GRIDSS_SVPREP_CALLING { PREPROCESS( ch_preprocess_inputs, gridss_config, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, + genome_fasta, + genome_fai, + genome_dict, + genome_bwa_index, + genome_bwa_index_image, + genome_gridss_index, ) ch_versions = ch_versions.mix(PREPROCESS.out.versions) // Gather BAMs and outputs from preprocessing for each tumor/normal set - // channel: [key, [[val(meta_gridss), bam, bam_filtered, preprocess_dir], ...]] + // channel: [key, [[ meta_gridss, bam, bam_filtered, preprocess_dir], ...] ] preprocess_group_tuple_size = run_config.type == Constants.RunType.TUMOR_NORMAL ? 2 : 1 ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( ch_preprocess_inputs, @@ -151,7 +153,7 @@ workflow GRIDSS_SVPREP_CALLING { // MODULE: GRIDSS assemble // // Order and organise inputs for assembly - // channel: [val(meta_gridss), [bams], [bams_filtered], [preprocess_dirs], [labels]] + // channel: [ meta_gridss, [bams], [bams_filtered], [preprocess_dirs], [labels] ] ch_assemble_inputs = ch_bams_and_preprocess .map { key, entries -> def (tmeta, tbam, tbam_filtered, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } @@ -190,13 +192,13 @@ workflow GRIDSS_SVPREP_CALLING { ASSEMBLE( ch_assemble_inputs, gridss_config, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blocklist, + genome_fasta, + genome_fai, + genome_dict, + genome_bwa_index, + genome_bwa_index_image, + genome_gridss_index, + gridss_blocklist, ) ch_versions = ch_versions.mix(ASSEMBLE.out.versions) @@ -204,7 +206,7 @@ workflow GRIDSS_SVPREP_CALLING { // MODULE: GRIDSS call // // Prepare inputs for variant calling - // channel: [val(meta_gridss), [bams], [bams_filtered], assemble_dir, [labels]] + // channel: [ meta_gridss, [bams], [bams_filtered], assemble_dir, [labels] ] ch_call_inputs = WorkflowOncoanalyser.groupByMeta( ch_assemble_inputs, ASSEMBLE.out.assemble_dir, @@ -221,13 +223,13 @@ workflow GRIDSS_SVPREP_CALLING { CALL( ch_call_inputs, gridss_config, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_gridss_blocklist, + genome_fasta, + genome_fai, + genome_dict, + genome_bwa_index, + genome_bwa_index_image, + genome_gridss_index, + gridss_blocklist, ) ch_versions = ch_versions.mix(CALL.out.versions) @@ -235,7 +237,7 @@ workflow GRIDSS_SVPREP_CALLING { // MODULE: SV Prep depth annotation // // Prepare inputs for depth annotation, restore original meta - // channel: [val(meta_svprep), [bams], [bais], vcf, [labels]] + // channel: [ meta_svprep, [bams], [bais], vcf, [labels] ] ch_depth_inputs = WorkflowOncoanalyser.groupByMeta( ch_inputs.map { meta -> [meta.id, meta] }, CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, @@ -281,8 +283,8 @@ workflow GRIDSS_SVPREP_CALLING { // Add depth annotations to SVs DEPTH_ANNOTATOR( ch_depth_inputs, - ref_data_genome_fasta, - ref_data_genome_version, + genome_fasta, + genome_version, ) // Reunite final VCF with the corresponding input meta object @@ -295,7 +297,7 @@ workflow GRIDSS_SVPREP_CALLING { .map { id, other -> other.flatten() } emit: - results = ch_out // channel: [val(meta), vcf] + results = ch_out // channel: [ meta, vcf ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/gripss_filtering.nf b/subworkflows/local/gripss_filtering.nf index d91c60b4..6b2c82e9 100644 --- a/subworkflows/local/gripss_filtering.nf +++ b/subworkflows/local/gripss_filtering.nf @@ -8,32 +8,32 @@ include { GRIPSS_SOMATIC as SOMATIC } from '../../modules/local/gripss/somatic workflow GRIPSS_FILTERING { take: // Sample inputs - ch_inputs // channel: [val(meta)] - ch_gridss // channel: [val(meta), gridss_vcf] + ch_inputs // channel: [mandatory] [ meta ] + ch_gridss // channel: [mandatory] [ meta, gridss_vcf ] // Reference data - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_version // val: genome version - breakend_pon // file: /path/to/breakend_pon - breakpoint_pon // file: /path/to/breakpoint_pon - known_fusions // file: /path/to/known_fusions - repeatmasker_annotations // file: /path/to/repeatmasker_annotations - target_regions_bed + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + breakend_pon // channel: [mandatory] /path/to/breakend_pon + breakpoint_pon // channel: [mandatory] /path/to/breakpoint_pon + known_fusions // channel: [mandatory] /path/to/known_fusions + repeatmasker_annotations // channel: [mandatory] /path/to/repeatmasker_annotations + target_regions_bed // channel: [optional] /path/to/target_regions_bed // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input source - // channel: [val(meta), gridss_vcf] ch_gripss_inputs_source = run_config.stages.gridss ? ch_gridss : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIDSS_VCF) // Create inputs and create process-specific meta - // channel: [val(meta_gripss), gridss_vcf] + // channel: [ meta_gripss, gridss_vcf ] ch_gripss_inputs = ch_gripss_inputs_source .filter { it[0] != Constants.PLACEHOLDER_META } .map { meta, gridss_vcf -> @@ -54,15 +54,16 @@ workflow GRIPSS_FILTERING { // // MODULE: GRIPSS germline // + // channel: [ meta, gripss_vcf, gripss_tbi ] ch_germline_out = Channel.empty() ch_germline_unfiltered_out = Channel.empty() if (run_config.type == Constants.RunType.TUMOR_NORMAL) { GERMLINE( ch_gripss_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, + genome_fasta, + genome_version, + genome_fai, breakend_pon, breakpoint_pon, known_fusions, @@ -80,9 +81,9 @@ workflow GRIPSS_FILTERING { // SOMATIC( ch_gripss_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, + genome_fasta, + genome_version, + genome_fai, breakend_pon, breakpoint_pon, known_fusions, @@ -95,10 +96,10 @@ workflow GRIPSS_FILTERING { ch_somatic_unfiltered_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_unfiltered, ch_inputs) emit: - somatic = ch_somatic_out // channel: [val(meta), vcf, tbi] - germline = ch_germline_out // channel: [val(meta), vcf, tbi] - somatic_unfiltered = ch_somatic_unfiltered_out // channel: [val(meta), vcf, tbi] - germline_unfiltered = ch_germline_unfiltered_out // channel: [val(meta), vcf, tbi] + somatic = ch_somatic_out // channel: [ meta, gripss_vcf, gripss_tbi ] + germline = ch_germline_out // channel: [ meta, gripss_vcf, gripss_tbi ] + somatic_unfiltered = ch_somatic_unfiltered_out // channel: [ meta, gripss_vcf, gripss_tbi ] + germline_unfiltered = ch_germline_unfiltered_out // channel: [ meta, gripss_vcf, gripss_tbi ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf index e9d62f63..5a061e9f 100644 --- a/subworkflows/local/isofox_quantification.nf +++ b/subworkflows/local/isofox_quantification.nf @@ -1,6 +1,7 @@ // -// XXX +// Isofox estimates transcript abundance, detects novel SJs, and identifies fusion events // + import Utils include { ISOFOX } from '../../modules/local/isofox/main' @@ -8,27 +9,28 @@ include { ISOFOX } from '../../modules/local/isofox/main' workflow ISOFOX_QUANTIFICATION { take: // Sample data - ch_inputs + ch_inputs // channel: [mandatory] [ meta ] // Reference data - ref_data_genome_fasta - ref_data_genome_fai - ref_data_genome_version - ref_data_ensembl_data_resources - ref_data_isofox_counts - ref_data_isofox_gc_ratios + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + isofox_counts // channel: [mandatory] /path/to/isofox_counts + isofox_gc_ratios // channel: [mandatory] /path/to/isofox_gc_ratios // Params - isofox_functions + isofox_functions // string: [optional] isofox functions //use_isofox_exp_counts_cache - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Create inputs and create process-specific meta - // channel: [meta_isofox, tumor_bam_wts] + // channel: [ meta_isofox, tumor_bam_wts ] if (run_config.stages.isofox) { ch_isofox_inputs = ch_inputs .map { meta -> @@ -53,19 +55,19 @@ workflow ISOFOX_QUANTIFICATION { // currently does not update functions // NOTE(SW): forcing use of cache for now since this feature is incomplete - //isofox_counts = params.use_isofox_exp_counts_cache ? ref_data_isofox_counts : [] - isofox_counts = ref_data_isofox_counts + //isofox_counts = params.use_isofox_exp_counts_cache ? isofox_counts : [] + isofox_counts = isofox_counts // Run process ISOFOX( ch_isofox_inputs, isofox_functions, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_ensembl_data_resources, + genome_fasta, + genome_version, + genome_fai, + ensembl_data_resources, isofox_counts, - ref_data_isofox_gc_ratios, + isofox_gc_ratios, ) // Set outputs, restoring original meta @@ -73,7 +75,7 @@ workflow ISOFOX_QUANTIFICATION { ch_versions = ch_versions.mix(ISOFOX.out.versions) emit: - isofox_dir = ch_outputs // channel: [val(meta), isofox_dir] + isofox_dir = ch_outputs // channel: [ meta, isofox_dir ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index 4ea8d923..aa9f98c2 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -1,6 +1,7 @@ // // LILAC is a WGS tool for HLA typing and somatic CNV and SNV calling // + import Constants import Utils @@ -12,24 +13,26 @@ include { LILAC } from '../../modules/local/lila workflow LILAC_CALLING { take: // Sample data - ch_inputs - ch_purple + ch_inputs // channel: [mandatory] [ meta ] + ch_purple // channel: [optional] [ meta, purple_dir ] // Reference data - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_lilac_resource_dir // file: /path/to/lilac_resource_dir/ - ref_data_hla_slice_bed + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + lilac_resource_dir // channel: [mandatory] /path/to/lilac_resource_dir/ + hla_slice_bed // channel: [mandatory] /path/to/hla_slice_bed // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [val(meta), purple_dir] + // channel: [ meta, purple_dir ] if (run_config.stages.purple) { ch_lilac_inputs_purple = ch_purple } else { @@ -37,7 +40,7 @@ workflow LILAC_CALLING { } // Create channel with all available input BAMs - // channel: [val(meta), wts_bam, wts_bai] + // channel: [ meta, wts_bam, wts_bai ] ch_lilac_bams_wts = Channel.empty() if (run_config.mode == Constants.RunMode.WTS || run_config.mode == Constants.RunMode.WGTS) { ch_lilac_bams_wts = ch_inputs @@ -49,7 +52,7 @@ workflow LILAC_CALLING { ch_lilac_bams_wts = ch_inputs.map { meta -> [meta, [], []] } } - // channel: [val(meta), bam, bai] + // channel: [ meta, bam, bai ] ch_lilac_bams = Channel.empty() if (run_config.mode == Constants.RunMode.WGS || run_config.mode == Constants.RunMode.WGTS) { @@ -74,7 +77,7 @@ workflow LILAC_CALLING { } // Combine BAMs - // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai] + // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai ] ch_lilac_bams = WorkflowOncoanalyser.groupByMeta( ch_lilac_bams_wts, ch_lilac_bams, @@ -100,7 +103,7 @@ workflow LILAC_CALLING { // NOTE(SW): here I remove duplicate files so that we only process each input once // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used // in Pipeline5, see LilacBamSlicer.java#L115 - // channel: [val(meta_lilac), bam, bai] + // channel: [ meta_lilac, bam, bai ] ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_lilac_bams, tumor_sequence_type) // Isolate meta containing expected file count to use for non-blocking groupTuple later ch_slice_meta_individual = ch_slice_inputs @@ -109,16 +112,16 @@ workflow LILAC_CALLING { return [key: meta_lilac.key, count: meta_lilac.count] } // Apply slicing to unique files only - // channel: [val(meta_lilac), bam, bai] + // channel: [ meta_lilac, bam, bai ] ch_slice_inputs_unique = WorkflowLilac.getUniqueInputFiles(ch_slice_inputs) SLICEBAM( ch_slice_inputs_unique, - ref_data_hla_slice_bed, + hla_slice_bed, ) ch_versions = ch_versions.mix(SLICEBAM.out.versions) // Realign contigs if using 38 (use of ALT contigs implied) - // channel: [val(meta_lilac), bam, bai] + // channel: [ meta_lilac, bam, bai ] ch_slices_out = SLICEBAM.out.bam if (params.ref_data_genome_type == 'alt') { // Align reads with chr6 @@ -127,8 +130,8 @@ workflow LILAC_CALLING { // are realigned for consistency. EXTRACTCONTIG( 'chr6', - ref_data_genome_fasta, - ref_data_genome_fai, + genome_fasta, + genome_fai, ) ch_versions = ch_versions.mix(EXTRACTCONTIG.out.versions) @@ -150,7 +153,7 @@ workflow LILAC_CALLING { } // Re-replicate and flow expected file count into meta - // channel: [val(meta_lilac), [sequence_type_str, sample_type_str, bam, bai]] + // channel: [ meta_lilac, [sequence_type_str, sample_type_str, bam, bai] ] ch_slices_out_individual = ch_slices_out .flatMap{ data -> def meta_lilac = data[0] @@ -160,7 +163,7 @@ workflow LILAC_CALLING { } } // Adding expected file count - // channel: [val(meta_lilac), [sequence_type_str, sample_type_str, bam, bai]] + // channel: [ meta_lilac, [sequence_type_str, sample_type_str, bam, bai] ] ch_slices_ready = WorkflowOncoanalyser.joinMeta( ch_slices_out_individual, ch_slice_meta_individual, @@ -168,7 +171,7 @@ workflow LILAC_CALLING { ) // Gather and order files from same grouping using non-blocked groupTuple via provided file counts - // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai] + // channel: [ meta_lilac, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai ] ch_slices_organised = WorkflowLilac.sortSlices(ch_slices_ready, tumor_sequence_type) // Restore original meta so we can join with PURPLE directory @@ -181,7 +184,7 @@ workflow LILAC_CALLING { ) // Get inputs from PURPLE - // channel: [val(meta), gene_cn] + // channel: [ meta, gene_cn ] ch_lilac_inputs_gene_cn = ch_lilac_inputs_purple .map { meta, purple_dir -> if (purple_dir == []) { @@ -193,7 +196,7 @@ workflow LILAC_CALLING { return gene_cn.exists() ? [meta, gene_cn] : [meta, []] } - // channel: [val(meta), smlv_vcf] + // channel: [ meta, smlv_vcf ] ch_lilac_inputs_smlv_vcf = ch_lilac_inputs_purple .map { meta, purple_dir -> if (purple_dir == []) { @@ -205,7 +208,7 @@ workflow LILAC_CALLING { return smlv_vcf.exists() ? [meta, smlv_vcf] : [meta, []] } - // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, purple_dir] + // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, purple_dir ] ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( ch_lilac_inputs_slices, ch_lilac_inputs_gene_cn, @@ -214,7 +217,7 @@ workflow LILAC_CALLING { ) // Create final input channel for LILAC, remove samples with only WTS BAMs - // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, gene_cn, smlv_vcf]] + // channel: [ meta_lilac, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, gene_cn, smlv_vcf ] ch_lilac_inputs = ch_lilac_inputs_full .map { def meta = it[0] @@ -241,9 +244,9 @@ workflow LILAC_CALLING { // Run LILAC LILAC( ch_lilac_inputs, - ref_data_genome_fasta, - params.ref_data_genome_version, - ref_data_lilac_resource_dir, + genome_fasta, + genome_version, + lilac_resource_dir, ) // Set outputs, restoring original meta @@ -251,7 +254,7 @@ workflow LILAC_CALLING { ch_outputs = WorkflowOncoanalyser.restoreMeta(LILAC.out.lilac_dir, ch_inputs) emit: - lilac_dir = ch_outputs // channel: [val(meta), lilac_dir] + lilac_dir = ch_outputs // channel: [ meta, lilac_dir ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf index cdce9c8d..8654d077 100644 --- a/subworkflows/local/linx_annotation.nf +++ b/subworkflows/local/linx_annotation.nf @@ -1,6 +1,7 @@ // -// Linx is an annotation, interpretation and visualisation tool for structural variants. +// LINX annotates and interprets structural variants // + import Constants import Utils @@ -10,35 +11,37 @@ include { LINX_SOMATIC as SOMATIC } from '../../modules/local/linx/somatic/mai workflow LINX_ANNOTATION { take: // Sample data - ch_inputs // channel: [val(meta)] - ch_purple // channel: [val(meta), purple_dir] + ch_inputs // channel: [mandatory] [ meta ] + ch_purple // channel: [optional] [ meta, purple_dir ] // Reference data - ref_data_genome_version // val: genome version - ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ - ref_data_known_fusion_data // file: /path/to/known_fusion_data - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - gene_id_file // file: /path/to/linx_gene_id_file + genome_version // channel: [mandatory] genome version + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + known_fusion_data // channel: [mandatory] /path/to/known_fusion_data + driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel + gene_id_file // channel: [mandatory] /path/to/linx_gene_id_file // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for versions.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [val(meta), purple_dir] + // channel: [ meta, purple_dir ] ch_linx_inputs_source = run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) // // MODULE: LINX germline annotation // + // channel: [ meta, sv_vcf ] ch_linx_germline_out = Channel.empty() if (run_config.type == Constants.RunType.TUMOR_NORMAL) { // Create germline inputs and create process-specific meta - // channel: [val(meta_linx), sv_vcf] + // channel: [ meta_linx, sv_vcf ] ch_linx_inputs_germline = ch_linx_inputs_source .map { meta, purple_dir -> @@ -61,14 +64,13 @@ workflow LINX_ANNOTATION { GERMLINE( ch_linx_inputs_germline, - ref_data_genome_version, - ref_data_ensembl_data_resources, - ref_data_driver_gene_panel, + genome_version, + ensembl_data_resources, + driver_gene_panel, ) // Set outputs, restoring original meta ch_versions = ch_versions.mix(GERMLINE.out.versions) - // channel: [val(meta), linx_annotation_dir] ch_linx_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.annotation_dir, ch_inputs) } @@ -76,7 +78,7 @@ workflow LINX_ANNOTATION { // MODULE: LINX somatic annotation // // Create somatic inputs and create process-specific meta - // channel: [val(meta_linx), purple_dir] + // channel: [ meta_linx, purple_dir ] ch_linx_inputs_somatic = ch_linx_inputs_source .map { meta, purple_dir -> def meta_linx = [ @@ -88,21 +90,20 @@ workflow LINX_ANNOTATION { SOMATIC( ch_linx_inputs_somatic, - ref_data_genome_version, - ref_data_ensembl_data_resources, - ref_data_known_fusion_data, - ref_data_driver_gene_panel, + genome_version, + ensembl_data_resources, + known_fusion_data, + driver_gene_panel, gene_id_file, ) // Set outputs, restoring original meta ch_versions = ch_versions.mix(SOMATIC.out.versions) - // channel: [val(meta), linx_annotation_dir] ch_linx_somatic_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.annotation_dir, ch_inputs) emit: - somatic = ch_linx_somatic_out // channel: [val(meta), linx_annotation_dir] - germline = ch_linx_germline_out // channel: [val(meta), linx_annotation_dir] + somatic = ch_linx_somatic_out // channel: [ meta, linx_annotation_dir ] + germline = ch_linx_germline_out // channel: [ meta, linx_annotation_dir ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/linx_plotting.nf b/subworkflows/local/linx_plotting.nf index 80f6b1fe..060711b7 100644 --- a/subworkflows/local/linx_plotting.nf +++ b/subworkflows/local/linx_plotting.nf @@ -1,6 +1,7 @@ // -// XXX +// LINX plotting visualises clusters structural variants // + import Utils include { GPGR_LINX as GPGR } from '../../modules/local/gpgr/linx/main' @@ -9,22 +10,23 @@ include { LINX_VISUALISER as VISUALISER } from '../../modules/local/linx/visuali workflow LINX_PLOTTING { take: // Sample data - ch_inputs - ch_annotations + ch_inputs // channel: [mandatory] [ meta ] + ch_annotations // channel: [mandatory] [ meta, linx_annotation_dir ] // Reference data - ref_data_genome_version // val: genome version - ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + genome_version // channel: [mandatory] genome version + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for versions.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [val(meta_linx), anno_dir] + // channel: [ meta_linx, linx_annotation_dir ] ch_linx_visualiser_inputs = ch_annotations .map { meta, anno_dir -> def meta_linx = [ @@ -36,8 +38,8 @@ workflow LINX_PLOTTING { VISUALISER( ch_linx_visualiser_inputs, - ref_data_genome_version, - ref_data_ensembl_data_resources, + genome_version, + ensembl_data_resources, ) // Set outputs, restoring original meta @@ -46,7 +48,7 @@ workflow LINX_PLOTTING { // Create inputs and create process-specific meta - // channel: [meta(meta_gpgr_linx), anno_dir, vis_dir] + // channel: [ meta_gpgr_linx, linx_annotation_dir, visualiser_dir ] ch_gpgr_linx_inputs = WorkflowOncoanalyser.groupByMeta( ch_annotations, ch_visualiser_out, @@ -66,7 +68,7 @@ workflow LINX_PLOTTING { ch_versions = ch_versions.mix(GPGR.out.versions) emit: - visualiser_dir = ch_visualiser_out // channel: [val(meta), visualiser_dir] + visualiser_dir = ch_visualiser_out // channel: [ meta, visualiser_dir] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 3e5eef62..b1f2e3f7 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -1,6 +1,7 @@ // -// XXX +// ORANGE collates outputs of hmftools into a static PDF report // + import Constants import Utils @@ -11,47 +12,48 @@ include { FLAGSTAT_METRICS } from './flagstat_metrics' workflow ORANGE_REPORTING { take: // Sample data - ch_inputs - ch_bamtools_somatic - ch_bamtools_germline - ch_sage_somatic_tumor_bqr - ch_sage_somatic_normal_bqr - ch_sage_germline_coverage - ch_sage_somatic_append - ch_sage_germline_append - ch_purple - ch_linx_somatic_annotation - ch_linx_somatic_plot - ch_linx_germline_annotation - ch_virusinterpreter - ch_chord - ch_sigs - ch_lilac - ch_cuppa - ch_isofox + ch_inputs // channel: [mandatory] [ meta ] + ch_bamtools_somatic // channel: [mandatory] [ meta, metrics ] + ch_bamtools_germline // channel: [optional] [ meta, metrics ] + ch_sage_somatic_tumor_bqr // channel: [mandatory] [ meta, sage_bqr_plot ] + ch_sage_somatic_normal_bqr // channel: [optional] [ meta, sage_bqr_plot ] + ch_sage_germline_coverage // channel: [optional] [ meta, sage_coverage ] + ch_sage_somatic_append // channel: [optional] [ meta, sage_append_vcf ] + ch_sage_germline_append // channel: [optional] [ meta, sage_append_vcf ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] + ch_linx_somatic_annotation // channel: [mandatory] [ meta, linx_annotation_dir ] + ch_linx_somatic_plot // channel: [mandatory] [ meta, linx_visualiser_dir ] + ch_linx_germline_annotation // channel: [optional] [ meta, linx_annotation_dir ] + ch_virusinterpreter // channel: [optional] [ meta, virusinterpreter ] + ch_chord // channel: [optional] [ meta, chord_prediction ] + ch_sigs // channel: [optional] [ meta, sigs_dir ] + ch_lilac // channel: [mandatory] [ meta, lilac_dir ] + ch_cuppa // channel: [optional] [ meta, cuppa_dir ] + ch_isofox // channel: [optional] [ meta, isofox_dir ] // Reference data - ref_data_genome_version - ref_data_disease_ontology - ref_data_cohort_mapping - ref_data_cohort_percentiles - ref_data_known_fusion_data - ref_data_driver_gene_panel - ref_data_ensembl_data_resources - ref_data_isofox_alt_sj - ref_data_isofox_gene_distribution + genome_version // channel: [mandatory] genome version + disease_ontology // channel: [mandatory] /path/to/disease_ontology + cohort_mapping // channel: [mandatory] /path/to/cohort_mapping + cohort_percentiles // channel: [mandatory] /path/to/cohort_percentiles + known_fusion_data // channel: [mandatory] /path/to/known_fusion_data + driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + isofox_alt_sj // channel: [mandatory] /path/to/isofox_alt_sj + isofox_gene_distribution // channel: [mandatory] /path/to/isofox_gene_distribution // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // // SUBWORKFLOW: Run SAMtools flagstat to generate stats required for ORANGE // - // channel: [val(meta), metrics] + // channel: [ meta, metrics ] ch_flagstat_somatic_out = Channel.empty() ch_flagstat_germline_out = Channel.empty() if (run_config.stages.flagstat) { @@ -83,6 +85,7 @@ workflow ORANGE_REPORTING { ch_orange_inputs_purple_dir = run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) // Get input smlv somatic VCF from either PURPLE or SAGE append + // channel: [ meta, sage_somatic_vcf, sage_germline_vcf ] if (run_config.mode == Constants.RunMode.WGS) { ch_orange_inputs_smlv_vcfs = ch_orange_inputs_purple_dir @@ -169,15 +172,15 @@ workflow ORANGE_REPORTING { // Run process ORANGE( ch_orange_inputs, - ref_data_genome_version, - ref_data_disease_ontology, - ref_data_cohort_mapping, - ref_data_cohort_percentiles, - ref_data_known_fusion_data, - ref_data_driver_gene_panel, - ref_data_ensembl_data_resources, - ref_data_isofox_alt_sj, - ref_data_isofox_gene_distribution, + genome_version, + disease_ontology, + cohort_mapping, + cohort_percentiles, + known_fusion_data, + driver_gene_panel, + ensembl_data_resources, + isofox_alt_sj, + isofox_gene_distribution, "5.32 [oncoanalyser]", ) @@ -185,5 +188,5 @@ workflow ORANGE_REPORTING { ch_versions = ch_versions.mix(ORANGE.out.versions) emit: - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf index b823b732..9638606e 100644 --- a/subworkflows/local/pave_annotation.nf +++ b/subworkflows/local/pave_annotation.nf @@ -1,5 +1,5 @@ // -// PAVE annotates somatic and germline variant VCFs with gene and transcript coding and protein effects. +// PAVE annotates somatic and germline variant VCFs with gene and transcript coding and protein effects // include { PAVE_GERMLINE as GERMLINE } from '../../modules/local/pave/germline/main' @@ -8,26 +8,26 @@ include { PAVE_SOMATIC as SOMATIC } from '../../modules/local/pave/somatic/mai workflow PAVE_ANNOTATION { take: // Sample data - ch_inputs // channel: [val(meta)] - ch_sage_germline_vcf // channel: [val(meta), sage_germline_vcf] - ch_sage_somatic_vcf // channel: [val(meta), sage_somatic_vcf] + ch_inputs // channel: [mandatory] [ meta ] + ch_sage_germline_vcf // channel: [optional] [ meta, sage_germline_vcf ] + ch_sage_somatic_vcf // channel: [mandatory] [ meta, sage_somatic_vcf ] // Reference data - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_version // val: genome version - ref_data_sage_pon // file: /path/to/sage_pon - ref_data_sage_pon_artefacts // file: /path/to/sage_pon_artefacts - ref_data_sage_blocklist_regions // file: /path/to/sage_blocklist_regions - ref_data_sage_blocklist_sites // file: /path/to/sage_blocklist_sites - ref_data_clinvar_annotations // file: /path/to/clinvar_annotations - ref_data_segment_mappability // file: /path/to/segment_mappability - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ - ref_data_gnomad_resource // file: /path/to/gnomad_resource + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + sage_pon // channel: [mandatory] /path/to/sage_pon + sage_pon_artefacts // channel: [mandatory] /path/to/sage_pon_artefacts + sage_blocklist_regions // channel: [mandatory] /path/to/sage_blocklist_regions + sage_blocklist_sites // channel: [mandatory] /path/to/sage_blocklist_sites + clinvar_annotations // channel: [mandatory] /path/to/clinvar_annotations + segment_mappability // channel: [mandatory] /path/to/segment_mappability + driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + gnomad_resource // channel: [mandatory] /path/to/gnomad_resource // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files @@ -67,15 +67,15 @@ workflow PAVE_ANNOTATION { GERMLINE( ch_pave_germline_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_sage_blocklist_regions, - ref_data_sage_blocklist_sites, - ref_data_clinvar_annotations, - ref_data_segment_mappability, - ref_data_driver_gene_panel, - ref_data_ensembl_data_resources, + genome_fasta, + genome_version, + genome_fai, + sage_blocklist_regions, + sage_blocklist_sites, + clinvar_annotations, + segment_mappability, + driver_gene_panel, + ensembl_data_resources, ) ch_versions = ch_versions.mix(GERMLINE.out.versions) @@ -99,15 +99,15 @@ workflow PAVE_ANNOTATION { SOMATIC( ch_pave_somatic_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_version, - ref_data_sage_pon, - ref_data_sage_pon_artefacts, - ref_data_segment_mappability, - ref_data_driver_gene_panel, - ref_data_ensembl_data_resources, - ref_data_gnomad_resource, + genome_fasta, + genome_version, + genome_fai, + sage_pon, + sage_pon_artefacts, + segment_mappability, + driver_gene_panel, + ensembl_data_resources, + gnomad_resource, ) ch_versions = ch_versions.mix(SOMATIC.out.versions) diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf index 93b9a50a..0720bcb3 100644 --- a/subworkflows/local/prepare_input.nf +++ b/subworkflows/local/prepare_input.nf @@ -1,3 +1,7 @@ +// +// Prepare input data +// + import Constants import Utils @@ -5,10 +9,10 @@ import Utils workflow PREPARE_INPUT { take: // Sample data - ch_samplesheet + ch_samplesheet // channel: [mandatory] /path/to/samplesheet // Params - run_config + run_config // channel: [mandatory] run configuration main: diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 3fc39ae9..e48329a2 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -14,10 +14,11 @@ include { GRIDSS_INDEX as GRIDSS_INDEX } from '../../modules workflow PREPARE_REFERENCE { take: - run_config // map: run configuration + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // @@ -142,7 +143,7 @@ workflow PREPARE_REFERENCE { virusbreakenddb = ch_virusbreakenddb // path: VIRUSBreakend database hmf_data = ch_hmf_data // map: HMF data paths - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } def createDataMap(entries, ref_data_path) { diff --git a/subworkflows/local/purple_calling.nf b/subworkflows/local/purple_calling.nf index 931e8600..41070ea3 100644 --- a/subworkflows/local/purple_calling.nf +++ b/subworkflows/local/purple_calling.nf @@ -1,6 +1,7 @@ // // PURPLE is a CNV caller that infers purity/ploidy and recovers low-confidence SVs // + import Constants include { PURPLE } from '../../modules/local/purple/main' @@ -10,39 +11,40 @@ include { CHANNEL_INPUTS_PURPLE } from './channel_inputs_purple' workflow PURPLE_CALLING { take: // Sample data - ch_inputs - ch_amber - ch_cobalt - ch_smlv_somatic - ch_smlv_germline - ch_sv_somatic - ch_sv_germline - ch_sv_somatic_unfiltered + ch_inputs // channel: [mandatory] [ meta ] + ch_amber // channel: [mandatory] [ meta, amber_dir ] + ch_cobalt // channel: [mandatory] [ meta, cobalt_dir ] + ch_smlv_somatic // channel: [optional] [ meta, pave_vcf ] + ch_smlv_germline // channel: [optional] [ meta, pave_vcf ] + ch_sv_somatic // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] + ch_sv_germline // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] + ch_sv_somatic_unfiltered // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] // Reference data - ref_data_genome_fasta - ref_data_genome_fai - ref_data_genome_dict - ref_data_genome_version - gc_profile - sage_known_hotspots_somatic - sage_known_hotspots_germline - driver_gene_panel - ensembl_data_resources - purple_germline_del - target_region_bed - target_region_ratios - target_region_msi_indels + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict + gc_profile // channel: [mandatory] /path/to/gc_profile + sage_known_hotspots_somatic // channel: [mandatory] /path/to/sage_known_hotspots_somatic + sage_known_hotspots_germline // channel: [mandatory] /path/to/sage_known_hotspots_germline + driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + purple_germline_del // channel: [mandatory] /path/to/purple_germline_del + target_region_bed // channel: [mandatory] /path/to/target_region_bed + target_region_ratios // channel: [mandatory] /path/to/target_region_ratios + target_region_msi_indels // channel: [mandatory] /path/to/target_region_msi_indels // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [val(meta), amber_dir, cobalt_dir, sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi, smlv_tumor_vcf, smlv_normal_vcf] + // channel: [ meta, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] CHANNEL_INPUTS_PURPLE( ch_inputs, ch_amber, @@ -56,7 +58,7 @@ workflow PURPLE_CALLING { ) // Create process-specific meta - // channel: [val(meta_purple), amber_dir, cobalt_dir, sv_tumor_vcf, sv_tumor_tbi, sv_tumor_unfiltered_vcf, sv_tumor_unfiltered_tbi, smlv_tumor_vcf, smlv_normal_vcf] + // channel: [ meta_purple, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] ch_purple_inputs = CHANNEL_INPUTS_PURPLE.out .map { def meta = it[0] @@ -75,10 +77,10 @@ workflow PURPLE_CALLING { PURPLE( ch_purple_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, + genome_fasta, + genome_version, + genome_fai, + genome_dict, gc_profile, sage_known_hotspots_somatic, sage_known_hotspots_germline, @@ -94,7 +96,7 @@ workflow PURPLE_CALLING { ch_versions = ch_versions.mix(PURPLE.out.versions) emit: - purple_dir = ch_outputs // channel: [val(meta), purple_dir] + purple_dir = ch_outputs // channel: [ meta, purple_dir ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/sage_append.nf b/subworkflows/local/sage_append.nf index 015aec2b..8060e898 100644 --- a/subworkflows/local/sage_append.nf +++ b/subworkflows/local/sage_append.nf @@ -1,6 +1,7 @@ // // SAGE append adds WTS data to an existing SAGE VCF // + import Constants include { SAGE_APPEND as SOMATIC } from '../../modules/local/sage/append/main' @@ -9,23 +10,24 @@ include { SAGE_APPEND as GERMLINE } from '../../modules/local/sage/append/main' workflow SAGE_APPEND { take: // Sample data - ch_inputs // channel: [val(meta)] - ch_purple_dir // channel: [val(meta), purple_dir] + ch_inputs // channel: [mandatory] [ meta ] + ch_purple_dir // channel: [mandatory] [ meta, purple_dir ] // Reference data - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_dict // file: /path/to/genome_dict + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [meta, purple_dir, tumor_wts_bam, tumor_wts_bai] + // channel: [ meta, purple_dir, tumor_wts_bam, tumor_wts_bai ] ch_sage_append_inputs_source = WorkflowOncoanalyser.groupByMeta( run_config.stages.purple ? ch_purple_dir : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), ch_inputs @@ -38,10 +40,11 @@ workflow SAGE_APPEND { // // MODULE: SAGE append germline // + // channel: [ meta, sage_append_vcf ] ch_germline_vcf = Channel.empty() if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - // channel: [sage_meta, purple_germline_smlv_vcf, tumor_wts_bam] + // channel: [ sage_meta, purple_germline_smlv_vcf, tumor_wts_bam ] ch_sage_germline_append_inputs = ch_sage_append_inputs_source .map { meta, purple_dir, bam, bai -> def tumor_id = Utils.getTumorWgsSampleName(meta) @@ -66,9 +69,9 @@ workflow SAGE_APPEND { GERMLINE( ch_sage_germline_append_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, + genome_fasta, + genome_fai, + genome_dict, ) // Set outputs, restoring original meta @@ -81,7 +84,7 @@ workflow SAGE_APPEND { // // NOTE(SW): revise to reduce repetition // Create inputs and create process-specific meta - // channel: [sage_meta, purple_somatic_smlv_vcf, tumor_wts_bam] + // channel: [ sage_meta, purple_somatic_smlv_vcf, tumor_wts_bam ] ch_sage_somatic_append_inputs = ch_sage_append_inputs_source .map { meta, purple_dir, bam, bai -> def tumor_id = Utils.getTumorWgsSampleName(meta) @@ -104,9 +107,9 @@ workflow SAGE_APPEND { SOMATIC( ch_sage_somatic_append_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, + genome_fasta, + genome_fai, + genome_dict, ) // Set outputs, restoring original meta @@ -114,8 +117,8 @@ workflow SAGE_APPEND { ch_versions = ch_versions.mix(SOMATIC.out.versions) emit: - somatic_vcf = ch_somatic_vcf // channel: [val(meta), somatic_vcf] - germline_vcf = ch_germline_vcf // channel: [val(meta), germline_vcf] + somatic_vcf = ch_somatic_vcf // channel: [ meta, sage_append_vcf ] + germline_vcf = ch_germline_vcf // channel: [ meta, sage_append_vcf ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index fecb95c8..7831c473 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -1,5 +1,5 @@ // -// SAGE is a precise and highly sensitive somatic SNV, MNV and small INDEL caller. +// SAGE is a precise and highly sensitive somatic SNV, MNV and small INDEL caller // include { SAGE_GERMLINE as GERMLINE } from '../../modules/local/sage/germline/main' @@ -8,31 +8,33 @@ include { SAGE_SOMATIC as SOMATIC } from '../../modules/local/sage/somatic/mai workflow SAGE_CALLING { take: // Sample data - ch_inputs // channel: [val(meta)] + ch_inputs // channel: [mandatory] [ meta ] // Reference data - ref_data_genome_fasta // file: /path/to/genome_fasta - ref_data_genome_fai // file: /path/to/genome_fai - ref_data_genome_dict // file: /path/to/genome_dict - ref_data_genome_version // val: genome version - ref_data_sage_known_hotspots_germline // file: /path/to/sage_known_hotspots_germline - ref_data_sage_known_hotspots_somatic // file: /path/to/sage_known_hotspots_somatic - ref_data_sage_actionable_panel // file: /path/to/sage_actionable_panel - ref_data_sage_coverage_panel // file: /path/to/sage_coverage_panel - ref_data_sage_highconf_regions // file: /path/to/sage_highconf_regions - ref_data_segment_mappability // file: /path/to/segment_mappability - ref_data_driver_gene_panel // file: /path/to/driver_gene_panel - ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ - ref_data_ensembl_data_resources // file: /path/to/ensembl_data_resources/ + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict + sage_known_hotspots_germline // channel: [optional] /path/to/sage_known_hotspots_germline + sage_known_hotspots_somatic // channel: [mandatory] /path/to/sage_known_hotspots_somatic + sage_actionable_panel // channel: [mandatory] /path/to/sage_actionable_panel + sage_coverage_panel // channel: [mandatory] /path/to/sage_coverage_panel + sage_highconf_regions // channel: [mandatory] /path/to/sage_highconf_regions + segment_mappability // channel: [mandatory] /path/to/segment_mappability + driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Get inputs + // channel: [ meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai ] ch_sage_inputs = ch_inputs .map { meta -> def meta_sage = [ @@ -62,21 +64,23 @@ workflow SAGE_CALLING { // // MODULE: SAGE germline // + // channel: [ meta, sage_vcf, sage_tbi ] ch_germline_vcf_out = Channel.empty() + // channel: [ meta, sage_coverage ] ch_germline_coverage_out = Channel.empty() if (run_config.type == Constants.RunType.TUMOR_NORMAL) { GERMLINE( ch_sage_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_sage_known_hotspots_germline, - ref_data_sage_actionable_panel, - ref_data_sage_coverage_panel, - ref_data_sage_highconf_regions, - ref_data_ensembl_data_resources, + genome_fasta, + genome_version, + genome_fai, + genome_dict, + sage_known_hotspots_germline, + sage_actionable_panel, + sage_coverage_panel, + sage_highconf_regions, + ensembl_data_resources, ) ch_versions = ch_versions.mix(GERMLINE.out.versions) @@ -89,15 +93,15 @@ workflow SAGE_CALLING { // SOMATIC( ch_sage_inputs, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_version, - ref_data_sage_known_hotspots_somatic, - ref_data_sage_actionable_panel, - ref_data_sage_coverage_panel, - ref_data_sage_highconf_regions, - ref_data_ensembl_data_resources, + genome_fasta, + genome_version, + genome_fai, + genome_dict, + sage_known_hotspots_somatic, + sage_actionable_panel, + sage_coverage_panel, + sage_highconf_regions, + ensembl_data_resources, ) ch_versions = ch_versions.mix(SOMATIC.out.versions) @@ -106,11 +110,11 @@ workflow SAGE_CALLING { ch_somatic_normal_bqr_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.normal_bqr_png, ch_inputs) emit: - germline_vcf = ch_germline_vcf_out // channel: [val(meta), sage_vcf, sage_tbi] - germline_coverage = ch_germline_coverage_out // channel: [val(meta), sage_coverage] - somatic_vcf = ch_somatic_vcf_out // channel: [val(meta), sage_vcf, sage_tbi] - somatic_tumor_bqr = ch_somatic_tumor_bqr_out // channel: [val(meta), sage_bqr_plot] - somatic_normal_bqr = ch_somatic_normal_bqr_out // channel: [val(meta), sage_brq_plot] + germline_vcf = ch_germline_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] + germline_coverage = ch_germline_coverage_out // channel: [ meta, sage_coverage ] + somatic_vcf = ch_somatic_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] + somatic_tumor_bqr = ch_somatic_tumor_bqr_out // channel: [ meta, sage_bqr_plot ] + somatic_normal_bqr = ch_somatic_normal_bqr_out // channel: [ meta, sage_brq_plot ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/sigs_fitting.nf b/subworkflows/local/sigs_fitting.nf index 323ea3b2..7a4d9bd7 100644 --- a/subworkflows/local/sigs_fitting.nf +++ b/subworkflows/local/sigs_fitting.nf @@ -1,6 +1,7 @@ // -// XXX +// Sigs fits trinucleotide signature definitions with sample SNV counts // + import Constants import Utils @@ -9,21 +10,22 @@ include { SIGS } from '../../modules/local/sigs/main' workflow SIGS_FITTING { take: // Sample data - ch_inputs - ch_purple + ch_inputs // channel: [mandatory] [ meta ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] // Reference data - ref_data_sigs_signatures + sigs_signatures // channel: [mandatory] /path/to/sigs_signatures // Params - run_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [val(meta), purple_dir] + // channel: [ meta, purple_dir ] if (run_config.stages.purple) { ch_sigs_inputs_source = ch_purple } else { @@ -31,7 +33,7 @@ workflow SIGS_FITTING { } // Create inputs and create process-specific meta - // channel: [val(meta_sigs), smlv_vcf] + // channel: [ meta_sigs, smlv_vcf ] ch_sigs_inputs = ch_sigs_inputs_source .map { meta, purple_dir -> @@ -54,7 +56,7 @@ workflow SIGS_FITTING { SIGS( ch_sigs_inputs, - ref_data_sigs_signatures, + sigs_signatures, ) // Set outputs, restoring original meta @@ -62,7 +64,7 @@ workflow SIGS_FITTING { ch_versions = ch_versions.mix(SIGS.out.versions) emit: - sigs_dir = ch_outputs // channel: [val(meta), sigs_dir] + sigs_dir = ch_outputs // channel: [ meta, sigs_dir ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index 7599295e..3cf7774b 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -1,6 +1,7 @@ // -// XXX +// VIRUSBreakend and Virus Interpreter identify viral content and insertion sites // + import Constants import Utils @@ -10,32 +11,33 @@ include { VIRUSINTERPRETER } from '../../modules/local/virusinterpreter/main' workflow VIRUSBREAKEND_CALLING { take: // Sample data - ch_inputs - ch_purple - ch_bamtools_somatic + ch_inputs // channel: [mandatory] [ meta ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] + ch_bamtools_somatic // channel: [mandatory] [ meta, metrics ] // Reference data - ref_data_genome_fasta - ref_data_genome_fai - ref_data_genome_dict - ref_data_genome_bwa_index - ref_data_genome_bwa_index_image - ref_data_genome_gridss_index - ref_data_virusbreakenddb - ref_data_virus_taxonomy_db - ref_data_virus_reporting_db + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict + genome_bwa_index // channel: [mandatory] /path/to/genome_bwa_index/ + genome_bwa_index_image // channel: [mandatory] /path/to/genome_bwa_index_image + genome_gridss_index // channel: [mandatory] /path/to/genome_gridss_index + virusbreakenddb // channel: [mandatory] /path/to/virusbreakenddb/ + virus_taxonomy_db // channel: [mandatory] /path/to/virus_taxonomy_db + virus_reporting_db // channel: [mandatory] /path/to/virus_reporting_db // Params - gridss_config - run_config + gridss_config // channel: [optional] /path/to/gridss_config + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files + // channel: [ versions.yml ] ch_versions = Channel.empty() // VIRUSBreakend // Create inputs and create process-specific meta - // channel: [val(meta_virus), tumor_bam] + // channel: [ meta_virus, tumor_bam ] ch_virusbreakend_inputs = ch_inputs .map { meta -> def meta_virus = [ @@ -49,13 +51,13 @@ workflow VIRUSBREAKEND_CALLING { VIRUSBREAKEND( ch_virusbreakend_inputs, gridss_config, - ref_data_genome_fasta, - ref_data_genome_fai, - ref_data_genome_dict, - ref_data_genome_bwa_index, - ref_data_genome_bwa_index_image, - ref_data_genome_gridss_index, - ref_data_virusbreakenddb, + genome_fasta, + genome_fai, + genome_dict, + genome_bwa_index, + genome_bwa_index_image, + genome_gridss_index, + virusbreakenddb, ) // Create inputs and create process-specific meta @@ -65,7 +67,7 @@ workflow VIRUSBREAKEND_CALLING { ch_virusinterpreter_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) } - // channel: [val(meta), purple_qc, wgs_metrics] + // channel: [ meta, purple_qc, wgs_metrics ] ch_virusinterpreter_inputs_purple_files = ch_virusinterpreter_inputs_purple .filter { it[0] != Constants.PLACEHOLDER_META } .map { meta, purple_dir -> @@ -81,7 +83,7 @@ workflow VIRUSBREAKEND_CALLING { } .filter { it != Constants.PLACEHOLDER_META } - // channel: [val(meta), virus_tsv, purple_purity, purple_qc, wgs_metrics] + // channel: [ meta, virus_tsv, purple_purity, purple_qc, wgs_metrics ] ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), ch_virusinterpreter_inputs_purple_files, @@ -90,7 +92,7 @@ workflow VIRUSBREAKEND_CALLING { // Virus Interpreter // Create inputs and create process-specific meta - // channel: [val(meta_virus), virus_tsv, purple_purity, purple_qc, wgs_metrics] + // channel: [ meta_virus, virus_tsv, purple_purity, purple_qc, wgs_metrics ] ch_virusinterpreter_inputs = ch_virusinterpreter_inputs_full .map { def meta = it[0] @@ -104,8 +106,8 @@ workflow VIRUSBREAKEND_CALLING { // Run process VIRUSINTERPRETER( ch_virusinterpreter_inputs, - ref_data_virus_taxonomy_db, - ref_data_virus_reporting_db, + virus_taxonomy_db, + virus_reporting_db, ) // Set outputs, restoring original meta @@ -116,7 +118,7 @@ workflow VIRUSBREAKEND_CALLING { ) emit: - virusinterpreter = ch_outputs // channel: [val(meta), virusinterpreter] + virusinterpreter = ch_outputs // channel: [ meta, virusinterpreter ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/workflows/wgts.nf b/workflows/wgts.nf index be68f2fa..be653852 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -9,7 +9,7 @@ import Utils ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -// Get run config and parameter summary +// Get run config run_config = WorkflowMain.getRunConfig(params, log) // Check input path parameters to see if they exist @@ -97,11 +97,11 @@ gridss_config = Utils.getFileObject(params.gridss_config) workflow WGTS { // Create channel for versions - // channel: [versions.yml] + // channel: [ versions.yml ] ch_versions = Channel.empty() // Get inputs from samplesheet, assign more human readable variable - // channel: [val(meta)] + // channel: [ meta ] PREPARE_INPUT( samplesheet, run_config, @@ -118,15 +118,15 @@ workflow WGTS { // // MODULE: Run Isofox to analyse WTS data // - // channel: [meta, isofox_dir] + // channel: [ meta, isofox_dir ] ch_isofox_out = Channel.empty() if (run_config.stages.isofox) { ISOFOX_QUANTIFICATION( ch_inputs, ref_data.genome_fasta, - ref_data.genome_fai, ref_data.genome_version, + ref_data.genome_fai, hmf_data.ensembl_data_resources, hmf_data.isofox_counts, hmf_data.isofox_gc_ratios, @@ -141,7 +141,7 @@ workflow WGTS { // // SUBWORKFLOW: Run Bam Tools to generate stats required for downstream processes // - // channel: [val(meta), metrics] + // channel: [ meta, metrics ] ch_bamtools_somatic_out = Channel.empty() ch_bamtools_germline_out = Channel.empty() if (run_config.stages.bamtools) { @@ -161,7 +161,7 @@ workflow WGTS { // // SUBWORKFLOW: Run AMBER to obtain b-allele frequencies // - // channel: [val(meta), amber_dir] + // channel: [ meta, amber_dir ] ch_amber_out = Channel.empty() if (run_config.stages.amber) { @@ -179,7 +179,7 @@ workflow WGTS { // // SUBWORKFLOW: Run COBALT to obtain read ratios // - // channel: [val(meta), cobalt_dir] + // channel: [ meta, cobalt_dir ] ch_cobalt_out = Channel.empty() if (run_config.stages.cobalt) { @@ -198,13 +198,12 @@ workflow WGTS { // // SUBWORKFLOW: Call structural variants with GRIDSS // - // channel: [val(meta), gridss_vcf] + // channel: [ meta, gridss_vcf ] ch_gridss_out = Channel.empty() if (run_config.stages.gridss) { GRIDSS_SVPREP_CALLING( ch_inputs, - gridss_config, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -215,6 +214,7 @@ workflow WGTS { hmf_data.gridss_region_blocklist, hmf_data.sv_prep_blocklist, hmf_data.known_fusions, + gridss_config, run_config, ) @@ -226,7 +226,7 @@ workflow WGTS { // // SUBWORKFLOW: Run GRIPSS to filter GRIDSS SV calls // - // channel: [val(meta), gripss_vcf, gripss_tbi] + // channel: [ meta, gripss_vcf, gripss_tbi ] ch_gripss_somatic_out = Channel.empty() ch_gripss_germline_out = Channel.empty() ch_gripss_somatic_unfiltered_out = Channel.empty() @@ -236,8 +236,8 @@ workflow WGTS { ch_inputs, ch_gridss_out, ref_data.genome_fasta, - ref_data.genome_fai, ref_data.genome_version, + ref_data.genome_fai, hmf_data.gridss_pon_breakends, hmf_data.gridss_pon_breakpoints, hmf_data.known_fusions, @@ -255,12 +255,12 @@ workflow WGTS { // // SUBWORKFLOW: call SNV, MNV, and small INDELS with SAGE // - // channel: [val(meta), sage_vcf, sage_tbi] + // channel: [ meta, sage_vcf, sage_tbi ] ch_sage_germline_vcf_out = Channel.empty() ch_sage_somatic_vcf_out = Channel.empty() - // channel: [val(meta), sage_coverage] + // channel: [ meta, sage_coverage ] ch_sage_germline_coverage_out = Channel.empty() - // channel: [val(meta), bqr_plot] + // channel: [ meta, sage_bqr_plot ] ch_sage_somatic_tumor_bqr_out = Channel.empty() ch_sage_somatic_normal_bqr_out = Channel.empty() if (run_config.stages.sage) { @@ -268,9 +268,9 @@ workflow WGTS { SAGE_CALLING( ch_inputs, ref_data.genome_fasta, + ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, - ref_data.genome_version, hmf_data.sage_known_hotspots_germline, hmf_data.sage_known_hotspots_somatic, hmf_data.sage_actionable_panel, @@ -293,7 +293,7 @@ workflow WGTS { // // SUBWORKFLOW: Annotate variants with PAVE // - // channel: [val(meta), pave_vcf] + // channel: [ meta, pave_vcf ] ch_pave_germline_out = Channel.empty() ch_pave_somatic_out = Channel.empty() if (run_config.stages.pave) { @@ -303,8 +303,8 @@ workflow WGTS { ch_sage_germline_vcf_out, ch_sage_somatic_vcf_out, ref_data.genome_fasta, - ref_data.genome_fai, ref_data.genome_version, + ref_data.genome_fai, hmf_data.sage_pon, [], // sage_pon_artefacts hmf_data.sage_blocklist_regions, @@ -325,7 +325,7 @@ workflow WGTS { // // SUBWORKFLOW: Call CNVs, infer purity and ploidy, and recover low quality SVs with PURPLE // - // channel: [val(meta), purple_dir] + // channel: [ meta, purple_dir ] ch_purple_out = Channel.empty() if (run_config.stages.purple) { @@ -339,9 +339,9 @@ workflow WGTS { ch_gripss_germline_out, ch_gripss_somatic_unfiltered_out, ref_data.genome_fasta, + ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, - ref_data.genome_version, hmf_data.gc_profile, hmf_data.sage_known_hotspots_somatic, hmf_data.sage_known_hotspots_germline, @@ -361,7 +361,7 @@ workflow WGTS { // // SUBWORKFLOW: Append WTS data to SAGE VCF // - // channel: [val(meta), append_vcf] + // channel: [ meta, sage_append_vcf ] ch_sage_somatic_append_vcf = Channel.empty() ch_sage_germline_append_vcf = Channel.empty() if (run_config.mode == Constants.RunMode.WGTS && run_config.stages.orange) { @@ -385,7 +385,7 @@ workflow WGTS { // // SUBWORKFLOW: Group structural variants into higher order events with LINX // - // channel: [val(meta), linx_annotation_dir] + // channel: [ meta, linx_annotation_dir ] ch_linx_somatic_out = Channel.empty() ch_linx_germline_out = Channel.empty() // channel: [val(meta), linx_visualiser_dir] @@ -422,7 +422,7 @@ workflow WGTS { // // SUBWORKFLOW: Run Sigs to fit somatic smlv to signature definitions // - // channel: [val(meta), sigs_dir] + // channel: [ meta, sigs_dir ] ch_sigs_out = Channel.empty() if (run_config.stages.sigs) { @@ -440,7 +440,7 @@ workflow WGTS { // // SUBWORKFLOW: Run CHORD to predict HR deficiency status // - // channel: [val(meta), chord_prediction] + // channel: [ meta, chord_prediction ] ch_chord_out = Channel.empty() if (run_config.stages.chord) { @@ -458,7 +458,7 @@ workflow WGTS { // // SUBWORKFLOW: Run LILAC for HLA typing and somatic CNV and SNV calling // - // channel: [val(meta), lilac_dir] + // channel: [ meta, lilac_dir ] ch_lilac_out = Channel.empty() if (run_config.stages.lilac) { @@ -475,6 +475,7 @@ workflow WGTS { ch_inputs, ch_purple_out, ref_data.genome_fasta, + ref_data.genome_version, ref_data.genome_fai, hmf_data.lilac_resources, ref_data_hla_slice_bed, @@ -488,7 +489,7 @@ workflow WGTS { // // SUBWORKFLOW: Run VIRUSBreakend and Virus Interpreter to quantify viral content // - // channel: [val(meta), virusinterpreter] + // channel: [ meta, virusinterpreter ] ch_virusinterpreter_out = Channel.empty() if (run_config.stages.virusinterpreter) { @@ -516,7 +517,7 @@ workflow WGTS { // // SUBWORKFLOW: Run CUPPA predict tissue of origin // - // channel: [val(meta), cuppa_dir] + // channel: [ meta, cuppa_dir ] ch_cuppa_out = Channel.empty() if (run_config.stages.cuppa) { From cdae328190ab1f911eaba920afb1d796374e59fb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 9 Jul 2023 12:21:25 +1000 Subject: [PATCH 183/562] Fix LINX fusion panel plotting --- modules/local/linx/Dockerfile | 3 +++ modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 10 +++++++--- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/modules/local/linx/Dockerfile b/modules/local/linx/Dockerfile index 322ce3d1..39ab87fa 100644 --- a/modules/local/linx/Dockerfile +++ b/modules/local/linx/Dockerfile @@ -14,11 +14,14 @@ RUN \ USER mambauser +# NOTE(SW): LINX currently (v1.23.6) requires R <4.1.0, see https://github.com/hartwigmedical/hmftools/issues/329 + RUN \ micromamba install -y -n base -c bioconda -c conda-forge \ bioconductor-gviz \ 'circos >=0.69.6' \ 'openjdk >=8' \ + 'r-base == 4.1.3' \ r-cowplot \ r-dplyr \ r-ggplot2 \ diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 3b9c2951..d4cd5de6 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -2,7 +2,7 @@ process LINX_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.23.2--0' + container 'docker.io/scwatts/linx:1.23.2--1' input: tuple val(meta), path(sv_vcf) diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 00952de6..e51853d1 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,7 +2,7 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.23.2--0' + container 'docker.io/scwatts/linx:1.23.2--1' input: tuple val(meta), path(purple_dir) diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 700894e9..06dc9af7 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,7 +2,7 @@ process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/linx:1.23.2--0' + container 'docker.io/scwatts/linx:1.23.2--1' input: tuple val(meta), path(linx) @@ -20,6 +20,10 @@ process LINX_VISUALISER { def args = task.ext.args ?: '' """ + # NOTE(SW): LINX v1.23.2 and current latest version (v1.23.6) require trailing slashes for the -plot_out and -data_out arguments since no filesystem separator is used when constructing fusion plot output filepaths. + # https://github.com/hartwigmedical/hmftools/blob/linx-v1.23.6/linx/src/main/java/com/hartwig/hmftools/linx/visualiser/circos/ChromosomeRangeExecution.java#L22-L29 + # https://github.com/hartwigmedical/hmftools/blob/linx-v1.23.6/linx/src/main/java/com/hartwig/hmftools/linx/visualiser/circos/FusionExecution.java#L18-L23 + java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -cp ${task.ext.jarPath} \\ @@ -31,8 +35,8 @@ process LINX_VISUALISER { -ensembl_data_dir ${ensembl_data_resources} \\ -circos ${task.ext.path_circos} \\ -threads ${task.cpus} \\ - -plot_out linx_visualiser/plot \\ - -data_out linx_visualiser/data + -plot_out linx_visualiser/plot/ \\ + -data_out linx_visualiser/data/ cat <<-END_VERSIONS > versions.yml "${task.process}": From 37dd66a3df0f521c22571f6775661d45072eb416 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 11 Jul 2023 10:12:55 +1000 Subject: [PATCH 184/562] =?UTF-8?q?Bump=20LINX=20version:=201.23.2=20?= =?UTF-8?q?=E2=86=92=201.24?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes fusion panel plotting for R >=4.2.0 * Remove note about R version requirements for LINX --- conf/modules.config | 2 +- modules/local/linx/Dockerfile | 4 +--- modules/local/linx/germline/main.nf | 4 ++-- modules/local/linx/somatic/main.nf | 6 ++---- modules/local/linx/visualiser/main.nf | 4 ++-- 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 5f21daa6..d58c83fa 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -136,7 +136,7 @@ process { } withName: '.*:LINX_PLOTTING:VISUALISER' { - ext.path_circos = 'circos' + ext.path_circos = '/opt/conda/bin/circos' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, diff --git a/modules/local/linx/Dockerfile b/modules/local/linx/Dockerfile index 39ab87fa..f0911602 100644 --- a/modules/local/linx/Dockerfile +++ b/modules/local/linx/Dockerfile @@ -10,12 +10,10 @@ RUN \ RUN \ mkdir -p /opt/linx/ && \ - wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.23.2/linx_v1.23.2.jar' + wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.24/linx_v1.24.jar' USER mambauser -# NOTE(SW): LINX currently (v1.23.6) requires R <4.1.0, see https://github.com/hartwigmedical/hmftools/issues/329 - RUN \ micromamba install -y -n base -c bioconda -c conda-forge \ bioconductor-gviz \ diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index d4cd5de6..74aed3a3 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -2,7 +2,7 @@ process LINX_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.23.2--1' + container 'docker.io/scwatts/linx:1.24--0' input: tuple val(meta), path(sv_vcf) @@ -35,7 +35,7 @@ process LINX_GERMLINE { cat <<-END_VERSIONS > versions.yml "${task.process}": - linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*LINX version: //') + linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*Linx version: //') END_VERSIONS """ diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index e51853d1..5aee2f6c 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,7 +2,7 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.23.2--1' + container 'docker.io/scwatts/linx:1.24--0' input: tuple val(meta), path(purple_dir) @@ -34,16 +34,14 @@ process LINX_SOMATIC { ${gene_id_file_arg} \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ - -check_fusions \\ -known_fusion_file ${known_fusion_data} \\ - -check_drivers \\ -driver_gene_panel ${driver_gene_panel} \\ -write_vis_data \\ -output_dir linx_somatic/ cat <<-END_VERSIONS > versions.yml "${task.process}": - linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*LINX version: //') + linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*Linx version: //') END_VERSIONS """ diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 06dc9af7..873e5da9 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,7 +2,7 @@ process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/linx:1.23.2--1' + container 'docker.io/scwatts/linx:1.24--0' input: tuple val(meta), path(linx) @@ -40,7 +40,7 @@ process LINX_VISUALISER { cat <<-END_VERSIONS > versions.yml "${task.process}": - linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*LINX version: //') + linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*Linx version: //') END_VERSIONS """ From a8a91dc61c8b5ee897984962ce4cace9f7c0cbde Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 14 Jul 2023 14:51:05 +1000 Subject: [PATCH 185/562] =?UTF-8?q?Bump=20gpgr=20version:=201.4.3=20?= =?UTF-8?q?=E2=86=92=201.4.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update to latest version * Apply temporary patch to handle changed LINX v1.24 fusion table --- modules/local/gpgr/linx/Dockerfile | 12 ++++++++++++ modules/local/gpgr/linx/assets/linx.R.patch | 12 ++++++++++++ modules/local/gpgr/linx/main.nf | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 modules/local/gpgr/linx/Dockerfile create mode 100644 modules/local/gpgr/linx/assets/linx.R.patch diff --git a/modules/local/gpgr/linx/Dockerfile b/modules/local/gpgr/linx/Dockerfile new file mode 100644 index 00000000..f7c4dd6c --- /dev/null +++ b/modules/local/gpgr/linx/Dockerfile @@ -0,0 +1,12 @@ +FROM docker.io/scwatts/gpgr:1.4.3 + +RUN \ + mamba install -y patch && mamba clean --all --force-pkgs-dirs --yes + +COPY assets/linx.R.patch /tmp/ + +RUN \ + git clone https://github.com/umccr/gpgr.git -b v1.4.4 /tmp/gpgr/ && \ + patch /tmp/gpgr/R/linx.R /tmp/linx.R.patch && \ + R CMD INSTALL --build /tmp/gpgr && \ + rm -rf /tmp/{gpgr,gpgr_1.4.4_R_x86_64-conda-linux-gnu.tar.gz,linx.R.patch} diff --git a/modules/local/gpgr/linx/assets/linx.R.patch b/modules/local/gpgr/linx/assets/linx.R.patch new file mode 100644 index 00000000..4afb6213 --- /dev/null +++ b/modules/local/gpgr/linx/assets/linx.R.patch @@ -0,0 +1,12 @@ +diff --git a/R/linx.R b/R/linx.R +index c1f3176..a74fa8e 100644 +--- a/R/linx.R ++++ b/R/linx.R +@@ -132,6 +132,7 @@ LINX_DESCRIPTIONS <- tibble::tribble( + "[KNOWN_PAIR, PROMISCUOUS_5, PROMISCUOUS_3, PROMISCUOUS_BOTH, EXON_DEL_DUP, ", + "IG_PROMISCUOUS, IG_KNOWN_PAIR, KNOWN_PAIR_UNMMABLE_3 or NONE (if no match is found)" + ), ++ "fusion", "reportableReasons", "c", "Reason for non-reportable status", + "fusion", "phased", "c", "Set to 1 if a phased fusion can be formed (after allowing for exon skipping)", + "fusion", "likelihood", "c", ".", + "fusion", "chainLength", "d", "0 for simple fusions. If fusion is chained equal to the total length of segments chained between 5' and 3' partners", diff --git a/modules/local/gpgr/linx/main.nf b/modules/local/gpgr/linx/main.nf index fd6a7ea3..112bd139 100644 --- a/modules/local/gpgr/linx/main.nf +++ b/modules/local/gpgr/linx/main.nf @@ -2,7 +2,7 @@ process GPGR_LINX { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/gpgr:1.4.3' + container 'docker.io/scwatts/gpgr:1.4.4--0' input: tuple val(meta), path(linx_annotation), path(linx_visualiser) From 0e803ec8b9710343eb0bff79f56273c4ff924ced Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 20 Jul 2023 12:19:11 +1000 Subject: [PATCH 186/562] =?UTF-8?q?Bump=20gpgr=20version:=201.4.4=20?= =?UTF-8?q?=E2=86=92=201.4.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Updates parsing for LINX v1.24 fusion output file --- modules/local/gpgr/linx/Dockerfile | 12 ------------ modules/local/gpgr/linx/assets/linx.R.patch | 12 ------------ modules/local/gpgr/linx/main.nf | 2 +- 3 files changed, 1 insertion(+), 25 deletions(-) delete mode 100644 modules/local/gpgr/linx/Dockerfile delete mode 100644 modules/local/gpgr/linx/assets/linx.R.patch diff --git a/modules/local/gpgr/linx/Dockerfile b/modules/local/gpgr/linx/Dockerfile deleted file mode 100644 index f7c4dd6c..00000000 --- a/modules/local/gpgr/linx/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM docker.io/scwatts/gpgr:1.4.3 - -RUN \ - mamba install -y patch && mamba clean --all --force-pkgs-dirs --yes - -COPY assets/linx.R.patch /tmp/ - -RUN \ - git clone https://github.com/umccr/gpgr.git -b v1.4.4 /tmp/gpgr/ && \ - patch /tmp/gpgr/R/linx.R /tmp/linx.R.patch && \ - R CMD INSTALL --build /tmp/gpgr && \ - rm -rf /tmp/{gpgr,gpgr_1.4.4_R_x86_64-conda-linux-gnu.tar.gz,linx.R.patch} diff --git a/modules/local/gpgr/linx/assets/linx.R.patch b/modules/local/gpgr/linx/assets/linx.R.patch deleted file mode 100644 index 4afb6213..00000000 --- a/modules/local/gpgr/linx/assets/linx.R.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/R/linx.R b/R/linx.R -index c1f3176..a74fa8e 100644 ---- a/R/linx.R -+++ b/R/linx.R -@@ -132,6 +132,7 @@ LINX_DESCRIPTIONS <- tibble::tribble( - "[KNOWN_PAIR, PROMISCUOUS_5, PROMISCUOUS_3, PROMISCUOUS_BOTH, EXON_DEL_DUP, ", - "IG_PROMISCUOUS, IG_KNOWN_PAIR, KNOWN_PAIR_UNMMABLE_3 or NONE (if no match is found)" - ), -+ "fusion", "reportableReasons", "c", "Reason for non-reportable status", - "fusion", "phased", "c", "Set to 1 if a phased fusion can be formed (after allowing for exon skipping)", - "fusion", "likelihood", "c", ".", - "fusion", "chainLength", "d", "0 for simple fusions. If fusion is chained equal to the total length of segments chained between 5' and 3' partners", diff --git a/modules/local/gpgr/linx/main.nf b/modules/local/gpgr/linx/main.nf index 112bd139..55de7fde 100644 --- a/modules/local/gpgr/linx/main.nf +++ b/modules/local/gpgr/linx/main.nf @@ -2,7 +2,7 @@ process GPGR_LINX { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/gpgr:1.4.4--0' + container 'docker.io/scwatts/gpgr:1.4.5' input: tuple val(meta), path(linx_annotation), path(linx_visualiser) From 6800f4508c8b4481e86103d2fd45b5e005efd19d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 20 Jul 2023 12:59:27 +1000 Subject: [PATCH 187/562] =?UTF-8?q?Bump=20LINX=20version:=201.24=20?= =?UTF-8?q?=E2=86=92=201.24.1=5Fbeta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes fusion panel plotting --- modules/local/linx/Dockerfile | 2 +- modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/linx/Dockerfile b/modules/local/linx/Dockerfile index f0911602..58eed266 100644 --- a/modules/local/linx/Dockerfile +++ b/modules/local/linx/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/linx/ && \ - wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.24/linx_v1.24.jar' + wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.24.1.beta/linx_v1.24.1.beta.jar' USER mambauser diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 74aed3a3..917e281b 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -2,7 +2,7 @@ process LINX_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.24--0' + container 'docker.io/scwatts/linx:1.24.1_beta--0' input: tuple val(meta), path(sv_vcf) diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 5aee2f6c..44e1e561 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,7 +2,7 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.24--0' + container 'docker.io/scwatts/linx:1.24.1_beta--0' input: tuple val(meta), path(purple_dir) diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 873e5da9..de544344 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,7 +2,7 @@ process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/linx:1.24--0' + container 'docker.io/scwatts/linx:1.24.1_beta--0' input: tuple val(meta), path(linx) From 44c4b63baa81cc7b2f6efe59eae0ca8d35f32b8c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 24 Jul 2023 12:07:56 +1000 Subject: [PATCH 188/562] Use tumor sample ID for LINX germline outputs --- modules/local/orange/main.nf | 12 +----------- subworkflows/local/linx_annotation.nf | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index ff9c78a4..61f5d3e2 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -40,8 +40,7 @@ process ORANGE { def normal_flagstat_arg = flagstat_germline ? "-ref_sample_flagstat_file ${flagstat_germline}" : '' def normal_sage_somatic_bqr_arg = sage_germline_bqr ? "-sage_somatic_ref_sample_bqr_plot ${sage_germline_bqr}" : '' def normal_sage_coverage_arg = sage_germline_coverage ? "-sage_germline_gene_coverage_tsv ${sage_germline_coverage}" : '' - // NOTE(SW): LINX germline outputs are processed below to contain tumor id in the filename as required by ORANGE - def normal_linx_arg = linx_germline_anno_dir ? "-linx_germline_data_directory normal_linx__prepared/" : '' + def normal_linx_arg = linx_germline_anno_dir ? "-linx_germline_data_directory ${linx_germline_anno_dir}" : '' def rna_id_arg = meta.containsKey('tumor_wts_id') ? "-rna_sample_id ${meta.tumor_wts_id}" : '' def isofox_summary_csv_arg = isofox_dir ? "-isofox_summary_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.summary.csv" : '' @@ -55,15 +54,6 @@ process ORANGE { """ echo "${pipeline_version_str}" > pipeline_version.txt - # Replace identifiers as required - if [[ -n "${normal_linx_arg}" ]]; then - mkdir -p normal_linx__prepared/; - for fp in ${linx_germline_anno_dir}/*; do - fn=\${fp##*/}; - ln -s ../${linx_germline_anno_dir}/\${fn} normal_linx__prepared/\$(sed 's/${meta.normal_wgs_id}/${meta.tumor_id}/' <<< \${fn}); - done; - fi - # When WTS data is present, ORANGE expects the somatic SAGE VCF to have appended WTS data; CS indicates this should # occur after PURPLE. Since ORANGE only collects the somatic SAGE VCF from the PURPLE output directory, we must # prepare accordingly diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf index 8654d077..9849d6a1 100644 --- a/subworkflows/local/linx_annotation.nf +++ b/subworkflows/local/linx_annotation.nf @@ -54,7 +54,7 @@ workflow LINX_ANNOTATION { def meta_linx = [ key: meta.id, - id: Utils.getNormalWgsSampleName(meta), + id: tumor_id, ] return [meta_linx, sv_vcf] From 72899cfdb1b4296fc81a9be08cacbf8bc54c41b6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 25 Jul 2023 13:56:08 +1000 Subject: [PATCH 189/562] Update LINX Docker image to 1.24.1_beta--1 * LINX 1.24.1_beta build artefact updated without new version * Visualiser now exits cleanly for empty input if no other config set --- modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 917e281b..9f780d4c 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -2,7 +2,7 @@ process LINX_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.24.1_beta--0' + container 'docker.io/scwatts/linx:1.24.1_beta--1' input: tuple val(meta), path(sv_vcf) diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 44e1e561..cc259d32 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,7 +2,7 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.24.1_beta--0' + container 'docker.io/scwatts/linx:1.24.1_beta--1' input: tuple val(meta), path(purple_dir) diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index de544344..ace21414 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,7 +2,7 @@ process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/linx:1.24.1_beta--0' + container 'docker.io/scwatts/linx:1.24.1_beta--1' input: tuple val(meta), path(linx) From 25bcb4c79981e4d6574df3a4629a101c239763e9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 27 Jul 2023 12:09:16 +1000 Subject: [PATCH 190/562] Fix memory allocation for SV Prep SAMtools sort --- modules/local/svprep/svprep/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 274974dc..41207992 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -43,7 +43,7 @@ process SVPREP { samtools sort \\ -@ ${task.cpus} \\ - -m ${Math.min(Math.round(task.memory.mega * 0.95), 4096)}K \\ + -m ${Math.round(task.memory.bytes * 0.95 / 1024 / task.cpus)}K \\ -T ${meta.id}.sv_prep.tmp \\ -o ${meta.id}.sv_prep.sorted.bam \\ ${meta.id}.sv_prep.bam From b883c43842a38278d5f88026a5c5a009ca0ccf4e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 27 Jul 2023 12:09:50 +1000 Subject: [PATCH 191/562] Always calculate fragment dist for SV Prep normal --- subworkflows/local/gridss_svprep_calling.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index ead84d64..d272b876 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -61,7 +61,7 @@ workflow GRIDSS_SVPREP_CALLING { genome_version, sv_prep_blocklist, known_fusions, - 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument switch and value + 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument ) ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) @@ -102,7 +102,7 @@ workflow GRIDSS_SVPREP_CALLING { genome_version, sv_prep_blocklist, known_fusions, - false, // -write_types argument switch and value + 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument ) ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) From c781480f044a99dcbe017964d9a8870a0fdaf3f7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 27 Jul 2023 18:20:19 +1000 Subject: [PATCH 192/562] Update LILAC subworkflow * No longer slice BAMs for non-alt references * Do not handle the case of duplicate inputs --- conf/hmf_data.config | 2 - lib/WorkflowLilac.groovy | 100 --------------- subworkflows/local/lilac_calling.nf | 182 +++++++++++++++------------- workflows/wgts.nf | 16 +-- 4 files changed, 105 insertions(+), 195 deletions(-) delete mode 100755 lib/WorkflowLilac.groovy diff --git a/conf/hmf_data.config b/conf/hmf_data.config index 29aff795..eeb9ee6a 100644 --- a/conf/hmf_data.config +++ b/conf/hmf_data.config @@ -20,7 +20,6 @@ params { isofox_gc_ratios = 'rna_pipeline/read_100_exp_gc_ratios.csv' // LILAC lilac_resources = 'dna_pipeline/immune/' - hla_slice_bed = 'other/lilac/hla.37.bed' // ORANGE cohort_mapping = 'orange/cohort_mapping.tsv' cohort_percentiles = 'orange/cohort_percentiles.tsv' @@ -71,7 +70,6 @@ params { isofox_gc_ratios = 'rna_pipeline/read_100_exp_gc_ratios.csv' // LILAC lilac_resources = 'dna_pipeline/immune/' - hla_slice_bed = 'other/lilac/hla.38.bed' // ORANGE cohort_mapping = 'orange/cohort_mapping.tsv' cohort_percentiles = 'orange/cohort_percentiles.tsv' diff --git a/lib/WorkflowLilac.groovy b/lib/WorkflowLilac.groovy deleted file mode 100755 index dc1fa124..00000000 --- a/lib/WorkflowLilac.groovy +++ /dev/null @@ -1,100 +0,0 @@ -// -// This file holds several functions specific to the subworkflows/lilac.nf in the nf-core/oncoanalyser pipeline -// -import nextflow.Nextflow - -import Constants -import Utils - - -class WorkflowLilac { - - public static getSliceInputs(ch, tumor_sequence_type) { - // channel: [val(meta_lilac), bam, bai] - return ch - .flatMap { meta, nbam_wgs, nbai_wgs, tbam_wgs, tbai_wgs, tbam_wts, tbai_wts -> - def data = [ - [nbam_wgs, nbai_wgs, Constants.SequenceType.WGS, Constants.SampleType.NORMAL], - [tbam_wgs, tbai_wgs, tumor_sequence_type, Constants.SampleType.TUMOR], - [tbam_wts, tbai_wts, Constants.SequenceType.WTS, Constants.SampleType.TUMOR], - ] - def data_present = data.findAll { it[0] } - data_present - .collect { bam, bai, sequence_type, sample_type -> - def sample_name = meta.getAt(['sample_name', sample_type, sequence_type]) - def meta_lilac = [ - key: meta.id, - id: sample_name, - // NOTE(SW): must use string representation for caching purposes - sample_type_str: sample_type.name(), - sequence_type_str: sequence_type.name(), - count: data_present.size(), - ] - return [meta_lilac, bam, bai] - } - } - } - - public static getUniqueInputFiles(ch) { - // channel: [val(meta_lilac), bam, bai] - def d = ch - .map { [it[1..-1], it[0]] } - .groupTuple() - .map { filepaths, meta_lilac -> - // NOTE(SW): pattern needs to be generalised - def (keys, sample_names, sequence_type_strs, sample_type_strs) = meta_lilac - .collect { [it.key, it.id, it.sequence_type_str, it.sample_type_str] } - .transpose() - def sample_type_str = getValue(sample_type_strs) - def sequence_type_str = getValue(sequence_type_strs) - - def key = keys.join('__') - def meta_lilac_new = [ - keys: keys, - id: sample_names.join('__'), - id_simple: keys.join('__'), - sequence_type_str: sequence_type_str, - sample_type_str: sample_type_str, - ] - return [meta_lilac_new, *filepaths] - } - return d - } - - public static sortSlices(ch, tumor_sequence_type) { - // Gather and order files from same grouping using non-blocked groupTuple via provided file counts - // channel: [val(meta_lilac), normal_wgs_bam, normal_wgs_bai, tumor_wgs_bam, tumor_wgs_bai, tumor_wts_bam, tumor_wts_bai] - def d = ch - .map { meta, data -> - return [nextflow.Nextflow.groupKey(meta.key, meta.count), meta, data] - } - .groupTuple() - .map { gk, metas, values -> - assert metas.unique().size() == 1 - def meta = metas[0] - def data = [:] - values.each { sequence_type_str, sample_type_str, bam, bai -> - def sample_type = Utils.getEnumFromString(sample_type_str, Constants.SampleType) - def sequence_type = Utils.getEnumFromString(sequence_type_str, Constants.SequenceType) - data[[sample_type, sequence_type, 'bam']] = bam - data[[sample_type, sequence_type, 'bai']] = bai - } - return [ - meta, - data.get([Constants.SampleType.NORMAL, Constants.SequenceType.WGS, 'bam'], []), - data.get([Constants.SampleType.NORMAL, Constants.SequenceType.WGS, 'bai'], []), - data.get([Constants.SampleType.TUMOR, tumor_sequence_type, 'bam'], []), - data.get([Constants.SampleType.TUMOR, tumor_sequence_type, 'bai'], []), - data.get([Constants.SampleType.TUMOR, Constants.SequenceType.WTS, 'bam'], []), - data.get([Constants.SampleType.TUMOR, Constants.SequenceType.WTS, 'bai'], []), - ] - } - return d - } - - public static getValue(l) { - def u = l.unique(false) - assert u.size() == 1 - return u[0] - } -} diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index aa9f98c2..d82a01e6 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -39,7 +39,7 @@ workflow LILAC_CALLING { ch_lilac_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional') } - // Create channel with all available input BAMs + // Create channels for available input BAMs // channel: [ meta, wts_bam, wts_bai ] ch_lilac_bams_wts = Channel.empty() if (run_config.mode == Constants.RunMode.WTS || run_config.mode == Constants.RunMode.WGTS) { @@ -76,19 +76,6 @@ workflow LILAC_CALLING { ch_lilac_bams = ch_inputs.map { meta -> [meta, [], [], [], []] } } - // Combine BAMs - // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai ] - ch_lilac_bams = WorkflowOncoanalyser.groupByMeta( - ch_lilac_bams_wts, - ch_lilac_bams, - flatten_mode: 'nonrecursive', - ) - .map { data -> - def meta = data[0] - def (tbam_wts, tbai_wts, tbam, nbam, tbai, nbai) = data[1..-1] - return [meta, nbam, nbai, tbam, tbai, tbam_wts, tbai_wts] - } - // Set tumor sequence type for non-WTS input (i.e. WGS or panel) switch(run_config.mode) { case Constants.RunMode.WGS: @@ -99,35 +86,64 @@ workflow LILAC_CALLING { assert false } - // Slice HLA regions - // NOTE(SW): here I remove duplicate files so that we only process each input once - // NOTE(SW): orphaned reads are sometimes obtained, this is the slicing procedure used - // in Pipeline5, see LilacBamSlicer.java#L115 - // channel: [ meta_lilac, bam, bai ] - ch_slice_inputs = WorkflowLilac.getSliceInputs(ch_lilac_bams, tumor_sequence_type) - // Isolate meta containing expected file count to use for non-blocking groupTuple later - ch_slice_meta_individual = ch_slice_inputs - .map { - def meta_lilac = it[0] - return [key: meta_lilac.key, count: meta_lilac.count] - } - // Apply slicing to unique files only - // channel: [ meta_lilac, bam, bai ] - ch_slice_inputs_unique = WorkflowLilac.getUniqueInputFiles(ch_slice_inputs) - SLICEBAM( - ch_slice_inputs_unique, - hla_slice_bed, - ) - ch_versions = ch_versions.mix(SLICEBAM.out.versions) - - // Realign contigs if using 38 (use of ALT contigs implied) - // channel: [ meta_lilac, bam, bai ] - ch_slices_out = SLICEBAM.out.bam + // Realign reads mapping to HLA regions and homologus regions if using reference genome with ALT contigs + // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them to the three + // relevant HLA genes on chr6. All reads including those previously mapped to chr6 are realigned for + // consistency. + // channel: [ meta, bam, bai ] + ch_lilac_bams = ch_lilac_bams if (params.ref_data_genome_type == 'alt') { - // Align reads with chr6 - // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them - // to the three relevant HLA genes on chr6. All reads including those previously mapped to chr6 - // are realigned for consistency. + + // Split non-WTS BAMs into tumor and normal, accounting for optional input + // channel: [ meta_extra, bam, bai ] + ch_slice_bams = ch_lilac_bams + .flatMap { meta, tumor_bam, normal_bam, tumor_bai, normal_bai -> + return [ + [[key: meta.id, *:meta, sequence_type: 'tumor'], tumor_bam, tumor_bai], + [[key: meta.id, *:meta, sequence_type: 'normal'], normal_bam, normal_bai], + ] + } + .branch { + def empty = it[1..-1] == [[], []] + present: !empty + absent: empty + } + + // Prepare slice input channel + // channel: [ meta_slice, bam, bai ] + ch_slice_bams_input = ch_slice_bams.present + .map { meta, bam, bai -> + + def sample_name + if (meta.sequence_type == 'tumor') { + sample_name = meta[['sample_name', Constants.SampleType.TUMOR, tumor_sequence_type]] + } else if (meta.sequence_type == 'normal') { + sample_name = meta[['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.WGS]] + } + + def meta_slice = [ + key: meta.id, + id: sample_name, + sequence_type: meta.sequence_type, + ] + + return [meta_slice, bam, bai] + + } + + // + // MODULE: Custom BAM slice (LILAC) + // + SLICEBAM( + ch_slice_bams_input, + hla_slice_bed, + ) + ch_versions = ch_versions.mix(SLICEBAM.out.versions) + + // + // MODULE: Custom extract contig (LILAC) + // + // Extract chromosome 6 from the reference and create BWA indexes EXTRACTCONTIG( 'chr6', genome_fasta, @@ -135,58 +151,57 @@ workflow LILAC_CALLING { ) ch_versions = ch_versions.mix(EXTRACTCONTIG.out.versions) - ch_slice_bams = SLICEBAM.out.bam - .branch { meta_lilac, bam, bai -> - def sequence_type = Utils.getEnumFromString(meta_lilac.sequence_type_str, Constants.SequenceType) - wts: sequence_type == Constants.SequenceType.WTS - // WGS or targetted - non_wts: sequence_type != Constants.SequenceType.WTS - } - + // + // MODULE: Custom realign reads (LILAC) + // + // Realign selected reads relevant to HLA to chromosome 6 REALIGNREADS( - ch_slice_bams.non_wts, + SLICEBAM.out.bam, EXTRACTCONTIG.out.contig, EXTRACTCONTIG.out.bwa_indices, ) - ch_slices_out = Channel.empty().mix(REALIGNREADS.out.bam, ch_slice_bams.wts) ch_versions = ch_versions.mix(REALIGNREADS.out.versions) - } - // Re-replicate and flow expected file count into meta - // channel: [ meta_lilac, [sequence_type_str, sample_type_str, bam, bai] ] - ch_slices_out_individual = ch_slices_out - .flatMap{ data -> - def meta_lilac = data[0] - def fps = data[1..-1] - meta_lilac.keys.collect { key -> - return [[key: key], [meta_lilac.sequence_type_str, meta_lilac.sample_type_str, *fps]] + // Split realigned BAMs by sequence type for processing below + // channel: [ meta, bam, bai ] + ch_slice_reunited_bams = REALIGNREADS.out.bam + .mix (ch_slice_bams.absent) + .branch { + def meta = it[0] + tumor: meta.sequence_type == 'tumor' + normal: meta.sequence_type == 'normal' + } + + // Restore original meta for realigned BAMs then combine with absent inputs + // channel: [ meta, tumor_bam, normal_bam, tumor_bai, normal_bai ] + ch_lilac_bams = WorkflowOncoanalyser.groupByMeta( + WorkflowOncoanalyser.restoreMeta(ch_slice_reunited_bams.tumor, ch_inputs), + WorkflowOncoanalyser.restoreMeta(ch_slice_reunited_bams.normal, ch_inputs), + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [meta, tumor_bam, normal_bam, tumor_bai, normal_bai] } - } - // Adding expected file count - // channel: [ meta_lilac, [sequence_type_str, sample_type_str, bam, bai] ] - ch_slices_ready = WorkflowOncoanalyser.joinMeta( - ch_slices_out_individual, - ch_slice_meta_individual, - key_a: 'key', - ) - // Gather and order files from same grouping using non-blocked groupTuple via provided file counts - // channel: [ meta_lilac, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai ] - ch_slices_organised = WorkflowLilac.sortSlices(ch_slices_ready, tumor_sequence_type) - - // Restore original meta so we can join with PURPLE directory - // channel: [val(meta)] - ch_metas = ch_lilac_bams.map { return it[0] } - // channel: [val(meta), normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai] - ch_lilac_inputs_slices = WorkflowOncoanalyser.restoreMeta( - ch_slices_organised, - ch_metas, + } + + // Combine non-WTS and WTS BAMs + // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai ] + ch_lilac_bams_combined = WorkflowOncoanalyser.groupByMeta( + ch_lilac_bams_wts, + ch_lilac_bams, + flatten_mode: 'nonrecursive', ) + .map { data -> + def meta = data[0] + def (tbam_wts, tbai_wts, tbam, nbam, tbai, nbai) = data[1..-1] + return [meta, nbam, nbai, tbam, tbai, tbam_wts, tbai_wts] + } - // Get inputs from PURPLE + // Get PURPLE inputs // channel: [ meta, gene_cn ] ch_lilac_inputs_gene_cn = ch_lilac_inputs_purple .map { meta, purple_dir -> + if (purple_dir == []) { return [meta, []] } @@ -208,9 +223,10 @@ workflow LILAC_CALLING { return smlv_vcf.exists() ? [meta, smlv_vcf] : [meta, []] } - // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, purple_dir ] + // Add PURPLE inputs + // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, gene_cn, smlv_vcf ] ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( - ch_lilac_inputs_slices, + ch_lilac_bams_combined, ch_lilac_inputs_gene_cn, ch_lilac_inputs_smlv_vcf, flatten_mode: 'nonrecursive', diff --git a/workflows/wgts.nf b/workflows/wgts.nf index be653852..c0b13a6e 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -24,8 +24,10 @@ if (run_config.stages.virusinterpreter) { checkPathParamList.add(params.ref_data_virusbreakenddb_path) } -if (run_config.stages.lilac && params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt') { - checkPathParamList.add(params.ref_data_hla_slice_bed) +if (run_config.stages.lilac) { + if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && params.containsKey('ref_data_hla_slice_bed')) { + checkPathParamList.add(params.ref_data_hla_slice_bed) + } } // TODO(SW): consider whether we should check for null entries here for errors to be more informative @@ -462,14 +464,8 @@ workflow WGTS { ch_lilac_out = Channel.empty() if (run_config.stages.lilac) { - // Select HLA slice BED - if (params.ref_data_genome_type == 'no_alt') { - ref_data_hla_slice_bed = hmf_data.hla_slice_bed.collect() - } else if (params.ref_data_genome_type == 'alt' && params.ref_data_genome_version == '38') { - ref_data_hla_slice_bed = params.ref_data_hla_slice_bed - } else { - assert false - } + // Set HLA slice BED if provided in params + ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] LILAC_CALLING( ch_inputs, From cd9d644b9946a2a41793a2d3080e47deea00aaed Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 27 Jul 2023 18:23:49 +1000 Subject: [PATCH 193/562] =?UTF-8?q?Bump=20LINX=20version:=201.24.1=5Fbeta?= =?UTF-8?q?=20=E2=86=92=201.24.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/linx/Dockerfile | 2 +- modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/linx/Dockerfile b/modules/local/linx/Dockerfile index 58eed266..b5d68ae9 100644 --- a/modules/local/linx/Dockerfile +++ b/modules/local/linx/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/linx/ && \ - wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.24.1.beta/linx_v1.24.1.beta.jar' + wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.24.1/linx_v1.24.1.jar' USER mambauser diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 9f780d4c..3a7c632b 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -2,7 +2,7 @@ process LINX_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.24.1_beta--1' + container 'docker.io/scwatts/linx:1.24.1--0' input: tuple val(meta), path(sv_vcf) diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index cc259d32..52944730 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,7 +2,7 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.24.1_beta--1' + container 'docker.io/scwatts/linx:1.24.1--0' input: tuple val(meta), path(purple_dir) diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index ace21414..64412d95 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,7 +2,7 @@ process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/linx:1.24.1_beta--1' + container 'docker.io/scwatts/linx:1.24.1--0' input: tuple val(meta), path(linx) From dcf79962492b3d7c7128f31b6a0b80aa5d1961f8 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 28 Jul 2023 11:24:21 +1000 Subject: [PATCH 194/562] =?UTF-8?q?Bump=20SV=20Prep=20version:=201.1=20?= =?UTF-8?q?=E2=86=92=201.2.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/svprep/Dockerfile | 4 ++-- modules/local/svprep/assemble/main.nf | 4 +++- modules/local/svprep/call/main.nf | 4 +++- modules/local/svprep/depth_annotator/main.nf | 5 +++-- modules/local/svprep/preprocess/main.nf | 4 +++- modules/local/svprep/svprep/main.nf | 9 +++++---- 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile index d3337b83..dd653602 100644 --- a/modules/local/svprep/Dockerfile +++ b/modules/local/svprep/Dockerfile @@ -11,8 +11,8 @@ RUN \ RUN \ mkdir -p /opt/svprep/ && \ - wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.1/sv-prep_v1.1.jar' && \ - wget -O /opt/svprep/gridss_svprep 'https://raw.githubusercontent.com/hartwigmedical/hmftools/sv-prep-v1.1/sv-prep/src/main/resources/gridss/gridss.run.sh' + wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.2.1/sv-prep_v1.2.1.jar' && \ + wget -O /opt/svprep/gridss_svprep 'https://raw.githubusercontent.com/hartwigmedical/hmftools/sv-prep-v1.2.1/sv-prep/src/main/resources/gridss/gridss.run.sh' COPY assets/gridss_svprep.patch /tmp/ RUN \ diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index ba358a88..0385f96b 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -2,7 +2,7 @@ process GRIDSS_ASSEMBLE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--1' + container 'docker.io/scwatts/svprep:1.2.1--0' input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) @@ -80,9 +80,11 @@ process GRIDSS_ASSEMBLE { ${bams_arg} \\ ${bams_filtered_arg} + # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + svprep: 1.2.1 END_VERSIONS """ diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 29b2e0dd..2bf235e3 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -2,7 +2,7 @@ process GRIDSS_CALL { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--1' + container 'docker.io/scwatts/svprep:1.2.1--0' input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) @@ -79,9 +79,11 @@ process GRIDSS_CALL { ${bams_arg} \\ ${bams_filtered_arg} + # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + svprep: 1.2.1 END_VERSIONS """ diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 16b0d700..de20bf4d 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -2,7 +2,7 @@ process SVPREP_DEPTH_ANNOTATOR { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--1' + container 'docker.io/scwatts/svprep:1.2.1--0' input: tuple val(meta), path(bams), path(bais), path(vcf), val(labels) @@ -38,9 +38,10 @@ process SVPREP_DEPTH_ANNOTATOR { -threads ${task.cpus} \\ -output_vcf ${meta.tumor_id}.gridss.vcf.gz + # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - svprep: \$(java -jar ${task.ext.jarPath} 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + svprep: 1.2.1 END_VERSIONS """ diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index a766531a..eb14ca39 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -2,7 +2,7 @@ process GRIDSS_PREPROCESS { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--1' + container 'docker.io/scwatts/svprep:1.2.1--0' input: tuple val(meta), path(bam), path(bam_filtered) @@ -43,9 +43,11 @@ process GRIDSS_PREPROCESS { --filtered_bams ${bam_filtered} \\ --output placeholder + # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + svprep: 1.2.1 END_VERSIONS """ diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 41207992..be3a3964 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -2,7 +2,7 @@ process SVPREP { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.1--1' + container 'docker.io/scwatts/svprep:1.2.1--0' input: tuple val(meta), path(bam), path(bai), path(junctions) @@ -14,7 +14,7 @@ process SVPREP { output: tuple val(meta), path("*.sorted.bam") , emit: bam - tuple val(meta), path("*.sv_prep.junctions.csv"), emit: junctions + tuple val(meta), path("*.sv_prep.junctions.tsv"), emit: junctions path 'versions.yml' , emit: versions when: @@ -48,16 +48,17 @@ process SVPREP { -o ${meta.id}.sv_prep.sorted.bam \\ ${meta.id}.sv_prep.bam + # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - svprep: \$(java -jar ${task.ext.jarPath} 2>&1 | head -n1 | sed 's/^.*SvPrep version: //') + svprep: 1.2.1 END_VERSIONS """ stub: """ touch "${meta.id}.sv_prep.sorted.bam" - touch "${meta.id}.sv_prep.junctions.csv" + touch "${meta.id}.sv_prep.junctions.tsv" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } From 2ec0ed95e42a91c30f6229c7fdf80c1ec6d7b1d6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 28 Jul 2023 12:20:43 +1000 Subject: [PATCH 195/562] Use Hartwig gridss.properties by default --- conf/hmf_data.config | 2 ++ lib/Constants.groovy | 4 ++-- nextflow.config | 1 - workflows/wgts.nf | 11 +++++++++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/conf/hmf_data.config b/conf/hmf_data.config index eeb9ee6a..1f74623b 100644 --- a/conf/hmf_data.config +++ b/conf/hmf_data.config @@ -45,6 +45,7 @@ params { driver_gene_panel = 'dna_pipeline/common/DriverGenePanel.37.tsv' ensembl_data_resources = 'dna_pipeline/common/ensembl_data/' gnomad_resource = 'dna_pipeline/variants/gnomad_variants_v37.csv.gz' + gridss_config = 'dna_pipeline/sv/gridss.properties' known_fusion_data = 'dna_pipeline/sv/known_fusion_data.37.csv' known_fusions = 'dna_pipeline/sv/known_fusions.37.bedpe' purple_germline_del = 'dna_pipeline/copy_number/cohort_germline_del_freq.37.csv' @@ -95,6 +96,7 @@ params { driver_gene_panel = 'dna_pipeline/common/DriverGenePanel.38.tsv' ensembl_data_resources = 'dna_pipeline/common/ensembl_data/' gnomad_resource = 'dna_pipeline/variants/gnomad/' + gridss_config = 'dna_pipeline/sv/gridss.properties' known_fusion_data = 'dna_pipeline/sv/known_fusion_data.38.csv' known_fusions = 'dna_pipeline/sv/known_fusions.38.bedpe' purple_germline_del = 'dna_pipeline/copy_number/cohort_germline_del_freq.38.csv' diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 28bfd26d..6fdf97de 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -9,8 +9,8 @@ class Constants { static List GENOMES_DEFINED = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 - static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.32_37_0.0.3.tar.gz' - static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.32_38_0.0.3.tar.gz' + static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.32_37_0.0.4.tar.gz' + static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.32_38_0.0.4.tar.gz' static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' diff --git a/nextflow.config b/nextflow.config index c84c0999..07a3ff63 100644 --- a/nextflow.config +++ b/nextflow.config @@ -40,7 +40,6 @@ params { enable_conda = false // Other workflow inputs and options - gridss_config = null linx_gene_id_file = null isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' use_isofox_exp_counts_cache = false diff --git a/workflows/wgts.nf b/workflows/wgts.nf index c0b13a6e..6ee43317 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -15,11 +15,16 @@ run_config = WorkflowMain.getRunConfig(params, log) // Check input path parameters to see if they exist def checkPathParamList = [ params.input, - params.gridss_config, params.linx_gene_id_file, ] // Conditional requirements +if (run_config.stages.gridss) { + if (params.containsKey('gridss_config')) { + checkPathParamList.add(params.gridss_config) + } +} + if (run_config.stages.virusinterpreter) { checkPathParamList.add(params.ref_data_virusbreakenddb_path) } @@ -95,7 +100,6 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft // Get absolute file paths samplesheet = Utils.getFileObject(params.input) -gridss_config = Utils.getFileObject(params.gridss_config) workflow WGTS { // Create channel for versions @@ -117,6 +121,9 @@ workflow WGTS { ref_data = PREPARE_REFERENCE.out hmf_data = PREPARE_REFERENCE.out.hmf_data + // Set GRIDSS config + gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config + // // MODULE: Run Isofox to analyse WTS data // From 380cca1d835d4c60c5db2860dde434f92028836f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 2 Aug 2023 09:28:57 +1000 Subject: [PATCH 196/562] Restore GRIDSS Dockerfile --- modules/local/gridss/Dockerfile | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 modules/local/gridss/Dockerfile diff --git a/modules/local/gridss/Dockerfile b/modules/local/gridss/Dockerfile new file mode 100644 index 00000000..6373cf84 --- /dev/null +++ b/modules/local/gridss/Dockerfile @@ -0,0 +1,37 @@ +FROM mambaorg/micromamba:0.24.0 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'gridss==2.13.2' && \ + micromamba clean --all --yes + +# NOTE(SW): required to correctly check SAMtools version built by Conda +RUN \ + sed -i \ + -e '209s/grep samtools/head -n1 | grep samtools/' \ + /opt/conda/share/gridss-2.13.2-1/gridss_extract_overlapping_fragments + +# NOTE(SW): required to run tests on compute with low resources; without the +# change this GRIDSS invoke will attempt to allocate the default 30 GB of +# memory even when `--gridssargs` is set +RUN \ + sed -i \ + -e '779a \\t\t$gridssargs \\' \ + /opt/conda/share/gridss-2.13.2-1/virusbreakend + +RUN \ + ln -sf \ + /opt/conda/pkgs/gridss-2.13.2-h20b1175_1/share/gridss-2.13.2-1/gridss \ + /opt/conda/bin/gridss + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" From 3f0adc4259446567282b871eb6ebd40a0da1b801 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 1 Aug 2023 18:05:52 +1000 Subject: [PATCH 197/562] Align with Pipeline5 v5.33 --- conf/modules.config | 8 +-- lib/Constants.groovy | 26 +++----- modules/local/bamtools/Dockerfile | 2 +- modules/local/bamtools/main.nf | 2 +- modules/local/chord/main.nf | 19 +++--- modules/local/chord/meta.yml | 11 +-- modules/local/cobalt/Dockerfile | 9 ++- modules/local/cobalt/main.nf | 4 +- modules/local/cuppa/Dockerfile | 4 +- modules/local/cuppa/main.nf | 10 +-- modules/local/isofox/main.nf | 4 +- modules/local/lilac/Dockerfile | 2 +- modules/local/lilac/main.nf | 12 ++-- modules/local/linx/visualiser/main.nf | 2 +- modules/local/orange/Dockerfile | 2 +- modules/local/orange/main.nf | 74 ++++++++++----------- modules/local/pave/Dockerfile | 2 +- modules/local/pave/germline/main.nf | 17 ++++- modules/local/pave/somatic/main.nf | 5 +- modules/local/purple/Dockerfile | 2 +- modules/local/purple/main.nf | 5 +- modules/local/sage/Dockerfile | 2 +- modules/local/sage/append/main.nf | 9 ++- modules/local/sage/germline/main.nf | 47 +++++++------ modules/local/sage/somatic/main.nf | 47 +++++++------ modules/local/sigs/main.nf | 2 +- modules/local/virusinterpreter/Dockerfile | 2 +- modules/local/virusinterpreter/main.nf | 15 ++--- subworkflows/local/channel_inputs_purple.nf | 2 + subworkflows/local/chord_prediction.nf | 9 ++- subworkflows/local/lilac_calling.nf | 35 ++-------- subworkflows/local/orange_reporting.nf | 25 +++---- subworkflows/local/pave_annotation.nf | 3 +- subworkflows/local/prepare_input.nf | 1 - subworkflows/local/purple_calling.nf | 10 +-- subworkflows/local/sage_append.nf | 15 +++-- subworkflows/local/sage_calling.nf | 20 +++--- subworkflows/local/virusbreakend_calling.nf | 26 ++------ workflows/wgts.nf | 33 +++++---- 39 files changed, 250 insertions(+), 275 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index d58c83fa..3f8a586a 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -22,7 +22,7 @@ process { } withName: 'COBALT' { - ext.jarPath = '/opt/conda/share/hmftools-cobalt-1.13-1/cobalt.jar' + ext.jarPath = '/opt/cobalt/cobalt.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -107,7 +107,7 @@ process { withName: 'PURPLE' { ext.jarPath = '/opt/purple/purple.jar' - ext.circosPath = 'circos' + ext.circosPath = '/opt/conda/bin/circos' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -136,7 +136,7 @@ process { } withName: '.*:LINX_PLOTTING:VISUALISER' { - ext.path_circos = '/opt/conda/bin/circos' + ext.circosPath = '/opt/conda/bin/circos' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -165,7 +165,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/chord/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/chord/${filename}" }, ] } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 6fdf97de..3dba47d5 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -9,8 +9,8 @@ class Constants { static List GENOMES_DEFINED = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 - static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.32_37_0.0.4.tar.gz' - static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.32_38_0.0.4.tar.gz' + static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.33_37--0.tar.gz' + static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.33_38--0.tar.gz' static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' @@ -66,13 +66,12 @@ class Constants { SAGE_VCF, VIRUSINTERPRETER_TSV, // ORANGE specific - CHORD_PREDICTION, + CHORD_DIR, SIGS_DIR, CUPPA_DIR, FLAGSTAT, LINX_PLOT_DIR, - SAGE_BQR, - SAGE_COVERAGE, + SAGE_DIR, } static enum SampleType { @@ -141,18 +140,13 @@ class Constants { SampleType.NORMAL, SequenceType.WGS ], - SAGE_BQR_TUMOR: [ - FileType.SAGE_BQR, + SAGE_DIR_TUMOR: [ + FileType.SAGE_DIR, SampleType.TUMOR, SequenceType.WGS, ], - SAGE_BQR_NORMAL: [ - FileType.SAGE_BQR, - SampleType.NORMAL, - SequenceType.WGS - ], - SAGE_COVERAGE: [ - FileType.SAGE_COVERAGE, + SAGE_DIR_NORMAL: [ + FileType.SAGE_DIR, SampleType.NORMAL, SequenceType.WGS ], @@ -217,8 +211,8 @@ class Constants { SequenceType.WGS ], - CHORD_PREDICTION: [ - FileType.CHORD_PREDICTION, + CHORD_DIR: [ + FileType.CHORD_DIR, SampleType.TUMOR, SequenceType.WGS ], diff --git a/modules/local/bamtools/Dockerfile b/modules/local/bamtools/Dockerfile index e850f9ce..ef221d50 100644 --- a/modules/local/bamtools/Dockerfile +++ b/modules/local/bamtools/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/bamtools/ && \ - wget -O /opt/bamtools/bamtools.jar 'https://github.com/hartwigmedical/hmftools/releases/download/bam-tools-v1.0.1/bam-tools_v1.0.1.jar' + wget -O /opt/bamtools/bamtools.jar 'https://github.com/hartwigmedical/hmftools/releases/download/bam-tools-v1.1/bam-tools_v1.1.jar' USER mambauser diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf index c0cd0dc3..a7136400 100644 --- a/modules/local/bamtools/main.nf +++ b/modules/local/bamtools/main.nf @@ -2,7 +2,7 @@ process BAMTOOLS { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/bamtools:1.0.1--0' + container 'docker.io/scwatts/bamtools:1.1--0' input: tuple val(meta), path(bam), path(bai) diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf index 5bd2abb3..d183ff37 100644 --- a/modules/local/chord/main.nf +++ b/modules/local/chord/main.nf @@ -9,9 +9,8 @@ process CHORD { val genome_ver output: - tuple val(meta), path('*_chord_prediction.txt'), emit: prediction - path '*_chord_signatures.txt' , emit: signatures - path 'versions.yml' , emit: versions + tuple val(meta), path('chord/'), emit: chord_dir + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -20,16 +19,19 @@ process CHORD { def args = task.ext.args ?: '' """ + mkdir -p chord/ + extractSigPredictHRD.R \\ ./ \\ ${meta.id} \\ ${smlv_vcf} \\ ${sv_vcf} \\ ${genome_ver} \\ - ${meta.id}_chord_signatures.txt \\ - ${meta.id}_chord_prediction.txt + chord_signatures.txt \\ + chord_prediction.txt + + mv ${meta.id}_chord_signatures.txt ${meta.id}_chord_prediction.txt chord/ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": CHORD: \$(R -s -e "message(packageVersion('CHORD'))") @@ -39,8 +41,9 @@ process CHORD { stub: """ - touch ${meta.id}_chord_signatures.txt - touch ${meta.id}_chord_prediction.txt + mkdir -p chord/ + touch chord/${meta.id}_chord_signatures.txt + touch chord/${meta.id}_chord_prediction.txt echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/chord/meta.yml b/modules/local/chord/meta.yml index d6d02374..56510f3d 100644 --- a/modules/local/chord/meta.yml +++ b/modules/local/chord/meta.yml @@ -32,14 +32,9 @@ output: description: | Groovy Map containing sample information e.g. [id: 'sample_id'] - - prediction: - type: file - description: HRD prediction - pattern: "*.{txt}" - - signatures: - type: file - description: Mutation signatures - pattern: "*.{txt}" + - chord_dir: + type: directory + description: CHORD output directory - versions: type: file description: File containing software versions diff --git a/modules/local/cobalt/Dockerfile b/modules/local/cobalt/Dockerfile index 867f4e7e..b7b4bd32 100644 --- a/modules/local/cobalt/Dockerfile +++ b/modules/local/cobalt/Dockerfile @@ -4,15 +4,20 @@ USER root RUN \ apt-get update && \ - apt-get install -y procps && \ + apt-get install -y procps wget && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* +RUN \ + mkdir -p /opt/cobalt/ && \ + wget -O /opt/cobalt/cobalt.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cobalt-v1.15.2/cobalt_v1.15.2.jar' + USER mambauser RUN \ micromamba install -y -n base -c bioconda -c conda-forge \ - 'hmftools-cobalt==1.13' \ + bioconductor-copynumber \ + 'openjdk >=8' \ r-dplyr && \ micromamba clean --all --yes diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index 8476e285..ff73d681 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -2,7 +2,7 @@ process COBALT { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/cobalt:1.13--1' + container 'docker.io/scwatts/cobalt:1.15.2--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -44,7 +44,7 @@ process COBALT { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - cobalt: 1.13 + cobalt: 1.15.2 END_VERSIONS """ diff --git a/modules/local/cuppa/Dockerfile b/modules/local/cuppa/Dockerfile index 1b84453b..51e50956 100644 --- a/modules/local/cuppa/Dockerfile +++ b/modules/local/cuppa/Dockerfile @@ -10,9 +10,9 @@ RUN \ RUN \ mkdir -p /opt/cuppa/ && \ - wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.8/cuppa_v1.8.jar' + wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.8.1/cuppa_v1.8.1.jar' -ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.8 +ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.8.1 ARG URL_BASE_CHART=${URL_BASE}/cuppa/src/main/resources/cuppa-chart ARG DIR_BASE=/opt/cuppa RUN \ diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index 72aa5f7f..346c8e28 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -2,7 +2,7 @@ process CUPPA { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.8--2' + container 'docker.io/scwatts/cuppa:1.8.1--0' input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter) @@ -60,25 +60,25 @@ process CUPPA { java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ - -sample_data ${meta.id} \\ + -sample ${meta.id} \\ -sample_data_dir sample_data/ \\ -categories ${categories_val} \\ -ref_data_dir ${cuppa_resources} \\ -ref_genome_version ${ref_genome_ver} \\ -create_pdf \\ - -output_dir ./cuppa/ + -output_dir cuppa/ if [[ ${categories_val} == 'DNA' || ${categories_val} == 'ALL' ]]; then python ${task.ext.chartScriptPath} \\ -sample ${meta.id} \\ -sample_data cuppa/${meta.id}.cup.data.csv \\ - -output_dir ./cuppa/; + -output_dir cuppa/; fi # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - cuppa: 1.8 + cuppa: 1.8.1 END_VERSIONS """ diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index e6aa71be..d9de66fe 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -2,7 +2,7 @@ process ISOFOX { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/isofox:1.6.1--0' + container 'docker.io/scwatts/isofox:1.6.2--0' input: tuple val(meta), path(bam), path(bai) @@ -42,7 +42,7 @@ process ISOFOX { -ensembl_data_dir ${ensembl_data_resources} \\ ${exp_counts_arg} \\ ${exp_gc_ratios_arg} \\ - -output_dir ./isofox/ \\ + -output_dir isofox/ \\ -threads ${task.cpus} cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/lilac/Dockerfile b/modules/local/lilac/Dockerfile index b7dfe9b9..d7ad496a 100644 --- a/modules/local/lilac/Dockerfile +++ b/modules/local/lilac/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/lilac/ && \ - wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.4.2/lilac_v1.4.2.jar' + wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.5/lilac_v1.5.jar' USER mambauser diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 65fdb26f..c5e81a90 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -2,10 +2,10 @@ process LILAC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/lilac:1.4.2--0' + container 'docker.io/scwatts/lilac:1.5--0' input: - tuple val(meta), path(normal_wgs_bam), path(normal_wgs_bai), path(tumor_bam), path(tumor_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(gene_cn), path(smlv_vcf) + tuple val(meta), path(normal_wgs_bam), path(normal_wgs_bai), path(tumor_bam), path(tumor_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(purple_dir) path genome_fasta val genome_ver path lilac_resources, stageAs: 'lilac_resources' @@ -25,8 +25,7 @@ process LILAC { def tumor_bam_arg = tumor_bam ? "-tumor_bam ${tumor_bam}" : '' def tumor_wts_bam_arg = tumor_wts_bam ? "-rna_bam ${tumor_wts_bam}" : '' - def gene_cn_arg = gene_cn ? "-gene_copy_number ${gene_cn}" : '' - def smlv_vcf_arg = smlv_vcf ? "-somatic_vcf ${smlv_vcf}" : '' + def purple_dir_arg = purple_dir ? "-purple_dir ${purple_dir}" : '' """ java \\ @@ -37,8 +36,7 @@ process LILAC { ${normal_bam_arg} \\ ${tumor_bam_arg} \\ ${tumor_wts_bam_arg} \\ - ${smlv_vcf_arg} \\ - ${gene_cn_arg} \\ + ${purple_dir_arg} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -resource_dir ${lilac_resources} \\ @@ -48,7 +46,7 @@ process LILAC { # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - lilac: 1.4.2 + lilac: 1.5 END_VERSIONS """ diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 64412d95..3102106a 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -33,7 +33,7 @@ process LINX_VISUALISER { -vis_file_dir ${linx} \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ - -circos ${task.ext.path_circos} \\ + -circos ${task.ext.circosPath} \\ -threads ${task.cpus} \\ -plot_out linx_visualiser/plot/ \\ -data_out linx_visualiser/data/ diff --git a/modules/local/orange/Dockerfile b/modules/local/orange/Dockerfile index 0581b863..5c479eef 100644 --- a/modules/local/orange/Dockerfile +++ b/modules/local/orange/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/orange/ && \ - wget -O /opt/orange/orange.jar 'https://github.com/hartwigmedical/hmftools/releases/download/orange-v2.3/orange_v2.3.jar' + wget -O /opt/orange/orange.jar 'https://github.com/hartwigmedical/hmftools/releases/download/orange-v2.6.0/orange_v2.6.0.jar' USER mambauser diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 61f5d3e2..edf650e3 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -2,10 +2,10 @@ process ORANGE { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/orange:2.3--0' + container 'docker.io/scwatts/orange:2.6.0--0' input: - tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_somatic_bqr), path(sage_germline_bqr), path(sage_germline_coverage), path(purple_dir), path(smlv_somatic_vcf), path(smlv_germline_vcf), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter), path(chord_prediction), path(sigs_dir), path(lilac_dir), path(cuppa_dir), path(isofox_dir) + tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_dir), path(sage_germline_dir), path(purple_dir), path(smlv_somatic_vcf), path(smlv_germline_vcf), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter_dir), path(chord_dir), path(sigs_dir), path(lilac_dir), path(cuppa_dir), path(isofox_dir) val genome_ver path disease_ontology path cohort_mapping @@ -29,27 +29,22 @@ process ORANGE { def args = task.ext.args ?: '' def pipeline_version_str = pipeline_version ?: 'not specified' - def virusinterpreter_arg = virusinterpreter ? "-annotated_virus_tsv ${virusinterpreter}" : '' - def chord_arg = chord_prediction ? "-chord_prediction_txt ${chord_prediction}" : '' - def sigs_arg = sigs_dir ? "-sigs_allocation_tsv ${sigs_dir}/${meta.tumor_id}.sig.allocation.tsv" : '' - def cuppa_csv_arg = cuppa_dir ? "-cuppa_result_csv ${cuppa_dir}/${meta.tumor_id}.cup.data.csv" : '' - def cuppa_summary_arg = cuppa_dir ? "-cuppa_summary_plot ${cuppa_dir}/${meta.tumor_id}.cup.report.summary.png" : '' + def virus_dir_arg = virusinterpreter_dir ? "-virus_dir ${virusinterpreter_dir}" : '' + def chord_dir_arg = chord_dir ? "-chord_dir ${chord_dir}" : '' + def sigs_dir_arg = sigs_dir ? "-sigs_dir ${sigs_dir}" : '' + def cuppa_dir_arg = cuppa_dir ? "-cuppa_dir ${cuppa_dir}" : '' def normal_id_arg = meta.containsKey('normal_wgs_id') ? "-reference_sample_id ${meta.normal_wgs_id}" : '' def normal_metrics_arg = bam_metrics_germline ? "-ref_sample_wgs_metrics_file ${bam_metrics_germline}" : '' def normal_flagstat_arg = flagstat_germline ? "-ref_sample_flagstat_file ${flagstat_germline}" : '' - def normal_sage_somatic_bqr_arg = sage_germline_bqr ? "-sage_somatic_ref_sample_bqr_plot ${sage_germline_bqr}" : '' - def normal_sage_coverage_arg = sage_germline_coverage ? "-sage_germline_gene_coverage_tsv ${sage_germline_coverage}" : '' - def normal_linx_arg = linx_germline_anno_dir ? "-linx_germline_data_directory ${linx_germline_anno_dir}" : '' + def normal_sage_dir = sage_germline_dir ? "-sage_germline_dir ${sage_germline_dir}" : '' + def normal_linx_arg = linx_germline_anno_dir ? "-linx_germline_dir ${linx_germline_anno_dir}" : '' def rna_id_arg = meta.containsKey('tumor_wts_id') ? "-rna_sample_id ${meta.tumor_wts_id}" : '' - def isofox_summary_csv_arg = isofox_dir ? "-isofox_summary_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.summary.csv" : '' - def isofox_gene_csv_arg = isofox_dir ? "-isofox_gene_data_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.gene_data.csv" : '' - def isofox_fusion_csv_arg = isofox_dir ? "-isofox_fusion_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.fusions.csv" : '' - def isofox_alt_sj_csv_arg = isofox_dir ? "-isofox_alt_splice_junction_csv ${isofox_dir}/${meta.tumor_wts_id}.isf.alt_splice_junc.csv" : '' + def isofox_dir_arg = isofox_dir ? '-isofox_dir isofox_dir__prepared/' : '' - def isofox_gene_distribution_arg = isofox_gene_distribution ? "-isofox_gene_distribution_csv ${isofox_gene_distribution}" : '' - def isofox_alt_sj_arg = isofox_alt_sj ? "-isofox_alt_sj_cohort_csv ${isofox_alt_sj}" : '' + def isofox_gene_distribution_arg = isofox_gene_distribution ? "-isofox_gene_distribution ${isofox_gene_distribution}" : '' + def isofox_alt_sj_arg = isofox_alt_sj ? "-isofox_alt_sj_cohort ${isofox_alt_sj}" : '' """ echo "${pipeline_version_str}" > pipeline_version.txt @@ -57,13 +52,21 @@ process ORANGE { # When WTS data is present, ORANGE expects the somatic SAGE VCF to have appended WTS data; CS indicates this should # occur after PURPLE. Since ORANGE only collects the somatic SAGE VCF from the PURPLE output directory, we must # prepare accordingly + # Isofox inputs are also expected to have the tumor sample ID in the filename purple_dir_local=${purple_dir} if [[ -n "${rna_id_arg}" ]]; then + purple_dir_local=purple__prepared; mkdir -p \${purple_dir_local}/; find -L ${purple_dir} -maxdepth 1 -exec ln -fs ../{} \${purple_dir_local}/ \\; ln -sf ../${smlv_somatic_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.somatic.vcf.gz; ln -sf ../${smlv_germline_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.germline.vcf.gz; + + mkdir -p isofox_dir__prepared/; + for fp in ${isofox_dir}/*; do + ln -s ../\${fp} isofox_dir__prepared/\$(sed 's/${meta.tumor_wts_id}/${meta.tumor_id}/' <<< \${fp##*/}); + done; + fi # NOTE(SW): '--add-opens java.base/java.time=ALL-UNNAMED' resolves issue writing JSON, see: @@ -71,54 +74,51 @@ process ORANGE { # NOTE(SW): DOID label: 162 [cancer]; Hartwig cohort group: unknown + mkdir -p output/ + java \\ --add-opens java.base/java.time=ALL-UNNAMED \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ \\ -experiment_date \$(date +%y%m%d) \\ + -add_disclaimer \\ -pipeline_version_file pipeline_version.txt \\ \\ -tumor_sample_id ${meta.tumor_id} \\ -primary_tumor_doids 162 \\ -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ -tumor_sample_flagstat_file ${flagstat_somatic} \\ - -sage_somatic_tumor_sample_bqr_plot ${sage_somatic_bqr} \\ - -purple_data_directory \${purple_dir_local} \\ - -purple_plot_directory \${purple_dir_local}/plot/ \\ - -linx_somatic_data_directory ${linx_somatic_anno_dir} \\ - -linx_plot_directory ${linx_somatic_plot_dir} \\ - -lilac_result_csv ${lilac_dir}/${meta.tumor_id}.lilac.csv \\ - -lilac_qc_csv ${lilac_dir}/${meta.tumor_id}.lilac.qc.csv \\ - ${virusinterpreter_arg} \\ - ${chord_arg} \\ - ${sigs_arg} \\ - ${cuppa_csv_arg} \\ - ${cuppa_summary_arg} \\ + -sage_dir ${sage_dir} \\ + -purple_dir \${purple_dir_local} \\ + -purple_plot_dir \${purple_dir_local}/plot/ \\ + -linx_dir ${linx_somatic_anno_dir} \\ + -linx_plot_dir ${linx_somatic_plot_dir} \\ + -lilac_dir ${lilac_dir} \\ + ${virus_dir_arg} \\ + ${chord_dir_arg} \\ + ${sigs_dir_arg} \\ + ${cuppa_dir_arg} \\ \\ ${normal_id_arg} \\ ${normal_metrics_arg} \\ ${normal_flagstat_arg} \\ - ${normal_sage_somatic_bqr_arg} \\ - ${normal_sage_coverage_arg} \\ + ${normal_sage_dir} \\ ${normal_linx_arg} \\ \\ ${rna_id_arg} \\ - ${isofox_summary_csv_arg} \\ - ${isofox_gene_csv_arg} \\ - ${isofox_fusion_csv_arg} \\ - ${isofox_alt_sj_csv_arg} \\ + ${isofox_dir_arg} \\ \\ -ref_genome_version ${genome_ver} \\ -doid_json ${disease_ontology} \\ -cohort_mapping_tsv ${cohort_mapping} \\ -cohort_percentiles_tsv ${cohort_percentiles} \\ -known_fusion_file ${known_fusion_data} \\ - -driver_gene_panel_tsv ${driver_gene_panel} \\ - -ensembl_data_directory ${ensembl_data_resources} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ ${isofox_gene_distribution_arg} \\ ${isofox_alt_sj_arg} \\ - -output_dir ./output/ + -output_dir output/ cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/pave/Dockerfile b/modules/local/pave/Dockerfile index 297aba7b..3e20e721 100644 --- a/modules/local/pave/Dockerfile +++ b/modules/local/pave/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/pave/ && \ - wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.4.3/pave_v1.4.3.jar' + wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.5/pave_v1.5.jar' USER mambauser diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index a2417d60..89a568cd 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -6,7 +6,7 @@ process PAVE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.4.3--0' + container 'docker.io/scwatts/pave:1.5--0' input: tuple val(meta), path(sage_vcf) @@ -19,6 +19,7 @@ process PAVE_GERMLINE { path segment_mappability path driver_gene_panel path ensembl_data_resources + path gnomad_resource output: tuple val(meta), path("*.vcf.gz") , emit: vcf @@ -30,6 +31,15 @@ process PAVE_GERMLINE { script: def args = task.ext.args ?: '' + def gnomad_args + if (genome_ver == '37') { + gnomad_args = "-gnomad_freq_file ${gnomad_resource}" + } else if (genome_ver == '38') { + gnomad_args = "-gnomad_freq_dir ${gnomad_resource} -gnomad_load_chr_on_demand" + } else { + log.error "got bad genome version: ${genome_ver}" + System.exit(1) + } """ java \\ @@ -46,12 +56,15 @@ process PAVE_GERMLINE { -ensembl_data_dir ${ensembl_data_resources} \\ -blacklist_bed ${sage_blocklist_regions} \\ -blacklist_vcf ${sage_blocklist_sites} \\ + -gnomad_pon_filter -1 \\ + ${gnomad_args} \\ -read_pass_only \\ -output_dir ./ + # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: \$(java -jar ${task.ext.jarPath} 2>&1 | sed -n 's/^.*version: //p') + pave: 1.5 END_VERSIONS """ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index b0f1f2f4..0ddeb2d0 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -2,7 +2,7 @@ process PAVE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.4.3--0' + container 'docker.io/scwatts/pave:1.5--0' input: tuple val(meta), path(sage_vcf) @@ -60,9 +60,10 @@ process PAVE_SOMATIC { -read_pass_only \\ -output_dir ./ + # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: \$(java -jar ${task.ext.jarPath} 2>&1 | sed -n 's/^.*version: //p') + pave: 1.5 END_VERSIONS """ diff --git a/modules/local/purple/Dockerfile b/modules/local/purple/Dockerfile index 1253714e..b91ba054 100644 --- a/modules/local/purple/Dockerfile +++ b/modules/local/purple/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/purple/ && \ - wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.8.2/purple_v3.8.2.jar' + wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.9/purple_v3.9.jar' USER mambauser diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 28bf42fa..5c00c0ff 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -2,7 +2,7 @@ process PURPLE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/purple:3.8.2--0' + container 'docker.io/scwatts/purple:3.9--0' input: tuple val(meta), path(amber), path(cobalt), path(sv_tumor_vcf), path(sv_tumor_tbi), path(sv_tumor_unfiltered_vcf), path(sv_tumor_unfiltered_tbi), path(sv_normal_vcf), path(sv_normal_tbi), path(smlv_tumor_vcf), path(smlv_normal_vcf) @@ -91,9 +91,10 @@ process PURPLE { -threads ${task.cpus} \\ -output_dir purple/ + # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - purple: \$(java -jar ${task.ext.jarPath} -version | sed 's/.*Purple version: //') + purple: 3.9 END_VERSIONS """ diff --git a/modules/local/sage/Dockerfile b/modules/local/sage/Dockerfile index a18f34d7..217d7573 100644 --- a/modules/local/sage/Dockerfile +++ b/modules/local/sage/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/sage/ && \ - wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.2.5/sage_v3.2.5.jar' + wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.3/sage_v3.3.jar' USER mambauser diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index 0c4c5134..c7f65dd2 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -2,11 +2,12 @@ process SAGE_APPEND { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.2.5--0' + container 'docker.io/scwatts/sage:3.3--0' input: tuple val(meta), path(vcf), path(bam), path(bai) path genome_fasta + val genome_ver path genome_fai path genome_dict @@ -29,12 +30,14 @@ process SAGE_APPEND { -reference ${meta.tumor_wts_id} \\ -reference_bam ${bam} \\ -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ -threads ${task.cpus} \\ - -out ./${meta.wgs_id}.sage.append.vcf.gz + -out ${meta.wgs_id}.sage.append.vcf.gz + # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*Sage version: //') + sage: 3.3 END_VERSIONS """ diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index e96524ee..313c77eb 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -10,7 +10,7 @@ process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.2.5--0' + container 'docker.io/scwatts/sage:3.3--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -25,13 +25,10 @@ process SAGE_GERMLINE { path ensembl_data_resources output: - tuple val(meta), path('*.sage.germline.vcf.gz'), path('*.sage.germline.vcf.gz.tbi') , emit: vcf - tuple val(meta), path('*.sage.germline.filtered.vcf.gz'), path('*.sage.germline.filtered.vcf.gz.tbi'), emit: vcf_filtered - tuple val(meta), path("${meta.tumor_id}.sage.bqr.png") , emit: tumor_bqr_png, optional: true - tuple val(meta), path("${meta.normal_id}.sage.bqr.png") , emit: normal_bqr_png, optional: true - tuple val(meta), path('*gene.coverage.tsv') , emit: gene_coverage, optional: true - path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true - path 'versions.yml' , emit: versions + tuple val(meta), path('sage_germline/*.sage.germline.vcf.gz'), path('sage_germline/*.sage.germline.vcf.gz.tbi') , emit: vcf + tuple val(meta), path('sage_germline/*.sage.germline.filtered.vcf.gz'), path('sage_germline/*.sage.germline.filtered.vcf.gz.tbi'), emit: vcf_filtered + tuple val(meta), path('sage_germline/') , emit: sage_dir + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -40,6 +37,8 @@ process SAGE_GERMLINE { def args = task.ext.args ?: '' """ + mkdir sage_germline/ + java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ @@ -66,28 +65,34 @@ process SAGE_GERMLINE { -write_bqr_data \\ -write_bqr_plot \\ -threads ${task.cpus} \\ - -out ./${meta.tumor_id}.sage.germline.vcf.gz + -out sage_germline/${meta.tumor_id}.sage.germline.vcf.gz + + bcftools view \\ + -f 'PASS' \\ + -o sage_germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz \\ + sage_germline/${meta.tumor_id}.sage.germline.vcf.gz - bcftools view -f 'PASS' -o ${meta.tumor_id}.sage.germline.filtered.vcf.gz ${meta.tumor_id}.sage.germline.vcf.gz - bcftools index -t ${meta.tumor_id}.sage.germline.filtered.vcf.gz + bcftools index -t sage_germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz + # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*Sage version: //') + sage: 3.3 END_VERSIONS """ stub: """ - touch "${meta.tumor_id}.sage.germline.vcf.gz" - touch "${meta.tumor_id}.sage.germline.vcf.gz.tbi" - touch "${meta.tumor_id}.sage.germline.filtered.vcf.gz" - touch "${meta.tumor_id}.sage.germline.filtered.vcf.gz.tbi" - touch "${meta.tumor_id}.sage.bqr.png" - touch "${meta.tumor_id}.sage.bqr.tsv" - touch "${meta.normal_id}.sage.bqr.png" - touch "${meta.normal_id}.sage.bqr.tsv" - touch "${meta.normal_id}.gene.coverage.tsv" + mkdir -p sage_germline/ + touch sage_germline/${meta.tumor_id}.sage.germline.vcf.gz + touch sage_germline/${meta.tumor_id}.sage.germline.vcf.gz.tbi + touch sage_germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz + touch sage_germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz.tbi + touch sage_germline/${meta.tumor_id}.sage.bqr.png + touch sage_germline/${meta.tumor_id}.sage.bqr.tsv + touch sage_germline/${meta.normal_id}.sage.bqr.png + touch sage_germline/${meta.normal_id}.sage.bqr.tsv + touch sage_germline/${meta.normal_id}.gene.coverage.tsv echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 829ae52e..8bd61130 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -4,7 +4,7 @@ process SAGE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.2.5--0' + container 'docker.io/scwatts/sage:3.3--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -19,13 +19,10 @@ process SAGE_SOMATIC { path ensembl_data_resources output: - tuple val(meta), path('*.sage.somatic.vcf.gz'), path('*.sage.somatic.vcf.gz.tbi') , emit: vcf - tuple val(meta), path('*.sage.somatic.filtered.vcf.gz'), path('*.sage.somatic.filtered.vcf.gz.tbi'), emit: vcf_filtered - tuple val(meta), path("${meta.tumor_id}.sage.bqr.png") , emit: tumor_bqr_png, optional: true - tuple val(meta), path("${meta.normal_id}.sage.bqr.png") , emit: normal_bqr_png, optional: true - tuple val(meta), path('*gene.coverage.tsv') , emit: gene_coverage, optional: true - path '*sage.bqr.tsv' , emit: bqr_tsv, optional: true - path 'versions.yml' , emit: versions + tuple val(meta), path('sage_somatic/*.sage.somatic.vcf.gz'), path('sage_somatic/*.sage.somatic.vcf.gz.tbi') , emit: vcf + tuple val(meta), path('sage_somatic/*.sage.somatic.filtered.vcf.gz'), path('sage_somatic/*.sage.somatic.filtered.vcf.gz.tbi'), emit: vcf_filtered + tuple val(meta), path('sage_somatic/') , emit: sage_dir + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -37,6 +34,8 @@ process SAGE_SOMATIC { def reference_bam_arg = normal_bam ? "-reference_bam ${normal_bam}" : '' """ + mkdir -p sage_somatic/ + java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ @@ -55,28 +54,34 @@ process SAGE_SOMATIC { -write_bqr_data \\ -write_bqr_plot \\ -threads ${task.cpus} \\ - -out ./${meta.tumor_id}.sage.somatic.vcf.gz + -out sage_somatic/${meta.tumor_id}.sage.somatic.vcf.gz + + bcftools view \\ + -f 'PASS' \\ + -o sage_somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz \\ + sage_somatic/${meta.tumor_id}.sage.somatic.vcf.gz - bcftools view -f 'PASS' -o ${meta.tumor_id}.sage.somatic.filtered.vcf.gz ${meta.tumor_id}.sage.somatic.vcf.gz - bcftools index -t ${meta.tumor_id}.sage.somatic.filtered.vcf.gz + bcftools index -t sage_somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz + # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*Sage version: //') + sage: 3.3 END_VERSIONS """ stub: """ - touch "${meta.tumor_id}.sage.somatic.vcf.gz" - touch "${meta.tumor_id}.sage.somatic.vcf.gz.tbi" - touch "${meta.tumor_id}.sage.somatic.filtered.vcf.gz" - touch "${meta.tumor_id}.sage.somatic.filtered.vcf.gz.tbi" - touch "${meta.tumor_id}.gene.coverage.tsv" - touch "${meta.tumor_id}.sage.bqr.png" - touch "${meta.tumor_id}.sage.bqr.tsv" - touch "${meta.normal_id}.sage.bqr.png" - touch "${meta.normal_id}.sage.bqr.tsv" + mkdir -p sage_somatic/ + touch sage_somatic/${meta.tumor_id}.sage.somatic.vcf.gz + touch sage_somatic/${meta.tumor_id}.sage.somatic.vcf.gz.tbi + touch sage_somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz + touch sage_somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz.tbi + touch sage_somatic/${meta.tumor_id}.gene.coverage.tsv + touch sage_somatic/${meta.tumor_id}.sage.bqr.png + touch sage_somatic/${meta.tumor_id}.sage.bqr.tsv + touch sage_somatic/${meta.normal_id}.sage.bqr.png + touch sage_somatic/${meta.normal_id}.sage.bqr.tsv echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index ecf0bf7a..50fea8b3 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -27,7 +27,7 @@ process SIGS { -sample ${meta.tumor_id} \\ -somatic_vcf_file ${smlv_vcf} \\ -signatures_file ${signatures} \\ - -output_dir ./sigs/ + -output_dir sigs/ # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/virusinterpreter/Dockerfile b/modules/local/virusinterpreter/Dockerfile index 7a330493..9a23603d 100644 --- a/modules/local/virusinterpreter/Dockerfile +++ b/modules/local/virusinterpreter/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/virusinterpreter/ && \ - wget -O /opt/virusinterpreter/virusinterpreter.jar 'https://github.com/hartwigmedical/hmftools/releases/download/virus-interpreter-v1.2/virus-interpreter.jar' + wget -O /opt/virusinterpreter/virusinterpreter.jar 'https://github.com/hartwigmedical/hmftools/releases/download/virus-interpreter-v1.3/virus-interpreter_v1.3.jar' USER mambauser diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index d8280233..6d665895 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -2,16 +2,16 @@ process VIRUSINTERPRETER { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/virus_interpreter:1.2--0' + container 'docker.io/scwatts/virus_interpreter:1.3--0' input: - tuple val(meta), path(virus_tsv), path(purple_purity), path(purple_qc), path(wgs_metrics) + tuple val(meta), path(virus_tsv), path(purple_dir), path(wgs_metrics) path taxonomy_db path reporting_db output: - tuple val(meta), path("${meta.id}.virus.annotated.tsv"), emit: virusinterpreter - path 'versions.yml' , emit: versions + tuple val(meta), path('virusinterpreter/'), emit: virusinterpreter_dir + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -25,14 +25,13 @@ process VIRUSINTERPRETER { java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ - -sample_id ${meta.id} \\ - -purple_purity_tsv ${purple_purity} \\ - -purple_qc_file ${purple_qc} \\ + -sample ${meta.id} \\ + -purple_dir ${purple_dir} \\ -tumor_sample_wgs_metrics_file ${wgs_metrics} \\ -virus_breakend_tsv ${virus_tsv} \\ -taxonomy_db_tsv ${taxonomy_db} \\ -virus_reporting_db_tsv ${reporting_db} \\ - -output_dir ./ + -output_dir virusinterpreter/ cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/subworkflows/local/channel_inputs_purple.nf b/subworkflows/local/channel_inputs_purple.nf index 42ef14db..d6f694da 100644 --- a/subworkflows/local/channel_inputs_purple.nf +++ b/subworkflows/local/channel_inputs_purple.nf @@ -42,10 +42,12 @@ workflow CHANNEL_INPUTS_PURPLE { ch_smlv_germline_source = run_config.stages.pave ? ch_smlv_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_NORMAL, type: 'optional') // Adjust for run type and mode + // NOTE(SW): Hartwig indicated unfiltered SVs should not be used for recovery in tumor-only mode if (run_config.type == Constants.RunType.TUMOR_ONLY) { ch_sv_germline_source = ch_inputs.map { meta -> [meta, [], []] } ch_smlv_germline_source = ch_inputs.map { meta -> [meta, []] } + ch_sv_somatic_unfiltered_source = ch_inputs.map { meta -> [meta, [], []] } } diff --git a/subworkflows/local/chord_prediction.nf b/subworkflows/local/chord_prediction.nf index 429251f8..7426be7f 100644 --- a/subworkflows/local/chord_prediction.nf +++ b/subworkflows/local/chord_prediction.nf @@ -45,7 +45,7 @@ workflow CHORD_PREDICTION { return Constants.PLACEHOLDER_META } - def meta_chord = [key: meta.id, id: meta.id] + def meta_chord = [key: meta.id, id: tumor_id] return [meta_chord, smlv_vcf, sv_vcf] } .filter { it != Constants.PLACEHOLDER_META } @@ -57,12 +57,11 @@ workflow CHORD_PREDICTION { ) // Set outputs, restoring original meta - ch_outputs = WorkflowOncoanalyser.restoreMeta(CHORD.out.prediction, ch_inputs) + ch_outputs = WorkflowOncoanalyser.restoreMeta(CHORD.out.chord_dir, ch_inputs) ch_versions = ch_versions.mix(CHORD.out.versions) emit: - prediction = ch_outputs // channel: [ meta, prediction ] + chord_dir = ch_outputs // channel: [ meta, chord_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } - diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index d82a01e6..c6485a2b 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -184,7 +184,7 @@ workflow LILAC_CALLING { } - // Combine non-WTS and WTS BAMs + // Combine non-WTS and WTS BAMs, and order as required // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai ] ch_lilac_bams_combined = WorkflowOncoanalyser.groupByMeta( ch_lilac_bams_wts, @@ -197,43 +197,16 @@ workflow LILAC_CALLING { return [meta, nbam, nbai, tbam, tbai, tbam_wts, tbai_wts] } - // Get PURPLE inputs - // channel: [ meta, gene_cn ] - ch_lilac_inputs_gene_cn = ch_lilac_inputs_purple - .map { meta, purple_dir -> - - if (purple_dir == []) { - return [meta, []] - } - - def tumor_id = Utils.getTumorSampleName(meta, run_config.mode) - def gene_cn = file(purple_dir).resolve("${tumor_id}.purple.cnv.gene.tsv") - return gene_cn.exists() ? [meta, gene_cn] : [meta, []] - } - - // channel: [ meta, smlv_vcf ] - ch_lilac_inputs_smlv_vcf = ch_lilac_inputs_purple - .map { meta, purple_dir -> - if (purple_dir == []) { - return [meta, []] - } - - def tumor_id = Utils.getTumorSampleName(meta, run_config.mode) - def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - return smlv_vcf.exists() ? [meta, smlv_vcf] : [meta, []] - } - // Add PURPLE inputs - // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, gene_cn, smlv_vcf ] + // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, purple_dir ] ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( ch_lilac_bams_combined, - ch_lilac_inputs_gene_cn, - ch_lilac_inputs_smlv_vcf, + ch_purple, flatten_mode: 'nonrecursive', ) // Create final input channel for LILAC, remove samples with only WTS BAMs - // channel: [ meta_lilac, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, gene_cn, smlv_vcf ] + // channel: [ meta_lilac, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, purple_dir ] ch_lilac_inputs = ch_lilac_inputs_full .map { def meta = it[0] diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index b1f2e3f7..d6270ff9 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -15,17 +15,16 @@ workflow ORANGE_REPORTING { ch_inputs // channel: [mandatory] [ meta ] ch_bamtools_somatic // channel: [mandatory] [ meta, metrics ] ch_bamtools_germline // channel: [optional] [ meta, metrics ] - ch_sage_somatic_tumor_bqr // channel: [mandatory] [ meta, sage_bqr_plot ] - ch_sage_somatic_normal_bqr // channel: [optional] [ meta, sage_bqr_plot ] - ch_sage_germline_coverage // channel: [optional] [ meta, sage_coverage ] + ch_sage_somatic // channel: [mandatory] [ meta, sage_dir ] + ch_sage_germline // channel: [optional] [ meta, sage_dir ] ch_sage_somatic_append // channel: [optional] [ meta, sage_append_vcf ] ch_sage_germline_append // channel: [optional] [ meta, sage_append_vcf ] ch_purple // channel: [mandatory] [ meta, purple_dir ] ch_linx_somatic_annotation // channel: [mandatory] [ meta, linx_annotation_dir ] ch_linx_somatic_plot // channel: [mandatory] [ meta, linx_visualiser_dir ] ch_linx_germline_annotation // channel: [optional] [ meta, linx_annotation_dir ] - ch_virusinterpreter // channel: [optional] [ meta, virusinterpreter ] - ch_chord // channel: [optional] [ meta, chord_prediction ] + ch_virusinterpreter // channel: [optional] [ meta, virusinterpreter_dir ] + ch_chord // channel: [optional] [ meta, chord_dir ] ch_sigs // channel: [optional] [ meta, sigs_dir ] ch_lilac // channel: [mandatory] [ meta, lilac_dir ] ch_cuppa // channel: [optional] [ meta, cuppa_dir ] @@ -39,8 +38,8 @@ workflow ORANGE_REPORTING { known_fusion_data // channel: [mandatory] /path/to/known_fusion_data driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ - isofox_alt_sj // channel: [mandatory] /path/to/isofox_alt_sj - isofox_gene_distribution // channel: [mandatory] /path/to/isofox_gene_distribution + isofox_alt_sj // channel: [optional] /path/to/isofox_alt_sj + isofox_gene_distribution // channel: [optional] /path/to/isofox_gene_distribution // Params run_config // channel: [mandatory] run configuration @@ -73,12 +72,11 @@ workflow ORANGE_REPORTING { // // Create placeholders for tumor-only if (run_config.type == Constants.RunType.TUMOR_ONLY) { + ch_flagstat_germline_out = ch_inputs.map { meta -> [meta, []] } ch_bamtools_germline = ch_inputs.map { meta -> [meta, []] } + ch_sage_germline = ch_inputs.map { meta -> [meta, []] } ch_sage_germline_append = ch_inputs.map { meta -> [meta, []] } - ch_flagstat_germline_out = ch_inputs.map { meta -> [meta, []] } - ch_sage_germline_coverage = ch_inputs.map { meta -> [meta, []] } ch_linx_germline_annotation = ch_inputs.map { meta -> [meta, []] } - ch_sage_somatic_normal_bqr = ch_inputs.map { meta -> [meta, []] } } // Get PURPLE input source for processing @@ -127,16 +125,15 @@ workflow ORANGE_REPORTING { run_config.stages.bamtools ? ch_bamtools_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_NORMAL, type: 'optional'), run_config.stages.flagstat ? ch_flagstat_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_TUMOR), run_config.stages.flagstat ? ch_flagstat_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_NORMAL, type: 'optional'), - run_config.stages.sage ? ch_sage_somatic_tumor_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_TUMOR), - run_config.stages.sage ? ch_sage_somatic_normal_bqr : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_BQR_NORMAL, type: 'optional'), - run_config.stages.sage ? ch_sage_germline_coverage : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_COVERAGE, type: 'optional'), + run_config.stages.sage ? ch_sage_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_DIR_TUMOR), + run_config.stages.sage ? ch_sage_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_DIR_NORMAL, type: 'optional'), ch_orange_inputs_purple_dir, ch_orange_inputs_smlv_vcfs, run_config.stages.linx ? ch_linx_somatic_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), run_config.stages.linx ? ch_linx_somatic_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_TUMOR), run_config.stages.linx ? ch_linx_germline_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_NORMAL, type: 'optional'), run_config.stages.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), - run_config.stages.chord ? ch_chord : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_PREDICTION, type: 'optional'), + run_config.stages.chord ? ch_chord : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_DIR, type: 'optional'), run_config.stages.sigs ? ch_sigs : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SIGS_DIR, type: 'optional'), run_config.stages.lilac ? ch_lilac : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), run_config.stages.cuppa ? ch_cuppa : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_DIR, type: 'optional'), diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf index 9638606e..959180aa 100644 --- a/subworkflows/local/pave_annotation.nf +++ b/subworkflows/local/pave_annotation.nf @@ -17,7 +17,7 @@ workflow PAVE_ANNOTATION { genome_version // channel: [mandatory] genome version genome_fai // channel: [mandatory] /path/to/genome_fai sage_pon // channel: [mandatory] /path/to/sage_pon - sage_pon_artefacts // channel: [mandatory] /path/to/sage_pon_artefacts + sage_pon_artefacts // channel: [optional] /path/to/sage_pon_artefacts sage_blocklist_regions // channel: [mandatory] /path/to/sage_blocklist_regions sage_blocklist_sites // channel: [mandatory] /path/to/sage_blocklist_sites clinvar_annotations // channel: [mandatory] /path/to/clinvar_annotations @@ -76,6 +76,7 @@ workflow PAVE_ANNOTATION { segment_mappability, driver_gene_panel, ensembl_data_resources, + gnomad_resource, ) ch_versions = ch_versions.mix(GERMLINE.out.versions) diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf index 0720bcb3..4f427f56 100644 --- a/subworkflows/local/prepare_input.nf +++ b/subworkflows/local/prepare_input.nf @@ -273,7 +273,6 @@ workflow PREPARE_INPUT { data = ch_inputs } - def process_sample_name(sample_name, key_sample_name, meta) { if (meta.containsKey(key_sample_name) && meta[key_sample_name] != sample_name) { log.error "\nERROR: got unexpected sample name for ${key}/${meta[key_sample_name]}: ${sample_name}" diff --git a/subworkflows/local/purple_calling.nf b/subworkflows/local/purple_calling.nf index 41070ea3..06f1110d 100644 --- a/subworkflows/local/purple_calling.nf +++ b/subworkflows/local/purple_calling.nf @@ -27,13 +27,13 @@ workflow PURPLE_CALLING { genome_dict // channel: [mandatory] /path/to/genome_dict gc_profile // channel: [mandatory] /path/to/gc_profile sage_known_hotspots_somatic // channel: [mandatory] /path/to/sage_known_hotspots_somatic - sage_known_hotspots_germline // channel: [mandatory] /path/to/sage_known_hotspots_germline + sage_known_hotspots_germline // channel: [optional] /path/to/sage_known_hotspots_germline driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ - purple_germline_del // channel: [mandatory] /path/to/purple_germline_del - target_region_bed // channel: [mandatory] /path/to/target_region_bed - target_region_ratios // channel: [mandatory] /path/to/target_region_ratios - target_region_msi_indels // channel: [mandatory] /path/to/target_region_msi_indels + purple_germline_del // channel: [optional] /path/to/purple_germline_del + target_region_bed // channel: [optional] /path/to/target_region_bed + target_region_ratios // channel: [optional] /path/to/target_region_ratios + target_region_msi_indels // channel: [optional] /path/to/target_region_msi_indels // Params run_config // channel: [mandatory] run configuration diff --git a/subworkflows/local/sage_append.nf b/subworkflows/local/sage_append.nf index 8060e898..1858ae2d 100644 --- a/subworkflows/local/sage_append.nf +++ b/subworkflows/local/sage_append.nf @@ -10,16 +10,17 @@ include { SAGE_APPEND as GERMLINE } from '../../modules/local/sage/append/main' workflow SAGE_APPEND { take: // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_purple_dir // channel: [mandatory] [ meta, purple_dir ] + ch_inputs // channel: [mandatory] [ meta ] + ch_purple_dir // channel: [mandatory] [ meta, purple_dir ] // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_fai // channel: [mandatory] /path/to/genome_fai - genome_dict // channel: [mandatory] /path/to/genome_dict + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict // Params - run_config // channel: [mandatory] run configuration + run_config // channel: [mandatory] run configuration main: // Channel for version.yml files @@ -70,6 +71,7 @@ workflow SAGE_APPEND { GERMLINE( ch_sage_germline_append_inputs, genome_fasta, + genome_version, genome_fai, genome_dict, ) @@ -108,6 +110,7 @@ workflow SAGE_APPEND { SOMATIC( ch_sage_somatic_append_inputs, genome_fasta, + genome_version, genome_fai, genome_dict, ) diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index 7831c473..0996fe9c 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -66,8 +66,8 @@ workflow SAGE_CALLING { // // channel: [ meta, sage_vcf, sage_tbi ] ch_germline_vcf_out = Channel.empty() - // channel: [ meta, sage_coverage ] - ch_germline_coverage_out = Channel.empty() + // channel: [ meta, sage_dir ] + ch_germline_dir = Channel.empty() if (run_config.type == Constants.RunType.TUMOR_NORMAL) { GERMLINE( @@ -85,7 +85,7 @@ workflow SAGE_CALLING { ch_versions = ch_versions.mix(GERMLINE.out.versions) ch_germline_vcf_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_filtered, ch_inputs) - ch_germline_coverage_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.gene_coverage, ch_inputs) + ch_germline_dir = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.sage_dir, ch_inputs) } // @@ -106,15 +106,13 @@ workflow SAGE_CALLING { ch_versions = ch_versions.mix(SOMATIC.out.versions) ch_somatic_vcf_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_filtered, ch_inputs) - ch_somatic_tumor_bqr_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.tumor_bqr_png, ch_inputs) - ch_somatic_normal_bqr_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.normal_bqr_png, ch_inputs) + ch_somatic_dir = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.sage_dir, ch_inputs) emit: - germline_vcf = ch_germline_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] - germline_coverage = ch_germline_coverage_out // channel: [ meta, sage_coverage ] - somatic_vcf = ch_somatic_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] - somatic_tumor_bqr = ch_somatic_tumor_bqr_out // channel: [ meta, sage_bqr_plot ] - somatic_normal_bqr = ch_somatic_normal_bqr_out // channel: [ meta, sage_brq_plot ] + germline_vcf = ch_germline_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] + somatic_vcf = ch_somatic_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] + germline_dir = ch_germline_dir // channel: [ meta, sage_dir ] + somatic_dir = ch_somatic_dir // channel: [ meta, sage_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index 3cf7774b..9b8045f8 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -67,32 +67,16 @@ workflow VIRUSBREAKEND_CALLING { ch_virusinterpreter_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) } - // channel: [ meta, purple_qc, wgs_metrics ] - ch_virusinterpreter_inputs_purple_files = ch_virusinterpreter_inputs_purple - .filter { it[0] != Constants.PLACEHOLDER_META } - .map { meta, purple_dir -> - def tumor_id = Utils.getTumorSampleName(meta, run_config.mode) - def purple_purity = file(purple_dir).resolve("${tumor_id}.purple.purity.tsv") - def purple_qc = file(purple_dir).resolve("${tumor_id}.purple.qc") - - // Require both purity and QC files from the PURPLE directory - if (!purple_purity.exists() || !purple_qc.exists()) { - return Constants.PLACEHOLDER_META - } - return [meta, purple_purity, purple_qc] - } - .filter { it != Constants.PLACEHOLDER_META } - - // channel: [ meta, virus_tsv, purple_purity, purple_qc, wgs_metrics ] + // channel: [ meta, virus_tsv, purple_dir, wgs_metrics ] ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), - ch_virusinterpreter_inputs_purple_files, + ch_virusinterpreter_inputs_purple, run_config.stages.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TUMOR), ) // Virus Interpreter // Create inputs and create process-specific meta - // channel: [ meta_virus, virus_tsv, purple_purity, purple_qc, wgs_metrics ] + // channel: [ meta_virus, virus_tsv, purple_dir, wgs_metrics ] ch_virusinterpreter_inputs = ch_virusinterpreter_inputs_full .map { def meta = it[0] @@ -111,14 +95,14 @@ workflow VIRUSBREAKEND_CALLING { ) // Set outputs, restoring original meta - ch_outputs = WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter, ch_inputs) + ch_outputs = WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter_dir, ch_inputs) ch_versions = ch_versions.mix( VIRUSINTERPRETER.out.versions, VIRUSBREAKEND.out.versions, ) emit: - virusinterpreter = ch_outputs // channel: [ meta, virusinterpreter ] + virusinterpreter = ch_outputs // channel: [ meta, virusinterpreter_dir ] versions = ch_versions // channel: [ versions.yml ] } diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 6ee43317..58bcef3b 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -251,7 +251,7 @@ workflow WGTS { hmf_data.gridss_pon_breakpoints, hmf_data.known_fusions, hmf_data.repeatmasker_annotations, - [], + [], // target_region_bed run_config, ) @@ -267,11 +267,9 @@ workflow WGTS { // channel: [ meta, sage_vcf, sage_tbi ] ch_sage_germline_vcf_out = Channel.empty() ch_sage_somatic_vcf_out = Channel.empty() - // channel: [ meta, sage_coverage ] - ch_sage_germline_coverage_out = Channel.empty() - // channel: [ meta, sage_bqr_plot ] - ch_sage_somatic_tumor_bqr_out = Channel.empty() - ch_sage_somatic_normal_bqr_out = Channel.empty() + // channel: [ meta, sage_dir ] + ch_sage_germline_dir_out = Channel.empty() + ch_sage_somatic_dir_out = Channel.empty() if (run_config.stages.sage) { SAGE_CALLING( @@ -293,10 +291,9 @@ workflow WGTS { ch_versions = ch_versions.mix(SAGE_CALLING.out.versions) ch_sage_germline_vcf_out = ch_sage_germline_vcf_out.mix(SAGE_CALLING.out.germline_vcf) - ch_sage_germline_coverage_out = ch_sage_germline_coverage_out.mix(SAGE_CALLING.out.germline_coverage) ch_sage_somatic_vcf_out = ch_sage_somatic_vcf_out.mix(SAGE_CALLING.out.somatic_vcf) - ch_sage_somatic_tumor_bqr_out = ch_sage_somatic_tumor_bqr_out.mix(SAGE_CALLING.out.somatic_tumor_bqr) - ch_sage_somatic_normal_bqr_out = ch_sage_somatic_normal_bqr_out.mix(SAGE_CALLING.out.somatic_normal_bqr) + ch_sage_germline_dir_out = ch_sage_germline_dir_out.mix(SAGE_CALLING.out.germline_dir) + ch_sage_somatic_dir_out = ch_sage_somatic_dir_out.mix(SAGE_CALLING.out.somatic_dir) } // @@ -357,9 +354,9 @@ workflow WGTS { hmf_data.driver_gene_panel, hmf_data.ensembl_data_resources, hmf_data.purple_germline_del, - [], - [], - [], + [], // target_region_bed + [], // target_region_ratios + [], // target_region_msi_indels run_config, ) @@ -381,6 +378,7 @@ workflow WGTS { ch_inputs, ch_purple_out, ref_data.genome_fasta, + ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, run_config, @@ -449,7 +447,7 @@ workflow WGTS { // // SUBWORKFLOW: Run CHORD to predict HR deficiency status // - // channel: [ meta, chord_prediction ] + // channel: [ meta, chord_dir ] ch_chord_out = Channel.empty() if (run_config.stages.chord) { @@ -461,7 +459,7 @@ workflow WGTS { ) ch_versions = ch_versions.mix(CHORD_PREDICTION.out.versions) - ch_chord_out = ch_chord_out.mix(CHORD_PREDICTION.out.prediction) + ch_chord_out = ch_chord_out.mix(CHORD_PREDICTION.out.chord_dir) } // @@ -492,7 +490,7 @@ workflow WGTS { // // SUBWORKFLOW: Run VIRUSBreakend and Virus Interpreter to quantify viral content // - // channel: [ meta, virusinterpreter ] + // channel: [ meta, virusinterpreter_dir ] ch_virusinterpreter_out = Channel.empty() if (run_config.stages.virusinterpreter) { @@ -548,9 +546,8 @@ workflow WGTS { ch_inputs, ch_bamtools_somatic_out, ch_bamtools_germline_out, - ch_sage_somatic_tumor_bqr_out, - ch_sage_somatic_normal_bqr_out, - ch_sage_germline_coverage_out, + ch_sage_somatic_dir_out, + ch_sage_germline_dir_out, ch_sage_somatic_append_vcf, ch_sage_germline_append_vcf, ch_purple_out, From cf34beef24cadebcae6ad3d5f1c054ede3b0f392 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 3 Aug 2023 13:43:36 +1000 Subject: [PATCH 198/562] Update module meta.yml files --- modules/local/amber/meta.yml | 4 +- modules/local/bamtools/meta.yml | 2 +- modules/local/chord/meta.yml | 2 +- modules/local/cobalt/meta.yml | 12 +- modules/local/cuppa/main.nf | 4 +- modules/local/cuppa/meta.yml | 34 +----- modules/local/gpgr/linx/main.nf | 6 +- modules/local/gpgr/linx/meta.yml | 4 +- modules/local/gridss/index/meta.yml | 2 +- modules/local/gripss/germline/main.nf | 4 +- modules/local/gripss/germline/meta.yml | 8 +- modules/local/gripss/somatic/main.nf | 4 +- modules/local/gripss/somatic/meta.yml | 11 +- modules/local/isofox/meta.yml | 8 +- modules/local/lilac/meta.yml | 17 +-- modules/local/linx/germline/meta.yml | 9 +- modules/local/linx/somatic/meta.yml | 12 +- modules/local/linx/visualiser/main.nf | 4 +- modules/local/linx/visualiser/meta.yml | 6 +- modules/local/orange/meta.yml | 106 +++++++++--------- modules/local/pave/germline/meta.yml | 10 +- modules/local/pave/somatic/meta.yml | 11 +- modules/local/purple/meta.yml | 47 +++++--- modules/local/sage/germline/meta.yml | 17 +-- modules/local/sage/somatic/meta.yml | 33 +++--- modules/local/sigs/meta.yml | 2 +- modules/local/svprep/assemble/meta.yml | 4 +- modules/local/svprep/call/meta.yml | 4 +- modules/local/svprep/depth_annotator/meta.yml | 8 +- modules/local/svprep/preprocess/meta.yml | 2 +- modules/local/svprep/svprep/meta.yml | 2 +- modules/local/virusbreakend/meta.yml | 2 +- modules/local/virusinterpreter/main.nf | 3 +- modules/local/virusinterpreter/meta.yml | 18 +-- subworkflows/local/cuppa_prediction.nf | 6 +- subworkflows/local/virusbreakend_calling.nf | 4 +- workflows/wgts.nf | 2 +- 37 files changed, 210 insertions(+), 224 deletions(-) diff --git a/modules/local/amber/meta.yml b/modules/local/amber/meta.yml index dfa92a3e..824f7a4b 100644 --- a/modules/local/amber/meta.yml +++ b/modules/local/amber/meta.yml @@ -34,9 +34,9 @@ input: - genome_ver: type: string description: Reference genome version - - loci: + - heterozygous_sites: type: file - description: AMBER loci file + description: AMBER heterozygous sites file pattern: "*.{vcf.gz}" output: - meta: diff --git a/modules/local/bamtools/meta.yml b/modules/local/bamtools/meta.yml index 1a257f7c..ac8cee66 100644 --- a/modules/local/bamtools/meta.yml +++ b/modules/local/bamtools/meta.yml @@ -24,7 +24,7 @@ input: pattern: "*.{bai}" - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" - genome_ver: type: string diff --git a/modules/local/chord/meta.yml b/modules/local/chord/meta.yml index 56510f3d..fd53d09f 100644 --- a/modules/local/chord/meta.yml +++ b/modules/local/chord/meta.yml @@ -21,7 +21,7 @@ input: pattern: "*.{vcf.gz}" - sv_vcf: type: file - description: GRIPSS structural variant VCF file with PURPLE annotations + description: PURPLE SV VCF file pattern: "*.{vcf.gz}" - genome_ver: type: string diff --git a/modules/local/cobalt/meta.yml b/modules/local/cobalt/meta.yml index cedfc27d..27adc051 100644 --- a/modules/local/cobalt/meta.yml +++ b/modules/local/cobalt/meta.yml @@ -34,15 +34,23 @@ input: pattern: "*.{bai}" - gc_profile: type: file - description: COBALT GC Profile file + description: GC profile file pattern: "*.{cnp}" + - diploid_regions: + type: file + description: Diploid regions file (optional) + pattern: "*.{bed.gz}" + - target_region_normalisation: + type: file + description: Normalisation file (optional) + pattern: "*.{bed.gz}" output: - meta: type: map description: | Groovy Map containing sample information e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - - cobalt: + - cobalt_dir: type: directory description: COBALT output directory - versions: diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index 346c8e28..098340dd 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -5,7 +5,7 @@ process CUPPA { container 'docker.io/scwatts/cuppa:1.8.1--0' input: - tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter) + tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) val ref_genome_ver path cuppa_resources, stageAs: 'cuppa_reference_data' @@ -40,7 +40,7 @@ process CUPPA { # Symlink input files into a single directory mkdir -p sample_data/ if [[ ${categories_val} == 'DNA' || ${categories_val} == 'ALL' ]]; then - find -L ${purple_dir} ${linx_dir} ${virusinterpreter} -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; + find -L ${purple_dir} ${linx_dir} ${virusinterpreter_dir} -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; fi if [[ ${categories_val} == 'RNA' ]]; then diff --git a/modules/local/cuppa/meta.yml b/modules/local/cuppa/meta.yml index 5fc0a714..e8488ce2 100644 --- a/modules/local/cuppa/meta.yml +++ b/modules/local/cuppa/meta.yml @@ -25,10 +25,9 @@ input: - linx_dir: type: directory description: LINX output directory (optional) - - virusinterpreter: - type: file - description: Virus Interpreter annotations file (optional) - pattern: "*.{tsv}" + - virusinterpreter_dir: + type: directory + description: Virus Interpreter output directory (optional) - cuppa_resources: type: directory description: CUPPA resource directory @@ -38,30 +37,9 @@ output: description: | Groovy Map containing sample information e.g. [id: 'sample_id'] - - csv: - type: file - description: Classification file - pattern: "*.{csv}" - - conclusion: - type: file - description: Conclusion file - pattern: "*.{txt}" - - report: - type: file - description: Report PDF file - pattern: "*.{pdf}" - - summary_plot: - type: file - description: Summary plot file - pattern: "*.{png}" - - feature_plot: - type: file - description: Feature plot file - pattern: "*.{png}" - - chart_plot: - type: file - description: Chart plot file - pattern: "*.{png}" + - cuppa_dir: + type: directory + description: CUPPA output directory - versions: type: file description: File containing software versions diff --git a/modules/local/gpgr/linx/main.nf b/modules/local/gpgr/linx/main.nf index 55de7fde..decb0b34 100644 --- a/modules/local/gpgr/linx/main.nf +++ b/modules/local/gpgr/linx/main.nf @@ -5,7 +5,7 @@ process GPGR_LINX { container 'docker.io/scwatts/gpgr:1.4.5' input: - tuple val(meta), path(linx_annotation), path(linx_visualiser) + tuple val(meta), path(linx_annotation_dir), path(linx_visualiser_dir) output: tuple val(meta), path('*_linx.html'), emit: html @@ -21,8 +21,8 @@ process GPGR_LINX { gpgr.R linx \\ ${args} \\ --sample ${meta.id} \\ - --plot ${linx_visualiser}/ \\ - --table ${linx_annotation}/ \\ + --plot ${linx_visualiser_dir}/ \\ + --table ${linx_annotation_dir}/ \\ --out ${meta.id}_linx.html cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/gpgr/linx/meta.yml b/modules/local/gpgr/linx/meta.yml index dbb21a04..1d6efba9 100644 --- a/modules/local/gpgr/linx/meta.yml +++ b/modules/local/gpgr/linx/meta.yml @@ -17,10 +17,10 @@ input: description: | Groovy Map containing sample information e.g. [id: 'sample_id'] - - linx_annotation: + - linx_annotation_dir: type: directory description: Somatic LINX annotation output directory - - linx_visualiser: + - linx_visualiser_dir: type: directory description: Somatic LINX visualiser output directory output: diff --git a/modules/local/gridss/index/meta.yml b/modules/local/gridss/index/meta.yml index 6f6c51c5..9988df16 100644 --- a/modules/local/gridss/index/meta.yml +++ b/modules/local/gridss/index/meta.yml @@ -12,7 +12,7 @@ tools: input: - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" - genome_fai: type: file diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index ed923a47..540044bd 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -7,7 +7,7 @@ process GRIPSS_GERMLINE { input: tuple val(meta), path(gridss_vcf) path genome_fasta - val genome_version + val genome_ver path genome_fai path pon_breakends path pon_breakpoints @@ -35,7 +35,7 @@ process GRIPSS_GERMLINE { -vcf ${gridss_vcf} \\ -germline \\ -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_version} \\ + -ref_genome_version ${genome_ver} \\ -pon_sgl_file ${pon_breakends} \\ -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ diff --git a/modules/local/gripss/germline/meta.yml b/modules/local/gripss/germline/meta.yml index bca56b20..03ae9328 100644 --- a/modules/local/gripss/germline/meta.yml +++ b/modules/local/gripss/germline/meta.yml @@ -22,15 +22,15 @@ input: pattern: "*.{vcf.gz}" - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version - genome_fai: type: file description: Reference genome assembly fai file pattern: "*.{fai}" - - genome_ver: - type: string - description: Reference genome version - pon_breakends: type: file description: GRIDSS breakend PON file diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index ff8289ca..991ac057 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -7,7 +7,7 @@ process GRIPSS_SOMATIC { input: tuple val(meta), path(gridss_vcf) path genome_fasta - val genome_version + val genome_ver path genome_fai path pon_breakends path pon_breakpoints @@ -39,7 +39,7 @@ process GRIPSS_SOMATIC { ${reference_arg} \\ -vcf ${gridss_vcf} \\ -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_version} \\ + -ref_genome_version ${genome_ver} \\ -pon_sgl_file ${pon_breakends} \\ -pon_sv_file ${pon_breakpoints} \\ -known_hotspot_file ${known_fusions} \\ diff --git a/modules/local/gripss/somatic/meta.yml b/modules/local/gripss/somatic/meta.yml index a6ff96b7..ee959724 100644 --- a/modules/local/gripss/somatic/meta.yml +++ b/modules/local/gripss/somatic/meta.yml @@ -22,15 +22,15 @@ input: pattern: "*.{vcf.gz}" - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version - genome_fai: type: file description: Reference genome assembly fai file pattern: "*.{fai}" - - genome_ver: - type: string - description: Reference genome version - pon_breakend: type: file description: GRIDSS breakend PON file @@ -46,6 +46,9 @@ input: - repeatmasker_annotations: type: file description: RepeatMasker annotations file + - target_regions_bed: + type: file + description: Target regions BED file (optional) output: - meta: type: map diff --git a/modules/local/isofox/meta.yml b/modules/local/isofox/meta.yml index 3e9e1381..b1106588 100644 --- a/modules/local/isofox/meta.yml +++ b/modules/local/isofox/meta.yml @@ -25,15 +25,15 @@ input: pattern: "*.{bai}" - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version - genome_fai: type: file description: Reference genome assembly fai file pattern: "*.{fai}" - - genome_ver: - type: string - description: Reference genome version - ensembl_data_resources: type: directory description: HMF ensembl data resources directory diff --git a/modules/local/lilac/meta.yml b/modules/local/lilac/meta.yml index acaaaf88..29a64c1f 100644 --- a/modules/local/lilac/meta.yml +++ b/modules/local/lilac/meta.yml @@ -18,11 +18,11 @@ input: e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - normal_wgs_bam: type: file - description: Normal WGS BAM file + description: Normal WGS BAM file (optional) pattern: "*.{bam}" - normal_wgs_bai: type: file - description: Normal WGS BAI file + description: Normal WGS BAI file (optional) pattern: "*.{bai}" - tumor_wgs_bam: type: file @@ -40,17 +40,12 @@ input: type: file description: Tumor WTS BAI file (optional) pattern: "*.{bai}" - - gene_cn: - type: file - description: PURPLE somatic gene copy number file (optional) - pattern: "*.{tsv}" - - smlv_vcf: - type: file - description: PURPLE somatic small variant VCF file (optional) - pattern: "*.{vcf.gz}" + - purple_dir: + type: directory + description: PURPLE output directory (optional) - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" - genome_ver: type: string diff --git a/modules/local/linx/germline/meta.yml b/modules/local/linx/germline/meta.yml index 57c411e7..50c7b694 100644 --- a/modules/local/linx/germline/meta.yml +++ b/modules/local/linx/germline/meta.yml @@ -16,16 +16,13 @@ input: description: | Groovy Map containing sample information e.g. [id: 'sample_id'] - - purple_dir: + - sv_vcf: type: directory - description: PURPLE output directory + description: PURPLE germline SV VCF file + pattern: "*.{vcf.gz}" - genome_ver: type: string description: Reference genome version - - fragile_regions: - type: file - description: LINX fragile regions file - pattern: "*.{csv}" - ensembl_data_resources: type: directory description: HMF ensembl data resources directory diff --git a/modules/local/linx/somatic/meta.yml b/modules/local/linx/somatic/meta.yml index bc2ed58b..2a232313 100644 --- a/modules/local/linx/somatic/meta.yml +++ b/modules/local/linx/somatic/meta.yml @@ -22,20 +22,12 @@ input: - genome_ver: type: string description: Reference genome version - - fragile_regions: - type: file - description: LINX fragile regions file - pattern: "*.{csv}" - - lines: - type: file - description: LINEs file - pattern: "*.{csv}" - ensembl_data_resources: type: directory description: HMF ensembl data resources directory - known_fusion_data: type: file - description: Known susions data file + description: Known fusions data file pattern: "*.{bedpe}" - driver_gene_panel: type: file @@ -43,7 +35,7 @@ input: pattern: "*.{csv}" - gene_id_file: type: file - description: Ensembl gene ID file + description: Ensembl gene ID file (optional) pattern: "*.{csv}" output: - meta: diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 3102106a..5c2cbf07 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -5,7 +5,7 @@ process LINX_VISUALISER { container 'docker.io/scwatts/linx:1.24.1--0' input: - tuple val(meta), path(linx) + tuple val(meta), path(linx_annotation_dir) val genome_ver path ensembl_data_resources @@ -30,7 +30,7 @@ process LINX_VISUALISER { com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ ${args} \\ -sample ${meta.id} \\ - -vis_file_dir ${linx} \\ + -vis_file_dir ${linx_annotation_dir} \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -circos ${task.ext.circosPath} \\ diff --git a/modules/local/linx/visualiser/meta.yml b/modules/local/linx/visualiser/meta.yml index 43012afc..d35d9182 100644 --- a/modules/local/linx/visualiser/meta.yml +++ b/modules/local/linx/visualiser/meta.yml @@ -17,12 +17,12 @@ input: description: | Groovy Map containing sample information e.g. [id: 'sample_id'] + - linx_annotation_dir: + type: directory + description: LINX somatic annotation output directory - genome_ver: type: string description: Reference genome version - - linx: - type: directory - description: LINX somatic annotation output directory - ensembl_data_resources: type: directory description: HMF ensembl data resources directory diff --git a/modules/local/orange/meta.yml b/modules/local/orange/meta.yml index 2206ed7f..31d2a1b0 100644 --- a/modules/local/orange/meta.yml +++ b/modules/local/orange/meta.yml @@ -19,35 +19,28 @@ input: description: Somatic collectwgsmetrics file - bam_metrics_germline: type: file - description: Germline collectwgsmetrics file + description: Germline collectwgsmetrics file (optional) - flagstat_somatic: type: file description: Somatic SAMtools flagstat output file - flagstat_germline: type: file - description: Somatic SAMtools flagstat output file - - chord_prediction: - type: file - description: CHORD prediction file - pattern: "*.{txt}" - - lilac_dir: + description: Somatic SAMtools flagstat output file (optional) + - sage_dir: type: directory - description: LILAC output directory - - sage_somatic_bqr: - type: file - description: SAGE somatic tumor BQR plot file - pattern: "*.{png}" - - sage_germline_bqr: - type: file - description: SAGE somatic normal BQR plot file - pattern: "*.{png}" - - sage_germline_coverage: - type: file - description: SAGE germline coverage file - pattern: "*.{tsv}" + description: SAGE somatic output directory + - sage_germline_dir: + type: directory + description: SAGE germline output directory (optional) - purple_dir: type: directory description: PURPLE output directory + - smlv_somatic_vcf: + type: file + description: Small somatic variant VCF file (annotated with RNA data) (optional) + - smlv_germline_vcf: + type: file + description: Small germline variant VCF file (annotated with RNA data) (optional) - linx_somatic_anno_dir: type: directory description: LINX somatic annotation output directory @@ -56,54 +49,59 @@ input: description: LINX somatic plot output directory - linx_germline_anno_dir: type: directory - description: LINX germline annotation output directory - - protect: - type: file - description: PROTECT output file - pattern: "*.{tsv}" - - peach_genotype: - type: file - description: PEACH genotype file - pattern: "*.{tsv}" - - cuppa: - type: file - description: CUPPA classification file - pattern: "*.{csv}" - - cuppa_summary_plot: - type: file - description: CUPPA summary plot file - pattern: "*.{png}" - - cuppa_feature_plot: - type: file - description: CUPPA feature plot file - pattern: "*.{png}" - - virusinterpreter: - type: file - description: Virus Interpreter annotations file - pattern: "*.{tsv}" + description: LINX germline annotation output directory (optional) + - virusinterpreter_dir: + type: directory + description: Virus Interpreter output directory (optional) + - chord_dir: + type: directory + description: CHORD output directory (optional) + - sigs_dir: + type: directory + description: Sigs output directory (optional) + - lilac_dir: + type: directory + description: LILAC output directory + - cuppa_dir: + type: directory + description: CUPPA output directory (optional) + - isofox_dir: + type: directory + description: Isofox output directory (optional) - genome_ver: type: string description: Reference genome version - disease_ontology: - type: string + type: file description: Disease ontology file pattern: "*.{json}" + - cohort_mapping: + type: file + description: HMF cohort mapping file + pattern: "*.{tsv}" + - cohort_percentiles: + type: file + description: HMF cohort percentiles file + pattern: "*.{tsv}" - known_fusion_data: type: file - description: Known susions data file + description: Known fusions data file pattern: "*.{bedpe}" - driver_gene_panel: type: file description: Driver gene panel file pattern: "*.{csv}" - - cohort_mapping: + - ensembl_data_resources: + type: directory + description: HMF ensembl data resources directory + - isofox_alt_sj: type: file - description: HMF cohort mapping file - pattern: "*.{tsv}" - - cohort_percentiles: + description: Isofox cohort alternate slice junction file + pattern: "*.{csv}" + - isofox_gene_distribution: type: file - description: HMF cohort percentiles file - pattern: "*.{tsv}" + description: Isofox cohort gene expression file + pattern: "*.{csv}" - pipeline_version: type: string description: Pipeline version to display in report @@ -118,7 +116,7 @@ output: description: Report file pattern: "*.{pdf}" - json: - type: directory + type: file description: Compiled JSON output file pattern: "*.{json}" - versions: diff --git a/modules/local/pave/germline/meta.yml b/modules/local/pave/germline/meta.yml index 8b68e820..45875836 100644 --- a/modules/local/pave/germline/meta.yml +++ b/modules/local/pave/germline/meta.yml @@ -24,15 +24,15 @@ input: pattern: "*.{vcf.gz}" - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version - genome_fai: type: file description: Reference genome assembly fai file pattern: "*.{fai}" - - genome_ver: - type: string - description: Reference genome version - sage_blocklist_regions: type: file description: SAGE regions blocklist file @@ -56,6 +56,8 @@ input: - ensembl_data_resources: type: directory description: HMF ensembl data resources directory + - gnomad_resource: + description: gnomAD resource output: - meta: type: map diff --git a/modules/local/pave/somatic/meta.yml b/modules/local/pave/somatic/meta.yml index 5e88a0ab..2d695c08 100644 --- a/modules/local/pave/somatic/meta.yml +++ b/modules/local/pave/somatic/meta.yml @@ -25,19 +25,22 @@ input: pattern: "*.{vcf.gz}" - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version - genome_fai: type: file description: Reference genome assembly fai file pattern: "*.{fai}" - - genome_ver: - type: string - description: Reference genome version - sage_pon: type: file description: SAGE PON file pattern: "*.{tsv.gz}" + - pon_artefacts: + type: file + description: Taregeted sequencing PON artefacts file (optional) - segment_mappability: type: file description: Segment mappability file diff --git a/modules/local/purple/meta.yml b/modules/local/purple/meta.yml index e88b0327..9c55dea9 100644 --- a/modules/local/purple/meta.yml +++ b/modules/local/purple/meta.yml @@ -24,21 +24,29 @@ input: - cobalt: type: directory description: COBALT output directory - - sv_vcf: + - sv_tumor_vcf: type: file - description: GRIPSS VCF file + description: GRIPSS somatic VCF file (optional) pattern: "*.{vcf.gz}" - - sv_vcf_index: + - sv_tumor_tbi: type: file - description: GRIPSS VCF index file + description: GRIPSS somatic VCF index file (optional) pattern: "*.{vcf.gz.tbi}" - - sv_unfiltered_vcf: + - sv_tumor_unfiltered_vcf: type: file - description: GRIPSS unfiltered VCF file + description: GRIPSS unfiltered somatic VCF file (optional) pattern: "*.{vcf.gz}" - - sv_unfiltered_vcf_index: + - sv_tumor_unfiltered_tbi: type: file - description: GRIPSS unfiltered VCF index file + description: GRIPSS unfiltered somatic VCF index file (optional) + pattern: "*.{vcf.gz.tbi}" + - sv_normal_vcf: + type: file + description: GRIPSS germline VCF file (optional) + pattern: "*.{vcf.gz}" + - sv_normal_tbi: + type: file + description: GRIPSS germline VCF index file (optional) pattern: "*.{vcf.gz.tbi}" - smlv_tumor_vcf: type: file @@ -50,8 +58,11 @@ input: pattern: "*.{vcf.gz}" - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version - genome_fai: type: file description: Reference genome assembly fai file @@ -60,12 +71,9 @@ input: type: file description: Reference genome assembly dict file pattern: "*.{dict}" - - genome_ver: - type: string - description: Reference genome version - gc_profile: type: file - description: COBALT GC profile file + description: GC profile file pattern: "*.{cnp}" - sage_known_hotspots_somatic: type: file @@ -84,8 +92,19 @@ input: description: HMF ensembl data resources directory - germline_del: type: file - description: Cohort frequency for germline deletions + description: Cohort frequency for germline deletions (optional) pattern: "*.{csv}" + - target_regions_bed: + type: file + description: Target regions BED file (optional) + - target_regions_ratios: + type: file + description: Target regions ratios file (optional) + pattern: "*.{tsv}" + - target_regions_msi_indels: + type: file + description: Target regions MSI/INDELS file (optional) + pattern: "*.{tsv}" output: - meta: type: map diff --git a/modules/local/sage/germline/meta.yml b/modules/local/sage/germline/meta.yml index ccc46270..12a0f1b0 100644 --- a/modules/local/sage/germline/meta.yml +++ b/modules/local/sage/germline/meta.yml @@ -35,8 +35,11 @@ input: pattern: "*.{bai}" - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version - genome_fai: type: file description: Reference genome assembly fai file @@ -45,9 +48,6 @@ input: type: file description: Reference genome assembly dict file pattern: "*.{dict}" - - genome_ver: - type: string - description: Reference genome version - sage_known_hotspots_germline: type: file description: SAGE germline known hotspots file @@ -77,10 +77,13 @@ output: type: file description: VCF file pattern: "*.{vcf.gz}" - - gene_coverage: + - vcf_filtered: type: file - description: Gene coverage file - pattern: "*.{tsv}" + description: Filtered VCF file + pattern: "*.{vcf.gz}" + - sage_dir: + type: directory + description: SAGE output directory - versions: type: file description: File containing software versions diff --git a/modules/local/sage/somatic/meta.yml b/modules/local/sage/somatic/meta.yml index 172d7ad9..88ff985b 100644 --- a/modules/local/sage/somatic/meta.yml +++ b/modules/local/sage/somatic/meta.yml @@ -35,8 +35,11 @@ input: pattern: "*.{bai}" - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version - genome_fai: type: file description: Reference genome assembly fai file @@ -45,9 +48,6 @@ input: type: file description: Reference genome assembly dict file pattern: "*.{dict}" - - genome_ver: - type: string - description: Reference genome version - sage_known_hotspots_somatic: type: file description: SAGE somatic known hotspots file @@ -56,6 +56,10 @@ input: type: file description: SAGE actionable gene panel file pattern: "*.{bed.gz}" + - sage_coverage_panel: + type: file + description: SAGE coverage gene panel file + pattern: "*.{bed.gz}" - sage_highconf_regions: type: file description: SAGE high confidence regions file @@ -73,22 +77,13 @@ output: type: file description: SAGE VCF file pattern: "*.{vcf.gz}" - - tumor_bqr_png: - type: file - description: Tumor BQR plot file - pattern: "*.{png}" - - normal_bqr_png: - type: file - description: Normal BQR plot file - pattern: "*.{png}" - - gene_coverage: + - vcf_filtered: type: file - description: Gene coverage output file - pattern: "*.{tsv}" - - bqr_tsv: - type: file - description: BQR data files - pattern: "*.{tsv}" + description: Filtered VCF file + pattern: "*.{vcf.gz}" + - sage_dir: + type: directory + description: SAGE output directory - versions: type: file description: File containing software versions diff --git a/modules/local/sigs/meta.yml b/modules/local/sigs/meta.yml index 08d6db55..70dd85b6 100644 --- a/modules/local/sigs/meta.yml +++ b/modules/local/sigs/meta.yml @@ -17,7 +17,7 @@ input: e.g. [id: 'sample_id', tumor_id: 'tumor_name'] - smlv_vcf: type: file - description: Tumor small variant VCF file + description: Small somatic variant VCF file pattern: "*.{vcf.gz}" - signatures: type: file diff --git a/modules/local/svprep/assemble/meta.yml b/modules/local/svprep/assemble/meta.yml index a54c7fa9..60541c7c 100644 --- a/modules/local/svprep/assemble/meta.yml +++ b/modules/local/svprep/assemble/meta.yml @@ -18,11 +18,9 @@ input: - bams: type: list description: List of BAM files - pattern: "*.{bam}" - bams_filtered: type: list description: List of filtered BAM files - pattern: "*.{bam}" - preprocess_dirs: type: list description: List of GRIDSS preprocess output directories @@ -34,7 +32,7 @@ input: description: GRIDSS configuration file (optional) - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" - genome_fai: type: file diff --git a/modules/local/svprep/call/meta.yml b/modules/local/svprep/call/meta.yml index e3a1a69d..2838a46f 100644 --- a/modules/local/svprep/call/meta.yml +++ b/modules/local/svprep/call/meta.yml @@ -18,11 +18,9 @@ input: - bams: type: list description: List of BAM files - pattern: "*.{bam}" - bams_filtered: type: list description: List of filtered BAM files - pattern: "*.{bam}" - assemble_dir: type: directory description: GRIDSS assemble output directory @@ -34,7 +32,7 @@ input: description: GRIDSS configuration file (optional) - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" - genome_fai: type: file diff --git a/modules/local/svprep/depth_annotator/meta.yml b/modules/local/svprep/depth_annotator/meta.yml index 22198296..893d9ad8 100644 --- a/modules/local/svprep/depth_annotator/meta.yml +++ b/modules/local/svprep/depth_annotator/meta.yml @@ -19,11 +19,9 @@ input: - bams: type: list description: BAM files - pattern: "*.{bam}" - bai: type: list description: BAI files - pattern: "*.{bai}" - vcf: type: file description: VCF file @@ -33,7 +31,7 @@ input: description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" - genome_ver: type: string @@ -48,6 +46,10 @@ output: type: file description: VCF file pattern: "*.{vcf.gz}" + - tbi: + type: file + description: VCF index file + pattern: "*.{vcf.gz.tbi}" - versions: type: file description: File containing software versions diff --git a/modules/local/svprep/preprocess/meta.yml b/modules/local/svprep/preprocess/meta.yml index c792bda5..90f1659c 100644 --- a/modules/local/svprep/preprocess/meta.yml +++ b/modules/local/svprep/preprocess/meta.yml @@ -28,7 +28,7 @@ input: description: GRIDSS configuration file (optional) - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" - genome_fai: type: file diff --git a/modules/local/svprep/svprep/meta.yml b/modules/local/svprep/svprep/meta.yml index e25a0202..d214e268 100644 --- a/modules/local/svprep/svprep/meta.yml +++ b/modules/local/svprep/svprep/meta.yml @@ -30,7 +30,7 @@ input: pattern: "*.{csv}" - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" - genome_ver: type: string diff --git a/modules/local/virusbreakend/meta.yml b/modules/local/virusbreakend/meta.yml index ae9641d9..b3f4c8c2 100644 --- a/modules/local/virusbreakend/meta.yml +++ b/modules/local/virusbreakend/meta.yml @@ -24,7 +24,7 @@ input: description: GRIDSS configuration file (optional) - genome_fasta: type: file - description: Reference genome assembly fa file + description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" - genome_fai: type: file diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index 6d665895..f01453fc 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -41,7 +41,8 @@ process VIRUSINTERPRETER { stub: """ - touch ${meta.id}.virus.annotated.tsv + mkdir -p virusinterpreter/ + touch virusinterpreter/${meta.id}.virus.annotated.tsv echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/virusinterpreter/meta.yml b/modules/local/virusinterpreter/meta.yml index df59f4e8..251ef87f 100644 --- a/modules/local/virusinterpreter/meta.yml +++ b/modules/local/virusinterpreter/meta.yml @@ -21,14 +21,9 @@ input: type: file description: VIRUSBreakend summary file pattern: "*.{tsv}" - - purple_purity: - type: file - description: PURPLE purity file - pattern: "*.{tsv}" - - purple_qc: - type: file - description: PURPLE QC file - pattern: "*.{qc}" + - purple_dir: + type: directory + description: PURPLE output directory - wgs_metrics: type: file description: Somatic collectwgsmetrics file @@ -46,10 +41,9 @@ output: description: | Groovy Map containing sample information e.g. [id: 'sample_id'] - - virusinterpreter: - type: file - description: Virus Interpreter output file - pattern: "*.{tsv}" + - virusinterpreter_dir: + type: directory + description: Virus Interpreter output direcotry - versions: type: file description: File containing software versions diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index ab5da6d7..435ac894 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -13,7 +13,7 @@ workflow CUPPA_PREDICTION { ch_isofox // channel: [optional] [ meta, isofox_dir ] ch_purple // channel: [optional] [ meta, purple_dir ] ch_linx // channel: [optional] [ meta, linx_annotation_dir ] - ch_virusinterpreter // channel: [optional] [ meta, virusinterpreter ] + ch_virusinterpreter // channel: [optional] [ meta, virusinterpreter_dir ] // Reference data genome_version // channel: [mandatory] genome version @@ -31,7 +31,7 @@ workflow CUPPA_PREDICTION { // channel: [ meta, isofox_dir ] ch_cuppa_inputs_isofox = run_config.stages.isofox ? ch_isofox : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional') - // channel: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter ] + // channel: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_cuppa_inputs_isofox, run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional'), @@ -41,7 +41,7 @@ workflow CUPPA_PREDICTION { ) // Create inputs and create process-specific meta - // channel: [ meta_cuppa, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter ] + // channel: [ meta_cuppa, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] ch_cuppa_inputs = ch_cuppa_inputs_source .map { data -> def meta = data[0] diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index 9b8045f8..3831c505 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -102,7 +102,7 @@ workflow VIRUSBREAKEND_CALLING { ) emit: - virusinterpreter = ch_outputs // channel: [ meta, virusinterpreter_dir ] + virusinterpreter_dir = ch_outputs // channel: [ meta, virusinterpreter_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 58bcef3b..e4f149f6 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -512,7 +512,7 @@ workflow WGTS { ) ch_versions = ch_versions.mix(VIRUSBREAKEND_CALLING.out.versions) - ch_virusinterpreter_out = ch_virusinterpreter_out.mix(VIRUSBREAKEND_CALLING.out.virusinterpreter) + ch_virusinterpreter_out = ch_virusinterpreter_out.mix(VIRUSBREAKEND_CALLING.out.virusinterpreter_dir) } // From 6b6580da30e23dbcccbb49963d7c089718992886 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 3 Aug 2023 16:00:25 +1000 Subject: [PATCH 199/562] Create new arrays with sort rather than mutating --- lib/WorkflowOncoanalyser.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index f62729f5..2da965cc 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -42,7 +42,7 @@ class WorkflowOncoanalyser { def values_map = data[1] def values_list = values_map - .sort { it.position } + .sort(false) { it.position } .collect { it.values } return [meta, *values_list] } From 21094eb1e596fb3a5f796d0f283cfcaab79d9962 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 14 Jul 2023 17:21:39 +1000 Subject: [PATCH 200/562] Implement panel workflow --- conf/panel_data.config | 46 ++ conf/panel_parameters.config | 31 ++ conf/test.config | 2 +- lib/Constants.groovy | 38 +- lib/Processes.groovy | 16 + lib/Utils.groovy | 14 +- lib/WorkflowMain.groovy | 56 +++ main.nf | 5 +- modules/local/pave/somatic/main.nf | 4 +- nextflow.config | 8 +- nextflow_schema.json | 10 + subworkflows/local/channel_inputs_purple.nf | 7 +- subworkflows/local/cuppa_prediction.nf | 3 + subworkflows/local/lilac_calling.nf | 11 + subworkflows/local/orange_reporting.nf | 2 +- subworkflows/local/pave_annotation.nf | 4 +- subworkflows/local/prepare_input.nf | 12 +- subworkflows/local/prepare_reference.nf | 32 ++ workflows/panel.nf | 438 +++++++++++++++++++- 19 files changed, 710 insertions(+), 29 deletions(-) create mode 100644 conf/panel_data.config create mode 100644 conf/panel_parameters.config diff --git a/conf/panel_data.config b/conf/panel_data.config new file mode 100644 index 00000000..22d0ad82 --- /dev/null +++ b/conf/panel_data.config @@ -0,0 +1,46 @@ +params { + + panel_data_paths { + + hmf { + + '38' { + driver_gene_panel = 'common/DriverGenePanel.38.tsv' + sage_actionable_panel = 'variants/ActionableCodingPanel.38.bed.gz' + sage_coverage_panel = 'variants/CoverageCodingPanel.38.bed.gz' + pon_artefacts = 'variants/PanelArtefacts.38.tsv' + target_region_bed = 'copy_number/target_regions_definition.38.bed' + target_region_normalisation = 'copy_number/target_regions_normalisation.38.tsv' + target_region_ratios = 'copy_number/target_regions_ratios.38.tsv' + target_region_msi_indels = 'copy_number/target_regions_msi_indels.38.tsv' + } + + } + + tso500 { + + '37' { + driver_gene_panel = 'common/DriverGenePanel.tso500.37.tsv' + sage_actionable_panel = 'variants/ActionableCodingPanel.tso500.37.bed.gz' + sage_coverage_panel = 'variants/CoverageCodingPanel.tso500.37.bed.gz' + pon_artefacts = 'variants/pon_artefacts.tso500.37.tsv.gz' + target_region_bed = 'copy_number/target_regions_definition.tso500.37.bed.gz' + target_region_normalisation = 'copy_number/cobalt_normalisation.tso500.37.tsv' + target_region_ratios = 'copy_number/target_regions_ratios.tso500.37.tsv' + target_region_msi_indels = 'copy_number/target_regions_msi_indels.tso500.37.tsv' + } + + '38' { + driver_gene_panel = 'common/DriverGenePanel.tso500.38.tsv' + sage_actionable_panel = 'variants/ActionableCodingPanel.tso500.38.bed.gz' + sage_coverage_panel = 'variants/CoverageCodingPanel.tso500.38.bed.gz' + pon_artefacts = 'variants/pon_artefacts.tso500.38.tsv.gz' + target_region_bed = 'copy_number/target_regions_definition.tso500.38.bed.gz' + target_region_normalisation = 'copy_number/cobalt_normalisation.tso500.38.tsv' + target_region_ratios = 'copy_number/target_regions_ratios.tso500.38.tsv' + target_region_msi_indels = 'copy_number/target_regions_msi_indels.tso500.38.tsv' + } + + } + } +} diff --git a/conf/panel_parameters.config b/conf/panel_parameters.config new file mode 100644 index 00000000..661237dd --- /dev/null +++ b/conf/panel_parameters.config @@ -0,0 +1,31 @@ +process.'withName:^.*:AMBER_PROFILING:AMBER'.ext.args = [ + '-tumor_only_min_depth 80', +].join(' ').trim() + +process.'withName:^.*:COBALT_PROFILING:COBALT'.ext.args = [ + '-pcf_gamma 15', +].join(' ').trim() + +process.'withName:^.*:SAGE_CALLING:SOMATIC'.ext.args = [ + '-hard_min_tumor_vaf 0.005', + '-hotspot_min_tumor_vaf 0.01', + '-hotspot_min_tumor_qual 100', + '-panel_min_tumor_qual 250', + '-high_confidence_min_tumor_qual 350', + '-low_confidence_min_tumor_qual 500', + '-max_read_depth 100000', + '-sync_fragments', +].join(' ').trim() + +process.'withName:^.*:GRIPSS_FILTERING:SOMATIC'.ext.args = [ + '-hard_min_tumor_qual 200', + '-min_qual_break_point 1000', + '-min_qual_break_end 1000', +].join(' ').trim() + +process.'withName:^.*:PURPLE_CALLING:PURPLE'.ext.args = [ + '-min_diploid_tumor_ratio_count 3', + '-min_diploid_tumor_ratio_count_centromere 3', + '-ploidy_penalty_factor 0.6', + '-ploidy_penalty_standard_deviation 0.15', +].join(' ').trim() diff --git a/conf/test.config b/conf/test.config index 2da2c9ee..56c3ae60 100644 --- a/conf/test.config +++ b/conf/test.config @@ -35,7 +35,7 @@ params { // Defined here to be accessible within a workflow script; downloaded manually prior to process // execution. - schema_ignore_params = 'genomes,hmf_data_paths' + schema_ignore_params = 'genomes,hmf_data_paths,panel_data_paths' // Limit resources so that this can run on GitHub Actions max_cpus = 1 diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 3dba47d5..f0fe802c 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -8,11 +8,19 @@ class Constants { static List GENOMES_SUPPORTED = ['GRCh37_hmf', 'GRCh38_hmf'] static List GENOMES_DEFINED = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 + static List PANELS_DEFINED = ['hmf', 'tso500'] + static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.33_37--0.tar.gz' static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.33_38--0.tar.gz' + static String HMF_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/hmf_5.33_38--0.tar.gz' + + static String TSO500_PANEL_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.33_37--0.tar.gz' + static String TSO500_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.33_38--0.tar.gz' + + static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' static String HLA_SLICE_BED_GRCH38_ALT_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/umccr_reference_data/other/hla_slice/grch38_alt.plus_homologous.bed' @@ -23,6 +31,7 @@ class Constants { } static enum RunMode { + PANEL, WGS, WGTS, WTS, @@ -81,6 +90,7 @@ class Constants { } static enum SequenceType { + TARGETTED, WGS, WGTS, WTS, @@ -100,18 +110,18 @@ class Constants { AMBER_DIR: [ FileType.AMBER_DIR, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS] ], COBALT_DIR: [ FileType.COBALT_DIR, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS] ], BAMTOOLS_TUMOR: [ FileType.BAMTOOLS, SampleType.TUMOR, - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], BAMTOOLS_NORMAL: [ FileType.BAMTOOLS, @@ -122,7 +132,7 @@ class Constants { FLAGSTAT_TUMOR: [ FileType.FLAGSTAT, SampleType.TUMOR, - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], FLAGSTAT_NORMAL: [ FileType.FLAGSTAT, @@ -133,7 +143,7 @@ class Constants { SAGE_VCF_TUMOR: [ FileType.SAGE_VCF, SampleType.TUMOR, - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], SAGE_VCF_NORMAL: [ FileType.SAGE_VCF, @@ -143,7 +153,7 @@ class Constants { SAGE_DIR_TUMOR: [ FileType.SAGE_DIR, SampleType.TUMOR, - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], SAGE_DIR_NORMAL: [ FileType.SAGE_DIR, @@ -154,7 +164,7 @@ class Constants { PAVE_VCF_TUMOR: [ FileType.PAVE_VCF, SampleType.TUMOR, - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], PAVE_VCF_NORMAL: [ FileType.PAVE_VCF, @@ -165,13 +175,13 @@ class Constants { GRIDSS_VCF: [ FileType.GRIDSS_VCF, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], GRIPSS_VCF_TUMOR: [ FileType.GRIPSS_VCF, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], GRIPSS_VCF_NORMAL: [ FileType.GRIPSS_VCF, @@ -181,7 +191,7 @@ class Constants { GRIPSS_UNFILTERED_VCF_TUMOR: [ FileType.GRIPSS_UNFILTERED_VCF, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], GRIPSS_UNFILTERED_VCF_NORMAL: [ FileType.GRIPSS_UNFILTERED_VCF, @@ -192,18 +202,18 @@ class Constants { PURPLE_DIR: [ FileType.PURPLE_DIR, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], LINX_PLOT_DIR_TUMOR: [ FileType.LINX_PLOT_DIR, SampleType.TUMOR, - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], LINX_ANNO_DIR_TUMOR: [ FileType.LINX_ANNO_DIR, SampleType.TUMOR, - SequenceType.WGS, + [SequenceType.TARGETTED, SequenceType.WGS], ], LINX_ANNO_DIR_NORMAL: [ FileType.LINX_ANNO_DIR, @@ -224,7 +234,7 @@ class Constants { LILAC_DIR: [ FileType.LILAC_DIR, [SampleType.TUMOR, SampleType.NORMAL, SampleType.TUMOR_NORMAL], - [SequenceType.WGS, SequenceType.WGTS], + [SequenceType.TARGETTED, SequenceType.WGS, SequenceType.WGTS], ], VIRUSINTERPRETER_TSV: [ diff --git a/lib/Processes.groovy b/lib/Processes.groovy index 6cf1863a..2862d106 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -59,6 +59,22 @@ class Processes { Constants.Process.VIRUSINTERPRETER, ] break + case Constants.RunMode.PANEL: + processes = [ + Constants.Process.AMBER, + Constants.Process.BAMTOOLS, + Constants.Process.COBALT, + Constants.Process.FLAGSTAT, + Constants.Process.GRIDSS, + Constants.Process.GRIPSS, + Constants.Process.LILAC, + Constants.Process.LINX, + Constants.Process.ORANGE, + Constants.Process.PAVE, + Constants.Process.PURPLE, + Constants.Process.SAGE, + ] + break default: log.error "\nERROR: we should never have come here" System.exit(1) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 6e3b37bb..d6a05377 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -73,7 +73,12 @@ class Utils { // NOTE(SW): this should /only/ be used to get panel or WGS tumor sample name, WTS sample name retrieval is not supported - def sequence_type = Constants.SequenceType.WGS + def sequence_type + if (run_mode == Constants.RunMode.PANEL) { + sequence_type = Constants.SequenceType.TARGETTED + } else if (run_mode == Constants.RunMode.WGS || run_mode == Constants.RunMode.WGTS) { + sequence_type = Constants.SequenceType.WGS + } return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, sequence_type]) } @@ -96,7 +101,12 @@ class Utils { // NOTE(SW): this should /only/ be used to get panel or WGS tumor BAM, WTS BAM retrieval is not supported - def sequence_type = Constants.SequenceType.WGS + def sequence_type + if (run_mode == Constants.RunMode.PANEL) { + sequence_type = Constants.SequenceType.TARGETTED + } else if (run_mode == Constants.RunMode.WGS || run_mode == Constants.RunMode.WGTS) { + sequence_type = Constants.SequenceType.WGS + } return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, sequence_type]) } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index d2ccaca0..35d69db3 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -146,6 +146,25 @@ class WorkflowMain { } } + if (run_mode == Constants.RunMode.PANEL) { + + if (!params.containsKey('run_type')) { + params.run_type = 'tumor_only' + } + + // Attempt to set default panel data path; make no assumption on valid 'panel' value + if (!params.containsKey('ref_data_panel_data_path') && params.containsKey('panel')) { + if (params.panel == 'hmf' && params.ref_data_genome_version == '38') { + params.ref_data_panel_data_path = Constants.HMF_PANEL_38_PATH + } else if (params.panel == 'tso500' && params.ref_data_genome_version == '37') { + params.ref_data_panel_data_path = Constants.TSO500_PANEL_37_PATH + } else if (params.panel == 'tso500' && params.ref_data_genome_version == '38') { + params.ref_data_panel_data_path = Constants.TSO500_PANEL_38_PATH + } + } + + } + def stages = Processes.getRunStages( run_mode, params.processes_include, @@ -277,6 +296,43 @@ class WorkflowMain { } + if (run_mode == Constants.RunMode.PANEL) { + + if (run_type != Constants.RunType.TUMOR_ONLY) { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " The panel run mode does not support tumor/normal data, please adjust the CLI \n" + + " --run_type option or corresponding configuration file.\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + if (!params.containsKey('panel')) { + def panels = Constants.PANELS_DEFINED.join('\n - ') + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " A panel is required to be set using the --panel CLI argument or in a \n" + + " configuration file.\n" + + " Currently, the available panels are:\n" + + " - ${panels}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } else if (!Constants.PANELS_DEFINED.contains(params.panel)) { + def panels = Constants.PANELS_DEFINED.join('\n - ') + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " The ${params.panel} is not defined. Currently, the available panels are:\n" + + " - ${panels}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + if (params.panel == 'hmf' && params.ref_data_genome_version == '37') { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " The Hartwig panel (hmf) is not available for the GRCh37 reference genome.\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + } + } public static getRunConfig(params, log) { diff --git a/main.nf b/main.nf index fc9c7560..e4d43e00 100644 --- a/main.nf +++ b/main.nf @@ -45,7 +45,8 @@ WorkflowMain.paramsSummaryLog(workflow, params, log) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { WGTS } from './workflows/wgts' +include { PANEL } from './workflows/panel' +include { WGTS } from './workflows/wgts' // // WORKFLOW: Run main nf-core/oncoanalyser analysis pipeline @@ -57,6 +58,8 @@ workflow NFCORE_ONCOANALYSER { run_modes_wgts = [Constants.RunMode.WGS, Constants.RunMode.WTS, Constants.RunMode.WGTS] if (run_modes_wgts.contains(run_mode)) { WGTS() + } else if (run_mode == Constants.RunMode.PANEL) { + PANEL() } else { assert false } diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 0ddeb2d0..f921831b 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -10,7 +10,7 @@ process PAVE_SOMATIC { val genome_ver path genome_fai path sage_pon - path sage_pon_artefacts + path pon_artefacts path segment_mappability path driver_gene_panel path ensembl_data_resources @@ -27,7 +27,7 @@ process PAVE_SOMATIC { script: def args = task.ext.args ?: '' - def pon_artefact_arg = sage_pon_artefacts ? "-pon_artefact_file ${sage_pon_artefacts}" : '' + def pon_artefact_arg = pon_artefacts ? "-pon_artefact_file ${pon_artefacts}" : '' def pon_filters def gnomad_args diff --git a/nextflow.config b/nextflow.config index 07a3ff63..a46ddce6 100644 --- a/nextflow.config +++ b/nextflow.config @@ -36,7 +36,7 @@ params { help = false validate_params = true show_hidden_params = false - schema_ignore_params = 'genomes,hmf_data_paths' + schema_ignore_params = 'genomes,hmf_data_paths,panel_data_paths' enable_conda = false // Other workflow inputs and options @@ -156,6 +156,12 @@ if (!params.igenomes_ignore) { // Load data configs includeConfig 'conf/hmf_data.config' includeConfig 'conf/hmf_genomes.config' +includeConfig 'conf/panel_data.config' + +// Load panel configuration if needed +if (params.containsKey('run_mode') && params.run_mode == 'panel') { + includeConfig 'conf/panel_parameters.config' +} // Export these variables to prevent local Python/R libraries from conflicting with those in the container diff --git a/nextflow_schema.json b/nextflow_schema.json index a75e5af8..8510fdcc 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -121,6 +121,11 @@ "fa_icon": "fas fa-book", "hidden": true }, + "panel": { + "type": "string", + "description": "Name of pane to use.", + "fa_icon": "fas fa-book" + }, "igenomes_base": { "type": "string", "format": "directory-path", @@ -141,6 +146,11 @@ "description": "Path to HMF data.", "fa_icon": "far fa-folder-open" }, + "ref_data_panel_data_path": { + "type": "string", + "description": "Path to panel data.", + "fa_icon": "far fa-folder-open" + }, "ref_data_virusbreakenddb_path": { "type": "string", "format": "directory-path", diff --git a/subworkflows/local/channel_inputs_purple.nf b/subworkflows/local/channel_inputs_purple.nf index d6f694da..7a6c7244 100644 --- a/subworkflows/local/channel_inputs_purple.nf +++ b/subworkflows/local/channel_inputs_purple.nf @@ -42,15 +42,18 @@ workflow CHANNEL_INPUTS_PURPLE { ch_smlv_germline_source = run_config.stages.pave ? ch_smlv_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_NORMAL, type: 'optional') // Adjust for run type and mode - // NOTE(SW): Hartwig indicated unfiltered SVs should not be used for recovery in tumor-only mode if (run_config.type == Constants.RunType.TUMOR_ONLY) { ch_sv_germline_source = ch_inputs.map { meta -> [meta, [], []] } ch_smlv_germline_source = ch_inputs.map { meta -> [meta, []] } - ch_sv_somatic_unfiltered_source = ch_inputs.map { meta -> [meta, [], []] } } + // NOTE(SW): Hartwig indicated unfiltered SVs should not be used for recovery in panel or tumor-only mode + if (run_config.mode == Constants.RunMode.PANEL || run_config.type == Constants.RunType.TUMOR_ONLY) { + ch_sv_somatic_unfiltered_source = ch_inputs.map { meta -> [meta, [], []] } + } + // Combine into single channel ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( ch_amber_source, diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index 435ac894..50bce74a 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -58,6 +58,9 @@ workflow CUPPA_PREDICTION { meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) meta_cuppa.id_wts = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) break + case Constants.RunMode.PANEL: + meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.TARGETTED]) + break default: assert false } diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index c6485a2b..e233104d 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -72,6 +72,14 @@ workflow LILAC_CALLING { [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", normal_bai] } + } else if (run_config.mode == Constants.RunMode.PANEL) { + + ch_lilac_bams = ch_inputs + .map { meta -> + def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + [meta, tumor_bam, [], "${tumor_bam}.bai", []] + } + } else { ch_lilac_bams = ch_inputs.map { meta -> [meta, [], [], [], []] } } @@ -82,6 +90,9 @@ workflow LILAC_CALLING { case Constants.RunMode.WGTS: tumor_sequence_type = Constants.SequenceType.WGS break + case Constants.RunMode.PANEL: + tumor_sequence_type = Constants.SequenceType.TARGETTED + break default: assert false } diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index d6270ff9..9718d73a 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -84,7 +84,7 @@ workflow ORANGE_REPORTING { // Get input smlv somatic VCF from either PURPLE or SAGE append // channel: [ meta, sage_somatic_vcf, sage_germline_vcf ] - if (run_config.mode == Constants.RunMode.WGS) { + if (run_config.mode == Constants.RunMode.WGS || run_config.mode == Constants.RunMode.PANEL) { ch_orange_inputs_smlv_vcfs = ch_orange_inputs_purple_dir .map { meta, purple_dir -> diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf index 959180aa..f821f4ef 100644 --- a/subworkflows/local/pave_annotation.nf +++ b/subworkflows/local/pave_annotation.nf @@ -17,7 +17,7 @@ workflow PAVE_ANNOTATION { genome_version // channel: [mandatory] genome version genome_fai // channel: [mandatory] /path/to/genome_fai sage_pon // channel: [mandatory] /path/to/sage_pon - sage_pon_artefacts // channel: [optional] /path/to/sage_pon_artefacts + pon_artefacts // channel: [optional] /path/to/pon_artefacts sage_blocklist_regions // channel: [mandatory] /path/to/sage_blocklist_regions sage_blocklist_sites // channel: [mandatory] /path/to/sage_blocklist_sites clinvar_annotations // channel: [mandatory] /path/to/clinvar_annotations @@ -104,7 +104,7 @@ workflow PAVE_ANNOTATION { genome_version, genome_fai, sage_pon, - sage_pon_artefacts, + pon_artefacts, segment_mappability, driver_gene_panel, ensembl_data_resources, diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf index 4f427f56..c7847b17 100644 --- a/subworkflows/local/prepare_input.nf +++ b/subworkflows/local/prepare_input.nf @@ -28,7 +28,9 @@ workflow PREPARE_INPUT { assert false } - if (run_config.mode == Constants.RunMode.WGS) { + if (run_config.mode == Constants.RunMode.PANEL) { + sequence_types_allowed = [Constants.SequenceType.TARGETTED] + } else if (run_config.mode == Constants.RunMode.WGS) { sequence_types_allowed = [Constants.SequenceType.WGS] } else if (run_config.mode == Constants.RunMode.WTS) { sequence_types_allowed = [Constants.SequenceType.WTS] @@ -192,7 +194,13 @@ workflow PREPARE_INPUT { } def required_sample_types - if (run_config.mode == Constants.RunMode.WGS) { + if (run_config.mode == Constants.RunMode.PANEL) { + + required_sample_types = [ + [Constants.SampleType.TUMOR, Constants.SequenceType.TARGETTED], + ] + + } else if (run_config.mode == Constants.RunMode.WGS) { if (run_config.type == Constants.RunType.TUMOR_ONLY) { required_sample_types = [ diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index e48329a2..5b7e0fcd 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -8,6 +8,7 @@ include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_BWA_INDEX } from '../../modules/local/custom/extract_tarball/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_HMF_DATA } from '../../modules/local/custom/extract_tarball/main' +include { CUSTOM_EXTRACTTARBALL as DECOMP_PANEL_DATA } from '../../modules/local/custom/extract_tarball/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_VIRUSBREAKEND_DB } from '../../modules/local/custom/extract_tarball/main' include { GRIDSS_INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' include { GRIDSS_INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' @@ -131,6 +132,36 @@ workflow PREPARE_REFERENCE { ch_hmf_data = createDataMap(hmf_data_paths, params.ref_data_hmf_data_path) } + // + // Set panel reference paths / stage, unpack if required + // + ch_panel_data = Channel.empty() + if (run_config.mode == Constants.RunMode.PANEL) { + + // NOTE(SW): consider approach to implement custom panel support + + panel_data_paths_versions = params.panel_data_paths[params.panel] + panel_data_paths = panel_data_paths_versions[params.ref_data_genome_version] + + if (params.ref_data_panel_data_path.endsWith('tar.gz')) { + ch_panel_data_inputs = [ + [id: 'panel_data'], + file(params.ref_data_panel_data_path), + ] + DECOMP_PANEL_DATA(ch_panel_data_inputs) + + ch_panel_data = DECOMP_PANEL_DATA.out.dir + .collect() + .map { dir_list -> + assert dir_list.size() == 1 + def dirpath = dir_list[0].toUriString() + return createDataMap(panel_data_paths, dirpath) + } + } else { + ch_panel_data = createDataMap(panel_data_paths, params.ref_data_panel_data_path) + } + } + emit: genome_fasta = ch_genome_fasta // path: genome_fasta genome_fai = ch_genome_fai // path: genome_fai @@ -142,6 +173,7 @@ workflow PREPARE_REFERENCE { virusbreakenddb = ch_virusbreakenddb // path: VIRUSBreakend database hmf_data = ch_hmf_data // map: HMF data paths + panel_data = ch_panel_data // map: Panel data paths versions = ch_versions // channel: [ versions.yml ] } diff --git a/workflows/panel.nf b/workflows/panel.nf index d43b9490..a9ee6da8 100644 --- a/workflows/panel.nf +++ b/workflows/panel.nf @@ -1 +1,437 @@ -// PLACEHOLDER +import Constants +import Processes +import Utils + + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + VALIDATE INPUTS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// Get run config +run_config = WorkflowMain.getRunConfig(params, log) + +// Check input path parameters to see if they exist +def checkPathParamList = [ + params.input, + params.linx_gene_id_file, +] + +// Conditional requirements +if (run_config.stages.gridss) { + if (params.containsKey('gridss_config')) { + checkPathParamList.add(params.gridss_config) + } +} + +if (run_config.stages.lilac) { + if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && params.containsKey('ref_data_hla_slice_bed')) { + checkPathParamList.add(params.ref_data_hla_slice_bed) + } +} + +// TODO(SW): consider whether we should check for null entries here for errors to be more informative +for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } + +// Check mandatory parameters +if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } + +// Create Path objects for some input files +linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : [] + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CONFIG FILES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT LOCAL MODULES/SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// +// SUBWORKFLOWS +// +include { AMBER_PROFILING } from '../subworkflows/local/amber_profiling' +include { BAMTOOLS_METRICS } from '../subworkflows/local/bamtools_metrics' +include { COBALT_PROFILING } from '../subworkflows/local/cobalt_profiling' +include { GRIDSS_SVPREP_CALLING } from '../subworkflows/local/gridss_svprep_calling' +include { GRIPSS_FILTERING } from '../subworkflows/local/gripss_filtering' +include { LILAC_CALLING } from '../subworkflows/local/lilac_calling' +include { LINX_ANNOTATION } from '../subworkflows/local/linx_annotation' +include { LINX_PLOTTING } from '../subworkflows/local/linx_plotting' +include { ORANGE_REPORTING } from '../subworkflows/local/orange_reporting' +include { PAVE_ANNOTATION } from '../subworkflows/local/pave_annotation' +include { PREPARE_INPUT } from '../subworkflows/local/prepare_input' +include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' +include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' +include { SAGE_CALLING } from '../subworkflows/local/sage_calling' + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT NF-CORE MODULES/SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// +// MODULES +// +include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + RUN MAIN WORKFLOW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// Get absolute file paths +samplesheet = Utils.getFileObject(params.input) + +workflow PANEL { + + // Create channel for versions + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Get inputs from samplesheet, assign more human readable variable + // channel: [ meta ] + PREPARE_INPUT( + samplesheet, + run_config, + ) + ch_inputs = PREPARE_INPUT.out.data + + // Set up reference data, assign more human readable variables + PREPARE_REFERENCE( + run_config, + ) + ref_data = PREPARE_REFERENCE.out + hmf_data = PREPARE_REFERENCE.out.hmf_data + panel_data = PREPARE_REFERENCE.out.panel_data + + // Set GRIDSS config + gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config + + // + // SUBWORKFLOW: Run Bam Tools to generate stats required for downstream processes + // + // channel: [ meta, metrics ] + ch_bamtools_somatic_out = Channel.empty() + if (run_config.stages.bamtools) { + + BAMTOOLS_METRICS( + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_version, + run_config, + ) + + ch_versions = ch_versions.mix(BAMTOOLS_METRICS.out.versions) + ch_bamtools_somatic_out = ch_bamtools_somatic_out.mix(BAMTOOLS_METRICS.out.somatic) + } + + + // + // SUBWORKFLOW: Run AMBER to obtain b-allele frequencies + // + // channel: [ meta, amber_dir ] + ch_amber_out = Channel.empty() + if (run_config.stages.amber) { + + AMBER_PROFILING( + ch_inputs, + ref_data.genome_version, + hmf_data.heterozygous_sites, + run_config, + ) + + ch_versions = ch_versions.mix(AMBER_PROFILING.out.versions) + ch_amber_out = ch_amber_out.mix(AMBER_PROFILING.out.amber_dir) + } + + // + // SUBWORKFLOW: Run COBALT to obtain read ratios + // + // channel: [ meta, cobalt_dir ] + ch_cobalt_out = Channel.empty() + if (run_config.stages.cobalt) { + + COBALT_PROFILING( + ch_inputs, + hmf_data.gc_profile, + hmf_data.diploid_bed, + panel_data.target_region_normalisation, + run_config, + ) + + ch_versions = ch_versions.mix(COBALT_PROFILING.out.versions) + ch_cobalt_out = ch_cobalt_out.mix(COBALT_PROFILING.out.cobalt_dir) + } + + // + // SUBWORKFLOW: Call structural variants with GRIDSS + // + // channel: [ meta, gridss_vcf ] + ch_gridss_out = Channel.empty() + if (run_config.stages.gridss) { + + GRIDSS_SVPREP_CALLING( + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_version, + ref_data.genome_fai, + ref_data.genome_dict, + ref_data.genome_bwa_index, + ref_data.genome_bwa_index_image, + ref_data.genome_gridss_index, + hmf_data.gridss_region_blocklist, + hmf_data.sv_prep_blocklist, + hmf_data.known_fusions, + gridss_config, + run_config, + ) + + ch_versions = ch_versions.mix(GRIDSS_SVPREP_CALLING.out.versions) + ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP_CALLING.out.results) + } + + // + // SUBWORKFLOW: Run GRIPSS to filter GRIDSS SV calls + // + // channel: [ meta, vcf, tbi ] + ch_gripss_somatic_out = Channel.empty() + ch_gripss_somatic_unfiltered_out = Channel.empty() + if (run_config.stages.gripss) { + + GRIPSS_FILTERING( + ch_inputs, + ch_gridss_out, + ref_data.genome_fasta, + ref_data.genome_version, + ref_data.genome_fai, + hmf_data.gridss_pon_breakends, + hmf_data.gridss_pon_breakpoints, + hmf_data.known_fusions, + hmf_data.repeatmasker_annotations, + panel_data.target_region_bed, + run_config, + ) + + ch_versions = ch_versions.mix(GRIPSS_FILTERING.out.versions) + ch_gripss_somatic_out = ch_gripss_somatic_out.mix(GRIPSS_FILTERING.out.somatic) + ch_gripss_somatic_unfiltered_out = ch_gripss_somatic_unfiltered_out.mix(GRIPSS_FILTERING.out.somatic_unfiltered) + } + + // + // SUBWORKFLOW: call SNV, MNV, and small INDELS with SAGE + // + // channel: [ meta, sage_vcf, sage_tbi ] + ch_sage_somatic_vcf_out = Channel.empty() + // channel: [ meta, sage_dir ] + ch_sage_somatic_dir_out = Channel.empty() + if (run_config.stages.sage) { + + SAGE_CALLING( + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_version, + ref_data.genome_fai, + ref_data.genome_dict, + [], // sage_known_hotspots_germline + hmf_data.sage_known_hotspots_somatic, + panel_data.sage_actionable_panel, + panel_data.sage_coverage_panel, + hmf_data.sage_highconf_regions, + hmf_data.segment_mappability, + panel_data.driver_gene_panel, + hmf_data.ensembl_data_resources, + run_config, + ) + + ch_versions = ch_versions.mix(SAGE_CALLING.out.versions) + ch_sage_somatic_vcf_out = ch_sage_somatic_vcf_out.mix(SAGE_CALLING.out.somatic_vcf) + ch_sage_somatic_dir_out = ch_sage_somatic_dir_out.mix(SAGE_CALLING.out.somatic_dir) + } + + // + // SUBWORKFLOW: Annotate variants with PAVE + // + // channel: [ meta, pave_vcf ] + ch_pave_somatic_out = Channel.empty() + if (run_config.stages.pave) { + + PAVE_ANNOTATION( + ch_inputs, + [], // ch_sage_germline_vcf_out + ch_sage_somatic_vcf_out, + ref_data.genome_fasta, + ref_data.genome_version, + ref_data.genome_fai, + hmf_data.sage_pon, + panel_data.pon_artefacts, + hmf_data.sage_blocklist_regions, + hmf_data.sage_blocklist_sites, + hmf_data.clinvar_annotations, + hmf_data.segment_mappability, + panel_data.driver_gene_panel, + hmf_data.ensembl_data_resources, + hmf_data.gnomad_resource, + run_config, + ) + + ch_versions = ch_versions.mix(PAVE_ANNOTATION.out.versions) + ch_pave_somatic_out = ch_pave_somatic_out.mix(PAVE_ANNOTATION.out.somatic) + } + + // + // SUBWORKFLOW: Call CNVs, infer purity and ploidy, and recover low quality SVs with PURPLE + // + // channel: [ meta, purple_dir ] + ch_purple_out = Channel.empty() + if (run_config.stages.purple) { + + PURPLE_CALLING( + ch_inputs, + ch_amber_out, + ch_cobalt_out, + ch_pave_somatic_out, + [], // ch_pave_germline_out + ch_gripss_somatic_out, + [], // ch_gripss_germline_out + [], // ch_gripss_somatic_unfiltered_out, + ref_data.genome_fasta, + ref_data.genome_version, + ref_data.genome_fai, + ref_data.genome_dict, + hmf_data.gc_profile, + hmf_data.sage_known_hotspots_somatic, + [], // sage_known_hotspots_germline + panel_data.driver_gene_panel, + hmf_data.ensembl_data_resources, + [], // purple_germline_del + panel_data.target_region_bed, + panel_data.target_region_ratios, + panel_data.target_region_msi_indels, + run_config, + ) + + ch_versions = ch_versions.mix(PURPLE_CALLING.out.versions) + ch_purple_out = ch_purple_out.mix(PURPLE_CALLING.out.purple_dir) + } + + // + // SUBWORKFLOW: Group structural variants into higher order events with LINX + // + // channel: [ meta, linx_annotation_dir ] + ch_linx_somatic_out = Channel.empty() + // channel: [ meta, linx_visualiser_dir ] + ch_linx_somatic_plot_out = Channel.empty() + if (run_config.stages.linx) { + + LINX_ANNOTATION( + ch_inputs, + ch_purple_out, + ref_data.genome_version, + hmf_data.ensembl_data_resources, + hmf_data.known_fusion_data, + panel_data.driver_gene_panel, + linx_gene_id_file, + run_config, + ) + + ch_versions = ch_versions.mix(LINX_ANNOTATION.out.versions) + ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX_ANNOTATION.out.somatic) + + LINX_PLOTTING( + ch_inputs, + ch_linx_somatic_out, + ref_data.genome_version, + hmf_data.ensembl_data_resources, + run_config, + ) + + ch_versions = ch_versions.mix(LINX_PLOTTING.out.versions) + ch_linx_somatic_plot_out = ch_linx_somatic_plot_out.mix(LINX_PLOTTING.out.visualiser_dir) + } + + // + // SUBWORKFLOW: Run LILAC for HLA typing and somatic CNV and SNV calling + // + // channel: [ meta, lilac_dir ] + ch_lilac_out = Channel.empty() + if (run_config.stages.lilac) { + + // Set HLA slice BED if provided in params + ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] + + LILAC_CALLING( + ch_inputs, + ch_purple_out, + ref_data.genome_fasta, + ref_data.genome_version, + ref_data.genome_fai, + hmf_data.lilac_resources, + ref_data_hla_slice_bed, + run_config, + ) + + ch_versions = ch_versions.mix(LILAC_CALLING.out.versions) + ch_lilac_out = ch_lilac_out.mix(LILAC_CALLING.out.lilac_dir) + } + + // + // SUBWORKFLOW: Run ORANGE to generate static PDF report + // + if (run_config.stages.orange) { + + ORANGE_REPORTING( + ch_inputs, + ch_bamtools_somatic_out, + [], //ch_bamtools_germline_out + ch_sage_somatic_dir_out, + [], // ch_sage_germline_dir_out + [], // ch_sage_somatic_append_vcf + [], // ch_sage_germline_append_vcf + ch_purple_out, + ch_linx_somatic_out, + ch_linx_somatic_plot_out, + [], // ch_linx_germline_out + [], // ch_virusinterpreter_out + [], // ch_chord_out + [], // ch_sigs_out + ch_lilac_out, + [], // ch_cuppa_out + [], // ch_isofox_out + ref_data.genome_version, + hmf_data.disease_ontology, + hmf_data.cohort_mapping, + hmf_data.cohort_percentiles, + hmf_data.known_fusion_data, + panel_data.driver_gene_panel, + hmf_data.ensembl_data_resources, + [], // alt_sj_distribution + [], // gene_exp_distribution + run_config, + ) + + ch_versions = ch_versions.mix(ORANGE_REPORTING.out.versions) + } + + // + // MODULE: Pipeline reporting + // + CUSTOM_DUMPSOFTWAREVERSIONS( + ch_versions.unique().collectFile(name: 'collated_versions.yml') + ) + +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + THE END +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ From d332ee143e59ff904835fc0e35c7ebb1e998344a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 8 Aug 2023 18:17:01 +1000 Subject: [PATCH 201/562] Fix ORANGE WGS only mode --- subworkflows/local/orange_reporting.nf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 9718d73a..97acaed5 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -79,6 +79,13 @@ workflow ORANGE_REPORTING { ch_linx_germline_annotation = ch_inputs.map { meta -> [meta, []] } } + // Do not pass WTS reference files when not required + // NOTE(SW): ORANGE v2.6.0 will crash if WTS reference files but not WTS sample files provided + if (run_config.mode != Constants.RunMode.WTS && run_config.mode != Constants.RunMode.WGTS) { + isofox_alt_sj = [] + isofox_gene_distribution = [] + } + // Get PURPLE input source for processing ch_orange_inputs_purple_dir = run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) From 46cdcea85257b290293bbbe0cd49c7338c3329fb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 8 Aug 2023 21:41:00 +1000 Subject: [PATCH 202/562] Update output paths --- conf/modules.config | 8 +++--- lib/Constants.groovy | 6 ++-- modules/local/sage/germline/main.nf | 38 +++++++++++++------------- modules/local/sage/somatic/main.nf | 38 +++++++++++++------------- subworkflows/local/cuppa_prediction.nf | 2 +- subworkflows/local/orange_reporting.nf | 2 +- 6 files changed, 47 insertions(+), 47 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 3f8a586a..3e16b77a 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -75,7 +75,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/germline/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/${filename}" }, ] } @@ -83,7 +83,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/somatic/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/${filename}" }, ] } @@ -165,7 +165,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/chord/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } @@ -201,7 +201,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/virusinterpreter/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index f0fe802c..b06a8db4 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -73,7 +73,7 @@ class Constants { PAVE_VCF, PURPLE_DIR, SAGE_VCF, - VIRUSINTERPRETER_TSV, + VIRUSINTERPRETER_DIR, // ORANGE specific CHORD_DIR, SIGS_DIR, @@ -237,8 +237,8 @@ class Constants { [SequenceType.TARGETTED, SequenceType.WGS, SequenceType.WGTS], ], - VIRUSINTERPRETER_TSV: [ - FileType.VIRUSINTERPRETER_TSV, + VIRUSINTERPRETER_DIR: [ + FileType.VIRUSINTERPRETER_DIR, SampleType.TUMOR, SequenceType.WGS ], diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 313c77eb..f35917ec 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -25,10 +25,10 @@ process SAGE_GERMLINE { path ensembl_data_resources output: - tuple val(meta), path('sage_germline/*.sage.germline.vcf.gz'), path('sage_germline/*.sage.germline.vcf.gz.tbi') , emit: vcf - tuple val(meta), path('sage_germline/*.sage.germline.filtered.vcf.gz'), path('sage_germline/*.sage.germline.filtered.vcf.gz.tbi'), emit: vcf_filtered - tuple val(meta), path('sage_germline/') , emit: sage_dir - path 'versions.yml' , emit: versions + tuple val(meta), path('germline/*.sage.germline.vcf.gz'), path('germline/*.sage.germline.vcf.gz.tbi') , emit: vcf + tuple val(meta), path('germline/*.sage.germline.filtered.vcf.gz'), path('germline/*.sage.germline.filtered.vcf.gz.tbi'), emit: vcf_filtered + tuple val(meta), path('germline/') , emit: sage_dir + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -37,7 +37,7 @@ process SAGE_GERMLINE { def args = task.ext.args ?: '' """ - mkdir sage_germline/ + mkdir germline/ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ @@ -65,14 +65,14 @@ process SAGE_GERMLINE { -write_bqr_data \\ -write_bqr_plot \\ -threads ${task.cpus} \\ - -out sage_germline/${meta.tumor_id}.sage.germline.vcf.gz + -out germline/${meta.tumor_id}.sage.germline.vcf.gz bcftools view \\ -f 'PASS' \\ - -o sage_germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz \\ - sage_germline/${meta.tumor_id}.sage.germline.vcf.gz + -o germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz \\ + germline/${meta.tumor_id}.sage.germline.vcf.gz - bcftools index -t sage_germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz + bcftools index -t germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml @@ -83,16 +83,16 @@ process SAGE_GERMLINE { stub: """ - mkdir -p sage_germline/ - touch sage_germline/${meta.tumor_id}.sage.germline.vcf.gz - touch sage_germline/${meta.tumor_id}.sage.germline.vcf.gz.tbi - touch sage_germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz - touch sage_germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz.tbi - touch sage_germline/${meta.tumor_id}.sage.bqr.png - touch sage_germline/${meta.tumor_id}.sage.bqr.tsv - touch sage_germline/${meta.normal_id}.sage.bqr.png - touch sage_germline/${meta.normal_id}.sage.bqr.tsv - touch sage_germline/${meta.normal_id}.gene.coverage.tsv + mkdir -p germline/ + touch germline/${meta.tumor_id}.sage.germline.vcf.gz + touch germline/${meta.tumor_id}.sage.germline.vcf.gz.tbi + touch germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz + touch germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz.tbi + touch germline/${meta.tumor_id}.sage.bqr.png + touch germline/${meta.tumor_id}.sage.bqr.tsv + touch germline/${meta.normal_id}.sage.bqr.png + touch germline/${meta.normal_id}.sage.bqr.tsv + touch germline/${meta.normal_id}.gene.coverage.tsv echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 8bd61130..da8edbab 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -19,10 +19,10 @@ process SAGE_SOMATIC { path ensembl_data_resources output: - tuple val(meta), path('sage_somatic/*.sage.somatic.vcf.gz'), path('sage_somatic/*.sage.somatic.vcf.gz.tbi') , emit: vcf - tuple val(meta), path('sage_somatic/*.sage.somatic.filtered.vcf.gz'), path('sage_somatic/*.sage.somatic.filtered.vcf.gz.tbi'), emit: vcf_filtered - tuple val(meta), path('sage_somatic/') , emit: sage_dir - path 'versions.yml' , emit: versions + tuple val(meta), path('somatic/*.sage.somatic.vcf.gz'), path('somatic/*.sage.somatic.vcf.gz.tbi') , emit: vcf + tuple val(meta), path('somatic/*.sage.somatic.filtered.vcf.gz'), path('somatic/*.sage.somatic.filtered.vcf.gz.tbi'), emit: vcf_filtered + tuple val(meta), path('somatic/') , emit: sage_dir + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -34,7 +34,7 @@ process SAGE_SOMATIC { def reference_bam_arg = normal_bam ? "-reference_bam ${normal_bam}" : '' """ - mkdir -p sage_somatic/ + mkdir -p somatic/ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ @@ -54,14 +54,14 @@ process SAGE_SOMATIC { -write_bqr_data \\ -write_bqr_plot \\ -threads ${task.cpus} \\ - -out sage_somatic/${meta.tumor_id}.sage.somatic.vcf.gz + -out somatic/${meta.tumor_id}.sage.somatic.vcf.gz bcftools view \\ -f 'PASS' \\ - -o sage_somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz \\ - sage_somatic/${meta.tumor_id}.sage.somatic.vcf.gz + -o somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz \\ + somatic/${meta.tumor_id}.sage.somatic.vcf.gz - bcftools index -t sage_somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz + bcftools index -t somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml @@ -72,16 +72,16 @@ process SAGE_SOMATIC { stub: """ - mkdir -p sage_somatic/ - touch sage_somatic/${meta.tumor_id}.sage.somatic.vcf.gz - touch sage_somatic/${meta.tumor_id}.sage.somatic.vcf.gz.tbi - touch sage_somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz - touch sage_somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz.tbi - touch sage_somatic/${meta.tumor_id}.gene.coverage.tsv - touch sage_somatic/${meta.tumor_id}.sage.bqr.png - touch sage_somatic/${meta.tumor_id}.sage.bqr.tsv - touch sage_somatic/${meta.normal_id}.sage.bqr.png - touch sage_somatic/${meta.normal_id}.sage.bqr.tsv + mkdir -p somatic/ + touch somatic/${meta.tumor_id}.sage.somatic.vcf.gz + touch somatic/${meta.tumor_id}.sage.somatic.vcf.gz.tbi + touch somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz + touch somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz.tbi + touch somatic/${meta.tumor_id}.gene.coverage.tsv + touch somatic/${meta.tumor_id}.sage.bqr.png + touch somatic/${meta.tumor_id}.sage.bqr.tsv + touch somatic/${meta.normal_id}.sage.bqr.png + touch somatic/${meta.normal_id}.sage.bqr.tsv echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index 50bce74a..da00c12c 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -36,7 +36,7 @@ workflow CUPPA_PREDICTION { ch_cuppa_inputs_isofox, run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional'), run_config.stages.linx ? ch_linx : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR, type: 'optional'), - run_config.stages.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), + run_config.stages.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_DIR, type: 'optional'), flatten_mode: 'nonrecursive', ) diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 97acaed5..1b237e3e 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -139,7 +139,7 @@ workflow ORANGE_REPORTING { run_config.stages.linx ? ch_linx_somatic_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), run_config.stages.linx ? ch_linx_somatic_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_TUMOR), run_config.stages.linx ? ch_linx_germline_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_NORMAL, type: 'optional'), - run_config.stages.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_TSV, type: 'optional'), + run_config.stages.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_DIR, type: 'optional'), run_config.stages.chord ? ch_chord : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_DIR, type: 'optional'), run_config.stages.sigs ? ch_sigs : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SIGS_DIR, type: 'optional'), run_config.stages.lilac ? ch_lilac : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), From 7a466bff61b3bb80ff4b5e0766273f42bcddcbc6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 8 Aug 2023 22:41:02 +1000 Subject: [PATCH 203/562] Use correct PURPLE input source for LILAC --- subworkflows/local/lilac_calling.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index e233104d..ef84005e 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -212,7 +212,7 @@ workflow LILAC_CALLING { // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, purple_dir ] ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( ch_lilac_bams_combined, - ch_purple, + ch_lilac_inputs_purple, flatten_mode: 'nonrecursive', ) From 1fd41f53bbe1def2382219dde355864e7313256c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 21 Aug 2023 11:02:56 +1000 Subject: [PATCH 204/562] =?UTF-8?q?Bump=20ORANGE=20version:=202.6.0=20?= =?UTF-8?q?=E2=86=92=202.7.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/orange/Dockerfile | 2 +- modules/local/orange/main.nf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/orange/Dockerfile b/modules/local/orange/Dockerfile index 5c479eef..9ab9e442 100644 --- a/modules/local/orange/Dockerfile +++ b/modules/local/orange/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/orange/ && \ - wget -O /opt/orange/orange.jar 'https://github.com/hartwigmedical/hmftools/releases/download/orange-v2.6.0/orange_v2.6.0.jar' + wget -O /opt/orange/orange.jar 'https://github.com/hartwigmedical/hmftools/releases/download/orange-v2.7.0/orange_v2.7.0.jar' USER mambauser diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index edf650e3..8fa81974 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -2,7 +2,7 @@ process ORANGE { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/orange:2.6.0--0' + container 'docker.io/scwatts/orange:2.7.0--0' input: tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_dir), path(sage_germline_dir), path(purple_dir), path(smlv_somatic_vcf), path(smlv_germline_vcf), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter_dir), path(chord_dir), path(sigs_dir), path(lilac_dir), path(cuppa_dir), path(isofox_dir) @@ -122,7 +122,7 @@ process ORANGE { cat <<-END_VERSIONS > versions.yml "${task.process}": - orange: \$(java -jar ${task.ext.jarPath} | head -n1 | sed 's/.*ORANGE v//') + orange: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.*version //') END_VERSIONS """ From 465ad5c77eba78cc14a714d1d159ddbcfd234578 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 5 Sep 2023 17:45:36 +1000 Subject: [PATCH 205/562] Add bumpversion config --- .bumpversion.cfg | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .bumpversion.cfg diff --git a/.bumpversion.cfg b/.bumpversion.cfg new file mode 100644 index 00000000..6583cb43 --- /dev/null +++ b/.bumpversion.cfg @@ -0,0 +1,9 @@ +[bumpversion] +current_version = 0.0.1 +commit = True +tag = False +parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) + +[bumpversion:file:nextflow.config] +search = version = '{current_version}' +replace = version = '{new_version}' From 6c96a8d23bff3ddb93132d3d201ff1c781290031 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 5 Sep 2023 17:45:54 +1000 Subject: [PATCH 206/562] =?UTF-8?q?Bump=20version:=200.0.1=20=E2=86=92=200?= =?UTF-8?q?.1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 6583cb43..69136964 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.0.1 +current_version = 0.1.0 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index a46ddce6..81b0d4a5 100644 --- a/nextflow.config +++ b/nextflow.config @@ -205,7 +205,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.0.1' + version = '0.1.0' doi = '' } From 66803ca3cc870311bf985ca9deacbaa174afcf00 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 6 Sep 2023 09:45:54 +1000 Subject: [PATCH 207/562] =?UTF-8?q?Bump=20PURPLE=20version:=203.9=20?= =?UTF-8?q?=E2=86=92=203.9.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/purple/Dockerfile | 2 +- modules/local/purple/main.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/purple/Dockerfile b/modules/local/purple/Dockerfile index b91ba054..54c6eba0 100644 --- a/modules/local/purple/Dockerfile +++ b/modules/local/purple/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/purple/ && \ - wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.9/purple_v3.9.jar' + wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.9.2/purple_v3.9.2.jar' USER mambauser diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 5c00c0ff..8f17ca12 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -2,7 +2,7 @@ process PURPLE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/purple:3.9--0' + container 'docker.io/scwatts/purple:3.9.2--0' input: tuple val(meta), path(amber), path(cobalt), path(sv_tumor_vcf), path(sv_tumor_tbi), path(sv_tumor_unfiltered_vcf), path(sv_tumor_unfiltered_tbi), path(sv_normal_vcf), path(sv_normal_tbi), path(smlv_tumor_vcf), path(smlv_normal_vcf) From 721a2bda41ca36dd386f61ecf913c53b4a767089 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 6 Sep 2023 16:42:55 +1000 Subject: [PATCH 208/562] Use default memory allocation for samtools sort --- modules/local/svprep/svprep/main.nf | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index be3a3964..e1cdbafe 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -43,7 +43,6 @@ process SVPREP { samtools sort \\ -@ ${task.cpus} \\ - -m ${Math.round(task.memory.bytes * 0.95 / 1024 / task.cpus)}K \\ -T ${meta.id}.sv_prep.tmp \\ -o ${meta.id}.sv_prep.sorted.bam \\ ${meta.id}.sv_prep.bam From 273a3d8b7adecf28b1846e991ba1de5909ab40e9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 8 Sep 2023 12:53:17 +1000 Subject: [PATCH 209/562] =?UTF-8?q?Bump=20SvPrep=20version:=201.2.1=20?= =?UTF-8?q?=E2=86=92=201.2.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/svprep/Dockerfile | 4 ++-- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/depth_annotator/main.nf | 2 +- modules/local/svprep/preprocess/main.nf | 2 +- modules/local/svprep/svprep/main.nf | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile index dd653602..1b7d1712 100644 --- a/modules/local/svprep/Dockerfile +++ b/modules/local/svprep/Dockerfile @@ -11,8 +11,8 @@ RUN \ RUN \ mkdir -p /opt/svprep/ && \ - wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.2.1/sv-prep_v1.2.1.jar' && \ - wget -O /opt/svprep/gridss_svprep 'https://raw.githubusercontent.com/hartwigmedical/hmftools/sv-prep-v1.2.1/sv-prep/src/main/resources/gridss/gridss.run.sh' + wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.2.2/sv-prep_v1.2.2.jar' && \ + wget -O /opt/svprep/gridss_svprep 'https://raw.githubusercontent.com/hartwigmedical/hmftools/sv-prep-v1.2.2/sv-prep/src/main/resources/gridss/gridss.run.sh' COPY assets/gridss_svprep.patch /tmp/ RUN \ diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 0385f96b..2b8ee2a0 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -2,7 +2,7 @@ process GRIDSS_ASSEMBLE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.1--0' + container 'docker.io/scwatts/svprep:1.2.2--0' input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 2bf235e3..e2327e71 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -2,7 +2,7 @@ process GRIDSS_CALL { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.1--0' + container 'docker.io/scwatts/svprep:1.2.2--0' input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index de20bf4d..b1a9a1fe 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -2,7 +2,7 @@ process SVPREP_DEPTH_ANNOTATOR { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.1--0' + container 'docker.io/scwatts/svprep:1.2.2--0' input: tuple val(meta), path(bams), path(bais), path(vcf), val(labels) diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index eb14ca39..56da3f77 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -2,7 +2,7 @@ process GRIDSS_PREPROCESS { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.1--0' + container 'docker.io/scwatts/svprep:1.2.2--0' input: tuple val(meta), path(bam), path(bam_filtered) diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index e1cdbafe..3a06ed10 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -2,7 +2,7 @@ process SVPREP { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.1--0' + container 'docker.io/scwatts/svprep:1.2.2--0' input: tuple val(meta), path(bam), path(bai), path(junctions) From 8bbbddb32df38b8412e897a21ad80c6c19869070 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 8 Sep 2023 14:04:26 +1000 Subject: [PATCH 210/562] =?UTF-8?q?Bump=20version:=200.1.0=20=E2=86=92=200?= =?UTF-8?q?.1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 69136964..021d14d2 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.0 +current_version = 0.1.1 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index 81b0d4a5..7f10fa9e 100644 --- a/nextflow.config +++ b/nextflow.config @@ -205,7 +205,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.1.0' + version = '0.1.1' doi = '' } From efec04ed4ef38935725eeb88c476d929728827ea Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Sep 2023 15:01:59 +1000 Subject: [PATCH 211/562] =?UTF-8?q?Bump=20SAGE=20version:=203.3=20?= =?UTF-8?q?=E2=86=92=203.3.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/sage/Dockerfile | 2 +- modules/local/sage/append/main.nf | 2 +- modules/local/sage/germline/main.nf | 2 +- modules/local/sage/somatic/main.nf | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/sage/Dockerfile b/modules/local/sage/Dockerfile index 217d7573..12cb9430 100644 --- a/modules/local/sage/Dockerfile +++ b/modules/local/sage/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/sage/ && \ - wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.3/sage_v3.3.jar' + wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.3.1/sage_v3.3.1.jar' USER mambauser diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index c7f65dd2..8e6b846e 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -2,7 +2,7 @@ process SAGE_APPEND { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.3--0' + container 'docker.io/scwatts/sage:3.3.1--0' input: tuple val(meta), path(vcf), path(bam), path(bai) diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index f35917ec..3fefb129 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -10,7 +10,7 @@ process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.3--0' + container 'docker.io/scwatts/sage:3.3.1--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index da8edbab..2ae53af1 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -4,7 +4,7 @@ process SAGE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.3--0' + container 'docker.io/scwatts/sage:3.3.1--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) From 8b2165dd5547d85b1986b04ff5380758f8a62f8a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Sep 2023 15:02:12 +1000 Subject: [PATCH 212/562] =?UTF-8?q?Bump=20version:=200.1.1=20=E2=86=92=200?= =?UTF-8?q?.1.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 021d14d2..c480cf87 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.1 +current_version = 0.1.2 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index 7f10fa9e..e3370082 100644 --- a/nextflow.config +++ b/nextflow.config @@ -205,7 +205,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.1.1' + version = '0.1.2' doi = '' } From bbc1b8d8ff91f3894eb7407f48b6969a2de03396 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 20 Sep 2023 13:40:01 +1000 Subject: [PATCH 213/562] Update process stubs --- modules/local/amber/main.nf | 1 + modules/local/bamtools/main.nf | 2 +- modules/local/cobalt/main.nf | 1 + modules/local/isofox/main.nf | 1 + modules/local/lilac/main.nf | 1 + modules/local/linx/germline/main.nf | 1 + modules/local/linx/somatic/main.nf | 1 + modules/local/linx/visualiser/main.nf | 1 + modules/local/sigs/main.nf | 3 ++- modules/local/svprep/assemble/main.nf | 1 + modules/local/svprep/preprocess/main.nf | 1 + 11 files changed, 12 insertions(+), 2 deletions(-) diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index 2369c7d8..07d3a0f8 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -46,6 +46,7 @@ process AMBER { stub: """ mkdir -p amber/ + touch amber/placeholder echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf index a7136400..dab6341d 100644 --- a/modules/local/bamtools/main.nf +++ b/modules/local/bamtools/main.nf @@ -41,7 +41,7 @@ process BAMTOOLS { stub: """ - mkdir -p ${meta.id}.wgsmetrics + touch ${meta.id}.wgsmetrics echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index ff73d681..52fa6bda 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -51,6 +51,7 @@ process COBALT { stub: """ mkdir -p cobalt/ + touch cobalt/placeholder echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index d9de66fe..7d246a49 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -54,6 +54,7 @@ process ISOFOX { stub: """ mkdir -p isofox/ + touch isofox/placeholder echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index c5e81a90..a35eec4d 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -53,6 +53,7 @@ process LILAC { stub: """ mkdir -p lilac/ + touch lilac/placeholder echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 3a7c632b..6a9db783 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -42,6 +42,7 @@ process LINX_GERMLINE { stub: """ mkdir linx_germline/ + touch linx_germline/placeholder echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 52944730..d65a7861 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -48,6 +48,7 @@ process LINX_SOMATIC { stub: """ mkdir linx_somatic/ + touch linx_somatic/placeholder echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 5c2cbf07..89a502c7 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -47,6 +47,7 @@ process LINX_VISUALISER { stub: """ mkdir -p linx_visualiser/plot/ + touch linx_visualiser/plot/placeholder echo -e '${task.process}:\n stub: noversions\n' > versions.yml """ } diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 50fea8b3..aa0016f7 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -38,7 +38,8 @@ process SIGS { stub: """ - mkdir sigs/ + mkdir -p sigs/ + touch sigs/placeholder echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 2b8ee2a0..2048e28c 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -91,6 +91,7 @@ process GRIDSS_ASSEMBLE { stub: """ mkdir -p gridss_assemble/ + touch gridss_assemble/placeholder echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 56da3f77..8c29411e 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -54,6 +54,7 @@ process GRIDSS_PREPROCESS { stub: """ mkdir -p gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/ + touch gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/placeholder echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } From 33edb015791db037adf0b863fd3cda537642d569 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 28 Sep 2023 14:42:29 +1000 Subject: [PATCH 214/562] =?UTF-8?q?Bump=20LILAC=20version:=201.5=20?= =?UTF-8?q?=E2=86=92=201.5.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/lilac/Dockerfile | 2 +- modules/local/lilac/main.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/lilac/Dockerfile b/modules/local/lilac/Dockerfile index d7ad496a..cc6df91c 100644 --- a/modules/local/lilac/Dockerfile +++ b/modules/local/lilac/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/lilac/ && \ - wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.5/lilac_v1.5.jar' + wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.5.1/lilac_v1.5.1.jar' USER mambauser diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index a35eec4d..96dbf54f 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -2,7 +2,7 @@ process LILAC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/lilac:1.5--0' + container 'docker.io/scwatts/lilac:1.5.1--0' input: tuple val(meta), path(normal_wgs_bam), path(normal_wgs_bai), path(tumor_bam), path(tumor_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(purple_dir) From a175bc905b299af4269c35205fccade7fa98701d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 28 Sep 2023 14:44:00 +1000 Subject: [PATCH 215/562] Correct HMF pipeline version for ORANGE --- subworkflows/local/orange_reporting.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 1b237e3e..6c5e4f71 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -185,7 +185,7 @@ workflow ORANGE_REPORTING { ensembl_data_resources, isofox_alt_sj, isofox_gene_distribution, - "5.32 [oncoanalyser]", + "5.33 [oncoanalyser]", ) // Set outputs From ef4cf5257c4ad5abc1162f152c54e2e0dbe28866 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 28 Sep 2023 14:42:42 +1000 Subject: [PATCH 216/562] =?UTF-8?q?Bump=20version:=200.1.2=20=E2=86=92=200?= =?UTF-8?q?.1.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index c480cf87..835e38f8 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.2 +current_version = 0.1.3 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index e3370082..006f0dff 100644 --- a/nextflow.config +++ b/nextflow.config @@ -205,7 +205,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.1.2' + version = '0.1.3' doi = '' } From 323162a0bb585b84cbed185189313beca7225ac8 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 2 Oct 2023 16:25:18 +1100 Subject: [PATCH 217/562] First pass renaming DNA and RNA data types --- lib/Constants.groovy | 69 ++++++++++----------- lib/Utils.groovy | 52 ++++------------ lib/WorkflowMain.groovy | 12 ++-- modules/local/cuppa/main.nf | 4 +- modules/local/lilac/main.nf | 14 ++--- modules/local/lilac/meta.yml | 12 ++-- modules/local/orange/main.nf | 6 +- modules/local/sage/append/main.nf | 6 +- nextflow.config | 1 + nextflow_schema.json | 5 ++ subworkflows/local/amber_profiling.nf | 10 +-- subworkflows/local/bamtools_metrics.nf | 8 +-- subworkflows/local/chord_prediction.nf | 2 +- subworkflows/local/cobalt_profiling.nf | 8 +-- subworkflows/local/cuppa_prediction.nf | 17 +++-- subworkflows/local/flagstat_metrics.nf | 8 +-- subworkflows/local/gridss_svprep_calling.nf | 18 +++--- subworkflows/local/gripss_filtering.nf | 4 +- subworkflows/local/isofox_quantification.nf | 6 +- subworkflows/local/lilac_calling.nf | 59 +++++++----------- subworkflows/local/linx_annotation.nf | 4 +- subworkflows/local/linx_plotting.nf | 6 +- subworkflows/local/orange_reporting.nf | 16 ++--- subworkflows/local/pave_annotation.nf | 4 +- subworkflows/local/prepare_input.nf | 64 +++++++++++++------ subworkflows/local/purple_calling.nf | 4 +- subworkflows/local/sage_append.nf | 22 +++---- subworkflows/local/sage_calling.nf | 8 +-- subworkflows/local/sigs_fitting.nf | 2 +- subworkflows/local/virusbreakend_calling.nf | 4 +- 30 files changed, 224 insertions(+), 231 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index b06a8db4..7f6987a3 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -31,10 +31,9 @@ class Constants { } static enum RunMode { - PANEL, - WGS, - WGTS, - WTS, + DNA, + RNA, + DNA_RNA, } static enum Process { @@ -60,6 +59,7 @@ class Constants { static enum FileType { // Generic BAM, + BAI, // Process AMBER_DIR, BAMTOOLS, @@ -90,10 +90,9 @@ class Constants { } static enum SequenceType { - TARGETTED, - WGS, - WGTS, - WTS, + DNA, + RNA, + DNA_RNA, } static Map PLACEHOLDER_META = [meta_placeholder: null] @@ -104,149 +103,149 @@ class Constants { ISOFOX_DIR: [ FileType.ISOFOX_DIR, SampleType.TUMOR, - SequenceType.WTS + SequenceType.RNA, ], AMBER_DIR: [ FileType.AMBER_DIR, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - [SequenceType.TARGETTED, SequenceType.WGS] + SequenceType.DNA, ], COBALT_DIR: [ FileType.COBALT_DIR, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - [SequenceType.TARGETTED, SequenceType.WGS] + SequenceType.DNA, ], BAMTOOLS_TUMOR: [ FileType.BAMTOOLS, SampleType.TUMOR, - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], BAMTOOLS_NORMAL: [ FileType.BAMTOOLS, SampleType.NORMAL, - SequenceType.WGS, + SequenceType.DNA, ], FLAGSTAT_TUMOR: [ FileType.FLAGSTAT, SampleType.TUMOR, - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], FLAGSTAT_NORMAL: [ FileType.FLAGSTAT, SampleType.NORMAL, - SequenceType.WGS + SequenceType.DNA, ], SAGE_VCF_TUMOR: [ FileType.SAGE_VCF, SampleType.TUMOR, - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], SAGE_VCF_NORMAL: [ FileType.SAGE_VCF, SampleType.NORMAL, - SequenceType.WGS + SequenceType.DNA, ], SAGE_DIR_TUMOR: [ FileType.SAGE_DIR, SampleType.TUMOR, - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], SAGE_DIR_NORMAL: [ FileType.SAGE_DIR, SampleType.NORMAL, - SequenceType.WGS + SequenceType.DNA, ], PAVE_VCF_TUMOR: [ FileType.PAVE_VCF, SampleType.TUMOR, - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], PAVE_VCF_NORMAL: [ FileType.PAVE_VCF, SampleType.NORMAL, - SequenceType.WGS + SequenceType.DNA, ], GRIDSS_VCF: [ FileType.GRIDSS_VCF, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], GRIPSS_VCF_TUMOR: [ FileType.GRIPSS_VCF, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], GRIPSS_VCF_NORMAL: [ FileType.GRIPSS_VCF, SampleType.NORMAL, - SequenceType.WGS + SequenceType.DNA, ], GRIPSS_UNFILTERED_VCF_TUMOR: [ FileType.GRIPSS_UNFILTERED_VCF, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], GRIPSS_UNFILTERED_VCF_NORMAL: [ FileType.GRIPSS_UNFILTERED_VCF, SampleType.NORMAL, - SequenceType.WGS + SequenceType.DNA, ], PURPLE_DIR: [ FileType.PURPLE_DIR, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], LINX_PLOT_DIR_TUMOR: [ FileType.LINX_PLOT_DIR, SampleType.TUMOR, - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], LINX_ANNO_DIR_TUMOR: [ FileType.LINX_ANNO_DIR, SampleType.TUMOR, - [SequenceType.TARGETTED, SequenceType.WGS], + SequenceType.DNA, ], LINX_ANNO_DIR_NORMAL: [ FileType.LINX_ANNO_DIR, SampleType.NORMAL, - SequenceType.WGS + SequenceType.DNA, ], CHORD_DIR: [ FileType.CHORD_DIR, SampleType.TUMOR, - SequenceType.WGS + SequenceType.DNA, ], SIGS_DIR: [ FileType.SIGS_DIR, SampleType.TUMOR, - SequenceType.WGS + SequenceType.DNA, ], LILAC_DIR: [ FileType.LILAC_DIR, [SampleType.TUMOR, SampleType.NORMAL, SampleType.TUMOR_NORMAL], - [SequenceType.TARGETTED, SequenceType.WGS, SequenceType.WGTS], + [SequenceType.DNA, SequenceType.DNA_RNA], ], VIRUSINTERPRETER_DIR: [ FileType.VIRUSINTERPRETER_DIR, SampleType.TUMOR, - SequenceType.WGS + SequenceType.DNA, ], CUPPA_DIR: [ FileType.CUPPA_DIR, SampleType.TUMOR, - [SequenceType.WGS, SequenceType.WTS, SequenceType.WGTS], + [SequenceType.DNA, SequenceType.RNA, SequenceType.DNA_RNA], ], ] diff --git a/lib/Utils.groovy b/lib/Utils.groovy index d6a05377..f764cd96 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -69,58 +69,30 @@ class Utils { // Sample names - static public getTumorSampleName(meta, run_mode) { - - // NOTE(SW): this should /only/ be used to get panel or WGS tumor sample name, WTS sample name retrieval is not supported - - def sequence_type - if (run_mode == Constants.RunMode.PANEL) { - sequence_type = Constants.SequenceType.TARGETTED - } else if (run_mode == Constants.RunMode.WGS || run_mode == Constants.RunMode.WGTS) { - sequence_type = Constants.SequenceType.WGS - } - - return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, sequence_type]) - } - - static public getTumorWgsSampleName(meta) { - return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) + static public getTumorDnaSampleName(meta) { + return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.DNA]) } - static public getTumorWtsSampleName(meta) { - return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + static public getTumorRnaSampleName(meta) { + return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) } - static public getNormalWgsSampleName(meta) { - return getMetaEntry(meta, ['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.WGS]) + static public getNormalDnaSampleName(meta) { + return getMetaEntry(meta, ['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.DNA]) } // Files - static public getTumorBam(meta, run_mode) { - - // NOTE(SW): this should /only/ be used to get panel or WGS tumor BAM, WTS BAM retrieval is not supported - - def sequence_type - if (run_mode == Constants.RunMode.PANEL) { - sequence_type = Constants.SequenceType.TARGETTED - } else if (run_mode == Constants.RunMode.WGS || run_mode == Constants.RunMode.WGTS) { - sequence_type = Constants.SequenceType.WGS - } - - return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, sequence_type]) - } - - static public getTumorWgsBam(meta) { - return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) + static public getTumorDnaBam(meta) { + return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.DNA]) } - static public getNormalWgsBam(meta) { - return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.WGS]) + static public getTumorRnaBam(meta) { + return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) } - static public getTumorWtsBam(meta) { - return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + static public getNormalDnaBam(meta) { + return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.DNA]) } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 35d69db3..c3c67965 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -140,13 +140,13 @@ class WorkflowMain { return } - if (run_mode == Constants.RunMode.WTS) { + if (run_mode == Constants.RunMode.RNA) { if (!params.containsKey('run_type')) { params.run_type = 'tumor_only' } } - if (run_mode == Constants.RunMode.PANEL) { + if (params.targeted === true) { if (!params.containsKey('run_type')) { params.run_type = 'tumor_only' @@ -285,7 +285,7 @@ class WorkflowMain { def run_mode = Utils.getRunMode(params.run_mode, log) def run_type = Utils.getRunType(params.run_type, log) - if (run_mode == Constants.RunMode.WTS) { + if (run_mode == Constants.RunMode.RNA) { if (run_type != Constants.RunType.TUMOR_ONLY) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " The WTS run mode does not support tumor/normal data, please adjust the CLI \n" + @@ -296,7 +296,7 @@ class WorkflowMain { } - if (run_mode == Constants.RunMode.PANEL) { + if (params.targeted === true) { if (run_type != Constants.RunType.TUMOR_ONLY) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + @@ -307,6 +307,7 @@ class WorkflowMain { } if (!params.containsKey('panel')) { + def panels = Constants.PANELS_DEFINED.join('\n - ') log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " A panel is required to be set using the --panel CLI argument or in a \n" + @@ -315,13 +316,16 @@ class WorkflowMain { " - ${panels}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) + } else if (!Constants.PANELS_DEFINED.contains(params.panel)) { + def panels = Constants.PANELS_DEFINED.join('\n - ') log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " The ${params.panel} is not defined. Currently, the available panels are:\n" + " - ${panels}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) + } if (params.panel == 'hmf' && params.ref_data_genome_version == '37') { diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index 098340dd..5a7d55a2 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -48,11 +48,11 @@ process CUPPA { elif [[ ${categories_val} == 'ALL' ]]; then # NOTE(SW): CUPPA requires that the WTS sample name matches the WGS sample name for fp in \$(find -L ${isofox_dir} -maxdepth 1 -type f); do - fn_out=\$(sed 's/^${meta.id_wts}/${meta.id}/' <<< \${fp##*/}); + fn_out=\$(sed 's/^${meta.id_rna}/${meta.id}/' <<< \${fp##*/}); cp \${fp} sample_data/\${fn_out} done; # Rename identifier in the summary file - sed -i 's/^${meta.id_wts}/${meta.id}/g' sample_data/${meta.id}.isf.summary.csv; + sed -i 's/^${meta.id_rna}/${meta.id}/g' sample_data/${meta.id}.isf.summary.csv; fi; mkdir -p cuppa/ diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 96dbf54f..b9bb66e2 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -5,7 +5,7 @@ process LILAC { container 'docker.io/scwatts/lilac:1.5.1--0' input: - tuple val(meta), path(normal_wgs_bam), path(normal_wgs_bai), path(tumor_bam), path(tumor_bai), path(tumor_wts_bam), path(tumor_wts_bai), path(purple_dir) + tuple val(meta), path(normal_dna_bam), path(normal_dna_bai), path(tumor_dna_bam), path(tumor_dna_bai), path(tumor_rna_bam), path(tumor_rna_bai), path(purple_dir) path genome_fasta val genome_ver path lilac_resources, stageAs: 'lilac_resources' @@ -19,11 +19,11 @@ process LILAC { script: def args = task.ext.args ?: '' - def sample_name = getSampleName(meta, tumor_bam, normal_wgs_bam) + def sample_name = getSampleName(meta, tumor_dna_bam, normal_dna_bam) - def normal_bam_arg = normal_wgs_bam ? "-reference_bam ${normal_wgs_bam}" : '' - def tumor_bam_arg = tumor_bam ? "-tumor_bam ${tumor_bam}" : '' - def tumor_wts_bam_arg = tumor_wts_bam ? "-rna_bam ${tumor_wts_bam}" : '' + def normal_bam_arg = normal_dna_bam ? "-reference_bam ${normal_dna_bam}" : '' + def tumor_dna_bam_arg = tumor_dna_bam ? "-tumor_dna_bam ${tumor_dna_bam}" : '' + def tumor_rna_bam_arg = tumor_rna_bam ? "-rna_bam ${tumor_rna_bam}" : '' def purple_dir_arg = purple_dir ? "-purple_dir ${purple_dir}" : '' @@ -34,8 +34,8 @@ process LILAC { ${args} \\ -sample ${sample_name} \\ ${normal_bam_arg} \\ - ${tumor_bam_arg} \\ - ${tumor_wts_bam_arg} \\ + ${tumor_dna_bam_arg} \\ + ${tumor_rna_bam_arg} \\ ${purple_dir_arg} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ diff --git a/modules/local/lilac/meta.yml b/modules/local/lilac/meta.yml index 29a64c1f..323cfb94 100644 --- a/modules/local/lilac/meta.yml +++ b/modules/local/lilac/meta.yml @@ -16,27 +16,27 @@ input: description: | Groovy Map containing sample information e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - - normal_wgs_bam: + - normal_dna_bam: type: file description: Normal WGS BAM file (optional) pattern: "*.{bam}" - - normal_wgs_bai: + - normal_dna_bai: type: file description: Normal WGS BAI file (optional) pattern: "*.{bai}" - - tumor_wgs_bam: + - tumor_dna_bam: type: file description: Normal WGS BAM file (optional) pattern: "*.{bam}" - - tumor_wgs_bai: + - tumor_dna_bai: type: file description: Tumor WGS BAI file (optional) pattern: "*.{bai}" - - tumor_wts_bam: + - tumor_rna_bam: type: file description: Normal WTS BAM file (optional) pattern: "*.{bam}" - - tumor_wts_bai: + - tumor_rna_bai: type: file description: Tumor WTS BAI file (optional) pattern: "*.{bai}" diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 8fa81974..aebf0add 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -34,13 +34,13 @@ process ORANGE { def sigs_dir_arg = sigs_dir ? "-sigs_dir ${sigs_dir}" : '' def cuppa_dir_arg = cuppa_dir ? "-cuppa_dir ${cuppa_dir}" : '' - def normal_id_arg = meta.containsKey('normal_wgs_id') ? "-reference_sample_id ${meta.normal_wgs_id}" : '' + def normal_id_arg = meta.containsKey('normal_dna_id') ? "-reference_sample_id ${meta.normal_dna_id}" : '' def normal_metrics_arg = bam_metrics_germline ? "-ref_sample_wgs_metrics_file ${bam_metrics_germline}" : '' def normal_flagstat_arg = flagstat_germline ? "-ref_sample_flagstat_file ${flagstat_germline}" : '' def normal_sage_dir = sage_germline_dir ? "-sage_germline_dir ${sage_germline_dir}" : '' def normal_linx_arg = linx_germline_anno_dir ? "-linx_germline_dir ${linx_germline_anno_dir}" : '' - def rna_id_arg = meta.containsKey('tumor_wts_id') ? "-rna_sample_id ${meta.tumor_wts_id}" : '' + def rna_id_arg = meta.containsKey('tumor_rna_id') ? "-rna_sample_id ${meta.tumor_rna_id}" : '' def isofox_dir_arg = isofox_dir ? '-isofox_dir isofox_dir__prepared/' : '' def isofox_gene_distribution_arg = isofox_gene_distribution ? "-isofox_gene_distribution ${isofox_gene_distribution}" : '' @@ -64,7 +64,7 @@ process ORANGE { mkdir -p isofox_dir__prepared/; for fp in ${isofox_dir}/*; do - ln -s ../\${fp} isofox_dir__prepared/\$(sed 's/${meta.tumor_wts_id}/${meta.tumor_id}/' <<< \${fp##*/}); + ln -s ../\${fp} isofox_dir__prepared/\$(sed 's/${meta.tumor_rna_id}/${meta.tumor_id}/' <<< \${fp##*/}); done; fi diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index 8e6b846e..80962310 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -27,12 +27,12 @@ process SAGE_APPEND { -cp ${task.ext.jarPath} com.hartwig.hmftools.sage.append.SageAppendApplication \\ ${args} \\ -input_vcf ${vcf} \\ - -reference ${meta.tumor_wts_id} \\ + -reference ${meta.tumor_rna_id} \\ -reference_bam ${bam} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -threads ${task.cpus} \\ - -out ${meta.wgs_id}.sage.append.vcf.gz + -out ${meta.dna_id}.sage.append.vcf.gz # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml @@ -43,7 +43,7 @@ process SAGE_APPEND { stub: """ - touch "${meta.wgs_id}.sage.append.vcf.gz" + touch "${meta.dna_id}.sage.append.vcf.gz" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/nextflow.config b/nextflow.config index 006f0dff..21d62ebb 100644 --- a/nextflow.config +++ b/nextflow.config @@ -13,6 +13,7 @@ params { input = null // Pipeline run configuration + targeted = false processes_manual = false processes_include = null processes_exclude = null diff --git a/nextflow_schema.json b/nextflow_schema.json index 8510fdcc..d13c6b42 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -61,6 +61,11 @@ "description": "Skip check for restricted genome.", "fa_icon": "fas fa-palette" }, + "targeted": { + "type": "boolean", + "description": "Run in targeted mode.", + "fa_icon": "fas fa-diagram-project" + }, "processes_manual": { "type": "boolean", "description": "Run only processes manually provided in processes_include.", diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index 245553d0..8f2f77f1 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -30,20 +30,20 @@ workflow AMBER_PROFILING { def meta_amber = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorSampleName(meta, run_config.mode), + tumor_id: Utils.getTumorDnaSampleName(meta), ] - def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + def tumor_bam = Utils.getTumorDnaBam(meta) def normal_bam = [] def normal_bai = [] if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - assert [Constants.RunMode.WGS, Constants.RunMode.WGTS].contains(run_config.mode) + assert [Constants.RunMode.DNA, Constants.RunMode.DNA_RNA].contains(run_config.mode) - meta_amber.normal_id = Utils.getNormalWgsSampleName(meta) - normal_bam = Utils.getNormalWgsBam(meta) + meta_amber.normal_id = Utils.getNormalDnaSampleName(meta) + normal_bam = Utils.getNormalDnaBam(meta) normal_bai = "${normal_bam}.bai" } diff --git a/subworkflows/local/bamtools_metrics.nf b/subworkflows/local/bamtools_metrics.nf index 6ca8915a..b66786ba 100644 --- a/subworkflows/local/bamtools_metrics.nf +++ b/subworkflows/local/bamtools_metrics.nf @@ -32,21 +32,21 @@ workflow BAMTOOLS_METRICS { def meta_bamtools_tumor = [ key: meta.id, - id: Utils.getTumorSampleName(meta, run_config.mode), + id: Utils.getTumorDnaSampleName(meta), // NOTE(SW): must use string representation for caching purposes sample_type_str: Constants.SampleType.TUMOR.name(), ] - def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + def tumor_bam = Utils.getTumorDnaBam(meta) inputs.add([meta_bamtools_tumor, tumor_bam, "${tumor_bam}.bai"]) if (run_config.type == Constants.RunType.TUMOR_NORMAL) { def meta_bamtools_normal = [ key: meta.id, - id: Utils.getNormalWgsSampleName(meta), + id: Utils.getNormalDnaSampleName(meta), // NOTE(SW): must use string representation for caching purposes sample_type_str: Constants.SampleType.NORMAL.name(), ] - def normal_bam = Utils.getNormalWgsBam(meta) + def normal_bam = Utils.getNormalDnaBam(meta) inputs.add([meta_bamtools_normal, normal_bam, "${normal_bam}.bai"]) } diff --git a/subworkflows/local/chord_prediction.nf b/subworkflows/local/chord_prediction.nf index 7426be7f..dbfa18e8 100644 --- a/subworkflows/local/chord_prediction.nf +++ b/subworkflows/local/chord_prediction.nf @@ -36,7 +36,7 @@ workflow CHORD_PREDICTION { // channel: [ meta, smlv_vcf, sv_vcf ] ch_chord_inputs = ch_chord_inputs_source .map { meta, purple_dir -> - def tumor_id = Utils.getTumorWgsSampleName(meta) + def tumor_id = Utils.getTumorDnaSampleName(meta) def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index 995d5907..2b6434d2 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -31,9 +31,9 @@ workflow COBALT_PROFILING { def meta_cobalt = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorSampleName(meta, run_config.mode), + tumor_id: Utils.getTumorDnaSampleName(meta), ] - def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + def tumor_bam = Utils.getTumorDnaBam(meta) def normal_bam = [] def normal_bai = [] @@ -42,8 +42,8 @@ workflow COBALT_PROFILING { assert [Constants.RunMode.WGS, Constants.RunMode.WGTS].contains(run_config.mode) - meta_cobalt.normal_id = Utils.getNormalWgsSampleName(meta) - normal_bam = Utils.getNormalWgsBam(meta) + meta_cobalt.normal_id = Utils.getNormalDnaSampleName(meta) + normal_bam = Utils.getNormalDnaBam(meta) normal_bai = "${normal_bam}.bai" } diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index da00c12c..68abb32a 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -48,18 +48,15 @@ workflow CUPPA_PREDICTION { def meta_cuppa = [key: meta.id] switch (run_config.mode) { - case Constants.RunMode.WGS: - meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) + case Constants.RunMode.DNA: + meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.DNA]) break - case Constants.RunMode.WTS: - meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + case Constants.RunMode.RNA: + meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) break - case Constants.RunMode.WGTS: - meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WGS]) - meta_cuppa.id_wts = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) - break - case Constants.RunMode.PANEL: - meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.TARGETTED]) + case Constants.RunMode.DNA_RNA: + meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.DNA]) + meta_cuppa.id_rna = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) break default: assert false diff --git a/subworkflows/local/flagstat_metrics.nf b/subworkflows/local/flagstat_metrics.nf index 91cffacf..5ede734d 100644 --- a/subworkflows/local/flagstat_metrics.nf +++ b/subworkflows/local/flagstat_metrics.nf @@ -29,21 +29,21 @@ workflow FLAGSTAT_METRICS { def meta_flagstat_tumor = [ key: meta.id, - id: Utils.getTumorSampleName(meta, run_config.mode), + id: Utils.getTumorDnaSampleName(meta), // NOTE(SW): must use string representation for caching purposes sample_type_str: Constants.SampleType.TUMOR.name(), ] - def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + def tumor_bam = Utils.getTumorDnaBam(meta) inputs.add([meta_flagstat_tumor, tumor_bam, "${tumor_bam}.bai"]) if (run_config.type == Constants.RunType.TUMOR_NORMAL) { def meta_flagstat_normal = [ key: meta.id, - id: Utils.getNormalWgsSampleName(meta), + id: Utils.getNormalDnaSampleName(meta), // NOTE(SW): must use string representation for caching purposes sample_type_str: Constants.SampleType.NORMAL.name(), ] - def normal_bam = Utils.getNormalWgsBam(meta) + def normal_bam = Utils.getNormalDnaBam(meta) inputs.add([meta_flagstat_normal, normal_bam, "${normal_bam}.bai"]) } diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index d272b876..7c51486e 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -47,10 +47,10 @@ workflow GRIDSS_SVPREP_CALLING { .map { meta -> def meta_svprep = [ key: meta.id, - id: Utils.getTumorSampleName(meta, run_config.mode), + id: Utils.getTumorDnaSampleName(meta), sample_type: 'tumor', ] - def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + def tumor_bam = Utils.getTumorDnaBam(meta) return [meta_svprep, tumor_bam, "${tumor_bam}.bai", []] } @@ -89,10 +89,10 @@ workflow GRIDSS_SVPREP_CALLING { .map { meta, junctions_tumor -> def meta_svprep = [ key: meta.id, - id: Utils.getNormalWgsSampleName(meta), + id: Utils.getNormalDnaSampleName(meta), sample_type: 'normal', ] - def normal_bam = Utils.getNormalWgsBam(meta) + def normal_bam = Utils.getNormalDnaBam(meta) return [meta_svprep, normal_bam, "${normal_bam}.bai", junctions_tumor] } @@ -243,10 +243,10 @@ workflow GRIDSS_SVPREP_CALLING { CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, ) .map { id, meta, vcf -> - def tbam = Utils.getTumorBam(meta, run_config.mode) + def tbam = Utils.getTumorDnaBam(meta) def meta_svprep = [ id: meta.id, - tumor_id: Utils.getTumorSampleName(meta, run_config.mode), + tumor_id: Utils.getTumorDnaSampleName(meta) ] def data = [] @@ -257,19 +257,19 @@ workflow GRIDSS_SVPREP_CALLING { tbam, "${tbam}.bai", vcf, - Utils.getTumorSampleName(meta, run_config.mode), + Utils.getTumorDnaSampleName(meta), ] } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - def nbam = Utils.getNormalWgsBam(meta) + def nbam = Utils.getNormalDnaBam(meta) data = [ meta_svprep, [nbam, tbam], ["${nbam}.bai", "${tbam}.bai"], vcf, - [Utils.getNormalWgsSampleName(meta), Utils.getTumorWgsSampleName(meta)], + [Utils.getNormalDnaSampleName(meta), Utils.getTumorDnaSampleName(meta)], ] } else { diff --git a/subworkflows/local/gripss_filtering.nf b/subworkflows/local/gripss_filtering.nf index 6b2c82e9..a10bcc4b 100644 --- a/subworkflows/local/gripss_filtering.nf +++ b/subworkflows/local/gripss_filtering.nf @@ -41,11 +41,11 @@ workflow GRIPSS_FILTERING { def meta_gripss = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorSampleName(meta, run_config.mode), + tumor_id: Utils.getTumorDnaSampleName(meta), ] if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - meta_gripss.normal_id = Utils.getNormalWgsSampleName(meta) + meta_gripss.normal_id = Utils.getNormalDnaSampleName(meta) } return [meta_gripss, gridss_vcf] diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf index 5a061e9f..144c1f53 100644 --- a/subworkflows/local/isofox_quantification.nf +++ b/subworkflows/local/isofox_quantification.nf @@ -30,12 +30,12 @@ workflow ISOFOX_QUANTIFICATION { ch_versions = Channel.empty() // Create inputs and create process-specific meta - // channel: [ meta_isofox, tumor_bam_wts ] + // channel: [ meta_isofox, tumor_bam_rna ] if (run_config.stages.isofox) { ch_isofox_inputs = ch_inputs .map { meta -> - def bam = Utils.getTumorWtsBam(meta) - def meta_isofox = [key: meta.id, id: Utils.getTumorWtsSampleName(meta)] + def bam = Utils.getTumorRnaBam(meta) + def meta_isofox = [key: meta.id, id: Utils.getTumorRnaSampleName(meta)] return [meta_isofox, bam, "${bam}.bai"] } } else { diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index ef84005e..eb31186b 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -40,32 +40,32 @@ workflow LILAC_CALLING { } // Create channels for available input BAMs - // channel: [ meta, wts_bam, wts_bai ] - ch_lilac_bams_wts = Channel.empty() - if (run_config.mode == Constants.RunMode.WTS || run_config.mode == Constants.RunMode.WGTS) { - ch_lilac_bams_wts = ch_inputs + // channel: [ meta, rna_bam, rna_bai ] + ch_lilac_bams_rna = Channel.empty() + if (run_config.mode == Constants.RunMode.RNA || run_config.mode == Constants.RunMode.DNA_RNA) { + ch_lilac_bams_rna = ch_inputs .map { meta -> - def bam = Utils.getTumorWtsBam(meta) + def bam = Utils.getTumorRnaBam(meta) return [meta, bam, "${bam}.bai"] } } else { - ch_lilac_bams_wts = ch_inputs.map { meta -> [meta, [], []] } + ch_lilac_bams_rna = ch_inputs.map { meta -> [meta, [], []] } } // channel: [ meta, bam, bai ] ch_lilac_bams = Channel.empty() - if (run_config.mode == Constants.RunMode.WGS || run_config.mode == Constants.RunMode.WGTS) { + if (run_config.mode == Constants.RunMode.DNA || run_config.mode == Constants.RunMode.DNA_RNA) { ch_lilac_bams = ch_inputs .map { meta -> - def tumor_bam = Utils.getTumorWgsBam(meta) + def tumor_bam = Utils.getTumorDnaBam(meta) def normal_bam = [] def normal_bai = [] if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - normal_bam = Utils.getNormalWgsBam(meta) + normal_bam = Utils.getNormalDnaBam(meta) normal_bai = "${normal_bam}.bai" } @@ -84,19 +84,6 @@ workflow LILAC_CALLING { ch_lilac_bams = ch_inputs.map { meta -> [meta, [], [], [], []] } } - // Set tumor sequence type for non-WTS input (i.e. WGS or panel) - switch(run_config.mode) { - case Constants.RunMode.WGS: - case Constants.RunMode.WGTS: - tumor_sequence_type = Constants.SequenceType.WGS - break - case Constants.RunMode.PANEL: - tumor_sequence_type = Constants.SequenceType.TARGETTED - break - default: - assert false - } - // Realign reads mapping to HLA regions and homologus regions if using reference genome with ALT contigs // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them to the three // relevant HLA genes on chr6. All reads including those previously mapped to chr6 are realigned for @@ -105,7 +92,7 @@ workflow LILAC_CALLING { ch_lilac_bams = ch_lilac_bams if (params.ref_data_genome_type == 'alt') { - // Split non-WTS BAMs into tumor and normal, accounting for optional input + // Split DNA BAMs into tumor and normal, accounting for optional input // channel: [ meta_extra, bam, bai ] ch_slice_bams = ch_lilac_bams .flatMap { meta, tumor_bam, normal_bam, tumor_bai, normal_bai -> @@ -127,9 +114,9 @@ workflow LILAC_CALLING { def sample_name if (meta.sequence_type == 'tumor') { - sample_name = meta[['sample_name', Constants.SampleType.TUMOR, tumor_sequence_type]] + sample_name = meta[['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.DNA]] } else if (meta.sequence_type == 'normal') { - sample_name = meta[['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.WGS]] + sample_name = meta[['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.DNA]] } def meta_slice = [ @@ -195,41 +182,41 @@ workflow LILAC_CALLING { } - // Combine non-WTS and WTS BAMs, and order as required - // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai ] + // Combine DNA and RNA BAMs, and order as required + // channel: [ meta, normal_dna_bam, normal_dna_bai, tumor_bam, tumor_bai, tumor_rna_bam, tumor_rna_bai ] ch_lilac_bams_combined = WorkflowOncoanalyser.groupByMeta( - ch_lilac_bams_wts, + ch_lilac_bams_rna, ch_lilac_bams, flatten_mode: 'nonrecursive', ) .map { data -> def meta = data[0] - def (tbam_wts, tbai_wts, tbam, nbam, tbai, nbai) = data[1..-1] - return [meta, nbam, nbai, tbam, tbai, tbam_wts, tbai_wts] + def (tbam_rna, tbai_rna, tbam, nbam, tbai, nbai) = data[1..-1] + return [meta, nbam, nbai, tbam, tbai, tbam_rna, tbai_rna] } // Add PURPLE inputs - // channel: [ meta, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, purple_dir ] + // channel: [ meta, normal_dna_bam, normal_dna_bai, tumor_bam, tumor_bai, tumor_rna_bam, tumor_rna_bai, purple_dir ] ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( ch_lilac_bams_combined, ch_lilac_inputs_purple, flatten_mode: 'nonrecursive', ) - // Create final input channel for LILAC, remove samples with only WTS BAMs - // channel: [ meta_lilac, normal_wgs_bam, normal_wgs_bai, tumor_bam, tumor_bai, tumor_wts_bam, tumor_wts_bai, purple_dir ] + // Create final input channel for LILAC, remove samples with only RNA BAMs + // channel: [ meta_lilac, normal_dna_bam, normal_dna_bai, tumor_bam, tumor_bai, tumor_rna_bam, tumor_rna_bai, purple_dir ] ch_lilac_inputs = ch_lilac_inputs_full .map { def meta = it[0] def fps = it[1..-1] - // LILAC requires either tumor or normal WGS BAM + // LILAC requires either tumor or normal DNA BAM if (fps[0] == [] && fps[2] == []) { return Constants.PLACEHOLDER_META } - def normal_id_key = ['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.WGS] - def tumor_id_key = ['sample_name', Constants.SampleType.TUMOR, tumor_sequence_type] + def normal_id_key = ['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.DNA] + def tumor_id_key = ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.DNA] def meta_lilac = [ key: meta.id, diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf index 9849d6a1..0196da55 100644 --- a/subworkflows/local/linx_annotation.nf +++ b/subworkflows/local/linx_annotation.nf @@ -45,7 +45,7 @@ workflow LINX_ANNOTATION { ch_linx_inputs_germline = ch_linx_inputs_source .map { meta, purple_dir -> - def tumor_id = Utils.getTumorSampleName(meta, run_config.mode) + def tumor_id = Utils.getTumorDnaSampleName(meta) def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.germline.vcf.gz") if (!sv_vcf.exists()) { @@ -83,7 +83,7 @@ workflow LINX_ANNOTATION { .map { meta, purple_dir -> def meta_linx = [ key: meta.id, - id: Utils.getTumorSampleName(meta, run_config.mode), + id: Utils.getTumorDnaSampleName(meta), ] return [meta_linx, purple_dir] } diff --git a/subworkflows/local/linx_plotting.nf b/subworkflows/local/linx_plotting.nf index 060711b7..b539fce2 100644 --- a/subworkflows/local/linx_plotting.nf +++ b/subworkflows/local/linx_plotting.nf @@ -31,7 +31,7 @@ workflow LINX_PLOTTING { .map { meta, anno_dir -> def meta_linx = [ key: meta.id, - id: Utils.getTumorSampleName(meta, run_config.mode), + id: Utils.getTumorDnaSampleName(meta), ] return [meta_linx, anno_dir] } @@ -56,7 +56,7 @@ workflow LINX_PLOTTING { .map { meta, anno_dir, vis_dir -> def meta_gpgr_linx = [ key: meta.id, - id: Utils.getTumorSampleName(meta, run_config.mode), + id: Utils.getTumorDnaSampleName(meta), ] return [meta_gpgr_linx, anno_dir, vis_dir] } @@ -68,7 +68,7 @@ workflow LINX_PLOTTING { ch_versions = ch_versions.mix(GPGR.out.versions) emit: - visualiser_dir = ch_visualiser_out // channel: [ meta, visualiser_dir] + visualiser_dir = ch_visualiser_out // channel: [ meta, visualiser_dir ] versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 6c5e4f71..a6888947 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -95,7 +95,7 @@ workflow ORANGE_REPORTING { ch_orange_inputs_smlv_vcfs = ch_orange_inputs_purple_dir .map { meta, purple_dir -> - def tumor_id = Utils.getTumorSampleName(meta, run_config.mode) + def tumor_id = Utils.getTumorDnaSampleName(meta) def smlv_somatic_vcf = [] def smlv_germline_vcf = [] @@ -153,21 +153,21 @@ workflow ORANGE_REPORTING { def meta = it[0] // NOTE(SW): these attributes are optional - def normal_wgs_id = meta.getAt(['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.WGS]) - def tumor_wts_id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.WTS]) + def normal_dna_id = meta.getAt(['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.DNA]) + def tumor_rna_id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) def meta_orange = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorSampleName(meta, run_config.mode), + tumor_id: Utils.getTumorDnaSampleName(meta), ] // Add optional identifiers to meta - if (normal_wgs_id) { - meta_orange.normal_wgs_id = normal_wgs_id + if (normal_dna_id) { + meta_orange.normal_dna_id = normal_dna_id } - if (tumor_wts_id) { - meta_orange.tumor_wts_id = tumor_wts_id + if (tumor_rna_id) { + meta_orange.tumor_rna_id = tumor_rna_id } return [meta_orange, *it[1..-1]] diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf index f821f4ef..b43a0918 100644 --- a/subworkflows/local/pave_annotation.nf +++ b/subworkflows/local/pave_annotation.nf @@ -60,7 +60,7 @@ workflow PAVE_ANNOTATION { def pave_meta = [ key: meta.id, // NOTE(SW): use of tumor sample name for PAVE germline is correct - id: Utils.getTumorSampleName(meta, run_config.mode), + id: Utils.getTumorDnaSampleName(meta), ] return [pave_meta, sage_vcf] } @@ -93,7 +93,7 @@ workflow PAVE_ANNOTATION { .map { meta, sage_vcf, sage_tbi -> def pave_meta = [ key: meta.id, - id: Utils.getTumorSampleName(meta, run_config.mode), + id: Utils.getTumorDnaSampleName(meta), ] return [pave_meta, sage_vcf] } diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf index c7847b17..0b8fd4ea 100644 --- a/subworkflows/local/prepare_input.nf +++ b/subworkflows/local/prepare_input.nf @@ -28,18 +28,24 @@ workflow PREPARE_INPUT { assert false } - if (run_config.mode == Constants.RunMode.PANEL) { - sequence_types_allowed = [Constants.SequenceType.TARGETTED] - } else if (run_config.mode == Constants.RunMode.WGS) { - sequence_types_allowed = [Constants.SequenceType.WGS] - } else if (run_config.mode == Constants.RunMode.WTS) { - sequence_types_allowed = [Constants.SequenceType.WTS] - } else if (run_config.mode == Constants.RunMode.WGTS) { - sequence_types_allowed = [Constants.SequenceType.WGS, Constants.SequenceType.WTS] + if (run_config.mode == Constants.RunMode.DNA) { + sequence_types_allowed = [Constants.SequenceType.DNA] + } else if (run_config.mode == Constants.RunMode.RNA) { + sequence_types_allowed = [Constants.SequenceType.RNA] + } else if (run_config.mode == Constants.RunMode.DNA_RNA) { + sequence_types_allowed = [Constants.SequenceType.DNA, Constants.SequenceType.RNA] } else { assert false } + + + + // TODO(SW): ensure that config enforces targeted cannot be RNA only + + + + ch_inputs = Channel.of(ch_samplesheet) .splitCsv(header: true) .map { [it.id, it] } @@ -76,6 +82,13 @@ workflow PREPARE_INPUT { } + + + // TODO(SW): understand whether this does (or why it doesn't) failure on DNA_RNA inputs (e.g. CUPPA) + + + + // Sequence type def sequence_type_enum = Utils.getEnumFromString(it.sequence_type, Constants.SequenceType) if (!sequence_type_enum) { @@ -109,6 +122,14 @@ workflow PREPARE_INPUT { } input_types_seen.push(key_input_type) + + + + // TODO(SW): implement index finding when not provided in samplesheet + + + + // Check for relevant indices if (!workflow.stubRun) { def filetype_bai = [ @@ -138,7 +159,6 @@ workflow PREPARE_INPUT { } } - // Sample name def key_sample_name if (sample_type_enum == Constants.SampleType.TUMOR_NORMAL) { @@ -181,6 +201,10 @@ workflow PREPARE_INPUT { return meta } + + + + /* // Check we have the required sample types for the specified run configuration ch_inputs .map { meta -> @@ -204,12 +228,12 @@ workflow PREPARE_INPUT { if (run_config.type == Constants.RunType.TUMOR_ONLY) { required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.WGS], + [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], ] } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.WGS], - [Constants.SampleType.NORMAL, Constants.SequenceType.WGS], + [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], + [Constants.SampleType.NORMAL, Constants.SequenceType.DNA], ] } else { assert false @@ -218,21 +242,21 @@ workflow PREPARE_INPUT { } else if (run_config.mode == Constants.RunMode.WTS) { required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.WTS], + [Constants.SampleType.TUMOR, Constants.SequenceType.RNA], ] } else if (run_config.mode == Constants.RunMode.WGTS) { if (run_config.type == Constants.RunType.TUMOR_ONLY) { required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.WGS], - [Constants.SampleType.TUMOR, Constants.SequenceType.WTS], + [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], + [Constants.SampleType.TUMOR, Constants.SequenceType.RNA], ] } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.WGS], - [Constants.SampleType.TUMOR, Constants.SequenceType.WTS], - [Constants.SampleType.NORMAL, Constants.SequenceType.WGS], + [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], + [Constants.SampleType.TUMOR, Constants.SequenceType.RNA], + [Constants.SampleType.NORMAL, Constants.SequenceType.DNA], ] } else { assert false @@ -276,6 +300,10 @@ workflow PREPARE_INPUT { } } + */ + + + emit: data = ch_inputs diff --git a/subworkflows/local/purple_calling.nf b/subworkflows/local/purple_calling.nf index 06f1110d..4ea5768c 100644 --- a/subworkflows/local/purple_calling.nf +++ b/subworkflows/local/purple_calling.nf @@ -65,11 +65,11 @@ workflow PURPLE_CALLING { def meta_purple = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorSampleName(meta, run_config.mode), + tumor_id: Utils.getTumorDnaSampleName(meta), ] if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - meta_purple.normal_id = Utils.getNormalWgsSampleName(meta) + meta_purple.normal_id = Utils.getNormalDnaSampleName(meta) } return [meta_purple, *it[1..-1]] diff --git a/subworkflows/local/sage_append.nf b/subworkflows/local/sage_append.nf index 1858ae2d..aadda658 100644 --- a/subworkflows/local/sage_append.nf +++ b/subworkflows/local/sage_append.nf @@ -28,12 +28,12 @@ workflow SAGE_APPEND { ch_versions = Channel.empty() // Select input sources - // channel: [ meta, purple_dir, tumor_wts_bam, tumor_wts_bai ] + // channel: [ meta, purple_dir, tumor_rna_bam, tumor_rna_bai ] ch_sage_append_inputs_source = WorkflowOncoanalyser.groupByMeta( run_config.stages.purple ? ch_purple_dir : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), ch_inputs .map { meta -> - def bam = Utils.getTumorWtsBam(meta) + def bam = Utils.getTumorRnaBam(meta) return [meta, bam, "${bam}.bai"] }, ) @@ -45,11 +45,11 @@ workflow SAGE_APPEND { ch_germline_vcf = Channel.empty() if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - // channel: [ sage_meta, purple_germline_smlv_vcf, tumor_wts_bam ] + // channel: [ sage_meta, purple_germline_smlv_vcf, tumor_rna_bam ] ch_sage_germline_append_inputs = ch_sage_append_inputs_source .map { meta, purple_dir, bam, bai -> - def tumor_id = Utils.getTumorWgsSampleName(meta) - def normal_id = Utils.getNormalWgsSampleName(meta) + def tumor_id = Utils.getTumorDnaSampleName(meta) + def normal_id = Utils.getNormalDnaSampleName(meta) def purple_smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") @@ -61,8 +61,8 @@ workflow SAGE_APPEND { def sage_meta = [ key: meta.id, id: meta.id, - tumor_wts_id: Utils.getTumorWtsSampleName(meta), - wgs_id: normal_id, + tumor_rna_id: Utils.getTumorRnaSampleName(meta), + dna_id: normal_id, ] return [sage_meta, purple_smlv_vcf, bam, bai] } @@ -86,10 +86,10 @@ workflow SAGE_APPEND { // // NOTE(SW): revise to reduce repetition // Create inputs and create process-specific meta - // channel: [ sage_meta, purple_somatic_smlv_vcf, tumor_wts_bam ] + // channel: [ sage_meta, purple_somatic_smlv_vcf, tumor_rna_bam ] ch_sage_somatic_append_inputs = ch_sage_append_inputs_source .map { meta, purple_dir, bam, bai -> - def tumor_id = Utils.getTumorWgsSampleName(meta) + def tumor_id = Utils.getTumorDnaSampleName(meta) def purple_smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") // Require both somatic smlv from the PURPLE directory @@ -100,8 +100,8 @@ workflow SAGE_APPEND { def sage_meta = [ key: meta.id, id: meta.id, - tumor_wts_id: Utils.getTumorWtsSampleName(meta), - wgs_id: tumor_id, + tumor_rna_id: Utils.getTumorRnaSampleName(meta), + dna_id: tumor_id, ] return [sage_meta, purple_smlv_vcf, bam, bai] } diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index 0996fe9c..2e7ea15f 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -40,10 +40,10 @@ workflow SAGE_CALLING { def meta_sage = [ key: meta.id, id: meta.id, - tumor_id: Utils.getTumorSampleName(meta, run_config.mode), + tumor_id: Utils.getTumorDnaSampleName(meta), ] - def tumor_bam = Utils.getTumorBam(meta, run_config.mode) + def tumor_bam = Utils.getTumorDnaBam(meta) def normal_bam = [] def normal_bai = [] @@ -52,8 +52,8 @@ workflow SAGE_CALLING { assert [Constants.RunMode.WGS, Constants.RunMode.WGTS].contains(run_config.mode) - meta_sage.normal_id = Utils.getNormalWgsSampleName(meta) - normal_bam = Utils.getNormalWgsBam(meta) + meta_sage.normal_id = Utils.getNormalDnaSampleName(meta) + normal_bam = Utils.getNormalDnaBam(meta) normal_bai = "${normal_bam}.bai" } diff --git a/subworkflows/local/sigs_fitting.nf b/subworkflows/local/sigs_fitting.nf index 7a4d9bd7..5e13fcdb 100644 --- a/subworkflows/local/sigs_fitting.nf +++ b/subworkflows/local/sigs_fitting.nf @@ -37,7 +37,7 @@ workflow SIGS_FITTING { ch_sigs_inputs = ch_sigs_inputs_source .map { meta, purple_dir -> - def tumor_id = Utils.getTumorWgsSampleName(meta) + def tumor_id = Utils.getTumorDnaSampleName(meta) def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") // Require smlv VCF from the PURPLE directory diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index 3831c505..c5775c4d 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -44,7 +44,7 @@ workflow VIRUSBREAKEND_CALLING { key: meta.id, id: meta.id, ] - return [meta_virus, Utils.getTumorBam(meta, run_config.mode)] + return [meta_virus, Utils.getTumorDnaBam(meta)] } // Run process @@ -82,7 +82,7 @@ workflow VIRUSBREAKEND_CALLING { def meta = it[0] def meta_virus = [ key: meta.id, - id: Utils.getTumorSampleName(meta, run_config.mode), + id: Utils.getTumorDnaSampleName(meta), ] return [meta_virus, *it[1..-1]] } From 5a44b490a5e45711f196f4d49b69111455976576 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 10:14:13 +1100 Subject: [PATCH 218/562] Clean up and restore WGTS workflow stub run --- lib/Processes.groovy | 50 ++++++++++++--------- lib/WorkflowMain.groovy | 13 ++++++ main.nf | 7 +-- modules/local/cuppa/main.nf | 2 +- modules/local/lilac/meta.yml | 12 ++--- subworkflows/local/channel_inputs_purple.nf | 2 +- subworkflows/local/cobalt_profiling.nf | 2 +- subworkflows/local/gridss_svprep_calling.nf | 2 +- subworkflows/local/orange_reporting.nf | 12 ++--- subworkflows/local/prepare_input.nf | 6 +-- subworkflows/local/prepare_reference.nf | 2 +- subworkflows/local/sage_calling.nf | 2 +- workflows/wgts.nf | 6 +-- 13 files changed, 67 insertions(+), 51 deletions(-) diff --git a/lib/Processes.groovy b/lib/Processes.groovy index 2862d106..1a836909 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -4,7 +4,7 @@ import Utils class Processes { - public static setProcesses(run_mode, manual_select, log) { + public static setProcesses(run_mode, manual_select, targeted_mode, log) { def processes = [] if (manual_select) { @@ -12,7 +12,8 @@ class Processes { } switch(run_mode) { - case Constants.RunMode.WGS: + + case Constants.RunMode.DNA: processes = [ Constants.Process.AMBER, Constants.Process.BAMTOOLS, @@ -32,13 +33,15 @@ class Processes { Constants.Process.VIRUSINTERPRETER, ] break - case Constants.RunMode.WTS: + + case Constants.RunMode.RNA: processes = [ Constants.Process.CUPPA, Constants.Process.ISOFOX, ] break - case Constants.RunMode.WGTS: + + case Constants.RunMode.DNA_RNA: processes = [ Constants.Process.AMBER, Constants.Process.BAMTOOLS, @@ -59,31 +62,34 @@ class Processes { Constants.Process.VIRUSINTERPRETER, ] break - case Constants.RunMode.PANEL: - processes = [ - Constants.Process.AMBER, - Constants.Process.BAMTOOLS, - Constants.Process.COBALT, - Constants.Process.FLAGSTAT, - Constants.Process.GRIDSS, - Constants.Process.GRIPSS, - Constants.Process.LILAC, - Constants.Process.LINX, - Constants.Process.ORANGE, - Constants.Process.PAVE, - Constants.Process.PURPLE, - Constants.Process.SAGE, - ] - break + + //case Constants.RunMode.PANEL: + // processes = [ + // Constants.Process.AMBER, + // Constants.Process.BAMTOOLS, + // Constants.Process.COBALT, + // Constants.Process.FLAGSTAT, + // Constants.Process.GRIDSS, + // Constants.Process.GRIPSS, + // Constants.Process.LILAC, + // Constants.Process.LINX, + // Constants.Process.ORANGE, + // Constants.Process.PAVE, + // Constants.Process.PURPLE, + // Constants.Process.SAGE, + // ] + // break + default: log.error "\nERROR: we should never have come here" System.exit(1) } + return processes } - public static getRunStages(run_mode, include, exclude, manual_select, log) { - def processes = this.setProcesses(run_mode, manual_select, log) + public static getRunStages(run_mode, include, exclude, manual_select, targeted_mode, log) { + def processes = this.setProcesses(run_mode, manual_select, targeted_mode, log) def include_list = this.getProcessList(include, log) def exclude_list = this.getProcessList(exclude, log) this.checkIncludeExcludeList(include_list, exclude_list, log) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index c3c67965..ca6478ba 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -165,11 +165,23 @@ class WorkflowMain { } + + + + if (params.targeted === true) { + log.error "\nERROR: process selection for targeted mode not implemented yet" + System.exit(1) + } + + + + def stages = Processes.getRunStages( run_mode, params.processes_include, params.processes_exclude, params.processes_manual, + params.targeted, log, ) @@ -347,6 +359,7 @@ class WorkflowMain { params.processes_include, params.processes_exclude, params.processes_manual, + params.targeted, log, ) diff --git a/main.nf b/main.nf index e4d43e00..3b79317d 100644 --- a/main.nf +++ b/main.nf @@ -55,13 +55,10 @@ include { WGTS } from './workflows/wgts' run_mode = Utils.getRunMode(params.run_mode, log) workflow NFCORE_ONCOANALYSER { - run_modes_wgts = [Constants.RunMode.WGS, Constants.RunMode.WTS, Constants.RunMode.WGTS] - if (run_modes_wgts.contains(run_mode)) { + if (params.targeted == false) { WGTS() - } else if (run_mode == Constants.RunMode.PANEL) { - PANEL() } else { - assert false + //TARGETED() } } diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index 5a7d55a2..9735a13d 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -46,7 +46,7 @@ process CUPPA { if [[ ${categories_val} == 'RNA' ]]; then find -L ${isofox_dir} -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; elif [[ ${categories_val} == 'ALL' ]]; then - # NOTE(SW): CUPPA requires that the WTS sample name matches the WGS sample name + # NOTE(SW): CUPPA requires that the RNA sample name matches the DNA sample name for fp in \$(find -L ${isofox_dir} -maxdepth 1 -type f); do fn_out=\$(sed 's/^${meta.id_rna}/${meta.id}/' <<< \${fp##*/}); cp \${fp} sample_data/\${fn_out} diff --git a/modules/local/lilac/meta.yml b/modules/local/lilac/meta.yml index 323cfb94..b9b79617 100644 --- a/modules/local/lilac/meta.yml +++ b/modules/local/lilac/meta.yml @@ -18,27 +18,27 @@ input: e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] - normal_dna_bam: type: file - description: Normal WGS BAM file (optional) + description: Normal DNA BAM file (optional) pattern: "*.{bam}" - normal_dna_bai: type: file - description: Normal WGS BAI file (optional) + description: Normal DNA BAI file (optional) pattern: "*.{bai}" - tumor_dna_bam: type: file - description: Normal WGS BAM file (optional) + description: Normal DNA BAM file (optional) pattern: "*.{bam}" - tumor_dna_bai: type: file - description: Tumor WGS BAI file (optional) + description: Tumor DNA BAI file (optional) pattern: "*.{bai}" - tumor_rna_bam: type: file - description: Normal WTS BAM file (optional) + description: Normal RNA BAM file (optional) pattern: "*.{bam}" - tumor_rna_bai: type: file - description: Tumor WTS BAI file (optional) + description: Tumor RNA BAI file (optional) pattern: "*.{bai}" - purple_dir: type: directory diff --git a/subworkflows/local/channel_inputs_purple.nf b/subworkflows/local/channel_inputs_purple.nf index 7a6c7244..8634800b 100644 --- a/subworkflows/local/channel_inputs_purple.nf +++ b/subworkflows/local/channel_inputs_purple.nf @@ -50,7 +50,7 @@ workflow CHANNEL_INPUTS_PURPLE { } // NOTE(SW): Hartwig indicated unfiltered SVs should not be used for recovery in panel or tumor-only mode - if (run_config.mode == Constants.RunMode.PANEL || run_config.type == Constants.RunType.TUMOR_ONLY) { + if (params.targeted === true || run_config.type == Constants.RunType.TUMOR_ONLY) { ch_sv_somatic_unfiltered_source = ch_inputs.map { meta -> [meta, [], []] } } diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index 2b6434d2..29eec79d 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -40,7 +40,7 @@ workflow COBALT_PROFILING { if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - assert [Constants.RunMode.WGS, Constants.RunMode.WGTS].contains(run_config.mode) + assert [Constants.RunMode.DNA, Constants.RunMode.DNA_RNA].contains(run_config.mode) meta_cobalt.normal_id = Utils.getNormalDnaSampleName(meta) normal_bam = Utils.getNormalDnaBam(meta) diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index 7c51486e..8511ae92 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -81,7 +81,7 @@ workflow GRIDSS_SVPREP_CALLING { ch_preprocess_inputs_normal = Channel.empty() if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - assert [Constants.RunMode.WGS, Constants.RunMode.WGTS].contains(run_config.mode) + assert [Constants.RunMode.DNA, Constants.RunMode.DNA_RNA].contains(run_config.mode) // Prepare normal sample inputs // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index a6888947..9844b514 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -79,9 +79,9 @@ workflow ORANGE_REPORTING { ch_linx_germline_annotation = ch_inputs.map { meta -> [meta, []] } } - // Do not pass WTS reference files when not required - // NOTE(SW): ORANGE v2.6.0 will crash if WTS reference files but not WTS sample files provided - if (run_config.mode != Constants.RunMode.WTS && run_config.mode != Constants.RunMode.WGTS) { + // Do not pass RNA reference files when not required + // NOTE(SW): ORANGE v2.6.0 will crash if RNA reference files but not RNA sample files provided + if (run_config.mode != Constants.RunMode.RNA && run_config.mode != Constants.RunMode.DNA_RNA) { isofox_alt_sj = [] isofox_gene_distribution = [] } @@ -91,7 +91,7 @@ workflow ORANGE_REPORTING { // Get input smlv somatic VCF from either PURPLE or SAGE append // channel: [ meta, sage_somatic_vcf, sage_germline_vcf ] - if (run_config.mode == Constants.RunMode.WGS || run_config.mode == Constants.RunMode.PANEL) { + if (run_config.mode == Constants.RunMode.DNA) { ch_orange_inputs_smlv_vcfs = ch_orange_inputs_purple_dir .map { meta, purple_dir -> @@ -107,7 +107,7 @@ workflow ORANGE_REPORTING { smlv_somatic_vcf = smlv_somatic_vcf_path } - // NOTE(SW): can only evaluate to true with WGS tumor/normal + // NOTE(SW): can only evaluate to true with DNA tumor/normal if (smlv_germline_vcf_path.exists()) { smlv_germline_vcf = smlv_germline_vcf_path } @@ -115,7 +115,7 @@ workflow ORANGE_REPORTING { return [meta, smlv_somatic_vcf, smlv_germline_vcf] } - } else if (run_config.mode == Constants.RunMode.WGTS) { + } else if (run_config.mode == Constants.RunMode.DNA_RNA) { ch_orange_inputs_smlv_vcfs = WorkflowOncoanalyser.groupByMeta( ch_sage_somatic_append, diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf index 0b8fd4ea..8c1f929b 100644 --- a/subworkflows/local/prepare_input.nf +++ b/subworkflows/local/prepare_input.nf @@ -224,7 +224,7 @@ workflow PREPARE_INPUT { [Constants.SampleType.TUMOR, Constants.SequenceType.TARGETTED], ] - } else if (run_config.mode == Constants.RunMode.WGS) { + } else if (run_config.mode == Constants.RunMode.DNA) { if (run_config.type == Constants.RunType.TUMOR_ONLY) { required_sample_types = [ @@ -239,13 +239,13 @@ workflow PREPARE_INPUT { assert false } - } else if (run_config.mode == Constants.RunMode.WTS) { + } else if (run_config.mode == Constants.RunMode.RNA) { required_sample_types = [ [Constants.SampleType.TUMOR, Constants.SequenceType.RNA], ] - } else if (run_config.mode == Constants.RunMode.WGTS) { + } else if (run_config.mode == Constants.RunMode.DNA_RNA) { if (run_config.type == Constants.RunType.TUMOR_ONLY) { required_sample_types = [ diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 5b7e0fcd..12e90e33 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -136,7 +136,7 @@ workflow PREPARE_REFERENCE { // Set panel reference paths / stage, unpack if required // ch_panel_data = Channel.empty() - if (run_config.mode == Constants.RunMode.PANEL) { + if (params.targeted === true) { // NOTE(SW): consider approach to implement custom panel support diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index 2e7ea15f..69782635 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -50,7 +50,7 @@ workflow SAGE_CALLING { if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - assert [Constants.RunMode.WGS, Constants.RunMode.WGTS].contains(run_config.mode) + assert [Constants.RunMode.DNA, Constants.RunMode.DNA_RNA].contains(run_config.mode) meta_sage.normal_id = Utils.getNormalDnaSampleName(meta) normal_bam = Utils.getNormalDnaBam(meta) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index e4f149f6..15e0766d 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -125,7 +125,7 @@ workflow WGTS { gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config // - // MODULE: Run Isofox to analyse WTS data + // MODULE: Run Isofox to analyse RNA data // // channel: [ meta, isofox_dir ] ch_isofox_out = Channel.empty() @@ -365,12 +365,12 @@ workflow WGTS { } // - // SUBWORKFLOW: Append WTS data to SAGE VCF + // SUBWORKFLOW: Append RNA data to SAGE VCF // // channel: [ meta, sage_append_vcf ] ch_sage_somatic_append_vcf = Channel.empty() ch_sage_germline_append_vcf = Channel.empty() - if (run_config.mode == Constants.RunMode.WGTS && run_config.stages.orange) { + if (run_config.mode == Constants.RunMode.DNA_RNA && run_config.stages.orange) { // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented From 55b2a7585c058cc8cf5c727743fed86e616f50eb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 11:38:25 +1100 Subject: [PATCH 219/562] Update process selection, restore panel stub run --- lib/Processes.groovy | 96 +++++++++++++---------------------------- lib/WorkflowMain.groovy | 11 ----- 2 files changed, 31 insertions(+), 76 deletions(-) diff --git a/lib/Processes.groovy b/lib/Processes.groovy index 1a836909..a265803e 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -11,78 +11,44 @@ class Processes { return processes } - switch(run_mode) { - - case Constants.RunMode.DNA: - processes = [ - Constants.Process.AMBER, - Constants.Process.BAMTOOLS, + if (run_mode === Constants.RunMode.DNA || run_mode === Constants.RunMode.DNA_RNA) { + + processes += [ + Constants.Process.AMBER, + Constants.Process.BAMTOOLS, + Constants.Process.COBALT, + Constants.Process.FLAGSTAT, + Constants.Process.GRIDSS, + Constants.Process.GRIPSS, + Constants.Process.LILAC, + Constants.Process.LINX, + Constants.Process.ORANGE, + Constants.Process.PAVE, + Constants.Process.PURPLE, + Constants.Process.SAGE, + ] + + if (targeted_mode === false) { + processes += [ Constants.Process.CHORD, - Constants.Process.COBALT, Constants.Process.CUPPA, - Constants.Process.FLAGSTAT, - Constants.Process.GRIDSS, - Constants.Process.GRIPSS, - Constants.Process.LILAC, - Constants.Process.LINX, - Constants.Process.ORANGE, - Constants.Process.PAVE, - Constants.Process.PURPLE, - Constants.Process.SAGE, Constants.Process.SIGS, Constants.Process.VIRUSINTERPRETER, ] - break + } - case Constants.RunMode.RNA: - processes = [ - Constants.Process.CUPPA, - Constants.Process.ISOFOX, - ] - break + } + + if (run_mode === Constants.RunMode.RNA || run_mode === Constants.RunMode.DNA_RNA) { + + processes += [Constants.Process.ISOFOX] + + // TODO(SW): understand whether Hartwig will offer RNA-only panel processing + + if (targeted_mode === false) { + processes += [Constants.Process.CUPPA] + } - case Constants.RunMode.DNA_RNA: - processes = [ - Constants.Process.AMBER, - Constants.Process.BAMTOOLS, - Constants.Process.CHORD, - Constants.Process.COBALT, - Constants.Process.CUPPA, - Constants.Process.FLAGSTAT, - Constants.Process.GRIDSS, - Constants.Process.GRIPSS, - Constants.Process.ISOFOX, - Constants.Process.LILAC, - Constants.Process.LINX, - Constants.Process.ORANGE, - Constants.Process.PAVE, - Constants.Process.PURPLE, - Constants.Process.SAGE, - Constants.Process.SIGS, - Constants.Process.VIRUSINTERPRETER, - ] - break - - //case Constants.RunMode.PANEL: - // processes = [ - // Constants.Process.AMBER, - // Constants.Process.BAMTOOLS, - // Constants.Process.COBALT, - // Constants.Process.FLAGSTAT, - // Constants.Process.GRIDSS, - // Constants.Process.GRIPSS, - // Constants.Process.LILAC, - // Constants.Process.LINX, - // Constants.Process.ORANGE, - // Constants.Process.PAVE, - // Constants.Process.PURPLE, - // Constants.Process.SAGE, - // ] - // break - - default: - log.error "\nERROR: we should never have come here" - System.exit(1) } return processes diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index ca6478ba..2caac9d7 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -165,17 +165,6 @@ class WorkflowMain { } - - - - if (params.targeted === true) { - log.error "\nERROR: process selection for targeted mode not implemented yet" - System.exit(1) - } - - - - def stages = Processes.getRunStages( run_mode, params.processes_include, From c31665d3b68dd4f8b9a6baec27ff5ced0eecdca1 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 11:39:13 +1100 Subject: [PATCH 220/562] Add SAGE append meta.yml --- modules/local/sage/append/meta.yml | 61 ++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 modules/local/sage/append/meta.yml diff --git a/modules/local/sage/append/meta.yml b/modules/local/sage/append/meta.yml new file mode 100644 index 00000000..15ef5850 --- /dev/null +++ b/modules/local/sage/append/meta.yml @@ -0,0 +1,61 @@ +name: sage_append +description: A tool to append data to existing SAGE calls +keywords: + - append + - snv + - mnv +tools: + - sage: + description: A precise and highly sensitive somatic SNV, MNV and small INDEL caller. + homepage: https://github.com/hartwigmedical/hmftools/tree/master/sage + documentation: https://github.com/hartwigmedical/hmftools/tree/master/sage + licence: ['GPL v3'] +input: + - meta: + type: map + description: | + Groovy Map containing sample informatio + e.g. [id: 'sample_id', append_id: 'sample_id_append'] + - vcf: + type: file + description: VCF file + pattern: "*.{vcf.gz}" + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - bai: + type: file + description: BAI file + pattern: "*.{bai}" + - genome_fasta: + type: file + description: Reference genome assembly FASTA file + pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', append_id: 'sample_id_append'] + - vcf: + type: file + description: VCF file + pattern: "*.{vcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" From 620896da97e023b66bd0b56794ac825921c0051f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 11:39:29 +1100 Subject: [PATCH 221/562] Use correct lettercasing for Sigs name --- conf/hmf_data.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/hmf_data.config b/conf/hmf_data.config index 1f74623b..c380b1fc 100644 --- a/conf/hmf_data.config +++ b/conf/hmf_data.config @@ -35,7 +35,7 @@ params { sage_known_hotspots_germline = 'dna_pipeline/variants/KnownHotspots.germline.37.vcf.gz' sage_known_hotspots_somatic = 'dna_pipeline/variants/KnownHotspots.somatic.37.vcf.gz' sage_pon = 'dna_pipeline/variants/SageGermlinePon.1000x.37.tsv.gz' - // SIGS + // Sigs sigs_signatures = 'sigs/snv_cosmic_signatures.csv' // Virus Interpreter virus_reporting_db = 'virusinterpreter/virus_reporting_db.tsv' @@ -86,7 +86,7 @@ params { sage_known_hotspots_germline = 'dna_pipeline/variants/KnownHotspots.germline.38.vcf.gz' sage_known_hotspots_somatic = 'dna_pipeline/variants/KnownHotspots.somatic.38.vcf.gz' sage_pon = 'dna_pipeline/variants/SageGermlinePon.98x.38.tsv.gz' - // SIGS + // Sigs sigs_signatures = 'sigs/snv_cosmic_signatures.csv' // Virus Interpreter virus_reporting_db = 'virusinterpreter/virus_reporting_db.tsv' From 5c8f890892c481138cc9e1cac7ed903e99db771e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 12:06:39 +1100 Subject: [PATCH 222/562] =?UTF-8?q?Bump=20Isofox=20version:=201.6.2=20?= =?UTF-8?q?=E2=86=92=201.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/isofox/Dockerfile | 2 +- modules/local/isofox/main.nf | 17 ++++++++++++++--- modules/local/isofox/meta.yml | 14 ++++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/modules/local/isofox/Dockerfile b/modules/local/isofox/Dockerfile index 9f6986d2..791a3c31 100644 --- a/modules/local/isofox/Dockerfile +++ b/modules/local/isofox/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/isofox/ && \ - wget -O /opt/isofox/isofox.jar 'https://github.com/hartwigmedical/hmftools/releases/download/isofox-v1.6.2/isofox_v1.6.2.jar' + wget -O /opt/isofox/isofox.jar 'https://github.com/hartwigmedical/hmftools/releases/download/isofox-v1.7/isofox_v1.7.jar' USER mambauser diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 7d246a49..a6e914ea 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -2,17 +2,20 @@ process ISOFOX { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/isofox:1.6.2--0' + container 'docker.io/scwatts/isofox:1.7--0' input: tuple val(meta), path(bam), path(bai) val functions + val read_length path genome_fasta val genome_ver path genome_fai path ensembl_data_resources path exp_counts path exp_gc_ratios + path gene_ids + path tpm_norm output: tuple val(meta), path('isofox/'), emit: isofox_dir @@ -23,10 +26,15 @@ process ISOFOX { script: def args = task.ext.args ?: '' + def functions_arg = functions ? "-functions \'${functions}\'" : '' + def exp_counts_arg = exp_counts ? "-exp_counts_file ${exp_counts}" : '' def exp_gc_ratios_arg = exp_gc_ratios ? "-exp_gc_ratios_file ${exp_gc_ratios}" : '' + def gene_ids_arg = gene_ids ? "-gene_id_file ${gene_ids}" : '' + def tpm_norm_arg = tpm_norm ? "-panel_tpm_norm_file ${tpm_norm}" : '' + """ mkdir -p isofox/ @@ -37,13 +45,16 @@ process ISOFOX { -sample ${meta.id} \\ -bam_file ${bam} \\ ${functions_arg} \\ + -read_length ${read_length} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ ${exp_counts_arg} \\ ${exp_gc_ratios_arg} \\ - -output_dir isofox/ \\ - -threads ${task.cpus} + ${gene_ids_arg} \\ + ${tpm_norm_arg} \\ + -threads ${task.cpus} \\ + -output_dir isofox/ cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/isofox/meta.yml b/modules/local/isofox/meta.yml index b1106588..2e0d1930 100644 --- a/modules/local/isofox/meta.yml +++ b/modules/local/isofox/meta.yml @@ -23,6 +23,12 @@ input: type: file description: BAI file pattern: "*.{bai}" + - functions: + type: string + description: Isofox functions to run + - read_length: + type: integer + description: Read length - genome_fasta: type: file description: Reference genome assembly FASTA file @@ -45,6 +51,14 @@ input: type: file description: Isofox expected GC ratio counts file (optional) pattern: "*.{csv}" + - gene_ids: + type: file + description: Isofox gene ID file (optional) + pattern: "*.{csv}" + - tmp_norm: + type: file + description: Isofox TPM noramlisation file (optional) + pattern: "*.{csv}" output: - meta: type: map From 22ce787ccc99813993551405653ee4ffcfe0537e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 12:09:07 +1100 Subject: [PATCH 223/562] Adjust WGTS Isofox to null new panel options --- nextflow.config | 1 + subworkflows/local/isofox_quantification.nf | 9 +++++++-- workflows/wgts.nf | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/nextflow.config b/nextflow.config index 21d62ebb..f0d37d03 100644 --- a/nextflow.config +++ b/nextflow.config @@ -43,6 +43,7 @@ params { // Other workflow inputs and options linx_gene_id_file = null isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' + isofox_read_length = { params.targeted === false ? 151 : 93 } use_isofox_exp_counts_cache = false // Config options diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf index 144c1f53..ba42481d 100644 --- a/subworkflows/local/isofox_quantification.nf +++ b/subworkflows/local/isofox_quantification.nf @@ -18,10 +18,12 @@ workflow ISOFOX_QUANTIFICATION { ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ isofox_counts // channel: [mandatory] /path/to/isofox_counts isofox_gc_ratios // channel: [mandatory] /path/to/isofox_gc_ratios + isofox_gene_ids // channel: [optional] /path/to/gene_ids + isofox_tpm_norm // channel: [optional] /path/to/tpm_norm // Params - isofox_functions // string: [optional] isofox functions - //use_isofox_exp_counts_cache + isofox_functions // string: [optional] isofox functions + isofox_read_length // string: [mandatory] isofox_read_length run_config // channel: [mandatory] run configuration main: @@ -62,12 +64,15 @@ workflow ISOFOX_QUANTIFICATION { ISOFOX( ch_isofox_inputs, isofox_functions, + isofox_read_length, genome_fasta, genome_version, genome_fai, ensembl_data_resources, isofox_counts, isofox_gc_ratios, + isofox_gene_ids, + isofox_tpm_norm, ) // Set outputs, restoring original meta diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 15e0766d..bb8b9c72 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -139,7 +139,10 @@ workflow WGTS { hmf_data.ensembl_data_resources, hmf_data.isofox_counts, hmf_data.isofox_gc_ratios, + [], // isofox_gene_ids + [], // isofox_tpm_norm params.isofox_functions, + params.isofox_read_length, run_config, ) From 2e63aab9d1b101cfc65c56b79f16f2bcb6962040 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 16:34:07 +1100 Subject: [PATCH 224/562] Add RNA analysis to panel workflow --- conf/panel_data.config | 8 +++++ lib/WorkflowMain.groovy | 8 +++++ nextflow.config | 12 ++++++-- workflows/panel.nf | 67 +++++++++++++++++++++++++++++++++++++++-- workflows/wgts.nf | 21 ++++++++----- 5 files changed, 103 insertions(+), 13 deletions(-) diff --git a/conf/panel_data.config b/conf/panel_data.config index 22d0ad82..33ac6ad8 100644 --- a/conf/panel_data.config +++ b/conf/panel_data.config @@ -28,6 +28,10 @@ params { target_region_normalisation = 'copy_number/cobalt_normalisation.tso500.37.tsv' target_region_ratios = 'copy_number/target_regions_ratios.tso500.37.tsv' target_region_msi_indels = 'copy_number/target_regions_msi_indels.tso500.37.tsv' + isofox_tpm_norm = 'rna_resources/isofox.tso500_gene_normalisation.csv' + isofox_gene_ids = 'rna_resources/tso500_rna_gene_ids.csv' + isofox_counts = 'rna_resources/read_93_exp_counts.37.csv' + isofox_gc_ratios = 'rna_resources/read_93_exp_gc_ratios.37.csv' } '38' { @@ -39,6 +43,10 @@ params { target_region_normalisation = 'copy_number/cobalt_normalisation.tso500.38.tsv' target_region_ratios = 'copy_number/target_regions_ratios.tso500.38.tsv' target_region_msi_indels = 'copy_number/target_regions_msi_indels.tso500.38.tsv' + isofox_tpm_norm = 'rna_resources/isofox.tso500_gene_normalisation.csv' + isofox_gene_ids = 'rna_resources/tso500_rna_gene_ids.csv' + isofox_counts = 'rna_resources/read_93_exp_counts.38.csv' + isofox_gc_ratios = 'rna_resources/read_93_exp_gc_ratios.38.csv' } } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 2caac9d7..8753d320 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -336,6 +336,14 @@ class WorkflowMain { System.exit(1) } + def rna_run = run_mode == Constants.RunMode.RNA || run_mode == Constants.RunMode.DNA_RNA + if (rna_run && params.panel != 'tso500') { + log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Currently only the TSO500 panel (tso500) supports RNA analysis.\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + } } diff --git a/nextflow.config b/nextflow.config index f0d37d03..9546a8be 100644 --- a/nextflow.config +++ b/nextflow.config @@ -12,8 +12,16 @@ params { // Input options input = null - // Pipeline run configuration - targeted = false + // Enable targeted/panel mode; WGTS run by default + targeted = false + + // Isofox user inputs + isofox_counts = null + isofox_gc_ratios = null + isofox_gene_ids = null + isofox_tpm_norm = null + + // Process configuration processes_manual = false processes_include = null processes_exclude = null diff --git a/workflows/panel.nf b/workflows/panel.nf index a9ee6da8..69b3ec1e 100644 --- a/workflows/panel.nf +++ b/workflows/panel.nf @@ -15,6 +15,10 @@ run_config = WorkflowMain.getRunConfig(params, log) // Check input path parameters to see if they exist def checkPathParamList = [ params.input, + params.isofox_counts, + params.isofox_gc_ratios, + params.isofox_gene_ids, + params.isofox_tpm_norm, params.linx_gene_id_file, ] @@ -61,6 +65,7 @@ include { BAMTOOLS_METRICS } from '../subworkflows/local/bamtools_metrics' include { COBALT_PROFILING } from '../subworkflows/local/cobalt_profiling' include { GRIDSS_SVPREP_CALLING } from '../subworkflows/local/gridss_svprep_calling' include { GRIPSS_FILTERING } from '../subworkflows/local/gripss_filtering' +include { ISOFOX_QUANTIFICATION } from '../subworkflows/local/isofox_quantification' include { LILAC_CALLING } from '../subworkflows/local/lilac_calling' include { LINX_ANNOTATION } from '../subworkflows/local/linx_annotation' include { LINX_PLOTTING } from '../subworkflows/local/linx_plotting' @@ -69,6 +74,7 @@ include { PAVE_ANNOTATION } from '../subworkflows/local/pave_annotation' include { PREPARE_INPUT } from '../subworkflows/local/prepare_input' include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' +include { SAGE_APPEND } from '../subworkflows/local/sage_append' include { SAGE_CALLING } from '../subworkflows/local/sage_calling' /* @@ -116,6 +122,38 @@ workflow PANEL { // Set GRIDSS config gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config + // + // MODULE: Run Isofox to analyse RNA data + // + // channel: [ meta, isofox_dir ] + ch_isofox_out = Channel.empty() + if (run_config.stages.isofox) { + + isofox_counts = params.isofox_counts ? file(params.isofox_counts) : hmf_data.isofox_counts + isofox_gc_ratios = params.isofox_gc_ratios ? file(params.isofox_gc_ratios) : hmf_data.isofox_gc_ratios + + isofox_gene_ids = params.isofox_gene_ids ? file(params.isofox_gene_ids) : panel_data.isofox_gene_ids + isofox_tpm_norm = params.isofox_tpm_norm ? file(params.isofox_tpm_norm) : panel_data.isofox_tpm_norm + + ISOFOX_QUANTIFICATION( + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_version, + ref_data.genome_fai, + hmf_data.ensembl_data_resources, + isofox_counts, + isofox_gc_ratios, + isofox_gene_ids, + isofox_tpm_norm, + params.isofox_functions, + params.isofox_read_length, + run_config, + ) + + ch_versions = ch_versions.mix(ISOFOX_QUANTIFICATION.out.versions) + ch_isofox_out = ch_isofox_out.mix(ISOFOX_QUANTIFICATION.out.isofox_dir) + } + // // SUBWORKFLOW: Run Bam Tools to generate stats required for downstream processes // @@ -323,6 +361,29 @@ workflow PANEL { ch_purple_out = ch_purple_out.mix(PURPLE_CALLING.out.purple_dir) } + // + // SUBWORKFLOW: Append RNA data to SAGE VCF + // + // channel: [ meta, sage_append_vcf ] + ch_sage_somatic_append_out = Channel.empty() + if (run_config.mode == Constants.RunMode.DNA_RNA && run_config.stages.orange) { + + // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented + + SAGE_APPEND( + ch_inputs, + ch_purple_out, + ref_data.genome_fasta, + ref_data.genome_version, + ref_data.genome_fai, + ref_data.genome_dict, + run_config, + ) + + ch_versions = ch_versions.mix(SAGE_APPEND.out.versions) + ch_sage_somatic_append_out = ch_sage_somatic_append_out.mix(SAGE_APPEND.out.somatic_vcf) + } + // // SUBWORKFLOW: Group structural variants into higher order events with LINX // @@ -394,8 +455,8 @@ workflow PANEL { [], //ch_bamtools_germline_out ch_sage_somatic_dir_out, [], // ch_sage_germline_dir_out - [], // ch_sage_somatic_append_vcf - [], // ch_sage_germline_append_vcf + ch_sage_somatic_append_out, + [], // ch_sage_germline_append_out ch_purple_out, ch_linx_somatic_out, ch_linx_somatic_plot_out, @@ -405,7 +466,7 @@ workflow PANEL { [], // ch_sigs_out ch_lilac_out, [], // ch_cuppa_out - [], // ch_isofox_out + ch_isofox_out, ref_data.genome_version, hmf_data.disease_ontology, hmf_data.cohort_mapping, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index bb8b9c72..f26f0c64 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -15,6 +15,8 @@ run_config = WorkflowMain.getRunConfig(params, log) // Check input path parameters to see if they exist def checkPathParamList = [ params.input, + params.isofox_counts, + params.isofox_gc_ratios, params.linx_gene_id_file, ] @@ -131,14 +133,17 @@ workflow WGTS { ch_isofox_out = Channel.empty() if (run_config.stages.isofox) { + isofox_counts = params.isofox_counts ? file(params.isofox_counts) : hmf_data.isofox_counts + isofox_gc_ratios = params.isofox_gc_ratios ? file(params.isofox_gc_ratios) : hmf_data.isofox_gc_ratios + ISOFOX_QUANTIFICATION( ch_inputs, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, hmf_data.ensembl_data_resources, - hmf_data.isofox_counts, - hmf_data.isofox_gc_ratios, + isofox_counts, + isofox_gc_ratios, [], // isofox_gene_ids [], // isofox_tpm_norm params.isofox_functions, @@ -371,8 +376,8 @@ workflow WGTS { // SUBWORKFLOW: Append RNA data to SAGE VCF // // channel: [ meta, sage_append_vcf ] - ch_sage_somatic_append_vcf = Channel.empty() - ch_sage_germline_append_vcf = Channel.empty() + ch_sage_somatic_append_out = Channel.empty() + ch_sage_germline_append_out = Channel.empty() if (run_config.mode == Constants.RunMode.DNA_RNA && run_config.stages.orange) { // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented @@ -388,8 +393,8 @@ workflow WGTS { ) ch_versions = ch_versions.mix(SAGE_APPEND.out.versions) - ch_sage_somatic_append_vcf = ch_sage_somatic_append_vcf.mix(SAGE_APPEND.out.somatic_vcf) - ch_sage_germline_append_vcf = ch_sage_germline_append_vcf.mix(SAGE_APPEND.out.germline_vcf) + ch_sage_somatic_append_out = ch_sage_somatic_append_out.mix(SAGE_APPEND.out.somatic_vcf) + ch_sage_germline_append_out = ch_sage_germline_append_out.mix(SAGE_APPEND.out.germline_vcf) } // @@ -551,8 +556,8 @@ workflow WGTS { ch_bamtools_germline_out, ch_sage_somatic_dir_out, ch_sage_germline_dir_out, - ch_sage_somatic_append_vcf, - ch_sage_germline_append_vcf, + ch_sage_somatic_append_out, + ch_sage_germline_append_out, ch_purple_out, ch_linx_somatic_out, ch_linx_somatic_plot_out, From ad70a9a06e166d66257822b3bb87e8f27277584c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 16:34:59 +1100 Subject: [PATCH 225/562] Update note re use of iGenomes --- nextflow.config | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nextflow.config b/nextflow.config index 9546a8be..e82799bb 100644 --- a/nextflow.config +++ b/nextflow.config @@ -26,9 +26,7 @@ params { processes_include = null processes_exclude = null - // TODO(SW): default/suggest (very strongly) to use GRCh37_hmf or - // GRCh38_hmf (or whatever is equivalent); we may be able to get away with - // using an igenome in place of the HMF references, need to investigate + // Reference genome information; iGenomes is effectively disabled genome = null igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false From 67e2829f9eb1ba69bc74d7ff6a0e15d7f2123fc6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 16:35:20 +1100 Subject: [PATCH 226/562] Avoid using closure for params.isofox_read_length --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index e82799bb..1cf99223 100644 --- a/nextflow.config +++ b/nextflow.config @@ -49,7 +49,7 @@ params { // Other workflow inputs and options linx_gene_id_file = null isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' - isofox_read_length = { params.targeted === false ? 151 : 93 } + isofox_read_length = params.targeted === false ? 151 : 93 use_isofox_exp_counts_cache = false // Config options From abd4b6c086bd9d63be4e7ab006e92dac1ab9bbcf Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 16:35:46 +1100 Subject: [PATCH 227/562] Add new Isofox params to nextflow_schema.json --- nextflow_schema.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/nextflow_schema.json b/nextflow_schema.json index d13c6b42..e32fdf62 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -91,6 +91,30 @@ "description": "Path to LINX gene ID file.", "fa_icon": "fas fa-cog" }, + "isofox_read_length": { + "description": "User defined RNA read length used for Isofox.", + "fa_icon": "fas fa-cog" + }, + "isofox_gc_ratios": { + "type": "string", + "description": "User defined Isofox expected GC ratios file.", + "fa_icon": "fas fa-cog" + }, + "isofox_counts": { + "type": "string", + "description": "User defined Isofox expected counts files (read length dependent).", + "fa_icon": "fas fa-cog" + }, + "isofox_tpm_norm": { + "type": "string", + "description": "User defined Isofox TPM normalisation file for panel data.", + "fa_icon": "fas fa-cog" + }, + "isofox_gene_ids": { + "type": "string", + "description": "User defined Isofox gene list file for panel data.", + "fa_icon": "fas fa-cog" + }, "isofox_functions": { "type": "string", "description": "Semicolon-separated list of Isofox functions to run", From df28b493195b68b7d39918d12c1d8df8ed31815e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 16:39:48 +1100 Subject: [PATCH 228/562] Rename panel workflow to targeted workflow --- main.nf | 6 +++--- workflows/{panel.nf => targeted.nf} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename workflows/{panel.nf => targeted.nf} (99%) diff --git a/main.nf b/main.nf index 3b79317d..4bcccaff 100644 --- a/main.nf +++ b/main.nf @@ -45,8 +45,8 @@ WorkflowMain.paramsSummaryLog(workflow, params, log) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { PANEL } from './workflows/panel' -include { WGTS } from './workflows/wgts' +include { TARGETED } from './workflows/targeted' +include { WGTS } from './workflows/wgts' // // WORKFLOW: Run main nf-core/oncoanalyser analysis pipeline @@ -58,7 +58,7 @@ workflow NFCORE_ONCOANALYSER { if (params.targeted == false) { WGTS() } else { - //TARGETED() + TARGETED() } } diff --git a/workflows/panel.nf b/workflows/targeted.nf similarity index 99% rename from workflows/panel.nf rename to workflows/targeted.nf index 69b3ec1e..99ee7cb0 100644 --- a/workflows/panel.nf +++ b/workflows/targeted.nf @@ -97,7 +97,7 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft // Get absolute file paths samplesheet = Utils.getFileObject(params.input) -workflow PANEL { +workflow TARGETED { // Create channel for versions // channel: [ versions.yml ] From d7a8fca689b0dd085ca4aa787476a9385fa05686 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 16:41:00 +1100 Subject: [PATCH 229/562] Bump TSO500 bundle build version Added required Isofox resource files used in analysis of RNA panel data. --- lib/Constants.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 7f6987a3..2ffe8c4b 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -17,8 +17,8 @@ class Constants { static String HMF_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/hmf_5.33_38--0.tar.gz' - static String TSO500_PANEL_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.33_37--0.tar.gz' - static String TSO500_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.33_38--0.tar.gz' + static String TSO500_PANEL_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.33_37--1.tar.gz' + static String TSO500_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.33_38--1.tar.gz' static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' From 6a08c2768c8add9e4451a8e0c347e5bd75b11c97 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 18:01:31 +1100 Subject: [PATCH 230/562] Fix LILAC tumor DNA BAM argument --- modules/local/lilac/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index b9bb66e2..bd3f7a23 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -22,7 +22,7 @@ process LILAC { def sample_name = getSampleName(meta, tumor_dna_bam, normal_dna_bam) def normal_bam_arg = normal_dna_bam ? "-reference_bam ${normal_dna_bam}" : '' - def tumor_dna_bam_arg = tumor_dna_bam ? "-tumor_dna_bam ${tumor_dna_bam}" : '' + def tumor_dna_bam_arg = tumor_dna_bam ? "-tumor_bam ${tumor_dna_bam}" : '' def tumor_rna_bam_arg = tumor_rna_bam ? "-rna_bam ${tumor_rna_bam}" : '' def purple_dir_arg = purple_dir ? "-purple_dir ${purple_dir}" : '' From 7229dcf32da94879b0a65f6c7151e1d0ca412297 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 18:12:06 +1100 Subject: [PATCH 231/562] Clean up Isofox user inputs, defaults, and notes --- lib/Constants.groovy | 5 +++++ lib/WorkflowMain.groovy | 11 +++++++++++ nextflow.config | 10 ++++------ nextflow_schema.json | 6 ------ subworkflows/local/isofox_quantification.nf | 16 ---------------- 5 files changed, 20 insertions(+), 28 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 2ffe8c4b..899d364c 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -25,6 +25,11 @@ class Constants { static String HLA_SLICE_BED_GRCH38_ALT_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/umccr_reference_data/other/hla_slice/grch38_alt.plus_homologous.bed' + + static Integer DEFAULT_ISOFOX_READ_LENGTH_WTS = 151 + static Integer DEFAULT_ISOFOX_READ_LENGTH_TARGETED = 93 + + static enum RunType { TUMOR_NORMAL, TUMOR_ONLY, diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 8753d320..5655da5f 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -185,6 +185,17 @@ class WorkflowMain { params.ref_data_hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH } } + + if (stages.isofox && !params.containsKey('isofox_read_length')) { + + if (params.targeted === false) { + params.isofox_read_length = Constants.DEFAULT_ISOFOX_READ_LENGTH_WTS + } else { + params.isofox_read_length = Constants.DEFAULT_ISOFOX_READ_LENGTH_TARGETED + } + + } + } // diff --git a/nextflow.config b/nextflow.config index 1cf99223..040a945a 100644 --- a/nextflow.config +++ b/nextflow.config @@ -15,11 +15,11 @@ params { // Enable targeted/panel mode; WGTS run by default targeted = false - // Isofox user inputs - isofox_counts = null + // Isofox user input files + isofox_counts = null isofox_gc_ratios = null - isofox_gene_ids = null - isofox_tpm_norm = null + isofox_gene_ids = null + isofox_tpm_norm = null // Process configuration processes_manual = false @@ -49,8 +49,6 @@ params { // Other workflow inputs and options linx_gene_id_file = null isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' - isofox_read_length = params.targeted === false ? 151 : 93 - use_isofox_exp_counts_cache = false // Config options custom_config_version = 'master' diff --git a/nextflow_schema.json b/nextflow_schema.json index e32fdf62..87c91d37 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -120,12 +120,6 @@ "description": "Semicolon-separated list of Isofox functions to run", "default": "TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS", "fa_icon": "fas fa-cog" - }, - "use_isofox_exp_counts_cache": { - "type": "boolean", - "description": "Use the 151 bp read expected counts provided by the HMF bundle for Isofox", - "default": false, - "fa_icon": "fas fa-cog" } } }, diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf index ba42481d..86d0b9bd 100644 --- a/subworkflows/local/isofox_quantification.nf +++ b/subworkflows/local/isofox_quantification.nf @@ -44,22 +44,6 @@ workflow ISOFOX_QUANTIFICATION { ch_isofox_inputs = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional') } - // Set Isofox cache files - // NOTE(SW): the Isofox expected count file is read length dependent so required users to explicitly use expect - // counts generated for 151 bp reads that is available in the HMF reference bundle. When not specifying an - // expected count file, Isofox will automatically create one for the computed read length. However, doing so - // greatly increases runtime. - // NOTE(SW): consider alternative approaches for using the expected count file e.g. generate once at runtime, - // then use for all samples; generate all possible read lengths outside of pipeline and store on a remote for - // retrieval at runtime (requires inference of read length) - - // TODO(SW): this must be improved to allow users to set input file, use cache, or generate at runtime; - // currently does not update functions - // NOTE(SW): forcing use of cache for now since this feature is incomplete - - //isofox_counts = params.use_isofox_exp_counts_cache ? isofox_counts : [] - isofox_counts = isofox_counts - // Run process ISOFOX( ch_isofox_inputs, From 276e6e8acd483d10853098f67e979992a369871e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 3 Oct 2023 18:12:22 +1100 Subject: [PATCH 232/562] Fix whitespace --- lib/WorkflowMain.groovy | 2 ++ nextflow.config | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 5655da5f..414af56c 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -141,9 +141,11 @@ class WorkflowMain { } if (run_mode == Constants.RunMode.RNA) { + if (!params.containsKey('run_type')) { params.run_type = 'tumor_only' } + } if (params.targeted === true) { diff --git a/nextflow.config b/nextflow.config index 040a945a..67c5f542 100644 --- a/nextflow.config +++ b/nextflow.config @@ -27,9 +27,9 @@ params { processes_exclude = null // Reference genome information; iGenomes is effectively disabled - genome = null - igenomes_base = 's3://ngi-igenomes/igenomes' - igenomes_ignore = false + genome = null + igenomes_base = 's3://ngi-igenomes/igenomes' + igenomes_ignore = false // Boilerplate options outdir = null From bc9e871a6430b06890c6da17669e739999d8ab47 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 4 Oct 2023 09:23:50 +1100 Subject: [PATCH 233/562] =?UTF-8?q?Bump=20LILAC=20version:=201.5.1=20?= =?UTF-8?q?=E2=86=92=201.5.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/lilac/Dockerfile | 2 +- modules/local/lilac/main.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/lilac/Dockerfile b/modules/local/lilac/Dockerfile index cc6df91c..d3c643bf 100644 --- a/modules/local/lilac/Dockerfile +++ b/modules/local/lilac/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/lilac/ && \ - wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.5.1/lilac_v1.5.1.jar' + wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.5.2/lilac_v1.5.2.jar' USER mambauser diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index bd3f7a23..6245d2d3 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -2,7 +2,7 @@ process LILAC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/lilac:1.5.1--0' + container 'docker.io/scwatts/lilac:1.5.2--0' input: tuple val(meta), path(normal_dna_bam), path(normal_dna_bai), path(tumor_dna_bam), path(tumor_dna_bai), path(tumor_rna_bam), path(tumor_rna_bai), path(purple_dir) From e406740ec7628092bcf2ffb8d8b2f4f3d21fecc0 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 23 Oct 2023 16:06:58 +1100 Subject: [PATCH 234/562] =?UTF-8?q?Bump=20Isofox=20version:=201.7=20?= =?UTF-8?q?=E2=86=92=201.7.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/local/isofox/Dockerfile | 2 +- modules/local/isofox/main.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/isofox/Dockerfile b/modules/local/isofox/Dockerfile index 791a3c31..55c301ad 100644 --- a/modules/local/isofox/Dockerfile +++ b/modules/local/isofox/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/isofox/ && \ - wget -O /opt/isofox/isofox.jar 'https://github.com/hartwigmedical/hmftools/releases/download/isofox-v1.7/isofox_v1.7.jar' + wget -O /opt/isofox/isofox.jar 'https://github.com/hartwigmedical/hmftools/releases/download/isofox-v1.7.1/isofox_v1.7.1.jar' USER mambauser diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index a6e914ea..b376104e 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -2,7 +2,7 @@ process ISOFOX { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/isofox:1.7--0' + container 'docker.io/scwatts/isofox:1.7.1--0' input: tuple val(meta), path(bam), path(bai) From 6307faa51cf64778308d3678df204f9b461db1c2 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 25 Oct 2023 15:38:41 +1000 Subject: [PATCH 235/562] Refactor data flow and channel logic (#1) --- assets/samplesheet.csv | 20 +- assets/schema_input.json | 12 +- conf/modules.config | 31 +- ...ters.config => targeted_parameters.config} | 0 conf/test.config | 3 +- lib/Constants.groovy | 39 ++- lib/Processes.groovy | 54 +-- lib/Utils.groovy | 255 ++++++++++++-- lib/WorkflowMain.groovy | 96 ++---- lib/WorkflowOncoanalyser.groovy | 38 +-- main.nf | 11 +- modules.json | 12 +- modules/local/bamtools/main.nf | 4 +- modules/local/chord/main.nf | 8 +- modules/local/cobalt/meta.yml | 4 +- modules/local/cuppa/main.nf | 50 +-- modules/local/cuppa/meta.yml | 3 + .../custom/lilac_realign_reads_lilac/main.nf | 16 +- modules/local/gpgr/linx/main.nf | 6 +- modules/local/isofox/main.nf | 2 +- modules/local/lilac/main.nf | 2 +- modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/main.nf | 4 +- modules/local/linx/visualiser/main.nf | 50 ++- modules/local/orange/main.nf | 9 +- modules/local/orange/meta.yml | 8 +- modules/local/pave/germline/main.nf | 4 +- modules/local/pave/somatic/main.nf | 4 +- modules/local/sage/germline/main.nf | 8 - modules/local/sigs/main.nf | 2 +- modules/local/svprep/preprocess/main.nf | 10 +- modules/local/svprep/svprep/main.nf | 12 +- modules/local/virusbreakend/main.nf | 4 +- modules/local/virusinterpreter/main.nf | 4 +- modules/nf-core/samtools/flagstat/main.nf | 4 +- .../samtools/flagstat/samtools-flagstat.diff | 11 +- nextflow.config | 8 +- nextflow_schema.json | 20 +- subworkflows/local/amber_profiling.nf | 41 ++- subworkflows/local/bamtools_metrics.nf | 157 +++++---- subworkflows/local/channel_inputs_purple.nf | 78 ----- subworkflows/local/chord_prediction.nf | 62 ++-- subworkflows/local/cobalt_profiling.nf | 68 ++-- subworkflows/local/cuppa_prediction.nf | 149 +++++--- subworkflows/local/flagstat_metrics.nf | 160 +++++---- subworkflows/local/gridss_svprep_calling.nf | 253 ++++++++------ subworkflows/local/gripss_filtering.nf | 154 ++++++--- subworkflows/local/isofox_quantification.nf | 48 ++- subworkflows/local/lilac_calling.nf | 256 +++++++------- subworkflows/local/linx_annotation.nf | 143 +++++--- subworkflows/local/linx_plotting.nf | 98 ++++-- subworkflows/local/orange_reporting.nf | 300 ++++++++++------- subworkflows/local/pave_annotation.nf | 160 +++++---- subworkflows/local/prepare_input.nf | 318 ------------------ subworkflows/local/prepare_reference.nf | 9 +- subworkflows/local/purple_calling.nf | 93 +++-- subworkflows/local/sage_append.nf | 191 +++++++---- subworkflows/local/sage_calling.nf | 191 ++++++++--- subworkflows/local/sigs_fitting.nf | 59 ++-- subworkflows/local/virusbreakend_calling.nf | 107 ++++-- workflows/targeted.nf | 245 ++++++++++---- workflows/wgts.nf | 225 ++++++++++--- 62 files changed, 2558 insertions(+), 1837 deletions(-) rename conf/{panel_parameters.config => targeted_parameters.config} (100%) delete mode 100644 subworkflows/local/channel_inputs_purple.nf delete mode 100644 subworkflows/local/prepare_input.nf diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index e2a94197..84d41336 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,8 +1,12 @@ -id,subject_name,sample_name,sample_type,filetype,filepath -SONE_1,SUBJECT_ONE,SAMPLE_ONE_TUMOR,tumor,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_one_tumor.bam -SONE_1,SUBJECT_ONE,SAMPLE_ONE_NORMAL,normal,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_one_normal.bam -STWO_1,SUBJECT_TWO,SAMPLE_TWO_TUMOR_1,tumor,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_two_tumor_one.bam -STWO_1,SUBJECT_TWO,SAMPLE_TWO_TUMOR_1,tumor,bam_wts,/Users/stephen/repos/hmftools_pipeline/sample_two_tumor_one.rna.bam -STWO_1,SUBJECT_TWO,SAMPLE_TWO_NORMAL,normal,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_two_normal.bam -STWO_2,SUBJECT_TWO,SAMPLE_TWO_TUMOR_2,tumor,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_two_tumor_two.bam -STWO_2,SUBJECT_TWO,SAMPLE_TWO_NORMAL,normal,bam_wgs,/Users/stephen/repos/hmftools_pipeline/sample_two_normal.bam +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath +subject_one__to__dna,subject_one,sample_a,tumor,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.bam + +subject_one__tn__dna,subject_one,sample_a,tumor,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.bam +subject_one__tn__dna,subject_one,sample_b,normal,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_b.bam + +subject_one__tn__dna_rna,subject_one,sample_a,tumor,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.bam +subject_one__tn__dna_rna,subject_one,sample_b,normal,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_b.bam +subject_one__tn__dna_rna,subject_one,sample_c,tumor,bam,rna,/Users/stephen/repos/oncoanalyser/subject_one/sample_c.bam + +subject_one__to__dna_rna,subject_one,sample_a,tumor,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.bam +subject_one__to__dna_rna,subject_one,sample_c,tumor,bam,rna,/Users/stephen/repos/oncoanalyser/subject_one/sample_c.bam diff --git a/assets/schema_input.json b/assets/schema_input.json index aa8e460d..36182151 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -7,18 +7,18 @@ "items": { "type": "object", "properties": { - "id": { + "group_id": { "type": "string", "pattern": "^\\S+$", - "errorMessage": "id must be provided and cannot contain spaces" + "errorMessage": "group_id must be provided and cannot contain spaces" }, - "subject_name": { + "subject_id": { "pattern": "^\\S+$", - "errorMessage": "subject_name must be provided and cannot contain spaces" + "errorMessage": "subject_id must be provided and cannot contain spaces" }, - "sample_name": { + "sample_id": { "pattern": "^\\S+$", - "errorMessage": "subject_name must be provided and cannot contain spaces" + "errorMessage": "subject_id must be provided and cannot contain spaces" }, "sample_type": { "pattern": "^\\S+$", diff --git a/conf/modules.config b/conf/modules.config index 3e16b77a..89cf7564 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -17,7 +17,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } @@ -26,7 +26,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } @@ -43,7 +43,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gridss/${filename}" } + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/gridss/${filename}" } ] } @@ -55,7 +55,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gripss/germline/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/gripss/germline/${filename}" }, ] } @@ -63,7 +63,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/gripss/somatic/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/gripss/somatic/${filename}" }, ] } @@ -75,7 +75,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/sage/${filename}" }, ] } @@ -83,7 +83,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/sage/${filename}" }, ] } @@ -92,7 +92,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/sage/append/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/sage/append/${filename}" }, ] } @@ -111,7 +111,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } @@ -140,6 +140,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, + pattern: '*/plot_all', saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/somatic_plots/" }, ] } @@ -157,7 +158,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/bamtools/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/bamtools/${filename}" }, ] } @@ -174,7 +175,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" } + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" } ] } @@ -183,7 +184,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/${filename}" }, ] } @@ -192,7 +193,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id}/virusbreakend/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/virusbreakend/${filename}" }, ] } @@ -231,7 +232,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.id_simple}/flagstats/${filename}" }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/flagstats/${filename}" }, ] } @@ -246,7 +247,7 @@ process { return null } else { def tokens = filename.split('[/]') - return "${meta.id}/orange/${tokens[-1]}" + return "${meta.key}/orange/${tokens[-1]}" } } ] diff --git a/conf/panel_parameters.config b/conf/targeted_parameters.config similarity index 100% rename from conf/panel_parameters.config rename to conf/targeted_parameters.config diff --git a/conf/test.config b/conf/test.config index 56c3ae60..615b8427 100644 --- a/conf/test.config +++ b/conf/test.config @@ -49,8 +49,7 @@ params { genome = 'GRCh37_hmf' ref_data_virusbreakenddb_path = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/reference_data/virusbreakend/virusbreakenddb_test.tar.gz' - ref_data_known_fusion_data = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/known_fusion_data_custom.csv' + //ref_data_known_fusion_data = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/known_fusion_data_custom.csv' linx_gene_id_file = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/fusion_genes.csv' - use_isofox_exp_counts_cache = true } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 899d364c..10474f62 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -30,15 +30,9 @@ class Constants { static Integer DEFAULT_ISOFOX_READ_LENGTH_TARGETED = 93 - static enum RunType { - TUMOR_NORMAL, - TUMOR_ONLY, - } - static enum RunMode { - DNA, - RNA, - DNA_RNA, + TARGETED, + WGTS, } static enum Process { @@ -70,14 +64,18 @@ class Constants { BAMTOOLS, COBALT_DIR, GRIDSS_VCF, + GRIDSS_VCF_TBI, GRIPSS_VCF, + GRIPSS_VCF_TBI, GRIPSS_UNFILTERED_VCF, + GRIPSS_UNFILTERED_VCF_TBI, ISOFOX_DIR, LILAC_DIR, LINX_ANNO_DIR, PAVE_VCF, PURPLE_DIR, SAGE_VCF, + SAGE_APPEND_VCF, VIRUSINTERPRETER_DIR, // ORANGE specific CHORD_DIR, @@ -164,6 +162,16 @@ class Constants { SampleType.NORMAL, SequenceType.DNA, ], + SAGE_APPEND_VCF_TUMOR: [ + FileType.SAGE_APPEND_VCF, + SampleType.TUMOR, + [SequenceType.DNA_RNA], + ], + SAGE_APPEND_VCF_NORMAL: [ + FileType.SAGE_APPEND_VCF, + SampleType.NORMAL, + [SequenceType.DNA_RNA], + ], PAVE_VCF_TUMOR: [ FileType.PAVE_VCF, @@ -187,16 +195,31 @@ class Constants { [SampleType.TUMOR, SampleType.TUMOR_NORMAL], SequenceType.DNA, ], + GRIPSS_VCF_TUMOR_TBI: [ + FileType.GRIPSS_VCF_TBI, + [SampleType.TUMOR, SampleType.TUMOR_NORMAL], + SequenceType.DNA, + ], GRIPSS_VCF_NORMAL: [ FileType.GRIPSS_VCF, SampleType.NORMAL, SequenceType.DNA, ], + GRIPSS_VCF_NORMAL_TBI: [ + FileType.GRIPSS_VCF_TBI, + SampleType.NORMAL, + SequenceType.DNA, + ], GRIPSS_UNFILTERED_VCF_TUMOR: [ FileType.GRIPSS_UNFILTERED_VCF, [SampleType.TUMOR, SampleType.TUMOR_NORMAL], SequenceType.DNA, ], + GRIPSS_UNFILTERED_VCF_TUMOR_TBI: [ + FileType.GRIPSS_UNFILTERED_VCF_TBI, + [SampleType.TUMOR, SampleType.TUMOR_NORMAL], + SequenceType.DNA, + ], GRIPSS_UNFILTERED_VCF_NORMAL: [ FileType.GRIPSS_UNFILTERED_VCF, SampleType.NORMAL, diff --git a/lib/Processes.groovy b/lib/Processes.groovy index a265803e..f91fc606 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -4,58 +4,8 @@ import Utils class Processes { - public static setProcesses(run_mode, manual_select, targeted_mode, log) { - def processes = [] - - if (manual_select) { - return processes - } - - if (run_mode === Constants.RunMode.DNA || run_mode === Constants.RunMode.DNA_RNA) { - - processes += [ - Constants.Process.AMBER, - Constants.Process.BAMTOOLS, - Constants.Process.COBALT, - Constants.Process.FLAGSTAT, - Constants.Process.GRIDSS, - Constants.Process.GRIPSS, - Constants.Process.LILAC, - Constants.Process.LINX, - Constants.Process.ORANGE, - Constants.Process.PAVE, - Constants.Process.PURPLE, - Constants.Process.SAGE, - ] - - if (targeted_mode === false) { - processes += [ - Constants.Process.CHORD, - Constants.Process.CUPPA, - Constants.Process.SIGS, - Constants.Process.VIRUSINTERPRETER, - ] - } - - } - - if (run_mode === Constants.RunMode.RNA || run_mode === Constants.RunMode.DNA_RNA) { - - processes += [Constants.Process.ISOFOX] - - // TODO(SW): understand whether Hartwig will offer RNA-only panel processing - - if (targeted_mode === false) { - processes += [Constants.Process.CUPPA] - } - - } - - return processes - } - - public static getRunStages(run_mode, include, exclude, manual_select, targeted_mode, log) { - def processes = this.setProcesses(run_mode, manual_select, targeted_mode, log) + public static getRunStages(include, exclude, manual_select, log) { + def processes = manual_select ? [] : Constants.Process.values().toList() def include_list = this.getProcessList(include, log) def exclude_list = this.getProcessList(exclude, log) this.checkIncludeExcludeList(include_list, exclude_list, log) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index f764cd96..1a73fe3f 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -5,9 +5,183 @@ import org.yaml.snakeyaml.Yaml import nextflow.Nextflow +import nextflow.splitter.SplitterEx class Utils { + public static parseInput(input_fp_str, stub_run, log) { + + // NOTE(SW): using Nextflow .splitCsv channel operator, hence sould be easily interchangable + + def input_fp = nextflow.Nextflow.file(input_fp_str) + def inputs = nextflow.splitter.SplitterEx.splitCsv(input_fp, [header: true]) + .groupBy { it['group_id'] } + .collect { group_id, entries -> + + def meta = [group_id: group_id] + def sample_keys = [] as Set + + // Process each entry + entries.each { + // Add subject id if absent or check if current matches existing + if (meta.containsKey('subject_id') && meta.subject_id != it.subject_id) { + log.error "got unexpected subject name for ${group_id} ${meta.subject_id}: ${it.subject_id}" + System.exit(1) + } else { + meta.subject_id = it.subject_id + } + + + // Sample type + def sample_type_enum = Utils.getEnumFromString(it.sample_type, Constants.SampleType) + if (!sample_type_enum) { + def sample_type_str = Utils.getEnumNames(Constants.SampleType).join('\n - ') + log.error "received invalid sample type: '${it.sample_type}'. Valid options are:\n - ${sample_type_str}" + System.exit(1) + } + + // Sequence type + def sequence_type_enum = Utils.getEnumFromString(it.sequence_type, Constants.SequenceType) + if (!sequence_type_enum) { + def sequence_type_str = Utils.getEnumNames(Constants.SequenceType).join('\n - ') + log.error "received invalid sequence type: '${it.sequence_type}'. Valid options are:\n - ${sequence_type_str}" + System.exit(1) + } + + // Filetype + def filetype_enum = Utils.getEnumFromString(it.filetype, Constants.FileType) + if (!filetype_enum) { + def filetype_str = Utils.getEnumNames(Constants.FileType).join('\n - ') + log.error "received invalid file type: '${it.filetype}'. Valid options are:\n - ${filetype_str}" + System.exit(1) + } + + def sample_key = [sample_type_enum, sequence_type_enum] + def meta_sample = meta.get(sample_key, [sample_id: it.sample_id]) + + if (meta_sample.sample_id != it.sample_id) { + log.error "got unexpected sample name for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${sample_name}" + System.exit(1) + } + + if (meta_sample.containsKey(filetype_enum)) { + log.error "got duplicate file for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${filetype_enum}" + System.exit(1) + } + + meta_sample[filetype_enum] = it.filepath + + // Record sample key to simplify iteration later on + sample_keys << sample_key + + } + + // Check that required indexes are provided or are accessible + sample_keys.each { sample_key -> + + meta[sample_key]*.key.each { key -> + + // NOTE(SW): I was going to use two maps but was unable to get an enum map to compile + + def index_enum + def index_str + + if (key === Constants.FileType.BAM) { + index_enum = Constants.FileType.BAI + index_str = 'bai' + } else if (key === Constants.FileType.GRIDSS_VCF) { + index_enum = Constants.FileType.GRIDSS_VCF_TBI + index_str = 'vcf' + } else if (key === Constants.FileType.GRIPSS_VCF) { + index_enum = Constants.FileType.GRIPSS_VCF_TBI + index_str = 'vcf' + } else if (key === Constants.FileType.GRIPSS_UNFILTERED_VCF) { + index_enum = Constants.FileType.GRIPSS_UNFILTERED_VCF_TBI + index_str = 'vcf' + } else { + return + } + + if (meta[sample_key].containsKey(index_enum)) { + return + } + + def fp = meta[sample_key][key] + def index_fp = nextflow.Nextflow.file("${fp}.${index_str}") + + if (!index_fp.exists() && !stub_run) { + def (sample_type, sequence_type) = sample_key + log.error "no index provided or found for ${meta.group_id} ${sample_type}/${sequence_type}: ${key}: ${fp}" + System.exit(1) + } + + meta[sample_key][index_enum] = index_fp + + } + } + + return meta + } + + return inputs + } + + public static void validateInput(inputs, run_config, log) { + + def sample_keys = [ + [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], + [Constants.SampleType.TUMOR, Constants.SequenceType.RNA], + [Constants.SampleType.NORMAL, Constants.SequenceType.DNA], + ] + + inputs.each { meta -> + + // Require BAMs for each defined sample type + // NOTE(SW): repeating key pairs above to avoid having to duplicate error messages + sample_keys.each { key -> + + if (!meta.containsKey(key)) { + return + } + + def (sample_type, sequence_type) = key + + if (!meta[key].containsKey(Constants.FileType.BAM)) { + log.error "no BAM provided for ${meta.group_id} ${sample_type}/${sequence_type}\n\n" + + "NB: BAMs are always required as they are the basis to determine input sample type." + System.exit(1) + } + + } + + // Do not allow normal DNA in targeted mode and restrict targeted RNA analysis to TSO500 + if (run_config.mode === Constants.RunMode.TARGETED) { + + if (Utils.hasNormalDnaBam(meta)) { + log.error "targeted mode is not compatible with the normal DNA BAM provided for ${meta.group_id}\n\n" + + "The targeted workflow supports only tumor DNA BAMs (and tumor RNA BAMs for TSO500)" + System.exit(1) + } + + // Restrict targeted RNA inputs to TSO500 + if (Utils.hasTumorRnaBam(meta) && run_config.panel != 'tso500') { + def panel = run_config.panel.toUpperCase() + log.error "the ${panel} panel is not compatible with the tumor RNA BAM provided for ${meta.group_id}\n\n" + + "Only the TSO500 panel supports tumor RNA analysis" + System.exit(1) + } + + } + + // Do not allow normal DNA only + if (Utils.hasNormalDnaBam(meta) && !Utils.hasTumorDnaBam(meta)) { + log.error "germline only mode not supported, found only a normal DNA BAM for ${meta.group_id}\n" + System.exit(1) + } + + } + } + // // When running with -profile conda, warn if channels have not been set-up appropriately // @@ -70,38 +244,63 @@ class Utils { // Sample names static public getTumorDnaSampleName(meta) { - return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.DNA]) + def meta_sample = meta[Constants.SampleType.TUMOR, Constants.SequenceType.DNA] + return meta_sample['sample_id'] } static public getTumorRnaSampleName(meta) { - return getMetaEntry(meta, ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) + def meta_sample = meta[Constants.SampleType.TUMOR, Constants.SequenceType.RNA] + return meta_sample['sample_id'] } static public getNormalDnaSampleName(meta) { - return getMetaEntry(meta, ['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.DNA]) + def meta_sample = meta[Constants.SampleType.NORMAL, Constants.SequenceType.DNA] + return meta_sample['sample_id'] } // Files static public getTumorDnaBam(meta) { - return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.DNA]) + def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.DNA], [:]) + return meta_sample.getOrDefault(Constants.FileType.BAM, null) + } + + static public getTumorDnaBai(meta) { + def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.DNA], [:]) + return meta_sample.getOrDefault(Constants.FileType.BAI, null) + } + + static public hasTumorDnaBam(meta) { + return getTumorDnaBam(meta) !== null } static public getTumorRnaBam(meta) { - return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) + def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.RNA], [:]) + return meta_sample.getOrDefault(Constants.FileType.BAM, null) + } + + static public getTumorRnaBai(meta) { + def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.RNA], [:]) + return meta_sample.getOrDefault(Constants.FileType.BAI, null) } + static public hasTumorRnaBam(meta) { + return getTumorRnaBam(meta) !== null + } + + static public getNormalDnaBam(meta) { - return getMetaEntry(meta, [Constants.FileType.BAM, Constants.SampleType.NORMAL, Constants.SequenceType.DNA]) + def meta_sample = meta.getOrDefault([Constants.SampleType.NORMAL, Constants.SequenceType.DNA], [:]) + return meta_sample.getOrDefault(Constants.FileType.BAM, null) } + static public getNormalDnaBai(meta) { + def meta_sample = meta.getOrDefault([Constants.SampleType.NORMAL, Constants.SequenceType.DNA], [:]) + return meta_sample.getOrDefault(Constants.FileType.BAI, null) + } - static public getMetaEntry(meta, key) { - if (! meta.containsKey(key)) { - System.err.println "\nERROR: meta does not contain key ${key}: ${meta}" - System.exit(1) - } - return meta.getAt(key) + static public hasNormalDnaBam(meta) { + return getNormalDnaBam(meta) !== null } @@ -109,20 +308,36 @@ class Utils { def run_mode_enum = Utils.getEnumFromString(run_mode, Constants.RunMode) if (!run_mode_enum) { def run_modes_str = Utils.getEnumNames(Constants.RunMode).join('\n - ') - log.error "\nERROR: recieved an invalid run mode: '${run_mode}'. Valid options are:\n - ${run_modes_str}" + log.error "recieved an invalid run mode: '${run_mode}'. Valid options are:\n - ${run_modes_str}" System.exit(1) } return run_mode_enum } - static public getRunType(run_type, log) { - def run_type_enum = Utils.getEnumFromString(run_type, Constants.RunType) - if (!run_type_enum) { - def run_types_str = Utils.getEnumNames(Constants.RunType).join('\n - ') - log.error "\nERROR: recieved an invalid run type: '${run_type}'. Valid options are:\n - ${run_types_str}" - System.exit(1) + + public static getInput(meta, key) { + + def result + def (key_filetype, key_filetypes, key_sequencetypes) = key + + for (key_sample in [key_filetypes, key_sequencetypes].combinations()) { + if (meta.containsKey(key_sample) && meta[key_sample].containsKey(key_filetype)) { + return meta[key_sample].getAt(key_filetype) + } + } + } + + public static hasExistingInput(meta, key) { + return getInput(meta, key) !== null + } + + public static selectCurrentOrExisting(val, meta, key) { + if (hasExistingInput(meta, key)) { + return getInput(meta, key) + } else { + return val } - return run_type_enum } + } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 414af56c..98d3f276 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -71,7 +71,7 @@ class WorkflowMain { // Check input has been provided if (!params.input) { - log.error "Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'" + log.error "no samplesheet provided, please supply one on the CLI with --input or in a configuation file." System.exit(1) } } @@ -133,26 +133,14 @@ class WorkflowMain { // Set defaults specific to run configuration without attempting to validate def run_mode - if (params.containsKey('run_mode')) { - run_mode = Utils.getRunMode(params.run_mode, log) + if (params.containsKey('mode') && params.mode !== null) { + run_mode = Utils.getRunMode(params.mode, log) } else { // Bad configuration, catch in validateParams return } - if (run_mode == Constants.RunMode.RNA) { - - if (!params.containsKey('run_type')) { - params.run_type = 'tumor_only' - } - - } - - if (params.targeted === true) { - - if (!params.containsKey('run_type')) { - params.run_type = 'tumor_only' - } + if (run_mode === Constants.RunMode.TARGETED) { // Attempt to set default panel data path; make no assumption on valid 'panel' value if (!params.containsKey('ref_data_panel_data_path') && params.containsKey('panel')) { @@ -168,11 +156,9 @@ class WorkflowMain { } def stages = Processes.getRunStages( - run_mode, params.processes_include, params.processes_exclude, params.processes_manual, - params.targeted, log, ) @@ -190,9 +176,9 @@ class WorkflowMain { if (stages.isofox && !params.containsKey('isofox_read_length')) { - if (params.targeted === false) { + if (run_mode === Constants.RunMode.WGTS) { params.isofox_read_length = Constants.DEFAULT_ISOFOX_READ_LENGTH_WTS - } else { + } else if (run_mode === Constants.RunMode.TARGETED) { params.isofox_read_length = Constants.DEFAULT_ISOFOX_READ_LENGTH_TARGETED } @@ -208,7 +194,7 @@ class WorkflowMain { // Common parameters if (!params.genome) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome must be set using the --genome CLI argument or in a configuration file.\n" + " Currently, the available genome are:\n" + " ${params.genomes.keySet().join(", ")}\n" + @@ -274,10 +260,10 @@ class WorkflowMain { // Run configuration specific parameters - if (!params.run_mode) { + if (!params.mode) { def run_modes = Utils.getEnumNames(Constants.RunMode).join('\n - ') - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Run mode must be set using the --run_mode CLI argument or in a configuration \n" + + log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Run mode must be set using the --mode CLI argument or in a configuration \n" + " file.\n" + " Currently, the available run modes are:\n" + " - ${run_modes}\n" + @@ -285,45 +271,14 @@ class WorkflowMain { System.exit(1) } - if (!params.run_type) { - def run_types = Utils.getEnumNames(Constants.RunType).join('\n - ') - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Run type must be set using the --run_type CLI argument or in a configuration \n" + - " file.\n" + - " Currently, the available run types are:\n" + - " - ${run_types}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - - def run_mode = Utils.getRunMode(params.run_mode, log) - def run_type = Utils.getRunType(params.run_type, log) + def run_mode = Utils.getRunMode(params.mode, log) - if (run_mode == Constants.RunMode.RNA) { - if (run_type != Constants.RunType.TUMOR_ONLY) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " The WTS run mode does not support tumor/normal data, please adjust the CLI \n" + - " --run_type option or corresponding configuration file.\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - - } - - if (params.targeted === true) { - - if (run_type != Constants.RunType.TUMOR_ONLY) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " The panel run mode does not support tumor/normal data, please adjust the CLI \n" + - " --run_type option or corresponding configuration file.\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } + if (run_mode === Constants.RunMode.TARGETED) { if (!params.containsKey('panel')) { def panels = Constants.PANELS_DEFINED.join('\n - ') - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " A panel is required to be set using the --panel CLI argument or in a \n" + " configuration file.\n" + " Currently, the available panels are:\n" + @@ -334,7 +289,7 @@ class WorkflowMain { } else if (!Constants.PANELS_DEFINED.contains(params.panel)) { def panels = Constants.PANELS_DEFINED.join('\n - ') - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " The ${params.panel} is not defined. Currently, the available panels are:\n" + " - ${panels}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" @@ -343,40 +298,33 @@ class WorkflowMain { } if (params.panel == 'hmf' && params.ref_data_genome_version == '37') { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " The Hartwig panel (hmf) is not available for the GRCh37 reference genome.\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) } - def rna_run = run_mode == Constants.RunMode.RNA || run_mode == Constants.RunMode.DNA_RNA - if (rna_run && params.panel != 'tso500') { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Currently only the TSO500 panel (tso500) supports RNA analysis.\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - } } - public static getRunConfig(params, log) { - def run_mode = Utils.getRunMode(params.run_mode, log) - def run_type = Utils.getRunType(params.run_type, log) + public static getRunConfig(params, inputs, log) { + + def run_mode = Utils.getRunMode(params.mode, log) + def stages = Processes.getRunStages( - run_mode, params.processes_include, params.processes_exclude, params.processes_manual, - params.targeted, log, ) return [ mode: run_mode, - type: run_type, + panel: run_mode === Constants.RunMode.TARGETED ? params.panel : null, stages: stages, + has_dna: inputs.any { it.containsKey([Constants.SampleType.TUMOR, Constants.SequenceType.DNA]) }, + has_rna: inputs.any { it.containsKey([Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) }, ] } } diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 2da965cc..97f0a030 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -71,30 +71,25 @@ class WorkflowOncoanalyser { return groupByMeta([:], *channels) } - public static getInput(Map named_args, ch, key) { - def input_type = named_args.getOrDefault('type', 'required') - return ch.map { meta -> - def result - for (key_combination in key.combinations()) { - if (meta.containsKey(key_combination)) { - result = [meta, meta.getAt(key_combination)] - break - } - } + public static getInput(Map named_args, meta, key) { - if (result) { - return result - } + def result + def (key_filetype, key_filetypes, key_sequencetypes) = key - if (input_type == 'required') { - return [Constants.PLACEHOLDER_META, null] - } else if (input_type == 'optional') { - return [meta, []] - } else { - System.err.println "ERROR: got bad input type: ${input_type}" - System.exit(1) + for (key_sample in [key_filetypes, key_sequencetypes].combinations()) { + if (meta.containsKey(key_sample) && meta[key_sample].containsKey(key_filetype)) { + // NOTE(SW): could return early here then false below + return meta[key_sample].getAt(key_filetype) + break } } + + if (result) { + return result + } else { + return false + } + } // NOTE(SW): function signature required to catch where no named arguments are passed @@ -102,11 +97,10 @@ class WorkflowOncoanalyser { return getInput([:], ch, key) } - public static joinMeta(Map named_args, ch_a, ch_b) { // NOTE(SW): the cross operator is used to allow many-to-one relationship between ch_output // and ch_metas - def key_a = named_args.getOrDefault('key_a', 'id') + def key_a = named_args.getOrDefault('key_a', 'group_id') def key_b = named_args.getOrDefault('key_b', 'key') def ch_ready_a = ch_a.map { [it[0].getAt(key_b), it[1..-1]] } def ch_ready_b = ch_b.map { meta -> [meta.getAt(key_a), meta] } diff --git a/main.nf b/main.nf index 4bcccaff..c36542a7 100644 --- a/main.nf +++ b/main.nf @@ -51,15 +51,18 @@ include { WGTS } from './workflows/wgts' // // WORKFLOW: Run main nf-core/oncoanalyser analysis pipeline // - -run_mode = Utils.getRunMode(params.run_mode, log) +run_mode = Utils.getRunMode(params.mode, log) workflow NFCORE_ONCOANALYSER { - if (params.targeted == false) { + + if (run_mode === Constants.RunMode.WGTS) { WGTS() - } else { + } else if (run_mode === Constants.RunMode.TARGETED) { TARGETED() + } else { + assert false } + } /* diff --git a/modules.json b/modules.json index 1d2c2c13..b8c7002a 100644 --- a/modules.json +++ b/modules.json @@ -7,19 +7,23 @@ "nf-core": { "bwa/index": { "branch": "master", - "git_sha": "9518fa4f65f3fb8cde24fde7d40333b39ec8fd65" + "git_sha": "9518fa4f65f3fb8cde24fde7d40333b39ec8fd65", + "installed_by": ["modules"] }, "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "8022c68e7403eecbd8ba9c49496f69f8c49d50f0" + "git_sha": "8022c68e7403eecbd8ba9c49496f69f8c49d50f0", + "installed_by": ["modules"] }, "samtools/dict": { "branch": "master", - "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01" + "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", + "installed_by": ["modules"] }, "samtools/faidx": { "branch": "master", - "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01" + "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", + "installed_by": ["modules"] }, "samtools/flagstat": { "branch": "master", diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf index dab6341d..c34cbaf0 100644 --- a/modules/local/bamtools/main.nf +++ b/modules/local/bamtools/main.nf @@ -24,7 +24,7 @@ process BAMTOOLS { -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -cp ${task.ext.jarPath} \\ com.hartwig.hmftools.bamtools.metrics.BamMetrics \\ - -sample ${meta.id} \\ + -sample ${meta.sample_id} \\ -bam_file ${bam} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ @@ -41,7 +41,7 @@ process BAMTOOLS { stub: """ - touch ${meta.id}.wgsmetrics + touch ${meta.sample_id}.wgsmetrics echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf index d183ff37..6e5f8e0e 100644 --- a/modules/local/chord/main.nf +++ b/modules/local/chord/main.nf @@ -23,14 +23,14 @@ process CHORD { extractSigPredictHRD.R \\ ./ \\ - ${meta.id} \\ + ${meta.sample_id} \\ ${smlv_vcf} \\ ${sv_vcf} \\ ${genome_ver} \\ chord_signatures.txt \\ chord_prediction.txt - mv ${meta.id}_chord_signatures.txt ${meta.id}_chord_prediction.txt chord/ + mv ${meta.sample_id}_chord_signatures.txt ${meta.sample_id}_chord_prediction.txt chord/ cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -42,8 +42,8 @@ process CHORD { stub: """ mkdir -p chord/ - touch chord/${meta.id}_chord_signatures.txt - touch chord/${meta.id}_chord_prediction.txt + touch chord/${meta.sample_id}_chord_signatures.txt + touch chord/${meta.sample_id}_chord_prediction.txt echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/cobalt/meta.yml b/modules/local/cobalt/meta.yml index 27adc051..3b75d01c 100644 --- a/modules/local/cobalt/meta.yml +++ b/modules/local/cobalt/meta.yml @@ -22,7 +22,7 @@ input: pattern: "*.{bam}" - normal_bam: type: file - description: Normal BAM file + description: Normal BAM file (optional) pattern: "*.{bam}" - tumor_bai: type: file @@ -30,7 +30,7 @@ input: pattern: "*.{bai}" - normal_bai: type: file - description: Normal BAI file + description: Normal BAI file (optional) pattern: "*.{bai}" - gc_profile: type: file diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index 9735a13d..0a4ff2e3 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -8,6 +8,7 @@ process CUPPA { tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) val ref_genome_ver path cuppa_resources, stageAs: 'cuppa_reference_data' + val classifier output: tuple val(meta), path('cuppa/'), emit: cuppa_dir @@ -19,40 +20,23 @@ process CUPPA { script: def args = task.ext.args ?: '' - def has_rna = isofox_dir - def has_dna = purple_dir || linx_dir - if (has_dna && (!purple_dir || !linx_dir)) { - exit 1, "ERROR: CUPPA_CLASSIFIER: DNA classification requires both PURPLE and LINX inputs" - } - - def categories_val - if (has_dna && has_rna) { - categories_val = 'ALL' - } else if (has_dna) { - categories_val = 'DNA' - } else if (has_rna) { - categories_val = 'RNA' - } else { - exit 1, "ERROR: CUPPA_CLASSIFIER: either PURPLE and LINX inputs or Isofox inputs are required" - } - """ # Symlink input files into a single directory mkdir -p sample_data/ - if [[ ${categories_val} == 'DNA' || ${categories_val} == 'ALL' ]]; then + if [[ ${classifier} == 'DNA' || ${classifier} == 'ALL' ]]; then find -L ${purple_dir} ${linx_dir} ${virusinterpreter_dir} -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; fi - if [[ ${categories_val} == 'RNA' ]]; then + if [[ ${classifier} == 'RNA' ]]; then find -L ${isofox_dir} -maxdepth 1 -type f -exec ln -fs ../{} sample_data/ \\; - elif [[ ${categories_val} == 'ALL' ]]; then + elif [[ ${classifier} == 'ALL' ]]; then # NOTE(SW): CUPPA requires that the RNA sample name matches the DNA sample name for fp in \$(find -L ${isofox_dir} -maxdepth 1 -type f); do - fn_out=\$(sed 's/^${meta.id_rna}/${meta.id}/' <<< \${fp##*/}); + fn_out=\$(sed 's/^${meta.sample_rna_id}/${meta.sample_id}/' <<< \${fp##*/}); cp \${fp} sample_data/\${fn_out} done; # Rename identifier in the summary file - sed -i 's/^${meta.id_rna}/${meta.id}/g' sample_data/${meta.id}.isf.summary.csv; + sed -i 's/^${meta.sample_rna_id}/${meta.sample_id}/g' sample_data/${meta.sample_id}.isf.summary.csv; fi; mkdir -p cuppa/ @@ -60,18 +44,18 @@ process CUPPA { java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ - -sample ${meta.id} \\ + -sample ${meta.sample_id} \\ -sample_data_dir sample_data/ \\ - -categories ${categories_val} \\ + -categories ${classifier} \\ -ref_data_dir ${cuppa_resources} \\ -ref_genome_version ${ref_genome_ver} \\ -create_pdf \\ -output_dir cuppa/ - if [[ ${categories_val} == 'DNA' || ${categories_val} == 'ALL' ]]; then + if [[ ${classifier} == 'DNA' || ${classifier} == 'ALL' ]]; then python ${task.ext.chartScriptPath} \\ - -sample ${meta.id} \\ - -sample_data cuppa/${meta.id}.cup.data.csv \\ + -sample ${meta.sample_id} \\ + -sample_data cuppa/${meta.sample_id}.cup.data.csv \\ -output_dir cuppa/; fi @@ -85,12 +69,12 @@ process CUPPA { stub: """ mkdir -p cuppa/ - touch cuppa/${meta.id}.cup.data.csv - touch cuppa/${meta.id}.cuppa.conclusion.txt - touch cuppa/${meta.id}_cup_report.pdf - touch cuppa/${meta.id}.cup.report.summary.png - touch cuppa/${meta.id}.cup.report.features.png - touch cuppa/${meta.id}.cuppa.chart.png + touch cuppa/${meta.sample_id}.cup.data.csv + touch cuppa/${meta.sample_id}.cuppa.conclusion.txt + touch cuppa/${meta.sample_id}_cup_report.pdf + touch cuppa/${meta.sample_id}.cup.report.summary.png + touch cuppa/${meta.sample_id}.cup.report.features.png + touch cuppa/${meta.sample_id}.cuppa.chart.png echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/cuppa/meta.yml b/modules/local/cuppa/meta.yml index e8488ce2..7518dac4 100644 --- a/modules/local/cuppa/meta.yml +++ b/modules/local/cuppa/meta.yml @@ -31,6 +31,9 @@ input: - cuppa_resources: type: directory description: CUPPA resource directory + - classifer: + type: string + description: CUPPA classifier to use output: - meta: type: map diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf index a76778ee..57f3bcfb 100644 --- a/modules/local/custom/lilac_realign_reads_lilac/main.nf +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -20,19 +20,19 @@ process CUSTOM_REALIGNREADS { def args = task.ext.args ?: '' """ - sambamba sort -n ${bam} -o ${meta.id}_sorted.bam - samtools fastq -@${task.threads} ${meta.id}_sorted.bam \\ - -1 ${meta.id}_R1.fastq.gz \\ - -2 ${meta.id}_R2.fastq.gz \\ - -0 ${meta.id}_other.fastq.gz \\ - -s ${meta.id}_singleton.fastq.gz; + sambamba sort -n ${bam} -o ${meta.sample_id}_sorted.bam + samtools fastq -@${task.threads} ${meta.sample_id}_sorted.bam \\ + -1 ${meta.sample_id}_R1.fastq.gz \\ + -2 ${meta.sample_id}_R2.fastq.gz \\ + -0 ${meta.sample_id}_other.fastq.gz \\ + -s ${meta.sample_id}_singleton.fastq.gz; bwa mem \\ -t${task.cpus} \\ -Y \\ ${reference} \\ - ${meta.id}_R1.fastq.gz \\ - ${meta.id}_R2.fastq.gz | \\ + ${meta.sample_id}_R1.fastq.gz \\ + ${meta.sample_id}_R2.fastq.gz | \\ samtools sort -T tmp -o ${bam.baseName}.realigned.bam samtools index ${bam.baseName}.realigned.bam diff --git a/modules/local/gpgr/linx/main.nf b/modules/local/gpgr/linx/main.nf index decb0b34..5d3a6c01 100644 --- a/modules/local/gpgr/linx/main.nf +++ b/modules/local/gpgr/linx/main.nf @@ -20,10 +20,10 @@ process GPGR_LINX { """ gpgr.R linx \\ ${args} \\ - --sample ${meta.id} \\ + --sample ${meta.sample_id} \\ --plot ${linx_visualiser_dir}/ \\ --table ${linx_annotation_dir}/ \\ - --out ${meta.id}_linx.html + --out ${meta.sample_id}_linx.html cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -34,7 +34,7 @@ process GPGR_LINX { stub: """ - touch ${meta.id}_linx.html + touch ${meta.sample_id}_linx.html echo -e '${task.process}:\n stub: noversions\n' > versions.yml """ } diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index b376104e..9d215d1c 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -42,7 +42,7 @@ process ISOFOX { -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ - -sample ${meta.id} \\ + -sample ${meta.sample_id} \\ -bam_file ${bam} \\ ${functions_arg} \\ -read_length ${read_length} \\ diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 6245d2d3..cc6bfb88 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -2,7 +2,7 @@ process LILAC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/lilac:1.5.2--0' + container 'docker.io/scwatts/lilac:1.5.2--1' input: tuple val(meta), path(normal_dna_bam), path(normal_dna_bai), path(tumor_dna_bam), path(tumor_dna_bai), path(tumor_rna_bam), path(tumor_rna_bai), path(purple_dir) diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 6a9db783..9827e96b 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -25,7 +25,7 @@ process LINX_GERMLINE { -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ - -sample ${meta.id} \\ + -sample ${meta.sample_id} \\ -sv_vcf ${sv_vcf} \\ -germline \\ -ref_genome_version ${genome_ver} \\ diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index d65a7861..ad973b55 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -28,8 +28,8 @@ process LINX_SOMATIC { -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ - -sample ${meta.id} \\ - -sv_vcf ${purple_dir}/${meta.id}.purple.sv.vcf.gz \\ + -sample ${meta.sample_id} \\ + -sv_vcf ${purple_dir}/${meta.sample_id}.purple.sv.vcf.gz \\ -purple_dir ${purple_dir} \\ ${gene_id_file_arg} \\ -ref_genome_version ${genome_ver} \\ diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 89a502c7..f89ae097 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -10,8 +10,9 @@ process LINX_VISUALISER { path ensembl_data_resources output: - tuple val(meta), path('linx_visualiser/plot/'), emit: visualiser_dir - path 'versions.yml' , emit: versions + tuple val(meta), path('linx_visualiser/plot_all/') , emit: visualiser_dir_all + tuple val(meta), path('linx_visualiser/plot_reportable/'), emit: visualiser_dir_reportable + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -20,23 +21,52 @@ process LINX_VISUALISER { def args = task.ext.args ?: '' """ - # NOTE(SW): LINX v1.23.2 and current latest version (v1.23.6) require trailing slashes for the -plot_out and -data_out arguments since no filesystem separator is used when constructing fusion plot output filepaths. - # https://github.com/hartwigmedical/hmftools/blob/linx-v1.23.6/linx/src/main/java/com/hartwig/hmftools/linx/visualiser/circos/ChromosomeRangeExecution.java#L22-L29 - # https://github.com/hartwigmedical/hmftools/blob/linx-v1.23.6/linx/src/main/java/com/hartwig/hmftools/linx/visualiser/circos/FusionExecution.java#L18-L23 + # NOTE(SW): LINX v1.24.1 require trailing slashes for the -plot_out and -data_out arguments since no filesystem + # separator is used when constructing fusion plot output filepaths. + + # https://github.com/hartwigmedical/hmftools/blob/linx-v1.24.1/linx/src/main/java/com/hartwig/hmftools/linx/visualiser/circos/ChromosomeRangeExecution.java#L22-L29 + # https://github.com/hartwigmedical/hmftools/blob/linx-v1.24.1/linx/src/main/java/com/hartwig/hmftools/linx/visualiser/circos/FusionExecution.java#L18-L23 + + # Generate all chromosome and cluster plots by default + + java \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + -cp ${task.ext.jarPath} \\ + com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ + ${args} \\ + -sample ${meta.sample_id} \\ + -vis_file_dir ${linx_annotation_dir} \\ + -ref_genome_version ${genome_ver} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + -circos ${task.ext.circosPath} \\ + -threads ${task.cpus} \\ + -plot_out linx_visualiser/plot_all/ \\ + -data_out linx_visualiser/data_all/ + + # Rerun LINX to render only reportable cluster plots in a separate directory. While this is regenerating existing + # cluster plots, the number of reportable plots is generally very small and I prefer to rely on the internal LINX + # logic to determine whether a cluster is reportable rather than attempting to infer manually to copy out target + # plot files. + + # The ORANGE report receives only reportable clusters while the gpgr LINX report receives chromosome and all cluster + # plots. + + # https://github.com/hartwigmedical/hmftools/blob/linx-v1.24.1/linx/src/main/java/com/hartwig/hmftools/linx/visualiser/SampleData.java#L220-L236 java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -cp ${task.ext.jarPath} \\ com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ ${args} \\ - -sample ${meta.id} \\ + -sample ${meta.sample_id} \\ -vis_file_dir ${linx_annotation_dir} \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -circos ${task.ext.circosPath} \\ + -plot_reportable \\ -threads ${task.cpus} \\ - -plot_out linx_visualiser/plot/ \\ - -data_out linx_visualiser/data/ + -plot_out linx_visualiser/plot_reportable/ \\ + -data_out linx_visualiser/data_reportable/ cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -46,8 +76,8 @@ process LINX_VISUALISER { stub: """ - mkdir -p linx_visualiser/plot/ - touch linx_visualiser/plot/placeholder + mkdir -p linx_visualiser/plot_{all,reportable}/ + touch linx_visualiser/plot_{all,reportable}/placeholder echo -e '${task.process}:\n stub: noversions\n' > versions.yml """ } diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index aebf0add..227649fe 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -5,7 +5,7 @@ process ORANGE { container 'docker.io/scwatts/orange:2.7.0--0' input: - tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_dir), path(sage_germline_dir), path(purple_dir), path(smlv_somatic_vcf), path(smlv_germline_vcf), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter_dir), path(chord_dir), path(sigs_dir), path(lilac_dir), path(cuppa_dir), path(isofox_dir) + tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_somatic_dir), path(sage_germline_dir), path(smlv_somatic_vcf), path(smlv_germline_vcf), path(purple_dir), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter_dir), path(chord_dir), path(sigs_dir), path(lilac_dir), path(cuppa_dir), path(isofox_dir) val genome_ver path disease_ontology path cohort_mapping @@ -60,7 +60,10 @@ process ORANGE { mkdir -p \${purple_dir_local}/; find -L ${purple_dir} -maxdepth 1 -exec ln -fs ../{} \${purple_dir_local}/ \\; ln -sf ../${smlv_somatic_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.somatic.vcf.gz; - ln -sf ../${smlv_germline_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.germline.vcf.gz; + + if [[ -n "${smlv_germline_vcf}" ]]; then + ln -sf ../${smlv_germline_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.germline.vcf.gz; + fi; mkdir -p isofox_dir__prepared/; for fp in ${isofox_dir}/*; do @@ -89,7 +92,7 @@ process ORANGE { -primary_tumor_doids 162 \\ -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ -tumor_sample_flagstat_file ${flagstat_somatic} \\ - -sage_dir ${sage_dir} \\ + -sage_dir ${sage_somatic_dir} \\ -purple_dir \${purple_dir_local} \\ -purple_plot_dir \${purple_dir_local}/plot/ \\ -linx_dir ${linx_somatic_anno_dir} \\ diff --git a/modules/local/orange/meta.yml b/modules/local/orange/meta.yml index 31d2a1b0..3c6d9450 100644 --- a/modules/local/orange/meta.yml +++ b/modules/local/orange/meta.yml @@ -26,21 +26,21 @@ input: - flagstat_germline: type: file description: Somatic SAMtools flagstat output file (optional) - - sage_dir: + - sage_somatic_dir: type: directory description: SAGE somatic output directory - sage_germline_dir: type: directory description: SAGE germline output directory (optional) - - purple_dir: - type: directory - description: PURPLE output directory - smlv_somatic_vcf: type: file description: Small somatic variant VCF file (annotated with RNA data) (optional) - smlv_germline_vcf: type: file description: Small germline variant VCF file (annotated with RNA data) (optional) + - purple_dir: + type: directory + description: PURPLE output directory - linx_somatic_anno_dir: type: directory description: LINX somatic annotation output directory diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 89a568cd..2948b716 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -46,7 +46,7 @@ process PAVE_GERMLINE { -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ - -sample ${meta.id} \\ + -sample ${meta.sample_id} \\ -vcf_file ${sage_vcf} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ @@ -70,7 +70,7 @@ process PAVE_GERMLINE { stub: """ - touch ${meta.id}.sage.pave_germline.vcf.gz{,.tbi} + touch ${meta.sample_id}.sage.pave_germline.vcf.gz{,.tbi} echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index f921831b..2fe372eb 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -46,7 +46,7 @@ process PAVE_SOMATIC { java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ - -sample ${meta.id} \\ + -sample ${meta.sample_id} \\ -vcf_file ${sage_vcf} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ @@ -69,7 +69,7 @@ process PAVE_SOMATIC { stub: """ - touch ${meta.id}.sage.pave_somatic.vcf.gz{,.tbi} + touch ${meta.sample_id}.sage.pave_somatic.vcf.gz{,.tbi} echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 3fefb129..126df42c 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -1,11 +1,3 @@ -// NOTE(SW): use of tumor and normal sample names here is consistent with Pipeline5 -// - https://github.com/hartwigmedical/pipeline5/blob/v5.32/cluster/src/main/java/com/hartwig/pipeline/calling/sage/SageCommandBuilder.java#L95-L96 -// - https://github.com/hartwigmedical/pipeline5/blob/v5.32/cluster/src/main/java/com/hartwig/pipeline/calling/sage/SageCommandBuilder.java#L112-L118 - -// NOTE(SW): logic that determines BQR outputs assumes '-out' is a path that includes at least leading one directory - -// TODO(SW): check whether intentional sample name switch for germline also affects BQR outputs - process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index aa0016f7..9603739b 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -24,7 +24,7 @@ process SIGS { java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ - -sample ${meta.tumor_id} \\ + -sample ${meta.sample_id} \\ -somatic_vcf_file ${smlv_vcf} \\ -signatures_file ${signatures} \\ -output_dir sigs/ diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 8c29411e..25e7ac4c 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -15,8 +15,8 @@ process GRIDSS_PREPROCESS { path genome_gridss_index output: - tuple val(meta), path("gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/"), emit: preprocess_dir - path 'versions.yml' , emit: versions + tuple val(meta), path("gridss_preprocess/${meta.sample_id}.sv_prep.sorted.bam.gridss.working/"), emit: preprocess_dir + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -38,7 +38,7 @@ process GRIDSS_PREPROCESS { --workingdir gridss_preprocess/ \\ --threads ${task.cpus} \\ ${config_arg} \\ - --labels ${meta.id} \\ + --labels ${meta.sample_id} \\ --bams ${bam} \\ --filtered_bams ${bam_filtered} \\ --output placeholder @@ -53,8 +53,8 @@ process GRIDSS_PREPROCESS { stub: """ - mkdir -p gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/ - touch gridss_preprocess/${meta.id}.sv_prep.sorted.bam.gridss.working/placeholder + mkdir -p gridss_preprocess/${meta.sample_id}.sv_prep.sorted.bam.gridss.working/ + touch gridss_preprocess/${meta.sample_id}.sv_prep.sorted.bam.gridss.working/placeholder echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 3a06ed10..7e30835c 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -30,7 +30,7 @@ process SVPREP { -Xmx${Math.round(task.memory.bytes * 0.75)} \\ -jar ${task.ext.jarPath} \\ ${args} \\ - -sample ${meta.id} \\ + -sample ${meta.sample_id} \\ -bam_file ${bam} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ @@ -43,9 +43,9 @@ process SVPREP { samtools sort \\ -@ ${task.cpus} \\ - -T ${meta.id}.sv_prep.tmp \\ - -o ${meta.id}.sv_prep.sorted.bam \\ - ${meta.id}.sv_prep.bam + -T ${meta.sample_id}.sv_prep.tmp \\ + -o ${meta.sample_id}.sv_prep.sorted.bam \\ + ${meta.sample_id}.sv_prep.bam # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml @@ -56,8 +56,8 @@ process SVPREP { stub: """ - touch "${meta.id}.sv_prep.sorted.bam" - touch "${meta.id}.sv_prep.junctions.tsv" + touch "${meta.sample_id}.sv_prep.sorted.bam" + touch "${meta.sample_id}.sv_prep.junctions.tsv" echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 96a05f76..360942ff 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -37,7 +37,7 @@ process VIRUSBREAKEND { --gridssargs "--jvmheap ${Math.round(task.memory.bytes * 0.95)}" \\ --threads ${task.cpus} \\ --db ${virusbreakenddb.toString().replaceAll("/\$", "")}/ \\ - --output ${meta.id}.virusbreakend.vcf \\ + --output ${meta.sample_id}.virusbreakend.vcf \\ --reference ${genome_fasta} \\ ${bam} @@ -49,7 +49,7 @@ process VIRUSBREAKEND { stub: """ - touch ${meta.id}.virusbreakend.vcf ${meta.id}.summary.tsv + touch ${meta.sample_id}.virusbreakend.vcf ${meta.sample_id}.summary.tsv echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index f01453fc..29526576 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -25,7 +25,7 @@ process VIRUSINTERPRETER { java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ - -sample ${meta.id} \\ + -sample ${meta.sample_id} \\ -purple_dir ${purple_dir} \\ -tumor_sample_wgs_metrics_file ${wgs_metrics} \\ -virus_breakend_tsv ${virus_tsv} \\ @@ -42,7 +42,7 @@ process VIRUSINTERPRETER { stub: """ mkdir -p virusinterpreter/ - touch virusinterpreter/${meta.id}.virus.annotated.tsv + touch virusinterpreter/${meta.sample_id}.virus.annotated.tsv echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/nf-core/samtools/flagstat/main.nf b/modules/nf-core/samtools/flagstat/main.nf index 8d8d91dd..74fbaa5d 100644 --- a/modules/nf-core/samtools/flagstat/main.nf +++ b/modules/nf-core/samtools/flagstat/main.nf @@ -19,7 +19,7 @@ process SAMTOOLS_FLAGSTAT { script: def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" + def prefix = task.ext.prefix ?: "${meta.sample_id}" """ samtools \\ flagstat \\ @@ -34,7 +34,7 @@ process SAMTOOLS_FLAGSTAT { """ stub: - def prefix = task.ext.prefix ?: "${meta.id}" + def prefix = task.ext.prefix ?: "${meta.sample_id}" """ touch ${prefix}.flagstat echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml diff --git a/modules/nf-core/samtools/flagstat/samtools-flagstat.diff b/modules/nf-core/samtools/flagstat/samtools-flagstat.diff index 52c43355..462e26c9 100644 --- a/modules/nf-core/samtools/flagstat/samtools-flagstat.diff +++ b/modules/nf-core/samtools/flagstat/samtools-flagstat.diff @@ -1,13 +1,22 @@ Changes in module 'nf-core/samtools/flagstat' --- modules/nf-core/samtools/flagstat/main.nf +++ modules/nf-core/samtools/flagstat/main.nf +@@ -19,7 +19,7 @@ + + script: + def args = task.ext.args ?: '' +- def prefix = task.ext.prefix ?: "${meta.id}" ++ def prefix = task.ext.prefix ?: "${meta.sample_id}" + """ + samtools \\ + flagstat \\ @@ -32,4 +32,11 @@ samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') END_VERSIONS """ + + stub: -+ def prefix = task.ext.prefix ?: "${meta.id}" ++ def prefix = task.ext.prefix ?: "${meta.sample_id}" + """ + touch ${prefix}.flagstat + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml diff --git a/nextflow.config b/nextflow.config index 67c5f542..15474bcb 100644 --- a/nextflow.config +++ b/nextflow.config @@ -12,8 +12,8 @@ params { // Input options input = null - // Enable targeted/panel mode; WGTS run by default - targeted = false + // Workflow mode + mode = null // Isofox user input files isofox_counts = null @@ -165,8 +165,8 @@ includeConfig 'conf/hmf_genomes.config' includeConfig 'conf/panel_data.config' // Load panel configuration if needed -if (params.containsKey('run_mode') && params.run_mode == 'panel') { - includeConfig 'conf/panel_parameters.config' +if (params.containsKey('mode') && params.mode == 'targeted') { + includeConfig 'conf/targeted_parameters.config' } diff --git a/nextflow_schema.json b/nextflow_schema.json index 87c91d37..5fcd39d7 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -46,26 +46,21 @@ "help_text": "Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run.", "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" }, - "run_type": { + "mode": { "type": "string", - "description": "Pipeline run type.", + "description": "Workflow run mode.", "fa_icon": "fas fa-diagram-project" }, - "run_mode": { + "panel": { "type": "string", - "description": "Pipeline run mode.", - "fa_icon": "fas fa-diagram-project" + "description": "Name of pane to use.", + "fa_icon": "fas fa-book" }, "force_genome": { "type": "boolean", "description": "Skip check for restricted genome.", "fa_icon": "fas fa-palette" }, - "targeted": { - "type": "boolean", - "description": "Run in targeted mode.", - "fa_icon": "fas fa-diagram-project" - }, "processes_manual": { "type": "boolean", "description": "Run only processes manually provided in processes_include.", @@ -144,11 +139,6 @@ "fa_icon": "fas fa-book", "hidden": true }, - "panel": { - "type": "string", - "description": "Name of pane to use.", - "fa_icon": "fas fa-book" - }, "igenomes_base": { "type": "string", "format": "directory-path", diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index 8f2f77f1..d2988105 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -2,6 +2,7 @@ // AMBER determines b-allele frequencies at predetermined positions // +import Constants import Utils include { AMBER } from '../../modules/local/amber/main' @@ -15,40 +16,46 @@ workflow AMBER_PROFILING { genome_version // channel: [mandatory] genome version heterozygous_sites // channel: [optional] /path/to/heterozygous_sites - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Select input sources + // Sort inputs + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.AMBER_DIR) + runnable: Utils.hasTumorDnaBam(meta) && !has_existing + skip: true + } + + // Create process input channel // channel: [ meta_amber, tumor_bam, normal_bam, tumor_bai, normal_bai ] - ch_amber_inputs = ch_inputs + ch_amber_inputs = ch_inputs_sorted.runnable .map { meta -> + def meta_amber = [ - key: meta.id, - id: meta.id, + key: meta.group_id, + id: meta.group_id, tumor_id: Utils.getTumorDnaSampleName(meta), ] def tumor_bam = Utils.getTumorDnaBam(meta) + def tumor_bai = Utils.getTumorDnaBai(meta) def normal_bam = [] def normal_bai = [] - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - - assert [Constants.RunMode.DNA, Constants.RunMode.DNA_RNA].contains(run_config.mode) + if (Utils.hasNormalDnaBam(meta)) { meta_amber.normal_id = Utils.getNormalDnaSampleName(meta) normal_bam = Utils.getNormalDnaBam(meta) - normal_bai = "${normal_bam}.bai" + normal_bai = Utils.getNormalDnaBai(meta) } - [meta_amber, tumor_bam, normal_bam, "${tumor_bam}.bai", normal_bai] + [meta_amber, tumor_bam, normal_bam, tumor_bai, normal_bai] } // Run process @@ -58,10 +65,16 @@ workflow AMBER_PROFILING { heterozygous_sites, ) - // Set outputs, restoring original meta - ch_outputs = WorkflowOncoanalyser.restoreMeta(AMBER.out.amber_dir, ch_inputs) ch_versions = ch_versions.mix(AMBER.out.versions) + // Set outputs, restoring original meta + // channel: [ meta, amber_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(AMBER.out.amber_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + emit: amber_dir = ch_outputs // channel: [ meta, amber_dir ] diff --git a/subworkflows/local/bamtools_metrics.nf b/subworkflows/local/bamtools_metrics.nf index b66786ba..92237b83 100644 --- a/subworkflows/local/bamtools_metrics.nf +++ b/subworkflows/local/bamtools_metrics.nf @@ -16,68 +16,86 @@ workflow BAMTOOLS_METRICS { genome_fasta // channel: [mandatory] /path/to/genome_fasta genome_version // channel: [mandatory] genome version - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Select input sources - // channel: [ meta_bamtools, bam, bai ] - ch_bamtools_inputs_all = ch_inputs + // Sort inputs + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> + + def has_tumor_dna = Utils.hasTumorDnaBam(meta) + def has_normal_dna = Utils.hasNormalDnaBam(meta) + + runnable: has_tumor_dna || has_normal_dna + skip: true + } + + // Flatten into BAM/BAI pairs, select inputs that are eligible to run + // channel: runnable: [ meta_extra, bam, bai ] + // channel: skip: [ meta_extra ] + ch_bams_bais_sorted = ch_inputs_sorted.runnable .flatMap { meta -> - def inputs = [] - def meta_bamtools_tumor = [ - key: meta.id, - id: Utils.getTumorDnaSampleName(meta), - // NOTE(SW): must use string representation for caching purposes - sample_type_str: Constants.SampleType.TUMOR.name(), + def tumor_sample_id = [] + def tumor_bam = [] + def tumor_bai = [] + + def normal_sample_id = [] + def normal_bam = [] + def normal_bai = [] + + + if (Utils.hasTumorDnaBam(meta)) { + tumor_sample_id = Utils.getTumorDnaSampleName(meta) + tumor_bam = Utils.getTumorDnaBam(meta) + tumor_bai = Utils.getTumorDnaBai(meta) + } + + if (Utils.hasNormalDnaBam(meta)) { + normal_sample_id = Utils.getNormalDnaSampleName(meta) + normal_bam = Utils.getNormalDnaBam(meta) + normal_bai = Utils.getNormalDnaBai(meta) + } + + return [ + [[key: meta.group_id, *:meta, sample_id: tumor_sample_id, sample_type: 'tumor'], tumor_bam, tumor_bai], + [[key: meta.group_id, *:meta, sample_id: normal_sample_id, sample_type: 'normal'], normal_bam, normal_bai], ] - def tumor_bam = Utils.getTumorDnaBam(meta) - inputs.add([meta_bamtools_tumor, tumor_bam, "${tumor_bam}.bai"]) - - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - def meta_bamtools_normal = [ - key: meta.id, - id: Utils.getNormalDnaSampleName(meta), - // NOTE(SW): must use string representation for caching purposes - sample_type_str: Constants.SampleType.NORMAL.name(), - ] - def normal_bam = Utils.getNormalDnaBam(meta) - inputs.add([meta_bamtools_normal, normal_bam, "${normal_bam}.bai"]) + } + .branch { meta_extra, bam, bai -> + + def input_key + if (meta_extra.sample_type == 'tumor') { + input_key = Constants.INPUT.BAMTOOLS_TUMOR + } else if (meta_extra.sample_type == 'normal') { + input_key = Constants.INPUT.BAMTOOLS_NORMAL + } else { + assert false } - return inputs + def has_existing = Utils.hasExistingInput(meta_extra, input_key) + + runnable: bam && bai && !has_existing + skip: true + return meta_extra } - // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples - // NOTE(SW): no effective blocking by .groupTuple() as we're not dependent - // on any process + // Create process input channel // channel: [ meta_bamtools, bam, bai ] - ch_bamtools_inputs = ch_bamtools_inputs_all - .map { [it[1..-1], it[0]] } - .groupTuple() - .map { filepaths, meta_bamtools -> - def (keys, sample_names, sample_type_strs) = meta_bamtools - .collect { - [it.key, it.id, it.sample_type_str] - } - .transpose() - - def sample_type_strs_unique = sample_type_strs.unique(false) - assert sample_type_strs_unique.size() == 1 - def sample_type_str = sample_type_strs_unique[0] - - def meta_bamtools_new = [ - keys: keys, - id: sample_names.join('__'), - id_simple: keys.join('__'), - sample_type_str: sample_type_str, + ch_bamtools_inputs = ch_bams_bais_sorted.runnable + .map { meta_extra, bam, bai -> + + def meta_bamtools = [ + key: meta_extra.group_id, + id: "${meta_extra.group_id}__${meta_extra.sample_id}", + sample_id: meta_extra.sample_id, + sample_type: meta_extra.sample_type, ] - return [meta_bamtools_new, *filepaths] + + return [meta_bamtools, bam, bai] } // Run process @@ -87,31 +105,36 @@ workflow BAMTOOLS_METRICS { genome_version, ) - // Set version ch_versions = ch_versions.mix(BAMTOOLS.out.versions) - // Replicate outputs to reverse unique operation - // channel: [ meta_bamtools_individual, sample_type_str, metrics ] - ch_bamtools_out_individual = BAMTOOLS.out.metrics - .flatMap { meta_bamtools_shared, metrics -> - meta_bamtools_shared.keys.collect { key -> - return [meta_bamtools_shared + [key: key], meta_bamtools_shared.sample_type_str, metrics] - } + // Sort outputs into tumor and normal channels, adding partial skip entries + // channel: [ meta_bamtools, metrics ] + ch_outputs_sorted = Channel.empty() + .mix( + BAMTOOLS.out.metrics, + ch_bams_bais_sorted.skip.map { meta -> [meta, []] }, + ) + .branch { meta_bamtools, metrics -> + tumor: meta_bamtools.sample_type == 'tumor' + normal: meta_bamtools.sample_type == 'normal' } - // Set outputs - ch_outputs = WorkflowOncoanalyser.restoreMeta(ch_bamtools_out_individual, ch_inputs) - .branch { meta, sample_type_str, metrics -> - def sample_type = Utils.getEnumFromString(sample_type_str, Constants.SampleType) - somatic: sample_type == Constants.SampleType.TUMOR - return [meta, metrics] - germline: sample_type == Constants.SampleType.NORMAL - return [meta, metrics] - } + // Set outputs, restoring original meta, including full skip entries + ch_somatic_metrics = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_outputs_sorted.tumor, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + + ch_germline_metrics = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_outputs_sorted.normal, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - somatic = ch_outputs.somatic // channel: [ meta, metrics ] - germline = ch_outputs.germline // channel: [ meta, metrics ] + somatic = ch_somatic_metrics // channel: [ meta, metrics ] + germline = ch_germline_metrics // channel: [ meta, metrics ] versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/channel_inputs_purple.nf b/subworkflows/local/channel_inputs_purple.nf deleted file mode 100644 index 8634800b..00000000 --- a/subworkflows/local/channel_inputs_purple.nf +++ /dev/null @@ -1,78 +0,0 @@ -// -// Construct PURPLE input channel -// - -import Constants - -workflow CHANNEL_INPUTS_PURPLE { - take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_amber // channel: [mandatory] [ meta, amber_dir ] - ch_cobalt // channel: [mandatory] [ meta, cobalt_dir ] - ch_smlv_somatic // channel: [optional] [ meta, pave_vcf ] - ch_smlv_germline // channel: [optional] [ meta, pave_vcf ] - ch_sv_somatic // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] - ch_sv_germline // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] - ch_sv_somatic_unfiltered // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] - - // Params - run_config // channel: [mandatory] run configuration - - main: - // Set input sources - ch_amber_source = run_config.stages.amber ? ch_amber : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.AMBER_DIR) - ch_cobalt_source = run_config.stages.cobalt ? ch_cobalt : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.COBALT_DIR) - - if (run_config.stages.gripss) { - - ch_sv_somatic_source = ch_sv_somatic - ch_sv_somatic_unfiltered_source = ch_sv_somatic_unfiltered - ch_sv_germline_source = ch_sv_germline - - } else { - - ch_sv_somatic_source = getGripssSampleSheetInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_TUMOR) - ch_sv_somatic_unfiltered_source = getGripssSampleSheetInput(ch_inputs, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR) - ch_sv_germline_source = getGripssSampleSheetInput(ch_inputs, Constants.INPUT.GRIPSS_VCF_NORMAL) - - } - - ch_smlv_somatic_source = run_config.stages.pave ? ch_smlv_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_TUMOR, type: 'optional') - ch_smlv_germline_source = run_config.stages.pave ? ch_smlv_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PAVE_VCF_NORMAL, type: 'optional') - - // Adjust for run type and mode - if (run_config.type == Constants.RunType.TUMOR_ONLY) { - - ch_sv_germline_source = ch_inputs.map { meta -> [meta, [], []] } - ch_smlv_germline_source = ch_inputs.map { meta -> [meta, []] } - - } - - // NOTE(SW): Hartwig indicated unfiltered SVs should not be used for recovery in panel or tumor-only mode - if (params.targeted === true || run_config.type == Constants.RunType.TUMOR_ONLY) { - ch_sv_somatic_unfiltered_source = ch_inputs.map { meta -> [meta, [], []] } - } - - // Combine into single channel - ch_purple_inputs_source = WorkflowOncoanalyser.groupByMeta( - ch_amber_source, - ch_cobalt_source, - ch_sv_somatic_source, - ch_sv_somatic_unfiltered_source, - ch_sv_germline_source, - ch_smlv_somatic_source, - ch_smlv_germline_source, - ) - - emit: - ch_purple_inputs_source // channel: [ meta, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] -} - -def getGripssSampleSheetInput(ch_inputs, input_type) { - WorkflowOncoanalyser.getInput(ch_inputs, input_type, type: 'optional') - .map { meta, vcf -> - def tbi = vcf == [] ? [] : "${vcf}.tbi" - return [meta, vcf, tbi] - } -} diff --git a/subworkflows/local/chord_prediction.nf b/subworkflows/local/chord_prediction.nf index dbfa18e8..715c4280 100644 --- a/subworkflows/local/chord_prediction.nf +++ b/subworkflows/local/chord_prediction.nf @@ -16,9 +16,6 @@ workflow CHORD_PREDICTION { // Reference data genome_version // channel: [mandatory] genome version - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] @@ -26,29 +23,46 @@ workflow CHORD_PREDICTION { // Select input sources // channel: [ meta, purple_dir ] - if (run_config.stages.purple) { - ch_chord_inputs_source = ch_purple - } else { - ch_chord_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - } - - // Create inputs and create process-specific meta - // channel: [ meta, smlv_vcf, sv_vcf ] - ch_chord_inputs = ch_chord_inputs_source + ch_inputs_selected = ch_purple .map { meta, purple_dir -> + return [meta, Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR)] + } + + // Sort inputs + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_inputs_selected + .branch { meta, purple_dir -> + def tumor_id = Utils.getTumorDnaSampleName(meta) + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.CHORD_DIR) + def has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] + def has_sv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") : [] + + runnable: purple_dir && has_smlv_vcf && has_sv_vcf && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_chord, smlv_vcf, sv_vcf ] + ch_chord_inputs = ch_inputs_sorted.runnable + .map { meta, purple_dir -> + + def tumor_id = Utils.getTumorDnaSampleName(meta) + + def meta_chord = [ + key: meta.group_id, + id: meta.group_id, + sample_id: tumor_id, + ] + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") - // Require both SV and smlv VCF from the PURPLE directory - if (!smlv_vcf.exists() || !sv_vcf.exists()) { - return Constants.PLACEHOLDER_META - } - - def meta_chord = [key: meta.id, id: tumor_id] return [meta_chord, smlv_vcf, sv_vcf] } - .filter { it != Constants.PLACEHOLDER_META } // Run process CHORD( @@ -56,10 +70,16 @@ workflow CHORD_PREDICTION { genome_version, ) - // Set outputs, restoring original meta - ch_outputs = WorkflowOncoanalyser.restoreMeta(CHORD.out.chord_dir, ch_inputs) ch_versions = ch_versions.mix(CHORD.out.versions) + // Set outputs, restoring original meta + // channel: [ meta, chord_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(CHORD.out.chord_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + emit: chord_dir = ch_outputs // channel: [ meta, chord_dir ] diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index 29eec79d..6fb81e08 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -2,6 +2,7 @@ // COBALT calculates read ratios between tumor and normal samples // +import Constants import Utils include { COBALT } from '../../modules/local/cobalt/main' @@ -16,58 +17,79 @@ workflow COBALT_PROFILING { diploid_bed // channel: [optional] /path/to/diploid_bed target_region_normalisation // channel: [optional] /path/to/target_region_normalisation - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Select input sources - // channel: [ meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai ] - ch_cobalt_inputs = ch_inputs - .map { meta -> + // Sort inputs + // NOTE(SW): germline mode is not currently supported + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.COBALT_DIR) + runnable_tn: Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) && !has_existing + runnable_to: Utils.hasTumorDnaBam(meta) && !has_existing + skip: true + } + + // First set diploid BED input for tumor/normal and tumor only samples + // NOTE(SW): since the diploid BED is provided as a channel, I seem to be only able to include via channel ops + // channel: [ meta, diploid_bed ] + ch_inputs_runnable = Channel.empty() + .mix( + ch_inputs_sorted.runnable_tn.map { meta -> [meta, []] }, + ch_inputs_sorted.runnable_to.combine(diploid_bed), + ) + + // Create process input channel + // channel: sample_data: [ meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai ] + // channel: diploid_bed: [ diploid_bed ] + ch_cobalt_inputs = ch_inputs_runnable + .multiMap { meta, diploid_bed -> + def meta_cobalt = [ - key: meta.id, - id: meta.id, + key: meta.group_id, + id: meta.group_id, tumor_id: Utils.getTumorDnaSampleName(meta), ] + def tumor_bam = Utils.getTumorDnaBam(meta) + def tumor_bai = Utils.getTumorDnaBai(meta) def normal_bam = [] def normal_bai = [] - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - - assert [Constants.RunMode.DNA, Constants.RunMode.DNA_RNA].contains(run_config.mode) + if (Utils.hasNormalDnaBam(meta)) { meta_cobalt.normal_id = Utils.getNormalDnaSampleName(meta) normal_bam = Utils.getNormalDnaBam(meta) - normal_bai = "${normal_bam}.bai" + normal_bai = Utils.getNormalDnaBai(meta) } - return [meta_cobalt, tumor_bam, normal_bam, "${tumor_bam}.bai", normal_bai] + sample_data: [meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai] + diploid_bed: diploid_bed } - // Set reference files on run type - if (run_config.type != Constants.RunType.TUMOR_ONLY) { - diploid_bed = [] - } - // Run process COBALT( - ch_cobalt_inputs, + ch_cobalt_inputs.sample_data, gc_profile, - diploid_bed, + ch_cobalt_inputs.diploid_bed, target_region_normalisation, ) - // Set outputs, restoring original meta - ch_outputs = WorkflowOncoanalyser.restoreMeta(COBALT.out.cobalt_dir, ch_inputs) ch_versions = ch_versions.mix(COBALT.out.versions) + // Set outputs, restoring original meta + // channel: [ meta, cobalt_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(COBALT.out.cobalt_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + emit: cobalt_dir = ch_outputs // channel: [ meta, cobalt_dir ] diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index 68abb32a..e6fe2dfa 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -10,72 +10,139 @@ workflow CUPPA_PREDICTION { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] - ch_isofox // channel: [optional] [ meta, isofox_dir ] - ch_purple // channel: [optional] [ meta, purple_dir ] - ch_linx // channel: [optional] [ meta, linx_annotation_dir ] - ch_virusinterpreter // channel: [optional] [ meta, virusinterpreter_dir ] + ch_isofox // channel: [mandatory] [ meta, isofox_dir ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] + ch_linx // channel: [mandatory] [ meta, linx_annotation_dir ] + ch_virusinterpreter // channel: [mandatory] [ meta, virusinterpreter_dir ] // Reference data genome_version // channel: [mandatory] genome version cuppa_resources // channel: [mandatory] /path/to/cuppa_resources/ - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() // Select input sources - // channel: [ meta, isofox_dir ] - ch_cuppa_inputs_isofox = run_config.stages.isofox ? ch_isofox : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional') - // channel: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] - ch_cuppa_inputs_source = WorkflowOncoanalyser.groupByMeta( - ch_cuppa_inputs_isofox, - run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional'), - run_config.stages.linx ? ch_linx : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR, type: 'optional'), - run_config.stages.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_DIR, type: 'optional'), - flatten_mode: 'nonrecursive', + ch_inputs_selected = WorkflowOncoanalyser.groupByMeta( + ch_isofox, + ch_purple, + ch_linx, + ch_virusinterpreter, ) + .map { meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir -> + + def inputs = [ + Utils.selectCurrentOrExisting(isofox_dir, meta, Constants.INPUT.ISOFOX_DIR), + Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), + Utils.selectCurrentOrExisting(linx_annotation_dir, meta, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + Utils.selectCurrentOrExisting(virusinterpreter_dir, meta, Constants.INPUT.VIRUSINTERPRETER_DIR), + ] + + return [meta, *inputs] + } + + // Sort inputs + // channel: runnable: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_inputs_selected + .branch { meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir -> + + // Run the following: + // - tumor DNA and normal DNA + // - tumor DNA and normal DNA, and tumor RNA + // - tumor RNA only + // + // Do not run the following: + // - tumor DNA only + // - panel mode (controlled by excluded from targeted subworkflow) + // + // (run exclusions currently done basis for presence of normal DNA) + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) + def has_normal_dna = Utils.hasNormalDnaBam(meta) + + def has_runnable_inputs = isofox_dir || (purple_dir && linx_annotation_dir && has_normal_dna) + + runnable: has_runnable_inputs && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: sample_data: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] + // channel: classifer: [ classifier ] + ch_cuppa_inputs = ch_inputs_sorted.runnable + .multiMap{ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir -> + + def meta_cuppa = [ + key: meta.group_id, + id: meta.group_id, + ] + + def has_tumor_dna = Utils.hasTumorDnaBam(meta) + def has_normal_dna = Utils.hasNormalDnaBam(meta) + def has_tumor_rna = Utils.hasTumorRnaBam(meta) + + def has_dna_inputs = (purple_dir && linx_annotation_dir) + def has_rna_inputs = isofox_dir + + def run_dna = has_dna_inputs && has_tumor_dna && has_normal_dna + def run_rna = has_rna_inputs && has_tumor_rna + + def classifier + + if (run_dna && run_rna) { + + classifier = 'ALL' + + meta_cuppa.sample_id = Utils.getTumorDnaSampleName(meta) + meta_cuppa.sample_rna_id = Utils.getTumorRnaSampleName(meta) + + } else if (run_dna) { + + classifier = 'DNA' + + meta_cuppa.sample_id = Utils.getTumorDnaSampleName(meta) + + } else if (run_rna) { + + classifier = 'RNA' + + meta_cuppa.sample_id = Utils.getTumorRnaSampleName(meta) + + } else { + + assert false - // Create inputs and create process-specific meta - // channel: [ meta_cuppa, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] - ch_cuppa_inputs = ch_cuppa_inputs_source - .map { data -> - def meta = data[0] - def meta_cuppa = [key: meta.id] - - switch (run_config.mode) { - case Constants.RunMode.DNA: - meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.DNA]) - break - case Constants.RunMode.RNA: - meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) - break - case Constants.RunMode.DNA_RNA: - meta_cuppa.id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.DNA]) - meta_cuppa.id_rna = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) - break - default: - assert false } - return [meta_cuppa, *data[1..-1]] + sample_data: [meta_cuppa, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir] + classifier: classifier } + // Run process CUPPA( - ch_cuppa_inputs, + ch_cuppa_inputs.sample_data, genome_version, cuppa_resources, + ch_cuppa_inputs.classifier, ) + ch_versions = ch_versions.mix(CUPPA.out.versions) + // Set outputs, restoring original meta - ch_output = WorkflowOncoanalyser.restoreMeta(CUPPA.out.cuppa_dir, ch_inputs) + // channel: [ meta, cuppa_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(CUPPA.out.cuppa_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - cuppa_dir = ch_output // channel: [ meta, cuppa_dir ] + cuppa_dir = ch_outputs // channel: [ meta, cuppa_dir ] - versions = CUPPA.out.versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/flagstat_metrics.nf b/subworkflows/local/flagstat_metrics.nf index 5ede734d..256d063d 100644 --- a/subworkflows/local/flagstat_metrics.nf +++ b/subworkflows/local/flagstat_metrics.nf @@ -12,67 +12,85 @@ workflow FLAGSTAT_METRICS { // Sample data ch_inputs // channel: [mandatory] [ meta ] - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Select input source - // Select input sources - // channel: [ meta_flagstat, bam, bai ] - ch_flagstat_inputs_all = ch_inputs + // Sort inputs + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> + + def has_tumor_dna = Utils.hasTumorDnaBam(meta) + def has_normal_dna = Utils.hasNormalDnaBam(meta) + + runnable: has_tumor_dna || has_normal_dna + skip: true + } + + // Flatten into BAM/BAI pairs, select inputs that are eligible to run + // channel: runnable: [ meta_extra, bam, bai ] + // channel: skip: [ meta_extra ] + ch_bams_bais_sorted = ch_inputs_sorted.runnable .flatMap { meta -> - def inputs = [] - def meta_flagstat_tumor = [ - key: meta.id, - id: Utils.getTumorDnaSampleName(meta), - // NOTE(SW): must use string representation for caching purposes - sample_type_str: Constants.SampleType.TUMOR.name(), + def tumor_sample_id = [] + def tumor_bam = [] + def tumor_bai = [] + + def normal_sample_id = [] + def normal_bam = [] + def normal_bai = [] + + if (Utils.hasTumorDnaBam(meta)) { + tumor_sample_id = Utils.getTumorDnaSampleName(meta) + tumor_bam = Utils.getTumorDnaBam(meta) + tumor_bai = Utils.getTumorDnaBai(meta) + } + + if (Utils.hasNormalDnaBam(meta)) { + normal_sample_id = Utils.getNormalDnaSampleName(meta) + normal_bam = Utils.getNormalDnaBam(meta) + normal_bai = Utils.getNormalDnaBai(meta) + } + + return [ + [[key: meta.group_id, *:meta, sample_id: tumor_sample_id, sample_type: 'tumor'], tumor_bam, tumor_bai], + [[key: meta.group_id, *:meta, sample_id: normal_sample_id, sample_type: 'normal'], normal_bam, normal_bai], ] - def tumor_bam = Utils.getTumorDnaBam(meta) - inputs.add([meta_flagstat_tumor, tumor_bam, "${tumor_bam}.bai"]) - - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - def meta_flagstat_normal = [ - key: meta.id, - id: Utils.getNormalDnaSampleName(meta), - // NOTE(SW): must use string representation for caching purposes - sample_type_str: Constants.SampleType.NORMAL.name(), - ] - def normal_bam = Utils.getNormalDnaBam(meta) - inputs.add([meta_flagstat_normal, normal_bam, "${normal_bam}.bai"]) + } + .branch { meta_extra, bam, bai -> + + def input_key + if (meta_extra.sample_type == 'tumor') { + input_key = Constants.INPUT.BAMTOOLS_TUMOR + } else if (meta_extra.sample_type == 'normal') { + input_key = Constants.INPUT.BAMTOOLS_NORMAL + } else { + assert false } - return inputs + def has_existing = Utils.hasExistingInput(meta_extra, input_key) + + runnable: bam && bai && !has_existing + skip: true + return meta_extra } - // Collapse duplicate files e.g. repeated normal BAMs for multiple tumor samples - // channel: [ meta_flagstat_shared, bam, bai ] - ch_flagstat_inputs = ch_flagstat_inputs_all - .map { [it[1..-1], it[0]] } - .groupTuple() - .map { filepaths, meta_flagstat -> - def (keys, sample_names, sample_type_strs) = meta_flagstat - .collect { - [it.key, it.id, it.sample_type_str] - } - .transpose() - - def sample_type_strs_unique = sample_type_strs.unique(false) - assert sample_type_strs_unique.size() == 1 - def sample_type_str = sample_type_strs_unique[0] - - def meta_flagstat_new = [ - keys: keys, - id: sample_names.join('__'), - id_simple: keys.join('__'), - sample_type_str: sample_type_str, + // Create process input channel + // channel: [ meta_flagstat, bam, bai ] + ch_flagstat_inputs = ch_bams_bais_sorted.runnable + .map { meta_extra, bam, bai -> + + def meta_flagstat = [ + key: meta_extra.group_id, + id: "${meta_extra.group_id}__${meta_extra.sample_id}", + sample_id: meta_extra.sample_id, + sample_type: meta_extra.sample_type, ] - return [meta_flagstat_new, *filepaths] + + return [meta_flagstat, bam, bai] } // Run process @@ -80,34 +98,36 @@ workflow FLAGSTAT_METRICS { ch_flagstat_inputs, ) - // Set version ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) - // Replicate outputs to reverse unique operation - // channel: [ meta_flagstat_individual, flagstat ] - ch_flagstat_out_individual = SAMTOOLS_FLAGSTAT.out.flagstat - .flatMap { meta_flagstat_shared, flagstat -> - def sample_type = Utils.getEnumFromString(meta_flagstat_shared.sample_type_str, Constants.SampleType) - meta_flagstat_shared.keys.collect { key -> - return [meta_flagstat_shared + [key: key], sample_type, flagstat] - } + // Sort outputs into tumor and normal channels, adding partial skip entries + // channel: [ meta_flagstat, metrics ] + ch_outputs_sorted = Channel.empty() + .mix( + SAMTOOLS_FLAGSTAT.out.flagstat, + ch_bams_bais_sorted.skip.map { meta -> [meta, []] }, + ) + .branch { meta_flagstat, metrics -> + tumor: meta_flagstat.sample_type == 'tumor' + normal: meta_flagstat.sample_type == 'normal' } - // Set outputs - // channel (somatic): [ meta, flagstat ] - // channel (germline): [ meta, flagstat ] - ch_outputs = WorkflowOncoanalyser.restoreMeta(ch_flagstat_out_individual, ch_inputs) - .branch { meta, sample_type, flagstat -> - somatic: sample_type == Constants.SampleType.TUMOR - return [meta, flagstat] - germline: sample_type == Constants.SampleType.NORMAL - return [meta, flagstat] - } - ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) + // Set outputs, restoring original meta, including full skip entries + ch_somatic_metrics = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_outputs_sorted.tumor, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + + ch_germline_metrics = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_outputs_sorted.normal, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - somatic = ch_outputs.somatic // channel: [ meta, metrics ] - germline = ch_outputs.germline // channel: [ meta, metrics ] + somatic = ch_somatic_metrics // channel: [ meta, metrics ] + germline = ch_germline_metrics // channel: [ meta, metrics ] versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index 8511ae92..9a58c34c 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -3,6 +3,7 @@ // GRIDSS detects structural variants, and reports breakends and breakpoints. // +import Constants import Utils include { GRIDSS_ASSEMBLE as ASSEMBLE } from '../../modules/local/svprep/assemble/main' @@ -31,38 +32,62 @@ workflow GRIDSS_SVPREP_CALLING { // Params gridss_config // channel: [optional] /path/to/gridss_config - run_config // channel: [mandatory] run configuration main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() + // Sort inputs + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIDSS_VCF) + + runnable_tn: Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) && !has_existing + runnable_to: Utils.hasTumorDnaBam(meta) && !has_existing + skip: true + } + // // MODULE: SV Prep (tumor) // - // Prepare tumor sample inputs + // Create process input channel // channel: [ meta_svprep, bam_tumor, bai_tumor, [] ] - ch_svprep_tumor_inputs = ch_inputs + ch_svprep_tumor_inputs = Channel.empty() + .mix( + ch_inputs_sorted.runnable_to, + ch_inputs_sorted.runnable_tn, + ) .map { meta -> + def meta_svprep = [ - key: meta.id, - id: Utils.getTumorDnaSampleName(meta), + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), sample_type: 'tumor', + // NOTE(SW): slightly redundant since we have this information then lose it with .mix above + group_size: Utils.hasNormalDnaBam(meta) ? 2 : 1 ] + def tumor_bam = Utils.getTumorDnaBam(meta) - return [meta_svprep, tumor_bam, "${tumor_bam}.bai", []] + def tumor_bai = Utils.getTumorDnaBai(meta) + + return [meta_svprep, tumor_bam, tumor_bai, []] + } - // Filter tumor BAM + // Run process SVPREP_TUMOR( ch_svprep_tumor_inputs, genome_fasta, genome_version, sv_prep_blocklist, known_fusions, - 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument + 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument ) + ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) // channel: [ meta_gridss, bam_tumor, bam_tumor_filtered ] @@ -77,56 +102,73 @@ workflow GRIDSS_SVPREP_CALLING { // // MODULE: SV Prep (normal) // - // channel: [ meta_gridss, bam_normal, bam_normal_filtered ] - ch_preprocess_inputs_normal = Channel.empty() - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - - assert [Constants.RunMode.DNA, Constants.RunMode.DNA_RNA].contains(run_config.mode) - - // Prepare normal sample inputs - // channel: [val(meta_svprep), bam_normal, bai_normal, junctions_tumor] - ch_svprep_normal_inputs = WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs) - .map { meta, junctions_tumor -> - def meta_svprep = [ - key: meta.id, - id: Utils.getNormalDnaSampleName(meta), - sample_type: 'normal', - ] - def normal_bam = Utils.getNormalDnaBam(meta) - return [meta_svprep, normal_bam, "${normal_bam}.bai", junctions_tumor] - } + // Create process input channel + // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_tn + // channel: [ meta_svprep, bam_normal, bai_normal, junctions_tumor ] + ch_svprep_normal_inputs = WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs_sorted.runnable_tn) + .map { meta, junctions_tumor -> - SVPREP_NORMAL( - ch_svprep_normal_inputs, - genome_fasta, - genome_version, - sv_prep_blocklist, - known_fusions, - 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument - ) - ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) + def meta_svprep = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getNormalDnaSampleName(meta), + sample_type: 'normal', + group_size: 2, // Assumption holds since germline only is not supported and we source from runnable_tn + ] - // channel: [ meta_gridss, bam_normal, bam_normal_filtered ] - ch_preprocess_inputs_normal = WorkflowOncoanalyser.groupByMeta( - SVPREP_NORMAL.out.bam, - ch_svprep_normal_inputs, - ) - .map { meta_svprep, bam_filtered, bam, bai, junctions -> - return [meta_svprep, bam, bam_filtered] - } - } + def normal_bam = Utils.getNormalDnaBam(meta) + def normal_bai = Utils.getNormalDnaBai(meta) + + return [meta_svprep, normal_bam, normal_bai, junctions_tumor] + + } + + // Run process + SVPREP_NORMAL( + ch_svprep_normal_inputs, + genome_fasta, + genome_version, + sv_prep_blocklist, + known_fusions, + 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument + ) + + ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) + + // channel: [ meta_gridss, bam_normal, bam_normal_filtered ] + ch_preprocess_inputs_normal = WorkflowOncoanalyser.groupByMeta( + SVPREP_NORMAL.out.bam, + ch_svprep_normal_inputs, + ) + // Switching meta name here from meta_svprep + .map { meta_gridss, bam_filtered, bam, bai, junctions -> + return [meta_gridss, bam, bam_filtered] + } // // MODULE: GRIDSS preprocess // + // Create process input channel // channel: [ meta_gridss, bam, bam_filtered ] ch_preprocess_inputs = Channel.empty() .mix( ch_preprocess_inputs_tumor, ch_preprocess_inputs_normal, ) + .map { meta_svprep, bam, bam_filtered -> + + def meta_gridss = [ + key: meta_svprep.key, + id: "${meta_svprep.id}__${meta_svprep.sample_id}", + sample_id: meta_svprep.sample_id, + sample_type: meta_svprep.sample_type, + group_size: meta_svprep.group_size, + ] + + return [meta_gridss, bam, bam_filtered] + } - // Preprocess reads + // Run process PREPROCESS( ch_preprocess_inputs, gridss_config, @@ -137,58 +179,76 @@ workflow GRIDSS_SVPREP_CALLING { genome_bwa_index_image, genome_gridss_index, ) + ch_versions = ch_versions.mix(PREPROCESS.out.versions) - // Gather BAMs and outputs from preprocessing for each tumor/normal set - // channel: [key, [[ meta_gridss, bam, bam_filtered, preprocess_dir], ...] ] - preprocess_group_tuple_size = run_config.type == Constants.RunType.TUMOR_NORMAL ? 2 : 1 + // Gather BAMs and outputs from preprocessing for each tumor/normal and tumor only set + // channel: [key, [[meta_gridss, bam, bam_filtered, preprocess_dir], ...] ] ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( ch_preprocess_inputs, PREPROCESS.out.preprocess_dir, ) - .map { [it[0].key, it] } - .groupTuple(size: preprocess_group_tuple_size) + .map { + def meta_gridss = it[0] + def other = it[1..-1] + [groupKey(meta_gridss.key, meta_gridss.group_size), [meta_gridss, *other]] + } + .groupTuple() // // MODULE: GRIDSS assemble // - // Order and organise inputs for assembly - // channel: [ meta_gridss, [bams], [bams_filtered], [preprocess_dirs], [labels] ] + // Create process input channel + // channel: tumor/normal: [ meta_gridss, [bams], [bams_filtered], [preprocess_dirs], [labels] ] + // channel: tumor only: [ meta_gridss, bam, bam_filtered, preprocess_dir, label ] ch_assemble_inputs = ch_bams_and_preprocess .map { key, entries -> - def (tmeta, tbam, tbam_filtered, tpreprocess) = entries.find { e -> e[0].sample_type == 'tumor' } - def meta_gridss = [id: tmeta.key] + + assert entries.size() == 1 || entries.size() == 2 + + def tumor_entry = entries.find { e -> e[0].sample_type == 'tumor' } + def normal_entry = entries.find { e -> e[0].sample_type == 'normal' } + + assert tumor_entry !== null + + def (tmeta, tbam, tbam_filtered, tpreprocess) = tumor_entry + def meta_gridss = [ + // Effectively meta.group_id, and both are required. Reminder: + // * key: channel element grouping + // * id: task tag + key: tmeta.key, + id: tmeta.key, + ] def data = [] - if (run_config.type == Constants.RunType.TUMOR_ONLY) { + + if (normal_entry === null) { data = [ meta_gridss, tbam, tbam_filtered, tpreprocess, - tmeta.id, + tmeta.sample_id, ] - } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + } else { - def (nmeta, nbam, nbam_filtered, npreprocess) = entries.find { e -> e[0].sample_type == 'normal' } + def (nmeta, nbam, nbam_filtered, npreprocess) = normal_entry data = [ meta_gridss, [nbam, tbam], [nbam_filtered, tbam_filtered], [npreprocess, tpreprocess], - [nmeta.id, tmeta.id], + [nmeta.sample_id, tmeta.sample_id], ] - } else { - assert false } return data } - // Assemble variants + // Run process ASSEMBLE( ch_assemble_inputs, gridss_config, @@ -200,12 +260,13 @@ workflow GRIDSS_SVPREP_CALLING { genome_gridss_index, gridss_blocklist, ) + ch_versions = ch_versions.mix(ASSEMBLE.out.versions) // // MODULE: GRIDSS call // - // Prepare inputs for variant calling + // Create process input channel // channel: [ meta_gridss, [bams], [bams_filtered], assemble_dir, [labels] ] ch_call_inputs = WorkflowOncoanalyser.groupByMeta( ch_assemble_inputs, @@ -213,13 +274,13 @@ workflow GRIDSS_SVPREP_CALLING { flatten: false, ) .map { data -> - def meta = data[0] + def meta_gridss = data[0] def (bams, bams_filtered, preprocess_dirs, labels) = data[1] def (assemble_dir) = data[2] - return [meta, bams, bams_filtered, assemble_dir, labels] + return [meta_gridss, bams, bams_filtered, assemble_dir, labels] } - // Call variants + // Run process CALL( ch_call_inputs, gridss_config, @@ -231,45 +292,47 @@ workflow GRIDSS_SVPREP_CALLING { genome_gridss_index, gridss_blocklist, ) + ch_versions = ch_versions.mix(CALL.out.versions) // // MODULE: SV Prep depth annotation // - // Prepare inputs for depth annotation, restore original meta - // channel: [ meta_svprep, [bams], [bais], vcf, [labels] ] - ch_depth_inputs = WorkflowOncoanalyser.groupByMeta( - ch_inputs.map { meta -> [meta.id, meta] }, - CALL.out.vcf.map { meta, vcf -> [meta.id, vcf] }, - ) - .map { id, meta, vcf -> - def tbam = Utils.getTumorDnaBam(meta) + // Restore original meta, create process input channel + // channel: tumor/normal: [ meta_svprep, [bams], [bais], vcf, [labels] ] + // channel: tumor only: [ meta_svprep, bam, bai, vcf, label ] + ch_depth_inputs = WorkflowOncoanalyser.restoreMeta(CALL.out.vcf, ch_inputs) + .map { meta, vcf -> + + // NOTE(SW): germline only is not currently supported + assert Utils.hasTumorDnaBam(meta) + def meta_svprep = [ - id: meta.id, + key: meta.group_id, + id: meta.group_id, tumor_id: Utils.getTumorDnaSampleName(meta) ] def data = [] - if (run_config.type == Constants.RunType.TUMOR_ONLY) { + + if (Utils.hasNormalDnaBam(meta)) { data = [ meta_svprep, - tbam, - "${tbam}.bai", + [Utils.getNormalDnaBam(meta), Utils.getTumorDnaBam(meta)], + [Utils.getNormalDnaBai(meta), Utils.getTumorDnaBai(meta)], vcf, - Utils.getTumorDnaSampleName(meta), + [Utils.getNormalDnaSampleName(meta), Utils.getTumorDnaSampleName(meta)], ] - } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - - def nbam = Utils.getNormalDnaBam(meta) + } else if (Utils.hasTumorDnaBam(meta)) { data = [ meta_svprep, - [nbam, tbam], - ["${nbam}.bai", "${tbam}.bai"], + Utils.getTumorDnaBam(meta), + Utils.getTumorDnaBai(meta), vcf, - [Utils.getNormalDnaSampleName(meta), Utils.getTumorDnaSampleName(meta)], + Utils.getTumorDnaSampleName(meta), ] } else { @@ -277,27 +340,27 @@ workflow GRIDSS_SVPREP_CALLING { } return data - } - // Add depth annotations to SVs + // Add depth annotations to calls DEPTH_ANNOTATOR( ch_depth_inputs, genome_fasta, genome_version, ) - // Reunite final VCF with the corresponding input meta object - ch_out = Channel.empty() - .concat( - ch_inputs.map { meta -> [meta.id, meta] }, - DEPTH_ANNOTATOR.out.vcf.map { meta, vcf -> [meta.id, vcf] }, + ch_versions = ch_versions.mix(DEPTH_ANNOTATOR.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, gridss_vcf ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(DEPTH_ANNOTATOR.out.vcf, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - .groupTuple(size: 2) - .map { id, other -> other.flatten() } emit: - results = ch_out // channel: [ meta, vcf ] + vcf = ch_outputs // channel: [ meta, vcf ] versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/gripss_filtering.nf b/subworkflows/local/gripss_filtering.nf index a10bcc4b..845a0aa4 100644 --- a/subworkflows/local/gripss_filtering.nf +++ b/subworkflows/local/gripss_filtering.nf @@ -2,6 +2,9 @@ // GRIPSS performs SV filtering. // +import Constants +import Utils + include { GRIPSS_GERMLINE as GERMLINE } from '../../modules/local/gripss/germline/main' include { GRIPSS_SOMATIC as SOMATIC } from '../../modules/local/gripss/somatic/main' @@ -21,66 +24,109 @@ workflow GRIPSS_FILTERING { repeatmasker_annotations // channel: [mandatory] /path/to/repeatmasker_annotations target_regions_bed // channel: [optional] /path/to/target_regions_bed - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Select input source - ch_gripss_inputs_source = run_config.stages.gridss ? ch_gridss : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.GRIDSS_VCF) + // Select input sources and sort + // channel: runnable: [ meta, gridss_vcf ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_gridss + .map { meta, gridss_vcf -> + return [ + meta, + Utils.selectCurrentOrExisting(gridss_vcf, meta, Constants.INPUT.GRIDSS_VCF), + ] + } + .branch { meta, gridss_vcf -> + runnable: gridss_vcf + skip: true + return meta + } + + // + // MODULE: GRIPSS germline + // + // Select inputs that are eligible to run + // channel: runnable: [ meta, gridss_vcf ] + // channel: skip: [ meta ] + ch_inputs_germline_sorted = ch_inputs_sorted.runnable + .branch { meta, gridss_vcf -> + def has_tumor_normal = Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIPSS_VCF_NORMAL) + + runnable: has_tumor_normal && !has_existing + skip: true + return meta + } - // Create inputs and create process-specific meta + // Create process input channel // channel: [ meta_gripss, gridss_vcf ] - ch_gripss_inputs = ch_gripss_inputs_source - .filter { it[0] != Constants.PLACEHOLDER_META } + ch_gripss_germline_inputs = ch_inputs_germline_sorted.runnable .map { meta, gridss_vcf -> def meta_gripss = [ - key: meta.id, - id: meta.id, + key: meta.group_id, + id: meta.group_id, tumor_id: Utils.getTumorDnaSampleName(meta), + normal_id: Utils.getNormalDnaSampleName(meta), ] - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - meta_gripss.normal_id = Utils.getNormalDnaSampleName(meta) - } - return [meta_gripss, gridss_vcf] } - // - // MODULE: GRIPSS germline - // - // channel: [ meta, gripss_vcf, gripss_tbi ] - ch_germline_out = Channel.empty() - ch_germline_unfiltered_out = Channel.empty() - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - - GERMLINE( - ch_gripss_inputs, - genome_fasta, - genome_version, - genome_fai, - breakend_pon, - breakpoint_pon, - known_fusions, - repeatmasker_annotations, - ) - - ch_versions = ch_versions.mix(GERMLINE.out.versions) - ch_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) - ch_germline_unfiltered_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_unfiltered, ch_inputs) + // Run process + GERMLINE( + ch_gripss_germline_inputs, + genome_fasta, + genome_version, + genome_fai, + breakend_pon, + breakpoint_pon, + known_fusions, + repeatmasker_annotations, + ) - } + ch_versions = ch_versions.mix(GERMLINE.out.versions) // // MODULE: GRIPSS somatic // + // Select inputs that are eligible to run + // channel: runnable: [ meta, gridss_vcf ] + // channel: skip: [ meta ] + ch_inputs_somatic_sorted = ch_inputs_sorted.runnable + .branch { meta, gridss_vcf -> + def has_tumor = Utils.hasTumorDnaBam(meta) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIPSS_VCF_TUMOR) + + runnable: has_tumor && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_gripss, gridss_vcf ] + ch_gripss_somatic_inputs = ch_inputs_somatic_sorted.runnable + .map { meta, gridss_vcf -> + + def meta_gripss = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + ] + + if (Utils.hasNormalDnaBam(meta)) { + meta_gripss.normal_id = Utils.getNormalDnaSampleName(meta) + } + + return [meta_gripss, gridss_vcf] + } + + // Run process SOMATIC( - ch_gripss_inputs, + ch_gripss_somatic_inputs, genome_fasta, genome_version, genome_fai, @@ -92,8 +138,36 @@ workflow GRIPSS_FILTERING { ) ch_versions = ch_versions.mix(SOMATIC.out.versions) - ch_somatic_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs) - ch_somatic_unfiltered_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_unfiltered, ch_inputs) + + // Set outputs, restoring original meta + // channel: [ meta, gripss_vcf, gripss_tbi ] + ch_somatic_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, + ) + + ch_somatic_unfiltered_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_unfiltered, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, + ) + + ch_germline_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, + ) + + ch_germline_unfiltered_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_unfiltered, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, + ) emit: somatic = ch_somatic_out // channel: [ meta, gripss_vcf, gripss_tbi ] diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf index 86d0b9bd..a82d7629 100644 --- a/subworkflows/local/isofox_quantification.nf +++ b/subworkflows/local/isofox_quantification.nf @@ -2,6 +2,7 @@ // Isofox estimates transcript abundance, detects novel SJs, and identifies fusion events // +import Constants import Utils include { ISOFOX } from '../../modules/local/isofox/main' @@ -22,27 +23,36 @@ workflow ISOFOX_QUANTIFICATION { isofox_tpm_norm // channel: [optional] /path/to/tpm_norm // Params - isofox_functions // string: [optional] isofox functions - isofox_read_length // string: [mandatory] isofox_read_length - run_config // channel: [mandatory] run configuration + isofox_functions // string: [optional] Isofox functions + isofox_read_length // string: [mandatory] Isofox read length main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Create inputs and create process-specific meta + // Sort inputs + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.ISOFOX_DIR) + runnable: Utils.hasTumorRnaBam(meta) && !has_existing + skip: true + } + + // Create process input channel // channel: [ meta_isofox, tumor_bam_rna ] - if (run_config.stages.isofox) { - ch_isofox_inputs = ch_inputs - .map { meta -> - def bam = Utils.getTumorRnaBam(meta) - def meta_isofox = [key: meta.id, id: Utils.getTumorRnaSampleName(meta)] - return [meta_isofox, bam, "${bam}.bai"] - } - } else { - ch_isofox_inputs = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional') - } + ch_isofox_inputs = ch_inputs_sorted.runnable + .map { meta -> + + def meta_isofox = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorRnaSampleName(meta), + ] + + return [meta_isofox, Utils.getTumorRnaBam(meta), Utils.getTumorRnaBai(meta)] + } // Run process ISOFOX( @@ -59,10 +69,16 @@ workflow ISOFOX_QUANTIFICATION { isofox_tpm_norm, ) - // Set outputs, restoring original meta - ch_outputs = WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs) ch_versions = ch_versions.mix(ISOFOX.out.versions) + // Set outputs, restoring original meta + // channel: [ meta, isofox_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + emit: isofox_dir = ch_outputs // channel: [ meta, isofox_dir ] diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index eb31186b..d69e8668 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -14,7 +14,7 @@ workflow LILAC_CALLING { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] - ch_purple // channel: [optional] [ meta, purple_dir ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] // Reference data genome_fasta // channel: [mandatory] /path/to/genome_fasta @@ -23,212 +23,194 @@ workflow LILAC_CALLING { lilac_resource_dir // channel: [mandatory] /path/to/lilac_resource_dir/ hla_slice_bed // channel: [mandatory] /path/to/hla_slice_bed - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Select input sources - // channel: [ meta, purple_dir ] - if (run_config.stages.purple) { - ch_lilac_inputs_purple = ch_purple - } else { - ch_lilac_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR, type: 'optional') - } + // Sort inputs + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> - // Create channels for available input BAMs - // channel: [ meta, rna_bam, rna_bai ] - ch_lilac_bams_rna = Channel.empty() - if (run_config.mode == Constants.RunMode.RNA || run_config.mode == Constants.RunMode.DNA_RNA) { - ch_lilac_bams_rna = ch_inputs - .map { meta -> - def bam = Utils.getTumorRnaBam(meta) - return [meta, bam, "${bam}.bai"] - } - } else { - ch_lilac_bams_rna = ch_inputs.map { meta -> [meta, [], []] } - } + def has_tumor_dna = Utils.hasTumorDnaBam(meta) + def has_normal_dna = Utils.hasNormalDnaBam(meta) - // channel: [ meta, bam, bai ] - ch_lilac_bams = Channel.empty() - if (run_config.mode == Constants.RunMode.DNA || run_config.mode == Constants.RunMode.DNA_RNA) { + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.LILAC_DIR) - ch_lilac_bams = ch_inputs - .map { meta -> + runnable: (has_tumor_dna || has_normal_dna) && !has_existing + skip: true + } - def tumor_bam = Utils.getTumorDnaBam(meta) + // Create channel for DNA BAMs + // channel: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] + ch_dna_inputs = ch_inputs_sorted.runnable + .map { meta -> - def normal_bam = [] - def normal_bai = [] + def tumor_bam = [] + def tumor_bai = [] - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - normal_bam = Utils.getNormalDnaBam(meta) - normal_bai = "${normal_bam}.bai" - } + def normal_bam = [] + def normal_bai = [] - [meta, tumor_bam, normal_bam, "${tumor_bam}.bai", normal_bai] + if (Utils.hasTumorDnaBam(meta)) { + tumor_bam = Utils.getTumorDnaBam(meta) + tumor_bai = Utils.getTumorDnaBai(meta) } - } else if (run_config.mode == Constants.RunMode.PANEL) { - - ch_lilac_bams = ch_inputs - .map { meta -> - def tumor_bam = Utils.getTumorBam(meta, run_config.mode) - [meta, tumor_bam, [], "${tumor_bam}.bai", []] + if (Utils.hasNormalDnaBam(meta)) { + normal_bam = Utils.getNormalDnaBam(meta) + normal_bai = Utils.getNormalDnaBai(meta) } - } else { - ch_lilac_bams = ch_inputs.map { meta -> [meta, [], [], [], []] } - } + return [meta, tumor_bam, tumor_bai, normal_bam, normal_bai] + } // Realign reads mapping to HLA regions and homologus regions if using reference genome with ALT contigs // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them to the three // relevant HLA genes on chr6. All reads including those previously mapped to chr6 are realigned for // consistency. - // channel: [ meta, bam, bai ] - ch_lilac_bams = ch_lilac_bams if (params.ref_data_genome_type == 'alt') { - // Split DNA BAMs into tumor and normal, accounting for optional input - // channel: [ meta_extra, bam, bai ] - ch_slice_bams = ch_lilac_bams - .flatMap { meta, tumor_bam, normal_bam, tumor_bai, normal_bai -> + // Flatten into BAM/BAI pairs, select inputs that are eligible to run + // channel: runnable: [ meta_extra, bam, bai ] + // channel: skip: [ meta_extra ] + ch_realign_inputs_sorted = ch_dna_inputs + .flatMap { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + + def tumor_sample_id = Utils.hasTumorDnaBam(meta) ? Utils.getTumorDnaSampleName(meta) : [] + def normal_sample_id = Utils.hasNormalDnaBam(meta) ? Utils.getNormalDnaSampleName(meta) : [] + return [ - [[key: meta.id, *:meta, sequence_type: 'tumor'], tumor_bam, tumor_bai], - [[key: meta.id, *:meta, sequence_type: 'normal'], normal_bam, normal_bai], + [[key: meta.group_id, *:meta, sample_id: tumor_sample_id, sample_type: 'tumor'], tumor_bam, tumor_bai], + [[key: meta.group_id, *:meta, sample_id: normal_sample_id, sample_type: 'normal'], normal_bam, normal_bai], ] } - .branch { - def empty = it[1..-1] == [[], []] - present: !empty - absent: empty + .branch { meta_extra, bam, bai -> + runnable: bam && bai + skip: true + return meta_extra } - // Prepare slice input channel - // channel: [ meta_slice, bam, bai ] - ch_slice_bams_input = ch_slice_bams.present - .map { meta, bam, bai -> - - def sample_name - if (meta.sequence_type == 'tumor') { - sample_name = meta[['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.DNA]] - } else if (meta.sequence_type == 'normal') { - sample_name = meta[['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.DNA]] - } - - def meta_slice = [ - key: meta.id, - id: sample_name, - sequence_type: meta.sequence_type, + // + // MODULE: Custom BAM slice (LILAC) + // + // Create process input channel + // channel: [ meta_realign, bam, bai ] + ch_slice_inputs = ch_realign_inputs_sorted.runnable + .map { meta_extra, bam, bai -> + + def meta_realign = [ + key: meta_extra.group_id, + id: "${meta_extra.group_id}__${meta_extra.sample_id}", + sample_id: meta_extra.sample_id, + sample_type: meta_extra.sample_type, ] - return [meta_slice, bam, bai] - + return [meta_realign, bam, bai] } - // - // MODULE: Custom BAM slice (LILAC) - // + // Run process SLICEBAM( - ch_slice_bams_input, + ch_slice_inputs, hla_slice_bed, ) + ch_versions = ch_versions.mix(SLICEBAM.out.versions) // // MODULE: Custom extract contig (LILAC) // - // Extract chromosome 6 from the reference and create BWA indexes EXTRACTCONTIG( 'chr6', genome_fasta, genome_fai, ) + ch_versions = ch_versions.mix(EXTRACTCONTIG.out.versions) // // MODULE: Custom realign reads (LILAC) // - // Realign selected reads relevant to HLA to chromosome 6 REALIGNREADS( SLICEBAM.out.bam, EXTRACTCONTIG.out.contig, EXTRACTCONTIG.out.bwa_indices, ) + ch_versions = ch_versions.mix(REALIGNREADS.out.versions) - // Split realigned BAMs by sequence type for processing below - // channel: [ meta, bam, bai ] - ch_slice_reunited_bams = REALIGNREADS.out.bam - .mix (ch_slice_bams.absent) - .branch { - def meta = it[0] - tumor: meta.sequence_type == 'tumor' - normal: meta.sequence_type == 'normal' + // Separate all BAMs by sample type so they can be merged with desired order + // channel: [ < meta_extra OR meta_realign >, bam, bai ] + ch_slice_reunited_bams = Channel.empty() + .mix( + ch_realign_inputs_sorted.skip.map { meta_extra -> [meta_extra, [], []] }, + REALIGNREADS.out.bam, + ) + .branch { meta_ambiguous, bam, bai -> + tumor: meta_ambiguous.sample_type == 'tumor' + normal: meta_ambiguous.sample_type == 'normal' } - // Restore original meta for realigned BAMs then combine with absent inputs - // channel: [ meta, tumor_bam, normal_bam, tumor_bai, normal_bai ] - ch_lilac_bams = WorkflowOncoanalyser.groupByMeta( + // Restore meta, pair tumor and normal BAMs + // channel: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] + ch_dna_inputs_ready = WorkflowOncoanalyser.groupByMeta( WorkflowOncoanalyser.restoreMeta(ch_slice_reunited_bams.tumor, ch_inputs), WorkflowOncoanalyser.restoreMeta(ch_slice_reunited_bams.normal, ch_inputs), ) - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - return [meta, tumor_bam, normal_bam, tumor_bai, normal_bai] - } + + } else { + + // channel: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] + ch_dna_inputs_ready = ch_dna_inputs } - // Combine DNA and RNA BAMs, and order as required - // channel: [ meta, normal_dna_bam, normal_dna_bai, tumor_bam, tumor_bai, tumor_rna_bam, tumor_rna_bai ] - ch_lilac_bams_combined = WorkflowOncoanalyser.groupByMeta( - ch_lilac_bams_rna, - ch_lilac_bams, - flatten_mode: 'nonrecursive', - ) - .map { data -> - def meta = data[0] - def (tbam_rna, tbai_rna, tbam, nbam, tbai, nbai) = data[1..-1] - return [meta, nbam, nbai, tbam, tbai, tbam_rna, tbai_rna] + // Create channel for RNA BAMs + // channel: [ meta, tumor_rna_bam, tumor_rna_bai ] + ch_rna_inputs_ready = ch_inputs + .map { meta -> + + def bam = [] + def bai = [] + + if (Utils.hasTumorRnaBam(meta)) { + bam = Utils.getTumorRnaBam(meta) + bai = Utils.getTumorRnaBai(meta) + } + + return [meta, bam, bai] } - // Add PURPLE inputs - // channel: [ meta, normal_dna_bam, normal_dna_bai, tumor_bam, tumor_bai, tumor_rna_bam, tumor_rna_bai, purple_dir ] - ch_lilac_inputs_full = WorkflowOncoanalyser.groupByMeta( - ch_lilac_bams_combined, - ch_lilac_inputs_purple, - flatten_mode: 'nonrecursive', + // + // MODULE: LILAC + // + // Create process input channel + // channel: [ meta_lilac, normal_dna_bam, normal_dna_bai, tumor_dna_bam, tumor_dna_bai, tumor_rna_bam, tumor_rna_bai, purple_dir ] + ch_lilac_inputs = WorkflowOncoanalyser.groupByMeta( + ch_dna_inputs_ready, + ch_rna_inputs_ready, + ch_purple, ) + .map { meta, tbam_dna, tbai_dna, nbam_dna, nbai_dna, tbam_rna, tbai_rna, purple_dir -> - // Create final input channel for LILAC, remove samples with only RNA BAMs - // channel: [ meta_lilac, normal_dna_bam, normal_dna_bai, tumor_bam, tumor_bai, tumor_rna_bam, tumor_rna_bai, purple_dir ] - ch_lilac_inputs = ch_lilac_inputs_full - .map { - def meta = it[0] - def fps = it[1..-1] + def meta_lilac = [ + key: meta.group_id, + id: meta.group_id, + ] - // LILAC requires either tumor or normal DNA BAM - if (fps[0] == [] && fps[2] == []) { - return Constants.PLACEHOLDER_META + if (Utils.hasTumorDnaBam(meta)) { + meta_lilac.tumor_id = Utils.getTumorDnaSampleName(meta) } - def normal_id_key = ['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.DNA] - def tumor_id_key = ['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.DNA] + if (Utils.hasNormalDnaBam(meta)) { + meta_lilac.normal_id = Utils.getNormalDnaSampleName(meta) + } - def meta_lilac = [ - key: meta.id, - id: meta.id, - tumor_id: meta.containsKey(tumor_id_key) ? meta.getAt(tumor_id_key) : '', - normal_id: meta.containsKey(normal_id_key) ? meta.getAt(normal_id_key) : '', - ] - return [meta_lilac, *fps] + return [meta_lilac, nbam_dna, nbai_dna, tbam_dna, tbai_dna, tbam_rna, tbai_rna, purple_dir] } - .filter { it != Constants.PLACEHOLDER_META } - // Run LILAC + // Run process LILAC( ch_lilac_inputs, genome_fasta, @@ -236,9 +218,15 @@ workflow LILAC_CALLING { lilac_resource_dir, ) - // Set outputs, restoring original meta ch_versions = ch_versions.mix(LILAC.out.versions) - ch_outputs = WorkflowOncoanalyser.restoreMeta(LILAC.out.lilac_dir, ch_inputs) + + // Set outputs, restoring original meta + // channel: [ meta, amber_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(LILAC.out.lilac_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: lilac_dir = ch_outputs // channel: [ meta, lilac_dir ] diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf index 0196da55..0795a72b 100644 --- a/subworkflows/local/linx_annotation.nf +++ b/subworkflows/local/linx_annotation.nf @@ -12,7 +12,7 @@ workflow LINX_ANNOTATION { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] - ch_purple // channel: [optional] [ meta, purple_dir ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] // Reference data genome_version // channel: [mandatory] genome version @@ -21,75 +21,109 @@ workflow LINX_ANNOTATION { driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel gene_id_file // channel: [mandatory] /path/to/linx_gene_id_file - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for versions.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Select input sources - // channel: [ meta, purple_dir ] - ch_linx_inputs_source = run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) + // Select input sources and sort + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_purple + .map { meta, purple_dir -> + return [ + meta, + Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), + ] + } + .branch { meta, purple_dir -> + runnable: purple_dir + skip: true + return meta + } // // MODULE: LINX germline annotation // - // channel: [ meta, sv_vcf ] - ch_linx_germline_out = Channel.empty() - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + // Select inputs that are eligible to run + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_germline_sorted = ch_inputs_sorted.runnable + .branch { meta, purple_dir -> + + def tumor_id = Utils.getTumorDnaSampleName(meta) - // Create germline inputs and create process-specific meta - // channel: [ meta_linx, sv_vcf ] - ch_linx_inputs_germline = ch_linx_inputs_source - .map { meta, purple_dir -> + def has_tumor_normal = Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) + def has_sv_germline_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.germline.vcf.gz") + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) - def tumor_id = Utils.getTumorDnaSampleName(meta) - def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.germline.vcf.gz") + runnable: has_tumor_normal && has_sv_germline_vcf && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta, sv_vcf ] + ch_linx_germline_inputs = ch_inputs_germline_sorted.runnable + .map { meta, purple_dir -> - if (!sv_vcf.exists()) { - return Constants.PLACEHOLDER_META - } + def tumor_id = Utils.getTumorDnaSampleName(meta) - def meta_linx = [ - key: meta.id, - id: tumor_id, - ] + def meta_linx = [ + key: meta.group_id, + id: meta.group_id, + sample_id: tumor_id, + ] - return [meta_linx, sv_vcf] - } - .filter { it != Constants.PLACEHOLDER_META } + def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.germline.vcf.gz") + return [meta_linx, sv_vcf] + } - GERMLINE( - ch_linx_inputs_germline, - genome_version, - ensembl_data_resources, - driver_gene_panel, - ) + // Run process + GERMLINE( + ch_linx_germline_inputs, + genome_version, + ensembl_data_resources, + driver_gene_panel, + ) - // Set outputs, restoring original meta - ch_versions = ch_versions.mix(GERMLINE.out.versions) - ch_linx_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.annotation_dir, ch_inputs) - } + ch_versions = ch_versions.mix(GERMLINE.out.versions) // // MODULE: LINX somatic annotation // - // Create somatic inputs and create process-specific meta - // channel: [ meta_linx, purple_dir ] - ch_linx_inputs_somatic = ch_linx_inputs_source + // Select inputs that are eligible to run + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_somatic_sorted = ch_inputs_sorted.runnable + .branch { meta, purple_dir -> + + def has_tumor = Utils.hasTumorDnaBam(meta) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) + + runnable: has_tumor && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta, purple_dir ] + ch_linx_somatic_inputs = ch_inputs_somatic_sorted.runnable .map { meta, purple_dir -> + def meta_linx = [ - key: meta.id, - id: Utils.getTumorDnaSampleName(meta), + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), ] + return [meta_linx, purple_dir] } + // Run process SOMATIC( - ch_linx_inputs_somatic, + ch_linx_somatic_inputs, genome_version, ensembl_data_resources, known_fusion_data, @@ -97,13 +131,28 @@ workflow LINX_ANNOTATION { gene_id_file, ) - // Set outputs, restoring original meta ch_versions = ch_versions.mix(SOMATIC.out.versions) - ch_linx_somatic_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.annotation_dir, ch_inputs) + + + // Set outputs, restoring original meta + // channel: [ meta, linx_annotation_dir ] + ch_somatic_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.annotation_dir, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + + ch_germline_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.annotation_dir, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - somatic = ch_linx_somatic_out // channel: [ meta, linx_annotation_dir ] - germline = ch_linx_germline_out // channel: [ meta, linx_annotation_dir ] + somatic = ch_somatic_out // channel: [ meta, linx_annotation_dir ] + germline = ch_germline_out // channel: [ meta, linx_annotation_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/linx_plotting.nf b/subworkflows/local/linx_plotting.nf index b539fce2..20d1e9cf 100644 --- a/subworkflows/local/linx_plotting.nf +++ b/subworkflows/local/linx_plotting.nf @@ -2,6 +2,7 @@ // LINX plotting visualises clusters structural variants // +import Constants import Utils include { GPGR_LINX as GPGR } from '../../modules/local/gpgr/linx/main' @@ -10,65 +11,108 @@ include { LINX_VISUALISER as VISUALISER } from '../../modules/local/linx/visuali workflow LINX_PLOTTING { take: // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_annotations // channel: [mandatory] [ meta, linx_annotation_dir ] + ch_inputs // channel: [mandatory] [ meta ] + ch_annotations // channel: [mandatory] [ meta, annotation_dir ] // Reference data - genome_version // channel: [mandatory] genome version - ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ - - // Params - run_config // channel: [mandatory] run configuration + genome_version // channel: [mandatory] genome version + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ main: // Channel for versions.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Select input sources - // channel: [ meta_linx, linx_annotation_dir ] - ch_linx_visualiser_inputs = ch_annotations - .map { meta, anno_dir -> + // Select input sources and sort + // channel: runnable: [ meta, annotation_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_annotations + .map { meta, annotation_dir -> + return [ + meta, + Utils.selectCurrentOrExisting(annotation_dir, meta, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + ] + } + .branch { meta, annotation_dir -> + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.LINX_PLOT_DIR_TUMOR) + + runnable: annotation_dir && !has_existing + skip: true + return meta + } + + // + // MODULE: LINX visualiser + // + // Create process input channel + // channel: [ meta_linx, annotation_dir ] + ch_linx_visualiser_inputs = ch_inputs_sorted.runnable + .map { meta, annotation_dir -> + def meta_linx = [ - key: meta.id, - id: Utils.getTumorDnaSampleName(meta), + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), ] - return [meta_linx, anno_dir] + + return [meta_linx, annotation_dir] } + // Run process VISUALISER( ch_linx_visualiser_inputs, genome_version, ensembl_data_resources, ) - // Set outputs, restoring original meta - ch_visualiser_out = WorkflowOncoanalyser.restoreMeta(VISUALISER.out.visualiser_dir, ch_inputs) ch_versions = ch_versions.mix(VISUALISER.out.versions) - - // Create inputs and create process-specific meta - // channel: [ meta_gpgr_linx, linx_annotation_dir, visualiser_dir ] + // + // MODULE: gpgr LINX report + // + // Create process input channel + // channel: [ meta_gpgr, annotation_dir, visualiser_dir_all ] ch_gpgr_linx_inputs = WorkflowOncoanalyser.groupByMeta( - ch_annotations, - ch_visualiser_out, + ch_inputs_sorted.runnable, + WorkflowOncoanalyser.restoreMeta(VISUALISER.out.visualiser_dir_all, ch_inputs), ) - .map { meta, anno_dir, vis_dir -> + .map { meta, annotation_dir, visualiser_dir -> + def meta_gpgr_linx = [ - key: meta.id, - id: Utils.getTumorDnaSampleName(meta), + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), ] - return [meta_gpgr_linx, anno_dir, vis_dir] + + return [meta_gpgr_linx, annotation_dir, visualiser_dir] } + // Run process GPGR( ch_gpgr_linx_inputs, ) ch_versions = ch_versions.mix(GPGR.out.versions) + // Set outputs, restoring original meta + // channel: [ meta, visualiser_dir_all ] + ch_visualiser_all_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(VISUALISER.out.visualiser_dir_all, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + + // channel: [ meta, visualiser_dir_reportable ] + ch_visualiser_reportable_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(VISUALISER.out.visualiser_dir_reportable, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + emit: - visualiser_dir = ch_visualiser_out // channel: [ meta, visualiser_dir ] + visualiser_dir_all = ch_visualiser_all_out // channel: [ meta, visualiser_dir_all ] + visualiser_dir_reportable = ch_visualiser_reportable_out // channel: [ meta, visualiser_dir_reportable ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 9844b514..e3818522 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -7,28 +7,28 @@ import Utils include { ORANGE } from '../../modules/local/orange/main' -include { FLAGSTAT_METRICS } from './flagstat_metrics' - workflow ORANGE_REPORTING { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] ch_bamtools_somatic // channel: [mandatory] [ meta, metrics ] - ch_bamtools_germline // channel: [optional] [ meta, metrics ] + ch_bamtools_germline // channel: [mandatory] [ meta, metrics ] + ch_flagstat_somatic // channel: [mandatory] [ meta, metrics ] + ch_flagstat_germline // channel: [mandatory] [ meta, metrics ] ch_sage_somatic // channel: [mandatory] [ meta, sage_dir ] - ch_sage_germline // channel: [optional] [ meta, sage_dir ] - ch_sage_somatic_append // channel: [optional] [ meta, sage_append_vcf ] - ch_sage_germline_append // channel: [optional] [ meta, sage_append_vcf ] + ch_sage_germline // channel: [mandatory] [ meta, sage_dir ] + ch_sage_somatic_append // channel: [mandatory] [ meta, sage_append_vcf ] + ch_sage_germline_append // channel: [mandatory] [ meta, sage_append_vcf ] ch_purple // channel: [mandatory] [ meta, purple_dir ] ch_linx_somatic_annotation // channel: [mandatory] [ meta, linx_annotation_dir ] - ch_linx_somatic_plot // channel: [mandatory] [ meta, linx_visualiser_dir ] - ch_linx_germline_annotation // channel: [optional] [ meta, linx_annotation_dir ] - ch_virusinterpreter // channel: [optional] [ meta, virusinterpreter_dir ] - ch_chord // channel: [optional] [ meta, chord_dir ] - ch_sigs // channel: [optional] [ meta, sigs_dir ] + ch_linx_somatic_plot // channel: [mandatory] [ meta, linx_visualiser_dir_reportable ] + ch_linx_germline_annotation // channel: [mandatory] [ meta, linx_annotation_dir ] + ch_virusinterpreter // channel: [mandatory] [ meta, virusinterpreter_dir ] + ch_chord // channel: [mandatory] [ meta, chord_dir ] + ch_sigs // channel: [mandatory] [ meta, sigs_dir ] ch_lilac // channel: [mandatory] [ meta, lilac_dir ] - ch_cuppa // channel: [optional] [ meta, cuppa_dir ] - ch_isofox // channel: [optional] [ meta, isofox_dir ] + ch_cuppa // channel: [mandatory] [ meta, cuppa_dir ] + ch_isofox // channel: [mandatory] [ meta, isofox_dir ] // Reference data genome_version // channel: [mandatory] genome version @@ -41,141 +41,188 @@ workflow ORANGE_REPORTING { isofox_alt_sj // channel: [optional] /path/to/isofox_alt_sj isofox_gene_distribution // channel: [optional] /path/to/isofox_gene_distribution - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // - // SUBWORKFLOW: Run SAMtools flagstat to generate stats required for ORANGE - // - // channel: [ meta, metrics ] - ch_flagstat_somatic_out = Channel.empty() - ch_flagstat_germline_out = Channel.empty() - if (run_config.stages.flagstat) { - - FLAGSTAT_METRICS( - ch_inputs, - run_config, - ) + // Set expected input ordering and size + input_expected_size = 18 + + dna_tumor_input_indexes = [ + 0, // bamtools_somatic + 2, // flagstat_somatic + 4, // sage_somatic + 8, // purple_dir + 9, // linx_somatic_annotation + 10, // linx_somatic_plot_dir + 15, // lilac_dir + ] + + dna_normal_input_indexes = [ + 1, // bamtools_germline + 3, // flagstat_germline + 5, // sage_germline + 11, // linx_germline_annotation + ] + + rna_tumor_input_indexes = [ + 6, // sage_somatic_append + 17, // isofox_dir + ] + + rna_sage_germline_append_index = 7 // sage_germline_append + + // Select input sources + // channel: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsage_append, nsage_append, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir ] + ch_inputs_selected = WorkflowOncoanalyser.groupByMeta( + ch_bamtools_somatic, + ch_bamtools_germline, + ch_flagstat_somatic, + ch_flagstat_germline, + ch_sage_somatic, + ch_sage_germline, + ch_sage_somatic_append, + ch_sage_germline_append, + ch_purple, + ch_linx_somatic_annotation, + ch_linx_somatic_plot, + ch_linx_germline_annotation, + ch_virusinterpreter, + ch_chord, + ch_sigs, + ch_lilac, + ch_cuppa, + ch_isofox, + ) + .map { d -> + + def meta = d[0] + def inputs = d[1..-1] + + assert inputs.size() == input_expected_size + + // NOTE(SW): avoiding further complexity with loops etc + + def inputs_selected = [ + Utils.selectCurrentOrExisting(inputs[0], meta, Constants.INPUT.BAMTOOLS_TUMOR), + Utils.selectCurrentOrExisting(inputs[1], meta, Constants.INPUT.BAMTOOLS_NORMAL), + Utils.selectCurrentOrExisting(inputs[2], meta, Constants.INPUT.FLAGSTAT_TUMOR), + Utils.selectCurrentOrExisting(inputs[3], meta, Constants.INPUT.FLAGSTAT_NORMAL), + Utils.selectCurrentOrExisting(inputs[4], meta, Constants.INPUT.SAGE_VCF_TUMOR), + Utils.selectCurrentOrExisting(inputs[5], meta, Constants.INPUT.SAGE_VCF_NORMAL), + Utils.selectCurrentOrExisting(inputs[6], meta, Constants.INPUT.SAGE_APPEND_VCF_TUMOR), + Utils.selectCurrentOrExisting(inputs[7], meta, Constants.INPUT.SAGE_APPEND_VCF_NORMAL), + Utils.selectCurrentOrExisting(inputs[8], meta, Constants.INPUT.PURPLE_DIR), + Utils.selectCurrentOrExisting(inputs[9], meta, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + Utils.selectCurrentOrExisting(inputs[10], meta, Constants.INPUT.LINX_PLOT_DIR_TUMOR), + Utils.selectCurrentOrExisting(inputs[11], meta, Constants.INPUT.LINX_ANNO_DIR_NORMAL), + Utils.selectCurrentOrExisting(inputs[12], meta, Constants.INPUT.VIRUSINTERPRETER_DIR), + Utils.selectCurrentOrExisting(inputs[13], meta, Constants.INPUT.CHORD_DIR), + Utils.selectCurrentOrExisting(inputs[14], meta, Constants.INPUT.SIGS_DIR), + Utils.selectCurrentOrExisting(inputs[15], meta, Constants.INPUT.LILAC_DIR), + Utils.selectCurrentOrExisting(inputs[16], meta, Constants.INPUT.CUPPA_DIR), + Utils.selectCurrentOrExisting(inputs[17], meta, Constants.INPUT.ISOFOX_DIR), + ] - ch_versions = ch_versions.mix(FLAGSTAT_METRICS.out.versions) - ch_flagstat_somatic_out = ch_flagstat_somatic_out.mix(FLAGSTAT_METRICS.out.somatic) - ch_flagstat_germline_out = ch_flagstat_germline_out.mix(FLAGSTAT_METRICS.out.germline) - } - - // - // MODULE: Run ORANGE - // - // Create placeholders for tumor-only - if (run_config.type == Constants.RunType.TUMOR_ONLY) { - ch_flagstat_germline_out = ch_inputs.map { meta -> [meta, []] } - ch_bamtools_germline = ch_inputs.map { meta -> [meta, []] } - ch_sage_germline = ch_inputs.map { meta -> [meta, []] } - ch_sage_germline_append = ch_inputs.map { meta -> [meta, []] } - ch_linx_germline_annotation = ch_inputs.map { meta -> [meta, []] } - } - - // Do not pass RNA reference files when not required - // NOTE(SW): ORANGE v2.6.0 will crash if RNA reference files but not RNA sample files provided - if (run_config.mode != Constants.RunMode.RNA && run_config.mode != Constants.RunMode.DNA_RNA) { - isofox_alt_sj = [] - isofox_gene_distribution = [] - } - - // Get PURPLE input source for processing - ch_orange_inputs_purple_dir = run_config.stages.purple ? ch_purple : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - - // Get input smlv somatic VCF from either PURPLE or SAGE append - // channel: [ meta, sage_somatic_vcf, sage_germline_vcf ] - if (run_config.mode == Constants.RunMode.DNA) { - - ch_orange_inputs_smlv_vcfs = ch_orange_inputs_purple_dir - .map { meta, purple_dir -> - def tumor_id = Utils.getTumorDnaSampleName(meta) - - def smlv_somatic_vcf = [] - def smlv_germline_vcf = [] - - def smlv_somatic_vcf_path = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - def smlv_germline_vcf_path = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") - - if (smlv_somatic_vcf_path.exists()) { - smlv_somatic_vcf = smlv_somatic_vcf_path - } - - // NOTE(SW): can only evaluate to true with DNA tumor/normal - if (smlv_germline_vcf_path.exists()) { - smlv_germline_vcf = smlv_germline_vcf_path - } - - return [meta, smlv_somatic_vcf, smlv_germline_vcf] - } + return [meta, *inputs_selected] + } + + // Sort inputs + // channel: runnable: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsage_append, nsage_append, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_inputs_selected + .branch { d -> + + def meta = d[0] + def inputs = d[1..-1] + + def has_dna_tumor = dna_tumor_input_indexes + .collect { i -> inputs[i] } + .every() - } else if (run_config.mode == Constants.RunMode.DNA_RNA) { + def has_rna_tumor = rna_tumor_input_indexes + .collect { i -> inputs[i] } + .every() - ch_orange_inputs_smlv_vcfs = WorkflowOncoanalyser.groupByMeta( - ch_sage_somatic_append, - ch_sage_germline_append, + runnable_dna_and_rna: has_dna_tumor && has_rna_tumor + runnable_dna: has_dna_tumor + skip: true + return meta + } + + // First set RNA reference files + // NOTE(SW): since the RNA reference files are provided as channels, I seem to be only able to include via channel ops + // channel: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsage_append, nsage_append, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir, isofox_alt_sj, isofox_gene_distribution ] + ch_inputs_runnable = Channel.empty() + .mix( + ch_inputs_sorted.runnable_dna.map { d -> [*d, [], []] }, + ch_inputs_sorted.runnable_dna_and_rna + .combine(isofox_alt_sj) + .combine(isofox_gene_distribution), ) - } else { - ch_orange_inputs_smlv_vcfs = ch_inputs.map { meta -> [meta, [], []] } - } - - // Select input source - ch_orange_inputs_source = WorkflowOncoanalyser.groupByMeta( - run_config.stages.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_TUMOR), - run_config.stages.bamtools ? ch_bamtools_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.BAMTOOLS_NORMAL, type: 'optional'), - run_config.stages.flagstat ? ch_flagstat_somatic_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_TUMOR), - run_config.stages.flagstat ? ch_flagstat_germline_out : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.FLAGSTAT_NORMAL, type: 'optional'), - run_config.stages.sage ? ch_sage_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_DIR_TUMOR), - run_config.stages.sage ? ch_sage_germline : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_DIR_NORMAL, type: 'optional'), - ch_orange_inputs_purple_dir, - ch_orange_inputs_smlv_vcfs, - run_config.stages.linx ? ch_linx_somatic_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_TUMOR), - run_config.stages.linx ? ch_linx_somatic_plot : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_PLOT_DIR_TUMOR), - run_config.stages.linx ? ch_linx_germline_annotation : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LINX_ANNO_DIR_NORMAL, type: 'optional'), - run_config.stages.virusinterpreter ? ch_virusinterpreter : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.VIRUSINTERPRETER_DIR, type: 'optional'), - run_config.stages.chord ? ch_chord : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CHORD_DIR, type: 'optional'), - run_config.stages.sigs ? ch_sigs : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SIGS_DIR, type: 'optional'), - run_config.stages.lilac ? ch_lilac : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.LILAC_DIR), - run_config.stages.cuppa ? ch_cuppa : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.CUPPA_DIR, type: 'optional'), - run_config.stages.isofox ? ch_isofox : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.ISOFOX_DIR, type: 'optional'), - flatten_mode: 'nonrecursive', - ) + // Create process input channel + // channel: sample_data: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsmlv_vcf, nsmlv_vcf, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir ] + // channel: isofox_alt_sj: [ isofox_alt_sj ] + // channel: isofox_gene_distribution: [ isofox_gene_distribution ] + ch_orange_inputs = ch_inputs_runnable + .multiMap { d -> - ch_orange_inputs = ch_orange_inputs_source - .map { - def meta = it[0] + def meta = d[0] + def inputs = d[1..-3] - // NOTE(SW): these attributes are optional - def normal_dna_id = meta.getAt(['sample_name', Constants.SampleType.NORMAL, Constants.SequenceType.DNA]) - def tumor_rna_id = meta.getAt(['sample_name', Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) + def isofox_alt_sj = d[-2] + def isofox_gene_distribution = d[-1] def meta_orange = [ - key: meta.id, - id: meta.id, + key: meta.group_id, + id: meta.group_id, tumor_id: Utils.getTumorDnaSampleName(meta), ] - // Add optional identifiers to meta - if (normal_dna_id) { - meta_orange.normal_dna_id = normal_dna_id + def inputs_selected = inputs.clone() + + // Require all normal DNA inputs to be present else clear them + def has_dna_normal = dna_normal_input_indexes + .collect { i -> inputs[i] } + .every() + + if (has_dna_normal) { + meta_orange.normal_dna_id = Utils.getNormalDnaSampleName(meta) + } else { + dna_normal_input_indexes.each { i -> inputs_selected[i] = [] } } - if (tumor_rna_id) { - meta_orange.tumor_rna_id = tumor_rna_id + + // Require all tumor RNA inputs to be present else clear them + // SAGE append germline is only required when normal DNA is present + def rna_tumor_input_indexes_ready + if (has_dna_normal) { + rna_tumor_input_indexes_ready = [*rna_tumor_input_indexes, rna_sage_germline_append_index] + } else { + rna_tumor_input_indexes_ready = rna_tumor_input_indexes.clone() } - return [meta_orange, *it[1..-1]] + def has_rna_tumor = rna_tumor_input_indexes_ready + .collect { i -> inputs[i] } + .every() + + if (has_rna_tumor) { + meta_orange.tumor_rna_id = Utils.getTumorRnaSampleName(meta) + } else { + rna_tumor_input_indexes.each { i -> inputs_selected[i] = [] } + } + + assert inputs_selected.size() == input_expected_size + + sample_data: [meta_orange, *inputs_selected] + isofox_alt_sj: isofox_alt_sj + isofox_gene_distribution: isofox_gene_distribution } // Run process ORANGE( - ch_orange_inputs, + ch_orange_inputs.sample_data, genome_version, disease_ontology, cohort_mapping, @@ -183,12 +230,11 @@ workflow ORANGE_REPORTING { known_fusion_data, driver_gene_panel, ensembl_data_resources, - isofox_alt_sj, - isofox_gene_distribution, + ch_orange_inputs.isofox_alt_sj, + ch_orange_inputs.isofox_gene_distribution, "5.33 [oncoanalyser]", ) - // Set outputs ch_versions = ch_versions.mix(ORANGE.out.versions) emit: diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf index b43a0918..54039413 100644 --- a/subworkflows/local/pave_annotation.nf +++ b/subworkflows/local/pave_annotation.nf @@ -2,6 +2,9 @@ // PAVE annotates somatic and germline variant VCFs with gene and transcript coding and protein effects // +import Constants +import Utils + include { PAVE_GERMLINE as GERMLINE } from '../../modules/local/pave/germline/main' include { PAVE_SOMATIC as SOMATIC } from '../../modules/local/pave/somatic/main' @@ -9,8 +12,8 @@ workflow PAVE_ANNOTATION { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] - ch_sage_germline_vcf // channel: [optional] [ meta, sage_germline_vcf ] - ch_sage_somatic_vcf // channel: [mandatory] [ meta, sage_somatic_vcf ] + ch_sage_germline_vcf // channel: [mandatory] [ meta, sage_germline_vcf, sage_somatic_tbi ] + ch_sage_somatic_vcf // channel: [mandatory] [ meta, sage_somatic_vcf, sage_somatic_tbi ] // Reference data genome_fasta // channel: [mandatory] /path/to/genome_fasta @@ -26,78 +29,100 @@ workflow PAVE_ANNOTATION { ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ gnomad_resource // channel: [mandatory] /path/to/gnomad_resource - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files ch_versions = Channel.empty() - // Select input sources - // channel: [meta, sage_vcf, sage_tbi] - if (run_config.stages.sage) { - ch_pave_germline_inputs_source = ch_sage_germline_vcf - ch_pave_somatic_inputs_source = ch_sage_somatic_vcf - } else { - ch_pave_germline_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_NORMAL) - .filter { it[0] != Constants.PLACEHOLDER_META } - .map { meta, vcf -> [meta, vcf, "${vcf}.tbi"] } - ch_pave_somatic_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.SAGE_VCF_TUMOR) - .filter { it[0] != Constants.PLACEHOLDER_META } - .map { meta, vcf -> [meta, vcf, "${vcf}.tbi"] } - } - // // MODULE: PAVE germline // - ch_germline_out = Channel.empty() - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - - // Create inputs and create process-specific meta - // channel: [val(meta_pave), sage_vcf] - ch_pave_germline_inputs = ch_pave_germline_inputs_source - .map { meta, sage_vcf, sage_tbi -> - def pave_meta = [ - key: meta.id, - // NOTE(SW): use of tumor sample name for PAVE germline is correct - id: Utils.getTumorDnaSampleName(meta), - ] - return [pave_meta, sage_vcf] - } - - GERMLINE( - ch_pave_germline_inputs, - genome_fasta, - genome_version, - genome_fai, - sage_blocklist_regions, - sage_blocklist_sites, - clinvar_annotations, - segment_mappability, - driver_gene_panel, - ensembl_data_resources, - gnomad_resource, - ) + // Select input sources and sort + // channel: runnable: [ meta, sage_vcf ] + // channel: skip: [ meta ] + ch_sage_germline_inputs_sorted = ch_sage_germline_vcf + .map { meta, sage_vcf, sage_tbi -> + return [ + meta, + Utils.selectCurrentOrExisting(sage_vcf, meta, Constants.INPUT.SAGE_VCF_NORMAL), + ] + } + .branch { meta, sage_vcf -> - ch_versions = ch_versions.mix(GERMLINE.out.versions) - ch_germline_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PAVE_VCF_NORMAL) + + runnable: Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) && sage_vcf && !has_existing + skip: true + return meta + } - } + // Create process input channel + // channel: [ meta_pave, sage_vcf ] + ch_pave_germline_inputs = ch_sage_germline_inputs_sorted.runnable + .map { meta, sage_vcf -> + + def meta_pave = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), + ] + + return [meta_pave, sage_vcf] + } + + // Run process + GERMLINE( + ch_pave_germline_inputs, + genome_fasta, + genome_version, + genome_fai, + sage_blocklist_regions, + sage_blocklist_sites, + clinvar_annotations, + segment_mappability, + driver_gene_panel, + ensembl_data_resources, + gnomad_resource, + ) + + ch_versions = ch_versions.mix(GERMLINE.out.versions) // // MODULE: PAVE somatic // - // Create inputs and create process-specific meta - // channel: [val(meta_pave), sage_vcf] - ch_pave_somatic_inputs = ch_pave_somatic_inputs_source + // Select input sources and sort + // channel: runnable: [ meta, sage_vcf ] + // channel: skip: [ meta ] + ch_sage_somatic_inputs_sorted = ch_sage_somatic_vcf .map { meta, sage_vcf, sage_tbi -> - def pave_meta = [ - key: meta.id, - id: Utils.getTumorDnaSampleName(meta), + return [ + meta, + Utils.selectCurrentOrExisting(sage_vcf, meta, Constants.INPUT.SAGE_VCF_TUMOR), + ] + } + .branch { meta, sage_vcf -> + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PAVE_VCF_TUMOR) + + runnable: Utils.hasTumorDnaBam(meta) && sage_vcf && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_pave, sage_vcf ] + ch_pave_somatic_inputs = ch_sage_somatic_inputs_sorted.runnable + .map { meta, sage_vcf -> + + def meta_pave = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), ] - return [pave_meta, sage_vcf] + + return [meta_pave, sage_vcf] } + // Run process SOMATIC( ch_pave_somatic_inputs, genome_fasta, @@ -112,11 +137,24 @@ workflow PAVE_ANNOTATION { ) ch_versions = ch_versions.mix(SOMATIC.out.versions) - ch_somatic_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs) + + // Set outputs, restoring original meta + // channel: [ meta, gripss_vcf, gripss_tbi ] + ch_somatic_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), + ch_sage_somatic_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + + ch_germline_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), + ch_sage_germline_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - germline = ch_germline_out // channel: [val(meta), pave_vcf] - somatic = ch_somatic_out // channel: [val(meta), pave_vcf] + germline = ch_germline_out // channel: [ meta, pave_vcf ] + somatic = ch_somatic_out // channel: [ meta, pave_vcf ] - versions = ch_versions // channel: [versions.yml] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/prepare_input.nf b/subworkflows/local/prepare_input.nf deleted file mode 100644 index 8c1f929b..00000000 --- a/subworkflows/local/prepare_input.nf +++ /dev/null @@ -1,318 +0,0 @@ -// -// Prepare input data -// - -import Constants -import Utils - - -workflow PREPARE_INPUT { - take: - // Sample data - ch_samplesheet // channel: [mandatory] /path/to/samplesheet - - // Params - run_config // channel: [mandatory] run configuration - - main: - - if (run_config.type == Constants.RunType.TUMOR_ONLY) { - sample_types_allowed = [Constants.SampleType.TUMOR] - } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - sample_types_allowed = [ - Constants.SampleType.TUMOR, - Constants.SampleType.NORMAL, - Constants.SampleType.TUMOR_NORMAL, - ] - } else { - assert false - } - - if (run_config.mode == Constants.RunMode.DNA) { - sequence_types_allowed = [Constants.SequenceType.DNA] - } else if (run_config.mode == Constants.RunMode.RNA) { - sequence_types_allowed = [Constants.SequenceType.RNA] - } else if (run_config.mode == Constants.RunMode.DNA_RNA) { - sequence_types_allowed = [Constants.SequenceType.DNA, Constants.SequenceType.RNA] - } else { - assert false - } - - - - - // TODO(SW): ensure that config enforces targeted cannot be RNA only - - - - - ch_inputs = Channel.of(ch_samplesheet) - .splitCsv(header: true) - .map { [it.id, it] } - .groupTuple() - .map { key, entries -> - def meta = [id: key] - def input_types_seen = [] - - // Process each entry - entries.each { - // Add subject name if absent or check if current matches existing - if (meta.containsKey('subject_name') && meta.subject_name != it.subject_name) { - log.error "\nERROR: got unexpected subject name for ${key}/${meta.subject_name}: ${it.subject_name}" - System.exit(1) - } else { - meta.subject_name = it.subject_name - } - - - // Sample type - def sample_type_enum = Utils.getEnumFromString(it.sample_type, Constants.SampleType) - if (!sample_type_enum) { - def sample_type_str = Utils.getEnumNames(Constants.SampleType).join('\n - ') - log.error "\nERROR: received invalid sample type: '${it.sample_type}'. Valid options are:\n - ${sample_type_str}" - System.exit(1) - } - - if (!sample_types_allowed.contains(sample_type_enum)) { - def sample_type_str = sample_types_allowed.collect { it.name().toLowerCase() }.join('\n - ') - def run_type_str = run_config.type.name().toLowerCase() - log.error "\nERROR: received invalid sample type for ${run_type_str} " + - "run: '${it.sample_type}'. Valid options are:\n - ${sample_type_str}" - System.exit(1) - } - - - - - // TODO(SW): understand whether this does (or why it doesn't) failure on DNA_RNA inputs (e.g. CUPPA) - - - - - // Sequence type - def sequence_type_enum = Utils.getEnumFromString(it.sequence_type, Constants.SequenceType) - if (!sequence_type_enum) { - def sequence_type_str = Utils.getEnumNames(Constants.SequenceType).join('\n - ') - log.error "\nERROR: received invalid sequence type: '${it.sequence_type}'. Valid options are:\n - ${sequence_type_str}" - System.exit(1) - } - - if (!sequence_types_allowed.contains(sequence_type_enum)) { - def sequence_types_str = sequence_types_allowed.collect { it.name().toLowerCase() }.join('\n - ') - def run_mode_str = run_config.mode.name().toLowerCase() - log.error "\nERROR: received invalid sample mode for ${run_mode_str} " + - "run: '${it.sequence_type}'. Valid options are:\n - ${sequence_types_str}" - System.exit(1) - } - - - // Filetype - def filetype_enum = Utils.getEnumFromString(it.filetype, Constants.FileType) - if (!filetype_enum) { - def filetype_str = Utils.getEnumNames(Constants.FileType).join('\n - ') - log.error "\nERROR: received invalid file type: '${it.filetype}'. Valid options are:\n - ${filetype_str}" - System.exit(1) - } - - // Check whether this input type already exists - def key_input_type = [sample_type_enum, sequence_type_enum, filetype_enum] - if (input_types_seen.contains(key_input_type)) { - log.error "\nERROR: got duplicate inputs for ${key}: ${sample_type_enum}/${filetype_enum}" - System.exit(1) - } - input_types_seen.push(key_input_type) - - - - - // TODO(SW): implement index finding when not provided in samplesheet - - - - - // Check for relevant indices - if (!workflow.stubRun) { - def filetype_bai = [ - Constants.FileType.BAM, - ] - - def filetype_tbi = [ - Constants.FileType.GRIDSS_VCF, - Constants.FileType.GRIPSS_VCF, - Constants.FileType.GRIPSS_UNFILTERED_VCF, - ] - - def index_ext - if (filetype_bai.contains(filetype_enum)) { - index_ext = 'bai' - } else if (filetype_tbi.contains(filetype_enum)) { - index_ext = 'tbi' - } - - if (index_ext) { - def index_fp_str = "${it.filepath}.${index_ext}".toString() - def index_fp = file(index_fp_str) - if (! index_fp.exists()) { - log.error "\nERROR: No index found for ${it.filepath}" - System.exit(1) - } - } - } - - // Sample name - def key_sample_name - if (sample_type_enum == Constants.SampleType.TUMOR_NORMAL) { - if (it.sample_name.contains(';')) { - def sample_name_tokens = it.sample_name.split(';') - if (sample_name_tokens.size() != 2) { - log.error "\nERROR: expected two sample names but got ${sample_name_tokens.size()}" - System.exit(1) - } - - def sample_name_and_types = [ - [Constants.SampleType.TUMOR, Constants.SampleType.NORMAL], - sample_name_tokens, - ] - sample_name_and_types - .transpose() - .each { st, sn -> - key_sample_name = ['sample_name', st, sequence_type_enum] - meta[key_sample_name] = process_sample_name(sn, key_sample_name, meta) - } - } else { - key_sample_name = ['sample_name', Constants.SampleType.TUMOR, sequence_type_enum] - meta[key_sample_name] = process_sample_name(it.sample_name, key_sample_name, meta) - } - } else { - key_sample_name = ['sample_name', sample_type_enum, sequence_type_enum] - meta[key_sample_name] = process_sample_name(it.sample_name, key_sample_name, meta) - } - - - // Filepath - def key_file = [filetype_enum, sample_type_enum, sequence_type_enum] - if (meta.containsKey(key_file)) { - log.error "\nERROR: got duplicate file for ${key}: ${filetype_enum}/${sample_type_enum}" - System.exit(1) - } else { - meta[key_file] = it.filepath - } - } - return meta - } - - - - - /* - // Check we have the required sample types for the specified run configuration - ch_inputs - .map { meta -> - - def sample_types = [] - for (e in meta) { - if (! e.key instanceof List || e.key[0] != 'sample_name') { - continue - } - sample_types.add(e.key[1..-1]) - } - - def required_sample_types - if (run_config.mode == Constants.RunMode.PANEL) { - - required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.TARGETTED], - ] - - } else if (run_config.mode == Constants.RunMode.DNA) { - - if (run_config.type == Constants.RunType.TUMOR_ONLY) { - required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], - ] - } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], - [Constants.SampleType.NORMAL, Constants.SequenceType.DNA], - ] - } else { - assert false - } - - } else if (run_config.mode == Constants.RunMode.RNA) { - - required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.RNA], - ] - - } else if (run_config.mode == Constants.RunMode.DNA_RNA) { - - if (run_config.type == Constants.RunType.TUMOR_ONLY) { - required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], - [Constants.SampleType.TUMOR, Constants.SequenceType.RNA], - ] - } else if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - required_sample_types = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], - [Constants.SampleType.TUMOR, Constants.SequenceType.RNA], - [Constants.SampleType.NORMAL, Constants.SequenceType.DNA], - ] - } else { - assert false - } - - } else { - assert false - } - - def sample_types_missing = required_sample_types - sample_types - def sample_types_extra = sample_types - required_sample_types - - - if (sample_types_missing) { - - def sample_type_str = sample_types_missing - .collect { e -> - def (sample, sequence) = e.collect { it.name().toLowerCase() } - return "${sample}/${sequence}" - } - .join('\n - ') - - def run_type_str = run_config.type.name().toLowerCase() - log.error "\nERROR: missing required input for ${run_type_str} run:\n - ${sample_type_str}" - System.exit(1) - } - - // NOTE(SW): this shold never evalutate as true with the above checks in place - if (sample_types_extra) { - - def sample_type_str = sample_types_extra - .collect { e -> - def (sample, sequence) = e.collect { it.name().toLowerCase() } - return "${sample}/${sequence}" - } - .join('\n - ') - - def run_type_str = run_config.type.name().toLowerCase() - log.error "\nERROR: extra input for ${run_type_str} run found:\n - ${sample_type_str}" - System.exit(1) - } - - } - */ - - - - - emit: - data = ch_inputs -} - -def process_sample_name(sample_name, key_sample_name, meta) { - if (meta.containsKey(key_sample_name) && meta[key_sample_name] != sample_name) { - log.error "\nERROR: got unexpected sample name for ${key}/${meta[key_sample_name]}: ${sample_name}" - System.exit(1) - } - return sample_name -} diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 12e90e33..848d9684 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -23,9 +23,10 @@ workflow PREPARE_REFERENCE { ch_versions = Channel.empty() // - // Set reference genome FASTA for consistency + // Set some variables for brevity // ch_genome_fasta = file(params.ref_data_genome_fasta) + run_virusinterpreter = run_config.mode !== Constants.RunMode.TARGETED && run_config.stages.virusinterpreter // // Create .fai and .dict for reference genome if required @@ -52,7 +53,7 @@ workflow PREPARE_REFERENCE { ch_genome_bwa_index = file(params.ref_data_genome_bwa_index) ch_genome_bwa_index_image = file(params.ref_data_genome_bwa_index_image) ch_genome_gridss_index = file(params.ref_data_genome_gridss_index) - if (run_config.stages.gridss || run_config.stages.virusinterpreter) { + if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { // NOTE(SW): the BWA index directory can be provided as a compressed tarball if (!params.ref_data_genome_bwa_index) { BWA_INDEX([[:], ch_genome_fasta]) @@ -97,7 +98,7 @@ workflow PREPARE_REFERENCE { // Set VIRUSBreakend database path / stage, unpack if required // ch_virusbreakenddb = Channel.empty() - if (run_config.stages.virusinterpreter) { + if (run_config.has_dna && run_virusinterpreter) { if (params.ref_data_virusbreakenddb_path.endsWith('.tar.gz')) { ch_virusbreakenddb_inputs = [ [id: 'virusbreakenddb'], @@ -136,7 +137,7 @@ workflow PREPARE_REFERENCE { // Set panel reference paths / stage, unpack if required // ch_panel_data = Channel.empty() - if (params.targeted === true) { + if (run_config.mode === Constants.RunMode.TARGETED) { // NOTE(SW): consider approach to implement custom panel support diff --git a/subworkflows/local/purple_calling.nf b/subworkflows/local/purple_calling.nf index 4ea5768c..3070cc1e 100644 --- a/subworkflows/local/purple_calling.nf +++ b/subworkflows/local/purple_calling.nf @@ -3,22 +3,21 @@ // import Constants +import Utils include { PURPLE } from '../../modules/local/purple/main' -include { CHANNEL_INPUTS_PURPLE } from './channel_inputs_purple' - workflow PURPLE_CALLING { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] ch_amber // channel: [mandatory] [ meta, amber_dir ] ch_cobalt // channel: [mandatory] [ meta, cobalt_dir ] - ch_smlv_somatic // channel: [optional] [ meta, pave_vcf ] - ch_smlv_germline // channel: [optional] [ meta, pave_vcf ] - ch_sv_somatic // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] - ch_sv_germline // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] - ch_sv_somatic_unfiltered // channel: [optional] [ meta, gripss_vcf, gripss_tbi ] + ch_smlv_somatic // channel: [mandatory] [ meta, pave_vcf ] + ch_smlv_germline // channel: [mandatory] [ meta, pave_vcf ] + ch_sv_somatic // channel: [mandatory] [ meta, gripss_vcf, gripss_tbi ] + ch_sv_germline // channel: [mandatory] [ meta, gripss_vcf, gripss_tbi ] + ch_sv_somatic_unfiltered // channel: [mandatory] [ meta, gripss_vcf, gripss_tbi ] // Reference data genome_fasta // channel: [mandatory] /path/to/genome_fasta @@ -35,9 +34,6 @@ workflow PURPLE_CALLING { target_region_ratios // channel: [optional] /path/to/target_region_ratios target_region_msi_indels // channel: [optional] /path/to/target_region_msi_indels - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] @@ -45,36 +41,76 @@ workflow PURPLE_CALLING { // Select input sources // channel: [ meta, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] - CHANNEL_INPUTS_PURPLE( - ch_inputs, + ch_inputs_selected = WorkflowOncoanalyser.groupByMeta( ch_amber, ch_cobalt, - ch_smlv_somatic, - ch_smlv_germline, ch_sv_somatic, - ch_sv_germline, ch_sv_somatic_unfiltered, - run_config, + ch_sv_germline, + ch_smlv_somatic, + ch_smlv_germline, ) + .map { d -> + + def meta = d[0] + + // NOTE(SW): avoiding further complexity with loops etc + + def inputs = [ + Utils.selectCurrentOrExisting(d[1], meta, Constants.INPUT.AMBER_DIR), + Utils.selectCurrentOrExisting(d[2], meta, Constants.INPUT.COBALT_DIR), + Utils.selectCurrentOrExisting(d[3], meta, Constants.INPUT.GRIPSS_VCF_TUMOR), + Utils.selectCurrentOrExisting(d[4], meta, Constants.INPUT.GRIPSS_VCF_TUMOR_TBI), + Utils.selectCurrentOrExisting(d[5], meta, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR), + Utils.selectCurrentOrExisting(d[6], meta, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR_TBI), + Utils.selectCurrentOrExisting(d[7], meta, Constants.INPUT.GRIPSS_VCF_NORMAL), + Utils.selectCurrentOrExisting(d[8], meta, Constants.INPUT.GRIPSS_VCF_NORMAL_TBI), + Utils.selectCurrentOrExisting(d[9], meta, Constants.INPUT.PAVE_VCF_TUMOR), + Utils.selectCurrentOrExisting(d[10], meta, Constants.INPUT.PAVE_VCF_NORMAL), + ] + + return [meta, *inputs] + } - // Create process-specific meta + // Sort inputs + // channel: runnable: [ meta, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_inputs_selected + .branch { d -> + def meta = d[0] + def amber_dir = d[1] + def cobalt_dir = d[2] + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) + + runnable: amber_dir && cobalt_dir && !has_existing + skip: true + return meta + } + + // Create process input channel // channel: [ meta_purple, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] - ch_purple_inputs = CHANNEL_INPUTS_PURPLE.out - .map { - def meta = it[0] + ch_purple_inputs = ch_inputs_sorted.runnable + .map { d -> + + def meta = d[0] + def inputs = d[1..-1] + def meta_purple = [ - key: meta.id, - id: meta.id, + key: meta.group_id, + id: meta.group_id, tumor_id: Utils.getTumorDnaSampleName(meta), ] - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + if (Utils.hasNormalDnaBam(meta)) { meta_purple.normal_id = Utils.getNormalDnaSampleName(meta) } - return [meta_purple, *it[1..-1]] + return [meta_purple, *inputs] + } + // Run process PURPLE( ch_purple_inputs, genome_fasta, @@ -92,9 +128,16 @@ workflow PURPLE_CALLING { target_region_msi_indels, ) - ch_outputs = WorkflowOncoanalyser.restoreMeta(PURPLE.out.purple_dir, ch_inputs) ch_versions = ch_versions.mix(PURPLE.out.versions) + // Set outputs, restoring original meta + // channel: [ meta, purple_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(PURPLE.out.purple_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + emit: purple_dir = ch_outputs // channel: [ meta, purple_dir ] diff --git a/subworkflows/local/sage_append.nf b/subworkflows/local/sage_append.nf index aadda658..342069b1 100644 --- a/subworkflows/local/sage_append.nf +++ b/subworkflows/local/sage_append.nf @@ -3,6 +3,7 @@ // import Constants +import Utils include { SAGE_APPEND as SOMATIC } from '../../modules/local/sage/append/main' include { SAGE_APPEND as GERMLINE } from '../../modules/local/sage/append/main' @@ -19,106 +20,148 @@ workflow SAGE_APPEND { genome_fai // channel: [mandatory] /path/to/genome_fai genome_dict // channel: [mandatory] /path/to/genome_dict - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Select input sources - // channel: [ meta, purple_dir, tumor_rna_bam, tumor_rna_bai ] - ch_sage_append_inputs_source = WorkflowOncoanalyser.groupByMeta( - run_config.stages.purple ? ch_purple_dir : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR), - ch_inputs - .map { meta -> - def bam = Utils.getTumorRnaBam(meta) - return [meta, bam, "${bam}.bai"] - }, - ) + // Select input sources and sort + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_purple_dir + .map { meta, purple_dir -> + return [ + meta, + Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), + ] + } + .branch { meta, purple_dir -> + runnable: purple_dir + skip: true + return meta + } // // MODULE: SAGE append germline // - // channel: [ meta, sage_append_vcf ] - ch_germline_vcf = Channel.empty() - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - - // channel: [ sage_meta, purple_germline_smlv_vcf, tumor_rna_bam ] - ch_sage_germline_append_inputs = ch_sage_append_inputs_source - .map { meta, purple_dir, bam, bai -> - def tumor_id = Utils.getTumorDnaSampleName(meta) - def normal_id = Utils.getNormalDnaSampleName(meta) - - def purple_smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.germline.vcf.gz") - - // Require both germline smlv from the PURPLE directory - if (!purple_smlv_vcf.exists()) { - return Constants.PLACEHOLDER_META - } - - def sage_meta = [ - key: meta.id, - id: meta.id, - tumor_rna_id: Utils.getTumorRnaSampleName(meta), - dna_id: normal_id, - ] - return [sage_meta, purple_smlv_vcf, bam, bai] - } - .filter { it != Constants.PLACEHOLDER_META } - - GERMLINE( - ch_sage_germline_append_inputs, - genome_fasta, - genome_version, - genome_fai, - genome_dict, - ) + // Select inputs that are eligible to run + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_germline_sorted = ch_inputs_sorted.runnable + .branch { meta, purple_dir -> + + def tumor_dna_id = Utils.getTumorDnaSampleName(meta) + + def has_normal_dna = Utils.hasNormalDnaBam(meta) + def has_tumor_rna = Utils.hasTumorRnaBam(meta) + def has_smlv_germline = file(purple_dir).resolve("${tumor_dna_id}.purple.germline.vcf.gz") + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_APPEND_VCF_NORMAL) + + runnable: has_normal_dna && has_tumor_rna && has_smlv_germline && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_append, purple_smlv_vcf, tumor_rna_bam, tumor_rna_bai ] + ch_sage_append_germline_inputs = ch_inputs_germline_sorted.runnable + .map { meta, purple_dir -> + + def tumor_dna_id = Utils.getTumorDnaSampleName(meta) + + def meta_append = [ + key: meta.group_id, + id: meta.group_id, + tumor_rna_id: Utils.getTumorRnaSampleName(meta), + dna_id: Utils.getNormalDnaSampleName(meta), + ] + + def tumor_rna_bam = Utils.getTumorRnaBam(meta) + def tumor_rna_bai = Utils.getTumorRnaBai(meta) + def purple_smlv_vcf = file(purple_dir).resolve("${tumor_dna_id}.purple.germline.vcf.gz") + + return [meta_append, purple_smlv_vcf, tumor_rna_bam, tumor_rna_bai] + } + + // Run process + GERMLINE( + ch_sage_append_germline_inputs, + genome_fasta, + genome_version, + genome_fai, + genome_dict, + ) - // Set outputs, restoring original meta - ch_germline_vcf = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs) - ch_versions = ch_versions.mix(GERMLINE.out.versions) - } + ch_versions = ch_versions.mix(GERMLINE.out.versions) // - // MODULE: SAGE append germline + // MODULE: SAGE append somatic // - // NOTE(SW): revise to reduce repetition - // Create inputs and create process-specific meta - // channel: [ sage_meta, purple_somatic_smlv_vcf, tumor_rna_bam ] - ch_sage_somatic_append_inputs = ch_sage_append_inputs_source - .map { meta, purple_dir, bam, bai -> - def tumor_id = Utils.getTumorDnaSampleName(meta) - def purple_smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - - // Require both somatic smlv from the PURPLE directory - if (!purple_smlv_vcf.exists()) { - return Constants.PLACEHOLDER_META - } - - def sage_meta = [ - key: meta.id, - id: meta.id, + // Select inputs that are eligible to run + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_somatic_sorted = ch_inputs_sorted.runnable + .branch { meta, purple_dir -> + def tumor_dna_id = Utils.getTumorDnaSampleName(meta) + + def has_tumor_dna = Utils.hasTumorDnaBam(meta) + def has_tumor_rna = Utils.hasTumorRnaBam(meta) + def has_smlv_somatic = file(purple_dir).resolve("${tumor_dna_id}.purple.somatic.vcf.gz") + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_APPEND_VCF_TUMOR) + + runnable: has_tumor_dna && has_tumor_rna && has_smlv_somatic && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_append, purple_smlv_vcf, tumor_rna_bam, tumor_rna_bai ] + ch_sage_append_somatic_inputs = ch_inputs_somatic_sorted.runnable + .map { meta, purple_dir -> + + def tumor_dna_id = Utils.getTumorDnaSampleName(meta) + + def meta_append = [ + key: meta.group_id, + id: meta.group_id, tumor_rna_id: Utils.getTumorRnaSampleName(meta), - dna_id: tumor_id, + dna_id: Utils.getTumorDnaSampleName(meta), ] - return [sage_meta, purple_smlv_vcf, bam, bai] + + def tumor_rna_bam = Utils.getTumorRnaBam(meta) + def tumor_rna_bai = Utils.getTumorRnaBai(meta) + def purple_smlv_vcf = file(purple_dir).resolve("${tumor_dna_id}.purple.somatic.vcf.gz") + + return [meta_append, purple_smlv_vcf, tumor_rna_bam, tumor_rna_bai] } - .filter { it != Constants.PLACEHOLDER_META } + // Run process SOMATIC( - ch_sage_somatic_append_inputs, + ch_sage_append_somatic_inputs, genome_fasta, genome_version, genome_fai, genome_dict, ) - // Set outputs, restoring original meta - ch_somatic_vcf = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs) ch_versions = ch_versions.mix(SOMATIC.out.versions) + // Set outputs, restoring original meta + // channel: [ meta, sage_append_vcf ] + ch_somatic_vcf = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + + ch_germline_vcf = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + emit: somatic_vcf = ch_somatic_vcf // channel: [ meta, sage_append_vcf ] germline_vcf = ch_germline_vcf // channel: [ meta, sage_append_vcf ] diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index 69782635..188511a6 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -2,6 +2,9 @@ // SAGE is a precise and highly sensitive somatic SNV, MNV and small INDEL caller // +import Constants +import Utils + include { SAGE_GERMLINE as GERMLINE } from '../../modules/local/sage/germline/main' include { SAGE_SOMATIC as SOMATIC } from '../../modules/local/sage/somatic/main' @@ -25,74 +28,131 @@ workflow SAGE_CALLING { ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Get inputs - // channel: [ meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai ] - ch_sage_inputs = ch_inputs + // Sort inputs + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> + runnable: Utils.hasTumorDnaBam(meta) + skip: true + } + + // + // MODULE: SAGE germline + // + // Select inputs that are eligible to run + // channel: [ meta ] + ch_inputs_germline_sorted = ch_inputs_sorted.runnable + .branch { meta -> + def has_tumor_normal = Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_VCF_NORMAL) + + runnable: has_tumor_normal && !has_existing + skip: true + } + + // Create process input channel + // channel: [ meta_sage, tbam, nbam, tbai, nbai ] + ch_sage_germline_inputs = ch_inputs_germline_sorted.runnable .map { meta -> + def meta_sage = [ - key: meta.id, - id: meta.id, + key: meta.group_id, + id: meta.group_id, tumor_id: Utils.getTumorDnaSampleName(meta), + normal_id: Utils.getNormalDnaSampleName(meta), ] - def tumor_bam = Utils.getTumorDnaBam(meta) + data = [ + meta_sage, + Utils.getTumorDnaBam(meta), + Utils.getNormalDnaBam(meta), + Utils.getTumorDnaBai(meta), + Utils.getNormalDnaBai(meta), + ] - def normal_bam = [] - def normal_bai = [] + return data - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { + } - assert [Constants.RunMode.DNA, Constants.RunMode.DNA_RNA].contains(run_config.mode) + // Run process + GERMLINE( + ch_sage_germline_inputs, + genome_fasta, + genome_version, + genome_fai, + genome_dict, + sage_known_hotspots_germline, + sage_actionable_panel, + sage_coverage_panel, + sage_highconf_regions, + ensembl_data_resources, + ) + + ch_versions = ch_versions.mix(GERMLINE.out.versions) + + // + // MODULE: SAGE somatic + // + // Select inputs that are eligible to run + // channel: [ meta ] + ch_inputs_somatic_sorted = ch_inputs_sorted.runnable + .branch { meta -> + def has_tumor = Utils.hasTumorDnaBam(meta) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_VCF_TUMOR) + + runnable: has_tumor && !has_existing + skip: true + } + + // Create process input channel + // channel: tumor/normal: [ meta_sage, tbam, nbam, tbai, nbai ] + // channel: tumor only: [ meta_sage, tbam, [], tbai, [] ] + ch_sage_somatic_inputs = ch_inputs_somatic_sorted.runnable + .map { meta -> + + def meta_sage = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + ] + + def data = [] + if (Utils.hasNormalDnaBam(meta)) { meta_sage.normal_id = Utils.getNormalDnaSampleName(meta) - normal_bam = Utils.getNormalDnaBam(meta) - normal_bai = "${normal_bam}.bai" - } + data = [ + meta_sage, + Utils.getTumorDnaBam(meta), + Utils.getNormalDnaBam(meta), + Utils.getTumorDnaBai(meta), + Utils.getNormalDnaBai(meta), + ] - return [meta_sage, tumor_bam, normal_bam, "${tumor_bam}.bai", normal_bai] - } + } else { - // - // MODULE: SAGE germline - // - // channel: [ meta, sage_vcf, sage_tbi ] - ch_germline_vcf_out = Channel.empty() - // channel: [ meta, sage_dir ] - ch_germline_dir = Channel.empty() - if (run_config.type == Constants.RunType.TUMOR_NORMAL) { - - GERMLINE( - ch_sage_inputs, - genome_fasta, - genome_version, - genome_fai, - genome_dict, - sage_known_hotspots_germline, - sage_actionable_panel, - sage_coverage_panel, - sage_highconf_regions, - ensembl_data_resources, - ) + data = [ + meta_sage, + Utils.getTumorDnaBam(meta), + [], + Utils.getTumorDnaBai(meta), + [], + ] + + } - ch_versions = ch_versions.mix(GERMLINE.out.versions) - ch_germline_vcf_out = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_filtered, ch_inputs) - ch_germline_dir = WorkflowOncoanalyser.restoreMeta(GERMLINE.out.sage_dir, ch_inputs) - } + return data - // - // MODULE: SAGE somatic - // + } + + // Run process SOMATIC( - ch_sage_inputs, + ch_sage_somatic_inputs, genome_fasta, genome_version, genome_fai, @@ -105,8 +165,39 @@ workflow SAGE_CALLING { ) ch_versions = ch_versions.mix(SOMATIC.out.versions) - ch_somatic_vcf_out = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_filtered, ch_inputs) - ch_somatic_dir = WorkflowOncoanalyser.restoreMeta(SOMATIC.out.sage_dir, ch_inputs) + + // Set outputs, restoring original meta + // channel: [ meta, sage_vcf, sage_tbi ] + ch_somatic_vcf_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_filtered, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, + ) + + // channel: [ meta, sage_vcf, sage_tbi ] + ch_germline_vcf_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_filtered, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, + ) + + // channel: [ meta, sage_dir ] + ch_somatic_dir = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.sage_dir, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + + // channel: [ meta, sage_dir ] + ch_germline_dir = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.sage_dir, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: germline_vcf = ch_germline_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] @@ -114,5 +205,5 @@ workflow SAGE_CALLING { germline_dir = ch_germline_dir // channel: [ meta, sage_dir ] somatic_dir = ch_somatic_dir // channel: [ meta, sage_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/sigs_fitting.nf b/subworkflows/local/sigs_fitting.nf index 5e13fcdb..167d7fa3 100644 --- a/subworkflows/local/sigs_fitting.nf +++ b/subworkflows/local/sigs_fitting.nf @@ -16,9 +16,6 @@ workflow SIGS_FITTING { // Reference data sigs_signatures // channel: [mandatory] /path/to/sigs_signatures - // Params - run_config // channel: [mandatory] run configuration - main: // Channel for version.yml files // channel: [ versions.yml ] @@ -26,43 +23,61 @@ workflow SIGS_FITTING { // Select input sources // channel: [ meta, purple_dir ] - if (run_config.stages.purple) { - ch_sigs_inputs_source = ch_purple - } else { - ch_sigs_inputs_source = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - } + ch_inputs_selected = ch_purple + .map { meta, purple_dir -> + return [meta, Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR)] + } + + // Sort inputs + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_inputs_selected + .branch { meta, purple_dir -> + + def tumor_id = Utils.getTumorDnaSampleName(meta) + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SIGS_DIR) + def has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] + + runnable: purple_dir && has_smlv_vcf && !has_existing + skip: true + return meta + } - // Create inputs and create process-specific meta + // Create process input channel // channel: [ meta_sigs, smlv_vcf ] - ch_sigs_inputs = ch_sigs_inputs_source + ch_sigs_inputs = ch_inputs_sorted.runnable .map { meta, purple_dir -> def tumor_id = Utils.getTumorDnaSampleName(meta) - def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - - // Require smlv VCF from the PURPLE directory - if (!smlv_vcf.exists()) { - return Constants.PLACEHOLDER_META - } def meta_sigs = [ - key: meta.id, - id: meta.id, - tumor_id: tumor_id, + key: meta.group_id, + id: meta.group_id, + sample_id: tumor_id, ] + + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + return [meta_sigs, smlv_vcf] } - .filter { it != Constants.PLACEHOLDER_META } + // Run process SIGS( ch_sigs_inputs, sigs_signatures, ) - // Set outputs, restoring original meta - ch_outputs = WorkflowOncoanalyser.restoreMeta(SIGS.out.sigs_dir, ch_inputs) ch_versions = ch_versions.mix(SIGS.out.versions) + // Set outputs, restoring original meta + // channel: [ meta, sigs_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SIGS.out.sigs_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + emit: sigs_dir = ch_outputs // channel: [ meta, sigs_dir ] diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index c5775c4d..c32389da 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -28,22 +28,38 @@ workflow VIRUSBREAKEND_CALLING { // Params gridss_config // channel: [optional] /path/to/gridss_config - run_config // channel: [mandatory] run configuration main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // VIRUSBreakend - // Create inputs and create process-specific meta + // Sort inputs + // NOTE(SW): VIRUSBreakend inputs are not allowed in the samplesheet, so aren't considered + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.VIRUSINTERPRETER_DIR) + + runnable: Utils.hasTumorDnaBam(meta) && !has_existing + skip: true + } + + // + // MODULE: VIRUSBreakend + // + // Create process input channel // channel: [ meta_virus, tumor_bam ] - ch_virusbreakend_inputs = ch_inputs + ch_virusbreakend_inputs = ch_inputs_sorted.runnable .map { meta -> + def meta_virus = [ - key: meta.id, - id: meta.id, + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), ] + return [meta_virus, Utils.getTumorDnaBam(meta)] } @@ -60,31 +76,54 @@ workflow VIRUSBREAKEND_CALLING { virusbreakenddb, ) - // Create inputs and create process-specific meta - if (run_config.stages.purple) { - ch_virusinterpreter_inputs_purple = ch_purple - } else { - ch_virusinterpreter_inputs_purple = WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.PURPLE_DIR) - } - - // channel: [ meta, virus_tsv, purple_dir, wgs_metrics ] - ch_virusinterpreter_inputs_full = WorkflowOncoanalyser.groupByMeta( - WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), - ch_virusinterpreter_inputs_purple, - run_config.stages.bamtools ? ch_bamtools_somatic : WorkflowOncoanalyser.getInput(ch_inputs, Constants.INPUT.INPUT_BAMTOOLS_TUMOR), + ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) + + // + // MODULE: Virus Interpreter + // + // Select input sources + // channel: [ meta, virus_tsv, purple_dir, metrics ] + ch_virusinterpreter_inputs_selected = WorkflowOncoanalyser.groupByMeta( + WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), + ch_purple, + ch_bamtools_somatic, ) + .map { meta, virus_tsv, purple_dir, metrics -> + + def inputs = [ + virus_tsv, + Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), + Utils.selectCurrentOrExisting(metrics, meta, Constants.INPUT.BAMTOOLS_TUMOR), + ] + + return [meta, *inputs] + } + + // Sort inputs + // channel: [ meta, virus_tsv, purple_dir, metrics ] + // channel: skip: [ meta ] + ch_virusinterpreter_inputs_sorted = ch_virusinterpreter_inputs_selected + .branch { meta, virus_tsv, purple_dir, metrics -> + runnable: virus_tsv && purple_dir && metrics + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_virus, virus_tsv, purple_dir, metrics ] + ch_virusinterpreter_inputs = ch_virusinterpreter_inputs_sorted.runnable + .map { d -> + + def meta = d[0] + def inputs = d[1..-1] - // Virus Interpreter - // Create inputs and create process-specific meta - // channel: [ meta_virus, virus_tsv, purple_dir, wgs_metrics ] - ch_virusinterpreter_inputs = ch_virusinterpreter_inputs_full - .map { - def meta = it[0] def meta_virus = [ - key: meta.id, - id: Utils.getTumorDnaSampleName(meta), + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), ] - return [meta_virus, *it[1..-1]] + + return [meta_virus, *inputs] } // Run process @@ -94,12 +133,16 @@ workflow VIRUSBREAKEND_CALLING { virus_reporting_db, ) + ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) + // Set outputs, restoring original meta - ch_outputs = WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter_dir, ch_inputs) - ch_versions = ch_versions.mix( - VIRUSINTERPRETER.out.versions, - VIRUSBREAKEND.out.versions, - ) + // channel: [ meta, virusinterpreter_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter_dir, ch_inputs), + ch_virusinterpreter_inputs_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: virusinterpreter_dir = ch_outputs // channel: [ meta, virusinterpreter_dir ] diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 99ee7cb0..f6bd4b17 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -8,13 +8,18 @@ import Utils VALIDATE INPUTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +// Parse input samplesheet +// NOTE(SW): this is done early and outside of gpars so that we can access synchronously and prior to pipeline execution +inputs = Utils.parseInput(params.input, workflow.stubRun, log) // Get run config -run_config = WorkflowMain.getRunConfig(params, log) +run_config = WorkflowMain.getRunConfig(params, inputs, log) + +// Validate inputs +Utils.validateInput(inputs, run_config, log) // Check input path parameters to see if they exist def checkPathParamList = [ - params.input, params.isofox_counts, params.isofox_gc_ratios, params.isofox_gene_ids, @@ -63,6 +68,7 @@ linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : include { AMBER_PROFILING } from '../subworkflows/local/amber_profiling' include { BAMTOOLS_METRICS } from '../subworkflows/local/bamtools_metrics' include { COBALT_PROFILING } from '../subworkflows/local/cobalt_profiling' +include { FLAGSTAT_METRICS } from '../subworkflows/local/flagstat_metrics' include { GRIDSS_SVPREP_CALLING } from '../subworkflows/local/gridss_svprep_calling' include { GRIPSS_FILTERING } from '../subworkflows/local/gripss_filtering' include { ISOFOX_QUANTIFICATION } from '../subworkflows/local/isofox_quantification' @@ -71,7 +77,6 @@ include { LINX_ANNOTATION } from '../subworkflows/local/linx_annotation' include { LINX_PLOTTING } from '../subworkflows/local/linx_plotting' include { ORANGE_REPORTING } from '../subworkflows/local/orange_reporting' include { PAVE_ANNOTATION } from '../subworkflows/local/pave_annotation' -include { PREPARE_INPUT } from '../subworkflows/local/prepare_input' include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' include { SAGE_APPEND } from '../subworkflows/local/sage_append' @@ -103,13 +108,9 @@ workflow TARGETED { // channel: [ versions.yml ] ch_versions = Channel.empty() - // Get inputs from samplesheet, assign more human readable variable + // Create input channel from parsed CSV // channel: [ meta ] - PREPARE_INPUT( - samplesheet, - run_config, - ) - ch_inputs = PREPARE_INPUT.out.data + ch_inputs = Channel.fromList(inputs) // Set up reference data, assign more human readable variables PREPARE_REFERENCE( @@ -129,8 +130,8 @@ workflow TARGETED { ch_isofox_out = Channel.empty() if (run_config.stages.isofox) { - isofox_counts = params.isofox_counts ? file(params.isofox_counts) : hmf_data.isofox_counts - isofox_gc_ratios = params.isofox_gc_ratios ? file(params.isofox_gc_ratios) : hmf_data.isofox_gc_ratios + isofox_counts = params.isofox_counts ? file(params.isofox_counts) : panel_data.isofox_counts + isofox_gc_ratios = params.isofox_gc_ratios ? file(params.isofox_gc_ratios) : panel_data.isofox_gc_ratios isofox_gene_ids = params.isofox_gene_ids ? file(params.isofox_gene_ids) : panel_data.isofox_gene_ids isofox_tpm_norm = params.isofox_tpm_norm ? file(params.isofox_tpm_norm) : panel_data.isofox_tpm_norm @@ -147,32 +148,18 @@ workflow TARGETED { isofox_tpm_norm, params.isofox_functions, params.isofox_read_length, - run_config, ) ch_versions = ch_versions.mix(ISOFOX_QUANTIFICATION.out.versions) + ch_isofox_out = ch_isofox_out.mix(ISOFOX_QUANTIFICATION.out.isofox_dir) - } - // - // SUBWORKFLOW: Run Bam Tools to generate stats required for downstream processes - // - // channel: [ meta, metrics ] - ch_bamtools_somatic_out = Channel.empty() - if (run_config.stages.bamtools) { + } else { - BAMTOOLS_METRICS( - ch_inputs, - ref_data.genome_fasta, - ref_data.genome_version, - run_config, - ) + ch_isofox_out = ch_inputs.map { meta -> [meta, []] } - ch_versions = ch_versions.mix(BAMTOOLS_METRICS.out.versions) - ch_bamtools_somatic_out = ch_bamtools_somatic_out.mix(BAMTOOLS_METRICS.out.somatic) } - // // SUBWORKFLOW: Run AMBER to obtain b-allele frequencies // @@ -184,11 +171,15 @@ workflow TARGETED { ch_inputs, ref_data.genome_version, hmf_data.heterozygous_sites, - run_config, ) ch_versions = ch_versions.mix(AMBER_PROFILING.out.versions) ch_amber_out = ch_amber_out.mix(AMBER_PROFILING.out.amber_dir) + + } else { + + ch_amber_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -203,11 +194,16 @@ workflow TARGETED { hmf_data.gc_profile, hmf_data.diploid_bed, panel_data.target_region_normalisation, - run_config, ) ch_versions = ch_versions.mix(COBALT_PROFILING.out.versions) + ch_cobalt_out = ch_cobalt_out.mix(COBALT_PROFILING.out.cobalt_dir) + + } else { + + ch_cobalt_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -230,11 +226,16 @@ workflow TARGETED { hmf_data.sv_prep_blocklist, hmf_data.known_fusions, gridss_config, - run_config, ) ch_versions = ch_versions.mix(GRIDSS_SVPREP_CALLING.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP_CALLING.out.results) + + ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP_CALLING.out.vcf) + + } else { + + ch_gridss_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -242,6 +243,7 @@ workflow TARGETED { // // channel: [ meta, vcf, tbi ] ch_gripss_somatic_out = Channel.empty() + ch_gripss_germline_out = Channel.empty() ch_gripss_somatic_unfiltered_out = Channel.empty() if (run_config.stages.gripss) { @@ -256,20 +258,30 @@ workflow TARGETED { hmf_data.known_fusions, hmf_data.repeatmasker_annotations, panel_data.target_region_bed, - run_config, ) ch_versions = ch_versions.mix(GRIPSS_FILTERING.out.versions) + ch_gripss_somatic_out = ch_gripss_somatic_out.mix(GRIPSS_FILTERING.out.somatic) + ch_gripss_germline_out = ch_gripss_germline_out.mix(GRIPSS_FILTERING.out.germline) ch_gripss_somatic_unfiltered_out = ch_gripss_somatic_unfiltered_out.mix(GRIPSS_FILTERING.out.somatic_unfiltered) + + } else { + + ch_gripss_somatic_out = ch_inputs.map { meta -> [meta, [], []] } + ch_gripss_germline_out = ch_inputs.map { meta -> [meta, [], []] } + ch_gripss_somatic_unfiltered_out = ch_inputs.map { meta -> [meta, [], []] } + } // // SUBWORKFLOW: call SNV, MNV, and small INDELS with SAGE // // channel: [ meta, sage_vcf, sage_tbi ] + ch_sage_germline_vcf_out = Channel.empty() ch_sage_somatic_vcf_out = Channel.empty() // channel: [ meta, sage_dir ] + ch_sage_germline_dir_out = Channel.empty() ch_sage_somatic_dir_out = Channel.empty() if (run_config.stages.sage) { @@ -287,24 +299,35 @@ workflow TARGETED { hmf_data.segment_mappability, panel_data.driver_gene_panel, hmf_data.ensembl_data_resources, - run_config, ) ch_versions = ch_versions.mix(SAGE_CALLING.out.versions) + + ch_sage_germline_vcf_out = ch_sage_germline_vcf_out.mix(SAGE_CALLING.out.germline_vcf) ch_sage_somatic_vcf_out = ch_sage_somatic_vcf_out.mix(SAGE_CALLING.out.somatic_vcf) + ch_sage_germline_dir_out = ch_sage_germline_dir_out.mix(SAGE_CALLING.out.germline_dir) ch_sage_somatic_dir_out = ch_sage_somatic_dir_out.mix(SAGE_CALLING.out.somatic_dir) + + } else { + + ch_sage_germline_vcf_out = ch_inputs.map { meta -> [meta, [], []] } + ch_sage_somatic_vcf_out = ch_inputs.map { meta -> [meta, [], []] } + ch_sage_germline_dir_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_somatic_dir_out = ch_inputs.map { meta -> [meta, []] } + } // // SUBWORKFLOW: Annotate variants with PAVE // // channel: [ meta, pave_vcf ] + ch_pave_germline_out = Channel.empty() ch_pave_somatic_out = Channel.empty() if (run_config.stages.pave) { PAVE_ANNOTATION( ch_inputs, - [], // ch_sage_germline_vcf_out + ch_sage_germline_vcf_out, ch_sage_somatic_vcf_out, ref_data.genome_fasta, ref_data.genome_version, @@ -318,11 +341,18 @@ workflow TARGETED { panel_data.driver_gene_panel, hmf_data.ensembl_data_resources, hmf_data.gnomad_resource, - run_config, ) ch_versions = ch_versions.mix(PAVE_ANNOTATION.out.versions) + + ch_pave_germline_out = ch_pave_germline_out.mix(PAVE_ANNOTATION.out.germline) ch_pave_somatic_out = ch_pave_somatic_out.mix(PAVE_ANNOTATION.out.somatic) + + } else { + + ch_pave_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_pave_somatic_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -337,10 +367,10 @@ workflow TARGETED { ch_amber_out, ch_cobalt_out, ch_pave_somatic_out, - [], // ch_pave_germline_out + ch_pave_germline_out, ch_gripss_somatic_out, - [], // ch_gripss_germline_out - [], // ch_gripss_somatic_unfiltered_out, + ch_gripss_germline_out, + ch_gripss_somatic_unfiltered_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -354,11 +384,16 @@ workflow TARGETED { panel_data.target_region_bed, panel_data.target_region_ratios, panel_data.target_region_msi_indels, - run_config, ) ch_versions = ch_versions.mix(PURPLE_CALLING.out.versions) + ch_purple_out = ch_purple_out.mix(PURPLE_CALLING.out.purple_dir) + + } else { + + ch_purple_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -366,7 +401,8 @@ workflow TARGETED { // // channel: [ meta, sage_append_vcf ] ch_sage_somatic_append_out = Channel.empty() - if (run_config.mode == Constants.RunMode.DNA_RNA && run_config.stages.orange) { + ch_sage_germline_append_out = Channel.empty() + if (run_config.stages.orange) { // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented @@ -377,11 +413,18 @@ workflow TARGETED { ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, - run_config, ) ch_versions = ch_versions.mix(SAGE_APPEND.out.versions) + ch_sage_somatic_append_out = ch_sage_somatic_append_out.mix(SAGE_APPEND.out.somatic_vcf) + ch_sage_germline_append_out = ch_sage_germline_append_out.mix(SAGE_APPEND.out.germline_vcf) + + } else { + + ch_sage_somatic_append_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_germline_append_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -389,8 +432,7 @@ workflow TARGETED { // // channel: [ meta, linx_annotation_dir ] ch_linx_somatic_out = Channel.empty() - // channel: [ meta, linx_visualiser_dir ] - ch_linx_somatic_plot_out = Channel.empty() + ch_linx_germline_out = Channel.empty() if (run_config.stages.linx) { LINX_ANNOTATION( @@ -401,22 +443,92 @@ workflow TARGETED { hmf_data.known_fusion_data, panel_data.driver_gene_panel, linx_gene_id_file, - run_config, ) ch_versions = ch_versions.mix(LINX_ANNOTATION.out.versions) + ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX_ANNOTATION.out.somatic) + ch_linx_germline_out = ch_linx_germline_out.mix(LINX_ANNOTATION.out.germline) + + } else { + + ch_linx_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_linx_germline_out = ch_inputs.map { meta -> [meta, []] } + + } + + // + // SUBWORKFLOW: Visualise LINX annotations + // + // channel: [ meta, linx_visualiser_dir_reportable ] + ch_linx_somatic_plot_reportable_out = Channel.empty() + if (run_config.stages.linx) { LINX_PLOTTING( ch_inputs, ch_linx_somatic_out, ref_data.genome_version, hmf_data.ensembl_data_resources, - run_config, ) ch_versions = ch_versions.mix(LINX_PLOTTING.out.versions) - ch_linx_somatic_plot_out = ch_linx_somatic_plot_out.mix(LINX_PLOTTING.out.visualiser_dir) + + ch_linx_somatic_plot_reportable_out = ch_linx_somatic_plot_reportable_out.mix(LINX_PLOTTING.out.visualiser_dir_reportable) + + } else { + + ch_linx_somatic_plot_reportable_out = ch_inputs.map { meta -> [meta, []] } + + } + + // + // SUBWORKFLOW: Run SAMtools flagstat to generate stats required for ORANGE + // + // channel: [ meta, metrics ] + ch_flagstat_somatic_out = Channel.empty() + ch_flagstat_germline_out = Channel.empty() + if (run_config.stages.orange && run_config.stages.flagstat) { + + FLAGSTAT_METRICS( + ch_inputs, + ) + + ch_versions = ch_versions.mix(FLAGSTAT_METRICS.out.versions) + + ch_flagstat_somatic_out = ch_flagstat_somatic_out.mix(FLAGSTAT_METRICS.out.somatic) + ch_flagstat_germline_out = ch_flagstat_germline_out.mix(FLAGSTAT_METRICS.out.germline) + + } else { + + ch_flagstat_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_flagstat_germline_out = ch_inputs.map { meta -> [meta, []] } + + } + + // + // SUBWORKFLOW: Run Bam Tools to generate stats required for downstream processes + // + // channel: [ meta, metrics ] + ch_bamtools_somatic_out = Channel.empty() + ch_bamtools_germline_out = Channel.empty() + if (run_config.stages.bamtools) { + + BAMTOOLS_METRICS( + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_version, + ) + + ch_versions = ch_versions.mix(BAMTOOLS_METRICS.out.versions) + + ch_bamtools_somatic_out = ch_bamtools_somatic_out.mix(BAMTOOLS_METRICS.out.somatic) + ch_bamtools_germline_out = ch_bamtools_germline_out.mix(BAMTOOLS_METRICS.out.germline) + + } else { + + ch_bamtools_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_bamtools_germline_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -437,11 +549,16 @@ workflow TARGETED { ref_data.genome_fai, hmf_data.lilac_resources, ref_data_hla_slice_bed, - run_config, ) ch_versions = ch_versions.mix(LILAC_CALLING.out.versions) + ch_lilac_out = ch_lilac_out.mix(LILAC_CALLING.out.lilac_dir) + + } else { + + ch_lilac_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -449,23 +566,31 @@ workflow TARGETED { // if (run_config.stages.orange) { + // Create placeholder channels for empty remaining channels + ch_chord_out = ch_inputs.map { meta -> [meta, []] } + ch_cuppa_out = ch_inputs.map { meta -> [meta, []] } + ch_sigs_out = ch_inputs.map { meta -> [meta, []] } + ch_virusinterpreter_out = ch_inputs.map { meta -> [meta, []] } + ORANGE_REPORTING( ch_inputs, ch_bamtools_somatic_out, - [], //ch_bamtools_germline_out + ch_bamtools_germline_out, + ch_flagstat_somatic_out, + ch_flagstat_germline_out, ch_sage_somatic_dir_out, - [], // ch_sage_germline_dir_out + ch_sage_germline_dir_out, ch_sage_somatic_append_out, - [], // ch_sage_germline_append_out + ch_sage_germline_append_out, ch_purple_out, ch_linx_somatic_out, - ch_linx_somatic_plot_out, - [], // ch_linx_germline_out - [], // ch_virusinterpreter_out - [], // ch_chord_out - [], // ch_sigs_out + ch_linx_somatic_plot_reportable_out, + ch_linx_germline_out, + ch_virusinterpreter_out, + ch_chord_out, + ch_sigs_out, ch_lilac_out, - [], // ch_cuppa_out + ch_cuppa_out, ch_isofox_out, ref_data.genome_version, hmf_data.disease_ontology, @@ -474,9 +599,8 @@ workflow TARGETED { hmf_data.known_fusion_data, panel_data.driver_gene_panel, hmf_data.ensembl_data_resources, - [], // alt_sj_distribution - [], // gene_exp_distribution - run_config, + hmf_data.alt_sj_distribution, + hmf_data.gene_exp_distribution, ) ch_versions = ch_versions.mix(ORANGE_REPORTING.out.versions) @@ -488,7 +612,6 @@ workflow TARGETED { CUSTOM_DUMPSOFTWAREVERSIONS( ch_versions.unique().collectFile(name: 'collated_versions.yml') ) - } /* diff --git a/workflows/wgts.nf b/workflows/wgts.nf index f26f0c64..6e18a8ec 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -2,19 +2,23 @@ import Constants import Processes import Utils - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALIDATE INPUTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +// Parse input samplesheet +// NOTE(SW): this is done early and outside of gpars so that we can access synchronously and prior to pipeline execution +inputs = Utils.parseInput(params.input, workflow.stubRun, log) // Get run config -run_config = WorkflowMain.getRunConfig(params, log) +run_config = WorkflowMain.getRunConfig(params, inputs, log) + +// Validate inputs +Utils.validateInput(inputs, run_config, log) // Check input path parameters to see if they exist def checkPathParamList = [ - params.input, params.isofox_counts, params.isofox_gc_ratios, params.linx_gene_id_file, @@ -67,6 +71,7 @@ include { BAMTOOLS_METRICS } from '../subworkflows/local/bamtools_metrics' include { CHORD_PREDICTION } from '../subworkflows/local/chord_prediction' include { COBALT_PROFILING } from '../subworkflows/local/cobalt_profiling' include { CUPPA_PREDICTION } from '../subworkflows/local/cuppa_prediction' +include { FLAGSTAT_METRICS } from '../subworkflows/local/flagstat_metrics' include { GRIDSS_SVPREP_CALLING } from '../subworkflows/local/gridss_svprep_calling' include { GRIPSS_FILTERING } from '../subworkflows/local/gripss_filtering' include { ISOFOX_QUANTIFICATION } from '../subworkflows/local/isofox_quantification' @@ -75,7 +80,6 @@ include { LINX_ANNOTATION } from '../subworkflows/local/linx_annotation' include { LINX_PLOTTING } from '../subworkflows/local/linx_plotting' include { ORANGE_REPORTING } from '../subworkflows/local/orange_reporting' include { PAVE_ANNOTATION } from '../subworkflows/local/pave_annotation' -include { PREPARE_INPUT } from '../subworkflows/local/prepare_input' include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' include { SAGE_APPEND } from '../subworkflows/local/sage_append' @@ -108,13 +112,9 @@ workflow WGTS { // channel: [ versions.yml ] ch_versions = Channel.empty() - // Get inputs from samplesheet, assign more human readable variable + // Create input channel from parsed CSV // channel: [ meta ] - PREPARE_INPUT( - samplesheet, - run_config, - ) - ch_inputs = PREPARE_INPUT.out.data + ch_inputs = Channel.fromList(inputs) // Set up reference data, assign more human readable variables PREPARE_REFERENCE( @@ -148,31 +148,16 @@ workflow WGTS { [], // isofox_tpm_norm params.isofox_functions, params.isofox_read_length, - run_config, ) ch_versions = ch_versions.mix(ISOFOX_QUANTIFICATION.out.versions) + ch_isofox_out = ch_isofox_out.mix(ISOFOX_QUANTIFICATION.out.isofox_dir) - } - // - // SUBWORKFLOW: Run Bam Tools to generate stats required for downstream processes - // - // channel: [ meta, metrics ] - ch_bamtools_somatic_out = Channel.empty() - ch_bamtools_germline_out = Channel.empty() - if (run_config.stages.bamtools) { + } else { - BAMTOOLS_METRICS( - ch_inputs, - ref_data.genome_fasta, - ref_data.genome_version, - run_config, - ) + ch_isofox_out = ch_inputs.map { meta -> [meta, []] } - ch_versions = ch_versions.mix(BAMTOOLS_METRICS.out.versions) - ch_bamtools_somatic_out = ch_bamtools_somatic_out.mix(BAMTOOLS_METRICS.out.somatic) - ch_bamtools_germline_out = ch_bamtools_germline_out.mix(BAMTOOLS_METRICS.out.germline) } // @@ -186,11 +171,16 @@ workflow WGTS { ch_inputs, ref_data.genome_version, hmf_data.heterozygous_sites, - run_config, ) ch_versions = ch_versions.mix(AMBER_PROFILING.out.versions) + ch_amber_out = ch_amber_out.mix(AMBER_PROFILING.out.amber_dir) + + } else { + + ch_amber_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -205,11 +195,16 @@ workflow WGTS { hmf_data.gc_profile, hmf_data.diploid_bed, [], // panel_target_region_normalisation - run_config, ) ch_versions = ch_versions.mix(COBALT_PROFILING.out.versions) + ch_cobalt_out = ch_cobalt_out.mix(COBALT_PROFILING.out.cobalt_dir) + + } else { + + ch_cobalt_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -232,11 +227,15 @@ workflow WGTS { hmf_data.sv_prep_blocklist, hmf_data.known_fusions, gridss_config, - run_config, ) ch_versions = ch_versions.mix(GRIDSS_SVPREP_CALLING.out.versions) - ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP_CALLING.out.results) + + ch_gridss_out = ch_gridss_out.mix(GRIDSS_SVPREP_CALLING.out.vcf) + + } else { + + ch_gridss_out = ch_inputs.map { meta -> [meta, []] } } @@ -260,13 +259,20 @@ workflow WGTS { hmf_data.known_fusions, hmf_data.repeatmasker_annotations, [], // target_region_bed - run_config, ) ch_versions = ch_versions.mix(GRIPSS_FILTERING.out.versions) + ch_gripss_somatic_out = ch_gripss_somatic_out.mix(GRIPSS_FILTERING.out.somatic) ch_gripss_germline_out = ch_gripss_germline_out.mix(GRIPSS_FILTERING.out.germline) ch_gripss_somatic_unfiltered_out = ch_gripss_somatic_unfiltered_out.mix(GRIPSS_FILTERING.out.somatic_unfiltered) + + } else { + + ch_gripss_somatic_out = ch_inputs.map { meta -> [meta, [], []] } + ch_gripss_germline_out = ch_inputs.map { meta -> [meta, [], []] } + ch_gripss_somatic_unfiltered_out = ch_inputs.map { meta -> [meta, [], []] } + } // @@ -294,14 +300,22 @@ workflow WGTS { hmf_data.segment_mappability, hmf_data.driver_gene_panel, hmf_data.ensembl_data_resources, - run_config, ) ch_versions = ch_versions.mix(SAGE_CALLING.out.versions) + ch_sage_germline_vcf_out = ch_sage_germline_vcf_out.mix(SAGE_CALLING.out.germline_vcf) ch_sage_somatic_vcf_out = ch_sage_somatic_vcf_out.mix(SAGE_CALLING.out.somatic_vcf) ch_sage_germline_dir_out = ch_sage_germline_dir_out.mix(SAGE_CALLING.out.germline_dir) ch_sage_somatic_dir_out = ch_sage_somatic_dir_out.mix(SAGE_CALLING.out.somatic_dir) + + } else { + + ch_sage_germline_vcf_out = ch_inputs.map { meta -> [meta, [], []] } + ch_sage_somatic_vcf_out = ch_inputs.map { meta -> [meta, [], []] } + ch_sage_germline_dir_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_somatic_dir_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -328,12 +342,18 @@ workflow WGTS { hmf_data.driver_gene_panel, hmf_data.ensembl_data_resources, hmf_data.gnomad_resource, - run_config, ) ch_versions = ch_versions.mix(PAVE_ANNOTATION.out.versions) + ch_pave_germline_out = ch_pave_germline_out.mix(PAVE_ANNOTATION.out.germline) ch_pave_somatic_out = ch_pave_somatic_out.mix(PAVE_ANNOTATION.out.somatic) + + } else { + + ch_pave_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_pave_somatic_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -365,11 +385,16 @@ workflow WGTS { [], // target_region_bed [], // target_region_ratios [], // target_region_msi_indels - run_config, ) ch_versions = ch_versions.mix(PURPLE_CALLING.out.versions) + ch_purple_out = ch_purple_out.mix(PURPLE_CALLING.out.purple_dir) + + } else { + + ch_purple_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -378,7 +403,7 @@ workflow WGTS { // channel: [ meta, sage_append_vcf ] ch_sage_somatic_append_out = Channel.empty() ch_sage_germline_append_out = Channel.empty() - if (run_config.mode == Constants.RunMode.DNA_RNA && run_config.stages.orange) { + if (run_config.stages.orange) { // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented @@ -389,12 +414,17 @@ workflow WGTS { ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, - run_config, ) ch_versions = ch_versions.mix(SAGE_APPEND.out.versions) ch_sage_somatic_append_out = ch_sage_somatic_append_out.mix(SAGE_APPEND.out.somatic_vcf) ch_sage_germline_append_out = ch_sage_germline_append_out.mix(SAGE_APPEND.out.germline_vcf) + + } else { + + ch_sage_somatic_append_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_germline_append_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -403,8 +433,6 @@ workflow WGTS { // channel: [ meta, linx_annotation_dir ] ch_linx_somatic_out = Channel.empty() ch_linx_germline_out = Channel.empty() - // channel: [val(meta), linx_visualiser_dir] - ch_linx_somatic_plot_out = Channel.empty() if (run_config.stages.linx) { LINX_ANNOTATION( @@ -415,23 +443,92 @@ workflow WGTS { hmf_data.known_fusion_data, hmf_data.driver_gene_panel, linx_gene_id_file, - run_config, ) ch_versions = ch_versions.mix(LINX_ANNOTATION.out.versions) + ch_linx_somatic_out = ch_linx_somatic_out.mix(LINX_ANNOTATION.out.somatic) ch_linx_germline_out = ch_linx_germline_out.mix(LINX_ANNOTATION.out.germline) + } else { + + ch_linx_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_linx_germline_out = ch_inputs.map { meta -> [meta, []] } + + } + + // + // SUBWORKFLOW: Visualise LINX annotations + // + // channel: [ meta, linx_visualiser_dir_reportable ] + ch_linx_somatic_plot_reportable_out = Channel.empty() + if (run_config.stages.linx) { + LINX_PLOTTING( ch_inputs, ch_linx_somatic_out, ref_data.genome_version, hmf_data.ensembl_data_resources, - run_config, ) ch_versions = ch_versions.mix(LINX_PLOTTING.out.versions) - ch_linx_somatic_plot_out = ch_linx_somatic_plot_out.mix(LINX_PLOTTING.out.visualiser_dir) + + ch_linx_somatic_plot_reportable_out = ch_linx_somatic_plot_reportable_out.mix(LINX_PLOTTING.out.visualiser_dir_reportable) + + } else { + + ch_linx_somatic_plot_reportable_out = ch_inputs.map { meta -> [meta, []] } + + } + + // + // SUBWORKFLOW: Run SAMtools flagstat to generate stats required for ORANGE + // + // channel: [ meta, metrics ] + ch_flagstat_somatic_out = Channel.empty() + ch_flagstat_germline_out = Channel.empty() + if (run_config.stages.orange && run_config.stages.flagstat) { + + FLAGSTAT_METRICS( + ch_inputs, + ) + + ch_versions = ch_versions.mix(FLAGSTAT_METRICS.out.versions) + + ch_flagstat_somatic_out = ch_flagstat_somatic_out.mix(FLAGSTAT_METRICS.out.somatic) + ch_flagstat_germline_out = ch_flagstat_germline_out.mix(FLAGSTAT_METRICS.out.germline) + + } else { + + ch_flagstat_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_flagstat_germline_out = ch_inputs.map { meta -> [meta, []] } + + } + + // + // SUBWORKFLOW: Run Bam Tools to generate stats required for downstream processes + // + // channel: [ meta, metrics ] + ch_bamtools_somatic_out = Channel.empty() + ch_bamtools_germline_out = Channel.empty() + if (run_config.stages.bamtools) { + + BAMTOOLS_METRICS( + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_version, + ) + + ch_versions = ch_versions.mix(BAMTOOLS_METRICS.out.versions) + + ch_bamtools_somatic_out = ch_bamtools_somatic_out.mix(BAMTOOLS_METRICS.out.somatic) + ch_bamtools_germline_out = ch_bamtools_germline_out.mix(BAMTOOLS_METRICS.out.germline) + + } else { + + ch_bamtools_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_bamtools_germline_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -445,11 +542,16 @@ workflow WGTS { ch_inputs, ch_purple_out, hmf_data.sigs_signatures, - run_config, ) ch_versions = ch_versions.mix(SIGS_FITTING.out.versions) + ch_sigs_out = ch_sigs_out.mix(SIGS_FITTING.out.sigs_dir) + + } else { + + ch_sigs_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -463,11 +565,16 @@ workflow WGTS { ch_inputs, ch_purple_out, ref_data.genome_version, - run_config, ) ch_versions = ch_versions.mix(CHORD_PREDICTION.out.versions) + ch_chord_out = ch_chord_out.mix(CHORD_PREDICTION.out.chord_dir) + + } else { + + ch_chord_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -477,7 +584,7 @@ workflow WGTS { ch_lilac_out = Channel.empty() if (run_config.stages.lilac) { - // Set HLA slice BED if provided in params + // Use HLA slice BED if provided in params or set as default requirement ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] LILAC_CALLING( @@ -488,11 +595,16 @@ workflow WGTS { ref_data.genome_fai, hmf_data.lilac_resources, ref_data_hla_slice_bed, - run_config, ) ch_versions = ch_versions.mix(LILAC_CALLING.out.versions) + ch_lilac_out = ch_lilac_out.mix(LILAC_CALLING.out.lilac_dir) + + } else { + + ch_lilac_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -516,11 +628,16 @@ workflow WGTS { hmf_data.virus_taxonomy_db, hmf_data.virus_reporting_db, gridss_config, - run_config, ) ch_versions = ch_versions.mix(VIRUSBREAKEND_CALLING.out.versions) + ch_virusinterpreter_out = ch_virusinterpreter_out.mix(VIRUSBREAKEND_CALLING.out.virusinterpreter_dir) + + } else { + + ch_virusinterpreter_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -538,11 +655,16 @@ workflow WGTS { ch_virusinterpreter_out, ref_data.genome_version, hmf_data.cuppa_resources, - run_config, ) ch_versions = ch_versions.mix(CUPPA_PREDICTION.out.versions) + ch_cuppa_out = ch_cuppa_out.mix(CUPPA_PREDICTION.out.cuppa_dir) + + } else { + + ch_cuppa_out = ch_inputs.map { meta -> [meta, []] } + } // @@ -554,13 +676,15 @@ workflow WGTS { ch_inputs, ch_bamtools_somatic_out, ch_bamtools_germline_out, + ch_flagstat_somatic_out, + ch_flagstat_germline_out, ch_sage_somatic_dir_out, ch_sage_germline_dir_out, ch_sage_somatic_append_out, ch_sage_germline_append_out, ch_purple_out, ch_linx_somatic_out, - ch_linx_somatic_plot_out, + ch_linx_somatic_plot_reportable_out, ch_linx_germline_out, ch_virusinterpreter_out, ch_chord_out, @@ -577,7 +701,6 @@ workflow WGTS { hmf_data.ensembl_data_resources, hmf_data.alt_sj_distribution, hmf_data.gene_exp_distribution, - run_config, ) ch_versions = ch_versions.mix(ORANGE_REPORTING.out.versions) From 81e1d939020b8049ad5dfedce1377232f3124f23 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 31 Oct 2023 14:52:34 +1100 Subject: [PATCH 236/562] Do not filter SNVs without AD for PURPLE --- modules/local/purple/main.nf | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 8f17ca12..2e58e43d 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -37,8 +37,8 @@ process PURPLE { def sv_tumor_recovery_vcf_arg = sv_tumor_unfiltered_vcf ? "-sv_recovery_vcf ${sv_tumor_unfiltered_vcf}" : '' - def smlv_tumor_vcf_fp = smlv_tumor_vcf ?: '' - def smlv_normal_vcf_fp = smlv_normal_vcf ?: '' + def smlv_tumor_vcf_arg = smlv_tumor_vcf ? "-somatic_vcf ${smlv_tumor_vcf}" : '' + def smlv_normal_vcf_arg = smlv_normal_vcf ? "-germline_vcf ${smlv_normal_vcf}" : '' def sage_known_hotspots_germline_arg = sage_known_hotspots_germline ? "-germline_hotspots ${sage_known_hotspots_germline}" : '' def germline_del_arg = germline_del ? "-germline_del_freq_file ${germline_del}" : '' @@ -48,21 +48,6 @@ process PURPLE { def target_region_msi_indels_arg = target_region_msi_indels ? "-target_regions_msi_indels ${target_region_msi_indels}" : '' """ - # For provided smlv VCFs, filter records that do not contain the required FORMAT/AD field and - # get argument for PURPLE - get_smlv_arg() { - fp=\${1} - fn=\${fp##*/} - if [[ "\${fp}" != '' ]]; then - fp_out=prepared__\${2}__\${fn} - bcftools view -e 'FORMAT/AD[*]="."' -o \${fp_out} \${fp} - echo "-\${2} \${fp_out}" - fi - } - smlv_tumor_vcf_arg=\$(get_smlv_arg "${smlv_tumor_vcf_fp}" somatic_vcf) - smlv_normal_vcf_arg=\$(get_smlv_arg "${smlv_normal_vcf_fp}" germline_vcf) - - # Run PURPLE java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar ${task.ext.jarPath} \\ @@ -74,8 +59,8 @@ process PURPLE { ${sv_tumor_vcf_arg} \\ ${sv_normal_vcf_arg} \\ ${sv_tumor_recovery_vcf_arg} \\ - \${smlv_tumor_vcf_arg} \\ - \${smlv_normal_vcf_arg} \\ + ${smlv_tumor_vcf_arg} \\ + ${smlv_normal_vcf_arg} \\ -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -driver_gene_panel ${driver_gene_panel} \\ From 44e9f7bd414f284be321f28461748d2f4edc76fd Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 31 Oct 2023 14:54:43 +1100 Subject: [PATCH 237/562] Disallow only tumor RNA in targetted mode --- lib/Utils.groovy | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 1a73fe3f..00579b8e 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -154,19 +154,27 @@ class Utils { } - // Do not allow normal DNA in targeted mode and restrict targeted RNA analysis to TSO500 + // Apply some required restrictions to targeted mode if (run_config.mode === Constants.RunMode.TARGETED) { + // Do not allow normal DNA if (Utils.hasNormalDnaBam(meta)) { log.error "targeted mode is not compatible with the normal DNA BAM provided for ${meta.group_id}\n\n" + "The targeted workflow supports only tumor DNA BAMs (and tumor RNA BAMs for TSO500)" System.exit(1) } - // Restrict targeted RNA inputs to TSO500 + // Do not allow only tumor RNA + if (Utils.hasTumorRnaBam(meta) && !Utils.hasTumorDnaBam(meta)) { + log.error "targeted mode is not compatible with only tumor RNA provided for ${meta.group_id}\n\n" + + "The targeted workflow requires tumor DNA and can optionally take tumor RNA, depending on " + + "the configured panel." + System.exit(1) + } + + // Restrict tumor RNA inputs to the TSO500 panel if (Utils.hasTumorRnaBam(meta) && run_config.panel != 'tso500') { def panel = run_config.panel.toUpperCase() - log.error "the ${panel} panel is not compatible with the tumor RNA BAM provided for ${meta.group_id}\n\n" + "Only the TSO500 panel supports tumor RNA analysis" System.exit(1) } From 9235d0d525a0dbdc5dd43075871f43a3f3793c73 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 31 Oct 2023 16:45:24 +1100 Subject: [PATCH 238/562] Fix variable names --- lib/Utils.groovy | 2 +- lib/WorkflowMain.groovy | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 00579b8e..0e6eab11 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -60,7 +60,7 @@ class Utils { def meta_sample = meta.get(sample_key, [sample_id: it.sample_id]) if (meta_sample.sample_id != it.sample_id) { - log.error "got unexpected sample name for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${sample_name}" + log.error "got unexpected sample name for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${it.sample_id}" System.exit(1) } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 98d3f276..0225c843 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -233,9 +233,9 @@ class WorkflowMain { if (!params.ref_data_genome_type) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome type wasn't provided and genome '${params.genome}' is not defined in \n" + - " genome version list.\n" + - " Currently, the list of genomes in the version list include:\n" + - " ${Constants.GENOMES_DEINFED.join(", ")}\n" + + " genome type list.\n" + + " Currently, the list of genomes in the type list include:\n" + + " ${Constants.GENOMES_DEFINED.join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) } From 31275f543e13d814db8db868d18a8a91829ebb14 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 31 Oct 2023 16:45:50 +1100 Subject: [PATCH 239/562] Correctly assign input reference file paths --- subworkflows/local/prepare_reference.nf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 848d9684..1c063544 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -34,8 +34,8 @@ workflow PREPARE_REFERENCE { // The fai and dict files should always be present if using a genome preset. These are // always created where they are not present without checking processes to run given they // are used in numerous processes and have a neglibile cost to generate. - ch_genome_fai = file(params.ref_data_genome_fai) - ch_genome_dict = file(params.ref_data_genome_dict) + ch_genome_fai = params.ref_data_genome_fai ? file(params.ref_data_genome_fai) : [] + ch_genome_dict = params.ref_data_genome_dict ? file(params.ref_data_genome_dict) : [] if (!params.ref_data_genome_fai) { SAMTOOLS_FAIDX([:], ch_genome_fasta) ch_genome_fai = SAMTOOLS_FAIDX.out.fai @@ -50,9 +50,9 @@ workflow PREPARE_REFERENCE { // // Create BWA index, BWA index image, and GRIDSS index for reference genome if required // - ch_genome_bwa_index = file(params.ref_data_genome_bwa_index) - ch_genome_bwa_index_image = file(params.ref_data_genome_bwa_index_image) - ch_genome_gridss_index = file(params.ref_data_genome_gridss_index) + ch_genome_bwa_index = params.ref_data_genome_bwa_index ? file(params.ref_data_genome_bwa_index) : [] + ch_genome_bwa_index_image = params.ref_data_genome_gridss_index ? file(params.ref_data_genome_bwa_index_image) : [] + ch_genome_gridss_index = params.ref_data_genome_gridss_index ? file(params.ref_data_genome_gridss_index) : [] if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { // NOTE(SW): the BWA index directory can be provided as a compressed tarball if (!params.ref_data_genome_bwa_index) { From 264da46fce15a90e80ba8461ff7d9f8f7b95827e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 31 Oct 2023 16:46:27 +1100 Subject: [PATCH 240/562] Update SAMtools indexing process channels --- subworkflows/local/prepare_reference.nf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 1c063544..7e368e49 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -37,12 +37,14 @@ workflow PREPARE_REFERENCE { ch_genome_fai = params.ref_data_genome_fai ? file(params.ref_data_genome_fai) : [] ch_genome_dict = params.ref_data_genome_dict ? file(params.ref_data_genome_dict) : [] if (!params.ref_data_genome_fai) { - SAMTOOLS_FAIDX([:], ch_genome_fasta) + ch_samtools_faidx_inputs = Channel.of([[:], ch_genome_fasta]) + SAMTOOLS_FAIDX(ch_samtools_faidx_inputs) ch_genome_fai = SAMTOOLS_FAIDX.out.fai ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions) } if (!params.ref_data_genome_dict) { - SAMTOOLS_DICT([:], ch_genome_fasta) + ch_samtools_dict_inputs = Channel.of([[:], ch_genome_fasta]) + SAMTOOLS_DICT(ch_samtools_dict_inputs) ch_genome_dict = SAMTOOLS_DICT.out.dict ch_versions = ch_versions.mix(SAMTOOLS_DICT.out.versions) } From 1e3ab9a434cca26bdc33c8b888ac241a9f3ecb3b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 31 Oct 2023 21:32:08 +1100 Subject: [PATCH 241/562] Patch nf-core bwa/index to retain all file exts --- modules.json | 3 ++- modules/nf-core/bwa/index/bwa-index.diff | 31 ++++++++++++++++++++++++ modules/nf-core/bwa/index/main.nf | 12 ++++----- 3 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 modules/nf-core/bwa/index/bwa-index.diff diff --git a/modules.json b/modules.json index b8c7002a..e49f34e1 100644 --- a/modules.json +++ b/modules.json @@ -8,7 +8,8 @@ "bwa/index": { "branch": "master", "git_sha": "9518fa4f65f3fb8cde24fde7d40333b39ec8fd65", - "installed_by": ["modules"] + "installed_by": ["modules"], + "patch": "modules/nf-core/bwa/index/bwa-index.diff" }, "custom/dumpsoftwareversions": { "branch": "master", diff --git a/modules/nf-core/bwa/index/bwa-index.diff b/modules/nf-core/bwa/index/bwa-index.diff new file mode 100644 index 00000000..779bcd5f --- /dev/null +++ b/modules/nf-core/bwa/index/bwa-index.diff @@ -0,0 +1,31 @@ +Changes in module 'nf-core/bwa/index' +--- modules/nf-core/bwa/index/main.nf ++++ modules/nf-core/bwa/index/main.nf +@@ -24,7 +24,7 @@ + bwa \\ + index \\ + $args \\ +- -p bwa/${fasta.baseName} \\ ++ -p bwa/${fasta.name} \\ + $fasta + + cat <<-END_VERSIONS > versions.yml +@@ -37,11 +37,11 @@ + """ + mkdir bwa + +- touch bwa/genome.amb +- touch bwa/genome.ann +- touch bwa/genome.bwt +- touch bwa/genome.pac +- touch bwa/genome.sa ++ touch bwa/genome.fasta.amb ++ touch bwa/genome.fasta.ann ++ touch bwa/genome.fasta.bwt ++ touch bwa/genome.fasta.pac ++ touch bwa/genome.fasta.sa + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + +************************************************************ diff --git a/modules/nf-core/bwa/index/main.nf b/modules/nf-core/bwa/index/main.nf index 6d70fc15..c305ffd9 100644 --- a/modules/nf-core/bwa/index/main.nf +++ b/modules/nf-core/bwa/index/main.nf @@ -24,7 +24,7 @@ process BWA_INDEX { bwa \\ index \\ $args \\ - -p bwa/${fasta.baseName} \\ + -p bwa/${fasta.name} \\ $fasta cat <<-END_VERSIONS > versions.yml @@ -37,11 +37,11 @@ process BWA_INDEX { """ mkdir bwa - touch bwa/genome.amb - touch bwa/genome.ann - touch bwa/genome.bwt - touch bwa/genome.pac - touch bwa/genome.sa + touch bwa/genome.fasta.amb + touch bwa/genome.fasta.ann + touch bwa/genome.fasta.bwt + touch bwa/genome.fasta.pac + touch bwa/genome.fasta.sa cat <<-END_VERSIONS > versions.yml "${task.process}": From 54708ea961452462ebbd8acd0e6491152a409262 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 31 Oct 2023 21:33:21 +1100 Subject: [PATCH 242/562] Add missing JAR file for GRIDSS index module --- conf/modules.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/conf/modules.config b/conf/modules.config index 89cf7564..01a74e9f 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -30,6 +30,10 @@ process { ] } + withName: '.*:GRIDSS.*INDEX.*' { + ext.jarPath = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' + } + withName: '.*:GRIDSS_SVPREP_CALLING:(?:DEPTH_ANNOTATOR|SVPREP_TUMOR|SVPREP_NORMAL)' { ext.jarPath = '/opt/svprep/svprep.jar' } From 4317475e1f801092130dbd8a2356b13e0e79a464 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 31 Oct 2023 21:33:49 +1100 Subject: [PATCH 243/562] Include class for GRIDSS index call --- modules/local/gridss/index/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 0c90de86..69228047 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -41,7 +41,7 @@ process GRIDSS_INDEX { -Dsamjdk.use_async_io_write_tribble=true \\ -Dsamjdk.buffer_size=4194304 \\ -Dsamjdk.async_io_read_threads=${task.cpus} \\ - -cp ${task.ext.jarPath} \\ + -cp ${task.ext.jarPath} gridss.PrepareReference \\ REFERENCE_SEQUENCE=${genome_fasta} \\ CREATE_SEQUENCE_DICTIONARY=${sequence_dict_arg} \\ CREATE_BWA_INDEX_IMAGE=${bwa_index_image_arg} \\ From 5e1cd3ab6b411b642fdcb481d5587d3345b7f658 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 31 Oct 2023 21:34:35 +1100 Subject: [PATCH 244/562] Further channel updates for building ref indexes --- subworkflows/local/prepare_reference.nf | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index 7e368e49..b7df9251 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -37,15 +37,13 @@ workflow PREPARE_REFERENCE { ch_genome_fai = params.ref_data_genome_fai ? file(params.ref_data_genome_fai) : [] ch_genome_dict = params.ref_data_genome_dict ? file(params.ref_data_genome_dict) : [] if (!params.ref_data_genome_fai) { - ch_samtools_faidx_inputs = Channel.of([[:], ch_genome_fasta]) - SAMTOOLS_FAIDX(ch_samtools_faidx_inputs) - ch_genome_fai = SAMTOOLS_FAIDX.out.fai + SAMTOOLS_FAIDX([[:], ch_genome_fasta]) + ch_genome_fai = SAMTOOLS_FAIDX.out.fai.map { meta, fai -> fai } ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions) } if (!params.ref_data_genome_dict) { - ch_samtools_dict_inputs = Channel.of([[:], ch_genome_fasta]) - SAMTOOLS_DICT(ch_samtools_dict_inputs) - ch_genome_dict = SAMTOOLS_DICT.out.dict + SAMTOOLS_DICT([[:], ch_genome_fasta]) + ch_genome_dict = SAMTOOLS_DICT.out.dict.map { meta, dict -> dict } ch_versions = ch_versions.mix(SAMTOOLS_DICT.out.versions) } @@ -59,7 +57,7 @@ workflow PREPARE_REFERENCE { // NOTE(SW): the BWA index directory can be provided as a compressed tarball if (!params.ref_data_genome_bwa_index) { BWA_INDEX([[:], ch_genome_fasta]) - ch_genome_bwa_index = BWA_INDEX.out.index.map { it[1] } + ch_genome_bwa_index = BWA_INDEX.out.index.map { meta, index -> index } ch_versions = ch_versions.mix(BWA_INDEX.out.versions) } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { ch_genome_bwa_index_inputs = [ From 3cf1cc9fc7a3f8190e7f5c929e563057053b8b1a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 31 Oct 2023 22:13:22 +1100 Subject: [PATCH 245/562] =?UTF-8?q?Bump=20version:=200.1.3=20=E2=86=92=200?= =?UTF-8?q?.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 835e38f8..d28ade98 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.3 +current_version = 0.2.0 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index 15474bcb..a8e76ae3 100644 --- a/nextflow.config +++ b/nextflow.config @@ -211,7 +211,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.1.3' + version = '0.2.0' doi = '' } From 3b51da3aa320f885eb679d53ae6609f1f7f12bc4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 1 Nov 2023 10:59:13 +1100 Subject: [PATCH 246/562] Only set default VIRUSBreakend db in WGTS mode --- lib/WorkflowMain.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 0225c843..9b101849 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -162,7 +162,7 @@ class WorkflowMain { log, ) - if (stages.virusinterpreter) { + if (stages.virusinterpreter && run_mode === Constants.RunMode.WGTS) { if (!params.containsKey('ref_data_virusbreakenddb_path')) { params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH } From d3a51e8c22c0c74cdc077ce43c995692da6ccbed Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 3 Nov 2023 13:26:37 +1100 Subject: [PATCH 247/562] Do not use symlinks to prepare inputs for ORANGE Using symlinks was seen to cause issues with HPC and Singularity --- modules/local/orange/main.nf | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 227649fe..1d89761a 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -52,22 +52,30 @@ process ORANGE { # When WTS data is present, ORANGE expects the somatic SAGE VCF to have appended WTS data; CS indicates this should # occur after PURPLE. Since ORANGE only collects the somatic SAGE VCF from the PURPLE output directory, we must # prepare accordingly + # Isofox inputs are also expected to have the tumor sample ID in the filename + + # Use of symlinks was causing reliability issues on HPC with Singularity, switched to full file copy instead + purple_dir_local=${purple_dir} if [[ -n "${rna_id_arg}" ]]; then purple_dir_local=purple__prepared; - mkdir -p \${purple_dir_local}/; - find -L ${purple_dir} -maxdepth 1 -exec ln -fs ../{} \${purple_dir_local}/ \\; - ln -sf ../${smlv_somatic_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.somatic.vcf.gz; + + if [[ -d \${purple_dir_local}/ ]]; then + rm -r \${purple_dir_local}/; + fi + + cp -rL ${purple_dir} \${purple_dir_local}/ + cp -L ${smlv_somatic_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.somatic.vcf.gz; if [[ -n "${smlv_germline_vcf}" ]]; then - ln -sf ../${smlv_germline_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.germline.vcf.gz; + cp -L ${smlv_germline_vcf} \${purple_dir_local}/${meta.tumor_id}.purple.germline.vcf.gz; fi; mkdir -p isofox_dir__prepared/; for fp in ${isofox_dir}/*; do - ln -s ../\${fp} isofox_dir__prepared/\$(sed 's/${meta.tumor_rna_id}/${meta.tumor_id}/' <<< \${fp##*/}); + cp -L \${fp} isofox_dir__prepared/\$(sed 's/${meta.tumor_rna_id}/${meta.tumor_id}/' <<< \${fp##*/}); done; fi From b0f85a4c32efa859d806a76815cdc7cee287134e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 3 Nov 2023 13:27:49 +1100 Subject: [PATCH 248/562] Only check VIRUSBreakend db exists in WGTS mode --- workflows/wgts.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 6e18a8ec..1559e836 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -31,7 +31,8 @@ if (run_config.stages.gridss) { } } -if (run_config.stages.virusinterpreter) { +// Mode check required as evaluated regardless of workflow selection +if (run_config.stages.virusinterpreter && run_config.mode !== Constants.RunMode.TARGETED) { checkPathParamList.add(params.ref_data_virusbreakenddb_path) } From 5f3065b0a4da57cd301923f092a3d0968fcc3ad8 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 3 Nov 2023 13:29:30 +1100 Subject: [PATCH 249/562] =?UTF-8?q?Bump=20version:=200.2.0=20=E2=86=92=200?= =?UTF-8?q?.2.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index d28ade98..45218b79 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.0 +current_version = 0.2.1 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index a8e76ae3..727ce7dd 100644 --- a/nextflow.config +++ b/nextflow.config @@ -211,7 +211,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.2.0' + version = '0.2.1' doi = '' } From 7584a64b79a1157576d168c454b843a82c67405c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 16 Nov 2023 15:25:36 +1100 Subject: [PATCH 250/562] Clean up some docs, templates --- CITATIONS.md | 4 -- README.md | 116 +++++++++++++++++++++-------------- assets/sendmail_template.txt | 25 -------- 3 files changed, 69 insertions(+), 76 deletions(-) diff --git a/CITATIONS.md b/CITATIONS.md index dfebcc85..385dca51 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -10,10 +10,6 @@ ## Pipeline tools -- [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) - -- [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) - > Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. ## Software packaging/containerisation tools diff --git a/README.md b/README.md index 95bace73..a2625264 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,114 @@ # ![nf-core/oncoanalyser](docs/images/nf-core-oncoanalyser_logo_light.png#gh-light-mode-only) ![nf-core/oncoanalyser](docs/images/nf-core-oncoanalyser_logo_dark.png#gh-dark-mode-only) -[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/oncoanalyser/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) +[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg)](https://www.nextflow.io/) -[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) +[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/oncoanalyser/results) + +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A522.10.5-23aa62.svg)](https://www.nextflow.io/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) -[![Launch on Nextflow Tower](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/oncoanalyser) +[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) +[![Launch on Nextflow Tower](https://img.shields.io/badge/launch%20on-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/oncoanalyser) -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23oncoanalyser-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/oncoanalyser)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23oncoanalyser-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/oncoanalyser) +[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core) +[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) ## Introduction - +**nf-core/oncoanalyser** is a Nextflow implementation of the comprehensive cancer RNA and DNA analysis and reporting +pipeline from the Hartwig Medical Foundation. For detailed information on each component of the Hartwig Medical +Foundation pipeline, please refer to [hartwigmedical/hmftools](https://github.com/hartwigmedical/hmftools/). -**nf-core/oncoanalyser** is a comprehensive cancer WGS/WTS analysis and reporting pipeline. +The oncoanalyser pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across +multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation +trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) +implementation of this pipeline uses one container per process which makes it much easier to maintain and update +software dependencies. Where possible, these processes have been submitted to and installed from +[nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to +everyone within the Nextflow community! -The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. Where possible, these processes have been submitted to and installed from [nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to everyone within the Nextflow community! - - - -On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources.The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/oncoanalyser/results). +On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud +infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on +real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other +analysis sources. The results obtained from the full-sized test can be viewed on the [nf-core +website](https://nf-co.re/oncoanalyser/results). ## Pipeline summary - +The following processes and tools can be run with oncoanalyser: -1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) -2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) +* SNV and MNV calling (`SAGE`, `PAVE`) +* SV calling (`SV Prep`, `GRIDSS`, `GRIPSS`, `PURPLE`, `LINX`) +* CNV calling (`AMBER`, `COBALT`, `PURPLE`) +* Transcript analysis (`Isofox`) +* Oncoviral detection (`VIRUSBreakend`, `Virus Interpreter`) +* HLA calling (`LILAC`) +* HRD status prediction (`CHORD`) +* Mutational signature fitting (`Sigs`) +* Tissue of origin prediction (`CUPPA`) +* Report generation (`ORANGE`, `gpgr [LINX]`) ## Quick Start -1. Install [`Nextflow`](https://www.nextflow.io/docs/latest/getstarted.html#installation) (`>=21.10.3`) - -2. Install any of [`Docker`](https://docs.docker.com/engine/installation/), [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/) (you can follow [this tutorial](https://singularity-tutorial.github.io/01-installation/)), [`Podman`](https://podman.io/), [`Shifter`](https://nersc.gitlab.io/development/shifter/how-to-use/) or [`Charliecloud`](https://hpc.github.io/charliecloud/) for full pipeline reproducibility _(you can use [`Conda`](https://conda.io/miniconda.html) both to install Nextflow itself and also to manage software within pipelines. Please only use it within pipelines as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles))_. +Create a samplesheet containing your inputs: -3. Download the pipeline and test it on a minimal dataset with a single command: +```text +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath +P1__wgts,P1,SA,tumor,dna,bam,/path/to/SA.tumor.dna.wgs.bam +P1__wgts,P1,SB,tumor,rna,bam,/path/to/SB.tumor.rna.wts.bam +P1__wgts,P1,SC,normal,dna,bam,/path/to/SC.normal.dna.wgs.bam +``` - ```bash - nextflow run nf-core/oncoanalyser -profile test,YOURPROFILE --outdir - ``` +Launch oncoanalyser: - Note that some form of configuration will be needed so that Nextflow knows how to fetch the required software. This is usually done in the form of a config profile (`YOURPROFILE` in the example command above). You can chain multiple config profiles in a comma-separated string. - - > - The pipeline comes with config profiles called `docker`, `singularity`, `podman`, `shifter`, `charliecloud` and `conda` which instruct the pipeline to use the named tool for software management. For example, `-profile test,docker`. - > - Please check [nf-core/configs](https://github.com/nf-core/configs#documentation) to see if a custom config file to run nf-core pipelines already exists for your Institute. If so, you can simply use `-profile ` in your command. This will enable either `docker` or `singularity` and set the appropriate execution settings for your local compute environment. - > - If you are using `singularity`, please use the [`nf-core download`](https://nf-co.re/tools/#downloading-pipelines-for-offline-use) command to download images first, before running the pipeline. Setting the [`NXF_SINGULARITY_CACHEDIR` or `singularity.cacheDir`](https://www.nextflow.io/docs/latest/singularity.html?#singularity-docker-hub) Nextflow options enables you to store and re-use the images from a central location for future pipeline runs. - > - If you are using `conda`, it is highly recommended to use the [`NXF_CONDA_CACHEDIR` or `conda.cacheDir`](https://www.nextflow.io/docs/latest/conda.html) settings to store the environments in a central location for future pipeline runs. - -4. Start running your own analysis! - - - - ```bash - nextflow run nf-core/oncoanalyser --input samplesheet.csv --outdir --genome GRCh37 -profile - ``` +```bash +nextflow run umccr/oncoanalyser \ + -profile docker \ + --mode wgts \ + --genome GRCh38_hmf \ + --input samplesheet.csv \ + --outdir output/ +``` ## Documentation -The nf-core/oncoanalyser pipeline comes with documentation about the pipeline [usage](https://nf-co.re/oncoanalyser/usage), [parameters](https://nf-co.re/oncoanalyser/parameters) and [output](https://nf-co.re/oncoanalyser/output). +The nf-core/oncoanalyser pipeline comes with documentation about the pipeline +[usage](https://nf-co.re/oncoanalyser/usage), [parameters](https://nf-co.re/oncoanalyser/parameters) and +[output](https://nf-co.re/oncoanalyser/output). ## Credits -nf-core/oncoanalyser was originally written by Stephen Watts. +The oncoanalyser pipeline was written by Stephen Watts at the [University of Melbourne Centre for Cancer +Research](https://mdhs.unimelb.edu.au/centre-for-cancer-research). -We thank the following people for their extensive assistance in the development of this pipeline: +We thank the following people for their extensive assistance in the development of this pipeline, listed in alphabetical +order: - +* Charles Shale +* Oliver Hofmann +* Peter Priestley ## Contributions and Support If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). -For further information or help, don't hesitate to get in touch on the [Slack `#oncoanalyser` channel](https://nfcore.slack.com/channels/oncoanalyser) (you can join with [this invite](https://nf-co.re/join/slack)). +For further information or help, don't hesitate to get in touch on the [Slack `#oncoanalyser` +channel](https://nfcore.slack.com/channels/oncoanalyser) (you can join with [this invite](https://nf-co.re/join/slack)). ## Citations - - - - +You can cite the oncoanalyser zenodo record for a specific version using the following doi: +[10.5281/zenodo.XXXXXXX](https://doi.org/10.5281/zenodo.XXXXXXX) -An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. +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: > **The nf-core framework for community-curated bioinformatics pipelines.** > -> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen. +> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, +> Paolo Di Tommaso & Sven Nahnsen. > > _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). diff --git a/assets/sendmail_template.txt b/assets/sendmail_template.txt index 72d5b869..b2e91ca6 100644 --- a/assets/sendmail_template.txt +++ b/assets/sendmail_template.txt @@ -25,29 +25,4 @@ Content-Disposition: inline; filename="nf-core-oncoanalyser_logo_light.png" flatten(). join( '\n' ) %> -<% -if (mqcFile){ -def mqcFileObj = new File("$mqcFile") -if (mqcFileObj.length() < mqcMaxSize){ -out << """ ---nfcoremimeboundary -Content-Type: text/html; name=\"multiqc_report\" -Content-Transfer-Encoding: base64 -Content-ID: -Content-Disposition: attachment; filename=\"${mqcFileObj.getName()}\" - -${mqcFileObj. - bytes. - encodeBase64(). - toString(). - tokenize( '\n' )*. - toList()*. - collate( 76 )*. - collect { it.join() }. - flatten(). - join( '\n' )} -""" -}} -%> - --nfcoremimeboundary-- From 2947d206245ebdfa896ce1d45ae7c13463846541 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 16 Nov 2023 15:25:48 +1100 Subject: [PATCH 251/562] Set default publish mode as 'copy' --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index 727ce7dd..f0c32256 100644 --- a/nextflow.config +++ b/nextflow.config @@ -34,7 +34,7 @@ params { // Boilerplate options outdir = null tracedir = "${params.outdir}/pipeline_info" - publish_dir_mode = 'symlink' + publish_dir_mode = 'copy' email = null email_on_fail = null plaintext_email = false From 5b84b1615f7255f3a8fa4ae7a504248e3adec749 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 20 Nov 2023 15:13:05 +1100 Subject: [PATCH 252/562] Only run Sigs and CHORD when DNA BAMs are provided --- subworkflows/local/chord_prediction.nf | 16 ++++++++++++---- subworkflows/local/sigs_fitting.nf | 12 +++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/subworkflows/local/chord_prediction.nf b/subworkflows/local/chord_prediction.nf index 715c4280..d5f3c187 100644 --- a/subworkflows/local/chord_prediction.nf +++ b/subworkflows/local/chord_prediction.nf @@ -34,13 +34,21 @@ workflow CHORD_PREDICTION { ch_inputs_sorted = ch_inputs_selected .branch { meta, purple_dir -> - def tumor_id = Utils.getTumorDnaSampleName(meta) + def has_dna = Utils.hasTumorDnaBam(meta) + + def tumor_id + def has_smlv_vcf + def has_sv_vcf + + if (has_dna) { + tumor_id = Utils.getTumorDnaSampleName(meta) + has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] + has_sv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") : [] + } def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.CHORD_DIR) - def has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] - def has_sv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") : [] - runnable: purple_dir && has_smlv_vcf && has_sv_vcf && !has_existing + runnable: has_dna && purple_dir && has_smlv_vcf && has_sv_vcf && !has_existing skip: true return meta } diff --git a/subworkflows/local/sigs_fitting.nf b/subworkflows/local/sigs_fitting.nf index 167d7fa3..4a2f159b 100644 --- a/subworkflows/local/sigs_fitting.nf +++ b/subworkflows/local/sigs_fitting.nf @@ -34,12 +34,18 @@ workflow SIGS_FITTING { ch_inputs_sorted = ch_inputs_selected .branch { meta, purple_dir -> - def tumor_id = Utils.getTumorDnaSampleName(meta) + def has_dna = Utils.hasTumorDnaBam(meta) + + def tumor_id + def has_smlv_vcf + if (has_dna) { + tumor_id = Utils.getTumorDnaSampleName(meta) + has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] + } def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SIGS_DIR) - def has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] - runnable: purple_dir && has_smlv_vcf && !has_existing + runnable: has_dna && purple_dir && has_smlv_vcf && !has_existing skip: true return meta } From 6b8c0d89ef7cf8be33ac1c006f80b638b43b3400 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 20 Nov 2023 18:03:23 +1100 Subject: [PATCH 253/562] Only run contig extraction when required --- conf/modules.config | 6 ++++++ modules/local/custom/lilac_extract_and_index_contig/main.nf | 1 + subworkflows/local/lilac_calling.nf | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/conf/modules.config b/conf/modules.config index 01a74e9f..2896a36a 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -174,6 +174,12 @@ process { ] } + withName: 'EXTRACTCONTIG' { + // Run is an boolean input value passed to the process that is conditioned on whether there are runnable + // inputs for LILAC + ext.when = { run } + } + withName: 'LILAC' { ext.jarPath = '/opt/lilac/lilac.jar' publishDir = [ diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index d0af2900..8065c8e2 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -8,6 +8,7 @@ process CUSTOM_EXTRACTCONTIG { val contig_name path genome_fasta path genome_fai + val run output: path "*extracted.fa" , emit: contig diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index d69e8668..ca25ff18 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -121,10 +121,16 @@ workflow LILAC_CALLING { // // MODULE: Custom extract contig (LILAC) // + // Only run if we have runnable inputs, no blocking since operating only on input metas + ch_extract_contig_run = ch_realign_inputs_sorted.runnable + .toList() + .map { !it.isEmpty() } + EXTRACTCONTIG( 'chr6', genome_fasta, genome_fai, + ch_extract_contig_run, ) ch_versions = ch_versions.mix(EXTRACTCONTIG.out.versions) From f60de25959e0c6a92f7ef50c3253164417379ac9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 20 Nov 2023 18:34:31 +1100 Subject: [PATCH 254/562] =?UTF-8?q?Bump=20version:=200.2.1=20=E2=86=92=200?= =?UTF-8?q?.2.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 45218b79..cc687d2f 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.1 +current_version = 0.2.2 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index f0c32256..9ff24275 100644 --- a/nextflow.config +++ b/nextflow.config @@ -211,7 +211,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.2.1' + version = '0.2.2' doi = '' } From 82a6a54fb1ef8dd213bacf397d762808f6ad605e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 20 Nov 2023 22:01:07 +1100 Subject: [PATCH 255/562] Use correct SAGE input for ORANGE --- subworkflows/local/orange_reporting.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index e3818522..60140dce 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -109,8 +109,8 @@ workflow ORANGE_REPORTING { Utils.selectCurrentOrExisting(inputs[1], meta, Constants.INPUT.BAMTOOLS_NORMAL), Utils.selectCurrentOrExisting(inputs[2], meta, Constants.INPUT.FLAGSTAT_TUMOR), Utils.selectCurrentOrExisting(inputs[3], meta, Constants.INPUT.FLAGSTAT_NORMAL), - Utils.selectCurrentOrExisting(inputs[4], meta, Constants.INPUT.SAGE_VCF_TUMOR), - Utils.selectCurrentOrExisting(inputs[5], meta, Constants.INPUT.SAGE_VCF_NORMAL), + Utils.selectCurrentOrExisting(inputs[4], meta, Constants.INPUT.SAGE_DIR_TUMOR), + Utils.selectCurrentOrExisting(inputs[5], meta, Constants.INPUT.SAGE_DIR_NORMAL), Utils.selectCurrentOrExisting(inputs[6], meta, Constants.INPUT.SAGE_APPEND_VCF_TUMOR), Utils.selectCurrentOrExisting(inputs[7], meta, Constants.INPUT.SAGE_APPEND_VCF_NORMAL), Utils.selectCurrentOrExisting(inputs[8], meta, Constants.INPUT.PURPLE_DIR), From dee9855aa3477094abc7517f566c858f90b9b06b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 20 Nov 2023 22:01:43 +1100 Subject: [PATCH 256/562] Check appropriate existing results for CUPPA --- subworkflows/local/cuppa_prediction.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index e6fe2dfa..bd9b5877 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -61,7 +61,7 @@ workflow CUPPA_PREDICTION { // // (run exclusions currently done basis for presence of normal DNA) - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.CUPPA_DIR) def has_normal_dna = Utils.hasNormalDnaBam(meta) def has_runnable_inputs = isofox_dir || (purple_dir && linx_annotation_dir && has_normal_dna) From 2b75c3bcdc5cd89e07326a6a5bcd8f78b5878442 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 21 Nov 2023 09:43:57 +1100 Subject: [PATCH 257/562] =?UTF-8?q?Bump=20version:=200.2.2=20=E2=86=92=200?= =?UTF-8?q?.2.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index cc687d2f..edb87a3f 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.2 +current_version = 0.2.3 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index 9ff24275..2f44df27 100644 --- a/nextflow.config +++ b/nextflow.config @@ -211,7 +211,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.2.2' + version = '0.2.3' doi = '' } From dc33f7e1472ef6807e6f2f2e6d903f02d1ce8bf3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 21 Nov 2023 13:29:41 +1100 Subject: [PATCH 258/562] Use index when slicing input LILAC BAMs --- modules/local/custom/lilac_slice/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index e3b371f7..6f73c415 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -21,7 +21,7 @@ process CUSTOM_SLICE { """ samtools view \\ ${args} \\ - -L ${bed} \\ + --regions-file ${bed} \\ -@${task.cpus} \\ -Obam \\ ${bam} | \\ From 029325a00908fbc36b9f679fbc859a57c683b2c3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 21 Nov 2023 13:30:00 +1100 Subject: [PATCH 259/562] Write out both 'reportable' and 'all' LINX plots Previously just the 'all' LINX plots were written but we need the 'reportable' plots when launching a WGTS run with existing WGS inputs in order to consistently reproduce the ORANGE report. --- conf/modules.config | 11 +++++++++-- modules/local/linx/visualiser/main.nf | 14 +++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 2896a36a..e1cc9fde 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -144,8 +144,15 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - pattern: '*/plot_all', - saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/somatic_plots/" }, + // NOTE(SW): java.io.File and Nextflow's file do not work here, resorting to string splitting + saveAs: { filename -> + if (filename.equals('versions.yml')) { + return null + } else { + def tokens = filename.split('[/]') + return "${meta.key}/linx/somatic_plots/${tokens[-1]}" + } + }, ] } diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index f89ae097..d077f401 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -10,9 +10,9 @@ process LINX_VISUALISER { path ensembl_data_resources output: - tuple val(meta), path('linx_visualiser/plot_all/') , emit: visualiser_dir_all - tuple val(meta), path('linx_visualiser/plot_reportable/'), emit: visualiser_dir_reportable - path 'versions.yml' , emit: versions + tuple val(meta), path('linx_visualiser/all/') , emit: visualiser_dir_all + tuple val(meta), path('linx_visualiser/reportable/'), emit: visualiser_dir_reportable + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -40,8 +40,8 @@ process LINX_VISUALISER { -ensembl_data_dir ${ensembl_data_resources} \\ -circos ${task.ext.circosPath} \\ -threads ${task.cpus} \\ - -plot_out linx_visualiser/plot_all/ \\ - -data_out linx_visualiser/data_all/ + -plot_out linx_visualiser/all/ \\ + -data_out linx_visualiser/all_data/ # Rerun LINX to render only reportable cluster plots in a separate directory. While this is regenerating existing # cluster plots, the number of reportable plots is generally very small and I prefer to rely on the internal LINX @@ -65,8 +65,8 @@ process LINX_VISUALISER { -circos ${task.ext.circosPath} \\ -plot_reportable \\ -threads ${task.cpus} \\ - -plot_out linx_visualiser/plot_reportable/ \\ - -data_out linx_visualiser/data_reportable/ + -plot_out linx_visualiser/reportable/ \\ + -data_out linx_visualiser/reportable_data/ cat <<-END_VERSIONS > versions.yml "${task.process}": From a017e37ff0a7d8d6e09698d17efe2bb2a14c502f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 21 Nov 2023 13:31:40 +1100 Subject: [PATCH 260/562] =?UTF-8?q?Bump=20version:=200.2.3=20=E2=86=92=200?= =?UTF-8?q?.2.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index edb87a3f..57ca2e81 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.3 +current_version = 0.2.4 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index 2f44df27..afd40cab 100644 --- a/nextflow.config +++ b/nextflow.config @@ -211,7 +211,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.2.3' + version = '0.2.4' doi = '' } From bae36525eb9c90b5161039459864eba884805397 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 22 Nov 2023 10:19:32 +1100 Subject: [PATCH 261/562] Use existing PURPLE input for LILAC --- subworkflows/local/lilac_calling.nf | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index ca25ff18..37980d18 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -213,7 +213,16 @@ workflow LILAC_CALLING { meta_lilac.normal_id = Utils.getNormalDnaSampleName(meta) } - return [meta_lilac, nbam_dna, nbai_dna, tbam_dna, tbai_dna, tbam_rna, tbai_rna, purple_dir] + return [ + meta_lilac, + nbam_dna, + nbai_dna, + tbam_dna, + tbai_dna, + tbam_rna, + tbai_rna, + Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), + ] } // Run process From d5cc9dfd545e891d635a9c1cb202022c0a6f504d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 22 Nov 2023 10:19:39 +1100 Subject: [PATCH 262/562] =?UTF-8?q?Bump=20version:=200.2.4=20=E2=86=92=200?= =?UTF-8?q?.2.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 57ca2e81..b531ecd7 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.4 +current_version = 0.2.5 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index afd40cab..c2ef44e5 100644 --- a/nextflow.config +++ b/nextflow.config @@ -211,7 +211,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.2.4' + version = '0.2.5' doi = '' } From 885ef2bb6353c761116f82c61fe3a597fceb9ab5 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 22 Nov 2023 19:51:06 +1100 Subject: [PATCH 263/562] Reorganise LINX plots under single parent dir --- modules/local/gpgr/linx/main.nf | 11 ++++++++- modules/local/linx/visualiser/main.nf | 32 ++++++++++++++++++-------- modules/local/orange/main.nf | 10 ++++++-- subworkflows/local/linx_plotting.nf | 22 ++++++------------ subworkflows/local/orange_reporting.nf | 2 +- workflows/targeted.nf | 10 ++++---- workflows/wgts.nf | 10 ++++---- 7 files changed, 59 insertions(+), 38 deletions(-) diff --git a/modules/local/gpgr/linx/main.nf b/modules/local/gpgr/linx/main.nf index 5d3a6c01..48eec890 100644 --- a/modules/local/gpgr/linx/main.nf +++ b/modules/local/gpgr/linx/main.nf @@ -17,11 +17,18 @@ process GPGR_LINX { script: def args = task.ext.args ?: '' + def plot_dir = linx_visualiser_dir.resolve('all/').toUriString().replaceAll('/$', '') + """ + # Set input plot directory and create it doesn't exist. See the LINX visualiser module for further info. + if [[ ! -e ${plot_dir}/ ]]; then + mkdir -p ${plot_dir}/; + fi; + gpgr.R linx \\ ${args} \\ --sample ${meta.sample_id} \\ - --plot ${linx_visualiser_dir}/ \\ + --plot ${plot_dir}/ \\ --table ${linx_annotation_dir}/ \\ --out ${meta.sample_id}_linx.html @@ -33,6 +40,8 @@ process GPGR_LINX { """ stub: + def plot_dir = linx_visualiser_dir.resolve('all/').toUriString().replaceAll('/$', '') + """ touch ${meta.sample_id}_linx.html echo -e '${task.process}:\n stub: noversions\n' > versions.yml diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index d077f401..b9bf4672 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -10,9 +10,8 @@ process LINX_VISUALISER { path ensembl_data_resources output: - tuple val(meta), path('linx_visualiser/all/') , emit: visualiser_dir_all - tuple val(meta), path('linx_visualiser/reportable/'), emit: visualiser_dir_reportable - path 'versions.yml' , emit: versions + tuple val(meta), path('plots/'), emit: plots + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -21,6 +20,16 @@ process LINX_VISUALISER { def args = task.ext.args ?: '' """ + # NOTE(SW): the output plot directories are always required for ORANGE, which is straightfoward to handle with POSIX + # fs but more involved with FusionFS since it will not write empty directories to S3. A placeholder file can't be + # used in the plot directory to force FusionFS to create the directory as ORANGE will treat the placeholder as a PNG + # and fail. Optional outputs are possible but requires further channel logic and output to detect when complete. + # Instead I place the two plot output directories under a parent directory, only operating on that to allow use of a + # placeholder and support empty outputs when using FusionFS. Handing missing/non-existent directories are deferred + # to downstream processes, bypassing the need to implement further channel operations. + + mkdir -p plots/ + # NOTE(SW): LINX v1.24.1 require trailing slashes for the -plot_out and -data_out arguments since no filesystem # separator is used when constructing fusion plot output filepaths. @@ -40,8 +49,8 @@ process LINX_VISUALISER { -ensembl_data_dir ${ensembl_data_resources} \\ -circos ${task.ext.circosPath} \\ -threads ${task.cpus} \\ - -plot_out linx_visualiser/all/ \\ - -data_out linx_visualiser/all_data/ + -plot_out plots/all/ \\ + -data_out reportable/all_data/ # Rerun LINX to render only reportable cluster plots in a separate directory. While this is regenerating existing # cluster plots, the number of reportable plots is generally very small and I prefer to rely on the internal LINX @@ -65,8 +74,13 @@ process LINX_VISUALISER { -circos ${task.ext.circosPath} \\ -plot_reportable \\ -threads ${task.cpus} \\ - -plot_out linx_visualiser/reportable/ \\ - -data_out linx_visualiser/reportable_data/ + -plot_out plots/reportable/ \\ + -data_out data/reportable/ + + # Create placeholders to force FusionFS to create parent plot directory on S3 + if [[ \$(ls plots/ | wc -l) -eq 0 ]]; then + touch plots/.keep; + fi; cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -76,8 +90,8 @@ process LINX_VISUALISER { stub: """ - mkdir -p linx_visualiser/plot_{all,reportable}/ - touch linx_visualiser/plot_{all,reportable}/placeholder + mkdir -p plots/{all,reportable}/ + touch plots/{all,reportable}/placeholder echo -e '${task.process}:\n stub: noversions\n' > versions.yml """ } diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 1d89761a..1f9cd177 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -33,6 +33,7 @@ process ORANGE { def chord_dir_arg = chord_dir ? "-chord_dir ${chord_dir}" : '' def sigs_dir_arg = sigs_dir ? "-sigs_dir ${sigs_dir}" : '' def cuppa_dir_arg = cuppa_dir ? "-cuppa_dir ${cuppa_dir}" : '' + def plot_dir = linx_somatic_plot_dir.resolve('reportable/').toUriString().replaceAll('/$', '') def normal_id_arg = meta.containsKey('normal_dna_id') ? "-reference_sample_id ${meta.normal_dna_id}" : '' def normal_metrics_arg = bam_metrics_germline ? "-ref_sample_wgs_metrics_file ${bam_metrics_germline}" : '' @@ -55,7 +56,7 @@ process ORANGE { # Isofox inputs are also expected to have the tumor sample ID in the filename - # Use of symlinks was causing reliability issues on HPC with Singularity, switched to full file copy instead + # NOTES(SW): Use of symlinks was causing reliability issues on HPC with Singularity, switched to full file copy instead purple_dir_local=${purple_dir} if [[ -n "${rna_id_arg}" ]]; then @@ -80,6 +81,11 @@ process ORANGE { fi + # Set input plot directory and create it doesn't exist. See the LINX visualiser module for further info. + if [[ ! -e ${plot_dir}/ ]]; then + mkdir -p ${plot_dir}/; + fi; + # NOTE(SW): '--add-opens java.base/java.time=ALL-UNNAMED' resolves issue writing JSON, see: # https://stackoverflow.com/questions/70412805/what-does-this-error-mean-java-lang-reflect-inaccessibleobjectexception-unable/70878195#70878195 @@ -104,7 +110,7 @@ process ORANGE { -purple_dir \${purple_dir_local} \\ -purple_plot_dir \${purple_dir_local}/plot/ \\ -linx_dir ${linx_somatic_anno_dir} \\ - -linx_plot_dir ${linx_somatic_plot_dir} \\ + -linx_plot_dir ${plot_dir}/ \\ -lilac_dir ${lilac_dir} \\ ${virus_dir_arg} \\ ${chord_dir_arg} \\ diff --git a/subworkflows/local/linx_plotting.nf b/subworkflows/local/linx_plotting.nf index 20d1e9cf..7853dc06 100644 --- a/subworkflows/local/linx_plotting.nf +++ b/subworkflows/local/linx_plotting.nf @@ -72,10 +72,10 @@ workflow LINX_PLOTTING { // MODULE: gpgr LINX report // // Create process input channel - // channel: [ meta_gpgr, annotation_dir, visualiser_dir_all ] + // channel: [ meta_gpgr, annotation_dir, visualiser_dir ] ch_gpgr_linx_inputs = WorkflowOncoanalyser.groupByMeta( ch_inputs_sorted.runnable, - WorkflowOncoanalyser.restoreMeta(VISUALISER.out.visualiser_dir_all, ch_inputs), + WorkflowOncoanalyser.restoreMeta(VISUALISER.out.plots, ch_inputs), ) .map { meta, annotation_dir, visualiser_dir -> @@ -96,23 +96,15 @@ workflow LINX_PLOTTING { ch_versions = ch_versions.mix(GPGR.out.versions) // Set outputs, restoring original meta - // channel: [ meta, visualiser_dir_all ] - ch_visualiser_all_out = Channel.empty() + // channel: [ meta, visualiser_dir ] + ch_visualiser_dir_out = Channel.empty() .mix( - WorkflowOncoanalyser.restoreMeta(VISUALISER.out.visualiser_dir_all, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - - // channel: [ meta, visualiser_dir_reportable ] - ch_visualiser_reportable_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(VISUALISER.out.visualiser_dir_reportable, ch_inputs), + WorkflowOncoanalyser.restoreMeta(VISUALISER.out.plots, ch_inputs), ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) emit: - visualiser_dir_all = ch_visualiser_all_out // channel: [ meta, visualiser_dir_all ] - visualiser_dir_reportable = ch_visualiser_reportable_out // channel: [ meta, visualiser_dir_reportable ] + visualiser_dir = ch_visualiser_dir_out // channel: [ meta, visualiser_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index 60140dce..c250cdc0 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -21,7 +21,7 @@ workflow ORANGE_REPORTING { ch_sage_germline_append // channel: [mandatory] [ meta, sage_append_vcf ] ch_purple // channel: [mandatory] [ meta, purple_dir ] ch_linx_somatic_annotation // channel: [mandatory] [ meta, linx_annotation_dir ] - ch_linx_somatic_plot // channel: [mandatory] [ meta, linx_visualiser_dir_reportable ] + ch_linx_somatic_plot // channel: [mandatory] [ meta, linx_visualiser_dir ] ch_linx_germline_annotation // channel: [mandatory] [ meta, linx_annotation_dir ] ch_virusinterpreter // channel: [mandatory] [ meta, virusinterpreter_dir ] ch_chord // channel: [mandatory] [ meta, chord_dir ] diff --git a/workflows/targeted.nf b/workflows/targeted.nf index f6bd4b17..7c605ac6 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -460,8 +460,8 @@ workflow TARGETED { // // SUBWORKFLOW: Visualise LINX annotations // - // channel: [ meta, linx_visualiser_dir_reportable ] - ch_linx_somatic_plot_reportable_out = Channel.empty() + // channel: [ meta, linx_visualiser_dir ] + ch_linx_somatic_visualiser_dir_out = Channel.empty() if (run_config.stages.linx) { LINX_PLOTTING( @@ -473,11 +473,11 @@ workflow TARGETED { ch_versions = ch_versions.mix(LINX_PLOTTING.out.versions) - ch_linx_somatic_plot_reportable_out = ch_linx_somatic_plot_reportable_out.mix(LINX_PLOTTING.out.visualiser_dir_reportable) + ch_linx_somatic_visualiser_dir_out = ch_linx_somatic_visualiser_dir_out.mix(LINX_PLOTTING.out.visualiser_dir) } else { - ch_linx_somatic_plot_reportable_out = ch_inputs.map { meta -> [meta, []] } + ch_linx_somatic_visualiser_dir_out = ch_inputs.map { meta -> [meta, []] } } @@ -584,7 +584,7 @@ workflow TARGETED { ch_sage_germline_append_out, ch_purple_out, ch_linx_somatic_out, - ch_linx_somatic_plot_reportable_out, + ch_linx_somatic_visualiser_dir_out, ch_linx_germline_out, ch_virusinterpreter_out, ch_chord_out, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 1559e836..27f437f6 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -461,8 +461,8 @@ workflow WGTS { // // SUBWORKFLOW: Visualise LINX annotations // - // channel: [ meta, linx_visualiser_dir_reportable ] - ch_linx_somatic_plot_reportable_out = Channel.empty() + // channel: [ meta, linx_visualiser_dir ] + ch_linx_somatic_visualiser_dir_out = Channel.empty() if (run_config.stages.linx) { LINX_PLOTTING( @@ -474,11 +474,11 @@ workflow WGTS { ch_versions = ch_versions.mix(LINX_PLOTTING.out.versions) - ch_linx_somatic_plot_reportable_out = ch_linx_somatic_plot_reportable_out.mix(LINX_PLOTTING.out.visualiser_dir_reportable) + ch_linx_somatic_visualiser_dir_out = ch_linx_somatic_visualiser_dir_out.mix(LINX_PLOTTING.out.visualiser_dir) } else { - ch_linx_somatic_plot_reportable_out = ch_inputs.map { meta -> [meta, []] } + ch_linx_somatic_visualiser_dir_out = ch_inputs.map { meta -> [meta, []] } } @@ -685,7 +685,7 @@ workflow WGTS { ch_sage_germline_append_out, ch_purple_out, ch_linx_somatic_out, - ch_linx_somatic_plot_reportable_out, + ch_linx_somatic_visualiser_dir_out, ch_linx_germline_out, ch_virusinterpreter_out, ch_chord_out, From f60d19accb43d423b7aea8a4a0cbc57114416ff2 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 22 Nov 2023 19:51:17 +1100 Subject: [PATCH 264/562] =?UTF-8?q?Bump=20version:=200.2.5=20=E2=86=92=200?= =?UTF-8?q?.2.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index b531ecd7..a2f7efa9 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.5 +current_version = 0.2.6 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index c2ef44e5..abf76473 100644 --- a/nextflow.config +++ b/nextflow.config @@ -211,7 +211,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.2.5' + version = '0.2.6' doi = '' } From 3bb03de0d0172c1ced35d98ffcd552c57ce5f641 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 22 Nov 2023 20:35:23 +1100 Subject: [PATCH 265/562] Fix LINX plot directory output --- conf/modules.config | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index e1cc9fde..c5896588 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -144,15 +144,7 @@ process { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, - // NOTE(SW): java.io.File and Nextflow's file do not work here, resorting to string splitting - saveAs: { filename -> - if (filename.equals('versions.yml')) { - return null - } else { - def tokens = filename.split('[/]') - return "${meta.key}/linx/somatic_plots/${tokens[-1]}" - } - }, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/linx/somatic_plots/" }, ] } From cc81cdbe3c7c40ce4ae7a73ff8dca2fd9ebafc3c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 22 Nov 2023 20:56:10 +1100 Subject: [PATCH 266/562] =?UTF-8?q?Bump=20version:=200.2.6=20=E2=86=92=200?= =?UTF-8?q?.2.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index a2f7efa9..050bd04b 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.6 +current_version = 0.2.7 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index abf76473..6834fb2b 100644 --- a/nextflow.config +++ b/nextflow.config @@ -211,7 +211,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.2.6' + version = '0.2.7' doi = '' } From 86220ec5b0399fcf99f9f02002cd5a981b7d4563 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Dec 2023 18:33:20 +1100 Subject: [PATCH 267/562] Basic isolated alignment subworkflow outline --- modules/local/bwa/mem2/main.nf | 39 +++++++++++++++++ modules/local/markdups/main.nf | 38 ++++++++++++++++ modules/local/star/main.nf | 40 +++++++++++++++++ subworkflows/local/read_alignment.nf | 39 +++++++++++++++++ subworkflows/local/read_processing.nf | 34 +++++++++++++++ workflows/wgts.nf | 62 +++++++++++++++++++++++++++ 6 files changed, 252 insertions(+) create mode 100644 modules/local/bwa/mem2/main.nf create mode 100644 modules/local/markdups/main.nf create mode 100644 modules/local/star/main.nf create mode 100644 subworkflows/local/read_alignment.nf create mode 100644 subworkflows/local/read_processing.nf diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf new file mode 100644 index 00000000..3b55a8a1 --- /dev/null +++ b/modules/local/bwa/mem2/main.nf @@ -0,0 +1,39 @@ +process BWA_MEM2 { + tag "${meta.id}" + label 'process_high' + + // TODO(SW): create container + //container 'foo' + + input: + // TODO(SW): decide input structure + tuple val(meta), path(fastqs) + + output: + // TODO(SW): set outputs + tuple val(meta), path('bar'), emit: bam + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + // TODO(SW): implement process + """ + touch bar + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwamem2: foo + END_VERSIONS + """ + + stub: + // TODO(SW): implement stub + """ + touch bar + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf new file mode 100644 index 00000000..ea02ed90 --- /dev/null +++ b/modules/local/markdups/main.nf @@ -0,0 +1,38 @@ +process MARKDUPS { + tag "${meta.id}" + label 'process_low' + + // TODO(SW): create container + //container 'foo' + + input: + tuple val(meta), path(bam) + + output: + // TODO(SW): set outputs + tuple val(meta), path('bar'), emit: bam + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + // TODO(SW): implement process + """ + echo bar + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + markdups: foo + END_VERSIONS + """ + + stub: + // TODO(SW): implement stub + """ + touch bar + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/star/main.nf b/modules/local/star/main.nf new file mode 100644 index 00000000..780139b3 --- /dev/null +++ b/modules/local/star/main.nf @@ -0,0 +1,40 @@ +process STAR { + tag "${meta.id}" + label 'process_low' + + // TODO(SW): create container + //container 'foo' + + input: + // TODO(SW): decide input structure + tuple val(meta), path(fastqs) + + output: + // TODO(SW): set outputs + tuple val(meta), path('bar'), emit: bam + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + // TODO(SW): implement process + """ + echo bar + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + star: foo + END_VERSIONS + """ + + stub: + // TODO(SW): implement stub + """ + touch bar + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} + diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf new file mode 100644 index 00000000..a13025fa --- /dev/null +++ b/subworkflows/local/read_alignment.nf @@ -0,0 +1,39 @@ +include { BWA_MEM2 } from '../../modules/local/bwa/mem2/main' +include { STAR } from '../../modules/local/star/main' + +workflow READ_ALIGNMENT { + take: + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + + main: + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // STAR + // TODO(SW): implement inputs + ch_star_inputs = Channel.of([[id: 'foo'], []]) + STAR( + ch_star_inputs, + // TODO(SW): include reference files + ) + // TODO(SW): implement outputs + ch_star_outputs = Channel.empty() + + // BWA MEM2 + // TODO(SW): implement inputs + ch_bwa_inputs = Channel.of([[id: 'foo'], []]) + BWA_MEM2( + ch_bwa_inputs, + // TODO(SW): include reference files + ) + // TODO(SW): implement outputs + ch_bwa_outputs = Channel.empty() + + emit: + dna = ch_bwa_outputs // channel: [ meta, bam_dna ] + rna = ch_star_outputs // channel: [ meta, bam_rna ] + + versions = ch_versions // channel: [ versions.yml ] +} diff --git a/subworkflows/local/read_processing.nf b/subworkflows/local/read_processing.nf new file mode 100644 index 00000000..af0bb10c --- /dev/null +++ b/subworkflows/local/read_processing.nf @@ -0,0 +1,34 @@ +include { MARKDUPS } from '../../modules/local/markdups/main' + +workflow READ_PROCESSING { + take: + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_dna_bams // channel: [mandatory] [ meta, bam_dna ] + ch_rna_bams // channel: [mandatory] [ meta, bam_rna ] + + main: + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // NOTE(SW): channel operations will be required to configure MarkDups for individual samples + + // MarkDups + // TODO(SW): implement inputs + ch_markdups_inputs = Channel.of([[id: 'foo'], []]) + MARKDUPS( + ch_markdups_inputs, + // TODO(SW): configuration + // TODO(SW): reference files + ) + // TODO(SW): implement outputs + ch_markduplicates_dna_out = Channel.empty() + ch_markduplicates_rna_out = Channel.empty() + + emit: + dna = ch_markduplicates_dna_out // channel: [ meta, bam_dna ] + rna = ch_markduplicates_rna_out // channel: [ meta, bam_rna ] + + versions = ch_versions // channel: [ versions.yml ] +} diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 5ffa4995..5e3476d9 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -83,6 +83,8 @@ include { ORANGE_REPORTING } from '../subworkflows/local/orange_reporting' include { PAVE_ANNOTATION } from '../subworkflows/local/pave_annotation' include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' +include { READ_ALIGNMENT } from '../subworkflows/local/read_alignment' +include { READ_PROCESSING } from '../subworkflows/local/read_processing' include { SAGE_APPEND } from '../subworkflows/local/sage_append' include { SAGE_CALLING } from '../subworkflows/local/sage_calling' include { SIGS_FITTING } from '../subworkflows/local/sigs_fitting' @@ -127,6 +129,65 @@ workflow WGTS { // Set GRIDSS config gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config + // + // SUBWORKFLOW: Align reads + // + // channel: [ meta, bam_dna ] + ch_dna_alignment_out = Channel.empty() + // channel: [ meta, bam_rna ] + ch_rna_alignment_out = Channel.empty() + // TODO(SW): set up correctly + if (true | run_config.stages.alignment) { + + READ_ALIGNMENT( + ch_inputs, + // alignment reference files + ) + + ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) + + ch_dna_alignment_out = ch_dna_alignment_out.mix(READ_ALIGNMENT.out.dna) + ch_rna_alignment_out = ch_rna_alignment_out.mix(READ_ALIGNMENT.out.rna) + + } else { + + ch_dna_alignment_out = ch_inputs.map { meta -> [meta, []] } + ch_rna_alignment_out = ch_inputs.map { meta -> [meta, []] } + + } + + // + // SUBWORKFLOW: Process read alignments + // + // channel: [ meta, bam_dna ] + ch_dna_processed_out = Channel.empty() + // channel: [ meta, bam_rna ] + ch_rna_processed_out = Channel.empty() + // TODO(SW): set up correctly + if (true | run_config.stages.markdups) { + + READ_PROCESSING( + ch_inputs, + ch_dna_alignment_out, + ch_rna_alignment_out, + ) + + ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) + + ch_dna_processed_out = ch_dna_processed_out.mix(READ_PROCESSING.out.dna) + ch_rna_processed_out = ch_rna_processed_out.mix(READ_PROCESSING.out.rna) + + } else { + + ch_dna_processed_out = ch_inputs.map { meta -> [meta, []] } + ch_rna_processed_out = ch_inputs.map { meta -> [meta, []] } + + } + + // TODO(SW): adjust downstream selection of input BAM + + /* + // // MODULE: Run Isofox to analyse RNA data // @@ -714,6 +775,7 @@ workflow WGTS { CUSTOM_DUMPSOFTWAREVERSIONS( ch_versions.unique().collectFile(name: 'collated_versions.yml') ) + */ } /* From dc82ba15eddae048233eed7ae47f20a4ed3c3916 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 12 Dec 2023 10:19:05 +1100 Subject: [PATCH 268/562] Capture CHORD version info from stderr --- modules/local/chord/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf index 6e5f8e0e..818f22b4 100644 --- a/modules/local/chord/main.nf +++ b/modules/local/chord/main.nf @@ -34,8 +34,8 @@ process CHORD { cat <<-END_VERSIONS > versions.yml "${task.process}": - CHORD: \$(R -s -e "message(packageVersion('CHORD'))") - mutSigExtractor: \$(R -s -e "message(packageVersion('mutSigExtractor'))") + CHORD: \$(R -s -e "message(packageVersion('CHORD'))" 2>&1) + mutSigExtractor: \$(R -s -e "message(packageVersion('mutSigExtractor'))" 2>&1) END_VERSIONS """ From 1e67bdbd04d8133f214fe7d4ec52fba06f10f750 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 12 Dec 2023 11:16:14 +1100 Subject: [PATCH 269/562] Add note for version support --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index a2625264..1fe86a78 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,16 @@ The nf-core/oncoanalyser pipeline comes with documentation about the pipeline [usage](https://nf-co.re/oncoanalyser/usage), [parameters](https://nf-co.re/oncoanalyser/parameters) and [output](https://nf-co.re/oncoanalyser/output). +## Version support + +As oncoanalyser is used in clinical settings and is subject to accreditation standards in some instances, there is a +need for long-term stability and reliability for feature releases in order to meet operational requirements. This is +accomplished through long-term support of several nominated feature releases, which all receive bug fixes and security +fixes during the period of extended support. + +Each release that is given extended support is allocated a separate long-lived git branch with the 'stable' prefix, e.g. +`stable/1.2.x`, `stable/1.5.x`. Feature development otherwise occurs on the `main` branch. + ## Credits The oncoanalyser pipeline was written by Stephen Watts at the [University of Melbourne Centre for Cancer From 443c3877630d5ac93a326902568ad6f1cf95e078 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 12 Dec 2023 11:25:18 +1100 Subject: [PATCH 270/562] Minor changelog adjustment --- CHANGELOG.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5b610f4..09612f63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,8 @@ # nf-core/oncoanalyser: Changelog -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). +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project mostly adheres to +[Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v1.0dev - [date] +## 1.0.0 - [date] Initial release of nf-core/oncoanalyser, created with the [nf-core](https://nf-co.re/) template. - -### `Added` - -### `Fixed` - -### `Dependencies` - -### `Deprecated` From 9c17f3ba482300fac3d97fa721f2e81806d4b3af Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 12 Dec 2023 11:25:29 +1100 Subject: [PATCH 271/562] Reword introduction description --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1fe86a78..4ef27934 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ ## Introduction -**nf-core/oncoanalyser** is a Nextflow implementation of the comprehensive cancer RNA and DNA analysis and reporting -pipeline from the Hartwig Medical Foundation. For detailed information on each component of the Hartwig Medical -Foundation pipeline, please refer to [hartwigmedical/hmftools](https://github.com/hartwigmedical/hmftools/). +**nf-core/oncoanalyser** is a Nextflow implementation of the comprehensive cancer DNA and RNA analysis and reporting +workflow from the Hartwig Medical Foundation. For detailed information on each component of the Hartwig Medical +Foundation workflow, please refer to [hartwigmedical/hmftools](https://github.com/hartwigmedical/hmftools/). The oncoanalyser pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation From 6b5912b5fad4983ee8514c866308a47ec12081ee Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 31 Jan 2024 15:17:44 +1100 Subject: [PATCH 272/562] Upgrade to match hmftools v5.34 * TEAL and CIDER to be implemented in the future * ORANGE and CUPPA remain unchanged for now * MarkDups excluded --- conf/hmf_data.config | 4 +- conf/modules.config | 5 ++- conf/targeted_parameters.config | 31 +++------------ lib/Constants.groovy | 23 ++++++++--- lib/Utils.groovy | 10 +++-- modules/local/amber/Dockerfile | 9 ++++- modules/local/amber/main.nf | 9 +++-- modules/local/amber/meta.yml | 4 ++ modules/local/bamtools/Dockerfile | 2 +- modules/local/bamtools/main.nf | 4 +- modules/local/cobalt/Dockerfile | 2 +- modules/local/cobalt/main.nf | 5 +-- modules/local/cobalt/meta.yml | 2 +- modules/local/cuppa/main.nf | 3 +- modules/local/gpgr/linx/main.nf | 2 +- modules/local/gripss/Dockerfile | 2 +- modules/local/gripss/germline/main.nf | 4 +- modules/local/gripss/somatic/main.nf | 8 ++-- modules/local/gripss/somatic/meta.yml | 5 ++- modules/local/isofox/main.nf | 2 +- modules/local/lilac/Dockerfile | 2 +- modules/local/lilac/main.nf | 5 +-- modules/local/linx/Dockerfile | 2 +- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 4 +- modules/local/orange/main.nf | 2 +- modules/local/pave/Dockerfile | 2 +- modules/local/pave/germline/main.nf | 14 +++---- modules/local/pave/somatic/main.nf | 26 +++++++++---- modules/local/pave/somatic/meta.yml | 12 ++++++ modules/local/purple/Dockerfile | 2 +- modules/local/purple/main.nf | 5 +-- modules/local/purple/meta.yml | 3 +- modules/local/sage/Dockerfile | 2 +- modules/local/sage/append/main.nf | 7 ++-- modules/local/sage/germline/main.nf | 23 +++-------- modules/local/sage/somatic/main.nf | 25 ++++-------- modules/local/sigs/main.nf | 2 +- modules/local/svprep/Dockerfile | 4 +- modules/local/svprep/assemble/main.nf | 9 ++--- modules/local/svprep/call/main.nf | 9 ++--- modules/local/svprep/depth_annotator/main.nf | 5 +-- modules/local/svprep/preprocess/main.nf | 9 ++--- modules/local/svprep/svprep/main.nf | 5 +-- subworkflows/local/amber_profiling.nf | 2 + subworkflows/local/gripss_filtering.nf | 4 +- subworkflows/local/pave_annotation.nf | 41 ++++++++++++++------ subworkflows/local/sage_calling.nf | 4 +- workflows/targeted.nf | 1 + workflows/wgts.nf | 1 + 50 files changed, 196 insertions(+), 174 deletions(-) diff --git a/conf/hmf_data.config b/conf/hmf_data.config index c380b1fc..fc6cf635 100644 --- a/conf/hmf_data.config +++ b/conf/hmf_data.config @@ -2,7 +2,7 @@ params { hmf_data_paths { '37' { // AMBER - heterozygous_sites = 'dna_pipeline/copy_number/GermlineHetPon.37.vcf.gz' + heterozygous_sites = 'dna_pipeline/copy_number/AmberGermlineSites.37.tsv.gz' // COBALT gc_profile = 'dna_pipeline/copy_number/GC_profile.1000bp.37.cnp' diploid_bed = 'dna_pipeline/copy_number/DiploidRegions.37.bed.gz' @@ -53,7 +53,7 @@ params { } '38' { // AMBER - heterozygous_sites = 'dna_pipeline/copy_number/GermlineHetPon.38.vcf.gz' + heterozygous_sites = 'dna_pipeline/copy_number/AmberGermlineSites.38.tsv.gz' // COBALT gc_profile = 'dna_pipeline/copy_number/GC_profile.1000bp.38.cnp' diploid_bed = 'dna_pipeline/copy_number/DiploidRegions.38.bed.gz' diff --git a/conf/modules.config b/conf/modules.config index c5896588..bb63d00e 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -13,7 +13,7 @@ process { withName: 'AMBER' { - ext.jarPath = '/opt/conda/share/hmftools-amber-3.9-1/amber.jar' + ext.jarPath = '/opt/amber/amber.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -39,7 +39,8 @@ process { } withName: '.*:GRIDSS_SVPREP_CALLING:(?:PREPROCESS|ASSEMBLE|CALL)' { - ext.jarPath = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' + ext.jarPathGridss = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' + ext.jarPathSvPrep = '/opt/svprep/svprep.jar' ext.otherJvmHeap = 4.GB } diff --git a/conf/targeted_parameters.config b/conf/targeted_parameters.config index 661237dd..bb4899e7 100644 --- a/conf/targeted_parameters.config +++ b/conf/targeted_parameters.config @@ -1,31 +1,10 @@ -process.'withName:^.*:AMBER_PROFILING:AMBER'.ext.args = [ - '-tumor_only_min_depth 80', -].join(' ').trim() - process.'withName:^.*:COBALT_PROFILING:COBALT'.ext.args = [ - '-pcf_gamma 15', + '-pcf_gamma 50', ].join(' ').trim() process.'withName:^.*:SAGE_CALLING:SOMATIC'.ext.args = [ - '-hard_min_tumor_vaf 0.005', - '-hotspot_min_tumor_vaf 0.01', - '-hotspot_min_tumor_qual 100', - '-panel_min_tumor_qual 250', - '-high_confidence_min_tumor_qual 350', - '-low_confidence_min_tumor_qual 500', - '-max_read_depth 100000', - '-sync_fragments', -].join(' ').trim() - -process.'withName:^.*:GRIPSS_FILTERING:SOMATIC'.ext.args = [ - '-hard_min_tumor_qual 200', - '-min_qual_break_point 1000', - '-min_qual_break_end 1000', -].join(' ').trim() - -process.'withName:^.*:PURPLE_CALLING:PURPLE'.ext.args = [ - '-min_diploid_tumor_ratio_count 3', - '-min_diploid_tumor_ratio_count_centromere 3', - '-ploidy_penalty_factor 0.6', - '-ploidy_penalty_standard_deviation 0.15', + '-high_depth_mode', + '-hard_min_tumor_vaf 0.002', + '-hotspot_min_tumor_vaf 0.015', + '-panel_min_tumor_qual 150', ].join(' ').trim() diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 10474f62..83c04d30 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -11,14 +11,14 @@ class Constants { static List PANELS_DEFINED = ['hmf', 'tso500'] - static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.33_37--0.tar.gz' - static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.33_38--0.tar.gz' + static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_37--0.tar.gz' + static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_38--0.tar.gz' static String HMF_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/hmf_5.33_38--0.tar.gz' - static String TSO500_PANEL_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.33_37--1.tar.gz' - static String TSO500_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.33_38--1.tar.gz' + static String TSO500_PANEL_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_37--0.tar.gz' + static String TSO500_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_38--0.tar.gz' static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' @@ -75,6 +75,7 @@ class Constants { PAVE_VCF, PURPLE_DIR, SAGE_VCF, + SAGE_VCF_TBI, SAGE_APPEND_VCF, VIRUSINTERPRETER_DIR, // ORANGE specific @@ -152,6 +153,16 @@ class Constants { SampleType.NORMAL, SequenceType.DNA, ], + SAGE_VCF_TBI_TUMOR: [ + FileType.SAGE_VCF_TBI, + SampleType.TUMOR, + SequenceType.DNA, + ], + SAGE_VCF_TBI_NORMAL: [ + FileType.SAGE_VCF_TBI, + SampleType.NORMAL, + SequenceType.DNA, + ], SAGE_DIR_TUMOR: [ FileType.SAGE_DIR, SampleType.TUMOR, @@ -165,12 +176,12 @@ class Constants { SAGE_APPEND_VCF_TUMOR: [ FileType.SAGE_APPEND_VCF, SampleType.TUMOR, - [SequenceType.DNA_RNA], + SequenceType.DNA_RNA, ], SAGE_APPEND_VCF_NORMAL: [ FileType.SAGE_APPEND_VCF, SampleType.NORMAL, - [SequenceType.DNA_RNA], + SequenceType.DNA_RNA, ], PAVE_VCF_TUMOR: [ diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 0e6eab11..af7ef5c9 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -73,7 +73,6 @@ class Utils { // Record sample key to simplify iteration later on sample_keys << sample_key - } // Check that required indexes are provided or are accessible @@ -91,13 +90,16 @@ class Utils { index_str = 'bai' } else if (key === Constants.FileType.GRIDSS_VCF) { index_enum = Constants.FileType.GRIDSS_VCF_TBI - index_str = 'vcf' + index_str = 'tbi' } else if (key === Constants.FileType.GRIPSS_VCF) { index_enum = Constants.FileType.GRIPSS_VCF_TBI - index_str = 'vcf' + index_str = 'tbi' } else if (key === Constants.FileType.GRIPSS_UNFILTERED_VCF) { index_enum = Constants.FileType.GRIPSS_UNFILTERED_VCF_TBI - index_str = 'vcf' + index_str = 'tbi' + } else if (key === Constants.FileType.SAGE_VCF) { + index_enum = Constants.FileType.SAGE_VCF_TBI + index_str = 'tbi' } else { return } diff --git a/modules/local/amber/Dockerfile b/modules/local/amber/Dockerfile index 45967ed2..87daec07 100644 --- a/modules/local/amber/Dockerfile +++ b/modules/local/amber/Dockerfile @@ -4,15 +4,20 @@ USER root RUN \ apt-get update && \ - apt-get install -y procps && \ + apt-get install -y procps wget && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* +RUN \ + mkdir -p /opt/amber/ && \ + wget -O /opt/amber/amber.jar 'https://github.com/hartwigmedical/hmftools/releases/download/amber-v4.0.rc1/amber_v4.0.rc1.jar' + USER mambauser RUN \ micromamba install -y -n base -c bioconda -c conda-forge \ - 'hmftools-amber==3.9' \ + bioconductor-copynumber \ + 'openjdk >=8' \ r-dplyr && \ micromamba clean --all --yes diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index 07d3a0f8..8765862b 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -2,12 +2,13 @@ process AMBER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/amber:3.9--3' + container 'docker.io/scwatts/amber:4.0.rc1--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) val ref_genome_ver path heterozygous_sites + path target_region_bed output: tuple val(meta), path('amber/'), emit: amber_dir @@ -22,6 +23,8 @@ process AMBER { def reference_arg = meta.containsKey('normal_id') ? "-reference ${meta.normal_id}" : '' def reference_bam_arg = normal_bam ? "-reference_bam ${normal_bam}" : '' + def target_regions_bed_arg = target_region_bed ? "-target_regions_bed ${target_region_bed}" : '' + """ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ @@ -31,15 +34,15 @@ process AMBER { -tumor_bam ${tumor_bam} \\ ${reference_arg} \\ ${reference_bam_arg} \\ + ${target_regions_bed_arg} \\ -ref_genome_version ${ref_genome_ver} \\ -loci ${heterozygous_sites} \\ -threads ${task.cpus} \\ -output_dir amber/ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - amber: 3.9 + amber: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/amber/meta.yml b/modules/local/amber/meta.yml index 824f7a4b..dbc5fc90 100644 --- a/modules/local/amber/meta.yml +++ b/modules/local/amber/meta.yml @@ -38,6 +38,10 @@ input: type: file description: AMBER heterozygous sites file pattern: "*.{vcf.gz}" + - target_region_bed: + type: file + description: Target region BED file (optional) + pattern: "*.{bed}" output: - meta: type: map diff --git a/modules/local/bamtools/Dockerfile b/modules/local/bamtools/Dockerfile index ef221d50..61ae054b 100644 --- a/modules/local/bamtools/Dockerfile +++ b/modules/local/bamtools/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/bamtools/ && \ - wget -O /opt/bamtools/bamtools.jar 'https://github.com/hartwigmedical/hmftools/releases/download/bam-tools-v1.1/bam-tools_v1.1.jar' + wget -O /opt/bamtools/bamtools.jar 'https://github.com/hartwigmedical/hmftools/releases/download/bam-tools-v1.2/bam-tools_v1.2.jar' USER mambauser diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf index c34cbaf0..fba57d83 100644 --- a/modules/local/bamtools/main.nf +++ b/modules/local/bamtools/main.nf @@ -2,7 +2,7 @@ process BAMTOOLS { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/bamtools:1.1--0' + container 'docker.io/scwatts/bamtools:1.2--0' input: tuple val(meta), path(bam), path(bai) @@ -35,7 +35,7 @@ process BAMTOOLS { cat <<-END_VERSIONS > versions.yml "${task.process}": - bamtools: \$(java -jar ${task.ext.jarPath} 2>&1 | sed -n '1s/^.*BamTools version: //p') + bamtools: \$(java -jar ${task.ext.jarPath} | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/cobalt/Dockerfile b/modules/local/cobalt/Dockerfile index b7b4bd32..817dd838 100644 --- a/modules/local/cobalt/Dockerfile +++ b/modules/local/cobalt/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/cobalt/ && \ - wget -O /opt/cobalt/cobalt.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cobalt-v1.15.2/cobalt_v1.15.2.jar' + wget -O /opt/cobalt/cobalt.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cobalt-v1.16.rc1/cobalt_v1.16.rc1.jar' USER mambauser diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index 52fa6bda..673cdbed 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -2,7 +2,7 @@ process COBALT { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/cobalt:1.15.2--0' + container 'docker.io/scwatts/cobalt:1.16.rc1--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -41,10 +41,9 @@ process COBALT { ${target_region_arg} \\ -output_dir cobalt/ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - cobalt: 1.15.2 + cobalt: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/cobalt/meta.yml b/modules/local/cobalt/meta.yml index 3b75d01c..61812410 100644 --- a/modules/local/cobalt/meta.yml +++ b/modules/local/cobalt/meta.yml @@ -43,7 +43,7 @@ input: - target_region_normalisation: type: file description: Normalisation file (optional) - pattern: "*.{bed.gz}" + pattern: "*.{tsv}" output: - meta: type: map diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index 0a4ff2e3..b4ea02a3 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -59,10 +59,9 @@ process CUPPA { -output_dir cuppa/; fi - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - cuppa: 1.8.1 + cuppa: \$(java -jar ${task.ext.jarPath} | sed -n '1s/^.* //p') END_VERSIONS """ diff --git a/modules/local/gpgr/linx/main.nf b/modules/local/gpgr/linx/main.nf index 48eec890..af78e438 100644 --- a/modules/local/gpgr/linx/main.nf +++ b/modules/local/gpgr/linx/main.nf @@ -2,7 +2,7 @@ process GPGR_LINX { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/gpgr:1.4.5' + container 'docker.io/scwatts/gpgr:1.5.0' input: tuple val(meta), path(linx_annotation_dir), path(linx_visualiser_dir) diff --git a/modules/local/gripss/Dockerfile b/modules/local/gripss/Dockerfile index 69a2d666..f4053ecb 100644 --- a/modules/local/gripss/Dockerfile +++ b/modules/local/gripss/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/gripss/ && \ - wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.3.5/gripss_v2.3.5.jar' + wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.4.rc1/gripss_v2.4.rc1.jar' USER mambauser diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 540044bd..d95fd691 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -2,7 +2,7 @@ process GRIPSS_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.3.5--0' + container 'docker.io/scwatts/gripss:2.4.rc1--0' input: tuple val(meta), path(gridss_vcf) @@ -45,7 +45,7 @@ process GRIPSS_GERMLINE { cat <<-END_VERSIONS > versions.yml "${task.process}": - gripss: \$(java -jar ${task.ext.jarPath} | sed -n '1s/^.*version: //p') + gripss: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index 991ac057..c361a770 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -2,7 +2,7 @@ process GRIPSS_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.3.5--0' + container 'docker.io/scwatts/gripss:2.4.rc1--0' input: tuple val(meta), path(gridss_vcf) @@ -13,7 +13,7 @@ process GRIPSS_SOMATIC { path pon_breakpoints path known_fusions path repeatmasker_annotations - path target_regions_bed + path target_region_bed output: tuple val(meta), path('*.gripss.filtered{,.somatic}.vcf.gz'), path('*.gripss.filtered{,.somatic}.vcf.gz.tbi'), emit: vcf @@ -27,7 +27,7 @@ process GRIPSS_SOMATIC { def args = task.ext.args ?: '' def reference_arg = meta.containsKey('normal_id') ? "-reference ${meta.normal_id}" : '' - def target_regions_bed_arg = target_regions_bed ? "-target_regions_bed ${target_regions_bed}" : '' + def target_regions_bed_arg = target_region_bed ? "-target_regions_bed ${target_region_bed}" : '' def output_id_arg = meta.containsKey('normal_id') ? '-output_id somatic' : '' """ @@ -50,7 +50,7 @@ process GRIPSS_SOMATIC { cat <<-END_VERSIONS > versions.yml "${task.process}": - gripss: \$(java -jar ${task.ext.jarPath} | sed -n '1s/^.*version: //p') + gripss: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/gripss/somatic/meta.yml b/modules/local/gripss/somatic/meta.yml index ee959724..171a8d0b 100644 --- a/modules/local/gripss/somatic/meta.yml +++ b/modules/local/gripss/somatic/meta.yml @@ -46,9 +46,10 @@ input: - repeatmasker_annotations: type: file description: RepeatMasker annotations file - - target_regions_bed: + - target_region_bed: type: file - description: Target regions BED file (optional) + description: Target region BED file (optional) + pattern: "*.{bed}" output: - meta: type: map diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 9d215d1c..50456928 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -58,7 +58,7 @@ process ISOFOX { cat <<-END_VERSIONS > versions.yml "${task.process}": - isofox: \$(java -jar ${task.ext.jarPath} | sed -n '1s/^.*version: //p') + isofox: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/lilac/Dockerfile b/modules/local/lilac/Dockerfile index d3c643bf..a3617e53 100644 --- a/modules/local/lilac/Dockerfile +++ b/modules/local/lilac/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/lilac/ && \ - wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.5.2/lilac_v1.5.2.jar' + wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.6.rc1/lilac_v1.6.rc1.jar' USER mambauser diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index cc6bfb88..14d97b03 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -2,7 +2,7 @@ process LILAC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/lilac:1.5.2--1' + container 'docker.io/scwatts/lilac:1.6.rc1--0' input: tuple val(meta), path(normal_dna_bam), path(normal_dna_bai), path(tumor_dna_bam), path(tumor_dna_bai), path(tumor_rna_bam), path(tumor_rna_bai), path(purple_dir) @@ -43,10 +43,9 @@ process LILAC { -threads ${task.cpus} \\ -output_dir lilac/ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - lilac: 1.5 + lilac: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/linx/Dockerfile b/modules/local/linx/Dockerfile index b5d68ae9..a7f3935f 100644 --- a/modules/local/linx/Dockerfile +++ b/modules/local/linx/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/linx/ && \ - wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.24.1/linx_v1.24.1.jar' + wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.25/linx_v1.25.jar' USER mambauser diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index ad973b55..c4cd676f 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,7 +2,7 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.24.1--0' + container 'docker.io/scwatts/linx:1.25--0' input: tuple val(meta), path(purple_dir) diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index b9bf4672..dcd56fc1 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,7 +2,7 @@ process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/linx:1.24.1--0' + container 'docker.io/scwatts/linx:1.25--0' input: tuple val(meta), path(linx_annotation_dir) @@ -50,7 +50,7 @@ process LINX_VISUALISER { -circos ${task.ext.circosPath} \\ -threads ${task.cpus} \\ -plot_out plots/all/ \\ - -data_out reportable/all_data/ + -data_out data/all/ # Rerun LINX to render only reportable cluster plots in a separate directory. While this is regenerating existing # cluster plots, the number of reportable plots is generally very small and I prefer to rely on the internal LINX diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index 1f9cd177..b5f015d9 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -139,7 +139,7 @@ process ORANGE { cat <<-END_VERSIONS > versions.yml "${task.process}": - orange: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.*version //') + orange: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/pave/Dockerfile b/modules/local/pave/Dockerfile index 3e20e721..a52a4303 100644 --- a/modules/local/pave/Dockerfile +++ b/modules/local/pave/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/pave/ && \ - wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.5/pave_v1.5.jar' + wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.6/pave_v1.6.jar' USER mambauser diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 2948b716..941ec61c 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -1,15 +1,15 @@ // NOTE(SW): use of tumor sample name here is consistent with Pipeline5 -// - https://github.com/hartwigmedical/pipeline5/blob/v5.32/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveGermline.java#L35-L39 -// - https://github.com/hartwigmedical/pipeline5/blob/v5.32/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L34-L44 +// - https://github.com/hartwigmedical/pipeline5/blob/v5.33/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveGermline.java#L36-L41 +// - https://github.com/hartwigmedical/pipeline5/blob/v5.33/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L31-L43 process PAVE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.5--0' + container 'docker.io/scwatts/pave:1.6--0' input: - tuple val(meta), path(sage_vcf) + tuple val(meta), path(sage_vcf), path(sage_tbi) path genome_fasta val genome_ver path genome_fai @@ -35,7 +35,7 @@ process PAVE_GERMLINE { if (genome_ver == '37') { gnomad_args = "-gnomad_freq_file ${gnomad_resource}" } else if (genome_ver == '38') { - gnomad_args = "-gnomad_freq_dir ${gnomad_resource} -gnomad_load_chr_on_demand" + gnomad_args = "-gnomad_freq_dir ${gnomad_resource}" } else { log.error "got bad genome version: ${genome_ver}" System.exit(1) @@ -59,12 +59,12 @@ process PAVE_GERMLINE { -gnomad_pon_filter -1 \\ ${gnomad_args} \\ -read_pass_only \\ + -threads ${task.cpus} \\ -output_dir ./ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: 1.5 + pave: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 2fe372eb..bad69a56 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -2,15 +2,18 @@ process PAVE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.5--0' + container 'docker.io/scwatts/pave:1.6--0' input: - tuple val(meta), path(sage_vcf) + tuple val(meta), path(sage_vcf), path(sage_tbi) path genome_fasta val genome_ver path genome_fai path sage_pon path pon_artefacts + path sage_blocklist_regions + path sage_blocklist_sites + path clinvar_annotations path segment_mappability path driver_gene_panel path ensembl_data_resources @@ -27,8 +30,6 @@ process PAVE_SOMATIC { script: def args = task.ext.args ?: '' - def pon_artefact_arg = pon_artefacts ? "-pon_artefact_file ${pon_artefacts}" : '' - def pon_filters def gnomad_args if (genome_ver == '37') { @@ -36,12 +37,19 @@ process PAVE_SOMATIC { gnomad_args = "-gnomad_freq_file ${gnomad_resource}" } else if (genome_ver == '38') { pon_filters = 'HOTSPOT:5:5;PANEL:2:5;UNKNOWN:2:0' - gnomad_args = "-gnomad_freq_dir ${gnomad_resource} -gnomad_load_chr_on_demand" + gnomad_args = "-gnomad_freq_dir ${gnomad_resource}" } else { log.error "got bad genome version: ${genome_ver}" System.exit(1) } + // Targetted mode + def pon_artefact_arg = pon_artefacts ? "-pon_artefact_file ${pon_artefacts}" : '' + def pathogenic_pass_force_arg = pon_artefacts ? '-force_pathogenic_pass': '' + def sage_blocklist_regions_arg = sage_blocklist_regions ? "-blacklist_bed ${sage_blocklist_regions}" : '' + def sage_blocklist_sites_arg = sage_blocklist_sites ? "-blacklist_vcf ${sage_blocklist_sites}" : '' + def clinvar_annotations = clinvar_annotations ? "-clinvar_vcf ${clinvar_annotations}" : '' + """ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ @@ -53,17 +61,21 @@ process PAVE_SOMATIC { -pon_file ${sage_pon} \\ -pon_filters "${pon_filters}" \\ ${pon_artefact_arg} \\ + ${clinvar_annotations} \\ -driver_gene_panel ${driver_gene_panel} \\ -mappability_bed ${segment_mappability} \\ -ensembl_data_dir ${ensembl_data_resources} \\ + ${sage_blocklist_regions_arg} \\ + ${sage_blocklist_sites_arg} \\ + ${pathogenic_pass_force_arg} \\ ${gnomad_args} \\ -read_pass_only \\ + -threads ${task.cpus} \\ -output_dir ./ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: 1.5 + pave: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/pave/somatic/meta.yml b/modules/local/pave/somatic/meta.yml index 2d695c08..97aa6729 100644 --- a/modules/local/pave/somatic/meta.yml +++ b/modules/local/pave/somatic/meta.yml @@ -41,6 +41,18 @@ input: - pon_artefacts: type: file description: Taregeted sequencing PON artefacts file (optional) + - sage_blocklist_regions: + type: file + description: SAGE regions blocklist file + pattern: "*.{bed}" + - sage_blocklist_sites: + type: file + description: SAGE sites blocklist file + pattern: "*.{vcf.gz}" + - clinvar_annotations: + type: file + description: ClinVar annotations VCF file + pattern: "*.{vcf.gz}" - segment_mappability: type: file description: Segment mappability file diff --git a/modules/local/purple/Dockerfile b/modules/local/purple/Dockerfile index 54c6eba0..66f81ad7 100644 --- a/modules/local/purple/Dockerfile +++ b/modules/local/purple/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/purple/ && \ - wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v3.9.2/purple_v3.9.2.jar' + wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v4.0.rc1/purple_v4.0.rc1.jar' USER mambauser diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 2e58e43d..a888ec59 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -2,7 +2,7 @@ process PURPLE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/purple:3.9.2--0' + container 'docker.io/scwatts/purple:4.0.rc1--0' input: tuple val(meta), path(amber), path(cobalt), path(sv_tumor_vcf), path(sv_tumor_tbi), path(sv_tumor_unfiltered_vcf), path(sv_tumor_unfiltered_tbi), path(sv_normal_vcf), path(sv_normal_tbi), path(smlv_tumor_vcf), path(smlv_normal_vcf) @@ -76,10 +76,9 @@ process PURPLE { -threads ${task.cpus} \\ -output_dir purple/ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - purple: 3.9 + purple: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/purple/meta.yml b/modules/local/purple/meta.yml index 9c55dea9..3a027a82 100644 --- a/modules/local/purple/meta.yml +++ b/modules/local/purple/meta.yml @@ -94,9 +94,10 @@ input: type: file description: Cohort frequency for germline deletions (optional) pattern: "*.{csv}" - - target_regions_bed: + - target_region_bed: type: file description: Target regions BED file (optional) + pattern: "*.{bed}" - target_regions_ratios: type: file description: Target regions ratios file (optional) diff --git a/modules/local/sage/Dockerfile b/modules/local/sage/Dockerfile index 12cb9430..c76db363 100644 --- a/modules/local/sage/Dockerfile +++ b/modules/local/sage/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/sage/ && \ - wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.3.1/sage_v3.3.1.jar' + wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.4.rc1/sage_v3.4.rc1.jar' USER mambauser diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index 80962310..0ce8aca1 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -2,7 +2,7 @@ process SAGE_APPEND { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.3.1--0' + container 'docker.io/scwatts/sage:3.4.rc1--0' input: tuple val(meta), path(vcf), path(bam), path(bai) @@ -32,12 +32,11 @@ process SAGE_APPEND { -ref_genome ${genome_fasta} \\ -ref_genome_version ${genome_ver} \\ -threads ${task.cpus} \\ - -out ${meta.dna_id}.sage.append.vcf.gz + -output_vcf ${meta.dna_id}.sage.append.vcf.gz - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: 3.3 + sage: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 126df42c..6c813acd 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -2,7 +2,7 @@ process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.3.1--0' + container 'docker.io/scwatts/sage:3.4.rc1--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -17,10 +17,9 @@ process SAGE_GERMLINE { path ensembl_data_resources output: - tuple val(meta), path('germline/*.sage.germline.vcf.gz'), path('germline/*.sage.germline.vcf.gz.tbi') , emit: vcf - tuple val(meta), path('germline/*.sage.germline.filtered.vcf.gz'), path('germline/*.sage.germline.filtered.vcf.gz.tbi'), emit: vcf_filtered - tuple val(meta), path('germline/') , emit: sage_dir - path 'versions.yml' , emit: versions + tuple val(meta), path('germline/*.sage.germline.vcf.gz'), path('germline/*.sage.germline.vcf.gz.tbi'), emit: vcf + tuple val(meta), path('germline/') , emit: sage_dir + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -57,19 +56,11 @@ process SAGE_GERMLINE { -write_bqr_data \\ -write_bqr_plot \\ -threads ${task.cpus} \\ - -out germline/${meta.tumor_id}.sage.germline.vcf.gz + -output_vcf germline/${meta.tumor_id}.sage.germline.vcf.gz - bcftools view \\ - -f 'PASS' \\ - -o germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz \\ - germline/${meta.tumor_id}.sage.germline.vcf.gz - - bcftools index -t germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz - - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: 3.3 + sage: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ @@ -78,8 +69,6 @@ process SAGE_GERMLINE { mkdir -p germline/ touch germline/${meta.tumor_id}.sage.germline.vcf.gz touch germline/${meta.tumor_id}.sage.germline.vcf.gz.tbi - touch germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz - touch germline/${meta.tumor_id}.sage.germline.filtered.vcf.gz.tbi touch germline/${meta.tumor_id}.sage.bqr.png touch germline/${meta.tumor_id}.sage.bqr.tsv touch germline/${meta.normal_id}.sage.bqr.png diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 2ae53af1..8d8286e8 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -1,10 +1,10 @@ -// NOTE(SW): logic that determines BQR outputs assumes '-out' is a path that includes at least leading one directory +// NOTE(SW): logic that determines BQR outputs assumes '-output_vcf' is a path that includes at least leading one directory process SAGE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.3.1--0' + container 'docker.io/scwatts/sage:3.4.rc1--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -19,10 +19,9 @@ process SAGE_SOMATIC { path ensembl_data_resources output: - tuple val(meta), path('somatic/*.sage.somatic.vcf.gz'), path('somatic/*.sage.somatic.vcf.gz.tbi') , emit: vcf - tuple val(meta), path('somatic/*.sage.somatic.filtered.vcf.gz'), path('somatic/*.sage.somatic.filtered.vcf.gz.tbi'), emit: vcf_filtered - tuple val(meta), path('somatic/') , emit: sage_dir - path 'versions.yml' , emit: versions + tuple val(meta), path('somatic/*.sage.somatic.vcf.gz'), path('somatic/*.sage.somatic.vcf.gz.tbi'), emit: vcf + tuple val(meta), path('somatic/') , emit: sage_dir + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -54,19 +53,11 @@ process SAGE_SOMATIC { -write_bqr_data \\ -write_bqr_plot \\ -threads ${task.cpus} \\ - -out somatic/${meta.tumor_id}.sage.somatic.vcf.gz + -output_vcf somatic/${meta.tumor_id}.sage.somatic.vcf.gz - bcftools view \\ - -f 'PASS' \\ - -o somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz \\ - somatic/${meta.tumor_id}.sage.somatic.vcf.gz - - bcftools index -t somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz - - # NOTE(SW): hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: 3.3 + sage: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ @@ -75,8 +66,6 @@ process SAGE_SOMATIC { mkdir -p somatic/ touch somatic/${meta.tumor_id}.sage.somatic.vcf.gz touch somatic/${meta.tumor_id}.sage.somatic.vcf.gz.tbi - touch somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz - touch somatic/${meta.tumor_id}.sage.somatic.filtered.vcf.gz.tbi touch somatic/${meta.tumor_id}.gene.coverage.tsv touch somatic/${meta.tumor_id}.sage.bqr.png touch somatic/${meta.tumor_id}.sage.bqr.tsv diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 9603739b..9e99de58 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -29,7 +29,7 @@ process SIGS { -signatures_file ${signatures} \\ -output_dir sigs/ - # NOTE(SW): hard coded since there is no reliable way to obtain version information. + # NOTE(SW): version not available at CLI cat <<-END_VERSIONS > versions.yml "${task.process}": sigs: 1.1 diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile index 1b7d1712..d330cc15 100644 --- a/modules/local/svprep/Dockerfile +++ b/modules/local/svprep/Dockerfile @@ -11,8 +11,8 @@ RUN \ RUN \ mkdir -p /opt/svprep/ && \ - wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.2.2/sv-prep_v1.2.2.jar' && \ - wget -O /opt/svprep/gridss_svprep 'https://raw.githubusercontent.com/hartwigmedical/hmftools/sv-prep-v1.2.2/sv-prep/src/main/resources/gridss/gridss.run.sh' + wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.2.3/sv-prep_v1.2.3.jar' && \ + wget -O /opt/svprep/gridss_svprep 'https://raw.githubusercontent.com/hartwigmedical/hmftools/sv-prep-v1.2.3/sv-prep/src/main/resources/gridss/gridss.run.sh' COPY assets/gridss_svprep.patch /tmp/ RUN \ diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 2048e28c..2bda4d80 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -2,7 +2,7 @@ process GRIDSS_ASSEMBLE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.2--0' + container 'docker.io/scwatts/svprep:1.2.3--0' input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) @@ -68,7 +68,7 @@ process GRIDSS_ASSEMBLE { ${args} \\ --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ - --jar ${task.ext.jarPath} \\ + --jar ${task.ext.jarPathGridss} \\ --steps assemble \\ --labels ${labels_arg} \\ --reference ${genome_fasta} \\ @@ -80,11 +80,10 @@ process GRIDSS_ASSEMBLE { ${bams_arg} \\ ${bams_filtered_arg} - # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - svprep: 1.2.1 + gridss: \$(java -cp ${task.ext.jarPathGridss} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + svprep: \$(java -jar ${task.ext.jarPathSvPrep} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index e2327e71..5ed13ce6 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -2,7 +2,7 @@ process GRIDSS_CALL { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.2--0' + container 'docker.io/scwatts/svprep:1.2.3--0' input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) @@ -66,7 +66,7 @@ process GRIDSS_CALL { ${args} \\ --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ - --jar ${task.ext.jarPath} \\ + --jar ${task.ext.jarPathGridss} \\ --steps call \\ --labels ${labels_arg} \\ --reference ${genome_fasta} \\ @@ -79,11 +79,10 @@ process GRIDSS_CALL { ${bams_arg} \\ ${bams_filtered_arg} - # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - svprep: 1.2.1 + gridss: \$(java -cp ${task.ext.jarPathGridss} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + svprep: \$(java -jar ${task.ext.jarPathSvPrep} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index b1a9a1fe..5103bbdb 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -2,7 +2,7 @@ process SVPREP_DEPTH_ANNOTATOR { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.2--0' + container 'docker.io/scwatts/svprep:1.2.3--0' input: tuple val(meta), path(bams), path(bais), path(vcf), val(labels) @@ -38,10 +38,9 @@ process SVPREP_DEPTH_ANNOTATOR { -threads ${task.cpus} \\ -output_vcf ${meta.tumor_id}.gridss.vcf.gz - # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - svprep: 1.2.1 + svprep: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 25e7ac4c..ac7a598a 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -2,7 +2,7 @@ process GRIDSS_PREPROCESS { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.2--0' + container 'docker.io/scwatts/svprep:1.2.3--0' input: tuple val(meta), path(bam), path(bam_filtered) @@ -32,7 +32,7 @@ process GRIDSS_PREPROCESS { gridss_svprep \\ ${args} \\ --jvmheap ${Math.round(task.memory.bytes * 0.95)} \\ - --jar ${task.ext.jarPath} \\ + --jar ${task.ext.jarPathGridss} \\ --steps preprocess \\ --reference ${genome_fasta} \\ --workingdir gridss_preprocess/ \\ @@ -43,11 +43,10 @@ process GRIDSS_PREPROCESS { --filtered_bams ${bam_filtered} \\ --output placeholder - # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - svprep: 1.2.1 + gridss: \$(java -cp ${task.ext.jarPathGridss} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + svprep: \$(java -jar ${task.ext.jarPathSvPrep} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 7e30835c..09cc5751 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -2,7 +2,7 @@ process SVPREP { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.2--0' + container 'docker.io/scwatts/svprep:1.2.3--0' input: tuple val(meta), path(bam), path(bai), path(junctions) @@ -47,10 +47,9 @@ process SVPREP { -o ${meta.sample_id}.sv_prep.sorted.bam \\ ${meta.sample_id}.sv_prep.bam - # NOTE(SW): partially hard coded since there is no reliable way to obtain version information. cat <<-END_VERSIONS > versions.yml "${task.process}": - svprep: 1.2.1 + svprep: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index d2988105..f20a3d24 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -15,6 +15,7 @@ workflow AMBER_PROFILING { // Reference data genome_version // channel: [mandatory] genome version heterozygous_sites // channel: [optional] /path/to/heterozygous_sites + target_region_bed // channel: [optional] /path/to/target_region_bed main: // Channel for version.yml files @@ -63,6 +64,7 @@ workflow AMBER_PROFILING { ch_amber_inputs, genome_version, heterozygous_sites, + target_region_bed, ) ch_versions = ch_versions.mix(AMBER.out.versions) diff --git a/subworkflows/local/gripss_filtering.nf b/subworkflows/local/gripss_filtering.nf index 845a0aa4..7913be75 100644 --- a/subworkflows/local/gripss_filtering.nf +++ b/subworkflows/local/gripss_filtering.nf @@ -22,7 +22,7 @@ workflow GRIPSS_FILTERING { breakpoint_pon // channel: [mandatory] /path/to/breakpoint_pon known_fusions // channel: [mandatory] /path/to/known_fusions repeatmasker_annotations // channel: [mandatory] /path/to/repeatmasker_annotations - target_regions_bed // channel: [optional] /path/to/target_regions_bed + target_region_bed // channel: [optional] /path/to/target_region_bed main: // Channel for version.yml files @@ -134,7 +134,7 @@ workflow GRIPSS_FILTERING { breakpoint_pon, known_fusions, repeatmasker_annotations, - target_regions_bed, + target_region_bed, ) ch_versions = ch_versions.mix(SOMATIC.out.versions) diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf index 54039413..98bbd273 100644 --- a/subworkflows/local/pave_annotation.nf +++ b/subworkflows/local/pave_annotation.nf @@ -37,16 +37,17 @@ workflow PAVE_ANNOTATION { // MODULE: PAVE germline // // Select input sources and sort - // channel: runnable: [ meta, sage_vcf ] + // channel: runnable: [ meta, sage_vcf, sage_tbi ] // channel: skip: [ meta ] ch_sage_germline_inputs_sorted = ch_sage_germline_vcf .map { meta, sage_vcf, sage_tbi -> return [ meta, Utils.selectCurrentOrExisting(sage_vcf, meta, Constants.INPUT.SAGE_VCF_NORMAL), + Utils.selectCurrentOrExisting(sage_tbi, meta, Constants.INPUT.SAGE_VCF_TBI_NORMAL), ] } - .branch { meta, sage_vcf -> + .branch { meta, sage_vcf, sage_tbi -> def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PAVE_VCF_NORMAL) @@ -56,9 +57,9 @@ workflow PAVE_ANNOTATION { } // Create process input channel - // channel: [ meta_pave, sage_vcf ] + // channel: [ meta_pave, sage_vcf, sage_tbi ] ch_pave_germline_inputs = ch_sage_germline_inputs_sorted.runnable - .map { meta, sage_vcf -> + .map { meta, sage_vcf, sage_tbi -> def meta_pave = [ key: meta.group_id, @@ -66,7 +67,7 @@ workflow PAVE_ANNOTATION { sample_id: Utils.getTumorDnaSampleName(meta), ] - return [meta_pave, sage_vcf] + return [meta_pave, sage_vcf, sage_tbi] } // Run process @@ -90,16 +91,17 @@ workflow PAVE_ANNOTATION { // MODULE: PAVE somatic // // Select input sources and sort - // channel: runnable: [ meta, sage_vcf ] + // channel: runnable: [ meta, sage_vcf, sage_tbi ] // channel: skip: [ meta ] ch_sage_somatic_inputs_sorted = ch_sage_somatic_vcf .map { meta, sage_vcf, sage_tbi -> return [ meta, Utils.selectCurrentOrExisting(sage_vcf, meta, Constants.INPUT.SAGE_VCF_TUMOR), + Utils.selectCurrentOrExisting(sage_tbi, meta, Constants.INPUT.SAGE_VCF_TBI_TUMOR), ] } - .branch { meta, sage_vcf -> + .branch { meta, sage_vcf, sage_tbi -> def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PAVE_VCF_TUMOR) @@ -109,9 +111,9 @@ workflow PAVE_ANNOTATION { } // Create process input channel - // channel: [ meta_pave, sage_vcf ] + // channel: [ meta_pave, sage_vcf, sage_tbi ] ch_pave_somatic_inputs = ch_sage_somatic_inputs_sorted.runnable - .map { meta, sage_vcf -> + .map { meta, sage_vcf, sage_tbi -> def meta_pave = [ key: meta.group_id, @@ -119,9 +121,23 @@ workflow PAVE_ANNOTATION { sample_id: Utils.getTumorDnaSampleName(meta), ] - return [meta_pave, sage_vcf] + return [meta_pave, sage_vcf, sage_tbi] } + // Set resource files according to run mode + // NOTE(SW): required since certain files can be used in germline and somatic depending on mode + // but want to avoid duplicating as multiple inputs + // NOTE(SW): this pattern should be used only sparingly; implicit config from workflows is prefered + sage_blocklist_regions_somatic = sage_blocklist_regions + sage_blocklist_sites_somatic = sage_blocklist_sites + clinvar_annotations_somatic = clinvar_annotations + run_mode = Utils.getEnumFromString(params.mode, Constants.RunMode) + if (run_mode === Constants.RunMode.WGTS) { + sage_blocklist_regions_somatic = [] + sage_blocklist_sites_somatic = [] + clinvar_annotations_somatic = [] + } + // Run process SOMATIC( ch_pave_somatic_inputs, @@ -130,6 +146,9 @@ workflow PAVE_ANNOTATION { genome_fai, sage_pon, pon_artefacts, + sage_blocklist_regions_somatic, + sage_blocklist_sites_somatic, + clinvar_annotations_somatic, segment_mappability, driver_gene_panel, ensembl_data_resources, @@ -139,7 +158,7 @@ workflow PAVE_ANNOTATION { ch_versions = ch_versions.mix(SOMATIC.out.versions) // Set outputs, restoring original meta - // channel: [ meta, gripss_vcf, gripss_tbi ] + // channel: [ meta, pave_vcf ] ch_somatic_out = Channel.empty() .mix( WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index 188511a6..f0bf1c9c 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -170,7 +170,7 @@ workflow SAGE_CALLING { // channel: [ meta, sage_vcf, sage_tbi ] ch_somatic_vcf_out = Channel.empty() .mix( - WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_filtered, ch_inputs), + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), ch_inputs_somatic_sorted.skip.map { meta -> [meta, [], []] }, ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, ) @@ -178,7 +178,7 @@ workflow SAGE_CALLING { // channel: [ meta, sage_vcf, sage_tbi ] ch_germline_vcf_out = Channel.empty() .mix( - WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_filtered, ch_inputs), + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), ch_inputs_germline_sorted.skip.map { meta -> [meta, [], []] }, ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, ) diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 7c605ac6..2951bbba 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -171,6 +171,7 @@ workflow TARGETED { ch_inputs, ref_data.genome_version, hmf_data.heterozygous_sites, + panel_data.target_region_bed, ) ch_versions = ch_versions.mix(AMBER_PROFILING.out.versions) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 27f437f6..e84f224b 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -172,6 +172,7 @@ workflow WGTS { ch_inputs, ref_data.genome_version, hmf_data.heterozygous_sites, + [], // target_region_bed ) ch_versions = ch_versions.mix(AMBER_PROFILING.out.versions) From b039219adf2c39a1d8e9fdddbc08182ea7892ed9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 1 Feb 2024 11:45:58 +1100 Subject: [PATCH 273/562] Remove HMF targeted panel --- conf/panel_data.config | 15 --------------- lib/Constants.groovy | 4 +--- lib/WorkflowMain.groovy | 11 +---------- 3 files changed, 2 insertions(+), 28 deletions(-) diff --git a/conf/panel_data.config b/conf/panel_data.config index 33ac6ad8..dbb979ce 100644 --- a/conf/panel_data.config +++ b/conf/panel_data.config @@ -2,21 +2,6 @@ params { panel_data_paths { - hmf { - - '38' { - driver_gene_panel = 'common/DriverGenePanel.38.tsv' - sage_actionable_panel = 'variants/ActionableCodingPanel.38.bed.gz' - sage_coverage_panel = 'variants/CoverageCodingPanel.38.bed.gz' - pon_artefacts = 'variants/PanelArtefacts.38.tsv' - target_region_bed = 'copy_number/target_regions_definition.38.bed' - target_region_normalisation = 'copy_number/target_regions_normalisation.38.tsv' - target_region_ratios = 'copy_number/target_regions_ratios.38.tsv' - target_region_msi_indels = 'copy_number/target_regions_msi_indels.38.tsv' - } - - } - tso500 { '37' { diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 83c04d30..8f2eb1fd 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -8,15 +8,13 @@ class Constants { static List GENOMES_SUPPORTED = ['GRCh37_hmf', 'GRCh38_hmf'] static List GENOMES_DEFINED = Constants.GENOMES_VERSION_37 + Constants.GENOMES_VERSION_38 - static List PANELS_DEFINED = ['hmf', 'tso500'] + static List PANELS_DEFINED = ['tso500'] static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_37--0.tar.gz' static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_38--0.tar.gz' - static String HMF_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/hmf_5.33_38--0.tar.gz' - static String TSO500_PANEL_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_37--0.tar.gz' static String TSO500_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_38--0.tar.gz' diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 9b101849..9bd6a46b 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -144,9 +144,7 @@ class WorkflowMain { // Attempt to set default panel data path; make no assumption on valid 'panel' value if (!params.containsKey('ref_data_panel_data_path') && params.containsKey('panel')) { - if (params.panel == 'hmf' && params.ref_data_genome_version == '38') { - params.ref_data_panel_data_path = Constants.HMF_PANEL_38_PATH - } else if (params.panel == 'tso500' && params.ref_data_genome_version == '37') { + if (params.panel == 'tso500' && params.ref_data_genome_version == '37') { params.ref_data_panel_data_path = Constants.TSO500_PANEL_37_PATH } else if (params.panel == 'tso500' && params.ref_data_genome_version == '38') { params.ref_data_panel_data_path = Constants.TSO500_PANEL_38_PATH @@ -297,13 +295,6 @@ class WorkflowMain { } - if (params.panel == 'hmf' && params.ref_data_genome_version == '37') { - log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " The Hartwig panel (hmf) is not available for the GRCh37 reference genome.\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - } } From 614233257caee6e0e1d291a830b00c015db66117 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 1 Feb 2024 11:14:05 +1100 Subject: [PATCH 274/562] Enforce use of unique identifiers for samples --- lib/Utils.groovy | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index af7ef5c9..8078b1a7 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -189,6 +189,21 @@ class Utils { System.exit(1) } + // Enforce unique samples names within groups + def sample_ids_duplicated = sample_keys + .groupBy { meta.getOrDefault(it, [:]).getOrDefault('sample_id', null) } + .findResults { k, v -> k !== null & v.size() > 1 ? [k, v] : null } + + if (sample_ids_duplicated) { + def duplicate_message_strs = sample_ids_duplicated.collect { sample_id, keys -> + def key_strs = keys.collect { sample_type, sequence_type -> "${sample_type}/${sequence_type}" } + return " * ${sample_id}: ${key_strs.join(", ")}" + } + log.error "duplicate sample names found for ${meta.group_id}:\n\n" + + "${duplicate_message_strs.join("\n")}" + System.exit(1) + } + } } From 850e2a7a928e1682727a2bff8e6752d50f6d9025 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 1 Feb 2024 12:11:11 +1100 Subject: [PATCH 275/562] Remove unneeded SAMtools flagstat container config --- conf/modules.config | 3 --- 1 file changed, 3 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index bb63d00e..4bf35427 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -236,9 +236,6 @@ process { } withName: 'SAMTOOLS_FLAGSTAT' { - container = { "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.12--h9aed4be_1' : - 'quay.io/biocontainers/samtools:1.12--h9aed4be_1' }" } publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, From 5beecc77a2dfff298a56b56f0bb5c4e289f1be68 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 2 Feb 2024 08:49:44 +1100 Subject: [PATCH 276/562] Update hmftools version string in ORANGE --- subworkflows/local/orange_reporting.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/orange_reporting.nf b/subworkflows/local/orange_reporting.nf index c250cdc0..13e4eb2c 100644 --- a/subworkflows/local/orange_reporting.nf +++ b/subworkflows/local/orange_reporting.nf @@ -232,7 +232,7 @@ workflow ORANGE_REPORTING { ensembl_data_resources, ch_orange_inputs.isofox_alt_sj, ch_orange_inputs.isofox_gene_distribution, - "5.33 [oncoanalyser]", + "5.34 [oncoanalyser]", ) ch_versions = ch_versions.mix(ORANGE.out.versions) From 11057dd80310bb69b1f5afd64b4d517e2557e96c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 7 Feb 2024 11:13:56 +1100 Subject: [PATCH 277/562] Switch some software from RCs to full releases Also update to Sig 1.2. Release candidate switch list: * AMBER * COBALT * GRIPSS * LILAC * PURPLE * SAGE --- modules/local/amber/Dockerfile | 2 +- modules/local/amber/main.nf | 2 +- modules/local/cobalt/Dockerfile | 2 +- modules/local/cobalt/main.nf | 2 +- modules/local/gripss/Dockerfile | 2 +- modules/local/gripss/germline/main.nf | 2 +- modules/local/gripss/somatic/main.nf | 2 +- modules/local/lilac/Dockerfile | 2 +- modules/local/lilac/main.nf | 2 +- modules/local/purple/Dockerfile | 2 +- modules/local/purple/main.nf | 2 +- modules/local/sage/Dockerfile | 2 +- modules/local/sage/append/main.nf | 2 +- modules/local/sage/germline/main.nf | 2 +- modules/local/sage/somatic/main.nf | 2 +- modules/local/sigs/Dockerfile | 2 +- modules/local/sigs/main.nf | 5 ++--- 17 files changed, 18 insertions(+), 19 deletions(-) diff --git a/modules/local/amber/Dockerfile b/modules/local/amber/Dockerfile index 87daec07..3cce34d7 100644 --- a/modules/local/amber/Dockerfile +++ b/modules/local/amber/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/amber/ && \ - wget -O /opt/amber/amber.jar 'https://github.com/hartwigmedical/hmftools/releases/download/amber-v4.0.rc1/amber_v4.0.rc1.jar' + wget -O /opt/amber/amber.jar 'https://github.com/hartwigmedical/hmftools/releases/download/amber-v4.0/amber_v4.0.jar' USER mambauser diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index 8765862b..25d6ac97 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -2,7 +2,7 @@ process AMBER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/amber:4.0.rc1--0' + container 'docker.io/scwatts/amber:4.0--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/cobalt/Dockerfile b/modules/local/cobalt/Dockerfile index 817dd838..6e2eb4d1 100644 --- a/modules/local/cobalt/Dockerfile +++ b/modules/local/cobalt/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/cobalt/ && \ - wget -O /opt/cobalt/cobalt.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cobalt-v1.16.rc1/cobalt_v1.16.rc1.jar' + wget -O /opt/cobalt/cobalt.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cobalt-v1.16/cobalt_v1.16.jar' USER mambauser diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index 673cdbed..30ae20be 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -2,7 +2,7 @@ process COBALT { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/cobalt:1.16.rc1--0' + container 'docker.io/scwatts/cobalt:1.16--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/gripss/Dockerfile b/modules/local/gripss/Dockerfile index f4053ecb..26b56bca 100644 --- a/modules/local/gripss/Dockerfile +++ b/modules/local/gripss/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/gripss/ && \ - wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.4.rc1/gripss_v2.4.rc1.jar' + wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.4/gripss_v2.4.jar' USER mambauser diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index d95fd691..6bce8f76 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -2,7 +2,7 @@ process GRIPSS_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.4.rc1--0' + container 'docker.io/scwatts/gripss:2.4--0' input: tuple val(meta), path(gridss_vcf) diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index c361a770..3ec6339f 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -2,7 +2,7 @@ process GRIPSS_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.4.rc1--0' + container 'docker.io/scwatts/gripss:2.4--0' input: tuple val(meta), path(gridss_vcf) diff --git a/modules/local/lilac/Dockerfile b/modules/local/lilac/Dockerfile index a3617e53..7c37c81c 100644 --- a/modules/local/lilac/Dockerfile +++ b/modules/local/lilac/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/lilac/ && \ - wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.6.rc1/lilac_v1.6.rc1.jar' + wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.6/lilac_v1.6.jar' USER mambauser diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 14d97b03..004fa1e4 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -2,7 +2,7 @@ process LILAC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/lilac:1.6.rc1--0' + container 'docker.io/scwatts/lilac:1.6--0' input: tuple val(meta), path(normal_dna_bam), path(normal_dna_bai), path(tumor_dna_bam), path(tumor_dna_bai), path(tumor_rna_bam), path(tumor_rna_bai), path(purple_dir) diff --git a/modules/local/purple/Dockerfile b/modules/local/purple/Dockerfile index 66f81ad7..330a907f 100644 --- a/modules/local/purple/Dockerfile +++ b/modules/local/purple/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/purple/ && \ - wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v4.0.rc1/purple_v4.0.rc1.jar' + wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v4.0/purple_v4.0.jar' USER mambauser diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index a888ec59..a2ab0243 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -2,7 +2,7 @@ process PURPLE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/purple:4.0.rc1--0' + container 'docker.io/scwatts/purple:4.0--0' input: tuple val(meta), path(amber), path(cobalt), path(sv_tumor_vcf), path(sv_tumor_tbi), path(sv_tumor_unfiltered_vcf), path(sv_tumor_unfiltered_tbi), path(sv_normal_vcf), path(sv_normal_tbi), path(smlv_tumor_vcf), path(smlv_normal_vcf) diff --git a/modules/local/sage/Dockerfile b/modules/local/sage/Dockerfile index c76db363..f680ee98 100644 --- a/modules/local/sage/Dockerfile +++ b/modules/local/sage/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/sage/ && \ - wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.4.rc1/sage_v3.4.rc1.jar' + wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.4/sage_v3.4.jar' USER mambauser diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index 0ce8aca1..0d392603 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -2,7 +2,7 @@ process SAGE_APPEND { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.4.rc1--0' + container 'docker.io/scwatts/sage:3.4--0' input: tuple val(meta), path(vcf), path(bam), path(bai) diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 6c813acd..fe110f2d 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -2,7 +2,7 @@ process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.4.rc1--0' + container 'docker.io/scwatts/sage:3.4--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 8d8286e8..3b545943 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -4,7 +4,7 @@ process SAGE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.4.rc1--0' + container 'docker.io/scwatts/sage:3.4--0' input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/sigs/Dockerfile b/modules/local/sigs/Dockerfile index 6e0fb67b..323ac17f 100644 --- a/modules/local/sigs/Dockerfile +++ b/modules/local/sigs/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/sigs/ && \ - wget -O /opt/sigs/sigs.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sigs-v1.1/sigs_v1.1.jar + wget -O /opt/sigs/sigs.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sigs-v1.2/sigs_v1.2.jar' USER mambauser diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 9e99de58..5fe7647d 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -2,7 +2,7 @@ process SIGS { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/sigs:1.1--0' + container 'docker.io/scwatts/sigs:1.2--0' input: tuple val(meta), path(smlv_vcf) @@ -29,10 +29,9 @@ process SIGS { -signatures_file ${signatures} \\ -output_dir sigs/ - # NOTE(SW): version not available at CLI cat <<-END_VERSIONS > versions.yml "${task.process}": - sigs: 1.1 + sigs: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') END_VERSIONS """ From 00cb9b29bd851ed6794522b36ded3755ae374bf5 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 7 Feb 2024 12:50:55 +1100 Subject: [PATCH 278/562] Bump Sigs to 1.2.1 --- modules/local/sigs/Dockerfile | 2 +- modules/local/sigs/main.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/sigs/Dockerfile b/modules/local/sigs/Dockerfile index 323ac17f..33961024 100644 --- a/modules/local/sigs/Dockerfile +++ b/modules/local/sigs/Dockerfile @@ -10,7 +10,7 @@ RUN \ RUN \ mkdir -p /opt/sigs/ && \ - wget -O /opt/sigs/sigs.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sigs-v1.2/sigs_v1.2.jar' + wget -O /opt/sigs/sigs.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sigs-v1.2.1/sigs_v1.2.1.jar' USER mambauser diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 5fe7647d..47971e67 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -2,7 +2,7 @@ process SIGS { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/sigs:1.2--0' + container 'docker.io/scwatts/sigs:1.2.1--0' input: tuple val(meta), path(smlv_vcf) From 4e92135a6694542d0c98dd0f4f13afc69c26be91 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Sun, 11 Feb 2024 12:49:47 +1100 Subject: [PATCH 279/562] Initial implementation of alignment workflow. --- lib/Constants.groovy | 14 ++ lib/Utils.groovy | 89 +++++++- modules/local/bwa/Dockerfile | 9 + modules/local/bwa/mem/main.nf | 54 +++++ modules/local/fastp/Dockerfile | 8 + modules/local/fastp/main.nf | 38 ++++ modules/local/markdups/Dockerfile | 12 ++ modules/local/markdups/main.nf | 91 ++++++-- modules/local/sambamba/Dockerfile | 8 + modules/local/sambamba/index/main.nf | 23 ++ subworkflows/local/alignment.nf | 305 +++++++++++++++++++++++++++ temp/genomes_GRCh37_hmf.config | 17 ++ workflows/targeted.nf | 2 + workflows/wgts.nf | 103 +++++---- 14 files changed, 707 insertions(+), 66 deletions(-) create mode 100644 modules/local/bwa/Dockerfile create mode 100644 modules/local/bwa/mem/main.nf create mode 100644 modules/local/fastp/Dockerfile create mode 100644 modules/local/fastp/main.nf create mode 100644 modules/local/markdups/Dockerfile create mode 100644 modules/local/sambamba/Dockerfile create mode 100644 modules/local/sambamba/index/main.nf create mode 100644 subworkflows/local/alignment.nf create mode 100644 temp/genomes_GRCh37_hmf.config diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 8f2eb1fd..f3fc958b 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -34,21 +34,26 @@ class Constants { } static enum Process { + // TODO[MC]: Add process here. + BWAMEM, AMBER, BAMTOOLS, CHORD, COBALT, CUPPA, + FASTP, FLAGSTAT, GRIDSS, GRIPSS, ISOFOX, LILAC, LINX, + MARKDUPS, ORANGE, PAVE, PURPLE, SAGE, + SAMBAMBA_INDEX, SIGS, VIRUSINTERPRETER, } @@ -57,6 +62,9 @@ class Constants { // Generic BAM, BAI, + BAM_MARKDUPS, + BAI_MARKDUPS, + FASTQ, // Process AMBER_DIR, BAMTOOLS, @@ -97,9 +105,15 @@ class Constants { DNA_RNA, } + static List DNA_SAMPLE_KEYS = [ + [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], + [Constants.SampleType.NORMAL, Constants.SequenceType.DNA], + ] + static Map PLACEHOLDER_META = [meta_placeholder: null] static List PLACEHOLDER_OPTIONAL_CHANNEL = [] + // TODO(MC): How is this used? static Map INPUT = [ ISOFOX_DIR: [ diff --git a/lib/Utils.groovy b/lib/Utils.groovy index cf2b1e0a..a3adb2cb 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -88,6 +88,9 @@ class Utils { if (key === Constants.FileType.BAM) { index_enum = Constants.FileType.BAI index_str = 'bai' + } else if (key === Constants.FileType.BAM_MARKDUPS) { + index_enum = Constants.FileType.BAI_MARKDUPS + index_str = 'bai' } else if (key === Constants.FileType.GRIDSS_VCF) { index_enum = Constants.FileType.GRIDSS_VCF_TBI index_str = 'tbi' @@ -177,7 +180,7 @@ class Utils { inputs.each { meta -> - // Require BAMs for each defined sample type + // Require BAMs or BAM_MARKDUPs or FASTQs for each defined sample type // NOTE(SW): repeating key pairs above to avoid having to duplicate error messages sample_keys.each { key -> @@ -187,9 +190,12 @@ class Utils { def (sample_type, sequence_type) = key - if (!meta[key].containsKey(Constants.FileType.BAM)) { - log.error "no BAM provided for ${meta.group_id} ${sample_type}/${sequence_type}\n\n" + - "NB: BAMs are always required as they are the basis to determine input sample type." + if (!meta[key].containsKey(Constants.FileType.BAM) && + !meta[key].containsKey(Constants.FileType.BAM_MARKDUPS) && + !meta[key].containsKey(Constants.FileType.FASTQ)) { + + log.error "no BAMs nor BAM_MARKDUPs nor FASTQs provided for ${meta.group_id} ${sample_type}/${sequence_type}\n\n" + + "NB: BAMs or BAM_MARKDUPs or FASTQs are always required as they are the basis to determine input sample type." System.exit(1) } @@ -367,6 +373,49 @@ class Utils { return getNormalDnaBam(meta) !== null } + static public getNormalDnaMarkdupsBam(meta) { + def meta_sample = meta.getOrDefault([Constants.SampleType.NORMAL, Constants.SequenceType.DNA], [:]) + return meta_sample.getOrDefault(Constants.FileType.BAM_MARKDUPS, null) + } + + static public hasNormalDnaMarkdupsBam(meta) { + return getNormalDnaMarkdupsBam(meta) !== null + } + + static public getTumorDnaMarkdupsBam(meta) { + def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.DNA], [:]) + return meta_sample.getOrDefault(Constants.FileType.BAM_MARKDUPS, null) + } + + static public hasTumorDnaMarkdupsBam(meta) { + return getTumorDnaMarkdupsBam(meta) !== null + } + + static public hasDnaMarkdupsBam(meta) { + return hasNormalDnaMarkdupsBam(meta) || hasTumorDnaMarkdupsBam(meta) + } + + static public getNormalDnaFastq(meta) { + def meta_sample = meta.getOrDefault([Constants.SampleType.NORMAL, Constants.SequenceType.DNA], [:]) + return meta_sample.getOrDefault(Constants.FileType.FASTQ, null) + } + + static public hasNormalDnaFastq(meta) { + return getNormalDnaFastq(meta) !== null + } + + static public getTumorDnaFastq(meta) { + def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.DNA], [:]) + return meta_sample.getOrDefault(Constants.FileType.FASTQ, null) + } + + static public hasTumorDnaFastq(meta) { + return getTumorDnaFastq(meta) !== null + } + + static public hasDnaFastq(meta) { + return hasNormalDnaFastq(meta) || hasTumorDnaFastq(meta) + } static public getRunMode(run_mode, log) { def run_mode_enum = Utils.getEnumFromString(run_mode, Constants.RunMode) @@ -404,4 +453,36 @@ class Utils { } } + // Alignment utils. + static public splitGroupIntoSamples(meta_group) { + def sample_entries = [:] + def common_entries = [:] + meta_group.each { key, value -> + + if ((value instanceof java.util.Map) && value.containsKey('sample_id')) { + sample_entries[key] = value + } else { + common_entries[key] = value + } + } + + def meta_samples = [] + sample_entries.each { key, value -> + + def meta_sample = common_entries.getClass().newInstance(common_entries) + meta_sample[key] = value + meta_samples.add(meta_sample) + } + + return meta_samples + } + + static public readGroupFromFastqPath(fastq_path) { + def base_name = fastq_path.split('/')[-1] + def pattern = /^(.+)_\d+\.fastq$/ + def matcher = base_name =~ pattern + assert matcher.find() + return matcher[0][1] + } + } diff --git a/modules/local/bwa/Dockerfile b/modules/local/bwa/Dockerfile new file mode 100644 index 00000000..2172ebc4 --- /dev/null +++ b/modules/local/bwa/Dockerfile @@ -0,0 +1,9 @@ +FROM docker.io/continuumio/miniconda3:23.10.0-1 + +RUN \ + conda install -y -n base conda-libmamba-solver && \ + conda config --set solver libmamba && \ + conda install -y -c bioconda -c conda-forge -c conda \ + 'bwa==0.7.17' \ + 'sambamba==1.0' && \ + conda clean -yaf diff --git a/modules/local/bwa/mem/main.nf b/modules/local/bwa/mem/main.nf new file mode 100644 index 00000000..428d1ce9 --- /dev/null +++ b/modules/local/bwa/mem/main.nf @@ -0,0 +1,54 @@ +// TODO(MC): BWA MEM2: Need docker and resource files. + +process BWA_MEM { + tag "${meta.id}" + + // TODO(MC): What process label? + // label 'process_medium' + + container 'docker.io/scwatts/bwa:0.7.17-sambamba' + + input: + tuple val(meta), path(reads_fwd), path(reads_rev) + path genome_fasta + path genome_bwa_index + + output: + tuple val(meta), path('*bam'), emit: bam + + // TODO(MC): How does this work? + when: + task.ext.when == null || task.ext.when + + // # TODO(MC): read group + // # -R ${meta.read_group} + + script: + """ + ln -s \$(find -L ${genome_bwa_index} -type f) ./ + + bwa mem \\ + -Y \\ + -t ${task.cpus} \\ + ${genome_fasta} \\ + ${reads_fwd} \\ + ${reads_rev} | \\ + \\ + sambamba view \\ + --sam-input \\ + --format bam \\ + --compression-level 0 \\ + --nthreads ${task.cpus} \\ + /dev/stdin | \\ + \\ + sambamba sort \\ + --nthreads ${task.cpus} \\ + --out ${meta.split}.${meta.sample_id}.${meta.read_group}.bam \\ + /dev/stdin + """ + + stub: + """ + touch ${meta.split}.${meta.sample_id}.${meta.read_group}.bam + """ +} diff --git a/modules/local/fastp/Dockerfile b/modules/local/fastp/Dockerfile new file mode 100644 index 00000000..5d7cdbf9 --- /dev/null +++ b/modules/local/fastp/Dockerfile @@ -0,0 +1,8 @@ +FROM docker.io/continuumio/miniconda3:23.10.0-1 + +RUN \ + conda install -y -n base conda-libmamba-solver && \ + conda config --set solver libmamba && \ + conda install -y -c bioconda -c conda-forge -c conda \ + 'fastp==0.23.4' && \ + conda clean -yaf diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf new file mode 100644 index 00000000..8deec567 --- /dev/null +++ b/modules/local/fastp/main.nf @@ -0,0 +1,38 @@ +process FASTP { + tag "${meta.id}" + + // TODO(MC): Resources? + + container 'docker.io/scwatts/fastp:0.23.4' + + input: + tuple val(meta), path(reads_fwd), path(reads_rev) + + output: + tuple val(meta), path('*_R1.fastp.fastq'), path('*_R2.fastp.fastq'), emit: fastq + + script: + // TODO(MC): UMI flags + // --umi \\ + // --umi_loc per_read \\ + // --umi_len 7 \\ + // --umi_skip 1 \\ + + """ + # * do not apply trimming/clipping, already done in BCL convert + + fastp \\ + --in1 ${reads_fwd} \\ + --in2 ${reads_rev} \\ + --disable_adapter_trimming \\ + --split_by_lines 40000000 \\ + --out1 ${meta.sample_id}_${meta.read_group}_R1.fastp.fastq \\ + --out2 ${meta.sample_id}_${meta.read_group}_R2.fastp.fastq + """ + + stub: + """ + touch 00{1..4}.${meta.sample_id}_${meta.read_group}_R1.fastp.fastq + touch 00{1..4}.${meta.sample_id}_${meta.read_group}_R2.fastp.fastq + """ +} diff --git a/modules/local/markdups/Dockerfile b/modules/local/markdups/Dockerfile new file mode 100644 index 00000000..d7232f05 --- /dev/null +++ b/modules/local/markdups/Dockerfile @@ -0,0 +1,12 @@ +FROM docker.io/continuumio/miniconda3:23.10.0-1 + +RUN \ + conda install -y -n base conda-libmamba-solver && \ + conda config --set solver libmamba && \ + conda install -y -c bioconda -c conda-forge -c conda \ + 'sambamba==1.0' 'samtools==1.17' 'openjdk >=8' && \ + conda clean -yaf + +RUN \ + mkdir -p /opt/markdups/ && \ + wget -O /opt/markdups/markdups.jar 'https://github.com/hartwigmedical/hmftools/releases/download/mark-dups-v1.1/mark-dups_v1.1.rc1.jar' diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index ea02ed90..7a25e728 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -1,38 +1,89 @@ process MARKDUPS { - tag "${meta.id}" - label 'process_low' + tag "${meta_bam.id}" - // TODO(SW): create container - //container 'foo' + // TODO(MC): Resources required? + // label 'process_low' + + container 'docker.io/scwatts/markdups:1.1.rc1' input: - tuple val(meta), path(bam) + tuple val(meta_bam), path(bams), path(bais) + path genome_fasta + path genome_fai + path genome_dict + path unmap_regions output: - // TODO(SW): set outputs - tuple val(meta), path('bar'), emit: bam - path 'versions.yml' , emit: versions + tuple val(meta_bam), path('*bam'), path('*bai'), emit: bam + path '*.tsv' + // TODO(MC): Make sure this is in each. when: task.ext.when == null || task.ext.when - script: - def args = task.ext.args ?: '' + // TODO(MC): Versions in each. + // path 'versions.yml' , emit: versions - // TODO(SW): implement process - """ - echo bar + // script: + // def args = task.ext.args ?: '' + + // // TODO(SW): implement process + // """ + // echo bar + + // cat <<-END_VERSIONS > versions.yml + // "${task.process}": + // markdups: foo + // END_VERSIONS + // """ - cat <<-END_VERSIONS > versions.yml - "${task.process}": - markdups: foo - END_VERSIONS + // stub: + // // TODO(SW): implement stub + // """ + // touch bar + // echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + // """ + + // # TODO(MC): Umi flags + // # -multi_bam \\ + // # -umi_enabled \\ + // # -umi_duplex \\ + // # -umi_duplex_delim _ \\ + // # -umi_base_diff_stats \\ + + script: + """ + java \\ + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + -jar /opt/markdups/markdups.jar \\ + \\ + -samtools \$(which samtools) \\ + -sambamba \$(which sambamba) \\ + \\ + -sample ${meta_bam.sample_id} \\ + -input_bam ${bams.join(',')} \\ + \\ + -form_consensus \\ + \\ + -unmap_regions ${unmap_regions} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version 37 \\ + \\ + -write_stats \\ + -threads 16 \\ + \\ + -output_bam ${meta_bam.sample_id}.mark_dups.bam """ stub: - // TODO(SW): implement stub """ - touch bar - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + touch ${meta_bam.sample_id}.mark_dups.bam + touch ${meta_bam.sample_id}.mark_dups.bam.bai + touch ${meta_bam.sample_id}.duplicate_freq.tsv """ + + // # TODO(MC): + // # touch ${meta_bam.sample_id}.umi_coord_freq.tsv + // # touch ${meta_bam.sample_id}.umi_edit_distance.tsv + // # touch ${meta_bam.sample_id}.umi_nucleotide_freq.tsv } diff --git a/modules/local/sambamba/Dockerfile b/modules/local/sambamba/Dockerfile new file mode 100644 index 00000000..8c2c38c5 --- /dev/null +++ b/modules/local/sambamba/Dockerfile @@ -0,0 +1,8 @@ +FROM docker.io/continuumio/miniconda3:23.10.0-1 + +RUN \ + conda install -y -n base conda-libmamba-solver && \ + conda config --set solver libmamba && \ + conda install -y -c bioconda -c conda-forge -c conda \ + 'sambamba==1.0' && \ + conda clean -yaf diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf new file mode 100644 index 00000000..f6cf00ea --- /dev/null +++ b/modules/local/sambamba/index/main.nf @@ -0,0 +1,23 @@ +process SAMBAMBA_INDEX { + tag "${meta.id}" + + container 'docker.io/scwatts/sambamba:1.0' + + input: + tuple val(meta), path(bam) + + output: + tuple val(meta), path(bam), path('*bai'), emit: bam + + script: + """ + sambamba index \\ + --nthreads ${task.cpus} \\ + ${meta.split}.${meta.sample_id}.${meta.read_group}.bam + """ + + stub: + """ + touch ${meta.split}.${meta.sample_id}.${meta.read_group}.bam.bai + """ +} diff --git a/subworkflows/local/alignment.nf b/subworkflows/local/alignment.nf new file mode 100644 index 00000000..4b34ac29 --- /dev/null +++ b/subworkflows/local/alignment.nf @@ -0,0 +1,305 @@ +include { BWA_MEM } from '../../modules/local/bwa/mem/main' +include { MARKDUPS } from '../../modules/local/markdups/main' +include { FASTP } from '../../modules/local/fastp/main' +include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' + +workflow ALIGNMENT { + take: + ch_inputs // channel: [ meta ] + genome_fasta + genome_fai + genome_dict + genome_bwa_index + unmap_regions + max_fastq_lines + + main: + // channel: [ meta ] (One sample per record). + ch_meta_samples = ch_inputs.flatMap { meta -> Utils.splitGroupIntoSamples(meta) } + + // Sort inputs + // channel: [ meta ] (One sample per record). + ch_meta_samples_sorted = ch_meta_samples + .branch { meta -> + runnable_fastq: Utils.hasDnaFastq(meta) + runnable_markdups: Utils.hasDnaMarkdupsBam(meta) + skip: true + } + + // TODO(MC): Simplify this branch. + if (max_fastq_lines > 0) { + // Split fastq files using fastp. + + // Create fastp process input channel. + // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] + ch_fastp_inputs = ch_meta_samples_sorted.runnable_fastq + .flatMap { meta -> + + def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } + if (sample_key === null) { + log.error "No DNA sample found" + System.exit(1) + } + + def sample_id = meta[sample_key]['sample_id'] + def fastq_files = meta[sample_key][Constants.FileType.FASTQ].tokenize(';') + + // TODO(MC): Validate fastq_files. + + def meta_fastq_common = [:] + meta.each { key, value -> + + + if (key === sample_key) { + return + } + + meta_fastq_common[key] = meta[key] + } + meta_fastq_common['sample_key'] = sample_key + meta_fastq_common['sample_id'] = sample_id + + def fastq_pairs = [] + for (i = 0; i < fastq_files.size(); i += 2) { + def reads_fwd = fastq_files[i] + def reads_rev = fastq_files[i + 1] + + def meta_fastq = meta_fastq_common.getClass().newInstance(meta_fastq_common) + meta_fastq['read_group'] = Utils.readGroupFromFastqPath(reads_fwd) + + fastq_pairs.add([meta_fastq, reads_fwd, reads_rev]) + } + + fastq_pairs + } + + FASTP(ch_fastp_inputs) + + // TODO(MC): See WISP implementation. + // Create inputs for bwa mem. + // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] + ch_bwa_mem_inputs = FASTP.out.fastq.flatMap { fastq -> + + def meta = fastq[0] + def fwd_reads = fastq[1] + def rev_reads = fastq[2] + + // Pair up the reads. + def read_pairs = [:] + fwd_reads.each { fastq_path -> + + def base_name = fastq_path.getFileName().toString() + def pattern = /^(\d+)\.(.+)_R[12]\.fastp\.fastq$/ + def matcher = base_name =~ pattern + assert matcher.find() + def split = matcher[0][1] + def key = "${split}.${matcher[0][2]}" + assert !read_pairs.containsKey(key) + read_pairs[key] = [split, fastq_path] + } + + rev_reads.each { fastq_path -> + + def base_name = fastq_path.getFileName().toString() + def pattern = /^(.+)_R[12]\.fastp\.fastq$/ + def matcher = base_name =~ pattern + assert matcher.find() + def key = matcher[0][1] + assert read_pairs.containsKey(key) + read_pairs[key].add(fastq_path) + } + + def fastqs = [] + read_pairs.values().each { split_fastq_pair -> + + meta_fastq = meta.getClass().newInstance(meta) + meta_fastq['split'] = split_fastq_pair[0] + + fastqs.add([meta_fastq, split_fastq_pair[1], split_fastq_pair[2]]) + } + + fastqs + } + } else { + + // Skip splitting fastq files using fastp. + + // Create inputs for bwa mem. + // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] + ch_bwa_mem_inputs = ch_meta_samples_sorted.runnable_fastq + .flatMap { meta -> + + def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } + if (sample_key === null) { + log.error "No DNA sample found" + System.exit(1) + } + + def sample_id = meta[sample_key]['sample_id'] + def fastq_files = meta[sample_key][Constants.FileType.FASTQ].tokenize(';') + + // TODO(MC): Validate fastq_files. + + def meta_fastq_common = [:] + meta.each { key, value -> + + + if (key === sample_key) { + return + } + + meta_fastq_common[key] = meta[key] + } + meta_fastq_common['sample_key'] = sample_key + meta_fastq_common['sample_id'] = sample_id + + def fastq_pairs = [] + for (i = 0; i < fastq_files.size(); i += 2) { + def reads_fwd = fastq_files[i] + def reads_rev = fastq_files[i + 1] + + def meta_fastq = meta_fastq_common.getClass().newInstance(meta_fastq_common) + meta_fastq['read_group'] = Utils.readGroupFromFastqPath(reads_fwd) + meta_fastq['split'] = '000' + + fastq_pairs.add([meta_fastq, reads_fwd, reads_rev]) + } + + fastq_pairs + } + } + + // channel: [ meta_fastq, bam ] + BWA_MEM( + ch_bwa_mem_inputs, + genome_fasta, + genome_bwa_index, + ) + + // channel: [ meta_fastq, bam, bai ] + SAMBAMBA_INDEX( + BWA_MEM.out.bam, + ) + + // Prepare input to markdups process. + // First we prepare a channel of inputs that have gone through alignment. + // channel: [ meta_bam, bams, bais ] + ch_fastq_markdups_inputs = SAMBAMBA_INDEX.out.bam + .map { bam -> // Strip read groups and splits. + + def meta = bam[0] + def meta_bam = [:] + meta.keySet().each { key -> + + if (key == 'read_group' || key == 'split') { + return + } + + meta_bam[key] = meta[key] + } + + [meta_bam, [meta_bam, bam[1], bam[2]]] + } + .groupTuple() + .map { key_lane_bams -> + def lane_bams = key_lane_bams[1] + def meta_bam = lane_bams[0][0] + def bams = [] + def bais = [] + lane_bams.each { lane_bam -> + + bams.add(lane_bam[1]) + bais.add(lane_bam[2]) + } + + [meta_bam, bams, bais] + } + + // Next we prepare channel for markdups input that started of as aligned bams. + // channel: [ meta, bams, bais ] (One sample per meta record). + ch_input_markdups_inputs = ch_meta_samples_sorted.runnable_markdups.map { meta -> + + def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } + if (sample_key === null) { + log.error "No DNA sample found" + System.exit(1) + } + + def sample_id = meta[sample_key]['sample_id'] + def bam = meta[sample_key][Constants.FileType.BAM_MARKDUPS] + def bai = meta[sample_key][Constants.FileType.BAI_MARKDUPS] + + def meta_bam = meta.getClass().newInstance(meta); + meta_bam['sample_key'] = sample_key + meta_bam['sample_id'] = sample_id + + [meta_bam, [bam], [bai]] + } + + // Merging the two markdups input channels. + // channel: [ meta_bam, bams, bais ] + ch_markdups_inputs = Channel.empty() + .mix( + ch_fastq_markdups_inputs, + ch_input_markdups_inputs, + ) + + // channel: [ meta_bam, bam, bai ] + MARKDUPS( + ch_markdups_inputs, + genome_fasta, + genome_fai, + genome_dict, + unmap_regions, + ) + + // Fill the sample information back in. + // channel: [ meta ] (One sample per meta record). + ch_bam_samples = MARKDUPS.out.bam.map { bam -> + + def meta_bam = bam[0] + + // TODO(MC): Safer to copy and delete unneeded fields. + def meta = [ + group_id: meta_bam.group_id, + subject_id: meta_bam.subject_id, + ] + + sample = [sample_id: meta_bam.sample_id] + sample[Constants.FileType.BAM] = bam[1] + sample[Constants.FileType.BAI] = bam[2] + meta[meta.sample_key] = sample + + meta + } + + // Merge back in skipped meta entries. + // channel: [ meta ] (One sample per meta record). + ch_all_samples = Channel.empty() + .mix( + ch_bam_samples, + ch_meta_samples_sorted.skip, + ) + + // TODO(MC): Get rid of blocking. + // Undo split of meta records. + // channel: [ meta_bam ] + ch_outputs = ch_all_samples + .map { sample -> [sample.group_id, sample]} + .groupTuple() + .map { key_samples -> + + def samples = key_samples[1] + def merged_sample = [:] + samples.each { sample -> + + sample.each { key, value -> merged_sample[key] = value } + } + + merged_sample + } + + emit: + meta_bam = ch_outputs + // TODO[MC]: Channel version outputs. +} diff --git a/temp/genomes_GRCh37_hmf.config b/temp/genomes_GRCh37_hmf.config new file mode 100644 index 00000000..480613a1 --- /dev/null +++ b/temp/genomes_GRCh37_hmf.config @@ -0,0 +1,17 @@ +params { + genomes { + 'GRCh37_hmf' { + fasta = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/Homo_sapiens.GRCh37.GATK.illumina.fasta" + fai = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" + dict = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" + bwa_index = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/bwa_index/0.7.17-r1188" + bwa_index_image = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" + gridss_index = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" + } + } + + ref_data_hmf_data_path = "/Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/hmftools/5.34_37--0" + ref_data_virusbreakenddb_path = "/Users/matthewcooper/projects/oncoanalyser/virusbreakend/virusbreakenddb_20210401" + refdata_unmap_regions = "/Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/markdups/unmap_regions_37.tsv" + max_fastq_records = 10000000 +} diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 2951bbba..3e9c0b1b 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -2,6 +2,8 @@ import Constants import Processes import Utils +// TODO[MC]: Alignment. + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 5e3476d9..24ea60c0 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -15,6 +15,7 @@ inputs = Utils.parseInput(params.input, workflow.stubRun, log) run_config = WorkflowMain.getRunConfig(params, inputs, log) // Validate inputs +// TODO(MC): Reexamine validation in light of fastq/bam markdups. Utils.validateInput(inputs, run_config, log) // Check input path parameters to see if they exist @@ -67,6 +68,7 @@ linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : // // SUBWORKFLOWS // +include { ALIGNMENT } from '../subworkflows/local/alignment' include { AMBER_PROFILING } from '../subworkflows/local/amber_profiling' include { BAMTOOLS_METRICS } from '../subworkflows/local/bamtools_metrics' include { CHORD_PREDICTION } from '../subworkflows/local/chord_prediction' @@ -117,7 +119,8 @@ workflow WGTS { // Create input channel from parsed CSV // channel: [ meta ] - ch_inputs = Channel.fromList(inputs) + // TODO[MC]: Rename this back to original, and swap name out for current ch_inputs. + ch_inputs0 = Channel.fromList(inputs) // Set up reference data, assign more human readable variables PREPARE_REFERENCE( @@ -126,63 +129,79 @@ workflow WGTS { ref_data = PREPARE_REFERENCE.out hmf_data = PREPARE_REFERENCE.out.hmf_data + // TODO[MC]: Skipping alignment, only running up to alignment? + ALIGNMENT( + ch_inputs0, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_dict, + ref_data.genome_bwa_index, + file(params.refdata_unmap_regions), + 4 * params.max_fastq_records, + ) + + ch_inputs = ALIGNMENT.out.meta_bam + // Set GRIDSS config gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config - // - // SUBWORKFLOW: Align reads - // - // channel: [ meta, bam_dna ] - ch_dna_alignment_out = Channel.empty() - // channel: [ meta, bam_rna ] - ch_rna_alignment_out = Channel.empty() - // TODO(SW): set up correctly - if (true | run_config.stages.alignment) { + // // + // // SUBWORKFLOW: Align reads + // // + // // channel: [ meta, bam_dna ] + // ch_dna_alignment_out = Channel.empty() + // // channel: [ meta, bam_rna ] + // ch_rna_alignment_out = Channel.empty() + // // TODO(MC): set up correctly + // // if (true | run_config.stages.alignment) { - READ_ALIGNMENT( - ch_inputs, - // alignment reference files - ) + // // READ_ALIGNMENT( + // // ch_inputs, + // // // alignment reference files + // // ) - ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) + // // ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) - ch_dna_alignment_out = ch_dna_alignment_out.mix(READ_ALIGNMENT.out.dna) - ch_rna_alignment_out = ch_rna_alignment_out.mix(READ_ALIGNMENT.out.rna) + // // ch_dna_alignment_out = ch_dna_alignment_out.mix(READ_ALIGNMENT.out.dna) + // // ch_rna_alignment_out = ch_rna_alignment_out.mix(READ_ALIGNMENT.out.rna) - } else { + // // } else { - ch_dna_alignment_out = ch_inputs.map { meta -> [meta, []] } - ch_rna_alignment_out = ch_inputs.map { meta -> [meta, []] } + // // ch_dna_alignment_out = ch_inputs.map { meta -> [meta, []] } + // // ch_rna_alignment_out = ch_inputs.map { meta -> [meta, []] } - } + // // } - // - // SUBWORKFLOW: Process read alignments - // - // channel: [ meta, bam_dna ] - ch_dna_processed_out = Channel.empty() - // channel: [ meta, bam_rna ] - ch_rna_processed_out = Channel.empty() - // TODO(SW): set up correctly - if (true | run_config.stages.markdups) { + // ch_dna_alignment_out = ch_inputs.map { meta -> [meta, []] } + // ch_rna_alignment_out = ch_inputs.map { meta -> [meta, []] } - READ_PROCESSING( - ch_inputs, - ch_dna_alignment_out, - ch_rna_alignment_out, - ) + // // + // // SUBWORKFLOW: Process read alignments + // // + // // channel: [ meta, bam_dna ] + // ch_dna_processed_out = Channel.empty() + // // channel: [ meta, bam_rna ] + // ch_rna_processed_out = Channel.empty() + // // TODO(SW): set up correctly + // if (true | run_config.stages.markdups) { - ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) + // READ_PROCESSING( + // ch_inputs, + // ch_dna_alignment_out, + // ch_rna_alignment_out, + // ) - ch_dna_processed_out = ch_dna_processed_out.mix(READ_PROCESSING.out.dna) - ch_rna_processed_out = ch_rna_processed_out.mix(READ_PROCESSING.out.rna) + // ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) - } else { + // ch_dna_processed_out = ch_dna_processed_out.mix(READ_PROCESSING.out.dna) + // ch_rna_processed_out = ch_rna_processed_out.mix(READ_PROCESSING.out.rna) - ch_dna_processed_out = ch_inputs.map { meta -> [meta, []] } - ch_rna_processed_out = ch_inputs.map { meta -> [meta, []] } + // } else { - } + // ch_dna_processed_out = ch_inputs.map { meta -> [meta, []] } + // ch_rna_processed_out = ch_inputs.map { meta -> [meta, []] } + + // } // TODO(SW): adjust downstream selection of input BAM From a9c112df18400ec132f93f86bde8cb3e5198af61 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 12 Feb 2024 10:33:56 +1100 Subject: [PATCH 280/562] Switch to bioconda/BioContainers, bump versions * CHORD 2.03 * ORANGE 2.7.1 * gpgr (LINX) switched to linxreport 1.0.0 --- conf/modules.config | 40 +---- lib/Utils.groovy | 2 +- modules/local/amber/Dockerfile | 24 --- modules/local/amber/environment.yml | 7 + modules/local/amber/main.nf | 30 ++-- modules/local/bamtools/Dockerfile | 22 --- modules/local/bamtools/environment.yml | 7 + modules/local/bamtools/main.nf | 26 ++-- modules/local/chord/Dockerfile | 38 ----- .../chord/assets/extractSigPredictHRD.R.patch | 64 -------- modules/local/chord/environment.yml | 7 + modules/local/chord/main.nf | 74 +++++++--- modules/local/cobalt/Dockerfile | 24 --- modules/local/cobalt/environment.yml | 7 + modules/local/cobalt/main.nf | 30 ++-- modules/local/cuppa/Dockerfile | 41 ------ modules/local/cuppa/environment.yml | 7 + modules/local/cuppa/main.nf | 26 ++-- modules/local/gridss/Dockerfile | 37 ----- modules/local/gridss/environment.yml | 7 + modules/local/gridss/index/main.nf | 18 ++- modules/local/gripss/Dockerfile | 22 --- modules/local/gripss/environment.yml | 7 + modules/local/gripss/germline/main.nf | 36 ++--- modules/local/gripss/somatic/main.nf | 36 ++--- modules/local/isofox/Dockerfile | 22 --- modules/local/isofox/environment.yml | 7 + modules/local/isofox/main.nf | 38 ++--- modules/local/lilac/Dockerfile | 22 --- modules/local/lilac/environment.yml | 7 + modules/local/lilac/main.nf | 32 ++-- modules/local/linx/Dockerfile | 31 ---- modules/local/linx/environment.yml | 7 + modules/local/linx/germline/main.nf | 26 ++-- modules/local/linx/somatic/main.nf | 32 ++-- modules/local/linx/visualiser/main.nf | 51 +++---- modules/local/linxreport/environment.yml | 7 + .../local/{gpgr/linx => linxreport}/main.nf | 11 +- .../local/{gpgr/linx => linxreport}/meta.yml | 12 +- modules/local/orange/Dockerfile | 22 --- modules/local/orange/environment.yml | 7 + modules/local/orange/main.nf | 92 ++++++------ modules/local/pave/Dockerfile | 22 --- modules/local/pave/environment.yml | 7 + modules/local/pave/germline/main.nf | 42 +++--- modules/local/pave/somatic/main.nf | 46 +++--- modules/local/purple/Dockerfile | 32 ---- modules/local/purple/environment.yml | 7 + modules/local/purple/main.nf | 58 ++++---- modules/local/sage/Dockerfile | 31 ---- modules/local/sage/append/main.nf | 27 ++-- modules/local/sage/environment.yml | 7 + modules/local/sage/germline/main.nf | 58 ++++---- modules/local/sage/somatic/main.nf | 42 +++--- modules/local/sigs/Dockerfile | 22 --- modules/local/sigs/environment.yml | 7 + modules/local/sigs/main.nf | 18 ++- modules/local/svprep/Dockerfile | 23 --- modules/local/svprep/assemble/main.nf | 10 +- .../local/svprep/assets/gridss_svprep.patch | 139 ------------------ modules/local/svprep/call/main.nf | 10 +- modules/local/svprep/depth_annotator/main.nf | 27 ++-- modules/local/svprep/environment.yml | 7 + modules/local/svprep/preprocess/main.nf | 10 +- modules/local/svprep/svprep/main.nf | 32 ++-- modules/local/virusbreakend/environment.yml | 7 + modules/local/virusbreakend/main.nf | 8 +- modules/local/virusinterpreter/Dockerfile | 22 --- .../local/virusinterpreter/environment.yml | 7 + modules/local/virusinterpreter/main.nf | 24 +-- subworkflows/local/linx_plotting.nf | 6 +- 71 files changed, 680 insertions(+), 1143 deletions(-) delete mode 100644 modules/local/amber/Dockerfile create mode 100644 modules/local/amber/environment.yml delete mode 100644 modules/local/bamtools/Dockerfile create mode 100644 modules/local/bamtools/environment.yml delete mode 100644 modules/local/chord/Dockerfile delete mode 100644 modules/local/chord/assets/extractSigPredictHRD.R.patch create mode 100644 modules/local/chord/environment.yml delete mode 100644 modules/local/cobalt/Dockerfile create mode 100644 modules/local/cobalt/environment.yml delete mode 100644 modules/local/cuppa/Dockerfile create mode 100644 modules/local/cuppa/environment.yml delete mode 100644 modules/local/gridss/Dockerfile create mode 100644 modules/local/gridss/environment.yml delete mode 100644 modules/local/gripss/Dockerfile create mode 100644 modules/local/gripss/environment.yml delete mode 100644 modules/local/isofox/Dockerfile create mode 100644 modules/local/isofox/environment.yml delete mode 100644 modules/local/lilac/Dockerfile create mode 100644 modules/local/lilac/environment.yml delete mode 100644 modules/local/linx/Dockerfile create mode 100644 modules/local/linx/environment.yml create mode 100644 modules/local/linxreport/environment.yml rename modules/local/{gpgr/linx => linxreport}/main.nf (75%) rename modules/local/{gpgr/linx => linxreport}/meta.yml (76%) delete mode 100644 modules/local/orange/Dockerfile create mode 100644 modules/local/orange/environment.yml delete mode 100644 modules/local/pave/Dockerfile create mode 100644 modules/local/pave/environment.yml delete mode 100644 modules/local/purple/Dockerfile create mode 100644 modules/local/purple/environment.yml delete mode 100644 modules/local/sage/Dockerfile create mode 100644 modules/local/sage/environment.yml delete mode 100644 modules/local/sigs/Dockerfile create mode 100644 modules/local/sigs/environment.yml delete mode 100644 modules/local/svprep/Dockerfile delete mode 100644 modules/local/svprep/assets/gridss_svprep.patch create mode 100644 modules/local/svprep/environment.yml create mode 100644 modules/local/virusbreakend/environment.yml delete mode 100644 modules/local/virusinterpreter/Dockerfile create mode 100644 modules/local/virusinterpreter/environment.yml diff --git a/conf/modules.config b/conf/modules.config index 4bf35427..a0cd58f9 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -13,7 +13,6 @@ process { withName: 'AMBER' { - ext.jarPath = '/opt/amber/amber.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -22,7 +21,6 @@ process { } withName: 'COBALT' { - ext.jarPath = '/opt/cobalt/cobalt.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -30,17 +28,7 @@ process { ] } - withName: '.*:GRIDSS.*INDEX.*' { - ext.jarPath = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' - } - - withName: '.*:GRIDSS_SVPREP_CALLING:(?:DEPTH_ANNOTATOR|SVPREP_TUMOR|SVPREP_NORMAL)' { - ext.jarPath = '/opt/svprep/svprep.jar' - } - withName: '.*:GRIDSS_SVPREP_CALLING:(?:PREPROCESS|ASSEMBLE|CALL)' { - ext.jarPathGridss = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' - ext.jarPathSvPrep = '/opt/svprep/svprep.jar' ext.otherJvmHeap = 4.GB } @@ -52,10 +40,6 @@ process { ] } - withName: '.*:GRIPSS_FILTERING:(?:GERMLINE|SOMATIC)' { - ext.jarPath = '/opt/gripss/gripss.jar' - } - withName: '.*:GRIPSS_FILTERING:GERMLINE' { publishDir = [ path: { "${params.outdir}" }, @@ -72,10 +56,6 @@ process { ] } - withName: '.*:SAGE_CALLING:(?:GERMLINE|SOMATIC)' { - ext.jarPath = '/opt/sage/sage.jar' - } - withName: '.*:SAGE_CALLING:GERMLINE' { publishDir = [ path: { "${params.outdir}" }, @@ -93,7 +73,6 @@ process { } withName: '.*:SAGE_APPEND:(?:GERMLINE|SOMATIC)' { - ext.jarPath = '/opt/sage/sage.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -102,7 +81,6 @@ process { } withName: '.*:PAVE_ANNOTATION:(?:GERMLINE|SOMATIC)' { - ext.jarPath = '/opt/pave/pave.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -111,8 +89,6 @@ process { } withName: 'PURPLE' { - ext.jarPath = '/opt/purple/purple.jar' - ext.circosPath = '/opt/conda/bin/circos' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -120,10 +96,6 @@ process { ] } - withName: '.*:LINX_ANNOTATION:(?:GERMLINE|SOMATIC)|.*:LINX_PLOTTING:VISUALISER' { - ext.jarPath = '/opt/linx/linx.jar' - } - withName: '.*:LINX_ANNOTATION:GERMLINE' { publishDir = [ path: { "${params.outdir}" }, @@ -141,7 +113,6 @@ process { } withName: '.*:LINX_PLOTTING:VISUALISER' { - ext.circosPath = '/opt/conda/bin/circos' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -149,7 +120,7 @@ process { ] } - withName: '.*:LINX_PLOTTING:GPGR' { + withName: '.*:LINX_PLOTTING:REPORT' { publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -158,7 +129,6 @@ process { } withName: 'BAMTOOLS' { - ext.jarPath = '/opt/bamtools/bamtools.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -181,7 +151,6 @@ process { } withName: 'LILAC' { - ext.jarPath = '/opt/lilac/lilac.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -190,7 +159,6 @@ process { } withName: 'SIGS' { - ext.jarPath = '/opt/sigs/sigs.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -199,7 +167,6 @@ process { } withName: 'VIRUSBREAKEND' { - ext.jarPath = '/opt/conda/share/gridss-2.13.2-1/gridss.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -208,7 +175,6 @@ process { } withName: 'VIRUSINTERPRETER' { - ext.jarPath = '/opt/virusinterpreter/virusinterpreter.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -217,7 +183,6 @@ process { } withName: 'ISOFOX' { - ext.jarPath = '/opt/isofox/isofox.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -226,8 +191,6 @@ process { } withName: 'CUPPA' { - ext.jarPath = '/opt/cuppa/cuppa.jar' - ext.chartScriptPath = '/opt/cuppa/chart/cuppa-chart.py' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, @@ -244,7 +207,6 @@ process { } withName: 'ORANGE' { - ext.jarPath = '/opt/orange/orange.jar' publishDir = [ path: { "${params.outdir}" }, mode: params.publish_dir_mode, diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 8078b1a7..d6331d5c 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -69,7 +69,7 @@ class Utils { System.exit(1) } - meta_sample[filetype_enum] = it.filepath + meta_sample[filetype_enum] = Utils.getFileObject(it.filepath) // Record sample key to simplify iteration later on sample_keys << sample_key diff --git a/modules/local/amber/Dockerfile b/modules/local/amber/Dockerfile deleted file mode 100644 index 3cce34d7..00000000 --- a/modules/local/amber/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/amber/ && \ - wget -O /opt/amber/amber.jar 'https://github.com/hartwigmedical/hmftools/releases/download/amber-v4.0/amber_v4.0.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - bioconductor-copynumber \ - 'openjdk >=8' \ - r-dplyr && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/amber/environment.yml b/modules/local/amber/environment.yml new file mode 100644 index 00000000..97d7f6ee --- /dev/null +++ b/modules/local/amber/environment.yml @@ -0,0 +1,7 @@ +name: amber +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::amber=4.0 diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index 25d6ac97..a360e0da 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -2,7 +2,10 @@ process AMBER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/amber:4.0--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-amber:4.0--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-amber:4.0--hdfd78af_0' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -26,23 +29,22 @@ process AMBER { def target_regions_bed_arg = target_region_bed ? "-target_regions_bed ${target_region_bed}" : '' """ - java \\ + amber \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -tumor ${meta.tumor_id} \\ - -tumor_bam ${tumor_bam} \\ - ${reference_arg} \\ - ${reference_bam_arg} \\ - ${target_regions_bed_arg} \\ - -ref_genome_version ${ref_genome_ver} \\ - -loci ${heterozygous_sites} \\ - -threads ${task.cpus} \\ - -output_dir amber/ + ${args} \\ + -tumor ${meta.tumor_id} \\ + -tumor_bam ${tumor_bam} \\ + ${reference_arg} \\ + ${reference_bam_arg} \\ + ${target_regions_bed_arg} \\ + -ref_genome_version ${ref_genome_ver} \\ + -loci ${heterozygous_sites} \\ + -threads ${task.cpus} \\ + -output_dir amber/ cat <<-END_VERSIONS > versions.yml "${task.process}": - amber: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + amber: \$(amber -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/bamtools/Dockerfile b/modules/local/bamtools/Dockerfile deleted file mode 100644 index 61ae054b..00000000 --- a/modules/local/bamtools/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/bamtools/ && \ - wget -O /opt/bamtools/bamtools.jar 'https://github.com/hartwigmedical/hmftools/releases/download/bam-tools-v1.2/bam-tools_v1.2.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'openjdk >=8' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/bamtools/environment.yml b/modules/local/bamtools/environment.yml new file mode 100644 index 00000000..a0b80cd2 --- /dev/null +++ b/modules/local/bamtools/environment.yml @@ -0,0 +1,7 @@ +name: bamtools +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-bam-tools=1.2=hdfd78af_1 diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf index fba57d83..6a193c30 100644 --- a/modules/local/bamtools/main.nf +++ b/modules/local/bamtools/main.nf @@ -2,7 +2,10 @@ process BAMTOOLS { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/bamtools:1.2--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-bam-tools:1.2--hdfd78af_1' : + 'quay.io/biocontainers/hmftools-bam-tools:1.2--hdfd78af_1' }" input: tuple val(meta), path(bam), path(bai) @@ -20,22 +23,21 @@ process BAMTOOLS { def args = task.ext.args ?: '' """ - java \\ + bamtools \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -cp ${task.ext.jarPath} \\ com.hartwig.hmftools.bamtools.metrics.BamMetrics \\ - -sample ${meta.sample_id} \\ - -bam_file ${bam} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -threads ${task.cpus} \\ - -write_old_style \\ - -log_level INFO \\ - -output_dir ./ + -sample ${meta.sample_id} \\ + -bam_file ${bam} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -threads ${task.cpus} \\ + -write_old_style \\ + -log_level INFO \\ + -output_dir ./ cat <<-END_VERSIONS > versions.yml "${task.process}": - bamtools: \$(java -jar ${task.ext.jarPath} | sed 's/^.* //') + bamtools: \$(bamtools -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/chord/Dockerfile b/modules/local/chord/Dockerfile deleted file mode 100644 index e87e6e8c..00000000 --- a/modules/local/chord/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y patch procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -ARG GH_BASE_URL=https://raw.githubusercontent.com/hartwigmedical/pipeline5 -COPY assets/extractSigPredictHRD.R.patch /tmp/ -RUN \ - mkdir -p /opt/chord/ && \ - wget -P /opt/chord/ ${GH_BASE_URL}/v5.30/cluster/images/extractSigPredictHRD.R && \ - patch -p1 /opt/chord/extractSigPredictHRD.R /tmp/extractSigPredictHRD.R.patch && \ - rm /tmp/extractSigPredictHRD.R.patch && \ - chmod 755 /opt/chord/extractSigPredictHRD.R - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - bioconductor-bsgenome \ - bioconductor-bsgenome.hsapiens.ucsc.hg19 \ - bioconductor-bsgenome.hsapiens.ucsc.hg38 \ - r-base \ - r-devtools \ - r-randomforest && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}:/opt/chord/" - -# NOTE(SW): mutSigExtractor must be installed second as the process to install -# CHORD can upgrade mutSigExtractor to an incompatible version -RUN \ - R -e "devtools::install_github('https://github.com/UMCUGenetics/CHORD', ref='2.00')" && \ - R -e "devtools::install_github('https://github.com/UMCUGenetics/mutSigExtractor', ref='1.14')" diff --git a/modules/local/chord/assets/extractSigPredictHRD.R.patch b/modules/local/chord/assets/extractSigPredictHRD.R.patch deleted file mode 100644 index 74a8e8c9..00000000 --- a/modules/local/chord/assets/extractSigPredictHRD.R.patch +++ /dev/null @@ -1,64 +0,0 @@ ---- a/extractSigPredictHRD.R -+++ b/extractSigPredictHRD.R -@@ -1,15 +1,14 @@ --#!/usr/bin/Rscript -+#!/usr/bin/env Rscript - - options(stringsAsFactors=F) # to avoid invalid factor level warning - - args <- commandArgs(TRUE) - --chordToolDir <- args[1] -- workingDir <- args[2] -- sampleName <- args[3] -- snvIndVcf <- args[4] -- svVcf <- args[5] --refGenomeVsn <- args[6] # RG_37 or RG_38 -+ workingDir <- args[1] -+ sampleName <- args[2] -+ snvIndVcf <- args[3] -+ svVcf <- args[4] -+refGenomeVsn <- args[5] # RG_37 or RG_38 - sigOutTxt <- paste0( workingDir, '/', sampleName, '_chord_signatures.txt') - prdOutTxt <- paste0( workingDir, '/', sampleName, '_chord_prediction.txt') - -@@ -18,8 +17,8 @@ setwd(workingDir) - - suppressPackageStartupMessages(library('devtools')) - suppressPackageStartupMessages(library('randomForest')) --suppressPackageStartupMessages(load_all(paste0(chordToolDir, '/mutSigExtractor-1.14'))) --suppressPackageStartupMessages(load_all(paste0(chordToolDir, '/CHORD-2.00'))) -+suppressPackageStartupMessages(library('mutSigExtractor')) -+suppressPackageStartupMessages(library('CHORD')) - - cat("[INFO] Package NamespaceVersions after loading:\n") - for (pkgName in c("mutSigExtractor", "CHORD")){ -@@ -28,18 +27,17 @@ for (pkgName in c("mutSigExtractor", "CHORD")){ - } - - ## Convert genome name to BSGenome name --if (refGenomeVsn == "RG_37") { -+if (refGenomeVsn == "37") { - suppressPackageStartupMessages(library(BSgenome.Hsapiens.UCSC.hg19)) - refGenome <- BSgenome.Hsapiens.UCSC.hg19 --} else if (refGenomeVsn == "RG_38") { -+} else if (refGenomeVsn == "38") { - suppressPackageStartupMessages(library(BSgenome.Hsapiens.UCSC.hg38)) - refGenome <- BSgenome.Hsapiens.UCSC.hg38 - } else { -- stop("Unsupported ref genome version: ", refGenomeVsn," (should be HG37 or HG38)\n") -+ stop("Unsupported ref genome version: ", refGenomeVsn," (should be 37 or 38)\n") - } - - cat("[INFO] CHORD Settings:\n") --cat("[INFO] Chord dir:", chordToolDir, "\n") - cat("[INFO] Working dir:", workingDir, "\n") - cat("[INFO] Sample name:", sampleName, "\n") - cat("[INFO] Somatic SNV/IND vcf:", snvIndVcf, "\n") -@@ -73,4 +71,4 @@ write.table(signatures, file=sigOutTxt, sep="\t") - cat("[INFO] Writing output file:", prdOutTxt,"\n") - write.table(prediction, file=prdOutTxt, sep="\t", quote=FALSE, row.names=FALSE) - --cat("[INFO] FINISHED CHORD signature extraction and HRD prediction\n") -\ No newline at end of file -+cat("[INFO] FINISHED CHORD signature extraction and HRD prediction\n") diff --git a/modules/local/chord/environment.yml b/modules/local/chord/environment.yml new file mode 100644 index 00000000..b698f67e --- /dev/null +++ b/modules/local/chord/environment.yml @@ -0,0 +1,7 @@ +name: chord +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::r-chord=2.03 diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf index 818f22b4..f2906676 100644 --- a/modules/local/chord/main.nf +++ b/modules/local/chord/main.nf @@ -2,7 +2,10 @@ process CHORD { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/chord:2.00--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/r-chord:2.03--r43hdfd78af_0' : + 'quay.io/biocontainers/r-chord:2.03--r43hdfd78af_0' }" input: tuple val(meta), path(smlv_vcf), path(sv_vcf) @@ -19,24 +22,59 @@ process CHORD { def args = task.ext.args ?: '' """ - mkdir -p chord/ + #!/usr/bin/env Rscript + library('CHORD') + + sampleName <- '${meta.sample_id}' + snvIndVcf <- '${smlv_vcf}' + svVcf <- '${sv_vcf}' + refGenomeVsn <- '${genome_ver}' + + sigOutTxt <- 'chord/${meta.sample_id}_chord_signatures.txt' + prdOutTxt <- 'chord/${meta.sample_id}_chord_prediction.txt' + + dir.create('chord/') + + if (refGenomeVsn == '37') { + library(BSgenome.Hsapiens.UCSC.hg19) + refGenome <- BSgenome.Hsapiens.UCSC.hg19 + } else if (refGenomeVsn == '38') { + library(BSgenome.Hsapiens.UCSC.hg38) + refGenome <- BSgenome.Hsapiens.UCSC.hg38 + } else { + stop('Unsupported ref genome version: ', refGenomeVsn, ' (should be 37 or 38)\\n') + } + + cat('[INFO] Performing chord signature extraction\\n') + signatures <- CHORD::extractSigsChord( + vcf.snv=snvIndVcf, + vcf.indel=snvIndVcf, + vcf.sv=svVcf, + sample.name=sampleName, + sv.caller='gridss', + vcf.filters=list(snv='PASS', indel='PASS', sv='PASS'), + ref.genome=refGenome + ) + + cat('[INFO] Performing chord HRD prediction\\n') + prediction <- chordPredict( + signatures, + hrd.cutoff=0.5 + ) + + cat('[INFO] Writing output file:', sigOutTxt,'\\n') + write.table(signatures, file=sigOutTxt, sep='\\t') + + cat('[INFO] Writing output file:', prdOutTxt,'\\n') + write.table(prediction, file=prdOutTxt, sep='\\t', quote=FALSE, row.names=FALSE) + + cat('[INFO] FINISHED CHORD signature extraction and HRD prediction\\n') - extractSigPredictHRD.R \\ - ./ \\ - ${meta.sample_id} \\ - ${smlv_vcf} \\ - ${sv_vcf} \\ - ${genome_ver} \\ - chord_signatures.txt \\ - chord_prediction.txt - - mv ${meta.sample_id}_chord_signatures.txt ${meta.sample_id}_chord_prediction.txt chord/ - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - CHORD: \$(R -s -e "message(packageVersion('CHORD'))" 2>&1) - mutSigExtractor: \$(R -s -e "message(packageVersion('mutSigExtractor'))" 2>&1) - END_VERSIONS + sink('versions.yml') + writeLines('"${task.process}":') + writeLines(paste(' CHORD:', packageVersion('CHORD'))) + writeLines(paste(' mutSigExtractor:', packageVersion('mutSigExtractor'))) + sink() """ stub: diff --git a/modules/local/cobalt/Dockerfile b/modules/local/cobalt/Dockerfile deleted file mode 100644 index 6e2eb4d1..00000000 --- a/modules/local/cobalt/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/cobalt/ && \ - wget -O /opt/cobalt/cobalt.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cobalt-v1.16/cobalt_v1.16.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - bioconductor-copynumber \ - 'openjdk >=8' \ - r-dplyr && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/cobalt/environment.yml b/modules/local/cobalt/environment.yml new file mode 100644 index 00000000..df3881f5 --- /dev/null +++ b/modules/local/cobalt/environment.yml @@ -0,0 +1,7 @@ +name: cobalt +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::cobalt=1.16 diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index 30ae20be..52a40eba 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -2,7 +2,10 @@ process COBALT { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/cobalt:1.16--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-cobalt:1.16--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-cobalt:1.16--hdfd78af_0' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -27,23 +30,22 @@ process COBALT { def target_region_arg = target_region_normalisation ? "-target_region ${target_region_normalisation}" : '' """ - java \\ + cobalt \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -tumor ${meta.tumor_id} \\ - -tumor_bam ${tumor_bam} \\ - ${reference_arg} \\ - ${reference_bam_arg} \\ - -threads ${task.cpus} \\ - -gc_profile ${gc_profile} \\ - ${diploid_regions_arg} \\ - ${target_region_arg} \\ - -output_dir cobalt/ + ${args} \\ + -tumor ${meta.tumor_id} \\ + -tumor_bam ${tumor_bam} \\ + ${reference_arg} \\ + ${reference_bam_arg} \\ + -threads ${task.cpus} \\ + -gc_profile ${gc_profile} \\ + ${diploid_regions_arg} \\ + ${target_region_arg} \\ + -output_dir cobalt/ cat <<-END_VERSIONS > versions.yml "${task.process}": - cobalt: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + cobalt: \$(cobalt -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/cuppa/Dockerfile b/modules/local/cuppa/Dockerfile deleted file mode 100644 index 51e50956..00000000 --- a/modules/local/cuppa/Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/cuppa/ && \ - wget -O /opt/cuppa/cuppa.jar 'https://github.com/hartwigmedical/hmftools/releases/download/cuppa-v1.8.1/cuppa_v1.8.1.jar' - -ARG URL_BASE=https://raw.githubusercontent.com/hartwigmedical/hmftools/cuppa-v1.8.1 -ARG URL_BASE_CHART=${URL_BASE}/cuppa/src/main/resources/cuppa-chart -ARG DIR_BASE=/opt/cuppa -RUN \ - mkdir -p ${DIR_BASE}/{chart,report} && \ - wget -P ${DIR_BASE}/chart/ ${URL_BASE_CHART}/requirements.txt && \ - wget -P ${DIR_BASE}/chart/ ${URL_BASE_CHART}/cuppa-chart.py && \ - wget -P ${DIR_BASE}/chart/main/ ${URL_BASE_CHART}/main/create_chart.py && \ - wget -P ${DIR_BASE}/chart/main/ ${URL_BASE_CHART}/main/prepare_data.py - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'matplotlib >=3.3,<4' \ - 'numpy >=1.19,<2' \ - 'openjdk >=8' \ - 'pandas >=1.1,<2' \ - 'scipy >=1,<2' \ - 'seaborn >=0.11,<1' \ - 'r-base ==4.2.2' \ - 'r-cowplot' \ - 'r-ggplot2' \ - 'r-gridextra' \ - 'r-stringi' \ - 'r-tidyr' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/cuppa/environment.yml b/modules/local/cuppa/environment.yml new file mode 100644 index 00000000..eb974257 --- /dev/null +++ b/modules/local/cuppa/environment.yml @@ -0,0 +1,7 @@ +name: cuppa +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-cuppa=1.8.1 diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index b4ea02a3..213f9819 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -2,7 +2,10 @@ process CUPPA { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/cuppa:1.8.1--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-cuppa:1.8.1--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-cuppa:1.8.1--hdfd78af_0' }" input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) @@ -41,19 +44,18 @@ process CUPPA { mkdir -p cuppa/ - java \\ + cuppa \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - -sample ${meta.sample_id} \\ - -sample_data_dir sample_data/ \\ - -categories ${classifier} \\ - -ref_data_dir ${cuppa_resources} \\ - -ref_genome_version ${ref_genome_ver} \\ - -create_pdf \\ - -output_dir cuppa/ + -sample ${meta.sample_id} \\ + -sample_data_dir sample_data/ \\ + -categories ${classifier} \\ + -ref_data_dir ${cuppa_resources} \\ + -ref_genome_version ${ref_genome_ver} \\ + -create_pdf \\ + -output_dir cuppa/ if [[ ${classifier} == 'DNA' || ${classifier} == 'ALL' ]]; then - python ${task.ext.chartScriptPath} \\ + cuppa-chart \\ -sample ${meta.sample_id} \\ -sample_data cuppa/${meta.sample_id}.cup.data.csv \\ -output_dir cuppa/; @@ -61,7 +63,7 @@ process CUPPA { cat <<-END_VERSIONS > versions.yml "${task.process}": - cuppa: \$(java -jar ${task.ext.jarPath} | sed -n '1s/^.* //p') + cuppa: \$(cuppa | sed -n '1s/^.* //p') END_VERSIONS """ diff --git a/modules/local/gridss/Dockerfile b/modules/local/gridss/Dockerfile deleted file mode 100644 index 6373cf84..00000000 --- a/modules/local/gridss/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'gridss==2.13.2' && \ - micromamba clean --all --yes - -# NOTE(SW): required to correctly check SAMtools version built by Conda -RUN \ - sed -i \ - -e '209s/grep samtools/head -n1 | grep samtools/' \ - /opt/conda/share/gridss-2.13.2-1/gridss_extract_overlapping_fragments - -# NOTE(SW): required to run tests on compute with low resources; without the -# change this GRIDSS invoke will attempt to allocate the default 30 GB of -# memory even when `--gridssargs` is set -RUN \ - sed -i \ - -e '779a \\t\t$gridssargs \\' \ - /opt/conda/share/gridss-2.13.2-1/virusbreakend - -RUN \ - ln -sf \ - /opt/conda/pkgs/gridss-2.13.2-h20b1175_1/share/gridss-2.13.2-1/gridss \ - /opt/conda/bin/gridss - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/gridss/environment.yml b/modules/local/gridss/environment.yml new file mode 100644 index 00000000..dbe711d9 --- /dev/null +++ b/modules/local/gridss/environment.yml @@ -0,0 +1,7 @@ +name: gridss +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::gridss=2.13.2=hdfd78af_3 diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 69228047..912aa654 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -2,7 +2,10 @@ process GRIDSS_INDEX { tag "${genome_fasta.name}" label 'process_single' - container 'docker.io/scwatts/gridss:2.13.2--3' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/gridss:2.13.2--h50ea8bc_3' : + 'quay.io/biocontainers/gridss:2.13.2--h50ea8bc_3' }" input: path genome_fasta @@ -32,7 +35,7 @@ process GRIDSS_INDEX { ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ # Run - java \\ + PrepareReference \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -XX:ParallelGCThreads=${task.cpus} \\ -Dsamjdk.reference_fasta=${genome_fasta} \\ @@ -41,15 +44,14 @@ process GRIDSS_INDEX { -Dsamjdk.use_async_io_write_tribble=true \\ -Dsamjdk.buffer_size=4194304 \\ -Dsamjdk.async_io_read_threads=${task.cpus} \\ - -cp ${task.ext.jarPath} gridss.PrepareReference \\ - REFERENCE_SEQUENCE=${genome_fasta} \\ - CREATE_SEQUENCE_DICTIONARY=${sequence_dict_arg} \\ - CREATE_BWA_INDEX_IMAGE=${bwa_index_image_arg} \\ - CREATE_GRIDSS_REFERENCE_CACHE=${gridss_index_arg} + REFERENCE_SEQUENCE=${genome_fasta} \\ + CREATE_SEQUENCE_DICTIONARY=${sequence_dict_arg} \\ + CREATE_BWA_INDEX_IMAGE=${bwa_index_image_arg} \\ + CREATE_GRIDSS_REFERENCE_CACHE=${gridss_index_arg} cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp ${task.ext.jarPath} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + gridss: \$(CallVariants --version 2>&1 | sed 's/-gridss\$//') END_VERSIONS """ diff --git a/modules/local/gripss/Dockerfile b/modules/local/gripss/Dockerfile deleted file mode 100644 index 26b56bca..00000000 --- a/modules/local/gripss/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/gripss/ && \ - wget -O /opt/gripss/gripss.jar 'https://github.com/hartwigmedical/hmftools/releases/download/gripss-v2.4/gripss_v2.4.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'openjdk >=8' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/gripss/environment.yml b/modules/local/gripss/environment.yml new file mode 100644 index 00000000..70a822be --- /dev/null +++ b/modules/local/gripss/environment.yml @@ -0,0 +1,7 @@ +name: gripss +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::gripss=2.4 diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 6bce8f76..4100369c 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -2,7 +2,10 @@ process GRIPSS_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.4--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-gripss:2.4--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-gripss:2.4--hdfd78af_0' }" input: tuple val(meta), path(gridss_vcf) @@ -26,26 +29,25 @@ process GRIPSS_GERMLINE { def args = task.ext.args ?: '' """ - java \\ + gripss \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -sample ${meta.normal_id} \\ - -reference ${meta.tumor_id} \\ - -vcf ${gridss_vcf} \\ - -germline \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -pon_sgl_file ${pon_breakends} \\ - -pon_sv_file ${pon_breakpoints} \\ - -known_hotspot_file ${known_fusions} \\ - -repeat_mask_file ${repeatmasker_annotations} \\ - -output_id germline \\ - -output_dir ./ + ${args} \\ + -sample ${meta.normal_id} \\ + -reference ${meta.tumor_id} \\ + -vcf ${gridss_vcf} \\ + -germline \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -pon_sgl_file ${pon_breakends} \\ + -pon_sv_file ${pon_breakpoints} \\ + -known_hotspot_file ${known_fusions} \\ + -repeat_mask_file ${repeatmasker_annotations} \\ + -output_id germline \\ + -output_dir ./ cat <<-END_VERSIONS > versions.yml "${task.process}": - gripss: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + gripss: \$(gripss -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index 3ec6339f..1c9b28ed 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -2,7 +2,10 @@ process GRIPSS_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/gripss:2.4--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-gripss:2.4--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-gripss:2.4--hdfd78af_0' }" input: tuple val(meta), path(gridss_vcf) @@ -31,26 +34,25 @@ process GRIPSS_SOMATIC { def output_id_arg = meta.containsKey('normal_id') ? '-output_id somatic' : '' """ - java \\ + gripss \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -sample ${meta.tumor_id} \\ - ${reference_arg} \\ - -vcf ${gridss_vcf} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -pon_sgl_file ${pon_breakends} \\ - -pon_sv_file ${pon_breakpoints} \\ - -known_hotspot_file ${known_fusions} \\ - -repeat_mask_file ${repeatmasker_annotations} \\ - ${target_regions_bed_arg} \\ - ${output_id_arg} \\ - -output_dir ./ + ${args} \\ + -sample ${meta.tumor_id} \\ + ${reference_arg} \\ + -vcf ${gridss_vcf} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -pon_sgl_file ${pon_breakends} \\ + -pon_sv_file ${pon_breakpoints} \\ + -known_hotspot_file ${known_fusions} \\ + -repeat_mask_file ${repeatmasker_annotations} \\ + ${target_regions_bed_arg} \\ + ${output_id_arg} \\ + -output_dir ./ cat <<-END_VERSIONS > versions.yml "${task.process}": - gripss: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + gripss: \$(gripss -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/isofox/Dockerfile b/modules/local/isofox/Dockerfile deleted file mode 100644 index 55c301ad..00000000 --- a/modules/local/isofox/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/isofox/ && \ - wget -O /opt/isofox/isofox.jar 'https://github.com/hartwigmedical/hmftools/releases/download/isofox-v1.7.1/isofox_v1.7.1.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'openjdk >=8' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/isofox/environment.yml b/modules/local/isofox/environment.yml new file mode 100644 index 00000000..0034bceb --- /dev/null +++ b/modules/local/isofox/environment.yml @@ -0,0 +1,7 @@ +name: isofox +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::isofox=1.7.1 diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 50456928..903e5e45 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -2,7 +2,10 @@ process ISOFOX { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/isofox:1.7.1--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-isofox:1.7.1-hdfd78af_0': + 'quay.io/biocontainers/hmftools-isofox:1.7.1--hdfd78af_0' }" input: tuple val(meta), path(bam), path(bai) @@ -38,27 +41,26 @@ process ISOFOX { """ mkdir -p isofox/ - java \\ + isofox \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -sample ${meta.sample_id} \\ - -bam_file ${bam} \\ - ${functions_arg} \\ - -read_length ${read_length} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - ${exp_counts_arg} \\ - ${exp_gc_ratios_arg} \\ - ${gene_ids_arg} \\ - ${tpm_norm_arg} \\ - -threads ${task.cpus} \\ - -output_dir isofox/ + ${args} \\ + -sample ${meta.sample_id} \\ + -bam_file ${bam} \\ + ${functions_arg} \\ + -read_length ${read_length} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + ${exp_counts_arg} \\ + ${exp_gc_ratios_arg} \\ + ${gene_ids_arg} \\ + ${tpm_norm_arg} \\ + -threads ${task.cpus} \\ + -output_dir isofox/ cat <<-END_VERSIONS > versions.yml "${task.process}": - isofox: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + isofox: \$(isofox -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/lilac/Dockerfile b/modules/local/lilac/Dockerfile deleted file mode 100644 index 7c37c81c..00000000 --- a/modules/local/lilac/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/lilac/ && \ - wget -O /opt/lilac/lilac.jar 'https://github.com/hartwigmedical/hmftools/releases/download/lilac-v1.6/lilac_v1.6.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'openjdk >=8' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/lilac/environment.yml b/modules/local/lilac/environment.yml new file mode 100644 index 00000000..93912603 --- /dev/null +++ b/modules/local/lilac/environment.yml @@ -0,0 +1,7 @@ +name: lilac +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::lilac=1.6 diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 004fa1e4..91936f07 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -2,7 +2,10 @@ process LILAC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/lilac:1.6--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-lilac:1.6--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-lilac:1.6--hdfd78af_0' }" input: tuple val(meta), path(normal_dna_bam), path(normal_dna_bai), path(tumor_dna_bam), path(tumor_dna_bai), path(tumor_rna_bam), path(tumor_rna_bai), path(purple_dir) @@ -28,24 +31,23 @@ process LILAC { def purple_dir_arg = purple_dir ? "-purple_dir ${purple_dir}" : '' """ - java \\ + lilac \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -sample ${sample_name} \\ - ${normal_bam_arg} \\ - ${tumor_dna_bam_arg} \\ - ${tumor_rna_bam_arg} \\ - ${purple_dir_arg} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -resource_dir ${lilac_resources} \\ - -threads ${task.cpus} \\ - -output_dir lilac/ + ${args} \\ + -sample ${sample_name} \\ + ${normal_bam_arg} \\ + ${tumor_dna_bam_arg} \\ + ${tumor_rna_bam_arg} \\ + ${purple_dir_arg} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -resource_dir ${lilac_resources} \\ + -threads ${task.cpus} \\ + -output_dir lilac/ cat <<-END_VERSIONS > versions.yml "${task.process}": - lilac: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + lilac: \$(lilac -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/linx/Dockerfile b/modules/local/linx/Dockerfile deleted file mode 100644 index a7f3935f..00000000 --- a/modules/local/linx/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/linx/ && \ - wget -O /opt/linx/linx.jar 'https://github.com/hartwigmedical/hmftools/releases/download/linx-v1.25/linx_v1.25.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - bioconductor-gviz \ - 'circos >=0.69.6' \ - 'openjdk >=8' \ - 'r-base == 4.1.3' \ - r-cowplot \ - r-dplyr \ - r-ggplot2 \ - r-magick \ - r-tidyr \ - xorg-libxtst && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/linx/environment.yml b/modules/local/linx/environment.yml new file mode 100644 index 00000000..b6a888dd --- /dev/null +++ b/modules/local/linx/environment.yml @@ -0,0 +1,7 @@ +name: linx +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::linx=1.25 diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 9827e96b..12421be1 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -2,7 +2,10 @@ process LINX_GERMLINE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.24.1--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': + 'quay.io/biocontainers/hmftools-linx:1.25--hdfd78af_0' }" input: tuple val(meta), path(sv_vcf) @@ -21,21 +24,20 @@ process LINX_GERMLINE { def args = task.ext.args ?: '' """ - java \\ + linx \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -sample ${meta.sample_id} \\ - -sv_vcf ${sv_vcf} \\ - -germline \\ - -ref_genome_version ${genome_ver} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - -driver_gene_panel ${driver_gene_panel} \\ - -output_dir linx_germline/ + ${args} \\ + -sample ${meta.sample_id} \\ + -sv_vcf ${sv_vcf} \\ + -germline \\ + -ref_genome_version ${genome_ver} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -output_dir linx_germline/ cat <<-END_VERSIONS > versions.yml "${task.process}": - linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*Linx version: //') + linx: \$(linx -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index c4cd676f..ea3475dd 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,7 +2,10 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/linx:1.25--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': + 'quay.io/biocontainers/hmftools-linx:1.25--hdfd78af_0' }" input: tuple val(meta), path(purple_dir) @@ -24,24 +27,23 @@ process LINX_SOMATIC { def gene_id_file_arg = gene_id_file ? "-gene_id_file ${gene_id_file}" : '' """ - java \\ + linx \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -sample ${meta.sample_id} \\ - -sv_vcf ${purple_dir}/${meta.sample_id}.purple.sv.vcf.gz \\ - -purple_dir ${purple_dir} \\ - ${gene_id_file_arg} \\ - -ref_genome_version ${genome_ver} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - -known_fusion_file ${known_fusion_data} \\ - -driver_gene_panel ${driver_gene_panel} \\ - -write_vis_data \\ - -output_dir linx_somatic/ + ${args} \\ + -sample ${meta.sample_id} \\ + -sv_vcf ${purple_dir}/${meta.sample_id}.purple.sv.vcf.gz \\ + -purple_dir ${purple_dir} \\ + ${gene_id_file_arg} \\ + -ref_genome_version ${genome_ver} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + -known_fusion_file ${known_fusion_data} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -write_vis_data \\ + -output_dir linx_somatic/ cat <<-END_VERSIONS > versions.yml "${task.process}": - linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*Linx version: //') + linx: \$(linx -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index dcd56fc1..f5613e4c 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,7 +2,10 @@ process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/linx:1.25--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': + 'quay.io/biocontainers/hmftools-linx:1.25--hdfd78af_0' }" input: tuple val(meta), path(linx_annotation_dir) @@ -38,19 +41,18 @@ process LINX_VISUALISER { # Generate all chromosome and cluster plots by default - java \\ + linx \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -cp ${task.ext.jarPath} \\ com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ - ${args} \\ - -sample ${meta.sample_id} \\ - -vis_file_dir ${linx_annotation_dir} \\ - -ref_genome_version ${genome_ver} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - -circos ${task.ext.circosPath} \\ - -threads ${task.cpus} \\ - -plot_out plots/all/ \\ - -data_out data/all/ + ${args} \\ + -sample ${meta.sample_id} \\ + -vis_file_dir ${linx_annotation_dir} \\ + -ref_genome_version ${genome_ver} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + -circos \$(which circos) \\ + -threads ${task.cpus} \\ + -plot_out plots/all/ \\ + -data_out data/all/ # Rerun LINX to render only reportable cluster plots in a separate directory. While this is regenerating existing # cluster plots, the number of reportable plots is generally very small and I prefer to rely on the internal LINX @@ -62,20 +64,19 @@ process LINX_VISUALISER { # https://github.com/hartwigmedical/hmftools/blob/linx-v1.24.1/linx/src/main/java/com/hartwig/hmftools/linx/visualiser/SampleData.java#L220-L236 - java \\ + linx \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -cp ${task.ext.jarPath} \\ com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ - ${args} \\ - -sample ${meta.sample_id} \\ - -vis_file_dir ${linx_annotation_dir} \\ - -ref_genome_version ${genome_ver} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - -circos ${task.ext.circosPath} \\ - -plot_reportable \\ - -threads ${task.cpus} \\ - -plot_out plots/reportable/ \\ - -data_out data/reportable/ + ${args} \\ + -sample ${meta.sample_id} \\ + -vis_file_dir ${linx_annotation_dir} \\ + -ref_genome_version ${genome_ver} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + -circos \$(which circos) \\ + -plot_reportable \\ + -threads ${task.cpus} \\ + -plot_out plots/reportable/ \\ + -data_out data/reportable/ # Create placeholders to force FusionFS to create parent plot directory on S3 if [[ \$(ls plots/ | wc -l) -eq 0 ]]; then @@ -84,7 +85,7 @@ process LINX_VISUALISER { cat <<-END_VERSIONS > versions.yml "${task.process}": - linx: \$(java -jar ${task.ext.jarPath} | sed 's/^.*Linx version: //') + linx: \$(linx -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/linxreport/environment.yml b/modules/local/linxreport/environment.yml new file mode 100644 index 00000000..33d28665 --- /dev/null +++ b/modules/local/linxreport/environment.yml @@ -0,0 +1,7 @@ +name: linxreport +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::r-linxreport=1.0.0 diff --git a/modules/local/gpgr/linx/main.nf b/modules/local/linxreport/main.nf similarity index 75% rename from modules/local/gpgr/linx/main.nf rename to modules/local/linxreport/main.nf index af78e438..9d830a36 100644 --- a/modules/local/gpgr/linx/main.nf +++ b/modules/local/linxreport/main.nf @@ -1,8 +1,11 @@ -process GPGR_LINX { +process LINXREPORT { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/gpgr:1.5.0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/r-linxreport:1.0.0--r43hdfd78af_0' : + 'quay.io/biocontainers/r-linxreport:1.0.0--r43hdfd78af_0' }" input: tuple val(meta), path(linx_annotation_dir), path(linx_visualiser_dir) @@ -25,7 +28,7 @@ process GPGR_LINX { mkdir -p ${plot_dir}/; fi; - gpgr.R linx \\ + linxreport.R \\ ${args} \\ --sample ${meta.sample_id} \\ --plot ${plot_dir}/ \\ @@ -35,7 +38,7 @@ process GPGR_LINX { cat <<-END_VERSIONS > versions.yml "${task.process}": R: \$(R --version | head -n1 | sed 's/^R version \\([0-9.]\\+\\).\\+/\\1/') - gpgr: \$(gpgr.R --version | cut -f2 -d' ') + linxreport: \$(linxreport.R --version) END_VERSIONS """ diff --git a/modules/local/gpgr/linx/meta.yml b/modules/local/linxreport/meta.yml similarity index 76% rename from modules/local/gpgr/linx/meta.yml rename to modules/local/linxreport/meta.yml index 1d6efba9..7bf2e0ab 100644 --- a/modules/local/gpgr/linx/meta.yml +++ b/modules/local/linxreport/meta.yml @@ -1,15 +1,15 @@ -name: gpgr_linx -description: Create an interactive report for LINX +name: linxreport +description: LINX result reporter keywords: - report - linx - sv - cnv tools: - - gpgr: - description: Create interactive reports from genomic data - homepage: https://github.com/umccr/gpgr - documentation: https://github.com/umccr/gpgr + - linxreport: + description: LINX result reporter + homepage: https://github.com/umccr/linxreport + documentation: https://github.com/umccr/linxreport licence: ["MIT"] input: - meta: diff --git a/modules/local/orange/Dockerfile b/modules/local/orange/Dockerfile deleted file mode 100644 index 9ab9e442..00000000 --- a/modules/local/orange/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/orange/ && \ - wget -O /opt/orange/orange.jar 'https://github.com/hartwigmedical/hmftools/releases/download/orange-v2.7.0/orange_v2.7.0.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'openjdk >=8' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/orange/environment.yml b/modules/local/orange/environment.yml new file mode 100644 index 00000000..eaaddf49 --- /dev/null +++ b/modules/local/orange/environment.yml @@ -0,0 +1,7 @@ +name: orange +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::orange=2.7.1 diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index b5f015d9..d36b1651 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -2,7 +2,10 @@ process ORANGE { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/orange:2.7.0--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-orange:2.7.1--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-orange:2.7.1--hdfd78af_0' }" input: tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_somatic_dir), path(sage_germline_dir), path(smlv_somatic_vcf), path(smlv_germline_vcf), path(purple_dir), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter_dir), path(chord_dir), path(sigs_dir), path(lilac_dir), path(cuppa_dir), path(isofox_dir) @@ -93,53 +96,58 @@ process ORANGE { mkdir -p output/ + # NOTE(SW): manually locating ORANGE install directory so that we can applu `--add-opens`, won't fix old bioconda recipe + orange_bin_fp=\$(which orange) + orange_install_dir=\$(readlink \${orange_bin_fp} | xargs dirname) + orange_jar=\$(dirname \${orange_bin_fp})/\${orange_install_dir}/orange.jar + java \\ --add-opens java.base/java.time=ALL-UNNAMED \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - \\ - -experiment_date \$(date +%y%m%d) \\ - -add_disclaimer \\ - -pipeline_version_file pipeline_version.txt \\ - \\ - -tumor_sample_id ${meta.tumor_id} \\ - -primary_tumor_doids 162 \\ - -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ - -tumor_sample_flagstat_file ${flagstat_somatic} \\ - -sage_dir ${sage_somatic_dir} \\ - -purple_dir \${purple_dir_local} \\ - -purple_plot_dir \${purple_dir_local}/plot/ \\ - -linx_dir ${linx_somatic_anno_dir} \\ - -linx_plot_dir ${plot_dir}/ \\ - -lilac_dir ${lilac_dir} \\ - ${virus_dir_arg} \\ - ${chord_dir_arg} \\ - ${sigs_dir_arg} \\ - ${cuppa_dir_arg} \\ - \\ - ${normal_id_arg} \\ - ${normal_metrics_arg} \\ - ${normal_flagstat_arg} \\ - ${normal_sage_dir} \\ - ${normal_linx_arg} \\ - \\ - ${rna_id_arg} \\ - ${isofox_dir_arg} \\ - \\ - -ref_genome_version ${genome_ver} \\ - -doid_json ${disease_ontology} \\ - -cohort_mapping_tsv ${cohort_mapping} \\ - -cohort_percentiles_tsv ${cohort_percentiles} \\ - -known_fusion_file ${known_fusion_data} \\ - -driver_gene_panel ${driver_gene_panel} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - ${isofox_gene_distribution_arg} \\ - ${isofox_alt_sj_arg} \\ - -output_dir output/ + -jar \${orange_jar} \\ + \\ + -experiment_date \$(date +%y%m%d) \\ + -add_disclaimer \\ + -pipeline_version_file pipeline_version.txt \\ + \\ + -tumor_sample_id ${meta.tumor_id} \\ + -primary_tumor_doids 162 \\ + -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ + -tumor_sample_flagstat_file ${flagstat_somatic} \\ + -sage_dir ${sage_somatic_dir} \\ + -purple_dir \${purple_dir_local} \\ + -purple_plot_dir \${purple_dir_local}/plot/ \\ + -linx_dir ${linx_somatic_anno_dir} \\ + -linx_plot_dir ${plot_dir}/ \\ + -lilac_dir ${lilac_dir} \\ + ${virus_dir_arg} \\ + ${chord_dir_arg} \\ + ${sigs_dir_arg} \\ + ${cuppa_dir_arg} \\ + \\ + ${normal_id_arg} \\ + ${normal_metrics_arg} \\ + ${normal_flagstat_arg} \\ + ${normal_sage_dir} \\ + ${normal_linx_arg} \\ + \\ + ${rna_id_arg} \\ + ${isofox_dir_arg} \\ + \\ + -ref_genome_version ${genome_ver} \\ + -doid_json ${disease_ontology} \\ + -cohort_mapping_tsv ${cohort_mapping} \\ + -cohort_percentiles_tsv ${cohort_percentiles} \\ + -known_fusion_file ${known_fusion_data} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + ${isofox_gene_distribution_arg} \\ + ${isofox_alt_sj_arg} \\ + -output_dir output/ cat <<-END_VERSIONS > versions.yml "${task.process}": - orange: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + orange: \$(orange -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/pave/Dockerfile b/modules/local/pave/Dockerfile deleted file mode 100644 index a52a4303..00000000 --- a/modules/local/pave/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/pave/ && \ - wget -O /opt/pave/pave.jar 'https://github.com/hartwigmedical/hmftools/releases/download/pave-v1.6/pave_v1.6.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'openjdk >=8' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/pave/environment.yml b/modules/local/pave/environment.yml new file mode 100644 index 00000000..261570a1 --- /dev/null +++ b/modules/local/pave/environment.yml @@ -0,0 +1,7 @@ +name: pave +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::pave=1.6 diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 941ec61c..614f38a8 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -6,7 +6,10 @@ process PAVE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.6--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-pave:1.6--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-pave:1.6--hdfd78af_0' }" input: tuple val(meta), path(sage_vcf), path(sage_tbi) @@ -42,29 +45,28 @@ process PAVE_GERMLINE { } """ - java \\ + pave \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -sample ${meta.sample_id} \\ - -vcf_file ${sage_vcf} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -clinvar_vcf ${clinvar_annotations} \\ - -driver_gene_panel ${driver_gene_panel} \\ - -mappability_bed ${segment_mappability} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - -blacklist_bed ${sage_blocklist_regions} \\ - -blacklist_vcf ${sage_blocklist_sites} \\ - -gnomad_pon_filter -1 \\ - ${gnomad_args} \\ - -read_pass_only \\ - -threads ${task.cpus} \\ - -output_dir ./ + ${args} \\ + -sample ${meta.sample_id} \\ + -vcf_file ${sage_vcf} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -clinvar_vcf ${clinvar_annotations} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -mappability_bed ${segment_mappability} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + -blacklist_bed ${sage_blocklist_regions} \\ + -blacklist_vcf ${sage_blocklist_sites} \\ + -gnomad_pon_filter -1 \\ + ${gnomad_args} \\ + -read_pass_only \\ + -threads ${task.cpus} \\ + -output_dir ./ cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + pave: \$(pave -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index bad69a56..6101928c 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -2,7 +2,10 @@ process PAVE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/pave:1.6--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-pave:1.6--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-pave:1.6--hdfd78af_0' }" input: tuple val(meta), path(sage_vcf), path(sage_tbi) @@ -51,31 +54,30 @@ process PAVE_SOMATIC { def clinvar_annotations = clinvar_annotations ? "-clinvar_vcf ${clinvar_annotations}" : '' """ - java \\ + pave \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - -sample ${meta.sample_id} \\ - -vcf_file ${sage_vcf} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -pon_file ${sage_pon} \\ - -pon_filters "${pon_filters}" \\ - ${pon_artefact_arg} \\ - ${clinvar_annotations} \\ - -driver_gene_panel ${driver_gene_panel} \\ - -mappability_bed ${segment_mappability} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - ${sage_blocklist_regions_arg} \\ - ${sage_blocklist_sites_arg} \\ - ${pathogenic_pass_force_arg} \\ - ${gnomad_args} \\ - -read_pass_only \\ - -threads ${task.cpus} \\ - -output_dir ./ + -sample ${meta.sample_id} \\ + -vcf_file ${sage_vcf} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -pon_file ${sage_pon} \\ + -pon_filters "${pon_filters}" \\ + ${pon_artefact_arg} \\ + ${clinvar_annotations} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -mappability_bed ${segment_mappability} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + ${sage_blocklist_regions_arg} \\ + ${sage_blocklist_sites_arg} \\ + ${pathogenic_pass_force_arg} \\ + ${gnomad_args} \\ + -read_pass_only \\ + -threads ${task.cpus} \\ + -output_dir ./ cat <<-END_VERSIONS > versions.yml "${task.process}": - pave: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + pave: \$(pave -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/purple/Dockerfile b/modules/local/purple/Dockerfile deleted file mode 100644 index 330a907f..00000000 --- a/modules/local/purple/Dockerfile +++ /dev/null @@ -1,32 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/purple/ && \ - wget -O /opt/purple/purple.jar 'https://github.com/hartwigmedical/hmftools/releases/download/purple-v4.0/purple_v4.0.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - bcftools \ - bioconductor-variantannotation \ - 'circos >=0.69.6' \ - 'openjdk >=8' \ - r-cairo \ - r-cowplot \ - r-dplyr \ - r-ggplot2 \ - r-tidyr \ - xorg-libxtst \ - zlib && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/purple/environment.yml b/modules/local/purple/environment.yml new file mode 100644 index 00000000..b5c9e755 --- /dev/null +++ b/modules/local/purple/environment.yml @@ -0,0 +1,7 @@ +name: purple +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::purple=4.0 diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index a2ab0243..57048656 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -2,7 +2,10 @@ process PURPLE { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/purple:4.0--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-purple:4.0--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-purple:4.0--hdfd78af_0' }" input: tuple val(meta), path(amber), path(cobalt), path(sv_tumor_vcf), path(sv_tumor_tbi), path(sv_tumor_unfiltered_vcf), path(sv_tumor_unfiltered_tbi), path(sv_normal_vcf), path(sv_normal_tbi), path(smlv_tumor_vcf), path(smlv_normal_vcf) @@ -48,37 +51,36 @@ process PURPLE { def target_region_msi_indels_arg = target_region_msi_indels ? "-target_regions_msi_indels ${target_region_msi_indels}" : '' """ - java \\ + purple \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -tumor ${meta.tumor_id} \\ - ${reference_arg} \\ - -amber ${amber} \\ - -cobalt ${cobalt} \\ - ${sv_tumor_vcf_arg} \\ - ${sv_normal_vcf_arg} \\ - ${sv_tumor_recovery_vcf_arg} \\ - ${smlv_tumor_vcf_arg} \\ - ${smlv_normal_vcf_arg} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -driver_gene_panel ${driver_gene_panel} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - -somatic_hotspots ${sage_known_hotspots_somatic} \\ - ${sage_known_hotspots_germline_arg} \\ - ${target_region_bed_arg} \\ - ${target_region_ratios_arg} \\ - ${target_region_msi_indels_arg} \\ - ${germline_del_arg} \\ - -gc_profile ${gc_profile} \\ - -circos ${task.ext.circosPath} \\ - -threads ${task.cpus} \\ - -output_dir purple/ + ${args} \\ + -tumor ${meta.tumor_id} \\ + ${reference_arg} \\ + -amber ${amber} \\ + -cobalt ${cobalt} \\ + ${sv_tumor_vcf_arg} \\ + ${sv_normal_vcf_arg} \\ + ${sv_tumor_recovery_vcf_arg} \\ + ${smlv_tumor_vcf_arg} \\ + ${smlv_normal_vcf_arg} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + -somatic_hotspots ${sage_known_hotspots_somatic} \\ + ${sage_known_hotspots_germline_arg} \\ + ${target_region_bed_arg} \\ + ${target_region_ratios_arg} \\ + ${target_region_msi_indels_arg} \\ + ${germline_del_arg} \\ + -gc_profile ${gc_profile} \\ + -circos \$(which circos) \\ + -threads ${task.cpus} \\ + -output_dir purple/ cat <<-END_VERSIONS > versions.yml "${task.process}": - purple: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + purple: \$(purple -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/sage/Dockerfile b/modules/local/sage/Dockerfile deleted file mode 100644 index f680ee98..00000000 --- a/modules/local/sage/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/sage/ && \ - wget -O /opt/sage/sage.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sage-v3.4/sage_v3.4.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'bcftools ==1.16' \ - bioconductor-genomicranges \ - bioconductor-variantannotation \ - font-ttf-dejavu \ - 'openjdk >=8' \ - r-dplyr \ - r-ggplot2 \ - r-tidyr \ - xorg-libxt \ - zlib && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index 0d392603..5b3bb554 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -2,7 +2,10 @@ process SAGE_APPEND { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.4--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : + 'quay.io/biocontainers/hmftools-sage:3.4--hdfd78af_1' }" input: tuple val(meta), path(vcf), path(bam), path(bai) @@ -22,21 +25,21 @@ process SAGE_APPEND { def args = task.ext.args ?: '' """ - java \\ + sage \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -cp ${task.ext.jarPath} com.hartwig.hmftools.sage.append.SageAppendApplication \\ - ${args} \\ - -input_vcf ${vcf} \\ - -reference ${meta.tumor_rna_id} \\ - -reference_bam ${bam} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -threads ${task.cpus} \\ - -output_vcf ${meta.dna_id}.sage.append.vcf.gz + com.hartwig.hmftools.sage.append.SageAppendApplication \\ + ${args} \\ + -input_vcf ${vcf} \\ + -reference ${meta.tumor_rna_id} \\ + -reference_bam ${bam} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -threads ${task.cpus} \\ + -output_vcf ${meta.dna_id}.sage.append.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + sage: \$(sage -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/sage/environment.yml b/modules/local/sage/environment.yml new file mode 100644 index 00000000..c23a68be --- /dev/null +++ b/modules/local/sage/environment.yml @@ -0,0 +1,7 @@ +name: sage +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::sage=3.4=hdfd78af_1 diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index fe110f2d..af5a51e0 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -2,7 +2,10 @@ process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.4--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : + 'quay.io/biocontainers/hmftools-sage:3.4--hdfd78af_1' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -30,37 +33,36 @@ process SAGE_GERMLINE { """ mkdir germline/ - java \\ + sage \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -tumor ${meta.normal_id} \\ - -tumor_bam ${normal_bam} \\ - -reference ${meta.tumor_id} \\ - -reference_bam ${tumor_bam} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -hotspots ${sage_known_hotspots_germline} \\ - -panel_bed ${sage_actionable_panel} \\ - -coverage_bed ${sage_coverage_panel} \\ - -high_confidence_bed ${sage_highconf_regions} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - -hotspot_min_tumor_qual 50 \\ - -panel_min_tumor_qual 75 \\ - -hotspot_max_germline_vaf 100 \\ - -hotspot_max_germline_rel_raw_base_qual 100 \\ - -panel_max_germline_vaf 100 \\ - -panel_max_germline_rel_raw_base_qual 100 \\ - -ref_sample_count 0 \\ - -panel_only \\ - -write_bqr_data \\ - -write_bqr_plot \\ - -threads ${task.cpus} \\ - -output_vcf germline/${meta.tumor_id}.sage.germline.vcf.gz + ${args} \\ + -tumor ${meta.normal_id} \\ + -tumor_bam ${normal_bam} \\ + -reference ${meta.tumor_id} \\ + -reference_bam ${tumor_bam} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -hotspots ${sage_known_hotspots_germline} \\ + -panel_bed ${sage_actionable_panel} \\ + -coverage_bed ${sage_coverage_panel} \\ + -high_confidence_bed ${sage_highconf_regions} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + -hotspot_min_tumor_qual 50 \\ + -panel_min_tumor_qual 75 \\ + -hotspot_max_germline_vaf 100 \\ + -hotspot_max_germline_rel_raw_base_qual 100 \\ + -panel_max_germline_vaf 100 \\ + -panel_max_germline_rel_raw_base_qual 100 \\ + -ref_sample_count 0 \\ + -panel_only \\ + -write_bqr_data \\ + -write_bqr_plot \\ + -threads ${task.cpus} \\ + -output_vcf germline/${meta.tumor_id}.sage.germline.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + sage: \$(sage -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 3b545943..5ade66ae 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -4,7 +4,10 @@ process SAGE_SOMATIC { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/sage:3.4--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : + 'quay.io/biocontainers/hmftools-sage:3.4--hdfd78af_1' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) @@ -35,29 +38,28 @@ process SAGE_SOMATIC { """ mkdir -p somatic/ - java \\ + sage \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - ${reference_arg} \\ - ${reference_bam_arg} \\ - -tumor ${meta.tumor_id} \\ - -tumor_bam ${tumor_bam} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -hotspots ${sage_known_hotspots_somatic} \\ - -panel_bed ${sage_actionable_panel} \\ - -coverage_bed ${sage_coverage_panel} \\ - -high_confidence_bed ${sage_highconf_regions} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - -write_bqr_data \\ - -write_bqr_plot \\ - -threads ${task.cpus} \\ - -output_vcf somatic/${meta.tumor_id}.sage.somatic.vcf.gz + ${args} \\ + ${reference_arg} \\ + ${reference_bam_arg} \\ + -tumor ${meta.tumor_id} \\ + -tumor_bam ${tumor_bam} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -hotspots ${sage_known_hotspots_somatic} \\ + -panel_bed ${sage_actionable_panel} \\ + -coverage_bed ${sage_coverage_panel} \\ + -high_confidence_bed ${sage_highconf_regions} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + -write_bqr_data \\ + -write_bqr_plot \\ + -threads ${task.cpus} \\ + -output_vcf somatic/${meta.tumor_id}.sage.somatic.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": - sage: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + sage: \$(sage -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/sigs/Dockerfile b/modules/local/sigs/Dockerfile deleted file mode 100644 index 33961024..00000000 --- a/modules/local/sigs/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/sigs/ && \ - wget -O /opt/sigs/sigs.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sigs-v1.2.1/sigs_v1.2.1.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'openjdk >=8' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/sigs/environment.yml b/modules/local/sigs/environment.yml new file mode 100644 index 00000000..8db3831a --- /dev/null +++ b/modules/local/sigs/environment.yml @@ -0,0 +1,7 @@ +name: sigs +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::r-sigs=1.2.1 diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 47971e67..56a011e9 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -2,7 +2,10 @@ process SIGS { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/sigs:1.2.1--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-sigs:1.2.1--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-sigs:1.2.1--hdfd78af_0' }" input: tuple val(meta), path(smlv_vcf) @@ -21,17 +24,16 @@ process SIGS { """ mkdir -p sigs/ - java \\ + sigs \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - -sample ${meta.sample_id} \\ - -somatic_vcf_file ${smlv_vcf} \\ - -signatures_file ${signatures} \\ - -output_dir sigs/ + -sample ${meta.sample_id} \\ + -somatic_vcf_file ${smlv_vcf} \\ + -signatures_file ${signatures} \\ + -output_dir sigs/ cat <<-END_VERSIONS > versions.yml "${task.process}": - sigs: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + sigs: \$(sigs -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/svprep/Dockerfile b/modules/local/svprep/Dockerfile deleted file mode 100644 index d330cc15..00000000 --- a/modules/local/svprep/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM docker.io/scwatts/gridss:2.13.2--3 - -ARG GH_BASE_URL='https://github.com/hartwigmedical/hmftools' -USER root - -RUN \ - apt-get update && \ - apt-get install -y patch && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/svprep/ && \ - wget -O /opt/svprep/svprep.jar 'https://github.com/hartwigmedical/hmftools/releases/download/sv-prep-v1.2.3/sv-prep_v1.2.3.jar' && \ - wget -O /opt/svprep/gridss_svprep 'https://raw.githubusercontent.com/hartwigmedical/hmftools/sv-prep-v1.2.3/sv-prep/src/main/resources/gridss/gridss.run.sh' - -COPY assets/gridss_svprep.patch /tmp/ -RUN \ - patch -lp1 -i /tmp/gridss_svprep.patch /opt/svprep/gridss_svprep && \ - chmod 755 /opt/svprep/gridss_svprep && \ - ln -s /opt/svprep/gridss_svprep /usr/local/bin/ - -USER mambauser diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 2bda4d80..caf294e4 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -2,7 +2,10 @@ process GRIDSS_ASSEMBLE { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.3--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : + 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) @@ -68,7 +71,6 @@ process GRIDSS_ASSEMBLE { ${args} \\ --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ - --jar ${task.ext.jarPathGridss} \\ --steps assemble \\ --labels ${labels_arg} \\ --reference ${genome_fasta} \\ @@ -82,8 +84,8 @@ process GRIDSS_ASSEMBLE { cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp ${task.ext.jarPathGridss} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - svprep: \$(java -jar ${task.ext.jarPathSvPrep} -version | sed 's/^.* //') + gridss: \$(CallVariants --version 2>&1 | sed 's/-gridss\$//') + svprep: \$(svprep -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/svprep/assets/gridss_svprep.patch b/modules/local/svprep/assets/gridss_svprep.patch deleted file mode 100644 index e8e1cb7e..00000000 --- a/modules/local/svprep/assets/gridss_svprep.patch +++ /dev/null @@ -1,139 +0,0 @@ ---- a/gridss.run.sh 2023-05-02 11:27:25 -+++ b/gridss.run.sh 2023-05-02 11:30:08 -@@ -48,13 +48,15 @@ - - -r/--reference: reference genome to use. - -o/--output: output VCF. -+ -a/--assembly: location of the GRIDSS assembly BAM. This file will be -+ created by GRIDSS. - -t/--threads: number of threads to use. (Default: $threads) - -j/--jar: location of GRIDSS jar - -w/--workingdir: directory to place GRIDSS intermediate and temporary files - .gridss.working subdirectories will be created. (Default: $workingdir) - -s/--steps: processing steps to run. Defaults to all steps. - Multiple steps are specified using comma separators. Possible steps are: -- preprocess, assemble, calling, all -+ preprocess, assemble, call, all - -e/--blacklist: BED file containing regions to ignore - -c/--configuration: configuration file use to override default GRIDSS - settings. -@@ -69,10 +71,14 @@ - -b/bams: comma separated full-path BAM files - -f/filtered_bams: comma separated full-path filtered BAM files - --jvmheap: size of JVM heap for the high-memory component of assembly and variant calling. (Default: $jvmheap) -+ --otherjvmheap: size of JVM heap for everything else. Useful to prevent -+ java out of memory errors when using large (>4Gb) reference genomes. -+ Note that some parts of assembly and variant calling use this heap -+ size. (Default: $otherjvmheap) - " - --OPTIONS=r:o:t:j:w:e:s:c:l:b:f: --LONGOPTS=reference:,output:,threads:,jar:,workingdir:,jvmheap:,blacklist:,steps:,configuration:,labels:,bams:,filtered_bams: -+OPTIONS=r:o:a:t:j:w:e:s:c:l:b:f: -+LONGOPTS=reference:,output:,assembly:,threads:,jar:,workingdir:,jvmheap:,otherjvmheap:,blacklist:,steps:,configuration:,labels:,bams:,filtered_bams: - ! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") - if [[ ${PIPESTATUS[0]} -ne 0 ]]; then - # e.g. return value is 1 -@@ -115,6 +121,15 @@ - output_vcf="$2" - shift 2 - ;; -+ -a|--assembly) -+ if [[ "$assembly" == "" ]] ; then -+ assembly="$2" -+ else -+ assembly="$assembly $2" -+ fi -+ # TODO: support multiple assembly files -+ shift 2 -+ ;; - -e|--blacklist) - blacklist="$2" - shift 2 -@@ -127,6 +142,10 @@ - jvmheap="$2" - shift 2 - ;; -+ --otherjvmheap) -+ otherjvmheap="$2" -+ shift 2 -+ ;; - -t|--threads) - printf -v threads '%d\n' "$2" 2>/dev/null - printf -v threads '%d' "$2" 2>/dev/null -@@ -242,25 +261,43 @@ - write_status "Using reference genome \"$reference\"" - - ##### --output --if [[ "$output_vcf" == "" ]] ; then -- write_status "$USAGE_MESSAGE" -- write_status "Output VCF not specified. Use --output to specify output file." -- exit $EX_USAGE -+if [[ $do_call == "true" ]] ; then -+ if [[ "$output_vcf" == "" ]] ; then -+ write_status "$USAGE_MESSAGE" -+ write_status "Output VCF not specified. Use --output to specify output file." -+ exit $EX_USAGE -+ fi -+ mkdir -p $(dirname $output_vcf) -+ if [[ ! -d $(dirname $output_vcf) ]] ; then -+ write_status "Unable to create directory for $output_vcf for output VCF." -+ exit $EX_CANTCREAT -+ fi -+ write_status "Using output VCF $output_vcf" - fi --mkdir -p $(dirname $output_vcf) --if [[ ! -d $(dirname $output_vcf) ]] ; then -- write_status "Unable to create directory for $output_vcf for output VCF." -- exit $EX_CANTCREAT --fi --write_status "Using output VCF $output_vcf" - - ##### --assembly --assembly=$output_vcf.assembly.bam --write_status "Using assembly bam $assembly" --mkdir -p $(dirname $assembly) --if [[ ! -d $(dirname $assembly) ]] ; then -- write_status "Unable to parent create directory for $assembly" -- exit $EX_CANTCREAT -+if [[ $do_assemble == "true" ]] || [[ $do_call == "true" ]]; then -+ if [[ "$assembly" == "" ]] ; then -+ if [[ "$output_vcf" == "" ]] ; then -+ write_status "Either the assembly output file must explicitly specified with -a, or the output VCF specified with -o" -+ exit $EX_USAGE -+ fi -+ assembly=$output_vcf.assembly.bam -+ fi -+ write_status "Using assembly bam $assembly" -+ if [[ $do_assemble == "true" ]] ; then -+ mkdir -p $(dirname $assembly) -+ if [[ ! -d $(dirname $assembly) ]] ; then -+ write_status "Unable to parent create directory for $assembly" -+ exit $EX_CANTCREAT -+ fi -+ else -+ if [[ ! -f $assembly ]] ; then -+ write_status "Missing assembly file $assembly" -+ write_status "Ensure the GRIDSS assembly step has been run" -+ exit $EX_NOINPUT -+ fi -+ fi - fi - - ##### --threads -@@ -433,12 +470,12 @@ - elif [[ "$step" == "preprocess" ]] ; then - do_preprocess=true - steps_message="$steps_message pre-process" -- elif [[ "$step" == "assembly" ]] ; then -+ elif [[ "$step" == "assemble" ]] ; then - do_assemble=true - steps_message="$steps_message assembly" -- elif [[ "$step" == "calling" ]] ; then -+ elif [[ "$step" == "call" ]] ; then - do_call=true -- steps_message="$steps_message calling" -+ steps_message="$steps_message call" - else - write_status "Unknown step \"$step\"" - exit $EX_USAGE diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 5ed13ce6..de0dd0d4 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -2,7 +2,10 @@ process GRIDSS_CALL { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.3--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : + 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) @@ -66,7 +69,6 @@ process GRIDSS_CALL { ${args} \\ --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ - --jar ${task.ext.jarPathGridss} \\ --steps call \\ --labels ${labels_arg} \\ --reference ${genome_fasta} \\ @@ -81,8 +83,8 @@ process GRIDSS_CALL { cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp ${task.ext.jarPathGridss} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - svprep: \$(java -jar ${task.ext.jarPathSvPrep} -version | sed 's/^.* //') + gridss: \$(CallVariants --version 2>&1 | sed 's/-gridss\$//') + svprep: \$(svprep -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 5103bbdb..cc38ff25 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -2,7 +2,10 @@ process SVPREP_DEPTH_ANNOTATOR { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.3--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : + 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" input: tuple val(meta), path(bams), path(bais), path(vcf), val(labels) @@ -26,21 +29,21 @@ process SVPREP_DEPTH_ANNOTATOR { def bams_arg = "${bams_list.join(',')}" """ - java \\ + svprep \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -cp ${task.ext.jarPath} com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ - ${args} \\ - -input_vcf ${vcf} \\ - -samples ${labels_arg} \\ - -bam_files ${bams_arg} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -threads ${task.cpus} \\ - -output_vcf ${meta.tumor_id}.gridss.vcf.gz + com.hartwig.hmftools.svprep.depth.DepthAnnotator \\ + ${args} \\ + -input_vcf ${vcf} \\ + -samples ${labels_arg} \\ + -bam_files ${bams_arg} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -threads ${task.cpus} \\ + -output_vcf ${meta.tumor_id}.gridss.vcf.gz cat <<-END_VERSIONS > versions.yml "${task.process}": - svprep: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + svprep: \$(svprep -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/svprep/environment.yml b/modules/local/svprep/environment.yml new file mode 100644 index 00000000..98c00d65 --- /dev/null +++ b/modules/local/svprep/environment.yml @@ -0,0 +1,7 @@ +name: svprep +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::sv-prep=1.2.3=hdfd78af_1 diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index ac7a598a..2d4f4791 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -2,7 +2,10 @@ process GRIDSS_PREPROCESS { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.3--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : + 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" input: tuple val(meta), path(bam), path(bam_filtered) @@ -32,7 +35,6 @@ process GRIDSS_PREPROCESS { gridss_svprep \\ ${args} \\ --jvmheap ${Math.round(task.memory.bytes * 0.95)} \\ - --jar ${task.ext.jarPathGridss} \\ --steps preprocess \\ --reference ${genome_fasta} \\ --workingdir gridss_preprocess/ \\ @@ -45,8 +47,8 @@ process GRIDSS_PREPROCESS { cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp ${task.ext.jarPathGridss} gridss.CallVariants --version 2>&1 | sed 's/-gridss//') - svprep: \$(java -jar ${task.ext.jarPathSvPrep} -version | sed 's/^.* //') + gridss: \$(CallVariants --version 2>&1 | sed 's/-gridss\$//') + svprep: \$(svprep -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 09cc5751..99181316 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -2,7 +2,10 @@ process SVPREP { tag "${meta.id}" label 'process_medium' - container 'docker.io/scwatts/svprep:1.2.3--0' + conda "${moduleDir}/../environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : + 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" input: tuple val(meta), path(bam), path(bai), path(junctions) @@ -26,20 +29,19 @@ process SVPREP { def existing_juction_file_arg = junctions ? "-existing_junction_file ${junctions}" : '' """ - java \\ + svprep \\ -Xmx${Math.round(task.memory.bytes * 0.75)} \\ - -jar ${task.ext.jarPath} \\ - ${args} \\ - -sample ${meta.sample_id} \\ - -bam_file ${bam} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - -blacklist_bed ${sv_blocklist} \\ - -known_fusion_bed ${known_fusions} \\ - ${write_types_arg} \\ - ${existing_juction_file_arg} \\ - -threads ${task.cpus} \\ - -output_dir ./ + ${args} \\ + -sample ${meta.sample_id} \\ + -bam_file ${bam} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + -blacklist_bed ${sv_blocklist} \\ + -known_fusion_bed ${known_fusions} \\ + ${write_types_arg} \\ + ${existing_juction_file_arg} \\ + -threads ${task.cpus} \\ + -output_dir ./ samtools sort \\ -@ ${task.cpus} \\ @@ -49,7 +51,7 @@ process SVPREP { cat <<-END_VERSIONS > versions.yml "${task.process}": - svprep: \$(java -jar ${task.ext.jarPath} -version | sed 's/^.* //') + svprep: \$(svprep -version | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/virusbreakend/environment.yml b/modules/local/virusbreakend/environment.yml new file mode 100644 index 00000000..cb3dd2e9 --- /dev/null +++ b/modules/local/virusbreakend/environment.yml @@ -0,0 +1,7 @@ +name: virusbreakend +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::gridss=2.13.2=h50ea8bc_3 diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 360942ff..64195c3c 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -4,7 +4,10 @@ process VIRUSBREAKEND { tag "${meta.id}" label 'process_high' - container 'docker.io/scwatts/gridss:2.13.2--3' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/gridss:2.13.2--h50ea8bc_3': + 'quay.io/biocontainers/gridss:2.13.2--h50ea8bc_3' }" input: tuple val(meta), path(bam) @@ -33,7 +36,6 @@ process VIRUSBREAKEND { ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ virusbreakend \\ - --jar ${task.ext.jarPath} \\ --gridssargs "--jvmheap ${Math.round(task.memory.bytes * 0.95)}" \\ --threads ${task.cpus} \\ --db ${virusbreakenddb.toString().replaceAll("/\$", "")}/ \\ @@ -43,7 +45,7 @@ process VIRUSBREAKEND { cat <<-END_VERSIONS > versions.yml "${task.process}": - gridss: \$(java -cp "${task.ext.jarPath}" gridss.CallVariants --version 2>&1 | sed 's/-gridss//') + gridss: \$(CallVariants --version 2>&1 | sed 's/-gridss\$//') END_VERSIONS """ diff --git a/modules/local/virusinterpreter/Dockerfile b/modules/local/virusinterpreter/Dockerfile deleted file mode 100644 index 9a23603d..00000000 --- a/modules/local/virusinterpreter/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN \ - mkdir -p /opt/virusinterpreter/ && \ - wget -O /opt/virusinterpreter/virusinterpreter.jar 'https://github.com/hartwigmedical/hmftools/releases/download/virus-interpreter-v1.3/virus-interpreter_v1.3.jar' - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'openjdk >=8' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/virusinterpreter/environment.yml b/modules/local/virusinterpreter/environment.yml new file mode 100644 index 00000000..c84193a8 --- /dev/null +++ b/modules/local/virusinterpreter/environment.yml @@ -0,0 +1,7 @@ +name: virusinterpreter +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::virus-interpreter=1.3 diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index 29526576..0d788545 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -2,7 +2,10 @@ process VIRUSINTERPRETER { tag "${meta.id}" label 'process_single' - container 'docker.io/scwatts/virus_interpreter:1.3--0' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-virus-interpreter:1.3--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-virus-interpreter:1.3--hdfd78af_0' }" input: tuple val(meta), path(virus_tsv), path(purple_dir), path(wgs_metrics) @@ -22,20 +25,19 @@ process VIRUSINTERPRETER { """ mkdir -p virusinterpreter/ - java \\ + virusinterpreter \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar ${task.ext.jarPath} \\ - -sample ${meta.sample_id} \\ - -purple_dir ${purple_dir} \\ - -tumor_sample_wgs_metrics_file ${wgs_metrics} \\ - -virus_breakend_tsv ${virus_tsv} \\ - -taxonomy_db_tsv ${taxonomy_db} \\ - -virus_reporting_db_tsv ${reporting_db} \\ - -output_dir virusinterpreter/ + -sample ${meta.sample_id} \\ + -purple_dir ${purple_dir} \\ + -tumor_sample_wgs_metrics_file ${wgs_metrics} \\ + -virus_breakend_tsv ${virus_tsv} \\ + -taxonomy_db_tsv ${taxonomy_db} \\ + -virus_reporting_db_tsv ${reporting_db} \\ + -output_dir virusinterpreter/ cat <<-END_VERSIONS > versions.yml "${task.process}": - "virus interpreter": \$(java -jar "${task.ext.jarPath}" | sed -n '1s/^.*Interpreter v//p') + virusinterpreter: \$(virusinterpreter | sed -n '1s/^.*Interpreter v//p') END_VERSIONS """ diff --git a/subworkflows/local/linx_plotting.nf b/subworkflows/local/linx_plotting.nf index 7853dc06..42cdd057 100644 --- a/subworkflows/local/linx_plotting.nf +++ b/subworkflows/local/linx_plotting.nf @@ -5,7 +5,7 @@ import Constants import Utils -include { GPGR_LINX as GPGR } from '../../modules/local/gpgr/linx/main' +include { LINXREPORT as REPORT } from '../../modules/local/linxreport/main' include { LINX_VISUALISER as VISUALISER } from '../../modules/local/linx/visualiser/main' workflow LINX_PLOTTING { @@ -89,11 +89,11 @@ workflow LINX_PLOTTING { } // Run process - GPGR( + REPORT( ch_gpgr_linx_inputs, ) - ch_versions = ch_versions.mix(GPGR.out.versions) + ch_versions = ch_versions.mix(REPORT.out.versions) // Set outputs, restoring original meta // channel: [ meta, visualiser_dir ] From 6c4f6b85ef3129ebb6c5d499e80bac79845808d0 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 13 Feb 2024 09:57:32 +1100 Subject: [PATCH 281/562] Properly hand filepath for index check --- lib/Utils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index d6331d5c..8af98f52 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -108,7 +108,7 @@ class Utils { return } - def fp = meta[sample_key][key] + def fp = meta[sample_key][key].toUriString() def index_fp = nextflow.Nextflow.file("${fp}.${index_str}") if (!index_fp.exists() && !stub_run) { From 3ebef22441986bdd970b4c977b5685e7e7328c9d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 13 Feb 2024 13:50:00 +1100 Subject: [PATCH 282/562] Improve JVM heap allocation in GRIDSS --- modules/local/svprep/assemble/main.nf | 10 ++++++++-- modules/local/svprep/call/main.nf | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index caf294e4..6e5d8572 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -37,6 +37,12 @@ process GRIDSS_ASSEMBLE { def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" + // JVM heap for other tasks must be no greater than 1/4 of task memory, defaults to 1 GB if not provided + def otherJvmHeap = Math.min( + Math.round(task.memory.bytes * 0.25), + task.ext.otherJvmHeap ? task.ext.otherJvmHeap.bytes : 1.GB.bytes + ) + """ # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present @@ -69,8 +75,8 @@ process GRIDSS_ASSEMBLE { # Run gridss_svprep \\ ${args} \\ - --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ - --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ + --jvmheap ${Math.round((task.memory.bytes - otherJvmHeap) * 0.95)} \\ + --otherjvmheap ${otherJvmHeap} \\ --steps assemble \\ --labels ${labels_arg} \\ --reference ${genome_fasta} \\ diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index de0dd0d4..ca2d92cb 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -37,6 +37,12 @@ process GRIDSS_CALL { def bams_filtered_list = bams_filtered instanceof List ? bams_filtered : [bams_filtered] def bams_filtered_arg = "--filtered_bams ${bams_filtered_list.join(',')}" + // JVM heap for other tasks must be no greater than 1/4 of task memory, defaults to 1 GB if not provided + def otherJvmHeap = Math.min( + Math.round(task.memory.bytes * 0.25), + task.ext.otherJvmHeap ? task.ext.otherJvmHeap.bytes : 1.GB.bytes + ) + """ # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present @@ -67,8 +73,8 @@ process GRIDSS_CALL { # Run gridss_svprep \\ ${args} \\ - --jvmheap ${Math.round((task.memory.bytes - task.ext.otherJvmHeap.bytes) * 0.95)} \\ - --otherjvmheap ${task.ext.otherJvmHeap.bytes} \\ + --jvmheap ${Math.round((task.memory.bytes - otherJvmHeap) * 0.95)} \\ + --otherjvmheap ${otherJvmHeap} \\ --steps call \\ --labels ${labels_arg} \\ --reference ${genome_fasta} \\ From 43f2a8bc836fc42fb4902d6ef25197f4a57732e9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 13 Feb 2024 16:17:19 +1100 Subject: [PATCH 283/562] Fix subworkflow inputs --- subworkflows/local/linx_annotation.nf | 2 +- subworkflows/local/sage_calling.nf | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf index 0795a72b..e5c9e26a 100644 --- a/subworkflows/local/linx_annotation.nf +++ b/subworkflows/local/linx_annotation.nf @@ -19,7 +19,7 @@ workflow LINX_ANNOTATION { ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ known_fusion_data // channel: [mandatory] /path/to/known_fusion_data driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel - gene_id_file // channel: [mandatory] /path/to/linx_gene_id_file + gene_id_file // channel: [optional] /path/to/linx_gene_id_file main: // Channel for versions.yml files diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index f0bf1c9c..5c05a511 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -26,7 +26,6 @@ workflow SAGE_CALLING { segment_mappability // channel: [mandatory] /path/to/segment_mappability driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ - ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ main: // Channel for version.yml files From 7991ef19ace5e3b0105970244a93196e56cc4840 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 11 Feb 2024 14:43:26 +1100 Subject: [PATCH 284/562] First pass on nf-test pipeline stub test --- lib/NfcoreSchema.groovy | 7 +- lib/Utils.groovy | 43 +++++++++++- main.nf | 12 ++++ modules/local/custom/extract_tarball/main.nf | 5 ++ nextflow.config | 1 + nextflow_schema.json | 6 ++ nf-test.config | 5 ++ subworkflows/local/prepare_inputs.nf | 26 ++++++++ tests/main.stub.nf.test | 65 +++++++++++++++++++ tests/main.stub.nf.test.config | 14 ++++ .../targeted.tso500.dna_rna.single.csv | 3 + tests/samplesheets/wgts.dna.single.csv | 3 + tests/samplesheets/wgts.dna_rna.single.csv | 4 ++ .../local/amber_profiling.nf.test | 43 ++++++++++++ 14 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 nf-test.config create mode 100644 subworkflows/local/prepare_inputs.nf create mode 100644 tests/main.stub.nf.test create mode 100644 tests/main.stub.nf.test.config create mode 100644 tests/samplesheets/targeted.tso500.dna_rna.single.csv create mode 100644 tests/samplesheets/wgts.dna.single.csv create mode 100644 tests/samplesheets/wgts.dna_rna.single.csv create mode 100644 tests/subworkflows/local/amber_profiling.nf.test diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy index b3d092f8..ab81e360 100755 --- a/lib/NfcoreSchema.groovy +++ b/lib/NfcoreSchema.groovy @@ -29,7 +29,12 @@ class NfcoreSchema { def has_error = false //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// // Check for nextflow core params and unexpected params - def json = new File(getSchemaPath(workflow, schema_filename=schema_filename)).text + def schema_fp = new File(getSchemaPath(workflow, schema_filename=schema_filename)) + if (! schema_fp.exists()) { + log.warn "Skipping parameter schema check, could not find schema at ${schema_fp}" + return + } + def json = schema_fp.text def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions') def nf_params = [ // Options for base `nextflow` command diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 8af98f52..cf2b1e0a 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -13,7 +13,7 @@ class Utils { // NOTE(SW): using Nextflow .splitCsv channel operator, hence sould be easily interchangable - def input_fp = nextflow.Nextflow.file(input_fp_str) + def input_fp = Utils.getFileObject(input_fp_str) def inputs = nextflow.splitter.SplitterEx.splitCsv(input_fp, [header: true]) .groupBy { it['group_id'] } .collect { group_id, entries -> @@ -128,6 +128,45 @@ class Utils { return inputs } + public static void createStubPlaceholders(params) { + + def fps = [ + params.ref_data_genome_fasta, + params.ref_data_genome_fai, + params.ref_data_genome_dict, + params.ref_data_genome_bwa_index, + params.ref_data_genome_bwa_index_image, + params.ref_data_genome_gridss_index, + params.ref_data_virusbreakenddb_path, + ] + + params.hmf_data_paths[params.ref_data_genome_version] + .each { k, v -> + fps << "${params.ref_data_hmf_data_path.replaceAll('/$', '')}/${v}" + } + + if(params.containsKey('panel')) { + params.panel_data_paths[params.panel][params.ref_data_genome_version] + .each { k, v -> + fps << "${params.ref_data_panel_data_path.replaceAll('/$', '')}/${v}" + } + } + + fps.each { fp_str -> + def fp = Utils.getFileObject(fp_str) + + if (!fp_str || fp.exists()) return + + if (fp_str.endsWith('/')) { + fp.mkdirs() + } else { + fp.getParent().mkdirs() + fp.toFile().createNewFile() + } + } + + } + public static void validateInput(inputs, run_config, log) { def sample_keys = [ @@ -263,7 +302,7 @@ class Utils { static public getFileObject(path) { - return path ? Nextflow.file(path) : [] + return path ? nextflow.Nextflow.file(path) : [] } diff --git a/main.nf b/main.nf index c36542a7..caa57956 100644 --- a/main.nf +++ b/main.nf @@ -39,6 +39,18 @@ WorkflowMain.setParamsDefaults(params, log) WorkflowMain.validateParams(params, log) WorkflowMain.paramsSummaryLog(workflow, params, log) +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CREATE PLACEHOLDER FILES FOR STUB RUNS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// NOTE(SW): required prior to workflow import + +if (workflow.stubRun && params.create_stub_placeholders) { + Utils.createStubPlaceholders(params) +} + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NAMED WORKFLOW FOR PIPELINE diff --git a/modules/local/custom/extract_tarball/main.nf b/modules/local/custom/extract_tarball/main.nf index d8a5f33c..989065a8 100644 --- a/modules/local/custom/extract_tarball/main.nf +++ b/modules/local/custom/extract_tarball/main.nf @@ -14,4 +14,9 @@ process CUSTOM_EXTRACTTARBALL { mkdir -p ${meta.id}/ tar -xzvf ${tarball} --strip-components 1 -C ${meta.id}/ """ + + stub: + """ + mkdir -p ${meta.id}/ + """ } diff --git a/nextflow.config b/nextflow.config index 6834fb2b..e7bc4c49 100644 --- a/nextflow.config +++ b/nextflow.config @@ -47,6 +47,7 @@ params { enable_conda = false // Other workflow inputs and options + create_stub_placeholders = false linx_gene_id_file = null isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' diff --git a/nextflow_schema.json b/nextflow_schema.json index 5fcd39d7..835ff2e3 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -76,6 +76,12 @@ "description": "Pipeline processes to include.", "fa_icon": "fas fa-diagram-project" }, + "create_stub_placeholders": { + "type": "boolean", + "description": "Create placeholders for reference data during stub run.", + "default": false, + "fa_icon": "fas fa-diagram-project" + }, "gridss_config": { "type": "string", "description": "Path to GRIDSS configuration file.", diff --git a/nf-test.config b/nf-test.config new file mode 100644 index 00000000..087e74e0 --- /dev/null +++ b/nf-test.config @@ -0,0 +1,5 @@ +config { + testsDir "tests/" + workDir ".nf-test" + configFile "" +} diff --git a/subworkflows/local/prepare_inputs.nf b/subworkflows/local/prepare_inputs.nf new file mode 100644 index 00000000..47b198e0 --- /dev/null +++ b/subworkflows/local/prepare_inputs.nf @@ -0,0 +1,26 @@ +// +// Prepare inputs (tests only) +// + +// NOTE(SW): inputs for the pipeline are prepared outside of NF +// workflow/channels to allow higher-level conditionals, however nf-test +// well-formed meta (including Constants) that can only be made available +// through running workflows/processes with 'setup'. Hence, this subworkflow +// isn't used in the main pipeline and is only used for execution of tests. + +import Constants +import Utils + +workflow PREPARE_INPUTS { + take: + input_fp_str + + main: + + ch_inputs = Channel.fromList( + Utils.parseInput(input_fp_str, workflow.stubRun, log) + ) + + emit: + inputs = ch_inputs // channel: [ meta ] +} diff --git a/tests/main.stub.nf.test b/tests/main.stub.nf.test new file mode 100644 index 00000000..4ee33022 --- /dev/null +++ b/tests/main.stub.nf.test @@ -0,0 +1,65 @@ +nextflow_pipeline { + + name "Pipeline end-to-end stub-run" + script "main.nf" + config "tests/main.stub.nf.test.config" + options "-stub-run --create_stub_placeholders" + + test("WGTS GRCh38") { + + when { + params { + mode "wgts" + genome "GRCh38_hmf" + + input "${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv" + outdir "${outputDir}" + + ref_data_virusbreakenddb_path "${workDir}/refdata/virusbreakenddb_20210401/" + ref_data_hmf_data_path "${workDir}/refdata/hmf_data/" + + max_cpus = 1 + max_memory = "10.GB" + + // NOTE(SW): create new variable for nf-test workDir so that we can use in genomes config + nfTestWorkDir = workDir + } + + } + + then { + assert workflow.success + } + + } + + test("Targeted (TSO500) GRCh38") { + + when { + params { + mode "targeted" + panel "tso500" + genome "GRCh38_hmf" + + input "${baseDir}/tests/samplesheets/targeted.tso500.dna_rna.single.csv" + outdir "${outputDir}" + + ref_data_hmf_data_path "${workDir}/refdata/hmf_data/" + ref_data_panel_data_path "${workDir}/refdata/panel_data/" + + max_cpus 1 + max_memory "10.GB" + + // NOTE(SW): create new variable for nf-test workDir so that we can use in genomes config + nfTestWorkDir = workDir + } + + } + + then { + assert workflow.success + } + + } + +} diff --git a/tests/main.stub.nf.test.config b/tests/main.stub.nf.test.config new file mode 100644 index 00000000..03a43382 --- /dev/null +++ b/tests/main.stub.nf.test.config @@ -0,0 +1,14 @@ +params { + genomes { + + 'GRCh38_hmf' { + fasta = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" + fai = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" + dict = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" + bwa_index = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz" + bwa_index_image = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" + gridss_index = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" + } + + } +} diff --git a/tests/samplesheets/targeted.tso500.dna_rna.single.csv b/tests/samplesheets/targeted.tso500.dna_rna.single.csv new file mode 100644 index 00000000..e4bb193b --- /dev/null +++ b/tests/samplesheets/targeted.tso500.dna_rna.single.csv @@ -0,0 +1,3 @@ +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath +SONE-1,SUBJECT_ONE,SAMPLE_ONE_TUMOR,tumor,dna,bam,/Users/stephen/repos/hmftools_pipeline/temp/sample/sample_one_tumor.bam +SONE-1,SUBJECT_ONE,SAMPLE_ONE_TUMOR_WTS,tumor,rna,bam,/Users/stephen/repos/hmftools_pipeline/temp/sample/sample_one_tumor.wts.bam diff --git a/tests/samplesheets/wgts.dna.single.csv b/tests/samplesheets/wgts.dna.single.csv new file mode 100644 index 00000000..3d584620 --- /dev/null +++ b/tests/samplesheets/wgts.dna.single.csv @@ -0,0 +1,3 @@ +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath +COLO829,COLO829,COLO829T,tumor,dna,bam,/Users/stephen/repos/oncoanalyser/tests/sampledata/COLO829T.bam +COLO829,COLO829,COLO829R,normal,dna,bam,/Users/stephen/repos/oncoanalyser/tests/sampledata/COLO829R.bam diff --git a/tests/samplesheets/wgts.dna_rna.single.csv b/tests/samplesheets/wgts.dna_rna.single.csv new file mode 100644 index 00000000..c31f787c --- /dev/null +++ b/tests/samplesheets/wgts.dna_rna.single.csv @@ -0,0 +1,4 @@ +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath +SONE-1,SUBJECT_ONE,SAMPLE_ONE_TUMOR,tumor,dna,bam,/Users/stephen/repos/hmftools_pipeline/temp/sample/sample_one_tumor.bam +SONE-1,SUBJECT_ONE,SAMPLE_ONE_NORMAL,normal,dna,bam,/Users/stephen/repos/hmftools_pipeline/temp/sample/sample_one_normal.bam +SONE-1,SUBJECT_ONE,SAMPLE_ONE_TUMOR_WTS,tumor,rna,bam,/Users/stephen/repos/hmftools_pipeline/temp/sample/sample_one_tumor.wts.bam diff --git a/tests/subworkflows/local/amber_profiling.nf.test b/tests/subworkflows/local/amber_profiling.nf.test new file mode 100644 index 00000000..1b05d7d2 --- /dev/null +++ b/tests/subworkflows/local/amber_profiling.nf.test @@ -0,0 +1,43 @@ +nextflow_workflow { + + name "Test AMBER subworkflow" + script "subworkflows/local/amber_profiling.nf" + workflow "AMBER_PROFILING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna.single.csv' + """ + } + } + } + + when { + params { + outdir "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = '38' + input[2] = '/Users/stephen/repos/oncoanalyser/tests/refdata/GermlineHetPon.38.vcf.gz' + input[3] = [] + """ + } + } + + then { + assert workflow.success + } + + } +} From f69caf9e53a5099da7b46a339aee1e61f95ba197 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 12 Feb 2024 10:39:03 +1100 Subject: [PATCH 285/562] Simplified condition on whether fastp is run in alignment subworkflow. --- subworkflows/local/alignment.nf | 180 ++++++++++++-------------------- 1 file changed, 69 insertions(+), 111 deletions(-) diff --git a/subworkflows/local/alignment.nf b/subworkflows/local/alignment.nf index 4b34ac29..dce56990 100644 --- a/subworkflows/local/alignment.nf +++ b/subworkflows/local/alignment.nf @@ -26,66 +26,71 @@ workflow ALIGNMENT { skip: true } - // TODO(MC): Simplify this branch. - if (max_fastq_lines > 0) { - // Split fastq files using fastp. - - // Create fastp process input channel. - // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] - ch_fastp_inputs = ch_meta_samples_sorted.runnable_fastq - .flatMap { meta -> - - def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } - if (sample_key === null) { - log.error "No DNA sample found" - System.exit(1) - } - - def sample_id = meta[sample_key]['sample_id'] - def fastq_files = meta[sample_key][Constants.FileType.FASTQ].tokenize(';') + // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] + ch_fastq_pairs = ch_meta_samples_sorted.runnable_fastq + .flatMap { meta -> + + def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } + if (sample_key === null) { + log.error "No DNA sample found" + System.exit(1) + } - // TODO(MC): Validate fastq_files. + def sample_id = meta[sample_key]['sample_id'] + def fastq_files = meta[sample_key][Constants.FileType.FASTQ].tokenize(';') - def meta_fastq_common = [:] - meta.each { key, value -> + // TODO(MC): Validate fastq_files. + def meta_fastq_common = [:] + meta.each { key, value -> - if (key === sample_key) { - return - } - meta_fastq_common[key] = meta[key] + if (key === sample_key) { + return } - meta_fastq_common['sample_key'] = sample_key - meta_fastq_common['sample_id'] = sample_id - def fastq_pairs = [] - for (i = 0; i < fastq_files.size(); i += 2) { - def reads_fwd = fastq_files[i] - def reads_rev = fastq_files[i + 1] + meta_fastq_common[key] = meta[key] + } + meta_fastq_common['sample_key'] = sample_key + meta_fastq_common['sample_id'] = sample_id - def meta_fastq = meta_fastq_common.getClass().newInstance(meta_fastq_common) - meta_fastq['read_group'] = Utils.readGroupFromFastqPath(reads_fwd) + def fastq_pairs = [] + for (i = 0; i < fastq_files.size(); i += 2) { + def reads_fwd = fastq_files[i] + def reads_rev = fastq_files[i + 1] - fastq_pairs.add([meta_fastq, reads_fwd, reads_rev]) - } + def meta_fastq = meta_fastq_common.getClass().newInstance(meta_fastq_common) + meta_fastq['read_group'] = Utils.readGroupFromFastqPath(reads_fwd) - fastq_pairs + fastq_pairs.add([meta_fastq, reads_fwd, reads_rev]) } - FASTP(ch_fastp_inputs) - - // TODO(MC): See WISP implementation. - // Create inputs for bwa mem. - // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] - ch_bwa_mem_inputs = FASTP.out.fastq.flatMap { fastq -> + fastq_pairs + } - def meta = fastq[0] - def fwd_reads = fastq[1] - def rev_reads = fastq[2] + // Split fastq files using fastp. + // channel: [ meta_fastq, reads_fwd_fastqs, reads_rev_fastqs ] + ch_split_fastq_pairs = Channel.empty() + if (max_fastq_lines > 0) { + FASTP(ch_fastq_pairs) + ch_split_fastq_pairs = FASTP.out.fastq + } else { + ch_split_fastq_pairs = ch_fastq_pairs.map { fastq_pair -> [fastq_pair[0], [fastq_pair[1]], [fastq_pair[2]]] } + } - // Pair up the reads. - def read_pairs = [:] + // TODO(MC): See WISP implementation. + // Create inputs for bwa mem. + // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] + ch_bwa_mem_inputs = ch_split_fastq_pairs.flatMap { fastq -> + def meta = fastq[0] + def fwd_reads = fastq[1] + def rev_reads = fastq[2] + + // Pair up the reads. + def read_pairs = [:] + if (fwd_reads.size() == 1) { + read_pairs[""] = ["000", fwd_reads[0], rev_reads[0]] + } else { fwd_reads.each { fastq_path -> def base_name = fastq_path.getFileName().toString() @@ -108,77 +113,30 @@ workflow ALIGNMENT { assert read_pairs.containsKey(key) read_pairs[key].add(fastq_path) } - - def fastqs = [] - read_pairs.values().each { split_fastq_pair -> - - meta_fastq = meta.getClass().newInstance(meta) - meta_fastq['split'] = split_fastq_pair[0] - - fastqs.add([meta_fastq, split_fastq_pair[1], split_fastq_pair[2]]) - } - - fastqs } - } else { - - // Skip splitting fastq files using fastp. - - // Create inputs for bwa mem. - // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] - ch_bwa_mem_inputs = ch_meta_samples_sorted.runnable_fastq - .flatMap { meta -> - - def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } - if (sample_key === null) { - log.error "No DNA sample found" - System.exit(1) - } - - def sample_id = meta[sample_key]['sample_id'] - def fastq_files = meta[sample_key][Constants.FileType.FASTQ].tokenize(';') - - // TODO(MC): Validate fastq_files. - - def meta_fastq_common = [:] - meta.each { key, value -> + def fastqs = [] + read_pairs.values().each { split_fastq_pair -> - if (key === sample_key) { - return - } + meta_fastq = meta.getClass().newInstance(meta) + meta_fastq['split'] = split_fastq_pair[0] - meta_fastq_common[key] = meta[key] - } - meta_fastq_common['sample_key'] = sample_key - meta_fastq_common['sample_id'] = sample_id - - def fastq_pairs = [] - for (i = 0; i < fastq_files.size(); i += 2) { - def reads_fwd = fastq_files[i] - def reads_rev = fastq_files[i + 1] - - def meta_fastq = meta_fastq_common.getClass().newInstance(meta_fastq_common) - meta_fastq['read_group'] = Utils.readGroupFromFastqPath(reads_fwd) - meta_fastq['split'] = '000' - - fastq_pairs.add([meta_fastq, reads_fwd, reads_rev]) - } + fastqs.add([meta_fastq, split_fastq_pair[1], split_fastq_pair[2]]) + } - fastq_pairs - } + fastqs } // channel: [ meta_fastq, bam ] BWA_MEM( - ch_bwa_mem_inputs, - genome_fasta, - genome_bwa_index, + ch_bwa_mem_inputs, + genome_fasta, + genome_bwa_index, ) // channel: [ meta_fastq, bam, bai ] SAMBAMBA_INDEX( - BWA_MEM.out.bam, + BWA_MEM.out.bam, ) // Prepare input to markdups process. @@ -208,8 +166,8 @@ workflow ALIGNMENT { def bais = [] lane_bams.each { lane_bam -> - bams.add(lane_bam[1]) - bais.add(lane_bam[2]) + bams.add(lane_bam[1]) + bais.add(lane_bam[2]) } [meta_bam, bams, bais] @@ -221,8 +179,8 @@ workflow ALIGNMENT { def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } if (sample_key === null) { - log.error "No DNA sample found" - System.exit(1) + log.error "No DNA sample found" + System.exit(1) } def sample_id = meta[sample_key]['sample_id'] @@ -261,8 +219,8 @@ workflow ALIGNMENT { // TODO(MC): Safer to copy and delete unneeded fields. def meta = [ - group_id: meta_bam.group_id, - subject_id: meta_bam.subject_id, + group_id: meta_bam.group_id, + subject_id: meta_bam.subject_id, ] sample = [sample_id: meta_bam.sample_id] @@ -299,7 +257,7 @@ workflow ALIGNMENT { merged_sample } - emit: + emit: meta_bam = ch_outputs // TODO[MC]: Channel version outputs. } From 1ef8abd29822693250b89a48d8703a9be845224b Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 12 Feb 2024 11:16:29 +1100 Subject: [PATCH 286/562] Get rid of blocking when merging individual sample records back into a single group record. --- lib/Utils.groovy | 4 ++++ subworkflows/local/alignment.nf | 22 ++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index a3adb2cb..2ca80db2 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -477,6 +477,10 @@ class Utils { return meta_samples } + static public groupSampleCounts(meta_group) { + return splitGroupIntoSamples(meta_group).size() + } + static public readGroupFromFastqPath(fastq_path) { def base_name = fastq_path.split('/')[-1] def pattern = /^(.+)_\d+\.fastq$/ diff --git a/subworkflows/local/alignment.nf b/subworkflows/local/alignment.nf index dce56990..750a06d7 100644 --- a/subworkflows/local/alignment.nf +++ b/subworkflows/local/alignment.nf @@ -14,6 +14,9 @@ workflow ALIGNMENT { max_fastq_lines main: + // channel: [ group_id, sample_count ] + ch_sample_counts = ch_inputs.map { meta -> [meta.group_id, Utils.groupSampleCounts(meta)] } + // channel: [ meta ] (One sample per record). ch_meta_samples = ch_inputs.flatMap { meta -> Utils.splitGroupIntoSamples(meta) } @@ -78,7 +81,6 @@ workflow ALIGNMENT { ch_split_fastq_pairs = ch_fastq_pairs.map { fastq_pair -> [fastq_pair[0], [fastq_pair[1]], [fastq_pair[2]]] } } - // TODO(MC): See WISP implementation. // Create inputs for bwa mem. // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] ch_bwa_mem_inputs = ch_split_fastq_pairs.flatMap { fastq -> @@ -226,7 +228,7 @@ workflow ALIGNMENT { sample = [sample_id: meta_bam.sample_id] sample[Constants.FileType.BAM] = bam[1] sample[Constants.FileType.BAI] = bam[2] - meta[meta.sample_key] = sample + meta[meta_bam.sample_key] = sample meta } @@ -239,11 +241,19 @@ workflow ALIGNMENT { ch_meta_samples_sorted.skip, ) - // TODO(MC): Get rid of blocking. - // Undo split of meta records. + // Merge individual sample records back into group records without blocking for the whole channel to be processed. // channel: [ meta_bam ] - ch_outputs = ch_all_samples - .map { sample -> [sample.group_id, sample]} + ch_outputs = ch_sample_counts + .cross( + ch_all_samples.map { meta -> [meta.group_id, meta] } + ) + .map { count_tuple, meta_tuple -> + def group_id = count_tuple[0] + def count = count_tuple[1] + def meta = meta_tuple[1] + + tuple(groupKey(group_id, count), meta) + } .groupTuple() .map { key_samples -> From b2c2ad7690841cba6209dc07ab6ae7b7dba255f6 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 12 Feb 2024 11:29:22 +1100 Subject: [PATCH 287/562] Simple improvement to the alignment subworkflow. --- subworkflows/local/alignment.nf | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/subworkflows/local/alignment.nf b/subworkflows/local/alignment.nf index 750a06d7..27e64942 100644 --- a/subworkflows/local/alignment.nf +++ b/subworkflows/local/alignment.nf @@ -42,8 +42,6 @@ workflow ALIGNMENT { def sample_id = meta[sample_key]['sample_id'] def fastq_files = meta[sample_key][Constants.FileType.FASTQ].tokenize(';') - // TODO(MC): Validate fastq_files. - def meta_fastq_common = [:] meta.each { key, value -> @@ -219,13 +217,11 @@ workflow ALIGNMENT { def meta_bam = bam[0] - // TODO(MC): Safer to copy and delete unneeded fields. - def meta = [ - group_id: meta_bam.group_id, - subject_id: meta_bam.subject_id, - ] + def meta = meta_bam.getClass().newInstance(meta_bam) + meta.remove('sample_key') + meta.remove('sample_id') - sample = [sample_id: meta_bam.sample_id] + def sample = [sample_id: meta_bam.sample_id] sample[Constants.FileType.BAM] = bam[1] sample[Constants.FileType.BAI] = bam[2] meta[meta_bam.sample_key] = sample From d2f1ebbc4dbb7cecec4317e669062b1e3a59d729 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 12 Feb 2024 19:16:46 +1100 Subject: [PATCH 288/562] Implement first set of subworkflow tests --- nf-test.config | 3 ++ tests/main.stub.nf.test | 13 +++--- ...> targeted.tso500.dna_rna.single.stub.csv} | 0 tests/samplesheets/wgts.dna.single.csv | 4 +- ...ingle.csv => wgts.dna_rna.single.stub.csv} | 0 .../local/amber_profiling.nf.test | 2 +- .../local/bamtools_metrics.nf.test | 43 +++++++++++++++++ .../local/chord_prediction.nf.test | 44 ++++++++++++++++++ .../local/cobalt_profiling.nf.test | 43 +++++++++++++++++ .../local/cuppa_prediction.nf.test | 46 +++++++++++++++++++ 10 files changed, 189 insertions(+), 9 deletions(-) rename tests/samplesheets/{targeted.tso500.dna_rna.single.csv => targeted.tso500.dna_rna.single.stub.csv} (100%) rename tests/samplesheets/{wgts.dna_rna.single.csv => wgts.dna_rna.single.stub.csv} (100%) create mode 100644 tests/subworkflows/local/bamtools_metrics.nf.test create mode 100644 tests/subworkflows/local/chord_prediction.nf.test create mode 100644 tests/subworkflows/local/cobalt_profiling.nf.test create mode 100644 tests/subworkflows/local/cuppa_prediction.nf.test diff --git a/nf-test.config b/nf-test.config index 087e74e0..b3869b6d 100644 --- a/nf-test.config +++ b/nf-test.config @@ -2,4 +2,7 @@ config { testsDir "tests/" workDir ".nf-test" configFile "" + stage { + symlink 'test_data/' + } } diff --git a/tests/main.stub.nf.test b/tests/main.stub.nf.test index 4ee33022..a4dc4a54 100644 --- a/tests/main.stub.nf.test +++ b/tests/main.stub.nf.test @@ -12,11 +12,11 @@ nextflow_pipeline { mode "wgts" genome "GRCh38_hmf" - input "${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv" + input "${baseDir}/tests/samplesheets/wgts.dna_rna.single.stub.csv" outdir "${outputDir}" - ref_data_virusbreakenddb_path "${workDir}/refdata/virusbreakenddb_20210401/" - ref_data_hmf_data_path "${workDir}/refdata/hmf_data/" + ref_data_virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" + ref_data_hmf_data_path "${workDir}/reference_data/hmf_data/" max_cpus = 1 max_memory = "10.GB" @@ -41,11 +41,12 @@ nextflow_pipeline { panel "tso500" genome "GRCh38_hmf" - input "${baseDir}/tests/samplesheets/targeted.tso500.dna_rna.single.csv" + input "${baseDir}/tests/samplesheets/targeted.tso500.dna_rna.single.stub.csv" outdir "${outputDir}" - ref_data_hmf_data_path "${workDir}/refdata/hmf_data/" - ref_data_panel_data_path "${workDir}/refdata/panel_data/" + ref_data_virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" + ref_data_hmf_data_path "${workDir}/reference_data/hmf_data/" + ref_data_panel_data_path "${workDir}/reference_data/panel_data/" max_cpus 1 max_memory "10.GB" diff --git a/tests/samplesheets/targeted.tso500.dna_rna.single.csv b/tests/samplesheets/targeted.tso500.dna_rna.single.stub.csv similarity index 100% rename from tests/samplesheets/targeted.tso500.dna_rna.single.csv rename to tests/samplesheets/targeted.tso500.dna_rna.single.stub.csv diff --git a/tests/samplesheets/wgts.dna.single.csv b/tests/samplesheets/wgts.dna.single.csv index 3d584620..61c5c36c 100644 --- a/tests/samplesheets/wgts.dna.single.csv +++ b/tests/samplesheets/wgts.dna.single.csv @@ -1,3 +1,3 @@ group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath -COLO829,COLO829,COLO829T,tumor,dna,bam,/Users/stephen/repos/oncoanalyser/tests/sampledata/COLO829T.bam -COLO829,COLO829,COLO829R,normal,dna,bam,/Users/stephen/repos/oncoanalyser/tests/sampledata/COLO829R.bam +COLO829,COLO829,COLO829v003T,tumor,dna,bam,meta/test_data/sample_data/COLO829T.bam +COLO829,COLO829,COLO829v003R,normal,dna,bam,meta/test_data/sample_data/COLO829R.bam diff --git a/tests/samplesheets/wgts.dna_rna.single.csv b/tests/samplesheets/wgts.dna_rna.single.stub.csv similarity index 100% rename from tests/samplesheets/wgts.dna_rna.single.csv rename to tests/samplesheets/wgts.dna_rna.single.stub.csv diff --git a/tests/subworkflows/local/amber_profiling.nf.test b/tests/subworkflows/local/amber_profiling.nf.test index 1b05d7d2..4aafe9f6 100644 --- a/tests/subworkflows/local/amber_profiling.nf.test +++ b/tests/subworkflows/local/amber_profiling.nf.test @@ -29,7 +29,7 @@ nextflow_workflow { """ input[0] = PREPARE_INPUTS.out.inputs input[1] = '38' - input[2] = '/Users/stephen/repos/oncoanalyser/tests/refdata/GermlineHetPon.38.vcf.gz' + input[2] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/copy_number/AmberGermlineSites.38.tsv.gz' input[3] = [] """ } diff --git a/tests/subworkflows/local/bamtools_metrics.nf.test b/tests/subworkflows/local/bamtools_metrics.nf.test new file mode 100644 index 00000000..64eecd23 --- /dev/null +++ b/tests/subworkflows/local/bamtools_metrics.nf.test @@ -0,0 +1,43 @@ +nextflow_workflow { + + name "Test BamTools subworkflow" + script "subworkflows/local/bamtools_metrics.nf" + workflow "BAMTOOLS_METRICS" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna.single.csv' + """ + } + } + } + + when { + params { + outdir "${outputDir}" + + // NOTE(SW): BamTools fails when using a single thread + max_cpus = 2 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[2] = '38' + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/chord_prediction.nf.test b/tests/subworkflows/local/chord_prediction.nf.test new file mode 100644 index 00000000..bdffb54f --- /dev/null +++ b/tests/subworkflows/local/chord_prediction.nf.test @@ -0,0 +1,44 @@ +nextflow_workflow { + + name "Test CHORD subworkflow" + script "subworkflows/local/chord_prediction.nf" + workflow "CHORD_PREDICTION" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna.single.csv' + """ + } + } + } + + when { + params { + outdir "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine( + Channel.of('${baseDir}/test_data/module_data/purple/') + ) + input[2] = '38' + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/cobalt_profiling.nf.test b/tests/subworkflows/local/cobalt_profiling.nf.test new file mode 100644 index 00000000..20633f2c --- /dev/null +++ b/tests/subworkflows/local/cobalt_profiling.nf.test @@ -0,0 +1,43 @@ +nextflow_workflow { + + name "Test COBALT subworkflow" + script "subworkflows/local/cobalt_profiling.nf" + workflow "COBALT_PROFILING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna.single.csv' + """ + } + } + } + + when { + params { + outdir "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/copy_number/GC_profile.1000bp.38.cnp' + input[2] = [] + input[3] = [] + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/cuppa_prediction.nf.test b/tests/subworkflows/local/cuppa_prediction.nf.test new file mode 100644 index 00000000..3171abd9 --- /dev/null +++ b/tests/subworkflows/local/cuppa_prediction.nf.test @@ -0,0 +1,46 @@ +nextflow_workflow { + + name "Test CUPPA subworkflow" + script "subworkflows/local/cuppa_prediction.nf" + workflow "CUPPA_PREDICTION" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna.single.csv' + """ + } + } + } + + when { + params { + outdir "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/isofox/')) + input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) + input[3] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx_somatic/')) + input[4] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/virusinterpreter/')) + input[5] = '38' + input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/cuppa/' + """ + } + } + + then { + assert workflow.success + } + + } +} From f3778619d144e4deea4df5fcb04d355cdac58b9c Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 13 Feb 2024 12:37:11 +1100 Subject: [PATCH 289/562] Merge alignment and markdups logic into Stephen's stubs. --- lib/Utils.groovy | 5 + modules/local/fastp/main.nf | 3 +- subworkflows/local/alignment.nf | 269 ---------------------- subworkflows/local/read_alignment.nf | 312 +++++++++++++++++++++++--- subworkflows/local/read_processing.nf | 148 ++++++++++-- workflows/wgts.nf | 109 +++++---- 6 files changed, 466 insertions(+), 380 deletions(-) delete mode 100644 subworkflows/local/alignment.nf diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 2ca80db2..58c412ca 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -453,6 +453,11 @@ class Utils { } } + public static shallow_copy(obj) { + + return obj.getClass().newInstance(obj) + } + // Alignment utils. static public splitGroupIntoSamples(meta_group) { def sample_entries = [:] diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index 8deec567..35d3714b 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -7,6 +7,7 @@ process FASTP { input: tuple val(meta), path(reads_fwd), path(reads_rev) + val(max_fastq_records) output: tuple val(meta), path('*_R1.fastp.fastq'), path('*_R2.fastp.fastq'), emit: fastq @@ -25,7 +26,7 @@ process FASTP { --in1 ${reads_fwd} \\ --in2 ${reads_rev} \\ --disable_adapter_trimming \\ - --split_by_lines 40000000 \\ + --split_by_lines ${4 * max_fastq_records} \\ --out1 ${meta.sample_id}_${meta.read_group}_R1.fastp.fastq \\ --out2 ${meta.sample_id}_${meta.read_group}_R2.fastp.fastq """ diff --git a/subworkflows/local/alignment.nf b/subworkflows/local/alignment.nf deleted file mode 100644 index 27e64942..00000000 --- a/subworkflows/local/alignment.nf +++ /dev/null @@ -1,269 +0,0 @@ -include { BWA_MEM } from '../../modules/local/bwa/mem/main' -include { MARKDUPS } from '../../modules/local/markdups/main' -include { FASTP } from '../../modules/local/fastp/main' -include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' - -workflow ALIGNMENT { - take: - ch_inputs // channel: [ meta ] - genome_fasta - genome_fai - genome_dict - genome_bwa_index - unmap_regions - max_fastq_lines - - main: - // channel: [ group_id, sample_count ] - ch_sample_counts = ch_inputs.map { meta -> [meta.group_id, Utils.groupSampleCounts(meta)] } - - // channel: [ meta ] (One sample per record). - ch_meta_samples = ch_inputs.flatMap { meta -> Utils.splitGroupIntoSamples(meta) } - - // Sort inputs - // channel: [ meta ] (One sample per record). - ch_meta_samples_sorted = ch_meta_samples - .branch { meta -> - runnable_fastq: Utils.hasDnaFastq(meta) - runnable_markdups: Utils.hasDnaMarkdupsBam(meta) - skip: true - } - - // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] - ch_fastq_pairs = ch_meta_samples_sorted.runnable_fastq - .flatMap { meta -> - - def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } - if (sample_key === null) { - log.error "No DNA sample found" - System.exit(1) - } - - def sample_id = meta[sample_key]['sample_id'] - def fastq_files = meta[sample_key][Constants.FileType.FASTQ].tokenize(';') - - def meta_fastq_common = [:] - meta.each { key, value -> - - - if (key === sample_key) { - return - } - - meta_fastq_common[key] = meta[key] - } - meta_fastq_common['sample_key'] = sample_key - meta_fastq_common['sample_id'] = sample_id - - def fastq_pairs = [] - for (i = 0; i < fastq_files.size(); i += 2) { - def reads_fwd = fastq_files[i] - def reads_rev = fastq_files[i + 1] - - def meta_fastq = meta_fastq_common.getClass().newInstance(meta_fastq_common) - meta_fastq['read_group'] = Utils.readGroupFromFastqPath(reads_fwd) - - fastq_pairs.add([meta_fastq, reads_fwd, reads_rev]) - } - - fastq_pairs - } - - // Split fastq files using fastp. - // channel: [ meta_fastq, reads_fwd_fastqs, reads_rev_fastqs ] - ch_split_fastq_pairs = Channel.empty() - if (max_fastq_lines > 0) { - FASTP(ch_fastq_pairs) - ch_split_fastq_pairs = FASTP.out.fastq - } else { - ch_split_fastq_pairs = ch_fastq_pairs.map { fastq_pair -> [fastq_pair[0], [fastq_pair[1]], [fastq_pair[2]]] } - } - - // Create inputs for bwa mem. - // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] - ch_bwa_mem_inputs = ch_split_fastq_pairs.flatMap { fastq -> - def meta = fastq[0] - def fwd_reads = fastq[1] - def rev_reads = fastq[2] - - // Pair up the reads. - def read_pairs = [:] - if (fwd_reads.size() == 1) { - read_pairs[""] = ["000", fwd_reads[0], rev_reads[0]] - } else { - fwd_reads.each { fastq_path -> - - def base_name = fastq_path.getFileName().toString() - def pattern = /^(\d+)\.(.+)_R[12]\.fastp\.fastq$/ - def matcher = base_name =~ pattern - assert matcher.find() - def split = matcher[0][1] - def key = "${split}.${matcher[0][2]}" - assert !read_pairs.containsKey(key) - read_pairs[key] = [split, fastq_path] - } - - rev_reads.each { fastq_path -> - - def base_name = fastq_path.getFileName().toString() - def pattern = /^(.+)_R[12]\.fastp\.fastq$/ - def matcher = base_name =~ pattern - assert matcher.find() - def key = matcher[0][1] - assert read_pairs.containsKey(key) - read_pairs[key].add(fastq_path) - } - } - - def fastqs = [] - read_pairs.values().each { split_fastq_pair -> - - meta_fastq = meta.getClass().newInstance(meta) - meta_fastq['split'] = split_fastq_pair[0] - - fastqs.add([meta_fastq, split_fastq_pair[1], split_fastq_pair[2]]) - } - - fastqs - } - - // channel: [ meta_fastq, bam ] - BWA_MEM( - ch_bwa_mem_inputs, - genome_fasta, - genome_bwa_index, - ) - - // channel: [ meta_fastq, bam, bai ] - SAMBAMBA_INDEX( - BWA_MEM.out.bam, - ) - - // Prepare input to markdups process. - // First we prepare a channel of inputs that have gone through alignment. - // channel: [ meta_bam, bams, bais ] - ch_fastq_markdups_inputs = SAMBAMBA_INDEX.out.bam - .map { bam -> // Strip read groups and splits. - - def meta = bam[0] - def meta_bam = [:] - meta.keySet().each { key -> - - if (key == 'read_group' || key == 'split') { - return - } - - meta_bam[key] = meta[key] - } - - [meta_bam, [meta_bam, bam[1], bam[2]]] - } - .groupTuple() - .map { key_lane_bams -> - def lane_bams = key_lane_bams[1] - def meta_bam = lane_bams[0][0] - def bams = [] - def bais = [] - lane_bams.each { lane_bam -> - - bams.add(lane_bam[1]) - bais.add(lane_bam[2]) - } - - [meta_bam, bams, bais] - } - - // Next we prepare channel for markdups input that started of as aligned bams. - // channel: [ meta, bams, bais ] (One sample per meta record). - ch_input_markdups_inputs = ch_meta_samples_sorted.runnable_markdups.map { meta -> - - def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } - if (sample_key === null) { - log.error "No DNA sample found" - System.exit(1) - } - - def sample_id = meta[sample_key]['sample_id'] - def bam = meta[sample_key][Constants.FileType.BAM_MARKDUPS] - def bai = meta[sample_key][Constants.FileType.BAI_MARKDUPS] - - def meta_bam = meta.getClass().newInstance(meta); - meta_bam['sample_key'] = sample_key - meta_bam['sample_id'] = sample_id - - [meta_bam, [bam], [bai]] - } - - // Merging the two markdups input channels. - // channel: [ meta_bam, bams, bais ] - ch_markdups_inputs = Channel.empty() - .mix( - ch_fastq_markdups_inputs, - ch_input_markdups_inputs, - ) - - // channel: [ meta_bam, bam, bai ] - MARKDUPS( - ch_markdups_inputs, - genome_fasta, - genome_fai, - genome_dict, - unmap_regions, - ) - - // Fill the sample information back in. - // channel: [ meta ] (One sample per meta record). - ch_bam_samples = MARKDUPS.out.bam.map { bam -> - - def meta_bam = bam[0] - - def meta = meta_bam.getClass().newInstance(meta_bam) - meta.remove('sample_key') - meta.remove('sample_id') - - def sample = [sample_id: meta_bam.sample_id] - sample[Constants.FileType.BAM] = bam[1] - sample[Constants.FileType.BAI] = bam[2] - meta[meta_bam.sample_key] = sample - - meta - } - - // Merge back in skipped meta entries. - // channel: [ meta ] (One sample per meta record). - ch_all_samples = Channel.empty() - .mix( - ch_bam_samples, - ch_meta_samples_sorted.skip, - ) - - // Merge individual sample records back into group records without blocking for the whole channel to be processed. - // channel: [ meta_bam ] - ch_outputs = ch_sample_counts - .cross( - ch_all_samples.map { meta -> [meta.group_id, meta] } - ) - .map { count_tuple, meta_tuple -> - def group_id = count_tuple[0] - def count = count_tuple[1] - def meta = meta_tuple[1] - - tuple(groupKey(group_id, count), meta) - } - .groupTuple() - .map { key_samples -> - - def samples = key_samples[1] - def merged_sample = [:] - samples.each { sample -> - - sample.each { key, value -> merged_sample[key] = value } - } - - merged_sample - } - - emit: - meta_bam = ch_outputs - // TODO[MC]: Channel version outputs. -} diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index a13025fa..acc92a4d 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -1,39 +1,297 @@ -include { BWA_MEM2 } from '../../modules/local/bwa/mem2/main' +include { BWA_MEM } from '../../modules/local/bwa/mem/main' +include { FASTP } from '../../modules/local/fastp/main' +include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' include { STAR } from '../../modules/local/star/main' workflow READ_ALIGNMENT { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + genome_fasta + genome_bwa_index + max_fastq_records main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // STAR - // TODO(SW): implement inputs - ch_star_inputs = Channel.of([[id: 'foo'], []]) - STAR( - ch_star_inputs, - // TODO(SW): include reference files + // TODO(MC): Versions. + // // Channel for version.yml files + // // channel: [ versions.yml ] + // ch_versions = Channel.empty() + + // channel: [ group_id, sample_count ] + ch_sample_counts = ch_inputs.map { meta -> [meta.group_id, Utils.groupSampleCounts(meta)] } + + // channel: [ meta ] (One sample per record). + ch_meta_samples = ch_inputs.flatMap { meta -> Utils.splitGroupIntoSamples(meta) } + + // Sort inputs + // channel: [ meta ] (One sample per record). + ch_meta_samples_sorted = ch_meta_samples + .branch { meta -> + runnable_fastq: Utils.hasDnaFastq(meta) + skip: true + } + + // STAR + // TODO(SW): implement inputs + // ch_star_inputs = Channel.of([[id: 'foo'], []]) + // STAR( + // ch_star_inputs, + // // TODO(SW): include reference files + // ) + // TODO(SW): implement outputs + ch_star_outputs = Channel.empty() + + // BWA MEM + // channel: [ sample_key, fastq_pair_count ] + ch_sample_fastq_pair_count = ch_meta_samples_sorted.runnable_fastq.map { meta_sample -> + + def sample_key = Utils.shallow_copy(meta_sample) + def fastq_pair_count = 0 + meta_sample.each { key, value -> + + if ((value instanceof java.util.Map) && value.containsKey('sample_id')) { + sample_key['sample_key'] = key + sample_key['sample_id'] = value.sample_id + sample_key.remove(key) + + fastq_pair_count = value[Constants.FileType.FASTQ].tokenize(';').size() / 2 + } + } + + [sample_key, fastq_pair_count] + } + + // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] + ch_fastq_pairs = ch_meta_samples_sorted.runnable_fastq + .flatMap { meta -> + + def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } + if (sample_key === null) { + log.error "No DNA sample found" + System.exit(1) + } + + def sample_id = meta[sample_key]['sample_id'] + def fastq_files = meta[sample_key][Constants.FileType.FASTQ].tokenize(';') + + def meta_fastq_common = [:] + meta.each { key, value -> + + + if (key === sample_key) { + return + } + + meta_fastq_common[key] = meta[key] + } + meta_fastq_common['sample_key'] = sample_key + meta_fastq_common['sample_id'] = sample_id + + def fastq_pairs = [] + for (i = 0; i < fastq_files.size(); i += 2) { + def reads_fwd = fastq_files[i] + def reads_rev = fastq_files[i + 1] + + def meta_fastq = Utils.shallow_copy(meta_fastq_common) + meta_fastq['read_group'] = Utils.readGroupFromFastqPath(reads_fwd) + + fastq_pairs.add([meta_fastq, reads_fwd, reads_rev]) + } + + fastq_pairs + } + + // Split fastq files using fastp. + // channel: [ meta_fastq, reads_fwd_fastqs, reads_rev_fastqs ] + ch_split_fastq_pairs = Channel.empty() + if (max_fastq_records > 0) { + FASTP( + ch_fastq_pairs, + max_fastq_records, ) - // TODO(SW): implement outputs - ch_star_outputs = Channel.empty() - - // BWA MEM2 - // TODO(SW): implement inputs - ch_bwa_inputs = Channel.of([[id: 'foo'], []]) - BWA_MEM2( - ch_bwa_inputs, - // TODO(SW): include reference files + + ch_split_fastq_pairs = FASTP.out.fastq + } else { + ch_split_fastq_pairs = ch_fastq_pairs.map { fastq_pair -> [fastq_pair[0], [fastq_pair[1]], [fastq_pair[2]]] } + } + + // channel: [ sample_key, fastq_pair_split_count ] + ch_sample_fastq_pair_split_count = ch_sample_fastq_pair_count + .cross( + ch_split_fastq_pairs.map { split_fastq_pairs -> + + def meta_sample = split_fastq_pairs[0] + def sample_key = Utils.shallow_copy(meta_sample) + sample_key.remove('read_group') + sample_key.remove(meta_sample.sample_key) + + [sample_key, split_fastq_pairs[1].size()] + } ) - // TODO(SW): implement outputs - ch_bwa_outputs = Channel.empty() + .map { count_tuple, split_count_tuple -> + def sample_key = count_tuple[0] + def count = count_tuple[1].intValue() + def split_count = split_count_tuple[1] + + tuple(groupKey(sample_key, count), sample_key, split_count) + } + .groupTuple() + .map { group_key, sample_keys, split_counts -> + + [sample_keys[0], split_counts.sum()] + } + + // Create inputs for bwa mem. + // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] + ch_bwa_mem_inputs = ch_split_fastq_pairs.flatMap { fastq -> + def meta = fastq[0] + def fwd_reads = fastq[1] + def rev_reads = fastq[2] + + // Pair up the reads. + def read_pairs = [:] + if (fwd_reads.size() == 1) { + read_pairs[""] = ["000", fwd_reads[0], rev_reads[0]] + } else { + fwd_reads.each { fastq_path -> + + def base_name = fastq_path.getFileName().toString() + def pattern = /^(\d+)\.(.+)_R[12]\.fastp\.fastq$/ + def matcher = base_name =~ pattern + assert matcher.find() + def split = matcher[0][1] + def key = "${split}.${matcher[0][2]}" + assert !read_pairs.containsKey(key) + read_pairs[key] = [split, fastq_path] + } + + rev_reads.each { fastq_path -> + + def base_name = fastq_path.getFileName().toString() + def pattern = /^(.+)_R[12]\.fastp\.fastq$/ + def matcher = base_name =~ pattern + assert matcher.find() + def key = matcher[0][1] + assert read_pairs.containsKey(key) + read_pairs[key].add(fastq_path) + } + } + + def fastqs = [] + read_pairs.values().each { split_fastq_pair -> + + meta_fastq = Utils.shallow_copy(meta) + meta_fastq['split'] = split_fastq_pair[0] + + fastqs.add([meta_fastq, split_fastq_pair[1], split_fastq_pair[2]]) + } + + fastqs + } + + // channel: [ meta_fastq, bam ] + BWA_MEM( + ch_bwa_mem_inputs, + genome_fasta, + genome_bwa_index, + ) + + // channel: [ meta_fastq, bam, bai ] + SAMBAMBA_INDEX( + BWA_MEM.out.bam, + ) + + // Merge all bam records for a single sample into a singlke record. + // channel: [ meta ] (One sample per meta record). + ch_merged_bam_samples = ch_sample_fastq_pair_split_count + .cross( + SAMBAMBA_INDEX.out.bam + .map { bam -> + + def meta_bam = bam[0] + def sample_key = Utils.shallow_copy(meta_bam) + sample_key.remove(meta_bam.sample_key) + sample_key.remove('read_group') + sample_key.remove('split') + + [sample_key, bam] + } + ) + .map { count_tuple, bam_tuple -> + + def sample_key = count_tuple[0] + def count = count_tuple[1] + def bam = bam_tuple[1] + + tuple(groupKey(sample_key, count), bam) + } + .groupTuple() + .map { group_key, bams -> + + def first_meta_bam = bams[0][0] + def sample_key = first_meta_bam.sample_key + + def bam_files = [] + def bai_files = [] + + def meta_bam = Utils.shallow_copy(first_meta_bam) + meta_bam.remove(sample_key) + meta_bam.remove('sample_key') + meta_bam.remove('sample_id') + meta_bam.remove('read_group') + meta_bam.remove('split') + + meta_bam[sample_key] = [sample_id: first_meta_bam.sample_id] + meta_bam[sample_key][Constants.FileType.BAM_MARKDUPS] = bam_files + meta_bam[sample_key][Constants.FileType.BAI_MARKDUPS] = bai_files + + bams.each { bam -> + bam_files.add(bam[1]) + bai_files.add(bam[2]) + } + + meta_bam + } + + // Merge back in skipped meta entries. + // channel: [ meta ] (One sample per meta record). + ch_all_samples = Channel.empty() + .mix( + ch_merged_bam_samples, + ch_meta_samples_sorted.skip, + ) + + // Merge individual sample records back into group records without blocking for the whole channel to be processed. + // channel: [ meta_bam ] + ch_bwa_outputs = ch_sample_counts + .cross( + ch_all_samples.map { meta -> [meta.group_id, meta] } + ) + .map { count_tuple, meta_tuple -> + def group_id = count_tuple[0] + def count = count_tuple[1] + def meta = meta_tuple[1] + + tuple(groupKey(group_id, count), meta) + } + .groupTuple() + .map { group_key, meta_samples -> + + def meta_group = [:] + meta_samples.each { meta_sample -> + + meta_sample.each { key, value -> meta_group[key] = value } + } + + meta_group + } emit: - dna = ch_bwa_outputs // channel: [ meta, bam_dna ] - rna = ch_star_outputs // channel: [ meta, bam_rna ] + dna = ch_bwa_outputs // channel: [ meta ] + + // TODO(MC): RNA alignment. + rna = ch_star_outputs // channel: [ meta, bam_rna ] - versions = ch_versions // channel: [ versions.yml ] + // TODO(MC): Versions. + // versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/read_processing.nf b/subworkflows/local/read_processing.nf index af0bb10c..d8de6b54 100644 --- a/subworkflows/local/read_processing.nf +++ b/subworkflows/local/read_processing.nf @@ -1,34 +1,134 @@ -include { MARKDUPS } from '../../modules/local/markdups/main' +include { MARKDUPS } from '../../modules/local/markdups/main' workflow READ_PROCESSING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_dna_bams // channel: [mandatory] [ meta, bam_dna ] - ch_rna_bams // channel: [mandatory] [ meta, bam_rna ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_dna_bams // channel: [mandatory] [ meta, bam_dna ] + ch_rna_bams // channel: [mandatory] [ meta, bam_rna ] + genome_fasta + genome_fai + genome_dict + unmap_regions main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // NOTE(SW): channel operations will be required to configure MarkDups for individual samples - - // MarkDups - // TODO(SW): implement inputs - ch_markdups_inputs = Channel.of([[id: 'foo'], []]) - MARKDUPS( - ch_markdups_inputs, - // TODO(SW): configuration - // TODO(SW): reference files + // TODO(MC): Versions. + // Channel for version.yml files + // channel: [ versions.yml ] + // ch_versions = Channel.empty() + + // channel: [ group_id, sample_count ] + ch_sample_counts = ch_inputs.map { meta -> [meta.group_id, Utils.groupSampleCounts(meta)] } + + // channel: [ meta ] (One sample per record). + ch_meta_samples = ch_dna_bams.flatMap { meta -> Utils.splitGroupIntoSamples(meta) } + + // Sort inputs + // channel: [ meta ] (One sample per record). + ch_meta_samples_sorted = ch_meta_samples + .branch { meta -> + runnable: Utils.hasDnaMarkdupsBam(meta) + skip: true + } + + // MarkDups + // Prepare input to markdups process. + // channel: [ meta_bam, bams, bais ] + ch_markdups_inputs = ch_meta_samples_sorted.runnable + .map { meta_sample -> + + def meta_bam = Utils.shallow_copy(meta_sample) + def bams = [] + def bais = [] + meta_sample.each { key, value -> + + if ((value instanceof java.util.Map) && value.containsKey('sample_id')) { + meta_bam['sample_id'] = value.sample_id + meta_bam['sample_key'] = key + bams = value[Constants.FileType.BAM_MARKDUPS] + bais = value[Constants.FileType.BAI_MARKDUPS] + } + } + + if (!(bams instanceof Collection)) { + bams = [bams] + } + + if (!(bais instanceof Collection)) { + bais = [bais] + } + + [meta_bam, bams, bais] + } + + // channel: [ meta_bam, bam, bai ] + MARKDUPS( + ch_markdups_inputs, + genome_fasta, + genome_fai, + genome_dict, + unmap_regions, + ) + + // Update sample information. + // channel: [ meta ] (One sample per meta record). + ch_bam_samples = MARKDUPS.out.bam.map { bam -> + + def meta_bam = bam[0] + + def meta = Utils.shallow_copy(meta_bam) + meta.remove('sample_id') + meta.remove('sample_key') + + def sample = [sample_id: meta_bam.sample_id] + sample[Constants.FileType.BAM] = bam[1] + sample[Constants.FileType.BAI] = bam[2] + meta[meta_bam.sample_key] = sample + + meta + } + + // Merge back in skipped meta entries. + // channel: [ meta ] (One sample per meta record). + ch_all_samples = Channel.empty() + .mix( + ch_bam_samples, + ch_meta_samples_sorted.skip, + ) + + // Merge individual sample records back into group records without blocking for the whole channel to be processed. + // channel: [ meta_bam ] + ch_markduplicates_dna_out = ch_sample_counts + .cross( + ch_all_samples.map { meta -> [meta.group_id, meta] } ) - // TODO(SW): implement outputs - ch_markduplicates_dna_out = Channel.empty() - ch_markduplicates_rna_out = Channel.empty() + .map { count_tuple, meta_tuple -> + + def group_id = count_tuple[0] + def count = count_tuple[1] + def meta = meta_tuple[1] + + tuple(groupKey(group_id, count), meta) + } + .groupTuple() + .map { group_key, meta_samples -> + + def meta_group = [:] + meta_samples.each { meta_sample -> + + meta_sample.each { key, value -> meta_group[key] = value } + } + + meta_group + } + + // TODO(SW): implement outputs + ch_markduplicates_rna_out = Channel.empty() emit: - dna = ch_markduplicates_dna_out // channel: [ meta, bam_dna ] - rna = ch_markduplicates_rna_out // channel: [ meta, bam_rna ] + dna = ch_markduplicates_dna_out // channel: [ meta ] + rna = ch_markduplicates_rna_out // channel: [ meta, bam_rna ] - versions = ch_versions // channel: [ versions.yml ] + // TODO(MC): Versions. + // versions = ch_versions // channel: [ versions.yml ] } diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 24ea60c0..1d55a889 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -68,7 +68,6 @@ linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : // // SUBWORKFLOWS // -include { ALIGNMENT } from '../subworkflows/local/alignment' include { AMBER_PROFILING } from '../subworkflows/local/amber_profiling' include { BAMTOOLS_METRICS } from '../subworkflows/local/bamtools_metrics' include { CHORD_PREDICTION } from '../subworkflows/local/chord_prediction' @@ -119,8 +118,7 @@ workflow WGTS { // Create input channel from parsed CSV // channel: [ meta ] - // TODO[MC]: Rename this back to original, and swap name out for current ch_inputs. - ch_inputs0 = Channel.fromList(inputs) + ch_inputs = Channel.fromList(inputs) // Set up reference data, assign more human readable variables PREPARE_REFERENCE( @@ -129,79 +127,72 @@ workflow WGTS { ref_data = PREPARE_REFERENCE.out hmf_data = PREPARE_REFERENCE.out.hmf_data - // TODO[MC]: Skipping alignment, only running up to alignment? - ALIGNMENT( - ch_inputs0, - ref_data.genome_fasta, - ref_data.genome_fai, - ref_data.genome_dict, - ref_data.genome_bwa_index, - file(params.refdata_unmap_regions), - 4 * params.max_fastq_records, - ) - - ch_inputs = ALIGNMENT.out.meta_bam - // Set GRIDSS config gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config - // // - // // SUBWORKFLOW: Align reads - // // - // // channel: [ meta, bam_dna ] - // ch_dna_alignment_out = Channel.empty() - // // channel: [ meta, bam_rna ] - // ch_rna_alignment_out = Channel.empty() - // // TODO(MC): set up correctly - // // if (true | run_config.stages.alignment) { + // + // SUBWORKFLOW: Align reads + // + // channel: [ meta ] + ch_dna_alignment_out = Channel.empty() + // channel: [ meta, bam_rna ] + ch_rna_alignment_out = Channel.empty() + // TODO(SW): set up correctly + if (true || run_config.stages.alignment) { - // // READ_ALIGNMENT( - // // ch_inputs, - // // // alignment reference files - // // ) + READ_ALIGNMENT( + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_bwa_index, + params.max_fastq_records, + ) - // // ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) + // TODO(MC): Versions. + // ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) - // // ch_dna_alignment_out = ch_dna_alignment_out.mix(READ_ALIGNMENT.out.dna) - // // ch_rna_alignment_out = ch_rna_alignment_out.mix(READ_ALIGNMENT.out.rna) + ch_dna_alignment_out = ch_dna_alignment_out.mix(READ_ALIGNMENT.out.dna) + ch_rna_alignment_out = ch_rna_alignment_out.mix(READ_ALIGNMENT.out.rna) - // // } else { - // // ch_dna_alignment_out = ch_inputs.map { meta -> [meta, []] } - // // ch_rna_alignment_out = ch_inputs.map { meta -> [meta, []] } + } else { - // // } + ch_dna_alignment_out = ch_inputs + ch_rna_alignment_out = ch_inputs.map { meta -> [meta, []] } - // ch_dna_alignment_out = ch_inputs.map { meta -> [meta, []] } - // ch_rna_alignment_out = ch_inputs.map { meta -> [meta, []] } + } - // // - // // SUBWORKFLOW: Process read alignments - // // - // // channel: [ meta, bam_dna ] - // ch_dna_processed_out = Channel.empty() - // // channel: [ meta, bam_rna ] - // ch_rna_processed_out = Channel.empty() - // // TODO(SW): set up correctly - // if (true | run_config.stages.markdups) { + // + // SUBWORKFLOW: Process read alignments + // + // channel: [ meta ] + ch_dna_processed_out = Channel.empty() + // channel: [ meta, bam_rna ] + ch_rna_processed_out = Channel.empty() + // TODO(SW): set up correctly + if (true || run_config.stages.markdups) { - // READ_PROCESSING( - // ch_inputs, - // ch_dna_alignment_out, - // ch_rna_alignment_out, - // ) + READ_PROCESSING( + ch_inputs, + ch_dna_alignment_out, + ch_rna_alignment_out, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_dict, + file(params.refdata_unmap_regions), + ) - // ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) + // TODO(MC): Versions. + // ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) - // ch_dna_processed_out = ch_dna_processed_out.mix(READ_PROCESSING.out.dna) - // ch_rna_processed_out = ch_rna_processed_out.mix(READ_PROCESSING.out.rna) + ch_dna_processed_out = ch_dna_processed_out.mix(READ_PROCESSING.out.dna) + ch_rna_processed_out = ch_rna_processed_out.mix(READ_PROCESSING.out.rna) - // } else { + } else { - // ch_dna_processed_out = ch_inputs.map { meta -> [meta, []] } - // ch_rna_processed_out = ch_inputs.map { meta -> [meta, []] } + ch_dna_processed_out = ch_inputs.map + ch_rna_processed_out = ch_inputs.map { meta -> [meta, []] } - // } + } // TODO(SW): adjust downstream selection of input BAM From 01510042bdbb5eda230e67eca3912249ac4f20dd Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 13 Feb 2024 14:01:54 +1100 Subject: [PATCH 290/562] Updgrading from bwa mem to bwa mem2. --- modules/local/bwa/mem/main.nf | 2 - modules/local/bwa/mem2/Dockerfile | 9 ++++ modules/local/bwa/mem2/main.nf | 66 +++++++++++++++++++++------- subworkflows/local/read_alignment.nf | 8 ++-- 4 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 modules/local/bwa/mem2/Dockerfile diff --git a/modules/local/bwa/mem/main.nf b/modules/local/bwa/mem/main.nf index 428d1ce9..e3b54dd4 100644 --- a/modules/local/bwa/mem/main.nf +++ b/modules/local/bwa/mem/main.nf @@ -1,5 +1,3 @@ -// TODO(MC): BWA MEM2: Need docker and resource files. - process BWA_MEM { tag "${meta.id}" diff --git a/modules/local/bwa/mem2/Dockerfile b/modules/local/bwa/mem2/Dockerfile new file mode 100644 index 00000000..0f2641da --- /dev/null +++ b/modules/local/bwa/mem2/Dockerfile @@ -0,0 +1,9 @@ +FROM docker.io/continuumio/miniconda3:23.10.0-1 + +RUN \ + conda install -y -n base conda-libmamba-solver && \ + conda config --set solver libmamba && \ + conda install -y -c bioconda -c conda-forge -c conda \ + 'bwa-mem2==2.2.1' \ + 'sambamba==1.0' && \ + conda clean -yaf diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index 3b55a8a1..03d5d327 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -2,38 +2,70 @@ process BWA_MEM2 { tag "${meta.id}" label 'process_high' - // TODO(SW): create container - //container 'foo' + // TODO(MC): Upload container. + container 'bwa-mem2:2.2.1-sambamba' input: - // TODO(SW): decide input structure - tuple val(meta), path(fastqs) + tuple val(meta), path(reads_fwd), path(reads_rev) + path genome_fasta + // TODO(MC): Copied into local genome_bwa_index for ref genome 37: + // + Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64 + // + Homo_sapiens.GRCh37.GATK.illumina.fasta.0123 + path genome_bwa_index output: - // TODO(SW): set outputs - tuple val(meta), path('bar'), emit: bam - path 'versions.yml' , emit: versions + tuple val(meta), path('*.bam'), emit: bam + // TODO(MC): Versions. + // path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' + // # TODO(MC): read group + // # -R ${meta.read_group} - // TODO(SW): implement process """ - touch bar + ln -s \$(find -L ${genome_bwa_index} -type f) ./ - cat <<-END_VERSIONS > versions.yml - "${task.process}": - bwamem2: foo - END_VERSIONS + bwa-mem2 mem \\ + -Y \\ + -t ${task.cpus} \\ + ${genome_fasta} \\ + ${reads_fwd} \\ + ${reads_rev} | \\ + \\ + sambamba view \\ + --sam-input \\ + --format bam \\ + --compression-level 0 \\ + --nthreads ${task.cpus} \\ + /dev/stdin | \\ + \\ + sambamba sort \\ + --nthreads ${task.cpus} \\ + --out ${meta.split}.${meta.sample_id}.${meta.read_group}.bam \\ + /dev/stdin """ + // TODO(SW): Versions. + // """ + // touch bar + + // cat <<-END_VERSIONS > versions.yml + // "${task.process}": + // bwamem2: foo + // END_VERSIONS + // """ + stub: - // TODO(SW): implement stub """ - touch bar - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + touch ${meta.split}.${meta.sample_id}.${meta.read_group}.bam """ + + // TODO(MV): Versions. + // """ + // touch bar + // echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + // """ } diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index acc92a4d..d8d654a8 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -1,4 +1,4 @@ -include { BWA_MEM } from '../../modules/local/bwa/mem/main' +include { BWA_MEM2 } from '../../modules/local/bwa/mem2/main' include { FASTP } from '../../modules/local/fastp/main' include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' include { STAR } from '../../modules/local/star/main' @@ -41,7 +41,7 @@ workflow READ_ALIGNMENT { // TODO(SW): implement outputs ch_star_outputs = Channel.empty() - // BWA MEM + // BWA MEM2 // channel: [ sample_key, fastq_pair_count ] ch_sample_fastq_pair_count = ch_meta_samples_sorted.runnable_fastq.map { meta_sample -> @@ -190,7 +190,7 @@ workflow READ_ALIGNMENT { } // channel: [ meta_fastq, bam ] - BWA_MEM( + BWA_MEM2( ch_bwa_mem_inputs, genome_fasta, genome_bwa_index, @@ -198,7 +198,7 @@ workflow READ_ALIGNMENT { // channel: [ meta_fastq, bam, bai ] SAMBAMBA_INDEX( - BWA_MEM.out.bam, + BWA_MEM2.out.bam, ) // Merge all bam records for a single sample into a singlke record. From 8456695db7c08b2726c8f517492b7e3f6a6f80fd Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 13 Feb 2024 14:28:39 +1100 Subject: [PATCH 291/562] Fixing read group flag for bwa mem2. --- modules/local/bwa/Dockerfile | 2 +- modules/local/bwa/mem/main.nf | 52 ------------------------------- modules/local/bwa/mem2/Dockerfile | 9 ------ modules/local/bwa/mem2/main.nf | 4 +-- 4 files changed, 3 insertions(+), 64 deletions(-) delete mode 100644 modules/local/bwa/mem/main.nf delete mode 100644 modules/local/bwa/mem2/Dockerfile diff --git a/modules/local/bwa/Dockerfile b/modules/local/bwa/Dockerfile index 2172ebc4..0f2641da 100644 --- a/modules/local/bwa/Dockerfile +++ b/modules/local/bwa/Dockerfile @@ -4,6 +4,6 @@ RUN \ conda install -y -n base conda-libmamba-solver && \ conda config --set solver libmamba && \ conda install -y -c bioconda -c conda-forge -c conda \ - 'bwa==0.7.17' \ + 'bwa-mem2==2.2.1' \ 'sambamba==1.0' && \ conda clean -yaf diff --git a/modules/local/bwa/mem/main.nf b/modules/local/bwa/mem/main.nf deleted file mode 100644 index e3b54dd4..00000000 --- a/modules/local/bwa/mem/main.nf +++ /dev/null @@ -1,52 +0,0 @@ -process BWA_MEM { - tag "${meta.id}" - - // TODO(MC): What process label? - // label 'process_medium' - - container 'docker.io/scwatts/bwa:0.7.17-sambamba' - - input: - tuple val(meta), path(reads_fwd), path(reads_rev) - path genome_fasta - path genome_bwa_index - - output: - tuple val(meta), path('*bam'), emit: bam - - // TODO(MC): How does this work? - when: - task.ext.when == null || task.ext.when - - // # TODO(MC): read group - // # -R ${meta.read_group} - - script: - """ - ln -s \$(find -L ${genome_bwa_index} -type f) ./ - - bwa mem \\ - -Y \\ - -t ${task.cpus} \\ - ${genome_fasta} \\ - ${reads_fwd} \\ - ${reads_rev} | \\ - \\ - sambamba view \\ - --sam-input \\ - --format bam \\ - --compression-level 0 \\ - --nthreads ${task.cpus} \\ - /dev/stdin | \\ - \\ - sambamba sort \\ - --nthreads ${task.cpus} \\ - --out ${meta.split}.${meta.sample_id}.${meta.read_group}.bam \\ - /dev/stdin - """ - - stub: - """ - touch ${meta.split}.${meta.sample_id}.${meta.read_group}.bam - """ -} diff --git a/modules/local/bwa/mem2/Dockerfile b/modules/local/bwa/mem2/Dockerfile deleted file mode 100644 index 0f2641da..00000000 --- a/modules/local/bwa/mem2/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM docker.io/continuumio/miniconda3:23.10.0-1 - -RUN \ - conda install -y -n base conda-libmamba-solver && \ - conda config --set solver libmamba && \ - conda install -y -c bioconda -c conda-forge -c conda \ - 'bwa-mem2==2.2.1' \ - 'sambamba==1.0' && \ - conda clean -yaf diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index 03d5d327..08c8e503 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -22,14 +22,14 @@ process BWA_MEM2 { task.ext.when == null || task.ext.when script: - // # TODO(MC): read group - // # -R ${meta.read_group} + def read_group_tag = "@RG\t${meta.read_group}" """ ln -s \$(find -L ${genome_bwa_index} -type f) ./ bwa-mem2 mem \\ -Y \\ + -R '${read_group_tag}' \\ -t ${task.cpus} \\ ${genome_fasta} \\ ${reads_fwd} \\ From c3f90500953b2ec32f040d14b0a9dcd7b0263112 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 13 Feb 2024 14:32:54 +1100 Subject: [PATCH 292/562] Reassigning TODO. --- subworkflows/local/read_alignment.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index d8d654a8..c258a06b 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -289,7 +289,7 @@ workflow READ_ALIGNMENT { emit: dna = ch_bwa_outputs // channel: [ meta ] - // TODO(MC): RNA alignment. + // TODO(SW): RNA alignment. rna = ch_star_outputs // channel: [ meta, bam_rna ] // TODO(MC): Versions. From f16be0ddcd46ec9bfa0be32112e85961615ca339 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 13 Feb 2024 16:12:11 +1100 Subject: [PATCH 293/562] Add tests for remaining subworkflows --- ...dna.single.csv => wgts.dna_rna.single.csv} | 1 + .../local/amber_profiling.nf.test | 4 +- .../local/bamtools_metrics.nf.test | 6 +- .../local/chord_prediction.nf.test | 8 +-- .../local/cobalt_profiling.nf.test | 4 +- .../local/cuppa_prediction.nf.test | 6 +- .../local/flagstat_metrics.nf.test | 40 +++++++++++ .../local/gridss_svprep_calling.nf.test | 51 ++++++++++++++ .../local/gripss_filtering.nf.test | 50 ++++++++++++++ .../local/isofox_quantification.nf.test | 50 ++++++++++++++ .../subworkflows/local/lilac_calling.nf.test | 46 +++++++++++++ .../local/linx_annotation.nf.test | 46 +++++++++++++ .../subworkflows/local/linx_plotting.nf.test | 43 ++++++++++++ .../local/orange_reporting.nf.test | 67 ++++++++++++++++++ .../local/pave_annotation.nf.test | 62 +++++++++++++++++ .../subworkflows/local/purple_calling.nf.test | 69 +++++++++++++++++++ tests/subworkflows/local/sage_append.nf.test | 45 ++++++++++++ tests/subworkflows/local/sage_calling.nf.test | 52 ++++++++++++++ .../subworkflows/local/sigs_fittings.nf.test | 42 +++++++++++ .../local/virusbreakend_calling.nf.test | 52 ++++++++++++++ 20 files changed, 729 insertions(+), 15 deletions(-) rename tests/samplesheets/{wgts.dna.single.csv => wgts.dna_rna.single.csv} (70%) create mode 100644 tests/subworkflows/local/flagstat_metrics.nf.test create mode 100644 tests/subworkflows/local/gridss_svprep_calling.nf.test create mode 100644 tests/subworkflows/local/gripss_filtering.nf.test create mode 100644 tests/subworkflows/local/isofox_quantification.nf.test create mode 100644 tests/subworkflows/local/lilac_calling.nf.test create mode 100644 tests/subworkflows/local/linx_annotation.nf.test create mode 100644 tests/subworkflows/local/linx_plotting.nf.test create mode 100644 tests/subworkflows/local/orange_reporting.nf.test create mode 100644 tests/subworkflows/local/pave_annotation.nf.test create mode 100644 tests/subworkflows/local/purple_calling.nf.test create mode 100644 tests/subworkflows/local/sage_append.nf.test create mode 100644 tests/subworkflows/local/sage_calling.nf.test create mode 100644 tests/subworkflows/local/sigs_fittings.nf.test create mode 100644 tests/subworkflows/local/virusbreakend_calling.nf.test diff --git a/tests/samplesheets/wgts.dna.single.csv b/tests/samplesheets/wgts.dna_rna.single.csv similarity index 70% rename from tests/samplesheets/wgts.dna.single.csv rename to tests/samplesheets/wgts.dna_rna.single.csv index 61c5c36c..6682d60b 100644 --- a/tests/samplesheets/wgts.dna.single.csv +++ b/tests/samplesheets/wgts.dna_rna.single.csv @@ -1,3 +1,4 @@ group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath COLO829,COLO829,COLO829v003T,tumor,dna,bam,meta/test_data/sample_data/COLO829T.bam COLO829,COLO829,COLO829v003R,normal,dna,bam,meta/test_data/sample_data/COLO829R.bam +COLO829,COLO829,PTC_NebRNA230605,tumor,rna,bam,meta/test_data/sample_data/PTC_NebRNA230605.md.mini.bam diff --git a/tests/subworkflows/local/amber_profiling.nf.test b/tests/subworkflows/local/amber_profiling.nf.test index 4aafe9f6..6f7a8d1e 100644 --- a/tests/subworkflows/local/amber_profiling.nf.test +++ b/tests/subworkflows/local/amber_profiling.nf.test @@ -12,7 +12,7 @@ nextflow_workflow { script "subworkflows/local/prepare_inputs.nf" process { """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna.single.csv' + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' """ } } @@ -20,7 +20,7 @@ nextflow_workflow { when { params { - outdir "${outputDir}" + outdir = "${outputDir}" max_cpus = 1 max_memory = "10.GB" diff --git a/tests/subworkflows/local/bamtools_metrics.nf.test b/tests/subworkflows/local/bamtools_metrics.nf.test index 64eecd23..23f809af 100644 --- a/tests/subworkflows/local/bamtools_metrics.nf.test +++ b/tests/subworkflows/local/bamtools_metrics.nf.test @@ -12,7 +12,7 @@ nextflow_workflow { script "subworkflows/local/prepare_inputs.nf" process { """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna.single.csv' + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' """ } } @@ -20,7 +20,7 @@ nextflow_workflow { when { params { - outdir "${outputDir}" + outdir = "${outputDir}" // NOTE(SW): BamTools fails when using a single thread max_cpus = 2 @@ -29,7 +29,7 @@ nextflow_workflow { workflow { """ input[0] = PREPARE_INPUTS.out.inputs - input[1] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[1] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' input[2] = '38' """ } diff --git a/tests/subworkflows/local/chord_prediction.nf.test b/tests/subworkflows/local/chord_prediction.nf.test index bdffb54f..4007120c 100644 --- a/tests/subworkflows/local/chord_prediction.nf.test +++ b/tests/subworkflows/local/chord_prediction.nf.test @@ -12,7 +12,7 @@ nextflow_workflow { script "subworkflows/local/prepare_inputs.nf" process { """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna.single.csv' + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' """ } } @@ -20,7 +20,7 @@ nextflow_workflow { when { params { - outdir "${outputDir}" + outdir = "${outputDir}" max_cpus = 1 max_memory = "10.GB" @@ -28,9 +28,7 @@ nextflow_workflow { workflow { """ input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine( - Channel.of('${baseDir}/test_data/module_data/purple/') - ) + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) input[2] = '38' """ } diff --git a/tests/subworkflows/local/cobalt_profiling.nf.test b/tests/subworkflows/local/cobalt_profiling.nf.test index 20633f2c..ec2ff985 100644 --- a/tests/subworkflows/local/cobalt_profiling.nf.test +++ b/tests/subworkflows/local/cobalt_profiling.nf.test @@ -12,7 +12,7 @@ nextflow_workflow { script "subworkflows/local/prepare_inputs.nf" process { """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna.single.csv' + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' """ } } @@ -20,7 +20,7 @@ nextflow_workflow { when { params { - outdir "${outputDir}" + outdir = "${outputDir}" max_cpus = 1 max_memory = "10.GB" diff --git a/tests/subworkflows/local/cuppa_prediction.nf.test b/tests/subworkflows/local/cuppa_prediction.nf.test index 3171abd9..b39424f3 100644 --- a/tests/subworkflows/local/cuppa_prediction.nf.test +++ b/tests/subworkflows/local/cuppa_prediction.nf.test @@ -12,7 +12,7 @@ nextflow_workflow { script "subworkflows/local/prepare_inputs.nf" process { """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna.single.csv' + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' """ } } @@ -20,7 +20,7 @@ nextflow_workflow { when { params { - outdir "${outputDir}" + outdir = "${outputDir}" max_cpus = 1 max_memory = "10.GB" @@ -30,7 +30,7 @@ nextflow_workflow { input[0] = PREPARE_INPUTS.out.inputs input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/isofox/')) input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[3] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx_somatic/')) + input[3] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx/somatic_annotations/')) input[4] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/virusinterpreter/')) input[5] = '38' input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/cuppa/' diff --git a/tests/subworkflows/local/flagstat_metrics.nf.test b/tests/subworkflows/local/flagstat_metrics.nf.test new file mode 100644 index 00000000..b898b521 --- /dev/null +++ b/tests/subworkflows/local/flagstat_metrics.nf.test @@ -0,0 +1,40 @@ +nextflow_workflow { + + name "Test flagstat subworkflow" + script "subworkflows/local/flagstat_metrics.nf" + workflow "FLAGSTAT_METRICS" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/gridss_svprep_calling.nf.test b/tests/subworkflows/local/gridss_svprep_calling.nf.test new file mode 100644 index 00000000..ad4b96d8 --- /dev/null +++ b/tests/subworkflows/local/gridss_svprep_calling.nf.test @@ -0,0 +1,51 @@ +nextflow_workflow { + + name "Test SvPrep subworkflow" + script "subworkflows/local/gridss_svprep_calling.nf" + workflow "GRIDSS_SVPREP_CALLING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[2] = '38' + input[3] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' + input[5] = '${baseDir}/test_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188/' + input[6] = '${baseDir}/test_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img' + input[7] = '${baseDir}/test_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache' + input[8] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/gridss_blacklist.38.bed.gz' + input[9] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/sv_prep_blacklist.38.bed' + input[10] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/known_fusions.38.bedpe' + input[11] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/gridss.properties' + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/gripss_filtering.nf.test b/tests/subworkflows/local/gripss_filtering.nf.test new file mode 100644 index 00000000..aa0f1d07 --- /dev/null +++ b/tests/subworkflows/local/gripss_filtering.nf.test @@ -0,0 +1,50 @@ +nextflow_workflow { + + name "Test GRIPSS subworkflow" + script "subworkflows/local/gripss_filtering.nf" + workflow "GRIPSS_FILTERING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + // NOTE(SW): BamTools fails when using a single thread + max_cpus = 2 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/gridss/depth_annotator/COLO829v003T.gridss.vcf.gz')) + input[2] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[3] = '38' + input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/sgl_pon.38.bed.gz' + input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/sv_pon.38.bedpe.gz' + input[7] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/known_fusions.38.bedpe' + input[8] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/repeat_mask_data.38.fa.gz' + input[9] = [] + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/isofox_quantification.nf.test b/tests/subworkflows/local/isofox_quantification.nf.test new file mode 100644 index 00000000..3e0469e5 --- /dev/null +++ b/tests/subworkflows/local/isofox_quantification.nf.test @@ -0,0 +1,50 @@ +nextflow_workflow { + + name "Test Isofox subworkflow" + script "subworkflows/local/isofox_quantification.nf" + workflow "ISOFOX_QUANTIFICATION" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[2] = '38' + input[3] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[4] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' + input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/rna_pipeline/read_151_exp_counts.csv' + input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/rna_pipeline/read_100_exp_gc_ratios.csv' + input[7] = [] + input[8] = [] + input[9] = '' + input[10] = 151 + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/lilac_calling.nf.test b/tests/subworkflows/local/lilac_calling.nf.test new file mode 100644 index 00000000..69761995 --- /dev/null +++ b/tests/subworkflows/local/lilac_calling.nf.test @@ -0,0 +1,46 @@ +nextflow_workflow { + + name "Test LILAC subworkflow" + script "subworkflows/local/lilac_calling.nf" + workflow "LILAC_CALLING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) + input[2] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[3] = '38' + input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/immune/' + input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/other/lilac/hla.38.bed' + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/linx_annotation.nf.test b/tests/subworkflows/local/linx_annotation.nf.test new file mode 100644 index 00000000..1cda649d --- /dev/null +++ b/tests/subworkflows/local/linx_annotation.nf.test @@ -0,0 +1,46 @@ +nextflow_workflow { + + name "Test LINX annotation subworkflow" + script "subworkflows/local/linx_annotation.nf" + workflow "LINX_ANNOTATION" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) + input[2] = '38' + input[3] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' + input[4] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/known_fusion_data.38.csv' + input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/DriverGenePanel.38.tsv' + input[6] = [] + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/linx_plotting.nf.test b/tests/subworkflows/local/linx_plotting.nf.test new file mode 100644 index 00000000..62e53300 --- /dev/null +++ b/tests/subworkflows/local/linx_plotting.nf.test @@ -0,0 +1,43 @@ +nextflow_workflow { + + name "Test LINX plotting subworkflow" + script "subworkflows/local/linx_plotting.nf" + workflow "LINX_PLOTTING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx/somatic_annotations/')) + input[2] = '38' + input[3] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/orange_reporting.nf.test b/tests/subworkflows/local/orange_reporting.nf.test new file mode 100644 index 00000000..a905687a --- /dev/null +++ b/tests/subworkflows/local/orange_reporting.nf.test @@ -0,0 +1,67 @@ +nextflow_workflow { + + name "Test ORANGE subworkflow" + script "subworkflows/local/orange_reporting.nf" + workflow "ORANGE_REPORTING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/bamtools/COLO829v003T.wgsmetrics')) + input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/bamtools/COLO829v003R.wgsmetrics')) + input[3] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/flagstats/COLO829v003T.flagstat')) + input[4] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/flagstats/COLO829v003R.flagstat')) + input[5] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/sage/somatic/')) + input[6] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/sage/germline/')) + input[7] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/sage/append/COLO829v003T.sage.append.vcf.gz')) + input[8] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/sage/append/COLO829v003R.sage.append.vcf.gz')) + input[9] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) + input[10] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx/somatic_annotations/')) + input[11] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx/somatic_plots/')) + input[12] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx/germline_annotations/')) + input[13] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/virusinterpreter/')) + input[14] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/chord/')) + input[15] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/sigs/')) + input[16] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/lilac/')) + input[17] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/cuppa/')) + input[18] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/isofox/')) + input[19] = '38' + input[20] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/disease_ontology/doid.json' + input[21] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/orange/cohort_mapping.tsv' + input[22] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/orange/cohort_percentiles.tsv' + input[23] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/known_fusion_data.38.csv' + input[24] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/DriverGenePanel.38.tsv' + input[25] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' + input[26] = Channel.of('${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/rna_pipeline/isofox.hmf_3444.alt_sj_cohort.38.csv') + input[27] = Channel.of('${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/rna_pipeline/isofox.hmf_3444.gene_distribution.38.csv') + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/pave_annotation.nf.test b/tests/subworkflows/local/pave_annotation.nf.test new file mode 100644 index 00000000..bedeb550 --- /dev/null +++ b/tests/subworkflows/local/pave_annotation.nf.test @@ -0,0 +1,62 @@ +nextflow_workflow { + + name "Test PAVE subworkflow" + script "subworkflows/local/pave_annotation.nf" + workflow "PAVE_ANNOTATION" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + mode = "wgts" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of([ + '${baseDir}/test_data/module_data/sage/somatic/COLO829v003T.sage.somatic.vcf.gz', + '${baseDir}/test_data/module_data/sage/somatic/COLO829v003T.sage.somatic.vcf.gz.tbi', + ])) + input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of([ + '${baseDir}/test_data/module_data/sage/germline/COLO829v003T.sage.germline.vcf.gz', + '${baseDir}/test_data/module_data/sage/germline/COLO829v003T.sage.germline.vcf.gz.tbi', + ])) + input[3] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[4] = '38' + input[5] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/SageGermlinePon.98x.38.tsv.gz' + input[7] = [] + input[8] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownBlacklist.germline.38.bed' + input[9] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownBlacklist.germline.38.vcf.gz' + input[10] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/clinvar.38.vcf.gz' + input[11] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/mappability_150.38.bed.gz' + input[12] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/DriverGenePanel.38.tsv' + input[13] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' + input[14] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/gnomad/' + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/purple_calling.nf.test b/tests/subworkflows/local/purple_calling.nf.test new file mode 100644 index 00000000..e64c0056 --- /dev/null +++ b/tests/subworkflows/local/purple_calling.nf.test @@ -0,0 +1,69 @@ +nextflow_workflow { + + name "Test PURPLE subworkflow" + script "subworkflows/local/purple_calling.nf" + workflow "PURPLE_CALLING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/amber/')) + input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/cobalt/')) + input[3] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/pave/COLO829v003T.sage.somatic.pave.vcf.gz')) + input[4] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/pave/COLO829v003T.sage.germline.pave.vcf.gz')) + input[5] = PREPARE_INPUTS.out.inputs.combine(Channel.of([ + '${baseDir}/test_data/module_data/gripss/somatic/COLO829v003T.gripss.filtered.somatic.vcf.gz', + '${baseDir}/test_data/module_data/gripss/somatic/COLO829v003T.gripss.filtered.somatic.vcf.gz.tbi', + ])) + input[6] = PREPARE_INPUTS.out.inputs.combine(Channel.of([ + '${baseDir}/test_data/module_data/gripss/germline/COLO829v003T.gripss.filtered.germline.vcf.gz', + '${baseDir}/test_data/module_data/gripss/germline/COLO829v003T.gripss.filtered.germline.vcf.gz.tbi', + ])) + input[7] = PREPARE_INPUTS.out.inputs.combine(Channel.of([ + '${baseDir}/test_data/module_data/gripss/somatic/COLO829v003T.gripss.somatic.vcf.gz', + '${baseDir}/test_data/module_data/gripss/somatic/COLO829v003T.gripss.somatic.vcf.gz.tbi', + ])) + input[8] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[9] = '38' + input[10] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[11] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' + input[12] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/copy_number/GC_profile.1000bp.38.cnp' + input[13] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.somatic.38.vcf.gz' + input[14] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.germline.38.vcf.gz' + input[15] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/DriverGenePanel.38.tsv' + input[16] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' + input[17] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/copy_number/cohort_germline_del_freq.38.csv' + input[18] = [] + input[19] = [] + input[20] = [] + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/sage_append.nf.test b/tests/subworkflows/local/sage_append.nf.test new file mode 100644 index 00000000..98e49270 --- /dev/null +++ b/tests/subworkflows/local/sage_append.nf.test @@ -0,0 +1,45 @@ +nextflow_workflow { + + name "Test SAGE append subworkflow" + script "subworkflows/local/sage_append.nf" + workflow "SAGE_APPEND" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) + input[2] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[3] = '38' + input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[5] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/sage_calling.nf.test b/tests/subworkflows/local/sage_calling.nf.test new file mode 100644 index 00000000..a3ea3f0a --- /dev/null +++ b/tests/subworkflows/local/sage_calling.nf.test @@ -0,0 +1,52 @@ +nextflow_workflow { + + name "Test SAGE calling subworkflow" + script "subworkflows/local/sage_calling.nf" + workflow "SAGE_CALLING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[2] = '38' + input[3] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' + input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.somatic.38.vcf.gz' + input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.germline.38.vcf.gz' + input[7] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/ActionableCodingPanel.38.bed.gz' + input[8] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/CoverageCodingPanel.38.bed.gz' + input[9] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz' + input[10] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/mappability_150.38.bed.gz' + input[11] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/DriverGenePanel.38.tsv' + input[12] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/sigs_fittings.nf.test b/tests/subworkflows/local/sigs_fittings.nf.test new file mode 100644 index 00000000..d54bac1e --- /dev/null +++ b/tests/subworkflows/local/sigs_fittings.nf.test @@ -0,0 +1,42 @@ +nextflow_workflow { + + name "Test Sigs subworkflow" + script "subworkflows/local/sigs_fitting.nf" + workflow "SIGS_FITTING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) + input[2] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/sigs/snv_cosmic_signatures.csv' + """ + } + } + + then { + assert workflow.success + } + + } +} diff --git a/tests/subworkflows/local/virusbreakend_calling.nf.test b/tests/subworkflows/local/virusbreakend_calling.nf.test new file mode 100644 index 00000000..e70b9480 --- /dev/null +++ b/tests/subworkflows/local/virusbreakend_calling.nf.test @@ -0,0 +1,52 @@ +nextflow_workflow { + + name "Test VIRUSBreakend subworkflow" + script "subworkflows/local/virusbreakend_calling.nf" + workflow "VIRUSBREAKEND_CALLING" + profile "docker" + + test("WGTS COLO829 mini") { + + setup { + run("PREPARE_INPUTS") { + script "subworkflows/local/prepare_inputs.nf" + process { + """ + input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' + """ + } + } + } + + when { + params { + outdir = "${outputDir}" + + max_cpus = 1 + max_memory = "10.GB" + } + workflow { + """ + input[0] = PREPARE_INPUTS.out.inputs + input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) + input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/bamtools/COLO829v003T.wgsmetrics')) + input[3] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[5] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' + input[6] = '${baseDir}/test_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188/' + input[7] = '${baseDir}/test_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img' + input[8] = '${baseDir}/test_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache' + input[9] = '${baseDir}/test_data/reference_data/other/virusbreakenddb_test/' + input[10] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/virusinterpreter/taxonomy_db.tsv' + input[11] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/virusinterpreter/virus_reporting_db.tsv' + input[12] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/gridss.properties' + """ + } + } + + then { + assert workflow.success + } + + } +} From fe49cf0f5648f3a57b7905fe575c47ca03c9ecb0 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 13 Feb 2024 17:07:48 +1100 Subject: [PATCH 294/562] Emiting versions. --- lib/Constants.groovy | 4 +-- modules/local/bwa/mem2/main.nf | 27 ++++++----------- modules/local/fastp/main.nf | 13 +++++++-- modules/local/markdups/main.nf | 42 +++++++++------------------ modules/local/sambamba/index/main.nf | 11 +++++++ subworkflows/local/read_alignment.nf | 18 +++++++----- subworkflows/local/read_processing.nf | 9 +++--- workflows/wgts.nf | 6 ++-- 8 files changed, 61 insertions(+), 69 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index f3fc958b..91f1059c 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -34,8 +34,7 @@ class Constants { } static enum Process { - // TODO[MC]: Add process here. - BWAMEM, + BWAMEM2, AMBER, BAMTOOLS, CHORD, @@ -113,7 +112,6 @@ class Constants { static Map PLACEHOLDER_META = [meta_placeholder: null] static List PLACEHOLDER_OPTIONAL_CHANNEL = [] - // TODO(MC): How is this used? static Map INPUT = [ ISOFOX_DIR: [ diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index 08c8e503..bc1df838 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -15,8 +15,7 @@ process BWA_MEM2 { output: tuple val(meta), path('*.bam'), emit: bam - // TODO(MC): Versions. - // path 'versions.yml' , emit: versions + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -46,26 +45,18 @@ process BWA_MEM2 { --nthreads ${task.cpus} \\ --out ${meta.split}.${meta.sample_id}.${meta.read_group}.bam \\ /dev/stdin - """ - - // TODO(SW): Versions. - // """ - // touch bar - // cat <<-END_VERSIONS > versions.yml - // "${task.process}": - // bwamem2: foo - // END_VERSIONS - // """ + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwamem2: 2.2.1 + sambamba: 1.0 + END_VERSIONS + """ stub: """ touch ${meta.split}.${meta.sample_id}.${meta.read_group}.bam - """ - // TODO(MV): Versions. - // """ - // touch bar - // echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - // """ + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ } diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index 35d3714b..a14b43ec 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -1,8 +1,6 @@ process FASTP { tag "${meta.id}" - // TODO(MC): Resources? - container 'docker.io/scwatts/fastp:0.23.4' input: @@ -11,6 +9,10 @@ process FASTP { output: tuple val(meta), path('*_R1.fastp.fastq'), path('*_R2.fastp.fastq'), emit: fastq + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when script: // TODO(MC): UMI flags @@ -29,11 +31,18 @@ process FASTP { --split_by_lines ${4 * max_fastq_records} \\ --out1 ${meta.sample_id}_${meta.read_group}_R1.fastp.fastq \\ --out2 ${meta.sample_id}_${meta.read_group}_R2.fastp.fastq + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastp: 0.23.4 + END_VERSIONS """ stub: """ touch 00{1..4}.${meta.sample_id}_${meta.read_group}_R1.fastp.fastq touch 00{1..4}.${meta.sample_id}_${meta.read_group}_R2.fastp.fastq + + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 7a25e728..c3f97e28 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -1,9 +1,6 @@ process MARKDUPS { tag "${meta_bam.id}" - // TODO(MC): Resources required? - // label 'process_low' - container 'docker.io/scwatts/markdups:1.1.rc1' input: @@ -15,35 +12,13 @@ process MARKDUPS { output: tuple val(meta_bam), path('*bam'), path('*bai'), emit: bam + path 'versions.yml' , emit: versions path '*.tsv' - // TODO(MC): Make sure this is in each. when: task.ext.when == null || task.ext.when - // TODO(MC): Versions in each. - // path 'versions.yml' , emit: versions - - // script: - // def args = task.ext.args ?: '' - - // // TODO(SW): implement process - // """ - // echo bar - - // cat <<-END_VERSIONS > versions.yml - // "${task.process}": - // markdups: foo - // END_VERSIONS - // """ - - // stub: - // // TODO(SW): implement stub - // """ - // touch bar - // echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - // """ - + script: // # TODO(MC): Umi flags // # -multi_bam \\ // # -umi_enabled \\ @@ -51,7 +26,6 @@ process MARKDUPS { // # -umi_duplex_delim _ \\ // # -umi_base_diff_stats \\ - script: """ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ @@ -73,6 +47,14 @@ process MARKDUPS { -threads 16 \\ \\ -output_bam ${meta_bam.sample_id}.mark_dups.bam + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sambamba: 1.0 + samtools: 1.17 + openjdk: >=8 + mark-dups: 1.1 + END_VERSIONS """ stub: @@ -80,9 +62,11 @@ process MARKDUPS { touch ${meta_bam.sample_id}.mark_dups.bam touch ${meta_bam.sample_id}.mark_dups.bam.bai touch ${meta_bam.sample_id}.duplicate_freq.tsv + + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ - // # TODO(MC): + // # TODO(MC): UMIs. // # touch ${meta_bam.sample_id}.umi_coord_freq.tsv // # touch ${meta_bam.sample_id}.umi_edit_distance.tsv // # touch ${meta_bam.sample_id}.umi_nucleotide_freq.tsv diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf index f6cf00ea..2c42e475 100644 --- a/modules/local/sambamba/index/main.nf +++ b/modules/local/sambamba/index/main.nf @@ -8,16 +8,27 @@ process SAMBAMBA_INDEX { output: tuple val(meta), path(bam), path('*bai'), emit: bam + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when script: """ sambamba index \\ --nthreads ${task.cpus} \\ ${meta.split}.${meta.sample_id}.${meta.read_group}.bam + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sambamba: 1.0 + END_VERSIONS """ stub: """ touch ${meta.split}.${meta.sample_id}.${meta.read_group}.bam.bai + + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index c258a06b..47259fd1 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -12,10 +12,9 @@ workflow READ_ALIGNMENT { max_fastq_records main: - // TODO(MC): Versions. - // // Channel for version.yml files - // // channel: [ versions.yml ] - // ch_versions = Channel.empty() + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() // channel: [ group_id, sample_count ] ch_sample_counts = ch_inputs.map { meta -> [meta.group_id, Utils.groupSampleCounts(meta)] } @@ -110,6 +109,8 @@ workflow READ_ALIGNMENT { max_fastq_records, ) + ch_versions = ch_versions.mix(FASTP.out.versions) + ch_split_fastq_pairs = FASTP.out.fastq } else { ch_split_fastq_pairs = ch_fastq_pairs.map { fastq_pair -> [fastq_pair[0], [fastq_pair[1]], [fastq_pair[2]]] } @@ -196,11 +197,15 @@ workflow READ_ALIGNMENT { genome_bwa_index, ) + ch_versions = ch_versions.mix(BWA_MEM2.out.versions) + // channel: [ meta_fastq, bam, bai ] SAMBAMBA_INDEX( BWA_MEM2.out.bam, ) + ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) + // Merge all bam records for a single sample into a singlke record. // channel: [ meta ] (One sample per meta record). ch_merged_bam_samples = ch_sample_fastq_pair_split_count @@ -288,10 +293,7 @@ workflow READ_ALIGNMENT { emit: dna = ch_bwa_outputs // channel: [ meta ] - // TODO(SW): RNA alignment. rna = ch_star_outputs // channel: [ meta, bam_rna ] - - // TODO(MC): Versions. - // versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/read_processing.nf b/subworkflows/local/read_processing.nf index d8de6b54..53815d86 100644 --- a/subworkflows/local/read_processing.nf +++ b/subworkflows/local/read_processing.nf @@ -12,10 +12,9 @@ workflow READ_PROCESSING { unmap_regions main: - // TODO(MC): Versions. // Channel for version.yml files // channel: [ versions.yml ] - // ch_versions = Channel.empty() + ch_versions = Channel.empty() // channel: [ group_id, sample_count ] ch_sample_counts = ch_inputs.map { meta -> [meta.group_id, Utils.groupSampleCounts(meta)] } @@ -70,6 +69,8 @@ workflow READ_PROCESSING { unmap_regions, ) + ch_versions = ch_versions.mix(MARKDUPS.out.versions) + // Update sample information. // channel: [ meta ] (One sample per meta record). ch_bam_samples = MARKDUPS.out.bam.map { bam -> @@ -128,7 +129,5 @@ workflow READ_PROCESSING { emit: dna = ch_markduplicates_dna_out // channel: [ meta ] rna = ch_markduplicates_rna_out // channel: [ meta, bam_rna ] - - // TODO(MC): Versions. - // versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 1d55a889..bc177865 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -147,8 +147,7 @@ workflow WGTS { params.max_fastq_records, ) - // TODO(MC): Versions. - // ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) + ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) ch_dna_alignment_out = ch_dna_alignment_out.mix(READ_ALIGNMENT.out.dna) ch_rna_alignment_out = ch_rna_alignment_out.mix(READ_ALIGNMENT.out.rna) @@ -181,8 +180,7 @@ workflow WGTS { file(params.refdata_unmap_regions), ) - // TODO(MC): Versions. - // ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) + ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) ch_dna_processed_out = ch_dna_processed_out.mix(READ_PROCESSING.out.dna) ch_rna_processed_out = ch_rna_processed_out.mix(READ_PROCESSING.out.rna) From 1d13b56331f47aa7a11d6f3efae6bc5d8506252b Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 13 Feb 2024 17:14:54 +1100 Subject: [PATCH 295/562] Updating TODOs. --- modules/local/bwa/mem2/main.nf | 5 +++-- workflows/wgts.nf | 9 ++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index bc1df838..aee328ea 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -2,15 +2,16 @@ process BWA_MEM2 { tag "${meta.id}" label 'process_high' - // TODO(MC): Upload container. + // TODO(SW): Upload container. container 'bwa-mem2:2.2.1-sambamba' input: tuple val(meta), path(reads_fwd), path(reads_rev) path genome_fasta - // TODO(MC): Copied into local genome_bwa_index for ref genome 37: + // TODO(SW): The following resourse files are needed from gs://hmf-public/HMFtools-Resources/ref_genome/37: // + Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64 // + Homo_sapiens.GRCh37.GATK.illumina.fasta.0123 + // Similarly for ref genome 38. path genome_bwa_index output: diff --git a/workflows/wgts.nf b/workflows/wgts.nf index bc177865..4a22c9b5 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -15,7 +15,6 @@ inputs = Utils.parseInput(params.input, workflow.stubRun, log) run_config = WorkflowMain.getRunConfig(params, inputs, log) // Validate inputs -// TODO(MC): Reexamine validation in light of fastq/bam markdups. Utils.validateInput(inputs, run_config, log) // Check input path parameters to see if they exist @@ -111,6 +110,14 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft // Get absolute file paths samplesheet = Utils.getFileObject(params.input) +// TODO(MC): New params, and resource files, documentation and proper placement. +// TODO(MC): Processed appearing as NULL. +// TODO(MC): WARN: Found unexpected parameters: +// * --max_fastq_records: 10000000 +// * --refdata_unmap_regions: /Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/markdups/unmap_regions_37.tsv +// - Ignore this warning: params.schema_ignore_params = "max_fastq_records,refdata_unmap_regions" +// TODO(MC): get error logs for amber, cobalt, and gripss +// TODO(MC): Drop commit 'WIP: Reverting bioconda containers'. workflow WGTS { // Create channel for versions // channel: [ versions.yml ] From b31d3cc411c500eebd6768281487a781d5c7faef Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 13 Feb 2024 18:35:06 +1100 Subject: [PATCH 296/562] Fix tab character indent --- tests/subworkflows/local/pave_annotation.nf.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/subworkflows/local/pave_annotation.nf.test b/tests/subworkflows/local/pave_annotation.nf.test index bedeb550..660e0d1c 100644 --- a/tests/subworkflows/local/pave_annotation.nf.test +++ b/tests/subworkflows/local/pave_annotation.nf.test @@ -22,7 +22,7 @@ nextflow_workflow { params { outdir = "${outputDir}" - mode = "wgts" + mode = "wgts" max_cpus = 1 max_memory = "10.GB" From 8ce78ff3727f13fa625a07b981d7c3ffecc41486 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Wed, 14 Feb 2024 10:20:38 +1100 Subject: [PATCH 297/562] Fixing tags for new processes. --- modules/local/bwa/mem2/main.nf | 2 +- modules/local/fastp/main.nf | 2 +- modules/local/markdups/main.nf | 2 +- modules/local/sambamba/index/main.nf | 2 +- workflows/wgts.nf | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index aee328ea..b77606f8 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -1,5 +1,5 @@ process BWA_MEM2 { - tag "${meta.id}" + tag "${meta.subject_id}__${meta.sample_id}" label 'process_high' // TODO(SW): Upload container. diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index a14b43ec..0205452c 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -1,5 +1,5 @@ process FASTP { - tag "${meta.id}" + tag "${meta.subject_id}__${meta.sample_id}" container 'docker.io/scwatts/fastp:0.23.4' diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index c3f97e28..aaa6e301 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -1,5 +1,5 @@ process MARKDUPS { - tag "${meta_bam.id}" + tag "${meta_bam.subject_id}__${meta_bam.sample_id}" container 'docker.io/scwatts/markdups:1.1.rc1' diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf index 2c42e475..cb205904 100644 --- a/modules/local/sambamba/index/main.nf +++ b/modules/local/sambamba/index/main.nf @@ -1,5 +1,5 @@ process SAMBAMBA_INDEX { - tag "${meta.id}" + tag "${meta.subject_id}__${meta.sample_id}" container 'docker.io/scwatts/sambamba:1.0' diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 4a22c9b5..784ed89c 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -111,7 +111,6 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft samplesheet = Utils.getFileObject(params.input) // TODO(MC): New params, and resource files, documentation and proper placement. -// TODO(MC): Processed appearing as NULL. // TODO(MC): WARN: Found unexpected parameters: // * --max_fastq_records: 10000000 // * --refdata_unmap_regions: /Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/markdups/unmap_regions_37.tsv From ee059adf13e5b49b84f7d160b91f14e2812f0faa Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Wed, 14 Feb 2024 10:29:09 +1100 Subject: [PATCH 298/562] Setting up targeted and wgts workflows for testing. + Put read_alignment and read_processing subworkflows into targeted workflow. + Uncomment the whole wgts worflow and integrate this with the read_alignment and read_processing subworkflows. --- workflows/targeted.nf | 150 +++++++++++++++++++++++++++++------------- workflows/wgts.nf | 112 +++++++++++++++---------------- 2 files changed, 159 insertions(+), 103 deletions(-) diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 3e9c0b1b..4fffbf0c 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -2,8 +2,6 @@ import Constants import Processes import Utils -// TODO[MC]: Alignment. - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -125,6 +123,68 @@ workflow TARGETED { // Set GRIDSS config gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config + // + // SUBWORKFLOW: Align reads + // + // channel: [ meta ] + ch_dna_alignment_out = Channel.empty() + // channel: [ meta, bam_rna ] + ch_rna_alignment_out = Channel.empty() + // TODO(SW): set up correctly + if (true || run_config.stages.alignment) { + + READ_ALIGNMENT( + ch_inputs, + ref_data.genome_fasta, + ref_data.genome_bwa_index, + params.max_fastq_records, + ) + + ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) + + ch_dna_alignment_out = ch_dna_alignment_out.mix(READ_ALIGNMENT.out.dna) + ch_rna_alignment_out = ch_rna_alignment_out.mix(READ_ALIGNMENT.out.rna) + + + } else { + + ch_dna_alignment_out = ch_inputs + ch_rna_alignment_out = ch_inputs.map { meta -> [meta, []] } + + } + + // + // SUBWORKFLOW: Process read alignments + // + // channel: [ meta ] + ch_dna_processed_out = Channel.empty() + // channel: [ meta, bam_rna ] + ch_rna_processed_out = Channel.empty() + // TODO(SW): set up correctly + if (true || run_config.stages.markdups) { + + READ_PROCESSING( + ch_inputs, + ch_dna_alignment_out, + ch_rna_alignment_out, + ref_data.genome_fasta, + ref_data.genome_fai, + ref_data.genome_dict, + file(params.refdata_unmap_regions), + ) + + ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) + + ch_dna_processed_out = ch_dna_processed_out.mix(READ_PROCESSING.out.dna) + ch_rna_processed_out = ch_rna_processed_out.mix(READ_PROCESSING.out.rna) + + } else { + + ch_dna_processed_out = ch_inputs.map + ch_rna_processed_out = ch_inputs.map { meta -> [meta, []] } + + } + // // MODULE: Run Isofox to analyse RNA data // @@ -139,7 +199,7 @@ workflow TARGETED { isofox_tpm_norm = params.isofox_tpm_norm ? file(params.isofox_tpm_norm) : panel_data.isofox_tpm_norm ISOFOX_QUANTIFICATION( - ch_inputs, + ch_dna_processed_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -158,7 +218,7 @@ workflow TARGETED { } else { - ch_isofox_out = ch_inputs.map { meta -> [meta, []] } + ch_isofox_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -170,7 +230,7 @@ workflow TARGETED { if (run_config.stages.amber) { AMBER_PROFILING( - ch_inputs, + ch_dna_processed_out, ref_data.genome_version, hmf_data.heterozygous_sites, panel_data.target_region_bed, @@ -181,7 +241,7 @@ workflow TARGETED { } else { - ch_amber_out = ch_inputs.map { meta -> [meta, []] } + ch_amber_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -193,7 +253,7 @@ workflow TARGETED { if (run_config.stages.cobalt) { COBALT_PROFILING( - ch_inputs, + ch_dna_processed_out, hmf_data.gc_profile, hmf_data.diploid_bed, panel_data.target_region_normalisation, @@ -205,7 +265,7 @@ workflow TARGETED { } else { - ch_cobalt_out = ch_inputs.map { meta -> [meta, []] } + ch_cobalt_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -217,7 +277,7 @@ workflow TARGETED { if (run_config.stages.gridss) { GRIDSS_SVPREP_CALLING( - ch_inputs, + ch_dna_processed_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -237,7 +297,7 @@ workflow TARGETED { } else { - ch_gridss_out = ch_inputs.map { meta -> [meta, []] } + ch_gridss_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -251,7 +311,7 @@ workflow TARGETED { if (run_config.stages.gripss) { GRIPSS_FILTERING( - ch_inputs, + ch_dna_processed_out, ch_gridss_out, ref_data.genome_fasta, ref_data.genome_version, @@ -271,9 +331,9 @@ workflow TARGETED { } else { - ch_gripss_somatic_out = ch_inputs.map { meta -> [meta, [], []] } - ch_gripss_germline_out = ch_inputs.map { meta -> [meta, [], []] } - ch_gripss_somatic_unfiltered_out = ch_inputs.map { meta -> [meta, [], []] } + ch_gripss_somatic_out = ch_dna_processed_out.map { meta -> [meta, [], []] } + ch_gripss_germline_out = ch_dna_processed_out.map { meta -> [meta, [], []] } + ch_gripss_somatic_unfiltered_out = ch_dna_processed_out.map { meta -> [meta, [], []] } } @@ -289,7 +349,7 @@ workflow TARGETED { if (run_config.stages.sage) { SAGE_CALLING( - ch_inputs, + ch_dna_processed_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -313,10 +373,10 @@ workflow TARGETED { } else { - ch_sage_germline_vcf_out = ch_inputs.map { meta -> [meta, [], []] } - ch_sage_somatic_vcf_out = ch_inputs.map { meta -> [meta, [], []] } - ch_sage_germline_dir_out = ch_inputs.map { meta -> [meta, []] } - ch_sage_somatic_dir_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_germline_vcf_out = ch_dna_processed_out.map { meta -> [meta, [], []] } + ch_sage_somatic_vcf_out = ch_dna_processed_out.map { meta -> [meta, [], []] } + ch_sage_germline_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_sage_somatic_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -329,7 +389,7 @@ workflow TARGETED { if (run_config.stages.pave) { PAVE_ANNOTATION( - ch_inputs, + ch_dna_processed_out, ch_sage_germline_vcf_out, ch_sage_somatic_vcf_out, ref_data.genome_fasta, @@ -353,8 +413,8 @@ workflow TARGETED { } else { - ch_pave_germline_out = ch_inputs.map { meta -> [meta, []] } - ch_pave_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_pave_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_pave_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -366,7 +426,7 @@ workflow TARGETED { if (run_config.stages.purple) { PURPLE_CALLING( - ch_inputs, + ch_dna_processed_out, ch_amber_out, ch_cobalt_out, ch_pave_somatic_out, @@ -395,7 +455,7 @@ workflow TARGETED { } else { - ch_purple_out = ch_inputs.map { meta -> [meta, []] } + ch_purple_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -410,7 +470,7 @@ workflow TARGETED { // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented SAGE_APPEND( - ch_inputs, + ch_dna_processed_out, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, @@ -425,8 +485,8 @@ workflow TARGETED { } else { - ch_sage_somatic_append_out = ch_inputs.map { meta -> [meta, []] } - ch_sage_germline_append_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_somatic_append_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_sage_germline_append_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -439,7 +499,7 @@ workflow TARGETED { if (run_config.stages.linx) { LINX_ANNOTATION( - ch_inputs, + ch_dna_processed_out, ch_purple_out, ref_data.genome_version, hmf_data.ensembl_data_resources, @@ -455,8 +515,8 @@ workflow TARGETED { } else { - ch_linx_somatic_out = ch_inputs.map { meta -> [meta, []] } - ch_linx_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_linx_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_linx_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -468,7 +528,7 @@ workflow TARGETED { if (run_config.stages.linx) { LINX_PLOTTING( - ch_inputs, + ch_dna_processed_out, ch_linx_somatic_out, ref_data.genome_version, hmf_data.ensembl_data_resources, @@ -480,7 +540,7 @@ workflow TARGETED { } else { - ch_linx_somatic_visualiser_dir_out = ch_inputs.map { meta -> [meta, []] } + ch_linx_somatic_visualiser_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -493,7 +553,7 @@ workflow TARGETED { if (run_config.stages.orange && run_config.stages.flagstat) { FLAGSTAT_METRICS( - ch_inputs, + ch_dna_processed_out, ) ch_versions = ch_versions.mix(FLAGSTAT_METRICS.out.versions) @@ -503,8 +563,8 @@ workflow TARGETED { } else { - ch_flagstat_somatic_out = ch_inputs.map { meta -> [meta, []] } - ch_flagstat_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_flagstat_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_flagstat_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -517,7 +577,7 @@ workflow TARGETED { if (run_config.stages.bamtools) { BAMTOOLS_METRICS( - ch_inputs, + ch_dna_processed_out, ref_data.genome_fasta, ref_data.genome_version, ) @@ -529,8 +589,8 @@ workflow TARGETED { } else { - ch_bamtools_somatic_out = ch_inputs.map { meta -> [meta, []] } - ch_bamtools_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_bamtools_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_bamtools_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -545,7 +605,7 @@ workflow TARGETED { ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] LILAC_CALLING( - ch_inputs, + ch_dna_processed_out, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, @@ -560,7 +620,7 @@ workflow TARGETED { } else { - ch_lilac_out = ch_inputs.map { meta -> [meta, []] } + ch_lilac_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -570,13 +630,13 @@ workflow TARGETED { if (run_config.stages.orange) { // Create placeholder channels for empty remaining channels - ch_chord_out = ch_inputs.map { meta -> [meta, []] } - ch_cuppa_out = ch_inputs.map { meta -> [meta, []] } - ch_sigs_out = ch_inputs.map { meta -> [meta, []] } - ch_virusinterpreter_out = ch_inputs.map { meta -> [meta, []] } + ch_chord_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_cuppa_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_sigs_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_virusinterpreter_out = ch_dna_processed_out.map { meta -> [meta, []] } ORANGE_REPORTING( - ch_inputs, + ch_dna_processed_out, ch_bamtools_somatic_out, ch_bamtools_germline_out, ch_flagstat_somatic_out, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 784ed89c..ada38f53 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -198,10 +198,6 @@ workflow WGTS { } - // TODO(SW): adjust downstream selection of input BAM - - /* - // // MODULE: Run Isofox to analyse RNA data // @@ -213,7 +209,7 @@ workflow WGTS { isofox_gc_ratios = params.isofox_gc_ratios ? file(params.isofox_gc_ratios) : hmf_data.isofox_gc_ratios ISOFOX_QUANTIFICATION( - ch_inputs, + ch_dna_processed_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -232,7 +228,7 @@ workflow WGTS { } else { - ch_isofox_out = ch_inputs.map { meta -> [meta, []] } + ch_isofox_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -244,7 +240,7 @@ workflow WGTS { if (run_config.stages.amber) { AMBER_PROFILING( - ch_inputs, + ch_dna_processed_out, ref_data.genome_version, hmf_data.heterozygous_sites, [], // target_region_bed @@ -256,7 +252,7 @@ workflow WGTS { } else { - ch_amber_out = ch_inputs.map { meta -> [meta, []] } + ch_amber_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -268,7 +264,7 @@ workflow WGTS { if (run_config.stages.cobalt) { COBALT_PROFILING( - ch_inputs, + ch_dna_processed_out, hmf_data.gc_profile, hmf_data.diploid_bed, [], // panel_target_region_normalisation @@ -280,7 +276,7 @@ workflow WGTS { } else { - ch_cobalt_out = ch_inputs.map { meta -> [meta, []] } + ch_cobalt_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -292,7 +288,7 @@ workflow WGTS { if (run_config.stages.gridss) { GRIDSS_SVPREP_CALLING( - ch_inputs, + ch_dna_processed_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -312,7 +308,7 @@ workflow WGTS { } else { - ch_gridss_out = ch_inputs.map { meta -> [meta, []] } + ch_gridss_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -326,7 +322,7 @@ workflow WGTS { if (run_config.stages.gripss) { GRIPSS_FILTERING( - ch_inputs, + ch_dna_processed_out, ch_gridss_out, ref_data.genome_fasta, ref_data.genome_version, @@ -346,9 +342,9 @@ workflow WGTS { } else { - ch_gripss_somatic_out = ch_inputs.map { meta -> [meta, [], []] } - ch_gripss_germline_out = ch_inputs.map { meta -> [meta, [], []] } - ch_gripss_somatic_unfiltered_out = ch_inputs.map { meta -> [meta, [], []] } + ch_gripss_somatic_out = ch_dna_processed_out.map { meta -> [meta, [], []] } + ch_gripss_germline_out = ch_dna_processed_out.map { meta -> [meta, [], []] } + ch_gripss_somatic_unfiltered_out = ch_dna_processed_out.map { meta -> [meta, [], []] } } @@ -364,7 +360,7 @@ workflow WGTS { if (run_config.stages.sage) { SAGE_CALLING( - ch_inputs, + ch_dna_processed_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -388,10 +384,10 @@ workflow WGTS { } else { - ch_sage_germline_vcf_out = ch_inputs.map { meta -> [meta, [], []] } - ch_sage_somatic_vcf_out = ch_inputs.map { meta -> [meta, [], []] } - ch_sage_germline_dir_out = ch_inputs.map { meta -> [meta, []] } - ch_sage_somatic_dir_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_germline_vcf_out = ch_dna_processed_out.map { meta -> [meta, [], []] } + ch_sage_somatic_vcf_out = ch_dna_processed_out.map { meta -> [meta, [], []] } + ch_sage_germline_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_sage_somatic_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -404,7 +400,7 @@ workflow WGTS { if (run_config.stages.pave) { PAVE_ANNOTATION( - ch_inputs, + ch_dna_processed_out, ch_sage_germline_vcf_out, ch_sage_somatic_vcf_out, ref_data.genome_fasta, @@ -428,8 +424,8 @@ workflow WGTS { } else { - ch_pave_germline_out = ch_inputs.map { meta -> [meta, []] } - ch_pave_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_pave_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_pave_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -441,7 +437,7 @@ workflow WGTS { if (run_config.stages.purple) { PURPLE_CALLING( - ch_inputs, + ch_dna_processed_out, ch_amber_out, ch_cobalt_out, ch_pave_somatic_out, @@ -470,7 +466,7 @@ workflow WGTS { } else { - ch_purple_out = ch_inputs.map { meta -> [meta, []] } + ch_purple_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -485,7 +481,7 @@ workflow WGTS { // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented SAGE_APPEND( - ch_inputs, + ch_dna_processed_out, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, @@ -499,8 +495,8 @@ workflow WGTS { } else { - ch_sage_somatic_append_out = ch_inputs.map { meta -> [meta, []] } - ch_sage_germline_append_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_somatic_append_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_sage_germline_append_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -513,7 +509,7 @@ workflow WGTS { if (run_config.stages.linx) { LINX_ANNOTATION( - ch_inputs, + ch_dna_processed_out, ch_purple_out, ref_data.genome_version, hmf_data.ensembl_data_resources, @@ -529,8 +525,8 @@ workflow WGTS { } else { - ch_linx_somatic_out = ch_inputs.map { meta -> [meta, []] } - ch_linx_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_linx_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_linx_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -542,7 +538,7 @@ workflow WGTS { if (run_config.stages.linx) { LINX_PLOTTING( - ch_inputs, + ch_dna_processed_out, ch_linx_somatic_out, ref_data.genome_version, hmf_data.ensembl_data_resources, @@ -554,7 +550,7 @@ workflow WGTS { } else { - ch_linx_somatic_visualiser_dir_out = ch_inputs.map { meta -> [meta, []] } + ch_linx_somatic_visualiser_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -567,7 +563,7 @@ workflow WGTS { if (run_config.stages.orange && run_config.stages.flagstat) { FLAGSTAT_METRICS( - ch_inputs, + ch_dna_processed_out, ) ch_versions = ch_versions.mix(FLAGSTAT_METRICS.out.versions) @@ -577,8 +573,8 @@ workflow WGTS { } else { - ch_flagstat_somatic_out = ch_inputs.map { meta -> [meta, []] } - ch_flagstat_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_flagstat_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_flagstat_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -591,7 +587,7 @@ workflow WGTS { if (run_config.stages.bamtools) { BAMTOOLS_METRICS( - ch_inputs, + ch_dna_processed_out, ref_data.genome_fasta, ref_data.genome_version, ) @@ -603,8 +599,8 @@ workflow WGTS { } else { - ch_bamtools_somatic_out = ch_inputs.map { meta -> [meta, []] } - ch_bamtools_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_bamtools_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_bamtools_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -616,7 +612,7 @@ workflow WGTS { if (run_config.stages.sigs) { SIGS_FITTING( - ch_inputs, + ch_dna_processed_out, ch_purple_out, hmf_data.sigs_signatures, ) @@ -627,7 +623,7 @@ workflow WGTS { } else { - ch_sigs_out = ch_inputs.map { meta -> [meta, []] } + ch_sigs_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -639,7 +635,7 @@ workflow WGTS { if (run_config.stages.chord) { CHORD_PREDICTION( - ch_inputs, + ch_dna_processed_out, ch_purple_out, ref_data.genome_version, ) @@ -650,7 +646,7 @@ workflow WGTS { } else { - ch_chord_out = ch_inputs.map { meta -> [meta, []] } + ch_chord_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -665,7 +661,7 @@ workflow WGTS { ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] LILAC_CALLING( - ch_inputs, + ch_dna_processed_out, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, @@ -680,7 +676,7 @@ workflow WGTS { } else { - ch_lilac_out = ch_inputs.map { meta -> [meta, []] } + ch_lilac_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -692,7 +688,7 @@ workflow WGTS { if (run_config.stages.virusinterpreter) { VIRUSBREAKEND_CALLING( - ch_inputs, + ch_dna_processed_out, ch_purple_out, ch_bamtools_somatic_out, ref_data.genome_fasta, @@ -713,7 +709,7 @@ workflow WGTS { } else { - ch_virusinterpreter_out = ch_inputs.map { meta -> [meta, []] } + ch_virusinterpreter_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -725,7 +721,7 @@ workflow WGTS { if (run_config.stages.cuppa) { CUPPA_PREDICTION( - ch_inputs, + ch_dna_processed_out, ch_isofox_out, ch_purple_out, ch_linx_somatic_out, @@ -740,7 +736,7 @@ workflow WGTS { } else { - ch_cuppa_out = ch_inputs.map { meta -> [meta, []] } + ch_cuppa_out = ch_dna_processed_out.map { meta -> [meta, []] } } @@ -750,7 +746,7 @@ workflow WGTS { if (run_config.stages.orange) { ORANGE_REPORTING( - ch_inputs, + ch_dna_processed_out, ch_bamtools_somatic_out, ch_bamtools_germline_out, ch_flagstat_somatic_out, @@ -783,13 +779,13 @@ workflow WGTS { ch_versions = ch_versions.mix(ORANGE_REPORTING.out.versions) } - // - // MODULE: Pipeline reporting - // - CUSTOM_DUMPSOFTWAREVERSIONS( - ch_versions.unique().collectFile(name: 'collated_versions.yml') - ) - */ + // TODO(MC): This is failing. + // // + // // MODULE: Pipeline reporting + // // + // CUSTOM_DUMPSOFTWAREVERSIONS( + // ch_versions.unique().collectFile(name: 'collated_versions.yml') + // ) } /* From f120d59d8e2bc2ade74c136d9a028711d69e3d3a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 14 Feb 2024 11:33:37 +1100 Subject: [PATCH 299/562] Adjust genomes location within local test_data dir --- tests/subworkflows/local/bamtools_metrics.nf.test | 2 +- .../subworkflows/local/gridss_svprep_calling.nf.test | 12 ++++++------ tests/subworkflows/local/gripss_filtering.nf.test | 4 ++-- .../subworkflows/local/isofox_quantification.nf.test | 4 ++-- tests/subworkflows/local/lilac_calling.nf.test | 4 ++-- tests/subworkflows/local/pave_annotation.nf.test | 4 ++-- tests/subworkflows/local/purple_calling.nf.test | 6 +++--- tests/subworkflows/local/sage_append.nf.test | 6 +++--- tests/subworkflows/local/sage_calling.nf.test | 6 +++--- .../subworkflows/local/virusbreakend_calling.nf.test | 12 ++++++------ 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/subworkflows/local/bamtools_metrics.nf.test b/tests/subworkflows/local/bamtools_metrics.nf.test index 23f809af..d91f217d 100644 --- a/tests/subworkflows/local/bamtools_metrics.nf.test +++ b/tests/subworkflows/local/bamtools_metrics.nf.test @@ -29,7 +29,7 @@ nextflow_workflow { workflow { """ input[0] = PREPARE_INPUTS.out.inputs - input[1] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[1] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' input[2] = '38' """ } diff --git a/tests/subworkflows/local/gridss_svprep_calling.nf.test b/tests/subworkflows/local/gridss_svprep_calling.nf.test index ad4b96d8..e7e200df 100644 --- a/tests/subworkflows/local/gridss_svprep_calling.nf.test +++ b/tests/subworkflows/local/gridss_svprep_calling.nf.test @@ -28,13 +28,13 @@ nextflow_workflow { workflow { """ input[0] = PREPARE_INPUTS.out.inputs - input[1] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[1] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' input[2] = '38' - input[3] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' - input[5] = '${baseDir}/test_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188/' - input[6] = '${baseDir}/test_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img' - input[7] = '${baseDir}/test_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache' + input[3] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' + input[5] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188/' + input[6] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img' + input[7] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache' input[8] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/gridss_blacklist.38.bed.gz' input[9] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/sv_prep_blacklist.38.bed' input[10] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/known_fusions.38.bedpe' diff --git a/tests/subworkflows/local/gripss_filtering.nf.test b/tests/subworkflows/local/gripss_filtering.nf.test index aa0f1d07..010e3e6c 100644 --- a/tests/subworkflows/local/gripss_filtering.nf.test +++ b/tests/subworkflows/local/gripss_filtering.nf.test @@ -30,9 +30,9 @@ nextflow_workflow { """ input[0] = PREPARE_INPUTS.out.inputs input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/gridss/depth_annotator/COLO829v003T.gridss.vcf.gz')) - input[2] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[2] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' input[3] = '38' - input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/sgl_pon.38.bed.gz' input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/sv_pon.38.bedpe.gz' input[7] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/known_fusions.38.bedpe' diff --git a/tests/subworkflows/local/isofox_quantification.nf.test b/tests/subworkflows/local/isofox_quantification.nf.test index 3e0469e5..b9bd80b8 100644 --- a/tests/subworkflows/local/isofox_quantification.nf.test +++ b/tests/subworkflows/local/isofox_quantification.nf.test @@ -28,9 +28,9 @@ nextflow_workflow { workflow { """ input[0] = PREPARE_INPUTS.out.inputs - input[1] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[1] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' input[2] = '38' - input[3] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[3] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' input[4] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/rna_pipeline/read_151_exp_counts.csv' input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/rna_pipeline/read_100_exp_gc_ratios.csv' diff --git a/tests/subworkflows/local/lilac_calling.nf.test b/tests/subworkflows/local/lilac_calling.nf.test index 69761995..0e47b94a 100644 --- a/tests/subworkflows/local/lilac_calling.nf.test +++ b/tests/subworkflows/local/lilac_calling.nf.test @@ -29,9 +29,9 @@ nextflow_workflow { """ input[0] = PREPARE_INPUTS.out.inputs input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[2] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[2] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' input[3] = '38' - input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/immune/' input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/other/lilac/hla.38.bed' """ diff --git a/tests/subworkflows/local/pave_annotation.nf.test b/tests/subworkflows/local/pave_annotation.nf.test index 660e0d1c..f4bcf3a6 100644 --- a/tests/subworkflows/local/pave_annotation.nf.test +++ b/tests/subworkflows/local/pave_annotation.nf.test @@ -38,9 +38,9 @@ nextflow_workflow { '${baseDir}/test_data/module_data/sage/germline/COLO829v003T.sage.germline.vcf.gz', '${baseDir}/test_data/module_data/sage/germline/COLO829v003T.sage.germline.vcf.gz.tbi', ])) - input[3] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[3] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' input[4] = '38' - input[5] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[5] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/SageGermlinePon.98x.38.tsv.gz' input[7] = [] input[8] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownBlacklist.germline.38.bed' diff --git a/tests/subworkflows/local/purple_calling.nf.test b/tests/subworkflows/local/purple_calling.nf.test index e64c0056..e7d2b998 100644 --- a/tests/subworkflows/local/purple_calling.nf.test +++ b/tests/subworkflows/local/purple_calling.nf.test @@ -44,10 +44,10 @@ nextflow_workflow { '${baseDir}/test_data/module_data/gripss/somatic/COLO829v003T.gripss.somatic.vcf.gz', '${baseDir}/test_data/module_data/gripss/somatic/COLO829v003T.gripss.somatic.vcf.gz.tbi', ])) - input[8] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[8] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' input[9] = '38' - input[10] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[11] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' + input[10] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[11] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' input[12] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/copy_number/GC_profile.1000bp.38.cnp' input[13] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.somatic.38.vcf.gz' input[14] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.germline.38.vcf.gz' diff --git a/tests/subworkflows/local/sage_append.nf.test b/tests/subworkflows/local/sage_append.nf.test index 98e49270..fafdac73 100644 --- a/tests/subworkflows/local/sage_append.nf.test +++ b/tests/subworkflows/local/sage_append.nf.test @@ -29,10 +29,10 @@ nextflow_workflow { """ input[0] = PREPARE_INPUTS.out.inputs input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[2] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[2] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' input[3] = '38' - input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[5] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' + input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[5] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' """ } } diff --git a/tests/subworkflows/local/sage_calling.nf.test b/tests/subworkflows/local/sage_calling.nf.test index a3ea3f0a..1b4c5f73 100644 --- a/tests/subworkflows/local/sage_calling.nf.test +++ b/tests/subworkflows/local/sage_calling.nf.test @@ -28,10 +28,10 @@ nextflow_workflow { workflow { """ input[0] = PREPARE_INPUTS.out.inputs - input[1] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[1] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' input[2] = '38' - input[3] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' + input[3] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.somatic.38.vcf.gz' input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.germline.38.vcf.gz' input[7] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/ActionableCodingPanel.38.bed.gz' diff --git a/tests/subworkflows/local/virusbreakend_calling.nf.test b/tests/subworkflows/local/virusbreakend_calling.nf.test index e70b9480..ad08f56a 100644 --- a/tests/subworkflows/local/virusbreakend_calling.nf.test +++ b/tests/subworkflows/local/virusbreakend_calling.nf.test @@ -30,12 +30,12 @@ nextflow_workflow { input[0] = PREPARE_INPUTS.out.inputs input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/bamtools/COLO829v003T.wgsmetrics')) - input[3] = '${baseDir}/test_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[4] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[5] = '${baseDir}/test_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' - input[6] = '${baseDir}/test_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188/' - input[7] = '${baseDir}/test_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img' - input[8] = '${baseDir}/test_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache' + input[3] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' + input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' + input[5] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' + input[6] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188/' + input[7] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img' + input[8] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache' input[9] = '${baseDir}/test_data/reference_data/other/virusbreakenddb_test/' input[10] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/virusinterpreter/taxonomy_db.tsv' input[11] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/virusinterpreter/virus_reporting_db.tsv' From 7b703c2e265b6e8012f12a4c37dfb64b8498c29d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 14 Feb 2024 11:34:29 +1100 Subject: [PATCH 300/562] Adjust genome stub placeholder paths in tests --- tests/main.stub.nf.test.config | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/main.stub.nf.test.config b/tests/main.stub.nf.test.config index 03a43382..cec6b687 100644 --- a/tests/main.stub.nf.test.config +++ b/tests/main.stub.nf.test.config @@ -2,12 +2,12 @@ params { genomes { 'GRCh38_hmf' { - fasta = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" - fai = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" - dict = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwa_index = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz" - bwa_index_image = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" - gridss_index = "${params.nfTestWorkDir}/refdata/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" + fasta = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" + fai = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" + dict = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" + bwa_index = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz" + bwa_index_image = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" + gridss_index = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" } } From 8776fe238d5a682a82b87eaff88df080684e3805 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 14 Feb 2024 18:01:22 +1100 Subject: [PATCH 301/562] Update built-in test profile --- conf/test.config | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/conf/test.config b/conf/test.config index 615b8427..53fd0894 100644 --- a/conf/test.config +++ b/conf/test.config @@ -44,12 +44,10 @@ params { max_time = '6.h' // Input data - input = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/samplesheet.csv' + input = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/other/samplesheet.csv' - genome = 'GRCh37_hmf' + mode = 'wgts' + genome = 'GRCh38_hmf' ref_data_virusbreakenddb_path = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/reference_data/virusbreakend/virusbreakenddb_test.tar.gz' - //ref_data_known_fusion_data = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/known_fusion_data_custom.csv' - - linx_gene_id_file = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/config/GRCh37_hmf/simulated/fusion_genes.csv' } From 94b35b59218786a91f5ea323268060e430614a05 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 08:52:10 +1100 Subject: [PATCH 302/562] Remove unneeded test config and comment --- conf/test.config | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/conf/test.config b/conf/test.config index 53fd0894..fa617223 100644 --- a/conf/test.config +++ b/conf/test.config @@ -10,25 +10,6 @@ ---------------------------------------------------------------------------------------- */ -process { - withName: 'ISOFOX' { - ext.args = '-specific_chr 19' - } - - withName: 'SAGE.*' { - ext.args = '-specific_chr 19' - } - - withName: 'PURPLE' { - ext.args = '-min_ploidy 2 -max_ploidy 2 -min_purity 1 -max_purity 1' - } - - withName: 'LINX_SOMATIC' { - ext.args = '-write_all_vis_fusions' - } - -} - params { config_profile_name = 'Test profile' config_profile_description = 'Minimal test dataset to check pipeline function' @@ -39,7 +20,6 @@ params { // Limit resources so that this can run on GitHub Actions max_cpus = 1 - // NOTE(SW): increased from 6GB to 8GB as required for GRIDSS max_memory = '8.GB' max_time = '6.h' From 2ce99f40c0bfc7bc59ac3bc12a3577518c56562b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 08:53:28 +1100 Subject: [PATCH 303/562] Update test samplesheet name --- conf/test.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/test.config b/conf/test.config index fa617223..4d267c6d 100644 --- a/conf/test.config +++ b/conf/test.config @@ -24,7 +24,7 @@ params { max_time = '6.h' // Input data - input = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/other/samplesheet.csv' + input = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/other/samplesheet.colo829_mini.dna_rna.grch38_hmf.csv' mode = 'wgts' genome = 'GRCh38_hmf' From e3f8d4576521f956b86068fadaf6647b6536bcba Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Thu, 15 Feb 2024 09:39:18 +1100 Subject: [PATCH 304/562] Minor fixes and style improvements. --- modules/local/markdups/main.nf | 2 +- subworkflows/local/read_alignment.nf | 6 +++--- workflows/targeted.nf | 3 ++- workflows/wgts.nf | 13 ++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index aaa6e301..9900288a 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -52,7 +52,7 @@ process MARKDUPS { "${task.process}": sambamba: 1.0 samtools: 1.17 - openjdk: >=8 + openjdk: 8 mark-dups: 1.1 END_VERSIONS """ diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index 47259fd1..4865ef10 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -53,7 +53,7 @@ workflow READ_ALIGNMENT { sample_key['sample_id'] = value.sample_id sample_key.remove(key) - fastq_pair_count = value[Constants.FileType.FASTQ].tokenize(';').size() / 2 + fastq_pair_count = value[Constants.FileType.FASTQ].toString().tokenize(';').size() / 2 } } @@ -71,12 +71,11 @@ workflow READ_ALIGNMENT { } def sample_id = meta[sample_key]['sample_id'] - def fastq_files = meta[sample_key][Constants.FileType.FASTQ].tokenize(';') + def fastq_files = meta[sample_key][Constants.FileType.FASTQ].toString().tokenize(';') def meta_fastq_common = [:] meta.each { key, value -> - if (key === sample_key) { return } @@ -251,6 +250,7 @@ workflow READ_ALIGNMENT { meta_bam[sample_key][Constants.FileType.BAI_MARKDUPS] = bai_files bams.each { bam -> + bam_files.add(bam[1]) bai_files.add(bam[2]) } diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 4fffbf0c..a40240af 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -102,6 +102,7 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft // Get absolute file paths samplesheet = Utils.getFileObject(params.input) +// TODO(MC): -panel targeted workflow TARGETED { // Create channel for versions @@ -123,7 +124,7 @@ workflow TARGETED { // Set GRIDSS config gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config - // + // // SUBWORKFLOW: Align reads // // channel: [ meta ] diff --git a/workflows/wgts.nf b/workflows/wgts.nf index ada38f53..d76774c1 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -779,13 +779,12 @@ workflow WGTS { ch_versions = ch_versions.mix(ORANGE_REPORTING.out.versions) } - // TODO(MC): This is failing. - // // - // // MODULE: Pipeline reporting - // // - // CUSTOM_DUMPSOFTWAREVERSIONS( - // ch_versions.unique().collectFile(name: 'collated_versions.yml') - // ) + // + // MODULE: Pipeline reporting + // + CUSTOM_DUMPSOFTWAREVERSIONS( + ch_versions.unique().collectFile(name: 'collated_versions.yml') + ) } /* From 8c79f19470741eb89515cd4d275ddc1b92ad2630 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 09:44:37 +1100 Subject: [PATCH 305/562] Bump BamTools to 1.2.1 --- modules/local/bamtools/environment.yml | 2 +- modules/local/bamtools/main.nf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/bamtools/environment.yml b/modules/local/bamtools/environment.yml index a0b80cd2..3423794a 100644 --- a/modules/local/bamtools/environment.yml +++ b/modules/local/bamtools/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-bam-tools=1.2=hdfd78af_1 + - bioconda::hmftools-bam-tools=1.2.1 diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf index 6a193c30..64fa90c9 100644 --- a/modules/local/bamtools/main.nf +++ b/modules/local/bamtools/main.nf @@ -4,8 +4,8 @@ process BAMTOOLS { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-bam-tools:1.2--hdfd78af_1' : - 'quay.io/biocontainers/hmftools-bam-tools:1.2--hdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/hmftools-bam-tools:1.2.1--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-bam-tools:1.2.1--hdfd78af_0' }" input: tuple val(meta), path(bam), path(bai) From 779882ecf0f0da8b5070de7c3e4cf40eed5f1f19 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 11:46:34 +1100 Subject: [PATCH 306/562] Correct process Conda environment packages --- modules/local/amber/environment.yml | 2 +- modules/local/cobalt/environment.yml | 2 +- modules/local/isofox/environment.yml | 2 +- modules/local/lilac/environment.yml | 2 +- modules/local/linx/environment.yml | 2 +- modules/local/orange/environment.yml | 2 +- modules/local/pave/environment.yml | 2 +- modules/local/purple/environment.yml | 2 +- modules/local/sage/environment.yml | 2 +- modules/local/svprep/environment.yml | 2 +- modules/local/virusinterpreter/environment.yml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/local/amber/environment.yml b/modules/local/amber/environment.yml index 97d7f6ee..dbe8bf6c 100644 --- a/modules/local/amber/environment.yml +++ b/modules/local/amber/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::amber=4.0 + - bioconda::hmftools-amber=4.0 diff --git a/modules/local/cobalt/environment.yml b/modules/local/cobalt/environment.yml index df3881f5..727b5a89 100644 --- a/modules/local/cobalt/environment.yml +++ b/modules/local/cobalt/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::cobalt=1.16 + - bioconda::hmftools-cobalt=1.16 diff --git a/modules/local/isofox/environment.yml b/modules/local/isofox/environment.yml index 0034bceb..d4251c57 100644 --- a/modules/local/isofox/environment.yml +++ b/modules/local/isofox/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::isofox=1.7.1 + - bioconda::hmftools-isofox=1.7.1 diff --git a/modules/local/lilac/environment.yml b/modules/local/lilac/environment.yml index 93912603..8832e639 100644 --- a/modules/local/lilac/environment.yml +++ b/modules/local/lilac/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::lilac=1.6 + - bioconda::hmftools-lilac=1.6 diff --git a/modules/local/linx/environment.yml b/modules/local/linx/environment.yml index b6a888dd..d276dc1b 100644 --- a/modules/local/linx/environment.yml +++ b/modules/local/linx/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::linx=1.25 + - bioconda::hmftools-linx=1.25 diff --git a/modules/local/orange/environment.yml b/modules/local/orange/environment.yml index eaaddf49..f3d03cc2 100644 --- a/modules/local/orange/environment.yml +++ b/modules/local/orange/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::orange=2.7.1 + - bioconda::hmftools-orange=2.7.1 diff --git a/modules/local/pave/environment.yml b/modules/local/pave/environment.yml index 261570a1..6c6ecbea 100644 --- a/modules/local/pave/environment.yml +++ b/modules/local/pave/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::pave=1.6 + - bioconda::hmftools-pave=1.6 diff --git a/modules/local/purple/environment.yml b/modules/local/purple/environment.yml index b5c9e755..ce725d80 100644 --- a/modules/local/purple/environment.yml +++ b/modules/local/purple/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::purple=4.0 + - bioconda::hmftools-purple=4.0 diff --git a/modules/local/sage/environment.yml b/modules/local/sage/environment.yml index c23a68be..6ae3d44e 100644 --- a/modules/local/sage/environment.yml +++ b/modules/local/sage/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::sage=3.4=hdfd78af_1 + - bioconda::hmftools-sage=3.4=hdfd78af_1 diff --git a/modules/local/svprep/environment.yml b/modules/local/svprep/environment.yml index 98c00d65..6b56b03b 100644 --- a/modules/local/svprep/environment.yml +++ b/modules/local/svprep/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::sv-prep=1.2.3=hdfd78af_1 + - bioconda::hmftools-sv-prep=1.2.3=hdfd78af_1 diff --git a/modules/local/virusinterpreter/environment.yml b/modules/local/virusinterpreter/environment.yml index c84193a8..ff968f29 100644 --- a/modules/local/virusinterpreter/environment.yml +++ b/modules/local/virusinterpreter/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::virus-interpreter=1.3 + - bioconda::hmftools-virus-interpreter=1.3 From 72b6466397d901a20c230a5ff86438623711de8e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 12:06:06 +1100 Subject: [PATCH 307/562] Relocate Conda env files to module directory Otherwise generates a java.nio.channels.OverlappingFileLockException error --- modules/local/gridss/{ => index}/environment.yml | 0 modules/local/gridss/index/main.nf | 2 +- modules/local/gripss/{ => germline}/environment.yml | 0 modules/local/gripss/germline/main.nf | 2 +- modules/local/gripss/somatic/environment.yml | 7 +++++++ modules/local/gripss/somatic/main.nf | 2 +- modules/local/linx/{ => germline}/environment.yml | 0 modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/environment.yml | 7 +++++++ modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/environment.yml | 7 +++++++ modules/local/linx/visualiser/main.nf | 2 +- modules/local/pave/{ => germline}/environment.yml | 0 modules/local/pave/germline/main.nf | 2 +- modules/local/pave/somatic/environment.yml | 7 +++++++ modules/local/pave/somatic/main.nf | 2 +- modules/local/sage/{ => append}/environment.yml | 0 modules/local/sage/append/main.nf | 2 +- modules/local/sage/germline/environment.yml | 7 +++++++ modules/local/sage/germline/main.nf | 2 +- modules/local/sage/somatic/environment.yml | 7 +++++++ modules/local/sage/somatic/main.nf | 2 +- modules/local/svprep/{ => assemble}/environment.yml | 0 modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/environment.yml | 7 +++++++ modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/depth_annotator/environment.yml | 7 +++++++ modules/local/svprep/depth_annotator/main.nf | 2 +- modules/local/svprep/preprocess/environment.yml | 7 +++++++ modules/local/svprep/preprocess/main.nf | 2 +- modules/local/svprep/svprep/environment.yml | 7 +++++++ modules/local/svprep/svprep/main.nf | 2 +- 32 files changed, 86 insertions(+), 16 deletions(-) rename modules/local/gridss/{ => index}/environment.yml (100%) rename modules/local/gripss/{ => germline}/environment.yml (100%) create mode 100644 modules/local/gripss/somatic/environment.yml rename modules/local/linx/{ => germline}/environment.yml (100%) create mode 100644 modules/local/linx/somatic/environment.yml create mode 100644 modules/local/linx/visualiser/environment.yml rename modules/local/pave/{ => germline}/environment.yml (100%) create mode 100644 modules/local/pave/somatic/environment.yml rename modules/local/sage/{ => append}/environment.yml (100%) create mode 100644 modules/local/sage/germline/environment.yml create mode 100644 modules/local/sage/somatic/environment.yml rename modules/local/svprep/{ => assemble}/environment.yml (100%) create mode 100644 modules/local/svprep/call/environment.yml create mode 100644 modules/local/svprep/depth_annotator/environment.yml create mode 100644 modules/local/svprep/preprocess/environment.yml create mode 100644 modules/local/svprep/svprep/environment.yml diff --git a/modules/local/gridss/environment.yml b/modules/local/gridss/index/environment.yml similarity index 100% rename from modules/local/gridss/environment.yml rename to modules/local/gridss/index/environment.yml diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 912aa654..4cc51f24 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -2,7 +2,7 @@ process GRIDSS_INDEX { tag "${genome_fasta.name}" label 'process_single' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/gridss:2.13.2--h50ea8bc_3' : 'quay.io/biocontainers/gridss:2.13.2--h50ea8bc_3' }" diff --git a/modules/local/gripss/environment.yml b/modules/local/gripss/germline/environment.yml similarity index 100% rename from modules/local/gripss/environment.yml rename to modules/local/gripss/germline/environment.yml diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 4100369c..ef2e5242 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -2,7 +2,7 @@ process GRIPSS_GERMLINE { tag "${meta.id}" label 'process_low' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-gripss:2.4--hdfd78af_0' : 'quay.io/biocontainers/hmftools-gripss:2.4--hdfd78af_0' }" diff --git a/modules/local/gripss/somatic/environment.yml b/modules/local/gripss/somatic/environment.yml new file mode 100644 index 00000000..70a822be --- /dev/null +++ b/modules/local/gripss/somatic/environment.yml @@ -0,0 +1,7 @@ +name: gripss +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::gripss=2.4 diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index 1c9b28ed..14f08944 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -2,7 +2,7 @@ process GRIPSS_SOMATIC { tag "${meta.id}" label 'process_low' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-gripss:2.4--hdfd78af_0' : 'quay.io/biocontainers/hmftools-gripss:2.4--hdfd78af_0' }" diff --git a/modules/local/linx/environment.yml b/modules/local/linx/germline/environment.yml similarity index 100% rename from modules/local/linx/environment.yml rename to modules/local/linx/germline/environment.yml diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 12421be1..14efc84c 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -2,7 +2,7 @@ process LINX_GERMLINE { tag "${meta.id}" label 'process_low' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': 'quay.io/biocontainers/hmftools-linx:1.25--hdfd78af_0' }" diff --git a/modules/local/linx/somatic/environment.yml b/modules/local/linx/somatic/environment.yml new file mode 100644 index 00000000..d276dc1b --- /dev/null +++ b/modules/local/linx/somatic/environment.yml @@ -0,0 +1,7 @@ +name: linx +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-linx=1.25 diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index ea3475dd..fcfbb5dc 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -2,7 +2,7 @@ process LINX_SOMATIC { tag "${meta.id}" label 'process_low' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': 'quay.io/biocontainers/hmftools-linx:1.25--hdfd78af_0' }" diff --git a/modules/local/linx/visualiser/environment.yml b/modules/local/linx/visualiser/environment.yml new file mode 100644 index 00000000..d276dc1b --- /dev/null +++ b/modules/local/linx/visualiser/environment.yml @@ -0,0 +1,7 @@ +name: linx +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-linx=1.25 diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index f5613e4c..5ff176c5 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -2,7 +2,7 @@ process LINX_VISUALISER { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': 'quay.io/biocontainers/hmftools-linx:1.25--hdfd78af_0' }" diff --git a/modules/local/pave/environment.yml b/modules/local/pave/germline/environment.yml similarity index 100% rename from modules/local/pave/environment.yml rename to modules/local/pave/germline/environment.yml diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 614f38a8..8c297bda 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -6,7 +6,7 @@ process PAVE_GERMLINE { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-pave:1.6--hdfd78af_0' : 'quay.io/biocontainers/hmftools-pave:1.6--hdfd78af_0' }" diff --git a/modules/local/pave/somatic/environment.yml b/modules/local/pave/somatic/environment.yml new file mode 100644 index 00000000..6c6ecbea --- /dev/null +++ b/modules/local/pave/somatic/environment.yml @@ -0,0 +1,7 @@ +name: pave +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-pave=1.6 diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 6101928c..8ebcbb89 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -2,7 +2,7 @@ process PAVE_SOMATIC { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-pave:1.6--hdfd78af_0' : 'quay.io/biocontainers/hmftools-pave:1.6--hdfd78af_0' }" diff --git a/modules/local/sage/environment.yml b/modules/local/sage/append/environment.yml similarity index 100% rename from modules/local/sage/environment.yml rename to modules/local/sage/append/environment.yml diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index 5b3bb554..2540a13f 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -2,7 +2,7 @@ process SAGE_APPEND { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : 'quay.io/biocontainers/hmftools-sage:3.4--hdfd78af_1' }" diff --git a/modules/local/sage/germline/environment.yml b/modules/local/sage/germline/environment.yml new file mode 100644 index 00000000..6ae3d44e --- /dev/null +++ b/modules/local/sage/germline/environment.yml @@ -0,0 +1,7 @@ +name: sage +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-sage=3.4=hdfd78af_1 diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index af5a51e0..7bb46f31 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -2,7 +2,7 @@ process SAGE_GERMLINE { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : 'quay.io/biocontainers/hmftools-sage:3.4--hdfd78af_1' }" diff --git a/modules/local/sage/somatic/environment.yml b/modules/local/sage/somatic/environment.yml new file mode 100644 index 00000000..6ae3d44e --- /dev/null +++ b/modules/local/sage/somatic/environment.yml @@ -0,0 +1,7 @@ +name: sage +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-sage=3.4=hdfd78af_1 diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 5ade66ae..3b11a984 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -4,7 +4,7 @@ process SAGE_SOMATIC { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : 'quay.io/biocontainers/hmftools-sage:3.4--hdfd78af_1' }" diff --git a/modules/local/svprep/environment.yml b/modules/local/svprep/assemble/environment.yml similarity index 100% rename from modules/local/svprep/environment.yml rename to modules/local/svprep/assemble/environment.yml diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 6e5d8572..77d0c01a 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -2,7 +2,7 @@ process GRIDSS_ASSEMBLE { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" diff --git a/modules/local/svprep/call/environment.yml b/modules/local/svprep/call/environment.yml new file mode 100644 index 00000000..6b56b03b --- /dev/null +++ b/modules/local/svprep/call/environment.yml @@ -0,0 +1,7 @@ +name: svprep +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-sv-prep=1.2.3=hdfd78af_1 diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index ca2d92cb..c23ae6ac 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -2,7 +2,7 @@ process GRIDSS_CALL { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" diff --git a/modules/local/svprep/depth_annotator/environment.yml b/modules/local/svprep/depth_annotator/environment.yml new file mode 100644 index 00000000..6b56b03b --- /dev/null +++ b/modules/local/svprep/depth_annotator/environment.yml @@ -0,0 +1,7 @@ +name: svprep +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-sv-prep=1.2.3=hdfd78af_1 diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index cc38ff25..02858a86 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -2,7 +2,7 @@ process SVPREP_DEPTH_ANNOTATOR { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" diff --git a/modules/local/svprep/preprocess/environment.yml b/modules/local/svprep/preprocess/environment.yml new file mode 100644 index 00000000..6b56b03b --- /dev/null +++ b/modules/local/svprep/preprocess/environment.yml @@ -0,0 +1,7 @@ +name: svprep +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-sv-prep=1.2.3=hdfd78af_1 diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 2d4f4791..4acf3adb 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -2,7 +2,7 @@ process GRIDSS_PREPROCESS { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" diff --git a/modules/local/svprep/svprep/environment.yml b/modules/local/svprep/svprep/environment.yml new file mode 100644 index 00000000..6b56b03b --- /dev/null +++ b/modules/local/svprep/svprep/environment.yml @@ -0,0 +1,7 @@ +name: svprep +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-sv-prep=1.2.3=hdfd78af_1 diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 99181316..b7a15ce8 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -2,7 +2,7 @@ process SVPREP { tag "${meta.id}" label 'process_medium' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" From f5c5d7269c04bcc402592ed4339b8a9499bb0727 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 13:51:37 +1100 Subject: [PATCH 308/562] Set unique names for process Conda environments --- modules/local/gridss/index/environment.yml | 2 +- modules/local/gripss/germline/environment.yml | 2 +- modules/local/gripss/somatic/environment.yml | 2 +- modules/local/linx/germline/environment.yml | 2 +- modules/local/linx/somatic/environment.yml | 2 +- modules/local/linx/visualiser/environment.yml | 2 +- modules/local/pave/germline/environment.yml | 2 +- modules/local/pave/somatic/environment.yml | 2 +- modules/local/sage/append/environment.yml | 2 +- modules/local/sage/germline/environment.yml | 2 +- modules/local/sage/somatic/environment.yml | 2 +- modules/local/svprep/assemble/environment.yml | 2 +- modules/local/svprep/call/environment.yml | 2 +- modules/local/svprep/depth_annotator/environment.yml | 2 +- modules/local/svprep/preprocess/environment.yml | 2 +- modules/local/svprep/svprep/environment.yml | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/local/gridss/index/environment.yml b/modules/local/gridss/index/environment.yml index dbe711d9..3f1fee42 100644 --- a/modules/local/gridss/index/environment.yml +++ b/modules/local/gridss/index/environment.yml @@ -1,4 +1,4 @@ -name: gridss +name: gridss_index channels: - conda-forge - bioconda diff --git a/modules/local/gripss/germline/environment.yml b/modules/local/gripss/germline/environment.yml index 70a822be..99ec3115 100644 --- a/modules/local/gripss/germline/environment.yml +++ b/modules/local/gripss/germline/environment.yml @@ -1,4 +1,4 @@ -name: gripss +name: gripss_germline channels: - conda-forge - bioconda diff --git a/modules/local/gripss/somatic/environment.yml b/modules/local/gripss/somatic/environment.yml index 70a822be..99ec3115 100644 --- a/modules/local/gripss/somatic/environment.yml +++ b/modules/local/gripss/somatic/environment.yml @@ -1,4 +1,4 @@ -name: gripss +name: gripss_germline channels: - conda-forge - bioconda diff --git a/modules/local/linx/germline/environment.yml b/modules/local/linx/germline/environment.yml index d276dc1b..2b587a0d 100644 --- a/modules/local/linx/germline/environment.yml +++ b/modules/local/linx/germline/environment.yml @@ -1,4 +1,4 @@ -name: linx +name: linx_germline channels: - conda-forge - bioconda diff --git a/modules/local/linx/somatic/environment.yml b/modules/local/linx/somatic/environment.yml index d276dc1b..2c7883f5 100644 --- a/modules/local/linx/somatic/environment.yml +++ b/modules/local/linx/somatic/environment.yml @@ -1,4 +1,4 @@ -name: linx +name: linx_somatic channels: - conda-forge - bioconda diff --git a/modules/local/linx/visualiser/environment.yml b/modules/local/linx/visualiser/environment.yml index d276dc1b..a0fa994a 100644 --- a/modules/local/linx/visualiser/environment.yml +++ b/modules/local/linx/visualiser/environment.yml @@ -1,4 +1,4 @@ -name: linx +name: linx_visualiser channels: - conda-forge - bioconda diff --git a/modules/local/pave/germline/environment.yml b/modules/local/pave/germline/environment.yml index 6c6ecbea..c7f743e7 100644 --- a/modules/local/pave/germline/environment.yml +++ b/modules/local/pave/germline/environment.yml @@ -1,4 +1,4 @@ -name: pave +name: pave_germline channels: - conda-forge - bioconda diff --git a/modules/local/pave/somatic/environment.yml b/modules/local/pave/somatic/environment.yml index 6c6ecbea..686998c2 100644 --- a/modules/local/pave/somatic/environment.yml +++ b/modules/local/pave/somatic/environment.yml @@ -1,4 +1,4 @@ -name: pave +name: pave_somatic channels: - conda-forge - bioconda diff --git a/modules/local/sage/append/environment.yml b/modules/local/sage/append/environment.yml index 6ae3d44e..45fbf017 100644 --- a/modules/local/sage/append/environment.yml +++ b/modules/local/sage/append/environment.yml @@ -1,4 +1,4 @@ -name: sage +name: sage_append channels: - conda-forge - bioconda diff --git a/modules/local/sage/germline/environment.yml b/modules/local/sage/germline/environment.yml index 6ae3d44e..16793c78 100644 --- a/modules/local/sage/germline/environment.yml +++ b/modules/local/sage/germline/environment.yml @@ -1,4 +1,4 @@ -name: sage +name: sage_germline channels: - conda-forge - bioconda diff --git a/modules/local/sage/somatic/environment.yml b/modules/local/sage/somatic/environment.yml index 6ae3d44e..e9ca7c06 100644 --- a/modules/local/sage/somatic/environment.yml +++ b/modules/local/sage/somatic/environment.yml @@ -1,4 +1,4 @@ -name: sage +name: sage_somatic channels: - conda-forge - bioconda diff --git a/modules/local/svprep/assemble/environment.yml b/modules/local/svprep/assemble/environment.yml index 6b56b03b..744167d9 100644 --- a/modules/local/svprep/assemble/environment.yml +++ b/modules/local/svprep/assemble/environment.yml @@ -1,4 +1,4 @@ -name: svprep +name: svprep_assemble channels: - conda-forge - bioconda diff --git a/modules/local/svprep/call/environment.yml b/modules/local/svprep/call/environment.yml index 6b56b03b..8961a674 100644 --- a/modules/local/svprep/call/environment.yml +++ b/modules/local/svprep/call/environment.yml @@ -1,4 +1,4 @@ -name: svprep +name: svprep_call channels: - conda-forge - bioconda diff --git a/modules/local/svprep/depth_annotator/environment.yml b/modules/local/svprep/depth_annotator/environment.yml index 6b56b03b..c715d41a 100644 --- a/modules/local/svprep/depth_annotator/environment.yml +++ b/modules/local/svprep/depth_annotator/environment.yml @@ -1,4 +1,4 @@ -name: svprep +name: svprep_depth_annotator channels: - conda-forge - bioconda diff --git a/modules/local/svprep/preprocess/environment.yml b/modules/local/svprep/preprocess/environment.yml index 6b56b03b..6a1e5fd0 100644 --- a/modules/local/svprep/preprocess/environment.yml +++ b/modules/local/svprep/preprocess/environment.yml @@ -1,4 +1,4 @@ -name: svprep +name: svprep_preprocess channels: - conda-forge - bioconda diff --git a/modules/local/svprep/svprep/environment.yml b/modules/local/svprep/svprep/environment.yml index 6b56b03b..5fb5d9c9 100644 --- a/modules/local/svprep/svprep/environment.yml +++ b/modules/local/svprep/svprep/environment.yml @@ -1,4 +1,4 @@ -name: svprep +name: svprep_svprep channels: - conda-forge - bioconda From 61c219793b5006482f14c39f33bd0e590f54692c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 15:11:27 +1100 Subject: [PATCH 309/562] Fix Conda environment name typo --- modules/local/gripss/somatic/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/gripss/somatic/environment.yml b/modules/local/gripss/somatic/environment.yml index 99ec3115..076bb26e 100644 --- a/modules/local/gripss/somatic/environment.yml +++ b/modules/local/gripss/somatic/environment.yml @@ -1,4 +1,4 @@ -name: gripss_germline +name: gripss_somatic channels: - conda-forge - bioconda From f0a361960e7502fda60f28dee0f1a1f67a11e309 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 15:14:31 +1100 Subject: [PATCH 310/562] Fix GRIPSS Conda package name --- modules/local/gripss/germline/environment.yml | 2 +- modules/local/gripss/somatic/environment.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/gripss/germline/environment.yml b/modules/local/gripss/germline/environment.yml index 99ec3115..c2e0d23f 100644 --- a/modules/local/gripss/germline/environment.yml +++ b/modules/local/gripss/germline/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::gripss=2.4 + - bioconda::hmftools-gripss=2.4 diff --git a/modules/local/gripss/somatic/environment.yml b/modules/local/gripss/somatic/environment.yml index 076bb26e..5ae83f45 100644 --- a/modules/local/gripss/somatic/environment.yml +++ b/modules/local/gripss/somatic/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::gripss=2.4 + - bioconda::hmftools-gripss=2.4 From 08736bea05353ec4b4335229c486b2f7636769ad Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 15:24:22 +1100 Subject: [PATCH 311/562] Use mulled multicontainers for custom processes --- modules/local/custom/extract_tarball/main.nf | 5 ++++- .../lilac_extract_and_index_contig/Dockerfile | 19 ------------------ .../lilac_extract_and_index_contig/main.nf | 5 ++++- .../lilac_realign_reads_lilac/Dockerfile | 20 ------------------- .../custom/lilac_realign_reads_lilac/main.nf | 5 ++++- modules/local/custom/lilac_slice/main.nf | 5 ++++- 6 files changed, 16 insertions(+), 43 deletions(-) delete mode 100644 modules/local/custom/lilac_extract_and_index_contig/Dockerfile delete mode 100644 modules/local/custom/lilac_realign_reads_lilac/Dockerfile diff --git a/modules/local/custom/extract_tarball/main.nf b/modules/local/custom/extract_tarball/main.nf index 989065a8..7f88303f 100644 --- a/modules/local/custom/extract_tarball/main.nf +++ b/modules/local/custom/extract_tarball/main.nf @@ -1,7 +1,10 @@ process CUSTOM_EXTRACTTARBALL { label 'process_single' - container 'docker.io/ubuntu:20.04' + conda "conda-forge::tar" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/debian:bullseye-slim' : + 'docker pull debian:bullseye-slim' }" input: tuple val(meta), path(tarball) diff --git a/modules/local/custom/lilac_extract_and_index_contig/Dockerfile b/modules/local/custom/lilac_extract_and_index_contig/Dockerfile deleted file mode 100644 index d356441d..00000000 --- a/modules/local/custom/lilac_extract_and_index_contig/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - bwa \ - samtools && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index 8065c8e2..3c22e136 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -2,7 +2,10 @@ process CUSTOM_EXTRACTCONTIG { tag "${contig_name}" label 'process_single' - container 'docker.io/scwatts/custom-extract_and_index_contig:0.0.1--3' + conda "bwa=0.7.17 samtools=1.19.2" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-4908f45b5b676e6a2fed6b1977d445b16b7b8dee:2411d64e0a784487e81828123aaf68a549531e5c-0' : + 'quay.io/biocontainers/mulled-v2-4908f45b5b676e6a2fed6b1977d445b16b7b8dee:2411d64e0a784487e81828123aaf68a549531e5c-0' }" input: val contig_name diff --git a/modules/local/custom/lilac_realign_reads_lilac/Dockerfile b/modules/local/custom/lilac_realign_reads_lilac/Dockerfile deleted file mode 100644 index ff6213ff..00000000 --- a/modules/local/custom/lilac_realign_reads_lilac/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM mambaorg/micromamba:0.24.0 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps wget && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - bwa \ - sambamba \ - samtools && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf index 57f3bcfb..a926254f 100644 --- a/modules/local/custom/lilac_realign_reads_lilac/main.nf +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -2,7 +2,10 @@ process CUSTOM_REALIGNREADS { tag "${meta.id}" label 'process_low' - container 'docker.io/scwatts/custom-realign_reads_lilac:0.0.1--3' + conda "bwa=0.7.17 samtools=1.19.2 sambamba=1.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-4908f45b5b676e6a2fed6b1977d445b16b7b8dee:2411d64e0a784487e81828123aaf68a549531e5c-0' : + 'quay.io/biocontainers/mulled-v2-4908f45b5b676e6a2fed6b1977d445b16b7b8dee:2411d64e0a784487e81828123aaf68a549531e5c-0' }" input: tuple val(meta), path(bam), path(bai) diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index 6f73c415..b8013974 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -2,7 +2,10 @@ process CUSTOM_SLICE { tag "${meta.id}" label 'process_single' - container 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' + conda "samtools=1.19.2" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.19.2--h50ea8bc_0' : + 'quay.io/biocontainers/samtools:1.19.2--h50ea8bc_0' }" input: tuple val(meta), path(bam), path(bai) From 9b8dd27db404dfe6ba0f9046090f5e1f2e373262 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 15:29:05 +1100 Subject: [PATCH 312/562] Fix Sigs Conda package name --- modules/local/sigs/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/sigs/environment.yml b/modules/local/sigs/environment.yml index 8db3831a..6804c9a4 100644 --- a/modules/local/sigs/environment.yml +++ b/modules/local/sigs/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::r-sigs=1.2.1 + - bioconda::hmftools-sigs=1.2.1 From 58ed71cee585837c053da9980b5cef4ab1d21661 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Thu, 15 Feb 2024 15:37:07 +1100 Subject: [PATCH 313/562] Adding a TODO. --- modules/local/markdups/main.nf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 9900288a..97da2c6d 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -26,6 +26,8 @@ process MARKDUPS { // # -umi_duplex_delim _ \\ // # -umi_base_diff_stats \\ + // TODO(MC): Ref genome version. + """ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ From e4b27c2c401fe897e2eb9acd7e4e0b0297fb2d91 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Feb 2024 16:37:34 +1100 Subject: [PATCH 314/562] Correct linxreport conda environment path --- modules/local/linxreport/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/linxreport/main.nf b/modules/local/linxreport/main.nf index 9d830a36..ef016f65 100644 --- a/modules/local/linxreport/main.nf +++ b/modules/local/linxreport/main.nf @@ -2,7 +2,7 @@ process LINXREPORT { tag "${meta.id}" label 'process_single' - conda "${moduleDir}/../environment.yml" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/r-linxreport:1.0.0--r43hdfd78af_0' : 'quay.io/biocontainers/r-linxreport:1.0.0--r43hdfd78af_0' }" From 7e82c4ed8bd9ddbce0a531ff111024238039aa89 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 16 Feb 2024 10:57:03 +1100 Subject: [PATCH 315/562] Fix/switch extract process container The Debian slim container didn't have ps, which is required by Nextflow --- modules/local/custom/extract_tarball/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/custom/extract_tarball/main.nf b/modules/local/custom/extract_tarball/main.nf index 7f88303f..521860a5 100644 --- a/modules/local/custom/extract_tarball/main.nf +++ b/modules/local/custom/extract_tarball/main.nf @@ -3,8 +3,8 @@ process CUSTOM_EXTRACTTARBALL { conda "conda-forge::tar" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/debian:bullseye-slim' : - 'docker pull debian:bullseye-slim' }" + 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : + 'quay.io/nf-core/ubuntu:20.04' }" input: tuple val(meta), path(tarball) From de77de8b678ea3078dcd4c5cb7fd1cca897ea410 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 19 Feb 2024 05:11:34 +1100 Subject: [PATCH 316/562] Add has_umis switch to markdups. --- modules/local/markdups/main.nf | 20 +++++++++----------- subworkflows/local/read_processing.nf | 1 + 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 97da2c6d..56da8954 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -9,6 +9,7 @@ process MARKDUPS { path genome_fai path genome_dict path unmap_regions + val has_umis output: tuple val(meta_bam), path('*bam'), path('*bai'), emit: bam @@ -19,12 +20,7 @@ process MARKDUPS { task.ext.when == null || task.ext.when script: - // # TODO(MC): Umi flags - // # -multi_bam \\ - // # -umi_enabled \\ - // # -umi_duplex \\ - // # -umi_duplex_delim _ \\ - // # -umi_base_diff_stats \\ + def umi_flags = has_umis ? '-umi_enabled -umi_duplex -umi_duplex_delim _ -umi_base_diff_stats' : '' // TODO(MC): Ref genome version. @@ -40,6 +36,8 @@ process MARKDUPS { -input_bam ${bams.join(',')} \\ \\ -form_consensus \\ + -multi_bam \\ + ${umi_flags} \\ \\ -unmap_regions ${unmap_regions} \\ -ref_genome ${genome_fasta} \\ @@ -60,16 +58,16 @@ process MARKDUPS { """ stub: + def umi_output_files = has_umis ? 'touch ${meta_bam.sample_id}.umi_coord_freq.tsv;' + + ' touch ${meta_bam.sample_id}.umi_edit_distance.tsv;' + + ' touch ${meta_bam.sample_id}.umi_nucleotide_freq.tsv' : '' + """ touch ${meta_bam.sample_id}.mark_dups.bam touch ${meta_bam.sample_id}.mark_dups.bam.bai touch ${meta_bam.sample_id}.duplicate_freq.tsv + ${umi_output_files} echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ - - // # TODO(MC): UMIs. - // # touch ${meta_bam.sample_id}.umi_coord_freq.tsv - // # touch ${meta_bam.sample_id}.umi_edit_distance.tsv - // # touch ${meta_bam.sample_id}.umi_nucleotide_freq.tsv } diff --git a/subworkflows/local/read_processing.nf b/subworkflows/local/read_processing.nf index 53815d86..060d0e45 100644 --- a/subworkflows/local/read_processing.nf +++ b/subworkflows/local/read_processing.nf @@ -67,6 +67,7 @@ workflow READ_PROCESSING { genome_fai, genome_dict, unmap_regions, + false, ) ch_versions = ch_versions.mix(MARKDUPS.out.versions) From 01ad68d713e2da1801bc0d1c650a0e4e718c012e Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 19 Feb 2024 08:00:40 +1100 Subject: [PATCH 317/562] Force symlink overwrite so process does not fail on resume. --- modules/local/bwa/mem2/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index b77606f8..f56da635 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -25,7 +25,7 @@ process BWA_MEM2 { def read_group_tag = "@RG\t${meta.read_group}" """ - ln -s \$(find -L ${genome_bwa_index} -type f) ./ + ln -fs \$(find -L ${genome_bwa_index} -type f) ./ bwa-mem2 mem \\ -Y \\ From df6e65a378fd1fc3721a5ad99ff0a071a3bee290 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 19 Feb 2024 08:18:44 +1100 Subject: [PATCH 318/562] Change name of output bam from markdups. --- modules/local/markdups/main.nf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 56da8954..1c2ceafd 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -46,7 +46,7 @@ process MARKDUPS { -write_stats \\ -threads 16 \\ \\ - -output_bam ${meta_bam.sample_id}.mark_dups.bam + -output_bam ${meta_bam.sample_id}.markdups.bam cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -63,8 +63,8 @@ process MARKDUPS { ' touch ${meta_bam.sample_id}.umi_nucleotide_freq.tsv' : '' """ - touch ${meta_bam.sample_id}.mark_dups.bam - touch ${meta_bam.sample_id}.mark_dups.bam.bai + touch ${meta_bam.sample_id}.markdups.bam + touch ${meta_bam.sample_id}.markdups.bam.bai touch ${meta_bam.sample_id}.duplicate_freq.tsv ${umi_output_files} From a4a95b1526db56549d70659b34573c176ecd68c9 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 19 Feb 2024 11:24:33 +1100 Subject: [PATCH 319/562] Fix read group arg to bwa mem2. --- modules/local/bwa/mem2/main.nf | 3 ++- modules/local/fastp/main.nf | 7 +------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index f56da635..28da8562 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -22,7 +22,8 @@ process BWA_MEM2 { task.ext.when == null || task.ext.when script: - def read_group_tag = "@RG\t${meta.read_group}" + // TODO(MC): Double check this with Charles. + def read_group_tag = "@RG\\tID:${meta.read_group}\\tSM:${meta.sample_id}" """ ln -fs \$(find -L ${genome_bwa_index} -type f) ./ diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index 0205452c..fdbbb2d6 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -15,14 +15,9 @@ process FASTP { task.ext.when == null || task.ext.when script: - // TODO(MC): UMI flags - // --umi \\ - // --umi_loc per_read \\ - // --umi_len 7 \\ - // --umi_skip 1 \\ - """ # * do not apply trimming/clipping, already done in BCL convert + # * do not process umis, already done for us fastp \\ --in1 ${reads_fwd} \\ From 61aa1b18da08dbaf8e3334b03daa395c68aebd5b Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 19 Feb 2024 11:43:12 +1100 Subject: [PATCH 320/562] Add TODO. --- workflows/wgts.nf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index d76774c1..fa3ae8a4 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -117,6 +117,8 @@ samplesheet = Utils.getFileObject(params.input) // - Ignore this warning: params.schema_ignore_params = "max_fastq_records,refdata_unmap_regions" // TODO(MC): get error logs for amber, cobalt, and gripss // TODO(MC): Drop commit 'WIP: Reverting bioconda containers'. +// TODO(MC): Drop commit 'WIP: Turn FASTP back on by default'. +// TODO(MC): Check on bwa vs bwa-mem2 differences. workflow WGTS { // Create channel for versions // channel: [ versions.yml ] From a1dde8e9052a2e56ee1dc19aaf903a01ee5e5c86 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 19 Feb 2024 16:33:19 +1100 Subject: [PATCH 321/562] Fix markdups umi flags for TSO500 panel samples. --- modules/local/markdups/main.nf | 2 +- workflows/wgts.nf | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 1c2ceafd..a2727f81 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -20,7 +20,7 @@ process MARKDUPS { task.ext.when == null || task.ext.when script: - def umi_flags = has_umis ? '-umi_enabled -umi_duplex -umi_duplex_delim _ -umi_base_diff_stats' : '' + def umi_flags = has_umis ? '-umi_enabled -umi_duplex -umi_duplex_delim +' : '' // TODO(MC): Ref genome version. diff --git a/workflows/wgts.nf b/workflows/wgts.nf index fa3ae8a4..5d2ffef3 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -119,6 +119,7 @@ samplesheet = Utils.getFileObject(params.input) // TODO(MC): Drop commit 'WIP: Reverting bioconda containers'. // TODO(MC): Drop commit 'WIP: Turn FASTP back on by default'. // TODO(MC): Check on bwa vs bwa-mem2 differences. +// TODO(MC): Run all TSO500 test. workflow WGTS { // Create channel for versions // channel: [ versions.yml ] From 8f06a9fd8a4b95bbcab39bc68a647877ed86601d Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 19 Feb 2024 17:29:01 +1100 Subject: [PATCH 322/562] Add TODO. --- workflows/wgts.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 5d2ffef3..1d5ea3c7 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -120,6 +120,7 @@ samplesheet = Utils.getFileObject(params.input) // TODO(MC): Drop commit 'WIP: Turn FASTP back on by default'. // TODO(MC): Check on bwa vs bwa-mem2 differences. // TODO(MC): Run all TSO500 test. +// TODO(MC): Go from .fastq.gz. workflow WGTS { // Create channel for versions // channel: [ versions.yml ] From a2330b2dd73b59f7c59943e2baddc16a7ea4a651 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Mon, 19 Feb 2024 19:27:09 +1100 Subject: [PATCH 323/562] Fix read group extraction from fastq filenames and a bug in the markdups stub. --- lib/Utils.groovy | 11 +++++++---- modules/local/markdups/main.nf | 6 +++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 58c412ca..e40711e6 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -488,10 +488,13 @@ class Utils { static public readGroupFromFastqPath(fastq_path) { def base_name = fastq_path.split('/')[-1] - def pattern = /^(.+)_\d+\.fastq$/ - def matcher = base_name =~ pattern - assert matcher.find() - return matcher[0][1] + def components = base_name.split('_') + def read_group_components = [] + for (def i = 0; i < components.size() - 2; ++i) { + read_group_components.add(components[i]) + } + + return read_group_components.join('_') } } diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index a2727f81..e060d18c 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -58,9 +58,9 @@ process MARKDUPS { """ stub: - def umi_output_files = has_umis ? 'touch ${meta_bam.sample_id}.umi_coord_freq.tsv;' + - ' touch ${meta_bam.sample_id}.umi_edit_distance.tsv;' + - ' touch ${meta_bam.sample_id}.umi_nucleotide_freq.tsv' : '' + def umi_output_files = has_umis ? "touch ${meta_bam.sample_id}.umi_coord_freq.tsv;" + + " touch ${meta_bam.sample_id}.umi_edit_distance.tsv;" + + " touch ${meta_bam.sample_id}.umi_nucleotide_freq.tsv" : '' """ touch ${meta_bam.sample_id}.markdups.bam From 36c96fcc244c4247fad03ed1b87d2d18b36ff7f6 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 20 Feb 2024 08:56:54 +1100 Subject: [PATCH 324/562] Running with umis for targeted and without for wgts. --- subworkflows/local/read_processing.nf | 3 ++- workflows/targeted.nf | 1 + workflows/wgts.nf | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/subworkflows/local/read_processing.nf b/subworkflows/local/read_processing.nf index 060d0e45..11017a28 100644 --- a/subworkflows/local/read_processing.nf +++ b/subworkflows/local/read_processing.nf @@ -10,6 +10,7 @@ workflow READ_PROCESSING { genome_fai genome_dict unmap_regions + has_umis main: // Channel for version.yml files @@ -67,7 +68,7 @@ workflow READ_PROCESSING { genome_fai, genome_dict, unmap_regions, - false, + has_umis, ) ch_versions = ch_versions.mix(MARKDUPS.out.versions) diff --git a/workflows/targeted.nf b/workflows/targeted.nf index a40240af..2234f23a 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -172,6 +172,7 @@ workflow TARGETED { ref_data.genome_fai, ref_data.genome_dict, file(params.refdata_unmap_regions), + true, ) ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 1d5ea3c7..5e984da4 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -188,6 +188,7 @@ workflow WGTS { ref_data.genome_fai, ref_data.genome_dict, file(params.refdata_unmap_regions), + false, ) ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) From c8cec7532028dc7fa936a988de9f86143f8d83d4 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 20 Feb 2024 09:13:52 +1100 Subject: [PATCH 325/562] Fix includes in targeted.nf. --- workflows/targeted.nf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 2234f23a..84d1a770 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -79,6 +79,8 @@ include { ORANGE_REPORTING } from '../subworkflows/local/orange_reporting' include { PAVE_ANNOTATION } from '../subworkflows/local/pave_annotation' include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' +include { READ_ALIGNMENT } from '../subworkflows/local/read_alignment' +include { READ_PROCESSING } from '../subworkflows/local/read_processing' include { SAGE_APPEND } from '../subworkflows/local/sage_append' include { SAGE_CALLING } from '../subworkflows/local/sage_calling' From b45b43a0dce703fc50fe949027c7b10e0bf4dbac Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 20 Feb 2024 09:25:05 +1100 Subject: [PATCH 326/562] Only run markdups with UMIs when tso500 panel is selected. --- workflows/targeted.nf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 84d1a770..0eb935ed 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -104,7 +104,6 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft // Get absolute file paths samplesheet = Utils.getFileObject(params.input) -// TODO(MC): -panel targeted workflow TARGETED { // Create channel for versions @@ -166,6 +165,8 @@ workflow TARGETED { // TODO(SW): set up correctly if (true || run_config.stages.markdups) { + has_umis = params.panel.equalsIgnoreCase('tso500') + READ_PROCESSING( ch_inputs, ch_dna_alignment_out, @@ -174,7 +175,7 @@ workflow TARGETED { ref_data.genome_fai, ref_data.genome_dict, file(params.refdata_unmap_regions), - true, + has_umis, ) ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) From 247922958c2604941ae4fadcbfe51937b4ff46ea Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 20 Feb 2024 09:40:04 +1100 Subject: [PATCH 327/562] Create switch between bwa mem and bwa mem2 for debugging purposes. --- modules/local/bwa/mem/Dockerfile | 9 ++++ modules/local/bwa/mem/main.nf | 60 +++++++++++++++++++++++++ modules/local/bwa/{ => mem2}/Dockerfile | 0 subworkflows/local/read_alignment.nf | 32 +++++++++---- temp/genomes_GRCh37_hmf.config | 3 +- workflows/targeted.nf | 1 + workflows/wgts.nf | 1 + 7 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 modules/local/bwa/mem/Dockerfile create mode 100644 modules/local/bwa/mem/main.nf rename modules/local/bwa/{ => mem2}/Dockerfile (100%) diff --git a/modules/local/bwa/mem/Dockerfile b/modules/local/bwa/mem/Dockerfile new file mode 100644 index 00000000..2172ebc4 --- /dev/null +++ b/modules/local/bwa/mem/Dockerfile @@ -0,0 +1,9 @@ +FROM docker.io/continuumio/miniconda3:23.10.0-1 + +RUN \ + conda install -y -n base conda-libmamba-solver && \ + conda config --set solver libmamba && \ + conda install -y -c bioconda -c conda-forge -c conda \ + 'bwa==0.7.17' \ + 'sambamba==1.0' && \ + conda clean -yaf diff --git a/modules/local/bwa/mem/main.nf b/modules/local/bwa/mem/main.nf new file mode 100644 index 00000000..554251ca --- /dev/null +++ b/modules/local/bwa/mem/main.nf @@ -0,0 +1,60 @@ +process BWA_MEM { + tag "${meta.subject_id}__${meta.sample_id}" + label 'process_high' + + container 'docker.io/scwatts/bwa:0.7.17-sambamba' + + input: + tuple val(meta), path(reads_fwd), path(reads_rev) + path genome_fasta + path genome_bwa_index + + output: + tuple val(meta), path('*.bam'), emit: bam + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + // TODO(MC): Double check this with Charles. + def read_group_tag = "@RG\\tID:${meta.read_group}\\tSM:${meta.sample_id}" + + // TODO(MC): Fix versions. + """ + ln -fs \$(find -L ${genome_bwa_index} -type f) ./ + + bwa mem \\ + -Y \\ + -R '${read_group_tag}' \\ + -t ${task.cpus} \\ + ${genome_fasta} \\ + ${reads_fwd} \\ + ${reads_rev} | \\ + \\ + sambamba view \\ + --sam-input \\ + --format bam \\ + --compression-level 0 \\ + --nthreads ${task.cpus} \\ + /dev/stdin | \\ + \\ + sambamba sort \\ + --nthreads ${task.cpus} \\ + --out ${meta.split}.${meta.sample_id}.${meta.read_group}.bam \\ + /dev/stdin + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwamem2: 2.2.1 + sambamba: 1.0 + END_VERSIONS + """ + + stub: + """ + touch ${meta.split}.${meta.sample_id}.${meta.read_group}.bam + + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/bwa/Dockerfile b/modules/local/bwa/mem2/Dockerfile similarity index 100% rename from modules/local/bwa/Dockerfile rename to modules/local/bwa/mem2/Dockerfile diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index 4865ef10..3e2281bb 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -1,3 +1,4 @@ +include { BWA_MEM } from '../../modules/local/bwa/mem/main' include { BWA_MEM2 } from '../../modules/local/bwa/mem2/main' include { FASTP } from '../../modules/local/fastp/main' include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' @@ -10,6 +11,7 @@ workflow READ_ALIGNMENT { genome_fasta genome_bwa_index max_fastq_records + use_mem2 main: // Channel for version.yml files @@ -40,7 +42,7 @@ workflow READ_ALIGNMENT { // TODO(SW): implement outputs ch_star_outputs = Channel.empty() - // BWA MEM2 + // BWA MEM/MEM2 // channel: [ sample_key, fastq_pair_count ] ch_sample_fastq_pair_count = ch_meta_samples_sorted.runnable_fastq.map { meta_sample -> @@ -190,17 +192,31 @@ workflow READ_ALIGNMENT { } // channel: [ meta_fastq, bam ] - BWA_MEM2( - ch_bwa_mem_inputs, - genome_fasta, - genome_bwa_index, - ) + ch_alignment_output = Channel.empty() + if (use_mem2) { + BWA_MEM2( + ch_bwa_mem_inputs, + genome_fasta, + genome_bwa_index, + ) + + ch_alignment_output = BWA_MEM2.out.bam + ch_versions = ch_versions.mix(BWA_MEM2.out.versions) + } + else { + BWA_MEM( + ch_bwa_mem_inputs, + genome_fasta, + genome_bwa_index, + ) - ch_versions = ch_versions.mix(BWA_MEM2.out.versions) + ch_alignment_output = BWA_MEM.out.bam + ch_versions = ch_versions.mix(BWA_MEM.out.versions) + } // channel: [ meta_fastq, bam, bai ] SAMBAMBA_INDEX( - BWA_MEM2.out.bam, + ch_alignment_output, ) ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) diff --git a/temp/genomes_GRCh37_hmf.config b/temp/genomes_GRCh37_hmf.config index 480613a1..4249b1f0 100644 --- a/temp/genomes_GRCh37_hmf.config +++ b/temp/genomes_GRCh37_hmf.config @@ -13,5 +13,6 @@ params { ref_data_hmf_data_path = "/Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/hmftools/5.34_37--0" ref_data_virusbreakenddb_path = "/Users/matthewcooper/projects/oncoanalyser/virusbreakend/virusbreakenddb_20210401" refdata_unmap_regions = "/Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/markdups/unmap_regions_37.tsv" - max_fastq_records = 10000000 + max_fastq_records = 0 + use_mem2 = true } diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 0eb935ed..de85c31c 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -140,6 +140,7 @@ workflow TARGETED { ref_data.genome_fasta, ref_data.genome_bwa_index, params.max_fastq_records, + params.use_mem2, ) ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 5e984da4..00da6520 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -155,6 +155,7 @@ workflow WGTS { ref_data.genome_fasta, ref_data.genome_bwa_index, params.max_fastq_records, + params.use_mem2, ) ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) From 3b832650f08e0553661a7e81f2a13bc8a469cdf6 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 20 Feb 2024 16:19:16 +1100 Subject: [PATCH 328/562] Move new params into nextflow.config. --- nextflow.config | 4 ++++ nextflow_schema.json | 10 ++++++++++ temp/genomes_GRCh37_hmf.config | 2 -- workflows/targeted.nf | 2 +- workflows/wgts.nf | 4 ---- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/nextflow.config b/nextflow.config index 908ebb92..9bcf70e6 100644 --- a/nextflow.config +++ b/nextflow.config @@ -15,6 +15,10 @@ params { // Workflow mode mode = null + // Alignment options + max_fastq_records = 0 + use_mem2 = true + // Isofox user input files isofox_counts = null isofox_gc_ratios = null diff --git a/nextflow_schema.json b/nextflow_schema.json index 835ff2e3..4c852122 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -82,6 +82,16 @@ "default": false, "fa_icon": "fas fa-diagram-project" }, + "max_fastq_records": { + "type": "integer", + "description": "When positive, will use fastp to split fastq files so that each resultant fastq file has no more than max_fastq_records records. When nonpositive, fastp is not used and the provided fastq files are passed as-is to the aligner.", + "fa_icon": "fas fa-cog" + }, + "use_mem2": { + "type": "boolean", + "description": "When set uses bwa-mem2 for alignment, otherwise uses bwa mem for alignment.", + "fa_icon": "fas fa-cog" + }, "gridss_config": { "type": "string", "description": "Path to GRIDSS configuration file.", diff --git a/temp/genomes_GRCh37_hmf.config b/temp/genomes_GRCh37_hmf.config index 4249b1f0..2eef3d1d 100644 --- a/temp/genomes_GRCh37_hmf.config +++ b/temp/genomes_GRCh37_hmf.config @@ -13,6 +13,4 @@ params { ref_data_hmf_data_path = "/Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/hmftools/5.34_37--0" ref_data_virusbreakenddb_path = "/Users/matthewcooper/projects/oncoanalyser/virusbreakend/virusbreakenddb_20210401" refdata_unmap_regions = "/Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/markdups/unmap_regions_37.tsv" - max_fastq_records = 0 - use_mem2 = true } diff --git a/workflows/targeted.nf b/workflows/targeted.nf index de85c31c..ba97bfdc 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -166,7 +166,7 @@ workflow TARGETED { // TODO(SW): set up correctly if (true || run_config.stages.markdups) { - has_umis = params.panel.equalsIgnoreCase('tso500') + has_umis = run_config.panel.equalsIgnoreCase('tso500') READ_PROCESSING( ch_inputs, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 00da6520..69736dc6 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -111,10 +111,6 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft samplesheet = Utils.getFileObject(params.input) // TODO(MC): New params, and resource files, documentation and proper placement. -// TODO(MC): WARN: Found unexpected parameters: -// * --max_fastq_records: 10000000 -// * --refdata_unmap_regions: /Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/markdups/unmap_regions_37.tsv -// - Ignore this warning: params.schema_ignore_params = "max_fastq_records,refdata_unmap_regions" // TODO(MC): get error logs for amber, cobalt, and gripss // TODO(MC): Drop commit 'WIP: Reverting bioconda containers'. // TODO(MC): Drop commit 'WIP: Turn FASTP back on by default'. From 00cfe507210fae117daa57b53eec04ddaaca00b9 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 20 Feb 2024 15:45:03 +1100 Subject: [PATCH 329/562] Add label to markdups process. --- modules/local/markdups/main.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index e060d18c..dfe8c3c8 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -1,5 +1,6 @@ process MARKDUPS { tag "${meta_bam.subject_id}__${meta_bam.sample_id}" + label 'process_medium' container 'docker.io/scwatts/markdups:1.1.rc1' From 00bf6eed36a6a11e0f027ff947e3b4c07bee9648 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 20 Feb 2024 15:34:34 +1100 Subject: [PATCH 330/562] Add TODO. --- workflows/wgts.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 69736dc6..76cda24b 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -117,6 +117,7 @@ samplesheet = Utils.getFileObject(params.input) // TODO(MC): Check on bwa vs bwa-mem2 differences. // TODO(MC): Run all TSO500 test. // TODO(MC): Go from .fastq.gz. +// TODO(MC): Unmap region file location. workflow WGTS { // Create channel for versions // channel: [ versions.yml ] From ba241d1daae37018d4270cac28693f1445448a7f Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Wed, 21 Feb 2024 14:22:39 +1100 Subject: [PATCH 331/562] Disable all filtering and poly-g trimming in fastp. --- modules/local/fastp/main.nf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index fdbbb2d6..09bd6e0d 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -17,12 +17,16 @@ process FASTP { script: """ # * do not apply trimming/clipping, already done in BCL convert + # * turn off all filtering # * do not process umis, already done for us fastp \\ --in1 ${reads_fwd} \\ --in2 ${reads_rev} \\ + --disable_quality_filtering \\ + --disable_length_filtering \\ --disable_adapter_trimming \\ + --disable_trim_poly_g \\ --split_by_lines ${4 * max_fastq_records} \\ --out1 ${meta.sample_id}_${meta.read_group}_R1.fastp.fastq \\ --out2 ${meta.sample_id}_${meta.read_group}_R2.fastp.fastq From 3c1815439af283b9cf4533708765516cbca62d1f Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Wed, 21 Feb 2024 14:04:59 +1100 Subject: [PATCH 332/562] Use fastp by default. --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index 9bcf70e6..a8c892a6 100644 --- a/nextflow.config +++ b/nextflow.config @@ -16,7 +16,7 @@ params { mode = null // Alignment options - max_fastq_records = 0 + max_fastq_records = 10000000 use_mem2 = true // Isofox user input files From 6b4f80512bfd2d01cafcbdad55e5d445d0c40a09 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Wed, 21 Feb 2024 16:05:18 +1100 Subject: [PATCH 333/562] Remove bwa mem process. --- modules/local/bwa/{mem2 => }/Dockerfile | 0 modules/local/bwa/mem/Dockerfile | 9 ---- modules/local/bwa/mem/main.nf | 60 ------------------------- nextflow.config | 1 - nextflow_schema.json | 5 --- subworkflows/local/read_alignment.nf | 32 ++++--------- workflows/targeted.nf | 1 - workflows/wgts.nf | 1 - 8 files changed, 8 insertions(+), 101 deletions(-) rename modules/local/bwa/{mem2 => }/Dockerfile (100%) delete mode 100644 modules/local/bwa/mem/Dockerfile delete mode 100644 modules/local/bwa/mem/main.nf diff --git a/modules/local/bwa/mem2/Dockerfile b/modules/local/bwa/Dockerfile similarity index 100% rename from modules/local/bwa/mem2/Dockerfile rename to modules/local/bwa/Dockerfile diff --git a/modules/local/bwa/mem/Dockerfile b/modules/local/bwa/mem/Dockerfile deleted file mode 100644 index 2172ebc4..00000000 --- a/modules/local/bwa/mem/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM docker.io/continuumio/miniconda3:23.10.0-1 - -RUN \ - conda install -y -n base conda-libmamba-solver && \ - conda config --set solver libmamba && \ - conda install -y -c bioconda -c conda-forge -c conda \ - 'bwa==0.7.17' \ - 'sambamba==1.0' && \ - conda clean -yaf diff --git a/modules/local/bwa/mem/main.nf b/modules/local/bwa/mem/main.nf deleted file mode 100644 index 554251ca..00000000 --- a/modules/local/bwa/mem/main.nf +++ /dev/null @@ -1,60 +0,0 @@ -process BWA_MEM { - tag "${meta.subject_id}__${meta.sample_id}" - label 'process_high' - - container 'docker.io/scwatts/bwa:0.7.17-sambamba' - - input: - tuple val(meta), path(reads_fwd), path(reads_rev) - path genome_fasta - path genome_bwa_index - - output: - tuple val(meta), path('*.bam'), emit: bam - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - // TODO(MC): Double check this with Charles. - def read_group_tag = "@RG\\tID:${meta.read_group}\\tSM:${meta.sample_id}" - - // TODO(MC): Fix versions. - """ - ln -fs \$(find -L ${genome_bwa_index} -type f) ./ - - bwa mem \\ - -Y \\ - -R '${read_group_tag}' \\ - -t ${task.cpus} \\ - ${genome_fasta} \\ - ${reads_fwd} \\ - ${reads_rev} | \\ - \\ - sambamba view \\ - --sam-input \\ - --format bam \\ - --compression-level 0 \\ - --nthreads ${task.cpus} \\ - /dev/stdin | \\ - \\ - sambamba sort \\ - --nthreads ${task.cpus} \\ - --out ${meta.split}.${meta.sample_id}.${meta.read_group}.bam \\ - /dev/stdin - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - bwamem2: 2.2.1 - sambamba: 1.0 - END_VERSIONS - """ - - stub: - """ - touch ${meta.split}.${meta.sample_id}.${meta.read_group}.bam - - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/nextflow.config b/nextflow.config index a8c892a6..8525b232 100644 --- a/nextflow.config +++ b/nextflow.config @@ -17,7 +17,6 @@ params { // Alignment options max_fastq_records = 10000000 - use_mem2 = true // Isofox user input files isofox_counts = null diff --git a/nextflow_schema.json b/nextflow_schema.json index 4c852122..32e470a8 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -87,11 +87,6 @@ "description": "When positive, will use fastp to split fastq files so that each resultant fastq file has no more than max_fastq_records records. When nonpositive, fastp is not used and the provided fastq files are passed as-is to the aligner.", "fa_icon": "fas fa-cog" }, - "use_mem2": { - "type": "boolean", - "description": "When set uses bwa-mem2 for alignment, otherwise uses bwa mem for alignment.", - "fa_icon": "fas fa-cog" - }, "gridss_config": { "type": "string", "description": "Path to GRIDSS configuration file.", diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index 3e2281bb..4865ef10 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -1,4 +1,3 @@ -include { BWA_MEM } from '../../modules/local/bwa/mem/main' include { BWA_MEM2 } from '../../modules/local/bwa/mem2/main' include { FASTP } from '../../modules/local/fastp/main' include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' @@ -11,7 +10,6 @@ workflow READ_ALIGNMENT { genome_fasta genome_bwa_index max_fastq_records - use_mem2 main: // Channel for version.yml files @@ -42,7 +40,7 @@ workflow READ_ALIGNMENT { // TODO(SW): implement outputs ch_star_outputs = Channel.empty() - // BWA MEM/MEM2 + // BWA MEM2 // channel: [ sample_key, fastq_pair_count ] ch_sample_fastq_pair_count = ch_meta_samples_sorted.runnable_fastq.map { meta_sample -> @@ -192,31 +190,17 @@ workflow READ_ALIGNMENT { } // channel: [ meta_fastq, bam ] - ch_alignment_output = Channel.empty() - if (use_mem2) { - BWA_MEM2( - ch_bwa_mem_inputs, - genome_fasta, - genome_bwa_index, - ) - - ch_alignment_output = BWA_MEM2.out.bam - ch_versions = ch_versions.mix(BWA_MEM2.out.versions) - } - else { - BWA_MEM( - ch_bwa_mem_inputs, - genome_fasta, - genome_bwa_index, - ) + BWA_MEM2( + ch_bwa_mem_inputs, + genome_fasta, + genome_bwa_index, + ) - ch_alignment_output = BWA_MEM.out.bam - ch_versions = ch_versions.mix(BWA_MEM.out.versions) - } + ch_versions = ch_versions.mix(BWA_MEM2.out.versions) // channel: [ meta_fastq, bam, bai ] SAMBAMBA_INDEX( - ch_alignment_output, + BWA_MEM2.out.bam, ) ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) diff --git a/workflows/targeted.nf b/workflows/targeted.nf index ba97bfdc..e6c60379 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -140,7 +140,6 @@ workflow TARGETED { ref_data.genome_fasta, ref_data.genome_bwa_index, params.max_fastq_records, - params.use_mem2, ) ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 76cda24b..0aea0f8d 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -152,7 +152,6 @@ workflow WGTS { ref_data.genome_fasta, ref_data.genome_bwa_index, params.max_fastq_records, - params.use_mem2, ) ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) From c132e2b29473c8d3a3344b406044fe25a8d12e5f Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Wed, 21 Feb 2024 16:42:49 +1100 Subject: [PATCH 334/562] Remove obsolete TODOs. --- workflows/wgts.nf | 5 ----- 1 file changed, 5 deletions(-) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 0aea0f8d..6588c0f8 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -110,12 +110,7 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft // Get absolute file paths samplesheet = Utils.getFileObject(params.input) -// TODO(MC): New params, and resource files, documentation and proper placement. -// TODO(MC): get error logs for amber, cobalt, and gripss // TODO(MC): Drop commit 'WIP: Reverting bioconda containers'. -// TODO(MC): Drop commit 'WIP: Turn FASTP back on by default'. -// TODO(MC): Check on bwa vs bwa-mem2 differences. -// TODO(MC): Run all TSO500 test. // TODO(MC): Go from .fastq.gz. // TODO(MC): Unmap region file location. workflow WGTS { From 97104e476e27d002116cb70e03da6635c1a397d3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 21 Feb 2024 19:10:03 +1100 Subject: [PATCH 335/562] =?UTF-8?q?Bump=20version:=200.2.7=20=E2=86=92=200?= =?UTF-8?q?.3.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 050bd04b..cd1d9228 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.7 +current_version = 0.3.0 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/nextflow.config b/nextflow.config index e7bc4c49..cf37c819 100644 --- a/nextflow.config +++ b/nextflow.config @@ -212,7 +212,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.2.7' + version = '0.3.0' doi = '' } From ec992f1d35bf8561521e6333fcaf5667eec42cd6 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Thu, 22 Feb 2024 10:07:24 +1100 Subject: [PATCH 336/562] Pass ref genome version to markdups. --- modules/local/markdups/main.nf | 5 ++--- subworkflows/local/read_processing.nf | 2 ++ workflows/targeted.nf | 1 + workflows/wgts.nf | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index dfe8c3c8..255da3db 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -6,6 +6,7 @@ process MARKDUPS { input: tuple val(meta_bam), path(bams), path(bais) + val genome_ver path genome_fasta path genome_fai path genome_dict @@ -23,8 +24,6 @@ process MARKDUPS { script: def umi_flags = has_umis ? '-umi_enabled -umi_duplex -umi_duplex_delim +' : '' - // TODO(MC): Ref genome version. - """ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ @@ -42,7 +41,7 @@ process MARKDUPS { \\ -unmap_regions ${unmap_regions} \\ -ref_genome ${genome_fasta} \\ - -ref_genome_version 37 \\ + -ref_genome_version ${genome_ver} \\ \\ -write_stats \\ -threads 16 \\ diff --git a/subworkflows/local/read_processing.nf b/subworkflows/local/read_processing.nf index 11017a28..969f89d5 100644 --- a/subworkflows/local/read_processing.nf +++ b/subworkflows/local/read_processing.nf @@ -6,6 +6,7 @@ workflow READ_PROCESSING { ch_inputs // channel: [mandatory] [ meta ] ch_dna_bams // channel: [mandatory] [ meta, bam_dna ] ch_rna_bams // channel: [mandatory] [ meta, bam_rna ] + genome_ver genome_fasta genome_fai genome_dict @@ -64,6 +65,7 @@ workflow READ_PROCESSING { // channel: [ meta_bam, bam, bai ] MARKDUPS( ch_markdups_inputs, + genome_ver, genome_fasta, genome_fai, genome_dict, diff --git a/workflows/targeted.nf b/workflows/targeted.nf index e6c60379..13170ba1 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -171,6 +171,7 @@ workflow TARGETED { ch_inputs, ch_dna_alignment_out, ch_rna_alignment_out, + ref_data.genome_version, ref_data.genome_fasta, ref_data.genome_fai, ref_data.genome_dict, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 6588c0f8..f5f600ff 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -176,6 +176,7 @@ workflow WGTS { ch_inputs, ch_dna_alignment_out, ch_rna_alignment_out, + ref_data.genome_version, ref_data.genome_fasta, ref_data.genome_fai, ref_data.genome_dict, From 58a4c197f96d63f30b339688cdadedc4bd3c688f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 22 Feb 2024 10:16:30 +1100 Subject: [PATCH 337/562] Adjust README.md; example command and affiliation --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4ef27934..b2d1f419 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,8 @@ P1__wgts,P1,SC,normal,dna,bam,/path/to/SC.normal.dna.wgs.bam Launch oncoanalyser: ```bash -nextflow run umccr/oncoanalyser \ +nextflow run nf-core/oncoanalyser \ + -revision v0.3.0 \ -profile docker \ --mode wgts \ --genome GRCh38_hmf \ @@ -89,8 +90,9 @@ Each release that is given extended support is allocated a separate long-lived g ## Credits -The oncoanalyser pipeline was written by Stephen Watts at the [University of Melbourne Centre for Cancer -Research](https://mdhs.unimelb.edu.au/centre-for-cancer-research). +The oncoanalyser pipeline was written by Stephen Watts while in the [Genomics Platform +Group](https://mdhs.unimelb.edu.au/centre-for-cancer-research/our-research/genomics-platform-group) at the [University +of Melbourne Centre for Cancer Research](https://mdhs.unimelb.edu.au/centre-for-cancer-research). We thank the following people for their extensive assistance in the development of this pipeline, listed in alphabetical order: From 7970f83ab62ebc629d973b5a08f9cc6c1880d08d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 22 Feb 2024 10:22:14 +1100 Subject: [PATCH 338/562] Add version from README.md to bumpversion config --- .bumpversion.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index cd1d9228..69867631 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -7,3 +7,7 @@ parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) [bumpversion:file:nextflow.config] search = version = '{current_version}' replace = version = '{new_version}' + +[bumpversion:file:README.md] +search = -revision v{current_version} +replace = -revision v{new_version} From f7d3e5cf23700f4c9f76cf10828d0ea17b50f959 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Thu, 22 Feb 2024 10:36:27 +1100 Subject: [PATCH 339/562] Add TODO. --- workflows/wgts.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index f5f600ff..41199858 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -113,6 +113,7 @@ samplesheet = Utils.getFileObject(params.input) // TODO(MC): Drop commit 'WIP: Reverting bioconda containers'. // TODO(MC): Go from .fastq.gz. // TODO(MC): Unmap region file location. +// TODO(MC): Fix warnings. workflow WGTS { // Create channel for versions // channel: [ versions.yml ] From a01df622f1a18b3f81697f2d215c9f7820909f12 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Thu, 22 Feb 2024 11:30:26 +1100 Subject: [PATCH 340/562] Get versions from CLIs. --- modules/local/bwa/mem2/main.nf | 5 +++-- modules/local/fastp/main.nf | 2 +- modules/local/markdups/main.nf | 9 +++++---- modules/local/sambamba/index/main.nf | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index 28da8562..4072a54b 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -25,6 +25,7 @@ process BWA_MEM2 { // TODO(MC): Double check this with Charles. def read_group_tag = "@RG\\tID:${meta.read_group}\\tSM:${meta.sample_id}" + // NOTE(MC): Hardcoding bwa-mem2 version since the CLI does not have a --version flag. """ ln -fs \$(find -L ${genome_bwa_index} -type f) ./ @@ -50,8 +51,8 @@ process BWA_MEM2 { cat <<-END_VERSIONS > versions.yml "${task.process}": - bwamem2: 2.2.1 - sambamba: 1.0 + bwa-mem2: 2.2.1 + sambamba: \$(sambamba --version 2>&1 | egrep '^sambamba' | head -n 1 | awk '{ print \$NF }') END_VERSIONS """ diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index 09bd6e0d..95ec9e39 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -33,7 +33,7 @@ process FASTP { cat <<-END_VERSIONS > versions.yml "${task.process}": - fastp: 0.23.4 + fastp: \$(fastp --version 2>&1 | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 255da3db..e7737d65 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -24,6 +24,7 @@ process MARKDUPS { script: def umi_flags = has_umis ? '-umi_enabled -umi_duplex -umi_duplex_delim +' : '' + // TODO(MC): Update mark-dups version command, and update to bioconda container. """ java \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ @@ -50,10 +51,10 @@ process MARKDUPS { cat <<-END_VERSIONS > versions.yml "${task.process}": - sambamba: 1.0 - samtools: 1.17 - openjdk: 8 - mark-dups: 1.1 + mark-dups: \$(java -jar /opt/markdups/markdups.jar -version | awk '{ print \$NF }') + openjdk: \$(java --version | egrep '^OpenJDK Runtime Environment ' | sed 's/^.*build //' | sed 's/.\$//') + sambamba: \$(sambamba --version 2>&1 | egrep '^sambamba' | head -n 1 | awk '{ print \$NF }') + samtools: \$(samtools --version 2>&1 | egrep '^samtools\\s' | head -n 1 | sed 's/^.* //') END_VERSIONS """ diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf index cb205904..8d54aa07 100644 --- a/modules/local/sambamba/index/main.nf +++ b/modules/local/sambamba/index/main.nf @@ -21,7 +21,7 @@ process SAMBAMBA_INDEX { cat <<-END_VERSIONS > versions.yml "${task.process}": - sambamba: 1.0 + sambamba: \$(sambamba --version 2>&1 | egrep '^sambamba' | head -n 1 | awk '{ print \$NF }') END_VERSIONS """ From 2c298c4db8580923835bcc24b90c34535c43598c Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Thu, 22 Feb 2024 16:52:39 +1100 Subject: [PATCH 341/562] Delete Dockerfiles and update containers to biocontainer equivalents. --- modules/local/bwa/Dockerfile | 9 ------ modules/local/bwa/mem2/main.nf | 5 +-- modules/local/fastp/Dockerfile | 8 ----- modules/local/fastp/main.nf | 4 ++- modules/local/markdups/Dockerfile | 12 ------- modules/local/markdups/main.nf | 48 ++++++++++++++-------------- modules/local/sambamba/Dockerfile | 8 ----- modules/local/sambamba/index/main.nf | 4 ++- 8 files changed, 33 insertions(+), 65 deletions(-) delete mode 100644 modules/local/bwa/Dockerfile delete mode 100644 modules/local/fastp/Dockerfile delete mode 100644 modules/local/markdups/Dockerfile delete mode 100644 modules/local/sambamba/Dockerfile diff --git a/modules/local/bwa/Dockerfile b/modules/local/bwa/Dockerfile deleted file mode 100644 index 0f2641da..00000000 --- a/modules/local/bwa/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM docker.io/continuumio/miniconda3:23.10.0-1 - -RUN \ - conda install -y -n base conda-libmamba-solver && \ - conda config --set solver libmamba && \ - conda install -y -c bioconda -c conda-forge -c conda \ - 'bwa-mem2==2.2.1' \ - 'sambamba==1.0' && \ - conda clean -yaf diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index 4072a54b..f43b520b 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -2,8 +2,9 @@ process BWA_MEM2 { tag "${meta.subject_id}__${meta.sample_id}" label 'process_high' - // TODO(SW): Upload container. - container 'bwa-mem2:2.2.1-sambamba' + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bwa-mem2:2.2.1--hd03093a_5' : + 'quay.io/biocontainers/bwa-mem2:2.2.1--hd03093a_5' }" input: tuple val(meta), path(reads_fwd), path(reads_rev) diff --git a/modules/local/fastp/Dockerfile b/modules/local/fastp/Dockerfile deleted file mode 100644 index 5d7cdbf9..00000000 --- a/modules/local/fastp/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM docker.io/continuumio/miniconda3:23.10.0-1 - -RUN \ - conda install -y -n base conda-libmamba-solver && \ - conda config --set solver libmamba && \ - conda install -y -c bioconda -c conda-forge -c conda \ - 'fastp==0.23.4' && \ - conda clean -yaf diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index 95ec9e39..86f72f92 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -1,7 +1,9 @@ process FASTP { tag "${meta.subject_id}__${meta.sample_id}" - container 'docker.io/scwatts/fastp:0.23.4' + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/fastp:0.23.4--hadf994f_2' : + 'quay.io/biocontainers/fastp:0.23.4--hadf994f_2' }" input: tuple val(meta), path(reads_fwd), path(reads_rev) diff --git a/modules/local/markdups/Dockerfile b/modules/local/markdups/Dockerfile deleted file mode 100644 index d7232f05..00000000 --- a/modules/local/markdups/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM docker.io/continuumio/miniconda3:23.10.0-1 - -RUN \ - conda install -y -n base conda-libmamba-solver && \ - conda config --set solver libmamba && \ - conda install -y -c bioconda -c conda-forge -c conda \ - 'sambamba==1.0' 'samtools==1.17' 'openjdk >=8' && \ - conda clean -yaf - -RUN \ - mkdir -p /opt/markdups/ && \ - wget -O /opt/markdups/markdups.jar 'https://github.com/hartwigmedical/hmftools/releases/download/mark-dups-v1.1/mark-dups_v1.1.rc1.jar' diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index e7737d65..2860ab05 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -2,7 +2,9 @@ process MARKDUPS { tag "${meta_bam.subject_id}__${meta_bam.sample_id}" label 'process_medium' - container 'docker.io/scwatts/markdups:1.1.rc1' + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-mark-dups:1.1--hdfd78af_0' }" input: tuple val(meta_bam), path(bams), path(bais) @@ -24,34 +26,32 @@ process MARKDUPS { script: def umi_flags = has_umis ? '-umi_enabled -umi_duplex -umi_duplex_delim +' : '' - // TODO(MC): Update mark-dups version command, and update to bioconda container. """ - java \\ + markdups \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -jar /opt/markdups/markdups.jar \\ - \\ - -samtools \$(which samtools) \\ - -sambamba \$(which sambamba) \\ - \\ - -sample ${meta_bam.sample_id} \\ - -input_bam ${bams.join(',')} \\ - \\ - -form_consensus \\ - -multi_bam \\ - ${umi_flags} \\ - \\ - -unmap_regions ${unmap_regions} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - \\ - -write_stats \\ - -threads 16 \\ - \\ - -output_bam ${meta_bam.sample_id}.markdups.bam + \\ + -samtools \$(which samtools) \\ + -sambamba \$(which sambamba) \\ + \\ + -sample ${meta_bam.sample_id} \\ + -input_bam ${bams.join(',')} \\ + \\ + -form_consensus \\ + -multi_bam \\ + ${umi_flags} \\ + \\ + -unmap_regions ${unmap_regions} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + \\ + -write_stats \\ + -threads 16 \\ + \\ + -output_bam ${meta_bam.sample_id}.markdups.bam cat <<-END_VERSIONS > versions.yml "${task.process}": - mark-dups: \$(java -jar /opt/markdups/markdups.jar -version | awk '{ print \$NF }') + markdups: \$(markdups -version | awk '{ print \$NF }') openjdk: \$(java --version | egrep '^OpenJDK Runtime Environment ' | sed 's/^.*build //' | sed 's/.\$//') sambamba: \$(sambamba --version 2>&1 | egrep '^sambamba' | head -n 1 | awk '{ print \$NF }') samtools: \$(samtools --version 2>&1 | egrep '^samtools\\s' | head -n 1 | sed 's/^.* //') diff --git a/modules/local/sambamba/Dockerfile b/modules/local/sambamba/Dockerfile deleted file mode 100644 index 8c2c38c5..00000000 --- a/modules/local/sambamba/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM docker.io/continuumio/miniconda3:23.10.0-1 - -RUN \ - conda install -y -n base conda-libmamba-solver && \ - conda config --set solver libmamba && \ - conda install -y -c bioconda -c conda-forge -c conda \ - 'sambamba==1.0' && \ - conda clean -yaf diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf index 8d54aa07..f39b0ea7 100644 --- a/modules/local/sambamba/index/main.nf +++ b/modules/local/sambamba/index/main.nf @@ -1,7 +1,9 @@ process SAMBAMBA_INDEX { tag "${meta.subject_id}__${meta.sample_id}" - container 'docker.io/scwatts/sambamba:1.0' + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/sambamba:1.0--h98b6b92_0' : + 'quay.io/biocontainers/sambamba:1.0--h98b6b92_0' }" input: tuple val(meta), path(bam) From 33244d90067323477ab111e13c5c18310f4e9713 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Thu, 22 Feb 2024 16:14:12 +1100 Subject: [PATCH 342/562] Removing temp config. --- temp/genomes_GRCh37_hmf.config | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 temp/genomes_GRCh37_hmf.config diff --git a/temp/genomes_GRCh37_hmf.config b/temp/genomes_GRCh37_hmf.config deleted file mode 100644 index 2eef3d1d..00000000 --- a/temp/genomes_GRCh37_hmf.config +++ /dev/null @@ -1,16 +0,0 @@ -params { - genomes { - 'GRCh37_hmf' { - fasta = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/Homo_sapiens.GRCh37.GATK.illumina.fasta" - fai = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" - dict = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" - bwa_index = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/bwa_index/0.7.17-r1188" - bwa_index_image = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" - gridss_index = "/Users/matthewcooper/projects/oncoanalyser/genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" - } - } - - ref_data_hmf_data_path = "/Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/hmftools/5.34_37--0" - ref_data_virusbreakenddb_path = "/Users/matthewcooper/projects/oncoanalyser/virusbreakend/virusbreakenddb_20210401" - refdata_unmap_regions = "/Users/matthewcooper/projects/oncoanalyser/hmf_reference_data/markdups/unmap_regions_37.tsv" -} From 8d82bacfc5f69a8d4a98017fd840cdc3221129c2 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Fri, 23 Feb 2024 09:54:55 +1100 Subject: [PATCH 343/562] Fix process tags. --- modules/local/bwa/mem2/main.nf | 2 +- modules/local/fastp/main.nf | 2 +- modules/local/markdups/main.nf | 2 +- modules/local/sambamba/index/main.nf | 2 +- subworkflows/local/read_alignment.nf | 4 +++- subworkflows/local/read_processing.nf | 3 +++ 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index f43b520b..f9c0151f 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -1,5 +1,5 @@ process BWA_MEM2 { - tag "${meta.subject_id}__${meta.sample_id}" + tag "${meta.id}" label 'process_high' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index 86f72f92..be254c16 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -1,5 +1,5 @@ process FASTP { - tag "${meta.subject_id}__${meta.sample_id}" + tag "${meta.id}" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastp:0.23.4--hadf994f_2' : diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 2860ab05..1a98731a 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -1,5 +1,5 @@ process MARKDUPS { - tag "${meta_bam.subject_id}__${meta_bam.sample_id}" + tag "${meta_bam.id}" label 'process_medium' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf index f39b0ea7..0f620584 100644 --- a/modules/local/sambamba/index/main.nf +++ b/modules/local/sambamba/index/main.nf @@ -1,5 +1,5 @@ process SAMBAMBA_INDEX { - tag "${meta.subject_id}__${meta.sample_id}" + tag "${meta.id}" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/sambamba:1.0--h98b6b92_0' : diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index 4865ef10..3724345a 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -73,7 +73,7 @@ workflow READ_ALIGNMENT { def sample_id = meta[sample_key]['sample_id'] def fastq_files = meta[sample_key][Constants.FileType.FASTQ].toString().tokenize(';') - def meta_fastq_common = [:] + def meta_fastq_common = [id: "${meta.group_id}__${sample_id}"] meta.each { key, value -> if (key === sample_key) { @@ -122,6 +122,7 @@ workflow READ_ALIGNMENT { def meta_sample = split_fastq_pairs[0] def sample_key = Utils.shallow_copy(meta_sample) + sample_key.remove('id') sample_key.remove('read_group') sample_key.remove(meta_sample.sample_key) @@ -214,6 +215,7 @@ workflow READ_ALIGNMENT { def meta_bam = bam[0] def sample_key = Utils.shallow_copy(meta_bam) + sample_key.remove('id') sample_key.remove(meta_bam.sample_key) sample_key.remove('read_group') sample_key.remove('split') diff --git a/subworkflows/local/read_processing.nf b/subworkflows/local/read_processing.nf index 969f89d5..bdd71a5a 100644 --- a/subworkflows/local/read_processing.nf +++ b/subworkflows/local/read_processing.nf @@ -51,6 +51,8 @@ workflow READ_PROCESSING { } } + meta_bam['id'] = "${meta_bam.group_id}__${meta_bam.sample_id}" + if (!(bams instanceof Collection)) { bams = [bams] } @@ -82,6 +84,7 @@ workflow READ_PROCESSING { def meta_bam = bam[0] def meta = Utils.shallow_copy(meta_bam) + meta.remove('id') meta.remove('sample_id') meta.remove('sample_key') From be271bbe3c3c4f1df7d90313a1f30923e958f62f Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Fri, 23 Feb 2024 10:15:11 +1100 Subject: [PATCH 344/562] Reassign TODO. --- workflows/wgts.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 41199858..42fc0ebb 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -112,7 +112,7 @@ samplesheet = Utils.getFileObject(params.input) // TODO(MC): Drop commit 'WIP: Reverting bioconda containers'. // TODO(MC): Go from .fastq.gz. -// TODO(MC): Unmap region file location. +// TODO(SW): Unmap region resouce files. // TODO(MC): Fix warnings. workflow WGTS { // Create channel for versions From 1364c8b27ce3e7502cb1d22bbd90c1c440798cb7 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Fri, 23 Feb 2024 10:50:35 +1100 Subject: [PATCH 345/562] Add TODO. --- workflows/wgts.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 42fc0ebb..4d2a74fc 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -111,7 +111,7 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft samplesheet = Utils.getFileObject(params.input) // TODO(MC): Drop commit 'WIP: Reverting bioconda containers'. -// TODO(MC): Go from .fastq.gz. +// TODO(MC): Run full tests for going from .fastq.gz. // TODO(SW): Unmap region resouce files. // TODO(MC): Fix warnings. workflow WGTS { From e35e4f35d64cd5be1bc286d81c9c8d785b68f996 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Fri, 23 Feb 2024 11:51:09 +1100 Subject: [PATCH 346/562] Align read group construction with HMF pipeline5. --- lib/Utils.groovy | 43 ++++++++++++++++++++++++---- modules/local/bwa/mem2/main.nf | 1 - subworkflows/local/read_alignment.nf | 2 +- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index e40711e6..387b207b 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -486,15 +486,46 @@ class Utils { return splitGroupIntoSamples(meta_group).size() } - static public readGroupFromFastqPath(fastq_path) { + static public fastqBasenameWithoutExtension(fastq_path) { def base_name = fastq_path.split('/')[-1] - def components = base_name.split('_') - def read_group_components = [] - for (def i = 0; i < components.size() - 2; ++i) { - read_group_components.add(components[i]) + def matcher = base_name =~ /^(.*)\.fastq(\.gz|)$/ + assert matcher.find() + return matcher[0][1] + } + + static public readGroupFromFastqPath(fwd_fastq_path, rev_fastq_path) { + def fwd_fastq_no_extension = fastqBasenameWithoutExtension(fwd_fastq_path) + def rev_fastq_no_extension = fastqBasenameWithoutExtension(rev_fastq_path) + + def lane_fastq_pattern = /^(.*)_(.*_L[0-9]{3})_(R[12])_([0-9]{3})$/ + def fwd_matcher = fwd_fastq_no_extension =~ lane_fastq_pattern + def rev_matcher = rev_fastq_no_extension =~ lane_fastq_pattern + + if (fwd_matcher.find()) { + assert rev_matcher.find() + assert fwd_matcher[0][3].equals("R1") + assert rev_matcher[0][3].equals("R2") + + def fwd_read_group = "${fwd_matcher[0][2]}_${fwd_matcher[0][4]}" + def rev_read_group = "${rev_matcher[0][2]}_${rev_matcher[0][4]}" + assert fwd_read_group.equals(rev_read_group) + return fwd_read_group } - return read_group_components.join('_') + // Case for when lane fastq files are from picard SamToFastq. + lane_fastq_pattern = /^(.*)_(.*_L[0-9]{3})_([0-9]{3})_([12])$/ + fwd_matcher = fwd_fastq_no_extension =~ lane_fastq_pattern + rev_matcher = rev_fastq_no_extension =~ lane_fastq_pattern + + assert fwd_matcher.find() + assert rev_matcher.find() + assert fwd_matcher[0][4].equals("1") + assert rev_matcher[0][4].equals("2") + + def fwd_read_group = "${fwd_matcher[0][1]}_${fwd_matcher[0][2]}" + def rev_read_group = "${rev_matcher[0][1]}_${rev_matcher[0][2]}" + assert fwd_read_group.equals(rev_read_group) + return fwd_read_group } } diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index f9c0151f..062a24ae 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -23,7 +23,6 @@ process BWA_MEM2 { task.ext.when == null || task.ext.when script: - // TODO(MC): Double check this with Charles. def read_group_tag = "@RG\\tID:${meta.read_group}\\tSM:${meta.sample_id}" // NOTE(MC): Hardcoding bwa-mem2 version since the CLI does not have a --version flag. diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index 3724345a..bee3cdbd 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -91,7 +91,7 @@ workflow READ_ALIGNMENT { def reads_rev = fastq_files[i + 1] def meta_fastq = Utils.shallow_copy(meta_fastq_common) - meta_fastq['read_group'] = Utils.readGroupFromFastqPath(reads_fwd) + meta_fastq['read_group'] = Utils.readGroupFromFastqPath(reads_fwd, reads_rev) fastq_pairs.add([meta_fastq, reads_fwd, reads_rev]) } From aa77b223348cb19ccf4d0b279d102b5671be9850 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 24 Feb 2024 08:15:49 +1100 Subject: [PATCH 347/562] Bump MarkDups to 1.1.1 --- modules/local/markdups/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 1a98731a..0f6f25d7 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -3,8 +3,8 @@ process MARKDUPS { label 'process_medium' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-mark-dups:1.1--hdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.1--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-mark-dups:1.1.1--hdfd78af_0' }" input: tuple val(meta_bam), path(bams), path(bais) From 127239efdd01f03e7c9d7b291344463a14246017 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 27 Feb 2024 16:18:50 +1100 Subject: [PATCH 348/562] Update pipeline summary tool list --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2d1f419..949e871d 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ The following processes and tools can be run with oncoanalyser: * HRD status prediction (`CHORD`) * Mutational signature fitting (`Sigs`) * Tissue of origin prediction (`CUPPA`) -* Report generation (`ORANGE`, `gpgr [LINX]`) +* Report generation (`ORANGE`, `linxreport`) ## Quick Start From 130193266d66a3de19e82a3e30e06737d4519085 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 28 Feb 2024 12:26:30 +1100 Subject: [PATCH 349/562] Patch --- conf/hmf_data.config | 2 + conf/hmf_genomes.config | 4 + lib/Constants.groovy | 96 ++++- lib/Utils.groovy | 273 +++++++------ main.nf | 2 + modules/local/bwa/mem2/Dockerfile | 19 + modules/local/bwa/mem2/main.nf | 14 +- modules/local/fastp/main.nf | 12 +- modules/local/markdups/main.nf | 36 +- modules/local/sambamba/index/main.nf | 8 +- nextflow_schema.json | 14 + subworkflows/local/amber_profiling.nf | 42 +- subworkflows/local/bamtools_metrics.nf | 119 +++--- subworkflows/local/chord_prediction.nf | 2 +- subworkflows/local/cobalt_profiling.nf | 48 +-- subworkflows/local/cuppa_prediction.nf | 6 +- subworkflows/local/flagstat_metrics.nf | 132 +++--- subworkflows/local/gridss_svprep_calling.nf | 127 +++--- subworkflows/local/gripss_filtering.nf | 6 +- subworkflows/local/lilac_calling.nf | 67 ++-- subworkflows/local/linx_annotation.nf | 4 +- subworkflows/local/pave_annotation.nf | 4 +- subworkflows/local/prepare_reference.nf | 11 + subworkflows/local/purple_calling.nf | 2 +- subworkflows/local/read_alignment.nf | 421 ++++++++------------ subworkflows/local/read_processing.nf | 215 +++++----- subworkflows/local/sage_append.nf | 2 +- subworkflows/local/sage_calling.nf | 89 ++--- subworkflows/local/sigs_fitting.nf | 2 +- subworkflows/local/virusbreakend_calling.nf | 23 +- workflows/targeted.nf | 148 +++---- workflows/wgts.nf | 160 ++++---- 32 files changed, 1065 insertions(+), 1045 deletions(-) create mode 100644 modules/local/bwa/mem2/Dockerfile diff --git a/conf/hmf_data.config b/conf/hmf_data.config index fc6cf635..6fdcba0b 100644 --- a/conf/hmf_data.config +++ b/conf/hmf_data.config @@ -50,6 +50,7 @@ params { known_fusions = 'dna_pipeline/sv/known_fusions.37.bedpe' purple_germline_del = 'dna_pipeline/copy_number/cohort_germline_del_freq.37.csv' segment_mappability = 'dna_pipeline/variants/mappability_150.37.bed.gz' + unmap_regions = 'dna_pipeline/common/unmap_regions.37.tsv' } '38' { // AMBER @@ -101,6 +102,7 @@ params { known_fusions = 'dna_pipeline/sv/known_fusions.38.bedpe' purple_germline_del = 'dna_pipeline/copy_number/cohort_germline_del_freq.38.csv' segment_mappability = 'dna_pipeline/variants/mappability_150.38.bed.gz' + unmap_regions = 'dna_pipeline/common/unmap_regions.38.tsv' } } } diff --git a/conf/hmf_genomes.config b/conf/hmf_genomes.config index 147d4274..5e38201b 100644 --- a/conf/hmf_genomes.config +++ b/conf/hmf_genomes.config @@ -14,6 +14,8 @@ params { fai = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" dict = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" bwa_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/0.7.17-r1188.tar.gz" + bwa_index_bseq = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.0123" + bwa_index_biidx = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64" bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" } @@ -22,6 +24,8 @@ params { fai = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" dict = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" bwa_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz" + bwa_index_bseq = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" + bwa_index_biiseq= "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 91f1059c..10bdc0ea 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -11,8 +11,8 @@ class Constants { static List PANELS_DEFINED = ['tso500'] - static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_37--0.tar.gz' - static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_38--0.tar.gz' + static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_37--2.tar.gz' + static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_38--2.tar.gz' static String TSO500_PANEL_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_37--0.tar.gz' @@ -34,13 +34,12 @@ class Constants { } static enum Process { - BWAMEM2, + ALIGNMENT, AMBER, BAMTOOLS, CHORD, COBALT, CUPPA, - FASTP, FLAGSTAT, GRIDSS, GRIPSS, @@ -52,7 +51,6 @@ class Constants { PAVE, PURPLE, SAGE, - SAMBAMBA_INDEX, SIGS, VIRUSINTERPRETER, } @@ -104,16 +102,96 @@ class Constants { DNA_RNA, } - static List DNA_SAMPLE_KEYS = [ - [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], - [Constants.SampleType.NORMAL, Constants.SequenceType.DNA], - ] + static enum InfoField { + CANCER_TYPE, + LANE, + LIBRARY_ID, + } static Map PLACEHOLDER_META = [meta_placeholder: null] static List PLACEHOLDER_OPTIONAL_CHANNEL = [] static Map INPUT = [ + BAM_DNA_TUMOR: [ + FileType.BAM, + SampleType.TUMOR, + SequenceType.DNA, + ], + + BAM_MARKDUPS_DNA_TUMOR: [ + FileType.BAM_MARKDUPS, + SampleType.TUMOR, + SequenceType.DNA, + ], + + BAM_RNA_TUMOR : [ + FileType.BAM, + SampleType.TUMOR, + SequenceType.RNA, + ], + + BAM_DNA_NORMAL: [ + FileType.BAM, + SampleType.NORMAL, + SequenceType.DNA, + ], + + BAM_MARKDUPS_DNA_NORMAL: [ + FileType.BAM_MARKDUPS, + SampleType.NORMAL, + SequenceType.DNA, + ], + + BAM_RNA_NORMAL : [ + FileType.BAM, + SampleType.NORMAL, + SequenceType.RNA, + ], + + + + + + BAI_DNA_TUMOR: [ + FileType.BAI, + SampleType.TUMOR, + SequenceType.DNA, + ], + + BAI_MARKDUPS_DNA_TUMOR: [ + FileType.BAI_MARKDUPS, + SampleType.TUMOR, + SequenceType.DNA, + ], + + BAI_RNA_TUMOR : [ + FileType.BAI, + SampleType.TUMOR, + SequenceType.RNA, + ], + + BAI_DNA_NORMAL: [ + FileType.BAI, + SampleType.NORMAL, + SequenceType.DNA, + ], + + BAI_MARKDUPS_DNA_NORMAL: [ + FileType.BAI_MARKDUPS, + SampleType.NORMAL, + SequenceType.DNA, + ], + + BAI_RNA_NORMAL : [ + FileType.BAI, + SampleType.NORMAL, + SequenceType.RNA, + ], + + + + ISOFOX_DIR: [ FileType.ISOFOX_DIR, SampleType.TUMOR, diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 387b207b..2ab04a11 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -11,7 +11,7 @@ class Utils { public static parseInput(input_fp_str, stub_run, log) { - // NOTE(SW): using Nextflow .splitCsv channel operator, hence sould be easily interchangable + // NOTE(SW): using NF .splitCsv channel operator, hence should be easily interchangable with NF syntax def input_fp = Utils.getFileObject(input_fp_str) def inputs = nextflow.splitter.SplitterEx.splitCsv(input_fp, [header: true]) @@ -31,7 +31,6 @@ class Utils { meta.subject_id = it.subject_id } - // Sample type def sample_type_enum = Utils.getEnumFromString(it.sample_type, Constants.SampleType) if (!sample_type_enum) { @@ -64,12 +63,75 @@ class Utils { System.exit(1) } - if (meta_sample.containsKey(filetype_enum)) { + if (meta_sample.containsKey(filetype_enum) & filetype_enum != Constants.FileType.FASTQ) { log.error "got duplicate file for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${filetype_enum}" System.exit(1) } - meta_sample[filetype_enum] = Utils.getFileObject(it.filepath) + // Info data + def info_data = [:] + if (it.containsKey('info')) { + // Parse + it.info + .tokenize(';') + .each { e -> + def (k, v) = e.tokenize(':') + def info_field_enum = Utils.getEnumFromString(k, Constants.InfoField) + + if (!info_field_enum) { + def info_field_str = Utils.getEnumNames(Constants.InfoField).join('\n - ') + log.error "received invalid info field: '${k}'. Valid options are:\n - ${info_field_str}" + System.exit(1) + } + + if (info_data.containsKey(info_field_enum)) { + log.error "got duplicate info field for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${info_field_enum}" + System.exit(1) + } + + info_data[info_field_enum] = v + } + + // Process + if (info_data.containsKey(Constants.InfoField.CANCER_TYPE)) { + meta[Constants.InfoField.CANCER_TYPE] = info_data[Constants.InfoField.CANCER_TYPE] + } + + } + + + // Handle inputs appropriately + if (filetype_enum === Constants.FileType.FASTQ) { + + if (!info_data.containsKey(Constants.InfoField.LIBRARY_ID)) { + log.error "missing 'library_id' info field for ${group_id} ${sample_type_enum}/${sequence_type_enum}" + System.exit(1) + } + + if (!info_data.containsKey(Constants.InfoField.LANE)) { + log.error "missing 'lane' info field for ${group_id} ${sample_type_enum}/${sequence_type_enum}" + System.exit(1) + } + + def (fwd, rev) = it.filepath.tokenize(';') + def fastq_key = [info_data[Constants.InfoField.LIBRARY_ID], info_data[Constants.InfoField.LANE]] + + if (meta_sample.containsKey(fastq_key)) { + log.error "got duplicate lane + library_id data for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${fastq_key}" + System.exit(1) + } + + if (!meta_sample.containsKey(filetype_enum)) { + meta_sample[filetype_enum] = [:] + } + + meta_sample[filetype_enum][fastq_key] = ['fwd': fwd, 'rev': rev] + + } else { + + meta_sample[filetype_enum] = Utils.getFileObject(it.filepath) + + } // Record sample key to simplify iteration later on sample_keys << sample_key @@ -205,14 +267,14 @@ class Utils { if (run_config.mode === Constants.RunMode.TARGETED) { // Do not allow normal DNA - if (Utils.hasNormalDnaBam(meta)) { + if (Utils.hasNormalDna(meta)) { log.error "targeted mode is not compatible with the normal DNA BAM provided for ${meta.group_id}\n\n" + "The targeted workflow supports only tumor DNA BAMs (and tumor RNA BAMs for TSO500)" System.exit(1) } // Do not allow only tumor RNA - if (Utils.hasTumorRnaBam(meta) && !Utils.hasTumorDnaBam(meta)) { + if (Utils.hasTumorRnaBam(meta) && !Utils.hasTumorDna(meta)) { log.error "targeted mode is not compatible with only tumor RNA provided for ${meta.group_id}\n\n" + "The targeted workflow requires tumor DNA and can optionally take tumor RNA, depending on " + "the configured panel." @@ -229,7 +291,7 @@ class Utils { } // Do not allow normal DNA only - if (Utils.hasNormalDnaBam(meta) && !Utils.hasTumorDnaBam(meta)) { + if (Utils.hasNormalDna(meta) && !Utils.hasTumorDna(meta)) { log.error "germline only mode not supported, found only a normal DNA BAM for ${meta.group_id}\n" System.exit(1) } @@ -311,124 +373,134 @@ class Utils { return path ? nextflow.Nextflow.file(path) : [] } + static public getRunMode(run_mode, log) { + def run_mode_enum = Utils.getEnumFromString(run_mode, Constants.RunMode) + if (!run_mode_enum) { + def run_modes_str = Utils.getEnumNames(Constants.RunMode).join('\n - ') + log.error "recieved an invalid run mode: '${run_mode}'. Valid options are:\n - ${run_modes_str}" + System.exit(1) + } + return run_mode_enum + } + + + // Sample records + static public getTumorDnaSample(meta) { + return meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.DNA], [:]) + } + + static public getTumorRnaSample(meta) { + return meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.RNA], [:]) + } + + static public getNormalDnaSample(meta) { + return meta.getOrDefault([Constants.SampleType.NORMAL, Constants.SequenceType.DNA], [:]) + } + // Sample names static public getTumorDnaSampleName(meta) { - def meta_sample = meta[Constants.SampleType.TUMOR, Constants.SequenceType.DNA] - return meta_sample['sample_id'] + return getTumorDnaSample(meta)['sample_id'] } static public getTumorRnaSampleName(meta) { - def meta_sample = meta[Constants.SampleType.TUMOR, Constants.SequenceType.RNA] - return meta_sample['sample_id'] + return getTumorRnaSample(meta)['sample_id'] } static public getNormalDnaSampleName(meta) { - def meta_sample = meta[Constants.SampleType.NORMAL, Constants.SequenceType.DNA] - return meta_sample['sample_id'] + return getNormalDnaSample(meta)['sample_id'] } // Files static public getTumorDnaBam(meta) { - def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.DNA], [:]) - return meta_sample.getOrDefault(Constants.FileType.BAM, null) + return getTumorDnaSample(meta).getOrDefault(Constants.FileType.BAM, null) } static public getTumorDnaBai(meta) { - def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.DNA], [:]) - return meta_sample.getOrDefault(Constants.FileType.BAI, null) + return getTumorDnaSample(meta).getOrDefault(Constants.FileType.BAI, null) + } + + static public getTumorDnaMarkdupsBam(meta) { + return getTumorDnaSample(meta).getOrDefault(Constants.FileType.BAM_MARKDUPS, null) + } + + static public getTumorDnaFastq(meta) { + return getTumorDnaSample(meta).getOrDefault(Constants.FileType.FASTQ, null) } static public hasTumorDnaBam(meta) { return getTumorDnaBam(meta) !== null } + static public hasTumorDnaMarkdupsBam(meta) { + return getTumorDnaMarkdupsBam(meta) !== null + } + + static public hasTumorDnaFastq(meta) { + return getTumorDnaFastq(meta) !== null + } + static public getTumorRnaBam(meta) { - def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.RNA], [:]) - return meta_sample.getOrDefault(Constants.FileType.BAM, null) + return getTumorRnaSample(meta).getOrDefault(Constants.FileType.BAM, null) } static public getTumorRnaBai(meta) { - def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.RNA], [:]) - return meta_sample.getOrDefault(Constants.FileType.BAI, null) + return getTumorRnaSample(meta).getOrDefault(Constants.FileType.BAI, null) } static public hasTumorRnaBam(meta) { return getTumorRnaBam(meta) !== null } - static public getNormalDnaBam(meta) { - def meta_sample = meta.getOrDefault([Constants.SampleType.NORMAL, Constants.SequenceType.DNA], [:]) - return meta_sample.getOrDefault(Constants.FileType.BAM, null) + return getNormalDnaSample(meta).getOrDefault(Constants.FileType.BAM, null) } static public getNormalDnaBai(meta) { - def meta_sample = meta.getOrDefault([Constants.SampleType.NORMAL, Constants.SequenceType.DNA], [:]) - return meta_sample.getOrDefault(Constants.FileType.BAI, null) - } - - static public hasNormalDnaBam(meta) { - return getNormalDnaBam(meta) !== null + return getNormalDnaSample(meta).getOrDefault(Constants.FileType.BAI, null) } static public getNormalDnaMarkdupsBam(meta) { - def meta_sample = meta.getOrDefault([Constants.SampleType.NORMAL, Constants.SequenceType.DNA], [:]) - return meta_sample.getOrDefault(Constants.FileType.BAM_MARKDUPS, null) + return getNormalDnaSample(meta).getOrDefault(Constants.FileType.BAM_MARKDUPS, null) } - static public hasNormalDnaMarkdupsBam(meta) { - return getNormalDnaMarkdupsBam(meta) !== null - } - - static public getTumorDnaMarkdupsBam(meta) { - def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.DNA], [:]) - return meta_sample.getOrDefault(Constants.FileType.BAM_MARKDUPS, null) - } - - static public hasTumorDnaMarkdupsBam(meta) { - return getTumorDnaMarkdupsBam(meta) !== null + static public getNormalDnaFastq(meta) { + return getNormalDnaSample(meta).getOrDefault(Constants.FileType.FASTQ, null) } - static public hasDnaMarkdupsBam(meta) { - return hasNormalDnaMarkdupsBam(meta) || hasTumorDnaMarkdupsBam(meta) + static public hasNormalDnaBam(meta) { + return getNormalDnaBam(meta) !== null } - static public getNormalDnaFastq(meta) { - def meta_sample = meta.getOrDefault([Constants.SampleType.NORMAL, Constants.SequenceType.DNA], [:]) - return meta_sample.getOrDefault(Constants.FileType.FASTQ, null) + static public hasNormalDnaMarkdupsBam(meta) { + return getNormalDnaMarkdupsBam(meta) !== null } static public hasNormalDnaFastq(meta) { return getNormalDnaFastq(meta) !== null } - static public getTumorDnaFastq(meta) { - def meta_sample = meta.getOrDefault([Constants.SampleType.TUMOR, Constants.SequenceType.DNA], [:]) - return meta_sample.getOrDefault(Constants.FileType.FASTQ, null) - } - - static public hasTumorDnaFastq(meta) { - return getTumorDnaFastq(meta) !== null + static public hasDnaMarkdupsBam(meta) { + return hasNormalDnaMarkdupsBam(meta) || hasTumorDnaMarkdupsBam(meta) } static public hasDnaFastq(meta) { return hasNormalDnaFastq(meta) || hasTumorDnaFastq(meta) } - static public getRunMode(run_mode, log) { - def run_mode_enum = Utils.getEnumFromString(run_mode, Constants.RunMode) - if (!run_mode_enum) { - def run_modes_str = Utils.getEnumNames(Constants.RunMode).join('\n - ') - log.error "recieved an invalid run mode: '${run_mode}'. Valid options are:\n - ${run_modes_str}" - System.exit(1) - } - return run_mode_enum + + // Status + static public hasTumorDna(meta) { + return hasTumorDnaBam(meta) || hasTumorDnaMarkdupsBam(meta) || hasTumorDnaFastq(meta) } + static public hasNormalDna(meta) { + return hasNormalDnaBam(meta) || hasNormalDnaMarkdupsBam(meta) || hasNormalDnaFastq(meta) + } + // Misc public static getInput(meta, key) { def result @@ -453,79 +525,4 @@ class Utils { } } - public static shallow_copy(obj) { - - return obj.getClass().newInstance(obj) - } - - // Alignment utils. - static public splitGroupIntoSamples(meta_group) { - def sample_entries = [:] - def common_entries = [:] - meta_group.each { key, value -> - - if ((value instanceof java.util.Map) && value.containsKey('sample_id')) { - sample_entries[key] = value - } else { - common_entries[key] = value - } - } - - def meta_samples = [] - sample_entries.each { key, value -> - - def meta_sample = common_entries.getClass().newInstance(common_entries) - meta_sample[key] = value - meta_samples.add(meta_sample) - } - - return meta_samples - } - - static public groupSampleCounts(meta_group) { - return splitGroupIntoSamples(meta_group).size() - } - - static public fastqBasenameWithoutExtension(fastq_path) { - def base_name = fastq_path.split('/')[-1] - def matcher = base_name =~ /^(.*)\.fastq(\.gz|)$/ - assert matcher.find() - return matcher[0][1] - } - - static public readGroupFromFastqPath(fwd_fastq_path, rev_fastq_path) { - def fwd_fastq_no_extension = fastqBasenameWithoutExtension(fwd_fastq_path) - def rev_fastq_no_extension = fastqBasenameWithoutExtension(rev_fastq_path) - - def lane_fastq_pattern = /^(.*)_(.*_L[0-9]{3})_(R[12])_([0-9]{3})$/ - def fwd_matcher = fwd_fastq_no_extension =~ lane_fastq_pattern - def rev_matcher = rev_fastq_no_extension =~ lane_fastq_pattern - - if (fwd_matcher.find()) { - assert rev_matcher.find() - assert fwd_matcher[0][3].equals("R1") - assert rev_matcher[0][3].equals("R2") - - def fwd_read_group = "${fwd_matcher[0][2]}_${fwd_matcher[0][4]}" - def rev_read_group = "${rev_matcher[0][2]}_${rev_matcher[0][4]}" - assert fwd_read_group.equals(rev_read_group) - return fwd_read_group - } - - // Case for when lane fastq files are from picard SamToFastq. - lane_fastq_pattern = /^(.*)_(.*_L[0-9]{3})_([0-9]{3})_([12])$/ - fwd_matcher = fwd_fastq_no_extension =~ lane_fastq_pattern - rev_matcher = rev_fastq_no_extension =~ lane_fastq_pattern - - assert fwd_matcher.find() - assert rev_matcher.find() - assert fwd_matcher[0][4].equals("1") - assert rev_matcher[0][4].equals("2") - - def fwd_read_group = "${fwd_matcher[0][1]}_${fwd_matcher[0][2]}" - def rev_read_group = "${rev_matcher[0][1]}_${rev_matcher[0][2]}" - assert fwd_read_group.equals(rev_read_group) - return fwd_read_group - } - } diff --git a/main.nf b/main.nf index caa57956..65841c42 100644 --- a/main.nf +++ b/main.nf @@ -25,6 +25,8 @@ params.ref_data_genome_fasta = WorkflowMain.getGenomeAttribute(params, params.ref_data_genome_fai = WorkflowMain.getGenomeAttribute(params, 'fai') params.ref_data_genome_dict = WorkflowMain.getGenomeAttribute(params, 'dict') params.ref_data_genome_bwa_index = WorkflowMain.getGenomeAttribute(params, 'bwa_index') +params.ref_data_genome_bwa_index_bseq = WorkflowMain.getGenomeAttribute(params, 'bwa_index_bseq') +params.ref_data_genome_bwa_index_biidx = WorkflowMain.getGenomeAttribute(params, 'bwa_index_biidx') params.ref_data_genome_bwa_index_image = WorkflowMain.getGenomeAttribute(params, 'bwa_index_image') params.ref_data_genome_gridss_index = WorkflowMain.getGenomeAttribute(params, 'gridss_index') diff --git a/modules/local/bwa/mem2/Dockerfile b/modules/local/bwa/mem2/Dockerfile new file mode 100644 index 00000000..0a0bc7ea --- /dev/null +++ b/modules/local/bwa/mem2/Dockerfile @@ -0,0 +1,19 @@ +FROM docker.io/mambaorg/micromamba:1.5.6 + +USER root + +RUN \ + apt-get update && \ + apt-get install -y procps && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +USER mambauser + +RUN \ + micromamba install -y -n base -c bioconda -c conda-forge \ + 'bwa-mem2 ==2.2.1' \ + 'sambamba ==1.0' && \ + micromamba clean --all --yes + +ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa/mem2/main.nf index 062a24ae..ee76a9cc 100644 --- a/modules/local/bwa/mem2/main.nf +++ b/modules/local/bwa/mem2/main.nf @@ -2,18 +2,15 @@ process BWA_MEM2 { tag "${meta.id}" label 'process_high' - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/bwa-mem2:2.2.1--hd03093a_5' : - 'quay.io/biocontainers/bwa-mem2:2.2.1--hd03093a_5' }" + // TODO(SW): create BioContainers multi-package image when appropriate + container 'docker.io/scwatts/bwa-mem2:2.2.1' input: tuple val(meta), path(reads_fwd), path(reads_rev) path genome_fasta - // TODO(SW): The following resourse files are needed from gs://hmf-public/HMFtools-Resources/ref_genome/37: - // + Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64 - // + Homo_sapiens.GRCh37.GATK.illumina.fasta.0123 - // Similarly for ref genome 38. path genome_bwa_index + path genome_bwa_index_bseq + path genome_bwa_index_biidx output: tuple val(meta), path('*.bam'), emit: bam @@ -25,7 +22,6 @@ process BWA_MEM2 { script: def read_group_tag = "@RG\\tID:${meta.read_group}\\tSM:${meta.sample_id}" - // NOTE(MC): Hardcoding bwa-mem2 version since the CLI does not have a --version flag. """ ln -fs \$(find -L ${genome_bwa_index} -type f) ./ @@ -51,7 +47,7 @@ process BWA_MEM2 { cat <<-END_VERSIONS > versions.yml "${task.process}": - bwa-mem2: 2.2.1 + bwa-mem2: \$(bwa-mem2 version 2>/dev/null) sambamba: \$(sambamba --version 2>&1 | egrep '^sambamba' | head -n 1 | awk '{ print \$NF }') END_VERSIONS """ diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index be254c16..9b1121a9 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -10,8 +10,8 @@ process FASTP { val(max_fastq_records) output: - tuple val(meta), path('*_R1.fastp.fastq'), path('*_R2.fastp.fastq'), emit: fastq - path 'versions.yml' , emit: versions + tuple val(meta), path('*_R1.fastp.fastq.gz'), path('*_R2.fastp.fastq.gz'), emit: fastq + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -30,8 +30,8 @@ process FASTP { --disable_adapter_trimming \\ --disable_trim_poly_g \\ --split_by_lines ${4 * max_fastq_records} \\ - --out1 ${meta.sample_id}_${meta.read_group}_R1.fastp.fastq \\ - --out2 ${meta.sample_id}_${meta.read_group}_R2.fastp.fastq + --out1 ${meta.sample_id}_${meta.library_id}_${meta.lane}_R1.fastp.fastq.gz \\ + --out2 ${meta.sample_id}_${meta.library_id}_${meta.lane}_R2.fastp.fastq.gz cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -41,8 +41,8 @@ process FASTP { stub: """ - touch 00{1..4}.${meta.sample_id}_${meta.read_group}_R1.fastp.fastq - touch 00{1..4}.${meta.sample_id}_${meta.read_group}_R2.fastp.fastq + touch 00{1..4}.${meta.sample_id}_${meta.library_id}_${meta.lane}_R1.fastp.fastq.gz + touch 00{1..4}.${meta.sample_id}_${meta.library_id}_${meta.lane}_R2.fastp.fastq.gz echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 0f6f25d7..a26b4111 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -1,22 +1,22 @@ process MARKDUPS { - tag "${meta_bam.id}" + tag "${meta.id}" label 'process_medium' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.1--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-mark-dups:1.1.1--hdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.2--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-mark-dups:1.1.2--hdfd78af_0' }" input: - tuple val(meta_bam), path(bams), path(bais) - val genome_ver + tuple val(meta), path(bams), path(bais) path genome_fasta + val genome_ver path genome_fai path genome_dict path unmap_regions val has_umis output: - tuple val(meta_bam), path('*bam'), path('*bai'), emit: bam + tuple val(meta), path('*bam'), path('*bai'), emit: bam path 'versions.yml' , emit: versions path '*.tsv' @@ -33,7 +33,7 @@ process MARKDUPS { -samtools \$(which samtools) \\ -sambamba \$(which sambamba) \\ \\ - -sample ${meta_bam.sample_id} \\ + -sample ${meta.sample_id} \\ -input_bam ${bams.join(',')} \\ \\ -form_consensus \\ @@ -45,29 +45,29 @@ process MARKDUPS { -ref_genome_version ${genome_ver} \\ \\ -write_stats \\ - -threads 16 \\ + -threads ${task.cpus} \\ \\ - -output_bam ${meta_bam.sample_id}.markdups.bam + -output_bam ${meta.sample_id}.markdups.bam cat <<-END_VERSIONS > versions.yml "${task.process}": markdups: \$(markdups -version | awk '{ print \$NF }') - openjdk: \$(java --version | egrep '^OpenJDK Runtime Environment ' | sed 's/^.*build //' | sed 's/.\$//') sambamba: \$(sambamba --version 2>&1 | egrep '^sambamba' | head -n 1 | awk '{ print \$NF }') samtools: \$(samtools --version 2>&1 | egrep '^samtools\\s' | head -n 1 | sed 's/^.* //') END_VERSIONS """ stub: - def umi_output_files = has_umis ? "touch ${meta_bam.sample_id}.umi_coord_freq.tsv;" + - " touch ${meta_bam.sample_id}.umi_edit_distance.tsv;" + - " touch ${meta_bam.sample_id}.umi_nucleotide_freq.tsv" : '' - """ - touch ${meta_bam.sample_id}.markdups.bam - touch ${meta_bam.sample_id}.markdups.bam.bai - touch ${meta_bam.sample_id}.duplicate_freq.tsv - ${umi_output_files} + touch ${meta.sample_id}.markdups.bam + touch ${meta.sample_id}.markdups.bam.bai + touch ${meta.sample_id}.duplicate_freq.tsv + + if [[ -n "${has_umis}" ]]; then + touch ${meta.sample_id}.umi_coord_freq.tsv + touch ${meta.sample_id}.umi_edit_distance.tsv + touch ${meta.sample_id}.umi_nucleotide_freq.tsv + fi; echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf index 0f620584..f6b238e3 100644 --- a/modules/local/sambamba/index/main.nf +++ b/modules/local/sambamba/index/main.nf @@ -9,8 +9,8 @@ process SAMBAMBA_INDEX { tuple val(meta), path(bam) output: - tuple val(meta), path(bam), path('*bai'), emit: bam - path 'versions.yml' , emit: versions + tuple val(meta), path('*bai'), emit: bai + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when @@ -19,7 +19,7 @@ process SAMBAMBA_INDEX { """ sambamba index \\ --nthreads ${task.cpus} \\ - ${meta.split}.${meta.sample_id}.${meta.read_group}.bam + ${bam} cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -29,7 +29,7 @@ process SAMBAMBA_INDEX { stub: """ - touch ${meta.split}.${meta.sample_id}.${meta.read_group}.bam.bai + touch ${bam}.bai echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ diff --git a/nextflow_schema.json b/nextflow_schema.json index 32e470a8..d75b428d 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -218,6 +218,20 @@ "fa_icon": "far fa-file-code", "hidden": true }, + "ref_data_genome_bwa_index_bseq": { + "type": "string", + "format": "directory-path", + "description": "Path to directory containing reference genome BWA MEM 2 binary sequence index file.", + "fa_icon": "far fa-file-code", + "hidden": true + }, + "ref_data_genome_bwa_index_biidx": { + "type": "string", + "format": "directory-path", + "description": "Path to directory containing reference genome BWA MEM 2 bi-index file.", + "fa_icon": "far fa-file-code", + "hidden": true + }, "ref_data_genome_bwa_index_image": { "type": "string", "format": "file-path", diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index f20a3d24..fb021e91 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -11,6 +11,8 @@ workflow AMBER_PROFILING { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] // Reference data genome_version // channel: [mandatory] genome version @@ -22,19 +24,33 @@ workflow AMBER_PROFILING { // channel: [ versions.yml ] ch_versions = Channel.empty() - // Sort inputs - // channel: [ meta ] - ch_inputs_sorted = ch_inputs - .branch { meta -> + // Select input sources and sort + // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai] + // channel: skip: [ meta ] + ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_bam, + ch_normal_bam, + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + ] + } + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.AMBER_DIR) - runnable: Utils.hasTumorDnaBam(meta) && !has_existing + runnable: tumor_bam && !has_existing skip: true + meta } // Create process input channel // channel: [ meta_amber, tumor_bam, normal_bam, tumor_bai, normal_bai ] ch_amber_inputs = ch_inputs_sorted.runnable - .map { meta -> + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> def meta_amber = [ key: meta.group_id, @@ -42,20 +58,6 @@ workflow AMBER_PROFILING { tumor_id: Utils.getTumorDnaSampleName(meta), ] - def tumor_bam = Utils.getTumorDnaBam(meta) - def tumor_bai = Utils.getTumorDnaBai(meta) - - def normal_bam = [] - def normal_bai = [] - - if (Utils.hasNormalDnaBam(meta)) { - - meta_amber.normal_id = Utils.getNormalDnaSampleName(meta) - normal_bam = Utils.getNormalDnaBam(meta) - normal_bai = Utils.getNormalDnaBai(meta) - - } - [meta_amber, tumor_bam, normal_bam, tumor_bai, normal_bai] } diff --git a/subworkflows/local/bamtools_metrics.nf b/subworkflows/local/bamtools_metrics.nf index 92237b83..ba6aebee 100644 --- a/subworkflows/local/bamtools_metrics.nf +++ b/subworkflows/local/bamtools_metrics.nf @@ -11,6 +11,8 @@ workflow BAMTOOLS_METRICS { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] // Reference data genome_fasta // channel: [mandatory] /path/to/genome_fasta @@ -21,78 +23,55 @@ workflow BAMTOOLS_METRICS { // channel: [ versions.yml ] ch_versions = Channel.empty() - // Sort inputs - // channel: [ meta ] - ch_inputs_sorted = ch_inputs - .branch { meta -> - - def has_tumor_dna = Utils.hasTumorDnaBam(meta) - def has_normal_dna = Utils.hasNormalDnaBam(meta) - - runnable: has_tumor_dna || has_normal_dna + // Sort inputs, separate by tumor and normal + // channel: runnable: [ meta, bam, bai ] + // channel: skip: [ meta ] + ch_inputs_tumor_sorted = ch_tumor_bam + .map { meta, bam, bai -> + return [ + meta, + Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + ] + } + .branch { meta, bam, bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAMTOOLS_TUMOR) + runnable: bam && !has_existing skip: true + meta } - // Flatten into BAM/BAI pairs, select inputs that are eligible to run - // channel: runnable: [ meta_extra, bam, bai ] - // channel: skip: [ meta_extra ] - ch_bams_bais_sorted = ch_inputs_sorted.runnable - .flatMap { meta -> - - def tumor_sample_id = [] - def tumor_bam = [] - def tumor_bai = [] - - def normal_sample_id = [] - def normal_bam = [] - def normal_bai = [] - - - if (Utils.hasTumorDnaBam(meta)) { - tumor_sample_id = Utils.getTumorDnaSampleName(meta) - tumor_bam = Utils.getTumorDnaBam(meta) - tumor_bai = Utils.getTumorDnaBai(meta) - } - - if (Utils.hasNormalDnaBam(meta)) { - normal_sample_id = Utils.getNormalDnaSampleName(meta) - normal_bam = Utils.getNormalDnaBam(meta) - normal_bai = Utils.getNormalDnaBai(meta) - } - + // channel: runnable: [ meta, bam, bai ] + // channel: skip: [ meta ] + ch_inputs_normal_sorted = ch_normal_bam + .map { meta, bam, bai -> return [ - [[key: meta.group_id, *:meta, sample_id: tumor_sample_id, sample_type: 'tumor'], tumor_bam, tumor_bai], - [[key: meta.group_id, *:meta, sample_id: normal_sample_id, sample_type: 'normal'], normal_bam, normal_bai], + meta, + Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), ] } - .branch { meta_extra, bam, bai -> - - def input_key - if (meta_extra.sample_type == 'tumor') { - input_key = Constants.INPUT.BAMTOOLS_TUMOR - } else if (meta_extra.sample_type == 'normal') { - input_key = Constants.INPUT.BAMTOOLS_NORMAL - } else { - assert false - } - - def has_existing = Utils.hasExistingInput(meta_extra, input_key) - - runnable: bam && bai && !has_existing + .branch { meta, bam, bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAMTOOLS_NORMAL) + runnable: bam && !has_existing skip: true - return meta_extra + meta } // Create process input channel // channel: [ meta_bamtools, bam, bai ] - ch_bamtools_inputs = ch_bams_bais_sorted.runnable - .map { meta_extra, bam, bai -> + ch_bamtools_inputs = Channel.empty() + .mix( + ch_inputs_tumor_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bam, bai] }, + ch_inputs_normal_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getNormalDnaSample(meta), 'normal', bam, bai] }, + ) + .map { meta, meta_sample, sample_type, bam, bai -> def meta_bamtools = [ - key: meta_extra.group_id, - id: "${meta_extra.group_id}__${meta_extra.sample_id}", - sample_id: meta_extra.sample_id, - sample_type: meta_extra.sample_type, + key: meta.group_id, + id: "${meta.group_id}_${meta_sample.sample_id}", + sample_id: meta_sample.sample_id, + sample_type: sample_type, ] return [meta_bamtools, bam, bai] @@ -107,29 +86,27 @@ workflow BAMTOOLS_METRICS { ch_versions = ch_versions.mix(BAMTOOLS.out.versions) - // Sort outputs into tumor and normal channels, adding partial skip entries - // channel: [ meta_bamtools, metrics ] - ch_outputs_sorted = Channel.empty() - .mix( - BAMTOOLS.out.metrics, - ch_bams_bais_sorted.skip.map { meta -> [meta, []] }, - ) + // Sort into a tumor and normal channel + ch_bamtools_out = BAMTOOLS.out.metrics .branch { meta_bamtools, metrics -> + assert ['tumor', 'normal'].contains(meta_bamtools.sample_type) tumor: meta_bamtools.sample_type == 'tumor' normal: meta_bamtools.sample_type == 'normal' + placeholder: true } - // Set outputs, restoring original meta, including full skip entries + // Set outputs, restoring original meta + // channel: [ meta, metrics ] ch_somatic_metrics = Channel.empty() .mix( - WorkflowOncoanalyser.restoreMeta(ch_outputs_sorted.tumor, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, + WorkflowOncoanalyser.restoreMeta(ch_bamtools_out.tumor, ch_inputs), + ch_inputs_tumor_sorted.skip.map { meta -> [meta, []] }, ) ch_germline_metrics = Channel.empty() .mix( - WorkflowOncoanalyser.restoreMeta(ch_outputs_sorted.normal, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, + WorkflowOncoanalyser.restoreMeta(ch_bamtools_out.normal, ch_inputs), + ch_inputs_normal_sorted.skip.map { meta -> [meta, []] }, ) emit: diff --git a/subworkflows/local/chord_prediction.nf b/subworkflows/local/chord_prediction.nf index d5f3c187..516917fe 100644 --- a/subworkflows/local/chord_prediction.nf +++ b/subworkflows/local/chord_prediction.nf @@ -34,7 +34,7 @@ workflow CHORD_PREDICTION { ch_inputs_sorted = ch_inputs_selected .branch { meta, purple_dir -> - def has_dna = Utils.hasTumorDnaBam(meta) + def has_dna = Utils.hasTumorDna(meta) def tumor_id def has_smlv_vcf diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index 6fb81e08..322575cc 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -11,6 +11,8 @@ workflow COBALT_PROFILING { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] // Reference data gc_profile // channel: [mandatory] /path/to/gc_profile @@ -22,23 +24,37 @@ workflow COBALT_PROFILING { // channel: [ versions.yml ] ch_versions = Channel.empty() - // Sort inputs + // Select input sources and sort // NOTE(SW): germline mode is not currently supported - // channel: [ meta ] - ch_inputs_sorted = ch_inputs - .branch { meta -> + // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai] + // channel: skip: [ meta ] + ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_bam, + ch_normal_bam, + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + ] + } + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.COBALT_DIR) - runnable_tn: Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) && !has_existing - runnable_to: Utils.hasTumorDnaBam(meta) && !has_existing + runnable_tn: tumor_bam && normal_bam && !has_existing + runnable_to: tumor_bam && !has_existing skip: true + meta } // First set diploid BED input for tumor/normal and tumor only samples // NOTE(SW): since the diploid BED is provided as a channel, I seem to be only able to include via channel ops - // channel: [ meta, diploid_bed ] + // channel: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai, diploid_bed ] ch_inputs_runnable = Channel.empty() .mix( - ch_inputs_sorted.runnable_tn.map { meta -> [meta, []] }, + ch_inputs_sorted.runnable_tn.map { [*it, []] }, ch_inputs_sorted.runnable_to.combine(diploid_bed), ) @@ -46,7 +62,7 @@ workflow COBALT_PROFILING { // channel: sample_data: [ meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai ] // channel: diploid_bed: [ diploid_bed ] ch_cobalt_inputs = ch_inputs_runnable - .multiMap { meta, diploid_bed -> + .multiMap { meta, tumor_bam, tumor_bai, normal_bam, normal_bai, diploid_bed -> def meta_cobalt = [ key: meta.group_id, @@ -54,20 +70,6 @@ workflow COBALT_PROFILING { tumor_id: Utils.getTumorDnaSampleName(meta), ] - def tumor_bam = Utils.getTumorDnaBam(meta) - def tumor_bai = Utils.getTumorDnaBai(meta) - - def normal_bam = [] - def normal_bai = [] - - if (Utils.hasNormalDnaBam(meta)) { - - meta_cobalt.normal_id = Utils.getNormalDnaSampleName(meta) - normal_bam = Utils.getNormalDnaBam(meta) - normal_bai = Utils.getNormalDnaBai(meta) - - } - sample_data: [meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai] diploid_bed: diploid_bed } diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index bd9b5877..bc486322 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -62,7 +62,7 @@ workflow CUPPA_PREDICTION { // (run exclusions currently done basis for presence of normal DNA) def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.CUPPA_DIR) - def has_normal_dna = Utils.hasNormalDnaBam(meta) + def has_normal_dna = Utils.hasNormalDna(meta) def has_runnable_inputs = isofox_dir || (purple_dir && linx_annotation_dir && has_normal_dna) @@ -82,8 +82,8 @@ workflow CUPPA_PREDICTION { id: meta.group_id, ] - def has_tumor_dna = Utils.hasTumorDnaBam(meta) - def has_normal_dna = Utils.hasNormalDnaBam(meta) + def has_tumor_dna = Utils.hasTumorDna(meta) + def has_normal_dna = Utils.hasNormalDna(meta) def has_tumor_rna = Utils.hasTumorRnaBam(meta) def has_dna_inputs = (purple_dir && linx_annotation_dir) diff --git a/subworkflows/local/flagstat_metrics.nf b/subworkflows/local/flagstat_metrics.nf index 256d063d..cd2344a9 100644 --- a/subworkflows/local/flagstat_metrics.nf +++ b/subworkflows/local/flagstat_metrics.nf @@ -10,84 +10,64 @@ include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/samtools/flagstat/main workflow FLAGSTAT_METRICS { take: // Sample data - ch_inputs // channel: [mandatory] [ meta ] + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] main: // Channel for version.yml files // channel: [ versions.yml ] ch_versions = Channel.empty() - // Sort inputs - // channel: [ meta ] - ch_inputs_sorted = ch_inputs - .branch { meta -> - - def has_tumor_dna = Utils.hasTumorDnaBam(meta) - def has_normal_dna = Utils.hasNormalDnaBam(meta) - - runnable: has_tumor_dna || has_normal_dna + // Sort inputs, separate by tumor and normal + // channel: runnable: [ meta, bam, bai ] + // channel: skip: [ meta ] + ch_inputs_tumor_sorted = ch_tumor_bam + .map { meta, bam, bai -> + return [ + meta, + Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + ] + } + .branch { meta, bam, bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.FLAGSTAT_TUMOR) + runnable: bam && !has_existing skip: true + meta } - // Flatten into BAM/BAI pairs, select inputs that are eligible to run - // channel: runnable: [ meta_extra, bam, bai ] - // channel: skip: [ meta_extra ] - ch_bams_bais_sorted = ch_inputs_sorted.runnable - .flatMap { meta -> - - def tumor_sample_id = [] - def tumor_bam = [] - def tumor_bai = [] - - def normal_sample_id = [] - def normal_bam = [] - def normal_bai = [] - - if (Utils.hasTumorDnaBam(meta)) { - tumor_sample_id = Utils.getTumorDnaSampleName(meta) - tumor_bam = Utils.getTumorDnaBam(meta) - tumor_bai = Utils.getTumorDnaBai(meta) - } - - if (Utils.hasNormalDnaBam(meta)) { - normal_sample_id = Utils.getNormalDnaSampleName(meta) - normal_bam = Utils.getNormalDnaBam(meta) - normal_bai = Utils.getNormalDnaBai(meta) - } - + // channel: runnable: [ meta, bam, bai ] + // channel: skip: [ meta ] + ch_inputs_normal_sorted = ch_normal_bam + .map { meta, bam, bai -> return [ - [[key: meta.group_id, *:meta, sample_id: tumor_sample_id, sample_type: 'tumor'], tumor_bam, tumor_bai], - [[key: meta.group_id, *:meta, sample_id: normal_sample_id, sample_type: 'normal'], normal_bam, normal_bai], + meta, + Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), ] } - .branch { meta_extra, bam, bai -> - - def input_key - if (meta_extra.sample_type == 'tumor') { - input_key = Constants.INPUT.BAMTOOLS_TUMOR - } else if (meta_extra.sample_type == 'normal') { - input_key = Constants.INPUT.BAMTOOLS_NORMAL - } else { - assert false - } - - def has_existing = Utils.hasExistingInput(meta_extra, input_key) - - runnable: bam && bai && !has_existing + .branch { meta, bam, bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.FLAGSTAT_NORMAL) + runnable: bam && !has_existing skip: true - return meta_extra + meta } // Create process input channel // channel: [ meta_flagstat, bam, bai ] - ch_flagstat_inputs = ch_bams_bais_sorted.runnable - .map { meta_extra, bam, bai -> + ch_flagstat_inputs = Channel.empty() + .mix( + ch_inputs_tumor_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bam, bai] }, + ch_inputs_normal_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getNormalDnaSample(meta), 'normal', bam, bai] }, + ) + .map { meta, meta_sample, sample_type, bam, bai -> def meta_flagstat = [ - key: meta_extra.group_id, - id: "${meta_extra.group_id}__${meta_extra.sample_id}", - sample_id: meta_extra.sample_id, - sample_type: meta_extra.sample_type, + key: meta.group_id, + id: "${meta.group_id}_${meta_sample.sample_id}", + sample_id: meta_sample.sample_id, + sample_type: sample_type, ] return [meta_flagstat, bam, bai] @@ -100,34 +80,32 @@ workflow FLAGSTAT_METRICS { ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) - // Sort outputs into tumor and normal channels, adding partial skip entries - // channel: [ meta_flagstat, metrics ] - ch_outputs_sorted = Channel.empty() - .mix( - SAMTOOLS_FLAGSTAT.out.flagstat, - ch_bams_bais_sorted.skip.map { meta -> [meta, []] }, - ) - .branch { meta_flagstat, metrics -> + // Sort into a tumor and normal channel + ch_flagstat_out = SAMTOOLS_FLAGSTAT.out.flagstat + .branch { meta_flagstat, flagstat -> + assert ['tumor', 'normal'].contains(meta_flagstat.sample_type) tumor: meta_flagstat.sample_type == 'tumor' normal: meta_flagstat.sample_type == 'normal' + placeholder: true } - // Set outputs, restoring original meta, including full skip entries - ch_somatic_metrics = Channel.empty() + // Set outputs, restoring original meta + // channel: [ meta, flagstat ] + ch_somatic_flagstat = Channel.empty() .mix( - WorkflowOncoanalyser.restoreMeta(ch_outputs_sorted.tumor, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, + WorkflowOncoanalyser.restoreMeta(ch_flagstat_out.tumor, ch_inputs), + ch_inputs_tumor_sorted.skip.map { meta -> [meta, []] }, ) - ch_germline_metrics = Channel.empty() + ch_germline_flagstat = Channel.empty() .mix( - WorkflowOncoanalyser.restoreMeta(ch_outputs_sorted.normal, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, + WorkflowOncoanalyser.restoreMeta(ch_flagstat_out.normal, ch_inputs), + ch_inputs_normal_sorted.skip.map { meta -> [meta, []] }, ) emit: - somatic = ch_somatic_metrics // channel: [ meta, metrics ] - germline = ch_germline_metrics // channel: [ meta, metrics ] + somatic = ch_somatic_flagstat // channel: [ meta, flagstat ] + germline = ch_germline_flagstat // channel: [ meta, flagstat ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index 9a58c34c..71aed28a 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -17,6 +17,8 @@ workflow GRIDSS_SVPREP_CALLING { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] // Reference data genome_fasta // channel: [mandatory] /path/to/genome_fasta @@ -38,16 +40,32 @@ workflow GRIDSS_SVPREP_CALLING { // channel: [ versions.yml ] ch_versions = Channel.empty() - // Sort inputs - // channel: [ meta ] - ch_inputs_sorted = ch_inputs - .branch { meta -> + // Select input sources and sort + // channel: runnable_tn: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] + // channel: runnable_to: [ meta, tumor_bam, tumor_bai ] + // channel: skip: [ meta ] + ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_bam, + ch_normal_bam, + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + ] + } + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIDSS_VCF) - runnable_tn: Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) && !has_existing - runnable_to: Utils.hasTumorDnaBam(meta) && !has_existing + runnable_tn: tumor_bam && normal_bam && !has_existing + runnable_to: tumor_bam && !has_existing + [meta, tumor_bam, tumor_bai] skip: true + meta } // @@ -57,10 +75,10 @@ workflow GRIDSS_SVPREP_CALLING { // channel: [ meta_svprep, bam_tumor, bai_tumor, [] ] ch_svprep_tumor_inputs = Channel.empty() .mix( - ch_inputs_sorted.runnable_to, + ch_inputs_sorted.runnable_to.map { [*it, [], []] }, ch_inputs_sorted.runnable_tn, ) - .map { meta -> + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> def meta_svprep = [ key: meta.group_id, @@ -68,12 +86,9 @@ workflow GRIDSS_SVPREP_CALLING { sample_id: Utils.getTumorDnaSampleName(meta), sample_type: 'tumor', // NOTE(SW): slightly redundant since we have this information then lose it with .mix above - group_size: Utils.hasNormalDnaBam(meta) ? 2 : 1 + group_size: normal_bam ? 2 : 1 ] - def tumor_bam = Utils.getTumorDnaBam(meta) - def tumor_bai = Utils.getTumorDnaBai(meta) - return [meta_svprep, tumor_bam, tumor_bai, []] } @@ -103,10 +118,13 @@ workflow GRIDSS_SVPREP_CALLING { // MODULE: SV Prep (normal) // // Create process input channel - // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_tn // channel: [ meta_svprep, bam_normal, bai_normal, junctions_tumor ] - ch_svprep_normal_inputs = WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs_sorted.runnable_tn) - .map { meta, junctions_tumor -> + ch_svprep_normal_inputs = WorkflowOncoanalyser.groupByMeta( + ch_inputs_sorted.runnable_tn, + // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_tn + WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs_sorted.runnable_tn.map { it[0] }) + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai, junctions_tumor -> def meta_svprep = [ key: meta.group_id, @@ -116,9 +134,6 @@ workflow GRIDSS_SVPREP_CALLING { group_size: 2, // Assumption holds since germline only is not supported and we source from runnable_tn ] - def normal_bam = Utils.getNormalDnaBam(meta) - def normal_bai = Utils.getNormalDnaBai(meta) - return [meta_svprep, normal_bam, normal_bai, junctions_tumor] } @@ -299,13 +314,49 @@ workflow GRIDSS_SVPREP_CALLING { // MODULE: SV Prep depth annotation // // Restore original meta, create process input channel - // channel: tumor/normal: [ meta_svprep, [bams], [bais], vcf, [labels] ] - // channel: tumor only: [ meta_svprep, bam, bai, vcf, label ] - ch_depth_inputs = WorkflowOncoanalyser.restoreMeta(CALL.out.vcf, ch_inputs) - .map { meta, vcf -> + // channel: [ meta, [bams], [bais], vcf, [labels] ] + ch_depth_inputs_tn = WorkflowOncoanalyser.groupByMeta( + ch_inputs_sorted.runnable_tn, + // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_tn + WorkflowOncoanalyser.restoreMeta(CALL.out.vcf, ch_inputs_sorted.runnable_tn.map { it[0] }) + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai, vcf -> + return [ + meta, + [normal_bam, tumor_bam], + [normal_bai, tumor_bai], + vcf, + [Utils.getNormalDnaSampleName(meta), Utils.getTumorDnaSampleName(meta)], + ] + } + + // channel: [ meta, bam, bai, vcf, label ] + ch_depth_inputs_to = WorkflowOncoanalyser.groupByMeta( + ch_inputs_sorted.runnable_to, + // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_to + WorkflowOncoanalyser.restoreMeta(CALL.out.vcf, ch_inputs_sorted.runnable_to.map { it[0] }) + ) + .map { meta, tumor_bam, tumor_bai, vcf -> + return [ + meta, + tumor_bam, + tumor_bai, + vcf, + Utils.getTumorDnaSampleName(meta), + ] + } + + // channel: runnable_tn: [ meta_svprep, [bams], [bais], vcf, [labels] ] + // channel: runnable_to: [ meta_svprep, bam, bai, vcf, label ] + ch_depth_inputs = Channel.empty() + .mix( + ch_depth_inputs_tn, + ch_depth_inputs_to, + ) + .map { d -> - // NOTE(SW): germline only is not currently supported - assert Utils.hasTumorDnaBam(meta) + def meta = d[0] + def fps = d[1..-1] def meta_svprep = [ key: meta.group_id, @@ -313,33 +364,7 @@ workflow GRIDSS_SVPREP_CALLING { tumor_id: Utils.getTumorDnaSampleName(meta) ] - def data = [] - - if (Utils.hasNormalDnaBam(meta)) { - - data = [ - meta_svprep, - [Utils.getNormalDnaBam(meta), Utils.getTumorDnaBam(meta)], - [Utils.getNormalDnaBai(meta), Utils.getTumorDnaBai(meta)], - vcf, - [Utils.getNormalDnaSampleName(meta), Utils.getTumorDnaSampleName(meta)], - ] - - } else if (Utils.hasTumorDnaBam(meta)) { - - data = [ - meta_svprep, - Utils.getTumorDnaBam(meta), - Utils.getTumorDnaBai(meta), - vcf, - Utils.getTumorDnaSampleName(meta), - ] - - } else { - assert false - } - - return data + return [meta_svprep, *fps] } // Add depth annotations to calls diff --git a/subworkflows/local/gripss_filtering.nf b/subworkflows/local/gripss_filtering.nf index 7913be75..90f0cbd2 100644 --- a/subworkflows/local/gripss_filtering.nf +++ b/subworkflows/local/gripss_filtering.nf @@ -53,7 +53,7 @@ workflow GRIPSS_FILTERING { // channel: skip: [ meta ] ch_inputs_germline_sorted = ch_inputs_sorted.runnable .branch { meta, gridss_vcf -> - def has_tumor_normal = Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) + def has_tumor_normal = Utils.hasTumorDna(meta) && Utils.hasNormalDna(meta) def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIPSS_VCF_NORMAL) runnable: has_tumor_normal && !has_existing @@ -98,7 +98,7 @@ workflow GRIPSS_FILTERING { // channel: skip: [ meta ] ch_inputs_somatic_sorted = ch_inputs_sorted.runnable .branch { meta, gridss_vcf -> - def has_tumor = Utils.hasTumorDnaBam(meta) + def has_tumor = Utils.hasTumorDna(meta) def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIPSS_VCF_TUMOR) runnable: has_tumor && !has_existing @@ -117,7 +117,7 @@ workflow GRIPSS_FILTERING { tumor_id: Utils.getTumorDnaSampleName(meta), ] - if (Utils.hasNormalDnaBam(meta)) { + if (Utils.hasNormalDna(meta)) { meta_gripss.normal_id = Utils.getNormalDnaSampleName(meta) } diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index 37980d18..eb8ac01d 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -14,6 +14,8 @@ workflow LILAC_CALLING { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] ch_purple // channel: [mandatory] [ meta, purple_dir ] // Reference data @@ -28,42 +30,29 @@ workflow LILAC_CALLING { // channel: [ versions.yml ] ch_versions = Channel.empty() - // Sort inputs - // channel: [ meta ] - ch_inputs_sorted = ch_inputs - .branch { meta -> - - def has_tumor_dna = Utils.hasTumorDnaBam(meta) - def has_normal_dna = Utils.hasNormalDnaBam(meta) + // Select input sources and sort for DNA BAMs + // channel: runnable: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] + // channel: skip: [ meta ] + ch_dna_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_bam, + ch_normal_bam, + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + ] + } + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.LILAC_DIR) - runnable: (has_tumor_dna || has_normal_dna) && !has_existing + runnable: (tumor_bam || normal_bam) && !has_existing skip: true - } - - // Create channel for DNA BAMs - // channel: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] - ch_dna_inputs = ch_inputs_sorted.runnable - .map { meta -> - - def tumor_bam = [] - def tumor_bai = [] - - def normal_bam = [] - def normal_bai = [] - - if (Utils.hasTumorDnaBam(meta)) { - tumor_bam = Utils.getTumorDnaBam(meta) - tumor_bai = Utils.getTumorDnaBai(meta) - } - - if (Utils.hasNormalDnaBam(meta)) { - normal_bam = Utils.getNormalDnaBam(meta) - normal_bai = Utils.getNormalDnaBai(meta) - } - - return [meta, tumor_bam, tumor_bai, normal_bam, normal_bai] + meta } // Realign reads mapping to HLA regions and homologus regions if using reference genome with ALT contigs @@ -75,11 +64,11 @@ workflow LILAC_CALLING { // Flatten into BAM/BAI pairs, select inputs that are eligible to run // channel: runnable: [ meta_extra, bam, bai ] // channel: skip: [ meta_extra ] - ch_realign_inputs_sorted = ch_dna_inputs + ch_realign_inputs_sorted = ch_dna_inputs_sorted.runnable .flatMap { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - def tumor_sample_id = Utils.hasTumorDnaBam(meta) ? Utils.getTumorDnaSampleName(meta) : [] - def normal_sample_id = Utils.hasNormalDnaBam(meta) ? Utils.getNormalDnaSampleName(meta) : [] + def tumor_sample_id = Utils.hasTumorDna(meta) ? Utils.getTumorDnaSampleName(meta) : [] + def normal_sample_id = Utils.hasNormalDna(meta) ? Utils.getNormalDnaSampleName(meta) : [] return [ [[key: meta.group_id, *:meta, sample_id: tumor_sample_id, sample_type: 'tumor'], tumor_bam, tumor_bai], @@ -168,7 +157,7 @@ workflow LILAC_CALLING { } else { // channel: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] - ch_dna_inputs_ready = ch_dna_inputs + ch_dna_inputs_ready = ch_dna_inputs_sorted.runnable } @@ -205,11 +194,11 @@ workflow LILAC_CALLING { id: meta.group_id, ] - if (Utils.hasTumorDnaBam(meta)) { + if (Utils.hasTumorDna(meta)) { meta_lilac.tumor_id = Utils.getTumorDnaSampleName(meta) } - if (Utils.hasNormalDnaBam(meta)) { + if (Utils.hasNormalDna(meta)) { meta_lilac.normal_id = Utils.getNormalDnaSampleName(meta) } @@ -240,7 +229,7 @@ workflow LILAC_CALLING { ch_outputs = Channel.empty() .mix( WorkflowOncoanalyser.restoreMeta(LILAC.out.lilac_dir, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ch_dna_inputs_sorted.skip.map { meta -> [meta, []] }, ) emit: diff --git a/subworkflows/local/linx_annotation.nf b/subworkflows/local/linx_annotation.nf index e5c9e26a..5ae97275 100644 --- a/subworkflows/local/linx_annotation.nf +++ b/subworkflows/local/linx_annotation.nf @@ -53,7 +53,7 @@ workflow LINX_ANNOTATION { def tumor_id = Utils.getTumorDnaSampleName(meta) - def has_tumor_normal = Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) + def has_tumor_normal = Utils.hasTumorDna(meta) && Utils.hasNormalDna(meta) def has_sv_germline_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.germline.vcf.gz") def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) @@ -99,7 +99,7 @@ workflow LINX_ANNOTATION { ch_inputs_somatic_sorted = ch_inputs_sorted.runnable .branch { meta, purple_dir -> - def has_tumor = Utils.hasTumorDnaBam(meta) + def has_tumor = Utils.hasTumorDna(meta) def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) runnable: has_tumor && !has_existing diff --git a/subworkflows/local/pave_annotation.nf b/subworkflows/local/pave_annotation.nf index 98bbd273..ea15ed27 100644 --- a/subworkflows/local/pave_annotation.nf +++ b/subworkflows/local/pave_annotation.nf @@ -51,7 +51,7 @@ workflow PAVE_ANNOTATION { def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PAVE_VCF_NORMAL) - runnable: Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) && sage_vcf && !has_existing + runnable: Utils.hasTumorDna(meta) && Utils.hasNormalDna(meta) && sage_vcf && !has_existing skip: true return meta } @@ -105,7 +105,7 @@ workflow PAVE_ANNOTATION { def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PAVE_VCF_TUMOR) - runnable: Utils.hasTumorDnaBam(meta) && sage_vcf && !has_existing + runnable: Utils.hasTumorDna(meta) && sage_vcf && !has_existing skip: true return meta } diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index b7df9251..fc7b724f 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -2,6 +2,11 @@ // Prepare reference data as required // + +// NOTE(SW): BWA MEM2 indexes are required and are not created +// TODO(SW): consider removing index creation since it's unlikely to be used, replace with documentation + + include { SAMTOOLS_FAIDX } from '../../modules/nf-core/samtools/faidx/main' include { SAMTOOLS_DICT } from '../../modules/nf-core/samtools/dict/main' include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' @@ -94,6 +99,10 @@ workflow PREPARE_REFERENCE { } } + // Explicitly create value channels for BWA MEM2 index files + ch_genome_bwa_index_bseq = Channel.value(params.ref_data_genome_bwa_index_bseq) + ch_genome_bwa_index_biidx = Channel.value(params.ref_data_genome_bwa_index_biidx) + // // Set VIRUSBreakend database path / stage, unpack if required // @@ -168,6 +177,8 @@ workflow PREPARE_REFERENCE { genome_fai = ch_genome_fai // path: genome_fai genome_dict = ch_genome_dict // path: genome_dict genome_bwa_index = ch_genome_bwa_index // path: genome_bwa_index + genome_bwa_index_bseq = ch_genome_bwa_index_bseq // path: genome_bwa_index_bseq + genome_bwa_index_biidx = ch_genome_bwa_index_biidx // path: genome_bwa_index_biidx genome_bwa_index_image = ch_genome_bwa_index_image // path: genome_bwa_index_image genome_gridss_index = ch_genome_gridss_index // path: genome_gridss_index genome_version = params.ref_data_genome_version // val: genome_version diff --git a/subworkflows/local/purple_calling.nf b/subworkflows/local/purple_calling.nf index 3070cc1e..182b460a 100644 --- a/subworkflows/local/purple_calling.nf +++ b/subworkflows/local/purple_calling.nf @@ -102,7 +102,7 @@ workflow PURPLE_CALLING { tumor_id: Utils.getTumorDnaSampleName(meta), ] - if (Utils.hasNormalDnaBam(meta)) { + if (Utils.hasNormalDna(meta)) { meta_purple.normal_id = Utils.getNormalDnaSampleName(meta) } diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index bee3cdbd..809e9982 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -1,301 +1,234 @@ -include { BWA_MEM2 } from '../../modules/local/bwa/mem2/main' +include { BWA_MEM2 } from '../../modules/local/bwa/mem2/main' include { FASTP } from '../../modules/local/fastp/main' include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' -include { STAR } from '../../modules/local/star/main' workflow READ_ALIGNMENT { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - genome_fasta - genome_bwa_index - max_fastq_records + // Sample data + ch_inputs // channel: [mandatory] [ meta ] - main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // channel: [ group_id, sample_count ] - ch_sample_counts = ch_inputs.map { meta -> [meta.group_id, Utils.groupSampleCounts(meta)] } - - // channel: [ meta ] (One sample per record). - ch_meta_samples = ch_inputs.flatMap { meta -> Utils.splitGroupIntoSamples(meta) } - - // Sort inputs - // channel: [ meta ] (One sample per record). - ch_meta_samples_sorted = ch_meta_samples - .branch { meta -> - runnable_fastq: Utils.hasDnaFastq(meta) - skip: true - } - - // STAR - // TODO(SW): implement inputs - // ch_star_inputs = Channel.of([[id: 'foo'], []]) - // STAR( - // ch_star_inputs, - // // TODO(SW): include reference files - // ) - // TODO(SW): implement outputs - ch_star_outputs = Channel.empty() - - // BWA MEM2 - // channel: [ sample_key, fastq_pair_count ] - ch_sample_fastq_pair_count = ch_meta_samples_sorted.runnable_fastq.map { meta_sample -> - - def sample_key = Utils.shallow_copy(meta_sample) - def fastq_pair_count = 0 - meta_sample.each { key, value -> - - if ((value instanceof java.util.Map) && value.containsKey('sample_id')) { - sample_key['sample_key'] = key - sample_key['sample_id'] = value.sample_id - sample_key.remove(key) - - fastq_pair_count = value[Constants.FileType.FASTQ].toString().tokenize(';').size() / 2 - } - } + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_bwa_index // channel: [mandatory] /path/to/genome_bwa_index_dir/ + genome_bwa_index_bseq // channel: [mandatory] /path/to/genome_bwa_index_binary_seq + genome_bwa_index_biidx // channel: [mandatory] /path/to/genome_bwa_index_bi-index - [sample_key, fastq_pair_count] - } + // Params + max_fastq_records // numeric: [mandatory] max number of FASTQ records per split - // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] - ch_fastq_pairs = ch_meta_samples_sorted.runnable_fastq - .flatMap { meta -> - - def sample_key = Constants.DNA_SAMPLE_KEYS.find { key -> meta.containsKey(key) } - if (sample_key === null) { - log.error "No DNA sample found" - System.exit(1) + main: + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Sort inputs, separate by tumor and normal + // channel: [ meta ] + ch_inputs_tumor_sorted = ch_inputs + .branch { meta -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_TUMOR) + runnable: Utils.hasTumorDnaFastq(meta) && !has_existing + skip: true } - def sample_id = meta[sample_key]['sample_id'] - def fastq_files = meta[sample_key][Constants.FileType.FASTQ].toString().tokenize(';') - - def meta_fastq_common = [id: "${meta.group_id}__${sample_id}"] - meta.each { key, value -> - - if (key === sample_key) { - return - } + ch_inputs_normal_sorted = ch_inputs + .branch { meta -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_NORMAL) + runnable: Utils.hasNormalDnaFastq(meta) && !has_existing + skip: true + } - meta_fastq_common[key] = meta[key] + // Create FASTQ input channel + // channel: [ meta_fastq, fastq_fwd, fastq_rev ] + ch_fastq_inputs = Channel.empty() + .mix( + ch_inputs_tumor_sorted.runnable.map { meta -> [meta, Utils.getTumorDnaSample(meta), 'tumor'] }, + ch_inputs_normal_sorted.runnable.map { meta -> [meta, Utils.getNormalDnaSample(meta), 'normal'] }, + ) + .flatMap { meta, meta_sample, sample_type -> + meta_sample + .getAt(Constants.FileType.FASTQ) + .collect { key, fps -> + def (library_id, lane) = key + + def meta_fastq = [ + key: meta.group_id, + id: "${meta.group_id}_${meta_sample.sample_id}", + sample_id: meta_sample.sample_id, + library_id: library_id, + lane: lane, + sample_type: sample_type, + ] + + return [meta_fastq, fps['fwd'], fps['rev']] + } } - meta_fastq_common['sample_key'] = sample_key - meta_fastq_common['sample_id'] = sample_id - def fastq_pairs = [] - for (i = 0; i < fastq_files.size(); i += 2) { - def reads_fwd = fastq_files[i] - def reads_rev = fastq_files[i + 1] + // + // MODULE: fastp + // + // Split FASTQ into chunks if requested for distributed processing + // channel: [ meta_fastq_ready, fastq_fwd, fastq_fwd ] + ch_fastqs_ready = Channel.empty() + if (max_fastq_records > 0) { - def meta_fastq = Utils.shallow_copy(meta_fastq_common) - meta_fastq['read_group'] = Utils.readGroupFromFastqPath(reads_fwd, reads_rev) + // Run process + FASTP( + ch_fastq_inputs, + max_fastq_records, + ) - fastq_pairs.add([meta_fastq, reads_fwd, reads_rev]) - } + ch_versions = ch_versions.mix(FASTP.out.versions) - fastq_pairs - } + // Prepare outputs within conditional block + ch_fastqs_ready = FASTP.out.fastq + .flatMap { meta_fastq, reads_fwd, reads_rev -> - // Split fastq files using fastp. - // channel: [ meta_fastq, reads_fwd_fastqs, reads_rev_fastqs ] - ch_split_fastq_pairs = Channel.empty() - if (max_fastq_records > 0) { - FASTP( - ch_fastq_pairs, - max_fastq_records, - ) + def data = [reads_fwd, reads_rev] + .transpose() + .collect { fwd, rev -> - ch_versions = ch_versions.mix(FASTP.out.versions) + def split_fwd = fwd.name.replaceAll('\\..+$', '') + def split_rev = rev.name.replaceAll('\\..+$', '') - ch_split_fastq_pairs = FASTP.out.fastq - } else { - ch_split_fastq_pairs = ch_fastq_pairs.map { fastq_pair -> [fastq_pair[0], [fastq_pair[1]], [fastq_pair[2]]] } - } + assert split_fwd == split_rev - // channel: [ sample_key, fastq_pair_split_count ] - ch_sample_fastq_pair_split_count = ch_sample_fastq_pair_count - .cross( - ch_split_fastq_pairs.map { split_fastq_pairs -> + // NOTE(SW): split allows meta_fastq_ready to be unique, which is required during reunite below + def meta_fastq_ready = [ + *:meta_fastq, + id: "${meta_fastq.id}_${split_fwd}", + split: split_fwd, + ] - def meta_sample = split_fastq_pairs[0] - def sample_key = Utils.shallow_copy(meta_sample) - sample_key.remove('id') - sample_key.remove('read_group') - sample_key.remove(meta_sample.sample_key) + return [meta_fastq_ready, fwd, rev] + } - [sample_key, split_fastq_pairs[1].size()] - } - ) - .map { count_tuple, split_count_tuple -> - def sample_key = count_tuple[0] - def count = count_tuple[1].intValue() - def split_count = split_count_tuple[1] + return data + } - tuple(groupKey(sample_key, count), sample_key, split_count) - } - .groupTuple() - .map { group_key, sample_keys, split_counts -> + } else { - [sample_keys[0], split_counts.sum()] - } + ch_fastqs_ready = ch_fastq_inputs + .map { meta_fastq, fastq_fwd, fastq_rev -> - // Create inputs for bwa mem. - // channel: [ meta_fastq, reads_fwd_fastq, reads_rev_fastq ] - ch_bwa_mem_inputs = ch_split_fastq_pairs.flatMap { fastq -> - def meta = fastq[0] - def fwd_reads = fastq[1] - def rev_reads = fastq[2] - - // Pair up the reads. - def read_pairs = [:] - if (fwd_reads.size() == 1) { - read_pairs[""] = ["000", fwd_reads[0], rev_reads[0]] - } else { - fwd_reads.each { fastq_path -> - - def base_name = fastq_path.getFileName().toString() - def pattern = /^(\d+)\.(.+)_R[12]\.fastp\.fastq$/ - def matcher = base_name =~ pattern - assert matcher.find() - def split = matcher[0][1] - def key = "${split}.${matcher[0][2]}" - assert !read_pairs.containsKey(key) - read_pairs[key] = [split, fastq_path] - } + def meta_fastq_ready = [ + *:meta_fastq, + split: null, + ] - rev_reads.each { fastq_path -> + return [meta_fastq_ready, fastq_fwd, fastq_rev] + } - def base_name = fastq_path.getFileName().toString() - def pattern = /^(.+)_R[12]\.fastp\.fastq$/ - def matcher = base_name =~ pattern - assert matcher.find() - def key = matcher[0][1] - assert read_pairs.containsKey(key) - read_pairs[key].add(fastq_path) - } } - def fastqs = [] - read_pairs.values().each { split_fastq_pair -> + // + // MODULE: BWA-MEM2 + // + // Create process input channel + // channel: [ meta_bwa, fastq_fwd, fastq_rev ] + ch_bwa_inputs = ch_fastqs_ready + .map { meta_fastq_ready, fastq_fwd, fastq_rev -> - meta_fastq = Utils.shallow_copy(meta) - meta_fastq['split'] = split_fastq_pair[0] + def meta_bwa = [ + *:meta_fastq_ready, - fastqs.add([meta_fastq, split_fastq_pair[1], split_fastq_pair[2]]) - } - fastqs - } + // TODO(SW): understand target format + read_group: "${meta_fastq_ready.sample_id}.${meta_fastq_ready.library_id}.${meta_fastq_ready.lane}", - // channel: [ meta_fastq, bam ] - BWA_MEM2( - ch_bwa_mem_inputs, - genome_fasta, - genome_bwa_index, - ) - ch_versions = ch_versions.mix(BWA_MEM2.out.versions) + ] - // channel: [ meta_fastq, bam, bai ] - SAMBAMBA_INDEX( - BWA_MEM2.out.bam, - ) + return [meta_bwa, fastq_fwd, fastq_rev] - ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) + } - // Merge all bam records for a single sample into a singlke record. - // channel: [ meta ] (One sample per meta record). - ch_merged_bam_samples = ch_sample_fastq_pair_split_count - .cross( - SAMBAMBA_INDEX.out.bam - .map { bam -> + // Run process + BWA_MEM2( + ch_bwa_inputs, + genome_fasta, + genome_bwa_index, + genome_bwa_index_bseq, + genome_bwa_index_biidx, + ) - def meta_bam = bam[0] - def sample_key = Utils.shallow_copy(meta_bam) - sample_key.remove('id') - sample_key.remove(meta_bam.sample_key) - sample_key.remove('read_group') - sample_key.remove('split') + ch_versions = ch_versions.mix(BWA_MEM2.out.versions) - [sample_key, bam] - } + // + // MODULE: Sambamba index + // + SAMBAMBA_INDEX( + BWA_MEM2.out.bam, ) - .map { count_tuple, bam_tuple -> - def sample_key = count_tuple[0] - def count = count_tuple[1] - def bam = bam_tuple[1] - - tuple(groupKey(sample_key, count), bam) - } - .groupTuple() - .map { group_key, bams -> + ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) - def first_meta_bam = bams[0][0] - def sample_key = first_meta_bam.sample_key + // Combine BAMs and BAIs + ch_bams_flat = Channel.empty() + .mix( + BWA_MEM2.out.bam, + SAMBAMBA_INDEX.out.bai + ) + .groupTuple(size: 2) + .map { it.flatten() } - def bam_files = [] - def bai_files = [] - def meta_bam = Utils.shallow_copy(first_meta_bam) - meta_bam.remove(sample_key) - meta_bam.remove('sample_key') - meta_bam.remove('sample_id') - meta_bam.remove('read_group') - meta_bam.remove('split') - meta_bam[sample_key] = [sample_id: first_meta_bam.sample_id] - meta_bam[sample_key][Constants.FileType.BAM_MARKDUPS] = bam_files - meta_bam[sample_key][Constants.FileType.BAI_MARKDUPS] = bai_files + // Reunite BAMs + // First, count expected BAMs per sample for non-blocking groupTuple op + ch_sample_fastq_counts = ch_bwa_inputs + .map { meta_bwa, reads_fwd, reads_rev -> - bams.each { bam -> + def meta_count = [ + key: meta_bwa.key, + sample_type: meta_bwa.sample_type, + ] - bam_files.add(bam[1]) - bai_files.add(bam[2]) + return [meta_count, meta_bwa] } + .groupTuple() + .map { meta_count, meta_bwas -> return [meta_count, meta_bwas.size()] } - meta_bam - } + // Now, group with expected size then sort into tumor and normal channels + ch_bams_united = ch_sample_fastq_counts + .cross( + // First element to match meta_count above for `cross` + ch_bams_flat.map { meta_bwa, bam, bai -> [[key: meta_bwa.key, sample_type: meta_bwa.sample_type], bam, bai] } + ) + .map { count_tuple, bam_tuple -> - // Merge back in skipped meta entries. - // channel: [ meta ] (One sample per meta record). - ch_all_samples = Channel.empty() - .mix( - ch_merged_bam_samples, - ch_meta_samples_sorted.skip, - ) + def group_size = count_tuple[1] + def (meta_bam, bam, bai) = bam_tuple - // Merge individual sample records back into group records without blocking for the whole channel to be processed. - // channel: [ meta_bam ] - ch_bwa_outputs = ch_sample_counts - .cross( - ch_all_samples.map { meta -> [meta.group_id, meta] } - ) - .map { count_tuple, meta_tuple -> - def group_id = count_tuple[0] - def count = count_tuple[1] - def meta = meta_tuple[1] - - tuple(groupKey(group_id, count), meta) - } - .groupTuple() - .map { group_key, meta_samples -> + def meta_group = [ + *:meta_bam, + ] - def meta_group = [:] - meta_samples.each { meta_sample -> - - meta_sample.each { key, value -> meta_group[key] = value } + return tuple(groupKey(meta_group, group_size), bam, bai) + } + .groupTuple() + .branch { meta_group, bams, bais -> + assert ['tumor', 'normal'].contains(meta_group.sample_type) + tumor: meta_group.sample_type == 'tumor' + normal: meta_group.sample_type == 'normal' + placeholder: true } - meta_group - } + // Set outputs, restoring original meta + // channel: [ meta, [bam, ...], [bai, ...] ] + ch_bam_tumor_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_bams_united.tumor, ch_inputs), + ch_inputs_tumor_sorted.skip.map { meta -> [meta, [], []] }, + ) + + ch_bam_normal_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_bams_united.normal, ch_inputs), + ch_inputs_normal_sorted.skip.map { meta -> [meta, [], []] }, + ) emit: - dna = ch_bwa_outputs // channel: [ meta ] - // TODO(SW): RNA alignment. - rna = ch_star_outputs // channel: [ meta, bam_rna ] - versions = ch_versions // channel: [ versions.yml ] + dna_tumor = ch_bam_tumor_out // channel: [ meta, [bam, ...], [bai, ...] ] + dna_normal = ch_bam_normal_out // channel: [ meta, [bam, ...], [bai, ...] ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/read_processing.nf b/subworkflows/local/read_processing.nf index bdd71a5a..d3cef837 100644 --- a/subworkflows/local/read_processing.nf +++ b/subworkflows/local/read_processing.nf @@ -1,140 +1,115 @@ -include { MARKDUPS } from '../../modules/local/markdups/main' +include { MARKDUPS } from '../../modules/local/markdups/main' workflow READ_PROCESSING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_dna_bams // channel: [mandatory] [ meta, bam_dna ] - ch_rna_bams // channel: [mandatory] [ meta, bam_rna ] - genome_ver - genome_fasta - genome_fai - genome_dict - unmap_regions - has_umis + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_dna_tumor // channel: [mandatory] [ meta, [bam, ...], [bai, ...] ] + ch_dna_normal // channel: [mandatory] [ meta, [bam, ...], [bai, ...] ] - main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // channel: [ group_id, sample_count ] - ch_sample_counts = ch_inputs.map { meta -> [meta.group_id, Utils.groupSampleCounts(meta)] } - - // channel: [ meta ] (One sample per record). - ch_meta_samples = ch_dna_bams.flatMap { meta -> Utils.splitGroupIntoSamples(meta) } + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_ver // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict + unmap_regions // channel: [mandatory] /path/to/unmap_regions - // Sort inputs - // channel: [ meta ] (One sample per record). - ch_meta_samples_sorted = ch_meta_samples - .branch { meta -> - runnable: Utils.hasDnaMarkdupsBam(meta) - skip: true - } + // Params + has_umis // boolean: [mandatory] UMI processing flag - // MarkDups - // Prepare input to markdups process. - // channel: [ meta_bam, bams, bais ] - ch_markdups_inputs = ch_meta_samples_sorted.runnable - .map { meta_sample -> - - def meta_bam = Utils.shallow_copy(meta_sample) - def bams = [] - def bais = [] - meta_sample.each { key, value -> - - if ((value instanceof java.util.Map) && value.containsKey('sample_id')) { - meta_bam['sample_id'] = value.sample_id - meta_bam['sample_key'] = key - bams = value[Constants.FileType.BAM_MARKDUPS] - bais = value[Constants.FileType.BAI_MARKDUPS] - } + main: + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select and sort input sources, separating bytumor and normal + // channel: runnable: [ meta, bams, bais ] + // channel: skip: [ meta ] + ch_inputs_tumor_sorted = ch_dna_tumor + .map { meta, bams, bais -> + return [ + meta, + Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_TUMOR) ? [Utils.getInput(meta, Constants.INPUT.BAM_DNA_TUMOR)] : bams, + Utils.hasExistingInput(meta, Constants.INPUT.BAI_DNA_TUMOR) ? [Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR)] : bais, + ] } - - meta_bam['id'] = "${meta_bam.group_id}__${meta_bam.sample_id}" - - if (!(bams instanceof Collection)) { - bams = [bams] + .branch { meta, bams, bais -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR) + runnable: bams && !has_existing + skip: true + return meta } - if (!(bais instanceof Collection)) { - bais = [bais] + ch_inputs_normal_sorted = ch_dna_normal + .map { meta, bams, bais -> + return [ + meta, + Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_NORMAL) ? [Utils.getInput(meta, Constants.INPUT.BAM_DNA_NORMAL)] : bams, + Utils.hasExistingInput(meta, Constants.INPUT.BAI_DNA_NORMAL) ? [Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL)] : bais, + ] + } + .branch { meta, bams, bais -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL) + runnable: bams && !has_existing + skip: true + return meta } - [meta_bam, bams, bais] - } - - // channel: [ meta_bam, bam, bai ] - MARKDUPS( - ch_markdups_inputs, - genome_ver, - genome_fasta, - genome_fai, - genome_dict, - unmap_regions, - has_umis, - ) - - ch_versions = ch_versions.mix(MARKDUPS.out.versions) - - // Update sample information. - // channel: [ meta ] (One sample per meta record). - ch_bam_samples = MARKDUPS.out.bam.map { bam -> - - def meta_bam = bam[0] - - def meta = Utils.shallow_copy(meta_bam) - meta.remove('id') - meta.remove('sample_id') - meta.remove('sample_key') - - def sample = [sample_id: meta_bam.sample_id] - sample[Constants.FileType.BAM] = bam[1] - sample[Constants.FileType.BAI] = bam[2] - meta[meta_bam.sample_key] = sample - - meta - } - - // Merge back in skipped meta entries. - // channel: [ meta ] (One sample per meta record). - ch_all_samples = Channel.empty() - .mix( - ch_bam_samples, - ch_meta_samples_sorted.skip, - ) + // Create process input channel + // channel: [ meta_markdups, bam, bai ] + ch_markdups_inputs = Channel.empty() + .mix( + ch_inputs_tumor_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bam, bai] }, + ch_inputs_normal_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getNormalDnaSample(meta), 'normal', bam, bai] }, + ) + .map { meta, meta_sample, sample_type, bam, bai -> + + def meta_markdups = [ + key: meta.group_id, + id: "${meta.group_id}_${meta_sample.sample_id}", + sample_id: meta_sample.sample_id, + sample_type: sample_type, + ] + + return [meta_markdups, bam, bai] + } - // Merge individual sample records back into group records without blocking for the whole channel to be processed. - // channel: [ meta_bam ] - ch_markduplicates_dna_out = ch_sample_counts - .cross( - ch_all_samples.map { meta -> [meta.group_id, meta] } + // Run process + MARKDUPS( + ch_markdups_inputs, + genome_fasta, + genome_ver, + genome_fai, + genome_dict, + unmap_regions, + has_umis, ) - .map { count_tuple, meta_tuple -> - - def group_id = count_tuple[0] - def count = count_tuple[1] - def meta = meta_tuple[1] - - tuple(groupKey(group_id, count), meta) - } - .groupTuple() - .map { group_key, meta_samples -> - - def meta_group = [:] - meta_samples.each { meta_sample -> - meta_sample.each { key, value -> meta_group[key] = value } + // Sort into a tumor and normal channel + ch_markdups_out = MARKDUPS.out.bam + .branch { meta_markdups, bam, bai -> + assert ['tumor', 'normal'].contains(meta_markdups.sample_type) + tumor: meta_markdups.sample_type == 'tumor' + normal: meta_markdups.sample_type == 'normal' + placeholder: true } - meta_group - } + // Set outputs, restoring original meta + // channel: [ meta, bam, bai ] + ch_bam_tumor_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_markdups_out.tumor, ch_inputs), + ch_inputs_tumor_sorted.skip.map { meta -> [meta, [], []] }, + ) - // TODO(SW): implement outputs - ch_markduplicates_rna_out = Channel.empty() + ch_bam_normal_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_markdups_out.normal, ch_inputs), + ch_inputs_normal_sorted.skip.map { meta -> [meta, [], []] }, + ) emit: - dna = ch_markduplicates_dna_out // channel: [ meta ] - rna = ch_markduplicates_rna_out // channel: [ meta, bam_rna ] - versions = ch_versions // channel: [ versions.yml ] + dna_tumor = ch_bam_tumor_out // channel: [ meta, bam, bai ] + dna_normal = ch_bam_normal_out // channel: [ meta, bam, bai ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/sage_append.nf b/subworkflows/local/sage_append.nf index 342069b1..29a9c438 100644 --- a/subworkflows/local/sage_append.nf +++ b/subworkflows/local/sage_append.nf @@ -104,7 +104,7 @@ workflow SAGE_APPEND { .branch { meta, purple_dir -> def tumor_dna_id = Utils.getTumorDnaSampleName(meta) - def has_tumor_dna = Utils.hasTumorDnaBam(meta) + def has_tumor_dna = Utils.hasTumorDna(meta) def has_tumor_rna = Utils.hasTumorRnaBam(meta) def has_smlv_somatic = file(purple_dir).resolve("${tumor_dna_id}.purple.somatic.vcf.gz") def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_APPEND_VCF_TUMOR) diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index 5c05a511..cdec723b 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -12,6 +12,8 @@ workflow SAGE_CALLING { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] // Reference data genome_fasta // channel: [mandatory] /path/to/genome_fasta @@ -33,31 +35,47 @@ workflow SAGE_CALLING { ch_versions = Channel.empty() // Sort inputs - // channel: [ meta ] - ch_inputs_sorted = ch_inputs - .branch { meta -> - runnable: Utils.hasTumorDnaBam(meta) + // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] + // channel: skip: [ meta ] + ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_bam, + ch_normal_bam, + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + ] + } + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + runnable: tumor_bam skip: true + meta } // // MODULE: SAGE germline // // Select inputs that are eligible to run - // channel: [ meta ] + // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] + // channel: skip: [ meta ] ch_inputs_germline_sorted = ch_inputs_sorted.runnable - .branch { meta -> - def has_tumor_normal = Utils.hasTumorDnaBam(meta) && Utils.hasNormalDnaBam(meta) + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + def has_tumor_normal = tumor_bam && normal_bam def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_VCF_NORMAL) runnable: has_tumor_normal && !has_existing skip: true + meta } // Create process input channel - // channel: [ meta_sage, tbam, nbam, tbai, nbai ] + // channel: [ meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai ] ch_sage_germline_inputs = ch_inputs_germline_sorted.runnable - .map { meta -> + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> def meta_sage = [ key: meta.group_id, @@ -66,16 +84,7 @@ workflow SAGE_CALLING { normal_id: Utils.getNormalDnaSampleName(meta), ] - data = [ - meta_sage, - Utils.getTumorDnaBam(meta), - Utils.getNormalDnaBam(meta), - Utils.getTumorDnaBai(meta), - Utils.getNormalDnaBai(meta), - ] - - return data - + return [meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai] } // Run process @@ -98,21 +107,23 @@ workflow SAGE_CALLING { // MODULE: SAGE somatic // // Select inputs that are eligible to run - // channel: [ meta ] + // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] + // channel: skip: [ meta ] ch_inputs_somatic_sorted = ch_inputs_sorted.runnable - .branch { meta -> - def has_tumor = Utils.hasTumorDnaBam(meta) + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + def has_tumor = tumor_bam def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_VCF_TUMOR) runnable: has_tumor && !has_existing skip: true + meta } // Create process input channel - // channel: tumor/normal: [ meta_sage, tbam, nbam, tbai, nbai ] - // channel: tumor only: [ meta_sage, tbam, [], tbai, [] ] + // channel: tumor/normal: [ meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai ] + // channel: tumor only: [ meta_sage, tumor_bam, [], tumor_bai, [] ] ch_sage_somatic_inputs = ch_inputs_somatic_sorted.runnable - .map { meta -> + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> def meta_sage = [ key: meta.group_id, @@ -120,33 +131,7 @@ workflow SAGE_CALLING { tumor_id: Utils.getTumorDnaSampleName(meta), ] - def data = [] - if (Utils.hasNormalDnaBam(meta)) { - - meta_sage.normal_id = Utils.getNormalDnaSampleName(meta) - - data = [ - meta_sage, - Utils.getTumorDnaBam(meta), - Utils.getNormalDnaBam(meta), - Utils.getTumorDnaBai(meta), - Utils.getNormalDnaBai(meta), - ] - - } else { - - data = [ - meta_sage, - Utils.getTumorDnaBam(meta), - [], - Utils.getTumorDnaBai(meta), - [], - ] - - } - - return data - + return [meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai] } // Run process diff --git a/subworkflows/local/sigs_fitting.nf b/subworkflows/local/sigs_fitting.nf index 4a2f159b..9d47f8f7 100644 --- a/subworkflows/local/sigs_fitting.nf +++ b/subworkflows/local/sigs_fitting.nf @@ -34,7 +34,7 @@ workflow SIGS_FITTING { ch_inputs_sorted = ch_inputs_selected .branch { meta, purple_dir -> - def has_dna = Utils.hasTumorDnaBam(meta) + def has_dna = Utils.hasTumorDna(meta) def tumor_id def has_smlv_vcf diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index c32389da..87e16488 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -12,6 +12,7 @@ workflow VIRUSBREAKEND_CALLING { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] ch_purple // channel: [mandatory] [ meta, purple_dir ] ch_bamtools_somatic // channel: [mandatory] [ meta, metrics ] @@ -36,14 +37,20 @@ workflow VIRUSBREAKEND_CALLING { // Sort inputs // NOTE(SW): VIRUSBreakend inputs are not allowed in the samplesheet, so aren't considered - // channel: [ meta ] - ch_inputs_sorted = ch_inputs - .branch { meta -> - + // channel: [ meta, tumor_bam, tumor_bai ] + ch_inputs_sorted = ch_tumor_bam + .map { meta, tumor_bam, tumor_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + ] + } + .branch { meta, tumor_bam, tumor_bai -> def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.VIRUSINTERPRETER_DIR) - - runnable: Utils.hasTumorDnaBam(meta) && !has_existing + runnable: tumor_bam && !has_existing skip: true + meta } // @@ -52,7 +59,7 @@ workflow VIRUSBREAKEND_CALLING { // Create process input channel // channel: [ meta_virus, tumor_bam ] ch_virusbreakend_inputs = ch_inputs_sorted.runnable - .map { meta -> + .map { meta, tumor_bam, tumor_bai -> def meta_virus = [ key: meta.group_id, @@ -60,7 +67,7 @@ workflow VIRUSBREAKEND_CALLING { sample_id: Utils.getTumorDnaSampleName(meta), ] - return [meta_virus, Utils.getTumorDnaBam(meta)] + return [meta_virus, tumor_bam] } // Run process diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 13170ba1..d8507996 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -128,66 +128,64 @@ workflow TARGETED { // // SUBWORKFLOW: Align reads // - // channel: [ meta ] - ch_dna_alignment_out = Channel.empty() - // channel: [ meta, bam_rna ] - ch_rna_alignment_out = Channel.empty() - // TODO(SW): set up correctly - if (true || run_config.stages.alignment) { + // channel: [ meta, [bam, ...], [bai, ...] ] + ch_align_dna_tumor_out = Channel.empty() + ch_align_dna_normal_out = Channel.empty() + if (run_config.stages.alignment) { READ_ALIGNMENT( ch_inputs, ref_data.genome_fasta, ref_data.genome_bwa_index, + ref_data.genome_bwa_index_bseq, + ref_data.genome_bwa_index_biidx, params.max_fastq_records, ) ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) - ch_dna_alignment_out = ch_dna_alignment_out.mix(READ_ALIGNMENT.out.dna) - ch_rna_alignment_out = ch_rna_alignment_out.mix(READ_ALIGNMENT.out.rna) - + ch_align_dna_tumor_out = ch_align_dna_tumor_out.mix(READ_ALIGNMENT.out.dna_tumor) + ch_align_dna_normal_out = ch_align_dna_normal_out.mix(READ_ALIGNMENT.out.dna_normal) } else { - ch_dna_alignment_out = ch_inputs - ch_rna_alignment_out = ch_inputs.map { meta -> [meta, []] } + ch_align_dna_tumor_out = ch_inputs.map { meta -> [meta, [], []] } + ch_align_dna_normal_out = ch_inputs.map { meta -> [meta, [], []] } } // // SUBWORKFLOW: Process read alignments // - // channel: [ meta ] - ch_dna_processed_out = Channel.empty() - // channel: [ meta, bam_rna ] - ch_rna_processed_out = Channel.empty() - // TODO(SW): set up correctly - if (true || run_config.stages.markdups) { + // channel: [ meta, bam, bai ] + ch_process_dna_tumor_out = Channel.empty() + ch_process_dna_normal_out = Channel.empty() + if (run_config.stages.markdups) { + // NOTE(SW/MC): hardcoded for initial testing purposes has_umis = run_config.panel.equalsIgnoreCase('tso500') READ_PROCESSING( ch_inputs, - ch_dna_alignment_out, - ch_rna_alignment_out, - ref_data.genome_version, + ch_align_dna_tumor_out, + ch_align_dna_normal_out, ref_data.genome_fasta, + ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, - file(params.refdata_unmap_regions), + hmf_data.unmap_regions, has_umis, ) ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) - ch_dna_processed_out = ch_dna_processed_out.mix(READ_PROCESSING.out.dna) - ch_rna_processed_out = ch_rna_processed_out.mix(READ_PROCESSING.out.rna) + ch_process_dna_tumor_out = ch_process_dna_tumor_out.mix(READ_PROCESSING.out.dna_tumor) + ch_process_dna_normal_out = ch_process_dna_normal_out.mix(READ_PROCESSING.out.dna_normal) } else { - ch_dna_processed_out = ch_inputs.map - ch_rna_processed_out = ch_inputs.map { meta -> [meta, []] } + ch_process_dna_normal_out = ch_inputs.map + ch_process_dna_normal_out = ch_inputs.map { meta -> [meta, []] } } @@ -205,7 +203,7 @@ workflow TARGETED { isofox_tpm_norm = params.isofox_tpm_norm ? file(params.isofox_tpm_norm) : panel_data.isofox_tpm_norm ISOFOX_QUANTIFICATION( - ch_dna_processed_out, + ch_inputs, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -224,7 +222,7 @@ workflow TARGETED { } else { - ch_isofox_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_isofox_out = ch_inputs.map { meta -> [meta, []] } } @@ -236,7 +234,9 @@ workflow TARGETED { if (run_config.stages.amber) { AMBER_PROFILING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ref_data.genome_version, hmf_data.heterozygous_sites, panel_data.target_region_bed, @@ -247,7 +247,7 @@ workflow TARGETED { } else { - ch_amber_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_amber_out = ch_inputs.map { meta -> [meta, []] } } @@ -259,7 +259,9 @@ workflow TARGETED { if (run_config.stages.cobalt) { COBALT_PROFILING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, hmf_data.gc_profile, hmf_data.diploid_bed, panel_data.target_region_normalisation, @@ -271,7 +273,7 @@ workflow TARGETED { } else { - ch_cobalt_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_cobalt_out = ch_inputs.map { meta -> [meta, []] } } @@ -283,7 +285,9 @@ workflow TARGETED { if (run_config.stages.gridss) { GRIDSS_SVPREP_CALLING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -303,7 +307,7 @@ workflow TARGETED { } else { - ch_gridss_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_gridss_out = ch_inputs.map { meta -> [meta, []] } } @@ -317,7 +321,7 @@ workflow TARGETED { if (run_config.stages.gripss) { GRIPSS_FILTERING( - ch_dna_processed_out, + ch_inputs, ch_gridss_out, ref_data.genome_fasta, ref_data.genome_version, @@ -337,9 +341,9 @@ workflow TARGETED { } else { - ch_gripss_somatic_out = ch_dna_processed_out.map { meta -> [meta, [], []] } - ch_gripss_germline_out = ch_dna_processed_out.map { meta -> [meta, [], []] } - ch_gripss_somatic_unfiltered_out = ch_dna_processed_out.map { meta -> [meta, [], []] } + ch_gripss_somatic_out = ch_inputs.map { meta -> [meta, [], []] } + ch_gripss_germline_out = ch_inputs.map { meta -> [meta, [], []] } + ch_gripss_somatic_unfiltered_out = ch_inputs.map { meta -> [meta, [], []] } } @@ -355,7 +359,9 @@ workflow TARGETED { if (run_config.stages.sage) { SAGE_CALLING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -379,10 +385,10 @@ workflow TARGETED { } else { - ch_sage_germline_vcf_out = ch_dna_processed_out.map { meta -> [meta, [], []] } - ch_sage_somatic_vcf_out = ch_dna_processed_out.map { meta -> [meta, [], []] } - ch_sage_germline_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_sage_somatic_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_sage_germline_vcf_out = ch_inputs.map { meta -> [meta, [], []] } + ch_sage_somatic_vcf_out = ch_inputs.map { meta -> [meta, [], []] } + ch_sage_germline_dir_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_somatic_dir_out = ch_inputs.map { meta -> [meta, []] } } @@ -395,7 +401,7 @@ workflow TARGETED { if (run_config.stages.pave) { PAVE_ANNOTATION( - ch_dna_processed_out, + ch_inputs, ch_sage_germline_vcf_out, ch_sage_somatic_vcf_out, ref_data.genome_fasta, @@ -419,8 +425,8 @@ workflow TARGETED { } else { - ch_pave_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_pave_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_pave_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_pave_somatic_out = ch_inputs.map { meta -> [meta, []] } } @@ -432,7 +438,7 @@ workflow TARGETED { if (run_config.stages.purple) { PURPLE_CALLING( - ch_dna_processed_out, + ch_inputs, ch_amber_out, ch_cobalt_out, ch_pave_somatic_out, @@ -461,7 +467,7 @@ workflow TARGETED { } else { - ch_purple_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_purple_out = ch_inputs.map { meta -> [meta, []] } } @@ -476,7 +482,7 @@ workflow TARGETED { // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented SAGE_APPEND( - ch_dna_processed_out, + ch_inputs, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, @@ -491,8 +497,8 @@ workflow TARGETED { } else { - ch_sage_somatic_append_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_sage_germline_append_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_sage_somatic_append_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_germline_append_out = ch_inputs.map { meta -> [meta, []] } } @@ -505,7 +511,7 @@ workflow TARGETED { if (run_config.stages.linx) { LINX_ANNOTATION( - ch_dna_processed_out, + ch_inputs, ch_purple_out, ref_data.genome_version, hmf_data.ensembl_data_resources, @@ -521,8 +527,8 @@ workflow TARGETED { } else { - ch_linx_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_linx_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_linx_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_linx_germline_out = ch_inputs.map { meta -> [meta, []] } } @@ -534,7 +540,7 @@ workflow TARGETED { if (run_config.stages.linx) { LINX_PLOTTING( - ch_dna_processed_out, + ch_inputs, ch_linx_somatic_out, ref_data.genome_version, hmf_data.ensembl_data_resources, @@ -546,7 +552,7 @@ workflow TARGETED { } else { - ch_linx_somatic_visualiser_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_linx_somatic_visualiser_dir_out = ch_inputs.map { meta -> [meta, []] } } @@ -559,7 +565,9 @@ workflow TARGETED { if (run_config.stages.orange && run_config.stages.flagstat) { FLAGSTAT_METRICS( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ) ch_versions = ch_versions.mix(FLAGSTAT_METRICS.out.versions) @@ -569,8 +577,8 @@ workflow TARGETED { } else { - ch_flagstat_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_flagstat_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_flagstat_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_flagstat_germline_out = ch_inputs.map { meta -> [meta, []] } } @@ -583,7 +591,9 @@ workflow TARGETED { if (run_config.stages.bamtools) { BAMTOOLS_METRICS( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ref_data.genome_fasta, ref_data.genome_version, ) @@ -595,8 +605,8 @@ workflow TARGETED { } else { - ch_bamtools_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_bamtools_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_bamtools_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_bamtools_germline_out = ch_inputs.map { meta -> [meta, []] } } @@ -611,7 +621,9 @@ workflow TARGETED { ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] LILAC_CALLING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, @@ -626,7 +638,7 @@ workflow TARGETED { } else { - ch_lilac_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_lilac_out = ch_inputs.map { meta -> [meta, []] } } @@ -636,13 +648,13 @@ workflow TARGETED { if (run_config.stages.orange) { // Create placeholder channels for empty remaining channels - ch_chord_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_cuppa_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_sigs_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_virusinterpreter_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_chord_out = ch_inputs.map { meta -> [meta, []] } + ch_cuppa_out = ch_inputs.map { meta -> [meta, []] } + ch_sigs_out = ch_inputs.map { meta -> [meta, []] } + ch_virusinterpreter_out = ch_inputs.map { meta -> [meta, []] } ORANGE_REPORTING( - ch_dna_processed_out, + ch_inputs, ch_bamtools_somatic_out, ch_bamtools_germline_out, ch_flagstat_somatic_out, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 4d2a74fc..66984000 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -112,7 +112,6 @@ samplesheet = Utils.getFileObject(params.input) // TODO(MC): Drop commit 'WIP: Reverting bioconda containers'. // TODO(MC): Run full tests for going from .fastq.gz. -// TODO(SW): Unmap region resouce files. // TODO(MC): Fix warnings. workflow WGTS { // Create channel for versions @@ -136,67 +135,65 @@ workflow WGTS { // // SUBWORKFLOW: Align reads // - // channel: [ meta ] - ch_dna_alignment_out = Channel.empty() - // channel: [ meta, bam_rna ] - ch_rna_alignment_out = Channel.empty() - // TODO(SW): set up correctly - if (true || run_config.stages.alignment) { + // channel: [ meta, [bam, ...], [bai, ...] ] + ch_align_dna_tumor_out = Channel.empty() + ch_align_dna_normal_out = Channel.empty() + if (run_config.stages.alignment) { READ_ALIGNMENT( ch_inputs, ref_data.genome_fasta, ref_data.genome_bwa_index, + ref_data.genome_bwa_index_bseq, + ref_data.genome_bwa_index_biidx, params.max_fastq_records, ) ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) - ch_dna_alignment_out = ch_dna_alignment_out.mix(READ_ALIGNMENT.out.dna) - ch_rna_alignment_out = ch_rna_alignment_out.mix(READ_ALIGNMENT.out.rna) - + ch_align_dna_tumor_out = ch_align_dna_tumor_out.mix(READ_ALIGNMENT.out.dna_tumor) + ch_align_dna_normal_out = ch_align_dna_normal_out.mix(READ_ALIGNMENT.out.dna_normal) } else { - ch_dna_alignment_out = ch_inputs - ch_rna_alignment_out = ch_inputs.map { meta -> [meta, []] } + ch_align_dna_tumor_out = ch_inputs.map { meta -> [meta, [], []] } + ch_align_dna_normal_out = ch_inputs.map { meta -> [meta, [], []] } } // // SUBWORKFLOW: Process read alignments // - // channel: [ meta ] - ch_dna_processed_out = Channel.empty() - // channel: [ meta, bam_rna ] - ch_rna_processed_out = Channel.empty() - // TODO(SW): set up correctly - if (true || run_config.stages.markdups) { + // channel: [ meta, bam, bai ] + ch_process_dna_tumor_out = Channel.empty() + ch_process_dna_normal_out = Channel.empty() + if (run_config.stages.markdups) { READ_PROCESSING( ch_inputs, - ch_dna_alignment_out, - ch_rna_alignment_out, - ref_data.genome_version, + ch_align_dna_tumor_out, + ch_align_dna_normal_out, ref_data.genome_fasta, + ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, - file(params.refdata_unmap_regions), - false, + hmf_data.unmap_regions, + false, // has_umis ) ch_versions = ch_versions.mix(READ_PROCESSING.out.versions) - ch_dna_processed_out = ch_dna_processed_out.mix(READ_PROCESSING.out.dna) - ch_rna_processed_out = ch_rna_processed_out.mix(READ_PROCESSING.out.rna) + ch_process_dna_tumor_out = ch_process_dna_tumor_out.mix(READ_PROCESSING.out.dna_tumor) + ch_process_dna_normal_out = ch_process_dna_normal_out.mix(READ_PROCESSING.out.dna_normal) } else { - ch_dna_processed_out = ch_inputs.map - ch_rna_processed_out = ch_inputs.map { meta -> [meta, []] } + ch_process_dna_normal_out = ch_inputs.map + ch_process_dna_normal_out = ch_inputs.map { meta -> [meta, []] } } + // // MODULE: Run Isofox to analyse RNA data // @@ -208,7 +205,7 @@ workflow WGTS { isofox_gc_ratios = params.isofox_gc_ratios ? file(params.isofox_gc_ratios) : hmf_data.isofox_gc_ratios ISOFOX_QUANTIFICATION( - ch_dna_processed_out, + ch_inputs, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -227,7 +224,7 @@ workflow WGTS { } else { - ch_isofox_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_isofox_out = ch_inputs.map { meta -> [meta, []] } } @@ -239,7 +236,9 @@ workflow WGTS { if (run_config.stages.amber) { AMBER_PROFILING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ref_data.genome_version, hmf_data.heterozygous_sites, [], // target_region_bed @@ -251,7 +250,7 @@ workflow WGTS { } else { - ch_amber_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_amber_out = ch_inputs.map { meta -> [meta, []] } } @@ -263,7 +262,9 @@ workflow WGTS { if (run_config.stages.cobalt) { COBALT_PROFILING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, hmf_data.gc_profile, hmf_data.diploid_bed, [], // panel_target_region_normalisation @@ -275,7 +276,7 @@ workflow WGTS { } else { - ch_cobalt_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_cobalt_out = ch_inputs.map { meta -> [meta, []] } } @@ -287,7 +288,9 @@ workflow WGTS { if (run_config.stages.gridss) { GRIDSS_SVPREP_CALLING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -307,7 +310,7 @@ workflow WGTS { } else { - ch_gridss_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_gridss_out = ch_inputs.map { meta -> [meta, []] } } @@ -321,7 +324,7 @@ workflow WGTS { if (run_config.stages.gripss) { GRIPSS_FILTERING( - ch_dna_processed_out, + ch_inputs, ch_gridss_out, ref_data.genome_fasta, ref_data.genome_version, @@ -341,9 +344,9 @@ workflow WGTS { } else { - ch_gripss_somatic_out = ch_dna_processed_out.map { meta -> [meta, [], []] } - ch_gripss_germline_out = ch_dna_processed_out.map { meta -> [meta, [], []] } - ch_gripss_somatic_unfiltered_out = ch_dna_processed_out.map { meta -> [meta, [], []] } + ch_gripss_somatic_out = ch_inputs.map { meta -> [meta, [], []] } + ch_gripss_germline_out = ch_inputs.map { meta -> [meta, [], []] } + ch_gripss_somatic_unfiltered_out = ch_inputs.map { meta -> [meta, [], []] } } @@ -359,7 +362,9 @@ workflow WGTS { if (run_config.stages.sage) { SAGE_CALLING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -383,10 +388,10 @@ workflow WGTS { } else { - ch_sage_germline_vcf_out = ch_dna_processed_out.map { meta -> [meta, [], []] } - ch_sage_somatic_vcf_out = ch_dna_processed_out.map { meta -> [meta, [], []] } - ch_sage_germline_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_sage_somatic_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_sage_germline_vcf_out = ch_inputs.map { meta -> [meta, [], []] } + ch_sage_somatic_vcf_out = ch_inputs.map { meta -> [meta, [], []] } + ch_sage_germline_dir_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_somatic_dir_out = ch_inputs.map { meta -> [meta, []] } } @@ -399,7 +404,7 @@ workflow WGTS { if (run_config.stages.pave) { PAVE_ANNOTATION( - ch_dna_processed_out, + ch_inputs, ch_sage_germline_vcf_out, ch_sage_somatic_vcf_out, ref_data.genome_fasta, @@ -423,8 +428,8 @@ workflow WGTS { } else { - ch_pave_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_pave_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_pave_germline_out = ch_inputs.map { meta -> [meta, []] } + ch_pave_somatic_out = ch_inputs.map { meta -> [meta, []] } } @@ -436,7 +441,7 @@ workflow WGTS { if (run_config.stages.purple) { PURPLE_CALLING( - ch_dna_processed_out, + ch_inputs, ch_amber_out, ch_cobalt_out, ch_pave_somatic_out, @@ -465,7 +470,7 @@ workflow WGTS { } else { - ch_purple_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_purple_out = ch_inputs.map { meta -> [meta, []] } } @@ -480,7 +485,7 @@ workflow WGTS { // NOTE(SW): currently used only for ORANGE but will also be used for Neo once implemented SAGE_APPEND( - ch_dna_processed_out, + ch_inputs, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, @@ -494,8 +499,8 @@ workflow WGTS { } else { - ch_sage_somatic_append_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_sage_germline_append_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_sage_somatic_append_out = ch_inputs.map { meta -> [meta, []] } + ch_sage_germline_append_out = ch_inputs.map { meta -> [meta, []] } } @@ -508,7 +513,7 @@ workflow WGTS { if (run_config.stages.linx) { LINX_ANNOTATION( - ch_dna_processed_out, + ch_inputs, ch_purple_out, ref_data.genome_version, hmf_data.ensembl_data_resources, @@ -524,8 +529,8 @@ workflow WGTS { } else { - ch_linx_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_linx_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_linx_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_linx_germline_out = ch_inputs.map { meta -> [meta, []] } } @@ -537,7 +542,7 @@ workflow WGTS { if (run_config.stages.linx) { LINX_PLOTTING( - ch_dna_processed_out, + ch_inputs, ch_linx_somatic_out, ref_data.genome_version, hmf_data.ensembl_data_resources, @@ -549,7 +554,7 @@ workflow WGTS { } else { - ch_linx_somatic_visualiser_dir_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_linx_somatic_visualiser_dir_out = ch_inputs.map { meta -> [meta, []] } } @@ -562,7 +567,9 @@ workflow WGTS { if (run_config.stages.orange && run_config.stages.flagstat) { FLAGSTAT_METRICS( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ) ch_versions = ch_versions.mix(FLAGSTAT_METRICS.out.versions) @@ -572,8 +579,8 @@ workflow WGTS { } else { - ch_flagstat_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_flagstat_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_flagstat_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_flagstat_germline_out = ch_inputs.map { meta -> [meta, []] } } @@ -586,7 +593,9 @@ workflow WGTS { if (run_config.stages.bamtools) { BAMTOOLS_METRICS( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ref_data.genome_fasta, ref_data.genome_version, ) @@ -598,8 +607,8 @@ workflow WGTS { } else { - ch_bamtools_somatic_out = ch_dna_processed_out.map { meta -> [meta, []] } - ch_bamtools_germline_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_bamtools_somatic_out = ch_inputs.map { meta -> [meta, []] } + ch_bamtools_germline_out = ch_inputs.map { meta -> [meta, []] } } @@ -611,7 +620,7 @@ workflow WGTS { if (run_config.stages.sigs) { SIGS_FITTING( - ch_dna_processed_out, + ch_inputs, ch_purple_out, hmf_data.sigs_signatures, ) @@ -622,7 +631,7 @@ workflow WGTS { } else { - ch_sigs_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_sigs_out = ch_inputs.map { meta -> [meta, []] } } @@ -634,7 +643,7 @@ workflow WGTS { if (run_config.stages.chord) { CHORD_PREDICTION( - ch_dna_processed_out, + ch_inputs, ch_purple_out, ref_data.genome_version, ) @@ -645,7 +654,7 @@ workflow WGTS { } else { - ch_chord_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_chord_out = ch_inputs.map { meta -> [meta, []] } } @@ -660,7 +669,9 @@ workflow WGTS { ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] LILAC_CALLING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, + ch_process_dna_normal_out, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, @@ -675,7 +686,7 @@ workflow WGTS { } else { - ch_lilac_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_lilac_out = ch_inputes.map { meta -> [meta, []] } } @@ -687,7 +698,8 @@ workflow WGTS { if (run_config.stages.virusinterpreter) { VIRUSBREAKEND_CALLING( - ch_dna_processed_out, + ch_inputs, + ch_process_dna_tumor_out, ch_purple_out, ch_bamtools_somatic_out, ref_data.genome_fasta, @@ -708,7 +720,7 @@ workflow WGTS { } else { - ch_virusinterpreter_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_virusinterpreter_out = ch_inputs.map { meta -> [meta, []] } } @@ -720,7 +732,7 @@ workflow WGTS { if (run_config.stages.cuppa) { CUPPA_PREDICTION( - ch_dna_processed_out, + ch_inputs, ch_isofox_out, ch_purple_out, ch_linx_somatic_out, @@ -735,7 +747,7 @@ workflow WGTS { } else { - ch_cuppa_out = ch_dna_processed_out.map { meta -> [meta, []] } + ch_cuppa_out = ch_inputs.map { meta -> [meta, []] } } @@ -745,7 +757,7 @@ workflow WGTS { if (run_config.stages.orange) { ORANGE_REPORTING( - ch_dna_processed_out, + ch_inputs, ch_bamtools_somatic_out, ch_bamtools_germline_out, ch_flagstat_somatic_out, From 0b27c4a089d68193045ab9ba950db7ef99640c6b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 10:21:39 +1100 Subject: [PATCH 350/562] Fix join for alignment BAM and corresponding BAIs --- subworkflows/local/read_alignment.nf | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index 809e9982..cd9c65ce 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -163,15 +163,12 @@ workflow READ_ALIGNMENT { ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) // Combine BAMs and BAIs - ch_bams_flat = Channel.empty() - .mix( - BWA_MEM2.out.bam, - SAMBAMBA_INDEX.out.bai - ) - .groupTuple(size: 2) - .map { it.flatten() } - - + // channel: [ meta, sample_type, bam, bai ] + ch_bams_flat = WorkflowOncoanalyser.groupByMeta( + BWA_MEM2.out.bam.map { meta_bwa, bam -> [meta_bwa, meta_bwa.sample_type] }, + BWA_MEM2.out.bam, + SAMBAMBA_INDEX.out.bai, + ) // Reunite BAMs // First, count expected BAMs per sample for non-blocking groupTuple op @@ -188,11 +185,12 @@ workflow READ_ALIGNMENT { .groupTuple() .map { meta_count, meta_bwas -> return [meta_count, meta_bwas.size()] } + // Now, group with expected size then sort into tumor and normal channels ch_bams_united = ch_sample_fastq_counts .cross( // First element to match meta_count above for `cross` - ch_bams_flat.map { meta_bwa, bam, bai -> [[key: meta_bwa.key, sample_type: meta_bwa.sample_type], bam, bai] } + ch_bams_flat.map { meta, sample_type, bam, bai -> [[key: meta.key, sample_type: sample_type], bam, bai] } ) .map { count_tuple, bam_tuple -> From 0ca87ec97de928b63fbff2882365f7b34eadb7cd Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 10:22:39 +1100 Subject: [PATCH 351/562] Improve comments, syntax, etc --- modules/local/markdups/main.nf | 2 +- subworkflows/local/read_alignment.nf | 1 - subworkflows/local/read_processing.nf | 12 ++++++------ workflows/wgts.nf | 1 - 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index a26b4111..a1805036 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -17,7 +17,7 @@ process MARKDUPS { output: tuple val(meta), path('*bam'), path('*bai'), emit: bam - path 'versions.yml' , emit: versions + path 'versions.yml' , emit: versions path '*.tsv' when: diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment.nf index cd9c65ce..a876a132 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment.nf @@ -139,7 +139,6 @@ workflow READ_ALIGNMENT { ] return [meta_bwa, fastq_fwd, fastq_rev] - } // Run process diff --git a/subworkflows/local/read_processing.nf b/subworkflows/local/read_processing.nf index d3cef837..638e197b 100644 --- a/subworkflows/local/read_processing.nf +++ b/subworkflows/local/read_processing.nf @@ -23,7 +23,7 @@ workflow READ_PROCESSING { ch_versions = Channel.empty() // Select and sort input sources, separating bytumor and normal - // channel: runnable: [ meta, bams, bais ] + // channel: runnable: [ meta, [bam, ...], [bai, ...] ] // channel: skip: [ meta ] ch_inputs_tumor_sorted = ch_dna_tumor .map { meta, bams, bais -> @@ -56,13 +56,13 @@ workflow READ_PROCESSING { } // Create process input channel - // channel: [ meta_markdups, bam, bai ] + // channel: [ meta_markdups, [bam, ...], [bai, ...] ] ch_markdups_inputs = Channel.empty() .mix( - ch_inputs_tumor_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bam, bai] }, - ch_inputs_normal_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getNormalDnaSample(meta), 'normal', bam, bai] }, + ch_inputs_tumor_sorted.runnable.map { meta, bams, bais -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bams, bais] }, + ch_inputs_normal_sorted.runnable.map { meta, bams, bais -> [meta, Utils.getNormalDnaSample(meta), 'normal', bams, bais] }, ) - .map { meta, meta_sample, sample_type, bam, bai -> + .map { meta, meta_sample, sample_type, bams, bais -> def meta_markdups = [ key: meta.group_id, @@ -71,7 +71,7 @@ workflow READ_PROCESSING { sample_type: sample_type, ] - return [meta_markdups, bam, bai] + return [meta_markdups, bams, bais] } // Run process diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 66984000..aa706180 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -193,7 +193,6 @@ workflow WGTS { } - // // MODULE: Run Isofox to analyse RNA data // From 51e21b509edb7ea1dff01a3840f5af6c2b84a1b1 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 13:33:02 +1100 Subject: [PATCH 352/562] Implement RNA alignment --- conf/hmf_genomes.config | 2 + lib/Constants.groovy | 42 +--- lib/Utils.groovy | 73 ++++--- lib/WorkflowMain.groovy | 7 +- main.nf | 1 + modules/local/sambamba/index/main.nf | 1 - modules/local/sambamba/merge/main.nf | 33 +++ modules/local/star/main.nf | 52 +++-- modules/nf-core/gatk4/markduplicates/main.nf | 65 ++++++ modules/nf-core/gatk4/markduplicates/meta.yml | 72 +++++++ modules/nf-core/samtools/sort/main.nf | 49 +++++ modules/nf-core/samtools/sort/meta.yml | 51 +++++ nextflow_schema.json | 7 +- subworkflows/local/amber_profiling.nf | 4 +- subworkflows/local/bamtools_metrics.nf | 4 +- subworkflows/local/cobalt_profiling.nf | 4 +- subworkflows/local/cuppa_prediction.nf | 2 +- subworkflows/local/flagstat_metrics.nf | 4 +- subworkflows/local/gridss_svprep_calling.nf | 4 +- subworkflows/local/isofox_quantification.nf | 26 ++- subworkflows/local/lilac_calling.nf | 23 +- subworkflows/local/prepare_reference.nf | 15 ++ ...ead_alignment.nf => read_alignment_dna.nf} | 9 +- subworkflows/local/read_alignment_rna.nf | 197 ++++++++++++++++++ subworkflows/local/sage_append.nf | 58 +++--- subworkflows/local/sage_calling.nf | 4 +- subworkflows/local/virusbreakend_calling.nf | 2 +- workflows/targeted.nf | 30 ++- workflows/wgts.nf | 29 ++- 29 files changed, 697 insertions(+), 173 deletions(-) create mode 100644 modules/local/sambamba/merge/main.nf create mode 100644 modules/nf-core/gatk4/markduplicates/main.nf create mode 100644 modules/nf-core/gatk4/markduplicates/meta.yml create mode 100644 modules/nf-core/samtools/sort/main.nf create mode 100644 modules/nf-core/samtools/sort/meta.yml rename subworkflows/local/{read_alignment.nf => read_alignment_dna.nf} (96%) create mode 100644 subworkflows/local/read_alignment_rna.nf diff --git a/conf/hmf_genomes.config b/conf/hmf_genomes.config index 5e38201b..868315a9 100644 --- a/conf/hmf_genomes.config +++ b/conf/hmf_genomes.config @@ -18,6 +18,7 @@ params { bwa_index_biidx = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64" bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" + star_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/star_index/gencode_19/2.7.3a.tar.gz" } 'GRCh38_hmf' { fasta = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" @@ -28,6 +29,7 @@ params { bwa_index_biiseq= "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" + star_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/star_index/gencode_38/2.7.3a.tar.gz" } } } diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 10bdc0ea..c7618ac3 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -58,9 +58,8 @@ class Constants { static enum FileType { // Generic BAM, - BAI, BAM_MARKDUPS, - BAI_MARKDUPS, + BAI, FASTQ, // Process AMBER_DIR, @@ -125,12 +124,6 @@ class Constants { SequenceType.DNA, ], - BAM_RNA_TUMOR : [ - FileType.BAM, - SampleType.TUMOR, - SequenceType.RNA, - ], - BAM_DNA_NORMAL: [ FileType.BAM, SampleType.NORMAL, @@ -143,55 +136,30 @@ class Constants { SequenceType.DNA, ], - BAM_RNA_NORMAL : [ + BAM_RNA_TUMOR: [ FileType.BAM, - SampleType.NORMAL, + SampleType.TUMOR, SequenceType.RNA, ], - - - - BAI_DNA_TUMOR: [ FileType.BAI, SampleType.TUMOR, SequenceType.DNA, ], - BAI_MARKDUPS_DNA_TUMOR: [ - FileType.BAI_MARKDUPS, - SampleType.TUMOR, - SequenceType.DNA, - ], - - BAI_RNA_TUMOR : [ - FileType.BAI, - SampleType.TUMOR, - SequenceType.RNA, - ], - BAI_DNA_NORMAL: [ FileType.BAI, SampleType.NORMAL, SequenceType.DNA, ], - BAI_MARKDUPS_DNA_NORMAL: [ - FileType.BAI_MARKDUPS, - SampleType.NORMAL, - SequenceType.DNA, - ], - - BAI_RNA_NORMAL : [ + BAI_RNA_TUMOR: [ FileType.BAI, - SampleType.NORMAL, + SampleType.TUMOR, SequenceType.RNA, ], - - - ISOFOX_DIR: [ FileType.ISOFOX_DIR, SampleType.TUMOR, diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 2ab04a11..6cfa638b 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -151,7 +151,7 @@ class Utils { index_enum = Constants.FileType.BAI index_str = 'bai' } else if (key === Constants.FileType.BAM_MARKDUPS) { - index_enum = Constants.FileType.BAI_MARKDUPS + index_enum = Constants.FileType.BAI index_str = 'bai' } else if (key === Constants.FileType.GRIDSS_VCF) { index_enum = Constants.FileType.GRIDSS_VCF_TBI @@ -413,20 +413,25 @@ class Utils { // Files + static public getTumorDnaFastq(meta) { + return getTumorDnaSample(meta).getOrDefault(Constants.FileType.FASTQ, null) + } + static public getTumorDnaBam(meta) { return getTumorDnaSample(meta).getOrDefault(Constants.FileType.BAM, null) } + static public getTumorDnaMarkdupsBam(meta) { + return getTumorDnaSample(meta).getOrDefault(Constants.FileType.BAM_MARKDUPS, null) + } + static public getTumorDnaBai(meta) { return getTumorDnaSample(meta).getOrDefault(Constants.FileType.BAI, null) } - static public getTumorDnaMarkdupsBam(meta) { - return getTumorDnaSample(meta).getOrDefault(Constants.FileType.BAM_MARKDUPS, null) - } - static public getTumorDnaFastq(meta) { - return getTumorDnaSample(meta).getOrDefault(Constants.FileType.FASTQ, null) + static public hasTumorDnaFastq(meta) { + return getTumorDnaFastq(meta) !== null } static public hasTumorDnaBam(meta) { @@ -437,36 +442,25 @@ class Utils { return getTumorDnaMarkdupsBam(meta) !== null } - static public hasTumorDnaFastq(meta) { - return getTumorDnaFastq(meta) !== null - } - - static public getTumorRnaBam(meta) { - return getTumorRnaSample(meta).getOrDefault(Constants.FileType.BAM, null) - } - - static public getTumorRnaBai(meta) { - return getTumorRnaSample(meta).getOrDefault(Constants.FileType.BAI, null) - } - static public hasTumorRnaBam(meta) { - return getTumorRnaBam(meta) !== null + static public getNormalDnaFastq(meta) { + return getNormalDnaSample(meta).getOrDefault(Constants.FileType.FASTQ, null) } static public getNormalDnaBam(meta) { return getNormalDnaSample(meta).getOrDefault(Constants.FileType.BAM, null) } + static public getNormalDnaMarkdupsBam(meta) { + return getNormalDnaSample(meta).getOrDefault(Constants.FileType.BAM_MARKDUPS, null) + } static public getNormalDnaBai(meta) { return getNormalDnaSample(meta).getOrDefault(Constants.FileType.BAI, null) } - static public getNormalDnaMarkdupsBam(meta) { - return getNormalDnaSample(meta).getOrDefault(Constants.FileType.BAM_MARKDUPS, null) - } - static public getNormalDnaFastq(meta) { - return getNormalDnaSample(meta).getOrDefault(Constants.FileType.FASTQ, null) + static public hasNormalDnaFastq(meta) { + return getNormalDnaFastq(meta) !== null } static public hasNormalDnaBam(meta) { @@ -477,16 +471,35 @@ class Utils { return getNormalDnaMarkdupsBam(meta) !== null } - static public hasNormalDnaFastq(meta) { - return getNormalDnaFastq(meta) !== null + + static public hasDnaFastq(meta) { + return hasNormalDnaFastq(meta) || hasTumorDnaFastq(meta) } static public hasDnaMarkdupsBam(meta) { return hasNormalDnaMarkdupsBam(meta) || hasTumorDnaMarkdupsBam(meta) } - static public hasDnaFastq(meta) { - return hasNormalDnaFastq(meta) || hasTumorDnaFastq(meta) + + static public getTumorRnaFastq(meta) { + return getTumorRnaSample(meta).getOrDefault(Constants.FileType.FASTQ, null) + } + + static public getTumorRnaBam(meta) { + return getTumorRnaSample(meta).getOrDefault(Constants.FileType.BAM, null) + } + + static public getTumorRnaBai(meta) { + return getTumorRnaSample(meta).getOrDefault(Constants.FileType.BAI, null) + } + + + static public hasTumorRnaFastq(meta) { + return getTumorRnaFastq(meta) !== null + } + + static public hasTumorRnaBam(meta) { + return getTumorRnaBam(meta) !== null } @@ -499,6 +512,10 @@ class Utils { return hasNormalDnaBam(meta) || hasNormalDnaMarkdupsBam(meta) || hasNormalDnaFastq(meta) } + static public hasTumorRna(meta) { + return hasTumorRnaBam(meta) || hasTumorRnaFastq(meta) + } + // Misc public static getInput(meta, key) { diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 9bd6a46b..b38de223 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -1,6 +1,8 @@ // // This file holds several functions specific to the main.nf workflow in the nf-core/oncoanalyser pipeline // +import Utils + class WorkflowMain { @@ -314,8 +316,9 @@ class WorkflowMain { mode: run_mode, panel: run_mode === Constants.RunMode.TARGETED ? params.panel : null, stages: stages, - has_dna: inputs.any { it.containsKey([Constants.SampleType.TUMOR, Constants.SequenceType.DNA]) }, - has_rna: inputs.any { it.containsKey([Constants.SampleType.TUMOR, Constants.SequenceType.RNA]) }, + has_dna: inputs.any { Utils.hasTumorDna(it) }, + has_rna: inputs.any { Utils.hasTumorRna(it) }, + has_rna_fastq: inputs.any { Utils.hasTumorRnaFastq(it) }, ] } } diff --git a/main.nf b/main.nf index 65841c42..5e4c5768 100644 --- a/main.nf +++ b/main.nf @@ -29,6 +29,7 @@ params.ref_data_genome_bwa_index_bseq = WorkflowMain.getGenomeAttribute(params, params.ref_data_genome_bwa_index_biidx = WorkflowMain.getGenomeAttribute(params, 'bwa_index_biidx') params.ref_data_genome_bwa_index_image = WorkflowMain.getGenomeAttribute(params, 'bwa_index_image') params.ref_data_genome_gridss_index = WorkflowMain.getGenomeAttribute(params, 'gridss_index') +params.ref_data_genome_star_index = WorkflowMain.getGenomeAttribute(params, 'star_index') /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf index f6b238e3..d3e3a2d2 100644 --- a/modules/local/sambamba/index/main.nf +++ b/modules/local/sambamba/index/main.nf @@ -30,7 +30,6 @@ process SAMBAMBA_INDEX { stub: """ touch ${bam}.bai - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sambamba/merge/main.nf b/modules/local/sambamba/merge/main.nf new file mode 100644 index 00000000..2551ed2f --- /dev/null +++ b/modules/local/sambamba/merge/main.nf @@ -0,0 +1,33 @@ +process SAMBAMBA_MERGE { + tag "${meta.id}" + + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/sambamba:1.0--h98b6b92_0' : + 'quay.io/biocontainers/sambamba:1.0--h98b6b92_0' }" + + input: + tuple val(meta), path(bams), path(bais) + + output: + tuple val(meta), path('*bam'), emit: bam + path 'versions.yml' , emit: versions + + script: + """ + sambamba merge \\ + --nthreads ${task.cpus} \\ + ${meta.sample_id}.bam \\ + ${bams} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sambamba: \$(sambamba --version 2>&1 | grep -m1 sambamba | sed 's/^sambamba //') + END_VERSIONS + """ + + stub: + """ + touch ${meta.sample_id}.bam + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/local/star/main.nf b/modules/local/star/main.nf index 780139b3..fc906880 100644 --- a/modules/local/star/main.nf +++ b/modules/local/star/main.nf @@ -1,40 +1,60 @@ process STAR { tag "${meta.id}" - label 'process_low' + label 'process_medium' - // TODO(SW): create container - //container 'foo' + container 'quay.io/biocontainers/star:2.7.3a--0' input: - // TODO(SW): decide input structure - tuple val(meta), path(fastqs) + tuple val(meta), path(fastq_fwd), path(fastq_rev) + path genome_star_index output: - // TODO(SW): set outputs - tuple val(meta), path('bar'), emit: bam - path 'versions.yml' , emit: versions + tuple val(meta), path('*bam'), emit: bam + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' - - // TODO(SW): implement process """ - echo bar + STAR \\ + --readFilesIn ${fastq_fwd} ${fastq_rev} \\ + --genomeDir ${genome_star_index} \\ + --runThreadN ${task.cpus} \\ + --readFilesCommand zcat \\ + --alignSJstitchMismatchNmax 5 -1 5 5 \\ + --alignSplicedMateMapLmin 35 \\ + --alignSplicedMateMapLminOverLmate 0.33 \\ + --chimJunctionOverhangMin 10 \\ + --chimOutType WithinBAM SoftClip \\ + --chimScoreDropMax 30 \\ + --chimScoreJunctionNonGTAG 0 \\ + --chimScoreMin 1 \\ + --chimScoreSeparation 1 \\ + --chimSegmentMin 10 \\ + --chimSegmentReadGapMax 3 \\ + --limitOutSJcollapsed 3000000 \\ + --outBAMcompression 0 \\ + --outFilterMatchNmin 35 \\ + --outFilterMatchNminOverLread 0.33 \\ + --outFilterMismatchNmax 3 \\ + --outFilterMultimapNmax 10 \\ + --outFilterScoreMinOverLread 0.33 \\ + --outSAMattributes All \\ + --outSAMattrRGline 'ID:${meta.read_group} SM:${meta.sample_id}' \\ + --outSAMtype BAM Unsorted \\ + --outSAMunmapped Within \\ + --runRNGseed 0 cat <<-END_VERSIONS > versions.yml "${task.process}": - star: foo + star: \$(STAR --version | sed -e "s/STAR_//g") END_VERSIONS """ stub: - // TODO(SW): implement stub """ - touch bar + touch Aligned.out.bam echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } - diff --git a/modules/nf-core/gatk4/markduplicates/main.nf b/modules/nf-core/gatk4/markduplicates/main.nf new file mode 100644 index 00000000..356cac0f --- /dev/null +++ b/modules/nf-core/gatk4/markduplicates/main.nf @@ -0,0 +1,65 @@ +process GATK4_MARKDUPLICATES { + tag "$meta.id" + label 'process_medium' + + conda "bioconda::gatk4=4.4.0.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/gatk4:4.4.0.0--py36hdfd78af_0': + 'quay.io/biocontainers/gatk4:4.4.0.0--py36hdfd78af_0' }" + + input: + tuple val(meta), path(bam) + path fasta + path fasta_fai + + output: + tuple val(meta), path("*cram"), emit: cram, optional: true + tuple val(meta), path("*bam"), emit: bam, optional: true + tuple val(meta), path("*.crai"), emit: crai, optional: true + tuple val(meta), path("*.bai"), emit: bai, optional: true + tuple val(meta), path("*.metrics"), emit: metrics + path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.sample_id}" + def input_list = bam.collect{"--INPUT $it"}.join(' ') + def reference = fasta ? "--REFERENCE_SEQUENCE ${fasta}" : "" + + def avail_mem = 3072 + if (!task.memory) { + log.info '[GATK MarkDuplicates] Available memory not known - defaulting to 3GB. Specify process memory requirements to change this.' + } else { + avail_mem = (task.memory.mega*0.8).intValue() + } + """ + gatk --java-options "-Xmx${avail_mem}M" MarkDuplicates \\ + $input_list \\ + --OUTPUT ${prefix}.md.bam \\ + --METRICS_FILE ${prefix}.md.metrics \\ + --TMP_DIR . \\ + --CREATE_INDEX \\ + ${reference} \\ + $args + + mv ${prefix}.md.bai ${prefix}.md.bam.bai + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gatk4: \$(echo \$(gatk --version 2>&1) | sed 's/^.*(GATK) v//; s/ .*\$//') + END_VERSIONS + """ + + stub: + prefix = task.ext.prefix ?: "${meta.sample_id}" + + """ + touch ${prefix}.md.bam + touch ${prefix}.md.bam.bai + touch ${prefix}.md.metrics + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml + """ +} diff --git a/modules/nf-core/gatk4/markduplicates/meta.yml b/modules/nf-core/gatk4/markduplicates/meta.yml new file mode 100644 index 00000000..ddf98d2f --- /dev/null +++ b/modules/nf-core/gatk4/markduplicates/meta.yml @@ -0,0 +1,72 @@ +name: gatk4_markduplicates +description: This tool locates and tags duplicate reads in a BAM or SAM file, where duplicate reads are defined as originating from a single fragment of DNA. +keywords: + - markduplicates + - bam + - sort +tools: + - gatk4: + description: + Developed in the Data Sciences Platform at the Broad Institute, the toolkit offers a wide variety of tools + with a primary focus on variant discovery and genotyping. Its powerful processing engine + and high-performance computing features make it capable of taking on projects of any size. + homepage: https://gatk.broadinstitute.org/hc/en-us + documentation: https://gatk.broadinstitute.org/hc/en-us/articles/360037052812-MarkDuplicates-Picard- + tool_dev_url: https://github.com/broadinstitute/gatk + doi: 10.1158/1538-7445.AM2017-3590 + licence: ["MIT"] + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: Sorted BAM file + pattern: "*.{bam}" + - fasta: + type: file + description: Fasta file + pattern: "*.{fasta}" + - fasta_fai: + type: file + description: Fasta index file + pattern: "*.{fai}" + +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" + - bam: + type: file + description: Marked duplicates BAM file + pattern: "*.{bam}" + - cram: + type: file + description: Marked duplicates CRAM file + pattern: "*.{cram}" + - bai: + type: file + description: BAM index file + pattern: "*.{bam.bai}" + - crai: + type: file + description: CRAM index file + pattern: "*.{cram.crai}" + - metrics: + type: file + description: Duplicate metrics file generated by GATK + pattern: "*.{metrics.txt}" + +authors: + - "@ajodeh-juma" + - "@FriederikeHanssen" + - "@maxulysse" diff --git a/modules/nf-core/samtools/sort/main.nf b/modules/nf-core/samtools/sort/main.nf new file mode 100644 index 00000000..18a3e1dc --- /dev/null +++ b/modules/nf-core/samtools/sort/main.nf @@ -0,0 +1,49 @@ +process SAMTOOLS_SORT { + tag "$meta.id" + label 'process_medium' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.18--h50ea8bc_1' : + 'biocontainers/samtools:1.18--h50ea8bc_1' }" + + input: + tuple val(meta), path(bam) + + output: + tuple val(meta), path("*.bam"), emit: bam + tuple val(meta), path("*.csi"), emit: csi, 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.prefix}" + if ("$bam" == "${prefix}.bam") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" + """ + samtools sort \\ + $args \\ + -@ $task.cpus \\ + -o ${prefix}.bam \\ + -T $prefix \\ + $bam + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.prefix}" + """ + touch ${prefix}.bam + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/samtools/sort/meta.yml b/modules/nf-core/samtools/sort/meta.yml new file mode 100644 index 00000000..2200de72 --- /dev/null +++ b/modules/nf-core/samtools/sort/meta.yml @@ -0,0 +1,51 @@ +name: samtools_sort +description: Sort SAM/BAM/CRAM file +keywords: + - sort + - bam + - sam + - cram +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: Sorted BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - csi: + type: file + description: BAM index file (optional) + pattern: "*.csi" +authors: + - "@drpatelh" + - "@ewels" +maintainers: + - "@drpatelh" + - "@ewels" diff --git a/nextflow_schema.json b/nextflow_schema.json index d75b428d..f52ffdb0 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -213,7 +213,6 @@ }, "ref_data_genome_bwa_index": { "type": "string", - "format": "directory-path", "description": "Path to directory containing reference genome BWA indices.", "fa_icon": "far fa-file-code", "hidden": true @@ -247,6 +246,12 @@ "description": "Path to reference genome GRIDSS index file.", "fa_icon": "far fa-file-code", "hidden": true + }, + "ref_data_genome_star_index": { + "type": "string", + "description": "Path to reference genome STAR index file.", + "fa_icon": "far fa-file-code", + "hidden": true } } }, diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index fb021e91..ab156969 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -35,9 +35,9 @@ workflow AMBER_PROFILING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> diff --git a/subworkflows/local/bamtools_metrics.nf b/subworkflows/local/bamtools_metrics.nf index ba6aebee..ca446828 100644 --- a/subworkflows/local/bamtools_metrics.nf +++ b/subworkflows/local/bamtools_metrics.nf @@ -31,7 +31,7 @@ workflow BAMTOOLS_METRICS { return [ meta, Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_DNA_TUMOR), ] } .branch { meta, bam, bai -> @@ -48,7 +48,7 @@ workflow BAMTOOLS_METRICS { return [ meta, Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, bam, bai -> diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index 322575cc..c425cd55 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -36,9 +36,9 @@ workflow COBALT_PROFILING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> diff --git a/subworkflows/local/cuppa_prediction.nf b/subworkflows/local/cuppa_prediction.nf index bc486322..66ea086f 100644 --- a/subworkflows/local/cuppa_prediction.nf +++ b/subworkflows/local/cuppa_prediction.nf @@ -84,7 +84,7 @@ workflow CUPPA_PREDICTION { def has_tumor_dna = Utils.hasTumorDna(meta) def has_normal_dna = Utils.hasNormalDna(meta) - def has_tumor_rna = Utils.hasTumorRnaBam(meta) + def has_tumor_rna = Utils.hasTumorRna(meta) def has_dna_inputs = (purple_dir && linx_annotation_dir) def has_rna_inputs = isofox_dir diff --git a/subworkflows/local/flagstat_metrics.nf b/subworkflows/local/flagstat_metrics.nf index cd2344a9..83be4cd8 100644 --- a/subworkflows/local/flagstat_metrics.nf +++ b/subworkflows/local/flagstat_metrics.nf @@ -27,7 +27,7 @@ workflow FLAGSTAT_METRICS { return [ meta, Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_DNA_TUMOR), ] } .branch { meta, bam, bai -> @@ -44,7 +44,7 @@ workflow FLAGSTAT_METRICS { return [ meta, Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, bam, bai -> diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index 71aed28a..7bbe3d79 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -52,9 +52,9 @@ workflow GRIDSS_SVPREP_CALLING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf index a82d7629..7e40c379 100644 --- a/subworkflows/local/isofox_quantification.nf +++ b/subworkflows/local/isofox_quantification.nf @@ -11,6 +11,7 @@ workflow ISOFOX_QUANTIFICATION { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_rna_bam // channel: [mandatory] [ meta, bam, bai ] // Reference data genome_fasta // channel: [mandatory] /path/to/genome_fasta @@ -31,19 +32,28 @@ workflow ISOFOX_QUANTIFICATION { // channel: [ versions.yml ] ch_versions = Channel.empty() - // Sort inputs - // channel: [ meta ] - ch_inputs_sorted = ch_inputs - .branch { meta -> + // Select input sources and sort + // channel: runnable: [ meta, tumor_bam, tumor_bai ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_tumor_rna_bam + .map { meta, tumor_bam, tumor_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_RNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_RNA_TUMOR), + ] + } + .branch { meta, tumor_bam, tumor_bai -> def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.ISOFOX_DIR) - runnable: Utils.hasTumorRnaBam(meta) && !has_existing + runnable: tumor_bam && !has_existing skip: true + meta } // Create process input channel - // channel: [ meta_isofox, tumor_bam_rna ] + // channel: [ meta_isofox, tumor_bam, tumor_bai ] ch_isofox_inputs = ch_inputs_sorted.runnable - .map { meta -> + .map { meta, tumor_bam, tumor_bai -> def meta_isofox = [ key: meta.group_id, @@ -51,7 +61,7 @@ workflow ISOFOX_QUANTIFICATION { sample_id: Utils.getTumorRnaSampleName(meta), ] - return [meta_isofox, Utils.getTumorRnaBam(meta), Utils.getTumorRnaBai(meta)] + return [meta_isofox, tumor_bam, tumor_bai] } // Run process diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index eb8ac01d..be91e6d8 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -16,6 +16,7 @@ workflow LILAC_CALLING { ch_inputs // channel: [mandatory] [ meta ] ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] + ch_tumor_rna_bam // channel: [mandatory] [ meta, bam, bai ] ch_purple // channel: [mandatory] [ meta, purple_dir ] // Reference data @@ -41,9 +42,9 @@ workflow LILAC_CALLING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> @@ -161,22 +162,6 @@ workflow LILAC_CALLING { } - // Create channel for RNA BAMs - // channel: [ meta, tumor_rna_bam, tumor_rna_bai ] - ch_rna_inputs_ready = ch_inputs - .map { meta -> - - def bam = [] - def bai = [] - - if (Utils.hasTumorRnaBam(meta)) { - bam = Utils.getTumorRnaBam(meta) - bai = Utils.getTumorRnaBai(meta) - } - - return [meta, bam, bai] - } - // // MODULE: LILAC // @@ -184,7 +169,7 @@ workflow LILAC_CALLING { // channel: [ meta_lilac, normal_dna_bam, normal_dna_bai, tumor_dna_bam, tumor_dna_bai, tumor_rna_bam, tumor_rna_bai, purple_dir ] ch_lilac_inputs = WorkflowOncoanalyser.groupByMeta( ch_dna_inputs_ready, - ch_rna_inputs_ready, + ch_tumor_rna_bam, ch_purple, ) .map { meta, tbam_dna, tbai_dna, nbam_dna, nbai_dna, tbam_rna, tbai_rna, purple_dir -> diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index fc7b724f..c04a9540 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -14,6 +14,7 @@ include { BWA_INDEX } from '../../modules/nf-core/bwa/index/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_BWA_INDEX } from '../../modules/local/custom/extract_tarball/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_HMF_DATA } from '../../modules/local/custom/extract_tarball/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_PANEL_DATA } from '../../modules/local/custom/extract_tarball/main' +include { CUSTOM_EXTRACTTARBALL as DECOMP_STAR_INDEX } from '../../modules/local/custom/extract_tarball/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_VIRUSBREAKEND_DB } from '../../modules/local/custom/extract_tarball/main' include { GRIDSS_INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../modules/local/gridss/index/main' include { GRIDSS_INDEX as GRIDSS_INDEX } from '../../modules/local/gridss/index/main' @@ -103,6 +104,19 @@ workflow PREPARE_REFERENCE { ch_genome_bwa_index_bseq = Channel.value(params.ref_data_genome_bwa_index_bseq) ch_genome_bwa_index_biidx = Channel.value(params.ref_data_genome_bwa_index_biidx) + // + // Decompress STAR index + // + ch_genome_star_index = params.ref_data_genome_star_index ? file(params.ref_data_genome_star_index) : [] + if (run_config.has_rna_fastq && run_config.stages.alignment && params.ref_data_genome_star_index.endsWith('.tar.gz')) { + ch_genome_star_index_inputs = [ + [id: 'star_index'], + file(params.ref_data_genome_star_index), + ] + DECOMP_STAR_INDEX(ch_genome_star_index_inputs) + ch_genome_star_index = DECOMP_STAR_INDEX.out.dir + } + // // Set VIRUSBreakend database path / stage, unpack if required // @@ -181,6 +195,7 @@ workflow PREPARE_REFERENCE { genome_bwa_index_biidx = ch_genome_bwa_index_biidx // path: genome_bwa_index_biidx genome_bwa_index_image = ch_genome_bwa_index_image // path: genome_bwa_index_image genome_gridss_index = ch_genome_gridss_index // path: genome_gridss_index + genome_star_index = ch_genome_star_index // path: genome_star_index genome_version = params.ref_data_genome_version // val: genome_version virusbreakenddb = ch_virusbreakenddb // path: VIRUSBreakend database diff --git a/subworkflows/local/read_alignment.nf b/subworkflows/local/read_alignment_dna.nf similarity index 96% rename from subworkflows/local/read_alignment.nf rename to subworkflows/local/read_alignment_dna.nf index a876a132..a9529e57 100644 --- a/subworkflows/local/read_alignment.nf +++ b/subworkflows/local/read_alignment_dna.nf @@ -2,7 +2,7 @@ include { BWA_MEM2 } from '../../modules/local/bwa/mem2/main' include { FASTP } from '../../modules/local/fastp/main' include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' -workflow READ_ALIGNMENT { +workflow READ_ALIGNMENT_DNA { take: // Sample data ch_inputs // channel: [mandatory] [ meta ] @@ -162,7 +162,7 @@ workflow READ_ALIGNMENT { ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) // Combine BAMs and BAIs - // channel: [ meta, sample_type, bam, bai ] + // channel: [ meta_bwa, sample_type, bam, bai ] ch_bams_flat = WorkflowOncoanalyser.groupByMeta( BWA_MEM2.out.bam.map { meta_bwa, bam -> [meta_bwa, meta_bwa.sample_type] }, BWA_MEM2.out.bam, @@ -171,6 +171,7 @@ workflow READ_ALIGNMENT { // Reunite BAMs // First, count expected BAMs per sample for non-blocking groupTuple op + // channel: [ meta_count, group_size ] ch_sample_fastq_counts = ch_bwa_inputs .map { meta_bwa, reads_fwd, reads_rev -> @@ -184,12 +185,12 @@ workflow READ_ALIGNMENT { .groupTuple() .map { meta_count, meta_bwas -> return [meta_count, meta_bwas.size()] } - // Now, group with expected size then sort into tumor and normal channels + // channel: [ meta_group, [bam, ...], [bai, ...] ] ch_bams_united = ch_sample_fastq_counts .cross( // First element to match meta_count above for `cross` - ch_bams_flat.map { meta, sample_type, bam, bai -> [[key: meta.key, sample_type: sample_type], bam, bai] } + ch_bams_flat.map { meta_bwa, sample_type, bam, bai -> [[key: meta_bwa.key, sample_type: sample_type], bam, bai] } ) .map { count_tuple, bam_tuple -> diff --git a/subworkflows/local/read_alignment_rna.nf b/subworkflows/local/read_alignment_rna.nf new file mode 100644 index 00000000..61736170 --- /dev/null +++ b/subworkflows/local/read_alignment_rna.nf @@ -0,0 +1,197 @@ +include { GATK4_MARKDUPLICATES } from '../../modules/nf-core/gatk4/markduplicates/main' +include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' +include { SAMBAMBA_MERGE } from '../../modules/local/sambamba/merge/main' +include { SAMTOOLS_SORT } from '../../modules/nf-core/samtools/sort/main' +include { STAR } from '../../modules/local/star/main' + +workflow READ_ALIGNMENT_RNA { + take: + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + + // Reference data + genome_star_index // channel: [mandatory] /path/to/genome_star_index/ + + main: + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Sort inputs + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_RNA_TUMOR) + runnable: Utils.hasTumorRnaFastq(meta) && !has_existing + skip: true + } + + // Create FASTQ input channel + // channel: [ meta_fastq, fastq_fwd, fastq_rev ] + ch_fastq_inputs = ch_inputs_sorted.runnable + .flatMap { meta -> + def meta_sample = Utils.getTumorRnaSample(meta) + meta_sample + .getAt(Constants.FileType.FASTQ) + .collect { key, fps -> + def (library_id, lane) = key + + def meta_fastq = [ + key: meta.group_id, + id: "${meta.group_id}_${meta_sample.sample_id}", + sample_id: meta_sample.sample_id, + library_id: library_id, + lane: lane, + ] + + return [meta_fastq, fps['fwd'], fps['rev']] + } + } + + // + // MODULE: STAR + // + // Create process input channel + // channel: [ meta_star, fastq_fwd, fastq_rev ] + ch_star_inputs = ch_fastq_inputs + .map { meta_fastq, fastq_fwd, fastq_rev -> + def meta_star = [ + *:meta_fastq, + + + // TODO(SW): understand target format + read_group: "${meta_fastq.sample_id}.${meta_fastq.library_id}.${meta_fastq.lane}", + + + ] + + return [meta_star, fastq_fwd, fastq_rev] + } + + // Run process + STAR( + ch_star_inputs, + genome_star_index, + ) + + ch_versions = ch_versions.mix(STAR.out.versions) + + // + // MODULE: SAMtools sort + // + // Create process input channel + // channel: [ meta_sort, bam ] + ch_sort_inputs = STAR.out.bam + .map { meta_star, bam -> + def meta_sort = [ + *:meta_star, + prefix: meta_star.read_group, + ] + + return [meta_sort, bam] + } + + // Run process + SAMTOOLS_SORT( + ch_sort_inputs, + ) + + ch_versions = ch_versions.mix(SAMTOOLS_SORT.out.versions) + + // + // MODULE: Sambamba index + // + SAMBAMBA_INDEX( + SAMTOOLS_SORT.out.bam, + ) + + ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) + + // + // MODULE: Sambamba merge + // + // Combine BAMs and BAIs + // channel: [ meta_star, bam, bai ] + ch_bams_flat = WorkflowOncoanalyser.groupByMeta( + SAMTOOLS_SORT.out.bam, + SAMBAMBA_INDEX.out.bai, + ) + + // Reunite BAMs + // First, count expected BAMs per sample for non-blocking groupTuple op + ch_sample_fastq_counts = ch_star_inputs + .map { meta_star, reads_fwd, reads_rev -> + def meta_count = [key: meta_star.key] + return [meta_count, meta_star] + } + .groupTuple() + .map { meta_count, meta_stars -> return [meta_count, meta_stars.size()] } + + // Now, group with expected size then sort into tumor and normal channels + ch_bams_united = ch_sample_fastq_counts + .cross( + // First element to match meta_count above for `cross` + ch_bams_flat.map { meta_star, bam, bai -> [[key: meta_star.key], bam, bai] } + ) + .map { count_tuple, bam_tuple -> + + def group_size = count_tuple[1] + def (meta_bam, bam, bai) = bam_tuple + + def meta_group = [ + *:meta_bam, + ] + + return tuple(groupKey(meta_group, group_size), bam, bai) + } + .groupTuple() + + // Create process input channel + // channel: [ meta_merge, [bams, ...], [bais, ...] ] + ch_merge_inputs = WorkflowOncoanalyser.restoreMeta(ch_bams_united, ch_inputs) + .map { meta, bams, bais -> + def meta_merge = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorRnaSampleName(meta), + ] + return [meta_merge, bams, bais] + } + + // Run process + SAMBAMBA_MERGE( + ch_merge_inputs, + ) + + ch_versions = ch_versions.mix(SAMBAMBA_MERGE.out.versions) + + // + // MODULE: GATK4 markduplicates + // + GATK4_MARKDUPLICATES( + SAMBAMBA_MERGE.out.bam, + [], + [], + ) + + ch_versions = ch_versions.mix(GATK4_MARKDUPLICATES.out.versions) + + // Combine BAMs and BAIs + // channel: [ meta, bam, bai ] + ch_bams_ready = WorkflowOncoanalyser.groupByMeta( + WorkflowOncoanalyser.restoreMeta(GATK4_MARKDUPLICATES.out.bam, ch_inputs), + WorkflowOncoanalyser.restoreMeta(GATK4_MARKDUPLICATES.out.bai, ch_inputs), + ) + + // Set outputs + // channel: [ meta, bam, bai ] + ch_bam_out = Channel.empty() + .mix( + ch_bams_ready, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, + ) + + emit: + rna_tumor = ch_bam_out // channel: [ meta, bam, bai ] + versions = ch_versions // channel: [ versions.yml ] +} diff --git a/subworkflows/local/sage_append.nf b/subworkflows/local/sage_append.nf index 29a9c438..ad2e892b 100644 --- a/subworkflows/local/sage_append.nf +++ b/subworkflows/local/sage_append.nf @@ -11,14 +11,15 @@ include { SAGE_APPEND as GERMLINE } from '../../modules/local/sage/append/main' workflow SAGE_APPEND { take: // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_purple_dir // channel: [mandatory] [ meta, purple_dir ] + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_rna_bam // channel: [mandatory] [ meta, bam, bai ] + ch_purple_dir // channel: [mandatory] [ meta, purple_dir ] // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_version // channel: [mandatory] genome version - genome_fai // channel: [mandatory] /path/to/genome_fai - genome_dict // channel: [mandatory] /path/to/genome_dict + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict main: // Channel for version.yml files @@ -26,17 +27,22 @@ workflow SAGE_APPEND { ch_versions = Channel.empty() // Select input sources and sort - // channel: runnable: [ meta, purple_dir ] + // channel: runnable: [ meta, tumor_bam, tumor_bai, purple_dir ] // channel: skip: [ meta ] - ch_inputs_sorted = ch_purple_dir - .map { meta, purple_dir -> + ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_rna_bam, + ch_purple_dir, + ) + .map { meta, tumor_bam, tumor_bai, purple_dir -> return [ meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_RNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_RNA_TUMOR), Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), ] } - .branch { meta, purple_dir -> - runnable: purple_dir + .branch { meta, tumor_bam, tumor_bai, purple_dir -> + runnable: tumor_bam && purple_dir skip: true return meta } @@ -45,15 +51,15 @@ workflow SAGE_APPEND { // MODULE: SAGE append germline // // Select inputs that are eligible to run - // channel: runnable: [ meta, purple_dir ] + // channel: runnable: [ meta, tumor_bam, tumor_bai, purple_dir ] // channel: skip: [ meta ] ch_inputs_germline_sorted = ch_inputs_sorted.runnable - .branch { meta, purple_dir -> + .branch { meta, tumor_bam, tumor_bai, purple_dir -> def tumor_dna_id = Utils.getTumorDnaSampleName(meta) - def has_normal_dna = Utils.hasNormalDnaBam(meta) - def has_tumor_rna = Utils.hasTumorRnaBam(meta) + def has_normal_dna = Utils.hasNormalDna(meta) + def has_tumor_rna = Utils.hasTumorRna(meta) def has_smlv_germline = file(purple_dir).resolve("${tumor_dna_id}.purple.germline.vcf.gz") def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_APPEND_VCF_NORMAL) @@ -63,9 +69,9 @@ workflow SAGE_APPEND { } // Create process input channel - // channel: [ meta_append, purple_smlv_vcf, tumor_rna_bam, tumor_rna_bai ] + // channel: [ meta_append, purple_smlv_vcf, tumor_bam, tumor_bai ] ch_sage_append_germline_inputs = ch_inputs_germline_sorted.runnable - .map { meta, purple_dir -> + .map { meta, tumor_bam, tumor_bai, purple_dir -> def tumor_dna_id = Utils.getTumorDnaSampleName(meta) @@ -76,11 +82,9 @@ workflow SAGE_APPEND { dna_id: Utils.getNormalDnaSampleName(meta), ] - def tumor_rna_bam = Utils.getTumorRnaBam(meta) - def tumor_rna_bai = Utils.getTumorRnaBai(meta) def purple_smlv_vcf = file(purple_dir).resolve("${tumor_dna_id}.purple.germline.vcf.gz") - return [meta_append, purple_smlv_vcf, tumor_rna_bam, tumor_rna_bai] + return [meta_append, purple_smlv_vcf, tumor_bam, tumor_bai] } // Run process @@ -98,14 +102,14 @@ workflow SAGE_APPEND { // MODULE: SAGE append somatic // // Select inputs that are eligible to run - // channel: runnable: [ meta, purple_dir ] + // channel: runnable: [ meta, tumor_bam, tumor_bai, purple_dir ] // channel: skip: [ meta ] ch_inputs_somatic_sorted = ch_inputs_sorted.runnable - .branch { meta, purple_dir -> + .branch { meta, tumor_bam, tumor_bai, purple_dir -> def tumor_dna_id = Utils.getTumorDnaSampleName(meta) def has_tumor_dna = Utils.hasTumorDna(meta) - def has_tumor_rna = Utils.hasTumorRnaBam(meta) + def has_tumor_rna = Utils.hasTumorRna(meta) def has_smlv_somatic = file(purple_dir).resolve("${tumor_dna_id}.purple.somatic.vcf.gz") def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_APPEND_VCF_TUMOR) @@ -115,9 +119,9 @@ workflow SAGE_APPEND { } // Create process input channel - // channel: [ meta_append, purple_smlv_vcf, tumor_rna_bam, tumor_rna_bai ] + // channel: [ meta_append, purple_smlv_vcf, tumor_bam, tumor_bai ] ch_sage_append_somatic_inputs = ch_inputs_somatic_sorted.runnable - .map { meta, purple_dir -> + .map { meta, tumor_bam, tumor_bai, purple_dir -> def tumor_dna_id = Utils.getTumorDnaSampleName(meta) @@ -128,11 +132,9 @@ workflow SAGE_APPEND { dna_id: Utils.getTumorDnaSampleName(meta), ] - def tumor_rna_bam = Utils.getTumorRnaBam(meta) - def tumor_rna_bai = Utils.getTumorRnaBai(meta) def purple_smlv_vcf = file(purple_dir).resolve("${tumor_dna_id}.purple.somatic.vcf.gz") - return [meta_append, purple_smlv_vcf, tumor_rna_bam, tumor_rna_bai] + return [meta_append, purple_smlv_vcf, tumor_bam, tumor_bai] } // Run process diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index cdec723b..92342463 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -45,9 +45,9 @@ workflow SAGE_CALLING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_NORMAL), + Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index 87e16488..c13c940b 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -43,7 +43,7 @@ workflow VIRUSBREAKEND_CALLING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), ] } .branch { meta, tumor_bam, tumor_bai -> diff --git a/workflows/targeted.nf b/workflows/targeted.nf index d8507996..41008cf1 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -79,7 +79,8 @@ include { ORANGE_REPORTING } from '../subworkflows/local/orange_reporting' include { PAVE_ANNOTATION } from '../subworkflows/local/pave_annotation' include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' -include { READ_ALIGNMENT } from '../subworkflows/local/read_alignment' +include { READ_ALIGNMENT_DNA } from '../subworkflows/local/read_alignment_dna' +include { READ_ALIGNMENT_RNA } from '../subworkflows/local/read_alignment_rna' include { READ_PROCESSING } from '../subworkflows/local/read_processing' include { SAGE_APPEND } from '../subworkflows/local/sage_append' include { SAGE_CALLING } from '../subworkflows/local/sage_calling' @@ -105,7 +106,6 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft samplesheet = Utils.getFileObject(params.input) workflow TARGETED { - // Create channel for versions // channel: [ versions.yml ] ch_versions = Channel.empty() @@ -126,14 +126,15 @@ workflow TARGETED { gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config // - // SUBWORKFLOW: Align reads + // SUBWORKFLOW: Run read alignment to generate BAMs // // channel: [ meta, [bam, ...], [bai, ...] ] ch_align_dna_tumor_out = Channel.empty() ch_align_dna_normal_out = Channel.empty() + ch_align_rna_tumor_out = Channel.empty() if (run_config.stages.alignment) { - READ_ALIGNMENT( + READ_ALIGNMENT_DNA( ch_inputs, ref_data.genome_fasta, ref_data.genome_bwa_index, @@ -142,20 +143,30 @@ workflow TARGETED { params.max_fastq_records, ) - ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) + READ_ALIGNMENT_RNA( + ch_inputs, + ref_data.genome_star_index, + ) + + ch_versions = ch_versions.mix( + READ_ALIGNMENT_DNA.out.versions, + READ_ALIGNMENT_RNA.out.versions, + ) - ch_align_dna_tumor_out = ch_align_dna_tumor_out.mix(READ_ALIGNMENT.out.dna_tumor) - ch_align_dna_normal_out = ch_align_dna_normal_out.mix(READ_ALIGNMENT.out.dna_normal) + ch_align_dna_tumor_out = ch_align_dna_tumor_out.mix(READ_ALIGNMENT_DNA.out.dna_tumor) + ch_align_dna_normal_out = ch_align_dna_normal_out.mix(READ_ALIGNMENT_DNA.out.dna_normal) + ch_align_rna_tumor_out = ch_align_rna_tumor_out.mix(READ_ALIGNMENT_RNA.out.rna_tumor) } else { ch_align_dna_tumor_out = ch_inputs.map { meta -> [meta, [], []] } ch_align_dna_normal_out = ch_inputs.map { meta -> [meta, [], []] } + ch_align_rna_tumor_out = ch_inputs.map { meta -> [meta, [], []] } } // - // SUBWORKFLOW: Process read alignments + // SUBWORKFLOW: Run MarkDups for DNA BAMs // // channel: [ meta, bam, bai ] ch_process_dna_tumor_out = Channel.empty() @@ -204,6 +215,7 @@ workflow TARGETED { ISOFOX_QUANTIFICATION( ch_inputs, + ch_align_rna_tumor_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -483,6 +495,7 @@ workflow TARGETED { SAGE_APPEND( ch_inputs, + ch_align_rna_tumor_out, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, @@ -624,6 +637,7 @@ workflow TARGETED { ch_inputs, ch_process_dna_tumor_out, ch_process_dna_normal_out, + ch_align_rna_tumor_out, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index aa706180..8405a5fa 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -83,7 +83,8 @@ include { ORANGE_REPORTING } from '../subworkflows/local/orange_reporting' include { PAVE_ANNOTATION } from '../subworkflows/local/pave_annotation' include { PREPARE_REFERENCE } from '../subworkflows/local/prepare_reference' include { PURPLE_CALLING } from '../subworkflows/local/purple_calling' -include { READ_ALIGNMENT } from '../subworkflows/local/read_alignment' +include { READ_ALIGNMENT_DNA } from '../subworkflows/local/read_alignment_dna' +include { READ_ALIGNMENT_RNA } from '../subworkflows/local/read_alignment_rna' include { READ_PROCESSING } from '../subworkflows/local/read_processing' include { SAGE_APPEND } from '../subworkflows/local/sage_append' include { SAGE_CALLING } from '../subworkflows/local/sage_calling' @@ -133,14 +134,15 @@ workflow WGTS { gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config // - // SUBWORKFLOW: Align reads + // SUBWORKFLOW: Run read alignment to generate BAMs // // channel: [ meta, [bam, ...], [bai, ...] ] ch_align_dna_tumor_out = Channel.empty() ch_align_dna_normal_out = Channel.empty() + ch_align_rna_tumor_out = Channel.empty() if (run_config.stages.alignment) { - READ_ALIGNMENT( + READ_ALIGNMENT_DNA( ch_inputs, ref_data.genome_fasta, ref_data.genome_bwa_index, @@ -149,20 +151,30 @@ workflow WGTS { params.max_fastq_records, ) - ch_versions = ch_versions.mix(READ_ALIGNMENT.out.versions) + READ_ALIGNMENT_RNA( + ch_inputs, + ref_data.genome_star_index, + ) + + ch_versions = ch_versions.mix( + READ_ALIGNMENT_DNA.out.versions, + READ_ALIGNMENT_RNA.out.versions, + ) - ch_align_dna_tumor_out = ch_align_dna_tumor_out.mix(READ_ALIGNMENT.out.dna_tumor) - ch_align_dna_normal_out = ch_align_dna_normal_out.mix(READ_ALIGNMENT.out.dna_normal) + ch_align_dna_tumor_out = ch_align_dna_tumor_out.mix(READ_ALIGNMENT_DNA.out.dna_tumor) + ch_align_dna_normal_out = ch_align_dna_normal_out.mix(READ_ALIGNMENT_DNA.out.dna_normal) + ch_align_rna_tumor_out = ch_align_rna_tumor_out.mix(READ_ALIGNMENT_RNA.out.rna_tumor) } else { ch_align_dna_tumor_out = ch_inputs.map { meta -> [meta, [], []] } ch_align_dna_normal_out = ch_inputs.map { meta -> [meta, [], []] } + ch_align_rna_tumor_out = ch_inputs.map { meta -> [meta, [], []] } } // - // SUBWORKFLOW: Process read alignments + // SUBWORKFLOW: Run MarkDups for DNA BAMs // // channel: [ meta, bam, bai ] ch_process_dna_tumor_out = Channel.empty() @@ -205,6 +217,7 @@ workflow WGTS { ISOFOX_QUANTIFICATION( ch_inputs, + ch_align_rna_tumor_out, ref_data.genome_fasta, ref_data.genome_version, ref_data.genome_fai, @@ -485,6 +498,7 @@ workflow WGTS { SAGE_APPEND( ch_inputs, + ch_align_rna_tumor_out, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, @@ -671,6 +685,7 @@ workflow WGTS { ch_inputs, ch_process_dna_tumor_out, ch_process_dna_normal_out, + ch_align_rna_tumor_out, ch_purple_out, ref_data.genome_fasta, ref_data.genome_version, From 3220f7bd4f5653ff0836b76b1c4ddb9d9b7974e4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 15:14:34 +1100 Subject: [PATCH 353/562] Move, rename bwa-mem2 module --- modules/local/{bwa/mem2 => bwa-mem2/mem}/Dockerfile | 0 modules/local/{bwa/mem2 => bwa-mem2/mem}/main.nf | 0 subworkflows/local/read_alignment_dna.nf | 12 ++++++------ 3 files changed, 6 insertions(+), 6 deletions(-) rename modules/local/{bwa/mem2 => bwa-mem2/mem}/Dockerfile (100%) rename modules/local/{bwa/mem2 => bwa-mem2/mem}/main.nf (100%) diff --git a/modules/local/bwa/mem2/Dockerfile b/modules/local/bwa-mem2/mem/Dockerfile similarity index 100% rename from modules/local/bwa/mem2/Dockerfile rename to modules/local/bwa-mem2/mem/Dockerfile diff --git a/modules/local/bwa/mem2/main.nf b/modules/local/bwa-mem2/mem/main.nf similarity index 100% rename from modules/local/bwa/mem2/main.nf rename to modules/local/bwa-mem2/mem/main.nf diff --git a/subworkflows/local/read_alignment_dna.nf b/subworkflows/local/read_alignment_dna.nf index a9529e57..bd4bea84 100644 --- a/subworkflows/local/read_alignment_dna.nf +++ b/subworkflows/local/read_alignment_dna.nf @@ -1,4 +1,4 @@ -include { BWA_MEM2 } from '../../modules/local/bwa/mem2/main' +include { BWAMEM2_ALIGN } from '../../modules/local/bwa-mem2/mem/main' include { FASTP } from '../../modules/local/fastp/main' include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' @@ -142,7 +142,7 @@ workflow READ_ALIGNMENT_DNA { } // Run process - BWA_MEM2( + BWAMEM2_ALIGN( ch_bwa_inputs, genome_fasta, genome_bwa_index, @@ -150,13 +150,13 @@ workflow READ_ALIGNMENT_DNA { genome_bwa_index_biidx, ) - ch_versions = ch_versions.mix(BWA_MEM2.out.versions) + ch_versions = ch_versions.mix(BWAMEM2_ALIGN.out.versions) // // MODULE: Sambamba index // SAMBAMBA_INDEX( - BWA_MEM2.out.bam, + BWAMEM2_ALIGN.out.bam, ) ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) @@ -164,8 +164,8 @@ workflow READ_ALIGNMENT_DNA { // Combine BAMs and BAIs // channel: [ meta_bwa, sample_type, bam, bai ] ch_bams_flat = WorkflowOncoanalyser.groupByMeta( - BWA_MEM2.out.bam.map { meta_bwa, bam -> [meta_bwa, meta_bwa.sample_type] }, - BWA_MEM2.out.bam, + BWAMEM2_ALIGN.out.bam.map { meta_bwa, bam -> [meta_bwa, meta_bwa.sample_type] }, + BWAMEM2_ALIGN.out.bam, SAMBAMBA_INDEX.out.bai, ) From b9e88fe5fd2edef31a552587b7be8a6656b4ae48 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 15:34:29 +1100 Subject: [PATCH 354/562] Fix bwa-mem2 process name --- modules/local/bwa-mem2/mem/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index ee76a9cc..280bb829 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -1,4 +1,4 @@ -process BWA_MEM2 { +process BWAMEM2_ALIGN { tag "${meta.id}" label 'process_high' From 781d883a80a1757587d1026584e07c3b1cd0b298 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 15:38:51 +1100 Subject: [PATCH 355/562] Set STAR process label to 'process_high' --- modules/local/star/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/star/main.nf b/modules/local/star/main.nf index fc906880..2213bf47 100644 --- a/modules/local/star/main.nf +++ b/modules/local/star/main.nf @@ -1,6 +1,6 @@ process STAR { tag "${meta.id}" - label 'process_medium' + label 'process_high' container 'quay.io/biocontainers/star:2.7.3a--0' From 063aa3a08ccd0d13156c6296480cb18852b6f225 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 15:58:46 +1100 Subject: [PATCH 356/562] Fix incomplete container URL for SAMtools sort --- modules/nf-core/samtools/sort/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/samtools/sort/main.nf b/modules/nf-core/samtools/sort/main.nf index 18a3e1dc..8aaf9a5b 100644 --- a/modules/nf-core/samtools/sort/main.nf +++ b/modules/nf-core/samtools/sort/main.nf @@ -5,7 +5,7 @@ process SAMTOOLS_SORT { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/samtools:1.18--h50ea8bc_1' : - 'biocontainers/samtools:1.18--h50ea8bc_1' }" + 'quay.io/biocontainers/samtools:1.18--h50ea8bc_1' }" input: tuple val(meta), path(bam) From 914edaba3c20845c5298cfc90f78eb02c9a38c7f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 16:11:14 +1100 Subject: [PATCH 357/562] Handle when read count less than max read split --- modules/local/sambamba/merge/main.nf | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/modules/local/sambamba/merge/main.nf b/modules/local/sambamba/merge/main.nf index 2551ed2f..f0590530 100644 --- a/modules/local/sambamba/merge/main.nf +++ b/modules/local/sambamba/merge/main.nf @@ -14,10 +14,19 @@ process SAMBAMBA_MERGE { script: """ - sambamba merge \\ - --nthreads ${task.cpus} \\ - ${meta.sample_id}.bam \\ - ${bams} + # NOTE(SW): single BAM when read count is less than max split count; merge expects at least two BAMs + if [[ \$(tr -cd ' ' <<< ${bams} | wc -c) -eq 0 ]]; then + + ln -s ${bams} ${meta.sample_id}.bam; + + else + + sambamba merge \\ + --nthreads ${task.cpus} \\ + ${meta.sample_id}.bam \\ + ${bams} + + fi; cat <<-END_VERSIONS > versions.yml "${task.process}": From 2d8c76cb798c6317491bb58a2b23f2568c696318 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 16:33:54 +1100 Subject: [PATCH 358/562] Correctly format RG arg for STAR --- modules/local/star/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/star/main.nf b/modules/local/star/main.nf index 2213bf47..b58868ca 100644 --- a/modules/local/star/main.nf +++ b/modules/local/star/main.nf @@ -41,7 +41,7 @@ process STAR { --outFilterMultimapNmax 10 \\ --outFilterScoreMinOverLread 0.33 \\ --outSAMattributes All \\ - --outSAMattrRGline 'ID:${meta.read_group} SM:${meta.sample_id}' \\ + --outSAMattrRGline ID:${meta.read_group} SM:${meta.sample_id} \\ --outSAMtype BAM Unsorted \\ --outSAMunmapped Within \\ --runRNGseed 0 From 8749d4524d18e5ce6cae28c7871f2c7c14f52a11 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 16:50:28 +1100 Subject: [PATCH 359/562] Fix bwa-mem2 bi-index variable name typo --- conf/hmf_genomes.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/hmf_genomes.config b/conf/hmf_genomes.config index 868315a9..42b4fba7 100644 --- a/conf/hmf_genomes.config +++ b/conf/hmf_genomes.config @@ -26,7 +26,7 @@ params { dict = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" bwa_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz" bwa_index_bseq = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" - bwa_index_biiseq= "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" + bwa_index_biidx = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" star_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/star_index/gencode_38/2.7.3a.tar.gz" From de1aad043cdfef72832035635b4c499ed0ebd0a4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 17:03:23 +1100 Subject: [PATCH 360/562] Adjust, fix bwa-mem2 index handling --- conf/hmf_genomes.config | 4 ++-- subworkflows/local/prepare_reference.nf | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/conf/hmf_genomes.config b/conf/hmf_genomes.config index 42b4fba7..e067a3a0 100644 --- a/conf/hmf_genomes.config +++ b/conf/hmf_genomes.config @@ -25,8 +25,8 @@ params { fai = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" dict = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" bwa_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz" - bwa_index_bseq = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" - bwa_index_biidx = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" + bwa_index_bseq = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" + bwa_index_biidx = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" star_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/star_index/gencode_38/2.7.3a.tar.gz" diff --git a/subworkflows/local/prepare_reference.nf b/subworkflows/local/prepare_reference.nf index c04a9540..453d4ec9 100644 --- a/subworkflows/local/prepare_reference.nf +++ b/subworkflows/local/prepare_reference.nf @@ -100,9 +100,9 @@ workflow PREPARE_REFERENCE { } } - // Explicitly create value channels for BWA MEM2 index files - ch_genome_bwa_index_bseq = Channel.value(params.ref_data_genome_bwa_index_bseq) - ch_genome_bwa_index_biidx = Channel.value(params.ref_data_genome_bwa_index_biidx) + // Explicitly set BWA MEM2 index file inputs + ch_genome_bwa_index_bseq = file(params.ref_data_genome_bwa_index_bseq) + ch_genome_bwa_index_biidx = file(params.ref_data_genome_bwa_index_biidx) // // Decompress STAR index From 7e0fb7f018ec5489dd3531010fc02ff3eeb8ce65 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 29 Feb 2024 17:46:08 +1100 Subject: [PATCH 361/562] Remove deprecated MarkDups `-multi_bam` argument --- modules/local/markdups/main.nf | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index a1805036..18dbd4eb 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -37,7 +37,6 @@ process MARKDUPS { -input_bam ${bams.join(',')} \\ \\ -form_consensus \\ - -multi_bam \\ ${umi_flags} \\ \\ -unmap_regions ${unmap_regions} \\ From 60a62eb5cdde30ea3ee03b2a32791bf3421ca599 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 29 Feb 2024 16:11:11 +0000 Subject: [PATCH 362/562] Template update for nf-core/tools version 2.13.1 --- .devcontainer/devcontainer.json | 20 + .editorconfig | 17 +- .gitattributes | 1 + .github/CONTRIBUTING.md | 24 +- .github/ISSUE_TEMPLATE/bug_report.yml | 4 +- .github/PULL_REQUEST_TEMPLATE.md | 6 +- .github/workflows/awsfulltest.yml | 13 +- .github/workflows/awstest.yml | 12 +- .github/workflows/branch.yml | 4 +- .github/workflows/ci.yml | 11 +- .github/workflows/clean-up.yml | 24 + .github/workflows/download_pipeline.yml | 72 +++ .github/workflows/fix-linting.yml | 72 ++- .github/workflows/linting.yml | 69 +-- .github/workflows/linting_comment.yml | 6 +- .github/workflows/release-announcements.yml | 75 +++ .gitpod.yml | 14 +- .pre-commit-config.yaml | 10 + .prettierignore | 2 + CHANGELOG.md | 2 +- CITATION.cff | 56 -- CITATIONS.md | 6 + CODE_OF_CONDUCT.md | 133 ++++- README.md | 92 +-- assets/email_template.html | 4 +- assets/email_template.txt | 2 +- assets/methods_description_template.yml | 12 +- assets/multiqc_config.yml | 8 +- assets/nf-core-oncoanalyser_logo_light.png | Bin 11358 -> 112262 bytes assets/schema_input.json | 21 +- assets/slackreport.json | 34 ++ bin/check_samplesheet.py | 262 --------- conf/base.config | 2 +- conf/igenomes.config | 8 + conf/modules.config | 17 +- .../images/nf-core-oncoanalyser_logo_dark.png | Bin 87060 -> 29358 bytes .../nf-core-oncoanalyser_logo_light.png | Bin 86949 -> 24726 bytes docs/output.md | 5 +- docs/usage.md | 154 ++--- lib/NfcoreSchema.groovy | 529 ------------------ lib/NfcoreTemplate.groovy | 313 ----------- lib/Utils.groovy | 47 -- lib/WorkflowMain.groovy | 93 --- lib/WorkflowOncoanalyser.groovy | 77 --- lib/nfcore_external_java_deps.jar | Bin 2291171 -> 0 bytes main.nf | 82 ++- modules.json | 29 +- modules/local/samplesheet_check.nf | 27 - .../custom/dumpsoftwareversions/main.nf | 24 - .../custom/dumpsoftwareversions/meta.yml | 34 -- .../templates/dumpsoftwareversions.py | 91 --- modules/nf-core/fastqc/environment.yml | 7 + modules/nf-core/fastqc/main.nf | 50 +- modules/nf-core/fastqc/meta.yml | 5 + modules/nf-core/fastqc/tests/main.nf.test | 212 +++++++ .../nf-core/fastqc/tests/main.nf.test.snap | 88 +++ modules/nf-core/fastqc/tests/tags.yml | 2 + modules/nf-core/multiqc/environment.yml | 7 + modules/nf-core/multiqc/main.nf | 10 +- modules/nf-core/multiqc/meta.yml | 11 +- modules/nf-core/multiqc/tests/main.nf.test | 84 +++ .../nf-core/multiqc/tests/main.nf.test.snap | 41 ++ modules/nf-core/multiqc/tests/tags.yml | 2 + nextflow.config | 105 ++-- nextflow_schema.json | 48 +- pyproject.toml | 19 +- subworkflows/local/input_check.nf | 44 -- .../main.nf | 251 +++++++++ .../nf-core/utils_nextflow_pipeline/main.nf | 126 +++++ .../nf-core/utils_nextflow_pipeline/meta.yml | 38 ++ .../tests/main.function.nf.test | 54 ++ .../tests/main.function.nf.test.snap | 20 + .../tests/main.workflow.nf.test | 111 ++++ .../tests/nextflow.config | 9 + .../utils_nextflow_pipeline/tests/tags.yml | 2 + .../nf-core/utils_nfcore_pipeline/main.nf | 440 +++++++++++++++ .../nf-core/utils_nfcore_pipeline/meta.yml | 24 + .../tests/main.function.nf.test | 134 +++++ .../tests/main.function.nf.test.snap | 166 ++++++ .../tests/main.workflow.nf.test | 29 + .../tests/main.workflow.nf.test.snap | 19 + .../tests/nextflow.config | 9 + .../utils_nfcore_pipeline/tests/tags.yml | 2 + .../nf-core/utils_nfvalidation_plugin/main.nf | 62 ++ .../utils_nfvalidation_plugin/meta.yml | 44 ++ .../tests/main.nf.test | 200 +++++++ .../tests/nextflow_schema.json | 96 ++++ .../utils_nfvalidation_plugin/tests/tags.yml | 2 + tower.yml | 5 + workflows/oncoanalyser.nf | 131 ++--- 90 files changed, 3223 insertions(+), 2106 deletions(-) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .github/workflows/clean-up.yml create mode 100644 .github/workflows/download_pipeline.yml create mode 100644 .github/workflows/release-announcements.yml create mode 100644 .pre-commit-config.yaml delete mode 100644 CITATION.cff create mode 100644 assets/slackreport.json delete mode 100755 bin/check_samplesheet.py delete mode 100755 lib/NfcoreSchema.groovy delete mode 100755 lib/NfcoreTemplate.groovy delete mode 100644 lib/Utils.groovy delete mode 100755 lib/WorkflowMain.groovy delete mode 100755 lib/WorkflowOncoanalyser.groovy delete mode 100644 lib/nfcore_external_java_deps.jar delete mode 100644 modules/local/samplesheet_check.nf delete mode 100644 modules/nf-core/custom/dumpsoftwareversions/main.nf delete mode 100644 modules/nf-core/custom/dumpsoftwareversions/meta.yml delete mode 100644 modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py create mode 100644 modules/nf-core/fastqc/environment.yml create mode 100644 modules/nf-core/fastqc/tests/main.nf.test create mode 100644 modules/nf-core/fastqc/tests/main.nf.test.snap create mode 100644 modules/nf-core/fastqc/tests/tags.yml create mode 100644 modules/nf-core/multiqc/environment.yml create mode 100644 modules/nf-core/multiqc/tests/main.nf.test create mode 100644 modules/nf-core/multiqc/tests/main.nf.test.snap create mode 100644 modules/nf-core/multiqc/tests/tags.yml delete mode 100644 subworkflows/local/input_check.nf create mode 100644 subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf create mode 100644 subworkflows/nf-core/utils_nextflow_pipeline/main.nf create mode 100644 subworkflows/nf-core/utils_nextflow_pipeline/meta.yml create mode 100644 subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test create mode 100644 subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test.snap create mode 100644 subworkflows/nf-core/utils_nextflow_pipeline/tests/main.workflow.nf.test create mode 100644 subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config create mode 100644 subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/main.nf create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/meta.yml create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml create mode 100644 subworkflows/nf-core/utils_nfvalidation_plugin/main.nf create mode 100644 subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml create mode 100644 subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test create mode 100644 subworkflows/nf-core/utils_nfvalidation_plugin/tests/nextflow_schema.json create mode 100644 subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml create mode 100644 tower.yml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..b290e090 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,20 @@ +{ + "name": "nfcore", + "image": "nfcore/gitpod:latest", + "remoteUser": "gitpod", + "runArgs": ["--privileged"], + + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Set *default* container specific settings.json values on container create. + "settings": { + "python.defaultInterpreterPath": "/opt/conda/bin/python" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": ["ms-python.python", "ms-python.vscode-pylance", "nf-core.nf-core-extensionpack"] + } + } +} diff --git a/.editorconfig b/.editorconfig index b78de6e6..dd9ffa53 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,7 +8,7 @@ trim_trailing_whitespace = true indent_size = 4 indent_style = space -[*.{md,yml,yaml,html,css,scss,js,cff}] +[*.{md,yml,yaml,html,css,scss,js}] indent_size = 2 # These files are edited and tested upstream in nf-core/modules @@ -18,7 +18,20 @@ end_of_line = unset insert_final_newline = unset trim_trailing_whitespace = unset indent_style = unset -indent_size = unset +[/subworkflows/nf-core/**] +charset = unset +end_of_line = unset +insert_final_newline = unset +trim_trailing_whitespace = unset +indent_style = unset [/assets/email*] indent_size = unset + +# ignore Readme +[README.md] +indent_style = unset + +# ignore python +[*.{py,md}] +indent_style = unset diff --git a/.gitattributes b/.gitattributes index 050bb120..7a2dabc2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ *.config linguist-language=nextflow +*.nf.test linguist-language=nextflow modules/nf-core/** linguist-generated subworkflows/nf-core/** linguist-generated diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c54ec775..2509ca62 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -9,6 +9,7 @@ Please use the pre-filled template to save time. However, don't be put off by this template - other more general issues and suggestions are welcome! Contributions to the code are even more welcome ;) +> [!NOTE] > If you need help using or modifying nf-core/oncoanalyser then the best place to ask is on the nf-core Slack [#oncoanalyser](https://nfcore.slack.com/channels/oncoanalyser) channel ([join our Slack here](https://nf-co.re/join/slack)). ## Contribution workflow @@ -25,6 +26,12 @@ If you're not used to this workflow with git, you can start with some [docs from ## Tests +You have the option to test your changes locally by running the pipeline. For receiving warnings about process selectors and other `debug` information, it is recommended to use the debug profile. Execute all the tests with the following command: + +```bash +nf-test test --profile debug,test,docker --verbose +``` + When you create a pull request with changes, [GitHub Actions](https://github.com/features/actions) will run automatic tests. Typically, pull-requests are only fully reviewed when these tests are passing, though of course we can help out before then. @@ -85,7 +92,7 @@ Once there, use `nf-core schema build` to add to `nextflow_schema.json`. Sensible defaults for process resource requirements (CPUs / memory / time) for a process should be defined in `conf/base.config`. These should generally be specified generic with `withLabel:` selectors so they can be shared across multiple processes/steps of the pipeline. A nf-core standard set of labels that should be followed where possible can be seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/master/nf_core/pipeline-template/conf/base.config), which has the default process as a single core-process, and then different levels of multi-core configurations for increasingly large memory requirements defined with standardised labels. -The process resources can be passed on to the tool dynamically within the process with the `${task.cpu}` and `${task.memory}` variables in the `script:` block. +The process resources can be passed on to the tool dynamically within the process with the `${task.cpus}` and `${task.memory}` variables in the `script:` block. ### Naming schemes @@ -101,3 +108,18 @@ If you are using a new feature from core Nextflow, you may bump the minimum requ ### Images and figures For overview images and other documents we follow the nf-core [style guidelines and examples](https://nf-co.re/developers/design_guidelines). + +## GitHub Codespaces + +This repo includes a devcontainer configuration which will create a GitHub Codespaces for Nextflow development! This is an online developer environment that runs in your browser, complete with VSCode and a terminal. + +To get started: + +- Open the repo in [Codespaces](https://github.com/nf-core/oncoanalyser/codespaces) +- Tools installed + - nf-core + - Nextflow + +Devcontainer specs: + +- [DevContainer config](.devcontainer/devcontainer.json) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 3ed51a88..93b3c04b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -42,9 +42,9 @@ body: attributes: label: System information description: | - * Nextflow version _(eg. 21.10.3)_ + * Nextflow version _(eg. 23.04.0)_ * Hardware _(eg. HPC, Desktop, Cloud)_ * Executor _(eg. slurm, local, awsbatch)_ - * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter or Charliecloud)_ + * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter, Charliecloud, or Apptainer)_ * OS _(eg. CentOS Linux, macOS, Linux Mint)_ * Version of nf-core/oncoanalyser _(eg. 1.1, 1.5, 1.8.2)_ diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 045d9396..4fa4360a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,9 +15,11 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/onco - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/oncoanalyser/tree/master/.github/CONTRIBUTING.md)- [ ] If necessary, also make a PR on the nf-core/oncoanalyser _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/oncoanalyser/tree/master/.github/CONTRIBUTING.md) +- [ ] If necessary, also make a PR on the nf-core/oncoanalyser _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core lint`). -- [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). +- [ ] Ensure the test suite passes (`nf-test test main.nf.test -profile test,docker`). +- [ ] Check for unexpected warnings in debug mode (`nextflow run . -profile debug,test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. - [ ] Output Documentation in `docs/output.md` is updated. - [ ] `CHANGELOG.md` is updated. diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index f32fa1b6..86245f5e 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Launch workflow via tower - uses: nf-core/tower-action@v3 + uses: seqeralabs/action-tower-launch@v2 # TODO nf-core: You can customise AWS full pipeline tests as required # Add full size test data (but still relatively small datasets for few samples) # on the `test_full.config` test runs with only one set of parameters @@ -22,13 +22,18 @@ jobs: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + revision: ${{ github.sha }} workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/oncoanalyser/work-${{ github.sha }} parameters: | { + "hook_url": "${{ secrets.MEGATESTS_ALERTS_SLACK_HOOK_URL }}", "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/oncoanalyser/results-${{ github.sha }}" } - profiles: test_full,aws_tower - - uses: actions/upload-artifact@v3 + profiles: test_full + + - uses: actions/upload-artifact@v4 with: name: Tower debug log file - path: tower_action_*.log + path: | + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index 9a4ec76d..3996313a 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -12,18 +12,22 @@ jobs: steps: # Launch workflow using Tower CLI tool action - name: Launch workflow via tower - uses: nf-core/tower-action@v3 + uses: seqeralabs/action-tower-launch@v2 with: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + revision: ${{ github.sha }} workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/oncoanalyser/work-${{ github.sha }} parameters: | { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/oncoanalyser/results-test-${{ github.sha }}" } - profiles: test,aws_tower - - uses: actions/upload-artifact@v3 + profiles: test + + - uses: actions/upload-artifact@v4 with: name: Tower debug log file - path: tower_action_*.log + path: | + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 0a1cdd32..0494f13f 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -13,13 +13,13 @@ jobs: - name: Check PRs if: github.repository == 'nf-core/oncoanalyser' run: | - { [[ ${{github.event.pull_request.head.repo.full_name }} == nf-core/oncoanalyser ]] && [[ $GITHUB_HEAD_REF = "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] + { [[ ${{github.event.pull_request.head.repo.full_name }} == nf-core/oncoanalyser ]] && [[ $GITHUB_HEAD_REF == "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] # If the above check failed, post a comment on the PR explaining the failure # NOTE - this doesn't currently work if the PR is coming from a fork, due to limitations in GitHub actions secrets - name: Post PR comment if: failure() - uses: mshick/add-pr-comment@v1 + uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2 with: message: | ## This PR is against the `master` branch :x: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1f80dbd..38a7b6ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,10 @@ on: env: NXF_ANSI_LOG: false +concurrency: + group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" + cancel-in-progress: true + jobs: test: name: Run pipeline with test data @@ -20,17 +24,20 @@ jobs: strategy: matrix: NXF_VER: - - "21.10.3" + - "23.04.0" - "latest-everything" steps: - name: Check out pipeline code - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Install Nextflow uses: nf-core/setup-nextflow@v1 with: version: "${{ matrix.NXF_VER }}" + - name: Disk space cleanup + uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 + - name: Run pipeline with test data # TODO nf-core: You can customise CI pipeline run tests as required # For example: adding multiple test runs with different parameters diff --git a/.github/workflows/clean-up.yml b/.github/workflows/clean-up.yml new file mode 100644 index 00000000..0b6b1f27 --- /dev/null +++ b/.github/workflows/clean-up.yml @@ -0,0 +1,24 @@ +name: "Close user-tagged issues and PRs" +on: + schedule: + - cron: "0 0 * * 0" # Once a week + +jobs: + clean-up: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9 + with: + stale-issue-message: "This issue has been tagged as awaiting-changes or awaiting-feedback by an nf-core contributor. Remove stale label or add a comment otherwise this issue will be closed in 20 days." + stale-pr-message: "This PR has been tagged as awaiting-changes or awaiting-feedback by an nf-core contributor. Remove stale label or add a comment if it is still useful." + close-issue-message: "This issue was closed because it has been tagged as awaiting-changes or awaiting-feedback by an nf-core contributor and then staled for 20 days with no activity." + days-before-stale: 30 + days-before-close: 20 + days-before-pr-close: -1 + any-of-labels: "awaiting-changes,awaiting-feedback" + exempt-issue-labels: "WIP" + exempt-pr-labels: "WIP" + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml new file mode 100644 index 00000000..08622fd5 --- /dev/null +++ b/.github/workflows/download_pipeline.yml @@ -0,0 +1,72 @@ +name: Test successful pipeline download with 'nf-core download' + +# Run the workflow when: +# - dispatched manually +# - when a PR is opened or reopened to master branch +# - the head branch of the pull request is updated, i.e. if fixes for a release are pushed last minute to dev. +on: + workflow_dispatch: + inputs: + testbranch: + description: "The specific branch you wish to utilize for the test execution of nf-core download." + required: true + default: "dev" + pull_request: + types: + - opened + branches: + - master + pull_request_target: + branches: + - master + +env: + NXF_ANSI_LOG: false + +jobs: + download: + runs-on: ubuntu-latest + steps: + - name: Install Nextflow + uses: nf-core/setup-nextflow@v1 + + - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + with: + python-version: "3.11" + architecture: "x64" + - uses: eWaterCycle/setup-singularity@931d4e31109e875b13309ae1d07c70ca8fbc8537 # v7 + with: + singularity-version: 3.8.3 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install git+https://github.com/nf-core/tools.git@dev + + - name: Get the repository name and current branch set as environment variable + run: | + echo "REPO_LOWERCASE=${GITHUB_REPOSITORY,,}" >> ${GITHUB_ENV} + echo "REPOTITLE_LOWERCASE=$(basename ${GITHUB_REPOSITORY,,})" >> ${GITHUB_ENV} + echo "REPO_BRANCH=${{ github.event.inputs.testbranch || 'dev' }}" >> ${GITHUB_ENV} + + - name: Download the pipeline + env: + NXF_SINGULARITY_CACHEDIR: ./ + run: | + nf-core download ${{ env.REPO_LOWERCASE }} \ + --revision ${{ env.REPO_BRANCH }} \ + --outdir ./${{ env.REPOTITLE_LOWERCASE }} \ + --compress "none" \ + --container-system 'singularity' \ + --container-library "quay.io" -l "docker.io" -l "ghcr.io" \ + --container-cache-utilisation 'amend' \ + --download-configuration + + - name: Inspect download + run: tree ./${{ env.REPOTITLE_LOWERCASE }} + + - name: Run the downloaded pipeline + env: + NXF_SINGULARITY_CACHEDIR: ./ + NXF_SINGULARITY_HOME_MOUNT: true + run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -stub -profile test,singularity --outdir ./results diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix-linting.yml index 50f455de..fe37960c 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix-linting.yml @@ -4,7 +4,7 @@ on: types: [created] jobs: - deploy: + fix-linting: # Only run if comment is on a PR with the main repo, and if it contains the magic keywords if: > contains(github.event.comment.html_url, '/pull/') && @@ -13,10 +13,17 @@ jobs: runs-on: ubuntu-latest steps: # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@v3 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: token: ${{ secrets.nf_core_bot_auth_token }} + # indication that the linting is being fixed + - name: React on comment + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + with: + comment-id: ${{ github.event.comment.id }} + reactions: eyes + # Action runs on the issue comment, so we don't get the PR by default # Use the gh cli to check out the PR - name: Checkout Pull Request @@ -24,32 +31,59 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} - - uses: actions/setup-node@v2 + # Install and run pre-commit + - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + with: + python-version: 3.11 - - name: Install Prettier - run: npm install -g prettier @prettier/plugin-php + - name: Install pre-commit + run: pip install pre-commit - # Check that we actually need to fix something - - name: Run 'prettier --check' - id: prettier_status - run: | - if prettier --check ${GITHUB_WORKSPACE}; then - echo "::set-output name=result::pass" - else - echo "::set-output name=result::fail" - fi + - name: Run pre-commit + id: pre-commit + run: pre-commit run --all-files + continue-on-error: true - - name: Run 'prettier --write' - if: steps.prettier_status.outputs.result == 'fail' - run: prettier --write ${GITHUB_WORKSPACE} + # indication that the linting has finished + - name: react if linting finished succesfully + if: steps.pre-commit.outcome == 'success' + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + with: + comment-id: ${{ github.event.comment.id }} + reactions: "+1" - name: Commit & push changes - if: steps.prettier_status.outputs.result == 'fail' + id: commit-and-push + if: steps.pre-commit.outcome == 'failure' run: | git config user.email "core@nf-co.re" git config user.name "nf-core-bot" git config push.default upstream git add . git status - git commit -m "[automated] Fix linting with Prettier" + git commit -m "[automated] Fix code linting" git push + + - name: react if linting errors were fixed + id: react-if-fixed + if: steps.commit-and-push.outcome == 'success' + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + with: + comment-id: ${{ github.event.comment.id }} + reactions: hooray + + - name: react if linting errors were not fixed + if: steps.commit-and-push.outcome == 'failure' + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + with: + comment-id: ${{ github.event.comment.id }} + reactions: confused + + - name: react if linting errors were not fixed + if: steps.commit-and-push.outcome == 'failure' + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + with: + issue-number: ${{ github.event.issue.number }} + body: | + @${{ github.actor }} I tried to fix the linting errors, but it didn't work. Please fix them manually. + See [CI log](https://github.com/nf-core/oncoanalyser/actions/runs/${{ github.run_id }}) for more details. diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 8a5ce69b..073e1876 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -4,79 +4,42 @@ name: nf-core linting # that the code meets the nf-core guidelines. on: push: + branches: + - dev pull_request: release: types: [published] jobs: - EditorConfig: + pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - - uses: actions/setup-node@v2 - - - name: Install editorconfig-checker - run: npm install -g editorconfig-checker - - - name: Run ECLint check - run: editorconfig-checker -exclude README.md $(find .* -type f | grep -v '.git\|.py\|.md\|json\|yml\|yaml\|html\|css\|work\|.nextflow\|build\|nf_core.egg-info\|log.txt\|Makefile') - - Prettier: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - uses: actions/setup-node@v2 - - - name: Install Prettier - run: npm install -g prettier - - - name: Run Prettier --check - run: prettier --check ${GITHUB_WORKSPACE} - - PythonBlack: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Check code lints with Black - uses: psf/black@stable - - # If the above check failed, post a comment on the PR explaining the failure - - name: Post PR comment - if: failure() - uses: mshick/add-pr-comment@v1 + - name: Set up Python 3.11 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: - message: | - ## Python linting (`black`) is failing - - To keep the code consistent with lots of contributors, we run automated code consistency checks. - To fix this CI test, please run: - - * Install [`black`](https://black.readthedocs.io/en/stable/): `pip install black` - * Fix formatting errors in your pipeline: `black .` - - Once you push these changes the test should pass, and you can hide this comment :+1: + python-version: 3.11 + cache: "pip" - We highly recommend setting up Black in your code editor so that this formatting is done automatically on save. Ask about it on Slack for help! + - name: Install pre-commit + run: pip install pre-commit - Thanks again for your contribution! - repo-token: ${{ secrets.GITHUB_TOKEN }} - allow-repeats: false + - name: Run pre-commit + run: pre-commit run --all-files nf-core: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Install Nextflow uses: nf-core/setup-nextflow@v1 - - uses: actions/setup-python@v3 + - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: - python-version: "3.7" + python-version: "3.11" architecture: "x64" - name: Install dependencies @@ -97,7 +60,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 with: name: linting-logs path: | diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 04758f61..b706875f 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -11,17 +11,17 @@ jobs: runs-on: ubuntu-latest steps: - name: Download lint results - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@f6b0bace624032e30a85a8fd9c1a7f8f611f5737 # v3 with: workflow: linting.yml workflow_conclusion: completed - name: Get PR number id: pr_number - run: echo "::set-output name=pr_number::$(cat linting-logs/PR_number.txt)" + run: echo "pr_number=$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - name: Post PR comment - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} number: ${{ steps.pr_number.outputs.pr_number }} diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml new file mode 100644 index 00000000..d468aeaa --- /dev/null +++ b/.github/workflows/release-announcements.yml @@ -0,0 +1,75 @@ +name: release-announcements +# Automatic release toot and tweet anouncements +on: + release: + types: [published] + workflow_dispatch: + +jobs: + toot: + runs-on: ubuntu-latest + steps: + - name: get topics and convert to hashtags + id: get_topics + run: | + curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ' >> $GITHUB_OUTPUT + + - uses: rzr/fediverse-action@master + with: + access-token: ${{ secrets.MASTODON_ACCESS_TOKEN }} + host: "mstdn.science" # custom host if not "mastodon.social" (default) + # GitHub event payload + # https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#release + message: | + Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! + + Please see the changelog: ${{ github.event.release.html_url }} + + ${{ steps.get_topics.outputs.GITHUB_OUTPUT }} #nfcore #openscience #nextflow #bioinformatics + + send-tweet: + runs-on: ubuntu-latest + + steps: + - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + with: + python-version: "3.10" + - name: Install dependencies + run: pip install tweepy==4.14.0 + - name: Send tweet + shell: python + run: | + import os + import tweepy + + client = tweepy.Client( + access_token=os.getenv("TWITTER_ACCESS_TOKEN"), + access_token_secret=os.getenv("TWITTER_ACCESS_TOKEN_SECRET"), + consumer_key=os.getenv("TWITTER_CONSUMER_KEY"), + consumer_secret=os.getenv("TWITTER_CONSUMER_SECRET"), + ) + tweet = os.getenv("TWEET") + client.create_tweet(text=tweet) + env: + TWEET: | + Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! + + Please see the changelog: ${{ github.event.release.html_url }} + TWITTER_CONSUMER_KEY: ${{ secrets.TWITTER_CONSUMER_KEY }} + TWITTER_CONSUMER_SECRET: ${{ secrets.TWITTER_CONSUMER_SECRET }} + TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} + TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} + + bsky-post: + runs-on: ubuntu-latest + steps: + - uses: zentered/bluesky-post-action@80dbe0a7697de18c15ad22f4619919ceb5ccf597 # v0.1.0 + with: + post: | + Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! + + Please see the changelog: ${{ github.event.release.html_url }} + env: + BSKY_IDENTIFIER: ${{ secrets.BSKY_IDENTIFIER }} + BSKY_PASSWORD: ${{ secrets.BSKY_PASSWORD }} + # diff --git a/.gitpod.yml b/.gitpod.yml index 85d95ecc..105a1821 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,14 +1,20 @@ image: nfcore/gitpod:latest +tasks: + - name: Update Nextflow and setup pre-commit + command: | + pre-commit install --install-hooks + nextflow self-update + - name: unset JAVA_TOOL_OPTIONS + command: | + unset JAVA_TOOL_OPTIONS vscode: extensions: # based on nf-core.nf-core-extensionpack - - codezombiech.gitignore # Language support for .gitignore files - # - cssho.vscode-svgviewer # SVG viewer - esbenp.prettier-vscode # Markdown/CommonMark linting and style checking for Visual Studio Code - - eamodio.gitlens # Quickly glimpse into whom, why, and when a line or code block was changed - EditorConfig.EditorConfig # override user/workspace settings with settings found in .editorconfig files - Gruntfuggly.todo-tree # Display TODO and FIXME in a tree view in the activity bar - mechatroner.rainbow-csv # Highlight columns in csv files in different colors - # - nextflow.nextflow # Nextflow syntax highlighting + # - nextflow.nextflow # Nextflow syntax highlighting - oderwat.indent-rainbow # Highlight indentation level - streetsidesoftware.code-spell-checker # Spelling checker for source code + - charliermarsh.ruff # Code linter Ruff diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..af57081f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,10 @@ +repos: + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v3.1.0" + hooks: + - id: prettier + - repo: https://github.com/editorconfig-checker/editorconfig-checker.python + rev: "2.7.3" + hooks: + - id: editorconfig-checker + alias: ec diff --git a/.prettierignore b/.prettierignore index eb74a574..437d763d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,6 @@ email_template.html adaptivecard.json +slackreport.json .nextflow* work/ data/ @@ -8,3 +9,4 @@ results/ testing/ testing* *.pyc +bin/ diff --git a/CHANGELOG.md b/CHANGELOG.md index f5b610f4..a3f8ca48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v1.0dev - [date] +## v0.3.0 - [date] Initial release of nf-core/oncoanalyser, created with the [nf-core](https://nf-co.re/) template. diff --git a/CITATION.cff b/CITATION.cff deleted file mode 100644 index 017666c0..00000000 --- a/CITATION.cff +++ /dev/null @@ -1,56 +0,0 @@ -cff-version: 1.2.0 -message: "If you use `nf-core tools` in your work, please cite the `nf-core` publication" -authors: - - family-names: Ewels - given-names: Philip - - family-names: Peltzer - given-names: Alexander - - family-names: Fillinger - given-names: Sven - - family-names: Patel - given-names: Harshil - - family-names: Alneberg - given-names: Johannes - - family-names: Wilm - given-names: Andreas - - family-names: Garcia - given-names: Maxime Ulysse - - family-names: Di Tommaso - given-names: Paolo - - family-names: Nahnsen - given-names: Sven -title: "The nf-core framework for community-curated bioinformatics pipelines." -version: 2.4.1 -doi: 10.1038/s41587-020-0439-x -date-released: 2022-05-16 -url: https://github.com/nf-core/tools -prefered-citation: - type: article - authors: - - family-names: Ewels - given-names: Philip - - family-names: Peltzer - given-names: Alexander - - family-names: Fillinger - given-names: Sven - - family-names: Patel - given-names: Harshil - - family-names: Alneberg - given-names: Johannes - - family-names: Wilm - given-names: Andreas - - family-names: Garcia - given-names: Maxime Ulysse - - family-names: Di Tommaso - given-names: Paolo - - family-names: Nahnsen - given-names: Sven - doi: 10.1038/s41587-020-0439-x - journal: nature biotechnology - start: 276 - end: 278 - title: "The nf-core framework for community-curated bioinformatics pipelines." - issue: 3 - volume: 38 - year: 2020 - url: https://dx.doi.org/10.1038/s41587-020-0439-x diff --git a/CITATIONS.md b/CITATIONS.md index dfebcc85..4aa55803 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -12,7 +12,10 @@ - [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) + > Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. + - [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) + > Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. ## Software packaging/containerisation tools @@ -31,5 +34,8 @@ - [Docker](https://dl.acm.org/doi/10.5555/2600239.2600241) + > Merkel, D. (2014). Docker: lightweight linux containers for consistent development and deployment. Linux Journal, 2014(239), 2. doi: 10.5555/2600239.2600241. + - [Singularity](https://pubmed.ncbi.nlm.nih.gov/28494014/) + > Kurtzer GM, Sochat V, Bauer MW. Singularity: Scientific containers for mobility of compute. PLoS One. 2017 May 11;12(5):e0177459. doi: 10.1371/journal.pone.0177459. eCollection 2017. PubMed PMID: 28494014; PubMed Central PMCID: PMC5426675. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index f4fd052f..c089ec78 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,18 +1,20 @@ -# Code of Conduct at nf-core (v1.0) +# Code of Conduct at nf-core (v1.4) ## Our Pledge -In the interest of fostering an open, collaborative, and welcoming environment, we as contributors and maintainers of nf-core, pledge to making participation in our projects and community a harassment-free experience for everyone, regardless of: +In the interest of fostering an open, collaborative, and welcoming environment, we as contributors and maintainers of nf-core pledge to making participation in our projects and community a harassment-free experience for everyone, regardless of: - Age +- Ability - Body size +- Caste - Familial status - Gender identity and expression - Geographical location - Level of experience - Nationality and national origins - Native language -- Physical and neurological ability +- Neurodiversity - Race or ethnicity - Religion - Sexual identity and orientation @@ -22,80 +24,133 @@ Please note that the list above is alphabetised and is therefore not ranked in a ## Preamble -> Note: This Code of Conduct (CoC) has been drafted by the nf-core Safety Officer and been edited after input from members of the nf-core team and others. "We", in this document, refers to the Safety Officer and members of the nf-core core team, both of whom are deemed to be members of the nf-core community and are therefore required to abide by this Code of Conduct. This document will amended periodically to keep it up-to-date, and in case of any dispute, the most current version will apply. +:::note +This Code of Conduct (CoC) has been drafted by Renuka Kudva, Cris Tuñí, and Michael Heuer, with input from the nf-core Core Team and Susanna Marquez from the nf-core community. "We", in this document, refers to the Safety Officers and members of the nf-core Core Team, both of whom are deemed to be members of the nf-core community and are therefore required to abide by this Code of Conduct. This document will be amended periodically to keep it up-to-date. In case of any dispute, the most current version will apply. +::: -An up-to-date list of members of the nf-core core team can be found [here](https://nf-co.re/about). Our current safety officer is Renuka Kudva. +An up-to-date list of members of the nf-core core team can be found [here](https://nf-co.re/about). + +Our Safety Officers are Saba Nafees, Cris Tuñí, and Michael Heuer. nf-core is a young and growing community that welcomes contributions from anyone with a shared vision for [Open Science Policies](https://www.fosteropenscience.eu/taxonomy/term/8). Open science policies encompass inclusive behaviours and we strive to build and maintain a safe and inclusive environment for all individuals. -We have therefore adopted this code of conduct (CoC), which we require all members of our community and attendees in nf-core events to adhere to in all our workspaces at all times. Workspaces include but are not limited to Slack, meetings on Zoom, Jitsi, YouTube live etc. +We have therefore adopted this CoC, which we require all members of our community and attendees of nf-core events to adhere to in all our workspaces at all times. Workspaces include, but are not limited to, Slack, meetings on Zoom, gather.town, YouTube live etc. -Our CoC will be strictly enforced and the nf-core team reserve the right to exclude participants who do not comply with our guidelines from our workspaces and future nf-core activities. +Our CoC will be strictly enforced and the nf-core team reserves the right to exclude participants who do not comply with our guidelines from our workspaces and future nf-core activities. -We ask all members of our community to help maintain a supportive and productive workspace and to avoid behaviours that can make individuals feel unsafe or unwelcome. Please help us maintain and uphold this CoC. +We ask all members of our community to help maintain supportive and productive workspaces and to avoid behaviours that can make individuals feel unsafe or unwelcome. Please help us maintain and uphold this CoC. -Questions, concerns or ideas on what we can include? Contact safety [at] nf-co [dot] re +Questions, concerns, or ideas on what we can include? Contact members of the Safety Team on Slack or email safety [at] nf-co [dot] re. ## Our Responsibilities -The safety officer is responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behaviour. +Members of the Safety Team (the Safety Officers) are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behaviour. -The safety officer in consultation with the nf-core core team have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. +The Safety Team, in consultation with the nf-core core team, have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this CoC, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. -Members of the core team or the safety officer who violate the CoC will be required to recuse themselves pending investigation. They will not have access to any reports of the violations and be subject to the same actions as others in violation of the CoC. +Members of the core team or the Safety Team who violate the CoC will be required to recuse themselves pending investigation. They will not have access to any reports of the violations and will be subject to the same actions as others in violation of the CoC. -## When are where does this Code of Conduct apply? +## When and where does this Code of Conduct apply? -Participation in the nf-core community is contingent on following these guidelines in all our workspaces and events. This includes but is not limited to the following listed alphabetically and therefore in no order of preference: +Participation in the nf-core community is contingent on following these guidelines in all our workspaces and events, such as hackathons, workshops, bytesize, and collaborative workspaces on gather.town. These guidelines include, but are not limited to, the following (listed alphabetically and therefore in no order of preference): - Communicating with an official project email address. - Communicating with community members within the nf-core Slack channel. - Participating in hackathons organised by nf-core (both online and in-person events). -- Participating in collaborative work on GitHub, Google Suite, community calls, mentorship meetings, email correspondence. -- Participating in workshops, training, and seminar series organised by nf-core (both online and in-person events). This applies to events hosted on web-based platforms such as Zoom, Jitsi, YouTube live etc. +- Participating in collaborative work on GitHub, Google Suite, community calls, mentorship meetings, email correspondence, and on the nf-core gather.town workspace. +- Participating in workshops, training, and seminar series organised by nf-core (both online and in-person events). This applies to events hosted on web-based platforms such as Zoom, gather.town, Jitsi, YouTube live etc. - Representing nf-core on social media. This includes both official and personal accounts. ## nf-core cares 😊 -nf-core's CoC and expectations of respectful behaviours for all participants (including organisers and the nf-core team) include but are not limited to the following (listed in alphabetical order): +nf-core's CoC and expectations of respectful behaviours for all participants (including organisers and the nf-core team) include, but are not limited to, the following (listed in alphabetical order): - Ask for consent before sharing another community member’s personal information (including photographs) on social media. - Be respectful of differing viewpoints and experiences. We are all here to learn from one another and a difference in opinion can present a good learning opportunity. -- Celebrate your accomplishments at events! (Get creative with your use of emojis 🎉 🥳 💯 🙌 !) +- Celebrate your accomplishments! (Get creative with your use of emojis 🎉 🥳 💯 🙌 !) - Demonstrate empathy towards other community members. (We don’t all have the same amount of time to dedicate to nf-core. If tasks are pending, don’t hesitate to gently remind members of your team. If you are leading a task, ask for help if you feel overwhelmed.) - Engage with and enquire after others. (This is especially important given the geographically remote nature of the nf-core community, so let’s do this the best we can) - Focus on what is best for the team and the community. (When in doubt, ask) -- Graciously accept constructive criticism, yet be unafraid to question, deliberate, and learn. +- Accept feedback, yet be unafraid to question, deliberate, and learn. - Introduce yourself to members of the community. (We’ve all been outsiders and we know that talking to strangers can be hard for some, but remember we’re interested in getting to know you and your visions for open science!) -- Show appreciation and **provide clear feedback**. (This is especially important because we don’t see each other in person and it can be harder to interpret subtleties. Also remember that not everyone understands a certain language to the same extent as you do, so **be clear in your communications to be kind.**) +- Show appreciation and **provide clear feedback**. (This is especially important because we don’t see each other in person and it can be harder to interpret subtleties. Also remember that not everyone understands a certain language to the same extent as you do, so **be clear in your communication to be kind.**) - Take breaks when you feel like you need them. -- Using welcoming and inclusive language. (Participants are encouraged to display their chosen pronouns on Zoom or in communication on Slack.) +- Use welcoming and inclusive language. (Participants are encouraged to display their chosen pronouns on Zoom or in communication on Slack) ## nf-core frowns on 😕 -The following behaviours from any participants within the nf-core community (including the organisers) will be considered unacceptable under this code of conduct. Engaging or advocating for any of the following could result in expulsion from nf-core workspaces. +The following behaviours from any participants within the nf-core community (including the organisers) will be considered unacceptable under this CoC. Engaging or advocating for any of the following could result in expulsion from nf-core workspaces: - Deliberate intimidation, stalking or following and sustained disruption of communication among participants of the community. This includes hijacking shared screens through actions such as using the annotate tool in conferencing software such as Zoom. - “Doxing” i.e. posting (or threatening to post) another person’s personal identifying information online. - Spamming or trolling of individuals on social media. -- Use of sexual or discriminatory imagery, comments, or jokes and unwelcome sexual attention. -- Verbal and text comments that reinforce social structures of domination related to gender, gender identity and expression, sexual orientation, ability, physical appearance, body size, race, age, religion or work experience. +- Use of sexual or discriminatory imagery, comments, jokes, or unwelcome sexual attention. +- Verbal and text comments that reinforce social structures of domination related to gender, gender identity and expression, sexual orientation, ability, physical appearance, body size, race, age, religion, or work experience. ### Online Trolling -The majority of nf-core interactions and events are held online. Unfortunately, holding events online comes with the added issue of online trolling. This is unacceptable, reports of such behaviour will be taken very seriously, and perpetrators will be excluded from activities immediately. +The majority of nf-core interactions and events are held online. Unfortunately, holding events online comes with the risk of online trolling. This is unacceptable — reports of such behaviour will be taken very seriously and perpetrators will be excluded from activities immediately. -All community members are required to ask members of the group they are working within for explicit consent prior to taking screenshots of individuals during video calls. +All community members are **required** to ask members of the group they are working with for explicit consent prior to taking screenshots of individuals during video calls. -## Procedures for Reporting CoC violations +## Procedures for reporting CoC violations If someone makes you feel uncomfortable through their behaviours or actions, report it as soon as possible. -You can reach out to members of the [nf-core core team](https://nf-co.re/about) and they will forward your concerns to the safety officer(s). +You can reach out to members of the Safety Team (Saba Nafees, Cris Tuñí, and Michael Heuer) on Slack. Alternatively, contact a member of the nf-core core team [nf-core core team](https://nf-co.re/about), and they will forward your concerns to the Safety Team. + +Issues directly concerning members of the Core Team or the Safety Team will be dealt with by other members of the core team and the safety manager — possible conflicts of interest will be taken into account. nf-core is also in discussions about having an ombudsperson and details will be shared in due course. + +All reports will be handled with the utmost discretion and confidentiality. + +You can also report any CoC violations to safety [at] nf-co [dot] re. In your email report, please do your best to include: + +- Your contact information. +- Identifying information (e.g. names, nicknames, pseudonyms) of the participant who has violated the Code of Conduct. +- The behaviour that was in violation and the circumstances surrounding the incident. +- The approximate time of the behaviour (if different than the time the report was made). +- Other people involved in the incident, if applicable. +- If you believe the incident is ongoing. +- If there is a publicly available record (e.g. mailing list record, a screenshot). +- Any additional information. + +After you file a report, one or more members of our Safety Team will contact you to follow up on your report. + +## Who will read and handle reports + +All reports will be read and handled by the members of the Safety Team at nf-core. + +If members of the Safety Team are deemed to have a conflict of interest with a report, they will be required to recuse themselves as per our Code of Conduct and will not have access to any follow-ups. + +To keep this first report confidential from any of the Safety Team members, please submit your first report by direct messaging on Slack/direct email to any of the nf-core members you are comfortable disclosing the information to, and be explicit about which member(s) you do not consent to sharing the information with. + +## Reviewing reports + +After receiving the report, members of the Safety Team will review the incident report to determine whether immediate action is required, for example, whether there is immediate threat to participants’ safety. + +The Safety Team, in consultation with members of the nf-core core team, will assess the information to determine whether the report constitutes a Code of Conduct violation, for them to decide on a course of action. + +In the case of insufficient information, one or more members of the Safety Team may contact the reporter, the reportee, or any other attendees to obtain more information. -Issues directly concerning members of the core team will be dealt with by other members of the core team and the safety manager, and possible conflicts of interest will be taken into account. nf-core is also in discussions about having an ombudsperson, and details will be shared in due course. +Once additional information is gathered, the Safety Team will collectively review and decide on the best course of action to take, if any. The Safety Team reserves the right to not act on a report. -All reports will be handled with utmost discretion and confidentially. +## Confidentiality + +All reports, and any additional information included, are only shared with the team of safety officers (and possibly members of the core team, in case the safety officer is in violation of the CoC). We will respect confidentiality requests for the purpose of protecting victims of abuse. + +We will not name harassment victims, beyond discussions between the safety officer and members of the nf-core team, without the explicit consent of the individuals involved. + +## Enforcement + +Actions taken by the nf-core’s Safety Team may include, but are not limited to: + +- Asking anyone to stop a behaviour. +- Asking anyone to leave the event and online spaces either temporarily, for the remainder of the event, or permanently. +- Removing access to the gather.town and Slack, either temporarily or permanently. +- Communicating to all participants to reinforce our expectations for conduct and remind what is unacceptable behaviour; this may be public for practical reasons. +- Communicating to all participants that an incident has taken place and how we will act or have acted — this may be for the purpose of letting event participants know we are aware of and dealing with the incident. +- Banning anyone from participating in nf-core-managed spaces, future events, and activities, either temporarily or permanently. +- No action. ## Attribution and Acknowledgements @@ -106,6 +161,22 @@ All reports will be handled with utmost discretion and confidentially. ## Changelog -### v1.0 - March 12th, 2021 +### v1.4 - February 8th, 2022 + +- Included a new member of the Safety Team. Corrected a typographical error in the text. + +### v1.3 - December 10th, 2021 + +- Added a statement that the CoC applies to nf-core gather.town workspaces. Corrected typographical errors in the text. + +### v1.2 - November 12th, 2021 + +- Removed information specific to reporting CoC violations at the Hackathon in October 2021. + +### v1.1 - October 14th, 2021 + +- Updated with names of new Safety Officers and specific information for the hackathon in October 2021. + +### v1.0 - March 15th, 2021 - Complete rewrite from original [Contributor Covenant](http://contributor-covenant.org/) CoC. diff --git a/README.md b/README.md index 95bace73..944a687d 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,82 @@ -# ![nf-core/oncoanalyser](docs/images/nf-core-oncoanalyser_logo_light.png#gh-light-mode-only) ![nf-core/oncoanalyser](docs/images/nf-core-oncoanalyser_logo_dark.png#gh-dark-mode-only) - -[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/oncoanalyser/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) - -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg)](https://www.nextflow.io/) +

    + + + nf-core/oncoanalyser + +

    + +[![GitHub Actions CI Status](https://github.com/nf-core/oncoanalyser/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/oncoanalyser/actions/workflows/ci.yml) +[![GitHub Actions Linting Status](https://github.com/nf-core/oncoanalyser/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/oncoanalyser/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/oncoanalyser/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) +[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) + +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A523.04.0-23aa62.svg)](https://www.nextflow.io/) [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) -[![Launch on Nextflow Tower](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/oncoanalyser) +[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/oncoanalyser) -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23oncoanalyser-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/oncoanalyser)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23oncoanalyser-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/oncoanalyser)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) ## Introduction - - -**nf-core/oncoanalyser** is a comprehensive cancer WGS/WTS analysis and reporting pipeline. - -The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. Where possible, these processes have been submitted to and installed from [nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to everyone within the Nextflow community! - - +**nf-core/oncoanalyser** is a bioinformatics pipeline that ... -On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources.The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/oncoanalyser/results). - -## Pipeline summary + + 1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) 2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) -## Quick Start +## Usage + +> [!NOTE] +> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` before running the workflow on actual data. + + - Note that some form of configuration will be needed so that Nextflow knows how to fetch the required software. This is usually done in the form of a config profile (`YOURPROFILE` in the example command above). You can chain multiple config profiles in a comma-separated string. +Now, you can run the pipeline using: - > - The pipeline comes with config profiles called `docker`, `singularity`, `podman`, `shifter`, `charliecloud` and `conda` which instruct the pipeline to use the named tool for software management. For example, `-profile test,docker`. - > - Please check [nf-core/configs](https://github.com/nf-core/configs#documentation) to see if a custom config file to run nf-core pipelines already exists for your Institute. If so, you can simply use `-profile ` in your command. This will enable either `docker` or `singularity` and set the appropriate execution settings for your local compute environment. - > - If you are using `singularity`, please use the [`nf-core download`](https://nf-co.re/tools/#downloading-pipelines-for-offline-use) command to download images first, before running the pipeline. Setting the [`NXF_SINGULARITY_CACHEDIR` or `singularity.cacheDir`](https://www.nextflow.io/docs/latest/singularity.html?#singularity-docker-hub) Nextflow options enables you to store and re-use the images from a central location for future pipeline runs. - > - If you are using `conda`, it is highly recommended to use the [`NXF_CONDA_CACHEDIR` or `conda.cacheDir`](https://www.nextflow.io/docs/latest/conda.html) settings to store the environments in a central location for future pipeline runs. + -4. Start running your own analysis! +```bash +nextflow run nf-core/oncoanalyser \ + -profile \ + --input samplesheet.csv \ + --outdir +``` - +> [!WARNING] +> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; +> see [docs](https://nf-co.re/usage/configuration#custom-configuration-files). - ```bash - nextflow run nf-core/oncoanalyser --input samplesheet.csv --outdir --genome GRCh37 -profile - ``` +For more details and further functionality, please refer to the [usage documentation](https://nf-co.re/oncoanalyser/usage) and the [parameter documentation](https://nf-co.re/oncoanalyser/parameters). -## Documentation +## Pipeline output -The nf-core/oncoanalyser pipeline comes with documentation about the pipeline [usage](https://nf-co.re/oncoanalyser/usage), [parameters](https://nf-co.re/oncoanalyser/parameters) and [output](https://nf-co.re/oncoanalyser/output). +To see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/oncoanalyser/results) tab on the nf-core website pipeline page. +For more details about the output files and reports, please refer to the +[output documentation](https://nf-co.re/oncoanalyser/output). ## Credits @@ -77,7 +95,7 @@ For further information or help, don't hesitate to get in touch on the [Slack `# ## Citations - + diff --git a/assets/email_template.html b/assets/email_template.html index 098117ff..0d1bf471 100644 --- a/assets/email_template.html +++ b/assets/email_template.html @@ -4,7 +4,7 @@ - + nf-core/oncoanalyser Pipeline Report @@ -12,7 +12,7 @@ -

    nf-core/oncoanalyser v${version}

    +

    nf-core/oncoanalyser ${version}

    Run Name: $runName

    <% if (!success){ diff --git a/assets/email_template.txt b/assets/email_template.txt index 9058d515..30511616 100644 --- a/assets/email_template.txt +++ b/assets/email_template.txt @@ -4,7 +4,7 @@ |\\ | |__ __ / ` / \\ |__) |__ } { | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-, `._,._,' - nf-core/oncoanalyser v${version} + nf-core/oncoanalyser ${version} ---------------------------------------------------- Run Name: $runName diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml index 5e1aba5b..6bb8cb5b 100644 --- a/assets/methods_description_template.yml +++ b/assets/methods_description_template.yml @@ -3,17 +3,21 @@ description: "Suggested text and references to use when describing pipeline usag section_name: "nf-core/oncoanalyser Methods Description" section_href: "https://github.com/nf-core/oncoanalyser" plot_type: "html" -## TODO nf-core: Update the HTML below to your prefered methods description, e.g. add publication citation for this pipeline +## TODO nf-core: Update the HTML below to your preferred methods description, e.g. add publication citation for this pipeline ## You inject any metadata in the Nextflow '${workflow}' object data: |

    Methods

    -
    +

    Data was processed using nf-core/oncoanalyser v${workflow.manifest.version} ${doi_text} of the nf-core collection of workflows (Ewels et al., 2020), utilising reproducible software environments from the Bioconda (Grüning et al., 2018) and Biocontainers (da Veiga Leprevost et al., 2017) projects.

    The pipeline was executed with Nextflow v${workflow.nextflow.version} (Di Tommaso et al., 2017) with the following command:

    ${workflow.commandLine}
    +

    ${tool_citations}

    References

      -
    • Di Tommaso, P., Chatzou, M., Floden, E. W., Barja, P. P., Palumbo, E., & Notredame, C. (2017). Nextflow enables reproducible computational workflows. Nature Biotechnology, 35(4), 316-319. https://doi.org/10.1038/nbt.3820
    • -
    • Ewels, P. A., Peltzer, A., Fillinger, S., Patel, H., Alneberg, J., Wilm, A., Garcia, M. U., Di Tommaso, P., & Nahnsen, S. (2020). The nf-core framework for community-curated bioinformatics pipelines. Nature Biotechnology, 38(3), 276-278. https://doi.org/10.1038/s41587-020-0439-x
    • +
    • Di Tommaso, P., Chatzou, M., Floden, E. W., Barja, P. P., Palumbo, E., & Notredame, C. (2017). Nextflow enables reproducible computational workflows. Nature Biotechnology, 35(4), 316-319. doi: 10.1038/nbt.3820
    • +
    • Ewels, P. A., Peltzer, A., Fillinger, S., Patel, H., Alneberg, J., Wilm, A., Garcia, M. U., Di Tommaso, P., & Nahnsen, S. (2020). The nf-core framework for community-curated bioinformatics pipelines. Nature Biotechnology, 38(3), 276-278. doi: 10.1038/s41587-020-0439-x
    • +
    • Grüning, B., Dale, R., Sjödin, A., Chapman, B. A., Rowe, J., Tomkins-Tinch, C. H., Valieris, R., Köster, J., & Bioconda Team. (2018). Bioconda: sustainable and comprehensive software distribution for the life sciences. Nature Methods, 15(7), 475–476. doi: 10.1038/s41592-018-0046-7
    • +
    • da Veiga Leprevost, F., Grüning, B. A., Alves Aflitos, S., Röst, H. L., Uszkoreit, J., Barsnes, H., Vaudel, M., Moreno, P., Gatto, L., Weber, J., Bai, M., Jimenez, R. C., Sachsenberg, T., Pfeuffer, J., Vera Alvarez, R., Griss, J., Nesvizhskii, A. I., & Perez-Riverol, Y. (2017). BioContainers: an open-source and community-driven framework for software standardization. Bioinformatics (Oxford, England), 33(16), 2580–2582. doi: 10.1093/bioinformatics/btx192
    • + ${tool_bibliography}
    Notes:
    diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index dfb73cca..780ba33e 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,9 @@ report_comment: > - This report has been generated by the nf-core/oncoanalyser + + This report has been generated by the nf-core/oncoanalyser analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. + report_section_order: "nf-core-oncoanalyser-methods-description": order: -1000 @@ -11,3 +13,5 @@ report_section_order: order: -1002 export_plots: true + +disable_version_detection: true diff --git a/assets/nf-core-oncoanalyser_logo_light.png b/assets/nf-core-oncoanalyser_logo_light.png index 72327aa5792d50d626ec3be3aeb73dd9309e4213..f529ea38deaf9dcc0956894bfb750b71b7529773 100644 GIT binary patch literal 112262 zcmeEuXE@y37Pp+7M4HG=1R;nMC3+`%5)m0SdPa{jqDSu~BykYLjKQeUqnFV}4GA&~ zGTLZEgkdm3DDQO~s1=q|BbqM@Oo13i7L zM?-Vrh=%5@!iDp||DazAUZ$Zr6X>9#@(iS+a_5IrDObI4@e{lQuNV!K? z3^bM1*$ynp4lD)@_-FR}Uw!@un7dFWfHPU-<*e0bSq}48(rs4V;dHcYVyed75Xht9 z+JQh8jNgiw(}?n3#rSoQ`RjL#v%0DympWh_*|p)0n{ls_p;6p#2HxOP&7SS|56{_! zNXeQnxWQ_l`rQ^>?dbQS>vnpMekuFHU$)%L$FOLsJ19yKk(CA?6PS+BPPua?T~n<6 ze#rS-3FGm!9A~R@v|H;FmHVRS`Nd00bE`B{ubi98DOcag`Di;=;!fXL>&uNC zBPommAR~7T{&Q}HKmL5QNLM4A6lgTQIDh63)=fiPWj+0|N2|*c)2}Z3%9;$i5SlYI zG@!>14gAtcc;9qeI|SuqC8WP-%ss$^=L-1DL-VuYf0icP#=O3hB3jn8Y-}7-+B9?Q zs^@Ed^IRCGh4;>5G(Otc2+NMSO5^lkz&wiI`c?*l##u zE@ilAwiv<%y#N2k|2XhJ4*ZV;|6e#D%2`VMd!w;H9p!+w*Ujc8citX|)gOpKwu%Xx z9eD=D0q;Xjdh6vg=ybMR}id+^gvbU ziE#YXRYM%zkTD$$3J0kDGsr!CuRPd zea#AoB@<7JHVCF}E?S#f=V)j?t9<-*_CNH$clHm0(OK-r$hXTcqj+b>e$0ZQ$`2ui z4&-)rSk2ItEZX;5{>(mEI+`ABC*GyLdv0LslM=y`D87~wvC35)<^A^5F7}yw0725t zOUnPDOJhz%sFkNozJzBwM=6fmDD-Q_Uxs*q)|&K}#seWdFa|tfP^6C(>A$@mAW#13 z>)PUt&wB^h2%5JX{~;3Q>Ota+yls_~^@345aXXLeO>vWewg-AKI|UJr*kraVuTVRP zbZuDj%@UGh0&b@HXqNUri$7kz9XR$P^4nZm_<=rm*@gCbtgn-QIXdZgeN3?D!U5k5 zWmRZ~Uyh!-E`gElKkI0$c;q*J9WT@(H&?XA1?;44As)V+V||8MV*Xxlts*#iPI#8S zzN`Gc$(Uru41ncUJlTJ9UKAY{ zy3N@gz}u?Tp6M`+@AX-|Uatk!Og)qV9?6RTACDvo>X%z7wLNwV*^nb_#DcCTE$CZ~ zmz%#>F#fZedj7nsod3Qk4d(Z5#emN1@o44qNC{1&Oh*l0MP`8C#xks{-N(OnC)b7l zx^(-Szd3!;hm?CYB*!CIl+Nc(lM{>JPi_hQ_ewt@ZXZbiX;IWYz^VH8(EM06K2grLPYA66f%+b!hR1gJ3*;?{=5l@xp==Pf!G~uz~&`!f|7M z?8{X-v`33biqH(cIv&B7!q+GeFl9ApqFUxXlp#JTXgrdqlpMglbKYMkQRw2}O) z6vX^A+IBrPl$fhjJTs;6+7vk1=LmnRbGQFX}K*VqxBk36=^r{urQ zs@15@?iQymoupDX4V`$`9ub0?EiOsa7z9VMn@k%xjhfsg1W0u`@`4sno%FvWb9r*M zZJ=foJX^j7X$O&QK`Uit7ssvu+pwSchkUyG9JSLnOY+PrM!n58=OdHuTiwVv+jQe$ zoXP4Q+;eMKDroZYo$S8t^J`0E(7p@#OQJ44g)iVJR)Z;cMW&5h&}DQDxWt1q&j$fN z^{-)dTXCl{B6GGp^h%S-u9*IN_hGH9%buG@ghpTMy zPqam0W_`qsiBBY<8A>0AQT&&Y-vAL35&c^mtkQ3v5F@T`GE?rR#7)4fb(qsqJxkQu z=HJawDEe~=?cDN|4-pp0T`})9yw=F zV$)n(6RA@BV9%-p`0>~HJdG@55BNpVwE4dKVx}vxE6K6>xeT_ zVe-bw(+@%ua0ivaxG0rO#LAr5ex&RE&U%RWzs3PNmA?OwQc}JRy&_R0eEbBKsPyx# zIbE`avd-+BFm!LLcBFN|u*c@$|*F?b<+Xc{l`qcad09_TWyguXjG!p&u=E z(6o{U$db0tiTt63AYt;;!T1ob6(i9448>UB z4?qNIy6A8GZFP1(4{>;Y&(Suu)DpbC`|53$RRNJ=rz0TJFw4|7rr>`O*h|#>?LSaQ zQx)7heT_YvWMgBOC7-`vpBM}f6}9-MV9T(Dj-63^yyPA5Cck;gd~HKTW@?+fuB|5t zOvTV>?o;9abc|`~qAkzs6J~{NctD5RvSqD-dXIqLT6O&c7Asi+1Z`K-plB*$UU9&< z_GVummQ);XCf|j@=>RekXaAw9_#ar2D~#{hUByHsU>aGn6r9Y-tHJR9hi1$v&ED1D zT{wPjS!wEd%`9-X{k+bnZ6ODc{J#+2ryXpc0sm@N7->aDDQ^dHTz)8QZdm8imipBX zn49u&@SprSx8m05zyVX{Aw zuc=is87tK=cGt#u4A)+*UA>5=g*Y$^^Y|Z9$o}xxpcv=aQDhOB^b1xo?KM<(BkKb7 zaJT-!N;Rtm5&yhizimyi5J&M%>Q<24zYW_jQEi2z&%xY^ogA*R6=JM1Np(j9T#o@n z`g}$0Z$$d>qDEZVygDJ z(+QvRp2kog@UQVbwl$CtLQXr_j7(d*3&JY)z_K&~_Adk1rLN|__8V>u z$7r8V+&qeAvuZpNmi2aD-nqb-sclzY$ogO+J!VX-DD%M3%5bMytcb?JZV&y zSCni5!)w0iE1&-{`Anyv`!c@691VYm*oRReZwGs(4-FUz{`5vXVYD^h(N@geWa&m_;IW{zS zE6FbPKkH7)Yi7)(uOpp%-$YV{%I9z9@tA(^?JKPyGRrrRpU}@bf~tsu4`e>=ei9sN zZK}>oHbdEir8kPGYzX|XY=?miDsUWk$MvK8-7P6dEEem=kntOlG5cQun9@dpWGNK9 zM7G-$SR`8HcZQl~qYhZN!hlXfO*8S1JX&-15@KENTS7BD)+eC)@Y~b6YWtd8WJOO* z92LH4K6~kv8705{xcF^Eia_Ig{9^6s0QbJs4D7}5(TNMY$WQwDWjHSd*SH`C%nw7n z24F$+2CccTt0iyD>uE21RDkRl{pVhRwMi{346h)#~{l z7OHNxOnpk4(4tFB)fk!izSuuWM2+%R(_w>K&P_6_ySG&Iu3Px`cc-b&K&YppDM)=R z_oO^GroT!;g8aD$F5sU*;Q)(Ho>hGI!w72=nlN~mLcVCEfLu|`aMSv!Z&-UfZPi<0ihkq0W7LdOM zYmJbQcL7areD9x9UlMQNc{$&MPt*AiVD67rKm|TCyduKw;jAO=cdgfW8&~|?q>`Sq z9L`r+7ATb@bv4Rk*ZKBRniS$UvAgVUINu=X8v}@EpQJHFPZYuB<}Hq>d-uW3+-LQ` zbpEgiWT|gN>FPl$zuN0JKDFVWHF4~0ie?3cR1p>o@=(cjH^z#Ex!&koAU%obwtkP- zpQmd6`v-uEHGc0HuzV)+w*R-4H@poiwcXH?|B0PsXg6D-Ii)X(?lk=SJbVpr=>W;k@g)5igd~?I zFvRr#=Eb^qe?8M-tm#g59uOxqq|ofslm% zv?}?B4?~ms+O-W7-bXu=YA5)1+ z`Qbt+p;K`LyV=`pW3Lh5{0SbIsD*|8 z82TJ^lvAuu?f+?j_n9k=9BaI1BvWfy`l3bdys~KGP_(`7G>L)jR3T|J!?>{H(I!S- zaT#7Y-7B>YLrGM<@9l-Ic66HYtVl$iT4tV`0BcjY$mag-4=j4Lw}dk4`LLJ37ovsT zB(SG16z1UcAYyt~UvpH8Y<=>)e!eYLwUDOK)ZbWm9{Q+KaxeWaLWVLe=-+|KXsL?( z!j~ybjDxUwVO0lm=qZ~%OOB@Dw7ufhNIf4vpnqs*7dsju>{56bl5-#i5A1K z$M>=C#l{SIn;7F8%5^VuSD087nG6>5sNVof4(RLuxxm<`Vr^r|N@kuA+bT|-jxJ;F zEt`1oav?XiPPzoON#Jlp&;J$t;7<|eBjDeLS`N$!+&oec;6@@AsNORm%7b(MLFI@Y zU##wK8F-C@U+(wsI~eLYyg_37BxK$^{}QJ!P5C}9hW|^98e?AjLYhNs+JF>yFgp+j z2be9l1aGk^LIX7N^Kesvit{Z6dAyCugoo7%DQO7PKjL{12_YC^(x>y1)uhHPHLo&yja^>E=sa6nuE}U>sj?|@b3b0<7ho%`E>ZoV8@5YQi&2N4HFhNK@{CnmddL5U`B&WwFZpg^TNKMHF1t6NYlU!htgZV zr;`E?Z0b8~d1CQ#RRfCgn?9pYue*>QPv-UI$M%*hhPI$)79jOcH|RNWWuXdN(eS`m zZB&>1Iu$*jlqj!9RVNAv<=;K3E}@R+d+Za?uaBZ(G#H!{-0vR_)}jwR1RMs+-}qpl76UNZwx%z%p|A8Cy|GqBw(vV3xJ&keGTX(bkq)$^ zm2U5&%Gb*-z6Uu?(iHct=uUr6AIs}Q&$a~Bt1fF_n$o=wo$=kMszN_7JZH#F$Nw^0 zRarfMUWlL<&<$Lw*xZ+rY%>{}nOMCephMnYuy&=M&xaaA&DoCEE@u8nYBL4hH}e;i z`^$s9H(CT05|aC>Esj#Eb(f>+IQIW`V($f6$*h(~z0p@;(e6`|pHvT~;O%hczw%45t-Jk9LC)S-UEm53sJVGKBh9aC zNtS_YMOdhY3d@4tE-IP(q1a)XQPyF?9z({dMu(w?O$D+DmrnTj7&7c=J&&_yAzLR) z4;OrCR3{dZi^2oYSCyd16t6#K-!`dy=PbvQJR3 zFJd0_0mCpc{&LVU-e}EvIQiITC}V?ZMJ~goFPNd!XMhtkefQM=cTvh^?ZJcS? z8mMcT?;Gr|`hI-FHKY`ERi;R%Iy%i*=*?jNkpDc3z~<^qojLTETH# zFG#DY!TGtd1T6nyCILzg@C{aNpOIf*+h&rn@N+06QbYbBs^J?`=`ELCL@`2j8s37V z6NA^{{|Z;Fc$SL{w7rHxQ^%iS!F8T!CAqBe5yFoKa5{zm?i+d`zoj*hS1HB)hL zve>1%r-Q-q+9YDL*W_2$q1_DyXigJ|Wn#)i`4`OFx5mgV)12MKM~^T$p`k(0wyb_s zFeu#jJ$min!Eyac+*GK)1>eq?mu$kTLUJ$OGiDdiLpp4}3rhcYV1Ri5(y2Y?JJrooyJ*hTyOThP;7UR zxtam*4fTs|5X2ml3#K(yK_Ali9K5CB^>LDptaa}uCSvc7_U!7jkY=Nmc|h37)pHS{ zQ?H2C2Vx-F0s_N^-+Cq>rwq=lS-tq+ebEbTq>5RjO+0I-+NeC4duUkU4W&%?dqS zoqFOWVs5XDJdG?pCx6P0^mLW^(v_OktH$n9#NlgTMrU4OPt^0PcJ)kDSIw%JnvZG9#ye+}ew6WJcbRB8 zpteH*`P)*X5+Skp!UjPqIwXh4555e_Cf-i5NHROoDc=k>$?#BxD)rTP-;sBV z+wnf<1NetLSfCoy{dQ4w{8dZ>@j7OQs4a`y!^GY;BQGG~7gqEhcuZ1GaE0v2XUxw) z%_P0uQ>>AT*2{zVYHpYn5F;GKt3+xWVdxUNx)T(%%52Z@M-q}F5Trf8uLCo#P|&OI-~x- z&$g%UjT4Bz>TcPp?kI+*owG*UTTFk9Hf<_>Ct#H zMkA6J8by6_?i@dt>CB^_F zyyA1mI_c$*-ViMf|3q%1jcXKfjjed$w%v~4=r~|c(GjXyRjWK=6)E9ioW3?#(*@Qz zJ<1PC&Or%xKHxjH<8kT-$=r6T_U*$pKVz5-lgxvsSD+t4u!FyfKfIBh?x~BNIvx~++h+hC4~I}Lnk8Z|9ZL19zc{BqsFDXkMPZIuP&&KDFAaG9aD zh4}q&^;vw??x3f#0AGJ_8`3dO)6fv}D% zDVuje!v4I;hJ)QEzvxAdrw$_jIzTbiX`;93gfC)t%od+>mm$-sQ6!-AZ3-Y^Nqrqa zTE(4FmLf%lUe`1gd&}idFvLb9hx-pvyqRhRhnk5*y|rw-skz_YzXTTO*Xv)!rnwY5 zvl#~ClV)#85bWjM>@LB##TE|t&f&6}nu!VkZT)skK<5RTrXn~IoW#=|kaltGbk85H zjbsT({6gvR`DB5)4q@s^z4!j1^-Z z#6da>b(0Zq(*T%{^dD)Q`XO~&Mmz%CIzshd$c*M&spG1Pfano@%(tE}&@}c%i&zY= zGxk?X=B1#xG(tI(E~7SE{;Bo{meNMC}SSYroysTZ|b@@7&n;ye%$C>-!bJs)hf5;L*+ zUw&GlT~v->e6EOzd%adiTE5KK*fC?m9bBWo+s;sZytk9n$%<3TB?v z?M9bn{bk%~8k7eFL_UCJgoI#xSU79V3sdaF?=5i@^f~VOqg5mItkuo`_l4ayEC#gR#0{iZ{%Y-W-oOwzd$d?F{&Es(rG>N>w0)4zd|LFhp_+ zdhkw3-lbY-DO7z8wb%*hQsHOz*Rww~@d6Z(2Q&zHR6_bn zu{bfA*qg!OXka{sP(HAldOwghLShEQ^SI9T39)4X_b6{2$;#+f_-TiJjr3go@` zoU5@$5_eYdOYupIIG_yy?=(KbB)Ba|u@rdAK2Weh5yo7|RC}w} z_+Zs<)}4uC56LQwdYxbhfbJ8j7a=cJe^-cZD@cwp5n&as0 z1N=a891*JFv-Cvd=;+)|z;q@at*+y}w}?0@Qdf!3>FW8bsDaYNeXV~Zd0TaycId5|3|N6MskaZITX?pMC3X7pRoMuF z^aeKFdrz}h50alM><#sGOyxuXX~EHZ=E4hWKRE$aZ(iib#_ZFz*Fe?4`3k&}6N`eV z%~Fn1S#t4{Qoi zlGU4_p5qh0q#0|1twIGg`$rSjv9rB>oBuK|0Gsv;8?@9C4xqTcCL5hG3q3m!fkMv$ z0+$o!<@DM&==}Si?PcE%vr93XMnf~e4V7IYX2bFquwXi-RB;6 zcYuI^9Gxh|ta^A^Y(n<1tFzP=SOXCRFrw1@LmyH-r6h<2BP$Iv^BC_=T`hClpFk9^0 zOp{JTu-RvoU)sX3{^xZsMymh1-CL@9Sxw-ewgCzvJUqT9PwW~F7rgB)r4$fp7T#Tj zxVk#&fta$RYGS{GEp?wTJ|Vx|#}a{NRL>9<`fTtipu_nStH!3OBncsH$FuC(&|!Fi zh%go59_SWyzjmP+(-3I&(^Xxgb&^Xzu;uao$w62(o;rl?xd{EyffqR*{ua{KKrm$A zbRr0@okq|p)#|#lhRZo`OYl47m%BSTo*(6fnka^3^fpVULuLGBzsJI=q38~JAZINH z_$Ckj^?Z_nhD$0^El_ZTQ<|IOPf>w~6(|iq(5uBQ zi?jU{V`Q_dcz%68;|OQOA6#~dqJX>T9rbf%M2q|kzkY!;2&`8~yhl{(RU#K3D@;fz zisi0H+-f(^PBfSzodcdb{Rbe=kn}Zw!GG_zqTXRm&0;4KzgJ6o#Zc(!eS4#7UL)v1Sh}>UwGkvg|+j=^2 z_cpp%)qcF)PJne})IPfZ^;(U;-{eDAIlj7-wFm?nc@GXdi|@z=DvbX*BvTriNsDl^ z1*0kE7+g8ncls-;UmR0)++Y=8LN&U_Hzx9g0L5eSK=3K|_bky21&i9CdZBrw=un^S zNbo3-3dY=~n#kfb!5+q&Y&I3Y!w{o(E@Ty~?&+OVI`|pC+=B9-=32^bE=8Zpe)D#C zs%D`-Bj9s02=sE}s#ff4Axvz5vRG9Ep@HZeTZ@B{sDrxBegYRtX0zCh|KA>lzG0Dp z$?WD3P+8<)SFS1=Z!V#}3V{-YN>c>MzU9C;XEq7G`H}+%5n8h`D(5M@}JWc4_?c(hp14?BBP&vSwiJhX&?GV-^?hs0%2vtI#9hmpbA>H z=Uxl|F*Maj+3f#VaI}>T+T7(%HtSfTcHIE&Jg=vxr)Ar>fy9u75aT1jt7r0hd8$mQc1*UmyCdD?u$8q@%E1nKpO|d79?|fQ2;IrAnbp0nJeN z0&kZAsYvRuisoNlC~KGt~jXoj{So?T=>E{Avx zm<Nd6wpL&2=tA+Vki6Gqek#i~hAFi>S4t zo=a=$Q!Ur6^*oDMrb^f!jpRqC;keGlI3mD9g3{LI1qi7KLaf5`UQM>zn|*>hn2FVE zCJw36^)8d6(BZ_yn}J)e6_Z|)Hg5O?DQO^~pI%1QeT~&CCsSUOe%^*XE#BGPH9`uO zz^zLg6B`46LG^q^cr!PHYpbhlL@&9sAn0~Cb4ihb$6l3k)Zk-&R3x;k)#4&& zqV;?E=$mCP9l@?H5>5n&kc3m3_XOy=$!c9Kl*^%T>1mT&OsZ4f6RZq#=kn4LVtv}e z%AdLV$1(Ox7@{vO+B3r0V$`7zN!+@QM2U^v2DLvqqj$syu0Nhr}Hjzedo2h2C_NeW(k9C z!yj_Kd-v{8O-+qL`hRr@ zYMdA9dMJ^`jr7+u%lo7%Ho$m(=%>QPEv;gW;#9ZLen~WDEqG0`X;Ib?3fzOsIW#9x zBlFX({3jozzbcqYn6O&lb9)^1p9>LI6ef6des(d#V*4PTWq##f=PzWA4Pi)kyazro z=uDloP*tN>Lq#LkULdi`^tvC7FQ{0!m9j#{bK>>905}MX0-9s=I|f%QkoRgA(wU{^ zQ3FO7RK)2}PTw>mzO>;UI4;K<(xpnKr0w}VlbyHNyw)QufGC=WfbJ#R8VvheM$G!LXmCy#Cc` z$5?Mzkjx7mR5Ez>8jX*}gt74YI-&9bs?W32KRR`B!P8cH9w@h@LVD*)A6vu}R3mx{ zo=F$Y>s7MR{%!|tdL-`i`McsbGeo#dZlFYi47XEbq|ut=`K^NPW<;$(pO&FiK)6fg zC;4153%ALQ@Cv@_+kTA; zC6Ex?Qs)Vh&Tg45#xR0RxImX|CdFY2DQ3d-6O8k$wjpXQMqs-^ehK_2+PegSpKz8o z)-qGTJR_**S8Em}ahKb1PKeW+OgY90KgHO0PaQ`545Ot}&px5VvraCZv6&Qbx1s-I za-%aa+P&R3Xq?*@JT|?~9H``m_?Z>Hv{q`4YAS^IYJ~V2Jcp?}dGxM{3RK*>bqf_Z zxQ4h@T3_$$nq(K5a*!Q0{;+I;7~)~d$Y3w72At~?XWY$M+ zl-Wb}Af!U61_n3c1c$e;`ihecdAlsB!23S*_5-NoJ)~#jC(_+`N=sSU=pNP4NJ{GR5n`bz$@kR|8an``a~%_GT80rN&% zR^DhQ#z)+VLsb!cYc?YDb7R^Ifxg2H7?O#PkA$UxPpG?Ze5C z?Jj5M9bO66$q>ey^8Ti}ri!&?Wd%UnNZ)}eAtbWbb>mtnq=2JLX(w8qmsoxlXj!~+ zoUQC7GR+QniN;W4e_e))Y;SuBl#bJ9!8vQxxH)IL($l zvkcPoT;F8dA27^1Lj3zS(KIKrtPG14sx|S}|Fy4XysskKB$RrbZB&AY;%e42p#-oCsLR5H4W`-ojmSpD6w3(hm6*_aFZG)kQT$9~-ylGs% zwfb9ht`pBI45d>@^w8rDBxy1?qhBXRBd+KZkXP4ER35ccYg)Mg+Om~?iK74J{9Q|` zY0+h{WuRAHX{~Q=;ml0HjEDi3DgV%5V4LlwO+jCm1ZY|G!Dv8Pwc%Quc6jTUyeK&o zS8gufxENKb0*Ev76vw)ll6HICwxDVHw?%bno$|r4{OC~1R23LTr_Pe-6$aATtlB$F zgIf6lwK91viiG}th$NXpBoZgA2dx{6MtZt?ybXY$Nfgvhx(j_0-5N&Gv!Np3v}${?1fAz(S1(Kh?2eNw0Ku?FUaqg5FY6%{v6D>kmArE z_vnL1@}@$nseU!q4wq5?#8r9oS}W7$k=n=)rx2OSn(R3dG|x|n6)uI(r?$~( zBbs|jpyEAvug2!J%xmH7Ou5SCLyl{?R<)0dK|bp%-DJ3bwBPj!hcrWp67|%!VA0pM z4|xc}Zs-;~^DS3g3EUfcY%v(?y1V0na^Ff4a(wD|^BTvVAq$J1i_U;m#Eh zInA^J!@qZxX68#9fTR-QdgYTLW1=i@D1K2Prk0- z>q>+S7}eI6HA@!k+Ar*WB~tvh8pec%xkuKvhMR{zWeNvk@*t@~4!ep&;h4v7Vy-V~)fCs4LZ8&rMmQOb=+i7LV_WnJn~7h`ozTJddQ!_$|Ju z-)^A@y}*zGV(F#3V;g5 zIos&6>wm8L%y~y2vT6|>Ic^B1B$CzC9t9mgkY7#RL3d23Z;j&G;?GJx@YN_DS^g{yDIKQ$?$-@cj{awr5Q3V!wM@Z+n9h(8LluDjx%A8PLHZGg{ibI`c?YamG|)?{)_!Pq6VY zA3F}$Tm0q0m#Negy2Ghhn+K7W`8^FeXZB&$I#IgZrFMP4tE;TVlFdP=6*=N?QUu%K zqf63`JpRs%40d~x*yh_;l-yP|Mr}B`;q>J8xAyt5lL=#?RoihrouDZ037IEs*Yi}k z*sS3-I@o;TCR?xT3up01)_S7;@|Jv;XSP$0KMNk@ySScs5o9^s7}=^`YLqMPjU?rD zo3isRBzN89X8U7k_J+qX%+A@RX>w}kERt>RAci0=fs8Mc+ZhxAqVmsY-(>17J>y2_ zP93=~1T61D2i`B1&-5HU@g$=ne>Huut9MoYtl+tqrxQj|w+odCw3a;aOjg8o70CQZ zkRlv5qC&Al`xyxd{UR|}-$Y?8i%41AAy1#(?=aW#S^`NNyZ>Bcy?LZ8SYM)MQpPH& zs7*g^6HM5A?doH8MNYfCFm3!ON8)DxaiK?W`;Fj2>4`(i`6xSujmqWP9$u~8pVSV( zHK(Z#Fpz+yRkeTUYZ^l6W%Ns>B*O=76nkUhB$jewYeSh#pND$6^<|ElI&sKJYo^4A@1D=_8JpNI`5wp z95mu!+}wPcIk^F30d~iLw#HYlP#GMAB4u^Z{9chh4@(BRRjGU z%+jT^nRDdYN>H$)&uV?Af?C&TJ*8-K!m3CS?XpW>~xv5!W=Ts=G%04I; zyZ`QfSVQ4praGa>HJ}`wDL7;kb5#b-9O|~cS3F%H=BWO zFC{>>fbZznU*2ce1!9~}k-wD1g#_h#uL_@Rzs&V6PqBTcR=F;<$dRHkqi4NkKcR%H z1D!3Og+X>)?%NnyF8!JgFpQ$}o`QEam@cNIBKRFXR5u(Le~BeEYE9Oe*SoLeBv`?1 zA^5T(C|uuPo_th1BrKo*7x#+@H%$zpSVW&X(p*M^n z1u?|sV%>hw2XxcDYoeZpB_sKekdV<)^d+AUXs6*I_Dl`&BH^Kb@vw19Ajn;rj)Zt@ zhw&EI!Q()`{d(2K^h<|isYG9X5s$qgbGbKs40B)dBDCbj@B_pmgOEkY30uC7WLn>d zs{NO8guHRfT~mSXZ=_p1q1NRMPcL28QV%9af4=P$a7QAIcPU>t2QIgF3>+E?qP)(^B zW}IU`at~MJYU)ko%G>Pm%2QRsE!;7e^<+<`wB6Z9^u2)0Kv-0llaa!AAc*yps%Jz( zLUmN*6W-3*1r+xhe>1GLx~b9iE^QjAz!aFn`$QBh>d#21c3InC)eG{iogha5K}4$& zc7x{&)Ty8RQcv4b3Fc$1$&~baC(+F$cv)>)-;2@e-SSe&2s;~I#A}H`f-V{tGS_L& za&?e?YDZUN=;RhV`!rY5abtW{j?O{8a9}Q)F$zY2EYM-+H1re!u9r(B)s5U1;>jlaT=YOGsjg2iMPG8rlWn_8IJRmnsTePU2_(0!4 zrM!Z6X}w-5O-4QSU+eiB-vKMN`8cE&6DLfSa5Cj(uKWA00J_g#On^Q$`$+Xe%jryt zn{p0_T~SyI*43%8Fcabxy800+xbg8r{FYZPSBf4oC>V*{J;84j?!#STI}wRobB*w| z#fgx%_3gLhnW4Jif$-J+Iea}5sCqSLgmz2&YMTLl>4m|vK*WbJBY8z~Ijq4e*2;{L z+*KJIRz;b2+?2ujzwUDz&1^(ZugUfe69WAfe)rM8otDA{f-F<}6?6xdC0S2U`^#I( zuewE;P97(li6774&(io%Q8vw$|k7Yy_~+KMUNT^~#1X6sp>$-4+)fo{Jm&0oZ=5JI&)n;e}=b|P~k`n-;h zk5w|X7ilCy0}Am03FqV=ZwAIETDftFvk5sQq;JpflgK4n^DXE$R zefjp=!~9vG#5OmlyJQeH`&s&rkeqNf3!vuk=Z2o{Zo9B}Os|jAYB682jh^agkhWzo zJ}tSw_O+y}V5*>J)(15Wc5{@%tDJq>joulBB(~U7-C64ZV#u4q-Isg)b2f}w48=>W;;g0?j^yj+#OrI5q3lL_ z+`*v1o=oKSpHf+IK)>ITymrfWq-ytB8iw)-QvqchlB9shM89qa+17oV4^4Oy*b;bT z)M9e1{ztIADe}M*l&jjECKw!?no+O8s}X=WCtprfkVqZ>&67-K-p&DZ-UhWj4nd-- ziO(gpS`6d{Rs1}rU6t{9g%TNd9gnqg9gNPxds5%kZzqnIqUWLnn7R~z5Il}e8P%50L^b`#stDICy+(0 z6f)9N=RZ;-Cl5NmE0EuJ6TVq+j-Xe_OUI7@vj~oj)#QEvWjtZudcq!jf50VJzJ$^^ z4ssii&rO>+7~Lt0b9J&;Ned597tgo&G5E5;kxyht!^GGCaAU)wp3K_615*wDSIOG~ z8kvIQxjEe`DyW*zTznE$&V$20RyEa~?VyGq^B>jrz0X++9uy%mA%jC^t;H4htILuJSsqsT(iQ^IYzJac?p;0V4TO2 zuK2O%&k!FSKs^$k%!#|d3VZ~xFC$=w0d<0!io046!Bv2?N`4d2;-SsB({m@#8T+C@ z3fT#5v#+sGEHD36pPQR2!^n0K##>^*?o?3dJ>njSi{y5pHnzOG>BN+`YM0wPRk;4( z6DIHOkk_hwQa|zw*>Ov*-SL1cE0HBv;PU8J^SKCzP?pi-nOfHBoy~09OFBj#vG{t< zc)3!8*111hCz5U|5)L8_deG78vbO~DqY&rlrJ3{FtDfwPt>WF0<~Fp6hZ<4mZN)*f z>T*1d;X$Sn0o7u?-disP$acBj7(NSw%-m84yJ{G$*UfUlNcZ(p|vrCB7`LN&PMl(V*>&M7rRo9L)mw%VTUpO5s_BA zerOK;3d1ac%Wmv!Y{&lCgo3mxLh?~3+tNT^twA-riPD%M04P=M$JbGr{Q50`mb_ar z&<`3BJZhyl$J1(=dAuH;C@z$ygk1Hp*1J+* zZ&Xs>Vuwx#UoM8fF6jP&sDKH04w<2@Bdgx(3Z($GnZ}^sqVJ0}%0b}veQQ}VEOU)* zrcEzu9EzD*4Mv1FS3~EaY2=)1Pqc55+E!DtGtb2gd5xAzE|u|QFGJvFEY6L+Hp7`d zXiTXH=+R8NB#|$FIBReQ=A0_=(QtLQz|zHOYNNAna^a*JCL-#K8s81O;b$L*-*^0Q z+P68x@-}OU*n@=LY-v#`gKTmkEckIl+#^D@!;hE+qHT413f2*KB%d}8sI z79OkT)*ZbE=_};PXVY8gXod{jDi#*}3AJJ?&BEW#%YK@w1?ns*Ks%@o;r>9iZ`#s@ z5Zb~wP!R98xs%;dem4%+8m01EHS<%CnVFeW;PsO_G0|?~2fE^hG5v4&3J3Lt+Ke{q zdnHSVq7pD62^@I^-cyAotqO+TZ!zSD=d&Nbh2Xb4Iw`p$j^%uE=L+H|Dcp49n-_)D z88}mN6qE`rj)6aN&({dFsT#;JcYrf7Eh<5g)Wcv?Am40(8AR^8K2Fx z)~Xl11@X>P0iU15t7In@WU4u&i%;VLE8|Lor>a-_{a1?hl>_v#Sm1NflET8x znv@l{a1t75tiu4`=`p1)G6j^^rxxjXv6Je+!sG}4ho|q1YU+Es4x*rfpr|w{(xvy_ z6r?wiX6Oin4gw+cq6jD`y@e`Wgn-fm1W=?y=)FrxLhl{&UVi^)z4r^OtOYCQoH;Xl zX7-+oGL%GDoRk4{3UMXkG)Dl548K}0K2^rW&X%PHvFm=E8OGy@23r93A`+U?y-(=Ry&M-fDD9&Ju3-SaZajjI~bgyx{BS(%ois zbqm0J2%WDzWa5)#c1Xydcfp@?7+oFxQ>xBCYcx!j<*p+u(H~L*b8y8hdFMK9@pYY9 z)Y@oUYXSK4%q1_X-m6;&5|0_AN*e0pAR9B`PnE5+0wXHQKQJUTaJO&vK($(YTOhB~ z*twD@Y{6wP?&gM3v|*aFS>hHK_YATwzEsw(tFb!Jw&8r!+gXmiX5a4FiM3*Z$UX!eB^}B!+ld<=%cLY38v1Pd z_gN(y&F|u`1HebtvD3htN$R%qA}7W1*$-@W#;T--!T|z4f?<6%m?I2Gi9Yzlp|O}N zxG^F?H*fIDbkJ9z>Fn$b(xH8R&6~8^uuTjuo^-y!|LY!E1XKb<;83ESrpde!XnzjQ^&af@j*OnlVQ#V;QS`Xp%=8Hr#BVV}|?t*hV$0 z!_=mNF?FUa0RO=|cSqR3EWprrGA^)xKQ()^BCj-qPe=_A((oRQ_S^IMN~a_xsB~yw zjO;m~efzqH<+)C!WKe z_LZlfbB8T2{+3=UfRAOiW&$Td&G@f2+g!Qen=HczSbE|FmHD@W^No97dibZ)ON1I& z6Atbjb2nFSjm-zku4Czw)ct&%=#CRGzWRs^p37hj%-rtO^mhIJs*FVR?gk( zmg6;t46em-MwRjMv(u+ehzyz0%I_$%8uaXFHY+Z!py~*Ls%Hlv%oYG)BH{ikCH^G^ zNAOj@ulb4!qBz~HJux=MnUq@3Fp-UQb-C*0dZR{2Uoqop|220QW@22T&qun4XPL~+ zZM9roD^8kU7@AN0;*K5uq9&?_sr`}U>#4BUeVCW$6onq)1)N63-wRRr#>P`#DkpC% zH`3zfx$lj`v*v6-xRmg*hluqT93PK#hq8PZg^tnU2-5}}UnN+Lpn!3FLO=UyOvkuW$z0t#m@VGe*8TR_aNMH~ z_xi!hFiRofHmqR(o*OdEyLReqE?#lI#!9DrzowFZmKnDemfgG%UX>s}Zt7MmQu^)~ zWxU#>d3V^66&NqjLJ0T=W`LjkTLBzUR&p7Bf5Q@f%R8l(qoyFHxUcdVo0tte*m-gk zb67UjQ)vry%Ztp*`33s%FDj@s?kZt^e=*oDHkjj_w4iN{7*3z;%F7}@I7+sVl$mKl zVkMM*j5||vb+a8rFuj3JM*9DiX z_2Oi0_tO_JLcc7j!K9ZJIg`7rrkW5x^i(MY z<6hoPNlufO_zbo;504)&mAM=$k2xn|<(1hhck^yOdAyE)1&F41vxis@FsCPpK|*RV z^xw%FEw4)Zw#^%U$)~X;oGNpQcUgbY&?rE-Wym|t4%;2~YuH@sRyf}XGMDB~p=iTy z%Jeip?8EzRU6ovQYz(1&%Ra;-*c&8Q-8EE85tdrs>$@}Lug50GZTB^UVhuFB`g29J zZD~sKBY~M!SyM_SI!y;1OCAN})w~U?>h;iB#;c}B`zQTOZ$zUN9a!s29xC)l*^#?m zE+!Ak2i6W|Fxn&xojRmDBs;AO6Q3EETgdpYm#UwJXn*Nu_vwChyU>x%AaAlswEpT6 zNF9h755H?nJ*-Am^VdUB`QCiU)y8#10=`-^m_glPlH;An1Hh8?l@{%|-l5ov^UvGe zO+BfFqcDINC;ZVSN~65Na&t|O|59xb4g!&v0g?ee^=;u{K(!9+urY$~tKfO<(@cQL zr72X|v7#<-SP~{KPP^GpMQ>N3Uoy%;bee7>)%vW?DuYy?>m0I$XCL+i{#F(PDW5Ye zFB`VsXA~8iAkga!cRbwnkS{CAn(S-(Suom&!cwRH2zXU!CQUWcUWoINj`~I4%vsA{ z_vb6UPLTgG4ddBxYvB5a{;UR>dy8s0lfH$$SyoBVrrJuB6!EC~=SFy-pj-8v4+fWg zahYW?yajK-PtP@9k>hLU&4M5H4oQ%$q-rx5@N8+GfMM^9g%5S*~LkkgCx5aVL?4p4#Nj28)_^rf*xfD8TxpnT|J0Wre+Vw!=R&QuMFzNm5h)(D+b3jx}g2 zlRvewqMxi%yzdG_eaIhgvn0~~D^o?bu-Oi+VMl)TJMf?KMjfkC49DS7>1m4`iIfig zn#ok$nN-5N#&55+lWcck!t&yb#ijz@6g_g%*L2wS?qPoXx3{oDa9-R@_|TPC!`UNm1JSX!F+p1dp4n!bT>jzSnn~zG$Y6lZ zu+CLy%<+@DmCYAYT7p;ILjpAjvj>{-UBbZ@);|x@rge}PTe4lhYBzpS!IXzq@l@6q zng#J+dc5j2=#S5OFyv_Yij1=KPi=)BYM&eT3w;&E@qK%zm8&W0Bx!>hrxH9`NAG$y zlRSQCbKrCQWjxW5-T}^walv5hP%=Zt%mIyw-hO)>a`AHulDXyd~WDBjZ{j`_F%eaqcL1k-7oE< zzhp2COU45n!ruqF|0M<4iMW2?db*1*52^U87qmu^eJ~r2(~gB&0$tyD@Cb3+TagJ8 z2(8ageq+u!&DN~*QOZ4zQmM^7Bg8eOcRVw2bjQc}IDE;i^U7z+)D|=e2Tv=JDPn$iYvsLDpMtU(ibZWv4 z(PAvR5t*K-bj;=;be6Lc6@;${QzTA~A4pIWd*AwzRgEb%p7r}EE?{tf6~0gA)1kuw z4Q;UMn=}$N%yh@ub|2F9Ul!eM(3Jx$EVU4ziV4Rx@Qjk3y$Y&)7XXM=1bHTe z*t%8#*q)tRxvrp;%429uhvmNBn8 ztLi};d#$OsrG39$o9%Hrd!0FiMV^+(v`?2_+;4-6bXL}ZDd#HAMtbHr8}hl$J$WT| z5b^?(2EJQz<|PVBoOFieJd)nu@zFA8=JRL?!=o;3EMnGcGKfT6*6Lf(I}x3wn^b}M zzbaxHDqtK9%({DjB#F%{Ab-T`i48M-PrXCqg=J#0zo(YAooy~451%_ zA@+iMH%4+pEkD2+(o<3X&(jQ`k7TL)Qm4^KY1tQl+U)&4j;nxTI;6~A^>z{t(^n!(7Iv>XhS?616p z_BP0RmYSErLH^W5?K)7Sw2y217&1~iLrypQ&9>3ic#30m35IO$iu|1S8GnfpmEBes zD>U%Y2hMu$+>T&ct?6=_DLlf2J*dRrb;W`4%DQ1Lz}6Y#wu?t!&z!8O1@7-}$XGXQWy5@-k>3sokhkFNR0 zNN?3uT~EtdLl~K_Rz!)wgd__kg)>Krll!@)h#8C-mVlz*J9+sY&%hGw{nRPP0vAGd z4d>E{*y4m>R&jY3p!s*v`oqqw9#*kmDtQ>`#Ys+VX3Mz+Y>1P@)^7t$JZ1RL!|W8ah38=I&rV7`UP+;y>YH==i;!wP4`6Q;^h(RBqiKVLfIjsyY@6Ou*4u=F%lf!gK%#AXE z0MYBi7L_JHzAGkZXZ(7Kj21ADs4@2n4V||&6hIU}j_R9?H~S;WJ`n#fEYXR_0gTTH z@RzGL!xArl;QCa9xzWj-yV^%jklNfyKd5HiyH}cdgoZcm0yaAMf^|2R`vM3;ZOT+Ar2Ful`xkayiafWf8)gcU{ZIQN&YU8~dcdmgFzu02UA5YX9VnWHAV>QCNgkpt5v4)nP=Ue@+#uJKBd4A3E(UTo^xNyXX^W%Dc7ufO6 zu+iHBIq^&DDYdM|wS%6r=EKQtr^lIU@rKzRlWsiy{Rgn4;}zIa>1dJpZbGiGZ2W0V zz0Jf5BX>a;i-ix>3LwH1+s^f^+*(WWf~^p2v)k_ZI3w!UQ0Kfno8x-mRJgitMq^Rb zYfjyg(bK@y`p)Fbwsy7Y9SIY!RTa1W(rq@usNnU%TCjt&(ecUUM*z>%KU|u459f;! z!nH+_nV)8RtCvJY6M}}p7S(6@re~?}@JRHH1EARPayT6j*m1Ty=cLaKjgKE!x=h!& zJd+}Ol|Pv_JKn2&rBry$$G;_*Ij2_~V4XjDcAT4MsR^VwIfAe(M>BndJI?>Ba^5=0 zeQc0Z&@b$C{c=2Tb9OBaGfxMnSy3n~T?0$hk^EPPzhWAD<$gdwA+E}Ee2`F{^@F$tuC(>6jzw^-_-?v)|0?O#+=SIkCio2IJ`N5X&UX#C0iY7u zdurRJutQ{X6#b>kv!ZjK^v5Uw93Qm5B)1IT=iy3BXjLqL=C-@x96>FY`e)qdDyPkG z2emSu>Cm(Ru0Q7`#o zPFDdiLnlq6JE9Ur_TJ%Nyas#iJ)u6^^^)53Nw3lF6I8yJH_~~bFKX497q^&l*sUdH z{cRf z%rq8LW_h}f2|jHz6WOB$6~;V%&E_&~Vgu731cTJ}9Iw>7qB#L0Eq%J*yrD7N0f3}u z>N*8`A}MBXpk$Bwdsn$2_|nJRTuOFu9FXA)Auo~j#j&(Y{mLc?H-MPkLdfesWFaDR zVw8?3brB1)d$BrL?S^RF00+u8_cJUzn!WDGr@D7^dG*iM)9%nP-glFSv37I&hltjQ ztF3qe6MiD!Er6m_ZnMG-^BDEblsCBM|C1j;oXTDCtvxISm`4D%Da?~zPonCCmi^@s zeN+x4BV)_uiHU$6>7{fL?Z4jRkAL>XdKE6})Dn8h_)r7-_6t~|2@`El4n!bLs{AFJ zwKAa}VdUy-*IzrdNB_zyxh>nMd+B(rla1~5O2K{v(OGVqbpPh(cvA)o!4Z5!EiYWS zA(7p43M?235aY6JcNG=SFAuvFZfJgx&I+7Nlb6{KE%_hS?RvMVt>d{HlNAR+0!?cL zLl0Juv~|m#dt<$Dhe9TA06}jcyZ>7tFG~id-zD&jJo!qZ31}`}3>Z*&`k!v30a^+h zq9+2UG;6tmnOpU?`I8rbMhPTSrF4F|q7HA`tdNLS40;qgNih0)8>e{b1QWT+&DZZX z7q%N)6X(s6{>}=|eEjoE3add$vGL}{d4b5HBp?~Fj9gC>{|$M*#iPR?0O!h+s)xpg<3y&7xlR5aDDk(*z z7Wz5P}07 zreBFBfb)rent=ze6ka2-Pg4!UyBz||2AM*-e&w?t*QQlj45|$T&Xn3zP#JPPj+{&2 z?<+`A{Xs>)Y~CdFd6$INWS00jl}WZi@WN1eM?-hI8qCKH;W6~w!m~55XPOG#be?e< z8VVkGr3+jr_4t>YJb1O@e|Yel>tU5&uC=c1bv6$1^$}%KEM%aQEGtX1=#Ll55>70<=dfEd8v2J)4-L zsq=6GqT4Su&_*O7c|ag{YS}h)ueaUZtQ=c5Q;KifCrXGZdm|Olz406Aq8FS+b*#>O zQ?DpNH22~%v}eAi_~%pLyHSe+`kRfvYz}P|P8Klepc)|Ic@lrtx9Jj31h`=56ji?x zpUap#mXN52xVC@CB*W9+dhy!U{YApMd=4W8h^?l<+3~JGM8168IX~N_?v~SR;Oqo` zoKmedzCuAyN6z!K zRQnc*JhD73=q*sg3Ht3Ga!0q^(1OjOJyAk4z9+)0W-32v^{lKnD4nB8&Y|s|IhV_u zrhd66uJyRWqv&mLQ-H76Y`s@y1y8!c9kFLoioT@88dou?~cY7#n48CItR0e{Nj zZ^qQMh15Jd-eLZl)b4xlvqJ$;a!l+Rvvxfa71g%4@v6*sXz`Clj0g7#`FDX8vaLBTSJMoDPWmYH8U!ru=Hxa`}}^7TNI! z9>GLsj~4)1(?Y`%_6w3Z+a zj!QbyS0o3k^gka}VpU#F>h*2>bpIl6`vvu{CS_#(FeW-WT8NWkSfdv$N^(v`Z%q*( z$z`6Lzv6a}oV@%=KlfZvpvCkR$HAy$OjM*@-G*rbBnDGc|6%ga-^-Qws~YUH;mJ~P zC6RGno}KY4pe}g)4&P^AaOMll>`3(hXe*&?Zl8ytWM-WAx}|qRi5X7(x=(?#AHE&N z2<1$8iE6S&s0Za410db=j3?%iDHIJQsMMU?{v6vZ>fB{Pfk9G zD9YTbkM$Uj++6G5&B=-=y4c@;UQpr2p2_8*(}%6r6a(T&XAcarm_+bRPt$;d5pAQ~o^wNK+4ap`#+vGq&UQJ;{Aa!~{Rj zjlXUbzS1y^u+*^5Fz2_`D0tZiJ6dPGGf!DQ44}|L-~|C#zTY-o6N%7m8(rOdT~F?g z#jfjY)pzk+wacC&6dHxU)`&tf5qWDgW#8jDJjMNr2e(%incR+Dt5$c+n99)=`Ea9z z*JIg9e?nFY2-cU+xkjyd*W4@W-jp$juitTa)}xu#1~<9-T=q(P6$3VX4Sl2*51+^E z@H3c;&+7bl5T9|?LS7yFcHXq^$BULVb1U**mFc0=?B4Tye7;D7|GbZf%G%H=pg;dTtKROicgfV}FDba;ASj0UZN z^^nd@`n_QH1eI{3zL>@H;-(ZzNY%Dyv~Jj<2MH0yO|jP2|5t6%Uvhlhr@eC z40k5Y_dfSISNfZB#?*42m788o-~Yqgy3)@3B>NJF@c&hytMB@yE-jCf_ODM+A4dS{mXWBkYE z)xubfcNsTdcZF$u|1DM+HqkED2K@&L5BbH}UROI?T`Qi1!(7arcl4?nR~}J*JxCY! zYYIrN&gYEjR?m~{_qAyFHR?FG`)=H=n&B$MI&U!b=FU4E{q_~pEvS@t_;#t0G);?R z%UG=GTu&{vPd`Vj3>!516w(s-F|fTgu+F?({=O8slu~tOwek|9vcR6Zg=P>{i<4>w zt<=PgH*X7ukl)AUsiivKT0y4oTus>fgPaQ|AuTRek6a)PDBm9jQ=|v(Q!o9`@MmGq zZEXuaj6%8`_a*3dN?w!^&Cvcye&T$y-8O_?c~9Vm>*{%3TWXP-LIFiIwB4w`!zBXJ zf)HtR`Jvk^2Ani7&^lO`htguv9+IJ>?0uuI=A5|0)O}8habI#wGkCaBz9-4U zItp=OT}-gR5+m)hkCkol>EwB0ezD69>RqRaQ?c;95>_j#dEr;MV+kD_61{!i8Scq< z1;a`(M>M%vH#?--~+{Oq~6W#M$#POfM-nZl{L`J6CVKE6Nr zH}i1^QDYj)tFrZT2;K$6cuPPh%mx0n#cNb~iH$t)^R4VDkDsL9T}upq-D}Z0uWyNb zOzon*8gsBLI9G?3Y(|IV5zrAnUAf4hdw%u@{4U@^W(M|(=tA7=EMnB}oGPcXcg$Wy zEc)wWpIXVg^7p}inBL^ATIoDX@hlp5+{}(Z3)y&x`17@}C=lZW6-RyXzXl{<+PHe4 zgUsEkU@B-{jfiFBf`o_t`|&ca#9&&fs87IikbPIa;^zc-(pJs58s_J_cA3(NMc++0 zcMaZEO2}CvXbI$R@R1Dx#&=Ab;Pa?CVs^hSYo?(X+^Z-Z2CT$M+9}9y#2oOMN4A7z z-+EC$@L;v~`NS(mnMXACnK-#Cc$AIHP*YX!hQ_V(vmjXvfF)$7ubn zmg&g0f8zAJ;v1S-wCY51Z}Z;-?CIz2q6WZ}pBE)>T{3OVd{+DB^(15(f~tSTLrETk zDoZ)j{&AYb5|FC-aiYd{7th_Id?+!)zRM?%X2Oy7cKjI-wgON1b^i2OZA&R z*m|>nr3vD?I2asyyZec9ckR8DT?FhgE&I(U+fotEBJ>*Gm)#Ui+@E0#1 z3_4bKyf~*AzfzNhGCTktoc!Y;n?(t~{G*WC0}8t%q~Y=y@NyWXP!GBtBWL+zMLkei z>n*B_1uTc_6|2dW8+J#XaCSiFT#y{paVBAQkihlwCE2GK3&p9(0l^#J|LkNZ7czdY zp7tiB{z=dMI}((8&=_Cc=1|=hn_^V5vM`auA1`DwTuw&cN8W)4JW_ zVii!pkjxBJ0CIF{oOkM6JLs={#h35y>W*u%?+j@Cb>{=Q#AKK1wSUp`R7 zRHmpUUci_uGcGOoR%fN<8^yN{6CWe;u~y|U#R)=zRs`Q_I>&nTb~xJOJJ93O(I^ z`V7}tBFgRSV}PsKxkH=AQEn3wC-99y<-%~aTdq=eU%IQ^^Xf8hbvWh3(C^-iz{T3J zK<@%w%w2lLmo_^Ec2=K^_GMI`g!B9Fu#NgH-P6-Un8fZ@^vhLotRFIt(e}xgjXr6n z^gVW@mb+QGPEe%~A^ocD?e4GW08K32{(>BNql4p*xXB6~9hCXJzKe*(txA5tx9Dhl zp|c)HeeBEuiz)B4<>(!JolJiA$HYn0`40Vx<%nZ-pU63haL<7a9dY8qJ9g-hnMGpH zsh#BBuN=>V`}XOz+#DPn-q&H^@ZB>R$0)Mzg^lcq;DlZKjK-y1QVhnVAV)AFXC-cwmj5rY%A~1ix|-F(0%S zDI>|WdoOZr;y=E&Ps_|o3S^M)=t0DGh@s4TN;$#@=>!kSuE--c*4<`I57-HtG7nqt zkSlxK44(&SKl_Mg_V^jOau)TRfk8?oTXS&nLve9CxdO4|qfyAdbjT%1$a^#5Ci$_` z{YG6&9%yoo<<@2nOYiDE@q(6G1Lqu;b$|%R{_qVP-+2%h0eC4L;tO!A*uPbyR5Kc1d_}R} zWnSkFK`j!iY3&eDU;nmkn`U6Fk@udpl6&d_LiDEJdLMTWgG{k&L{Y z?%n9fsXRy^2Gq&iLS%kc81 zjEAA)yZ|#8fB)Nf7gFU0h+EFD7j>n!KV!d8_^kU%FZc6e)N+^{5a+L#BtIE^y`=C; z`G#qxV~(-CdHQxWc_PC1dHr?n`#UI4;G7>QRbd{O(n@v8IQnK^nIQ)QW^I7N3|4?} z@#=j2(C@ON+IVS}FETiD0ZDX06{3u_m$eT2^NWadG*OPcp=wOhQZ|vD!=!e2+P~M? z2+I?wBqQbG_%`2018Ew>)5}03r6N!L&fD=K<@~)LmdEp#CkMOiE+Sz^1uc4=pOBW9h))Ms)2H6e zv;$3!jEo!shqh;o+I1$sA_|Ejm?37kpmu<5XbO z(ahy98*n?obM`R`$BZ9U*?sT|u`1!wgXBa(g_F*6kAd|i_ON8%d}o2B^R%j>`iPFT zO)}kzgPhzW9q4~V*kn;M8bl!#@#%m{&9g6X6n^=aXv zn4F${;%WTK-+U5&8|fbwWbeL^y%I4`yB%zmupqb1Y*o(b^1%t2E0!Bwro+?aNYE zjGEufBKr17Dx&kf1l{-hN33M8aux>MWxL2Dvw#*N|Xe(&^)ex3c|#~-ad_l z%&Lg1NUc}s9^X)oGRwe^wa+7chJQEC=YZ3)G6ykN3|W(etGVJjVvZJf=-Hy$ftv$r z^tQQ~Qs_`zw?JT6O0DFwc90`scn|bfi?U6zq1%ZO29KIk+PC-}8$f~D#jSYwsv!Vc z51P3`{_r(UzeSrNejYamoNdiVvO%N6GrLz@7Y|}54c;paWrv|(K9{@=fc683-9x(6 zhw-FGd5(FfsB5s7^>WumbJ!h|8+nYo;+KD}`fc`z)9k`!Z^k){3fRB6(8514s*E#- zN9Cg9=9l5YM{~02HXp5g!Y4p1>P>Yv&&b4px>^mtBn1S2e`VHT>?m}XKM6#kxS33x zyP9dDp{(5UJCG`eMHR&Q<>m72`B~9dgFoB#`khC45sgtHVMx&$y@nbUu|RyT+Ej168I=-AV41mdWZ}wvp z!?HtHO?QiTd;+j^m6CPGgwz=csxR})OLga4>Lild5&}HjKSHE0mHrLoyjkbGPG87% z!WiS^CUig3t61ItCvQx<8Eok=oDx zy7hIsrX@a9emAmAuSt-C=tH#Xofaf6S8Iy*Y{08WoRxxNRR&8(N3fpsq1P)?K6*z$ zqH=3pD#e}CitHP~yXPa9612Bf2m>&UCYV7~aA=MR<=dhz8_-1GI-QmKO?HPS3&ydq zpZWTJns=qyq0w@}LuLY#KY}Hp_a&io=PIr4Z^pt(%f)D;cE8y_L0{d<>TfImV${P< ze!(8%7J+7}V2tyXYyX}5!Y5UNis1;qrbpdfk?)Ngw;yZ(*{uDtCjYDw1B%chkXEqk zihRs1F!gxl2czUi+k3xfJt=8ETJ(kq`fr?;mDmlsGWr7e-BA7MjRgZdR( zVgA?Fr}Wf6=8Y23W2;XajCV@NJ8lqxZYGN?y#``>;1UZ<>YKF(7ct^*{tedqK6I3C zIv(he8`kr$52J+@VyGKzX}<|)7MWn(v5g2%_i-HEFVD6)JP0(#Nz~U^=#QHd$Tt7v z8rqR#v`!?|j)5C{|YTCNhTXWU)4+8Iu9nc%U?Q-2ob7AQJa6z!&kU@UTTHl|3-d|2M_xj~|HB5jobMWMjkK%fA-}g%!Sxe$z z`_HqviE&`d;VyM>k<*IuW>v`wdPtAVSqT^OBwhMAADwo3X{gSUMu&Lr%+73RGYJVejnZJcgyXvGu7V7XD|ZQBBE3NpC#!JM zc)?Km^wZE$dKb(EMls^HEe4&LAkskeTpF6(^i&6|%Y`7LS6sHLo_2aJ!w&s|6#6&y z*1ann@a7r_!)bzrb8z5&WsgV8G&!C&pN0J&64@&t369&`&%Rzerz;wyWZ%T2<7do; zg=wO~b5H)4fbx7)ROX;XP8u-Uie~MPxK)#~zu7Z{L-fuy>=6`_%cox%wEXq*R(yC$%+By#Y3o z6P8CvJTLDwDO!dL8r>w&;OqFqO9e~Kqy)heR;DXrunBeA`0qfdVo3IkVUnbkYB#;V zLssW{ybuT`IzLw`lwnm-G>WnnB$Y zUvKv3Zk1@L5_YP%KdXtn%_=j<$>vpbx1h}Af~n=1^~0clC*Y?k5z&M4jrC(c0;QpM zaiKNRq!1P0Bl4Tgpr>~-S@J(a_RR^Ko&W&(?~aTt^mbfCTtus|VniypTU|fLV2mOr z)tl2*G^RnJLqh*%G#w2M7{F+htS!E*?FyJwNX;z6KnmhFDb|cj_;3MACzT zgZawlsQ%9!NUzt=qwe`6_H3Hk7F+u}Vlnec>fj_Zd~7y(v_6nzO@8v7sx2cZvx3|& zj8YObQJ;_?!qC?n+G?npzA4&_?V@fg#X~@pI3`2`Tc9w zN#}htTAwOK$`oF%8hCGL?bq5{dZcX1yt?n*q2qK;R z5Z5!%3MB2VAUYRdoe{(vkw7Uy5&LwAN;9sk^<9AbTw?rj7@6ShTp%s~K>iUuNDh&? z)oIzIM;XRij8Hlk9LTFoA)2U8Ce(Z z^_kRu+f6tW2*#=`b-_J!+(wi8xW*3(FH+M*B_n3m_n@iph0wWWhOO$RlG?GTS&BH% zSr7DqOOA<5#nuWW@`dYJQ^RB~TB>}GR%ks)wN%=r({H8V%d>*7)*usl09*q{`gf@{ z$5VBF*+GI+1D|zN&>*s7(lO%La6^UWc0xjeH1Dt;4}>Y%h-={P6B^ZI(YB;yRsjXJ(GI=Fo>bO!j@WiuZ=ptI4#^{?`ykgj`gR`Kf4I1@E15| zij>OznvUG%l$^@{9k?!#Z!kz;w)PQKgXuL)%u$c-q~^F^U-5bZ)k~&K>M`yG%@ps9 z^+dn=6*`O`TgKK(2(C*qeC}rUmOc|ks*Qe}8-EZf>snqxUVn@!-1c1E#_^!FbdG=F z#`{d?8?+lfMGyP>m)jj*VlS9NoHdoAVx^PcIVoVU#PJpmV(G`>Xr@a+F)>4;Sv3Ir z!nJRRatrb*Kxd~yTj@3$@%FS$DvQLGOW%(u{ z^1ILI4DM#yz7nN9wF~u80KioK+HwA9%d|#+GT}mug%1c40dq$tR4oIsbb+rRcY(6y zeI*fTQRpX0A>u1m=%-uBpw5kc65)(x(;t8Ov?C_>6)_Ve?t&q+{~5Z}8J11! z2K@S+i~{KrM-wDZfRBNv^Ur^#e)32Uv>s7WukunTI+Idk>4?|<%0|{6)@hrK8#Qh@ zkSfJ_kPl{V5LzCYL3<>gTDp!&{d5&U*UQ3+ZX&my*rfy(lDq)+Cpy#30XjRqHV0XL zem@+2dBlGH)FZP8=6O(|t#g~%674k>CmA6^d(o|fG?gR$yW2W&Ea;YEO>KCytLl-2 z95fus45F@ez9l5zS2+KLZ{Nx9b_-qfZzkT_M{xPP(~CP|stGU2w5FvS1c8OC%-pc4 zjNI%@Qk8h*^!A)5vKOd6d10T*5^2^?$k71lH;>Go0=Xg!cZ_+$$aA4e+c(#TEGYtD zx!zETel==ZsVt_7&e#x|v|5)J`|bChOGPY^lT|9OOSBvsT6uA7NQk36NaE7@_CioX zI(CWL$K_jG{NkvZ9fEo`QCTzg;XUhdL?BfrG>6C#m7lr~k7|M~2pIqLKC z{7}zX=KE5&SYSr(zjLI!h%?{5s_k5AaN9=p4Z!D?8mvE-O80eO7yORZh*ct<5k3rB znBk&;^Bdehc~LzQ^b|^loYppOV_~hd?QQwrP@IQ$d5bmb&~#SemA8$K-B(Kg<2Ljo#&=^PjM^!o zexc!h4?p6RH@qUs62Ez-V=`~I z5YD&Vghim41C>${=D-f~P6W#YtT}n4pQx9&Bgh2P-;cMC+V5)hQ^ZXQ2`xr| zcymI5RRRx>5M0ilP3XJpB&rk%D{w2>W~sOhO&3H=*X9Pb24;$yd&*+bb00J2Xv@)? z;3BlJS;jBip;@MU5RCH^$m$)cSl$(OT4ZtrziJR?vkyOve2(gpK{Y7Vnl3}i7Ffnn zcyrfYP5LxG&O;&3`jKT*x6FwdIa3nWqws`^2ZuQ{10s7V*q}5U`+=6xN&MNekBzxf zY~Z_sv9T)fgp!9ZP!oJHWlvjRJ(=0Tq}U0!a#3c8l41SBV8QoTE~-@K#~P!KK;Q#Mc=3>4H*0F)z(>Yw!*5d# z1AfLSj+!iab%=?$){*as6}9pV4+nu#MY+wCXH2n>}KhRUV zdi%t$ih902r8FNrG2*c!-T8}(ppt6{{-?dCCs|ei2_!Jj2<-ysHr4Oc68d-m>$VEl z#h?uRx>~;Lb47sDk}G##E$76^(6``nJUf32P6#@rtpc#^eq1Q(PUxY`iq>b$xMIZp zxPesi%!Lq|fJqe-g^v5zD-BD!Y&8VJH&d(tA>hk469Zq*r%Y$?t$@CH&Q^mnneWkA zLBDxs{<~LS(ommLxh3+Hu!w^YxwT@pTz`wP*1MP(bwj&IbA+DxrW;!&Tn3q6z>QJ z(0vxoQS43P@OGZ9ucnpi2ytxnF~Q#VROZ`77w@nT=Jg%jrC1q|v~g$lebX>&P60&r zXOvMoVhh)G&iI!7CtsBnOWa>lN)ieQtD$etE0kP2^J{bF0kROF??!o@bDdL)1lKdD z4oM<*|3SM7g*l6i)&$3S2M4_TglGH}$W7fM(VFfNC@&M%nTZ3q|mG~X|`|w=xpPXjNKJ_Je7cDQPTWxb;$&M z(zQ9K35P#nQ=AjMN_IP1$1tgaRNS9?j3aDoO&dYBQshPAHb^kPw79>QVQtHBgR{3* zisy#;o#EhyN!wg-`SuLxnCr=*y5gA0W701IWDL{ zo^?;2Gq&q?J>{f~im>`=Xh|0-Ml(w<^%o>;4fV&~zg*}`4nsc``YO}={BaN~wMP7s zg57OId`SjbOp$d+kfOl9X+4DDYE%ugkas%|;y{Ql@R;Jib^QPJ=zHJL*)K!bU!2H2 z-Sy-e@Q>Or);$ zq}H?3n~1$MIFQQ!BNM1hE)hpYgls3nRAIzGAxx&hd3gPz*L+jytyDyxG2>W656;v{u{ZOW8E2`YQ(Z0vwqLP zriL5(<;7}-6ZKCHXf#sb8ZE@a2|0w8?YTjZ6gy(uqFmjng1T4s996O&N_99B1=O0C zTQCAQ=%XF%Js}VviaaUaC=4A1TLG@)0S)`4oWN56`QKNiChe21$@OhLL)&Ca&fD0% zC8vKu93qCIBtdI6Bm9pud!YE~jP+#u3ErDI{?Z>6YbSbs zo>6Y>0CH>d#vBqSYC0!L4Ka*4MPCV=xJurMTQA%8nC+5tg>>t98-OX1sVZS;0VCEQ zNSH}jHq%Sbp4cv~S?ATjG(*KAY8&U;hiRh#{NWD$`t@tEB~$48FJwI@;yPXbkEySK ziu!xr-lbzHK?J2iK|mU$yAcpXN*Y`cB&3m+?vfUeR%wuKkZzFf2I+2i?|$|7p8uZX zK@MOo3BkKV{8Ht)&^IC&pooknVbW#(Fk_Gp zm#A+lofF{=J6m2M4AMm8p_7%wGC;3PJ6vzpG6ceME2VorN|BuAoNVi6K~0rdPiA8^ z>r3&-azpr27KJ#a9^ub^=ePQJIiPo@=w)xybc~WZY0)@Q-o-1s`mI*|{l^`R3UYG(CLIEGORk4W`<$V@{)R%)kNZc(14vAsm0A{4pOdhgs(0Ng zqmrVbax(Yz%UyAN?v;kFh<9KZju#$&r_&?hm%)QNFA)+F4hE|bKq0>_%Byl zc)+!blYVSs1ZL<}^UCp$la7E$ zFKdm5ofvS+Rhq$7LC_VWCWGY9!suF-TlP&Aw(KC6{U8oE=MDX@6*Ut zS82q8>;}yJYuSzeI9vYl;j7qg{1-)uB6P24IqukL6#XbkG2~PkALf(r2QXWqbgElu zZIEFXXfhXaFMI)N5Y7pWoE&W@-+pQupH@NKJwdC!c0tiUP96wkA@$DY)C5S9V4tkS zvR$s!xjaij%x#EO-{2RT*5k{4Rl1o!mh^P0_p{ggnn|BsqObjbo=xZRq8w|BZQnk3 zMI}RrG=5B(BT84A>~NUh*(FNfz1bHVasNo@k?+d4MeGLSWcszBW4cPBYnn1)|G^An zP+rT^)GTN7sYI~J8vQk7f1>8KekNWkU%ckh7U`Wj3ds=~h(&duv}Vu_6Yris)>@Bd z(6;xZ9G-h&V>4&nO8l?^1@K=|U}K;G$o6qz4R{bmgc~5x3gto^nXFua@*I~AbuN!m zsM%TLHYaCx?wgh%o!p;rrEP?G-H0EM_PXbbN3e$~m*O z{-d0Gy-WsKKTT>kE_4-1aEZUk&meH6{JPsSR!^0SEuAvWy}ppKd*Z*T;$K3<-!h}} zHkkTt3Z}@UbOrPrr1V-uijSM{iOvGu#0Wi1AkJkZUmJ)Y{|uaC#UnSOj_p|;Me)Q& z{+;uD0xz#`4G&TBZ(j0l&18@;4gvd#*qAo61l+cuz(BGZE3q7xaR6`Y@XQ{&GhZE# zfz0*r*eZ^b>E}$ZVA|$W5ely@UFRHnF2LJp>~31l+sJE8s54k%xe8w#DQYPLt7lJF%YmzU-VT+k<_qWq4>oBjHgAd&T&WC$ZgY%NF& zY)*pKn#SwCN@ud5|9%j8#CY8aVJjmMWdTR#SoShIU4og;)DhPkj89I;{<9&Btk{kp zh5i8^AP}EU|2)uk1LOa=>CFmbgfBa~boH*-EA09+VriH2vvsbfP>ZRExAyZgoCSNF z34;K4_C#wo*!(kYt~Bb%kiz7tTIQvLJv5>kGjUc8pK9xZs@<{L1dLKHf(a5-HUWVQ3C1-E`% zX<%c#GBwRwmfUyJy~FcJY`kyZmI>tiIbrn=r=~#;6zpXe7_cVU-XA0d=uOgO5rA77 znvgfvr2{F`gLR8~R0rNy9ijl78C&vo#cvG zuW*u&)?1r6yxjmOT=TFA=Yd)Gf3hYT!T?+Z4lvM>JkM%!JaD<)m+oJAz7K>=di~KN( z+;>fu1qYlR(6f*uSmJtyEeh+Er1i1vT*ZnX-FoQzl*V=1W9zgv!MK^@uxWbm!nl z_3@c=Q+adQy1AjqO;T1xl_z74)!&Zf=WEHwYiIk9)2v2v359HJAaz?evriYCrEPHc zXDic3kUu%4+}X_D*Yn4ibD*`iu6#vhJ5tT>WNAZJ2MtG4z!|A+z>O}dG}_CY#=A|z zeiA{gDPmk4HArgWkw6`v$f-<;3Q&^6=}BbXAj=x!%Yvp)V3N=x3kriuY38+xzmBzjYn)wL}R6I zdxHCCx||BtD2(S`AZYc7G*fB}`%Wbn;fPHqZ z#^(kMhVuQa)lR655;o^a&K@Maq{I6P6U~e94~2#elCE`QD1M!4BVU95zVJ>u`+YUMT1ucQ1H5DwIF!M7w3+DWa=w_en?3qJL$O%Vnsx;d5wm+WYg-0@)~K!P~&e#NpU?Xg_5Y&!hGeN>R(y zH^^vsR{YX9`*~^C!#wf%Wt1!1?&?)7SFQ|W0z0WV_p6N9AGoH4Ii2xBaXm*>=xK!6Lv{*4UWGy8!-+aM;IZggln9Py0)>V&c&?8tSE*|^<( zrp6DzWlOVaT#Z{tc9z^A6GG$a+g1=Lc{N=pX_D4k7)Cz(aJ`g!W1O$$-+K-Hd#}aE zC^_N*2?8OyCXClGS`ifVd>jHL-gJEab}EGtF4NvyU&3Ee zEfSR|LMbY2A4%#M!gsbh_*Bxw#zK}i9`7Q{y*Tz@%QVt{@MV9M`G?x zR=J!+r&+5_)0E-WDK$e`FC}M)Vcbmw!4S=NOp$wE?BtM1KDA`QeA1s?hY~I4LjDt) zI79UF#7*nG|hxf;>=)${Nn72BY5N zgQ4f^_FwhJYpuPSV}6o&5kX+6xNe@bPupCcVgc*&Kp4+3r3&M!%y1}3)H$2-i|@s*{-3HBB8YkR0ty=Xl6@g?kUHxQgDdI)Qv{O1 zMe)hu^--r62|OEQE!|$~MASGb5_G{CPXH@mf)9JUNdG`;!132p;B}Us$$@?e-$0mf zT1}?ihf~~S`%7VF$%_gs5yW$a$evPEBWmi*Y_`B#;WyR%m#8a&M9|5;Uq+h`2xo0e zyeHF!rPM-}&HTctRTGlThXIET`;^Xf9U2;%k8;iQJ~Gvb%dL9M>W;%629~knB8`cl znnkh9S=i58vN>6R+5R5Fv1{@A9EDUOcF&8$cnw=5C6~z($E#NvBdVUgoftBi^!(01 zawUZl2uC6>CgSBx8uyK7s_%mnOI=E6rfn*oBx|O!0l8Uo-#UP#0d9f$`_b((WGdYU zxT|SCzVhA$W!d3voGdP63^iFqhsNJ`{qQ&a^y%+y@7hjtQ?%*ROt(3AE_2b}U>+7J zP`9#UF*iLR`uz?Ct9T<}kPj`<&XLTmLV1D;O6y3qh00AzY&rY~g|m^6!0Y*a(o#mW z3Gv+HnEK3~E8=7)YtpQM{5JVfk_;LXzIa!zpfUjH!kX4|yvV`v=v=USS68Uk{p|bm z((z1goC^yE*#rJo zNKf(sfe+WSMf}I%GlcxUvJs@(68n2tD8X~<6&2bsAVHyN;r+P-%cM=uRg$3rjS=4k>I2liMDyA5cB`iNi=M!n+C^47B3)YFvN((T=+SVREVeB zgeKPW+J{pht$A51mTOlcMAM|jALN>=H^ztQY9ny#o)5lX#VXXk|9>T8VZ1P3miD$mI0o zK^|EskjskGIr65h3=i^stTTM%)dPMZ>OIN)2qV(%hj&S{&qBUGhiFc|$Q=FOSq72? z#90=RokK7Cj*w3TA#^k860-U(O+X%R)NiJ+oB+_2&rutp9B%K&&k}F_yK>H4fy3WC zpg2pKwD~;PDZ|_xy$YD8rPnORI89~HUqC~1DDo-{wAcU+`u+ZWiq$UyEpOuJubrI@ zUb6?ZO8l##rvDA09xJvdHRwPToypqC{jS>>P*V*Yksy7**I9$y_c(3t1mw@)gI|(l z9j<`J-jwUzMdkx)El~Z(`kWjAI1}Qs7Hp^>jeW4zLjo5}FD`q0f-bbZ?E_FZdY$x8 z-fzZi33&AXoQm&X=W@l)?u~|12}BXBT!N1v66=w-2R4cNo2WEtNmwFRk^(~Zz8+M( zDtXW55gV+WH>#~%mdksTY%J1KU-g4s~j15v>wr{UOKvPHLEp;_JC}n0q*(jhl;fGAU+fhK~ z?&DqSeYFM7O0Oz<^)vfG;SUt2W)PJPs?zhH=6>|}&L2UAKCu-Y*FpeZ2_|?~rk_1yxKbkTT35y*7bi|ZddEt~N6g>Jd?uxG6as!n z)^WQANViDYi1La?e)|-cUpN{A)i&ZiIqv=*V?Ibw8G4=8Ga$kG;OxGEF)T87B?KuI zSqYT7mJgZN}3Grdg8#xzCc&M6=%e8OgsVu7nh@Cw+niUyyJakjaG_7f~e z%olG~FiS2V0GB2tKsh=-8nF1`@8EcBijA;>qkB<4hP&@nRt|Yk!qT|7BQ=u;E&f45 z5P}eH#Jh9dDbmq;gT!5;Fk^BHvEd|?;0h)V{Twzg_~{GC>Yx^ySo%xe=D-o4W`F^0UIxahxyTZ%@uBa1sN0#fGRXsDHt@}(FU=acZ5qdDh=XfE$ zK8`n1_7+9?M`Aq(DD2|p41I(EQJtMM#r>EF9CBmG%I0vct!xgtOBv{fqdJTXd?PNi z!L*cbRPt>vlVd)3ZaFMnV!Lg-wj6%s2|Pj6d-i>pOriY9;?wJ_xdkDm798u~f6nFN zzhoe=6UwnS<|-isG_{NgXRQC(0WOVQyktQEyaJe}2iuyI4S7^Ml!c58~7YE(()JU(PRnbF>rOx09Nsl70DGUmsVr>Hl1cyN`Coy=RN3B z*0TdM;s43pLoVg)5l7!=vGYpyJ*YgVeOV?X-!BEltlhc@N0MS{a4c-xguS8$*~Lrg zT=Hp^a8ojsRV9ZM5hw8T@93g{{y}SBp&}iYG_cz+)=XC%G;=KSz3-z*@c~NIG?S&P zyH1o!hgsB9Yp7q#hOvtYLyT#w|JRE3H(jvxdZLj12B!)X06aLT{4YcXR&8^EP92O= zAD)5Y$}OU6>M_QqlJZN6N2eF$|Jw*y*3(F z^M|Jw-fsd5V> zcq4>OXZnRSA`048mXCQzxvP{(7Bn@DT@ob)9QIk5cmZ6GHF z?iD&Hi-Jy@DG z*TY934UKwVeX)jp_+6PYCWLmPc<1;}#`^bvB>eyX2){mDlOsCaaBQPwnKT zEVtRXh1yv)D?d;aEaWsWO5byuBhk}+N|Z{>-|m*DR@^Pn5c5kG^gyi$&D=p`LH@{x z&oyV_{|v;Q2mH5hzN?)JnGGxJ$I55Zf|?xAU^7Fa5#{hQmxbEY>kk0FM+-T&Cfjm- zNrWBPrxj*TkKfJy0a8}*GP(Ur(%44kfELc=gFhhon%o*u->{q86VKIJbMjeA2uQ+5w6RYD!!+x;+Eg1uIZ|+4b!c z!zTZ5pwCU1m-7Iw!uD&sw@~Wo5m*UA?^1$2##nhz_uncqvEu7pUoyiP?}xN$#D)0v zkT2b3Em~s=#uTUDX|64AoI!~|>}Ox7;Og@f0-1MLj_vnz3l$=Ao?p{-;41e{fd^Y> zE(qUF{m($s1DExaCSS%fp87Q<5?r(m+1_sVhaeer$)@ku#+skV1kQ-~xCx@=e-ks6 zaDs%|Klt3Uy6y*j5TX@KI9OQJR%?U#X06W(!ge3T-Db9lv)=cD;8dyG7mG}mTZ}g% zF$CboK&wG&;g+p-zSZ4NF5>V@icTMGp-L;BbdG=k(fCei$Rj)A4mr9THCLP?<@XOX ziAfZqBsr|WgVEWc0TtwbiEg6EUmAoA^hbWz#jWG85BC#YQnTI-mjAwANlQ!1B(aW3 z$4DGv(bKlH)t%jP)^}h`rGy%ZP5xeA)ovW}4R}veTCTfv`Rv1QKv10x)Me5u!e|pE z0QdX2E-u{x$hcxKx>aBespGZ}N5vnxPVUJbZu1j2BxywN(?WFLei;w}NaFIvwliT9 zHsnjMlxDPir-nCK0(TL-VwA-FVXNm)J;^n1-P1#imBbaBv;iZu6R`K9Hf`II_2-^8C*C7{gOvs&IBN%u%S;(-to*8tj3Ay5 zSKr`40O*svMCdq@D}*kia+A+w3@6T9pf>%`weVsK)<6l<&45f6SC@CQLL)d z>^}r83I6thuP!-%hd9lCGRxB2Rn^64+iEvQ(8rvu$t;|$!>nf@d;_EPpjb#N;T)o8 zQk6X21e6nc+C2fCq=9v1+?17<_p$s4X(nW3zYy~GxUrQbJ@w=Nd!Qa_p6tz&je;Xa8x+&6gaec%>@~I;hm|y^Kf|Y8)ZACIa2cpg`kQyHP+B!Zh}!BC!Uql^=^DC~gMr?d@?$ zf{&UYLc~iah}PlsSAnwrL#cWUk_R*!S53W;BL&e)9{adz&9k=WDM&f-RjRvAV%P8u zLBvz~&>f+}5iVIg>3w;F(jicnh*Nz?XzrIIn$iL2jDH7yQ ziPQ9+#>+ZRE6)}kYsVw;`M>5-+D(> zt$!1zctE1^vEzL&pme6OGYl0$FGCk!*EB;>_j0a}I4@BBZey74wG4&z{0X&v94}xA z<}8?IYo0${-gwi0Kn_X6It(0KL{pi1FC6XP%=j(I9bfbw!f%Wey52gHH!n-9Ycjwg zfkQ;S?-xyX?yuj~C=Uj%lbGc(e!p#w67}jM*($VMBKXqvjwRn2HAj0+QZcswdoGL#hW|*0g3< zkK!}HJOT+5CD2M(VOw&}j`YC4{~p>n|AMZ`;(&sb$B5K9-uUVB7ZuuPNM->_PF}WP z;?VuX{G9a>u?Ccd7+4_0Xv5>rnf?lSe>P6PJteZ0-G^&L&l6qk)EdPeOeXu?zP|DU zUl-(N0+W(`;|EolBA$0W1P2oKR(z^>k!%C6#&l0=vbP4R?UgqI|1$&8zcG#P2hWs# z{^ywps4%yE+@LHo>UO2!xut{}`gH_&GCadNQh2h?9M3BKn`B3%n4^@psBGG->*1Us z5t);64pW(54u)_K-qj!Mw0aar^xpKoIYhn(@?s8s4B+lanca;_G_Pf=ht9iM3~1~N z3!~(-ohw}Kp708D+9#kIo)>j>bqN4qx`{l%P%|~WQb31?NB)E;8WqX3b@@Hz2lwiP zyA1Zr!n50Uc$tg!h8vzbOT31_p7JrA{*yD;0;O_DKZKLh-Nqm^?EYB!8)vBvGFNsT zL2mAHCcvk5v6$|TW3`#(Ps&TkXyMPnR&7&Hw3%KJzE^IztQ(qoeRd~o+<z*zy?BJx5CRHxBjcl2bfrS+wYEH%~_u`--waijroC0-ISQv@$0ONoH(% z;?p=lTA9_q!&XKvyzaD8P;O_AB~Wq~Bx+?()T3R{GW^M|M|C~^<6hj*Rrc3ss53)2 z3%n%ZPQ}Y|D==Ri*Vc70fQlSHhqUeCJ6GUb@aun4jtHcG9@1v5?xn2$D2x??!3}?+ z!MLg~YgZJ|VOJHHkIqAz<^C?m zg78D@=ZE1sg&rNhP>AzGKb$Xqd!ZDk%%-4}wJ14EZXK6u&?INCQ}&Y2|8;Gj#yw4d zpkUKYzdgyDmU!h^Y1}JKTV3NT--PMgvFz^FXbbkfFQ0YOO3h811}zz$;Z=W5WXAh$ zp3ye=XO-FKY$J0vz4Seb2>6TQA%EkTYP;H?QYeyaE~kPPdoTeIp4CQ}Q$ za&h49K7}wttI>*)XSVXpBmTS|e?5v{*uDF|!FiVXsvC25ew-?8d?P;N0)lz;PmQ5v zGERYP&I9uUwuR)F@-YXHf*h;FM7d)=)q~o;1``A5WDYSQsiF{RwUi4Xx!Nk%EZ>5; z{gBS>^&q>-whwi+kvW6{(lYeL4i-4*ceK@PAdPrp$rFKc^AI_lO>)cZH1IoSKJ{=m zTX>Yt)J5XJBISG~L_J@Ved?Ry&D>WvHq55p1|5)X;G{@NmgbF_33A8?H`L4KTpgeP zMqcp$q^1IBwarFe)D9WwHMtR&}+;-*>* zbnOsV4w&+LsHgVR`;F_(){)m%Eb-H9!oqWqL1|O@ru5@xGOz0ilHhmzwvtm;B7Fp= ziIYWynz%GeUSxE-qCwfW5|C40T$*9!QS+lI;L_ZY)_waqzG0||s$+nOB%5@pJ6&-; zL=c2w!|oMW z?0o9uKWFUKrn9?KdHMS{)26c;Aj#+6qmwoI_77MA!UB%ATNM&f6iO7Qk(ci8<-b_p z9Qb<7tf=KHu?I_46Zy@zFjLx98IoG={o8cUVgV#e&uf+Vn-80}c6Zk9Vs?mN0HgZ1 zhFN1)^Qs?qX>G2{05Ji#aCKwIx#6kWQ2$b;bb)RvFfqv{F>F5fisin?HY|Cu3i-Qb zfZcT8)$Ck#lAT;@xt5d3pFSF7qaLk(=6K_z@K1u>WZ{{U2XY}1$k8&q&+|T4$R;lK zR2v=Co{TkFW8(8^Vt#QaYBz;w67wp=tw2}K7`Gg6jaQF7r(ev*&pxqUpGb9>NBcJP zNHPkyr~^`f^!Q@=&qV27Mg<>e>h1b=5cYtXbHQcD@g9Hor=vN8Idz#2x5a~6r*GRv z*Td9@!>qX<+;Ecz%bvYjoV^p)eG4O#PY=mwdVBZ}cyTC)7N-=|ZgXLh`Eyj_qUD-=jxa*)g5KyWl? zPEzYh*%mto{?_HCOoV@%_Z7v5v?)hBy8@o|$PzS*7dEGX{GC}b)14yu`8dcZyOLT( zF8*|zWmjz%#(P}f4r+;8RAv}2Cn#H0J{ad`g~-;YYle1c%W>Gydy-vTJg2zta*ab% z7w$W4J&B&ufaj%hImZ7tmE_#&e;2JY};0diTaX6fuLpkys~@^xq6R zaET5eknpN0Ckf?X)k=-HJIz<2`KU%7- zN{{YR@De(mMe%CsSXQEq>g|mCPK7bD)AQ)+*$yGN@2T_+n}N;<6Aa`OarwY4DZu? z;i$GgCcrV&U>1+H*SQ(MbVt9Sw=Q%MSU_#8Yhn+WNE)qJo|(YJFsP>ZLfW{V%PsnU zadxnpIO*)Pf;SiqZmWeMwDB!wl22XlbS$b|BlV7j*Xil9S;6DY^w-~w(K!X~ zO_d?I`i#E}hg(8I!i3cR4%!P)IUD8#IKq6G?rM>g3aUSO6 z5B!ofNae_z<8g;En2t_^%*%f`WYGk4c3AzA8nUHBYob}nsQiuZe!9UlZ|}D89{cUI z`&~`@$eq##S-Oig1F`Mntbz{TZkylS)*nrt&NmQ!u%{+titAm}Q02teEZ_Yx9(KZ- z4s1`B=P!-Pp`7zDY>VswFh7!Txv-(fXjf^2Vsuxs*AC^gw*ZpRV1FMqpIz(pM16^! zB9#?E0v({T(f+T)i|Q~95EyhLupX^I@?QQ|YIV(RyYC-d4Ujvux%iYfSU3DkwvNa& zD?hstns4T7seX?W|Bn9Ym+JV*@&~`L-NpqkgOBtEDjGvCHXh3g8QA5=f5fBJD1TP@ zLxkYJjaB%&u`X)gxWP!KJVb5m`}h`~=AYZHUQiyTnUtDXRru4V0Dgc;tzYCx?2j1P zFwDxNQJ5d;{0ac7GFH&lH!YEi-^Ib{nRTJnhJ~D;f~0cHyOyC`SbKO~2|E(cDsZa5 z8pm`kunS$EV%_`@9w_H?mb`G26UYT$F;1YPuo1ND7&`bATR-M;t7tK%=WrW9Qj1s3 z%ioqHr*AbbDB8M6@Z~?;P`dGNSt9`CT)VEt(Y~Yh$(;M4FM%Ma>5_Y|XH#z}pIfv9 zF{{>k1u-nnCr(xX|9zRRmEw#A29EW!D;O2`Kz>UAmy_S4N5Oa4>8_|+qK>s*)lbvl zG`l|U+;*VPd*=(mTpvAsb7%jX)U#2uyWm~rh(rT`L@o`q2FFFdd(Og!jfl=uP)*hZLrt-nq_>t~W03 zD>u}Xex+WIT8&G=39x%pAaQkH&{lGefbVMsz1)+cwEX$o(^?+OkBd8xlrPVBgN%82 zVwPrie%d$Zkkj8>xF=T%4O&?T1;NR1P8W%-DR6g#ruRGsnAWz0)!k38TO(=?ubo`a zi>Pdsi+?*|@!y!BX>@l4&i=WbD@GiLQ`jl(%m1jS54QC#1ihX>8WNQXc$^*FTUN+V zanmRmyW2ZJPlkZ%2q{Xr^p<|_{vtRuYZ*HILhW846K7XQ-q-)Gp7#c^ccoqAwZ_gO z6-AgLBX!NuM1js(q^$j{PuoE>~Zvc-hwN_3K~VL3!_339d@su5N#<0jpp^-&OpOlF7G=MwE`(bXz8;*4~J&ypsbFQ%C0&-<4Poo|AU zl5IQ$ZCX)R)$=Y`FLaK-IbJpS@AJtJ83oWx6mn0Wxxec;4{w|(F1W35eV%()>@eQt zM7K%cvPC94sZmCURNOTk-B{<@G4x=jHoM~c+)M)c&DX+n`Fjz(;S}SYlL9;5*xff( zeGVF_o_{2NZr=F1hex^Am5;bQyM%bTAP1Ik3SZ_pd+Z@pUna$y&5_{oJCP=FLTTr( zGo#eg4HoLc28sDF-pwuVCH<7acQfB$)YJ0R)= z&eDLFKsV+}6Pa|%xq@}8ytDJS{+-n4irD{})98tz;V7R?9ZgQC-7X5r9nZl5Q+UH+ zU7k*~huKYayj5c5SNFI_OgfPfnGd*=@fy2BK-G}U%h4QfrYg5${f7{th3BMM*vzELayDr0?z3aZ#IICz+1wKBW+t|FL>ON3As(1K+?b9@IldVl5>e{@khFFZIe>%j-_LAxN zWKR@*hG;hxFdVe@QCL`;(e;DygKU&=yc8KU)rX{W!jtB@g#19^_5*0OKp|!NS+KCo z((geRNnEvuwedqXU|60IyrM_dQw~IrR;s5m;ff-c#Z2|5&G+!|4aic$<5Jd^&$(sv z-EU93}wAiDzAV$ zEyXJ)vL@MOM$rZby!8AqR-JaGy;&;aY2dnvI{K$ygwJTSzr@Yn_qilRN@*XJ>?=GO zjnmY-s+(}9dF+J+igkTgu{x{qo5oGrI}Nrki?%AwQ=8Ym?hGkQ!_h5=LxK=RD$ubT zCG{`#psME?_Gm&qXV9eO1exq9qNHgrJhDj|34h5znK8kV$WOx_DDfnxVUSCjM82Nh zN$zGjlW9MWLBRtHX5!iXHs5>l2vRes1>YAacf48$oEOX|YgK23*H(797FO(t#T&iC z4!NZ$@$8uzNW0TBwpYwkoi07eSH@FoHX7OSy!x3?M-{G{J*u=wM&O_z+@C*t+E7xK z(*8)h>vV4~apoj@b~L6!^U}=vYe|_KQ_fb;!yjZ`#42@0b&kIx@*X)gz8x(UNUh5% zg*yndoOi}f&7ozSkL>23GUm!%9#}fnU4aW^FGc1j=N(c#c2EyyW0EO)gwE~~qgZq7 z*y{|NdxS;L?A|J51gU#0?&%;*#^$fd+-m}QD(mcMR{_p}x+}ipP88rBA%xJgo-k3e!WB!e$uj|_8G9R3IZhBVd+{fCC?IWy2 z)_5gE|9Hijg$3y)ZJ`c55FkcdEvuZxX3<7QhijlGi--Q7TM!ZpQu5;mi%i(vqO~B zKLw%akI~aUz+F2njwnN&?SbO}bByZ&#~meoZMeaFFBQE(yawA#mk>B#6RCosTeWJE z0<;6XmoBPk;|%Xu(KN9{j59hK=FPZ()YPxDSQcC1OL{V6JW6=Ow3JkgKL`&vDQ z-ak%GE?B$#$XQ8!5}>sbw+4|k(9bz1V?gS3ZMBS}_^_BmUS+Pa=*`*D?W$K|v{~`C zdZY6Br zTIOpa67`eIZETg^bbL^K1}OPn^k23G3iJ^ApY5uT2xQWzZEQCLOEd;_FdumS?-O z%U}#;1g!+>FFT3#DE#xAiK}t-g>Na)d$Dp?)0h?>zSHa(O5Im0x z^$|(FD39QbXyr&XXxv);@efX7A%)%#q>HpiDYjS!RI{M1%pC3oE!k>tEWQ-Fl7#RfhxYEs4$n01 zl8Kxk*FLe4ruMv>WQyD7&;Bgpp-UYf{_BH@2`WM2!-c+uoAi1gx<#@@FTF1GWA$XS z+#Q?(x|;g2s`ahfCo)CWTw~l#v|ngt$Dcaja46decQ={pB0TlK`ZWhtd-C#GAw+MS z;r<+SAI}@gf22*E^0EF_G+Wgr2_w^3r;s?`%JDM#GC|e{Wx)W z)s#ttM8Ka-MP^iDmQEm>Xz`XdAA#-!|CTaMytYxEs94{=&DN|#ZJPJu<*|RFRR=DZ z8GG9kS6?uiuiUb~Ht1q%?pY?_f!{vn`7^Rs)dV*${VbO za)eN7e^k5PQ31@cX?Jja=d)D0NK7?Q|d$h z2xh%nr#%XNx815QXsDbM)#hG- zy-Or{#!HONB99&3>EM4jh>SKU2uaZDd1Nje_N4y)A5mc%CKIPW5wzWC+uRfk7X13t zCsi+H#bv<9C%}~Zo83cS7mXJcsWGy0rq#tSSTBnq4@ePr!@v4}JYoffa=M^K$V;pg zxl1E@!@VSP9uX|iS14^V!40N~CN)_gidfJF;>kHln#q{V);xCE0n})bJno0u>yJ6` zZ2cZLjDCCl`mBowDbO{W?4GnFPKFLTB&|j8^agXSx0@}R;Y`okIgrT&AJZ$@j%8R5 z8@QCxZ<}AE5C#Ov1NofA34Q%sAa>u2JV&}L$AY2rM=gy>O{@|DQPu1d4qSE4KjyCS z)lLbtWS1lIp3h_K1Nh5rPogD=(6%Kn9)q~_Zp7y4F{iAFUTD0k^}^>L*{yyX`M1F} zo<>_gc|BK^&vyF#t8}*^)*eSu*~$O0ZT}xTc%P+Ysass*e5t4KFM{l+6Lu|ezqZ!x z`rY`eX~57-2~SteoXeGxq~7hvP!)?kNmSd0fT(K0_`F=J1;h;uTh}5AhVNF&vfzrf>-t@l`OXSf)VFlXl@wlaR5rwb#l!dtH$`=?<)wC4j^xC3!r_^Cm=%5BEJ` zh_Y$a;%mlO3e*WLP+x|xG$MnUz!D~!t4=)iQKS7+v{BR&Ezv}w@84`NAl!NSUj`+b zdbuf8yTC;btDzHi*U@|G+fR4(xn(~@yMPDGW)}RRzEyB0u>Y2=R@k0o60eNuo;7O$ z&(s~JBK#gH$*Whd1b&>1T^)Y+O!bZj_Ae2{<%-)$3v_1(@He{kx04`s_t(l+J?fVL zt$Mr!#p>E;D*5H>h|T}U;Y5o8iqjZu_f_XKA?%cNgmf6Wxz`ctR4!tr3qX(o??umO zcf^`^KS)L2w+6$lz&VQl?e)gc*`a*M4PY8@_X8EdWaaG6DXaO(WnSMtKPQmYN08A; z2;2Jxs4~WeqiloLmfp2Mg&$4fh>tY+jH%LP@X1%G2#2pMlK-r1vA}=A$Ed--6l@nu z^851L{L$nhv>T?r>vG7?Mq!B0tbEy-fOVq^z+W0g^de}3SSc3i2!8v=*w&uyTq0g!2qwHh);2eFfGF-%|YW3O@M|WZ9 z-zKF~#si~$yyT4SNg*PQMhY2xMP-o3>jU^5Dk`0=0myL6*19T^;$z|NUb z^8yQX$h>8oe9-}X9pCvOZ9^O?$)VO4jE<2z=N%Ar9V3|farh2bK zI{o^~za?0*FO{*BhJaS+%CDfoRaO#LwQRDk60+nBkNuOdw;ucr4|lSND(ES(pL&~sihyPEpH z@uL4*OwxM--g3XUD1WFird2v#9oX-pO1q*qzfCX0Aw}MI(7fCv8ajJ;;-6~b7O7o! zaT42fmMecTK(Kp;339<4sjsLDBTt=GGUv|4HrT-M4RD`D>HQ{+Ex(o`LO0C7d8pbo z<~OXR>F<*oP^Z=(A8*!9nnWuZdsbUU4Bdu4F4wd_! zCT5Yv>PBeS+c{;z1!?sE$0j*UK-5x)=%eiyxC!4iOdLp2_0!tiLt7=sCliVQ|N@x17LFVHkVr6|G;>PQu& z-~9UNXl}{~6C}$nxFPdT<9jI4t}PaKaOgV3P2bSfJ-@0(7763Jf$OkXlTlL6BSW^3 z(FO3iZpAiWWu)hsI`y}+9|7$iB01G!^7-g&q%9YS{W+M)4ByrCKt&K^Eddn4|5yL0 zdsv{pbxORi3=!s4WfbaYox>{Yh}I$C*FmF$S0pzHq3N}9)t3S_HZB#I#Ft+7wjD^V zaUuFh`=dak^U&?^Ni-`;722iy%FEZa`tc81xrH_I3?D&?aw0lk<{<<|NarpDZJuFR zr^LJs_nNdJDhuyh+t@ITViMi^HiUJpxva!ZgCDX9Q}9fSF~ly>CrrNT^4|QIo7D(M znz#?>4I>o>8|6Pc9=sr+hR8M+m%Xu5;5-n)P5JvI8wO#I zGFmVF$?OO?ggC}UE#62s?&Hd@+pTh37DgAtOV4k^f;yXjD2;AuK&yVJ1*c(z=qpad zz<9@^m^iLSepvGlJZgDl^W3{O^tSe^d%3p7ouGXMbrdLBq#--M$yU91q%d6sb>V?U z*oODK(D%iQ@JcK|cR>~^Ofcsvl-z^-B>RB@dcFgNN&L^maK8XDfI#v3E$J%W*MvIn z1#2kp{gvp!#nPOsvPQ!uWG_n^XY?+MoIeT;(D!}EN%*D*TVk+&I)*X<)v7!|a%#P} zE;J!iusbt7ylDBT@Iv#(5+OBcPs{By!Fnf+=M%}+`Z;7IXi$Z? zSIz=fyW2SWd|IJk)qR6EAUMlu1(ZUM`fco{USRb6Sr4Wwz*=_-Py*t`m%v*gMN=ZW z?Pa4m@sCQlgol%b;=r`^BR_*CR)~)ET%pWLQPJ3x2zJW51c&kd8*KF@+U)PwWqtc} zUX5sF9Z@=|edzT!G7yR?^kPcnQ$p+A8tM82pTTN>KfcPawIZ2ZwwO^?flpOnDl2BD z{}h~SKNV;;J!PgoCP7Uhf~~z2d!28!ZZcApXFo+GE;=GrlDO0+&ca_7HB2{ReN4j?f@z z5JaU2&SFJ79kbZ;C{g2ahlxbiX37hn+#B!xXl)mVwp6;f1hsijm32E z9b%#h`h+Y0!Y{&PpJ2swYs+=i)oI#^i7BWBBg*WaF;26;mf6CFG`s}5y=pEYYHy+F zrV&GDVxYs8fi-&x7@R+$al?z7Q-5SR?^n=yoE0Rd#u!_u_+vDgofrKVUQ!}^*m4&j zgYyxDI7Aq40kq=2ja42YB->VD6P)fey*Kz!d4Xl?GkwwXfj1jB$QMyjS5A9#DJkT- z=+q9oWJn!A+Gq@qVTr%Pc&Hu3SURYxFkbsaNH!oeRe_Pi2a-=3`?r-xRs)_kfl#qT zxe$hhhB8a!IV8}hVJ$I#QbsL-r69fZ-4+bzf;{zl;w4~sE3>vl2|Xw6QUt?^>D3NN z1)11Yzc91d^@}9U)#EpDijjr&V`8`34}VHOIvMv}bR2Ameb~74rM65xZ%2H6OI>m$ zGGEgh+)Yy@_=M7QuCX()OqQj?#+@>y;EZ$LX95l%=d0Sgq`RQDt$tRnZF#S0P`UV7 ze2;~}Z5ax<^+O?|S@>1nbA8Y{(`jVCGHU%X<7m^fM(1aLbZ=@5!|)=8!Vc3T{lkL? zzTpUT!@=NxB1eIMzkK$a|2Z`Q$PC(o5k#d#Q)l^$KwI<*(Yj6WPzut5Y*H-Fw@7AW z24=O+U2WX2M^5Da{D$1LTWr&qODrVTev>$blh>O>#n@ix+Wh4XgO(j?$YD<*kDxlp zRE+UGOx`Oc{k0tr_jzfRGA0weGwGx;ZSX}(${LjFp)tOSBvsS@kG(g4gzA0&$IlR2 zM3c#qwINg@`%W=KDj~*Jma=Exw=j~7Jt|~3DjG>yvyWscd$uf%Da%Nh5M%eb_53_P z@7L=u`2O&HpC5*BPWQR)>$>j8wKuuRm2q>`a)Um$u}e!!hkRI!VsU?3y0g*_oO}!o z(Z4@_vHF(ywo;ucd`j?OHl6jWXPC>z&=ZF}7hZi``Z<{*?h#1;^xN!*wOw1aA&76> z=$~02X(Jda?+f-HU3m12sp+m|HID~DpwJhgd0cV+kIOBZJ@&3wQ8+v$&|Hj%w(4CPH0zF*W z%^){hp)e`)KEY#SPWFB(aaZF_HOdSGwVX`vOo@gccHnJU9By*y-b`G4_&}+%H9qtC z$b%%d3mF3MJFvC9f!^pIS@`*_>ZJY#3~18-N3*)SJ* zRU6f$y)}8jBGn;qFOBkBq_zl*c+oLo=zI2 zx&k`Sgdw(l`G`TBb5`CimSumhLF7=|tCS+w$Y#QgNs0 z?DC)Lq;%>dUo+cqWu3Hb#tAn)gdgSP{?jmW=JzJ!Ct>VEE^a9OxvY*%y~E>+&6x{~ z_+qFM^xt*uJy1>$a5bOy*NOvL8V)~CtuKSYBQXG4vzO(UDD6ca5RZ&aX>$IYXv?+& z?_Hymg!Q$F!)dWbC&C$<%l=Hxb^HXPautmpTvn=9u2c}mf7Vx8xVb0g7!^BdVi^y21eer z6I=&bw$I*JSV^A0-3@DX&o!<)zWHpQh|A~xv047!_^I&SyLT`Ctc?M4N2@u^q-Zb$ zMD3FjggC-Fh&3}iS6`x7hOQOO>_o}e%{A9*w(Z}=h59D|z5hBmTcgptb#zlp-~n&5 zaP!_ElF}ZxWwqYNba0!auo;#NKX5Ptp6YTSpYVpiw}Ow$?7X1?EyPr) zJt{#eLLN*SrAC5Uui%xW5ZraaP$5B{?`(U5GhWmW)u{z}ll!+ZpZ!Oo{vlwYO7#|( z{o4NQE*+KaHdr|b^CdAk{Rql=J}mv^6pYIwDdI(C?9`ZCW--Qc|NU9D6BqZ<;@_)O zL_4vJw_0Vt^+0XDr8`JHkHT#ewtDIvIh=AXz1F0YBJ#lSI__Z&-!l_IKs^Dhpgp%g ze}6v2-zzEZ48^M;{9bq@i&QLpk5QKf=Q4fsXsbr{v2s!@@TqKIgk}#;tmU*1pG=KR z*zYWo%=?J+mFX9iUiz*ou1x4Xh%D065Np|H|p9Rr#DJ8Ts9~ZFJ*DfBusb0yTPM0XjP2|3DiBqXNDp5Pd zcXh+e`9=D&;CJ}NdF;nMf5{k2-=3@L_2+$r03DLV{_%SKC906}9jK9C>7&c@5T|mv zpqs!S>1BOmc%2i=4F_%nnBx5;`qACS5b>Z@-p18;y#M!o;{Wq~49+03VLw1M+aJyg zmrz!u7!c_;LroFEw8a8Hr0&G+g>tx3tk`v*1I+ddf4sY%dy;k}wrA<{r2o<;=|7)! zdy4D@=!Jo~5L-wVvU0%e2HS2j=y@Iq%@Vi6SgAwku(Vt`l+wajl*vsLMuz!5BjWRf1! zx@zS+|D|>}bVo6D@euD-@Gzl{^5-UhX#+lNf4{pW){yv-{~q+*0C;v* zgS(vESxWjj2*<(>D(GqUbv zli9%VA^&}b__yrt?;bFkyt^fO>q?uqCet(fb&Yp70=v4iltqAXkhH6`yyC9%S+RCt z`iFzr59P>|mInvCSsI>}A99oSpeOP_{&}7ABp9+3Aat|<>-MTCu}1V{gdqEL+Yzw$ zN*_i;zmVOveoR!&eI3Wht1a3r^!DxlpZ}I2{uNewLUNJHXZ)15P;6cq1cg^}Sz5Tt zh=W8f)J&VFN!{*8p%}FXx3)7(QK#8k-x!XbdPB2Mtsbzd_->b~GBx*M&?K`;oMXwL zd!8Y?j|~cba;`N=w!dXbGWM(4x4~cWzTTRn@=kJpny6L?dip|cn<3>ZjI<`Ox;LB| za&IzLg5-0-#A+*2p6^$DkB_}W`iP=9Kga8=Zj;fsmoM-)rGFA%@ss6wqvrP0z-p&k zTH>09_I}-jnah8iI$R*Q@$>SB&@0w&_BE5uCRL= z`+diRAD;5Va`O+XT-~1^&NE(y=OluEU6#D7#s#0a^1DRn8meh+{r=w>KyCy9J`1L4vI!4>N;XV&u z@YxSN|IUJ1?C<^}@%rn@3GYd2$ZKAu{c`a3J79k7Uy|?tgUoe~BX&4RLDlDxc*J-7 z-TbB6{dOrIlxODTRU|8Bb8by#+e42wdy{4!&OQk_9#$6HZ!$sqaCOsoZKT6aqNk)Q zv3|U6=MaycceR51f{#b6dV=*71T|#E^?NiXP580wz1tPhwoE)C(YY>S2^i1z{XgEF zzl1su#W`vwE{QRSe$wm?8FE zk9TJ{rn@0)%+A)|tjAX=HTD)J-+cYM4##lO<6^LQ{Qdj3mxKfbEN6&xwC}n5I)4c=x zxR!AJ+s%od6&dNC3;nALi-a0V_DVMGU!A@B=#^nXcW3evH6{%-ec3p-s(w>CTZQAP z1xW<&XBM#gE4x6e=fG3|=PS#qoOYs42x` z7t5fD#^~#6N#O}E&LM*6<8GByHx8MuY;9Tj4CU1F?p!Q=IhGkB+ z1=`r>Y9DqnngSDg@+~YlMewAGg$?&~JIP%YT%gG7`RH3P$HY1t*Ne8f)qD9td! zh&xRR?hBd$$6NB>meBhvDXcme6gHBHJE)vVi>ZFatDtGrV>CO|in<<7`n4%Y#~D7e zE1VxR7b2myHPo8~Sr0K3=y4e0bU?SCbRRU#b5-(l%|7qL>krh8EsCCef!^S088p)&+s1k)J)&;GMj)b zh-o6-$*+cT&G;Jb^&uiJsI4@uOxYkXFe$4ywI7$1>deSbM&T z^!#Q%=oe}I@T`4IJF}?0#=ymQhhv_StRrE@A38MedIZ1O^%F64tEYb4vw&|pgWiBh ze78*#D|pv`uZqF@M=WcZWRz~4YCG~L@XK4c6zgikIg7B5=w6wy%Y%EVN!uN?to6YY zSz!a+X-nUR^)lvcA0l(61trD%pW=M%rWj4eea8#T^H%nsX}~GAzMq@%e=mH(*R^ev zZZD7802>yzma^QS19->Jj|rjW+da02!=G;_!pIDS4cgJEW?ELjQ2gWd*MF&@8q1*m zFI~Xb0nf1z+If26AfK9~@CffgN^Dc#S*fc=+|bE89n$ZOV%dno39y@6G`2|9>A8oT zFjTG+3&w(h>?Ju9_Tzn^V(rBKJ{x4c`yZYIJ5Zx{DmL`DzcS?q&A6R}oj*@lfj!H^ z8|Fztmo(!({=ompd9Fy7Ws-r}GWWhXtYU5Srs6)86!ODtm|>T&&$zgn`~SUAwzc)e zPfM3oyhTbj?uptT_NjqC`<~aIhi{!d%U~Q_BAE2m&LDf-tLJKWwX~1hzjXTFum4Md z|6fo5zxJpX_E&QL`M44>G`eHts{~BAPWB7PQsItLZrE#P-iLpGJ@;Q~V1Nz403>xs z9yZS^z?$W7gcGwPjWw||^K+fO@K;+HS;_hQ?Hc|ME%C{PbGbMf(4q3dDUZdhzmHVv ze86(?e^g6(%2~eY3OUw`no;}e5s44_Z~gdJPZ~u2$6597;tMtYTYdktfK&ga{{C48 z;n;s2Gk+fm#~l2RL-^lko_+9N+T@>Qp7?N||DOl_&nN!y?f+8a|GUiprRKj(1it<+ zZ~l*j?|=9Ixd;_bT%LvYSMr$nj`<%2@b|OnAvaEZ$hmoTb_$oQRa|VJ*^0BTOn!x(Y!XO zD_yn&_8iu*4=V^!jsXDy_USJTKfmkrK%fncd>xD5U8C2Fvl};Tm4ZVpHEmLp)28iI&4K6Jd_bM~^CEWZC$kIKoNzC$tbZH+P4A9s8Gp z?JFqMDpK?ft0XqS!=ty@*W#FpXGnXTjNiTo;V0alX9I$@By(1743Bw_{CouB6yYfr^!njr6BBX`#V6IO@3&3mt9 z3iW;baWY2d3(v*HdOdx_XI(L=M9B0svIy)9$`+me@+wRv;m-Z1g(la)=!LRnl^kAl zpBQz=2hwC4X2#qFUkY|t zKPA+-+z}H*UNu@JiFGW(eqX-X;Dr})rb}DM%=lTK;~Mv@m>>;ZGZ;Jry^LwUfQ8vy zdre?tQ1?t0VnH|U8mfCi&%E94T%wg6sU_5Cp^O8msnP9|$kOrPz4tgU0%v3g;#*vk z$2umzoQ#&-juVY}nS#b^ioW4xvsn*Vki4g8ApVQ9xx_+1$vEM=Noq+3rZsI^Cs~EX z+G)cbr(|~+J2EtCHl21ag>aqeLdE#F>{kZU7;$_!jgUZR`m^5ZXXZ_qbtFNY!6OH^U7fj7!=1T;?}kHTX3kY| ztu8MJH($*GHiB7$J&$gOKHtxg(X~HlK$;^tdnT=@KKB_?sEPu{W8c!G5qc@ZPa`?hkIq%@YD(5M~N9moA0KZI*Taj z#?b||2Zxp5#+~D;If%S=O+2yTg=~0*1b^slEG;x@d9*YF*J(JYl}*uwbg3b1(;qGc z7JL2*YEWP884B8^Z*eA<^lU8;r&P$H`()h^#OCRhy-=IZ5YpBbcYJHT^U&)+#OvOY zh}+H!4G;@TGGzpfamW*M6m64QGTbwWYLjN4Mt!c~tGYMOLp%uy4vk`vrMECt*zY#c zm^aQ9=EM1-qe7#c9BoTTNI95VWirSB24JHq4F_L|`Yp(!o=4yLUK##lN6vifvCEaD zvDRyKZ$8t0GPi8~R=|2XFW_*m={$01yDT=Hyo8|O6uTAe}Y66(pa1j&0bcvClgVRgk2XJ|Y@Etf!x zX|Fdxd>h*zL+hb#%8bge?#@(fK4<*;s{zVyjU=Hz$k3V=300myGAP_Sbrdli6V&-T@bI5zDP2Z`XABU! zK1cmTTjLwH(`MN-X9CqM{dBnGTjLZdTE-=o^~dKQX>iN)p!+T%y&&uk%62%qOBH$; zFB##yH_g%&eiQ=3#>{>Nz8-{(Q@t&(Lbq7S>42~&`S}}5*uo3fDnU|vFkm1D#l2cV ztgF6EA*ZOa@zEy?YOb{fW?SA*8u?8IJ)ud`7GT4Z7z;U1el~PpS9dkHww4xO#-9ko z(>`@~?>nAnC+g?-rTwf|=OjvFR`ua#4@CU#K06xv@NU{HB*{qDgWfEYtcDzA+&Fo8 zE#mLoj*qP^S3F?1O6~2{m)1!xuA|k)v|oq(jwfZo=COA!sP-*-EmWq~3pcaH9?2I~ zvi-(PHiw2^IBj0spyXSR`HsF9#x^M=H~_q#ixZP;oj+pjjwp$a)`_fs2JtKKF9e-lnol%)^k?u<`oQ;!Q*a< zT_bB&B<^fa-usEWA3ec9I=AWZ-x`=KR_kz_OKhplXLJ6Gl8H+Lz85Wi4f}>nL0TB! zNSv5vAJ_D43<$oY1W>8*_}Ng(I6>BVNGRY(J6AW`fC;m8Oobl@q#fJdukRAXeQ|Z> zgYZo4;_;-b^|aKfz|bQxEDOcNkwSS>#5bQPAjxPHi`LRTt6P5VIkRe`MLk>56;&wA zo*2?3fEqTPxwW&tzJA!F`Q~|`CY6f0+Lk`3^!UrPf(7?OJlN&+VzsivEkb?MgiU4V zg?fre?`mEAZBHuc0!VWvn zniU^(A0z>e*_l;>sP7qMR3McVo}{Y5PH&Ka1{OqET&LX`CYEINmF5~8Opjun7x_S&A z7_nBEZ&y)%DAkxh@<(WC9cQ2EA{*Zb&k}Lpy zDsIJ%FraVixxSjyM0&;JwgJ;{=ZkJ$9WllTIeOkrFz2+gASeFT`vg!^zTm+eSz8s zS(I-WMA(Yjl_-8ElD+}WMfa7BxQHxOjuEE|(Z#sKJWgPLLF1WrBNd`GK3|01ksZ9! zyJqO9JJ4M9r`{)#2Y6zO$6l9Cn!ARs0qm2Yrf|2Wj(_Z23|_U47M!nwJai(HTf8mY zAJ^^*?LH?|0VQ{ClT0yX^5mhuAw<2JGeCMVV>j}oeMfkq&@)JNz2qr*>+j|kM{hdQ z&QhJ%)<{(MI5Xy4E4hF-#)CQZ?`1$A&6~wT7J2l2Q(${WowzCEE0|R?QO4)B4?t7q zXM|liv4Rj}kWER=Ei8W?ln&0^22n3L^kz7I_InV#T1F>1=YH*( zUoITZ3o8&0gLR1)J|c!LS3NaSJ?vQ0gs_g+>G!xHmS#^L^`7886=*BA-E#KZ+G|xb z#+}I{A9pMH6Y}PqTYGK3>)J>%P7m2HGQqvLQhn)|JTMZd>|J2vWeRes*p~ zB3u`oRE<_8kY2I4ZAKykkdBi|hEMl5!zcrUsujvI zPGqKeGh`sE$?+^DGn@Ov1sK5wNr z6Iran7b3S)7YY!BbiNq?zM z=dbIU0Hw#aLPK_>K60djdnNXJcES2)A@;=`yYhYIsz8>3YP zh$*HWjL2!)`fz^rAhy#IK>YjcxBnaBlBT61eOR88&JT5~JRS7|E z8#RHVJ_7e;GP)SdQtB_FvWp49DJ?nunoLEatmG!IAKS{)U+)R|6cTPX^-Q4*{xI8g z+IOANK6)P)ssgz78VqDVtxR2hhBNGT54&1bIn z2ML>;Sm!v&iF5Ma%Sv3`M$QWznAPc4PQP`F#8StF4>G!Y+|aN9!RCh=WdpLr;thYg zcuejny_(B`-4pL9)r&w6K5dRZJ9?uZFREmO>P93{u*I2Ux&}T{8tF$vpe`zb?(H$GCc{{XF%JLUtnL`Gpkug$Kz!!7^3jt=;twf@jx1}} z6nTV~fcJs~2|>|>>{i22iz1OOpL| zcqk&+qVB0nhz9LrYHt@qCB_SZHE zHp(435-QxI=+6+7AN^~tymXT8X{I-*30mz{9M!?>o$n}31bz1z`(IZC6XwpvOG+?a zV5<|MkNGtP;2<@&UA|1L_UOFjxASA>&Q@oU?yw82JoIjaL8##jGUr*xBnvtAaB^~fmDBCtAZ=xVO?o~KtK+=qepCl`YqnnfT+d2JQ^rS2dD~*uizq;{ zyNDyK16tE8PxynW5($&*tsqg1NyA|drU_cZ0-)?{wE9Any{d3Ue2Elxs%Pb#zK?${ z3xE&)m~SSiY)XAt9_|`z)~iHOZ0xeiUOH`;1}z@p#bu*_0^b(vs9YgY?c)@giQkc> z+OyUn0Ahd>dCxqX(nwDYRJJ23R@D;tgpeYIbJFMslevp##e@mWAQk8j-kAIH=B(`7 z*DQHs)w6%BIHfl*h~c-+IZx-;vO`dLjSlLP(E=-K>H*jQ$9UX)j?gFGya<<9K=q00 z_BZ22gHB@|B93%(OTBB~*0t#bX7lzLpIjw?;gzQYLshWy(d`L&D@I=@37cW9Y2HQK zd>BFL;)+^2h1X)sigdT~GZ2`1ZPayZ`Ib2{TecjgS&?=JDnS{{HdC(C;tS^(2%E(! zJrXRuFZIkQ<7&{_Dv4?nH^McywTP&J8yYWl^7Og2CVzdg=~!M-Oa$;H-+Q z$6h-D-?*Eel-j8UFKx=c^WFN8)!&nF*$0A%!ithND zk$-;@>j>pgVm`sZ(V8ZYS1`5@A}j37xnb%F;}-Yeo4Eqrid6-K1`H~J=>n)f{=kXN z38wCe^sHDtWHIzLe0lAeteo81Tq)K|63dk*-S_y_+f&5shPGbIJ}kH!@Vbt&BSBhms|Gf|!C*g(Cm!D(|LtDTRTeT0YDjebxLS6=H2Gr+l0@G{)e&hd7`-7wGL?82%`?*(bK%9T)CLIE( zRtLxj;m?kWXJfwIK$N8J9e8`zCoL2lQH!K4R$Ti#>pZ=Z_wq6Lg2cqc;XrL$>4eED zKs!rR$U2zB-wjX871d00yj0#`|mE$FI0KkeRuh)M= zLeiPuJqCl5Fdi{v8BzQ`hK9v$`zH(KF!UbgeTfuGn6#*)xzl@O;yQuekh{x6)I~1$ z3F(B!-RUc&z9Sc?zOIPEwd)y7OqMmKz5F?m&noxMXnUW$RnC1sY17$QXWwc8g8qOBlumx zY41?nUvg8OSzJA%u$gk_S6?2ZZ?aK;w_KETosx`gUQm0d;3@I&k-l zN7S}(>|}rgv_+VcBm`yR#13Xf*W9Tl>}sdjSwXcsJ~x^xEzpB@e{sQZY!ysFz=!j0Y)$}mZ~w5fCGTu}fExLQ5-lyDyA!H(?#UX!-o z+Zwl<^tKcz*O`8s4a^o6Q~(_Ws@ud5WeEyV#?R^VP-JbETlUwYc+Uyngq!g9HkSc^>-4u`(3V2W+uG8jkPU;ugzh;3`|Z`0{-9+P4X`W=vdp*8^Wd{ z)We(=IeHc2zCsEc4Gxpr{B3#=Xu3fS=LJ^6cK!G<_{NoFp@OJxxc*e;76L1+$>hX= z*)dD8leom{?^Zg*_YmJpiOeheBaI0$MFHGnWi5X~0Ces6yjmZj>2L}no`nZm0o}m( z2&ib7a15Rj(;kgnR(YH6>$p#xN=_jN2Uws{a>nKD*Mhlh7&&8TR6e4FD&iz_a_pw_ z-Zw@6cak$5&~Ejc$GqiEs3{}L_;5#t&s{c~PUm_WCANJcyhUvQ-I~@&|C<*);|t2R zM>Ix_nz` zoTvNEIy71aTn4f}X_ml;erwgd;x5e10L41Jg!fmb*`ZIU)vOE=Fo)wJG}s8sVufCkSg(ZXqRnsJ#@r;>$**+ z3Gq&jr4$CEK9{*=s%}*v7aonDJwO=;Ab|43`LNj9snKg<2WPzv3$AAYCy+_JB$bgk z^jKB^xq_Nf&+^UzYTqZDnCb22$B8h6|+;c#A zsdZ?yK#|hGL^gqT8Hksx;Q~(q$blMuW{#Z$viT^AVR#-0N)UR_W<-y-c~w@Nq!kD?^|0_h zCjcQr8~mY%-03bHQ(|3xT0Jz{Ll+?b)qvo3faqN+R+~HGQp(1?8mow0K0^WhZW@-4HC)q7~rU{QsG_zU(G z93S;@xVldBtGshwAh>T#IaPfpV)(FVmkIXHl7N&Sch+g7!-H;(EJ0*!nb?*V0xbgmHE3Vc8OlEEoaDSYeY^HJTv6I z(>COCLr$Tt>F@ri&kPF^`IeNeFPprF$-j2=+pUX3DkNvdkY04_yIL7Ks7iQ}gqbtz z(X1CpM&JbSN1(0fdIn!Cj;Z#nlt2n^;ff*m?rj?aK%Dgg zm=-Z4U>un=b%~bS`O*J=0pK7j?}Nf4cQ8BpJZ)5{_aN^>!fD<9Bd~E^z~=LuZA(c& z2izWOngVU@Gb+~fF*}S{ki2>--MU!y8m93uxvW@!sj2B*T#<8QkOt#q&WhTM^>)h<_hwc9(&>lp#hGLj&8F8D2rbG!LW16J8$zPT@z%d z={$M6^an$g8BGEAu&f60uOG$=`QQL+Md0Tr7!h4-L=nO$i1bmwegA zp1mUA#q#Uk(MORakg*z+Q-pKZ39E4D1q0-AApB?5oB`c_N&8e8fZ#xfuw2n($~9Mz z=~Nl?l*p4`;vo<7%TcVI;ppAL}X`T(M&CZav2; z3Dzd5Qqg=!C%KM`C+9{Or~V+T0>$!#(m_nDpz+YzsKFvLA^Jq_yNpfAfG#hG_BFE=39O?oix}V3l25B z8vu?ufM1!&{jYQ9-S=Z}YO)tD5Cvm#au-pSw~JNTRJ7N0z;dq-jk-T+n}Pd|$pvPI z9VY^BPhRdr*u8c|T50bkT+J;1>k4=Jw$mtXB(&SY>Fu>o`5(|drG!Zifb<8Ggg((D zy+UVscuN~A{Dyl^)wC#9nT(u%Cl31fnuF%v5EgLd8Y#>ILu1K`biD7q2theE@AO;` zVjB}D*Si1`#epEj1bS)`vVXv$Ilu};hiTvM3gy6)LNpxmeuDs+N{>1vb4(g+A|H*# zdEr!^<{y9%Nu(|J*mh~~Hw`k5#XIhBMIbVV^-%V(^&W+U91f);1|0Q3lW;__TpE}} z0+jYS0gKwPzKBtu%$&r_xDq5G3d}K*T1GcgPc3RKXR_vAbNUwXI{;j zwWjT8Fr7*V*h3sr>sYPdG#I2QQLclbWAqP4va$+mH|?PDo`F9S`32Fy8`t$0nQ*dJnLBQSYU~lgUEW>_l0>BKL7B{-fni;0T{BS6%xm z$eyI+8v0&MC;1nc@GIv!>f^l72C19}w5sSd9_)cBC;&Zz<0OXNbOz0ipLZcH@+loK zPzSKG3mk2t$O^@t)X}+v&I@5M$NjZ5CxBx=WcJu8&^TTh+jGA~4RJZJj+CKE$t4LQ zm6a$B3Mwj~l@>eR?O0MIqy|fvh?cvIvTV=if0YBQHl5@@t0CuHQ%)0tJZF#bdQE|3 zl1iXA0>nHzc3%D#XS(XTLEeS zKX<1|FJ6(-4H3CR%_ZQ9Af)3TPGvxGFZTeaIuAIgj(oNda%s}J1VTRf=&1?lJy0YL zyec5xZicAE<2IY#0ciGMp8@V5T0YDNXzU>Aem^|9$WqX)52@38xRZIZfGTl_Wa)FV z^UtaAkqQFdk|U6s?LnK)PY{X4@8EOLgqE@!fp!d;#HsX59DdUe(#(HkXooE16ZRN$ z;YtTr<=`72alsOy#AHx%JSmW{DfeeWcTa{gE&@|g1@ylOtTZa)1qtx2D{>j>yr4`B z=AL6^CqC=0uHV;pp0ULhB@6<25yyN#86%fjAVUqNJQBd%6-Y1NS)MEbq{O9qihDX~ ztJxsu*O+c#wiOpBvTLj5wjnXOA@jiD8mx$IJdzbrGq(z$3qt7t9K$Bk^2_OE#Tq@b zR22NrAxJ4r6lu&+X8qnNb5=}9Lq%myLit?M|EDfM}Wk z>YD(vqeHTtTZaS657zOoGlM;C7)(3YTIM#$PJ0>1+7r!&dwufQc;Jq`-DjlU^pq`@; zI5fl{_XCL@!lTDvzvn<4QE`8>V{!999fMg|ga@D>mbpvc8Nw#MmrKbOL@n=cj#IZ0 z#QZ$II)Ho-NmWrn_wc@4z_QnddJbnr+*hjab5sFiagl_S8fKPP*7bnL-s;W@80jz) znLw6F=3X(xcN}O0d0e{_PxIKlKeotc)-IrCu zn6L}<_5wl2ofndzT|oE4;@vCTg4S(X$WdlsIVCA1Sm|HiJns5x1Nc$-L%dvoAO)Pj zJ_GyFj)16aN%es1cV!h6-m61=)9A;2$C47eo=Hc=-Wp)NLm5}!m*ZbXtML%NR}oi( zMzNbZk2F1#YdMbD37tK*AdCcQ42nQU5*v_GV4$bpZ<5u%2<7ojmSGHc5(hwBuvoCs2C{3(%WAW)y;4{vjIkRqBx=NJMKCjbR7l5&?{m zZu0Ip^ID;!w2D5B7aZB7@B0W?+UFo%TrrwgDOzssrzg+wuA?QsLIyo`+L~fKs!%bM zO)qc+=v*FbL7pY|$*5mOAD^XBi1{3x3z?jplz%lh4d5T}Pc81B zstJAo$O0HQ0)7@jP$Spxp$pq2ayUdD0Dda~!2NbypzPPA_valcM4`jrO zEPYG>Z8Mk*I5;sOrxXrdF26(wqJ#EDm!oTqqz*_*c<>bI1S2SkDp*NK5Hg0DvRI=xwvv|jHuS&KWq{blnY(_Y5WIrl zUmkO-Y$P*>vJsu$W{d+Lu8qX((#w0TQ&e-P&#|e;H_i1HY0;qcT ztI1O=l<^+ez{2Hm!5<2iAXCycFXGx47kHr7>@iob7ZqzYLOSSH;j+8=U3UKW*kTi^$apTII-AlUzrVI7_noHvdNY~~X8}Tj9C7%FDCWkDoAh?}IuJkf_ z1BZ(_c*cFw(o@(uZ46Swtv->2#QN2OQ=aCL4oritSbsv4! zcSDPU$oa*U2W>{HlJGzy3_rT>P9sC^biI4@Wjui$B)axP03&?&5|id2-hz(^&zkh! zw1l@UDaxiziHshTY!%B^4PNUNOjIcq_Tj|yo#3)z>0YS|zi7dLqvHf=C`1qj(cD{% zE6{xm{3`II{yCrVD%^Y~Wy2CW8zMo@R0gwzfhxTSa&Y1k62uRkAO`QJ#FGp zR%Br+u6-UfFW5edAMEW(^zEJ$W`q}lf=vL4tG(u7p>XVNsCj4!5E%W)}Z@mqDhzt9apu{KudlYl|4dE#C4kx2u zKFOycNs@C8`SXi0O4qod(jRstbZ+X^BrQH(QQ_glLHGzekq2vvkNH!I&&`m-_fsn*ckYbIV6&P3=oZFe4^QC6}9)GBPI|4xw)WG2B8 z+D>~yJu7a>DM{*% zO>3Gq+SWIl!lpfb8bV@t^#>JV@Ru-InCxg}6AXp^E1W0;=h9lrq!yun9Q7b=wScJ0 zD{w#>4T8ypv$t&^tyvw+CHW*9Wm7UF5RJ)2G#7)UeLLvDs&s$kY&?b$X+C9?XJVSgjx8uA%oj2VDqfK%oVVvHQ{qa^}|c6g!Z4A>ota2Tx)!K%56C zIT`3ckjl_=JZT?>U7{mznd;F--9#Hx^Y|JJ5kxzPltkHB&1=qG-?;8$1)Kp6&x zgFpdFV$E((uEyP_?r`5-zjq+UbHW4|G@@8H{t5YPp-(wbU1gu+z2@M(+fbB`qNYea z53!&xYXfDjj+W#Y((rV>Y9xz(=XnbKuG-bN`pt!hKN=jbp@ik+ghb^&>bm@XX8KF+ z*E$Z8`MkAPq0Wf5JxJ8AjuzLDRG&e8#Ebfs>21hY+-uGg@wi`(-_N*E>2Yo}Eh5mO z+asaw&!zLNL{Fd+6s<5}y^b=Lg@h7D53#usq=#!W((5cXwnCA3ufeq^!?!=&j*V`oLzL_df{^P= zQ;hS3l%I6*jlp1jG1NFc*$-1+*5^202^{s6R5~6`&a_maPj8T=MYwqu>r>cbjBhaf z+1O&+uiJ)oG>JDq544T)nGEJ=8T*dVIyCG*fsBF^SS#S8m2b`bULTf?b77M* zO08ogau_Ta@79C50}>M%2Cp{3xMK#@6)B5%E6l?TcE*$*pAYD!Kq=3iYPvr)0b8#a za0(6hvtXcjpf=C6eSYhWFQG;vCUS8axFa|1rd1br09Q%Q_#wX8FLLtnHH2*}PoIrDAsG#30PO$auKR^2? zcD~vq#y?;wr*JISn@p#9lIUj3$t$0(~cge(m*NLVCQ(dU6zSbVXWqjB*Gjp74AW~3&?i#Tf=^p z@aFq?iyLl@zJSKOm$J{J2Idh&i@(3)I)2=AX?-#})bvc4ecLOki?Xt^7dlt+P%Ivw zd)x-{mwi6j1)q|QO4D59jF~~P1zX$K*iwx0enBl`Ft%x&{^zL>x)FfvrsT}Tr5C@| z!LijJrrG+U;1f&T5o>&f#UI>_EJ|6hMBLz)=>(QYKjywz*h=hzaA&PW<(icfwS5Jk ztD|h}{}Slx7Z(>_%jg^ilmIMx_SYM@2Gob?_ZL9k%XRegm=;a`tl&c%4A1&b(?p|W zcVxsmq5_aqZSV$mp0Df5`xLRqcA~k+IFWEHNEYx6i&#N8B81_pk$)u;P8V-@bnu2| zgx^frzKl}_HB>Ym=f+kfuud2ze4u+_o)E(e#{=Oy~Z)4+cK{ z$LU^f#|Gw;VeIPjlGoes(~loN)RCQUrvBxGhm8Fa8{8Z*oEg*c@lRNK4;!uCwrTT^ z74&7R4_n=?k*4wA_lMlp)zt+X@8G)tJh>ZVo31S{4*V%B9Sr&< zZ-)|w#4-J^SI5%KCwZ5k`Pqbk%#pghzu%?^2L5ytA~tO*wCiX3X3e`w#Y(>OCD?H@ z1y**_eKf)cF-}y9w(f*b%0EAhy&w7qsNCFKT=I%qv2>AAz-usXHXjwjm?bD0qDG50 z2Gz!^#lWBR$K3agw+p%)ZSK&bk;{N=@m$L6zT*N6#)}Ay;FpBMN}MjZUGL|7Ij=cO zq@OqjGsHN0OC_KuSkZp`X1aM5SwOX_*1a5QAFv}FTP{yfXzI=I+dwfMGu=#pkcjw| zxc&vMzm>kI_LD~Frqr(LdDH5~ z{=UJ+TT;v3v_!(MO0wBJa(Jf0@nuX{XwGC&{RGg__+NX}sn%GYGi$oH^%rH|RU`qc z9m{s^55ypL`Om6Eg9LT_wqGiVUzJ{wL)S$)Y;rvr0R&LxI_^(sN59xT9{vK90gxSg zlAXz#5aPNJJGS2u;?ewTv!}o0-(D>o2a$ni$9!ClqXf@SV}H!Db*!KdP%G_gN3N8= z8<>50Ia3N2PXWa$cCHLp@$ulPwr|AgNLY4>g>Mu2tpQv zh$P>o7y=Ldgf@&QJQ#cdtHL^fM)>@?o1E~W;KLuG1vI#@2tabsIXC%=eTBm-R9%Lbmuf;*o#ccjyK z1wUBeY`RzN94lBJ%F=7Y_BHXB9Fa@~Y9LqrXFx7S=f|W?oY{A`VAdOi>{#GZpYAAh ze2u3*AAlK3?scoe+ZGb3lz{(wV zubmyKz24C)s`;;)Qc8Jx!q9RPDCWS4ZVGFz+MKRsN9+O7_nmT1yJK^nZ6(M{WL;`( z^M!uFuOOPclIVC0ExK`zZK0vz!GaHajA=C~pDYF>XD+2m0h{Y_Db{ZEcXfH13ZY=8 z{lUVXIyO%63jL;(=~R zBKU2f^Be}ASIShoo*u{M#jjUVNh+;HbHexlm5ofvYertPT>`R?SH|iNT^Q;vk%E+u zrqWFiL|ZMBb7s7z=TCI4n#2JVV-mlumz1LkKLtkFVJF=;Ku2+JrUJI41FdyknR4Bc0s`y{D0I z);C34qc~#{^2m{}LTeEn1gU68T{(m(1P8A2B8xZnAV{#$Kt2u6-OZtB1>I)RXjcHSU+dP`Q) zNW<7BL`;ixb+0fFHy>orH~4a$M@P!@u(nblcbVX~uTJy45EM>Tmxj??#@MHjG;$)j zM&;0jAi5_N>7}M4NB#!$|0SVC;uAuL<=nI&Lx&pY3!%IMEMwcWk)b6}GGHi}+z>^aO z{l;)|{=y8&Z1SCElHfO3u@uIM6=KKcZw}xnGkP!2WAWRr@pfq%UQG6UI=z3Pc-O)& zF!Sd08hHsg$>#R#7enfR1xelI_8KQ{Y;%Zx z_&O;fGE#|lq6#{S7X%mHrh9fAL!emVu2)X?xE7C&frJ!e`%FHHlSm%>*UMMgGf}-`z`$W}WY{AkTN;1(@QVzDB@~qdFG_CAvJ8Nv zUbw%4<{t}RUCz8ml*+l`{s#mcQh#)aTFLL1x7y_1+=;O~2er!C>pAcJJ{CJI)xH+| zrh!>LkJLe(^}@*OgpqCNUOmB@$cfeD+~TX}1|b5NiR1(I>3s?Gj!C3{!>>I6V01*3 z!+*&qr}p2G`4is!6FzSc$Tnt0qD0yt9hh z7=D$F)CyxH^m_kh`=;)KAa&pgOFzUL3&=%|W1D&zA*0-Kp?d_vM3{o44_SYEpU zn=q7*7yCu12>2_R`v*i=73%t(l(^2Tr;=7QY;~It&1awkdppF2)jR{z4Sy(LItagb46R<9f=7t>WAkHN(R#b_#b`-7xKTH88I024f$Jrwb_t; zPG|!SoKg^FxxT*sB0k^-%<|*u)?x6WtK0k69C4h!G%AC|0vH_252=HL)t4oBAX78i zuBFHY46{yoM#)|^T79e)YkmZKMRD&dXkMFq))=3s`P&=AVT1a`OZ^#yaAuK|WA*Ny zTw3H3h-eIOy2kx)!dX(XP|@{tt#3thEk$My**>*yU%m@tS=NeABg)7G2<>(}pktsR z_OQ%*n?m~wQkELxy)*K7yN1KA@$h*X-CAYh`|5YVd;u>%ajq3}gkR%pbV}KG%D#y%KwW>Y04ZP6lOP7$=|i)H z@r?R*BxVvh^rS--SM!)&rT_d~&G_L}N2Ph-6l=x)J_D=;wSQhUhl3CEWT)K52l&C< zh!@rufS$lg^gBv)4?#N?#|}U1_#mYfI~V!uN^PYn%LFq72G@rVt8=S{Jyl}?i-e^( z3tabnAUiJOkyicJk$g$4G3o}HU+=K~1CSt1)%{`6u!v4?veBxAaH@*eE&Xc#?*ZvP z+`*l>j+O2JBS6Plr?zA{NR1Wz_XyB-nu~l`?K6aCZ=zN?_d#INpP;G!(AebPuBs6= zk(D^t-cw0B+MJq}qu$>&ab-Wlzvr zt_!c2uJ_Nvf@zdCX&(rV&a7;bqO0$v>6;>|VVvjy$|QKW2?VFsogF+>XZhZ`;fz}7 zbQXlvH;FiZ3habxxZXN*;WN%5cVE>(S=pzBOyn}MTWV(30fw-)u{R|gUC zOQo_x7XZJ7Fra#Hq7}NQcU`JN=UR)-;Y*7w!jLcDhd_M;$22pSq5QAy*d`1uo8U;> z8sT^6-&IkZpfbC~SMNVtB5jCcq00|-l!mI|9P7V*!Id?Ca`T;}fq(M~Mqt1py=Q_3BBP_n!Mee}NK|ouy-J*1>EX;xn+6lqPd|ab`1*Zh;RG*l!S)g-9ATb% z{QtfTCfNn8ulzpU$15?^=RxcSQi>Tcih=wtLA$O7fyFRcgZW^q|E?=yrMi7k-QI8E zT-|5C>qN2=vICzy2`LP58XA2Y2~pYyS+|=$$!kq>22eT6M$ z%rEXjW3@0`_C3J#5HD>o5jrw~A)=F^NE#a{U;s@?ln8$R6}-+8ChG}?2eVN%{w z6r(=+u#IKIHz@}{#$2NC{lUU`Hmal&QEO&3wfZUiVdOVLAG@q!K#JZNgCkmRtoP~Y*|5AQflw8J-=b_p#m6TSL zl#~>M8ERHB&D*_cC+_zVXV*^gYBT4<``!a_;zc$(098n6mjVKr_Ba+-#buN8q@(K` zFpN&N79{{y?R3$AIQ+ud0ho$t(A<5ddXs$P!gtq~*7@ST~uivuAb1TY}}vgwX%dIPSvO|)wgu1R-W!$8K+%`oHTE!3@>Q>*d(Ak z0h!$o>{3abnU@s{tL$uTZS$x*yu?9W6TDq0zfX=U&)0A4s(7;5|DYniO!PELhM%s%~Go#fAruReEYe%-|^-!|G+&W0o+?l-yf zg?4%-(hqKWIde*SQ^W%xus1D%DBK;9Jc{kY;-*Zm>eZ55MDR5r(OUqMTYIs+3iZef zNiX1P61oHkL^+t2V}Os5)0aJ=iR;kmEs-UuxM!S3H(c48f{ap8zGq>F4bMivC~Dsu zw-+5XBOC!?1mIW^WX*&yg^+Qgx>WBJ9{>~y#?0s7Ck66iaS0&JI%JKXKIwX2IQUVQ zK$$*@a)MIb2=c}WZf=v~Sp7J->xz&`VEsVfs>gZi`YPmbFMN#>4E+uJv6TNnDG*dF zst8&hCYp$+EJnAEYjpoZ{nV#VLPK#G?;G$&41+1f?k~N#R?Vr{c^UOPgsPA>{-f3! zSN=4$x#oH>5Sin~UXm~cwNfU8r|{|JoH8BYwCLl?;6>LW+;3@O{gPv{Rzc}Nz7t;V zW#iO^#{>es3LdbmkR+aO=YQ4IA^plHJi_Hkf&1Qwzt9*4V8{b9st$-|m{QV#3jH`; z`mG*MlO`SU`tX_*;tqxJ2CPVU8~uATm{vn^r*Z1ksc49G&^e6~(VFx36iu#!0R>b8 zVvFz5S_m$jbkpUu8@i6LBpQGJxOIv3%r-?Do{pqj_XO$)ERTfvU$+Bv27J z&0SygK8Bp$?=(t3aS<_@7InpVQCu`qpg+qd4s-{HHr=}jB$Hei?+UXf@?)E9eHZGU zj-ACuI?2i^v-L|b&dTZ0>94Z9jRwsza0gPloJ#rFVnp1h755=cKDaL-X$KYLJ%eTc ztu8L!wG!`(f?AMq!hzUe8$-C(Ui6lOH zbrld`Uh13pM?|S`=TxV89>MXHP*Xa13Wtk2$a`Db!a2g%4p0qdcrY(VH%B+cPbpYi zopdJ?E9Rsh-CQ(>LH6XL;$CMTzW*+S1iD4|YQfEV(s5l5;v)i5XOEKSs)xs`3_Hy- zQ3sfWT!uD!3kcyqZz9s_p|7%*E_T*&W51YU`kY;=!#&&L;?(P5IZqbM!Dy%^tr1Zc z-rGf>|Jmz&PGx}?#lFQ&h)9==;^ID+WcT?80do?X1Eq?a`jquSS*WqO=@&JS!$7%x zQN)j01EoyN?(nT~H5b<9#%}g!+1y@34|V|B`~Pxk~YO3*9`0@e+y1*Z%pr z2pmBAa#jovFOO~VXZl3tBu2DEj|#s9=Ox4bp|&aH$2pL|!G^vE4MTvDS9F&G{Ls3v zG4kaknkztV$-IKMntq+XWon>uCDv9BZ^4Ca5*$6!bgv-#7_>#+ta;>zt&+ht003qz z0?^J3QoN=v0U>Q1rLAZV5}Ds6iP8(Bw=qS`!3Droaw_^h#`H$K$#3=d?GGs5L2HQd zuJ^%d%ZiCNMCi1dl4+ZADoi)kLm74O5|<3tuLEfxxW!=b-*=)%22@5)QnIY9;$%Zj zB6%L+gN@hmyMIWpCb#>J`F?AlOyZQR`?x#=!f3;=Tz|*vpj0U30WAuUWDntMzMA^G zPV?x+gkMQH7Yj*~!_?Rk- z3xEw|w=Nhx(XZnC-G3n{+{sdAuRu?uyU7j_AdhVBJP(BiF$v~iSCR539R?1VBDvtp z@O6?X%CB1EZM&Mui(F&+-vKB`E`t&WMBC%}WGj#nK5n?!>5Dt7!=(`r7PGmN8jd{` zmJx~=6^$x&#~(j&!XK&MhAVlX@URTn3|Tz)^Au+Y^8)3c9EVmejXcJa@a_J44bs5<@cT zGgty&?1{rd-+TiinPOP;UAP8QHFc7n&-h}(n>*q7Jf>mIdpP{iiQlG;S@>WO8pTxE z$GSr5w8CI6ZbWTFN&N}y;vRZ3z>xIvf71~2{a_B74Ye#M$$T+W|Fs7b?)MB}7CrZE z+9bNontW-#dX&bW0I#}TNLUOs(5k7;%4p-yjn0_j7jEiov0b-X5Tf*BZol?3B87vB%chvrn0-L3D{qI zm3JPQ4rrrZX1;Ce;LOI4-Pix=u#uM* z)bhX~1aqG*xRT|aTry#c@4_nrXN;@5!yEGQn1m*O$v$RP9LMwKt-Ts}2*CVdh||kJ z7c$y<=!@Sz6`T#PUxb0@j;h8mZ=nvpeE;y9>t|bw81P=OfU*-I;$9J`@^LJk0qDYJ zi%hbYSM=E|lXB!}Kkh}R519Lm2&bg_v3e$2ZM^+U;C8bPfy}1`R@D@wSw>aJ$408_3D`C zmi*MlH*>z^D^Lw=+M?A-H~Cq8FM2-HJr?7Oj5!z744H0zw=b?h%r}`@xQdz3ZD}rg z{eP?Z?Vh|MmA*L_Pvw-H)>Bt4hgZx z#6Z#t4)5uc!W13aV_g#}UAW2JrAY$}PT_)D;P_Joxt)P^kml0+$^Tw^fW=cEFqVV{ z09Vb0oSh34T#ZLVjW2oYcAD#fKd$lTY*X@>B*8*4JIZgNKR;nlopDXLkDJ4!onMfvrUq+pM?eSA&M|@ z@2OK7^}CH{6+{dE}pr#%%YlzG-qzFv52p;JpofL~B=a zQzS4RUECvl%L!Zcrkm`}^NBF*ZtAMoxI$Oo0pHXEx10ijFd1g>?wa>-x7g?ZBPk5b z5H?;h^9IXa!<8BIU*+5)l2ayF>T?b8+r@+@aI`#(yr7CV(!s(r|bp>e8lT7`n+JK5YmVHK|DRxj>6tisQ9pSy#!{q96YJc_=+%bB+A^ zgjL1;sV}SP1LNgvUsuyvEY3Y2!n78F+;RLgMq1s$@v#HUb^xmI@m^77U|=W*P-oFi z*}f`|YymjsMb9W^)|e)|7hVT@*!|rgX4w!q1D+FArE8b*H77e)!VRJ~Q!Ux^$sKq; ziSTBd={ny*O|Z{o&HL4T)693FLRYh|3G_IVMqbWr><98*-BK?&BAVEIDu8=-W~4e@{0 zasGh8*QVPkCxt1;#Dcl%yZc(YBHyOlx0MI`@VBb@^ha5QrbYr#Tlci z@mm0I0X)_4=A#SSkG~I90q4l(!LOksx2dZ)gPUCBEcuBkd`Dvz=pMjJF)#3Zv!#l` z?>M%g&gTh6eQekF`&Ik`eL2 z8~`MbfPUJC$0Fk=t3^1sF5x%t<&uV;A$!iKf5#-wH;UfquR-Qa#RCr!(Q9+M=Kcx4 zaws>=o5nY1ZL6FT)EmJ{t$H z-~%2JjC=#^Md4yRVfk<%9^PCN@iB8O7GUM3y<17$@g$9?qkf>r#vpQMw3fMo*>9b? zVV0D`bZ%$p23~2zbd#Blemp=O@AH=I|CAc&0C$aNfps-q#L9C+ZSZF6rrB3k7*tR}b3AKwK9FqUQA9!kmi6q_@Y1sMnDR>({1Xn3G*(G>0tb14RDeT zrn%sIi#VbFhmmQ~v9Jq4sl-ctq5mH{?D6NWo&hsLz)v^}ENlFpmafI1yAL&N&#^Vh z-#s5GTuo%5R~g$>$&BV0o7KhV-q1a@z38`VUL+Xp3#Uh@nrXMD3GFV z^sCoUVd2(r2Ikl4FXO4lVz!Y>I2b@Tnfh0ud#czAFp!|1`1xMSe?O-e2s{)>9QkBv zgy(n7crRCRE_#{0qV_PIJZ(KIhL)9kX>1(s3v+!W6xE|(6t`dUsI0xaaMj$=()Q-& zW}ELrOyGKBRQ;bC?hn`^z*LvhYjWweM-we^dFdRAj?+u>VViScuJlJZtWlpw^V)1V zdoX8sb9k#WS#0XUs=f1kDa;23-tcLj^m$q8y;-Wrf7DBTFn#b5c>V=|0ZxrOAOTt} z5mK!WL|d^_Q@#~(IjFRLbpjZG2wyydVLBIhUBN!0B5okk6i~Z*+vm+aUEF?gQh(CJ z>PW~}kCGlu0k>e#Qqu3m`AwRe!Wgf0(*nX=$gi7;lX$Ph(lu4q3Uz!?jNPCfGQy9w zy=2~XIwLX>uo?}Vu2H{5iw+%rL7W-+j46@`qj*WIj;YMO_SeU|{~fa;*X*9%puRdv z&!m<|2VMfGpM!#IJ~S4VJq02Bc%`D2$@>f2k-n+pN3cyf&{zoJEyOUQ>w})35f&I} zAa_zp+AWiHJ0~%9ph}m;Vp}L9vlBH|H)B3IqOACo=-W2Rtg8Z00hZ+uWcHwiCXKA4 zaXSJ;au0fV2WQI>)^cm-_47|2XeFoHpk3h)+4%v}7IIm-FEj&HK{QH6vDEy5N6Ach%k}iJ0@p>c=q4YNU}+nk|<4@*bIO z`rxVQ!j5};E8_JW+!R#t1E-t`0!>uAc@e#=C9hVV$n>wX@s^e9^Ym-L z+ORDMIHJLDV(1~QwHY9Qyo?i5j!9ASB)ISVfaFL8pBA=M3S{Ne5{F~x1rGA z(6>ADXY&i2QFVJ3)Z!YfOsd~A=N5ZuyBJgKj@pMToW|9BLdn%(dP9ZZir$`oak<2R z839TTG`tp5HCF6cP0%Ldg`++toxrvVUc>jBvV8%lEflR~tDiLxy}x#f!Fqo%iS9wI z2jw1qJ00Bt-U5jl}-|@5*?uaP(8zs!&AY85&MsecMXP{ z=Z$8SzCxq8=e=-6N2WCzl$>`+BS2d)#RbmQ?8cR@)xzVnb^AKFBG8V)^$}5g?~&jc z;_kgwTnUTUodGj5DEU5;!$Djm8kPZ2Ld{iNeC99G7%Bp93iySx#)wE%(rJ{x*Mugu z%#rBSe2?oIrxc@MmF)Qw~+#)G_J1mcOerJ7jMjxi1#3wpcjzA6W)b!WMX@FDR0BPDM=~ z1N0!ItD&-u(EJ*3Fcl4hFBC&uKv?)+r8a*RLYQ77k-Q9$&fn{sTkVhw?z3_iKKM%Y zT&#Hl7Uim?XCn3aQog8lZx9UTB=d?cV0yaaDfsxDnd2n$Y^DsHZL_~sKea;u#P-$H zLJrVbhvo&Vg9R``z3CiOfT{q8B@_r42ECvgox*R+3SlNmr|r53bMyMMsVq$ul1-x5FoZL@Oq_HPo`?+O&PDJ|P4U?Cg-j&<>(pOr?>r&x3Q}hJD$tylds4@&54y%!VsDZ`XHV}nC@sy727~pDM3btJb z|2af=HDK*rTwGW_Qm#HCic~2bTRm&}!0#0*ixUL#|M?c)C6oUh>C5^{A;PTO@Z8}; z2>~(DrJ)${>iKEq`vTm3bn>qJBJQw33tL0sbq-S?sL@aAmb z*o)kJ+jkCUD-;ZMV&L@a%>%)7`i~bJQc3XS30bc=#ls3&^kN-6=lMzmnqJJZ6JiYV zU?%JGu0&|bX*ix3I*8FP)<7Q$e(K)nL=&O8*kE3FCV}pw96;@M5&!m!D05oj_mswK zbc?$98gLN1$EG2%Px92=67Y^Ho(K*3dG9`MJDf9>F9(eqaou8bMzTQAj|ysif3qRS z&Ad0p$>6h&NaV$S7R*C$1ZtjCYVdc*m-g@m8hJgmwS@;(W(Qz;QS$p8u0gMO&>YnH zCYa@W5bH>JF+#zUzz!7SyaikU)733pNg~WkSnhRLFixxzn=ce#a_HoXtCdB;uWB!F zM;Z1PzS&rL4K|&Kbu!CCGN=p;7?j=1ZKpav76HK=^(Adqp2KN?Z^wrwLLZXwWFM#&o>Aj z6g!|T9j+HhFYfyx8Jxa{0}L>biK4A;^oy-~SS@btc?NMlr3ZW;3C*b|c9Uzg@a{0q zmD>Z&7=u^zAAc&TJQ7ob`~3nCU{mK^CBS>t9Fh*uD+YBC>WnAXZT&NCAiGI~%>@K_8sg1TRw z;m3aMX{3z)7H(rk%)viO~69mM1I)Tlt@+pQk;9>y1$d73PK_A)-W_h8rF z2^zDfG1?#sE-2+s$-RAgd_*|?R|=6pR>S98F4D2yIuqw7MO?qRfAyoTkLeUsMvI$~ z(l-Sk6iq#iQ3OYsxCRy$+@7X{N+gFOZQv_KxC4G)z~i%l0zMn<m*^0kp^ zg&=$c6DhFc$kgF$U)kbeqj&1F0V7rX_74#LEz^-kYSUL-9tphve3(81Emn6pnIQ=U z@bDpYSNe8C=QH0v8wR(2PLJnK=_4A3b_e-VjLxAV#GMQ9H7AVWD*v5+1?E@B!#bEf zz|-O?ybfeg1J*C0ky5)+Wd4+^qhDv~yv(6-)WnG&Ovz-90`7kIet7*<}faxyzf?Fq(@D_1PU21L>y8k)hq0D@=Wy#}Pko^%JaKED{&N=7m|r zl35gEE;#(L1t1Wo{^-jSEM%rz;QGiI`TvWe0CQU(f2L?bIs za3R&BYuP_;1q?Nu7g5bbN8X;-hCg82`nv^o23 zeaa?rd?Rec5R3vtC72kUa{)Ob-%X*E?EP9~U#9{k98UQxVEeFYzcx7xbQDOIKt#lq zdRHDZNCVe4W15db|3jlVGnG<~KBM7zO72*(f~3w2(3=@>G=VKT%~PVa1C(Y6g8t7~ ziliF3qPm3zdtGF6_xKf~#{H`Hbp-wGG*+Ll?&iE4-#%W_>pS7+)ZoX&wRkh6Qi`~< zQp7SaqnrPkN_1#E56=_;9ft{1WHT*lWa9Ne=V7YAO#&nSxZ>84{!Uufe{Tscdloba1jynR@VRxlz#|~N5@eWI{}vbv_Bi__eU|Tq z0L>!kc@oE=sE7zre1AFZO%5!RYb>3{?{nXW=+qeogIhY=4YRrTm{|t=;M(E7Lfo-V zVsAfT96E4|1BueV5Y1iic|ZVVaAghwS!f5``e;UD0bC_Trvet8PB^+ivD z){t1#ABVpR6v<+o0b)LwINAg4Zkl zbn?-=ZYe~Gd*>@cpI_m{ZoPl{^BH&FgqJX;nj4ehEeUum6sgP8ksW7WG<-{ngaak~ zcg6GE!ggI)^Y=#{`btLIe6fV99Ti~bHBW4)rdizwcvL>*DieGVOrZpImd5mQrtg0s zxb&9EjILV8+mS$ddKz3}RiKZ1IDHZ<>1?6aknZ3mj(B=AD27!QU zuQa~Jvig9xXd;v-SE9!7N{}@MY#Q`835?Ny$%jSP69t{;;Z+=I+x=)9TDNf2;1+l& z?YABV6AunH^CwwIgj5=H%B|S91fEE-R-Wq}Z>W2OqW;7mv73g?pp@Ft7 zFV7aMF_>u2E8aHHlSYpN;Rh~UsM=#}tHJg+Q&1z^v^W^}pi#=eo#@v9LzMh3ZejsU z*bhePmwd_gdV%HnDS~MbngWK-8Zx$@Bf(%3#xTVFux;Q;%mss=Zd;)9#Gzws{{zCr zJ1PR?sN>*pBZivwrR9+mV9sd0Hz@~Z*u<;KqeiP)&~V6QYJR_o%Ubp*HgY_w!3sBK zH9hqsV^8IjZ|a*3_J+4YqwjOj8@0kMT+&DPG9*-FzZ6*kDX)Qv(&{%BCJsq=g1XWW zee^TG2@rJ{;5fij0Uj;YlCGf^GIW8qpPV^YtJUYKP4iF@rgum7ykkn*w|!7Q#$ZeG z#Uh1wKp#&6V=``#p3b8imWWOI=dR1#$gWd_!fDU{45vu;c|AD%tfZzUE_n|}aOGj= zKS?AT^-aDC)lGaxh67KC*jrJA-2KzxxV$oOh`#A>A1G>Ae*E3_Nd3$IO=&|e>cL@% z!rb>GH0791hKL)KYVkCIBo&7KYNelN>7Kqp0%;~bz_7W2R-P-__z5?@T6@@pxbuzf zMU1V<+AaJxC%$0Wqufd!jF$GSrP3ciSU6Xcsu_1?B1a>m_6vO}-wh4}BfnsM@sXm| zPCt24PWms!H6w7xD&6?E|36{^^v(<#thQ6(3`FY)Ee*k&q?g`DVj5s_kPZXnA3zx2 zxnSn~eGa>@ZKh$n_nU4UWsPcojuzyh?)#(Jveyg&EujUfo*wF_^*;=bL4o8w*jJ|_ zFE4M5i<+^`Vetc7<}_e3&^-j63>a?Yk(psd!FLH>B@8;bWiWW)K~47ij}*PW(DhFX zxAt&kyh@L=$W4PvOQ?V_hBG1jVC1m8N9>U$;SPVf*Je}Wblb&6^m_kQpGVjGVTL>S z(?JQA00~>NjI(3Zw;jJD!;wd3s@ne8$0^@%&FB^gw^+bmO@SErAd8c}q|tv@n$3fN zFQp5vkzJJl{xOe{r}PWz&O-z^q}}J1FV+c$Wq@UKGK9FxDR&}#HJXvB5z)eOcvlq< z@bE3W(6p-(V`0sIfBwAXy>1d+L}%C^{nr#|mPb~@;?n6#8t$f&nD)9~EgGZB&xhf4 zGP{OOzXuBpd+{+!>-e#lcY8AsM@*4xIe)?i?U`54q2XGgTKn*m4_WdHg9Ak;4FE1p zf;e>J5JH!{PPOW35KVbW^O5Uo&BZuC$Sr_=sf!=Oe{%19gIt6QfxHsvoK z)UMxTgfkG5#%CYFU7%Y2EYCN!_;aVi?FKU;h3^kD*V7=}$^0N2d)EZ1yTKaZtz5I69an zSn+;A7JvRQ)6dS=DJeC>DckAL*N&?9C~N=cAjLCWCe~y;T2{d|*(5kWOJUQ9JS#n% zFWNfbP`x8!V9kWwynRhF`oq6}|4Pa0?;iM!D`)quvdD%vj{5ZEEF9w2w)d`iP*2ks zl4y~j_?fY-ax=gqw7$75c~GZ9U9>BnGPW8LuQ5q6OCDUS@DP1cRVY<_x`rek_UjvE z=S_CCP|no^&Ys}B?`8An1P$&)eEmc#cz?4fYt|$5hq-;3bFYm5=wMp76y=O#@>e~X z``_B4;yraJCnw)JCiUKq2%4j~`%tAlNDT{lBikCWMV`IP0&kDz3Y<(cJbLCGa-G=5 zi}>7$#9A)e*i)~ay?3Z_o{Mj?Ylg$0QhU{Nou*Ok>P+R4N~=~gwy!nAWf!Cblnxx% zlAB`raKyf>G|_dutZiT<{>Y~_@`G|UX|rCL_E_(Xg8~;-d%U%M+ok%iR$lFKe`Z0x zkvNFenr(BjxSChk5b&olLFU0TvD0|_GPTD~m)I$_1zGc_T^;Nd&-U(Hcm;#V=^Sop z|FT#4FS3{^fu)HSayd*l4+2ah0>= zjccdmq#GG*`(@e-TZ%4rv|0YA*!t&uF{jhr-~GG+DoSRCB-#4PO+01i^N0dAgWqPW z)3T7N?h}-lC8t&CPtoUM6u2n*WbtK=Ba127IrrraN7~e;k!?Tb%A$KXqw*3;pc~}~ z63_R7aZ;>ubAPdJbZ+ZNK=Oz{qtOgS(R*vQ>H~BQD)sPluBnCcS8VEM2>nv$CMpDIQ zoPC-2llQj*0|Rv*7phA?bam=>NN@0%f15S9_utE&<(EBSKWov6FnTE(pi5^1i(-rn-EE*dJT3 z$KO_|==J<_oO49a`Izq{6@1MViO#aw&at1_^`!od+K-V z+x+G4Z+{J&Cs)??dZaa3Tz!73CRnOlro9D4?>F6)^r`C{85waS-_3X5it?(U6MdOD z|F+?YOt@g3v;Bj#0Y^&h<(^ot^|P(_eYB!)qO*2oracOj9am|^^NkNG_P@~EX0^=Z zt=)*d(b+lvXXHkLwVI6x#XOG ziCJ;SIaa^O7j5HCRDEuD{js>&UL4A+;eR}W6|9_=x{iFB6jajcd3@pK`}x1DbLEfx zO>76s=Jnd}fSN#(ApHQka{&zv3ZLR{3pC5v2##be)q7oE<$G?yqbGsft)gjdw?!iEVj3^uo zYc&=AmKGv0U^wp67W}!~S(HiTUm)_@Qz3^~o_>?&4 z#N7D2BUO$>@foo0cF>9rAP3t~0@DtBOsKHbUN7bKX8mEG_b%aaRoW~?^XU;~xz}4A zt~SPmRjJ0w)4UQhHnBJ0lRqB$BrT{kHtNGGUdG8?97Wq{af!+n%a=jf-Ksbhpylv! zv)m@aD%R8M&qd|7zJ!u@uEVE>%arb~`}>>=`*qfSO;jsdve;jX?AN5(xIZGiHmmdM z2JR0}vRL-tqs-XQ5!16XQe^uN6aB66Vw-Ng`U}N~L63$`Z?%`V_nHm-f3R)sLa~yd zYn2akdPvLGjqKX5QO}#1cGr zM+7cg$Hl*U;Cth-M)33B6wZ&E{$UwE3SEcm_+H#jQ!J`=9nMV3@pb5x(Tn+eUn|$H zL*}3;nU+^tQL(D^uIgPwSh_;^1NIS1>Md4t9u7CkTsK#_CQsNz=t&ntM3VI(KK*q? zA|gCPxHebSq41qwh+9?gt}T}X39NL(}&;Gejy2&W*PuMROdymQ9TS9tR z)+dUd{J+$MtQR!43H?kr6nGL^aP!0M%@Kw7ch6?ej&A3SC~$mgTbo<;8~)uP<%Xg| zV{P88DK?KrMhnf*@V!5L&L^nP(8B#}#b$&3S`pWz|K|2icEyUzGcKEp-$y$;d2Q3% zA}Gn1nq+i5th8Q0hho{Y8J6)tqgN&^rbNi+P5a&J76YM`o9Kw@<=_zhh^K*dK^0l* z_epy>?|R{Y|3*Pj&A_bEn@r6(4Xw0R-rH)UeKPIFHWBVJ#R*zNRz0~R+tnitIgb*R ze8D=%r}gg4bNT(}o-787m5;<$m>|;#+!FJvGsl@tQ@jTsU-;1;k<5NJyTkZO)#g>{ z*i2rU;TzOw#82_Jz(#e`;1%RuV`Z z#g~ecf)$LgTh9vf^Jx*k9b z$DMS?q+D4YkHVKdD}n(xAJe`WzteU4Fw<{}UfbRF=hL;~jwG&0%L;V_q43bF*tpFW zl-FJz9i6|c9o@`p-R2_ZxG*BX(bD#Aj=Cu~)j>01PYHCS96I&)yw_bHp1{t?SU0$` z`}i`xO>aqw2s~MQwfDzI-9^HFwPaUX!gn65m2(>14v=cxJ<4m>$gJr{Gg|a%)Tfj8 z_LJ{9FL&z7T%+4~_tk~NVSKSVJFwe08kE&=&(NYo(||2{Y+b_6grY1;OHOJH%a9lH zA)Jku5k^c0%jT*7fBU1wT9<#G%{JEFIIN}ON%i=;KfHbQM|Q0><1Is3o2xy?1YKi* zNP ziO$qkcvv^|EE0Njwa+RU8cO&?N!|C+xxBQ@>}4S_D0PZbOER=@{!pLz zRwul6@AzxQCMp%6=<^Ca`d}@M20ez4oBt}LAyF&YCs=r!#49$vVib7d@P|d}puP9g zJDtoCaYsJsPy%mJcrvZ+rR_{=g?(5=Ung3i6w1g;!KX*~WTmBxZ74jG87S&-)if0r z%KVJu=c5+qo*WU%m}nZ6i1};KZ69df-9R(_9~39-0#E!&9a5O4?_S%x_e1MlZ@bjX zW1B{!VShc~=M_Kvx11s)PrLE7Vr2wRsWt5}h~20to`~xA3Q+Bp36;@V(UWQ%NE*~` zn|pdTo2tE$SJg@CkZ-haDXJbfw7k2$vFZ`qakIr)JR{{<6MIoS@aiJ?dw7qi$y<#E zNsj*@S@;O{>xJSM#=q@z=!gKa^$y}%P1eeN5*NF)e_Yle1X)ReC)$16pMn!# z_Qa-bE592Fs2kzF{5#`x^^Ln!f3csd9Fd6u=NccFQg{%_1BO>y1?OKXHVJ3FRK`T{ zaGUYWJeB%Q34EXBRq@y*N3-9nMiYBf(CMq?Aii{gvv>B(h$s?q;b36p&x>Al;VlQX^dQ>u z{PnA`Xn(t+X??}?!o?n@`UfVwYVv0wSq{~p=r(jXpFVCD_K#|fj3>RpB+w7~!Htdk z+dQIh+1j$luuQG6ZO%>mLCx3uUIuLAH>hcPLfpr;E`@&FJgC!%Y3a1Lx7Tgqr7e$! z>y`;uZ*Fl3*Lr&X)J$A#Sepq2wYAqQG%I(rqny0?pP(ZiVxydn$EAp+uR6VRLNn}? zoeMs7M%n}2-sY<#0nw*x?F$Zo>p(FBr^Zs>hysGZ4^Cr|ESA3T(Ra28sG|84r7h8C zoQ|}$)RApDJl^89B17;viNcvT*>q-9?et7(Y+1`|I;Jj}_OFy$$dXUb7dJVc=lIQG z`}rAj=lSA!4-(fSW=gHCYng+CgU?GN@%~kg?m>w2XMVFhQrt@e0s>E-%b)LSiyC@= z>+^*Q4`iAr;cvx=fNVly&841J57LiA#veC<*J1tJR7(!FrIc&3)g~g^Wq7S~bo-=_ zirJ`@%@EJiEQ^GVjL&L~&j$sMsXeI5vV?;WJpBD%#$(5>1#00-nFB9`{BMAt>xjU4 zGocx~3iXKQe)vUAb6PsB$chrEzZoq zGUhZ_XBCF~H|7}*tolNRh?J^r7^P~Ttr;K9wUb_m*A8gNaeU`REso!)3@4H(?gr25 zw2}Ih%!&VN@9Q6#Uc>*_Bh?}2`y0&pF?};rrchwR!LTzVGY4?$`Bty{>zOO0I0Q z{Eswbo>o%zE|SaJYXDGw6iebSw|%wqal_IY!r6zM=X#Ze&lNW3Tl61Zsdl>*S$8#y z77a@vqDvXQjud-^CK`dj%FrkVPq3A5pmcLdPHy zbAz^tbc6UFao%qGjmq13qhn5CXoWwwu2A#pW=Ij*#Bk(Lk{^ZkyUqCySn*RDbt5OE zPP(L*!D>T&7HQ53;O9^dc2ZBs^Tgd_oU+`PUa+7et?`0KjL_s4$1vG{3ekFZUD>+m z=}@UZ?y~s{^rE8L5UIwI6>7KhR%AA8uM|D@$CfCsA{kbWo-xl+Gna1F`J&;IJ{ze% zij0kpjFi5lE+IWE^^Ndd!e_TDd*0GbgwhZQjGF{)l1I;qsjq+C+@AWma;$~7s2t}2$KM-K7*V&d z&&??=qoc(IOP84`_!#5oQfQgj7xCG~mAa#{7r(%EO6QD;A5m;Sbw}oZl|Pz0gw%Hi z@h#z;JBG;Pw84lm%Jbx*&pp4w8ujIg*Gaz2SHqTTuOQ5r`U(|BGb?4y8q0>G032_p zNp|MsEN1;Q~#SDoR&+M`bTyhfkhw$i!6UX8+OJs#ALJQ%%l&_4oRUFz@xHrDMiS zk#nez%hJ1?v2EuX?RpH?;j->u%Du~h;PU+$iO7ONGHs!#2p`&tvGBh z-F0(n7Pg0vr*RVw?yp#RH47NVx7M$V8Zv`z_ZuhSX4j)m9pOwjLydzbrQp&X<}MXX z`WX3oW(W8uf0@*v!l3{8JH=#6Com9MPcLzY$@BNL+pR`q7o!y36AG~o_VR_0=K%dx zS=aa=>uv596-j0Fc|Z|kuJoy9w-J;^q)t}Kjl-jzkEH1am8;Xdzi0CHnmhyy?Fi4* z@8JHpsL11VVv_dSBuZ^L{LJTv&PVVQW@=BZQXL;okYh^ob?YecCn>)(mUyOy)t3K~ zxrJb~VyLM?5-x7oTL&KkfeX+5!sOTMVf$hqt4ztD|78U7q1PMBIKh}th7#Ppg@;j@-5_}C> z5*`R5-=5HEkqX;WKVWu@?ZOB>un{9dpbT|lgr0hZkF21nIy+6Dv8P2ALN1HB-}dS2 z(96f)wOh_Uq_u~*MgbnR02bvbjXB(DaDssLr$VFz+axR@&zloG$A0oUbNk|@_#tPDUi$tsZ zxmOblbw19CVCJ;)!y!f+WV3$AxTRkBvdHaKjYuu4&Z}@OH!F?Zo%ODs)61f#O*I!4 z?QR))grx`YYn;d_oDb_QfA8?y-Sgx)Zh#Y?0u}Ihg|^vNVk^(3CZHY4&pOSkW)F)# zdBHPnA*rDF=8bk$u!<6Q_S&#RNU<3-faMhmFDuSJrjY=&;*mNi266z9*sk;XL5IzI zbS+i`&o@A!WD`C(5tohEm)-W_pzLsOY};)@rU z66nARtIGq~;_eXpK-Z68{9tHJ0ihTEa-I?T{$TiA^zs8rnB!DzlR2d?1?Uwn6dJq- ziLQRnKP2kMxUmf*@>~p&7*{SmmF-VbJHXD(Pm_i59%eKpSEjMs$i1+XHrl#zlnmS# zr4)#5GCwau(q=F*@H2xxsIricbnll-cw zxG1uaHVh>to5f;9cZ{nOjEFv&DjuBa?T~S*ZFD$G!w)l*uipqeBt7^9K9`!OnPZ-H4u`q zijJVi+a)Gqaqh6y#`vHIv}w3=>yqSL8-SrUChDB&j7yZ-J4Ho-hn=1{BihRLK#aYv z(5{F1IzgCG!*!7ju|J{@zD51>@c!JKje=*8`tIMDDu578gGKD$O`nKDo2rp+SO!&} z-2pJ6leH-(kHtdV=98EiG2ViDCD<_C|+RXb{bT&zrXIQG?R zlND5&MwPXpqbR+d{dDo|P4_W=2ay;{>A@&?%)79m%Gma-KkoEqE4t%@tl`0|0+$KI z778`JU7cG;v-XDwbqP=B9nK}wCf8bi+4X4V{BZ($f;~1pU%(lo%A4XPOP(*`jMeIqZv2}0py-oohu;Ek@7l)gfJ&;H zRT1|1=t&G&64$?4+K(5n7*iohnU`^x9!^eyu%;545}y|OzDo33|Ar88o0gclqvo

    ZA%(!&lfU8?qroT0I+hxu{{ZyeUag@_FS~7 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 SHp)q!9A|lOU#Yq0rT+uR++y7T literal 11358 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 aVr_2|SZrswIRFm~gOugfU{xgood<% } else { %>danger<%} %>", + "author_name": "nf-core/oncoanalyser ${version} - ${runName}", + "author_icon": "https://www.nextflow.io/docs/latest/_static/favicon.ico", + "text": "<% if (success) { %>Pipeline completed successfully!<% } else { %>Pipeline completed with errors<% } %>", + "fields": [ + { + "title": "Command used to launch the workflow", + "value": "```${commandLine}```", + "short": false + } + <% + if (!success) { %> + , + { + "title": "Full error message", + "value": "```${errorReport}```", + "short": false + }, + { + "title": "Pipeline configuration", + "value": "<% out << summary.collect{ k,v -> k == "hook_url" ? "_${k}_: (_hidden_)" : ( ( v.class.toString().contains('Path') || ( v.class.toString().contains('String') && v.contains('/') ) ) ? "_${k}_: `${v}`" : (v.class.toString().contains('DateTime') ? ("_${k}_: " + v.format(java.time.format.DateTimeFormatter.ofLocalizedDateTime(java.time.format.FormatStyle.MEDIUM))) : "_${k}_: ${v}") ) }.join(",\n") %>", + "short": false + } + <% } + %> + ], + "footer": "Completed at <% out << dateComplete.format(java.time.format.DateTimeFormatter.ofLocalizedDateTime(java.time.format.FormatStyle.MEDIUM)) %> (duration: ${duration})" + } + ] +} diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py deleted file mode 100755 index 11b15572..00000000 --- a/bin/check_samplesheet.py +++ /dev/null @@ -1,262 +0,0 @@ -#!/usr/bin/env python - - -"""Provide a command line tool to validate and transform tabular samplesheets.""" - - -import argparse -import csv -import logging -import sys -from collections import Counter -from pathlib import Path - -logger = logging.getLogger() - - -class RowChecker: - """ - Define a service that can validate and transform each given row. - - Attributes: - modified (list): A list of dicts, where each dict corresponds to a previously - validated and transformed row. The order of rows is maintained. - - """ - - VALID_FORMATS = ( - ".fq.gz", - ".fastq.gz", - ) - - def __init__( - self, - sample_col="sample", - first_col="fastq_1", - second_col="fastq_2", - single_col="single_end", - **kwargs, - ): - """ - Initialize the row checker with the expected column names. - - 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"). - - """ - super().__init__(**kwargs) - self._sample_col = sample_col - self._first_col = first_col - self._second_col = second_col - self._single_col = single_col - self._seen = set() - self.modified = [] - - def validate_and_transform(self, row): - """ - Perform all validations on the given row and insert the read pairing status. - - Args: - row (dict): A mapping from column headers (keys) to elements of that row - (values). - - """ - self._validate_sample(row) - self._validate_first(row) - self._validate_second(row) - self._validate_pair(row) - self._seen.add((row[self._sample_col], row[self._first_col])) - self.modified.append(row) - - def _validate_sample(self, row): - """Assert that the sample name exists and convert spaces to underscores.""" - if len(row[self._sample_col]) <= 0: - raise AssertionError("Sample input is required.") - # Sanitize samples slightly. - 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.""" - 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]) - - 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]) - - 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_fastq_format(self, filename): - """Assert that a given filename has one of the expected FASTQ extensions.""" - 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"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. - - 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. - - """ - if len(self._seen) != len(self.modified): - raise AssertionError("The pair of sample name and FASTQ 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]}" - - -def read_head(handle, num_lines=10): - """Read the specified number of lines from the current position in the file.""" - lines = [] - for idx, line in enumerate(handle): - if idx == num_lines: - break - lines.append(line) - return "".join(lines) - - -def sniff_format(handle): - """ - Detect the tabular format. - - Args: - handle (text file): A handle to a `text file`_ object. The read position is - expected to be at the beginning (index 0). - - Returns: - csv.Dialect: The detected tabular format. - - .. _text file: - https://docs.python.org/3/glossary.html#term-text-file - - """ - peek = read_head(handle) - handle.seek(0) - sniffer = csv.Sniffer() - if not sniffer.has_header(peek): - logger.critical("The given sample sheet does not appear to contain a header.") - sys.exit(1) - dialect = sniffer.sniff(peek) - return dialect - - -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. - - Args: - file_in (pathlib.Path): The given tabular samplesheet. The format can be either - CSV, TSV, or any other format automatically recognized by ``csv.Sniffer``. - file_out (pathlib.Path): Where the validated and transformed samplesheet should - be created; always in CSV format. - - Example: - 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, - - .. _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"} - # 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)) - # Validate the existence of the expected header columns. - if not required_columns.issubset(reader.fieldnames): - req_cols = ", ".join(required_columns) - logger.critical(f"The sample sheet **must** contain these column headers: {req_cols}.") - sys.exit(1) - # Validate each row. - checker = RowChecker() - for i, row in enumerate(reader): - try: - checker.validate_and_transform(row) - except AssertionError as error: - logger.critical(f"{str(error)} On line {i + 2}.") - sys.exit(1) - checker.validate_unique_samples() - header = list(reader.fieldnames) - 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=",") - writer.writeheader() - for row in checker.modified: - writer.writerow(row) - - -def parse_args(argv=None): - """Define and immediately parse command line arguments.""" - parser = argparse.ArgumentParser( - description="Validate and transform a tabular samplesheet.", - epilog="Example: python check_samplesheet.py samplesheet.csv samplesheet.valid.csv", - ) - parser.add_argument( - "file_in", - metavar="FILE_IN", - type=Path, - help="Tabular input samplesheet in CSV or TSV format.", - ) - parser.add_argument( - "file_out", - metavar="FILE_OUT", - type=Path, - help="Transformed output samplesheet in CSV format.", - ) - parser.add_argument( - "-l", - "--log-level", - help="The desired log level (default WARNING).", - choices=("CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"), - default="WARNING", - ) - return parser.parse_args(argv) - - -def main(argv=None): - """Coordinate argument parsing and program execution.""" - args = parse_args(argv) - logging.basicConfig(level=args.log_level, format="[%(levelname)s] %(message)s") - if not args.file_in.is_file(): - logger.error(f"The given input file {args.file_in} was not found!") - sys.exit(2) - args.file_out.parent.mkdir(parents=True, exist_ok=True) - check_samplesheet(args.file_in, args.file_out) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/conf/base.config b/conf/base.config index 05eac721..5802f0f1 100644 --- a/conf/base.config +++ b/conf/base.config @@ -15,7 +15,7 @@ process { memory = { check_max( 6.GB * task.attempt, 'memory' ) } time = { check_max( 4.h * task.attempt, 'time' ) } - errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } + errorStrategy = { task.exitStatus in ((130..145) + 104) ? 'retry' : 'finish' } maxRetries = 1 maxErrors = '-1' diff --git a/conf/igenomes.config b/conf/igenomes.config index 7a1b3ac6..3f114377 100644 --- a/conf/igenomes.config +++ b/conf/igenomes.config @@ -36,6 +36,14 @@ params { macs_gsize = "2.7e9" blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" } + 'CHM13' { + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAIndex/" + bwamem2 = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAmem2Index/" + gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/CHM13/Annotation/Genes/genes.gtf" + gff = "ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/009/914/755/GCF_009914755.1_T2T-CHM13v2.0/GCF_009914755.1_T2T-CHM13v2.0_genomic.gff.gz" + mito_name = "chrM" + } 'GRCm38' { fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" diff --git a/conf/modules.config b/conf/modules.config index da58a5d8..e3ea8fa6 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,14 +18,6 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] - withName: SAMPLESHEET_CHECK { - publishDir = [ - path: { "${params.outdir}/pipeline_info" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } - ] - } - withName: FASTQC { ext.args = '--quiet' } @@ -38,4 +30,13 @@ process { ] } + withName: 'MULTIQC' { + ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } + publishDir = [ + path: { "${params.outdir}/multiqc" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + } diff --git a/docs/images/nf-core-oncoanalyser_logo_dark.png b/docs/images/nf-core-oncoanalyser_logo_dark.png index 6e9f66c1e81c97da2504f06623d225734ffe5197..8be3600766ff0f1d1cbbdc8a9fcc3adc30ae4c25 100644 GIT binary patch literal 29358 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 R{3Q7n*<-((^%M2i{{oi35HA1# diff --git a/docs/images/nf-core-oncoanalyser_logo_light.png b/docs/images/nf-core-oncoanalyser_logo_light.png index 5d6f1c71ba0d76002047ae721880d6a65df8286d..8a840262195aeb5b5731135591fdaaa10364bea4 100644 GIT binary patch literal 24726 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 literal 86949 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%0DdkSBkTJ0jfo-uX{!snR7# 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 PIuv4Kcd%f;*AM> **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. +:::note +The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. +::: ### MultiQC @@ -62,6 +64,7 @@ Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQ - Reports generated by Nextflow: `execution_report.html`, `execution_timeline.html`, `execution_trace.txt` and `pipeline_dag.dot`/`pipeline_dag.svg`. - Reports generated by the pipeline: `pipeline_report.html`, `pipeline_report.txt` and `software_versions.yml`. The `pipeline_report*` files will only be present if the `--email` / `--email_on_fail` parameter's are used when running the pipeline. - Reformatted samplesheet files used as input to the pipeline: `samplesheet.valid.csv`. + - Parameters used by the pipeline run: `params.json`. diff --git a/docs/usage.md b/docs/usage.md index 8d291b27..39274fa8 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -20,7 +20,7 @@ You will need to create a samplesheet with information about the samples you wou The `sample` identifiers have to be the same when you have re-sequenced the same sample more than once e.g. to increase sequencing depth. The pipeline will concatenate the raw reads before performing any downstream analysis. Below is an example for the same sample sequenced across 3 lanes: -```console +```csv title="samplesheet.csv" sample,fastq_1,fastq_2 CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz CONTROL_REP1,AEG588A1_S1_L003_R1_001.fastq.gz,AEG588A1_S1_L003_R2_001.fastq.gz @@ -33,7 +33,7 @@ The pipeline will auto-detect whether a sample is single- or paired-end using th A final samplesheet file consisting of both single- and paired-end data may look something like the one below. This is for 6 samples, where `TREATMENT_REP3` has been sequenced twice. -```console +```csv title="samplesheet.csv" sample,fastq_1,fastq_2 CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz CONTROL_REP2,AEG588A2_S2_L002_R1_001.fastq.gz,AEG588A2_S2_L002_R2_001.fastq.gz @@ -57,7 +57,7 @@ An [example samplesheet](../assets/samplesheet.csv) has been provided with the p The typical command for running the pipeline is as follows: ```bash -nextflow run nf-core/oncoanalyser --input samplesheet.csv --outdir --genome GRCh37 -profile docker +nextflow run nf-core/oncoanalyser --input ./samplesheet.csv --outdir ./results --genome GRCh37 -profile docker ``` This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. @@ -71,6 +71,31 @@ work # Directory containing the nextflow working files # Other nextflow hidden files, eg. history of pipeline runs and old logs. ``` +If you wish to repeatedly use the same parameters for multiple runs, rather than specifying each flag in the command, you can specify these in a params file. + +Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. + +:::warning +Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). +::: + +The above pipeline run specified with a params file in yaml format: + +```bash +nextflow run nf-core/oncoanalyser -profile docker -params-file params.yaml +``` + +with `params.yaml` containing: + +```yaml +input: './samplesheet.csv' +outdir: './results/' +genome: 'GRCh37' +<...> +``` + +You can also generate such `YAML`/`JSON` files via [nf-core/launch](https://nf-co.re/launch). + ### Updating the pipeline When you run the above command, Nextflow automatically pulls the pipeline code from GitHub and stores it as a cached version. When running the pipeline after this, it will always use the cached version if available - even if the pipeline has been updated since. To make sure that you're running the latest version of the pipeline, make sure that you regularly update the cached version of the pipeline: @@ -83,29 +108,42 @@ nextflow pull nf-core/oncoanalyser It is a good idea to specify a pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. -First, go to the [nf-core/oncoanalyser releases page](https://github.com/nf-core/oncoanalyser/releases) and find the latest version number - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. +First, go to the [nf-core/oncoanalyser releases page](https://github.com/nf-core/oncoanalyser/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. + +This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. + +To further assist in reproducbility, you can use share and re-use [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. -This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. +:::tip +If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. +::: ## Core Nextflow arguments -> **NB:** These options are part of Nextflow and use a _single_ hyphen (pipeline parameters use a double-hyphen). +:::note +These options are part of Nextflow and use a _single_ hyphen (pipeline parameters use a double-hyphen). +::: ### `-profile` Use this parameter to choose a configuration profile. Profiles can give configuration presets for different compute environments. -Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Conda) - see below. When using Biocontainers, most of these software packaging methods pull Docker containers from quay.io e.g [FastQC](https://quay.io/repository/biocontainers/fastqc) except for Singularity which directly downloads Singularity images via https hosted by the [Galaxy project](https://depot.galaxyproject.org/singularity/) and Conda which downloads and installs software locally from [Bioconda](https://bioconda.github.io/). +Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Apptainer, Conda) - see below. -> We highly recommend the use of Docker or Singularity containers for full pipeline reproducibility, however when this is not possible, Conda is also supported. +:::info +We highly recommend the use of Docker or Singularity containers for full pipeline reproducibility, however when this is not possible, Conda is also supported. +::: The pipeline also dynamically loads configurations from [https://github.com/nf-core/configs](https://github.com/nf-core/configs) when it runs, making multiple config profiles for various institutional clusters available at run time. For more information and to see if your system is available in these configs please see the [nf-core/configs documentation](https://github.com/nf-core/configs#documentation). Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! They are loaded in sequence, so later profiles can overwrite earlier profiles. -If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended. +If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer enviroment. +- `test` + - A profile with a complete configuration for automated testing + - Includes links to test data so needs no other parameters - `docker` - A generic configuration profile to be used with [Docker](https://docker.com/) - `singularity` @@ -116,11 +154,10 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) - `charliecloud` - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) +- `apptainer` + - A generic configuration profile to be used with [Apptainer](https://apptainer.org/) - `conda` - - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter or Charliecloud. -- `test` - - A profile with a complete configuration for automated testing - - Includes links to test data so needs no other parameters + - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter, Charliecloud, or Apptainer. ### `-resume` @@ -138,96 +175,19 @@ Specify the path to a specific config file (this is a core Nextflow command). Se Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the steps in the pipeline, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher requests (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. -For example, if the nf-core/rnaseq pipeline is failing after multiple re-submissions of the `STAR_ALIGN` process due to an exit code of `137` this would indicate that there is an out of memory issue: - -```console -[62/149eb0] NOTE: Process `NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN (WT_REP1)` terminated with an error exit status (137) -- Execution is retried (1) -Error executing process > 'NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN (WT_REP1)' - -Caused by: - Process `NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN (WT_REP1)` terminated with an error exit status (137) - -Command executed: - STAR \ - --genomeDir star \ - --readFilesIn WT_REP1_trimmed.fq.gz \ - --runThreadN 2 \ - --outFileNamePrefix WT_REP1. \ - - -Command exit status: - 137 - -Command output: - (empty) - -Command error: - .command.sh: line 9: 30 Killed STAR --genomeDir star --readFilesIn WT_REP1_trimmed.fq.gz --runThreadN 2 --outFileNamePrefix WT_REP1. -Work dir: - /home/pipelinetest/work/9d/172ca5881234073e8d76f2a19c88fb - -Tip: you can replicate the issue by changing to the process work dir and entering the command `bash .command.run` -``` - -To bypass this error you would need to find exactly which resources are set by the `STAR_ALIGN` process. The quickest way is to search for `process STAR_ALIGN` in the [nf-core/rnaseq Github repo](https://github.com/nf-core/rnaseq/search?q=process+STAR_ALIGN). -We have standardised the structure of Nextflow DSL2 pipelines such that all module files will be present in the `modules/` directory and so, based on the search results, the file we want is `modules/nf-core/software/star/align/main.nf`. -If you click on the link to that file you will notice that there is a `label` directive at the top of the module that is set to [`label process_high`](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/modules/nf-core/software/star/align/main.nf#L9). -The [Nextflow `label`](https://www.nextflow.io/docs/latest/process.html#label) directive allows us to organise workflow processes in separate groups which can be referenced in a configuration file to select and configure subset of processes having similar computing requirements. -The default values for the `process_high` label are set in the pipeline's [`base.config`](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L33-L37) which in this case is defined as 72GB. -Providing you haven't set any other standard nf-core parameters to **cap** the [maximum resources](https://nf-co.re/usage/configuration#max-resources) used by the pipeline then we can try and bypass the `STAR_ALIGN` process failure by creating a custom config file that sets at least 72GB of memory, in this case increased to 100GB. -The custom config below can then be provided to the pipeline via the [`-c`](#-c) parameter as highlighted in previous sections. - -```nextflow -process { - withName: 'NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN' { - memory = 100.GB - } -} -``` - -> **NB:** We specify the full process name i.e. `NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN` in the config file because this takes priority over the short name (`STAR_ALIGN`) and allows existing configuration using the full process name to be correctly overridden. -> -> If you get a warning suggesting that the process selector isn't recognised check that the process name has been specified correctly. - -### Updating containers - -The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. If for some reason you need to use a different version of a particular tool with the pipeline then you just need to identify the `process` name and override the Nextflow `container` definition for that process using the `withName` declaration. For example, in the [nf-core/viralrecon](https://nf-co.re/viralrecon) pipeline a tool called [Pangolin](https://github.com/cov-lineages/pangolin) has been used during the COVID-19 pandemic to assign lineages to SARS-CoV-2 genome sequenced samples. Given that the lineage assignments change quite frequently it doesn't make sense to re-release the nf-core/viralrecon everytime a new version of Pangolin has been released. However, you can override the default container used by the pipeline by creating a custom config file and passing it as a command-line argument via `-c custom.config`. - -1. Check the default version used by the pipeline in the module file for [Pangolin](https://github.com/nf-core/viralrecon/blob/a85d5969f9025409e3618d6c280ef15ce417df65/modules/nf-core/software/pangolin/main.nf#L14-L19) -2. Find the latest version of the Biocontainer available on [Quay.io](https://quay.io/repository/biocontainers/pangolin?tag=latest&tab=tags) -3. Create the custom config accordingly: - - - For Docker: +To change the resource requests, please see the [max resources](https://nf-co.re/docs/usage/configuration#max-resources) and [tuning workflow resources](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources) section of the nf-core website. - ```nextflow - process { - withName: PANGOLIN { - container = 'quay.io/biocontainers/pangolin:3.0.5--pyhdfd78af_0' - } - } - ``` +### Custom Containers - - For Singularity: +In some cases you may wish to change which container or conda environment a step of the pipeline uses for a particular tool. By default nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However in some cases the pipeline specified version maybe out of date. - ```nextflow - process { - withName: PANGOLIN { - container = 'https://depot.galaxyproject.org/singularity/pangolin:3.0.5--pyhdfd78af_0' - } - } - ``` +To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/usage/configuration#updating-tool-versions) section of the nf-core website. - - For Conda: +### Custom Tool Arguments - ```nextflow - process { - withName: PANGOLIN { - conda = 'bioconda::pangolin=3.0.5' - } - } - ``` +A pipeline might not always support every possible argument or option of a particular tool used in pipeline. Fortunately, nf-core pipelines provide some freedom to users to insert additional parameters that the pipeline does not include by default. -> **NB:** If you wish to periodically update individual tool-specific results (e.g. Pangolin) generated by the pipeline then you must ensure to keep the `work/` directory otherwise the `-resume` ability of the pipeline will be compromised and it will restart from scratch. +To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/usage/configuration#customising-tool-arguments) section of the nf-core website. ### nf-core/configs diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy deleted file mode 100755 index b3d092f8..00000000 --- a/lib/NfcoreSchema.groovy +++ /dev/null @@ -1,529 +0,0 @@ -// -// This file holds several functions used to perform JSON parameter validation, help and summary rendering for the nf-core pipeline template. -// - -import org.everit.json.schema.Schema -import org.everit.json.schema.loader.SchemaLoader -import org.everit.json.schema.ValidationException -import org.json.JSONObject -import org.json.JSONTokener -import org.json.JSONArray -import groovy.json.JsonSlurper -import groovy.json.JsonBuilder - -class NfcoreSchema { - - // - // Resolve Schema path relative to main workflow directory - // - public static String getSchemaPath(workflow, schema_filename='nextflow_schema.json') { - return "${workflow.projectDir}/${schema_filename}" - } - - // - // Function to loop over all parameters defined in schema and check - // whether the given parameters adhere to the specifications - // - /* groovylint-disable-next-line UnusedPrivateMethodParameter */ - public static void validateParameters(workflow, params, log, schema_filename='nextflow_schema.json') { - def has_error = false - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - // Check for nextflow core params and unexpected params - def json = new File(getSchemaPath(workflow, schema_filename=schema_filename)).text - def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions') - def nf_params = [ - // Options for base `nextflow` command - 'bg', - 'c', - 'C', - 'config', - 'd', - 'D', - 'dockerize', - 'h', - 'log', - 'q', - 'quiet', - 'syslog', - 'v', - 'version', - - // Options for `nextflow run` command - 'ansi', - 'ansi-log', - 'bg', - 'bucket-dir', - 'c', - 'cache', - 'config', - 'dsl2', - 'dump-channels', - 'dump-hashes', - 'E', - 'entry', - 'latest', - 'lib', - 'main-script', - 'N', - 'name', - 'offline', - 'params-file', - 'pi', - 'plugins', - 'poll-interval', - 'pool-size', - 'profile', - 'ps', - 'qs', - 'queue-size', - 'r', - 'resume', - 'revision', - 'stdin', - 'stub', - 'stub-run', - 'test', - 'w', - 'with-charliecloud', - 'with-conda', - 'with-dag', - 'with-docker', - 'with-mpi', - 'with-notification', - 'with-podman', - 'with-report', - 'with-singularity', - 'with-timeline', - 'with-tower', - 'with-trace', - 'with-weblog', - 'without-docker', - 'without-podman', - 'work-dir' - ] - def unexpectedParams = [] - - // Collect expected parameters from the schema - def expectedParams = [] - def enums = [:] - for (group in schemaParams) { - for (p in group.value['properties']) { - expectedParams.push(p.key) - if (group.value['properties'][p.key].containsKey('enum')) { - enums[p.key] = group.value['properties'][p.key]['enum'] - } - } - } - - for (specifiedParam in params.keySet()) { - // nextflow params - if (nf_params.contains(specifiedParam)) { - log.error "ERROR: You used a core Nextflow option with two hyphens: '--${specifiedParam}'. Please resubmit with '-${specifiedParam}'" - has_error = true - } - // unexpected params - def params_ignore = params.schema_ignore_params.split(',') + 'schema_ignore_params' - def expectedParamsLowerCase = expectedParams.collect{ it.replace("-", "").toLowerCase() } - def specifiedParamLowerCase = specifiedParam.replace("-", "").toLowerCase() - def isCamelCaseBug = (specifiedParam.contains("-") && !expectedParams.contains(specifiedParam) && expectedParamsLowerCase.contains(specifiedParamLowerCase)) - if (!expectedParams.contains(specifiedParam) && !params_ignore.contains(specifiedParam) && !isCamelCaseBug) { - // Temporarily remove camelCase/camel-case params #1035 - def unexpectedParamsLowerCase = unexpectedParams.collect{ it.replace("-", "").toLowerCase()} - if (!unexpectedParamsLowerCase.contains(specifiedParamLowerCase)){ - unexpectedParams.push(specifiedParam) - } - } - } - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - // Validate parameters against the schema - InputStream input_stream = new File(getSchemaPath(workflow, schema_filename=schema_filename)).newInputStream() - JSONObject raw_schema = new JSONObject(new JSONTokener(input_stream)) - - // Remove anything that's in params.schema_ignore_params - raw_schema = removeIgnoredParams(raw_schema, params) - - Schema schema = SchemaLoader.load(raw_schema) - - // Clean the parameters - def cleanedParams = cleanParameters(params) - - // Convert to JSONObject - def jsonParams = new JsonBuilder(cleanedParams) - JSONObject params_json = new JSONObject(jsonParams.toString()) - - // Validate - try { - schema.validate(params_json) - } catch (ValidationException e) { - println '' - log.error 'ERROR: Validation of pipeline parameters failed!' - JSONObject exceptionJSON = e.toJSON() - printExceptions(exceptionJSON, params_json, log, enums) - println '' - has_error = true - } - - // Check for unexpected parameters - if (unexpectedParams.size() > 0) { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - println '' - def warn_msg = 'Found unexpected parameters:' - for (unexpectedParam in unexpectedParams) { - warn_msg = warn_msg + "\n* --${unexpectedParam}: ${params[unexpectedParam].toString()}" - } - log.warn warn_msg - log.info "- ${colors.dim}Ignore this warning: params.schema_ignore_params = \"${unexpectedParams.join(',')}\" ${colors.reset}" - println '' - } - - if (has_error) { - System.exit(1) - } - } - - // - // Beautify parameters for --help - // - public static String paramsHelp(workflow, params, command, schema_filename='nextflow_schema.json') { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - Integer num_hidden = 0 - String output = '' - output += 'Typical pipeline command:\n\n' - output += " ${colors.cyan}${command}${colors.reset}\n\n" - Map params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) - Integer max_chars = paramsMaxChars(params_map) + 1 - Integer desc_indent = max_chars + 14 - Integer dec_linewidth = 160 - desc_indent - for (group in params_map.keySet()) { - Integer num_params = 0 - String group_output = colors.underlined + colors.bold + group + colors.reset + '\n' - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (group_params.get(param).hidden && !params.show_hidden_params) { - num_hidden += 1 - continue; - } - def type = '[' + group_params.get(param).type + ']' - def description = group_params.get(param).description - def defaultValue = group_params.get(param).default != null ? " [default: " + group_params.get(param).default.toString() + "]" : '' - def description_default = description + colors.dim + defaultValue + colors.reset - // Wrap long description texts - // Loosely based on https://dzone.com/articles/groovy-plain-text-word-wrap - if (description_default.length() > dec_linewidth){ - List olines = [] - String oline = "" // " " * indent - description_default.split(" ").each() { wrd -> - if ((oline.size() + wrd.size()) <= dec_linewidth) { - oline += wrd + " " - } else { - olines += oline - oline = wrd + " " - } - } - olines += oline - description_default = olines.join("\n" + " " * desc_indent) - } - group_output += " --" + param.padRight(max_chars) + colors.dim + type.padRight(10) + colors.reset + description_default + '\n' - num_params += 1 - } - group_output += '\n' - if (num_params > 0){ - output += group_output - } - } - if (num_hidden > 0){ - output += colors.dim + "!! Hiding $num_hidden params, use --show_hidden_params to show them !!\n" + colors.reset - } - output += NfcoreTemplate.dashedLine(params.monochrome_logs) - return output - } - - // - // Groovy Map summarising parameters/workflow options used by the pipeline - // - public static LinkedHashMap paramsSummaryMap(workflow, params, schema_filename='nextflow_schema.json') { - // Get a selection of core Nextflow workflow options - def Map workflow_summary = [:] - if (workflow.revision) { - workflow_summary['revision'] = workflow.revision - } - workflow_summary['runName'] = workflow.runName - if (workflow.containerEngine) { - workflow_summary['containerEngine'] = workflow.containerEngine - } - if (workflow.container) { - workflow_summary['container'] = workflow.container - } - workflow_summary['launchDir'] = workflow.launchDir - workflow_summary['workDir'] = workflow.workDir - workflow_summary['projectDir'] = workflow.projectDir - workflow_summary['userName'] = workflow.userName - workflow_summary['profile'] = workflow.profile - workflow_summary['configFiles'] = workflow.configFiles.join(', ') - - // Get pipeline parameters defined in JSON Schema - def Map params_summary = [:] - def params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) - for (group in params_map.keySet()) { - def sub_params = new LinkedHashMap() - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (params.containsKey(param)) { - def params_value = params.get(param) - def schema_value = group_params.get(param).default - def param_type = group_params.get(param).type - if (schema_value != null) { - if (param_type == 'string') { - if (schema_value.contains('$projectDir') || schema_value.contains('${projectDir}')) { - def sub_string = schema_value.replace('\$projectDir', '') - sub_string = sub_string.replace('\${projectDir}', '') - if (params_value.contains(sub_string)) { - schema_value = params_value - } - } - if (schema_value.contains('$params.outdir') || schema_value.contains('${params.outdir}')) { - def sub_string = schema_value.replace('\$params.outdir', '') - sub_string = sub_string.replace('\${params.outdir}', '') - if ("${params.outdir}${sub_string}" == params_value) { - schema_value = params_value - } - } - } - } - - // We have a default in the schema, and this isn't it - if (schema_value != null && params_value != schema_value) { - sub_params.put(param, params_value) - } - // No default in the schema, and this isn't empty - else if (schema_value == null && params_value != "" && params_value != null && params_value != false) { - sub_params.put(param, params_value) - } - } - } - params_summary.put(group, sub_params) - } - return [ 'Core Nextflow options' : workflow_summary ] << params_summary - } - - // - // Beautify parameters for summary and return as string - // - public static String paramsSummaryLog(workflow, params) { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - String output = '' - def params_map = paramsSummaryMap(workflow, params) - def max_chars = paramsMaxChars(params_map) - for (group in params_map.keySet()) { - def group_params = params_map.get(group) // This gets the parameters of that particular group - if (group_params) { - output += colors.bold + group + colors.reset + '\n' - for (param in group_params.keySet()) { - output += " " + colors.blue + param.padRight(max_chars) + ": " + colors.green + group_params.get(param) + colors.reset + '\n' - } - output += '\n' - } - } - output += "!! Only displaying parameters that differ from the pipeline defaults !!\n" - output += NfcoreTemplate.dashedLine(params.monochrome_logs) - return output - } - - // - // Loop over nested exceptions and print the causingException - // - private static void printExceptions(ex_json, params_json, log, enums, limit=5) { - def causingExceptions = ex_json['causingExceptions'] - if (causingExceptions.length() == 0) { - def m = ex_json['message'] =~ /required key \[([^\]]+)\] not found/ - // Missing required param - if (m.matches()) { - log.error "* Missing required parameter: --${m[0][1]}" - } - // Other base-level error - else if (ex_json['pointerToViolation'] == '#') { - log.error "* ${ex_json['message']}" - } - // Error with specific param - else { - def param = ex_json['pointerToViolation'] - ~/^#\// - def param_val = params_json[param].toString() - if (enums.containsKey(param)) { - def error_msg = "* --${param}: '${param_val}' is not a valid choice (Available choices" - if (enums[param].size() > limit) { - log.error "${error_msg} (${limit} of ${enums[param].size()}): ${enums[param][0..limit-1].join(', ')}, ... )" - } else { - log.error "${error_msg}: ${enums[param].join(', ')})" - } - } else { - log.error "* --${param}: ${ex_json['message']} (${param_val})" - } - } - } - for (ex in causingExceptions) { - printExceptions(ex, params_json, log, enums) - } - } - - // - // Remove an element from a JSONArray - // - private static JSONArray removeElement(json_array, element) { - def list = [] - int len = json_array.length() - for (int i=0;i - if(raw_schema.keySet().contains('definitions')){ - raw_schema.definitions.each { definition -> - for (key in definition.keySet()){ - if (definition[key].get("properties").keySet().contains(ignore_param)){ - // Remove the param to ignore - definition[key].get("properties").remove(ignore_param) - // If the param was required, change this - if (definition[key].has("required")) { - def cleaned_required = removeElement(definition[key].required, ignore_param) - definition[key].put("required", cleaned_required) - } - } - } - } - } - if(raw_schema.keySet().contains('properties') && raw_schema.get('properties').keySet().contains(ignore_param)) { - raw_schema.get("properties").remove(ignore_param) - } - if(raw_schema.keySet().contains('required') && raw_schema.required.contains(ignore_param)) { - def cleaned_required = removeElement(raw_schema.required, ignore_param) - raw_schema.put("required", cleaned_required) - } - } - return raw_schema - } - - // - // Clean and check parameters relative to Nextflow native classes - // - private static Map cleanParameters(params) { - def new_params = params.getClass().newInstance(params) - for (p in params) { - // remove anything evaluating to false - if (!p['value']) { - new_params.remove(p.key) - } - // Cast MemoryUnit to String - if (p['value'].getClass() == nextflow.util.MemoryUnit) { - new_params.replace(p.key, p['value'].toString()) - } - // Cast Duration to String - if (p['value'].getClass() == nextflow.util.Duration) { - new_params.replace(p.key, p['value'].toString().replaceFirst(/d(?!\S)/, "day")) - } - // Cast LinkedHashMap to String - if (p['value'].getClass() == LinkedHashMap) { - new_params.replace(p.key, p['value'].toString()) - } - } - return new_params - } - - // - // This function tries to read a JSON params file - // - private static LinkedHashMap paramsLoad(String json_schema) { - def params_map = new LinkedHashMap() - try { - params_map = paramsRead(json_schema) - } catch (Exception e) { - println "Could not read parameters settings from JSON. $e" - params_map = new LinkedHashMap() - } - return params_map - } - - // - // Method to actually read in JSON file using Groovy. - // Group (as Key), values are all parameters - // - Parameter1 as Key, Description as Value - // - Parameter2 as Key, Description as Value - // .... - // Group - // - - private static LinkedHashMap paramsRead(String json_schema) throws Exception { - def json = new File(json_schema).text - def Map schema_definitions = (Map) new JsonSlurper().parseText(json).get('definitions') - def Map schema_properties = (Map) new JsonSlurper().parseText(json).get('properties') - /* Tree looks like this in nf-core schema - * definitions <- this is what the first get('definitions') gets us - group 1 - title - description - properties - parameter 1 - type - description - parameter 2 - type - description - group 2 - title - description - properties - parameter 1 - type - description - * properties <- parameters can also be ungrouped, outside of definitions - parameter 1 - type - description - */ - - // Grouped params - def params_map = new LinkedHashMap() - schema_definitions.each { key, val -> - def Map group = schema_definitions."$key".properties // Gets the property object of the group - def title = schema_definitions."$key".title - def sub_params = new LinkedHashMap() - group.each { innerkey, value -> - sub_params.put(innerkey, value) - } - params_map.put(title, sub_params) - } - - // Ungrouped params - def ungrouped_params = new LinkedHashMap() - schema_properties.each { innerkey, value -> - ungrouped_params.put(innerkey, value) - } - params_map.put("Other parameters", ungrouped_params) - - return params_map - } - - // - // Get maximum number of characters across all parameter names - // - private static Integer paramsMaxChars(params_map) { - Integer max_chars = 0 - for (group in params_map.keySet()) { - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (param.size() > max_chars) { - max_chars = param.size() - } - } - } - return max_chars - } -} diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy deleted file mode 100755 index 27feb009..00000000 --- a/lib/NfcoreTemplate.groovy +++ /dev/null @@ -1,313 +0,0 @@ -// -// This file holds several functions used within the nf-core pipeline template. -// - -import org.yaml.snakeyaml.Yaml - -class NfcoreTemplate { - - // - // Check AWS Batch related parameters have been specified correctly - // - public static void awsBatch(workflow, params) { - if (workflow.profile.contains('awsbatch')) { - // Check params.awsqueue and params.awsregion have been set if running on AWSBatch - assert (params.awsqueue && params.awsregion) : "Specify correct --awsqueue and --awsregion parameters on AWSBatch!" - // Check outdir paths to be S3 buckets if running on AWSBatch - assert params.outdir.startsWith('s3:') : "Outdir not on S3 - specify S3 Bucket to run on AWSBatch!" - } - } - - // - // Warn if a -profile or Nextflow config has not been provided to run the pipeline - // - public static void checkConfigProvided(workflow, log) { - if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { - log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + - "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + - " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + - " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + - " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + - "Please refer to the quick start section and usage docs for the pipeline.\n " - } - } - - // - // Construct and send completion email - // - public static void email(workflow, params, summary_params, projectDir, log, multiqc_report=[]) { - - // Set up the e-mail variables - def subject = "[$workflow.manifest.name] Successful: $workflow.runName" - if (!workflow.success) { - subject = "[$workflow.manifest.name] FAILED: $workflow.runName" - } - - def summary = [:] - for (group in summary_params.keySet()) { - summary << summary_params[group] - } - - def misc_fields = [:] - misc_fields['Date Started'] = workflow.start - misc_fields['Date Completed'] = workflow.complete - misc_fields['Pipeline script file path'] = workflow.scriptFile - misc_fields['Pipeline script hash ID'] = workflow.scriptId - if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository - if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId - if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision - misc_fields['Nextflow Version'] = workflow.nextflow.version - misc_fields['Nextflow Build'] = workflow.nextflow.build - misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp - - def email_fields = [:] - email_fields['version'] = workflow.manifest.version - email_fields['runName'] = workflow.runName - email_fields['success'] = workflow.success - email_fields['dateComplete'] = workflow.complete - email_fields['duration'] = workflow.duration - email_fields['exitStatus'] = workflow.exitStatus - email_fields['errorMessage'] = (workflow.errorMessage ?: 'None') - email_fields['errorReport'] = (workflow.errorReport ?: 'None') - email_fields['commandLine'] = workflow.commandLine - email_fields['projectDir'] = workflow.projectDir - email_fields['summary'] = summary << misc_fields - - // On success try attach the multiqc report - def mqc_report = null - try { - if (workflow.success) { - mqc_report = multiqc_report.getVal() - if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { - if (mqc_report.size() > 1) { - log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" - } - mqc_report = mqc_report[0] - } - } - } catch (all) { - if (multiqc_report) { - log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" - } - } - - // Check if we are only sending emails on failure - def email_address = params.email - if (!params.email && params.email_on_fail && !workflow.success) { - email_address = params.email_on_fail - } - - // Render the TXT template - def engine = new groovy.text.GStringTemplateEngine() - def tf = new File("$projectDir/assets/email_template.txt") - def txt_template = engine.createTemplate(tf).make(email_fields) - def email_txt = txt_template.toString() - - // Render the HTML template - def hf = new File("$projectDir/assets/email_template.html") - def html_template = engine.createTemplate(hf).make(email_fields) - def email_html = html_template.toString() - - // Render the sendmail template - def max_multiqc_email_size = params.max_multiqc_email_size as nextflow.util.MemoryUnit - def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] - def sf = new File("$projectDir/assets/sendmail_template.txt") - def sendmail_template = engine.createTemplate(sf).make(smail_fields) - def sendmail_html = sendmail_template.toString() - - // Send the HTML e-mail - Map colors = logColours(params.monochrome_logs) - if (email_address) { - try { - if (params.plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } - // Try to send HTML e-mail using sendmail - [ 'sendmail', '-t' ].execute() << sendmail_html - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" - } catch (all) { - // Catch failures and try with plaintext - def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] - if ( mqc_report.size() <= max_multiqc_email_size.toBytes() ) { - mail_cmd += [ '-A', mqc_report ] - } - mail_cmd.execute() << email_html - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" - } - } - - // Write summary e-mail HTML to a file - def output_d = new File("${params.outdir}/pipeline_info/") - if (!output_d.exists()) { - output_d.mkdirs() - } - def output_hf = new File(output_d, "pipeline_report.html") - output_hf.withWriter { w -> w << email_html } - def output_tf = new File(output_d, "pipeline_report.txt") - output_tf.withWriter { w -> w << email_txt } - } - - // - // Construct and send adaptive card - // https://adaptivecards.io - // - public static void adaptivecard(workflow, params, summary_params, projectDir, log) { - def hook_url = params.hook_url - - def summary = [:] - for (group in summary_params.keySet()) { - summary << summary_params[group] - } - - def misc_fields = [:] - misc_fields['start'] = workflow.start - misc_fields['complete'] = workflow.complete - misc_fields['scriptfile'] = workflow.scriptFile - misc_fields['scriptid'] = workflow.scriptId - if (workflow.repository) misc_fields['repository'] = workflow.repository - if (workflow.commitId) misc_fields['commitid'] = workflow.commitId - if (workflow.revision) misc_fields['revision'] = workflow.revision - misc_fields['nxf_version'] = workflow.nextflow.version - misc_fields['nxf_build'] = workflow.nextflow.build - misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp - - def msg_fields = [:] - msg_fields['version'] = workflow.manifest.version - msg_fields['runName'] = workflow.runName - msg_fields['success'] = workflow.success - msg_fields['dateComplete'] = workflow.complete - msg_fields['duration'] = workflow.duration - msg_fields['exitStatus'] = workflow.exitStatus - msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') - msg_fields['errorReport'] = (workflow.errorReport ?: 'None') - msg_fields['commandLine'] = workflow.commandLine - msg_fields['projectDir'] = workflow.projectDir - msg_fields['summary'] = summary << misc_fields - - // Render the JSON template - def engine = new groovy.text.GStringTemplateEngine() - def hf = new File("$projectDir/assets/adaptivecard.json") - def json_template = engine.createTemplate(hf).make(msg_fields) - def json_message = json_template.toString() - - // POST - def post = new URL(hook_url).openConnection(); - post.setRequestMethod("POST") - post.setDoOutput(true) - post.setRequestProperty("Content-Type", "application/json") - post.getOutputStream().write(json_message.getBytes("UTF-8")); - def postRC = post.getResponseCode(); - if (! postRC.equals(200)) { - log.warn(post.getErrorStream().getText()); - } - } - - // - // Print pipeline summary on completion - // - public static void summary(workflow, params, log) { - Map colors = logColours(params.monochrome_logs) - if (workflow.success) { - if (workflow.stats.ignoredCount == 0) { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" - } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" - } - } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" - } - } - - // - // ANSII Colours used for terminal logging - // - public static Map logColours(Boolean monochrome_logs) { - Map colorcodes = [:] - - // Reset / Meta - colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" - colorcodes['bold'] = monochrome_logs ? '' : "\033[1m" - colorcodes['dim'] = monochrome_logs ? '' : "\033[2m" - colorcodes['underlined'] = monochrome_logs ? '' : "\033[4m" - colorcodes['blink'] = monochrome_logs ? '' : "\033[5m" - colorcodes['reverse'] = monochrome_logs ? '' : "\033[7m" - colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" - - // Regular Colors - colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" - colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" - colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" - colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" - colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" - colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" - colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" - colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" - - // Bold - colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" - colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" - colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" - colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" - colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" - colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" - colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" - colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" - - // Underline - colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" - colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" - colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" - colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" - colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" - colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" - colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" - colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" - - // High Intensity - colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" - colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" - colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" - colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" - colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" - colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" - colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" - colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" - - // Bold High Intensity - colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" - colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" - colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" - colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" - colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" - colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" - colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" - colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" - - return colorcodes - } - - // - // Does what is says on the tin - // - public static String dashedLine(monochrome_logs) { - Map colors = logColours(monochrome_logs) - return "-${colors.dim}----------------------------------------------------${colors.reset}-" - } - - // - // nf-core logo - // - public static String logo(workflow, monochrome_logs) { - Map colors = logColours(monochrome_logs) - String.format( - """\n - ${dashedLine(monochrome_logs)} - ${colors.green},--.${colors.black}/${colors.green},-.${colors.reset} - ${colors.blue} ___ __ __ __ ___ ${colors.green}/,-._.--~\'${colors.reset} - ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} - ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} - ${colors.green}`._,._,\'${colors.reset} - ${colors.purple} ${workflow.manifest.name} v${workflow.manifest.version}${colors.reset} - ${dashedLine(monochrome_logs)} - """.stripIndent() - ) - } -} diff --git a/lib/Utils.groovy b/lib/Utils.groovy deleted file mode 100644 index 8d030f4e..00000000 --- a/lib/Utils.groovy +++ /dev/null @@ -1,47 +0,0 @@ -// -// This file holds several Groovy functions that could be useful for any Nextflow pipeline -// - -import org.yaml.snakeyaml.Yaml - -class Utils { - - // - // When running with -profile conda, warn if channels have not been set-up appropriately - // - public static void checkCondaChannels(log) { - Yaml parser = new Yaml() - def channels = [] - try { - def config = parser.load("conda config --show channels".execute().text) - channels = config.channels - } catch(NullPointerException | IOException e) { - log.warn "Could not verify conda channel configuration." - return - } - - // Check that all channels are present - // This channel list is ordered by required channel priority. - def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] - def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean - - // Check that they are in the right order - def channel_priority_violation = false - def n = required_channels_in_order.size() - for (int i = 0; i < n - 1; i++) { - channel_priority_violation |= !(channels.indexOf(required_channels_in_order[i]) < channels.indexOf(required_channels_in_order[i+1])) - } - - if (channels_missing | channel_priority_violation) { - log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " There is a problem with your Conda configuration!\n\n" + - " You will need to set-up the conda-forge and bioconda channels correctly.\n" + - " Please refer to https://bioconda.github.io/\n" + - " The observed channel order is \n" + - " ${channels}\n" + - " but the following channel order is required:\n" + - " ${required_channels_in_order}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - } - } -} diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy deleted file mode 100755 index 07f95372..00000000 --- a/lib/WorkflowMain.groovy +++ /dev/null @@ -1,93 +0,0 @@ -// -// This file holds several functions specific to the main.nf workflow in the nf-core/oncoanalyser pipeline -// - -class WorkflowMain { - - // - // Citation string for pipeline - // - public static String citation(workflow) { - return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + - // TODO nf-core: Add Zenodo DOI for pipeline after first release - //"* The pipeline\n" + - //" https://doi.org/10.5281/zenodo.XXXXXXX\n\n" + - "* The nf-core framework\n" + - " https://doi.org/10.1038/s41587-020-0439-x\n\n" + - "* Software dependencies\n" + - " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" - } - - // - // Print help to screen if required - // - public static String help(workflow, params, log) { - def command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh37 -profile docker" - def help_string = '' - help_string += NfcoreTemplate.logo(workflow, params.monochrome_logs) - help_string += NfcoreSchema.paramsHelp(workflow, params, command) - help_string += '\n' + citation(workflow) + '\n' - help_string += NfcoreTemplate.dashedLine(params.monochrome_logs) - return help_string - } - - // - // Print parameter summary log to screen - // - public static String paramsSummaryLog(workflow, params, log) { - def summary_log = '' - summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) - summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) - summary_log += '\n' + citation(workflow) + '\n' - summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) - return summary_log - } - - // - // Validate parameters and print summary to screen - // - public static void initialise(workflow, params, log) { - // Print help to screen if required - if (params.help) { - log.info help(workflow, params, log) - System.exit(0) - } - - // Validate workflow parameters via the JSON schema - if (params.validate_params) { - NfcoreSchema.validateParameters(workflow, params, log) - } - - // Print parameter summary log to screen - - log.info paramsSummaryLog(workflow, params, log) - - // Check that a -profile or Nextflow config has been provided to run the pipeline - NfcoreTemplate.checkConfigProvided(workflow, log) - - // Check that conda channels are set-up correctly - if (params.enable_conda) { - Utils.checkCondaChannels(log) - } - - // Check AWS batch settings - NfcoreTemplate.awsBatch(workflow, params) - - // Check input has been provided - if (!params.input) { - log.error "Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'" - System.exit(1) - } - } - // - // 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)) { - return params.genomes[ params.genome ][ attribute ] - } - } - return null - } -} diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy deleted file mode 100755 index ae6958ad..00000000 --- a/lib/WorkflowOncoanalyser.groovy +++ /dev/null @@ -1,77 +0,0 @@ -// -// This file holds several functions specific to the workflow/oncoanalyser.nf in the nf-core/oncoanalyser pipeline -// - -import groovy.text.SimpleTemplateEngine - -class WorkflowOncoanalyser { - - // - // Check and validate parameters - // - public static void initialise(params, log) { - genomeExistsError(params, log) - - - if (!params.fasta) { - log.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." - System.exit(1) - } - } - - // - // Get workflow summary for MultiQC - // - public static String paramsSummaryMultiqc(workflow, summary) { - String summary_section = '' - for (group in summary.keySet()) { - def group_params = summary.get(group) // This gets the parameters of that particular group - if (group_params) { - summary_section += "

    $group

    \n" - summary_section += "
    \n" - for (param in group_params.keySet()) { - summary_section += "
    $param
    ${group_params.get(param) ?: 'N/A'}
    \n" - } - summary_section += "
    \n" - } - } - - String yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" - yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" - yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" - yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" - yaml_file_text += "plot_type: 'html'\n" - yaml_file_text += "data: |\n" - yaml_file_text += "${summary_section}" - return yaml_file_text - } - - public static String methodsDescriptionText(run_workflow, mqc_methods_yaml) { - // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file - def meta = [:] - meta.workflow = run_workflow.toMap() - meta["manifest_map"] = run_workflow.manifest.toMap() - - meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" - meta["nodoi_text"] = meta.manifest_map.doi ? "": "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " - - def methods_text = mqc_methods_yaml.text - - def engine = new SimpleTemplateEngine() - def description_html = engine.createTemplate(methods_text).make(meta) - - return description_html - }// - // Exit pipeline if incorrect --genome key provided - // - private static void genomeExistsError(params, log) { - if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + - " Currently, the available genome keys are:\n" + - " ${params.genomes.keySet().join(", ")}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) - } - } -} diff --git a/lib/nfcore_external_java_deps.jar b/lib/nfcore_external_java_deps.jar deleted file mode 100644 index 805c8bb5e4fd43a12a5891eea5a68788309629b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2291171 zcma%i1CS<7mu}m(-Ea4_?dhK8v~AnAZQHhO+qP}n-E-&Lf8*Yb{bM(7MpZ;s){{|L znGpxiIY(9k6buar3JMCSNkdW|=)W{*ATS^)VMTsgF=-L{?{Od?P#{?eNT`1hApZ%I z{U0Zz{YCuW$x{5%Vj{u{igZ#U4^op8k`lCZbMO+hRMV3)4e|_&%)3YSbmCGpVp4NX zni_mKLGakt&P12{r^KCD0GPa9sIuy`fu+agt?8O-hY9i{WloGe}y@kSsDEY_Fud9 z-?2ab4J)MQXe4E3Xl-U<>PRMQZ)0m@@90KnV5#Te5Tz`pvZ0Lj4F<9%Flh(`Qb;Tn zMV!iFmH{S^fF*j#MCKRUd`7m>9||*;WE32I_6pg4-Q1C#ke$$aVmP-TtfJ+j+N9;Q z>bxN=bCVQkg$Jzty71(+~A9}ZfANuYIVnTdW!??Sj)Ti-Qpk8XgPDab8pk2QD&dwUl=iFhd1c$C2uMVagr zWc@z9s$#g__{3?VGb#)^fSNp^lZh zU>MI!D?+L)nyth{@@L0+B&_M8iR08L)G6#PZQLFmvz-9DlZkwRWigRIyI4xYr7>tRJ-N6MlBB`nJQ!!8D)mI2lB3PP;dC{<{Td>^ zq-9=xI?w%(ymHP(ee81dqv8mVjmJ9X5dUGLNl_$iKa~e6d^-(kDz##CYpXfc12;@+QK?UcF zB)4A?5B@+?^*bxGA~SA*{F$-y<^vkuR_K(v+0yJV;;I1+(I{|yv(%PamO{(pQ-8Zh zoQtO8-gq^}232Yr_CUQQ{TAB_@`_`?^Q|U+^+mgRrQ&V7__WsMbG(PUAoI_hPE+(t zmM(|xn5!hS==(ghO#i%HFbMR_!330LbRj+QTC~I4WH60B%2WTxOD}DAnGemzqN~i} zU2L9;*-JaL%pp#2a7)V7K@JTKnC7>O4T8>sT@(O%XT-~Dd+DxMGjH!ta6%@}!CS@w zidG6;+nYh@?b@nLV{XM@*)>I!;<7b6!Ko8guGP1#cl2paXYwQ$OV+E+{O<$h=if0N zx%P$AS>BQ~i8v~~clSni>}f5T*xvN$Xys6@(WWX(TDyD zYR@)4fVrPn+Yb4&;&lCdmk=NIhxnJID5!8FXIrKX0!4SS1hK&2Xm8~OOB2s9%m=$ zrN0s1XA#X2-jzcR9`ooNtjt;5o##%_vPnb&D;o}LP6#_r*^%-G5alrO-9q1M#>jO; zYe7kfzMhFprkIcsD5mEcFVXAs};!w`H0f#lf9c8QtajeByU9#}HJ8 ztalrDLmq(57L^n-py_w>Wuo%>Xm5~H zZS#|}G(ZPapy`)LtYMLM9ETFRT_$P6IJEfW9?`vr04c;0#w6cLkR7gO@3cuk<2OYSEj^5@!$$&(I!4j znUqG6Gfw;>c_6RlKDp9J98)|T?Ev+kV8~RnED(I-_w|+Tdqh{z>^u|nHs{2_Iul1{ zr)STd>$L~`sGL798-ze~d)9a+xBPI>o|IF+?FMh_SisGW4-P-bqN!h5{AUVH_`5Ze ziYcYUAUx@&Sk0;>97sV({q4cfgOOD@05vK>2kFgD8h~-ITO#LccZm zKL0$P#XRdY>Q=*ED_Tx;sO%$R505uDRPD4_XueG1=ebm4U_ne-6ql~RRR9Q(8u}O* zY}AWgg7!4aaTi5Zuov^SP~irQ7EmOjvZVGZ@20ri@;CY)!mt4fXGk((9{N!LZ=ft< z{yu8|6*9*(Zi1o-1}7*C7~)+9U_@hXJ1F#V6=JA0#dM~qJ9Vomy7dmkqaRVIvC!e& z2e(>(7HL%n(YL=Z&C5M=d?uc_TAH7fW*Dok`nyZ^(ww?1ZSLABGiygSk;y22iF7k} zd7yvyZkk=bs++czhFht4E?IMEI3Cn*fsNUnTHd7tO#8IxL(xDfsE#6}jWh)plA#=Mn zeMM1%zxX(&hIgAZU;U*%U60c(lD^k}N478#-9?QTGmc^J6nF^D*7d3{LgJ(%ElO`||K98__buh{w|X+Q71ppSPDL9E3%^M2~^5D=qu zfzYFb5XU3uS_|WX#3^k3kHQ$f-+yF?2XhRWM;wGf~f1w5c@e_}W z$n{l0VW%4(9&VC=hlUn0h=O$i%}O+*0=-%kBAg0B+!e%@flNd*aK!jZID5%*Fh2e| zc!KZ6Zf8TV!ed+n&9f1rN%DE&L50&QVOO-<4IV$KPLAo<`ub^7i}EI*ICln*Wq$Zv z6qzmRHCR=k6jM48|;Q;-N30avb2m?il~VS2Y*veS`Gp$_BwPa))a+0s51 z+(!>yEWpClDao8Sd=S&~6LcE*FmaIQNUnd@E|}P7-+Hjb&*LY|kSe{pj4M-{Y&U~~ zD_8P@Z=O_;%By}#xe`y(u)$mk@?Moj-b&`hwsgSV#062yGb#OVShdfV54U=__`3RgAt7B)wt zAgVaVr2BV`*{`Jq46G!Yv^6v?veY#O&6o0}0_gHgtG;z-=5oGZA72p{4`TKoyqVjk zj6qKv9ge@Y-;TX67<2>>uP$&o)|YLg*NQKzI6Fz`s1W zx@(9%n+f9%$j(6#VLARZ6W!Y|DU86bxYSfv$K={d9{G<%p74_{u! zvL^3GmpN)!z2sY!u)_TY1p;kOLK_P-d4I(xz--V#YuOoZk8HxaociKq4p>n+0^ni-}eVA_bfG%lL zY~#xDQqkVjI$i!FpMPfEq<-Abh?q)AcI<*t#=^vJd0ZhpMSgQem~uTeH(;R*dm9hx zcx6JMZd0f@v#~Tyf%(Tunlz_#y;C$K>DeTgSj@`8bK%jt7(6$Orn-Nbtvy8=wzBPM zXHqhT&Q3%FO+ms%vjeA0_2QIk8N#uB8<0~FIL;flKA z_&F>@_%8K{@x`@`;;W7S0N5V(4_n}{-skc*(U)!AG4Q(vTUh2gD2#Vj{^T1;6RPB~ zK2>G0L%p#zSR5?5HN$U_`~>!4xug3oByMLbWu!J4(GY`xPOVoeafdI}d%O9^v>m$~nd(~ix zu$-iWjo^O!6UQ;EB(IslmG6Mb_s2?{G0n%#an&Sn)i#Pm7EVXRO5hDE#jN{BcFDPt zwrtx*|U$Jo0mg ze&`Nm8RxQ3sivg^?C5j(%?&y+U*wp(4F~(qJnG{@&*$fU&F>|3YG#!x!V$*XhQLn% zPv{k80`^Rn@pWe)66bE+Iy-R>zczUa+64C1SM&o)nhX_KZj?&sirAa+(fcS!;~Ti; zKKefTG5VeolMn2>=@oq9G_`MtC@vP1ZFq6VEkpZUwD$H>0xl8${tna@H@`x*2O|!O zLQ-9^a3XELtLX{JxXLZu(JYt~AZdG`dmD`e%E2n^3;Wn;Fk=xVYD*|6SXl8HZ`8nH z!Gqyp73CqBr#ZV6^Hvr0Kut)gSCLj+ls+FNrXc+f1YSStS9Lts zSJvYOBV3|2aoWW5N|t*Ut%6kJCt2n0o;x4jY_Fx{b?vyN-rTYCEvdb3_RtvP2|EKy z?YW7?7R#!%avu?eF}1PTkJ36^lc53eKEzjgd$42{e|r>1DgN|oHxeR)0T#e>KC#)_ z))xidwn|R)3ZB|%sSizNHHukJGJp%6!Pk~~!rP~V?(gH`mn2?ht%Q;3+o2OeHW^;q!BHF65w=6dAabyZrx8tck|O;m}d8?D@pmKHrVmhZ&Zbd{0IzqmRp z?FLs?)iJy4Gcy$Rj2j0+P4W2Fzc%svuywq0bOP;b;Llg;T>Ky9BHv-Ey1O8PTZ9v} zg9yAq_hwn!;&gR%)}c6JbqBRp%f)1}Xro`mk#5Y9JCXOZh_i|AE@t_(5N(ruop<`P z=WtgwmSRVE>07@J%XtOjN4)xoD3TGE4a|9bAWl3XbL6UkGn4Ny_g^~@q*iP7*`aae zEJasQhJu5t-b?pM!(*tr4UwaGFx>{L4L-)Pw}x6kIF2UPcwXxBJvhSAF|2GXz`fnOs%E|E`L+T%*O7Snd^)FqXqzdh+c+|va zaxHmnXpc%{NK6)6OTiqMJ4yl!77qli#sICG3m$R^z|Nd3Y^ZI`ZC1BxQnF|QuK=NH z-Syum3q`j=SKsJvUtaHiZ*N^Ha&o(Q({A#*$-LQCvp<=J@1;NS-g%q;L$l*P-FaI> zkptn|aHod-y#WrDGjYo&{i=ic*MYwF*$bq9`;fu>g#Dfg@)gx;w3D#U!^fvvh0bAq z^M@Y08l(X*p_W9heL69Y+2#4SZH^l-1&^&-&a*{}@m}E58~8;A(NTuXWT^`2&=@oM ziG{%eU~6ni667(H_s9SVX^G5bx=canDfM+_beX{mYOW#((_~mqCU!0HV(6$XurRX& zq2?l)LtAT-=B|zDW0siHeGOTz(Xc1`ZI*i3uqOu~m~?{=s*cDB>VSwe8om0&u{X(N zMzv`}@B}WvlO#@RrD1*em^mOyGCj3YZ+@~cNQ^px4PdcW0&8eF<0o~=s}I@0t<{RK z!fa-Q$!^PnX`FDPMN=Oq%*OZ@j@mO0l9AOKWb#Bp;cm2f4#MaB;EITvBu1aWEArAY z8}h|uop7g5@vemwb)Wo>pC-|yK zXQIQm^?KZXa)5SKWDlda>fiAql(UoW?(!`i3lj^z-7V5kP^FZbM!9 z-iDT4B0w}RG?%Gi!yuftBeSKcvS3}p2Saqm9g>7v3&Cdvo2W&20qYq4sFF2Wau2k> z5CepXDKCf~JdXpu6&2Z{ip}iPL;02T%nz+JTFSPN`}j5j`O@ps=NKU_s>emH2wjYa zxeM0PviWCoJuP!^81c&P8wd1w6b#GCi-c3a>UA>Y;63khinCY66t>%^@5LBoUU;cS+CCQ-O(U8o7aon1wBQ<2E-JG zBWs(3aTTBTwe&Uf{9I!o9$abt{X~52?6~Ty*uz}TU2&96Temx?qbH+W zzPhsK0KJ>0f0<)Z;RFt8;K&$tgD2TJZy};{CRaUw zc1MvjT~-*}33WY3(4iPQUj;!jhg2m9YT)38z2Sbr0vIZP8cNmD*~brCn#LC0!gb?@ z%OLKcX#1?rPHb9%XbhUUmZ^4{{&jv%1xlKne9U0<{8kF2|3 zgI-z(cuH=)NmAQ6w#+)+)B6P$Zh${0x$2WT@IBV;i zC`ZO!|MgM@PG}$w#yy_8xf~rho|MHqO6gLNQfeF5*uGY0IM!b;auiF+mRkgE71V{Y z71U+CRiaN~_k+gScWg`Ynm;x6%xd>eP!eI>wah;{rCT#!v(OlS1%}` z{R{uK_uy8K-3x=upXsfbwhttyJ3ZIbXSLuJnmSyalG{6EPsL$U7~bF*YFD%zS%zRi z7=!~x@a1K}CXy=@@g3h+wC_}F4y$_OJO7_jXJ3^tI;x>T1pxtlvO+}( z><^FEB-`&4Xs!tXpQH(VjBm^dGJDL}Ie8=8Z5ijUSS=8w_;%dK8P#zzTD=!GP(l8l zK~SnejNEIyFSKS?l)#+dbj9a{h3waXKSj5CpU0z@HZ;D(bu=1TI(St;puFn@J zMdk0mNFI>g^-1{$vU59TG+ng@PfC8Xx7ZlUv;KjDsZ1nxZ|DjLpz1*|NgIyeyC>1b zE|S9-m=={az$Q!=vP#-Yk+lDjVm*#kpIy)~$l5kf2p8Na9)c9UyHv*8Q=3T9UeWcf ztz~KH9~V0&Rg2SH0bGSMt8lg;)0Qz`ou%zuFVb30ABXq+Tt2}`@1n@Yn)WNwjs3(6 z%q;Akw447Aou7rFrrP>9L0usBg7;6@mBdl6yGD;WZ1e|Gh&Ee1;oh+k5$49*NVup_ zGks&Ct-7$R1`#F5jDRie9^o_c$gnqhLh>216S0Qwt!eH6R3jRUsNhKQF>G_0pp|06 zghjn|7WXZE`FWg2!y8d$PBl<>;e*w@B)Vq;xiF6RrglMsP!%+L4(%U?@TVu_H8ZMA zkK_(tLTR~5AW~*B;w_<>^zVzXwDfi~9ZODGPM_4ij0DU?DnMSEeD~n|M{fN0jwR+Y zA3v$C0yV6p#W)n%#yN8bDj+jISp&E@yKR3nG3Q3u6zp9`{aMwwYsiO$-%0&;BH0QfzKd(?luOaL0u2UPYe&-IhuEn z*T6?a$1`v=NQa265~3FlQLVRUV%tpJN)M>|_+6e|LbU?jkgLV*ABmp~1t^@tVGE^) z=JNLNO*Q1?9=h~z6XL~lDM^Q|A;jDe)q10h?cUUz)h#|kIuJW~9t=Ufc+Slu_@Lwv zZ6c?<`HB|ggL1a`huYh5fu$0suCbfkG=nc^`wC81YSuGIk&NSr0RiS<$vZXxzGX_E z_(K`!H&AFdF-ghf4o|3I>?0kLx0ImIt@clr`&nt7H7)ODq(fX_8~MpU#6T~pAj7!8 zgebeDz^y8flVm=wgGbN1%(4t%K@f0L+HCo~c#>Fi`LSEs=fspuAmPNY6i~f+Xr%GR zh3;74QjxBsqD{S+?E_BehH-01le7ndR8KsB3x0@wI|bE! z$)K*e8eH*^?mN;X#~$4VEE54p#|bp0lZUh)ja78_xh>L05z`V&uoo0YAF23Og7%YHkz>YzzRJ6a z0wO|RHe*qKaARWmm%6h5M02=+HhfVt0Ox1+?5fnma7Hbl+K$mngJ%h{&%1EF;OdQ> zy789f>-q<2f5td_!j%BiJa}7kl%XMNWQ$d>STn7xQ3sUqMkm=D+NUaetN0Gm0?+MKf@9mY7{GRYU1}B75W!d6sezW0$r_k@ zUUar>J7l;c{8M`{Iso@b`TmHFve_>EE+LYaMfKIz*K_yxLrF4kW#jE0!`m&=+bxt` z&cx{e6)a(N9HI=$iJJtWvc~JJ!u=lS{T`W}jPYaMTz?4WSV&5!!}xp%0G81EH}7Y* z=PRh4Px4#{D+X_;1aIf>%p4OTc8y#<;>VIfH)7KEA&@WdydJV?dYS{9DZHLTppHcF zq4p2<@|4P(MWPb~T2}FI9^@LF_k%Fi%Q~>mH-WJrG#J@=-{3JMS#yEo;AQ ziBpHLhkPS2d< z+8~nMjL)S=Ud!6sJ^lMWnamZYeEP;;zoEObIC|m)y0b;4k56Yr zNc`>Jtyy07MDF(he$gjFdhUsa@5|wtqYpHe>!3^7Cb|nG9${ZtMGA>jX!Q1p9H&9r ziAwQKDEH#^uR%qZW?`dw-RUe$2?|zc2)3dw{v=!AZ}YsVG*=iqJ(a7sVA7X-PC`sxlZRB?0?;`pn(-cyf+j8E` zl$pruwK4&ng&%-{B_{wJ}A!OK>@33^|`sp5sVlyfyg9Su$}d5AZoY^?ZLoDOJ8ty%2nQ?lkec ziNxZHq->MWAN{a$W`4W9k7V-lKCmT$M=Oa%D%3^y{2SGL94T3i&~A$`bp!u%iuY{t z@-;AYz`KfsVg$4~``inyoE4z-BGg+qti2a(sOT#sxzrhTQ9GYdEuTwDHWT5`6iU-H z*btxb=N3v+AJ`E25u=!kYGq}%%hR){eO@p3rr}5 zn@E52e`x&hsy(Bumvy7k3EVyI_F2W<`3R!x@iIejhK|@HccI*)G}O zZ%MSv)j?^0LD-M55q0uZ0Z^;9bpeSyNV5qk(;vTE4Iwf6=Rk^rk}EJD=^F8Z z1Y}@>y4gG8i=NDn7WuM`O}1aAJRXd+dhJyW^~ z9s2|yJ%j>7_K=YYf<{gsJQm-(p<)J5NiKZ{$Oy>n0tXYwynpTg0QMH`;Ul?ggqrD% zDSJXinTdCm4rFrG4#eCQ-v9a$mJ|2N8CC*y2W$Q%ADFUhB>#;brlYW91NK@4>rK(m zRR8pH3z`2`09DglLGlUxEg4>e-gkksg8TReX!;h|r+xR#7}OE#6x`SH|C$2#p~&}v zx|Kmr->rrH7Vh~2xXXt97VNo!z4e2lz10EcMazr&{1gpzW_m@305Ko|ONHl5%L)t# zOb`Nw_6v*MSa9xkwsw86cdk6p5Tb#rU(QWKzfdRo3F3ov)j^;Ox)u|+BdK&VF~lhg zd6NrIAzxew8)pL2DH_7SF4M=zYb1MjJC_e765-8bQI&%$5mCMECvwqu)}AYtmua*J zI&0~^`QH7KBtK;0skWxRkB21oTo`tyIa8KiGe0>SisHh>>@=SeXYx#?|I?nS>Q*Rm znND|t--f%MT*0vUlkKKlPm(v!lg0z%lC%P&?9_x~M}f9iJF@57mH*{Lng`s#qY`Vn@X2B4S?P#6bv(v>=(HdrQ5VCq3 z4`!@5GYpH5mH8x7F!M*MbVLU;;pLzvbwd6)_Z>}oD=un5{5{~s+@Y#7GI~xFB%qnG z#>~xi`J|3iXLc--7h8e&YQj?_qHwEBXlbt%VT*jiL~ld*s(BZSEsJ!I(hYF0lhq#T zQy9A*i$Hrwh_lR^-ksEZxZ|fhOeei%(}=1RG`ZVwz+;@Ebj%P?#t_zk`=i z_KT>~#<1Qf%?LUc8_A4lqpZ#n5@w_r&(Rdn_FPm&jWgz$Ynapb+CQ7Pr%yRxYW0g* z^->O{4tP^s(RXr;#Q}T>hcs~m8TuJWeo@*g+$v18Py<>4iam#!C}zHH2sdWF$%G79 z<)${N*+7r^0F)FxqKzSLQO)(@XNCs)0Je!KH5lY6$u{e>Ss{T=>fbIjiGPFs& zdSak}eq!IJ<_c2Oh}a-l^Dlj+%5=#xVmXO^+CHyI(%K*tjlpwKy*jXuUA!<_JqhyW z$fX2TI)<7-&q{v%D9fP1Ps<`O16#W7N`(vLP@%&--9k>bM6AA4<4Q43zRrbA^i`@b z{DEll?j;cJXx?Qg%c{ZUx+St`%vER?lU@Zx)34{1#*CckKgIi?R z#CG&yA8C-xK5RNZ40InFvW3ftEgsPtR8_LWDh!pc9h}=t z?e!JfJiEkQ1sUT`aG@^h>0@g2C+WuN#n~1e5ReD;;}rd!I+KJ@3IuGEw|T$Tr55yA zh5}aPj=Ot#bgSD0;eX#s(-6cjP0HI&$?>=`1v8w$;)1exN9OV}-0rfFlna7H{T_BMvO1vAfEecPG8xd7oN5$xUlLE8nF*_?(>_-Je zYgn(8a#O9;@rx4b^e&cq0?1?yUnZffCzQMJ?4BsvKM6n;zI_O_ebTEzRp7O_(gQm& zz`8pldFU{Ea2%)}{;LOlyzdTDAQ!lh8^o5(r@z&FdwkOif96`$fOFqe-SPqtCFtHz zJ4FUOK!yz!iYqyS0YbcfyTY)G?9Lkzhbg z|HL;T%5O0A9Q6#e4F>v$XObhHIf8w(+9wA|34Me}!wFU5Nl`+-*{X!~hZkyXEhuBe zZOg)nEfV5n9>l&-&bfN1EwR+DME^d`Jh&*(C0FB>yJiM%ZsHb{(IrNy5v1IK=c^%? zovE|(Yc`QNJ;lOl3YlKn+?t(jE%c@cqVA1%>n{rE-SxO82~VC6nhWYG!jPlitrucM z(k@OYp0wLRYKcXShnH%Fo(STru)D_e`=dd(KeC)tq%S6lt9XAUpC7_=xfR4|YWT9p zeoB$~z+&!NY5Kb8LVIAc-b$6o%tyO}CjxHK@n~S!aT#hPN=!fTh#Gwofvk=cRLs#&FEa zteM&s9fD9(PNOTf;ZUNISxVpi80YZy#9)7EQ+Sh5psL~-1MTQoNOOon0VTRs`&|D+?XP_(mempJ6CaX>1ra*x(SAj5JfpBj$#TbLvf$c-nc6B1R zR~zBz83wP-+<0%I?^v)I!cfD{(i^YM{h#OMa7(Mv1k*^XqhYaX`8+LU!SfiNF* zrA;|7xK|x=2NkN$Yfly%W3bh03A4lW#OdyMY`FVYg#H%3-||k|z`Wm1uOjd7G7pU= zx0!~Ac>(WIt;)Zxfc;F?h6<%#(mLEgFhL($ARR;w)JMp`-g%A?I>`7$meszc3>q;L!Z;Jkg9@lUn@t}!qqU=dRRWtI_ z^t<2SjO)S>r82V#xG9wJCv`%(RXpcrxUe)Y1sdO=mBR;=UQyoE3RyAp&lNmMODL8= zhlekB(8y^4DBUga>xG;$a!YG_Hc*_xq0RZmJ!s@Mq-0a_J6BMa4E)>^>JEK~pWNEX0n z@#y@L<6~^%Vsf%3^K~;C08|U+g~B5b6f^F7n+g^)ar@I%00I_|+LyxUm6vB|ACks< zbl;3Rl<>g9;YWnNg zWPg9ZI8vh+<=AWxI0^=nh_T$DfSw$UAfn8oKlveCvV37}WR9_zDqVoYAXrR79SAjf zCT#%jNp0#xez-8J6p{s5Wm2tlzk8rR?cQuFPBg(U+04FNoNE|YQe;+tSq!-WZyVhX zoak4CR6< z{RPood3rUZ=Y$IQTic~vqKLSk=DM!8y{+x(kuTgGkeRsb@Fa?7yKqiXjvk0em8J<6 z8_QeO@Esj1Zllm8Y3#59Vm%JJ8@h;y489(5o6aweZ4m8k?5xvYfb$!d=O@ms%^U&S z9_&0%GCZ7%dx*u|T6UVuf;MjT_hMSF4aoLYmQ%ezZY zU9cWcOzN9CvVQDjO@E5w5`#6y5#Ae+2SeTR+$9of)x?Y&M!G=9qqhMw4>Irb$)Hah z6c#X-iws2zoLY{Z$afovR#X?dy^4~sv~WC_n?km@mMaG?sq;;`)$pzmZZV&2DzlzH zK`xx^2YPP&nCYf9l&3|ru(w(lqpv?^PpTjrXtH)yWhILY>XI7|A&jq0gl>@~fiJ@5 zeu~skx?v~@N2B7)GU7ohkgZDhBeiKw)mNazh_-%ObT4mSynleRXC0`vm;e)JLB<+? zE};Wd#>nN3ad-cFlA|`Y$+S@eAF+Zroa#>5DhhmU>gqc* z=lM^&E(03+Ndnu_8LaH5ArGZ1tZ@^Xvm=I2ZxM~+ibHV}Hp;fXk;SLRaWzQYFqgJDjAbRnrmA^j< z##(@)fOpEE3&vWcB+v`SGgtsr)L6FMuuUZcpV_ zQuA-M1Ne-<`T#t0A%}Jq@qb>lC{&TMUW{5!qquVT7h;xo!3B!d3&T@(tc4@ggXZso z2rZ>IUnfQ9i)Kox&QxvZlrwaJWe|CpgW%Z-5^?coN0#Mmb9BI*3HyyA#~`t#apO~p zv$Gz;QFfxu$W~-Zwvx-B5I;C%>KKfm^sK8H??V#~n)~RwF(2$%qzE6v7(*7W(#MsB z2)Ktb;$x0mze%;QMIsGd_8b>QDS3{gn5Y_jgb=~gN6h+2Jw>k666VlKEQFUB(pK-{ z%&!qAGRntXrerzkXGcVPTADz(DgYDxM=cAn57si6Lu@y%t>Y`oA#-`7=kxP>=2f}l zKP{iYP1~MSaxskCL(L{aTh5_!s+P4hk0Tzbq?H_|^KH}}$AzehGuYX931A{5m?Rc* z3+J_e1iIZRvnWK`XR1^ovH#}ar%4|(I-zr~+jleWNL4b4P&~jV*hYSiHi=iW>gHN~ zbpk}BN_S&4R9Js9 zDH7!}SRZaQS2HGrD7D_RihIJ~RqKoRlI>NqDp_@=@Gc}{p?#XXAL`emip9#JTR)j; zZ12iksZvj7m)2Hm^G6##o1HyYV?*uI!!|?OuAD-U=mjBQ`0JH{qbLrf)#4&e@AIMg zrK~G9%{rj#wC;PLJsS>xEpBrcd9gKtDy$nUB1oHs=#r!Lb7Tts)H}x}iV)q2xEjfI z1({W_7WaM2gRXVGG!nL}U7tWBjtHV5P6OH?zQe468bjIT(-by^kaOSuy(t%JwrOq7 z_)-tolDHQw2KBePrz*IDum_6x$Hsx|@=Ww%3x#g-wz_|ePirIUt!{QzQ$hAxtbOr)X} zNv0z!iU^!9N}m^(ubXp;(&D1>m}I4kDOx_NTW;fN7LTY1pVn^5J`^t;%o=GIBs*7QsWs(c0e;{?ojnxm{k%WspeYR-=;xpj z|1}|qU9f~l%L5YSiiWWppgR)M=NHp&@0p3D(tE<3Ccv%sB49BkuT|V@BB~9oVuWCA zZa)+l74W5JTAlVItKcf+M+uz<3m+DrlbmT=Bxm%``UVd33jWfU*(x!~unaS>RUEM2dgP zWs4N^(sZ%3s)k2bT@w0RWn(-#_h>PjtR%jywL08`r03}wxmtt$&pp$3TjLE>BB^yO zhMHPM^>u^+@jx4X6OE!HhD=j`>58s#oDd~y%cN%9+-YqygWptE_#m@p{_A9wfE)cQ zx~HMM`NnXg0Om}or;PDCleX*@y26qy&=>HhI)51p(x?On(@x=gfMAqDB``4rLz1s`7eYypMp>z73Tjz%+oT$e&Awmkm zFR;gR>}U!%+)Z9`a>jtEXuH+Qk!s{sZWc>+x6zZrxU{jJ?r*Zk8k?4xh=E@53$Rw6 zhAKn52{H*z9ed;U@5wJ&O9Ef2}J)$rRru&mW4ZZ^oSz z^eSCjOrR^QgHE(|TEDwqj*rZ1HB5Hfqgt&g=(Kk}?(JFEt(a}4kXGdO-F@9}LT&`w zSsFuE$Mt10;Gdauj$9Eshk#~M3`roj&3%3R44ELejeUL64)r+l_i&rKr9)^$@t`f`7C|};-TaqoVVnK^8{wb$cvCw1bh?z@d3v~$o z&6E3Ap_HPV?SE$YMybJjDlR4Qy>zobXaiylv9Lr%i3U_80Xitatk8cMd$`z0a%jC@ zvBb<|pb2Rl%zFbd?N>2Z<`qj?8ho`?;mYa}9kIVq!1yDCBR1CQEi9^++V-`lAr^BKn;I^GE95NAVSO?2po34B3v#-XBr# z-2NO<@6!Gpv2Wp^7*X#^re9;J;~ZjQMoeNE5EJ^5;m9j?C zkc;(aR1R^@BD@)6o1)QE`7LXY%0jY|3?aFJxrw@TeLVh5Ac%dQ{@`G+(0@bT07{Bh ze~2ns)gn-3=9=+xQDxLcq(!RA>Aq@13B1|q^M^Gh%O6kbBDI;j=KdB?)#Ro`revlh z2k0yT#*mwRosZ7=eNT@~LApWX)QC0G*=1Em{ze1&47zi~g>YX0Fy2jU) zmh+f;#;q0CC={Fdjk1I)B7(1#S4AMn)DWY(!-#&>rs=}=Nr7oVHzRLW)?UHDGT8zK z!bBO`88byi_Uo*5s6m^P`x=w(RGH8ti`XCv1obr5zMlI`f>Y2LYG0hM2;nHO(W-aQ zH&H8b#f9^ouKM~!G;gLwb!bv?!~?M_Q$L%`ym;nRTBr$NmWxP0_u6si%y@)IS4UGiTy2Qg#E25bfcBPg$;eyIEbs1qVftYPF1*RD6+Ec=zvZNi|r(U13DB-4Zn@ z0X9hL3sg0`+(Q8e_3_&*$T8yOBE=+LsHIimgZ+3SpgjE%HM_Bt*4gh)rN)Vz zbiPmPqG(SABXQC-4Ea+UUX+zy zG%B+tGu>^@^T(KmQo4 z1k6*RtwwF&i4(*qrcYkAyf|;Qy!eQ=Fk(W>U7c>? zNIgdRwh{3n?uek|$y57EWO5skKb2NclcHVDkBJ-q&ZJJml$mK7lQu!H@Irg#@DdbS zR9#Ygan|@de~Qs#Mu|Bj>aKB^ss$anP9Xbq&ZA*>7K1$&84+yt=Vb8oAyh-m5(C40 zxVj{P^*hl52_dG!HFC@R*mS|%UeE{CA`+w&$Q0-lm;^S1lugVj=ZLO9y9<1G0c)Cq z2G=9#ZC9ut#E@9S$k^U%c|%xnPf^b1IjWkWj*ukHq>9Z;oO!$ww3z((EOEL;?kp9= zpfpfpkpN+Uo+tWcd4o0=#w-yuG6IYmw(s2i9n_6*+p;C;#LRr1HXqctjP zk01$?POW4^!61#jELd|>dr~^qxyJ-kX(OhXp*6yxJ@gPV*3{ru)))S{SKvMbC_m8~ z?!GvvZNe9*J}ytGpxXWgY+fh@D@V+p(!SO`kYlCLJ#;vI(r4Sser0SNV*sXZLWY3{ zZAMM!S6^KZ6FKbxZM_t4f|Ltv7;1}#$vY-qAf6M+r607ze$9D!83XFeP@B>!&;DBq zh}v)tF~a417-3IVEA$z|ylhZjy$;(8S6A>O6-qmsCc_QC#BGOMQ0J~a9KXyBS0LcW z71;}KpD)<+z*d`9V-y0unJ`+!id*En#i9CVOC95%R3kU-b~L~=@zBT zsKn4Cd2C$al@(1?k*K@$%6{ORMPo&KHM#1^@0F|15tha<25k>FCE+MW>j@pd;W9_7 zT`me=RylM5xZP~LPZWW9fGLuO{6u}YzTrW6Q_K*CT<72f%87cf`9?X6;TQ!%_9M8r zL4!#C#w&>@{8F0&y%i@6!=qt$+EL~Q&jz(mp-jmVY!!L4)^h{W@qxlDkAEM95&mQV z&z{50r^?Gf`aoHIObP5p9@6D+(3E-19kp>&A_0q00IXLnk$}VKJFM65czAB;5TD+7 z1I9xPxYv9l0_MYkP@lngNVwN>qTi;Y3^;c*p+1xGaX5ESBKXMjVq%h#Rg%KSe8O4* z0)zGX2hqO+sz>5EMA|(tSGlhz7(Jmqd&#(#{s_TK9vGg(jvg3Z!>$hB0zt2i+!7*C z9=sgT=f@u85blbq@k1|K<;Xuakq}CK`P06GvS$exw!VW#?jw}{BB0Azb*7dd5`b7( z_LA`TiYv5%kU+EufODc4oefKV+e4S^MJ$fLXe3_?gKfAqq9kni474p!sVA(2Ztx1M z5{aK$88dG@97WEc9+guIFQJxPUm%5Xmh^*=I`cyAlSJ5kJDy9hi0|4WTw{ZkCtjnM zlyB8>ZYm8_J`xQ9(t$v+fKQ@G7*jd9uAB`pTKBiG$It0(-*YzWXCtA}9XBALFE&YH zK%v)wAHzsE(weJOvTe6`QX#&;p>ODK=?L+ z$hAWLbCUY@1j}}9{1k6C_c?7>+8@uK5ZymPy9tD@M`quDc>kOp2Z#*=%+@z1?&(4!iwudjihc9mL z@3-Z(-0A1s>L)$%FZtzlT`8{v++v?SX5Sg+-fL&y#U8$J%7g#xMPKQy$FWoE<2?gr zg3kC{5KD6c*ZnK)VQYA4*it-aa087Uq&_D?{h&?}7~NkEq6QRy_neXH4&59-%P(=# z4*emeP0EMFnYd-b(Ks++ujw1H)s2cfhJ3zn`;vIf2tgJT}AJd-`>jR2L~CF%{M8#In={^kF&Wl`hf81zrhiQa5~r z6Vl99RA-O6tkT3t3wK9liQqX>U;_IA*J4b2+>+!-GSb;lq=_G*z&cvosIX`^>ozW` zS5~7!an|9gw=JsITH_+SXt(J0isHuCA)i&gA=;6IXy~a_TlK5dgAXE!Leq9)QgN_M zlRp*`ceuPyU(FUnsehN1a%kKuJvP%=jG$bTOPX%YaxBC3laF=(oPa2<8-ZmNQnCLF z?0zjwG2~iiRiZB17j_EQ5YM76!sUkx6tZq8PdnVzp1Wr-%?+!DQShHWm`&iFz1JJ^ zm0jXIh@ZRQ(YM0ty*X9Eotj*Eeb%qCEzzA?pm|f7UPv%ET(&q2Mx9<%8zX-jc)YMW z!vL$GKEQx%2Gg)tWB2T|MwPC>?tYpzo36<2p~|&dFFHWnO8xUIGX1@G?o669hr#f~ zi}Utq?a{d>=uWVMju*=HADS0?KfIlR+7XxqE!YHou*{p0tZ3&_57-vZO8H*7?K70R zH60g_7W}NP0xycuE|@z{4%C|%#-Qij6^z^1UvaD$WGN_F&zzgdP&GNpK0Nzeo@0zT z7U}DAuJ;)vS}jO}4t-t&EwE6=7eYiEiEkGHD&Y(RG@(xIM!LJz*dcatfy4w5TI23F zQiBcy;6*doBp~=!As(pq_VhV`ADf3&O+9B;bt(8@n0!+QC*okr+?X;Jsy zdHopte3zn!m2p!_H8ZETF4H?X{SZTJAVEqUpLFpDTYnCB`k906s|D+}q%O119K{6@ z<3UI)Z6?i55DkQVbz;2`DZV7FzR`avOU}slCpekE{g|+`$B7MiWJPrh88Q5`hTS?v z_kMJdfd`&KFu*pjyOt$Y5&4|8Ee>UzRoNMLL_X{?Pt@%PWsmm_U@``%LtbSkbMyMMI=Cu_U==B&EVX1Fsv5oG=BMLDJXtK`$+WHOoe+e&H$ppy z)M(GKTdRBS87IY$R2XxTohhsN4F}|01ME@Z*sa>P>=;^%{x;hKpdMS>D^P9SHf%n_ z3gA-|`ud@y$9?=TS&OK`W~t+PT>b*{!~(M6K}?FU09D#M#zUT^yL0gwE|8PGTxomq zcmCv4VIWpWs4`Iny3}FTr_h$k)cIn+zy!`ZO0ZXnm-^)^;0xzd9J89h_{o+AQ0A36 zqu(q_DxDVd`gFw0H<%KULpEhXMEI3MESgt|)jSECRY-r`I^f!m*@kj8r4*-FE=DG+ z6Xh)JCj0EBE*B2XOhuj!1Psk8Cp8r=hWB)eGN=^AuWpn6TI?j#0%)Cq(Yy7rR^V8y zftx8K=yz-n8{EIu`5G(wcc{d}a`KtPV+VL!frTC-t(xEjbUz`jmPPmaxq;cc86U7y zwAjz!!X9}Rfwe)fS^`nv7qQ$5QU#(ZLQkbHuk;bO;XC-!S$@LL{zmz_`xn1S%YsmV z_FFNl^IbvwpW_ac{}y-n2h^hBZ1w-CF?LH_`!8I}452b*Cr?`-&gSY1{NO6gf@t*M zL;$>ImEAl%c~>R|zdwQ*FALuiHXG@u^Ou=7_ufCG79jcphu#Wc3y5r-SrfxSVg4WZ zOry^iUwlEt9(rVhu;V8&!JgXIzXQd&3$#S;$zczRSmfTw9-95llQO3tIt_~X*U_3F zeKOc9Ps`7-bcUS7X!j+%&mEDtRI-y$meTDHz+tFHD=olMj0}H$HVMBLqz4Dcyqb$k zDoc^f^=$9H>t|aP3nv!x%xXI~g4Rq^J=p5(R3~0_StP@fSyju{i*hu}r*aJrQS6W3 z&sl9jU&RtD+|@J8_YY!dExpc zunKQH2C8M)OBnVWZS>%8WsXH1G&oSP5G}HdXp$zmdbpZ#j3xzpxZFOrQ%;-ECaFDA zYXr|AdcE8x*%i|Bp5Q%VEGy6K5QDK}^bBsc56D09BcY_6vTu+gknlHj=Rez#{NL;- z>tJGJ`;Q#p|AlaAXt|(BAbu@BS(|y)$8be689I?Bm<6@1g_PGGR-15%o?;f%6 z@=P?k0B45{H)4T12_OU0hV5Q!u}iVL07q6gW?0-4;{;(S+sd+|XR&6%K-+?AL0w`Q zoo6!9T}0bwP?(4y7b8JU6sBf4u`XmRM_0xF1>CG?{M`BNt{rF)cZ5Oe8l&yb%L=hz50zK15lq43x5~pGE4*Ae=@JQAmcYL~|(~vjkED6SJsoU&MK^Or;~Ep!MpB zcev-!T2rVprbu;lp;+J$YEDkFNWUcuf5@jL!EskVBv?(?sve;Tv*Rb_aXj2K;Z2?8 z%-}dD=23lU-CSLjfyqugF-@_4#a$@OVHqTBRdb$hKAF0w?mZ2@dX)P7gZNXLrvWFYnKd-;Q$T1_Sb62H@S>niE67J8^iWY zTD#m61eE$|*A30V@OPw5Tg|>4?(rHNxI={}4nVCd$b-z5`jOKdlehva$elS0x%8kL z8j7d%STufG=g&-jK6nCRM83#27QI2ETLP4JqY#4({XHMr_5C!#;glSj5^Ti_BEjuN zd}N&06O?_$OY)Q*dtQBekPdR746EUU(}pz6MuGUdj0&51W`8WUHaW?O*`;G0kLQG$Q(>>@X^A8>M(&t)fa|A^4a< z&F%FUBzn!V6eNAE#>Ld)Jt_ z$X{tQk6bKMW>CliFHO06?Xhtzb=NSy(BZgPZ&%ZUWEYf^)we}+Lk#4NLwF@l1NWs@ zr8f2KVPoBr6|*Og9Sz`n^70kAUo(EvZsx`9WQ*iW2a;=>MhTbIOZDuAJ}b@UcxEdC z>RJ^qy|Kx#&8Ba07=q(+?$n^05Z+;C3FolRW*j!|+`!+s3#6#{np9)$YodLVE`WKp z$YMgj8DtHRPUS!`g6LLBDJ(fdV+G<~O7v*bHeQycx;c31%71t?Ikp&s@9 z@l%COOW%Mt3~bLi(CStmJ937xak;AX`qG)ksfX28gItpWCW9PY2+*243*&J+Fw*t_ z$+lJSR~^)wTc#3cyEV1_e3DP6+-*3&9ODx3s)IIELU^R6a9z}#aN%Qs?;uY9mcVv= zLH@JyCnZofm4X8Sd3|RO{`1O@^KUD^ikXRnz3Kmjd;vUBHPHUTtxb_;N&N`8lk^P2 zWbaK~zJqOok|MOyHx;2=j7+*9#p+m#=}c0z)|t0nT2|NDS(GMtDnL&OBnNJ4Sr1&6 z@LiPf-FPc^`26_L_{hmvlVk40dFdhF$psv5-}A%)X0l!W4E@dVg6Q@B=tQK3hiTUu z8r73w(90P;Ba1h#CW@CV!iC%hRV zT@8E+^B;zNragB|{?ttNBlVBlHv#s+&5LhGn)77!hrAi%MYZ2M2zpV)Pu@C=-75gX zA0`3jjZ~=gr1eknv(0(BD2}Jti0{j&&6wH6j0L zp0w=2GA%(e^L90Nm>XO=DR3X}R&##dL_G~3kNIOf^l$ctThlQ+xb?h~tdN)4!CAKa zyZazXXkf;a`J^Qt_6a+3j<-iL3mJXSaveODxNP6HbX+35NL;vW(LwKW6z!iUqOxOm zJ|m`M-At8 z*a;TH9u-yNzSU*w{n3wdp!%~+s7V#{ELQWHag7a81deXZ z=f9@Xt?d3(u#k12qLQ6Bhb2Tygn8||P-`eS7gxXM&zVHD`i3qUV$Vtb*%OkkE`NAa z=SZ%@lY~K1m5pyifVVb+ur^NFXQ}pF-P-F8bs`bTNCU3JpwwX|(kUY-J=v6v;}lRk zuX#}z|h8y#(+a$7~1yKv*?BQkW4t>4R~Lsu zUQl^xhxG&R@9d4jhm6pXDrCoFG14zGC>4{%x*dl<&1!Xr#BBbrD>-MlTMl(Dx=q`o zolTbO_X4c+=_$+kpSswP%ayVBiS3+pP$p|L%P2tyvJ=j z6n=qH(NCzk6q>zJXBAHZ<_k6ESxqS_-<>O@x>w30L`gMpaE?Aem=~;DS^ix0bIBcR zXJ3u9QWy~6vXV+HoAb5cJ}O-;ZIf{`(n>5ZPlS`@(&o?sgxNwj$p4_m38d80R%1cs z-j^Eqj5fV(kfG%~ls}ff6jv^gQ6E8Ok1J5-1HlxhCF&4fF5`1_(eE%6?{;=v(Qf(e1+djtsKKHBIq1j>wuOAzqO=6+6;ELO7*#8ZuxBfRulBK~SP@zu z`%B-kGO9MxO$ZlJk!ZNY2|a?e+VahhKzRdc5rJUpX1~(L-~bZv!LsV+!NnUvX4w5*>@W~e!nkpY%fT!DJoR=A0d$$6At-(X1Et$lmg4G0cotrS zDxBt5$m2Mae!AYUR8DVr9GUFhj znksmZ4y`P>t8~63aV00Hs7Ai*JR+LEr;eer92)tJCTi-ueoq-#-M=1q!q5y*)^LZs zqNrIjZBW&ri^=A;^Uj&k?%6n^;T(&jU(qFVo33zZ1iNiGnl)cGxXQL}nt>A+#TN*C$$Z+efe)$GmOD7=St7^!(KHCwpUKruG>D zsEkralGs5w%+3f895f5U9rl75^G@757Zyu1hscfG7b}P5B*nW~qyYT^T%?7_*NF$q zBgFc?Mk1UGbuK!+Ts6YFIWXcZLI#Uq1A`aYjtl)c;i3NkDesO|_M*hdaH!W08*&tr zk|`U^`Xn}x--D#%YWg-dGf0T@zFnnH^(n-d@&lo)*2kbcb7VkKQLTM-@v%+7HES#3 zL=1MCxmK)wl2~x&Vsfknzh5#M>#jROxj)XhT1z2Prb@9iPBO4VZXuROIInn))d;CU zIwJ@SuGd+=FMA%QiDG>Y$7*VjLL0Bc9Ztmtu|s^7;W|E9tLh;%_#QS!;A_s9#gdMB z{A=~7PHwJLb_AlOJREh%c>Dw6pRKPAVsfI9hK}DVKIiV~Cg&&+r_corL(b=jJE;TC?nPj3?vSjO2%#w;NgJ+dxT` z@g)n19M#K}KpMCucFD2ouV!7(alB(#lB*vOTkV!Cj#!s57+|@|=jAfz)Jx8gDG&gl z2|V!r(KBni3(6oDiBx~Ejd|EE6I~Y&aN^&0$evHTBL>AGurvE%5 z1{I0b&b2O8&Ohsg-fcQz?ftcYJTAY|rOvA%v~=FF0$0mcmbH3!&%M=KC+7>#v-6K7 zkdo_%*}g4N`afC%^WQA-U4rue@j#NkJ&^f$K`-<)xH@5-x}%KvV%wgs%-|culB^3- zSX=jnEjhwvZR;K4$2sj1u}HLPZB=M?C^4P0q9*XlN2q0uX6xo2ogKgZ>q%MmF;k3} zo-d~vK9}p)oDn{Ys|>HNp9;KChDcvoQM?z(&QbBt(CuoYcEa`;&SCN2-U!*DJ=*mG z=k@Z9-^H9G+f~8{Livj!K7TNRO&i9u)yt2o6~*v4>le(Y$VE^uPsI0NpG}#Co9QiB ztsMqwf_X=vyxAK@ekz+zu>&Evy#6va-oP2l7us(HrV{S_jh7D*%(z=8s}E9`8gFS| z7zweXs-OY#mDApv8my&ecpolq(km3)$n6oXj~IULWXJ1fyNg!mNmyu^qwu6a^?oHZ zZ`Q9&Y*g7_F+)6{8^(KzgjViY0pp4W#uNdlsgJ0)Emd~E_LIswjP#OZ`_$KL z;O%$yUDRyUx&t>m?%;H^Cu~;Kpa`l6_8V~~vN9{fGtV0qkfJ<75(C6Z?1%f8mPO{n z7o3d(WeOxKkrdMFPdW@sKuW}gzA`mg6JW)XstY9J_S90lz9!eZk6LGQ82Qv4D;PK# zd?|C;>gx&&eX6n8&Hx?j(VjBpbp0v3Lh6`fc%evYv->W6S<#A`U_mWgW*Do}hI~cq z!-~9PoGcZ1>(lw{Iz9;Vmt+}R$6in7%Zh~dVIsGVB}J#>(Ye}O|UHiA$wOP^}McD%LFy z(I$LO69LJHLa$(JdmH5yCW-@{s04Y@Y&>Nh+l(zbW~UIEI7MbF!`}N=X4P=x@|daB zEJb`$LGvoZk~}&^M_F+AMx51Mjbg8bMy~}bii(N1!QqNtjPBEoKKFr>q8`Oz2!0-L zT5HpaAlvlZvhmwXC{meQNDDtS9_sV^&1#85JBQv)Rkp?F(Wco_CG*9?5E*2E?>B{_z)X`Qy0C`ReeZLs6)aSm9vG2;r@zTQR^x= zaCqUtpmuxM)1&?>ILLcRi~V^Z&=o1ZVFyDNEeI~ff+h}oj@N3S2fo1Ih)@T+5!xZT zk#&KL(dBYzmg&BoYPch9)A9{o*CbtDOS@9X-cAvAPg9wup-0?$xPu$nY(&q>-4)Y`WPQ5H)0d6SSzl+{G_G54rzm7% zddI{IZ^_G{Pzq52bk^H)_PM7_M1l1lBlAjfq{BGKSVBL+%;S%_!N_{j~1t%+aJjT5{$7VQ3C^e zN2AAzT+W=%TulQb39a>}KyOA9hM=d$_^`9#QPm;<|r=|CAN&TL=8MMSKmS)MRo)JP3QVQ5WnUyr^@OgRhAKma;thDpP91 z2w=9kdyO*+3=~3Lnz|ktY(SyB7$N=5_jr()vLM?2JNg#hxM4yy!j0Xd5Xhqd)8qcP zJ4a0~zWF+w5<(Kw;Bp5r?##1A}DTRsJkY;c`vE%(SUT&}>1FTbzVsR(M{S zH{9lIVIp~xA~jg(ds49hgm1jKR_wCv&r_gMf#bV<*qKk-b`QqdmJirzWgjk9K9l4n zTboa_dAcef9q(TxmwQ6(WCkQ~_431#)2=c-LhIAk4P+Jz1X@!l2+&KTgy!u)k!g#D zr)&Nbc!E9Pl=y=eLX%D+@)bfY?(@ivmJ z_ipt>z%}FNj7o&9wfyiq!>3hHEo2!v6m+~a_TmELo4fdd0I2P;B^>2p z3+`QA0lR4e@J8S60c3&S)!_Cz&-2T^O>P1j2UI#PxOG>-oB-PpYDg&*szG8%rh-Km zLO1pVR*C@`WiDtnuk1>xhvG;jEPC2dHrn*_Wb^Oj;K8}XiEXr8Il`QyhKQ- zr`_4Wi2#-87uM@ejJ6Jz#vWgLUj&O;kI=ViJl~vXH#z+U=XBod zN8#<6+6!qU-<(Q#Mm1D0CS#nr>VP*7IbV|1_Ad12(IK=nAyE=n_eM=G4&hY;I*}^>GH3x5+;}H+X5G;& z{`40|p^YH+!YZX(( zuAdn%E$a$*rUrWFa6&*w$7Y!UBF`y`C$NCaY7NV7Oxk6NEj1*yLH2o!@+beOqRA$c zD0_95)orvTx5!ew5%v|Mh|LRQ27ZP~xvZv@@d^c;ifk1wB?sLbq|B5wscwB<@^&S_w!h!^kKi0rY54u1piPjAGNA96K=s4xFwMtg^$(9S4qSQq+cMn=XO<$l&K4tc2oL7UnuMjqW#XC0 zKID%VV1MMJJ}a9g{bH9S30)n`lawE5M5L-C_F~WVyH|VgF$F|DlN^#wrSIa-mR5qrBoN9sXVccm~USz{HYcd zF|?dDQy5zxX5NrpGM0DpLv>A7GZ({AcpBe|)l=>#1Fia^;?FLO09xs#yJ;9KiBjVG zWat#b??zdVuvR!1Tj#|SV18e zY^UTmxd*6Uy-eQ3CW^nmKbm#IPhrcFNcJ;0#Ta2bUsn`b?DyzM%X16LJjx-*@gy~n zaZKtIC$MDFvt-nm_>wz+dJsnIr4tA%j{HN#*W0`f=~$}9!Ee2CS7D5H#f_Ah(`Bd|I4L~QPojd z5JdfI!B93)v_u<(fl$pRe8lmeNY_Z{^Fq^Wi|>z*q=g0NLX$dF z(;ch}42(n-SEiH(P=!p)>r3rfLl;30tLhH8Mf@(P5%o zp2)=s-h@kQUqF;1eEQnjK(K+uLus)IOM)GV8T#`9&cMCd9GNoPs%OL7IvGz1C^h8l zuI}$p~WprV#vnkpBN!GHbN?&xu@xb(c{@JTK;4Zs2QP&B} zv^C2Z!n`C86zQyBW~(>VARmYP=jH0M zb~)q+_$^rVN!8H#ny!>ZTb+WvD;esfbz2x095)0egvU`Uu!nD@63R~^%<0RiuCrG* zeDtzY*UF|`JNi??(ZBv-1vgO4NJ|n?kfS1w)&arwgaFGEL!eO898AdpH4}mnl0LaL z>Pu!(4&BXoQ@k#HjG8gU@Wrn@7jjSP2W|RL6LC@@@ zOFW+o@`z)$Ekd>NiCEzA;tXpp@eJXsu_@0T21j2HD^i)2YSuQ>TY|35aGuo&0un#b z^SuR(PPmw%{Q=_DY<7(dj!F^j!%VL-cTdP5d!oV{$6P(|(bo;ag9FKuoeD!dDY*d4Up&3* z1lg)T9J8OGSXOrgPMYg<#VZHrJg?rF#sq?WBI9a(P^wf1%$M-&GM-l)|3oQL`2ht# zz9*R9ce?aHPcZC%n_&OF8&!!Gl#hy8i$GcXGr1gtA~f(ih}?wwf-o=|8fK_)6lwwZ zxG`|rtnRvC<{~M0WMnzx8Rc19&_U>VG-rdQ4)`;;=!kE|^Ks0^Bw(gYA!o{KqHU6E z=QA-iE326MD9z>f(Z}CEoA-8qI&t5hZYh8bq48Zz;JG*R^Y_1ba}?ZLC;htiPCQIA zAssl`oP-FF`-B+BJWh-lFq@oUVI8vrDMrzlSD}@TU{S*8VziN3(WXq1Lzd`dv|Y5D zwneOIb!M`Rp)w{~(I!l}LtyAfwDN{~E+*jW4R@l$^2SO-s!4jBA$clV*`v@DM}e^v zfBNLJhnG~^ys4uWG-WNAf`(+#1&o=Z*8C=o*`ut{T{I`nlm-e@hq`o;%Q~I-mz~@K zU}kpz2%|@7E>;qL;pRD33oY~WrP)MHtv4~WIN3#%R~)PWt)xb-Yx?pqdKKZM?KxxA z?2b!Ifv|E~7$?DKkYS6HLL;;}vDG;3X+?x)G~{nn!JtgL9jtw~XqZWX1HGRDpxtP9E`La&zJJQ(V4uxM0%^{OD(^D#8)fVAlTlhvH? zWgMgC+2KJWMC1J9SSlt?yZku;U;nVJ@FAUQdsKIb^$q90SLwoX5@v0xz&8WC}iD5?l8#?MdU zWV{NK%VT7gZ6i|MT5wo26{rk)fNH9r-cP5u5h;Xiq(o88sr;b!n<--GV_E+wI6 z{~^?HoJaN=z+XDB0q3es@Gg_MCZVvSS7&tTU9`rkW44f+Q9tX32OkYf>+py@xwk*IJXb)%Hr)>S|q{dO18M3+GQ3pf$@4WrITl z8-=IMFd^%uSFX>~rq<<$O0~%5%DroBM}`?b0i-Aw-K93m(n7-_xfWunjubMB>;sI$ zJb?{plIT)^KT`Z8b7KFBD56+cbYawlIi^@+v`Ox)0+{k*VghTsDP_u&BBaS{Lfz0& zF#tU~;QhWQ#n~T|r^Q+r?Ajkr@YngC#R;h%y##QQfB_Zq=9As}(GmKM=hg)rV(cnVW8I%pe{`h0{BCjCK zj59|AJf?afy_&Sj!Q*#%|W4Tc5{dklqUY9}zV{!`jvo`RV zl|Ay8b`*x$Tj4e=qw=kB$9?tXZpkpnU98{+eT6e&BJ2r8x2BS!sUIUY92_{8$2_Sz z^1=?HwlPc&Iuf*3C9o@<%QvAs!bIes!x0;>(p`g>z4`5X9R49B%!Xl@m|8G{50}ZuFJLwt%4+TKoPS`K}D1){{0E z50;T6?(Il{m0R|%oa5h~^^2bSc%Egk9`&n19_Qcklga~M&)=~Kj*l3+pJY*xS{G)w zh*1Xhp6Os8@b)WvzUTyXFY!YXwEX6`0Q8@RPH?*CgTCBXBcR+qz=uiH>Xq;Y10394 zAPgrr%uyz^`o>PlLrBP;hy+giMckVadQISW^Go$Ofb5rac#pku+yxBc_pG56LZkK%(?#&>Dg~@9@(}4?%Ab5s5)~s2cu(U7}yvxf3%1cSO%g~A? z3u1)UnocgfKE>YfJI{|m^lx`~XQk`T{WwOVi<>`aM%nrDam2C)!eraMK2nqH3L(@g zFhcCIgxP&Wj zB*WT$W-8?fQ+xH- zvnpJyB4+=ScZj(yRh{mK?2fn0brz($Z%r{hE+ab*aK?LznG|72l2;V=S=y8WV!Ouj za&AKT;j$_R8P72XtwQDk#?lglfqGUI`|`A1d99S{J^B)zu4Y;}+6JVL7cXYRgj1vW z7&C6BlYW?h=@b~UM~<4gGks_f%lI9Nx=ZkSv}KgfYlkCme-imoppjeyR{6-GDvJ_| zvXZ+NTM0>r0OAQKE@~tET$`;(Q%6ngj(D{D0oOz(`pP$E$%LKz6Sa|8X-_NRVpl7nd{ir;D)al8%|fh@eZ8TiZi(7RM;?~%*ua98`TkJ;Yh1;G zp2}Vyy}&WkAg|miT+VN@wJ-USFoBCFBZ!{$ZetFFyGi-pTt3l`9W_BwhjzSpeb|_| z@@chnCi|sS&|Ad@hB8Bc!{7VfCWe`XM7EZF?n%Wqvk?&5CYdGYI+$EWohZI`%bqo) zmJ^r0EyJ@VJxD%SCfiu=v!)w-O9d#yi$A#!tREKLp8Flq30>+Bq9Fu-5nL&S?hFC} zBzD8n29H=%<_y0HL_?I8_?A`S1Jmqz8u8%z>J0=Sv>^DI7N$qaHrE5@K5v(K%TPIS?ymLY5%)%9elZz}WkSfU&7ohmmeVF(o z&A)P2u?}j@VX1z_=(Lk?Sd&z(0@fPU4poh6w%bzH9d3C&DLz4u;mfdY6Y*5@HQUfC z_F38;W%>M&mfB5shH(j8*!}+g&uJ~IJd$-l4@31$3nj|shA7|~p%85wy`&pqnQzhh2J;u7ZqD^?Q#Zs`+#BA?8RlLDpD14FmqcgyH zJ`mU~G@gGwIysS1XaI&cP7Yi!5K0N|T$2GHs`;pD<$@I1(e&vd?RA)2v(a9&p`g1U zxIZ)w2;0CR2SgS<5W^5*^z2P%N0ePB;Ycy+aiE_ls@uE(f&`rP!i0WQNGKIyf1~W{ zW`uqYkw|!mU;m7C~>0pL`@?E%BRXhn87d0UysVT3J zCwLo_a{0Q^cCfCGj3NBGVVz=gUzb8U0@yK9M1~+H1>b#ej_?%3166hY4A{w>=`1P} zExmylSv&h=;3&~JZknL$qYx!B(;Ng-D&hfH;l}o`BaJaWkvv8?J^+U*TwNFpe4hz` zLsAt^Nn{Li+twX}Iv5hXN{twHVTY=Xl!mnL9KdPoKmsn5#5s~ZsPG_knEoSIUrc=v zUwD%aQDGgB638hTE&;Y*p$ewHPMAwE2m^B4^a&^?+$I|YsConCCWJFNxAQ>F!40YR zhUFjmh|ubG2Ho{aGr#m+eA9^M4|;_FLx>?3+}AIXvULK>=KL~q*&`H0;OHH9PN z47QTS6^nVQAi-0N6@TQ6n`T1>IEsKgU`EE09RQmB(t2dQ1j^jQE^+ z!Re>jmQ7S>31@&XA#OlL`J@c)=?vPY$o||k;*It&8G%;Br4e#r70NY1OQrPBJ7uTnlB?VP&mXf%rAlqC6~RjrE->No#N&}XzcdYH&)VGE^_;33eKpY91W!_5 zm#`o_=cy@k+!37Kk*vNpHK!SyZV6kxB5whdKW83Tf}|B|t6q+i%xqijG9J`pv4*_gM~udVS@v@nEU%2O}QHRC*_BFR^!3RX!b z)+|O9X=Fy`PEm4(ZjAPi&!Oqx!a32aSlqK#|GxdO8%YhCV zk63*7``ISb;IiOerHb;byI(_erG569FR;0Nu_+VLnb4Mo@(jJNFV#)(6xPYg1 zw{K5$rM`cBaaHu?m}d58TXHiiyfdk-74i9X@!jcX+lc9(p6s?-!Yi7Hck2CZsqWv` z2+yk*o1GEw>ia!0Z4MMyJmt>_pL_UeIRFMH0ntqalxP0^);7Tkaq*#F}Tn%xzI7X@P;{=suWS+T)~^rnF@<@`nL6sfIsc2V zZ-9;UZ@1m;uDNU5wr$(CZMVC&ZQJ(luFa`!+wSf8pUZRZ_swK7nKzj?ndHeYYu2-{ z?^mplW1*n>a`M@QqitO+HyD zXKq+{3aC_XXW}5j`EEwyZ3hogj;X+ADQ^QmWVUwO{@C)d<=Z6$D5CwY$pQMgAVM!( z9ctJNG&I{Ns3WMUM@mOjc;KcpnF;`Ps>ZD$coBO}oZpbGeizZNugxpLvK+na!fBK` zc6g1+r{_CHI{;PY6-q%e?$|$u^)AS{He-E-!(r;#gnxn{M)&LdY^!7M-Rfd*%d^t2Hqp;6&d)Bv&#u?}!G>II zEC09~`dd6ur~CnH@kRHpmmBYr_GuIM3G3>ODETbzns9@JOCrXWR8{Y{V;ucq#b(vl zQ|7YhBk}oxaJ#@K5dUg+dqKCqrZ?JJJJQ+{fB4nERcyyqWGCefT94NShsaA)cuNq* zmh3DPI!I#k!+e#0rdfbqa6GhrRX?o?<*&32#Kcm_T;B)gpLklE1UCSf;YJ(u5O#o! zOsKw-5}Pxs^+~`T)v=mAP&jQ{9ahWjw|v0aa?NwWlg~7)QMoW%gvuXMlR|oKEKe6p zs(Xv{DdEqTn6T27;ka#q3bc(!_Rzxo7@h_n(vk(jfTf+?FA)teg(Q>z^;YRYcaOM4 zvSEMX9IR)bF*ci4;$d#m!M#eme5fGd;WbluaheV6kJ)F`_L+qXuS z1!CY|SQN-v1nzHEMK1)+m(+r1YJ#=zKn*z1#Hw2C+g>896R--MT=lRIM-9%_gt495 zwNGt9z@2C91+rnnp5xr%xbS8#(fN^Ujy8M#Li=*y6P1SX!vj0tw(S;Q`HIii_}gQ8 z3($kx<@+Yzz#)8i=4C~Ye*Exc`FCU-{eL6l{$KUo|5tYxGY!|v|7)lxU$dGIK}`)D z+nW1ld>jNMu6}c(Y32gy+QAMs_wP_dEm`b|oy<{hJzu8SqYF6w5ZT|RzflRKS8S6O zD~RXC_E-p3(a@0Y6fH>a(dKRivR}-TX-m_)#(voJ715WELw z%zWrHsd-G9)|hBCbgos_36684tSJrElfZml`vB*MRE#+3^*brSMz_9(X~)W&00;R# z|Kr}H7AAhI`TnJM->?55CZT@(_|_#ND|L#0U-;jT?@iqgJ4Z7*OFLr&I_GcC9-Wc7 zqn)iC-M{8CY5vt$M4Zhn?CdR!g#NjMwVm1jiUL-%vd3CL`K%$aI(Q&;h^luuAFzec zmvR-xh3%DH*M4j06)DsJu`wJfetjlsc3PDr|?jJ+kNsGVai;m3zJ#DW1y zV5Oy?q4DF&K5<^P-~t$w0Qf!tveO$VE!0{y-ArCjSzc2-PhFQBUbXK}AF)5G`q4yw z>4%B;B11|#Im-{AVk6QM>!$^Vg02&7>jFK6lMf-VT^?=O-R%JJa+3=V%n~LzM2)l4 zZgUZiUB`u8?HVA&ZYv zUBCKl^BcTueF6=qPCI`t)W2^J;AT|R)OPvsJ(EsDKMNqhZG$3MIRpst?W1;&-0@u zhXm;?)9kPY5qE{RqH{y@S;DYU$EoyDbjhF?b5gvA5Ws^!q%k%z*<7BlrHG%^E9;Y2 z5X)3J?(bSG=9N%rU4Z~^cA_2XsT-3kN%mL;I1%)*BUv6<93=WFpQoJPPcLqQ zec)|MeW7{ce#AQg7pu6CczZ}dXzgxv63-mG@z>DuFtkRB0TJx|E=+DGdp8d*ILe7k zr;R~+hFn`ON|0*o&Qy55!51)RM^SyO9L1vjkQ>-_PTXRvxZXnx1Q_2kEn@GOt-0Q5 zy0XZwN(vyM9DX0>ttM9Zr1JOaI zhXU-Bm}@4a7iBB2nJ|+!&r*o83byNH&X$hVX~1J*53!Sm)gg?9cy#6Aw}2z?t~oC~ zN%oYxYuLAV`m6ZpB%Fhj`3R7_hBdzUP!oLC5yzTKl=~zzCd^5m)SK*Tq_}s&{!pVV z-@3YNOKA$Tw6D~M8pi?5uz6e6I3%C=1mXQ4rp^MtVp}nf8My}#37K2E>}X1cU2g2E zSNw8;(^3cQ@|ao~v+(G4+Hk-P#+4f#SmdbMj3!urlqFqb#<3c2@-v!F?1Wf@`4ZDW zD>=Oj9MLb*H0jSKi{*I%n``@PUBl8pLsI=^RW5+_r|8N)Rz88$_19nY=GozDu!rB7 zAAp3{atGg;KZMi`AzY7!+T?0*K&itRQLIv^&Ki-xK;1J#5822t zx8G&nh}5y>gj!5iZvZS9RA0fMjgrH!F>vC{d2E5+zaSHwwJ5JKGNfSZ6r~SZT|wy8 zhdRj=1C`l#!0N2RNf({h7JlEMe9|#vj|o>bY|5Ni&q%A73Er(%ReKTj6B$|mmn?Pw zR;UBYr2y#Vpyaw35H~R1B^jic#E=m20eZ_WJLrMIdEt0vl-O+S@JMoO|6io0U5buB zywPgc)Vlpn?mwsZc(U^FV$sSAd#r<*5+J8AS7%3sPHtGMu=`oeN|+I=@nhxLb;-=> zE=Q`&38Iu#m9!~^HYJkc$RKnDrqFv8ugEJHmrt-Y>;MPPI2kLUT#bq`2NLb@=3UTl zOj)hQuGQD8;Rv^LqzhyU#~c?p!(%6d2aB-pj2J8uG4IGE`-h6&qE2p!h1Ld{5fNPB4RDHT&mMW-X$4%N~yGJ!HsrzAX%PCGOCFHiBh%eyx%lH(J zzl8I@m@Kc+3O=$=dsBsD1xC-clN~Y&n|Rd*{btwLzzfMzZ?^6qjr1vD9wA8vyGk9| zzl2=pddx%afNp8wh0?(N5Z8D%8JIoE>R5Mg{y=Y`+j7HiA^(}`Tk@DT{P3{OJBdb+ z8%<#F{@`Zy2>)Y&%$7ZT$i$@63x!V)PJAfHf;96tqRv13y3sIb8F6I`)0WXV zVH7q!2xKI(l|G#qL@`1fF)0KxofUqpNMDksTf#QMe^iLpDwWma%F+4L-no<0;Z|+d zk2-WbE_<%akpNh|(V^^R+hI6xHn&mJ<(N*KH2+#o{b3$pSE#lnf6sHrZL79v|F@gp z5Pmv!c47N$CU1Gxc!=j(0X|v~@Z*mNE4-A;w!MFdmT|doo$`=l*KUMSANCIfAHx&h1|I?G?xaZILC-t{yj06ipl|;A;Go=O+a5r45bg?p31-`Ms<2!3NWgW6 z!hTB8Q!XO_85Mk#>DMkhO!#Y_H|&K%F?L`!)$r={b{)#BqE>s7@4_p)1qbK|?bP8$ zDYHct(ya1V2T$*&e!m!CD<#Dhf=0sXq|atHwVnKvC0Yx_k~HrU6$#(n`Hxk=E=N&P+sa%{yC8C z9*EGb29HI+UiiAVp;#!!VCMKvv#Ppkw;0$R&kGun8Z&}nQb5Qs=FAZ-k}f`ml912f zsz^VTWuHYhYk&@K09eS=t4wDL z6G7CjU4@8@>_&c=n0fG($OJ&&zx1=+OwOLQIth!WasSi?BN)b}@Nv!aW=ad-*O) z*A)1^WJpki?J?!%-%RZ2(LuEv)JJsNCh7n26k6Gs+r) zz=&Mv79h3?b&@qVlQV>Kv;Y@~e1(>tqzlVlUlMgBOmr71kHt-y5o|_et1wHbPS&B^R3I~m3A6;QPW6{8 zPv`GdZ~md=L@wK}8LwvkLOpnAER}ofi#c$@Px+Y`C(6&?@B_ts70>c@u^{h|eyR?* zc;sn*>7nfsSjI;1#PfO8PKlc+;W&dEj*mgk1)GJiphbx~2jzkMy;8|E1>`gpR_(oW&B_@ugw>B&2Ea7K;9^XVi6xfS^fvM`PrPl^qaBPhXri zX5}!Jy$(qnAI)Zq?{2BeckIwO_Z}OG#S=J%o0f%Vne!hU8Z%{nlIJQ1Uex^deHtDKG ze;~`8sT$fyJN41#=f3!nQ=xth)yo-4aPoIYl1|F#Zh69w-A$B3ckhu#kXik%?p}Fy zyBRRLhfN0R1?&|Y9_**I!RZ&z&#T=aAuwuW@0d>JD&ap-Ji9N9S5XT_HPMG1tJ;|p z$$OUCpPZMOiH|fAUNICxw$bgnb~RR$3uZMJL!3D2Z9r#b20U&*#gFjnCVVg-8OWD# zL^IyV=K%JIEr$_+G#8i_xF-Z@OH|201>+*<^5R=$QWaLUE^!UeT(YcK>ORUt0|FXq zL4vPXDnZ!8ZOY4(>nls@LB_*Srp>0!Fo}={jH#@>I<~b_sca6fcr}Gn+Gdxf=MX^B zPc*uLl{87;JUEPr2jfEz$|Xh9J_7iNa;NBWz`;b+$;5gj;_OM&m56HjMas{*73qs3 zrKZ{fSNLYOh7w%S1>p;Ct~9IJ&9UboE7`$tl>QU6@yEQjf-2MY>Je8cj!Qx<6OBo7 z#wDeje24DAc?i|n-mwEkA)qt*K$VP1D3MBcCJS#bX)Ij8(0M{}i=fsCFLEcejnN2Z zaAC!a=`mi*>{Be6^u7`ZwG}F~)`SbHTww)E#i5ZYshD(_rJ85fjs?xl`(5 zlWMl0?*e(lpy8;mG4kpuoc4R!zP_RdoBStfnRIBPEZWS8;c1o#mD5YjWT-4>4@$ve zlG7|dGTob4HM-DuJ)|RYqF5YNr4x(?(FmGzgg+{TCVNOZQ5xy7^G_PYCU+2$Iilj~ zlihr030@}x3yM38(dPjl7$#0QqeFxV%wFrK@gcfaOBkoyBh@IwO>*Am%=%kyKVOxO zcoCz<&;^R~UcfX- z%>DgonUT@Wn+fdlB0*>vW(JW!w|a|ywlej))zP~V!moKCx#|O5?q*{hcDH5vIKv zv@}WaTm@A>S26HIk|#$s;~IwNM4)y>ok`=FxyCiTzQ}Y}(Zn7!hvYnP%QyurmC8~% zyt$ksToHpjz3N^CJk~&B7`>*3J)pRjl;zpUy8CFwlg_>ao6rP_HIs6@Eh1k+S;K>V z^cBM3@7#h#c?~Yfd8;w4qzSJqdQ;T6Pk0-z4a$;L)S1iB1K6HtWKx`o_QI$`w+y@f zXa{-v15Te7P2rea^r=o?9f^|w<()>Kz&LUnZG3=S)cLZU62-aA*Dq0DP52rc5Fp7ZA2n;P#GyT1;(D4tKPd;I>y@Vz;c1y z7+H|t!Ew)D@EbewUOw>+%ai+E}}UT;oHThpM01bH}~#8AUtg$t1)(8<6bS2Aht_=_Nr@V{jsngsd^ z<(aO%q~g@e_{0Nx{Dz~k`T`torl)BH0*l>8Id?us4%6)|es6EXxj(x6Mfm#CZuih@ zZZ0^tHh0&Uw@jZOTT;{9Z@1O#FTj@e-M(Hi-nTtI!ynV5+>9rnAX?RxmZD4+txrt% zVlq(h_d$agO$!$mF)vIemkrmg4xhd~_(J@3>Y9{vHK>kK&<7&B6}WvvAlOtD!2zCL z52lxkr;@gps3MmQ>axH^7~T1;b`WjIbZL{GjvG~$qb+}W6Vl&g8VxW_ecU?gYHX|| zgskQhi<@0kE#xZ0O@IuCsu;(VX0WU+tc;>r##b{0P}>Jrsidu-u7~a{10t?!*HWr< zE5GYImD7R`I9wy@8desg3T)9msk+C*MH*-SOmkEm;1SBIuF))DccM>|DFgX-tLU$m zWJ^U=hIazTtj(va+7BySa9Ym*N36#Dkjo-k&lJW(pe|EB>i_}*f-~om?Mf_~v}r6+ zHFI5H(*PVQF;_gDBe<(>Eml@#Y|{7{L!om99S~n{v9@NQu-4xB#uPWF=%z2ZsV@Y; zi!zOpAqgWB2}~FehA}4y7(bt|3NxiK5wGnupqEX#25T zZ&wPeR4mAzSr%iag9>ApB!^S8ieJTn&8Ihs*#F>7?Q+lf!)V~SNEk93yZ6gJpa~a7 zA0m)_Wj6HKsR9~4j(5HIjU3LsbA(Z{)CpOE_(X|T8~X#O@5#Bu7jQ|&N)L;{L~O)< z;ocNR=Oi3{QAkEYSs&I0FE=*s!ayR@_0cz^bWc(EcFpU5Kl7%DfkL$DBi>ja)>Jw< zr0bj@otOH^0hLyAW^zo(A=%8|sFa@V5#Nwip!NLo@A`SD=2P00O(EbbfZQs0 zTZC6oZZYXf`Y;94m(2+dLZ#Qw>l5&N;)EZCE;+O&fN7+3fKZowk2-9uO~g}9r#5eq z2wn5uoKZ6max$*?mH=w5z zGQ;onT-0k90|{J2t{c~C>>YH_HOZ({s5a^T)NS$upUVnCjQkH<6!2g6ayJOoRG|z) zwueTVYVby{>l1e7et=i7lFxr+^rq=CJ8$1AU*>-+qo@A2hl`lxe?3%+m9^}VRM0=+ zI!6y1{WhvIZF9ijB)*ygRXN{7xf2>MHp!51@ zBQ)cXAM^2zMPja4o;QjjIduaU&xBeRQf5cgVHxSgOs48N!kV zEV@E@F!2sosXT=Oy@tdCTp*`^8Df~P%>bQ@WBU1p2Aq^q{xHxxSfWtw$`zcxG_Dy5*BD zmDY)L)8#LDHe@ks|Cdqi-c?8aE!#?F1p|T z!^1bH7w?*NAA8qbUb1@Tr+rbe>I9V$P1Zu*6Tn!^^nrM!oek?%iiAZx89WRsd{Tp| zoor4^%^LMlL+0xgT9wSA)UajMY(16+EDM-tl6;Wt6=cSqd4rc`7M)U`;n%;V0Rkz7GA~3L;F7I_;-QO?|dX`gEvbj0VGr0RS z6sxd2HnRgUPSDe@{>jy-(cAHmM!sGjG}pDWbqLvDE%#D3SvHNG-+OKW#nEb_SeYk* zm-n8e={~9FS4xGCIM9>C$y#%aiR#k4m!O+_lA%)z0JSO3t7P#POG?Y5Ldvo z8tz-H-3}_CcT;a5e_K=0;0UV;9>8CVsA(hlLhrJ?80RHg{hs}6YA&u=GdOvPb|L@# z6SEMIhLj#+7?dkUgOVI^M9$m{rIOB_IxGdr8~c~jnS*11@^bV@cwVev$HJY4$o{MU zqGDiG0UNTs`46PC!ZX>g5(w#KjW1#tM9+%n6|F%zWtR#~l&xP=B=;&e!2(NW^G7my z;f9|e-e5u{VX)yCcLh7OyP%ksMFjGLfPrR2@JjcAnM(B19jMU$fJpXr5p+j(7^gxV zv=IvGP3!zDMySGjeEGi;Y0Pe1$J$%?HieA$?o2sT|PwgIHJA6 zzH-usZV)LRUCN=cV9B{+Y1iw`yx_E3lFF*TtSfer1jIbP!p=? z4K0Wa{H3@C*O=L^@|~;}D3Cp8NO6Ba`eoEXUYG*I?d@dP^+oJ&WW$1@Q3m=*;ZZckcu3xHWf^=Ifsw z?xxvxHxAg3A41>D+kd@~{a$we|97}zlK)^?Ia3W21IPch;}*3ru{QpnJ}xC0C4f9K zPpt1OA~mH*Jte+402Ol3K?nyY*q=hld3F^ewf2GtHt}$>h~g(-fAS{;T1R;dv}(<} zLd;V!Ki78{f|ISIQfO{$PC-Q*gJtPxf= z?nUlx?;XO)Bz-45!{WU>x5L$sxQH%mfEKF}OV z4{@r9c61ao$JrKr&^2+DpZ0(71;fUfWR0D1$@&eGeQ0`qIE2aK1 zMSgW>Lh%$0uHjC4ci%?P;qjq=bT%X-AGUaf2T~*m#;CyDkTF1YsQ6B@a>}exMIb;G zM~R>}Y zv+R8=+8eAnfUbOAJdStv7CIwgx*vb;IEIu5T%Vc>%~LC_uB~e~5^oU_-EZoLZ8Yg< zZ5pOY;DAe~Vt6_hhysB_wT!a`UO+vyR7D7}LB?t|d#$5Q(Pqn*&IN}wTcyVwEKV90 z_f{q#lH|Cz>`xYsmC(1C6GZs0LmEpcmf0lB^xQR#xe-5{TB#Q}r4`BK@=8v3hOS^r z6DA37tGsmJq_Ahvp*Y2I??8#o=h6fl{}fVZrT;AeO9e)|7ZFkkHsm1F@A5Md-ALRu zHOQbIprNue86$j0f}t$lerUR{lj_AWeCu-w5RR=7UTyBAEH_x2&IFEas=XWZQ9(C_ zf2KSvi8~{-w+h9dRVF`J9}S-KKFv~w$yH2d+~oaaL6(gXCz5l;W9Tzdw_YfT!i=z|l%<%wE8T})&&yp=}rYT1t zd8TIQT^P0n$re$MYM0_F>cxEr7XK9XXVq+Q{sUexb`PeSz%xI&m=3G&X~ro|SS==3 z`H@b#>{cALBXdAGGRrbPTG|!9JNMTadBf!GQFNX`9kApf2~ z)4X~0Z5?_9-#D`QkM||-+qusrk5?{J&*$Bq+>gcWjwm>^M|b>uCDByy^5wH$P3O*V z&u52RtT%_>Cwbu0d8rZ)an-TqsWw1tEd(R6m`Z$7VI&g;jWBgE4d~PesEH(Fj028g zBtwX1_3DV!p&B6?F?CUO+~c=d;M04c@VW!DNmaY~4kbp6y0>|7!#eD}Uvjs=atzs~ z93*=tkSh)}C6%J3sF7z1PI69(AQquP6GLSft;&E?<>;W4N3XS4DK)^b2_$W|RBN9X zCniZ!lduuN7e8~^D-BP<3s!%983s#1e!M3n2En8yDgkgtP)SC+k5ys_u;Iv7L3)R& zCR0EOt7ssyjX|WXWhY`hFU?~9BZjfWR#|38vqWFQ3!;l;Tqv2Eo@Qc}yC@|Z*Q2lu z)Tg-P1nI&YCxpBE;;ose!kz<-pj6TgRJCJf4MuMpNbw4DvwC4~;e8t|hyNX93wvT9 zfT8mI*RDroR|dvrB=PA~S8x z3PV$bsb!ci9HiZf3u!Kdx=*%uSCX+-sT@FaM!0GO#IE*Hy8t zz+JMy?ZSsUSOzWDC-a-m~(A=xEmc#0$!&FWsxOJn1YWI2o9d1@iS(HC2S^IOZ?4$S3Eu zS$f)LaDrXGR%fl+KXoj`8GDFZoY0)<`w5X%B@mtHHLE>dR6trvTCFF8j+!k_lz~}j zbi|i2K51+7p=G3ena;{K_epF>v_8bj(NBR{$yJt+F9iUj$lqQpvj`>w?+{sxf>JSkQ zTRt!5cMWSk$iX%Y7&)^n?pzm+;Un6Bh%nK+h6$c<`;$@;TSjjrC>MP{s}d)9_Ot*S zJYNjY+fVYhxTa)FrR?D4!hnT*f@r?&u{V_u>O?@rgEuJ46pwU|xZ=qYc-;>Y_0Z50 zvr*5RCZOS$V?tK|UbZ6hEjy15KNN!ead+gzT3m+{nl%2w(VF3Fcc~L#+z24(%5oD2GX2w3kp=VK~w=+K{66eU2##t8|{+39w8+Of^ zy`E^uk{8k~%D(&PK8Dy34Y{#?>q#*(ezY@_u_iy92u(?&E9gg7{PTnh+Qe<@ z_VwF{y(9r>(7M!Z%J${kBmt=qv`E^d?&aIX0pp;l&^5ob3Eb1SO#-Mu)u3t+wMpFD zw+{j;LDisj3ET&r3GVa5nxLT`5nT!+Sj|};6*SI=U9s~5*u!*R^DW|V{UZ{Y_pk$; zNi3b4ANIfm+XCr*17rB;fAcYf^^CmP2@|79Q@|_i--?`B`vo_C*lt=*)67d>*>;q5 zp;K%`#duM1IC-eK`zWK97yi+U^F*+qDEz}EZgcR~k2S|SS4LBoQ<3wyEKBisDW_dwjTbPLlUj7Y-L$Su zl8-*N)zFRnEtgK7gzcc!%6>=m;S$5 zBVr*JXFFFD$Nvk$H>=q=BOjpnnwmByQX@gc!3O;T1`%(_tb>pQ_U9J|VI|J{#jE5m z!MO4rakuBIKSMc^YPc{LfdUf|K%<#2A|*J38lhR0fy}$p*?b54f%j@dxvh&O5g7UZ4b^A{#d%VC}vtMmn{@``f{>97Fx$una zf4A`ig}S`b>WQLw2A2Dya7?Zt0`2JClX{I{aLuk|z+-l_jIM3Cd$-$u%I$J>-5{@# zq#&`6lIEIfvIQzhdxf~=n%FB3S%ByC-@#1`V3cH;)S#hzr}jRfXBk}+2BxBW=k|`n zOfj|nrS$u|9a^;w44`Fn5ALmmdxuCxKQl^R*j`VK_- zHZy5a@s}aRX&}J_5n19lNIZx&H+kskx|wu)HfsDXSQ7c@z*H}{`cwsadFYLsZlqeS z@FesMJuFut(j+1naxMPt@LCaf2p#fDGWU>SPTVF24Vjjgh|)($^=P};wBf~)9M;DQ zWc09VE*>2xB$O_(Ny>!u@L>73RHNuT-j#>jD(AOgq`QcRqg7~k=ll;pY8 z{cqfI#5~m40KetGp&M0HE5v_Qk*pWU`5rv^wXiPC7X_m&8*|Ag_3CeItbMlBtc;fd z5gu{*p=Zs%Yd{Hsi*^w?okvR%Y^iFfZsu5hltZzaX$etKmKLrQpUQH~g`d1m18FMs zDyhTc-<{8MVB_O(uT>aJ-IB75U_Y={1M|fv!iriH2a8aaJfu#enq!s-t#THvEU9t< zIF{ssHcBTpx1LfNBRkTH>Xog{76ddi1?iY!ybeFQIkoX%o<}s(jA&xOQ_i&_evHIZ zt1{JfKu1W49z&5q7N0{;b+2MbJ+`D>Ntazhh`w+)Oxi^*vlFt(M>-30MV0GgV+XT4 z6%jK4s^Zf!x+YAQB`@h=_1)PgW41g4ZwPCk8(rqiqs=F@6}=S9rfHadc=Wp4fxKha0R{EQ-kW@ z=b*uLr`7GzyDRtIn}{ZA>#h_z+h>fsu>$Ss1;-w=Ls<{}m1(Xr1E*~t(c4;Q| z4nYsWm=`Tu;==gI^`0}xt8C9k1;G@CPq{|~inj+3^@v}wjYR4udp&AorYqmf=x34z70ut1~#TF8S2hf1`Q5;V@OX< zr&PM{)hES`6++(-FUCHUVwYw!6Mhm2oV_;3jLYEmQ%AL|uJff6$(QGbRQt9Gnio)_ z`v=#2wCMsxR$Y>AaP(sm2{DOQ`71ZLNv&J`%St2kI*$)1v;F=o)gW7FkhZ37Y z4(4vzG7lURQaqLKd=9z8B;vB08Iks#l98u9DJCDIDH2lIliOUwv_;Jf{T=s)F@R5eY6Y6pQ7QCTf-$j@}!s`>fF;I>WQ=s9EP}wyi z-Uy2>aZ@r!VQ-y#3DV_K8ZZJmab$dLo=F2GGvPj3aFo; z#1#v9CgylRRyYY@LZKlMVb#3bi(rHmK|XJb3?cp5SjH(*k<%-D)0A(SS#C*sQ7;F# z7$?Rt)?psL0~#PxNYBG-;MuisA8Gtb!uZjUZz&Eysw$yFETZD>#bdI$M%#Zf+y#aH zA_?^K3gC^-VtLmjsc2-8{VKCL8ztO z#-{F>$ep&rveS=zhLf17G%j1dtuB7z z?LEwQVwlW`gokJ$cKiTU;8@zYG15hn^Sr!8KS6$EB7Df_XMx0^rQA6g$Cw)7i_We! zI#fk1w4J;X%E#9ps(!Krx5QG zRlZ9`j>I0$X6)w4y`#z_Y37K;%%U3C+^uT3;D|cWWy57XGmI6YrXNM zes!uiF)I;b%?h@Y5cQG6-4HfzVl$dTNH}%huL|N*;`0ky_C`t?=?gaY8BaNkO+gB0 z4nKUER>C}aP9gyJZ%NO~;rb3HmeC201i`V?XoiK!B%!z*AihLd!CMkVqa-OQ8fG*c za*nv*64PTHWf%oT3q^)RBJg|_?2%FT@uF7`?bJ>=QKF8{LxGzcRgbgH{!n2?4(ew9ib(TnhEL zjM80KyvW#$eEArQYV~glOuAqO*%Nb|!CpHPx3>{(m(et53vE7c;yPeTyK-HPHjq&R z><^w4%f79z-(y=UPHPx53?b)iv6qy*(N$i z6u?%J@Hx!IG6V8u8!wS8ZqwSew3MCCgNEVZO z)S;=&`3#`ouD-GZUaO0`=jVOTzL;_h7oXxEKI|pI>18;@Z}3Eeor9|Q1hwxQ=bLmT zTiUZ5CS5zCqwiKjgBPK^v$k^xNXBJGZ;=z^UB) z$m=Pb0%C568;Wcd0W1j_gAOdosw~s-8AlS68n<3_d|&o-zShVU{Bl=F?l`+&|Cpgd z%cj53zKLUNw0{RYIsO%SENx+9@qbYr#Q%K$FF|0*DmqG7Cdj^UK!}UQMezZ}@+~+; z1kgo#mNa20KQLkP5cy~3Y!lc!1(9f}-6k*|!aL&=TO%4c}Ig&`ZqV zO7P+d_%`&@S8u~kkh>$YYQA#@S>%-uGk4|PJl#)s=m%$Wq= zt;b_qsrEhp{`C-Kg}K;a&jYAmnsWltBz7*vUb}-`(_^d3IDX!Ved+o9RD8>su_)<| zY8+P8^1dD~VROu;&u~~*bR4EYm)NQbGyZeV*^)Ssh60cS?K()}%{Gj+0I+^w^f|v< z)28DXEs1M}=t$PQ)>x#LvNG#L4m)Hqt8N0X)Jv)$@gfsTyXGFn4$DG zNY)f_ipYTa*-n2;3AIfuV*j&WbZP}^s1ZT9R$}(u*vxO^7!O%52a_VmRk-3=Mqn7h}#10vtlFBKBu7O$; zf;g(W4+)5%_n2$pq9_)R7@cE07_krLN~3@8IFM#mj=Ko}Z96)_w8HdpdxPvWNq48d z{xvJlrZyHS*d_oURi5IR>sjxxb%H6F>OECrk{%T!?;XXa)HW7)(-_m`Z#HSA04#u7 zH>B>a`4^JAYTs3O(+?My9Sc02ohU3|i3v3N>C8m;k^n|OO)iMa+p=F}VE^_%AV(zwf3UI$O61$e=kLx$_4-N95u{@or#Z|?&Vnb!99kKGb z+2sFvARZSIf|UhPDG#x%_7ZEfNuW%`MSD2LciwxwgpZjBRjZ3{sdrzNX1;dgj_7aQf*Th>ca?` zuCQ3X|20c1yF`Bz?PWYyHRyMf`8LF(cUi5L^o-D#KiD3f!YGbfIEKttSlkWwUZT2L z4W)==M4hO#+c;*HDQR9}CD6z^NmTBSWG0cJT2vPtQNm=Xo)pJ2``c*-R{-d#b&=%< zU4T2=EjePa;^SpuT}W&-jfd$GY4Ok(U16}Ss8-W$IANUSldqiKNdiv_5 zjXw(x{ye5Ekymg4Gc(~LVQ$l0RAJ|q&-ZkuS6kAlkWKThhn)UL&~jwG>D(`#SP zHYq_K{GRYA8)qJR_mKrnkeP%WYv7&RdH866o^PTMkaNAwepyg+7T`&(0WqKb9{TrJ zmCnYCu~jJBdx3fT+SOx+pB7o*lE#+8H8E7q5}T(4waArbPo4FuZe8n98?PPd>k;xo zD=x1pET={F5h4#6u@C#_kDD3|gXwLs?#8`)WH^0HBzO3EtsTn*Rpl3EyuvT!&C+a( zj7h-ekLdmvqB=G75j`LOdAwbkL2zO*{LO{Td)ci3$yknlj){R105hXN&TDlv9t?|{ zc#c@hPcn6|B4XS4{qGhq2dB7WaN}F11ZNP6w=P&UK|HDbAxU#b0#*&uK;~$)TR%dU zFT@i)1{MZ%8PTth_as`DFDRieS9=k)ISN`7!-|AQLfS#^qhsuPs%+6ikG>U_1gDR< z(u5Jt(Q&ff_mur)B!V8Y@@$AviNmgXto12!sa@=Zr80HI zww$O};@aFFZsHC6gP1#}yHFC5%%riO@%zBM5&4bG5t`_TGpXn@h+l%Yrs_AXoBx1~ z4IZP?*6*Vs^xHo3uQ$~^{|apUKP;DojlH9Zk%g1Vf2X?!)g-L7M9@EVO|geB*P-o+Kuulb87;ze$KEo}+*6`_71CrVC-- z^J9FH&<1*n#w6IU$AvGS4vD{|f${1O6@@(Xiz?68>(U?Y^f!;VAt@&w~osh7j(%K(LA_TR}=q7udTsNlzFpYkDw%{X_T>e_xj# z1u!GKfUIaKKTlF=QicZ_-(WnZqh@N8%Un@T+AiNM)9{_Bk@)DKoeB8;7b6PNTA)!g z$7R<7wsWbdJlXQ9A_^rt{zq*Y%8s#O2^gX$Ck+62&$1IW3&|ZU8u-YeH#`#f0s>0A zuMwD&6r>=Gg8-D4h}IsI2RI~w)IkN`9~xLm(o!sxpG*)~NAgtFw>wX()9nH&s5D1v zv@Aa5=Sq}^PKkBX=i71T;*>fzencwoUQ$lfIHE0UttK-jDXu+NeMN)EBn`7N7Rku4 zRD883*7)ZSaO6D7epLkpEFlUEwsN^qL^t=rLxON8E~p7RO~3wx-2A zw}5Nom`!%7gYQ^yGV|4T!4BPI+oG!f!P#2{MFMqOngtY4xVwAe?(QV+?(XhdxVvlN z?(XhR;_mKJKmkP!e|Jwr$MoDA6BFw#U-ISTJ}39y-&(FO_Y=Pw&$M7tE@g7~`@UCG zD|P~@C1bQ9f5+zd$npJhSc)-4V>{J`&DFu?4wciNDQ>}KPe;xV*WZQm-lMhL3Xzz9 zX;6>%?x`$GxGL?#w55=t1%jy-B$=aJoxxkVX3)OEpf&|)2tVMC;|+IH5!6kAso2jk%OFO{A!913KrOIICcxh78x z0`3+Ilx4YS&A#yWKXkdR`PGVAJ3@xQW4(#F>_@nyny_wB({epTLns8VZy@#dl%~2q zEC2IulqHZ?Us$vs1kpQY>=kdw+RNIAe?Rd%iqSLL==vPjoWF3;-zb|a&MnhEldQji zI#&wQjXv!&pM&7kwoEY%oHDNj0cJTX5xo#0nxuu`!N1!LFN1Ua|K7cytYHc zZbg3C_%YlJ5_^zMuNvj}IOb`P4XhsGz8p}#7-c#1)Ayn@b%V8ekzu}KPD;h+=@r!> z3s(9|JZNrY*$pI9O$w$5=Z#(evT5~tKv(7N4^5!hvvWkbQwQ%wXz7mq3B54LJ3k@1 zHq+&paof+_o7~;?KvaXT==M00e{u2;g635Dn;NG9cxAlMHJRc&%n}K>TZRw;iJ~OT zk`p+)*v?Z?Ka|@~d)#d|+sR;5^#gI+j3#$g5htBJljZ@f4a1z~9viBS429+fwgqu% z*GSa!rAl{A0%xicCA}aNCBHSK-vP2j@=B>}^L$ZJ|I-WFN=`AH`^%=57vaCF(NzCm zYV`jce2-|t_^K{1|NAvD-JLl>79s>r5+Vi(&k6%3Hc$@;p(i0ptH*XU%J2e0QL;K= zvaRS9uhi7Ev=TEc)3k_RrU8j355NmoD%~p7uQmE^A2)4lv|HR4@*a1lWmqyp=5JRG z9%XKLUjpXb=lEapd>*&b-=85egc*62g8n6*1n9jA`tA+h-uV;=q?{mue933VK)$3! z0q7ShRst>uE+0VCK1ZiV3oMU+2ZILpZMMFVb?8BGW?~F%Nh6^PDHO44B-z1N3^8Ql zB;j!4N2VA@&PG&bw8fqEQ4$fdh_oe%43i~Fg9%hKmII?dYw_iQGTin}Q1Zqr?;C=pO{-O9Q)pa+))sl`Ubu75@{@JhA}M7o8nH8~=h3ld z^OFfwDR(PC?PhC-`OXcBByXiow&fu4MXNA2Ry|kPnWPg{=v+$Drjksuk1|@-l6l?G zlgMjQm=WIrtoA#~T#_6A;`vOL*7=FA-Sn(-ZQp-VozZ57k%}^*+LTMq1=b;z7}lYR zZX(NYEz0Fk1+%CZHX=2sl}hEyA~h)1HHw!ZJURuG%&&p2D_zJK?|nrGAb!dAS&R!l z94>=SypqdQ^JG^)kw0dtX!JzVZCY8F=l-OsRWVQ@8+52TA+VE66c811^;SWlrVn5^ zuVSWx7<6oI+bsB~~FtblCnKcn;&i zg^0>PXwNGs+K7-@8~SB?JOJOZMEI6fki#-OXx_V#hXUWK>9pe2s2gB91T zYLEEdliDDZt*&MAW0qpgZ&}}Xpaw*Q0iQ!#hMfcgtMg6ZKfuuzl9UOLUh`4cq3KLfG4QF5d4?M4=o&{Q+|ZiwMT@r z+?7oKK(&W;ej7Gi6P}e4kAC=~`D%n@G;!?h_i@RrHT!?}F>yfqg%205G-S*w6OMK+- zYvlJspAfXT4n>wwosvHSaEA#Zf(f&T7)X1<7)UaXhzGz_caU9oEQ`H(Lud4@(K)Z| z-6nSqSM`BecOi(tQ+-5sgY?R#7uq_(pej?Xsm6GLz1%y}^P6c_$7cd3Sa4iPq5F!M~ z7x{|N70FERYjNhj2;(Of;^7frz>T+diG|oP>*#mHDp#>i$&h0$9DbVZqR}%KXZ5@O zM;6DDzQmhREbxl)*ZHHA>P${%Kr8}w9Xj3Tae>L!(rk* z%vVHANd%L9z4mPAH~@ztc!$ZAAZJ`$6#g-B)@`HQS~sa_bFe_uMzl$3Lf79xQq-kK zh^5#73pcAHYszl8T1!hw$&j{cnGu$oWqy832b9x^T67an^szDM9iuZpzeY#e*fgrVAR%7<2 zz1eeptsQ|B@*r!)_Kn55C5ORmSu|$jh`E=`4Hnz$BF55gM`)apF@pN91qeT`*~=uA zJr?1Fx`gbiL|5d;4Op3;ai}CG9##{@P`!k(_;BMiC9{aI@fz<*s-4h z(x%?h@D(QG!hW6HO4~RLtbvNU>Rh~#XKoU9i~C_G#~(-Y(FqI7(7846l;iPuxakqpZWStO-azViDvminY& z4DY9-9#RTVdsPAgNe78>#e(uhcnJZwaZDf89N0hF{=)h3KZ{+x^@MKsei-0@ejh}! zy0IENNR*rj1getldyX5_KnA^?^YYY3wRNm0pqb}?@A}5YMCfryi0nVi4|g-d<%Pn^ zub-C~^G|i`<&LQDhg;U}&fAMo?i^`6_uu#OPx>&Kn^C&Vy&Ydb{ey?IxEHt<8e09s zYTCy}vVnLn3>TrHga}rf`zLsnrdnHtHEogmXKl4q|G6o18OceOof&zT5S!Ucs49W- zyNI+fkqX_|Tt>nAi*mMs-89oV92_Ad$QX<`LC9N{r`sZfQ=5uUFjD z2;DrZVm@9+@DJTGIKDh|u0Y7|Zk^CZyA@4>iKdK3?r;GZZB%HFgt=aQ1G0Z&Xku>M zJWQ5g=TO?$Mklw+@2YjXnYi(b+p_ zDP4_3Qh%eM!wn4w11cIZHsboH1mfF~4t*3sM|tzH%2x8_XM>Syt=o5ZhL8|sRknkQ zmL{xJ7#oB`*f!y=!wb+iM#OHPti3Y(g`4h=a=3o#;ty)_ zMY8aPo_pe|d1A^qp~re6S{!=mgRr;)^+z#0AwBjqa;6-dcX~&Ryd;qp0!{hSom!=F zb5sWl_7%4V_e*Im?IVS?RDf8e>RQ{OD+m4!vx_PpFXN-(*rD-?Aqt*Kh>bE~piF#^ zeSl-~UzqmnM!s0Nm4{JE9dQ#ZKBR1K-NqDCNdfB4k7VE<6;1sd+{mZ~J5Bm*&#WAxBTta^Hyb z1`P(uhipp6gs4POiWtKEalD5TI(l`2Bup4tg|?HEXF#0-&4UDGx}&}`&FPBQ@cO%< zi{R13S!1t(6=t<74L%!Q2U~bkdz9p_(~;IQ={DAQQF&B9Shd!naq4CaIl$~{Jf6DD z#B9v^GdS;y#ZF_ioRd7|y^8Ed>k&r=#b$p0j*oo~0MimhS9ONA4W3E~fyNT@M43NL z5dzl|!++LS{e-B@=fxP*6|bp$e2X~5J7yF^?RpmWX!qyYmm*Nb$4^$cY{va&v_fqi z&DLW;D@Vtd>MC>{8oqT4=I<+P4sb4%Y<(Rvp1TMAGDo1=kLuj_=Qh0vg~j02ktvoT zxq>@{!ZSX4B2lU2^+1fsef=^M zEsQ61rcrX3Jp6L4PVX!Zo2tr6EES%kFgd+cvF{T00g)QXTf!Wa(07^kNES(M@u$er z?tAD+M0CGd_MJ1I2}F;>VW<=t;>Ucu>{b zF0a_7=dEt--NM%2XCA#AWK5K}}b zTS&!)_k8He6T!n1BHrmM{J*&8b=#?7;|pMdF|OSxj@t(?|#iPe<4|3_{*WI z2kQ!%vfW5q;0Z%D_g)%KXRKB2GLO;yk1-yrSq{ZZ`N`*}{KzUD@Js%9qu{TWM;RKP z?1%2?9P9m~?1%3tXV$9(+6znX#4u-Od%RO$_aDr-Hph0$xayEwa94MG{jMc zlfG#9);bSoMs|0Y!}P3!^r+X8&Q~+aspA+ul7kPA%mHsRDzb|ED(t>2@86Gm%Y~=b zdUG7fx45IN$#MWV>chX{NfzK||YixvzO;^E;6`-cx@BWKAA0 zOc$$k*Y$@yy$Ps5cz5&J8S)PMY;Wu*3%uo}9t|1((M@OkIdZpTLPU4&@7U=J7QScx zanR=qT(SmxdT*=(MSY5he^X26cP+vEfHvo}uv!tVI#;gYX5T63$j%ce(svqSN)_n; z_(EXYP`AXiO}EL`)3wPq+aBm=AAg^U#f(4Zkm;Z>$~5xYU|D>?n>tTZpm(7+&^|HK zqK8|1Z~J3ymSd8fe7Y8aO3m-==yABxJk@JPqH=4FnfN<9Mc5QZr4I)*`LZZ(o$=O2 zQUi}%G3U0|<~c{FhS{X51tOwjpMJZ2jfYo@1v#9s`|kav+EHkn1>J`Cb9I=-4IsVd z{Q)?8*C#8~Z4!z*ZD1hPU3`l|GnF;(ig7j#4GsY#xM^MaC_img%%Jnj_>eb za!Zf?N${Wf*oqh}Ej-G%Zx(?6uEFwO;#&V>KBi%2X5;l=;96>OvZ@;BpLx@F8JtLp zMx#*#&~!BLHAUryRm$Is3BD_dl`r){y99o4383L45NW6FEL}9jB+fr+F^Bod5j2@cJ>kEBC4S zYDmI35RTVQMX|4wuIJk~8G&VC5L^Hcy(Ijk;!PQwmdl!35;r6n#MC!0Xa2L)LJM+k zQu_C!8!cd*w6ko|A+EesA9GI1aDr{$(d zouf=8vpR9|89S1B|Jv$GMz8Zuy9B(&<95f7s?|Ylk25>G#+4>l3P}#IHlNoTR!DZ< zjxv)4L?Ni3E0mKM#m`vXtRN0Z&tz#rfUT?|oG$K^3@qa&pjta{XQgnoRJLlmW%smBsFgLZvPkI2CGI)FeEsbn z5H^Zj`ni^DrBD`TnU&}d&UeY8ELvzb&C*z{I7_Lkb}iB;Bz!`hh*N}!en3-9MZK0R z8xL$Q;odoJ&p1F-2XLn~%Q%!_Oijc#c}%cJ#~su}x^6fJF|q!lND9l0f{Xe{V>-|y zO_q;Q=}P%28RJBjWyrBG`-#GwKp}mt=sk^#TvJMCzQ*8Jhg?P(V$_1IwJl>7&(gz0Dk!WoS?HFJPY6xEGZm4R0$id zOq{lH|MZV^=QXz`k6-QzF^$TQ7S2ZKe2wjBTW{4a$HC2=L2BK{{D*@qVPfH#QW=>L zgFMFJMp$?Lt6di6PSqUTjQ(%uxxwx36-Rc_Lt3nfMw_NF!V9@^6TNi0Ob8tXMi7|C zy5`2z(1~R<=2NF#l|$o*Q<;}#GBf8Ul4>qlt48Wff-a7OHwTpKgE(5l@5e2yn9&o} zt}rthXZR^xXMphW{ajTw`5LrQtY53T#@bk~8ucdvW7UD(_JedhO~m*dkKFX9O*!E# zs)hs^KRV3H$@}&h^v9&RDYokN`fyS5mezKmkQAt6r$s6<2O4$8qnEZqPF-Lz_@uSP zPWw&nOwiI?`q6JVkEf^FX;_4Is9fIuv=*nO3}q}<pH` zv*EByv2YZ>dQUO{BC>6PQ{Sjsw_2(p46Hh#cva+_wA`Fl;T1134CjgToId^3oW32b zr&N(XPn;?;~5_3-v7b9Qk^O-ZQR2bo=Y-+ z55gAvG1P6A9D(Y)o*evQhJF=-zUQfWfa3j>s~&@F-QDyAzs-ldEyPQA!q?F3deLgKsa}`#eH1+2 z^bc0&tl$ooX%9tm#3MSS^$o21^B#wC(J-`qHEB`%`5O4-H0u0hy)NCzK1F`Ui{P-! z6@A!&IQJE!o#=YHRljs}C4;#>wjCyzc#{R8nFpb{r&=|Q@Mrw2;Yx<0w)gtB{#5AYItUHo&CsU);A( z!bUrQD~-ONqa!>wkqNI4WH3`YvR7UCMwPTrx}w7W-UtHvSIy&t<|=oj`N( z)vafO`|mE3|1-Jqe=S?6xH?;z{BQeP|2L{;qxv6I?VkqJ4U;Z1@(~Gf1nhKvk(HKF z7JL>!3My!ijDgjI(D4*;r-KY6^Qe|tlA5~l{4K^9s^hXYN*@UEcwO$S4!Pl zJcKN?o+oOLY-O~qpKOoqqlGaZ_(wT2q?QPsQQ8j~!KrW2v#4gwn#Od&bm5w^X)#od3LvzVdNN#!J*4c;$x*c1JQs^ zXaKWS4Bk$IbfYYj!1|YbT1+eonXz4xqJJA-F6vQ1#X$OU=}B(tyX=hT)FL7q27(G6G5$WEruTl4otCCWqV@8355RRy)-I~3KU zLlclvRW&x0!5D|^EF!3|mMj)L6kn9uGNDX{zx2SD8Bb?^RY!P;87o1yn;u-n8zyT? zgmqZU?+63D=5iVe^ft-^bu&I@u5u)e%GA$uVpxtt3K-g(ijemEB039nzL0Q??wBSP zeWg2^S!%9$37k6WwIB&dgthWLw;Z)S(c~abN8tg)E7d#7MIAbaCSB8xVdu=7ZEByXGki0B)6d zXej*onIGl`GUGCS*M6|Q18uN`WA>#=FfA|I4yfJ#n%Goe$7>;LHE#8uPY9&rJZN)C zCipd(E!t)`LR>LtZcDu7ZeF`2_e^80bF#4JIAtp>t(S@+mqY9qoY<->D08|0H8inw zXz4gs0Y~z3O^MVz2Juh$bI3PyOB>9gR9RfDHoj4yZ{f05-=!4kn9f8s+FejvL}*jJ zlS3clXN`7Kchft_vlU(@dg|2c6{(Q-@7sQHYB%jnDhCmX^_J3&rSO9_Vxb-M?YYlw zXW72!v(rpCcC+#i?rKO-V!C~Vk4Rf9#Q!*kTxltC$h+ibuFer2nm2TOR#X@D(zL}7 z$_qs%6``To{b$rXDrdMUeFWL>==ZaC<#yo_-vqv4=A&Oa3HovI5$AF2as6T(&U`8= z3gL^NUxX?~0TaK;9?uI|%I!16w-S^eT(~Bbd;@g+hfXU9>!*S3%ko4BEe@VSRF><7 zd}8e42XV2~%6T}$xInOo3Gj?uArhFLR{y@aOmHaN;Dqbc=eJX7X%B^bcXJrlkOlG*-bwonX}A$~-Q(x^4PFU8!67G{ zb1SmEUwf9v(&bp}8k{Tyr77TGk`+5~N^hW>ka*%IJ7D!l#K8ttGUR3q26n zoz(XiA}%1$>b=TjB#{<@t;Krk4FT*bxV&+t0vpI)dyBxqRL>7Db9v|uN^xsa zSy7hWsV{4i{%G^eG6E8d;R{2rW{~tX&^wk>udT^Wt+0*768_uwRDI62mc8d3F9it; zC0AN5XhUfL)|>%b*p`Qeh5@*)5*No(b%TlvzM415f2mcLKN8ysfjD7>*`IG#j%_(t z2oo?#DZ91LXN{RGmYI2njh%EG1QD0g*AO_vQgtY+hvei&m5JVP3kUqcExcAP)N7y} z6w3++zUH=~y!~4IbQZcxrRn_Rr3hpCn(FdtuLeb;_@tJpY&AVA;7BKWk?0M`veYn5 zHEc9$WO~}Kt5p2>y9?G)wTj#F)`X)+>9Cfq`ww=l+xs?m0(DZ#>v>=)P87bKN|IAe zyeuuH!_1)x^1E8os&kn|9`C8;!9k3!U)XiqQ3<#5!?I};DHZOKaMV}no`gtwLD7mX zWmBSX}E^@owjKalHWzB=EiHu zMEeLl>m7uQVZ6@9DNHe(z#Cbf@9?68@E1yE`Rrz`?zd58PnL~N#D(*N?eep^MhMnf zATk@UA}Wlc2c~GNV|bM=t8(wT+LTIh4ADXVgxjfL?_bpw3lABU>5|6-rrdsAUgJ~m z7{^j_9U*N@gW=Jr4Ernw&#fU!F;0MK#YRVv(?xp(%uSnznC|{A5Jqq`7_~OY_@g$& zrd5ZRqC5OWT=z7uhh(41(_m0R`19X46;##XlaBgq$(3DyF}dlAF;szJ``*Vn@~xx! zuOEubmHAq?A-wwpkR3JZ(!4Hr8wd1!h^0%AbT9KEJt+CgPVna{Xk(%)3uHO&GR(A< zsl#lsmZ9gK%#$xhFK59bG3}gR-tI|+zRe{$<#-sH#*{H2Q zpHLzm%q?=+!`!su`>6tcnnfpEyGzS85Ob)Q0{pK1Wpvhm@=xi|xak|s4_e!Ao3u)( zcOABDrX4E6XAWeS*lD+zrI}u0l_aeGOd)xMO5!j9$yxI5DqYrlSQBkNK}VJ~p` z#4zkLe6Vft*!bg>9rksc7xF;g`5(oP9pDeL=>WP0KdRLA*`N$ELsimGYz@)6nZY|U;+Kf!QZEQeCLLFDkHDWohK=}F}zDYA*cn|9uq^0pw;BO{#)P%(Ks-m zSoam}c<@&PVgSj;ZiUcC^qCUiJa-Bt?}DyoUinJo-GycNWX|%LzC-vVA3h+^Se)U& z75r$@nCvgVm=mAu;e{>2hgVv^d5I_4;(&@bq`$j)7k_x8^jdZ=huJ&f0h2A+5L((6 z))Oi-cAu$a`-tMViG71J@*M4=H-L|v`7JW?jtQ$W15Za23|v-(RYwA!=fKJhx0*>g zG;6qLzc9;bNq_VNxTHkA=9FonhH^Y=R-Z|56|)8NxvDFI;Y_eRMj@q{`Vft->W_>~ zFbC(_E&V@j{|%aJ@$0_!mP7yl+5T%g*qfRDKRsb`HDNqezcP;)GbgfT^+ixwZBbE~ z_e?2`OcO_lb$*~qMI?PgP(Nn=T8*P(bvlWS*yvQXv$+IC!PV+*L7L^3D-D#i?`>F@ zSnJg2=-6F?wk!EhchVEOVX}wD{@n!Jbe!h+?DTwnWYOn)rt}SM1Ri14%drOw9Iv|_ zjMLjO8Jg3keFP4n&AZ{dpi?qsm@Yqh!m+)v3C%r2_LahN;k(xQO}4yq_F=-PaQp}Av-hdP%5d_GJkyMj zhFsw1SiAf0NQY$L8CgG)_BG(^n7SwLY{FK#{CvD%`;0vGhVXEAo(fU=%szP;v+6a5 zZrQs>X4-H*`|skgW;|D;U+x4f4*$}%3-smc5Y=BnAOt)eu-X3JQ~3B`9SSG(9iHoB z`cNC%{T`)0YGQurJH(PrmU|Kufn$d;e`(D8m43^f1Y}(=OP0n~Cns!jgH19gH5NFq1T|K|62|hA z=S^)M?s+ATfTN3xg#1~$Vf*l&@j@kPbV#C^n<3c!57vaezFcmK2Lh1_q8ZP`FuFzl zvrUeT&5KX!v2~2>FT%L7Sr)Xk9$Y-6kCls6Yzv%%6pY9)Ox%e$s3KZ2NC@b8Z@Z}G zF?ib4eA80I)i+s+DBOl;#ls7B^R>#^lxZGI_{^q@J_RHzbqFYUj^tp?k4{#n*BOpE zSsW$rZGnIj#~qbC#D}tHtF*qtxbN!S6VhVF*We?~7cU6P%8loCQDvw`&I39fYYo>_ zci#dV-ba_ki_E)Fae*%us%$ihpn!A)kbyq{Bf6({`5xzUwkF{0mFkm%$@<@>)>xlY zZQQ?~VV_vPE?+rjSMLdQr)%Kca%Kqr4PnVLg6=7Lk+C`Fb8_+3QeKWF#xyh)loahG zjYc>25DTJ7NM*)eoH7}7mr(7$;(1~Rh7yMM%*M^;aUQTAaKfU%IUG9}U@Iu1u;UB? z=6B5SCfKt~K}O_5fG{!~3D&Pypb@|fV8Rt;L^reme+++!J<5tt_R(41uh#h^BELTo zdMyTg5%G9A)gmt?r&wA~H4-M15Gt=T{IKAklwQbiLubY~Q{+#4`ITXG0u9j89odJb zVY|!ww2XLRjd@UHyY1;L5`Nscxd=ljwyMJyhTNW+maFgoRo6z{lmUxD^5kZ zIO1}F@7^MBxCC2k3x%8vL8$6x)SDO_>iw*@04?N}FLj~L64Spg=s|dq%rz4x_(a>e z{*YFdogp>i?(a;`EF0?6^i9lIHKO%VHTw*!Z9(?tlWPm^Wl|%e7tfp{>IBBkPQST)QHuE9RAsgOnFt$l5*q0fwDs2Y zq!}cQ(H;6X2=01eFyUF zlTtI0-Jw5t6Kh9>xsusf5F@M}2qb2U59p`OR6}da5U(N3nd8zWkmJK48L{K!01X9t*R&e%sN6o{5=ozLkiUhW9ib7n@wcJ|d5gyivducnnVC#X&Pu?bGBxEg ztx7aZ3V&Qt6Qh|lAJsn@55YWIC-{vw-ChKJ#2nceTpso*u zvx6YEu-Wf@e8Pc)Z?@h!1}?;5VZE@AdXw!wO7 z;s~j0bANMR$l)rl1sTU^20*ZR+ZH|pmI+%TuNf;yk&4PXrTuDUrmgHR7_P0Z zJUiCNq$}vf+sXsghPKdGRAUQ4_Ts`wan{r|(k8Z?aXZ}8J&e6t*wUVm;!YHAOFjbDMc6mBh^67g%)*PaQTs^!fi&n93FP@wLP`0g!ay2~iZ3)jkp@T!U=dDAASD6D zsU2woDQQ@gl7LZP3)(D+)VxeuNr&j%@<|m@vZJR4wd1Zpa{!BI(jf-7ev-9# zB}Hb%xGYd!@#s6yoSH=@X+3H>%`}eGg*>xrTo-sk&7zQmD{f7mSvT$rw8p4NH4P+% zBj;91M5E9u9~S{$pjRZDCXz-!FQ?m7B!RUpT6f?HY>Bep>ThV`RUFuf5Zn}1x(E)g zi9ov3rbgJc!*5z$U-jF0CKMy>D?J$^5svEf1-(T0Mddzaw#uA&%Ek;I8uR5LC*K!m z1aB9DDMY4vYBwL^80~90kvvDx-sQBT%td$I1+4{QjU0LcyCc%A6c!|NdPH@sFgnk; zDcbRN3~{3!e)6_=Bx(P~%YSS#!b(#FTHEd$A773FWoUw%Ipy`0j;rPBh_UKOk?Iy~ zUy`oeHjo?)QFn%sj+`Du&;K}YKK@ZPUUMnB_WF87XOFuyJ>U~hu;|BaY3^)l4#e8~ zn)C_xhzs|~3HOK!_sBH9G<+ihoqUWVUciD%Z>hS5Lx6)8Bh5kylZ`eecg&XP8Y`oF z43-GG!!+jsxb%1cV%Vq*#@JLm7Q{j&)hQu^3;Q?4)w66qA_K*dPgsEg+@~6I-W;i$ z_LEpT9tvVRzb4`~6Ez_o?iQg-&10_3vtzhVsiyE%#cn>nwcy3_h#dW98U)c;eLZw_ zI~JZaZOF3Hg{-i1uELObSzR&}C;D7+d@sx_>J#@$+t{a=`L~{wTDaYj@qZBiX&RE@ z^6V{txe8EY|94|4ivI>8F*30YZEdiET#h)R z`=%62ZMYGdNL03J?8#JlJBtHX=^(+8Sl(?{6Vi-!rq0CSP{9e$8%104gOjbt`&sTe zeh>eTw-3mEwPJS54E&&|b|x63Qa18LkRu8;#v*A3%0Nt%7SwUerDK@q@^AO)ur9mI z-t7bPiHAS9+<2-ptnjNmyQMOSZ>I& z3)Ae}sCTDtvf}1Fxlj*Y{qQvp7WTPt@5W`^Jb1hVNiS3`{}Ju=&?CrO@UZfv@2r$Pa?G8`U2%{`-6yYCh zl*K9%0FCBx?dC0iRQqMx@)v_ypfA zckDYTLp;n9p%S#>%^L7*&Jpv)YNgmeBa?Jw|AqQ3x91!BcJ@PTZsDGQxr6pVSBMQe z;yd!lRI_lKz9P-HRy_^5aB3W(sKS=s#nmuloJ#`EH4_O#6?POKF6a(V|Wo?>BYT{;bY=r^OOYt5BCkY#bnV;=t@S6sN#ZPmy!g#d}HRUyU7#!Jgr9&ZenD$J6XrsX2aI%EVA?`yv^O>v z(jX+s>v?4Bi_d5#okIxg+0!g$bKqIW2}9wJ4Kqe&L)q^ak=x_FV*kRHI#huW<+3zH zA%hBIP71Lygu#F)8pkbqN~Pkr-kNlhPrTsZwFv&j#xm+AKG<9 zqQnUFd9@}iB?PQ^Yc+=&`z@l!UE1a&VXTtl%YFKhLw%j=Bl-{3BHFt#d zRG%O5A7`?&+pM=98>sEf?BTBDEaS(`O|5iEv(N$$Lj0lI;CSlu95h=MRCaaMllLRg zqd}T_g_$nVpyZ1BKO)ttYfk$T8wyaCYHCH#G9W>*Gm{@H58C;C#D7m^^7O_0booNt z{|Vmr0zzV8$O9dNL?HNeQm8>yCs{;@$!9~&p=Bj@We=G)P7w}!`n|2Z^+a{XL~Q7}`0vUfC>e2{Msm-7-jYxmGR4@G^V|5Bw9!l^w9f}P>F0fwA$Nmz zz7nJh(Mzd3>7&KqNKAJDE72?AAm5gz>_9Q3Z?L?#6MbH}cc0P%yA%nmK{Ls$jLO^=-Y3I?N-HlZ6> z27K!R4+s_v)e9b4E`^y(y9}3ZX+st}>>gaO^JvDP&Jpzvxf#4`x>!jqo`hMx59+6B zrmO84CNLZZPNBh3O;ble`dcu7Fh6dC!`SaufE(Me&tgDnxCb$nX~K~(!SeDafY&i-i%m7}xI`AKBC5%{2c_ayuAKY}iy=f*oh zUmnO{|E;e)!+%vUgx~&K*suc0QM3UoobcOFB zLd3{FP!S>Yhi=Gm)*w7ML)N5w<~PcgF>i~a%J)L^S%xcH@)F+_6&Wxv7PPBcThuR? zUj!d1GT}vkrG=mR1?&cV?lL#szRZ|z#?SQ%i4_e$eAAOLC|hKIVhnKr$L~d$?>pyZ z>x2ILZ3-!$NLVn)AN=nyrtlB&fzUmPJK|yzPZZxD{voa*-$bB9kV();;0o|WI7ARd z7(_fm_(FU`2!HUSz#_w0-1*G;F2W|lheC(K zr-76|DT8Q)l7*6mQ}e0wEAnaP+2&mp*)5?gDa)bQ;9LbPIm$8FpxLn4kl2V^!O9Vv zzcnMflAMvwkL1e;r3azUlPdl|hpNc;R)i==DGtO8PID}XIRBx7OoKd1CM)!V1n}b# zf|RsS0Oc{Vo!FtIRALY)JW#1AE2k=!Vyb*>?yf9nDQ%jUC1riTwp9rX8fFvD#JJaF zDH&FNOp!{?YCY*ifL?7Dc&y21vnxzeh5TI^M}<3yH8v#eB^_OPj1e2@Nk* zLNgC&veQMxepzAG6elOt2CY??PE0-YLb|nS^DIq2LoYI4kTVfRB`cmgtz zF&Ed20q5FOr|yn&J%6sWV}6_DKcj%ySfOKdRp#O`s%kGcs8s~sF|F<_C19~z)Nqt= zU(1lyK1_0}Mw*wngpVnx7~9Zfs$B_@v`~;97jM;TMwT+=7R0TM;~D{jQFX#{^bunj zZz(BxM`I&ypLQ;58w@S!)pf;D|56{m5DI-l<@7?`WPyg1%~1@m1p}5Ef*z&ymfOh3 z^$UJl>nee8hSs;K2<@r4blY7N*jk)pf<8)Gp*n@pJ+O-mS)TnM-nu2G>8QL8<6MViS(b6y5R9_wyef zm`}uy#T=E`Bi4Cs;#8_4>1eBS5?&`K4U79ratf6d&mKR!z6V32R-$s$nXqQ$Hn(3X zW9V$8RLV6_P0HLyPWghrccukQA!`uXSN0qICS#IL&_0hQ{+s2GR*ZLEO6(_Z@G8b4 zHMj6646<@b_>^KK?hd(gPVkrMg9F{3?+|Z?*Tc>%=f9)aOSmAMfraSI`yxLf57t=L zLe_|SV()WU#{VP~_k`bfw~PbP`17=s~^M~(E zFkm`gD)Q@FMFJ2(wAjZO-t1C3LOMd5!kfZfLR~^W!al<9UxNNp_?K>jb|4A3GI&1U>Pbxy`G8iQ`L%Uy}cl{g(*8gqP1L1@?ba^ZaXNWo+qP|YY}>Y-bZpyp zCwXGqw(X9S4mvnlYn`g|)js=OReRU?IjiQcdCz-{Yg}O7A-}(5-XXfrVcsFT-(ub& zVafX@-YtK;#Jt0BkDWmf|00w@kmy-6d12zGaV%ltr*b@E;-_=`$Sm-+=*-|4e=DAp zAA18%W|+Te(ps>fl+BnVAY>Cx%U2$H*>`H+#M#dwQn!}>f9zUU-qgDC! z+7P_tPp~?(!?3$%q^yhdWVUUtBW;O*64B9jhRj`zP?ARSyaZpn%+ezL4PdOZdqGq zztzr8TRJ(=PK4=AYC6ar^s(^d0ap;O4QcX<;g@MUQZPb_miyMH?0n;Ev~e-wZCm&! zmuq5+j#q2q8eOxB*jDVeMwc&RVNdN^?nFH#I5qBnFPpEnFU)1yxA4y_>wY~kY}sE~ zzvQ%%?|4*gzH$VjuhwX=Kh?YD6*Z08@%1jh z$6C`hYsdY1q#IHEyILc$_S#(3RJY|7T?2(%^Zt8Te${K%vF3{gIbMBvc9CYo z_nY%vu;Y=Y8Q&4tHGbpjrcFD%!`ofh>nkGXb0SIfvtq{#E~g$^(kQ&(>M-htTRj!g{IfgOcA|i)>N%t zv%DEkM7rF$`FRM44PcHW>1Ru94T7IjQI|`~6et=|t4305QI^grG3BU5TD410=EE70 zcTroN=BJD0Mcs#JPohH@bz{=gBch1mEr22+!49eJ3p-}DO7fD^qccQG5BfP)JgZRd zQ`C>9Pzcv5A-Tn%R92}ic3_JIU% zOp>nrS5QvqP9VK)+EEpuBH|B_0#uVe1{K7iWh*H*azZ_ZO9k{a-G&afJ*e^sz0(jq zi|FwX0t|yfBiYUyD9q0Q|6va^DpfTwlZCTMo_l`p>5Rr5f8TdV1Jn%0%=mbwa3U-u z+!Q8&D!HwwMUfFFdFX)=CsAk;Q8x0YF;O=BUUYgc+JFZl%GZZ#;nG@TJ&fCex5aF4 zq6DzXETFf{h^@-F$~Hr7GqL^f@$;=Yff9-7DCg-S0r+Z8(3eZA=_%{_W>mF_Z7|cZ zRWV%H&1d1L8MVu|8`ci9C*RatLZj-I(2 zjq9C4KgxSsK+WR!7Z$*=BI82M>C=%47shq;Sb2A}mrqJC6JM=awp>a9K?WQI%Ey`1r06#|q8v(Sd z$7P=Lam1Iraub=P4Ji?4TshYtzl#~dMXVxEXqj(2XEwSg*p$dsCfAnGDmCSO3|eq7 z!pfsc-=-QH>Hd(0cb{#^J7QWnNAbE(BvG9#Kf9=H7Ft=D3FSE2w!_6O3u0{on^Mqn z8BS2Q_>vsk56E9_0;#Qn%zy!V0WDUxHmH2U_l)oBvvNFPmZgQ6`1wRk&selftSZ7w z7%KjR5e31+UiDK~f=2F&Ggk>ex>T5?AHGdR$o|5lA&RFIiX8q?u37iZ#EWOu_vadz zQaRKUD-?&%ahQppD9oeX5N>{%&DA=4i+c*_c_$+FMKcGJ*iUX3F#*BYx z%Z$zV$WC$$`bbZ@0~gfWvc{YebMRS|DDsK7B;WO)LtS_H>O{j~>#;d} zs^bPHj#6IjJ-5%3`P^*Tqunp(_gWN|Xv4^VCw5aFh!93Y1hSp*JF0FoorHW2~NJo^{=w zgwKDUv|4fx{0UD^x!7|L`cr!1=v@k6Q$hsLKQzi=T?XXT!x&8u&|7L}!K8P0peTIaN7@U3$f6 zP=X3cYHCVC8L=&PJ5q$T=2YbR4i`FD0P#q)=tRs1qmJ=kwkcoBe;U_|<8AMx=xDt#O-inJSab8Z+aWr>YUfJ&(5H2TEs&@{an-1rvaF%f%ATZ#-;Mu8)_Jq!q_1Gn=X{Jrw`^Yc=VE%a%T6ewn4z zP@bl)!JS6u!|zy8R?UizQ{CXq8E|F#beFLmek+UP$r9*vG=JuT`owsEx-LF2_3%?z zeqI?y?9?(u7*)-JW&$xJ>kKO-x8wxXD_2k9lzzQpmVUiv7J34I-I{?hZAL?b7v~QZ z>-h3h8O_p6afyO=7r_FiKirbun($PtLK3K%CU=UNN|eJ+(PYz3*!(Vv0+2~rZj zhq2=z{(zmZI-4RvF*!IJ*14Ecpgy(UM^wH)Z;I}koBT?cLIP4Jq(($FV_9ESx>;uo zmy9#?7s_nEMyioY`96Z{27V-R9UOIhEtV|Jc{P3x67A z*e-*=1#yi+s8II-M@V*z;FYoa#pM4ii`-QxIJF1b^nhOe*u*>$7A@r?T(hsNq3~X^ z3T?Dy!9#7_f;RfpPV&qG?hij93D#GY-KS6ZEUn?N@uM#Z`sjUC2WwNA&~$LBnch7g zZkhgRiJ7K%A)>DLHIsXYV>QB>-B~~5tl&5+;~nBI&cmj(Z1jOMV<+eZFMTKY1x#EV zXVlp>hu0tco`TUI@*X34cZ-r~B)$yl(w3cNc3Q#b5o)4pVzOzCbwnHiye&%fnD7Zt6upg5}B`jDjs8TH*g4Wh~ zkyQ~|x_0MIp5;47C2Xv6VbY8Ez#x0F{jG_iW7DDus1*xU^|*y4grN=HYjRgEyF{9R zNp6FTYJb=jF5?vr)qwC5xQ+g52Tys;1)2F+t<#RCXbHZ4Y+M+4{t`N zPJVl3x^2H3_y7*bZK3Gw@|lZ@p{O7ZkZq(Jawew+Kdh}|+9FKM5d$t&f#ww~Z{+$i zgFXSGl2yM|CgB>~h9*JZ38Eq9>_EAl`L3NaKllNbKL|%yUX!`%yI~KYd_QXcV~mcQ zpE+OlrL1Fy|8F+}^*^DX|4W1RA7NdN`gfn?A+%5VhAjKW7i3}5z;8r*@Ethl;D<2k z{Rx8XmfyjH)?e#i5@~JR2Jne%maVj_Y91?_#CWZ$jI^sQOoR8guzA<5E_7#>|5j5_ zH=ld6=qFCuLC^hW_{{j6%;K;&+wSz-0n6L*f(pne6dIt1qIVYFy~EWBq`~sL>{Z3~ zE81(3vuIt9P}510ZL-F4Ge6*di{lug$HDE0GGY0Q zvSR0EK#&BUL?8N&ZRc1B-ePuOgS*?k(dx!CfCq4A-W+n^7~li=n?1u0bOE*iP*_*S z5KqpRAfZrLALBP1p*<|TgEx!=0+=6TH_!t`fH)@J=^OBYB!E2AThyLqs5xe?sYmRd zCxzM`gkFCS)<@Bv7#staVsKhU&%P+0-t0|f=t}D=_W%ySo_lXVyVKm>+G8X_{B0$| z{T82L&zFL~H%#X*W#ev4v$y6s;uHS-O+5<5t{N2o-ktLHzyQ3@aqp+bDI>>6-rld! z83>qjP`toZCla$-SeJAfFtcA`f^~2qlaj8p;o?&kbuzq0gP?oyWJwe_>e>4oJZ-9k z0#@Rn;=jhCMI-9!bmWKf?|6^1*?7E+pPkrsEpq(6C5airvxoE-~(DN4d86e zs@1giI3T8J<+0L8v*sI@S+%04gc?^eiyq~1Dy5pw9bng(tLYJ$FAngsrbfBdNaIzp zpdpN+AbdnP?j?^OGnPc5gtFp04~iy~V`SHz(dD*XZM|no<79D`?RDYNH&Nl|ejJz3 z=Sv8Jj`3+2Fv1@B@L2X2|W zl+v|)ehd6PET}yiK12d^ysfM3QeuOMQOIgByhmRk&`#fOcrIrzuA}Cn1z4)SLjr(_ zMHX-EG*THHBRh7lEkAZjSQx1FbBc?Z(7*p&Kddmz*w`13Cxw|80n%t=p9f5C$6FwydD?2AvUOla?vF4Zv^68ie;x*NTLfE!ReHp+b zPpR1p*F?AG5C%8X%(ibvMoni;4j0SfyopU>dWP3FS(%Hl(^yvFWx+;-k zpvI7Gd7#c=P6|o$J67ApL+u*GsiiZspIe{QETnOZL(GaLQC6Wx;H-Nvy49#v;AU{T zrghi%&)Bky=g(ZWaNSYLZ1tJp8bt@JPM&X|Y0%L!T|TO}g1?5M7043{KRk37zvsp3 z@2i7i#@iO0Vf&7G6*tEPIbXz~9Al><0d->_jjeVxCHP1n- zj@s#7{t&T-yZjHm@VKV&ysc8N=ugVSYp~(xGHGB?ai|{E7B`eMIR&C^F$XJdLW;*$JqUYG^?@4TM>8O535(iV(S0L;1FI5_e;A zRv_pvL)KyP$%a@;#UtFRTpT1VaZBWnl9rqkBc8Uq-neKo!$KwiLEjsc);;q zLX!jm)4U;pq65+=c~QdEt0XH>l>J&B$APeTF!`U?N!lsx}*8dqd6q z2g^p_duu?`lU^Y%7yjuIINrQeXAp8_(3Ae5bUCaITAd)zOs@;fg{!r z7@I*=i-Dy>t(ABZU5U&y<$&g34DP(tu`=yR$QUebCCTNOOlxN~wwO^H z%8R+C6*c5EY!%Ha@t|sYR%dbszm?Q07PZ&Q)I8U^T-vuxE`1NFpC~Gt_eP#0xG$oW z!xO&m?}1TTUiEY4Z5(xDmE_VVUy4+a9-v_{jDd@hOEN1aL?p^6nIw`Xp=HpHp^BAC zGOH$3Bqq}+(T}l;l}ha^4U$D@Bejs?6T6i0Cd#Orw3F(IbtXJ&#E!2aD1JMs|k|$_G)( zhmtJ%l~JQ|OI!Z}AkxgoSaOT19(Z*#Fve!|`|&)m5cbg$eNwFI_Ix{I8E!&nZ%ZkM zwT)o5(Hn1KH6qej8Sc0gFn~2pg`5`_|TKsYs>oU+9GP60h^pUNRgj``Jb~Gh4 zcbubjKExh>jCfBpc9bZ}X{?a9fs$aU5V1-u!E_Gd=htOL^U$m)xzlOf{9QGLuH`;XE! zw}I5QGWYX2R6jy$1B`_;yxc%uCX|;$>JTG#saf}CHeXoTTp?3aA?G8^<((KEdgRqX z82Q8)9MywizZjE++ZQdK1U@QQy-*p&5XC}lG$StbaI{6~ywl}qyk+Osk8g7M`R+!2 zEy&N!^X|w?FaWVE_lN98 z^d}@M7DcJp)L<&?N^K$IjZ`$;P(%8l{{oua>{F{hzi?k7oc}gfaQxF)@oyH||0g3N zl{B<5Gcol19}rWFinaWL0;XSVN4=IHq9{1tsLNKXi$_|4xWp{|eInzFh12P@xYSB! zGs~pF9>JVw&*Tuo$2b3Qfq~~-JD6w)$)u-;&J)jV?Ysqjf4?{IUy&3rwfmVtsK><_ z>JIoTXtacMQ*f4c)C%zl_FAB8;HjAO&;5<9U39!VPB|^ZkYF@S01Vv`gjN(A=ME|( zkpr<4Vtm0@pI94 z_@BLxW(I3sYiw=b2$Y#t`-~yo8CRW+nie%uvOrTbnpu?5D%M49YCCC`P@eCb zs*VUxs=U1-Xx5bF>HY1I68VnR?RvU9&Q&@H)uFRfjFsDIMDIZxP1N?bTK%=m<-Xbj zjz86bZP&1Qr4Fn{vOy0Vxr}uBHaCJQqZ`JhvBGiLYFgJ7>aHzW=dQNFEtu#)n-^4g z-63ev@!L_^IH=+pMyI`R-PC*6K;;Wgrp<^jrTk!T554n9qpGD< zM_X*ShGQ>XjDdB++vFMKuy&klIPOjkv=(m=ayH}q&Cfux%Kgw}uuJ^VAD6?xL?SW) zvBc}|Vafg)k1k|zlR|nv0edhifCX;h4rffUn)uxQPUBD*Kb6Q*4){#h0Tcs=}H_k?dR^gIu(%B9e5=IzH4}QV0MwAlk3i))T zxO6}OV8A8RuylaYXQy^w!~9ZUHhR1Jsr&C!_fywX?#uNU#W$Ni{Y%PFdLkH+LcQoP zDAM1(LP+kC>4O~}uX0G&sRkq7q@5VoG<|=;-6N^i@zb{r`l6~2I3h%12_;Oo~y$LkgaaH zzOy~^%KHfoVvzZK*H7K;RrfeHM2fqaR3~e_p`76*-*d#>+x{{P(Ct_A3C8Lk`%&ug zs?Gbxjw17M?XW4)<}NdMi|it4(GLtq!96A7;o>GSQWMlvSz;q&%|BP9L%w=yhCy_L z(b$XlSrm%Q4w&pI;Kg*%|V)iLiHjd4YHJ%Jx2CRoe&2caRVL zJGGq%j`~(jWWgWBGF@enK5>vLtygVrp3W}c;H}HcE?eK?!u%hCj=e?T;;JC zjw1lNLwM2t!1UTG!+}f9Q#Z=FIXTlHl{N3CgkMI3F33@|iq%wM-W?={O-wQ9m`fyk z;T>e?fLJTV0b_WPgoLr-OB3BcZjXQ1+&$MJ|Ni9#Jx`^jH8={l@{lzEtEBqvLMyR( z905*ssLD@Q?KU(VrqU&k1v4jeM%)Ez=XMz7$^{vf1^i`ZgRv{8-WEQk6%db%@92&Y zQvp&`Zx^65uS&LBBu-KQb~tYp$r3CZ;Gw`GE=$O6_AOyw@;ghzUr;+8HJ6IL^1sGE zD5(u%NTL=x#wIDrq9B|Kil(Je#EVyEn{Fh%pqFXAOGS&$IctK#IW-v@`NpM?;j7vy z234^2vaVc^ACHS2ZVL07QejXA6H5gt+dvNyWF@;2((&{8hN`;hou}9v!@8+uN!}(Fxw6AKvYk`b1VB3?xQyHQ+;F3?ME=>jp<^3 zWg^^{V3upd00F1Ug*6kMoKRq*%_m-97E6V9k(PmlP|c|kGkL=l*gM9;5*R9vMzZq@ zOGVnM52>Jvk*TQMGI)I>mBFH57Y4agm`zfzOejtbNy4TSg4hswoFmneD)*s zyyr_IX}P31T;)Lr7Py)9lX{-{DJful(=?bJU3FH?RU;w<0Fq{kT9k|}l9kX()oi0m zs-00aeSR^;gE7*`VXrA&^wlsOjoUBzkf_V*+XQZwyL!~@YbwF*io-5HqOV)aW80=S=Os%4X8ZQ>JKxTvZI? zm+cu>n%DbbXYF*;04+Mh{pyi) zEj01Jtr^qy1Y8pjg-{=KkZ-6_L)YdysRYjyo)5TDY-ytYW<_WS;nM@Fu6-845dd#Bt6h1U4L@C0^D--P6@PoAWr| zVY5}g=rVyp;4ljrPwA5#Nt0njed7B5@10b?E;wx-8!5R%jPjiEbGcCeUW9;)62&6# z;Qsc@no^S#FvnG*P|l$zPE#9|F*iJ+Rf~5~AFxDad(Os~vKOan!p^`E`7YcFexMNs zT|4Nf1C?_VjtmJYhC;G(MM!%(oaxdC8L~T4sd4QxRDZV`q!h6#h~VS3rF`ucIgQ*J z+AX6g(O11M`TKh^UZCi9N?CvrmB%+RPEnTN)edNTBB*Ty#VP~Jv9@5=^wMnfpZpYS z)gHKFj}kdlrOSy(yM~~bfYB?&)Qk9&u=Ux<+zht@cL~jkN-H;1& zs+Yw+HFcO(Ih*pE6FWgmrCz>=rw{!Y{JsHx)F-u{zu~FmidSKFJwc;3VlKjxz=;(A0F>prt2kVR!m;JD-_n+LeiW z1)O=L7W&1`ztZY>?XKOS;!aLPl{XN^St)K&#eo5^4I1XXw8K2bQx6RGLR zMgJVX3##O-&Fn)H-56vI%WFH;&k@wcePme`1v7_da!wVS0A)2JPuns5&XEjpu*wV8 zk~Dm!slyjc=e#<;d8JH9wxYqU`(4L6>YyDlq4vP=Lx_Z{!O(&Ncij z#TdaMeI)2-k--_&D$9}q51creJ*@N4#@#5Zw}t1i$g#^jX0OnxzvRAT{;4Sctx*yDr$$A}*~ZZJfBGGf z%9t8D{7W{XVCdpv>SU+l>0tW*E(27g|0QbrxO!l+rBd)rmhiM1vaFD)5LD^afC*)S zLyjbEwJg1a17Mk*%SiWzeD;;lNAsW@fJO`shRoIU3=R4l@V1~TI2vXj@*Zb7_uRK% zt`HCifTRz~Knv->69>=;4+XbIG8NQ*FM&>pPe^vu9R?Q}Jc=#I!r63$+wdxRGGK(RQVfTu6q`1mx7It9D#rf1)gumO6BQ;L~Mu zwU+i(Sl>HZr!CoyyJ$aScA>!#fKBafzOu_Jex&?PO|A0lLM~&6MRdFTIPMPND1^M;wmAsY%9XCBdkPJw8d{TBTvv`3)edJ$Es)_xe=P|c%MT|dAt|}D?$!HOg%^utW&JJE5FHF@nJmm>XZA5L>nLHk&v4F)a zfyD;5{f_@o1YvlmeTFV=QRF%+JQ^3C6JNq3>3v=rPU)$PdVr*#M9`a9Z$1*A2sU!l zNfKQU<^t6zx(HFX7!!{w)O>+21vdpVbJTW>wD|7~jE&n>m>LDSyPYNS-4!u1<@+|pAdS`fd6Wv4Lx37+v zmZ(sSsx%KiuY|3v6iN)qxH`!pzgB?^i1ioRd`nz-_8jImU=+?c6f9 z;8L;7e}`b`dFu&|;69q8f9^9ESbe{S@z6eyS$ z{hAJoJObRoU1Tw9CRXDUOi$hZMPEYy7k!CCSsFk)HCu1-Z~9WIS+b|cpSn~5Hy%F= zV~Z6Gcbf?ypvt4yfysDn=&)9GHnCQ3f2^}5O=lLD?-Q3}WY$ZW!__^Ps5Wa2grAD=W@aQO?k{ z)t64y-I6q`?lik;^H4RlFk@=lTW{AaMihz7hpswP$%e_VJQG(yArBI_t+GK^157kj z5yi{hxPTT|WDpXDtd*F)ijE7QRG2h9cB4)zr`JPHU`> zS@l@r8^3YnnN}ESr(w!7qwX@-S+MlbP(x=)KcfVx=aUu^6DiBIhTQN)Z- zzc}gKpxd60KwF!SWrZ+kCPnr5J_F(n|gla5^AZb4GpD{L};x61_2GDgD&G2 zS&@~`I|hVFCR^MNwuZBqHy{e)Rk0_FZxtovxOv#2px#x863vR26EB943G=`liwH79 z>m}U!k3Uv*X;sW7C*=|CKtbPH^Y6+?!)DEatQot2u)EXZ?5_Ldrb=VZ{L)PLEsaKI z?=ibXeV7XKysNTHus9nbKsbrjOCj}Ci4v6}=^EFVo+wHGsMZIT0N3PWefR*bjoCXu zHH!)A)mX9ooI7|7`-BGwFFMczi4z3 z75a#;5vYI@DK}zK=IErK|7OI%)K-ki+847>kLv|3jQ}D(s{6jh`D$d z0GH6mx>+%ZX9@6{kpI;t0&w0$hmk0-_+?*VAs3 z#bT61tUQxhl9yvv3G;Xn37oCUE|&^som$7}mv;*^+^xQR+r%*zBLO1Mqv%z6DZL?U ze)i)$ycbNqkyAMKN35|G>)rJ)InCw?Y2DuIC;ljdhbDV^Kp- zd9!~Kj;iQ8Bdeo+>S_@7iZ4)N#UK|J{2+v@Un(b)iYWjZ$PkONy1AHvt+ZnGo4H{~ zylyhgjjU(9&WE|JmzE;Df5Ynu&@a8@n#kM@$~5GBx@zmW|8&0=`22X}2#{V4CydH~ z4t1o8j=Ql0&)Z{;qM98aa<{S#^pkHrajiA6&?Kz8@g#wkJ&$km*?&4vLWq=Sk0oT8%A_Oc??R$**yY06f!u_9S=$RdMHbGD7|K(6dw%lq**baArNY{GSX zgvvWJMr5?=85sht=qrVo>Wj!~jV4B_lI$QiL?=_OaXho3p;#X&3~fz)m0xWHKtsC# zv_@4%k``SNO~GHoPIh`fyrY~mc}}kX&ZM$#cV$$Llj>(#y;^wuL;pyq(A}piAAy;r%Nl@}hIXye3xh^{(FR-ieN;bHdcT>XR-}^~pS#DhIF1LUw z2pODCe2Ix%d&#xJp8bLMF^Hd>hcFog1XY)eMX3fOC`)Mq1MGDRc;`vqc9P|E;(7j(X6!8k&^; z`Gj=4=N;|xN0H!oZBEl|F=_M{N&~nbtN8O&Z{)#q&_%0IY%p-z^iKf{?X!7GIq#Tvz^5!6qR5^z*+)od08l!~aGZN&0UD-}yh2K}?Fdi;5U# zXpcQ|gNY`z7-BKU_X5#gITT@4LP24v;;rA?vg~VHIP5qMLok%9u;m5}gh3h#nS{_m zgtCam9-{9hP_dB`arkI)r%&5CLqx={#@Bx*oz0J@bDZ3tGT^cz%AxQc=Ox>xq+1s7 z^st58&BjgHBb^1Eh1>(LAg92lptiu;FiKi$T!Vb7n~5H5v&VR3(^DYg7*S@ zAh$p}rJLQzU&?38Z_0PgfBX_J;Rxbrq^!Ij2pyoaJ;KYu&qb0n3G|KXVn zSbPu_o;z=)`?6%Oh?QEVZ|v_2NI{g57q7`^)+Ne_kXc2yG8N6X=mc;yjXrG5dAQR4 ztewA1CsSnL%6>Bl{0qDXOhj&kfL0hTNwHy?kQIA6#lQ3=Tp=F0{b+6R9ZNWY3L9(P zY91@}WwRkWVO^eJB=YCg(e6yk!8`+t-0e6jUnWT>PSTyICa^`7F z?)lG3m`WO&9F5J?A#3HvKW$l+&bKd>*^RyB`*iV^f1-NBGvUiC8%UU2dw1lo^z5d7 z`KX9FBH-Q3QNFH9d~e4}zAl=hjD?H=`6`GQ2($ng!H|66SD3NkZM;Xy!}tXGZUv%%Xmk%2%<@vc^L+2$JO^#}gbvK?s7x!!-yADIluAP(!2y zjtdegK&!x0L#YN(3mPh5qJoGCDk`8J2H+}?l_Rs_vEreE4Ot|H!S9I)+|C*z;2Dnd zxnsRwoge0!H*u3bCE4_&K8H#axzRG%NSRVCk2oEN)>v5D`AM~1#!XayZj>5ZqYpe#(FqDP)v zMU@rRv571t&dk_HMw%khvY1m6rBMc=&kdv6iUC=~ypix^<`f4@N>53NH&AoL4$}*x z!fQ)U$qPHEoWyj@BJqj6G7HnfCuAK%!f9k3Q^Koc9b>|+W#_a-36vku=4Mde#dORg zL5LwUiRA|gl>z8XgQy~60G6Sf#*R4cIfXVmVgmb8$j%V0J2k73jdC9QGQG~=*Lyka z!43=7>r%(gG}>(mp>264enFNO!l^wG);xp-VSeGL7fiY%c}oa?aqAaO+d~Em3V$i@ z7aHzi{e=^sAh|m!?xCGo%a7ELLuH+?o|D%%u$EndHoDKjt!MMAu^tD3kCgjo)|2~d zol*ZAR{nuz;@sMF^K#bQnt9LM@m+}VfhZMn21Px+TAxnwr6V}%DEIQ$P6@WdqDmwJ z^_Z8RR{c8_rEghQ!{#c^N2+uxsa9l*T1|?!s_IK}j|zAy`b&y%DmjakDK#)E7+g7b zpH&DB621W!$G=JC*O~7Qt4l7_bNNQGS}WQ+WX*K*$Kcqq9+H#%qLNX!eh{?jgQv=0 z;IB(eef)dd>rEskIsCQq()+LG+5bo){a?1d|G6DXxWD@(sos6@KK;&C>fDo*en`>K z0WH6}MOf6?<^W(bDqR=^s&Hm=AS;y=tc&Xsnv3SOs++D5#Anq$$ao5B%~N1)`_*He>O85}J3+nrC{uZIXvn+V@bl~j3AccnJ7t9w~A z=#1e=nwY1P9J@i8=@}2GHW>~}W3#*<_HR_otQE>FRUDAmhrS$_VhR?}Y=+4o7Y0*C zP<0|F(oMM#vird3Hmi5d$T+G13b$h~kO2rQj5`^n_d0(}3MEI)G#R*&haI{llN(Ko+KYAPcKaY?u$m#cH&MdAn3FEp(Iq01pP7 zHKU99O4*<&bd%~p7v{mr=C5Zd81IRYID(^ddKMuEkzO^wU2M9C=KWGl@9Ng(CW&O{ zZ1m$uFw(W@DZky-$uY=rd>R2I2uQV;U6z4wd{$ViXL^=ItEUR3cDgA#ZroX=IzG!8 z)kBxm46QL{{6Ih;S*+7NC(k{&i2v@flz5)esb%QL=q$_TTZHX9i-^A>^s6;5f0TdH z?KR8?Sl+@C_O|*iBL7S=h6^$ommz}{<`JJU!*`i>FBrx@%p7&2&y}EYyVksC7n_}Z zQ(4U2L+=|fyn)w@54F+PR5z^j@wdL<&QTM4b@$CLh>P5HD@S#YoS-1;0ka|S^4e8J z?tvRemSU3MTi@)$%rhnk9R7AnUmOz|@Ch5$%;225d32<4@$%6pecs10Z1}b=itkU0 zw~QRXpYC(P@%ww9aqCwV0XMeJsB=~h++C80nRLXwvZv_FW;U>o@FSms-MttNDxJtDTYnW*3sIb=CtH zC##>hrm_o{_EyFnB+-UO$xND@?D2`U%8(-h1DY4NTr2K_jB!|!__PV=@biLxCC%+_ zdv8lqt~AFBpv#I#Y{Ea+HMV@H6#*lZ{Z|e~i`?0G^gkwFRz0MG-?qyta$=*@K&SX6ZeJ zvPiXA_}>oT+^jv5TiwTYJsTTx6S8)qYi!h5_Qz9eQuGtgAZO@NKibPiLY4Hht#UeC zdqFLkRdJ_L_mH!us+LbzW&YYBMiA?1jOdXfY1&jW`T~%MyV;w*d-A2zD%DwHOUl6> z@Y}mfq+3ug23ccqO5TT!9KbxDPH=-&)gfq;wlxdXfv>jKSFL-lj}~!3`B^-Qfqzk|hO1mbIGrWVNzK zPt^?!Z(aYyrcW#Zu?#R1E_gpPhWw z#0<)e_-M_&or}k2O2rm1q3!y@YF(H}oE*TOPaalVd2m zJ4W4M<4SO3;=|8m$?_X8T;($h5zR!Eh~J51MUluzd(LCUKOEEZe>9ko50rSQD$Pog z6&5!(*)HIs15*jhE1^I%RL_VqBFn^1Dg6(%NClt^vMy<9u@?v6J2smI z@ST~}UX-*1bWH)TF}=bp&j4K$Kzl5&I7=)**Gzm!0Rm zC?7%54^3JQAMPBb8DUx5`}bI)L}OK|EHVnXRGWj_`O@ZQ!3T}#(P$A$+*sY6y5N@* zTrDePY6!*>@6kZ{|Rm53%%Vhzp%z?j6VElil0be|WakQy6T zBZ{KL;wCZojHZ{7Z5=6422WA98A>)~N+9p+1&2gsl$bKIaDn9-fhmVz5uN)R?q9Kg{4c`5=36VEoTjor-^A zzbs23kGP(lu&_+eEgjt@>L$U4ZHI^HB|eHo$L>4&Y{v20V99MUUzSRNIMoNOF8Br1 zyXazB0t|nTG9b3Y(CR8lk4yNMtcrh~+Otbyw(mJ$*M%tJK7T|-B`==$l%yDGFWv4* z$Wm(cubTC4)9Y>@Jv_(Ahv?T7rhKHzW``v7%3M6JaBn_JCY%jsCo-UOg7uCbFe7w* z+Xd#7!mp7YQgI*fkwxz)xI&9-wuvRmtmC_HiX!c2P0T>+-B#va>f0(}qTwH^;Z6am zdrIQPN|zQDCWTTj!IC=W&wLf06Y=Pfe&-Gjp!;2AzU_qG!0Ev!s&f?3xfy69Uy>b| zQ&pDJkQseJNME?!m5=!AZ$M}~ueT2`uJg7{BRf@5i@0fc116LgllURh{%{D@*Cs%-pIIyRPSp@3`j$TjA~FY>GI4;H zy1z%_Jz^0X6!Wl%b8F_(D(1O&yQ<($>wwdN3?}!bqYLbo%9Gk0Y`pBf`%5Dj_d?_! zKnSMW=(kA>H)KQt_TXI;_h&`y7p+}*f$Q`Chq8AJ(j@BE1-r|(ZQHhO+qTtJZ`rnO zn_aeTciDDLojEt+PR!izM9hzjo%t&xa_?BN@>vhgG<{a7%ZG6q^uD97x9bvU{5UMx5=+BN}VBi1Hi%y;W+-}>9g|-yrYkx0yxGgzyI3PegYrE zs&cdgK1QIyIO8_NEhpujEJF|ezSf(d-6^oMmJdWy76M6-z-8bd_ywn+1ed@agg%t^ ze%Y4LWqTYDx)7U=$h|I%ssp6s?1p-7a~4hFDw#J#f;LtRpq&GR@*Q62>?^E>gh9a@ zbZ{UUL|;_Ji!Kpmf*vR_ZH(^FJUvE8DTUHoCuRr((Bvyluw}$jWQy}UQWxR9w}ZZb zUG}9D7-ba_t?jpyA-fOsy7~?WX zx)j-zD@X$knXpvyuMw^NeuEZKwj!);;#DIV>=i@C;(snx^@GJ&+of`P&W5Hu+LqBf zY@?IN7Eb;fqmvtyQSSXBZP4Qe{F5QTbqH|%SP-xb+WRwLUJkW+yMxL*lUBkEJ@Y24 zrvA3?aI`qXtN^i=!)7&%Y7m{1vZQLKkEe5jF{_9jKj2YJhkm}2%{;{##KdlB6% z0zTNV{oI_41c~2LQ`)^Io7z4o}UVEx|KS1GS=ME)vjMmwyM;&3pVQojTXp+e_-d#v&9-4XxDgDAtHnfKjoQ2x`6)5}sL)4(i+m0&V&fDsjrw##Ublet81;?SRO z@B!6q`sYMZ3{9aPL0LaRDQ`CGG)eeJK3{@8{&-^cSLGatEe5z4OTMPFNQUT@;>YdX zexL$gkmaH*e1G_&DoB1p2c}?}WHw5W=At1&MOh|p5a;3)Y`^4UHcpV$nH4}mdaH|I zveZrxK`!6U5aFz>628BDkrgCAzC%>dqQK4(L9X!Xfq(`5c_0DJ8=nTYp9zrKih>_v z8kCC&QXxf+VJqqQ)Hg1MrMsl$1TrmSc^TLUsOv}@Rtq(dMZo#2OW{=Khp2q(9jl^F zYfiQbq=v8!YP~1H6?8!Esu_}-RQ0XngTU+O9%y5S;Op<~e+eOYfrPKKaYyii*dDzp zA+RB9Q@@!y4a^1Iv)KxodN}6*IPO#_ikgF%xCa7=?jW`Mm&gEO@Vz_bWXWI#sS#jqHp(Eu15l9~-@;egvs2GHTa zXU>8h8}aExfz|;-@2NEnY-s?+?xT31mG*0M!14{9I>5*enp6p3s~Is)=ed#P094zc zj`P5+9gvszK{?>*2VPCoeN4oo7h1a*QM(zn!O`bx0gzm!yiPPGp}PQU!W@z(0Uav0 z;qh$2zg8l4WU7MOTbeYj#p^j!-qzB^b5@hCroGG4wu+996}wtt!sH~z)ZlUbrRAD} zQXa=CjTw;@m+gcvronSYGK|jkR^5+l4L&R+${9vpdFaQX_A z`YQ0&107}ecUly;+y^XrkM`1 z^+;(`SFRw}{1C!O3{vpUu-Kk8Ap%>M%8tkB`h{5L5{HYJA=hUjsahOv`c%HRE*pW% z%8eiMRftGuG+RyJiMQpqY^Nmg$MjH8R@vF@MW;y!2PIwt2`Ez$2nKz*0s*N|xrjJn z4E9jFwNX|gQ?S5lyP8wXwZXz#J8eIwoD=tDI>N=O^~_v_Ox6^Zc)AQa%G7&xVE2kl zQ~Yzgi4mSgF{DA_one8>ui$wSqlxge)qHW27TO$^3N|>?DZDg+UOB{-j4qhAoG1y| zc*ymCqyE_JHrkCV5~J4xqr2F#Dq?+?4z2ZMrA1m2B!Abtj|ZU#Tc+E{a*rCc?V9Io+73 z#^|}@J){f z-@*l4OwC0cOua1-g1om$IqgYJEeE-sw;B`g#3;M^c0NKkFlvdB-{I=4L!8c&jV7}V zpp>Ii6*n5@yTGwX@P{%NJNFT0%m1W%Wf9cezPfxhyoh8KY4fFc>0yo`obSo)(+?66 znio39d2?rDY@#m+4){XS!agUqliyOt-zU)TCA0;F?oMkgeH$zrs;Nes`b4{=&VTwJ zQ!KnYb?25mFWic>l{~^6Yt2-gU;Q{&g=}`6$0%zLa0RI6OaEj$e0(^z$5ghVt-rEh7o4@z7 z0t2P8d=Rdi0Exr?Ns|ieHGdu;4l-Z3%(UC~y*VLFtBjuqg#1o5yu{#aq#{(=BrY?!b$=L!2H^-;chPRAZsz79%GU!817;rWz8a?!`JJu=!+L|;x(N2W{e6QI4S)3=M3*z9{>Cf z#$%qzgVFqN=WlpM6|4-DU%v`}5&{1+J&5u@@#lUJPt*S`Z~1S)Gg%$l17!)7k9}=z zZ3{*)P8Wh?4OUPW0_k@q1qCTmQjx(d0)+*>up5#XTj%K&7(@?a9>D%LsC9GL`uhBv zg)otdwYBfE6@E+ea>Zhgb@P+0_T`_e$)oyBSj!%I^J&iKtnZKKP44F_p69;8Sj0IS zMqUA07k7WP*<;|Q*egR@{zz}l&5?aSG<}0xQ8ajzxzv*h8aRhxb(c3Petei&;Rgr* zh*Lzizr*|IG+vw!2L5klxl`h6JSrlgmDIXX?muBLp8ja1a|UE zHF%~RXFyIgy<+ln%*l3OXQ3Z>+4K+RQZ?TB;6MDE@f)titGXw9@Ef0ypFWeC)mNXH zm-S3{W;DH{hv+rBrVH(FdNXbC4DVB`x`+1Fd2Xzi{RV*ln%=wHeC15>*FA|pbx*DT z7(2sdUN^j&v+WpP($jp61OG9;yym%qXZs#I`n&3*U;5|#0YCeT`lPKXxnb%>iaNO^ zF+3&2ORzw3HcfO)gv*$WiF(Q-wfJ(Yr_<%NGa!xN8q=+Rng&4yBfCc_&Rmhn3=*qz zQBLF7&9$moiF&fx(c{65x{)m1Ukxw2hb7&rwub_fxsur}R8`mBtO`}Z!-r3ZeLdZk zmik9Nz)R&a*P+4`A4R^=iFk4#0RGT)B9TU15Cz<5^T5Q7*Se60VB5RnBEwVXpy&-JzqgK>t(CS3DU)uwogVzK z?7fO6roUSwFI`?@Gl!{>8Yje;TKQUoZ_M^(h*wn-q<#KS2z{c>bkT)KXC9=+XyhcU znd_!ZlRCFvm0liZwdIh}UAe=DrrA1{54O2ummvB)In26frt8~mo*YV%wq>Irw}#H- zJ{6jJU0aeUyHGHLNB{*(khn$2O@xr(+}=hRAzthHRNJQL9SXKbBWyl&F5O26L>N&L zdI;e#Ly9^|BN(F^PHCiL6yJ7U5XUwGvWNmYAzpe}q$H10LF8CS8j%!if2UO#lj5|N z20Eg!N}YKH1a_06%9&9Hp&SA^pyQ@bIMc-u$-5wpz?%*+IW2S1B2h54-i`CUCJyVp z#>5u-y(R(c-AiL*yvMdmcWNK&^kB}~(||j3rJ+5r`CLP12AEwU8r;t0o{Y`j z&8HD9BKao9&YCL|9!1F(m!fldS-%s})KDM0(Qiq#JpK%a}{+?J@>&KS%~KGhYp4; zyIIAJHqvR$^t1_;@sJalLJ%a&D1N@ocUR%lgCeREXOxZsOHc?tX1HRP8gcb%{VVK7 zb`I2siantq^(}w8+T6&kPIPT0ke0CX=)ejYPi{~tkbFQX+W|p%Xdc8Hipj5h5mt!m zM~F9;bPELE86?qBjsWUAJ>WQ=MIJAde z4h97Wo?j6DqW)PD=Vb{t5-J02w9>kVDeGYRzh;sHi+viBYFR3+3H3GAR)qO9rLg!g zw3crMZp@;8!T4enI&tRXF|0$0ZSE+7VZ@xuj{*9CjFv z1*rbfU@~AuNO^S5bbv2u%>}s7i=Oltn(i;|(PU}}@M#`NsPdyiYAI+OKzfZoDV|T} znX5&sp*}n$Dhk|p308x!4qp`B39EEvJk|?V$HpY;@eB!KJ+~pV`2G3G5VxbiSv){| z{^McZGV7(9Uy)ls6)jiJ4?ZiZ>c2T!{3B(-QG6eus8Z=q4xKK{Ew}qi$G=13AUwCJ@w>Qg%Dh|_} zzk~R925!Zy0R{%}n5174471XvuB2T3z_Pr2bsjAu_*wTfnuo%7doYw}06>9%e?goa z8V6^Pm^lPJEgGK|)c0$Fgpy1r%C#G%-ieaSJKk;J9@3xc6~b`Pv|Q zNwlW!1dD2PYu4U}vHVJA@EtG`ApQaui3_> zt6~Y=STHYo5hploMOi;bC|ShDQxQgR-Yn_II&9HulZHOi1_bHrfyO3)^sc~$wAPCN z=wBh!=52@34RK{>wurJ3HfK~9Z)Qj9+Lphz?~`d{6#RPPq+1_NCeXj5@77EXcG zj^mCFiul?7l-aA|>1ROzq0w^{Na#BfjJTD`mp=~{U!cf@_6qs;v9VmBULbd3sBfB3 z4^*R>DkqWtdbI-lsCQw_b4Ym z6wk3XsFum7TuOfCmMK02 zl~u59eRV-f1y4~}ib4QZ6^$U3TBSvEQ}fc(!p6e5Z7>TevtZ6nTcc5gBn7$G> z6k{YqCW$hWmOls(%LECzVPjCIY1!)ju-e!5z@Z-5^H|w18~xP?unb<(ttii+RLjI_ z0FU+)DW?9g-0}lM<}>Q{XGK))9wOeQ$sNV@mC+rBJ zRzDu3Hz*a8*ZS-}^`pzM1eu!15p)<_z}$U8xQv>#iMrKo)>YTdT)g`C`KP)-UKMpi zmyfPlIr5kXQ;VvBlsOZw^;%k#6|H8Wy!|QTv(}LnW}$gnt!(d)IjS~@ zNulzJlJ1y@TcH2B8nK~?Idl+KjjU{uBdKLZYSbCfzicrf{iJj4+R{|(^Mj^+My719 z{#j&ArjGnuxdO)Q;h2z^VF=kK3zgorSwzbVhQGKU*;-x?O1hB^JwsYt(uP)%RpBC7 zD{);yca`&6Rss1Vl5?&_-aT_0m8Fj&vD-PPGGsF^|2N?bnb6vRh>~r*L>K%y;`0ZYPpb|1%xa z=@8d9a9AbJ&}33x-|Ey_nZIwY>dDGtw#}U0M|z@MjWs91QMi%CQJIY~NAXIdjnD>-Qo0X!k*LRP18JP`|+GsUQe~+i#W|_`7EHQZbpW zu1oOLj5K+8bETXU%WU=(i_1HXf(*kj(@vB`i`dvrhb2DSEK3KS($R{wO^QAWG_VV3 z!dsX<0E>~u$&vv((&8?dgQEDL(=&6H=lLts@KEeE0n}GBm|t>&)KRmBtf4yQDEHo> z^hU6u{QTKTyM`i7zHm84VqESl@`GAYy8`ilTC;1)7sP4m7e>E=-BOR-ZvLuWbB%)C z;}?NGB^u=$LV0y(h^K?D-Y9DIx#TxkXm zOKd(#gZbhxdQ?K5C4K2fXdQVAyPc}i=Cp0o!2>a~`ka4geL}rT z8XHag88Iwdx-@W?=joLbgK)Ge+WWV>{ySLVGHGVm*=6&#yh+^}Eu@Pp+>R58@y)UZ zHl}!x%0~BW*yR$dTq8QX>O()Cpq?|k&R(6*Zp|0xN z1XAorly9sK@S29pX|n3#dFVbh*%JLLfrhfD3U}%uYU54eG{wPez64B-;Vc?<#ulNaZcL28ohg?_II$|R zA`gfm@_x{+)Q@kGd!^@-j-3c*4^d4;d^Ir%XKTVV3_rmnm}OtiM6}W_0W>qjth6~< zw_+AXXeMHa0QHpE9$LnXkhY^Abw%6#Y+J;8%xkvsAHmcYo&7BFLI|8)c6kOCh&h$s zGGz*A*6bi+6fevepe*t|sHLnR7XZFkn*5@CXkgS$!f#ZQeh)4t0WgTo7|@n=#|Km! ziM9HItO=d=WD3{cne-B&_qTX_)iuA|DZPUzngt?tZHfwgo8DH|yB(HsTZ4IC)k1lb z2I!oNI-qVsNS9FEDiescI_WMHi-9ppy`F@(_RyLK|3ysGU3os`tGQO%gi!a;*~BWr zt)Gu%?cs_iJ%i=fMU5e)sCw2~{-vg2R{d8tpmNFqfsSjsQ78o(#m0$KRr5=KwQ{`T z*;Asz-9tASn!;Z7BVs2XmwuQi8ml0;RHwSQ?I8~do8khjgeaWMW`Bg!lv@~cTFJqA z(e--R$tGX@NsYvT{;Kfr<*Jzd3HS{M-k`EaSPlvIiEjLeB2UD^YOu2h%(3OOFHboC zz9sWjZvBB@kX&_%y|07$YB|?^-{9tO5S5ropXwxF<8FOQb5}v+UNE}*?qWOC z|7`jl6;8EB-a7emk1QSI4H2`Q^1O>TObV^J%`L>Y!k%KAk9nIf!aax6q+$FZ)l`j2 z`=)w)As|_}@%*k6-k={-rIrua^^x+Wau~(Ix6Z#FG>SX;w)WL@{#xBFWWx5HQ?YOW z)y&PuiqpJWsak=W(>i(J+zQmZdR+gXyKX|WIfXTNFMYq2*WJ<{1J;~;@ja00u_9Hv zu|~+j!@@t&ef&J1?7Xh7pwQE?W@z&ISUufPhX^KDF#CD#b9fKnKP4+mJ2z-w;m-X5 zt-E`{ zQ>F`$n@KuLiupy$suT}1FYdt^;~DK)XJ8p%h^v8g@|BG=G@9dWT`JFnGFD2Y%B83$ zc{^)WQVY;&t7n^p;a|{yVP7Q~^NW|paAf_2ri%g;lw}*wID+2-j3&*}A3uL~H~tcIQA9j9KD~g_^6jQ;^X5-dh#SOics&rc;ik3Wz}z6)5A32! zC$4d#2OTPxn(GSJ5O)2?3e>!PR{xJ9t+4#1o6Kvn{FW@Oqw;>JRu!)WUwC4_) zm|?iX9^Iap(&#D~$^`9lRtjSg4cF?~QouS-x2Wd>xK&d#64EKh4vL|`+@k|-*3kk$fq^8^hU zfkqq1t<_O`&kC=Nqpu*F;xnPH9UYkg18X7VB6|v$$>9wzigm?eax5NB$mwA~(alB# zz0ydt{uiDj_*ydpVIQKV-i3woMa+@$YV!r=yn>M;`y8rz!*__%dn&SSxN33tl46A` z>)Z_5tCcMuTytfTE3M+2q-o=}n4F_>Z6^hZ8BUeSvJ;c=z}jtnY(Z!NLNUcjQ%6Y| zjX(tlkX_@Q-JZkaKoV%6lTz~3=9AQHkSOx6sltSST#19QgeXKS zQxD1L8ZVeKVTp4;Q2ox`&9k_SU16f8Uw}U#zc5CeQ$RD5cTIjuf^+V@(~RfU*Xy(W zpI>c(ArbJ5GdJ-OvGsZTvNU&0rA8>8sL~o{9+Nkafzt{GFG+^Mo|RM)8pb>1Hrl2y zQTc;)c*Ihi0N4^WqE!`#a!Op`G}KcT*p2nsd#EG;ARx<@RoAc`)v(2+_9g#irFPB! zuQI|?}Rg05|vb+{w9Ct z4fQQ*R@DL%*xM5b*R_jq@EE-b+rvtLD&ZDa_*}22<=$wPsxj3OELo_W z)?VwX`e8h2p5G|Maj_2>i?i7zbSB>~muzvUFh~r{@z$&V6XPs3IOFd)zml_s$5&c9 zu3&Y*Pe8Xxg@3kGsvlSYqiFMV0#H+pUwH; zc?2F*k(kl|B1IZI3ZB+j5q*pl0UKUy+fe?q{e$K@&mX4 zuO0FF9YyU(|5g6-z^*6w6YtRA?ZY~%|Ma5F_oqLWzxQLTe&f~w`?C)W1>)4som$cx za~B=5aVwSqfu>x9!`Uq;>rapg86r_?pD|2!%Nyt$(v=TcI!Ax;pFo|b6V$U;vV9M! zeGf5icZU^tk0pG2c?yja=YDVVu5&*6@zZq-xCVEKYi}!qCyrABk(o68&40V)XF>3t z^R*zSok6i3^Wp%PNRTHy$crGpqg1>v%-h`ut*`_L`Rh?x`80v=Ym6zn-lRcPeV-dn+cgpMgc)(8K2Y{UGY3eEqEs7~@IArnG|^CfdmnJ zCj!8a$5LOm6ch-;Yb>m32IFvU3un_b=td%>W427L8TQOI5s;z(`16l*ct?jP4^4Na z``#a!_Vn=c{eGy&&kOPb6=l(}c(Zt2HKZsfr=$Un#IUj|v&qm6{}(NVl&s`FSm##L zG)@<`9xWCc3o{guE@7lkO>2*SU*808l%+u4#tw}=k?$mWu2e*Y*QHS?Yg96EknVv> z2y_vm5r|(96%orDLTp^>V@3urx1#gRlE2|!z&&P~p9#tTfF6*rwgeBCP?oeiw*!?A z%DL;jl^MniTyc%z{?-g&+bR|rp~~CCL9*gVOv3E`b)Fe^h)%^su ztu42ix9YNkCqBn5ICNfkmYrb1np$JXjb6xXgsctW_w)6^Atpw9?rDGj`c?3A{pa1_ z{!hChF7>}hXe2V0cGjjQ|A%OhY?TSS1pyS^L=H!ztde5d*d&E{w9&#v6v*ENLKR4; zYZ0poMD;F-k`9hMhBoTsKqOz_Xc7n{Xg&F@FpTHAZadTG&1TGvg=^0N-jvY1KZFi3O z1`12!c#YLvY=|A+HZA@p^dk=|SK?vUoWQEbJU*nwY&h_cd-UHl@az>MN^$2=Uo+46 ziWCp!EsBORA7;jkuPE={sw-9BY-{$SPbm} z%||2)a9rhL<-zi zKWgbX&Il{qPA4@^9!*Yee?g+;?E#e)AJpQ|iJ=m4i#o&IH#vpV083&C^k`K^_x2De z>V5(a$pIL2iCGaT$-f)Mv1KR|6e@1}jz}q3epSC=jt%WYjE@ZXTFxu=7jMeGq!>l3sEH&PV5tz`S+TvL(1s$6h=Op5HnO)4 z@xXjByGSK#ZzMuJ@@pNF1E_d>2Yb$6c@3-sYB|+F@Cl)sU=(1C=m4}nxyk#tNCcN0 zbN~ZU8&o7Znl_uZ8$yggB`vM&QfZN?bqQlSCMv=K(3Isu9qy7tiAp!g=Xa4h`={@H zC_X6AdK%dyK)`*uDWcr7F|P#2R_hJs z=2N1lGDxSEvMa0`k4lh2hpzJS+Oe^*&!!++%en(@%PbMw;1RG3p^r9ycn;n&7KQqv zM{goH#hTYNEhUNN<2Kl;R&LXFFD|NRv$HrSPkY*=H&q{FHIIarCo8?CvnZxGQZh=( zLc%NV+7kqQetR|-oi$}YdAR9ymz20HQIt$iPfm0(kA}icl|Shei@E6ShsmUoQp@8W z5ZNAcq0Kv|Sf+JocKO9I0w^fkLg-Puf=NMF97PP|VR;JA8_LcG)asiEV2=-#^yr-a za(sjUKz`m+ylcIwG8+pF1xHl8i;Dxfp90w6DA=U{L&+LU1GwMj0E{tI9B{7h1(qS^ zp+ar~0CN$dJ;*rhlgqe8r)tYB%r=(On*f(4A6If9dnHxYLW~1$x#J6{Zlv>ZY3Y z7LqMKg&RUXrMTa&UOQqHn$r@|Wi3?$t4jj1K!P2H?dOq;Z{4>&V*LjM36}Q4t{s9^ z{Zkpdids4>wBl%+kzzgDE9KF>YCnq2j%D!xjRW?8YuDq-9Z;@fvsg>%u4D&QMOUPB z2b#0S&es-nRq>7SOt8oG^vPo9l4I*?bqu2ivFG`}y`gd!1Aenpg-c|EbK^n;oyn}b z(P+ zUX@a7i<+W_c*E;kd1#YD*;R2&6PvFF$0&?uHYiJ|A z7QVyV4kU5+O@+FImczVRF&z`QM#8{f@WduOj49T;tKeP=aC_eO?0*JvDJDL#N2RNt z<<-uxojI;6Z0minh@e5iB&;ZN#7A)`_acmMQW10|ar6p24-_5xQice@k|^ro{X|fq z6esFOiVq6t8ncG6M(&@YS_ScVuJk&KbW)kczDh~0>$tD(cpsSKXn@aAG@pnB~jFb_EG*BX5c#| zW)`)^g_O*?2N2oLYYD1pL`u8~04yVIO_$3b6ZF;vG8RchS2wZQo*fp(O3E@P89Tvk zV2VuLre#aoLSx(8Usp@K+e2e)JDw}Kce-0;GfJv#K0n)b+^3(vr#W{xkGXd&UyuG? ze?$2vtDO7e!gD%8>7zG>W`B5!Ov-UPvf?G*!eZ{AEZB3-M%!~^yrlK=&>cXMJKYu` z@AN6l`JnGO7of{WR_~zuK%ke}W4_KR~ z36;$a^?GfqhNML>yQ_zV|2sP8wp&iM(|>W+xO2n%?utq^`IrxPeM!dsi*{f?cx=k8 zhj?J0Z83;Bk^Y(ex9Py$?IXvXe)CK_zM)`Y0PKd%Jt z(Zb3nGDF7d*5WybFgg#UK#_JEM-ds4R?va8$wMRBW@$g%fyT=-FIXTGvVE%Ff~Z_9 zQG02$Zn)?B*j)c!!k&Ec-rh*0mqydn;lFmu&bH{Bl3CWGVHP3b?hcjZKZ&$ z*)GQh#yY-748Xm5wllx6aCUv6``WQh_D7xCUMsbpk_91F)YvsZL3l~y z{T~e`(>b|mhti~gw{-809ED6h+bd>E`3nA_rg~nufjxB7xwO&Q-~OzlX4fWn`?IZm zc$X(I?G5_VZIYNts(S$LW$FV~WqB}DOR=@GxcPHbvJ#+_76AsV!>hH)?Wtt2AwT`& zbT)~oAHdRMXuvf;YjbnYOp0-#lW6-AVPJb@3D+Xm+GnyRG-YMsuUt&kCcIU=3`;%` z-=RQ*g%vZ>Y|&8TY1JVq3)56Ce1R&i-o{@+7JAS{%Qj-0UY{$IMs2KEeH-m86E*x8 zO;ozk+3|TfRo$KH&JNvq+?HxD?ZH(4LN|H6lJJ}NQaFQdR9ltTT~W!oDpvk40Y;3~ zP1^J~(XEpsXE3g+a%v1C73b?ue9~VP5bJHcW?D#Yj zjY>A~iuV5F^thCpr%S9IsrbyU7R@TuJ1uvbaUl49 zVDtu|zjU>9E>~dATP+-c`)Uk3Q>PlXk+xB<7Tz+RT=emYX{G^8)l{(M@v{y=g{_P@ z@)&%x(aVm*;To~Z7#M8w<;Z7tff`gM@UTP1ozb*kCg%z?EDT$}Iz4j1+xOtuN-TBYkx#jPz8VfS9v%>-RjuK4G zf>%Q#C)EAn5hgThh>8cFTEf9X#VTZc|8SBc9%a;LkqkfPVSJ1fqD8Q%K&*6w0q?i| z0NmB`S*8n;s`0ZGGFC*mV%<2)tuzIt@>!>gq*I=*k5W zM69o8DXPgE%CNA(i0~N%Fi!cSWnKg-b9T03^%5+hEzWIBp}C9Z^|mS6bvIXz1d^mF zkKZMzZg5zIuPSR&?k(!n<`x{7t5-WIyM<@9!;>SVeVzyZdOO3zeA%(KW8fE7TQe9(l1QTav8pnVeCTw*thff`s}q$uC$qMJ)|_| zSFJUXS@NCx2lL4iI9N-?p55kCN{hu7OGx(WP1cAM3WpX`Zzi)krgt`F7qL|4@;F|j zy#ihi~rffHjZJQkD!d|+jlw3S!ZUC(@q;x`P|ku*-YQ)9#$>5Y|s z7oKQ41Fm>6@^n18LU%@AU##xTQ(jBAC5F!u7BAWbd%40H^S2NdFV+Qn$--3T&t(=b z%msVtLg_R=?-1T=32l1g3~uC-=d%aClJxDUdrr9PWxzWkb zf@c?=gScfS?bP|gImC@W9}F~IR>|oUv>`zWt$%X^F|cN}bckRZ1t9XBY~-*}~03piKi9CG{jN#a0OZ=7aL;R?r7y9-!gh~74bGQ;W2Fx$0G>9#t4px}8= z+$$Ea(vFF*?P678)Myic|*b9dp5P^94b6XQ>a8BC1au}%ZE_qKn_sYEDh z6MH{%Q9xUn>~qEvn+|&Vd<#U^&2b&hi;k8?D#~Fy5Wdby$XXPb>4;WG@r+WMV_+H+ z57F8_q{JGDb|2C{OB9w>v_f@sY#-Gh&9w-pUDKLgy7#uMaP841^DHZRuqS!jyf4E3 z6EA_$7;gn?O851o6sHXnT?{~V!R%U`64QxUSx^((3Y5d+>jPe-isqFnOnf@yebHo)XO20!xmijlA@U2+Oi$9(T&fAz8!6n!r$?{IlfzLMP8BNrxur^Y zDCsVD$P~FlxjjxFUad5y@CIbldt0LgzUT;~jb!)Qu=70=dbxVuET*58UnuE=_u_0N z&fi)GW5cp`MS22(XAZh^NB5Zga}KuH!p@QX9v>L(*aKKV+@|_TkSKzhd#s!eB}C?X zG?(KNM~&GN>xkh$u&|xggS;eGuQ3s9absxr`RorbhxlPNIs3b+IFU$c~S;15#-%)y8C&v@#C8FIOqN7 zgWG%>NF%t_w+*%RwGIz|ckPmj?<5c!|IUc^%D{;{5&qo)1b=T$SB7u=(3s}i5uYzW z{_et#EZ6AHk}TKoP7{C3H^%(AZnK-`ohOl=;g#rmyLw-`%Y89av`v2KlaI%r{(fH& zKV_GYOyBUdmgyBMF*Kd0|4@-EmXUM#(2-1@!82h@Stf>=v+wX+rl;?aB(XHzCsFs0 z^ia7_)N37>B9`?$`vzV$Y=ve%-Mzd4 zmUHspo?0H?-)5I`ztt;Q1rReA48@|W!}s_GuIAr~25&R!;fSrU=Gp`V^HSh+5!fuQ zpqf@fEHcq(>*)>%>Qlhixt~r8y^M+M#IU%l{CJI6R!TGwBb1HJH`xjeW4ad4a2hUN zK$m7oE6`4WQDoiocvUv&M%?gN_pcfr<6Y{YjbIoZe#_Sc^Vqc=K`3N$a#*a2HSI`j z6dz3G4%&yiYRoa9(m9itwh}3D3*RQiDfL+0I`}`vtB80jE2Paa*^qLaK+ju;X3Uga z2FM~#G$>c#fR0(SPKJ#!bhj{8WzPK$Bsq#prd0_T2siYsHeovTm(E^l8<+*>xL-MS z%c3)9hF+Q^X(Asqnh*737#RW3gx<>pqr|`~QUG~22!Kg7?x(M}R_XeDZHFSpK|#IidRK!-l8DpXYYW~=pIm0}O0cKct?3!KN@tJV}qjDj8|B5~zl7F64w4E{3qj~U#evo!5#!Dim@!Db>V z-Ri>b3_PiZghkzn(LY(d{GPtQ z@PcK(aiV{M(Bb1mwA9I08JG-sWYROVshy`Ctt70JFrzFi+GmC3A3Vp}mZ1Dwz9;^| z$laqjAUn(Yz?dc�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

    A$B3k~{RycObG@6y| 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 $@vz03z8Z`qI{ zfg51Cx^fWHo)krX7L>)|)r@g6_aIuWtEF*=NBsG6 z!$bIc_DGhT(Q&mdli~M~zf7|3(Fukvx2e7(ORkw{k$J$<$i{Di`X~N4d^zzWuVslE z`GseuI8!^LE|MwD+{aRji6Q1oi4Fz=4bwPLyDAMi$Zj%-UVg_;_P=c$A z-2rEL>K|b0Lh~K^KkbqId_T|&54|qDA0I|ij)kpxO|)NzyNSMfEgUmT()R^Lqi{%j z;l+^3FgZRR>ChQL+;+LgZGMB~*%jWsGzNo{Gg6c_oK`9v>Hk`|C~^N)flbaDn-Tkr zwXmxABFgVe>(ApDFss4BCcP{O(+6;?Aut!LJCrKAE!o654C-7zSy~=|lmM%(hjago zB=i?VJ3^x*vCQ|cH$g7m10C1+|0*`!AClQYd>R#M^$$_ewx0??QC{1_IUB(_d@umz6D(z zT_3pszg}1ucH0VP-lHHUYH`UU%iBKW3Jc*q(^#tBL=$3^PbS6m*MNzZiD$-u(MatQ zJ(5iJzBq~<4x|UYSQ9V(=ja* z+@%foApqCodF3TzySM-o>pSbJF+VRoKvH18$jx^0InvZ`W*D_Q_EF4uMDmkQC@1e- zZD|g>WQtWB`P8xN6@XS6bEiA4XpY6$LTZaO%<%o|UhR}w|Dg9E08ps|1&1D!#jpy( zur}Ux(rvoclUVbdts4U)Gd4AmMN-30kAf&_%>HBO?5E$-D?iKU&FNb+**izU({dM= zM5~bC=H%IjNn?I^Q@94UBR>6m*xUcKc03KJgJD?{oBB#`tvwTZb z(qo0D&635+$q;}HFJpqZGA>t7WUi1^eGZ#~3~&*EV>hb}W#2N3NU_K-Q>j>b5-w>>(9jZvkChY?wa0$xPoVSp0)HpYg2HX zy$zIy5Z9<5Nv3i8^zh62132(^gXz3Oov@jUEa5VEI~knn#Yt;kMZ%TGEk74sbo(1( zFiMA!%7ZyI0aZ~BWoaBw`tw&T0)|gX`y951pK_K~IVHoVPYl-S5t-L5~)qhI5K}w`f-czOL~Sn2kLiB07QhY_9Bl3V108`VcV2q3B(r z5d`IB(F2Q$$sS?P(52bYbCr4bu^u}DU{?jmsPaiD9g)C-2UIVN+Hj*^$G@RUQ1g|e zwh)k%p9p)1@3$a3jwYw1tHf<>Uo{~7RveHece#~m&l#rTBIM(hK`$0_5~5KliX}6% zg)S0Jx!@E*7c{q+Gw;&3jLBW{(#;bkysw0n#%-MtdIN`&AV2j#C;qCJp18ilL%d2d zf;@uZ?nzU*AqGj?p>$X6^N$=foyhng)seq(AVBI==}vV&ooTnkKq|SP8(9Y4^V2dw zLME*AwQi5jtXpGWLlQ)>O6%us4f~?%r*@6Gd!g~PTDY6+{_(TzB_}?+g5V<;@55Qy z%axP1>i9~Uw{XTFPX6y-|DDPs`ETlpPYFri%!mX*yP;_Qc_6y)g^M{B2`cQH6@Gi` z#FMwy5LbvuTfBApN!Vcp{jV7KqclxP7doTmJP!|rWzi?xJKluGnfl3f&L?^e{6edz zcq?S82!#8ZS<#EqN3`2CcSs*oTz~xK6)Ll_ruBMft)Q|B*{+j2{^LoY)BMJ|`mf^T zzj6V;|3h&iW$WN%YHaCj`oA62$Ym|TzkCD@wR_p0HjO?*C^qmr~$yD{>l#ETuHO>v50i3j4A6YNBcG zHv?=jXgSMyveo@OYvld$=85j7nC>EKpA7*IBd8_HCo?xUw=}o#2V(@C5K+&9#ws>4Ks=?iv2Or3XafGLeWRl8&7$C-rckUbvEgzj`t>H@ zl77O~1(!B=Nz;+YhA6(7mB2nMv^O2C$d=eVDiosVbuCY-C_es>0E%YTQ0 zc+!nx*6w^f{U8g%-yXYq@;1B8ngAI&s5w#7QPi?LlTR4Ge$EY`Ve&eVO5HvIKq8;2 ziGQ9W{8KkV&eF!l()oY*Lq{j+*{`bN41L68amlYK->+2L&dhX@pEWW6K(K%fawDYC z(@trc5o&ixoE=Lxc5h;{l+-=V?||(eM+tD`w#3E=|23yZOwzJ1ddbit#&@`cSeDwj z#wWnkeIqzI>iK#o*!>E%1y)^@Taea^@4*(X3} zJkId0VW^GC9NnZ@<1N5B^Uv0%jMe^#+-fn$kpI{@(2{(8(W<}&NqiB$VZcp zmCIOtwR$f*b~)fqRDUt7XPp+>Wmpq5G2wiFu)=8|)DP5_1kZ-8%?Yn?z zcnOSiRv8d8g-gv<+b((>*pd4t%zEGAl}&fV72}7g;hMz!J)0A#j0o=K=X#LzjVm`$xr4e?_f-w4K_dkcI zNoL2zYP(M}I;er>l}Z$&O$x}Vu`;j1M?R{yRnOH*HzSbIz+`Q3mP{d{?4m1@<4YVQ z1&3{fc48!7X)xOR=^*Bnymj zgyNLs(4xu$=Tr2Cbyz>lkTbV--|91il7jeA&t=29>Q%)i>_?RnP`TR;=MOX8SSrn+{1>Nco@fo zC|*$YE?H(ClYqx;1U-jI<4mQ;255Jr`fvl05t$moJWV(=-r|P$a=Z7$a%v$ z*ZwP=`F0OSAvLAlUB&Z}9<79`mucv_dx;ic=ZT$jMZ3z=G2TL~HCyu*=pR8YNv~Zs z-#xvm^a8f-EO#+}c135GLX$}v)xELdqBF<6W3Jo{9lha#B;vtKM&z$Ff*1b-Rv}^_ z;e7c#cKCfxG5e6#6gF~paWXV^`9E-R|892vA4*tVKc_51zEy!98iU2y_$!-45Y zAA;CEGlzT!W9ojTP|Npg2!)AD3yv77E6i`c$%olH)3bcf+5`qeoF2F1YL6*3j~spO zI9;Qc2z^>17c6|Emjrz`2u#c!!y6#K?=o>pLWOR0>4(iFT(yB{+XNt z=8kYu%%?jnC+)490kEJ`ot^*2Jt)2G@__`hlQsafGw`^U*ehdFZV$g9b3oZPD|33A*XcslX#oo7wYs3 zMz#s2N{R~^#xbgltw}M)mCA~^vjX4sZykxpIm4f`3?sqY8k15shi3w+S{r7QAI!La z<=c@=D`|%!(44rMYg&0S2~xc^UV8ga(55vsx%PNV&L5wJmmR`!*VKuZ6jk9usVN?b z3eB6*DyI5gWcak8VEGrCwdT6NEw0Hb(`Jn4hssS9ev(+URtS zEl;MOixVu-N3_L!4o`^l*b+8qG~POnPqwjx1n@N426lXs}~Ya zeSm?}Qu+f!0*8?XXLlNhQS3?w@`B}sdLwqn9d7W-8ARrx_Vd2;jXmcbGYLR5gA7M5qU)YxtLb9;v4EX|CaLl-ccSI+*znE%{aM zlD2Mbb`1yJ`37D2R4wM=m9HDchPsGhp4~p`CUN8HS?C3+L{x zA6P9Q69~Dvb|*AZpMV9%QD$4AkUncEgp{)mUNq6>WT&BbCkjz+!I5-j_a zw*ENm$-(kB&Mm~J?VMYpTdd|Xy<%kCluvs049Rs^;HxDYEbXRzX1MLPeEl`B5>0C= z27)8Gf^hQt?^8lkFV&}NwVM5#nL@EOJ-ZuqSxDD;>}3%_x%+^>Y458JMCYH@o+JDvqHH!%<`&n;V|dXFm^5**gV3&WD!kj&q=K!N_}ez zD<2Ms$O~gMvk77Ahe%QF!~hYO>By=&N+-V2Ou2UXWq#kLPe`)J3kNYTn<0IIJE#0B z!$Ml)j6yCQmRojGYiS7kplA( z`ssxVcx4YH9JvST$8ar5wSiQ0E?^(eTpjKYe2@mp|rI+y{8H=R1S4c zz6~MAqWv%mY89oteG!zsp>$#{8q}oI;*XLeeqo&gHtmU*(^k_B!I)CLOd56FBx7B% zmoDrtXNCh`NY;0Y4wQB=g}~`bAvi-op|C2Lpp4#I*j~WhuZXM9TTm{9r6>j)z{$Ub zcBwUL8CooTuVOe-0ETNE)QqyWLfgO|ZYB@MR4t}DJ{Qs+jQ$h8`5E3oOQz-{^onnY@aS+0j9Xg=HbKD zy&J;oC&s5tvYgZ~xo#b>9Lh5^qUpDFe*3!CY~<+|+GDFjFS}g#Aial~Pj{>z9{^bl z#|Q2P2Ypc0E~{I%D8T7!ys2ZubcnES(JLb{tw643b)M3iP~>AAPHb|7gT@r(g%M}8 zb^Utw)1D>A#H7Q>Yt|I?-4y??Hs7!9ln1r#AQiDS(HZ_*i)Vl^Y7Q*Xh(GGVANPVM z|9_nl00&Z`CZ99Q5tRRy&;O}a|J~Bf(&T^KH7Zj7)Ih3Xynpk3vV0c#fYFq;gogoH z%j7PRV$}MpDz8M`Lc`Jeo_Ql8>nB_%Bw;BEiwy<)Tbt>&7!LNN^N6BDn>m!Q9Zgip z=pFS|!4nQT+vz8A^c#gv+^)S$d_0|VKO9W&z94@+9SRl5>UmV z__qLX_^KBJXa17Xtf%mG1P}gzk_*IyX;MN}J3K9>JQaW)WCNU*=Jiq1+^P?$^z=cN z14YonkrCy}x9tf2w<-Y|L@VCF<4VO!QWR#y^l4#XSA>f=?QkBJUclSN!}7G9+hO+X z_C*QurJYcOqk=lcn@B=<)bakhPG{($#TTXkk?dtbiH`i*z=vDmYZ*tqNWj6fr8~c1 z=yI91d;MYrcY^wo3N(Jh4$4qA8pp$ZE zyCO9yNluKX-QnVDidCE=B+QWw8{vumRFSm=onP!w0>8t`&G;z+SMRj=(Zqj#tPUOg zf^ofR@^iM~@0C>I^h-v>7#x>q<8V>#b$8M3r9FDcQRc;NL)_>Cg$TMW^ZT74Llc4k z?>7if5tI(pSW-rdSB@oPUyhBFNr6F%aX!f8(UyGgy*OIjks@dOqrj3c%k9$ zAuyr$yqyO45ddlnjwD$7;u$-cKy0@(^X)#P{9^z};aowRRKKy1a_*>7brhy{e38`{OhBM98gcuDTUHP9wq zp}4WFXNh3WxQfvODX@M@4u;aX;giS2T#VbeU|6$@{+2YuyC9s!yRQ)>rRz9T`Ut#pxTbvQ5pYbw6nu+)rGks+R3NgP5n7vPDkq}F zY#cridPMvtzIO=5xyKXT@V7Hh(-jYR%c1Dns9SJw!6D|BPjaD_@R?>(QrYimc(Mha zQ+Trb)MuH`9@{Z`sI0L`hJ5gD=Hm*n5^srDF97b$ULp@E_%<)hVD}6wN)(vDd`Qy;j~_xi@~IbY zM4KJu6)rs*nC`-eQ1b*s6SA78U;{e}nSc_8S-4uY+*u<=h2Ix>_h1vl8APP1(+j6c zY%zJVu|C>*JtNBBP2#m?Jn7{zj(H&TVl+yq$C#5^jV%5s#qu`1eh^30TPU>B^*a;b zgHZ;j15KmoYq;D`e6w2w+jsk7?c0fA*k`G)fNq$Sd;n9cWesxxzAbvIT;} zj83U1?x-Pzsyp-7M1QlmSW+@Jk61lX$*WdRHoaUJZ1Eyrcb8UppD1}sY{c(s6_!XB~h0!JTxV|J$oV_YYg5qLsa)jg7V4zgVpQ0Z~m9wfQ+u1${5=#U|8Nx`>7# z5Kr;piQ5YBWk?dmtf*QXutZsa8vh=WQ^&%eCZWeS-i^c8XqClikvZ5?s2xMB!n1)G zgl@4toKiz%4qN85%ZoTrDV6I~diJnBUA}hwzS;f>@?r^T?g!h8^OFGLk^rME)gj{x zPaZsI1Z$(AOd*HU7-YQNZG(NdcI?0%NQYjpuq|2VRD`6T4|7Qz*`(d6Pd+Rebmz2H4 z@R)_)-Azk90t-5*MrWQA0sK_056I=p4qK zyV7ys#=s?>w5yNmEiS9+N}=9t14foRAHHLp28d(sNR7SbIu!cd25J)ec-)YSg=XTG zadOW<4|R5MXSDnKOz^hwZFhQZ3b&oU`UAfF?16Z=tQ-qsS3H?KNQ zm%mHutDn(9JnHaVWXDRom9bL3(ao@1^^EQ5lVG^9WBLN00Z$f_B_7ip`@~FLo86dH zy3m$p@gCTa(1A1S9EZe4i5AI86Hkz)fr{6id20sHp&7j||Jwyca|?&h6Y){G77(Lo zs~V$dE(EcveQt@WN1wros~LnmUK5d5egTq5JH1k3L~W{TmZO~Bc`hrN=yT1;Z_@yb z`AMY0u|2gb_~ywzJxMNdA}}(}DuAE?1Q|u&2&7i@^;C6LEktiQb09%l0Xn16vAg=V zl9a2)u?wFW#ahUARHmhel(0`4g%lFH3-6>eq%co1s~-4o3nceiY2W-kUsTp4}=eE>|k#_0seWwx9_;BWB7sk~`iXwn`aPq3KeHz;-bD7NF5>eJonsHW}#9{BNmY zy)L>$siI;FoXT=Ikr)VO=1GTq zTy}V&voE7xxuSY$zY98r<^W9yH@fp%ikv8fTsf)?_NMMIH*t7;2E;Vg=B{ z9=S&2U0UJF4MUj>9)FK2qm7?G6G$@}JqpJa)4r4_d015jT)Veui_BT7D#~}YH9nJz zx*?EdNF|7Pd2`&-`uP?PID>UXtN5`wIC!I;@eAzR$pAdV-cW}!*2)Oo%O#pND|_c_ ze!u{G%XEK+I(-Q0en>VCa4VdB!;4nSNaBmCQ)b~DS|7-+V^&$XtwX34C&O8;s|cl+ zuOfG93Av+UW+@ry&bcC;x<$Stv2{8mn7Gl9KfsZJ@>*;67M+GkH}5kya|&~fZqhZm zSULzu&;E{3w796)5ZYxqtSgVG+_Hzo)l5h}efj=ZzfE7!PJ;dEw;KO7H1YpSzx|O8 zDE#OT{?GKoBy|gnMbzPMTu7H}zuaNynsC@6kr z*PlPSbwo)kR6a~jv3B2Y{zTlee!pD5djr~Fel`4-Ja$ZZOKg~M%$!f%7}Y)7(W)}--7 zf%S34LCmRo{D=KOQ^v%>CvZ78(8O5ifoStzLi4-kgc9rtV-x53l1sH={|(gfbcSgb z3{w`9_9kx;ot=27BAeTl`&* z2z4W&qYJ0`d)1RqQc1x6bJDqmdgfg7T2(?ly(m+1!~CfU8qe7QkurAyPT>Rl>o&M7 zslqmC`ua%??#tA`y8s_qED{uN1ZbGm`uZf}(mN&O7OVTPTi-pCt;xCcyp4u|IT*!v zEqorfwnAhwVj%{+pVr`S5j$1Iv5;9_&f-w9-fEK3Ryi{UqFP{-tB_tSh8hP5*y@4v z<2(6*rPdVMug?+Fic|bnSmyfH726@iwT z=Vv+YQaF^fG{8BO%({1QuSM!~6_+~%Lb+ah_{3bkoL@w*KBPtlh*VTc$KWw#=i0zY zZoFnSgtv8aERH_JeAQn*L8v0Yp0HQqWN3VaRLFjyaB2IcwUM3 zYj^EMfa_-NLbXoOsbW#PIuQa|Ba#y!x$;c`^+V=+s^>Qc;fyn><$BL$3x8GDR?qcq z!^bm}xbEtE!oG^?JnBsyZ`5VYUW>2Q!`~A@ZK!Fq7u+Y*8e66y?!SKrVi5a5h^O z0*@bNn=jdV2y(sif5=I9fNg7qXY2LlcVN@OEaMqg9F!i#osNf<{JqwIhFndg%%}RF@5HcB3Vh)k?RfD1=VP7JWpM zS=13~n|N|*$R_tJ6k<>EY;N=W@b{7N>MYyg2>_GlUq0+2juAwv{73U#X|jiys3l{> zH+;-WZ>5t;HZ^Uf6Cap2wnN>{nl0H9B^7KE1@a0=h((BVgg~>vM_|HsXVgu}`#E2h zX$5}cVGgw|sM~M351YW~yXJxGv|&TtFZ4m|Qai%7B=T+9t)k$s;5(DS^YB7R0i?2g zMF#o1_eLd)%3OZjCOIs1c9eAfR@l3ls595iN*T)PYUPs@n6>JeeKr^<(gy*gwHjnH z$$Kf^Mac@%g`@$7Ll@x626VWitNaX|VvTN}KuK4*a(eJ+JF)&Z|AhH6=4z;tps``Z zGQ&^Oz$t~?*v1(YL^m0B_PHqvBU)vU zYCZwqpbq|#`8TY!esZU{UBd1TJ?!^D4ckGyrU?o?a%+y{WGb9>wdQI4VGbv%9Q+FY zrcUf}e~{yU16!pB<6`wc+&F_DZQVZ~s{RSslKI~xkN@ZT5hy<`jUWsAg|&G(Czs=s z1DvbCBd$)8;|Csw7Z6ZX0?w_+@wfRB5KFbGrJZqCM*%DpbU%6^{Oh+%uYV}stsX0|5q`wei-oC%v`N+xd0#^)C=x!jNBX05|&{uqd#}MapRbK?X5>r8sXh z)wq+eO|66u`o8K-Bx(2a@lX`~GVHPpmcq=Lz?&qtkAi0V&IVea{WADRlDiXN{jf~_ z-(@(~5xK-!lxpIqiF&-!?0SjC#NtU;F?$I+Lb_I-kt8+@cwAi1_y#ZR8P5P9&3@W z4}86X65`dNu3mDT?C(#cLx#{Ak>#ayx&O(Nmi{ovb8dT|G zDMnyZ$l^*_(%`Dj1Lbcc?(c;%V7gENGSO(z{jF+M*(B+Pgta;0w>t{oCpoh!##=&So9`UjAshisoKx9CX(!; z3Xd_{a*o6lgQ{GvLrYDs$=oHU@8{P56iozS8FLV;l*5Hq1>TZsY0yTP;*taYghdd= zY4^fsYRf!^YNXMxvb80^B9V?5TKAALxDP0?r6wpj!Q6N;(@C@-XFSm8hR@aM%CzI{gS zVO=O*L45Z5(%obXl%xxDd-p_b^O-A`h?DTsnBfgN%v$f4dO!|$Wb!#0uE9FK+@%l$ z+LcGgt4D=q(W>C1f9(_hs1V9a99XrQoT7M*qQ&i?D{D95xtoNfVYHA4XS9&zN|`&Jp)G)Gmlh82$i3E~HOHrkZg$ z4e!r{P$t$H^g=jQ_zRRX3F7o-0lRyFsSh|0&vR6aQPdpRUvWOOZ@X^TA4hw8y+ZdW zQvCfpL%t!CoZzLbN|ex2G~f*hSJq%5d^ zbCOcoEh=ckgT5pgivd#>Vl#+h(g^@Aj)9G8-f`}6GlrJC**z97L0m&%q;N8c;<@n5 zT}5R!XPN=Ch=t|)?Ji$RUlBxHZ!w=xHW@eiQq6ZYz0Z~lT!37P+jO}MI4R47d;%<1 z))sVy@!+!0JAqYX8u)g^(g98Oe#E5Q<}^71En?7!SVg~;tQf%=u=S|v(3eQV3x_En zRQ?4gkQ4z)!knetf-oAfurknNK5k)GeBv~hYvsQ!N^5c9*dx4 z<7R%~4jCX8u{>c6A;jGP%W4S(-GP`A#|}z%M3DxS=lGa<9T~|Sxk&CZ&1N*RM6yfZ z^Kzz5d%SZ7-N`Z_o!<6WS{6DITZeouy|1_bjuxnLM!nHj>Jm9u%?J-YHc@=kBsp@n zapA+BwKt%Bo&JizM;QGOu@i8{A~#b0SmAfgo`j#+&VBr#I&_3TTWHOf*{S#4 zb-r`Pnk0NyC*tehN;a~6g*3OHs&@UaO=!^vM71y{n)ujV_G%6{P8| zt6KGYVa94>Bdk+K!wnY&Op<1X!j>-$cA-En5%|y4oFU4pIk{Km3$E<@OtO+$A$-1q z+4ei&8~z)9npb^o3t?kf*95Em5&I9Ld@A*I{~D$HcS@fo0$>UaZOC(bi6j|ib;F+p zy22)GvJqh-t|4NOB1w%tLj+};#eh&$;1oq4^D~{Po??(H$OmP^!Dl~4)zUZFmmW=6 z*l_^PK$40ft-sZ-yplyu-(lzMYuVI5ZJ&MdVu(V#3RYkd$oXQd-AIWY9v9Z*AG@m& zJY(J8jotiQ$~oiRm%-r4JZ?*WK3$}C%$~M4r86j8YBdV$4#smB;?)smAZ0@hJO#NE zoXytH>*~%bK^rDMw3U=+%?wfFIodPym(&z3q}FAalsE3qw772i?7R#;#jOS?f?T=F6q){t7P90)*i*a|*wyOnSEyO3xIh+D zb_CNxUhh~!=9{qw-yQ_l3`$mmCK0hRW#MR zV-^RT64c8r>Y8Ec$`B$gt7T7=c49O1oWm-4GXGX%$mm!qu6<4XJs9w=7sxKz`3s}7Wmv89E)(z&?A9(mDs3fLENWe8JY zjzpCex$kG3` zkpD>~B4=o+Yiea+X!jqgxln1^{$B^)pQG&MxjCsw87zPQA3{%30Uk&Ir8melHJ9ymZa>a+pU3`wzXJUQdXp8F=|brfE0m!m8%+NLz&;WQ+z9>3CmW)v!t=4$ z6NQi{VTl$^tcRp)C#h#nXGw<@8N16Ha1l2OXtotKlBc6LV4`f72cQQa{VlJfghOe= z`itC$9AXW^Xp8QmAeCCB^`dpa2f$E;SKOOQodj)FZ>~n%=ySFIInP^n_YZL7k`JRb zlAY@vJcL@MuiO^N++%^^8Y%E@tOgfmcbqutZC)bnzT)~YB7=Iq5R+xwMbN&|64?{U zNx0i*L>}vu=&E)8h*~Yu{#gFTxnKNPc1s6`Gpym@>r478mp5igMx(ry^#{H{MN)@B__kTs^-VR}X%@JEJDBK_emq(07!6gz1__$(E>Y*r>Lfw<7sdjUaO zzFfXuzQ28WGh}kAi%mWO7IFTh(6fp?J2d%i5qk(1wEEA+E>hDfP1GY`xSIePJ3aFA zk*}Oxp4GWN4=wk`Hf{m7?pAu@_}z;MVn2q;z~-!^y{b2q1hAH=Eycc()i;vp#XP76Qk%=?dLS+zqqzefwaq{~Q)_b^a(j zy1-b@U1cCYIuf#EZAer>1&S5^gU|l98#STHNPb7cB82Ceae0_ zeS0#Tk6|)w2*`AY_Z%>JFT8kfiE3$l+&CZuzD7(i@{N> z5mjr0P>!&91#5K6Kit`0!0uMsQE)n;TP{!y%No|E4y!>gTqW$V0dMpebqqhgb8LWa z9I_vRVA}a#%_i3r>Vr!^25<+XEm`NgTFK62L%bJf94_b)-XRYk;|qPI&~fXsdyHjT zVL0Vq3Fr5lEVDa+Y@$6S@_UBwz^_>=?lIT^ap7Z?zC_71o?Oi-cV;aqA5iY6T6Nch zy%|2+xtM{kE8#b>6@JEHUlFChlB>O*wa4~j5NdN`E>?5mS;0kDid){uStCT(gO4v< zQZ-IBpX_={UzFaky{HbNkzkLBcS#>e2Z(Qt>W}cIZP;5sFI^DpSxdT&h<~T9D93+Q zB!5BHb`x=46n=|gl!$Kc7Jdt1RES>R%y|=MRV3J6CYwGX-%2l~a5qskrjxgdUE(%5 zh`c=Mm26Brt^JX?O6^{){l1BPOAgMkbyJ?f`fx3}Ie)_0@7 zf0CJcY&|Z9bv5qtAtAjqhLC~;wWwZi(W>ekB5}t+msQn_PC@!5gOGyMp_);(j9dC| zK>E`mu9kT3^P$TtFwA?<3;?fq$wKa#cZK24J;Iw2PrM#>bAg&-6 zqzEDlI7xRHCCLew!ZMFrAfsy zwZcFsSmr}GuKzA<=;(LWiV@n7njs_`lu%vME=t~`I9nK=P*AHkSU_Z9Q6YSV!`C+t zy8K%%My3=Z+IZ)sG*5p>&dRE-p_xouXBUn}lWPe7dR0+BsrUPHd7=U-pKA~6GFxqO zB?-A6GAJ{GO4UeB?dga_UC|auSP=+LPN#H4M_`bok4#EO!naZnOBJcuMs1K5!}!!U zjJ|`Te@@&*bx<`3Jc4$jB*nlqu29)VYY=fte&7%cuZ?OyjmvPbp44=u9-TJz$PDs9 z0D&%M;+QmM%;>^LcgkVXj6;^vVFsRQ5UVpU*k|5tyzVC9}>NAZp) zQvD0hpkM^JL!0{>A5&?yXtl4EI;9 z2YZeHyAtPePd=BTI>_$y_tJjPtZCFW1z@?%Z3_H6^t*?A(20s`XY_-D8A{@?Hb!>*Sk7i^m5q z;B4n{`6gGOM*=2Ua%TN#6W($Y!EBR$+}Wu9JV4&rP~Fesf7hDC+OfoSaq#4)hBNlT+>P?C=QxN%l!}U0K8Aq zddK`2J9iws%$z`iyR>dx{(GNjTb9eGc>{bJKGG8WaPX|^FmMMnJ7_4l;P?$?z2)D4|LVjh8W!Y4Kb`pLzbXa)NkJv=U}viT zpIi(A<;Jb%Wnej(sS$>A6NF9YiB17aJo(MifJJ0#aej~D)|jS4I9Yk1x7uBd*^;T; zpo{cS`yeub1AzBJ3^dr1f2|Wwo0x{8h=sRe#*D(rM$JcW}c~eM|Lz zeA~Q!he~Y%iy&Eqhf+7|zh8gLHBNQYaSqU;2dw1}7H+bsa9>-X;Lkf#EufpP(Y$R~ zUPbweYQ2VyU#rt(&v6ptJ*-Km7tb>P6t1TJtMZ2A?$w zku_E@RbsYQKnPI=H;V#|QMGW0HjGpY4e#+*fIn(wU1Sf2Gn7e3Av^ys7a6j*w_JKy zN_zmLELTN2Ym9e=azxU87-x568r~FVMY#i!HI{A3XpD& zB^7e#y-*Pa8uOD=ccH0TCYL3|P^s!ObhnAQO9=}j(?yjj`G}qh`4KAmc#2v@2zu+{ zOi$p4F&ZRFu+hV?Fd~L>mPjciVjGP?+SUf#3O%q)FR1bmeE~ssHiZbiiRf~&DqRhn zw(fBxQ7m?vLLVnsr@5L4DBDvA8~4Hn@2Ei}QSYa85lc`*8^ELcqC^Cix?bWIIfq>Y zsa~o3iu)Uh(E@e~?)XWhW$4goEMy#B489j^SYI=`q;yQS15C^`iYf2?gbkr=m8!DH&AXd?kbe>elflezm#cS?pif_)=1hJ# zb41ibrjj**K#*AipjG%`q)aY={vx_S%&5K0s#N+hh9n!&X1nko`nZ>z9_croHz70U z+6R$T20@(Lxnj_V_yR za?Pe=KN-a3v@rGe9Tf^EgvXKCS`Ae2MjXTst7YAx7;!>K-jz6gWz;w#!2C!+uj}MT zKcqqPlj+NGX7kuvl_CLCNiK7Ihnky1Z@9K+MB7Z7p{PHPCvL8kfPkBQvIh(2tUyU0 zsIWDabeYhMteJ2uH{TWckt8ur2YC@k(N1s}J3L}gkl)Z0zu(c?NQj|Z99rCNrEREN z%~;lgHiu9dr|=D-`qCW|9Tp@A!#TSUbz2)-1I3=Mvb6zc>TGvHrPyGJ*ff6lrhF$z zOo=Q}^#C*sm)eHS&|R?)u9B^jh^zggAu+ zX|*!dzAFib1$~@(^H;d7avvJVu|j7tm=V+1MroK8>c%Wa84gnx>ZPViAF#gzS3G0T z)#>l9B0xR_-eczGUI2n**v+mdCW?*hFy_XhE%-i!-ek=^UM8^yphoY+cLohsO`BCk zOO&Z`VP`yA%kJOyc074qNWtK!0(qOa5Pe|JNwIii^Quw*T$BjPT7?D;`(-ztrU(j8svjK;Z)n!kFH2V%LP@s!???+!j=y}^jfh_ignAoCRQet~1F z3AXa^C4ULypjxz(hy{(lWL2G6lqn(qSna1SCXfW@d_Ejg*TNK{*1j7axMdXl3fhXb zK3(z@F18+9HrT`dS66B^y`E+N@ukT7ugcng+WY@+goXd`*as@8|JeHcM4V%AjQ+<(<(mdzv5ai;(tilem?D}uAu z006%ADjPztzZ_Xf;`-`z)Shwek-X~t{eEx#Yu;tK4`>XTN{=mYS=e@z4G* z))0~Y&3!SirD!l6nJi_on3b}s_(lnW8HflEscmjuM)v^Z%gs`jrvfZO5s*8q5ZhX$ zx-w3DcKY$-WeOW$c*Ai!(z-3{SO_4gm9qUO^w{8>cZFgb2CWXGol;TDBAAY-gjN|y z$Vih-8zqGr%56-g@>Yjq`O309#4Vt^bJ}tI(Z4Pbk{7JHosyq2h*ySwXNd=GK1Eu$R|qK{pt!N>LbO}8$~DVO%$m!hN&RAaZj-XHk`}0lpB*RIkD@t8@`sy$wIpK6UH&tRX`00_c7yIeyZv`K=~jQj>&mRe$nRa!Kw*ped} z#iAq3FVdbRyDu)%u)}g6bHSp*hf(Xox&&8-t3tuI9yE|b820#? z<^gc%i*GM~;s&4Kn^czm4z_d-u%P0d+etDXbDqDz+qk4>JfWD@>`P2k!!L4Ng3Vu4 z<8Yu_mOY$2CEqxyO-fIa$0RIN+x;)TkbI#-%=w#Q44z;QsiC-gjhK|vpJA+ir#eF8 zKl+i@jEu@xPdpS#&>hoW9wL%i18h9v0n3R;nGc_sL+orf;*IAjcSG^vNoS-ALk3>~ zzS;0s^i2wLbdER&(k!PcWq(Akp5mZ*-k_jH9MTcMOM8}SnX^;}5$neAu(e;sMm4DGB%?Im?x{$tJmk9BBL z0MHzCA>tYYFn}fD4@0SRa7|{7hXrKYE z;!ml(@ma(lu7_Ffk=u;%xIR9epPF}{{+x22<~-hbKk8Pl{;d&=%E!$Gp^KG@Q%Cv2 z0)%ac`=IL^`TTl~@a5if6SE7~kJk_1ZwKaDakEXbKx%juC@cdVgUd6tOW%>LZyt%49299o+_)6tHNlTp82|*Y;O#6hA`LDTVinHnG=9BFL5{K=-})A$sim|(bZMO;qiN@S zW^sAbkqp*m&RagMH5LqfoP&d%MovUhxnZj58qHWQRF)G4ktSzkLzZsZ2LC!|jqpfO z4WxaL;i|jvo`=|a#0+%i^d?d9eVVL;>7^roCPG!Zk#j(4&LXm*Br~MnNv>eInYCPJ zYX+xzUlSb?#GVXxgrzBaT9~;Db4Xm+AKP@8siuJ3)IxzF8UayyIj2%J2-Fv~Y#V~|b*w|_l<)m-Ez$i*2+5yFlUQ49@zq)@F zX@|V^MM_-$EGtInGlWnp{v|1I={3LJFA4*H`uNqnqG?8eN~9>UTNUOGMH*xpgc`(f zC6^IAj-M}yksS_l(6G`_qA$?Pf5p1%MtTxjTuMFcYpI9XNhPwuy&n zI2On^|fz-a_WzFclG_a9WxBxZGy#BP3%^ zdvUO1Ewhg~kI?OC$Hs&>GcJjdec-Ni$@ySx% zGRn43RDNF4FFl8=>TDACTO7149wmzH0}t~Fzx(VeM=UrNjSB1WB{L>#0R*_?z_JZ( zw=?L$x#K}Opfu>giu#jr*MZ+HI{AxvSAze|kopHv{Q0g<{tB{5I*)4oA95H_NZ-5r z&qyQpUwuFc{sFl7_w7Q_!PLV3fAdF_%%w3D|9VNSx+lw3Rl29b1g>ok)`?vg@+8Y$ z$Wb*>AkL@-ZR)bKTv#Qms_lVNLyP9q4u#M@=`k=dGUYr$GB6=?o8}E+=XCRMzko6< zJx@&4T_o{2#<4Cxb4E-E&2kVw3T!LDGa#nKA7r z)pEYi8xGRadcNHQMwd#*p6f?RI~_D%sNIc#{xsqm!bZnyo8j~lo^53_(j(HX7=SI=iugP{l?wlpTQcmIbjC5l*|L2ap$ z;9zUwASEM8M4v2@rKrHRRXIu=%~7JOhI>NiP(N2CqW1#w9N$P=Ik`K$chvZeUSCZu z%uJ}6INwZ6EOWN9Z$oVOLZ%2w%Jeu>gf3%-#S2B4T)T53We)Xaqaj0S$QXo>5x<$3 zK6C|`UHj zps0J*enJU08^MGJjm%m~Yr%+#Zx2|>z(84q4B2flh?Ar;i$`~2PautR+XP_?{fTmi z90s|Z0eN`~+@P6s;R@N(MWFpFhZ4cm-RS6RRgon65Z6-yY=mD`w zIoRf<tmyU#SujDCI^tHKv~3wMIjplG&>%A(@eCQ6k^NU+&P&PQq@M zvu%3$Tcu*`aziO|I6uIi9eRVlne|9oqjYZaA(b6hA;npbUna)8-yQH7^>*P36742j0wtJo9^l(%@GneOart7F(*U<;t`*$zbwohkJ^L`jYvwiBLDBsdSmDlx z?}mNS4J)N+%KkXMONQ9vbZHrQ-kA*6d)j+V^s?~IH=JZKqhOZ`e;GR8$dcBzcen2K z#O|}vfn(oz#&J7&oNEtQJ8T#9`jE=;)*=2{_^l4rqYskP0??ufx&d}c&G(MZPV&I2 zcJ9r$t{O3vVN)Z=M^4y55xQhO+{iyGMf#+eBsH zih~#WIU$qCkG`f3EEXy!BeQT7CT%kS;TzyzJNHQ2-yP|nsr%@^-rE0(9`&ESAphsF zij-IV7qtFmwVq1{l|$jk`!_7-GDksUB`k+eL~XVO5gtJj8bRGVN{pvPqI&(8MCQM}s~B6%f{N2~FVChmHpena*1^$^`hDYUKXY;GKD;p*<5bTaRHJ^=p&)1aA@%tNTh1xRk? zk!c&^{OObcAp4Dc8wyP6*nJ4$utIrTGOiNi`mSVTElRlI$X3=X8}p><-2zjJe(Bcu zro?<#u!as|M&#|hawB-ng-VQSnXxF%nmU9cOZGvzdBH2}wKrK1eLOPlI>;#sXx@gE zxG`!Lk0l$|RU5aXNAxy7Fc2h$ye!>B5b1UptM(wHT=54Z7MtQxdBv5q7DK{^vgdxag;Igl{$&TK(lzAXXK_w=KsDfg*j*_oVu}4FS(3%F6AP|49E*mA{5G^<#$y;|iU10! z5(>L{gCy5!F=rX#M9+y^7($8qWe>8VBJ1a zPo?)>z5_w*ha)4-@F9oJfLCTi%3e!A-h!k8&B(GysdmznBvkSq#()(H{rElVX3;*vbr4v%yV&ww5J>hz7EXox~`b&_NxeFWZzO!JEdTZU{kx0UPCY zB%I+neSU3EMR|R0G>@fqQ|isg<<6HR`I)s+5>Ec1yx3f3rtz=gW8I|or^9(ns=FIP$J^**;;CyiY zIn$UW)li(mO*-BhWdN4zw12lcto`0QG>;%>ZF$4Upqsjnz zxq!eL>ljmpKL7`HdIzb0^>?iGDHYGJpVFJOf~i5_?HhZ)x3Fe2E%^*OqhcQy3?IYw z-)kPKeEZS3Xay?rt>;U|gE!X$VKu%!1LW>L&t^&`56be_^D4LXI9&9sU(eBI*Q{;i z_!UEv-u*@m)0aGH+HdS!DTKDaATVTRx(`ug=7bLBbIAP|Ne){iWC?`lr(;b6wyFrk zb#{bp;Ay_Vk)9A%0ANoDue2#&n7jC+V%ub+@_`a)Cy(=?bKNvyQi;}BV)kIBoo2E# zqbD%OK7!9vpNpZEnS>P9>EP0yGbMp8h`0I25Ltr-A$*6qz`5G^Rl-am9U-N3S!}0)( z$XKw2-S2R_J5@?uVjMM|`0e|0;yyAGT|Ga#^6Y)1^u2`6A84aq&~l5OOgW{!#}W;n z7+P9Gh(~kjq7|Y^aD}d&>?gME>$iS1-Ocx|&q5M-2mJ78) zlqBU3RN6SG(^3}8R!o{IH3=%vF#$Q&@dqMLOF2=wIj_b1hy7lb^kC`w!#bZ8ep4&_ zy6s!5ZH8xdf>3%kn1-(=KhH7m^b7yfvG*4H$1}fe7wnFPmvukUhUK6)=(9g8*@kXt z&~q*WE=$NHK1 z_dA$+_?kgpP>zvlp$Wc;1Bh8|{_+tGJDtU$5V6aBV*hB(Ar+(M;nX_8Q^bRbc6ELTeS*K5TMcZTUldXRQr_(ul zP=RWzehdARbD_0T7q!GDZ1By3eK^2>&4?mzi4K-zQAUFXx^$O72n&RUJuol#0LcIJ zN`98L9ArYuKtO@Fixfp!Q!&nlbqn(Z4taR3n2gz^xYcq*3u|k@dq2xmTcE5ci!O}$)Swwl6Hw+uqDoFDTkqfC3 zU?~v_5=XC0e5LCjt&WZ(<%zYfpO!0%C(sh!&)oj#ei8gRfvNNZ+8^1Ole4YHQqAWr zv++M5gV|>%(=eFjyCdrran!AltGadvA`zp$6L=B2#~{K;K!mF+AxGQH(*azA+9aJ{gVo*+ zbcM0mkf5rgLKG`m`^MTTib)~-7QJvHHtWpMPmk(Z!ofZi!jaL4z`B&O*~3lZmroM9 zv9i@ktR1B6+NranL7N_sSyX1(LSjXMvtLKCtfmIq)xlMXH#TD2ud67cwMY~d)QSQT zoc$wt6JSK6C|0+GC^hJ5_I~rHObti8q@QdK;PP#2?2yL9IRo|?01aY{dqF))nU;xE-W1)T2m^9g-aZ3$~ zzmNRcl)fr&g4_z)Ow|&V^@4(q;uRbkfCqxvEZvfDWB!A0KWn1zP$Cf0CzK;>F9!eiMVX>WOaXs0=(snEz zKL1;w&;6U|+oU4I7=Aft<#bdKKX@=&%s2(X`>WxcsTU0!REH>~jSlg`jriGF+VfLS z%*;o3o=2mGRJ4|!6+4TQjR{V=i%VAUOFU7A9hXNLepwVuGD~ref?L1mOS8XvbkDfb znfdvQg$&~+PrSc+a%a$e4{gpdebWn}?z$kAe0@@^c7DI`dHkG)Zy3<-zCYz*8MJ7# z+IkIvl9S)pR&M=cGwIHK!Wn15H7?6FZdo5LTObJX-l&eBF-jt7;VS8Yr>eh7FLl$Z zIh8&BOs{52i?Tj(I&O$^dOBVl|cGsE4#lD5^xLvSgUXp7(5!hb0t@CG16w5-m@Y zMo^8Wm#r3sTLjr9!gz%^*|1y9Kff>L=WJxco@jvx^i-%yn@{5|Z!J1MUf4+-y%^lh51V}s@%a6 zXBX=lyK@MvI-tLk>Z?m9ipE{pW|a6v(g(&y!=^ZXTbi^xNAmMWk{5WA7kSdV0M(0- z(w(-_T}bIcjNB;xAk-~}4O;swWp)qPEy)#vXRY?dFx@T7W0sAH}%AD0eMmxh!{7K3AE~P zu3IekHa>24tWr>#hl-^lqpVe%>^^F8r|u4p55pJ?@#r`(Kl#X(R}J|zKMlnD!T*67PB36nSH`C zooU<1Ui~;TH7!h)JL2F&QFjBZ_YKbY%Z~XvVTAwnTvslLn;!A-I|VbVVcsd(1ViJV zh9Wjvx=P;aLNsd;+yer?kwzhBr@ZT$81i;r7Il~88q*d}26D>Q?L)S^c`N< zZM}2#g{niv8BeI?%y}6y=F*(Bb(o_5SZOgmM%?e9FnZ1ah)?;Vw6#FFsgDqN@dP8Q zaMw_qqPJ zDQW$sG{Q^g90bYh9#`1sMYfMHye*4qX5qD>q`K{$)6N@ZfG>D9sx-AOH(dR|L|Cn} z+C-*uapi_KsjU4)+K|H=P>~DTPsX#s0|;LN1pIl($hx9bLvbVXlXtf zfE?oa>-f_r$~O3&IKBYcR}9BO*%<=8?FOKJ?ClhVfYapql4;KQ+Yr&&2kKW5EpIZv`_3=KtEQ z{~N|7Y;0)j@L&3*gAy!d=jFbuAWW?;1mhx*P%}|LRzbf_;W&9cJut;&Hi84_MOMS= zbB$8;VBO)f@OpV+WL!jKuQJHnFF}#hl&HC@Ch6~@=#0t`um`HcEn zFnXO}erkp9GF1uNv4-ntA!lF`)(aj5YN5xYGSMFd#|AOj1lvdCF7FkUnVoMmC<*zd zPBYf9245KqHCu@^FQZQG=Jr&pdfM{&`cBT2R+VX$GYmint4~^Cqmmkyvu2M{veD1> z@lGLeRG*b~_SB@BNi}iPbe7y(Ib;#GSSfJ`$qFpK@D?`>PR7?2LP{mAV;3n@--o9x z+Y!CwOyrd*@3f6MXXFycZIF=Cqma}lPs|S?Wyl%O<`jrN%*jtNqGq(sbM@)_5y8w9 zf`{uIc4ZK)w=X28D>}ZN4NZHx7$3*-nqWois4v3wZ^%X}grUL?(M!I6nOK@`pzo=n<(kI@el-y-2Y5VjhFT+E*DO7RzQ_X(Vi zOMBm1;gt`M%F|5v53KOk>j`(k10k=+05t*C$u3x)&pRKbw*x$W;o0vzXgWMwg2$<0 zbP02=bn^K_S?}LYd8o86r^5v-wv(qezDKg+ij^mZK5YO=w8tXwlXF+Qk2!K7I%Bv^WF)1UJrO_vmmfmt&;xE+r;O{X}S@9&pWkbf|% zMeiXM3AUgPIicW=h}dH@>u-epfpu)ot!AopVhWyJB#uPEeVi&_e&_x3>h}SW|#^GM{a^-%vPr z*0DZH0u+8Fs0**i(&`|xy?`s6@&@CD@1bhcj2GoHf+(J!n_CD4qOk>5L2Ir_X4C#r zDaVtKum4FDzIPL=xlz*azHhWybSLX=j%|>iQDmw7oF1DNgW^6|FyQtV;4?3FCdC>| zD0e(`z)@TtoJ@VnwXD>sXKoXPJ#|(NRV{@dyjzK`#hF+oIoXIi$bft3M;%;#&NPva zfHy4XC&>LOo@dpp!%jO!7);%QC4?jilaCRx3pP|ZV+O?j{Zf#GG7p|uh4U0}JpP^v zd%TW{wTsB%25|3Ts%_h5Yyk64JQ9#y@|(Q**hz0S}+NCtDLd7nz^L2Lm3N1@S{oT0}i? z3Fp*77(*bA%$q^O+e7US;)ak8;|PwX`5<4JU%{Dk5InY_W)Cq{B~HE4OXh_8k*o>c zm&8)UPYE&}Fs$(tjU~7^*M1#j#cUH4GTYu}J+QtY7W$Xu_#WM&4_!aruNOEaOhx1X zSP<^-+wpw$-&=CF$+J3AuW#?ED76n&*ttJ1O{#N_3NWw3jeP$(7F6$ht>0r2`aj3w zKRNt=SA6^%%>5@V5)>yO3&e;JwEd%wCLk|>h)k!02Aw^dRYwjPQgq+rPG!ZU*=W_G z`8?)+2mVG3Q|c$H-ouQ~=|n~f`{~>8Ikq1%4u=`{it7wv3*s_6k%X`)g~ujeZrPzo zRVo@2sZ+<*ud)&R@z@s)Kuh;Y77~@lmOZJFxLNgy32wfFu**wkeW2X|t@#xv^eV%y zZuX{_ptKQiny41?B|V17THKrk}dVnUvlj*=E z*Akm~MzR1g*WADdezJ@#4?C2?m`l~9sQc_Se=Z?`yr?K``g8qo149)!tsJo%Da_u6 zRw}xN^jf& zn|r9#uc%XVrE%j8g$Il->B)(7Mzk_7|8MPx}Wo2yoFDs~uzLm4Fh?}9Y zos+q(%|FkiQdM0ESry}x4hhN74+A|?5;7Dkf#6EH#-_yi=j@n5V-p<1K&?I!IdZdw zW~0S=F`u(8p7%*n<)7m0HSOtBsi(unx4X6F>}(%bCP8sg;dSs&&uicAudVCtt3cT= z_hTr(7miEO40NDNJg1Rb#c)sF6~f^xyoTyKZoJ@l8B-6#B6lI+5>gd54QQ zgBWxwkIq#87WBpy?qp`^aBl@33K79@K1wIbc%+p0`VSop_4NjHGA0`wyZt|Y{FPYg z@h5Uo4ap1Z>{X};86c7w@g8eRPW3_(MoOy3VOJls#TqG)APtS-rA_AEXCBhh4-L37 zr9g|562v;)^sD&`85^baek>Znm_m&1qvF9Y2v{DhmW?8(`2v63a~yt^%2IfA__Ujw zd1ON5G?C6P7h<6;@1|Y^2aWbwPjFOny34UHkuZD2Xf+lq{HBgs$}5_e%&eKS5&G^C zw&c}v^WC*>E~%YP+dt5-SF8(pN@llgOK-GNY(rY0!A%<#H%+ElcAC`cJ%iq6v28xy z$b|EU{kpw5$8+MirJ+bzKW=^Tl`7@29;J29+BeMI73Vv`n8MR0MBrqsN{5@|Cgw3k zxwOPYXRG;LD+K*!mN`Fw+#l`C8CDV%7Ko*a)c@+v;Z>9GxYMuEZXj-Ju2NjTeqnNT z(A24Q%+{51-m5|{g=rzV=n00JfCEI^f3}%Dfw2jbY&A~xW-_jM{^}gkwwMSrqGc}a z@e)!oY8HmKc$145vXYrBKN8ZgtLu$Q;NuBa1lrwYb>9C2_1zBMpkE&4RwTPPi8GU0Gocg~ACHMz;wWkCKPCe( z#OrFb%vrOJ4$Z-{!7^VrB&$v_vPuLPt(bF8zUX;2pOIP9?3e_ZdNSZ^uB?5&dz$(D z0_$#6)mthdnhUk~+$lM{{!^P8o|Zb8!(QJ?C5Z7;oiG#JC{B&|d;m+GYN@41hrVGs zqM}w@1!frXX3SzgOscg_)Ejb`Ifc+gOITiS;zxKsupOu*N7&6YK9*m5FKT=6S(_yV zbQ=(!1^2W8X|W+^C2{(=`v$DsVIftrva$o`l+G*V2GZH~q=aeBGu8XXqdm784LnR6 zn4Cwn5=gTA)F8(gC&cWe1{YS538A)@(9@FRl8kHo1qSl?ssJ@@F_u+v^lT|34!e#h zW)@Y7%!_8;vK$t4%omD1a)x*bxP4pZFJG)L>*=Z6?AGeboz55fN0@2c|^pIRD;V0 zVvMlAhGh$Yh=sp~9wcfTF=OHfL{}$bi!TCTh;2|LJ7V}`0;b+1qXdJmE7NkA6VBXKLh=JviTv;vFIM1F_5O@I|)l3b`sRQhAnmU{!)0 zVAxE;OB5+5VE~=vmQ=z^1W7kxfSu%)R>DgRXwb*q~wgt0&}M z?DO~uIj22`5w!acQghgRNnLNn7y0^GlPDU>godujy586ImU%+(&Rh(F=sCq zs9eRnTwlelC|I}|Jv^lr3idl%%0QXPkYsrq7anH~zJ`E0cLb{K7owLlDKqAr9{amz zsS@*OI83mEegZ+eFpEf3Rt$QJ*7-egYmZNF=R{4M+@zNo(!|PW9i>B|L&dHnTMM+d zge1aFHG+ma=%@_JVZno{-I8L8$8HNYK|GL=-{zE7DZ^g5Qt&Q=&?lKK`FQvu5U)fJON77_5 zu`r{*kOYHyClK<)A?wUxA_%eLYtVP&+yi?@0jX&OJ3x69YvCfb$s%Z$h0qO%>m(S| zYg8)M+GXEQ+k1u7+qp^QlCGxjahH2N*`JTUDg0ZWPg{=Due`_E+&MgdtHJTX?D#rU zVbe&!A7d-x4T@>NSH+!g3bYHYz&RIMrqjN)v6#i-B8N1_VHr%*a!K z;qVv+2Xb>KusdCO{$y{2{_eel?}edPcJIy^RZGcs+A(0kWg#m&%P+ax?)QiU0~ zE7C%Br)aMMlDa4mn3Z#tRF^8JYyq7*+iitxCoxD3YkD&f%ODTp1EC0sM`p(wf;s~b zZ-0A`h;eR10wOGr5ja3Fl#roB^E?>ZgyEgA)c@jd-tKMDvU@_@?ImON-Mq@RR5}Qa z6swAUT#6pz@LDw742R3jqzc%vDA8+f%4zEAu1{Q8K(1Co_vcFc2a$`>0G>JhF_do!VJd>7{93-9}r;&(i;0v$MU*%`7x}vNYC$ z#%#j8FHjlf(H^H%am#P?-L`?EXPaeMG0zQr@!s|o=$h^dYPd?jcMy3CbJE*1c4W4K zZ-rcC%bW*UN<2oM$t@=-Ju+;At91>J6_s^q8D$sI#n!_dEe@4YcjsuIRuedSY-7X9 zl^01Ms|qo;vW}$-*m5~^D zdss@^$+u7j9_jz_M`PpV*G_dyAyh;uE&)db%%*7{ze{);-xzwH`@wvF*YhWjFNvdM zjTR!XqLri)rXsV6e%fS+p43P>@&k0d)RC3c2oIU{A+$nkyty_a#<7GqBrOFU*Dg!Gg3NhC=};VbdIaL_Jtffmg%Sk&Zfat&VOvq+pV zC$7F>0{_CdM%PJLXteD}k{X**dDz72VgWb~#)`FaQ?Ef(TKnSs@5t+ld;c6K-eXA+ z?$Z5O4Zj5q6Bm$2c^o8vM2MvB9xt;dFj{b07>9d$t3xx^{rld+nC#yTl3s!SdR((ps;$E6|xsIb`T+~Z3$f!v)T`+(S~h0(9cpQjWZCf%V>eyb%V6^ERw-U5(X<5Zs=Ul0r>O^&kK9xEF@~h|BpJ}AllqPR9x2M*c$@&H? zhUY|2@L+>Be)4XZn4JjG8}cL%q*3h~cl6z&Oof6=J?HAe+|Xq2_c3|Q( zjQqTC9Y}pi$MSyU@RsT)c2nx-)q_XP`YXP0LxM*PGY%r_@B#TQUbv5y)w2z$lj|DN zc=Q+)DQ?$sD8t(_SUIc-#YUMo+kBgAY|%{{Hx&(6bz@TxhPDVcDWnr=Fj8~U3KeCt zNDjF;IgpW9WU3{R)RixfzF9ph5jP+dFCaBql5+BsFH3>J!Y<@8#zrFSXvA?O9UW?b z>$gu8%6Mb1bMApeRhq(kuB5y}pwU!jpU)cyx>Hmaxr3owx5%R~6Ub8-Msjw2aW9Xfufh33EGb+yaK)?yt$LN2Zm$wFQ8hR ztR06$nevBF(U>`S4v$7)<9_yDKOflY@&}hq*iXYp4ok+r7@956{X){AV2T6&jCc}T(BJGVGrBazX1FBT3+n2 zzv5t#_)1Yk*+$#%hhlqpO4f~9n>Z!~gwe*8%x1SpJK5zANaxl2k`q=P=DJ+DzuX;L zqG=7m&&a}T=!afWWxv3B$k|40tG%LwS*mMsPPdIT`z`$yJx47C|E{$J3=mZU=+a>u zHoB!^s9Q*u`iCN&7&7~2M-=#6rsksRdD%Mi`ym{%DxLu;py%Qy8Nu)iU*su{2~x0a za=(_A!*v7Q(3_2k=MZbAY(c!VE}mOcfd`#5gmq0>>{@SJL7GChnwBjDuMPHWUm3Jpwdyg)|>7goB?F?x!4whJ0>C)OuTANDkorV4i z-XcrRMS^u2il%GB=4s=zBT&4`+OM%pW-RkG8~^Pn5`kT$rFBF{Wa9Q_>(-7Tt8>ie zj7;yveOjg1M<0K#Mh7;CwZ$VnWCa$GSa`(z&`_091B3=86EY&uFL-+$EQ93-CnbH? zH35t092GJgD#UsylPn}X<$TcWXfp25I`)3Wt@kV+`dgMBrh1i|MU=XsJj>Mo(PfXd zPl?j@+vnE0g?2hp?mED66}p#6!2$3-U3;3UH~3&nqFvq97aJTIGxiJGgwEL-KCTTN zC7%tYw~mRAv;YTo%E?E1uS{=){}AU0C9+T0yEee-ogH{L!gDm7*!P^gU3T-*9ec)z z>CR^Q1k20=-o2I>K|?3jd0~se(;G$V&X5UcBjg2Yow^61v#07DDSOKH-&}{*++?Kq z%X4`W)QP@&o9ltZ>D&>+vpMrj)oXdz{2A z??-Qlab>Uu4CsU>UOlL7$#}v!)DE%7%is)xO&cOxstJR&l4NVMhXX> zf;x78i*4WFYyo%Q95JN@|Jz%;aeC1kJ6}Oiu3^WYFr0|ld-ij4A`jfY$&8{GOY}t0$w4M@E%B_=*{KZZSeXTahB3pkegx&cL2s z@=@rXBjkRVFY@Lg&uQrx+T#3s_jS&V!5CLh}{ z2o!R%xc=TRr;d!i=7^pUpWpCOR{>_|kWZ&I?xA4VSq!reZhPfzKz%!v+g|m)0xB zbuCqvy}N$(PG`Id@tv$zh33gXOI0v=GSi!X7Z&__kJ{P_9rY%&k6L^1El$xOO)2x~ zO5OUEMV+2Y8QF-Em>o?#&8&|TcR6+`WLy#oV=}`Bv2Gw=Y>{(+MM;OaSc*N-8TWbTd_7U%4dTb^l=qJ&oDCt5^A2F0Xa6p~Fh)={) zf5|#r@kMby7zPh8SIj2Z+bZ(a0ixKr=noaErX0Zvt(>gc(Q0hZIWf!H&))vfJw5*U zWXW-Mo)V3)QNmBh=z~u2^srNhM}rln5zn0DH7iBVz9=)~r@QJ$68)H?>Oskm z9z@sYX)nVtoOm*t*eB8saqwxrapR+7-j0}s!k-=nX!nWWJ!r0+SVup%;{-p+0lN1m zo_S4&ayZX?4=$dm$!5V*0r+(({C!@p+;oL8_L$y%>bJ5q$s`rYM$aUm!HJ;VMy3Tk zLB(&s?bE`V5797G88A{vdsEdWe&j1bgd7M~v7pG9V@Q&+DPc_!`9$WZ>1kQ{+govA zsFL-RXv~3eRFT4?j6%1wAO_8m1dEbJaNrvjjGF)OBGaFywTj`WDptt4zgN*z+=~MD z;xzP;`yIL?OdXKdIC|Po6}@s;DAjP1R9$`=l zMmmSHRFVvv6XQ?{hg|3Zh)Y+iHoeU(Tvj`8F;=ZQ+E635$DL(93u*{x=9xbBvKptb zjMyhxsHU#3({hA$ht(8`Qdi~&lsT~{{lr#852>>Q4SO%Gb+4K^b;q1?DvkDUs#A@L zD6tMpZ4V zq+I>XHf*HgT~rgwTOW9Tk}<75p8cQNiz0bcN}r%X=kopQauuqZI@*WjeI1*qR6o^LjN|BX&AVTBPIt=1B&P z{!Ny`T(6rkA^v`2$#}29hi!01ji(v&OSuJa6qA!~diPj!g1{v`Y!ydm-O?sgTcvHj zM1hAc2wc&+FsP}&<2X!98q&r z5;XUdg{*+$UR*PTAId}~HtPj+prVhc>Zg0bS{zu;QrHUBd*P~#ao0$8{j@yDx*26B zBG?Wr>3~)pXEzM-f_53#?ZJCtOTN+Uux_ngJ@e^=v^`OlOp|Km%UE>2jpc_6J;-U; zXsrZamu*i(K24*qzq=z;xr6wlSl&yb#sN8XGZC_{>O zmy-H&$XVj*Xm^C2y4@?B@QEOJ%$sJH(51J(DDa5}5}z?E)^3JHpDMpY4)He3!Lky? z1b666AzC)q0YPd{N>zDPi|w8pj|-dLcrf{buKfj9x31laj$6!G?Ue7}um12I6Q5+& zbuVl&bW*80nR!y>gfX)=n^NRtb?UTBI$u3$B@?~$UA^4l@ou8-4v7b5{(-7I;a4W` zEA&LX?r`B9HqH!tE#MOs{GJ_WqPa%i2R`dAha=Uu*ZS^lh1|CX$2VkKQ>Vm`KJ-_z zyWw)GNA)qEQLC)m#%4>cRD; zxG=R|xhrGS;l9pin|rBOhXCgk%j(EJ&34?7GqdR)nh~`s^RQ)XwH9=7T@>YKD#RKz z474amQxfV9n#`};IZh}taTk?UUb>8zUAt9nxT%BL()?l0dP_;V{f!@t!U_%8J58h>}1CU8gbnLkHULVS0Tr2v)c zGp+30Vf4HNZ9TjjY@44yOh~(uNxLXknNnRHKvLZkH@lML>v7}VkrPAhQX~j>WmEv~ zD~%c3x&pWV^bf|83WZvt{rDmD9TxWADOrmD0IvT*j;lJDJLwx(8B5qW89TV>Tm6e5 zj~|x-V*GA5C1MznKFG_P72ez#3bRyklOn;2B59)o^u}{Za|I2kI_?5L%MHn-%|e3*1P|?4r>#9l(j+e^hD+2vH#QoqPO3!!o-gWj)xgVZI`86847dXIb zSVb%J7&2NV3H8pnU-w1lB3?HTg!bN%Q&GwB^l9j*CeHjUYM{p1nyhYmRgKC-8r$U6 zpOUV#;7~vP5U4TuZ_Y%ZwmpHV#Xwc79>^ubxw?Ip)%0oNRB3Bi_vbi?0IiX>z(<%T ze`Z}=>BY|1(J>?hlSxI|vC>pJ9s#)8q}Z7nt=^^uB5Ap?QiV#s8*#YhN`ppBgMZPY zN{LAh?fsg4h5Y?+LcwpUy!U@n<==w1AGQvr^cJ>8`t(lUt%vmDw$2X!N*gFt zg>=(WM*Y-f9+lG7nIkD=k=B${El!wQA*x(yAT?KDBDJ=NFN%;%Gt!w;C1bWfB4zYz zfP$zSA+tcVP)9*opi3>PtZR{@Mce4z3oZ$TqNBL#@xAg~-I{3d!oT-^+F*Xl{>pTm z=Dp5*itcoI*8dT4v*woi92*M{-6}YeBv^%Xhe)Uj-6}dF7NkXez=gYvooUN(!?7_Ncz=4sYJcyQ>U}?d0=)Rc>d<#TJMbXv z1^ba6L7b`Y9JOwX9ZNS3{Fsp(F-Mn<&)0KK?o)sN;Tz}LcUau*1%wra<%JS`1tFqU z^;TZQC?zhJ6lL|C6N#c^^AU3`Rk5|YIHp$G@B8H)U2U@^SE9(S{DL)v-M+fDs?i4b zxb5cUFD=$kb>&t=V`H1XP}a?^vyj);>siqeSKjdpj0;J;He#_uXHo<5?BZFBA?c}r zeYjMdT6q#+HS9Uqt`f{TD!5NM%xx@eAZtmyVt8yZx#Q05qv|Z{K`*1FDwhT$JLgc& zUpcI#P+#yjZu8P#r$+VBWO2<%>Y~0SHJKdaK~^h>R}>cYxDxST?fG$;+N?<*mCkcw zi4fDtB3Co+3?1!O{Gwy2de5nn$86zY5PM!M3DNTqr>ulUO=negR?N*fqp>nqTSK23 zea`}R1EEw+%P7+i=IH3M{Au*Sb+5QmxL`wR!JL{)U;=x=kZDNLp5M{aTa3Z1Sg#;mGYq=&f;U=~@+1dGd-aRf- zDN&N;wOhR5yqiQ8eOt>4ulm6sqReBSnu+wdhhgZzu!rjVLc)Cgdze!!f%cjS;iT9@K@|vf$^#z4ML~}mz8<~$Ees~`K>2qyZ&W<_q zG{g&~OsZPcy)%#Hp6PRIv~FrBvHo6)_{npUnfdZ(MTFf^G@47&4s z?>FZ`j!U2BhUshKV=6<=IjswLN2O0c8RA0r?WZP-KNJ3>Eh+a=hyPkez_DzhjjyA!6i+W@G$|e4^bTj8;1H3} z6KsNIjc#gQ;gC`HIp|IInIqdpD^XsL4|5|*KDn4y`XlN>n)?AdR7)bl#^Dkq5>dZ36>sq-vt4~_##$8Ry-eM9pV0o^2 z(N=sC&|o(->RF|Uqb{2uGemSIqSc0Rc(y0+{&HJZZ7H<cOxs=)Ck@HGLSqDc^XK z3j^O7hIfgnuRhUml`Yp9SGf6pqH{{Eqa!qN>39rdYa^6Z%hCy5*Dt)t!ijt2EV13` zB%ZBQW_4S)4iMq0XtXK*Zli(>Aq`JpYLe$W(H7EjZ<~xWIsXmMuEonbVC)z3u=UF> z$_Y-}t2~;iDcJ5@Y2I<$_QXJ^pnW|az)8J-Xj~e9r*XNRSE$q4G6d&A=VNT#a(eI`wH2%a-aPyGi$v0yengQ!zw za=g<$h`svZ=)R+MEyJ?IJ&AqU!!av;yb!jm6;IzxO~?m_u16^{WotZ1w2CJL$Dya{ z4t&9MCkh9Y8#Us51M(7wXug!?2fE{d9SH{z4kg@6=*9lXeoLaz@k(#pw0)4*o_&`G ze?#XRV>EFHaZlWM+;Fbrfn($`0|(S2o_}lWI|0-a)&BV*bW$%+I)VsvQ!Xl_mBIZc zP)OEa;1-0GU7`zN?5ctR){~yUiEWVU?i;Sihj{G5!-IeGcRu~q3 zzJ;|4@22x=p~F*%Rl@NG$7`2V$SE>7K@?(vG1^}S{LECjrH}+;pgfQP=I|bLlE*9C zX$5CoH7(N`Jkvm7oHBNDA>`kgF6viqNh{K<>1EcI3K=YA781*q0x@rhWW7Zw3N_~x zUR+>Imr5#kjlVK^f4UjE&Kpv(dSID)VnGX*5qcpgdfBmofkX62t&v`t_yQ{5qv19d zioO_rnE5efR)WzJ2?K{i>>Z#HosS`VmrcUS(ji8Qs0+?(YT~YOFQ^E=H{s1kFT-#( z9p8?i$@{|0DaCX&|1iO*a=-9;Uw}@yCn0-Z01T6;dq+CQM&_D+K+}CtULdcQeSq^y zTwdfR7w~5IJM~h??4==rB{!MdKOUn|}pxu0cVjIIdx@391@ zE_{)6M%mz$3OcB$)D!FPsg4qc6DH`2qss1BWKc(C_t69`?qG_2e4#I0PBV1BvX^>L zyCgk#PIY=5K;QpN%TSv?*~O_}Y}%hLtW$QW{s6Sjq^?sV$u>{`rHd$LL4AGd^J~8c zhUY^~2WD{kLGiB;wuJ2PRgr~6O+WPP3pKRr!A$)9OGWDAplSMIy(y^KJhx=6B@Mft zzV9!69qKrbtkfRz&HB;YA&@Epdj=aKk0Ydck1VQ@H-@yV{odN0m=k4+7#`QVMx5hA z6GxZZU(FcYM};M||4 z22p+a*hft()WMqO2nfo6&#Qa51Xer1vtewVtCs+~f%_uV#i*iBDJ{Ae(7NJ$P8_pi zV>YMYw4wn21Boqn!J+Snnn7%pZ2;VN7Cwo}rd#XYht`hNwx=EEHQ3IyA4Jb9b{o8x zLeZs%Af>Jbb~6Q>%BOIEc2E0*0~!?2KA#57y!sPu2S-$&lGu~3-Ut)EDYMXsRIwpF zq>R)dgesSN`+LU*hY-oDKTd-D@q_z&@BZ&QH{pNmcK;TO{6E#!QHkpgNCF7Kp2$Fw zewpGVViN-Dc_y&gq@s)=NKpBxC2C1p(kqZ@3w2Vo?WNCPU6JTpW=ZILe(=Vt%QMPsoCAd#hxBVPdPc=KlD)9@(}{qjU`*Q$17l}P8!mq~)wCN=%=7xQtq;3E zF7MkXlcvwuZllDby5fui6Rt97%Z9uBoxs*r-77sy<)~@5E(A^I_cklFN+h%MXQu3q znZ@`)p(gtpa-4#j)#TP|7-9cpW3;PMS4uC1S+VFPt~FavrEA5|uhItkZ;OoRHLHOj zYMw)+F?8ANG=OH?Plw7xDx7o_unYqqK6vp{h0XsnM{B7764t;-E~Hcd2iPV&pZLn5 zeTWk1HA=e{UBh^|YTriVZU*eO-TBCVJyEPYCujK(z*P{jo_#`+gj|SscS;!wa96Y0 zbWJ12$*2Q-tW-tqw?{YT97)UU{}V zgLhU9lV_G-d%I{IC6&UH+r!|(6^adN8zdRx(b3j;TvyJw>pIDCse-=U(W4u~3APoa;^>6i zQO*~x1%eyt0tK)Oc#3H$PtJKpA3HGT6ugSMO2o^C%I>A@ zJM2U6OB!Uiig=R3LpNxQ*y4BoSH7Pd=a=f^cW;FKAN}^k|8@;YJN+*$YgY1(BC;yV zNDq3v6$G?FC=pfc3)4@F%2J9tqMk;Ad{p5%743LZI&EkBhB^!DC5?B*N zT6#TWjrU_I)Ai@4rmRnQTT7qF1qTI{mi@{fFOue1ZD)50#XM$!7OL2&l5Y3 zwK77{=33vF>V3nYYImeHlt||wDN|p2Un`*BP;>z^>*pfG#7xU0UFRdqO4%Z2+tUA#o>!(DMD1fUXog4r!Rv9lTFDcaux5%9|KtfAg;0Z(_(mb zphz>gFeQp$hfqi~*2KiXGPh?sXR$a+t3Eyq{cJf6Z9j&eP#BN4ILc8oN`F7~l)&Fo z7i286faXf8bN82e;x;A=F++Y_?5D%YARjeQ|J=sI!AwYK=G77ExxG#_HDYS{3uAer zo8=(DuE;-Gi5<+zb`&lz{uEGblnRcbtjy>*n!mgTIC+4vM5Cr|K_BZDl|1Tvxl}C& z<2ih)HB3Zu$_&1H$hs@F8BKoejG$qsUHZ9!9e=}EKe}zt$S!yc`bhE^7Llpj3ECyD zyi$4~V8mt0h6xM5K#ji9x;iaPjn36-h75qB z3l+-^Vl`t;&{0lWh+o$)Y&fVldD0RaNA9$OX=;Pm16U2iShi#0#SLhvGzsXS*ohBT zw9@ReXrbM+5f(V~dm@UUHq1s8g(*gxhOlRAxAE+@cOG-Zq0|PO7~3l8ZhiJKkcd z?cNFy7C^5W%V(uqjK)Pz_e#r3nLC)%SYXzztH%+Q&AnaJ{-!C?ZjYd_Gfy1R^VLyw z$T?{#V<;Q3pzcf*H2@P5M~&l_CEo7{yU|F`Y{R#Ka`zqmJ`8_F%3GHx3%bTQ$v(X} zvMJxZih}S$suZSN*5_fJy_c{ON*oq>v!UdNsgMgc;TBAnE)0t$EvU1?vSMcqitl(3 z_yQ*JS{~$$&o~PhVbwh``&(Df$Qm?1V_FGvh{Fy66hdPliMQ7j8Z5@J{}Yj%Hh+k4 z8F}x35>ftw)<3dec1I9r?VP}~tB4t@uK1YJb@O-dM;cmf6~(R-h$=*@1<*zWFfW^3 zg0CjptOg3gX0J6cZ?iA1Fi;QnOQ5eTt)3~KoB@c^DkGa+j;}ei88wzZ+$}B8P8=CS zg9~<67j;Qis5H^9pg(L6JW+gVvvlB`(y_k{JI@HIiV5Mssf*=abI+h@^5{9R$}u!} znCXno?uYs(c$&I_M;_5WiMd}OlU^_D0**HYBz^-iuAm(*c5B!?gf>$ z1Z$bl!ld%w;Lg*p2^ZI-@|PrICe{PhjM`dMC_36Bn|S3*(pO5HEx7|O;Re=X9FlY=2k^}Oe2@#XMTE$m@&sB{$2NUGDB zaZepv(e}BSRqjEZ2K$BgB(Bq|f>V|VN6*DKlu3Tcw(4j1%0q36rC+}SJFs)h?$V;P z1_9q^ouxr;ik*ajSJ#5<41|j>wjVSL8sV&Fq|~^u?xY7-4pliicqQI=Q*ZKy6p&PU z1|;54k?XohacvPwJY(SY9jI)2FNL0`dkq;5qesW*pIEjJjCl{r4ziKbbvA)t-O3Y+S)ic>f1Q} z_q5J*9r!KNgU-0J@NF=~AH_0Peqo`O4O&{q7Grt@WMnlxL5W=H+?UA!{6W#j zDRN}|k00Jh2LbqfFFD$Q1F2+JAD<4+$CJ(te4n20GD1v^@kJQwl;uUGbQDd6>e(he zh$K}0?GGyVwO4E#6`$Mk2!dS*iFBBtn#*D?5E7~BRVkzfzA7!$%3-a!sbxXJko*AB z8OB3)%;*aJY^21+PT?8*qIrMDXn7ad2EA3r(cG-`>t&hLp=A~8N5^(#I;^)c2eqk6 zbz#`460I4#etDBA3JvmuM$M;7vs9Y3Bnk)Sm4<>zKz;=mvm%`s#*(xrs$*tRF7}_| zPaMal&MtI35NlPnVgEi?8N=;meEm@+rHyCv6e`=&XV z%7VXBySs=uaZLS&^7A*3I9ts7(6ZHwyob2wR_kTw>$5Fukyi1@yti)>??Wx%ev@GzUYf<((tym z{wt7?ugq1Vtf%4y@7~KbodcdvFWV2F>OLkFe?T_XbgyJ`X7^;$;THPX?S=Fn_(P%% zzb1{PwYPFW*aU=*f!+WmC5FK}B{p(bb#&!yQ58wI|9PR_lRiK36j_3gxGXp&-3REO zQ$CxF+bZ|F=-T;@PCByxaLQZT>3@5%ZU6lDuDgn+6^ik9M7l@Xl_Q0mS>BO1;`&xI z^`ElY@Z@9x`wfc@6lfwTmyoN)wKT>oT9n)1Hwy!UNFkD83hvdAe1+dgAR<8Gi$bK` z885}%FA|X_lQJzETeMYS?{?E)Iq#1-UC%S$WVF>lwun7ZA);BrJY;Q8ui(B0qV}{+ zVttl;skND0)qWuEkzCoqJ|vv}dlo0F9Ws=}*8&SnkBLQo{@q$}bgn^;9% zOev=#nq7=`BpXBB1e%C66dFJ))B21uiq8S3r?Km!Snnahj98?QOExb3QDwl(swQRDU_;omFSBdNXlwGPb6_4$KgXW+LeX@w2Ev6xAI$mv#y< z)4LpG)W1Dg^pEkIMlQBnkxMhz_?E^la*-U6^1j#=!~x@>NXw|ih}Y-%N`}scyhX)X z?KWi+otn6;kBIY{Qr`E26uOVD5_2J-iRiVO4syTseq-W^#rT(`Pk~uAj5IS7$5}E- zlV1eYAy^YdRdOAY@A70n6!?lOI)GIlDH+hPbQ)k zK;3!Ljp6&dFDJ-HVPWc9A=+yN2jMdMOF`y|^q#MQiHm^XnbwMm(4HGD7RU_#!frG! z{6(a9=7>!Tl5C#Zo`!*HFEA_~InExmz&O22iby}<3R*Mn8rA0vcTCAVVRpDc*C>bA zR=lgaZ^gX2tUj}9=Yz<+ zTpJ4U>t8whPjDsJ4&1&RSMw;=)XsZ4cBBMwldOs##xjhkU5l+zFa-`8P`ORLirf z?kwRDHARZ3-}Tf_ZUG;}@LIp?#y-dD{VpfF(LUqOSh#8zJIZi#YJAcuX-7?&RG;k` zf=FbvTMYgl!L1818)s70c=Y18fPNN~qj5Ytqn6fsdslI+Riw^<_*vXgD;`(a?1%)_ z8}>R0LAbE$ZUFY}GpL{{p^Ul?WZW*nX%D!yP5h@fhFUP;_#^ufyA)mv+W0^Q_J(@= zri$2n3iT`NkTiT6bz9n>TZC-<&hX#A96^Wr)~RFZOcTe&a9neC-TnZ8lAeI=Puu>$ zRuW8_c=gfCWnNq$^$q*yD^#Dd_mOe$h4T{lAnnD}$TN@=xGV<+W~92{7U5mqE(cL{ ztuX8afZ+oyalNllbSo>WP!>LZh&o|kU?{tj*XH)K`31qs)Fu(_fOwiRP|}ha502w7 zP!g*wBb44M|J>$)*PTmsX#bJpGRc%YRtO6Xxm{?oEx^%T%>Nk-_M~aCXYIamV*uY> zK-eDgv%7@#%Qpo;yxlMBiq3by^WhI~kB`5nYB46meWqg2#TCyOG6_JznB0MwZy8u( zKWk>jY6tz|a16HT-|1UdDizMrGjAu+B&S4H^Mu1*W84~F@GKX8B^la_*p|F?uXm81 z8Nz4o_L<-P46^x<#(A@8lV?_h!O?_$&vUxf@*f<5RH9*@YA!KDngffDJ|cPaCGhIi zayZ#y%uJ&h5MJErjqk2d(@^2?D{oBsy;dKYaU?{m$*%`YJ#s?OPW4TPP*aFbk_s%+ z((8*s;vZzq3&h$MnUWS=zeWj0IEE_b_!~cY40*nNpHb#FA{zQ()QTlK(=`(q+vnj0@^esilVR zH&UVEzxc)?;1w6da3wFK~&t*nEIjYrTT2wfYGmZ*?rZfG~f;AEa&Y z1Hm@1@9=!HGBa;7+j4xmz996#TolC&IiKP)QQGAprkY$&gLQ$K#ItLt50+f{ z$AT$nzhFp!5b`ve$N3x1UL_VCpGRP{ z>mO&)o2}-W@Th8q=a-GU=rq&ohGPrOf>uC?FqSo{M`t|{)UA@ZSIkGkFk6-#b%tZSXT4?o+ zfJy7|Lh~xiW(|yg8h6lS9*BT3q40F?Y6TS5tF3D=SYNkiGgkCF1`V8r1ft#q4oL;q zAs;e4;N!=8zkC%NVKjewfwhIl6@jOLU8QfI{UVGKXwK<`Ata7GdG6bu^V>sNlflJd zGegDr2@!H?5K7Em1&|6fWhl3YIbk;Wh4+daXKOLJ?-_W2C?m2uy&yx(+!RiEw}E7e z7{bpUk9q1Eas455yo6`a5oiHFe2qWV6&m+fV7+JlHKSTzgymX3iha+_83M3kJ9`fl zCJHj<<>)moYZSm!7`^fuP2xTKz$d;?WQImPpAPNf2Y1-i6-kX%^Z73fY|! z*o@YuKEcSYA>&#GxK3j>T)9H|y>>{$k~XxeQP@n-SE3HytZup6s={mIx#OhKC*|{c z(h9Gk!_R@+UFDzc)cNT76aF)}T+~APgS~0KEA2GY~gfXw?V3Lm>gzxxh zMfh{K@}5!y2QRIcSIAL0vvvrwW-lb!i?@{AMSBab8Uv=cQgC-G*DJT`I12V^0}9;K z3Zg$BGVOAZukWd{R}cp0xIOuo=`CK6qL21K+c>ftZsv<5Io{7gf{|b9Q@_H)^+CI{ znrNk=OjrhydGfXZV(dm~ULvIfziecy6=N3~o07lnR*av`w6sl~6SkG>-4$Ks`WaIz z*3y8sDP`KKCR(Uuw?wBAWG{W{MJtj?SEB?kLrh4Eoa93l_H`SQcoXjCs%jBGg_>Nu zZzoD)KSKo%4(_jy@$;|Doj>Wc<<%M+>!vMRnzF)Ume)^QNnj)8zZIcA&-$R-U)rsV`w_7Y

    =%>>2|D73@_9Fx}<*!s;{SFX;r+XReUC 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 z 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

    qm4Wk) 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 z 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�!!ybUdR4n8i&a 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≻pfc-p+kq>A@&EZJ32ii;nzX4TDQYlf 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
    gy>fqEPDaO`QF}o` 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%0AO0^D-A)i$ldleqyk}TE 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 z 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

    tyv*0yP}nk-pv4zbBt@DbR|3V7ZQ73LXi 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 kF-h#lNtCW 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 diff --git a/main.nf b/main.nf index 5fa2e2fb..72bf2397 100644 --- a/main.nf +++ b/main.nf @@ -4,7 +4,6 @@ nf-core/oncoanalyser ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Github : https://github.com/nf-core/oncoanalyser - Website: https://nf-co.re/oncoanalyser Slack : https://nfcore.slack.com/channels/oncoanalyser ---------------------------------------------------------------------------------------- @@ -14,47 +13,96 @@ nextflow.enable.dsl = 2 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - GENOME PARAMETER VALUES + IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS / WORKFLOWS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -params.fasta = WorkflowMain.getGenomeAttribute(params, 'fasta') +include { ONCOANALYSER } from './workflows/oncoanalyser' +include { PIPELINE_INITIALISATION } from './subworkflows/local/utils_nfcore_oncoanalyser_pipeline' +include { PIPELINE_COMPLETION } from './subworkflows/local/utils_nfcore_oncoanalyser_pipeline' + +include { getGenomeAttribute } from './subworkflows/local/utils_nfcore_oncoanalyser_pipeline' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - VALIDATE & PRINT PARAMETER SUMMARY + GENOME PARAMETER VALUES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -WorkflowMain.initialise(workflow, params, log) +// TODO nf-core: Remove this line if you don't need a FASTA file +// This is an example of how to use getGenomeAttribute() to fetch parameters +// from igenomes.config using `--genome` +params.fasta = getGenomeAttribute('fasta') /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - NAMED WORKFLOW FOR PIPELINE + NAMED WORKFLOWS FOR PIPELINE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { ONCOANALYSER } from './workflows/oncoanalyser' - // -// WORKFLOW: Run main nf-core/oncoanalyser analysis pipeline +// WORKFLOW: Run main analysis pipeline depending on type of input // workflow NFCORE_ONCOANALYSER { - ONCOANALYSER () -} + take: + samplesheet // channel: samplesheet read in from --input + + main: + + // + // WORKFLOW: Run pipeline + // + ONCOANALYSER ( + samplesheet + ) + + emit: + multiqc_report = ONCOANALYSER.out.multiqc_report // channel: /path/to/multiqc_report.html + +} /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - RUN ALL WORKFLOWS + RUN MAIN WORKFLOW ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -// -// WORKFLOW: Execute a single named workflow for the pipeline -// See: https://github.com/nf-core/rnaseq/issues/619 -// workflow { - NFCORE_ONCOANALYSER () + + main: + + // + // SUBWORKFLOW: Run initialisation tasks + // + PIPELINE_INITIALISATION ( + params.version, + params.help, + params.validate_params, + params.monochrome_logs, + args, + params.outdir, + params.input + ) + + // + // WORKFLOW: Run main workflow + // + NFCORE_ONCOANALYSER ( + PIPELINE_INITIALISATION.out.samplesheet + ) + + // + // SUBWORKFLOW: Run completion tasks + // + PIPELINE_COMPLETION ( + params.email, + params.email_on_fail, + params.plaintext_email, + params.outdir, + params.monochrome_logs, + params.hook_url, + NFCORE_ONCOANALYSER.out.multiqc_report + ) } /* diff --git a/modules.json b/modules.json index 4ce9f998..cdb223d3 100644 --- a/modules.json +++ b/modules.json @@ -5,17 +5,34 @@ "https://github.com/nf-core/modules.git": { "modules": { "nf-core": { - "custom/dumpsoftwareversions": { - "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" - }, "fastqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c", + "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "b7ebe95761cd389603f9cc0e0dc384c0f663815a", + "installed_by": ["modules"] + } + } + }, + "subworkflows": { + "nf-core": { + "utils_nextflow_pipeline": { + "branch": "master", + "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", + "installed_by": ["subworkflows"] + }, + "utils_nfcore_pipeline": { + "branch": "master", + "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", + "installed_by": ["subworkflows"] + }, + "utils_nfvalidation_plugin": { + "branch": "master", + "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", + "installed_by": ["subworkflows"] } } } diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf deleted file mode 100644 index 6df76a07..00000000 --- a/modules/local/samplesheet_check.nf +++ /dev/null @@ -1,27 +0,0 @@ -process SAMPLESHEET_CHECK { - tag "$samplesheet" - - conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/python:3.8.3' : - 'quay.io/biocontainers/python:3.8.3' }" - - input: - path samplesheet - - output: - path '*.csv' , emit: csv - path "versions.yml", emit: versions - - script: // This script is bundled with the pipeline, in nf-core/oncoanalyser/bin/ - """ - check_samplesheet.py \\ - $samplesheet \\ - samplesheet.valid.csv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - python: \$(python --version | sed 's/Python //g') - END_VERSIONS - """ -} diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf deleted file mode 100644 index cebb6e05..00000000 --- a/modules/nf-core/custom/dumpsoftwareversions/main.nf +++ /dev/null @@ -1,24 +0,0 @@ -process CUSTOM_DUMPSOFTWAREVERSIONS { - label 'process_single' - - // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" - - input: - path versions - - output: - path "software_versions.yml" , emit: yml - path "software_versions_mqc.yml", emit: mqc_yml - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - template 'dumpsoftwareversions.py' -} diff --git a/modules/nf-core/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/custom/dumpsoftwareversions/meta.yml deleted file mode 100644 index 60b546a0..00000000 --- a/modules/nf-core/custom/dumpsoftwareversions/meta.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: custom_dumpsoftwareversions -description: Custom module used to dump software versions within the nf-core pipeline template -keywords: - - custom - - version -tools: - - custom: - description: Custom module used to dump software versions within the nf-core pipeline template - homepage: https://github.com/nf-core/tools - documentation: https://github.com/nf-core/tools - licence: ["MIT"] -input: - - versions: - type: file - description: YML file containing software versions - pattern: "*.yml" - -output: - - yml: - type: file - description: Standard YML file containing software versions - pattern: "software_versions.yml" - - mqc_yml: - type: file - description: MultiQC custom content YML file containing software versions - pattern: "software_versions_mqc.yml" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - -authors: - - "@drpatelh" - - "@grst" diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py deleted file mode 100644 index 787bdb7b..00000000 --- a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python - -import platform -from textwrap import dedent - -import yaml - - -def _make_versions_html(versions): - html = [ - dedent( - """\\ - - - - - - - - - - """ - ) - ] - for process, tmp_versions in sorted(versions.items()): - html.append("") - for i, (tool, version) in enumerate(sorted(tmp_versions.items())): - html.append( - dedent( - f"""\\ - - - - - - """ - ) - ) - html.append("") - html.append("
    Process Name Software Version
    {process if (i == 0) else ''}{tool}{version}
    ") - return "\\n".join(html) - - -versions_this_module = {} -versions_this_module["${task.process}"] = { - "python": platform.python_version(), - "yaml": yaml.__version__, -} - -with open("$versions") as f: - versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module - -# aggregate versions by the module name (derived from fully-qualified process name) -versions_by_module = {} -for process, process_versions in versions_by_process.items(): - module = process.split(":")[-1] - try: - if versions_by_module[module] != process_versions: - raise AssertionError( - "We assume that software versions are the same between all modules. " - "If you see this error-message it means you discovered an edge-case " - "and should open an issue in nf-core/tools. " - ) - except KeyError: - versions_by_module[module] = process_versions - -versions_by_module["Workflow"] = { - "Nextflow": "$workflow.nextflow.version", - "$workflow.manifest.name": "$workflow.manifest.version", -} - -versions_mqc = { - "id": "software_versions", - "section_name": "${workflow.manifest.name} Software Versions", - "section_href": "https://github.com/${workflow.manifest.name}", - "plot_type": "html", - "description": "are collected at run time from the software output.", - "data": _make_versions_html(versions_by_module), -} - -with open("software_versions.yml", "w") as f: - yaml.dump(versions_by_module, f, default_flow_style=False) -with open("software_versions_mqc.yml", "w") as f: - yaml.dump(versions_mqc, f, default_flow_style=False) - -with open("versions.yml", "w") as f: - yaml.dump(versions_this_module, f, default_flow_style=False) diff --git a/modules/nf-core/fastqc/environment.yml b/modules/nf-core/fastqc/environment.yml new file mode 100644 index 00000000..1787b38a --- /dev/null +++ b/modules/nf-core/fastqc/environment.yml @@ -0,0 +1,7 @@ +name: fastqc +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::fastqc=0.12.1 diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 05730368..9e19a74c 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -2,10 +2,10 @@ process FASTQC { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::fastqc=0.11.9" : null) + conda "${moduleDir}/environment.yml" 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' }" + 'https://depot.galaxyproject.org/singularity/fastqc:0.12.1--hdfd78af_0' : + 'biocontainers/fastqc:0.12.1--hdfd78af_0' }" input: tuple val(meta), path(reads) @@ -20,30 +20,26 @@ process FASTQC { script: def args = task.ext.args ?: '' - // Add soft-links to original FastQs for consistent naming in pipeline def prefix = task.ext.prefix ?: "${meta.id}" - if (meta.single_end) { - """ - [ ! -f ${prefix}.fastq.gz ] && ln -s $reads ${prefix}.fastq.gz - fastqc $args --threads $task.cpus ${prefix}.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ - } else { - """ - [ ! -f ${prefix}_1.fastq.gz ] && ln -s ${reads[0]} ${prefix}_1.fastq.gz - [ ! -f ${prefix}_2.fastq.gz ] && ln -s ${reads[1]} ${prefix}_2.fastq.gz - fastqc $args --threads $task.cpus ${prefix}_1.fastq.gz ${prefix}_2.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ - } + // 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 '/FastQC v/!d; s/.*v//' ) + END_VERSIONS + """ stub: def prefix = task.ext.prefix ?: "${meta.id}" @@ -53,7 +49,7 @@ process FASTQC { cat <<-END_VERSIONS > versions.yml "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) + fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) END_VERSIONS """ } diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml index 4da5bb5a..ee5507e0 100644 --- a/modules/nf-core/fastqc/meta.yml +++ b/modules/nf-core/fastqc/meta.yml @@ -50,3 +50,8 @@ authors: - "@grst" - "@ewels" - "@FelixKrueger" +maintainers: + - "@drpatelh" + - "@grst" + - "@ewels" + - "@FelixKrueger" diff --git a/modules/nf-core/fastqc/tests/main.nf.test b/modules/nf-core/fastqc/tests/main.nf.test new file mode 100644 index 00000000..70edae4d --- /dev/null +++ b/modules/nf-core/fastqc/tests/main.nf.test @@ -0,0 +1,212 @@ +nextflow_process { + + name "Test Process FASTQC" + script "../main.nf" + process "FASTQC" + + tag "modules" + tag "modules_nfcore" + tag "fastqc" + + test("sarscov2 single-end [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [ id: 'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + + // NOTE The report contains the date inside it, which means that the md5sum is stable per day, but not longer than that. So you can't md5sum it. + // looks like this:

    + // https://github.com/nf-core/modules/pull/3903#issuecomment-1743620039 + + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + + { assert snapshot(process.out.versions).match("fastqc_versions_single") } + ) + } + } + + test("sarscov2 paired-end [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + + { assert snapshot(process.out.versions).match("fastqc_versions_paired") } + ) + } + } + + test("sarscov2 interleaved [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + + { assert snapshot(process.out.versions).match("fastqc_versions_interleaved") } + ) + } + } + + test("sarscov2 paired-end [bam]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + + { assert snapshot(process.out.versions).match("fastqc_versions_bam") } + ) + } + } + + test("sarscov2 multiple [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.html[0][1][2] ==~ ".*/test_3_fastqc.html" }, + { assert process.out.html[0][1][3] ==~ ".*/test_4_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert process.out.zip[0][1][2] ==~ ".*/test_3_fastqc.zip" }, + { assert process.out.zip[0][1][3] ==~ ".*/test_4_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, + + { assert snapshot(process.out.versions).match("fastqc_versions_multiple") } + ) + } + } + + test("sarscov2 custom_prefix") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'mysample', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + + { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + + { assert snapshot(process.out.versions).match("fastqc_versions_custom_prefix") } + ) + } + } + + test("sarscov2 single-end [fastq] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id: 'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out.html.collect { file(it[1]).getName() } + + process.out.zip.collect { file(it[1]).getName() } + + process.out.versions ).match("fastqc_stub") } + ) + } + } + +} diff --git a/modules/nf-core/fastqc/tests/main.nf.test.snap b/modules/nf-core/fastqc/tests/main.nf.test.snap new file mode 100644 index 00000000..86f7c311 --- /dev/null +++ b/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -0,0 +1,88 @@ +{ + "fastqc_versions_interleaved": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-01-31T17:40:07.293713" + }, + "fastqc_stub": { + "content": [ + [ + "test.html", + "test.zip", + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-01-31T17:31:01.425198" + }, + "fastqc_versions_multiple": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-01-31T17:40:55.797907" + }, + "fastqc_versions_bam": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-01-31T17:40:26.795862" + }, + "fastqc_versions_single": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-01-31T17:39:27.043675" + }, + "fastqc_versions_paired": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-01-31T17:39:47.584191" + }, + "fastqc_versions_custom_prefix": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-01-31T17:41:14.576531" + } +} \ No newline at end of file diff --git a/modules/nf-core/fastqc/tests/tags.yml b/modules/nf-core/fastqc/tests/tags.yml new file mode 100644 index 00000000..7834294b --- /dev/null +++ b/modules/nf-core/fastqc/tests/tags.yml @@ -0,0 +1,2 @@ +fastqc: + - modules/nf-core/fastqc/** diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml new file mode 100644 index 00000000..ca39fb67 --- /dev/null +++ b/modules/nf-core/multiqc/environment.yml @@ -0,0 +1,7 @@ +name: multiqc +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::multiqc=1.21 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index a8159a57..47ac352f 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,10 +1,10 @@ process MULTIQC { label 'process_single' - conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.21--pyhdfd78af_0' : + 'biocontainers/multiqc:1.21--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" @@ -25,12 +25,14 @@ process MULTIQC { def args = task.ext.args ?: '' def config = multiqc_config ? "--config $multiqc_config" : '' def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + def logo = multiqc_logo ? /--cl-config 'custom_logo: "${multiqc_logo}"'/ : '' """ multiqc \\ --force \\ $args \\ $config \\ $extra_config \\ + $logo \\ . cat <<-END_VERSIONS > versions.yml @@ -41,7 +43,7 @@ process MULTIQC { stub: """ - touch multiqc_data + mkdir multiqc_data touch multiqc_plots touch multiqc_report.html diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index ebc29b27..45a9bc35 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -1,4 +1,4 @@ -name: MultiQC +name: multiqc description: Aggregate results from bioinformatics analyses across many samples into a single report keywords: - QC @@ -12,7 +12,6 @@ tools: homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ licence: ["GPL-3.0-or-later"] - input: - multiqc_files: type: file @@ -30,14 +29,13 @@ input: type: file description: Optional logo file for MultiQC pattern: "*.{png}" - output: - report: type: file description: MultiQC report file pattern: "multiqc_report.html" - data: - type: dir + type: directory description: MultiQC data dir pattern: "multiqc_data" - plots: @@ -53,3 +51,8 @@ authors: - "@bunop" - "@drpatelh" - "@jfy133" +maintainers: + - "@abhi18av" + - "@bunop" + - "@drpatelh" + - "@jfy133" diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test new file mode 100644 index 00000000..f1c4242e --- /dev/null +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -0,0 +1,84 @@ +nextflow_process { + + name "Test Process MULTIQC" + script "../main.nf" + process "MULTIQC" + + tag "modules" + tag "modules_nfcore" + tag "multiqc" + + test("sarscov2 single-end [fastqc]") { + + when { + process { + """ + input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[1] = [] + input[2] = [] + input[3] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, + { assert process.out.data[0] ==~ ".*/multiqc_data" }, + { assert snapshot(process.out.versions).match("multiqc_versions_single") } + ) + } + + } + + test("sarscov2 single-end [fastqc] [config]") { + + when { + process { + """ + input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[1] = Channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) + input[2] = [] + input[3] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, + { assert process.out.data[0] ==~ ".*/multiqc_data" }, + { assert snapshot(process.out.versions).match("multiqc_versions_config") } + ) + } + } + + test("sarscov2 single-end [fastqc] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[1] = [] + input[2] = [] + input[3] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.report.collect { file(it).getName() } + + process.out.data.collect { file(it).getName() } + + process.out.plots.collect { file(it).getName() } + + process.out.versions ).match("multiqc_stub") } + ) + } + + } +} diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap new file mode 100644 index 00000000..bfebd802 --- /dev/null +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -0,0 +1,41 @@ +{ + "multiqc_versions_single": { + "content": [ + [ + "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-29T08:48:55.657331" + }, + "multiqc_stub": { + "content": [ + [ + "multiqc_report.html", + "multiqc_data", + "multiqc_plots", + "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-29T08:49:49.071937" + }, + "multiqc_versions_config": { + "content": [ + [ + "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-29T08:49:25.457567" + } +} \ No newline at end of file diff --git a/modules/nf-core/multiqc/tests/tags.yml b/modules/nf-core/multiqc/tests/tags.yml new file mode 100644 index 00000000..bea6c0d3 --- /dev/null +++ b/modules/nf-core/multiqc/tests/tags.yml @@ -0,0 +1,2 @@ +multiqc: + - modules/nf-core/multiqc/** diff --git a/nextflow.config b/nextflow.config index 0eef462b..f43fd275 100644 --- a/nextflow.config +++ b/nextflow.config @@ -12,13 +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_base = 's3://ngi-igenomes/igenomes/' igenomes_ignore = false - // MultiQC options + fasta = null// MultiQC options multiqc_config = null multiqc_title = null multiqc_logo = null @@ -27,7 +25,6 @@ params { // Boilerplate options outdir = null - tracedir = "${params.outdir}/pipeline_info" publish_dir_mode = 'copy' email = null email_on_fail = null @@ -35,20 +32,15 @@ params { monochrome_logs = false hook_url = null help = false - validate_params = true - show_hidden_params = false - schema_ignore_params = 'genomes' - enable_conda = false - + version = false // Config options + config_profile_name = null + config_profile_description = null custom_config_version = 'master' custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" - config_profile_description = null config_profile_contact = null config_profile_url = null - config_profile_name = null - // Max resource options // Defaults only, expecting to be overwritten @@ -56,6 +48,13 @@ params { max_cpus = 16 max_time = '240.h' + // Schema validation default options + validationFailUnrecognisedParams = false + validationLenientMode = false + validationSchemaIgnoreParams = 'genomes,igenomes_base' + validationShowHiddenParams = false + validate_params = true + } // Load base.config by default for all pipelines @@ -69,79 +68,120 @@ try { } // Load nf-core/oncoanalyser custom profiles from different institutions. -// Warning: Uncomment only if a pipeline-specific instititutional config already exists on nf-core/configs! +// Warning: Uncomment only if a pipeline-specific institutional config already exists on nf-core/configs! // try { // includeConfig "${params.custom_config_base}/pipeline/oncoanalyser.config" // } catch (Exception e) { // System.err.println("WARNING: Could not load nf-core/config/oncoanalyser profiles: ${params.custom_config_base}/pipeline/oncoanalyser.config") // } - - profiles { - debug { process.beforeScript = 'echo $HOSTNAME' } + debug { + dumpHashes = true + process.beforeScript = 'echo $HOSTNAME' + cleanup = false + nextflow.enable.configProcessNamesValidation = true + } conda { - params.enable_conda = true + conda.enabled = true docker.enabled = false singularity.enabled = false podman.enabled = false shifter.enabled = false charliecloud.enabled = false + channels = ['conda-forge', 'bioconda', 'defaults'] + apptainer.enabled = false } mamba { - params.enable_conda = true + conda.enabled = true conda.useMamba = true docker.enabled = false singularity.enabled = false podman.enabled = false shifter.enabled = false charliecloud.enabled = false + apptainer.enabled = false } docker { docker.enabled = true - docker.userEmulation = true + conda.enabled = false singularity.enabled = false podman.enabled = false shifter.enabled = false charliecloud.enabled = false + apptainer.enabled = false + docker.runOptions = '-u $(id -u):$(id -g)' + } + arm { + docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' } singularity { singularity.enabled = true singularity.autoMounts = true + conda.enabled = false docker.enabled = false podman.enabled = false shifter.enabled = false charliecloud.enabled = false + apptainer.enabled = false } podman { podman.enabled = true + conda.enabled = false docker.enabled = false singularity.enabled = false shifter.enabled = false charliecloud.enabled = false + apptainer.enabled = false } shifter { shifter.enabled = true + conda.enabled = false docker.enabled = false singularity.enabled = false podman.enabled = false charliecloud.enabled = false + apptainer.enabled = false } charliecloud { charliecloud.enabled = true + conda.enabled = false + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + apptainer.enabled = false + } + apptainer { + apptainer.enabled = true + apptainer.autoMounts = true + conda.enabled = false docker.enabled = false singularity.enabled = false podman.enabled = false shifter.enabled = false + charliecloud.enabled = false } gitpod { executor.name = 'local' - executor.cpus = 16 - executor.memory = 60.GB + executor.cpus = 4 + executor.memory = 8.GB } test { includeConfig 'conf/test.config' } test_full { includeConfig 'conf/test_full.config' } } +// Set default registry for Apptainer, Docker, Podman and Singularity independent of -profile +// Will not be used unless Apptainer / Docker / Podman / Singularity are enabled +// Set to your registry if you have a mirror of containers +apptainer.registry = 'quay.io' +docker.registry = 'quay.io' +podman.registry = 'quay.io' +singularity.registry = 'quay.io' + +// Nextflow plugins +plugins { + id 'nf-validation@1.1.3' // Validation of pipeline parameters and creation of an input channel from a sample sheet +} // Load igenomes.config if required if (!params.igenomes_ignore) { @@ -149,8 +189,6 @@ if (!params.igenomes_ignore) { } 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. @@ -165,32 +203,35 @@ env { // Capture exit codes from upstream processes when piping process.shell = ['/bin/bash', '-euo', 'pipefail'] +// Disable process selector warnings by default. Use debug profile to enable warnings. +nextflow.enable.configProcessNamesValidation = false + def trace_timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') timeline { enabled = true - file = "${params.tracedir}/execution_timeline_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/execution_timeline_${trace_timestamp}.html" } report { enabled = true - file = "${params.tracedir}/execution_report_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/execution_report_${trace_timestamp}.html" } trace { enabled = true - file = "${params.tracedir}/execution_trace_${trace_timestamp}.txt" + file = "${params.outdir}/pipeline_info/execution_trace_${trace_timestamp}.txt" } dag { enabled = true - file = "${params.tracedir}/pipeline_dag_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/pipeline_dag_${trace_timestamp}.html" } manifest { name = 'nf-core/oncoanalyser' - author = 'Stephen Watts' + author = """Stephen Watts""" homePage = 'https://github.com/nf-core/oncoanalyser' - description = 'A comprehensive cancer WGS/WTS analysis and reporting pipeline' + description = """A comprehensive cancer NGS analysis and reporting pipeline""" mainScript = 'main.nf' - nextflowVersion = '!>=21.10.3' - version = '1.0dev' + nextflowVersion = '!>=23.04.0' + version = '0.3.0' doi = '' } diff --git a/nextflow_schema.json b/nextflow_schema.json index d570597b..dcd5f029 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema", "$id": "https://raw.githubusercontent.com/nf-core/oncoanalyser/master/nextflow_schema.json", "title": "nf-core/oncoanalyser pipeline parameters", - "description": "A comprehensive cancer WGS/WTS analysis and reporting pipeline", + "description": "A comprehensive cancer NGS analysis and reporting pipeline", "type": "object", "definitions": { "input_output_options": { @@ -15,9 +15,10 @@ "input": { "type": "string", "format": "file-path", + "exists": true, + "schema": "assets/schema_input.json", "mimetype": "text/csv", "pattern": "^\\S+\\.csv$", - "schema": "assets/schema_input.json", "description": "Path to comma-separated file containing information about the samples in the experiment.", "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/oncoanalyser/usage#samplesheet-input).", "fa_icon": "fas fa-file-csv" @@ -57,20 +58,13 @@ "fasta": { "type": "string", "format": "file-path", + "exists": true, "mimetype": "text/plain", "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", "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.", @@ -157,7 +151,7 @@ "description": "Maximum amount of time that can be requested for any single job.", "default": "240.h", "fa_icon": "far fa-clock", - "pattern": "^(\\d+\\.?\\s*(s|m|h|day)\\s*)+$", + "pattern": "^(\\d+\\.?\\s*(s|m|h|d|day)\\s*)+$", "hidden": true, "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" } @@ -176,6 +170,12 @@ "fa_icon": "fas fa-question-circle", "hidden": true }, + "version": { + "type": "boolean", + "description": "Display version and exit.", + "fa_icon": "fas fa-question-circle", + "hidden": true + }, "publish_dir_mode": { "type": "string", "default": "copy", @@ -217,11 +217,12 @@ "type": "string", "description": "Incoming hook URL for messaging service", "fa_icon": "fas fa-people-group", - "help_text": "Incoming hook URL for messaging service. Currently, only MS Teams is supported.", + "help_text": "Incoming hook URL for messaging service. Currently, MS Teams and Slack are supported.", "hidden": true }, "multiqc_config": { "type": "string", + "format": "file-path", "description": "Custom config file to supply to MultiQC.", "fa_icon": "fas fa-cog", "hidden": true @@ -237,13 +238,6 @@ "description": "Custom MultiQC yaml file containing HTML including a methods description.", "fa_icon": "fas fa-cog" }, - "tracedir": { - "type": "string", - "description": "Directory to keep pipeline Nextflow logs and reports.", - "default": "${params.outdir}/pipeline_info", - "fa_icon": "fas fa-cogs", - "hidden": true - }, "validate_params": { "type": "boolean", "description": "Boolean whether to validate parameters against the schema at runtime", @@ -251,18 +245,26 @@ "fa_icon": "fas fa-check-square", "hidden": true }, - "show_hidden_params": { + "validationShowHiddenParams": { "type": "boolean", "fa_icon": "far fa-eye-slash", "description": "Show all params when using `--help`", "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." }, - "enable_conda": { + "validationFailUnrecognisedParams": { + "type": "boolean", + "fa_icon": "far fa-check-circle", + "description": "Validation of parameters fails when an unrecognised parameter is found.", + "hidden": true, + "help_text": "By default, when an unrecognised parameter is found, it returns a warinig." + }, + "validationLenientMode": { "type": "boolean", - "description": "Run this workflow with Conda. You can also use '-profile conda' instead of providing this parameter.", + "fa_icon": "far fa-check-circle", + "description": "Validation of parameters in lenient more.", "hidden": true, - "fa_icon": "fas fa-bacon" + "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)." } } } diff --git a/pyproject.toml b/pyproject.toml index 0d62beb6..56110621 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,15 @@ -# Config file for Python. Mostly used to configure linting of bin/check_samplesheet.py with Black. +# Config file for Python. Mostly used to configure linting of bin/*.py with Ruff. # Should be kept the same as nf-core/tools to avoid fighting with template synchronisation. -[tool.black] +[tool.ruff] line-length = 120 -target_version = ["py37", "py38", "py39", "py310"] +target-version = "py38" +cache-dir = "~/.cache/ruff" -[tool.isort] -profile = "black" -known_first_party = ["nf_core"] -multi_line_output = 3 +[tool.ruff.lint] +select = ["I", "E1", "E4", "E7", "E9", "F", "UP", "N"] + +[tool.ruff.lint.isort] +known-first-party = ["nf_core"] + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["E402", "F401"] diff --git a/subworkflows/local/input_check.nf b/subworkflows/local/input_check.nf deleted file mode 100644 index 0aecf87f..00000000 --- a/subworkflows/local/input_check.nf +++ /dev/null @@ -1,44 +0,0 @@ -// -// Check input samplesheet and get read channels -// - -include { SAMPLESHEET_CHECK } from '../../modules/local/samplesheet_check' - -workflow INPUT_CHECK { - take: - samplesheet // file: /path/to/samplesheet.csv - - main: - SAMPLESHEET_CHECK ( samplesheet ) - .csv - .splitCsv ( header:true, sep:',' ) - .map { create_fastq_channel(it) } - .set { reads } - - emit: - reads // channel: [ val(meta), [ reads ] ] - versions = SAMPLESHEET_CHECK.out.versions // channel: [ versions.yml ] -} - -// Function to get list of [ meta, [ fastq_1, fastq_2 ] ] -def create_fastq_channel(LinkedHashMap row) { - // create meta map - def meta = [:] - meta.id = row.sample - meta.single_end = 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) ] ] - } - return fastq_meta -} diff --git a/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf b/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf new file mode 100644 index 00000000..bfdc184d --- /dev/null +++ b/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf @@ -0,0 +1,251 @@ +// +// Subworkflow with functionality specific to the nf-core/oncoanalyser pipeline +// + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +include { UTILS_NFVALIDATION_PLUGIN } from '../../nf-core/utils_nfvalidation_plugin' +include { paramsSummaryMap } from 'plugin/nf-validation' +include { fromSamplesheet } from 'plugin/nf-validation' +include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' +include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' +include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' +include { dashedLine } from '../../nf-core/utils_nfcore_pipeline' +include { nfCoreLogo } from '../../nf-core/utils_nfcore_pipeline' +include { imNotification } from '../../nf-core/utils_nfcore_pipeline' +include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' +include { workflowCitation } from '../../nf-core/utils_nfcore_pipeline' + +/* +======================================================================================== + SUBWORKFLOW TO INITIALISE PIPELINE +======================================================================================== +*/ + +workflow PIPELINE_INITIALISATION { + + take: + version // boolean: Display version and exit + help // boolean: Display help text + validate_params // boolean: Boolean whether to validate parameters against the schema at runtime + monochrome_logs // boolean: Do not use coloured log outputs + nextflow_cli_args // array: List of positional nextflow CLI args + outdir // string: The output directory where the results will be saved + input // string: Path to input samplesheet + + main: + + ch_versions = Channel.empty() + + // + // Print version and exit if required and dump pipeline parameters to JSON file + // + UTILS_NEXTFLOW_PIPELINE ( + version, + true, + outdir, + workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1 + ) + + // + // Validate parameters and generate parameter summary to stdout + // + pre_help_text = nfCoreLogo(monochrome_logs) + post_help_text = '\n' + workflowCitation() + '\n' + dashedLine(monochrome_logs) + def String workflow_command = "nextflow run ${workflow.manifest.name} -profile --input samplesheet.csv --outdir " + UTILS_NFVALIDATION_PLUGIN ( + help, + workflow_command, + pre_help_text, + post_help_text, + validate_params, + "nextflow_schema.json" + ) + + // + // Check config provided to the pipeline + // + UTILS_NFCORE_PIPELINE ( + nextflow_cli_args + ) + // + // Custom validation for pipeline parameters + // + validateInputParameters() + + // + // Create channel from input file provided through params.input + // + Channel + .fromSamplesheet("input") + .map { + meta, fastq_1, fastq_2 -> + if (!fastq_2) { + return [ meta.id, meta + [ single_end:true ], [ fastq_1 ] ] + } else { + return [ meta.id, meta + [ single_end:false ], [ fastq_1, fastq_2 ] ] + } + } + .groupTuple() + .map { + validateInputSamplesheet(it) + } + .map { + meta, fastqs -> + return [ meta, fastqs.flatten() ] + } + .set { ch_samplesheet } + + emit: + samplesheet = ch_samplesheet + versions = ch_versions +} + +/* +======================================================================================== + SUBWORKFLOW FOR PIPELINE COMPLETION +======================================================================================== +*/ + +workflow PIPELINE_COMPLETION { + + take: + email // string: email address + email_on_fail // string: email address sent on pipeline failure + plaintext_email // boolean: Send plain-text email instead of HTML + outdir // path: Path to output directory where results will be published + monochrome_logs // boolean: Disable ANSI colour codes in log output + hook_url // string: hook URL for notifications + multiqc_report // string: Path to MultiQC report + + main: + + summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") + + // + // Completion email and summary + // + workflow.onComplete { + if (email || email_on_fail) { + completionEmail(summary_params, email, email_on_fail, plaintext_email, outdir, monochrome_logs, multiqc_report.toList()) + } + + completionSummary(monochrome_logs) + + if (hook_url) { + imNotification(summary_params, hook_url) + } + } +} + +/* +======================================================================================== + FUNCTIONS +======================================================================================== +*/ +// +// Check and validate pipeline parameters +// +def validateInputParameters() { + genomeExistsError() +} + +// +// Validate channels from input samplesheet +// +def validateInputSamplesheet(input) { + def (metas, fastqs) = input[1..2] + + // Check that multiple runs of the same sample are of the same datatype i.e. single-end / paired-end + def endedness_ok = metas.collect{ it.single_end }.unique().size == 1 + if (!endedness_ok) { + error("Please check input samplesheet -> Multiple runs of a sample must be of the same datatype i.e. single-end or paired-end: ${metas[0].id}") + } + + return [ metas[0], fastqs ] +} +// +// Get attribute from genome config file e.g. fasta +// +def getGenomeAttribute(attribute) { + if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { + if (params.genomes[ params.genome ].containsKey(attribute)) { + return params.genomes[ params.genome ][ attribute ] + } + } + return null +} + +// +// Exit pipeline if incorrect --genome key provided +// +def genomeExistsError() { + if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { + def error_string = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + + " Currently, the available genome keys are:\n" + + " ${params.genomes.keySet().join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + error(error_string) + } +} + +// +// Generate methods description for MultiQC +// +def toolCitationText() { + // TODO nf-core: Optionally add in-text citation tools to this list. + // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "Tool (Foo et al. 2023)" : "", + // Uncomment function in methodsDescriptionText to render in MultiQC report + def citation_text = [ + "Tools used in the workflow included:", + "FastQC (Andrews 2010),", + "MultiQC (Ewels et al. 2016)", + "." + ].join(' ').trim() + + return citation_text +} + +def toolBibliographyText() { + // TODO nf-core: Optionally add bibliographic entries to this list. + // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "
  • Author (2023) Pub name, Journal, DOI
  • " : "", + // Uncomment function in methodsDescriptionText to render in MultiQC report + def reference_text = [ + "
  • Andrews S, (2010) FastQC, URL: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/).
  • ", + "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics , 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " + ].join(' ').trim() + + return reference_text +} + +def methodsDescriptionText(mqc_methods_yaml) { + // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file + def meta = [:] + meta.workflow = workflow.toMap() + meta["manifest_map"] = workflow.manifest.toMap() + + // Pipeline DOI + meta["doi_text"] = meta.manifest_map.doi ? "(doi:
    ${meta.manifest_map.doi})" : "" + meta["nodoi_text"] = meta.manifest_map.doi ? "": "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " + + // Tool references + meta["tool_citations"] = "" + meta["tool_bibliography"] = "" + + // TODO nf-core: Only uncomment below if logic in toolCitationText/toolBibliographyText has been filled! + // meta["tool_citations"] = toolCitationText().replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") + // meta["tool_bibliography"] = toolBibliographyText() + + + def methods_text = mqc_methods_yaml.text + + def engine = new groovy.text.SimpleTemplateEngine() + def description_html = engine.createTemplate(methods_text).make(meta) + + return description_html.toString() +} diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf new file mode 100644 index 00000000..ac31f28f --- /dev/null +++ b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf @@ -0,0 +1,126 @@ +// +// Subworkflow with functionality that may be useful for any Nextflow pipeline +// + +import org.yaml.snakeyaml.Yaml +import groovy.json.JsonOutput +import nextflow.extension.FilesEx + +/* +======================================================================================== + SUBWORKFLOW DEFINITION +======================================================================================== +*/ + +workflow UTILS_NEXTFLOW_PIPELINE { + + take: + print_version // boolean: print version + dump_parameters // boolean: dump parameters + outdir // path: base directory used to publish pipeline results + check_conda_channels // boolean: check conda channels + + main: + + // + // Print workflow version and exit on --version + // + if (print_version) { + log.info "${workflow.manifest.name} ${getWorkflowVersion()}" + System.exit(0) + } + + // + // Dump pipeline parameters to a JSON file + // + if (dump_parameters && outdir) { + dumpParametersToJSON(outdir) + } + + // + // When running with Conda, warn if channels have not been set-up appropriately + // + if (check_conda_channels) { + checkCondaChannels() + } + + emit: + dummy_emit = true +} + +/* +======================================================================================== + FUNCTIONS +======================================================================================== +*/ + +// +// Generate version string +// +def getWorkflowVersion() { + String version_string = "" + if (workflow.manifest.version) { + def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' + version_string += "${prefix_v}${workflow.manifest.version}" + } + + if (workflow.commitId) { + def git_shortsha = workflow.commitId.substring(0, 7) + version_string += "-g${git_shortsha}" + } + + return version_string +} + +// +// Dump pipeline parameters to a JSON file +// +def dumpParametersToJSON(outdir) { + def timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') + def filename = "params_${timestamp}.json" + def temp_pf = new File(workflow.launchDir.toString(), ".${filename}") + def jsonStr = JsonOutput.toJson(params) + temp_pf.text = JsonOutput.prettyPrint(jsonStr) + + FilesEx.copyTo(temp_pf.toPath(), "${outdir}/pipeline_info/params_${timestamp}.json") + temp_pf.delete() +} + +// +// When running with -profile conda, warn if channels have not been set-up appropriately +// +def checkCondaChannels() { + Yaml parser = new Yaml() + def channels = [] + try { + def config = parser.load("conda config --show channels".execute().text) + channels = config.channels + } catch(NullPointerException | IOException e) { + log.warn "Could not verify conda channel configuration." + return + } + + // Check that all channels are present + // This channel list is ordered by required channel priority. + def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] + def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean + + // Check that they are in the right order + def channel_priority_violation = false + def n = required_channels_in_order.size() + for (int i = 0; i < n - 1; i++) { + channel_priority_violation |= !(channels.indexOf(required_channels_in_order[i]) < channels.indexOf(required_channels_in_order[i+1])) + } + + if (channels_missing | channel_priority_violation) { + log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " There is a problem with your Conda configuration!\n\n" + + " You will need to set-up the conda-forge and bioconda channels correctly.\n" + + " Please refer to https://bioconda.github.io/\n" + + " The observed channel order is \n" + + " ${channels}\n" + + " but the following channel order is required:\n" + + " ${required_channels_in_order}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + } +} diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/meta.yml b/subworkflows/nf-core/utils_nextflow_pipeline/meta.yml new file mode 100644 index 00000000..e5c3a0a8 --- /dev/null +++ b/subworkflows/nf-core/utils_nextflow_pipeline/meta.yml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "UTILS_NEXTFLOW_PIPELINE" +description: Subworkflow with functionality that may be useful for any Nextflow pipeline +keywords: + - utility + - pipeline + - initialise + - version +components: [] +input: + - print_version: + type: boolean + description: | + Print the version of the pipeline and exit + - dump_parameters: + type: boolean + description: | + Dump the parameters of the pipeline to a JSON file + - output_directory: + type: directory + description: Path to output dir to write JSON file to. + pattern: "results/" + - check_conda_channel: + type: boolean + description: | + Check if the conda channel priority is correct. +output: + - dummy_emit: + type: boolean + description: | + Dummy emit to make nf-core subworkflows lint happy +authors: + - "@adamrtalbot" + - "@drpatelh" +maintainers: + - "@adamrtalbot" + - "@drpatelh" + - "@maxulysse" diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test b/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test new file mode 100644 index 00000000..68718e4f --- /dev/null +++ b/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test @@ -0,0 +1,54 @@ + +nextflow_function { + + name "Test Functions" + script "subworkflows/nf-core/utils_nextflow_pipeline/main.nf" + config "subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config" + tag 'subworkflows' + tag 'utils_nextflow_pipeline' + tag 'subworkflows/utils_nextflow_pipeline' + + test("Test Function getWorkflowVersion") { + + function "getWorkflowVersion" + + then { + assertAll( + { assert function.success }, + { assert snapshot(function.result).match() } + ) + } + } + + test("Test Function dumpParametersToJSON") { + + function "dumpParametersToJSON" + + when { + function { + """ + // define inputs of the function here. Example: + input[0] = "$outputDir" + """.stripIndent() + } + } + + then { + assertAll( + { assert function.success } + ) + } + } + + test("Test Function checkCondaChannels") { + + function "checkCondaChannels" + + then { + assertAll( + { assert function.success }, + { assert snapshot(function.result).match() } + ) + } + } +} diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test.snap b/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test.snap new file mode 100644 index 00000000..e3f0baf4 --- /dev/null +++ b/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test.snap @@ -0,0 +1,20 @@ +{ + "Test Function getWorkflowVersion": { + "content": [ + "v9.9.9" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:02:05.308243" + }, + "Test Function checkCondaChannels": { + "content": null, + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:02:12.425833" + } +} \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.workflow.nf.test b/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.workflow.nf.test new file mode 100644 index 00000000..ca964ce8 --- /dev/null +++ b/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.workflow.nf.test @@ -0,0 +1,111 @@ +nextflow_workflow { + + name "Test Workflow UTILS_NEXTFLOW_PIPELINE" + script "../main.nf" + config "subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config" + workflow "UTILS_NEXTFLOW_PIPELINE" + tag 'subworkflows' + tag 'utils_nextflow_pipeline' + tag 'subworkflows/utils_nextflow_pipeline' + + test("Should run no inputs") { + + when { + workflow { + """ + print_version = false + dump_parameters = false + outdir = null + check_conda_channels = false + + input[0] = print_version + input[1] = dump_parameters + input[2] = outdir + input[3] = check_conda_channels + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } + + test("Should print version") { + + when { + workflow { + """ + print_version = true + dump_parameters = false + outdir = null + check_conda_channels = false + + input[0] = print_version + input[1] = dump_parameters + input[2] = outdir + input[3] = check_conda_channels + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert workflow.stdout.contains("nextflow_workflow v9.9.9") } + ) + } + } + + test("Should dump params") { + + when { + workflow { + """ + print_version = false + dump_parameters = true + outdir = 'results' + check_conda_channels = false + + input[0] = false + input[1] = true + input[2] = outdir + input[3] = false + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } + + test("Should not create params JSON if no output directory") { + + when { + workflow { + """ + print_version = false + dump_parameters = true + outdir = null + check_conda_channels = false + + input[0] = false + input[1] = true + input[2] = outdir + input[3] = false + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } +} diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config b/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config new file mode 100644 index 00000000..d0a926bf --- /dev/null +++ b/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config @@ -0,0 +1,9 @@ +manifest { + name = 'nextflow_workflow' + author = """nf-core""" + homePage = 'https://127.0.0.1' + description = """Dummy pipeline""" + nextflowVersion = '!>=23.04.0' + version = '9.9.9' + doi = 'https://doi.org/10.5281/zenodo.5070524' +} diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml b/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml new file mode 100644 index 00000000..f8476112 --- /dev/null +++ b/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml @@ -0,0 +1,2 @@ +subworkflows/utils_nextflow_pipeline: + - subworkflows/nf-core/utils_nextflow_pipeline/** diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf new file mode 100644 index 00000000..a8b55d6f --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -0,0 +1,440 @@ +// +// Subworkflow with utility functions specific to the nf-core pipeline template +// + +import org.yaml.snakeyaml.Yaml +import nextflow.extension.FilesEx + +/* +======================================================================================== + SUBWORKFLOW DEFINITION +======================================================================================== +*/ + +workflow UTILS_NFCORE_PIPELINE { + + take: + nextflow_cli_args + + main: + valid_config = checkConfigProvided() + checkProfileProvided(nextflow_cli_args) + + emit: + valid_config +} + +/* +======================================================================================== + FUNCTIONS +======================================================================================== +*/ + +// +// Warn if a -profile or Nextflow config has not been provided to run the pipeline +// +def checkConfigProvided() { + valid_config = true + if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { + log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + + "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + + " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + + " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + + " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + + "Please refer to the quick start section and usage docs for the pipeline.\n " + valid_config = false + } + return valid_config +} + +// +// Exit pipeline if --profile contains spaces +// +def checkProfileProvided(nextflow_cli_args) { + if (workflow.profile.endsWith(',')) { + error "The `-profile` option cannot end with a trailing comma, please remove it and re-run the pipeline!\n" + + "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" + } + if (nextflow_cli_args[0]) { + log.warn "nf-core pipelines do not accept positional arguments. The positional argument `${nextflow_cli_args[0]}` has been detected.\n" + + "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" + } +} + +// +// Citation string for pipeline +// +def workflowCitation() { + return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + + "* The pipeline\n" + + " ${workflow.manifest.doi}\n\n" + + "* The nf-core framework\n" + + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + + "* Software dependencies\n" + + " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" +} + +// +// Generate workflow version string +// +def getWorkflowVersion() { + String version_string = "" + if (workflow.manifest.version) { + def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' + version_string += "${prefix_v}${workflow.manifest.version}" + } + + if (workflow.commitId) { + def git_shortsha = workflow.commitId.substring(0, 7) + version_string += "-g${git_shortsha}" + } + + return version_string +} + +// +// Get software versions for pipeline +// +def processVersionsFromYAML(yaml_file) { + Yaml yaml = new Yaml() + versions = yaml.load(yaml_file).collectEntries { k, v -> [ k.tokenize(':')[-1], v ] } + return yaml.dumpAsMap(versions).trim() +} + +// +// Get workflow version for pipeline +// +def workflowVersionToYAML() { + return """ + Workflow: + $workflow.manifest.name: ${getWorkflowVersion()} + Nextflow: $workflow.nextflow.version + """.stripIndent().trim() +} + +// +// Get channel of software versions used in pipeline in YAML format +// +def softwareVersionsToYAML(ch_versions) { + return ch_versions + .unique() + .map { processVersionsFromYAML(it) } + .unique() + .mix(Channel.of(workflowVersionToYAML())) +} + +// +// Get workflow summary for MultiQC +// +def paramsSummaryMultiqc(summary_params) { + def summary_section = '' + for (group in summary_params.keySet()) { + def group_params = summary_params.get(group) // This gets the parameters of that particular group + if (group_params) { + summary_section += "

    $group

    \n" + summary_section += "
    \n" + for (param in group_params.keySet()) { + summary_section += "
    $param
    ${group_params.get(param) ?: 'N/A'}
    \n" + } + summary_section += "
    \n" + } + } + + String yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" + yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" + yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" + yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" + yaml_file_text += "plot_type: 'html'\n" + yaml_file_text += "data: |\n" + yaml_file_text += "${summary_section}" + + return yaml_file_text +} + +// +// nf-core logo +// +def nfCoreLogo(monochrome_logs=true) { + Map colors = logColours(monochrome_logs) + String.format( + """\n + ${dashedLine(monochrome_logs)} + ${colors.green},--.${colors.black}/${colors.green},-.${colors.reset} + ${colors.blue} ___ __ __ __ ___ ${colors.green}/,-._.--~\'${colors.reset} + ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} + ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} + ${colors.green}`._,._,\'${colors.reset} + ${colors.purple} ${workflow.manifest.name} ${getWorkflowVersion()}${colors.reset} + ${dashedLine(monochrome_logs)} + """.stripIndent() + ) +} + +// +// Return dashed line +// +def dashedLine(monochrome_logs=true) { + Map colors = logColours(monochrome_logs) + return "-${colors.dim}----------------------------------------------------${colors.reset}-" +} + +// +// ANSII colours used for terminal logging +// +def logColours(monochrome_logs=true) { + Map colorcodes = [:] + + // Reset / Meta + colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" + colorcodes['bold'] = monochrome_logs ? '' : "\033[1m" + colorcodes['dim'] = monochrome_logs ? '' : "\033[2m" + colorcodes['underlined'] = monochrome_logs ? '' : "\033[4m" + colorcodes['blink'] = monochrome_logs ? '' : "\033[5m" + colorcodes['reverse'] = monochrome_logs ? '' : "\033[7m" + colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" + + // Regular Colors + colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" + colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" + colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" + colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" + colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" + colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" + colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" + colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" + + // Bold + colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" + colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" + colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" + colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" + colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" + colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" + colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" + colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" + + // Underline + colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" + colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" + colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" + colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" + colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" + colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" + colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" + colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" + + // High Intensity + colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" + colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" + colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" + colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" + colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" + colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" + colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" + colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" + + // Bold High Intensity + colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" + colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" + colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" + colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" + colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" + colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" + colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" + colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" + + return colorcodes +} + +// +// Attach the multiqc report to email +// +def attachMultiqcReport(multiqc_report) { + def mqc_report = null + try { + if (workflow.success) { + mqc_report = multiqc_report.getVal() + if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { + if (mqc_report.size() > 1) { + log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" + } + mqc_report = mqc_report[0] + } + } + } catch (all) { + if (multiqc_report) { + log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" + } + } + return mqc_report +} + +// +// Construct and send completion email +// +def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdir, monochrome_logs=true, multiqc_report=null) { + + // Set up the e-mail variables + def subject = "[$workflow.manifest.name] Successful: $workflow.runName" + if (!workflow.success) { + subject = "[$workflow.manifest.name] FAILED: $workflow.runName" + } + + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['Date Started'] = workflow.start + misc_fields['Date Completed'] = workflow.complete + misc_fields['Pipeline script file path'] = workflow.scriptFile + misc_fields['Pipeline script hash ID'] = workflow.scriptId + if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository + if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId + if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision + misc_fields['Nextflow Version'] = workflow.nextflow.version + misc_fields['Nextflow Build'] = workflow.nextflow.build + misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp + + def email_fields = [:] + email_fields['version'] = getWorkflowVersion() + email_fields['runName'] = workflow.runName + email_fields['success'] = workflow.success + email_fields['dateComplete'] = workflow.complete + email_fields['duration'] = workflow.duration + email_fields['exitStatus'] = workflow.exitStatus + email_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + email_fields['errorReport'] = (workflow.errorReport ?: 'None') + email_fields['commandLine'] = workflow.commandLine + email_fields['projectDir'] = workflow.projectDir + email_fields['summary'] = summary << misc_fields + + // On success try attach the multiqc report + def mqc_report = attachMultiqcReport(multiqc_report) + + // Check if we are only sending emails on failure + def email_address = email + if (!email && email_on_fail && !workflow.success) { + email_address = email_on_fail + } + + // Render the TXT template + def engine = new groovy.text.GStringTemplateEngine() + def tf = new File("${workflow.projectDir}/assets/email_template.txt") + def txt_template = engine.createTemplate(tf).make(email_fields) + def email_txt = txt_template.toString() + + // Render the HTML template + def hf = new File("${workflow.projectDir}/assets/email_template.html") + def html_template = engine.createTemplate(hf).make(email_fields) + def email_html = html_template.toString() + + // Render the sendmail template + def max_multiqc_email_size = (params.containsKey('max_multiqc_email_size') ? params.max_multiqc_email_size : 0) as nextflow.util.MemoryUnit + def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "${workflow.projectDir}", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] + def sf = new File("${workflow.projectDir}/assets/sendmail_template.txt") + def sendmail_template = engine.createTemplate(sf).make(smail_fields) + def sendmail_html = sendmail_template.toString() + + // Send the HTML e-mail + Map colors = logColours(monochrome_logs) + if (email_address) { + try { + if (plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } + // Try to send HTML e-mail using sendmail + def sendmail_tf = new File(workflow.launchDir.toString(), ".sendmail_tmp.html") + sendmail_tf.withWriter { w -> w << sendmail_html } + [ 'sendmail', '-t' ].execute() << sendmail_html + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" + } catch (all) { + // Catch failures and try with plaintext + def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] + mail_cmd.execute() << email_html + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" + } + } + + // Write summary e-mail HTML to a file + def output_hf = new File(workflow.launchDir.toString(), ".pipeline_report.html") + output_hf.withWriter { w -> w << email_html } + FilesEx.copyTo(output_hf.toPath(), "${outdir}/pipeline_info/pipeline_report.html"); + output_hf.delete() + + // Write summary e-mail TXT to a file + def output_tf = new File(workflow.launchDir.toString(), ".pipeline_report.txt") + output_tf.withWriter { w -> w << email_txt } + FilesEx.copyTo(output_tf.toPath(), "${outdir}/pipeline_info/pipeline_report.txt"); + output_tf.delete() +} + +// +// Print pipeline summary on completion +// +def completionSummary(monochrome_logs=true) { + Map colors = logColours(monochrome_logs) + if (workflow.success) { + if (workflow.stats.ignoredCount == 0) { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" + } else { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" + } + } else { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" + } +} + +// +// Construct and send a notification to a web server as JSON e.g. Microsoft Teams and Slack +// +def imNotification(summary_params, hook_url) { + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['start'] = workflow.start + misc_fields['complete'] = workflow.complete + misc_fields['scriptfile'] = workflow.scriptFile + misc_fields['scriptid'] = workflow.scriptId + if (workflow.repository) misc_fields['repository'] = workflow.repository + if (workflow.commitId) misc_fields['commitid'] = workflow.commitId + if (workflow.revision) misc_fields['revision'] = workflow.revision + misc_fields['nxf_version'] = workflow.nextflow.version + misc_fields['nxf_build'] = workflow.nextflow.build + misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp + + def msg_fields = [:] + msg_fields['version'] = getWorkflowVersion() + msg_fields['runName'] = workflow.runName + msg_fields['success'] = workflow.success + msg_fields['dateComplete'] = workflow.complete + msg_fields['duration'] = workflow.duration + msg_fields['exitStatus'] = workflow.exitStatus + msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + msg_fields['errorReport'] = (workflow.errorReport ?: 'None') + msg_fields['commandLine'] = workflow.commandLine.replaceFirst(/ +--hook_url +[^ ]+/, "") + msg_fields['projectDir'] = workflow.projectDir + msg_fields['summary'] = summary << misc_fields + + // Render the JSON template + def engine = new groovy.text.GStringTemplateEngine() + // Different JSON depending on the service provider + // Defaults to "Adaptive Cards" (https://adaptivecards.io), except Slack which has its own format + def json_path = hook_url.contains("hooks.slack.com") ? "slackreport.json" : "adaptivecard.json" + def hf = new File("${workflow.projectDir}/assets/${json_path}") + def json_template = engine.createTemplate(hf).make(msg_fields) + def json_message = json_template.toString() + + // POST + def post = new URL(hook_url).openConnection(); + post.setRequestMethod("POST") + post.setDoOutput(true) + post.setRequestProperty("Content-Type", "application/json") + post.getOutputStream().write(json_message.getBytes("UTF-8")); + def postRC = post.getResponseCode(); + if (! postRC.equals(200)) { + log.warn(post.getErrorStream().getText()); + } +} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/meta.yml b/subworkflows/nf-core/utils_nfcore_pipeline/meta.yml new file mode 100644 index 00000000..d08d2434 --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/meta.yml @@ -0,0 +1,24 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "UTILS_NFCORE_PIPELINE" +description: Subworkflow with utility functions specific to the nf-core pipeline template +keywords: + - utility + - pipeline + - initialise + - version +components: [] +input: + - nextflow_cli_args: + type: list + description: | + Nextflow CLI positional arguments +output: + - success: + type: boolean + description: | + Dummy output to indicate success +authors: + - "@adamrtalbot" +maintainers: + - "@adamrtalbot" + - "@maxulysse" diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test new file mode 100644 index 00000000..1dc317f8 --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test @@ -0,0 +1,134 @@ + +nextflow_function { + + name "Test Functions" + script "../main.nf" + config "subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config" + tag "subworkflows" + tag "subworkflows_nfcore" + tag "utils_nfcore_pipeline" + tag "subworkflows/utils_nfcore_pipeline" + + test("Test Function checkConfigProvided") { + + function "checkConfigProvided" + + then { + assertAll( + { assert function.success }, + { assert snapshot(function.result).match() } + ) + } + } + + test("Test Function checkProfileProvided") { + + function "checkProfileProvided" + + when { + function { + """ + input[0] = [] + """ + } + } + + then { + assertAll( + { assert function.success }, + { assert snapshot(function.result).match() } + ) + } + } + + test("Test Function workflowCitation") { + + function "workflowCitation" + + then { + assertAll( + { assert function.success }, + { assert snapshot(function.result).match() } + ) + } + } + + test("Test Function nfCoreLogo") { + + function "nfCoreLogo" + + when { + function { + """ + input[0] = false + """ + } + } + + then { + assertAll( + { assert function.success }, + { assert snapshot(function.result).match() } + ) + } + } + + test("Test Function dashedLine") { + + function "dashedLine" + + when { + function { + """ + input[0] = false + """ + } + } + + then { + assertAll( + { assert function.success }, + { assert snapshot(function.result).match() } + ) + } + } + + test("Test Function without logColours") { + + function "logColours" + + when { + function { + """ + input[0] = true + """ + } + } + + then { + assertAll( + { assert function.success }, + { assert snapshot(function.result).match() } + ) + } + } + + test("Test Function with logColours") { + function "logColours" + + when { + function { + """ + input[0] = false + """ + } + } + + then { + assertAll( + { assert function.success }, + { assert snapshot(function.result).match() } + ) + } + } +} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap new file mode 100644 index 00000000..1037232c --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap @@ -0,0 +1,166 @@ +{ + "Test Function checkProfileProvided": { + "content": null, + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:03.360873" + }, + "Test Function checkConfigProvided": { + "content": [ + true + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:02:59.729647" + }, + "Test Function nfCoreLogo": { + "content": [ + "\n\n-\u001b[2m----------------------------------------------------\u001b[0m-\n \u001b[0;32m,--.\u001b[0;30m/\u001b[0;32m,-.\u001b[0m\n\u001b[0;34m ___ __ __ __ ___ \u001b[0;32m/,-._.--~'\u001b[0m\n\u001b[0;34m |\\ | |__ __ / ` / \\ |__) |__ \u001b[0;33m} {\u001b[0m\n\u001b[0;34m | \\| | \\__, \\__/ | \\ |___ \u001b[0;32m\\`-._,-`-,\u001b[0m\n \u001b[0;32m`._,._,'\u001b[0m\n\u001b[0;35m nextflow_workflow v9.9.9\u001b[0m\n-\u001b[2m----------------------------------------------------\u001b[0m-\n" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:10.562934" + }, + "Test Function workflowCitation": { + "content": [ + "If you use nextflow_workflow for your analysis please cite:\n\n* The pipeline\n https://doi.org/10.5281/zenodo.5070524\n\n* The nf-core framework\n https://doi.org/10.1038/s41587-020-0439-x\n\n* Software dependencies\n https://github.com/nextflow_workflow/blob/master/CITATIONS.md" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:07.019761" + }, + "Test Function without logColours": { + "content": [ + { + "reset": "", + "bold": "", + "dim": "", + "underlined": "", + "blink": "", + "reverse": "", + "hidden": "", + "black": "", + "red": "", + "green": "", + "yellow": "", + "blue": "", + "purple": "", + "cyan": "", + "white": "", + "bblack": "", + "bred": "", + "bgreen": "", + "byellow": "", + "bblue": "", + "bpurple": "", + "bcyan": "", + "bwhite": "", + "ublack": "", + "ured": "", + "ugreen": "", + "uyellow": "", + "ublue": "", + "upurple": "", + "ucyan": "", + "uwhite": "", + "iblack": "", + "ired": "", + "igreen": "", + "iyellow": "", + "iblue": "", + "ipurple": "", + "icyan": "", + "iwhite": "", + "biblack": "", + "bired": "", + "bigreen": "", + "biyellow": "", + "biblue": "", + "bipurple": "", + "bicyan": "", + "biwhite": "" + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:17.969323" + }, + "Test Function dashedLine": { + "content": [ + "-\u001b[2m----------------------------------------------------\u001b[0m-" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:14.366181" + }, + "Test Function with logColours": { + "content": [ + { + "reset": "\u001b[0m", + "bold": "\u001b[1m", + "dim": "\u001b[2m", + "underlined": "\u001b[4m", + "blink": "\u001b[5m", + "reverse": "\u001b[7m", + "hidden": "\u001b[8m", + "black": "\u001b[0;30m", + "red": "\u001b[0;31m", + "green": "\u001b[0;32m", + "yellow": "\u001b[0;33m", + "blue": "\u001b[0;34m", + "purple": "\u001b[0;35m", + "cyan": "\u001b[0;36m", + "white": "\u001b[0;37m", + "bblack": "\u001b[1;30m", + "bred": "\u001b[1;31m", + "bgreen": "\u001b[1;32m", + "byellow": "\u001b[1;33m", + "bblue": "\u001b[1;34m", + "bpurple": "\u001b[1;35m", + "bcyan": "\u001b[1;36m", + "bwhite": "\u001b[1;37m", + "ublack": "\u001b[4;30m", + "ured": "\u001b[4;31m", + "ugreen": "\u001b[4;32m", + "uyellow": "\u001b[4;33m", + "ublue": "\u001b[4;34m", + "upurple": "\u001b[4;35m", + "ucyan": "\u001b[4;36m", + "uwhite": "\u001b[4;37m", + "iblack": "\u001b[0;90m", + "ired": "\u001b[0;91m", + "igreen": "\u001b[0;92m", + "iyellow": "\u001b[0;93m", + "iblue": "\u001b[0;94m", + "ipurple": "\u001b[0;95m", + "icyan": "\u001b[0;96m", + "iwhite": "\u001b[0;97m", + "biblack": "\u001b[1;90m", + "bired": "\u001b[1;91m", + "bigreen": "\u001b[1;92m", + "biyellow": "\u001b[1;93m", + "biblue": "\u001b[1;94m", + "bipurple": "\u001b[1;95m", + "bicyan": "\u001b[1;96m", + "biwhite": "\u001b[1;97m" + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:21.714424" + } +} \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test new file mode 100644 index 00000000..8940d32d --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test @@ -0,0 +1,29 @@ +nextflow_workflow { + + name "Test Workflow UTILS_NFCORE_PIPELINE" + script "../main.nf" + config "subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config" + workflow "UTILS_NFCORE_PIPELINE" + tag "subworkflows" + tag "subworkflows_nfcore" + tag "utils_nfcore_pipeline" + tag "subworkflows/utils_nfcore_pipeline" + + test("Should run without failures") { + + when { + workflow { + """ + input[0] = [] + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out).match() } + ) + } + } +} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap new file mode 100644 index 00000000..859d1030 --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap @@ -0,0 +1,19 @@ +{ + "Should run without failures": { + "content": [ + { + "0": [ + true + ], + "valid_config": [ + true + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:25.726491" + } +} \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config b/subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config new file mode 100644 index 00000000..d0a926bf --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config @@ -0,0 +1,9 @@ +manifest { + name = 'nextflow_workflow' + author = """nf-core""" + homePage = 'https://127.0.0.1' + description = """Dummy pipeline""" + nextflowVersion = '!>=23.04.0' + version = '9.9.9' + doi = 'https://doi.org/10.5281/zenodo.5070524' +} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml b/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml new file mode 100644 index 00000000..ac8523c9 --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml @@ -0,0 +1,2 @@ +subworkflows/utils_nfcore_pipeline: + - subworkflows/nf-core/utils_nfcore_pipeline/** diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/main.nf b/subworkflows/nf-core/utils_nfvalidation_plugin/main.nf new file mode 100644 index 00000000..2585b65d --- /dev/null +++ b/subworkflows/nf-core/utils_nfvalidation_plugin/main.nf @@ -0,0 +1,62 @@ +// +// Subworkflow that uses the nf-validation plugin to render help text and parameter summary +// + +/* +======================================================================================== + IMPORT NF-VALIDATION PLUGIN +======================================================================================== +*/ + +include { paramsHelp } from 'plugin/nf-validation' +include { paramsSummaryLog } from 'plugin/nf-validation' +include { validateParameters } from 'plugin/nf-validation' + +/* +======================================================================================== + SUBWORKFLOW DEFINITION +======================================================================================== +*/ + +workflow UTILS_NFVALIDATION_PLUGIN { + + take: + print_help // boolean: print help + workflow_command // string: default commmand used to run pipeline + pre_help_text // string: string to be printed before help text and summary log + post_help_text // string: string to be printed after help text and summary log + validate_params // boolean: validate parameters + schema_filename // path: JSON schema file, null to use default value + + main: + + log.debug "Using schema file: ${schema_filename}" + + // Default values for strings + pre_help_text = pre_help_text ?: '' + post_help_text = post_help_text ?: '' + workflow_command = workflow_command ?: '' + + // + // Print help message if needed + // + if (print_help) { + log.info pre_help_text + paramsHelp(workflow_command, parameters_schema: schema_filename) + post_help_text + System.exit(0) + } + + // + // Print parameter summary to stdout + // + log.info pre_help_text + paramsSummaryLog(workflow, parameters_schema: schema_filename) + post_help_text + + // + // Validate parameters relative to the parameter JSON schema + // + if (validate_params){ + validateParameters(parameters_schema: schema_filename) + } + + emit: + dummy_emit = true +} diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml b/subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml new file mode 100644 index 00000000..3d4a6b04 --- /dev/null +++ b/subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml @@ -0,0 +1,44 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "UTILS_NFVALIDATION_PLUGIN" +description: Use nf-validation to initiate and validate a pipeline +keywords: + - utility + - pipeline + - initialise + - validation +components: [] +input: + - print_help: + type: boolean + description: | + Print help message and exit + - workflow_command: + type: string + description: | + The command to run the workflow e.g. "nextflow run main.nf" + - pre_help_text: + type: string + description: | + Text to print before the help message + - post_help_text: + type: string + description: | + Text to print after the help message + - validate_params: + type: boolean + description: | + Validate the parameters and error if invalid. + - schema_filename: + type: string + description: | + The filename of the schema to validate against. +output: + - dummy_emit: + type: boolean + description: | + Dummy emit to make nf-core subworkflows lint happy +authors: + - "@adamrtalbot" +maintainers: + - "@adamrtalbot" + - "@maxulysse" diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test new file mode 100644 index 00000000..5784a33f --- /dev/null +++ b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test @@ -0,0 +1,200 @@ +nextflow_workflow { + + name "Test Workflow UTILS_NFVALIDATION_PLUGIN" + script "../main.nf" + workflow "UTILS_NFVALIDATION_PLUGIN" + tag "subworkflows" + tag "subworkflows_nfcore" + tag "plugin/nf-validation" + tag "'plugin/nf-validation'" + tag "utils_nfvalidation_plugin" + tag "subworkflows/utils_nfvalidation_plugin" + + test("Should run nothing") { + + when { + + params { + monochrome_logs = true + test_data = '' + } + + workflow { + """ + help = false + workflow_command = null + pre_help_text = null + post_help_text = null + validate_params = false + schema_filename = "$moduleTestDir/nextflow_schema.json" + + input[0] = help + input[1] = workflow_command + input[2] = pre_help_text + input[3] = post_help_text + input[4] = validate_params + input[5] = schema_filename + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } + + test("Should run help") { + + + when { + + params { + monochrome_logs = true + test_data = '' + } + workflow { + """ + help = true + workflow_command = null + pre_help_text = null + post_help_text = null + validate_params = false + schema_filename = "$moduleTestDir/nextflow_schema.json" + + input[0] = help + input[1] = workflow_command + input[2] = pre_help_text + input[3] = post_help_text + input[4] = validate_params + input[5] = schema_filename + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert workflow.exitStatus == 0 }, + { assert workflow.stdout.any { it.contains('Input/output options') } }, + { assert workflow.stdout.any { it.contains('--outdir') } } + ) + } + } + + test("Should run help with command") { + + when { + + params { + monochrome_logs = true + test_data = '' + } + workflow { + """ + help = true + workflow_command = "nextflow run noorg/doesntexist" + pre_help_text = null + post_help_text = null + validate_params = false + schema_filename = "$moduleTestDir/nextflow_schema.json" + + input[0] = help + input[1] = workflow_command + input[2] = pre_help_text + input[3] = post_help_text + input[4] = validate_params + input[5] = schema_filename + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert workflow.exitStatus == 0 }, + { assert workflow.stdout.any { it.contains('nextflow run noorg/doesntexist') } }, + { assert workflow.stdout.any { it.contains('Input/output options') } }, + { assert workflow.stdout.any { it.contains('--outdir') } } + ) + } + } + + test("Should run help with extra text") { + + + when { + + params { + monochrome_logs = true + test_data = '' + } + workflow { + """ + help = true + workflow_command = "nextflow run noorg/doesntexist" + pre_help_text = "pre-help-text" + post_help_text = "post-help-text" + validate_params = false + schema_filename = "$moduleTestDir/nextflow_schema.json" + + input[0] = help + input[1] = workflow_command + input[2] = pre_help_text + input[3] = post_help_text + input[4] = validate_params + input[5] = schema_filename + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert workflow.exitStatus == 0 }, + { assert workflow.stdout.any { it.contains('pre-help-text') } }, + { assert workflow.stdout.any { it.contains('nextflow run noorg/doesntexist') } }, + { assert workflow.stdout.any { it.contains('Input/output options') } }, + { assert workflow.stdout.any { it.contains('--outdir') } }, + { assert workflow.stdout.any { it.contains('post-help-text') } } + ) + } + } + + test("Should validate params") { + + when { + + params { + monochrome_logs = true + test_data = '' + outdir = 1 + } + workflow { + """ + help = false + workflow_command = null + pre_help_text = null + post_help_text = null + validate_params = true + schema_filename = "$moduleTestDir/nextflow_schema.json" + + input[0] = help + input[1] = workflow_command + input[2] = pre_help_text + input[3] = post_help_text + input[4] = validate_params + input[5] = schema_filename + """ + } + } + + then { + assertAll( + { assert workflow.failed }, + { assert workflow.stdout.any { it.contains('ERROR ~ ERROR: Validation of pipeline parameters failed!') } } + ) + } + } +} diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/nextflow_schema.json b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/nextflow_schema.json new file mode 100644 index 00000000..7626c1c9 --- /dev/null +++ b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/nextflow_schema.json @@ -0,0 +1,96 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "https://raw.githubusercontent.com/./master/nextflow_schema.json", + "title": ". pipeline parameters", + "description": "", + "type": "object", + "definitions": { + "input_output_options": { + "title": "Input/output options", + "type": "object", + "fa_icon": "fas fa-terminal", + "description": "Define where the pipeline should find input data and save output data.", + "required": ["outdir"], + "properties": { + "validate_params": { + "type": "boolean", + "description": "Validate parameters?", + "default": true, + "hidden": true + }, + "outdir": { + "type": "string", + "format": "directory-path", + "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", + "fa_icon": "fas fa-folder-open" + }, + "test_data_base": { + "type": "string", + "default": "https://raw.githubusercontent.com/nf-core/test-datasets/modules", + "description": "Base for test data directory", + "hidden": true + }, + "test_data": { + "type": "string", + "description": "Fake test data param", + "hidden": true + } + } + }, + "generic_options": { + "title": "Generic options", + "type": "object", + "fa_icon": "fas fa-file-import", + "description": "Less common options for the pipeline, typically set in a config file.", + "help_text": "These options are common to all nf-core pipelines and allow you to customise some of the core preferences for how the pipeline runs.\n\nTypically these options would be set in a Nextflow config file loaded for all pipeline runs, such as `~/.nextflow/config`.", + "properties": { + "help": { + "type": "boolean", + "description": "Display help text.", + "fa_icon": "fas fa-question-circle", + "hidden": true + }, + "version": { + "type": "boolean", + "description": "Display version and exit.", + "fa_icon": "fas fa-question-circle", + "hidden": true + }, + "logo": { + "type": "boolean", + "default": true, + "description": "Display nf-core logo in console output.", + "fa_icon": "fas fa-image", + "hidden": true + }, + "singularity_pull_docker_container": { + "type": "boolean", + "description": "Pull Singularity container from Docker?", + "hidden": true + }, + "publish_dir_mode": { + "type": "string", + "default": "copy", + "description": "Method used to save pipeline results to output directory.", + "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", + "fa_icon": "fas fa-copy", + "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], + "hidden": true + }, + "monochrome_logs": { + "type": "boolean", + "description": "Use monochrome_logs", + "hidden": true + } + } + } + }, + "allOf": [ + { + "$ref": "#/definitions/input_output_options" + }, + { + "$ref": "#/definitions/generic_options" + } + ] +} diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml new file mode 100644 index 00000000..60b1cfff --- /dev/null +++ b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml @@ -0,0 +1,2 @@ +subworkflows/utils_nfvalidation_plugin: + - subworkflows/nf-core/utils_nfvalidation_plugin/** diff --git a/tower.yml b/tower.yml new file mode 100644 index 00000000..787aedfe --- /dev/null +++ b/tower.yml @@ -0,0 +1,5 @@ +reports: + multiqc_report.html: + display: "MultiQC HTML report" + samplesheet.csv: + display: "Auto-created samplesheet with collated metadata and FASTQ paths" diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index 50bc12ad..adc6c5bd 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -1,56 +1,15 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - VALIDATE INPUTS + IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) - -// Validate input parameters -WorkflowOncoanalyser.initialise(params, log) - -// TODO nf-core: Add all file path parameters for the pipeline to the list below -// Check input path parameters to see if they exist -def checkPathParamList = [ params.input, params.multiqc_config, params.fasta ] -for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } - -// Check mandatory parameters -if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - CONFIG FILES -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) -ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath( params.multiqc_config, checkIfExists: true ) : Channel.empty() -ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath( params.multiqc_logo, checkIfExists: true ) : Channel.empty() -ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - IMPORT LOCAL MODULES/SUBWORKFLOWS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -// -// SUBWORKFLOW: Consisting of a mix of local and nf-core/modules -// -include { INPUT_CHECK } from '../subworkflows/local/input_check' - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - IMPORT NF-CORE MODULES/SUBWORKFLOWS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -// -// 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' +include { FASTQC } from '../modules/nf-core/fastqc/main' +include { MULTIQC } from '../modules/nf-core/multiqc/main' +include { paramsSummaryMap } from 'plugin/nf-validation' +include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' +include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' +include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_oncoanalyser_pipeline' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -58,72 +17,56 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -// Info required for completion email and summary -def multiqc_report = [] - workflow ONCOANALYSER { - ch_versions = Channel.empty() + take: + ch_samplesheet // channel: samplesheet read in from --input - // - // SUBWORKFLOW: Read in samplesheet, validate and stage input files - // - INPUT_CHECK ( - ch_input - ) - ch_versions = ch_versions.mix(INPUT_CHECK.out.versions) + main: + + ch_versions = Channel.empty() + ch_multiqc_files = Channel.empty() // // MODULE: Run FastQC // FASTQC ( - INPUT_CHECK.out.reads + ch_samplesheet ) + ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it[1]}) ch_versions = ch_versions.mix(FASTQC.out.versions.first()) - CUSTOM_DUMPSOFTWAREVERSIONS ( - ch_versions.unique().collectFile(name: 'collated_versions.yml') - ) + // + // Collate and save software versions + // + softwareVersionsToYAML(ch_versions) + .collectFile(storeDir: "${params.outdir}/pipeline_info", name: 'nf_core_pipeline_software_mqc_versions.yml', sort: true, newLine: true) + .set { ch_collated_versions } // // MODULE: MultiQC // - workflow_summary = WorkflowOncoanalyser.paramsSummaryMultiqc(workflow, summary_params) - ch_workflow_summary = Channel.value(workflow_summary) - - methods_description = WorkflowOncoanalyser.methodsDescriptionText(workflow, ch_multiqc_custom_methods_description) - ch_methods_description = Channel.value(methods_description) - - ch_multiqc_files = Channel.empty() - 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([])) + ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) + ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config, checkIfExists: true) : Channel.empty() + ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath(params.multiqc_logo, checkIfExists: true) : Channel.empty() + summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") + ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) + ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) + ch_methods_description = Channel.value(methodsDescriptionText(ch_multiqc_custom_methods_description)) + ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) + ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) + ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml', sort: false)) MULTIQC ( ch_multiqc_files.collect(), - ch_multiqc_config.collect().ifEmpty([]), - ch_multiqc_custom_config.collect().ifEmpty([]), - ch_multiqc_logo.collect().ifEmpty([]) + ch_multiqc_config.toList(), + ch_multiqc_custom_config.toList(), + ch_multiqc_logo.toList() ) - multiqc_report = MULTIQC.out.report.toList() - ch_versions = ch_versions.mix(MULTIQC.out.versions) -} - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - COMPLETION EMAIL AND SUMMARY -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ -workflow.onComplete { - if (params.email || params.email_on_fail) { - NfcoreTemplate.email(workflow, params, summary_params, projectDir, log, multiqc_report) - } - NfcoreTemplate.summary(workflow, params, log) - if (params.hook_url) { - NfcoreTemplate.adaptivecard(workflow, params, summary_params, projectDir, log) - } + emit: + multiqc_report = MULTIQC.out.report.toList() // channel: /path/to/multiqc_report.html + versions = ch_versions // channel: [ path(versions.yml) ] } /* From f47f33ea30d49854b9bef931532d548f215d6722 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Mar 2024 08:23:33 +1100 Subject: [PATCH 363/562] Fix AMBER subworkflow TN mode --- subworkflows/local/amber_profiling.nf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index ab156969..2a21d6b4 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -58,6 +58,10 @@ workflow AMBER_PROFILING { tumor_id: Utils.getTumorDnaSampleName(meta), ] + if (normal_bam) { + meta_amber.normal_id = Utils.getNormalDnaSampleName(meta) + } + [meta_amber, tumor_bam, normal_bam, tumor_bai, normal_bai] } From 08a58c81acde51e45aa62d654144991bcb68ae1d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Mar 2024 08:23:44 +1100 Subject: [PATCH 364/562] Fix COBALT subworkflow TN mode --- subworkflows/local/cobalt_profiling.nf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index c425cd55..15c56355 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -70,6 +70,10 @@ workflow COBALT_PROFILING { tumor_id: Utils.getTumorDnaSampleName(meta), ] + if (normal_bam) { + meta_cobalt.normal_id = Utils.getNormalDnaSampleName(meta) + } + sample_data: [meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai] diploid_bed: diploid_bed } From c53ac44cb5c1a61f2e75f52e06afe465e7b1388f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Mar 2024 08:24:29 +1100 Subject: [PATCH 365/562] Adjust indentation --- modules/local/bwa-mem2/mem/main.nf | 36 +++++++++++------------ modules/local/fastp/main.nf | 18 ++++++------ modules/local/markdups/main.nf | 44 ++++++++++++++-------------- modules/local/sambamba/index/main.nf | 4 +-- 4 files changed, 51 insertions(+), 51 deletions(-) diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index 280bb829..2ae102b6 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -26,24 +26,24 @@ process BWAMEM2_ALIGN { ln -fs \$(find -L ${genome_bwa_index} -type f) ./ bwa-mem2 mem \\ - -Y \\ - -R '${read_group_tag}' \\ - -t ${task.cpus} \\ - ${genome_fasta} \\ - ${reads_fwd} \\ - ${reads_rev} | \\ - \\ - sambamba view \\ - --sam-input \\ - --format bam \\ - --compression-level 0 \\ - --nthreads ${task.cpus} \\ - /dev/stdin | \\ - \\ - sambamba sort \\ - --nthreads ${task.cpus} \\ - --out ${meta.split}.${meta.sample_id}.${meta.read_group}.bam \\ - /dev/stdin + -Y \\ + -R '${read_group_tag}' \\ + -t ${task.cpus} \\ + ${genome_fasta} \\ + ${reads_fwd} \\ + ${reads_rev} | \\ + \\ + sambamba view \\ + --sam-input \\ + --format bam \\ + --compression-level 0 \\ + --nthreads ${task.cpus} \\ + /dev/stdin | \\ + \\ + sambamba sort \\ + --nthreads ${task.cpus} \\ + --out ${meta.split}.${meta.sample_id}.${meta.read_group}.bam \\ + /dev/stdin cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index 9b1121a9..8bd47159 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -23,15 +23,15 @@ process FASTP { # * do not process umis, already done for us fastp \\ - --in1 ${reads_fwd} \\ - --in2 ${reads_rev} \\ - --disable_quality_filtering \\ - --disable_length_filtering \\ - --disable_adapter_trimming \\ - --disable_trim_poly_g \\ - --split_by_lines ${4 * max_fastq_records} \\ - --out1 ${meta.sample_id}_${meta.library_id}_${meta.lane}_R1.fastp.fastq.gz \\ - --out2 ${meta.sample_id}_${meta.library_id}_${meta.lane}_R2.fastp.fastq.gz + --in1 ${reads_fwd} \\ + --in2 ${reads_rev} \\ + --disable_quality_filtering \\ + --disable_length_filtering \\ + --disable_adapter_trimming \\ + --disable_trim_poly_g \\ + --split_by_lines ${4 * max_fastq_records} \\ + --out1 ${meta.sample_id}_${meta.library_id}_${meta.lane}_R1.fastp.fastq.gz \\ + --out2 ${meta.sample_id}_${meta.library_id}_${meta.lane}_R2.fastp.fastq.gz cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 18dbd4eb..e9f17f5d 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -28,25 +28,25 @@ process MARKDUPS { """ markdups \\ - -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - \\ - -samtools \$(which samtools) \\ - -sambamba \$(which sambamba) \\ - \\ - -sample ${meta.sample_id} \\ - -input_bam ${bams.join(',')} \\ - \\ - -form_consensus \\ - ${umi_flags} \\ - \\ - -unmap_regions ${unmap_regions} \\ - -ref_genome ${genome_fasta} \\ - -ref_genome_version ${genome_ver} \\ - \\ - -write_stats \\ - -threads ${task.cpus} \\ - \\ - -output_bam ${meta.sample_id}.markdups.bam + -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + \\ + -samtools \$(which samtools) \\ + -sambamba \$(which sambamba) \\ + \\ + -sample ${meta.sample_id} \\ + -input_bam ${bams.join(',')} \\ + \\ + -form_consensus \\ + ${umi_flags} \\ + \\ + -unmap_regions ${unmap_regions} \\ + -ref_genome ${genome_fasta} \\ + -ref_genome_version ${genome_ver} \\ + \\ + -write_stats \\ + -threads ${task.cpus} \\ + \\ + -output_bam ${meta.sample_id}.markdups.bam cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -63,9 +63,9 @@ process MARKDUPS { touch ${meta.sample_id}.duplicate_freq.tsv if [[ -n "${has_umis}" ]]; then - touch ${meta.sample_id}.umi_coord_freq.tsv - touch ${meta.sample_id}.umi_edit_distance.tsv - touch ${meta.sample_id}.umi_nucleotide_freq.tsv + touch ${meta.sample_id}.umi_coord_freq.tsv + touch ${meta.sample_id}.umi_edit_distance.tsv + touch ${meta.sample_id}.umi_nucleotide_freq.tsv fi; echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf index d3e3a2d2..56bb38af 100644 --- a/modules/local/sambamba/index/main.nf +++ b/modules/local/sambamba/index/main.nf @@ -18,8 +18,8 @@ process SAMBAMBA_INDEX { script: """ sambamba index \\ - --nthreads ${task.cpus} \\ - ${bam} + --nthreads ${task.cpus} \\ + ${bam} cat <<-END_VERSIONS > versions.yml "${task.process}": From df1f5b78bc7c985c08719de8ad08dcfe5d1f4ed6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Mar 2024 08:24:44 +1100 Subject: [PATCH 366/562] Fix SAGE calling subworkflow TN mode --- subworkflows/local/sage_calling.nf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index 92342463..f3f18a15 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -131,6 +131,10 @@ workflow SAGE_CALLING { tumor_id: Utils.getTumorDnaSampleName(meta), ] + if (normal_bam) { + meta_sage.normal_id = Utils.getNormalDnaSampleName(meta) + } + return [meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai] } From 752f57ac5158e0a035175f2a43e2396c123c3659 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Mar 2024 08:25:42 +1100 Subject: [PATCH 367/562] Improving handling of 'no merge' RNA BAM scenarios --- modules/local/sambamba/merge/main.nf | 11 +-------- subworkflows/local/read_alignment_rna.nf | 29 ++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/modules/local/sambamba/merge/main.nf b/modules/local/sambamba/merge/main.nf index f0590530..06993865 100644 --- a/modules/local/sambamba/merge/main.nf +++ b/modules/local/sambamba/merge/main.nf @@ -14,20 +14,11 @@ process SAMBAMBA_MERGE { script: """ - # NOTE(SW): single BAM when read count is less than max split count; merge expects at least two BAMs - if [[ \$(tr -cd ' ' <<< ${bams} | wc -c) -eq 0 ]]; then - - ln -s ${bams} ${meta.sample_id}.bam; - - else - - sambamba merge \\ + sambamba merge \\ --nthreads ${task.cpus} \\ ${meta.sample_id}.bam \\ ${bams} - fi; - cat <<-END_VERSIONS > versions.yml "${task.process}": sambamba: \$(sambamba --version 2>&1 | grep -m1 sambamba | sed 's/^sambamba //') diff --git a/subworkflows/local/read_alignment_rna.nf b/subworkflows/local/read_alignment_rna.nf index 61736170..7767e2a0 100644 --- a/subworkflows/local/read_alignment_rna.nf +++ b/subworkflows/local/read_alignment_rna.nf @@ -146,9 +146,17 @@ workflow READ_ALIGNMENT_RNA { } .groupTuple() + // Sort into merge-eligible BAMs (at least two BAMs required) + ch_bams_united_sorted = ch_bams_united + .branch { meta_group, bams, bais -> + runnable: bams.size() > 1 + skip: + return [meta_group, bams[0], bais[0]] + } + // Create process input channel // channel: [ meta_merge, [bams, ...], [bais, ...] ] - ch_merge_inputs = WorkflowOncoanalyser.restoreMeta(ch_bams_united, ch_inputs) + ch_merge_inputs = WorkflowOncoanalyser.restoreMeta(ch_bams_united_sorted.runnable, ch_inputs) .map { meta, bams, bais -> def meta_merge = [ key: meta.group_id, @@ -168,8 +176,25 @@ workflow READ_ALIGNMENT_RNA { // // MODULE: GATK4 markduplicates // + // Create process input channel + // channel: [ meta_markdups, bam, bai ] + ch_markdups_inputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SAMBAMBA_MERGE.out.bam, ch_inputs), + WorkflowOncoanalyser.restoreMeta(ch_bams_united_sorted.skip, ch_inputs), + ) + .map { meta, bam, bai -> + def meta_markdups = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorRnaSampleName(meta), + ] + return [meta_markdups, bams, bais] + } + + // Run process GATK4_MARKDUPLICATES( - SAMBAMBA_MERGE.out.bam, + ch_markdups_inputs, [], [], ) From c648028e7ca07ce941dedcd41fc86bfcdb4b5c53 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Mar 2024 08:26:30 +1100 Subject: [PATCH 368/562] Set outputs for alignment workflows --- conf/modules.config | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/conf/modules.config b/conf/modules.config index a0cd58f9..f6de9265 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -12,6 +12,22 @@ process { + withName: 'GATK4_MARKDUPLICATES' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/alignments/rna/${filename}" }, + ] + } + + withName: 'MARKDUPS' { + publishDir = [ + path: { "${params.outdir}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : "${meta.key}/alignments/dna/${filename}" }, + ] + } + withName: 'AMBER' { publishDir = [ path: { "${params.outdir}" }, From db6bbf27f2510360b92b78cc3655d582767df5ee Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Mar 2024 08:27:38 +1100 Subject: [PATCH 369/562] Add missing channel docs --- subworkflows/local/read_alignment_rna.nf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subworkflows/local/read_alignment_rna.nf b/subworkflows/local/read_alignment_rna.nf index 7767e2a0..ea9ecc07 100644 --- a/subworkflows/local/read_alignment_rna.nf +++ b/subworkflows/local/read_alignment_rna.nf @@ -119,6 +119,7 @@ workflow READ_ALIGNMENT_RNA { // Reunite BAMs // First, count expected BAMs per sample for non-blocking groupTuple op + // channel: [ meta_count, group_size ] ch_sample_fastq_counts = ch_star_inputs .map { meta_star, reads_fwd, reads_rev -> def meta_count = [key: meta_star.key] @@ -128,6 +129,7 @@ workflow READ_ALIGNMENT_RNA { .map { meta_count, meta_stars -> return [meta_count, meta_stars.size()] } // Now, group with expected size then sort into tumor and normal channels + // channel: [ meta_group, [bam, ...], [bai, ...] ] ch_bams_united = ch_sample_fastq_counts .cross( // First element to match meta_count above for `cross` From c1f314225b0e06bd7e7704f2c44f652d1d1bef46 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Mar 2024 08:43:38 +1100 Subject: [PATCH 370/562] Further work on RNA BAM handling --- subworkflows/local/read_alignment_rna.nf | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/subworkflows/local/read_alignment_rna.nf b/subworkflows/local/read_alignment_rna.nf index ea9ecc07..eefa939d 100644 --- a/subworkflows/local/read_alignment_rna.nf +++ b/subworkflows/local/read_alignment_rna.nf @@ -149,11 +149,13 @@ workflow READ_ALIGNMENT_RNA { .groupTuple() // Sort into merge-eligible BAMs (at least two BAMs required) + // channel: runnable: [ meta_group, [bam, ...], [bai, ...] ] + // channel: skip: [ meta_group, bam ] ch_bams_united_sorted = ch_bams_united .branch { meta_group, bams, bais -> runnable: bams.size() > 1 - skip: - return [meta_group, bams[0], bais[0]] + skip: true + return [meta_group, bams[0]] } // Create process input channel @@ -179,19 +181,19 @@ workflow READ_ALIGNMENT_RNA { // MODULE: GATK4 markduplicates // // Create process input channel - // channel: [ meta_markdups, bam, bai ] + // channel: [ meta_markdups, bam ] ch_markdups_inputs = Channel.empty() .mix( WorkflowOncoanalyser.restoreMeta(SAMBAMBA_MERGE.out.bam, ch_inputs), WorkflowOncoanalyser.restoreMeta(ch_bams_united_sorted.skip, ch_inputs), ) - .map { meta, bam, bai -> + .map { meta, bam -> def meta_markdups = [ key: meta.group_id, id: meta.group_id, sample_id: Utils.getTumorRnaSampleName(meta), ] - return [meta_markdups, bams, bais] + return [meta_markdups, bam] } // Run process From bd45719bc84ce8ec2da1e65165b7ed97ce58a505 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Mar 2024 08:44:32 +1100 Subject: [PATCH 371/562] Use explicit returns in .branch ops --- subworkflows/local/amber_profiling.nf | 2 +- subworkflows/local/bamtools_metrics.nf | 4 ++-- subworkflows/local/cobalt_profiling.nf | 2 +- subworkflows/local/flagstat_metrics.nf | 4 ++-- subworkflows/local/gridss_svprep_calling.nf | 4 ++-- subworkflows/local/isofox_quantification.nf | 2 +- subworkflows/local/lilac_calling.nf | 2 +- subworkflows/local/sage_calling.nf | 6 +++--- subworkflows/local/virusbreakend_calling.nf | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/subworkflows/local/amber_profiling.nf b/subworkflows/local/amber_profiling.nf index 2a21d6b4..1cba9d18 100644 --- a/subworkflows/local/amber_profiling.nf +++ b/subworkflows/local/amber_profiling.nf @@ -44,7 +44,7 @@ workflow AMBER_PROFILING { def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.AMBER_DIR) runnable: tumor_bam && !has_existing skip: true - meta + return meta } // Create process input channel diff --git a/subworkflows/local/bamtools_metrics.nf b/subworkflows/local/bamtools_metrics.nf index ca446828..c1ccbf9a 100644 --- a/subworkflows/local/bamtools_metrics.nf +++ b/subworkflows/local/bamtools_metrics.nf @@ -38,7 +38,7 @@ workflow BAMTOOLS_METRICS { def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAMTOOLS_TUMOR) runnable: bam && !has_existing skip: true - meta + return meta } // channel: runnable: [ meta, bam, bai ] @@ -55,7 +55,7 @@ workflow BAMTOOLS_METRICS { def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAMTOOLS_NORMAL) runnable: bam && !has_existing skip: true - meta + return meta } // Create process input channel diff --git a/subworkflows/local/cobalt_profiling.nf b/subworkflows/local/cobalt_profiling.nf index 15c56355..b121ec6c 100644 --- a/subworkflows/local/cobalt_profiling.nf +++ b/subworkflows/local/cobalt_profiling.nf @@ -46,7 +46,7 @@ workflow COBALT_PROFILING { runnable_tn: tumor_bam && normal_bam && !has_existing runnable_to: tumor_bam && !has_existing skip: true - meta + return meta } // First set diploid BED input for tumor/normal and tumor only samples diff --git a/subworkflows/local/flagstat_metrics.nf b/subworkflows/local/flagstat_metrics.nf index 83be4cd8..cfa8b36c 100644 --- a/subworkflows/local/flagstat_metrics.nf +++ b/subworkflows/local/flagstat_metrics.nf @@ -34,7 +34,7 @@ workflow FLAGSTAT_METRICS { def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.FLAGSTAT_TUMOR) runnable: bam && !has_existing skip: true - meta + return meta } // channel: runnable: [ meta, bam, bai ] @@ -51,7 +51,7 @@ workflow FLAGSTAT_METRICS { def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.FLAGSTAT_NORMAL) runnable: bam && !has_existing skip: true - meta + return meta } // Create process input channel diff --git a/subworkflows/local/gridss_svprep_calling.nf b/subworkflows/local/gridss_svprep_calling.nf index 7bbe3d79..87b50b03 100644 --- a/subworkflows/local/gridss_svprep_calling.nf +++ b/subworkflows/local/gridss_svprep_calling.nf @@ -63,9 +63,9 @@ workflow GRIDSS_SVPREP_CALLING { runnable_tn: tumor_bam && normal_bam && !has_existing runnable_to: tumor_bam && !has_existing - [meta, tumor_bam, tumor_bai] + return [meta, tumor_bam, tumor_bai] skip: true - meta + return meta } // diff --git a/subworkflows/local/isofox_quantification.nf b/subworkflows/local/isofox_quantification.nf index 7e40c379..4859232c 100644 --- a/subworkflows/local/isofox_quantification.nf +++ b/subworkflows/local/isofox_quantification.nf @@ -47,7 +47,7 @@ workflow ISOFOX_QUANTIFICATION { def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.ISOFOX_DIR) runnable: tumor_bam && !has_existing skip: true - meta + return meta } // Create process input channel diff --git a/subworkflows/local/lilac_calling.nf b/subworkflows/local/lilac_calling.nf index be91e6d8..f696e6ed 100644 --- a/subworkflows/local/lilac_calling.nf +++ b/subworkflows/local/lilac_calling.nf @@ -53,7 +53,7 @@ workflow LILAC_CALLING { runnable: (tumor_bam || normal_bam) && !has_existing skip: true - meta + return meta } // Realign reads mapping to HLA regions and homologus regions if using reference genome with ALT contigs diff --git a/subworkflows/local/sage_calling.nf b/subworkflows/local/sage_calling.nf index f3f18a15..ffc5064e 100644 --- a/subworkflows/local/sage_calling.nf +++ b/subworkflows/local/sage_calling.nf @@ -53,7 +53,7 @@ workflow SAGE_CALLING { .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> runnable: tumor_bam skip: true - meta + return meta } // @@ -69,7 +69,7 @@ workflow SAGE_CALLING { runnable: has_tumor_normal && !has_existing skip: true - meta + return meta } // Create process input channel @@ -116,7 +116,7 @@ workflow SAGE_CALLING { runnable: has_tumor && !has_existing skip: true - meta + return meta } // Create process input channel diff --git a/subworkflows/local/virusbreakend_calling.nf b/subworkflows/local/virusbreakend_calling.nf index c13c940b..52cfba4b 100644 --- a/subworkflows/local/virusbreakend_calling.nf +++ b/subworkflows/local/virusbreakend_calling.nf @@ -50,7 +50,7 @@ workflow VIRUSBREAKEND_CALLING { def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.VIRUSINTERPRETER_DIR) runnable: tumor_bam && !has_existing skip: true - meta + return meta } // From 8d0648430ffb51a252aff67b54892b975fcf49dc Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 1 Mar 2024 09:12:07 +1100 Subject: [PATCH 372/562] Do not index RNA BAMs prior to merge --- modules/local/sambamba/merge/main.nf | 2 +- subworkflows/local/read_alignment_rna.nf | 35 ++++++------------------ 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/modules/local/sambamba/merge/main.nf b/modules/local/sambamba/merge/main.nf index 06993865..1bbb9646 100644 --- a/modules/local/sambamba/merge/main.nf +++ b/modules/local/sambamba/merge/main.nf @@ -6,7 +6,7 @@ process SAMBAMBA_MERGE { 'quay.io/biocontainers/sambamba:1.0--h98b6b92_0' }" input: - tuple val(meta), path(bams), path(bais) + tuple val(meta), path(bams) output: tuple val(meta), path('*bam'), emit: bam diff --git a/subworkflows/local/read_alignment_rna.nf b/subworkflows/local/read_alignment_rna.nf index eefa939d..29c84b02 100644 --- a/subworkflows/local/read_alignment_rna.nf +++ b/subworkflows/local/read_alignment_rna.nf @@ -1,5 +1,4 @@ include { GATK4_MARKDUPLICATES } from '../../modules/nf-core/gatk4/markduplicates/main' -include { SAMBAMBA_INDEX } from '../../modules/local/sambamba/index/main' include { SAMBAMBA_MERGE } from '../../modules/local/sambamba/merge/main' include { SAMTOOLS_SORT } from '../../modules/nf-core/samtools/sort/main' include { STAR } from '../../modules/local/star/main' @@ -98,25 +97,9 @@ workflow READ_ALIGNMENT_RNA { ch_versions = ch_versions.mix(SAMTOOLS_SORT.out.versions) - // - // MODULE: Sambamba index - // - SAMBAMBA_INDEX( - SAMTOOLS_SORT.out.bam, - ) - - ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) - // // MODULE: Sambamba merge // - // Combine BAMs and BAIs - // channel: [ meta_star, bam, bai ] - ch_bams_flat = WorkflowOncoanalyser.groupByMeta( - SAMTOOLS_SORT.out.bam, - SAMBAMBA_INDEX.out.bai, - ) - // Reunite BAMs // First, count expected BAMs per sample for non-blocking groupTuple op // channel: [ meta_count, group_size ] @@ -129,45 +112,45 @@ workflow READ_ALIGNMENT_RNA { .map { meta_count, meta_stars -> return [meta_count, meta_stars.size()] } // Now, group with expected size then sort into tumor and normal channels - // channel: [ meta_group, [bam, ...], [bai, ...] ] + // channel: [ meta_group, [bam, ...] ] ch_bams_united = ch_sample_fastq_counts .cross( // First element to match meta_count above for `cross` - ch_bams_flat.map { meta_star, bam, bai -> [[key: meta_star.key], bam, bai] } + SAMTOOLS_SORT.out.bam.map { meta_star, bam -> [[key: meta_star.key], bam] } ) .map { count_tuple, bam_tuple -> def group_size = count_tuple[1] - def (meta_bam, bam, bai) = bam_tuple + def (meta_bam, bam) = bam_tuple def meta_group = [ *:meta_bam, ] - return tuple(groupKey(meta_group, group_size), bam, bai) + return tuple(groupKey(meta_group, group_size), bam) } .groupTuple() // Sort into merge-eligible BAMs (at least two BAMs required) - // channel: runnable: [ meta_group, [bam, ...], [bai, ...] ] + // channel: runnable: [ meta_group, [bam, ...] ] // channel: skip: [ meta_group, bam ] ch_bams_united_sorted = ch_bams_united - .branch { meta_group, bams, bais -> + .branch { meta_group, bams -> runnable: bams.size() > 1 skip: true return [meta_group, bams[0]] } // Create process input channel - // channel: [ meta_merge, [bams, ...], [bais, ...] ] + // channel: [ meta_merge, [bams, ...] ] ch_merge_inputs = WorkflowOncoanalyser.restoreMeta(ch_bams_united_sorted.runnable, ch_inputs) - .map { meta, bams, bais -> + .map { meta, bams -> def meta_merge = [ key: meta.group_id, id: meta.group_id, sample_id: Utils.getTumorRnaSampleName(meta), ] - return [meta_merge, bams, bais] + return [meta_merge, bams] } // Run process From 361afb5ba05d420572cb56e64ee8450db1dfd41e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 3 Mar 2024 10:45:27 +1100 Subject: [PATCH 373/562] Update acknowledgements --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 949e871d..abbed368 100644 --- a/README.md +++ b/README.md @@ -94,12 +94,12 @@ The oncoanalyser pipeline was written by Stephen Watts while in the [Genomics Pl Group](https://mdhs.unimelb.edu.au/centre-for-cancer-research/our-research/genomics-platform-group) at the [University of Melbourne Centre for Cancer Research](https://mdhs.unimelb.edu.au/centre-for-cancer-research). -We thank the following people for their extensive assistance in the development of this pipeline, listed in alphabetical -order: +We thank the following organisations and people for their extensive assistance in the development of this pipeline, +listed in alphabetical order: -* Charles Shale +* [Hartwig Medical Foundation + Australia](https://www.hartwigmedicalfoundation.nl/en/partnerships/hartwig-medical-foundation-australia/) * Oliver Hofmann -* Peter Priestley ## Contributions and Support From 124b79bcad3cb5690dd9bd96a61f855845eef0ae Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 3 Mar 2024 10:45:50 +1100 Subject: [PATCH 374/562] Bump PURPLE to 4.0.2 --- modules/local/purple/environment.yml | 2 +- modules/local/purple/main.nf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/purple/environment.yml b/modules/local/purple/environment.yml index ce725d80..5226454d 100644 --- a/modules/local/purple/environment.yml +++ b/modules/local/purple/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-purple=4.0 + - bioconda::hmftools-purple=4.0.2 diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 57048656..73fcdeba 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -4,8 +4,8 @@ process PURPLE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-purple:4.0--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-purple:4.0--hdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/hmftools-purple:4.0.2--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-purple:4.0.2--hdfd78af_0' }" input: tuple val(meta), path(amber), path(cobalt), path(sv_tumor_vcf), path(sv_tumor_tbi), path(sv_tumor_unfiltered_vcf), path(sv_tumor_unfiltered_tbi), path(sv_normal_vcf), path(sv_normal_tbi), path(smlv_tumor_vcf), path(smlv_normal_vcf) From 31a2d12ae3fdb1d65ca4def1413a36cf9bebf449 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 3 Mar 2024 10:46:28 +1100 Subject: [PATCH 375/562] Correct comment capitalisation --- workflows/wgts.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index e84f224b..5ffa4995 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -278,7 +278,7 @@ workflow WGTS { } // - // SUBWORKFLOW: call SNV, MNV, and small INDELS with SAGE + // SUBWORKFLOW: Call SNV, MNV, and small INDELS with SAGE // // channel: [ meta, sage_vcf, sage_tbi ] ch_sage_germline_vcf_out = Channel.empty() From 22d3fd3d110f73aeb882b9d458eacca360be28d2 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 4 Mar 2024 09:53:06 +1100 Subject: [PATCH 376/562] Handle backslashes in linxreport more consistently --- modules/local/linxreport/main.nf | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/modules/local/linxreport/main.nf b/modules/local/linxreport/main.nf index ef016f65..da526c1d 100644 --- a/modules/local/linxreport/main.nf +++ b/modules/local/linxreport/main.nf @@ -20,19 +20,19 @@ process LINXREPORT { script: def args = task.ext.args ?: '' - def plot_dir = linx_visualiser_dir.resolve('all/').toUriString().replaceAll('/$', '') + def plot_dir = linx_visualiser_dir.resolve('all/').toUriString() """ # Set input plot directory and create it doesn't exist. See the LINX visualiser module for further info. - if [[ ! -e ${plot_dir}/ ]]; then - mkdir -p ${plot_dir}/; + if [[ ! -e ${plot_dir} ]]; then + mkdir -p ${plot_dir}; fi; linxreport.R \\ ${args} \\ --sample ${meta.sample_id} \\ - --plot ${plot_dir}/ \\ - --table ${linx_annotation_dir}/ \\ + --plot ${plot_dir} \\ + --table ${linx_annotation_dir} \\ --out ${meta.sample_id}_linx.html cat <<-END_VERSIONS > versions.yml @@ -43,8 +43,6 @@ process LINXREPORT { """ stub: - def plot_dir = linx_visualiser_dir.resolve('all/').toUriString().replaceAll('/$', '') - """ touch ${meta.sample_id}_linx.html echo -e '${task.process}:\n stub: noversions\n' > versions.yml From 8ced85bcf80bd1f91bdeb99c8d7df1a0b512a289 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 4 Mar 2024 09:57:41 +1100 Subject: [PATCH 377/562] Correct typo in PAVE somatic module --- modules/local/pave/somatic/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 8ebcbb89..7ad70200 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -46,7 +46,7 @@ process PAVE_SOMATIC { System.exit(1) } - // Targetted mode + // Targeted mode def pon_artefact_arg = pon_artefacts ? "-pon_artefact_file ${pon_artefacts}" : '' def pathogenic_pass_force_arg = pon_artefacts ? '-force_pathogenic_pass': '' def sage_blocklist_regions_arg = sage_blocklist_regions ? "-blacklist_bed ${sage_blocklist_regions}" : '' From 0881ae993690ff97a516bc6d1859ba2f6c30cc98 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 4 Mar 2024 11:40:53 +1100 Subject: [PATCH 378/562] =?UTF-8?q?Bump=20version:=200.3.0=20=E2=86=92=200?= =?UTF-8?q?.3.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- README.md | 2 +- nextflow.config | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 69867631..ed583aa7 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.3.0 +current_version = 0.3.1 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/README.md b/README.md index abbed368..728f3528 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Launch oncoanalyser: ```bash nextflow run nf-core/oncoanalyser \ - -revision v0.3.0 \ + -revision v0.3.1 \ -profile docker \ --mode wgts \ --genome GRCh38_hmf \ diff --git a/nextflow.config b/nextflow.config index cf37c819..908ebb92 100644 --- a/nextflow.config +++ b/nextflow.config @@ -212,7 +212,7 @@ manifest { // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release nextflowVersion = '!>=22.10.5' - version = '0.3.0' + version = '0.3.1' doi = '' } From c7e87c2dda8a0154b8e6738d685532d5a5723142 Mon Sep 17 00:00:00 2001 From: Matthew Cooper Date: Tue, 5 Mar 2024 20:33:06 +1100 Subject: [PATCH 379/562] Remove obsolete TODOs --- workflows/wgts.nf | 3 --- 1 file changed, 3 deletions(-) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 8405a5fa..7bf745d2 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -111,9 +111,6 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoft // Get absolute file paths samplesheet = Utils.getFileObject(params.input) -// TODO(MC): Drop commit 'WIP: Reverting bioconda containers'. -// TODO(MC): Run full tests for going from .fastq.gz. -// TODO(MC): Fix warnings. workflow WGTS { // Create channel for versions // channel: [ versions.yml ] From 1653daf620601893d9d837a245f79fb1afe77b19 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 8 Mar 2024 10:14:36 +1100 Subject: [PATCH 380/562] Fix Isofox singularity container URL --- modules/local/isofox/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 903e5e45..cd215d70 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -4,7 +4,7 @@ process ISOFOX { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-isofox:1.7.1-hdfd78af_0': + 'https://depot.galaxyproject.org/singularity/hmftools-isofox:1.7.1--hdfd78af_0': 'quay.io/biocontainers/hmftools-isofox:1.7.1--hdfd78af_0' }" input: From f618283ff199707b8053f2818434ce7f9daf7659 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 8 Mar 2024 10:15:01 +1100 Subject: [PATCH 381/562] Bump TSO500 data bundle version * restrict target regions to canonical Ensembl transcripts --- lib/Constants.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index c7618ac3..37c7ac75 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -15,8 +15,8 @@ class Constants { static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_38--2.tar.gz' - static String TSO500_PANEL_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_37--0.tar.gz' - static String TSO500_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_38--0.tar.gz' + static String TSO500_PANEL_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_37--1.tar.gz' + static String TSO500_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_38--1.tar.gz' static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' From 2bd379cbc57767539c1db292aecfaccf9400a73a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 8 Mar 2024 10:16:02 +1100 Subject: [PATCH 382/562] Remove -force_pathogenic_pass in PAVE somatic --- modules/local/pave/somatic/main.nf | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 7ad70200..dfecf48c 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -48,7 +48,6 @@ process PAVE_SOMATIC { // Targeted mode def pon_artefact_arg = pon_artefacts ? "-pon_artefact_file ${pon_artefacts}" : '' - def pathogenic_pass_force_arg = pon_artefacts ? '-force_pathogenic_pass': '' def sage_blocklist_regions_arg = sage_blocklist_regions ? "-blacklist_bed ${sage_blocklist_regions}" : '' def sage_blocklist_sites_arg = sage_blocklist_sites ? "-blacklist_vcf ${sage_blocklist_sites}" : '' def clinvar_annotations = clinvar_annotations ? "-clinvar_vcf ${clinvar_annotations}" : '' @@ -69,7 +68,6 @@ process PAVE_SOMATIC { -ensembl_data_dir ${ensembl_data_resources} \\ ${sage_blocklist_regions_arg} \\ ${sage_blocklist_sites_arg} \\ - ${pathogenic_pass_force_arg} \\ ${gnomad_args} \\ -read_pass_only \\ -threads ${task.cpus} \\ From 31967206c08e66f044d06be6848157785dc2a792 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 10:38:57 +1100 Subject: [PATCH 383/562] Apply prettier linting --- README.md | 24 ++++++++++++------------ modules/local/pave/germline/meta.yml | 2 +- modules/local/pave/somatic/meta.yml | 2 +- modules/local/sage/append/meta.yml | 2 +- modules/local/sage/germline/meta.yml | 2 +- modules/local/sage/somatic/meta.yml | 2 +- nextflow_schema.json | 14 ++------------ 7 files changed, 19 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 240f0e33..03d7b258 100644 --- a/README.md +++ b/README.md @@ -41,16 +41,16 @@ website](https://nf-co.re/oncoanalyser/results). The following processes and tools can be run with oncoanalyser: -* SNV and MNV calling (`SAGE`, `PAVE`) -* SV calling (`SV Prep`, `GRIDSS`, `GRIPSS`, `PURPLE`, `LINX`) -* CNV calling (`AMBER`, `COBALT`, `PURPLE`) -* Transcript analysis (`Isofox`) -* Oncoviral detection (`VIRUSBreakend`, `Virus Interpreter`) -* HLA calling (`LILAC`) -* HRD status prediction (`CHORD`) -* Mutational signature fitting (`Sigs`) -* Tissue of origin prediction (`CUPPA`) -* Report generation (`ORANGE`, `linxreport`) +- SNV and MNV calling (`SAGE`, `PAVE`) +- SV calling (`SV Prep`, `GRIDSS`, `GRIPSS`, `PURPLE`, `LINX`) +- CNV calling (`AMBER`, `COBALT`, `PURPLE`) +- Transcript analysis (`Isofox`) +- Oncoviral detection (`VIRUSBreakend`, `Virus Interpreter`) +- HLA calling (`LILAC`) +- HRD status prediction (`CHORD`) +- Mutational signature fitting (`Sigs`) +- Tissue of origin prediction (`CUPPA`) +- Report generation (`ORANGE`, `linxreport`) ## Usage @@ -109,9 +109,9 @@ of Melbourne Centre for Cancer Research](https://mdhs.unimelb.edu.au/centre-for- We thank the following organisations and people for their extensive assistance in the development of this pipeline, listed in alphabetical order: -* [Hartwig Medical Foundation +- [Hartwig Medical Foundation Australia](https://www.hartwigmedicalfoundation.nl/en/partnerships/hartwig-medical-foundation-australia/) -* Oliver Hofmann +- Oliver Hofmann ## Contributions and Support diff --git a/modules/local/pave/germline/meta.yml b/modules/local/pave/germline/meta.yml index 45875836..859e7fce 100644 --- a/modules/local/pave/germline/meta.yml +++ b/modules/local/pave/germline/meta.yml @@ -11,7 +11,7 @@ tools: description: Annotates small variant VCF with gene, transcript coding and protein effects. homepage: https://github.com/hartwigmedical/hmftools/tree/master/pave documentation: https://github.com/hartwigmedical/hmftools/tree/master/pave - licence: ['GPL v3'] + licence: ["GPL v3"] input: - meta: type: map diff --git a/modules/local/pave/somatic/meta.yml b/modules/local/pave/somatic/meta.yml index 97aa6729..552537c4 100644 --- a/modules/local/pave/somatic/meta.yml +++ b/modules/local/pave/somatic/meta.yml @@ -12,7 +12,7 @@ tools: description: Annotates small variant VCF with gene, transcript coding and protein effects. homepage: https://github.com/hartwigmedical/hmftools/tree/master/pave documentation: https://github.com/hartwigmedical/hmftools/tree/master/pave - licence: ['GPL v3'] + licence: ["GPL v3"] input: - meta: type: map diff --git a/modules/local/sage/append/meta.yml b/modules/local/sage/append/meta.yml index 15ef5850..970d2539 100644 --- a/modules/local/sage/append/meta.yml +++ b/modules/local/sage/append/meta.yml @@ -9,7 +9,7 @@ tools: description: A precise and highly sensitive somatic SNV, MNV and small INDEL caller. homepage: https://github.com/hartwigmedical/hmftools/tree/master/sage documentation: https://github.com/hartwigmedical/hmftools/tree/master/sage - licence: ['GPL v3'] + licence: ["GPL v3"] input: - meta: type: map diff --git a/modules/local/sage/germline/meta.yml b/modules/local/sage/germline/meta.yml index 12a0f1b0..a1054388 100644 --- a/modules/local/sage/germline/meta.yml +++ b/modules/local/sage/germline/meta.yml @@ -10,7 +10,7 @@ tools: description: A precise and highly sensitive somatic SNV, MNV and small INDEL caller. homepage: https://github.com/hartwigmedical/hmftools/tree/master/sage documentation: https://github.com/hartwigmedical/hmftools/tree/master/sage - licence: ['GPL v3'] + licence: ["GPL v3"] input: - meta: type: map diff --git a/modules/local/sage/somatic/meta.yml b/modules/local/sage/somatic/meta.yml index 88ff985b..9ce66ceb 100644 --- a/modules/local/sage/somatic/meta.yml +++ b/modules/local/sage/somatic/meta.yml @@ -10,7 +10,7 @@ tools: description: A precise and highly sensitive somatic SNV, MNV and small INDEL caller. homepage: https://github.com/hartwigmedical/hmftools/tree/master/sage documentation: https://github.com/hartwigmedical/hmftools/tree/master/sage - licence: ['GPL v3'] + licence: ["GPL v3"] input: - meta: type: map diff --git a/nextflow_schema.json b/nextflow_schema.json index 73f8aa56..098da2a5 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,10 +10,7 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": [ - "input", - "outdir" - ], + "required": ["input", "outdir"], "properties": { "input": { "type": "string", @@ -332,14 +329,7 @@ "description": "Method used to save pipeline results to output directory.", "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", "fa_icon": "fas fa-copy", - "enum": [ - "symlink", - "rellink", - "link", - "copy", - "copyNoFollow", - "move" - ], + "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], "hidden": true }, "email_on_fail": { From 37a402285002f5aa33807b88260080c355b2580e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 10:42:46 +1100 Subject: [PATCH 384/562] Fix indenting --- conf/modules.config | 2 +- lib/Utils.groovy | 4 +- lib/WorkflowMain.groovy | 6 +-- modules/local/chord/main.nf | 4 +- modules/local/orange/main.nf | 80 ++++++++++++++++++------------------ 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 94a27b76..320b0a7d 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -218,7 +218,7 @@ process { def tokens = filename.split('[/]') return "${meta.key}/orange/${tokens[-1]}" } - } + } ] } diff --git a/lib/Utils.groovy b/lib/Utils.groovy index e2da9ade..c4053a96 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -359,9 +359,9 @@ class Utils { public static selectCurrentOrExisting(val, meta, key) { if (hasExistingInput(meta, key)) { - return getInput(meta, key) + return getInput(meta, key) } else { - return val + return val } } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 499a7074..cdaa3997 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -161,9 +161,9 @@ class WorkflowMain { // NOTE(SW): this could be moved to the wgts.nf where we check that input files exist def null_check = [ - 'ref_data_genome_fasta', - 'ref_data_genome_type', - 'ref_data_genome_version', + 'ref_data_genome_fasta', + 'ref_data_genome_type', + 'ref_data_genome_version', ] null_check.each { k -> if (!params[k]) { diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf index f2906676..2fabc9a4 100644 --- a/modules/local/chord/main.nf +++ b/modules/local/chord/main.nf @@ -58,8 +58,8 @@ process CHORD { cat('[INFO] Performing chord HRD prediction\\n') prediction <- chordPredict( - signatures, - hrd.cutoff=0.5 + signatures, + hrd.cutoff=0.5 ) cat('[INFO] Writing output file:', sigOutTxt,'\\n') diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index d36b1651..ed66236f 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -67,7 +67,7 @@ process ORANGE { purple_dir_local=purple__prepared; if [[ -d \${purple_dir_local}/ ]]; then - rm -r \${purple_dir_local}/; + rm -r \${purple_dir_local}/; fi cp -rL ${purple_dir} \${purple_dir_local}/ @@ -105,45 +105,45 @@ process ORANGE { --add-opens java.base/java.time=ALL-UNNAMED \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar \${orange_jar} \\ - \\ - -experiment_date \$(date +%y%m%d) \\ - -add_disclaimer \\ - -pipeline_version_file pipeline_version.txt \\ - \\ - -tumor_sample_id ${meta.tumor_id} \\ - -primary_tumor_doids 162 \\ - -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ - -tumor_sample_flagstat_file ${flagstat_somatic} \\ - -sage_dir ${sage_somatic_dir} \\ - -purple_dir \${purple_dir_local} \\ - -purple_plot_dir \${purple_dir_local}/plot/ \\ - -linx_dir ${linx_somatic_anno_dir} \\ - -linx_plot_dir ${plot_dir}/ \\ - -lilac_dir ${lilac_dir} \\ - ${virus_dir_arg} \\ - ${chord_dir_arg} \\ - ${sigs_dir_arg} \\ - ${cuppa_dir_arg} \\ - \\ - ${normal_id_arg} \\ - ${normal_metrics_arg} \\ - ${normal_flagstat_arg} \\ - ${normal_sage_dir} \\ - ${normal_linx_arg} \\ - \\ - ${rna_id_arg} \\ - ${isofox_dir_arg} \\ - \\ - -ref_genome_version ${genome_ver} \\ - -doid_json ${disease_ontology} \\ - -cohort_mapping_tsv ${cohort_mapping} \\ - -cohort_percentiles_tsv ${cohort_percentiles} \\ - -known_fusion_file ${known_fusion_data} \\ - -driver_gene_panel ${driver_gene_panel} \\ - -ensembl_data_dir ${ensembl_data_resources} \\ - ${isofox_gene_distribution_arg} \\ - ${isofox_alt_sj_arg} \\ - -output_dir output/ + \\ + -experiment_date \$(date +%y%m%d) \\ + -add_disclaimer \\ + -pipeline_version_file pipeline_version.txt \\ + \\ + -tumor_sample_id ${meta.tumor_id} \\ + -primary_tumor_doids 162 \\ + -tumor_sample_wgs_metrics_file ${bam_metrics_somatic} \\ + -tumor_sample_flagstat_file ${flagstat_somatic} \\ + -sage_dir ${sage_somatic_dir} \\ + -purple_dir \${purple_dir_local} \\ + -purple_plot_dir \${purple_dir_local}/plot/ \\ + -linx_dir ${linx_somatic_anno_dir} \\ + -linx_plot_dir ${plot_dir}/ \\ + -lilac_dir ${lilac_dir} \\ + ${virus_dir_arg} \\ + ${chord_dir_arg} \\ + ${sigs_dir_arg} \\ + ${cuppa_dir_arg} \\ + \\ + ${normal_id_arg} \\ + ${normal_metrics_arg} \\ + ${normal_flagstat_arg} \\ + ${normal_sage_dir} \\ + ${normal_linx_arg} \\ + \\ + ${rna_id_arg} \\ + ${isofox_dir_arg} \\ + \\ + -ref_genome_version ${genome_ver} \\ + -doid_json ${disease_ontology} \\ + -cohort_mapping_tsv ${cohort_mapping} \\ + -cohort_percentiles_tsv ${cohort_percentiles} \\ + -known_fusion_file ${known_fusion_data} \\ + -driver_gene_panel ${driver_gene_panel} \\ + -ensembl_data_dir ${ensembl_data_resources} \\ + ${isofox_gene_distribution_arg} \\ + ${isofox_alt_sj_arg} \\ + -output_dir output/ cat <<-END_VERSIONS > versions.yml "${task.process}": From 4085b4f6ad70578ac5ed07197c8f6907acf1059f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 10:49:44 +1100 Subject: [PATCH 385/562] Fix more linting failures --- conf/test.config | 2 +- lib/Utils.groovy | 22 ++++---- lib/WorkflowMain.groovy | 52 +++++++++--------- main.nf | 12 ++--- nextflow.config | 55 ++++++++++++-------- nextflow_schema.json | 44 +++++++++------- subworkflows/local/lilac_calling/main.nf | 2 +- subworkflows/local/prepare_reference/main.nf | 50 +++++++++--------- tests/main.stub.nf.test | 10 ++-- workflows/targeted.nf | 13 ++--- workflows/wgts.nf | 15 ++---- 11 files changed, 140 insertions(+), 137 deletions(-) diff --git a/conf/test.config b/conf/test.config index 4d267c6d..6ecc8052 100644 --- a/conf/test.config +++ b/conf/test.config @@ -29,5 +29,5 @@ params { mode = 'wgts' genome = 'GRCh38_hmf' - ref_data_virusbreakenddb_path = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/reference_data/virusbreakend/virusbreakenddb_test.tar.gz' + virusbreakenddb_path = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/reference_data/virusbreakend/virusbreakenddb_test.tar.gz' } diff --git a/lib/Utils.groovy b/lib/Utils.groovy index c4053a96..7fe1f35b 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -131,24 +131,24 @@ class Utils { public static void createStubPlaceholders(params) { def fps = [ - params.ref_data_genome_fasta, - params.ref_data_genome_fai, - params.ref_data_genome_dict, - params.ref_data_genome_bwa_index, - params.ref_data_genome_bwa_index_image, - params.ref_data_genome_gridss_index, - params.ref_data_virusbreakenddb_path, + params.genome_fasta, + params.genome_fai, + params.genome_dict, + params.genome_bwa_index, + params.genome_bwa_index_image, + params.genome_gridss_index, + params.virusbreakenddb_path, ] - params.hmf_data_paths[params.ref_data_genome_version] + params.hmf_data_paths[params.genome_version] .each { k, v -> - fps << "${params.ref_data_hmf_data_path.replaceAll('/$', '')}/${v}" + fps << "${params.hmf_data_path.replaceAll('/$', '')}/${v}" } if(params.containsKey('panel')) { - params.panel_data_paths[params.panel][params.ref_data_genome_version] + params.panel_data_paths[params.panel][params.genome_version] .each { k, v -> - fps << "${params.ref_data_panel_data_path.replaceAll('/$', '')}/${v}" + fps << "${params.panel_data_path.replaceAll('/$', '')}/${v}" } } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index cdaa3997..a2304f5a 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -14,30 +14,30 @@ class WorkflowMain { def default_invalid = false if (params.containsKey('genome_version')) { - params.ref_data_genome_version = params.genome_version.toString() + params.genome_version = params.genome_version.toString() } else if (Constants.GENOMES_VERSION_37.contains(params.genome)) { - params.ref_data_genome_version = '37' + params.genome_version = '37' } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { - params.ref_data_genome_version = '38' + params.genome_version = '38' } else { default_invalid = true } if (params.containsKey('genome_type')) { - params.ref_data_genome_type = params.genome_type + params.genome_type = params.genome_type } else if (Constants.GENOMES_ALT.contains(params.genome)) { - params.ref_data_genome_type = 'alt' + params.genome_type = 'alt' } else if (Constants.GENOMES_DEFINED.contains(params.genome)) { - params.ref_data_genome_type = 'no_alt' + params.genome_type = 'no_alt' } else { default_invalid = true } - if (!params.containsKey('ref_data_hmf_data_path')) { - if (params.ref_data_genome_version == '37') { - params.ref_data_hmf_data_path = Constants.HMF_DATA_37_PATH - } else if (params.ref_data_genome_version == '38') { - params.ref_data_hmf_data_path = Constants.HMF_DATA_38_PATH + if (!params.containsKey('hmf_data_path')) { + if (params.genome_version == '37') { + params.hmf_data_path = Constants.HMF_DATA_37_PATH + } else if (params.genome_version == '38') { + params.hmf_data_path = Constants.HMF_DATA_38_PATH } } @@ -59,11 +59,11 @@ class WorkflowMain { if (run_mode === Constants.RunMode.TARGETED) { // Attempt to set default panel data path; make no assumption on valid 'panel' value - if (!params.containsKey('ref_data_panel_data_path') && params.containsKey('panel')) { - if (params.panel == 'tso500' && params.ref_data_genome_version == '37') { - params.ref_data_panel_data_path = Constants.TSO500_PANEL_37_PATH - } else if (params.panel == 'tso500' && params.ref_data_genome_version == '38') { - params.ref_data_panel_data_path = Constants.TSO500_PANEL_38_PATH + if (!params.containsKey('panel_data_path') && params.containsKey('panel')) { + if (params.panel == 'tso500' && params.genome_version == '37') { + params.panel_data_path = Constants.TSO500_PANEL_37_PATH + } else if (params.panel == 'tso500' && params.genome_version == '38') { + params.panel_data_path = Constants.TSO500_PANEL_38_PATH } } @@ -77,14 +77,14 @@ class WorkflowMain { ) if (stages.virusinterpreter && run_mode === Constants.RunMode.WGTS) { - if (!params.containsKey('ref_data_virusbreakenddb_path')) { - params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH + if (!params.containsKey('virusbreakenddb_path')) { + params.virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH } } if (stages.lilac) { - if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && !params.containsKey('ref_data_hla_slice_bed')) { - params.ref_data_hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH + if (params.genome_version == '38' && params.genome_type == 'alt' && !params.containsKey('hla_slice_bed')) { + params.hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH } } @@ -134,7 +134,7 @@ class WorkflowMain { } } - if (!params.ref_data_genome_version) { + if (!params.genome_version) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome version wasn't provided and genome '${params.genome}' is not defined in \n" + " genome version list.\n" + @@ -144,7 +144,7 @@ class WorkflowMain { System.exit(1) } - if (!params.ref_data_genome_type) { + if (!params.genome_type) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome type wasn't provided and genome '${params.genome}' is not defined in \n" + " genome type list.\n" + @@ -154,16 +154,16 @@ class WorkflowMain { System.exit(1) } - if (!params.ref_data_hmf_data_path) { + if (!params.hmf_data_path) { log.error "ERROR: HMF data path wasn't provided" System.exit(1) } // NOTE(SW): this could be moved to the wgts.nf where we check that input files exist def null_check = [ - 'ref_data_genome_fasta', - 'ref_data_genome_type', - 'ref_data_genome_version', + 'genome_fasta', + 'genome_type', + 'genome_version', ] null_check.each { k -> if (!params[k]) { diff --git a/main.nf b/main.nf index ca31499c..4da82d39 100644 --- a/main.nf +++ b/main.nf @@ -31,12 +31,12 @@ include { getGenomeAttribute } from './subworkflows/local/utils_nfcore_oncoanaly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -params.ref_data_genome_fasta = getGenomeAttribute('fasta') -params.ref_data_genome_fai = getGenomeAttribute('fai') -params.ref_data_genome_dict = getGenomeAttribute('dict') -params.ref_data_genome_bwa_index = getGenomeAttribute('bwa_index') -params.ref_data_genome_bwa_index_image = getGenomeAttribute('bwa_index_image') -params.ref_data_genome_gridss_index = getGenomeAttribute('gridss_index') +params.genome_fasta = getGenomeAttribute('fasta') +params.genome_fai = getGenomeAttribute('fai') +params.genome_dict = getGenomeAttribute('dict') +params.genome_bwa_index = getGenomeAttribute('bwa_index') +params.genome_bwa_index_image = getGenomeAttribute('bwa_index_image') +params.genome_gridss_index = getGenomeAttribute('gridss_index') WorkflowMain.setParamsDefaults(params, log) diff --git a/nextflow.config b/nextflow.config index 25084b0f..a2a05b51 100644 --- a/nextflow.config +++ b/nextflow.config @@ -14,38 +14,51 @@ params { // Workflow mode mode = null - - // Isofox user input files - isofox_counts = null - isofox_gc_ratios = null - isofox_gene_ids = null - isofox_tpm_norm = null + panel = null // Process configuration processes_manual = false processes_include = null processes_exclude = null - // Reference genome information; iGenomes is effectively disabled + // Reference genome information; iGenomes is effectively disabled but retained for linting genome = null + genome_version = null + genome_type = null + force_genome = null + igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false + // Other reference data and config exposed to user on CLI + hmf_data_path = null + panel_data_path = null + virusbreakenddb_path = null + hla_slice_bed = null + + isofox_counts = null + isofox_gc_ratios = null + isofox_gene_ids = null + isofox_tpm_norm = null + isofox_read_length = null + + gridss_config = null + // Boilerplate options - outdir = null - publish_dir_mode = 'copy' - email = null - email_on_fail = null - plaintext_email = false - monochrome_logs = false - hook_url = null - help = false - version = false + outdir = null + publish_dir_mode = 'copy' + email = null + email_on_fail = null + plaintext_email = false + monochrome_logs = false + hook_url = null + help = false + version = false // Other workflow inputs and options - create_stub_placeholders = false - linx_gene_id_file = null - isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' + create_stub_placeholders = false + linx_gene_id_file = null + isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' // Config options config_profile_name = null @@ -63,8 +76,8 @@ params { // Schema validation default options validationFailUnrecognisedParams = false - validationLenientMode = false - validationSchemaIgnoreParams = 'genomes,igenomes_base' + validationLenientMode = true + validationSchemaIgnoreParams = 'genomes,igenomes_base,hmf_data_paths,panel_data_paths' validationShowHiddenParams = false validate_params = true diff --git a/nextflow_schema.json b/nextflow_schema.json index 098da2a5..5bea4bad 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -133,16 +133,6 @@ "description": "Name of genome reference.", "fa_icon": "fas fa-book" }, - "genome_version": { - "description": "Reference genome version.", - "fa_icon": "fas fa-book", - "hidden": true - }, - "genome_type": { - "description": "Reference genome type.", - "fa_icon": "fas fa-book", - "hidden": true - }, "igenomes_ignore": { "type": "boolean", "description": "Do not load the iGenomes reference config.", @@ -150,29 +140,29 @@ "hidden": true, "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe c lashes between custom parameters and those supplied in `igenomes.config`." }, - "ref_data_hmf_data_path": { + "hmf_data_path": { "type": "string", "description": "Path to HMF data.", "fa_icon": "far fa-folder-open" }, - "ref_data_panel_data_path": { + "panel_data_path": { "type": "string", "description": "Path to panel data.", "fa_icon": "far fa-folder-open" }, - "ref_data_virusbreakenddb_path": { + "virusbreakenddb_path": { "type": "string", "format": "directory-path", "description": "Path to VIRUSBreakend database.", "fa_icon": "far fa-file-code" }, - "ref_data_hla_slice_bed": { + "hla_slice_bed": { "format": "file-path", "pattern": "^\\S+\\.bed$", "description": "Path to HLA slice BED file.", "fa_icon": "far fa-file-code" }, - "ref_data_genome_fasta": { + "genome_fasta": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", @@ -180,7 +170,21 @@ "fa_icon": "far fa-file-code", "hidden": true }, - "ref_data_genome_fai": { + "genome_version": { + "type": "string", + "description": "Version of reference genome.", + "fa_icon": "far fa-file-code", + "enum": ["37", "38"], + "hidden": true + }, + "genome_type": { + "type": "string", + "description": "Type of reference genome.", + "fa_icon": "far fa-file-code", + "enum": ["alt", "no_alt"], + "hidden": true + }, + "genome_fai": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.fai$", @@ -188,7 +192,7 @@ "fa_icon": "far fa-file-code", "hidden": true }, - "ref_data_genome_dict": { + "genome_dict": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.dict$", @@ -196,14 +200,14 @@ "fa_icon": "far fa-file-code", "hidden": true }, - "ref_data_genome_bwa_index": { + "genome_bwa_index": { "type": "string", "format": "directory-path", "description": "Path to directory containing reference genome BWA indices.", "fa_icon": "far fa-file-code", "hidden": true }, - "ref_data_genome_bwa_index_image": { + "genome_bwa_index_image": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.img$", @@ -211,7 +215,7 @@ "fa_icon": "far fa-file-code", "hidden": true }, - "ref_data_genome_gridss_index": { + "genome_gridss_index": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.gridsscache$", diff --git a/subworkflows/local/lilac_calling/main.nf b/subworkflows/local/lilac_calling/main.nf index 35cfdd97..bcc91dae 100644 --- a/subworkflows/local/lilac_calling/main.nf +++ b/subworkflows/local/lilac_calling/main.nf @@ -70,7 +70,7 @@ workflow LILAC_CALLING { // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them to the three // relevant HLA genes on chr6. All reads including those previously mapped to chr6 are realigned for // consistency. - if (params.ref_data_genome_type == 'alt') { + if (params.genome_type == 'alt') { // Flatten into BAM/BAI pairs, select inputs that are eligible to run // channel: runnable: [ meta_extra, bam, bai ] diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 5c37f7bb..0cd25e51 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -25,7 +25,7 @@ workflow PREPARE_REFERENCE { // // Set some variables for brevity // - ch_genome_fasta = file(params.ref_data_genome_fasta) + ch_genome_fasta = file(params.genome_fasta) run_virusinterpreter = run_config.mode !== Constants.RunMode.TARGETED && run_config.stages.virusinterpreter // @@ -34,14 +34,14 @@ workflow PREPARE_REFERENCE { // The fai and dict files should always be present if using a genome preset. These are // always created where they are not present without checking processes to run given they // are used in numerous processes and have a neglibile cost to generate. - ch_genome_fai = params.ref_data_genome_fai ? file(params.ref_data_genome_fai) : [] - ch_genome_dict = params.ref_data_genome_dict ? file(params.ref_data_genome_dict) : [] - if (!params.ref_data_genome_fai) { + ch_genome_fai = params.genome_fai ? file(params.genome_fai) : [] + ch_genome_dict = params.genome_dict ? file(params.genome_dict) : [] + if (!params.genome_fai) { SAMTOOLS_FAIDX([[:], ch_genome_fasta]) ch_genome_fai = SAMTOOLS_FAIDX.out.fai.map { meta, fai -> fai } ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions) } - if (!params.ref_data_genome_dict) { + if (!params.genome_dict) { SAMTOOLS_DICT([[:], ch_genome_fasta]) ch_genome_dict = SAMTOOLS_DICT.out.dict.map { meta, dict -> dict } ch_versions = ch_versions.mix(SAMTOOLS_DICT.out.versions) @@ -50,25 +50,25 @@ workflow PREPARE_REFERENCE { // // Create BWA index, BWA index image, and GRIDSS index for reference genome if required // - ch_genome_bwa_index = params.ref_data_genome_bwa_index ? file(params.ref_data_genome_bwa_index) : [] - ch_genome_bwa_index_image = params.ref_data_genome_gridss_index ? file(params.ref_data_genome_bwa_index_image) : [] - ch_genome_gridss_index = params.ref_data_genome_gridss_index ? file(params.ref_data_genome_gridss_index) : [] + ch_genome_bwa_index = params.genome_bwa_index ? file(params.genome_bwa_index) : [] + ch_genome_bwa_index_image = params.genome_gridss_index ? file(params.genome_bwa_index_image) : [] + ch_genome_gridss_index = params.genome_gridss_index ? file(params.genome_gridss_index) : [] if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { // NOTE(SW): the BWA index directory can be provided as a compressed tarball - if (!params.ref_data_genome_bwa_index) { + if (!params.genome_bwa_index) { BWA_INDEX([[:], ch_genome_fasta]) ch_genome_bwa_index = BWA_INDEX.out.index.map { meta, index -> index } ch_versions = ch_versions.mix(BWA_INDEX.out.versions) - } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { + } else if (params.genome_bwa_index.endsWith('.tar.gz')) { ch_genome_bwa_index_inputs = [ [id: 'bwa_index'], - file(params.ref_data_genome_bwa_index), + file(params.genome_bwa_index), ] DECOMP_BWA_INDEX(ch_genome_bwa_index_inputs) ch_genome_bwa_index = DECOMP_BWA_INDEX.out.dir } - if (!params.ref_data_genome_bwa_index_image) { + if (!params.genome_bwa_index_image) { GRIDSS_BWA_INDEX_IMAGE( ch_genome_fasta, ch_genome_fai, @@ -80,7 +80,7 @@ workflow PREPARE_REFERENCE { ch_genome_bwa_index_image = GRIDSS_BWA_INDEX_IMAGE.out.img ch_versions = ch_versions.mix(GRIDSS_BWA_INDEX_IMAGE.out.versions) } - if (!params.ref_data_genome_gridss_index) { + if (!params.genome_gridss_index) { GRIDSS_INDEX( ch_genome_fasta, ch_genome_fai, @@ -99,26 +99,26 @@ workflow PREPARE_REFERENCE { // ch_virusbreakenddb = Channel.empty() if (run_config.has_dna && run_virusinterpreter) { - if (params.ref_data_virusbreakenddb_path.endsWith('.tar.gz')) { + if (params.virusbreakenddb_path.endsWith('.tar.gz')) { ch_virusbreakenddb_inputs = [ [id: 'virusbreakenddb'], - file(params.ref_data_virusbreakenddb_path), + file(params.virusbreakenddb_path), ] DECOMP_VIRUSBREAKEND_DB(ch_virusbreakenddb_inputs) ch_virusbreakenddb = DECOMP_VIRUSBREAKEND_DB.out.dir } else { - ch_virusbreakenddb = file(params.ref_data_virusbreakenddb_path) + ch_virusbreakenddb = file(params.virusbreakenddb_path) } } // // Set HMF reference paths / stage, unpack if required // - hmf_data_paths = params.hmf_data_paths[params.ref_data_genome_version] - if (params.ref_data_hmf_data_path.endsWith('tar.gz')) { + hmf_data_paths = params.hmf_data_paths[params.genome_version] + if (params.hmf_data_path.endsWith('tar.gz')) { ch_hmf_data_inputs = [ [id: 'hmf_data'], - file(params.ref_data_hmf_data_path), + file(params.hmf_data_path), ] DECOMP_HMF_DATA(ch_hmf_data_inputs) @@ -130,7 +130,7 @@ workflow PREPARE_REFERENCE { return createDataMap(hmf_data_paths, dirpath) } } else { - ch_hmf_data = createDataMap(hmf_data_paths, params.ref_data_hmf_data_path) + ch_hmf_data = createDataMap(hmf_data_paths, params.hmf_data_path) } // @@ -142,12 +142,12 @@ workflow PREPARE_REFERENCE { // NOTE(SW): consider approach to implement custom panel support panel_data_paths_versions = params.panel_data_paths[params.panel] - panel_data_paths = panel_data_paths_versions[params.ref_data_genome_version] + panel_data_paths = panel_data_paths_versions[params.genome_version] - if (params.ref_data_panel_data_path.endsWith('tar.gz')) { + if (params.panel_data_path.endsWith('tar.gz')) { ch_panel_data_inputs = [ [id: 'panel_data'], - file(params.ref_data_panel_data_path), + file(params.panel_data_path), ] DECOMP_PANEL_DATA(ch_panel_data_inputs) @@ -159,7 +159,7 @@ workflow PREPARE_REFERENCE { return createDataMap(panel_data_paths, dirpath) } } else { - ch_panel_data = createDataMap(panel_data_paths, params.ref_data_panel_data_path) + ch_panel_data = createDataMap(panel_data_paths, params.panel_data_path) } } @@ -170,7 +170,7 @@ workflow PREPARE_REFERENCE { genome_bwa_index = ch_genome_bwa_index // path: genome_bwa_index genome_bwa_index_image = ch_genome_bwa_index_image // path: genome_bwa_index_image genome_gridss_index = ch_genome_gridss_index // path: genome_gridss_index - genome_version = params.ref_data_genome_version // val: genome_version + genome_version = params.genome_version // val: genome_version virusbreakenddb = ch_virusbreakenddb // path: VIRUSBreakend database hmf_data = ch_hmf_data // map: HMF data paths diff --git a/tests/main.stub.nf.test b/tests/main.stub.nf.test index a4dc4a54..3775d056 100644 --- a/tests/main.stub.nf.test +++ b/tests/main.stub.nf.test @@ -15,8 +15,8 @@ nextflow_pipeline { input "${baseDir}/tests/samplesheets/wgts.dna_rna.single.stub.csv" outdir "${outputDir}" - ref_data_virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" - ref_data_hmf_data_path "${workDir}/reference_data/hmf_data/" + virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" + hmf_data_path "${workDir}/reference_data/hmf_data/" max_cpus = 1 max_memory = "10.GB" @@ -44,9 +44,9 @@ nextflow_pipeline { input "${baseDir}/tests/samplesheets/targeted.tso500.dna_rna.single.stub.csv" outdir "${outputDir}" - ref_data_virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" - ref_data_hmf_data_path "${workDir}/reference_data/hmf_data/" - ref_data_panel_data_path "${workDir}/reference_data/panel_data/" + virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" + hmf_data_path "${workDir}/reference_data/hmf_data/" + panel_data_path "${workDir}/reference_data/panel_data/" max_cpus 1 max_memory "10.GB" diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 64d76dbb..1727c6f5 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -35,8 +35,8 @@ if (run_config.stages.gridss) { } if (run_config.stages.lilac) { - if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && params.containsKey('ref_data_hla_slice_bed')) { - checkPathParamList.add(params.ref_data_hla_slice_bed) + if (params.genome_version == '38' && params.genome_type == 'alt' && params.containsKey('hla_slice_bed')) { + checkPathParamList.add(params.hla_slice_bed) } } @@ -49,13 +49,6 @@ if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input sample // Create Path objects for some input files linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : [] -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - CONFIG FILES -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS @@ -528,7 +521,7 @@ workflow TARGETED { if (run_config.stages.lilac) { // Set HLA slice BED if provided in params - ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] + ref_data_hla_slice_bed = params.containsKey('hla_slice_bed') ? params.hla_slice_bed : [] LILAC_CALLING( ch_inputs, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 72db8010..65c9188c 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -33,12 +33,12 @@ if (run_config.stages.gridss) { // Mode check required as evaluated regardless of workflow selection if (run_config.stages.virusinterpreter && run_config.mode !== Constants.RunMode.TARGETED) { - checkPathParamList.add(params.ref_data_virusbreakenddb_path) + checkPathParamList.add(params.virusbreakenddb_path) } if (run_config.stages.lilac) { - if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && params.containsKey('ref_data_hla_slice_bed')) { - checkPathParamList.add(params.ref_data_hla_slice_bed) + if (params.genome_version == '38' && params.genome_type == 'alt' && params.containsKey('hla_slice_bed')) { + checkPathParamList.add(params.hla_slice_bed) } } @@ -51,13 +51,6 @@ if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input sample // Create Path objects for some input files linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : [] -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - CONFIG FILES -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS @@ -575,7 +568,7 @@ workflow WGTS { if (run_config.stages.lilac) { // Use HLA slice BED if provided in params or set as default requirement - ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] + ref_data_hla_slice_bed = params.containsKey('hla_slice_bed') ? params.hla_slice_bed : [] LILAC_CALLING( ch_inputs, From b4a37b3438dd03f9dac82b19e59d85adf92c0f8e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 10:55:46 +1100 Subject: [PATCH 386/562] More indenting fixes --- lib/WorkflowMain.groovy | 6 +++--- nextflow.config | 2 +- subworkflows/local/chord_prediction/main.nf | 12 ++++++------ subworkflows/local/gripss_filtering/main.nf | 10 +++++----- subworkflows/local/prepare_inputs/main.nf | 2 +- subworkflows/local/sigs_fitting/main.nf | 8 ++++---- subworkflows/local/virusbreakend_calling/main.nf | 6 +++--- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index a2304f5a..8baa9552 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -161,9 +161,9 @@ class WorkflowMain { // NOTE(SW): this could be moved to the wgts.nf where we check that input files exist def null_check = [ - 'genome_fasta', - 'genome_type', - 'genome_version', + 'genome_fasta', + 'genome_type', + 'genome_version', ] null_check.each { k -> if (!params[k]) { diff --git a/nextflow.config b/nextflow.config index a2a05b51..ec14c46b 100644 --- a/nextflow.config +++ b/nextflow.config @@ -223,7 +223,7 @@ includeConfig 'conf/panel_data.config' // Load panel configuration if needed if (params.containsKey('mode') && params.mode == 'targeted') { - includeConfig 'conf/targeted_parameters.config' + includeConfig 'conf/targeted_parameters.config' } // Export these variables to prevent local Python/R libraries from conflicting with those in the container diff --git a/subworkflows/local/chord_prediction/main.nf b/subworkflows/local/chord_prediction/main.nf index 04b0f61a..b8c0424e 100644 --- a/subworkflows/local/chord_prediction/main.nf +++ b/subworkflows/local/chord_prediction/main.nf @@ -41,16 +41,16 @@ workflow CHORD_PREDICTION { def has_sv_vcf if (has_dna) { - tumor_id = Utils.getTumorDnaSampleName(meta) - has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] - has_sv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") : [] + tumor_id = Utils.getTumorDnaSampleName(meta) + has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] + has_sv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") : [] } def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.CHORD_DIR) runnable: has_dna && purple_dir && has_smlv_vcf && has_sv_vcf && !has_existing skip: true - return meta + return meta } // Create process input channel @@ -74,8 +74,8 @@ workflow CHORD_PREDICTION { // Run process CHORD( - ch_chord_inputs, - genome_version, + ch_chord_inputs, + genome_version, ) ch_versions = ch_versions.mix(CHORD.out.versions) diff --git a/subworkflows/local/gripss_filtering/main.nf b/subworkflows/local/gripss_filtering/main.nf index 2277c1d2..7db6b449 100644 --- a/subworkflows/local/gripss_filtering/main.nf +++ b/subworkflows/local/gripss_filtering/main.nf @@ -111,11 +111,11 @@ workflow GRIPSS_FILTERING { ch_gripss_somatic_inputs = ch_inputs_somatic_sorted.runnable .map { meta, gridss_vcf -> - def meta_gripss = [ - key: meta.group_id, - id: meta.group_id, - tumor_id: Utils.getTumorDnaSampleName(meta), - ] + def meta_gripss = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + ] if (Utils.hasNormalDnaBam(meta)) { meta_gripss.normal_id = Utils.getNormalDnaSampleName(meta) diff --git a/subworkflows/local/prepare_inputs/main.nf b/subworkflows/local/prepare_inputs/main.nf index 47b198e0..f6e6dfae 100644 --- a/subworkflows/local/prepare_inputs/main.nf +++ b/subworkflows/local/prepare_inputs/main.nf @@ -13,7 +13,7 @@ import Utils workflow PREPARE_INPUTS { take: - input_fp_str + input_fp_str main: diff --git a/subworkflows/local/sigs_fitting/main.nf b/subworkflows/local/sigs_fitting/main.nf index 31418403..73cebff5 100644 --- a/subworkflows/local/sigs_fitting/main.nf +++ b/subworkflows/local/sigs_fitting/main.nf @@ -39,8 +39,8 @@ workflow SIGS_FITTING { def tumor_id def has_smlv_vcf if (has_dna) { - tumor_id = Utils.getTumorDnaSampleName(meta) - has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] + tumor_id = Utils.getTumorDnaSampleName(meta) + has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] } def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SIGS_DIR) @@ -70,8 +70,8 @@ workflow SIGS_FITTING { // Run process SIGS( - ch_sigs_inputs, - sigs_signatures, + ch_sigs_inputs, + sigs_signatures, ) ch_versions = ch_versions.mix(SIGS.out.versions) diff --git a/subworkflows/local/virusbreakend_calling/main.nf b/subworkflows/local/virusbreakend_calling/main.nf index 84abb4f7..0e328e06 100644 --- a/subworkflows/local/virusbreakend_calling/main.nf +++ b/subworkflows/local/virusbreakend_calling/main.nf @@ -84,9 +84,9 @@ workflow VIRUSBREAKEND_CALLING { // Select input sources // channel: [ meta, virus_tsv, purple_dir, metrics ] ch_virusinterpreter_inputs_selected = WorkflowOncoanalyser.groupByMeta( - WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), - ch_purple, - ch_bamtools_somatic, + WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), + ch_purple, + ch_bamtools_somatic, ) .map { meta, virus_tsv, purple_dir, metrics -> From 05c3503f255050a3998eda4a6baa4951b82aa8b6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 11:02:21 +1100 Subject: [PATCH 387/562] Update pipeline description --- nextflow.config | 2 +- nextflow_schema.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nextflow.config b/nextflow.config index ec14c46b..a28ff8ea 100644 --- a/nextflow.config +++ b/nextflow.config @@ -265,7 +265,7 @@ manifest { name = 'nf-core/oncoanalyser' author = """Stephen Watts""" homePage = 'https://github.com/nf-core/oncoanalyser' - description = 'A comprehensive cancer NGS analysis and reporting pipeline' + description = 'A comprehensive cancer DNA/RNA analysis and reporting pipeline' mainScript = 'main.nf' // NOTE(SW): staging reference data from S3 requires fixes made for the 22.10.4 release // NOTE(SW): bug relating to concurrently staging data fixed in 22.10.5 release diff --git a/nextflow_schema.json b/nextflow_schema.json index 5bea4bad..e6375fba 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema", "$id": "https://raw.githubusercontent.com/nf-core/oncoanalyser/master/nextflow_schema.json", "title": "nf-core/oncoanalyser pipeline parameters", - "description": "A comprehensive cancer NGS analysis and reporting pipeline", + "description": "A comprehensive cancer DNA/RNA analysis and reporting pipeline", "type": "object", "definitions": { "input_output_options": { From 1b9a4675e8139cc585fafa47be462b6ba9a27c24 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 11:17:25 +1100 Subject: [PATCH 388/562] Update test config, adjust relevant arg schema --- conf/test.config | 4 ++-- nextflow_schema.json | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/conf/test.config b/conf/test.config index 6ecc8052..d9c81020 100644 --- a/conf/test.config +++ b/conf/test.config @@ -16,7 +16,7 @@ params { // Defined here to be accessible within a workflow script; downloaded manually prior to process // execution. - schema_ignore_params = 'genomes,hmf_data_paths,panel_data_paths' + validationSchemaIgnoreParams = 'genomes,hmf_data_paths,panel_data_paths' // Limit resources so that this can run on GitHub Actions max_cpus = 1 @@ -26,7 +26,7 @@ params { // Input data input = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/other/samplesheet.colo829_mini.dna_rna.grch38_hmf.csv' - mode = 'wgts' + mode = 'wgts' genome = 'GRCh38_hmf' virusbreakenddb_path = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/reference_data/virusbreakend/virusbreakenddb_test.tar.gz' diff --git a/nextflow_schema.json b/nextflow_schema.json index e6375fba..3aabde44 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -152,8 +152,7 @@ }, "virusbreakenddb_path": { "type": "string", - "format": "directory-path", - "description": "Path to VIRUSBreakend database.", + "description": "Path to VIRUSBreakend database (directory or tarball).", "fa_icon": "far fa-file-code" }, "hla_slice_bed": { @@ -202,8 +201,7 @@ }, "genome_bwa_index": { "type": "string", - "format": "directory-path", - "description": "Path to directory containing reference genome BWA indices.", + "description": "Path to reference genome BWA indices (directory or tarball).", "fa_icon": "far fa-file-code", "hidden": true }, From 45ce69946f7493f53fb70ae951ddbd4af5cfc284 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 13:03:01 +1100 Subject: [PATCH 389/562] Reorganise reference data and params --- lib/Utils.groovy | 18 ++-- lib/WorkflowMain.groovy | 105 ++++++++----------- main.nf | 19 ++-- nextflow.config | 4 +- nextflow_schema.json | 75 +++---------- subworkflows/local/prepare_reference/main.nf | 52 ++++----- workflows/targeted.nf | 13 +-- workflows/wgts.nf | 13 +-- 8 files changed, 124 insertions(+), 175 deletions(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 7fe1f35b..268837f8 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -131,22 +131,22 @@ class Utils { public static void createStubPlaceholders(params) { def fps = [ - params.genome_fasta, - params.genome_fai, - params.genome_dict, - params.genome_bwa_index, - params.genome_bwa_index_image, - params.genome_gridss_index, - params.virusbreakenddb_path, + params.ref_data.genome_fasta, + params.ref_data.genome_fai, + params.ref_data.genome_dict, + params.ref_data.genome_bwa_index, + params.ref_data.genome_bwa_index_image, + params.ref_data.genome_gridss_index, + params.ref_data.virusbreakenddb_path, ] - params.hmf_data_paths[params.genome_version] + params.hmf_data_paths[params.ref_data.genome_version] .each { k, v -> fps << "${params.hmf_data_path.replaceAll('/$', '')}/${v}" } if(params.containsKey('panel')) { - params.panel_data_paths[params.panel][params.genome_version] + params.panel_data_paths[params.panel][params.ref_data.genome_version] .each { k, v -> fps << "${params.panel_data_path.replaceAll('/$', '')}/${v}" } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 8baa9552..4d866709 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -9,36 +9,38 @@ class WorkflowMain { // public static void setParamsDefaults(params, log) { - // Set defaults common to all run configuration - def default_invalid = false - if (params.containsKey('genome_version')) { - params.genome_version = params.genome_version.toString() + // Set defaults common to all run configuration + + if (params.genome_version !== null) { + params.ref_data.genome_version = params.genome_version.toString() } else if (Constants.GENOMES_VERSION_37.contains(params.genome)) { - params.genome_version = '37' + params.ref_data.genome_version = '37' } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { - params.genome_version = '38' + params.ref_data.genome_version = '38' } else { default_invalid = true } - if (params.containsKey('genome_type')) { - params.genome_type = params.genome_type + if (params.genome_type !== null) { + params.ref_data.genome_type = params.genome_type } else if (Constants.GENOMES_ALT.contains(params.genome)) { - params.genome_type = 'alt' + params.ref_data.genome_type = 'alt' } else if (Constants.GENOMES_DEFINED.contains(params.genome)) { - params.genome_type = 'no_alt' + params.ref_data.genome_type = 'no_alt' } else { default_invalid = true } - if (!params.containsKey('hmf_data_path')) { - if (params.genome_version == '37') { - params.hmf_data_path = Constants.HMF_DATA_37_PATH - } else if (params.genome_version == '38') { - params.hmf_data_path = Constants.HMF_DATA_38_PATH - } + if (params.hmf_data_path !== null) { + params.ref_data.hmf_data_path = params.hmf_data_path + } else if (params.ref_data.genome_version == '37') { + params.ref_data.hmf_data_path = Constants.HMF_DATA_37_PATH + } else if (params.ref_data.genome_version == '38') { + params.ref_data.hmf_data_path = Constants.HMF_DATA_38_PATH + } else { + default_invalid = true } // Bad configuration, catch in validateParams @@ -49,7 +51,7 @@ class WorkflowMain { // Set defaults specific to run configuration without attempting to validate def run_mode - if (params.containsKey('mode') && params.mode !== null) { + if (params.mode !== null) { run_mode = Utils.getRunMode(params.mode, log) } else { // Bad configuration, catch in validateParams @@ -59,14 +61,16 @@ class WorkflowMain { if (run_mode === Constants.RunMode.TARGETED) { // Attempt to set default panel data path; make no assumption on valid 'panel' value - if (!params.containsKey('panel_data_path') && params.containsKey('panel')) { + + if (params.panel_data_path !== null) { + params.ref_data.panel_data_path = params.panel_data_path + } else if (params.panel !== null ) { if (params.panel == 'tso500' && params.genome_version == '37') { - params.panel_data_path = Constants.TSO500_PANEL_37_PATH + params.ref_data.panel_data_path = Constants.TSO500_PANEL_37_PATH } else if (params.panel == 'tso500' && params.genome_version == '38') { - params.panel_data_path = Constants.TSO500_PANEL_38_PATH + params.ref_data.panel_data_path = Constants.TSO500_PANEL_38_PATH } } - } def stages = Processes.getRunStages( @@ -77,27 +81,21 @@ class WorkflowMain { ) if (stages.virusinterpreter && run_mode === Constants.RunMode.WGTS) { - if (!params.containsKey('virusbreakenddb_path')) { - params.virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH + if (params.virusbreakenddb_path !== null) { + params.ref_data.virusbreakenddb_path = params.virusbreakenddb_path + } else { + params.ref_data.virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH } } if (stages.lilac) { - if (params.genome_version == '38' && params.genome_type == 'alt' && !params.containsKey('hla_slice_bed')) { - params.hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH + if (params.hla_slice_bed !== null) { + params.ref_data.hla_slice_bed = params.hla_slice_bed + } else if (params.genome_version == '38' && params.genome_type == 'alt') { + params.ref_data.hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH } } - if (stages.isofox && !params.containsKey('isofox_read_length')) { - - if (run_mode === Constants.RunMode.WGTS) { - params.isofox_read_length = Constants.DEFAULT_ISOFOX_READ_LENGTH_WTS - } else if (run_mode === Constants.RunMode.TARGETED) { - params.isofox_read_length = Constants.DEFAULT_ISOFOX_READ_LENGTH_TARGETED - } - - } - } // @@ -107,36 +105,36 @@ class WorkflowMain { // Common parameters - if (!params.genome) { + if (!params.ref_data.genome) { log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome must be set using the --genome CLI argument or in a configuration file.\n" + " Currently, the available genome are:\n" + " ${params.genomes.keySet().join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) - } else if (!params.genomes.containsKey(params.genome)) { + } else if (!params.genomes.containsKey(params.ref_data.genome)) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + + " Genome '${params.ref_data.genome}' not found in any config files provided to the pipeline.\n" + " Currently, the available genome are:\n" + " ${params.genomes.keySet().join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) } - if (!Constants.GENOMES_SUPPORTED.contains(params.genome)) { - if (!params.containsKey('force_genome') || !params.force_genome) { - log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got ${params.genome}" + + if (!Constants.GENOMES_SUPPORTED.contains(params.ref_data.genome)) { + if (!params.ref_data.force_genome) { + log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got ${params.ref_data.genome}" + ", please adjust the --genome argument accordingly or override with --force_genome." System.exit(1) } else { log.warn "currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but forcing to " + - "proceed with \"${params.genome}\"" + "proceed with \"${params.ref_data.genome}\"" } } - if (!params.genome_version) { + if (!params.ref_data.genome_version) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome version wasn't provided and genome '${params.genome}' is not defined in \n" + + " Genome version wasn't provided and genome '${params.ref_data.genome}' is not defined in \n" + " genome version list.\n" + " Currently, the list of genomes in the version list include:\n" + " ${Constants.GENOMES_DEFINED.join(", ")}\n" + @@ -144,9 +142,9 @@ class WorkflowMain { System.exit(1) } - if (!params.genome_type) { + if (!params.ref_data.genome_type) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome type wasn't provided and genome '${params.genome}' is not defined in \n" + + " Genome type wasn't provided and genome '${params.ref_data.genome}' is not defined in \n" + " genome type list.\n" + " Currently, the list of genomes in the type list include:\n" + " ${Constants.GENOMES_DEFINED.join(", ")}\n" + @@ -154,24 +152,11 @@ class WorkflowMain { System.exit(1) } - if (!params.hmf_data_path) { + if (!params.ref_data.hmf_data_path) { log.error "ERROR: HMF data path wasn't provided" System.exit(1) } - // NOTE(SW): this could be moved to the wgts.nf where we check that input files exist - def null_check = [ - 'genome_fasta', - 'genome_type', - 'genome_version', - ] - null_check.each { k -> - if (!params[k]) { - log.error "ERROR: '${k}' cannot be set to null in any configuration and must be adjusted or removed to proceed." - System.exit(1) - } - } - // Run configuration specific parameters if (!params.mode) { diff --git a/main.nf b/main.nf index 4da82d39..98e306f1 100644 --- a/main.nf +++ b/main.nf @@ -31,14 +31,21 @@ include { getGenomeAttribute } from './subworkflows/local/utils_nfcore_oncoanaly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -params.genome_fasta = getGenomeAttribute('fasta') -params.genome_fai = getGenomeAttribute('fai') -params.genome_dict = getGenomeAttribute('dict') -params.genome_bwa_index = getGenomeAttribute('bwa_index') -params.genome_bwa_index_image = getGenomeAttribute('bwa_index_image') -params.genome_gridss_index = getGenomeAttribute('gridss_index') +// Reference config lifted up into params.ref_data to conform to standards/linting +params.ref_data = [ + genome: params.genome, + force_genome: params.force_genome, +] + +params.ref_data.genome_fasta = getGenomeAttribute('fasta') +params.ref_data.genome_fai = getGenomeAttribute('fai') +params.ref_data.genome_dict = getGenomeAttribute('dict') +params.ref_data.genome_bwa_index = getGenomeAttribute('bwa_index') +params.ref_data.genome_bwa_index_image = getGenomeAttribute('bwa_index_image') +params.ref_data.genome_gridss_index = getGenomeAttribute('gridss_index') WorkflowMain.setParamsDefaults(params, log) +WorkflowMain.validateParams(params, log) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/nextflow.config b/nextflow.config index a28ff8ea..1e1d1b3b 100644 --- a/nextflow.config +++ b/nextflow.config @@ -25,7 +25,7 @@ params { genome = null genome_version = null genome_type = null - force_genome = null + force_genome = false igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false @@ -77,7 +77,7 @@ params { // Schema validation default options validationFailUnrecognisedParams = false validationLenientMode = true - validationSchemaIgnoreParams = 'genomes,igenomes_base,hmf_data_paths,panel_data_paths' + validationSchemaIgnoreParams = 'genomes,igenomes_base,ref_data,hmf_data_paths,panel_data_paths' validationShowHiddenParams = false validate_params = true diff --git a/nextflow_schema.json b/nextflow_schema.json index 3aabde44..2f05ef50 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -57,6 +57,7 @@ "force_genome": { "type": "boolean", "description": "Skip check for restricted genome.", + "default": false, "fa_icon": "fas fa-palette" }, "processes_manual": { @@ -133,6 +134,20 @@ "description": "Name of genome reference.", "fa_icon": "fas fa-book" }, + "genome_version": { + "type": "string", + "description": "Version of reference genome.", + "fa_icon": "far fa-file-code", + "enum": ["37", "38"], + "hidden": true + }, + "genome_type": { + "type": "string", + "description": "Type of reference genome.", + "fa_icon": "far fa-file-code", + "enum": ["alt", "no_alt"], + "hidden": true + }, "igenomes_ignore": { "type": "boolean", "description": "Do not load the iGenomes reference config.", @@ -160,66 +175,6 @@ "pattern": "^\\S+\\.bed$", "description": "Path to HLA slice BED file.", "fa_icon": "far fa-file-code" - }, - "genome_fasta": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", - "description": "Path to reference genome FASTA file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "genome_version": { - "type": "string", - "description": "Version of reference genome.", - "fa_icon": "far fa-file-code", - "enum": ["37", "38"], - "hidden": true - }, - "genome_type": { - "type": "string", - "description": "Type of reference genome.", - "fa_icon": "far fa-file-code", - "enum": ["alt", "no_alt"], - "hidden": true - }, - "genome_fai": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.fai$", - "description": "Path to reference genome FAI file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "genome_dict": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.dict$", - "description": "Path to reference genome sequence dictionary file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "genome_bwa_index": { - "type": "string", - "description": "Path to reference genome BWA indices (directory or tarball).", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "genome_bwa_index_image": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.img$", - "description": "Path to reference genome BWA indices image file.", - "fa_icon": "far fa-file-code", - "hidden": true - }, - "genome_gridss_index": { - "type": "string", - "format": "file-path", - "pattern": "^\\S+\\.gridsscache$", - "description": "Path to reference genome GRIDSS index file.", - "fa_icon": "far fa-file-code", - "hidden": true } } }, diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 0cd25e51..54616930 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -25,7 +25,7 @@ workflow PREPARE_REFERENCE { // // Set some variables for brevity // - ch_genome_fasta = file(params.genome_fasta) + ch_genome_fasta = file(params.ref_data.genome_fasta) run_virusinterpreter = run_config.mode !== Constants.RunMode.TARGETED && run_config.stages.virusinterpreter // @@ -34,14 +34,14 @@ workflow PREPARE_REFERENCE { // The fai and dict files should always be present if using a genome preset. These are // always created where they are not present without checking processes to run given they // are used in numerous processes and have a neglibile cost to generate. - ch_genome_fai = params.genome_fai ? file(params.genome_fai) : [] - ch_genome_dict = params.genome_dict ? file(params.genome_dict) : [] - if (!params.genome_fai) { + ch_genome_fai = params.ref_data.genome_fai ? file(params.ref_data.genome_fai) : [] + ch_genome_dict = params.ref_data.genome_dict ? file(params.ref_data.genome_dict) : [] + if (!params.ref_data.genome_fai) { SAMTOOLS_FAIDX([[:], ch_genome_fasta]) ch_genome_fai = SAMTOOLS_FAIDX.out.fai.map { meta, fai -> fai } ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions) } - if (!params.genome_dict) { + if (!params.ref_data.genome_dict) { SAMTOOLS_DICT([[:], ch_genome_fasta]) ch_genome_dict = SAMTOOLS_DICT.out.dict.map { meta, dict -> dict } ch_versions = ch_versions.mix(SAMTOOLS_DICT.out.versions) @@ -50,25 +50,25 @@ workflow PREPARE_REFERENCE { // // Create BWA index, BWA index image, and GRIDSS index for reference genome if required // - ch_genome_bwa_index = params.genome_bwa_index ? file(params.genome_bwa_index) : [] - ch_genome_bwa_index_image = params.genome_gridss_index ? file(params.genome_bwa_index_image) : [] - ch_genome_gridss_index = params.genome_gridss_index ? file(params.genome_gridss_index) : [] + ch_genome_bwa_index = params.ref_data.genome_bwa_index ? file(params.ref_data.genome_bwa_index) : [] + ch_genome_bwa_index_image = params.ref_data.genome_gridss_index ? file(params.ref_data.genome_bwa_index_image) : [] + ch_genome_gridss_index = params.ref_data.genome_gridss_index ? file(params.ref_data.genome_gridss_index) : [] if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { // NOTE(SW): the BWA index directory can be provided as a compressed tarball - if (!params.genome_bwa_index) { + if (!params.ref_data.genome_bwa_index) { BWA_INDEX([[:], ch_genome_fasta]) ch_genome_bwa_index = BWA_INDEX.out.index.map { meta, index -> index } ch_versions = ch_versions.mix(BWA_INDEX.out.versions) - } else if (params.genome_bwa_index.endsWith('.tar.gz')) { + } else if (params.ref_data.genome_bwa_index.endsWith('.tar.gz')) { ch_genome_bwa_index_inputs = [ [id: 'bwa_index'], - file(params.genome_bwa_index), + file(params.ref_data.genome_bwa_index), ] DECOMP_BWA_INDEX(ch_genome_bwa_index_inputs) ch_genome_bwa_index = DECOMP_BWA_INDEX.out.dir } - if (!params.genome_bwa_index_image) { + if (!params.ref_data.genome_bwa_index_image) { GRIDSS_BWA_INDEX_IMAGE( ch_genome_fasta, ch_genome_fai, @@ -80,7 +80,7 @@ workflow PREPARE_REFERENCE { ch_genome_bwa_index_image = GRIDSS_BWA_INDEX_IMAGE.out.img ch_versions = ch_versions.mix(GRIDSS_BWA_INDEX_IMAGE.out.versions) } - if (!params.genome_gridss_index) { + if (!params.ref_data.genome_gridss_index) { GRIDSS_INDEX( ch_genome_fasta, ch_genome_fai, @@ -99,26 +99,26 @@ workflow PREPARE_REFERENCE { // ch_virusbreakenddb = Channel.empty() if (run_config.has_dna && run_virusinterpreter) { - if (params.virusbreakenddb_path.endsWith('.tar.gz')) { + if (params.ref_data.virusbreakenddb_path.endsWith('.tar.gz')) { ch_virusbreakenddb_inputs = [ [id: 'virusbreakenddb'], - file(params.virusbreakenddb_path), + file(params.ref_data.virusbreakenddb_path), ] DECOMP_VIRUSBREAKEND_DB(ch_virusbreakenddb_inputs) ch_virusbreakenddb = DECOMP_VIRUSBREAKEND_DB.out.dir } else { - ch_virusbreakenddb = file(params.virusbreakenddb_path) + ch_virusbreakenddb = file(params.ref_data.virusbreakenddb_path) } } // // Set HMF reference paths / stage, unpack if required // - hmf_data_paths = params.hmf_data_paths[params.genome_version] - if (params.hmf_data_path.endsWith('tar.gz')) { + hmf_data_paths = params.hmf_data_paths[params.ref_data.genome_version] + if (params.ref_data.hmf_data_path.endsWith('tar.gz')) { ch_hmf_data_inputs = [ [id: 'hmf_data'], - file(params.hmf_data_path), + file(params.ref_data.hmf_data_path), ] DECOMP_HMF_DATA(ch_hmf_data_inputs) @@ -130,7 +130,7 @@ workflow PREPARE_REFERENCE { return createDataMap(hmf_data_paths, dirpath) } } else { - ch_hmf_data = createDataMap(hmf_data_paths, params.hmf_data_path) + ch_hmf_data = createDataMap(hmf_data_paths, params.ref_data.hmf_data_path) } // @@ -141,13 +141,13 @@ workflow PREPARE_REFERENCE { // NOTE(SW): consider approach to implement custom panel support - panel_data_paths_versions = params.panel_data_paths[params.panel] - panel_data_paths = panel_data_paths_versions[params.genome_version] + panel_data_paths_versions = params.ref_data.panel_data_paths[params.panel] + panel_data_paths = panel_data_paths_versions[params.ref_data.genome_version] - if (params.panel_data_path.endsWith('tar.gz')) { + if (params.ref_data.panel_data_path.endsWith('tar.gz')) { ch_panel_data_inputs = [ [id: 'panel_data'], - file(params.panel_data_path), + file(params.ref_data.panel_data_path), ] DECOMP_PANEL_DATA(ch_panel_data_inputs) @@ -159,7 +159,7 @@ workflow PREPARE_REFERENCE { return createDataMap(panel_data_paths, dirpath) } } else { - ch_panel_data = createDataMap(panel_data_paths, params.panel_data_path) + ch_panel_data = createDataMap(panel_data_paths, params.ref_data.panel_data_path) } } @@ -170,7 +170,7 @@ workflow PREPARE_REFERENCE { genome_bwa_index = ch_genome_bwa_index // path: genome_bwa_index genome_bwa_index_image = ch_genome_bwa_index_image // path: genome_bwa_index_image genome_gridss_index = ch_genome_gridss_index // path: genome_gridss_index - genome_version = params.genome_version // val: genome_version + genome_version = params.ref_data.genome_version // val: genome_version virusbreakenddb = ch_virusbreakenddb // path: VIRUSBreakend database hmf_data = ch_hmf_data // map: HMF data paths diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 1727c6f5..8b821d98 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -29,14 +29,14 @@ def checkPathParamList = [ // Conditional requirements if (run_config.stages.gridss) { - if (params.containsKey('gridss_config')) { + if (params.gridss_config !== null) { checkPathParamList.add(params.gridss_config) } } if (run_config.stages.lilac) { - if (params.genome_version == '38' && params.genome_type == 'alt' && params.containsKey('hla_slice_bed')) { - checkPathParamList.add(params.hla_slice_bed) + if (params.ref_data.genome_version == '38' && params.ref_data.genome_type == 'alt' && params.ref_data.containsKey('hla_slice_bed')) { + checkPathParamList.add(params.ref_data.hla_slice_bed) } } @@ -102,7 +102,7 @@ workflow TARGETED { panel_data = PREPARE_REFERENCE.out.panel_data // Set GRIDSS config - gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config + gridss_config = params.gridss_config !== null ? file(params.gridss_config) : hmf_data.gridss_config // // MODULE: Run Isofox to analyse RNA data @@ -113,6 +113,7 @@ workflow TARGETED { isofox_counts = params.isofox_counts ? file(params.isofox_counts) : panel_data.isofox_counts isofox_gc_ratios = params.isofox_gc_ratios ? file(params.isofox_gc_ratios) : panel_data.isofox_gc_ratios + isofox_read_length = params.isofox_read_length !== null ? params.isofox_read_length : Constants.DEFAULT_ISOFOX_READ_LENGTH_TARGETED isofox_gene_ids = params.isofox_gene_ids ? file(params.isofox_gene_ids) : panel_data.isofox_gene_ids isofox_tpm_norm = params.isofox_tpm_norm ? file(params.isofox_tpm_norm) : panel_data.isofox_tpm_norm @@ -128,7 +129,7 @@ workflow TARGETED { isofox_gene_ids, isofox_tpm_norm, params.isofox_functions, - params.isofox_read_length, + isofox_read_length, ) ch_versions = ch_versions.mix(ISOFOX_QUANTIFICATION.out.versions) @@ -521,7 +522,7 @@ workflow TARGETED { if (run_config.stages.lilac) { // Set HLA slice BED if provided in params - ref_data_hla_slice_bed = params.containsKey('hla_slice_bed') ? params.hla_slice_bed : [] + ref_data_hla_slice_bed = params.ref_data.containsKey('hla_slice_bed') ? params.ref_data.hla_slice_bed : [] LILAC_CALLING( ch_inputs, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 65c9188c..eaedf1e7 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -26,7 +26,7 @@ def checkPathParamList = [ // Conditional requirements if (run_config.stages.gridss) { - if (params.containsKey('gridss_config')) { + if (params.gridss_config !== null) { checkPathParamList.add(params.gridss_config) } } @@ -37,8 +37,8 @@ if (run_config.stages.virusinterpreter && run_config.mode !== Constants.RunMode. } if (run_config.stages.lilac) { - if (params.genome_version == '38' && params.genome_type == 'alt' && params.containsKey('hla_slice_bed')) { - checkPathParamList.add(params.hla_slice_bed) + if (params.ref_data.genome_version == '38' && params.ref_data.genome_type == 'alt' && params.ref_data.containsKey('hla_slice_bed')) { + checkPathParamList.add(params.ref_data.hla_slice_bed) } } @@ -106,7 +106,7 @@ workflow WGTS { hmf_data = PREPARE_REFERENCE.out.hmf_data // Set GRIDSS config - gridss_config = params.containsKey('gridss_config') ? file(params.gridss_config) : hmf_data.gridss_config + gridss_config = params.gridss_config !== null ? file(params.gridss_config) : hmf_data.gridss_config // // MODULE: Run Isofox to analyse RNA data @@ -117,6 +117,7 @@ workflow WGTS { isofox_counts = params.isofox_counts ? file(params.isofox_counts) : hmf_data.isofox_counts isofox_gc_ratios = params.isofox_gc_ratios ? file(params.isofox_gc_ratios) : hmf_data.isofox_gc_ratios + isofox_read_length = params.isofox_read_length !== null ? params.isofox_read_length : Constants.DEFAULT_ISOFOX_READ_LENGTH_WTS ISOFOX_QUANTIFICATION( ch_inputs, @@ -129,7 +130,7 @@ workflow WGTS { [], // isofox_gene_ids [], // isofox_tpm_norm params.isofox_functions, - params.isofox_read_length, + isofox_read_length, ) ch_versions = ch_versions.mix(ISOFOX_QUANTIFICATION.out.versions) @@ -568,7 +569,7 @@ workflow WGTS { if (run_config.stages.lilac) { // Use HLA slice BED if provided in params or set as default requirement - ref_data_hla_slice_bed = params.containsKey('hla_slice_bed') ? params.hla_slice_bed : [] + ref_data_hla_slice_bed = params.ref_data.containsKey('hla_slice_bed') ? params.ref_data.hla_slice_bed : [] LILAC_CALLING( ch_inputs, From 94fa17a8a75668658edf08d39cd22314c2fbdafe Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 15:47:06 +1100 Subject: [PATCH 390/562] Fix creation of stub placeholders --- lib/Utils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 268837f8..087888b8 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -145,7 +145,7 @@ class Utils { fps << "${params.hmf_data_path.replaceAll('/$', '')}/${v}" } - if(params.containsKey('panel')) { + if(params.panel !== null) { params.panel_data_paths[params.panel][params.ref_data.genome_version] .each { k, v -> fps << "${params.panel_data_path.replaceAll('/$', '')}/${v}" From d6a213493938e53f05e4cd5f3a367604c07bcb37 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 15:47:30 +1100 Subject: [PATCH 391/562] Change ordering of HMF data config loading --- nextflow.config | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/nextflow.config b/nextflow.config index 1e1d1b3b..a41f0154 100644 --- a/nextflow.config +++ b/nextflow.config @@ -86,6 +86,16 @@ params { // Load base.config by default for all pipelines includeConfig 'conf/base.config' +// Load data configs +includeConfig 'conf/hmf_data.config' +includeConfig 'conf/hmf_genomes.config' +includeConfig 'conf/panel_data.config' + +// Load panel configuration if needed +if (params.containsKey('mode') && params.mode == 'targeted') { + includeConfig 'conf/targeted_parameters.config' +} + // Load nf-core custom profiles from different Institutions try { includeConfig "${params.custom_config_base}/nfcore_custom.config" @@ -216,16 +226,6 @@ if (!params.igenomes_ignore) { params.genomes = [:] } -// Load data configs -includeConfig 'conf/hmf_data.config' -includeConfig 'conf/hmf_genomes.config' -includeConfig 'conf/panel_data.config' - -// Load panel configuration if needed -if (params.containsKey('mode') && params.mode == 'targeted') { - includeConfig 'conf/targeted_parameters.config' -} - // 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. From 2838170161aae0c74b588df009cc88c3ba5db6ac Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 15:51:49 +1100 Subject: [PATCH 392/562] Add test_stub profile --- conf/test_stub.config | 54 +++++++++++++++++++++++++++++++++++++++++++ nextflow.config | 1 + 2 files changed, 55 insertions(+) create mode 100644 conf/test_stub.config diff --git a/conf/test_stub.config b/conf/test_stub.config new file mode 100644 index 00000000..a19120f3 --- /dev/null +++ b/conf/test_stub.config @@ -0,0 +1,54 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running stub tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a fast and simple pipeline test. + + Use as follows: + nextflow run nf-core/oncoanalyser -profile test, --outdir + +---------------------------------------------------------------------------------------- +*/ + +params { + config_profile_name = 'Stub test profile' + config_profile_description = 'Stub test dataset to check pipeline function' + + // Defined here to be accessible within a workflow script; downloaded manually prior to process + // execution. + validationSchemaIgnoreParams = 'genomes,hmf_data_paths,panel_data_paths' + + // Limit resources so that this can run on GitHub Actions + max_cpus = 1 + max_memory = '8.GB' + max_time = '6.h' + + // Input data + input = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/other/samplesheet.colo829_mini.dna_rna.grch38_hmf.stub.csv' + + // Reference data + genomes { + + 'GRCh38_hmf' { + fasta = "temp/GRCh38.fasta" + fai = "temp/GRCh38.fai" + dict = "temp/GRCh38.dict" + bwa_index = "temp/GRCh38_bwa/" + bwa_index_image = "temp/GRCh38.img" + bwa_index_bseq = "temp/GRCh38.fasta.0123" + bwa_index_biidx = "temp/GRCh38.fasta.bwt.2bit.64" + gridss_index = "temp/GRCh38.gridsscache" + star_index = "temp/GRCh38_star_index/" + } + + } + + virusbreakenddb_path = "temp/virusbreakenddb_20210401/" + hmf_data_path = "temp/hmf_bundle_38/" + panel_data_path = "temp/panel_bundle/tso500_38/" + + // Analysis config + mode = 'wgts' + genome = 'GRCh38_hmf' + create_stub_placeholders = true +} diff --git a/nextflow.config b/nextflow.config index a41f0154..4c9c3afd 100644 --- a/nextflow.config +++ b/nextflow.config @@ -204,6 +204,7 @@ profiles { } test { includeConfig 'conf/test.config' } test_full { includeConfig 'conf/test_full.config' } + test_stub { includeConfig 'conf/test_stub.config' } } // Set default registry for Apptainer, Docker, Podman and Singularity independent of -profile From 23f53ab04105913b1db45409f8b5bbadbd822ff6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 15:52:21 +1100 Subject: [PATCH 393/562] Run only stubs in CI job GHA executing instances do not have sufficient space to run the COLO829_mini test. --- .github/workflows/ci.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38a7b6ac..ea5db625 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,9 +38,6 @@ jobs: - name: Disk space cleanup uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - name: Run pipeline with test data - # TODO nf-core: You can customise CI pipeline run tests as required - # For example: adding multiple test runs with different parameters - # Remember that you can parallelise this by using strategy.matrix + - name: Run pipeline stubs only run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,docker --outdir ./results + nextflow run ${GITHUB_WORKSPACE} -stub -profile test_stub --outdir ./results From f76f79b1fe5a52c92ce73e2fa17e674e55b57b7c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 16 Mar 2024 17:24:28 +1100 Subject: [PATCH 394/562] Correct prepare reference panel data path lookup --- subworkflows/local/prepare_reference/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 54616930..b6e509a2 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -141,7 +141,7 @@ workflow PREPARE_REFERENCE { // NOTE(SW): consider approach to implement custom panel support - panel_data_paths_versions = params.ref_data.panel_data_paths[params.panel] + panel_data_paths_versions = params.panel_data_paths[params.panel] panel_data_paths = panel_data_paths_versions[params.ref_data.genome_version] if (params.ref_data.panel_data_path.endsWith('tar.gz')) { From 9b012d0558ba54170bdb82e5bdd393d3db5d7205 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 16 Mar 2024 18:10:53 +1100 Subject: [PATCH 395/562] Fix optional channel placeholders --- workflows/wgts.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index bd3c6edf..832988d9 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -178,7 +178,7 @@ workflow WGTS { } else { - ch_process_dna_normal_out = ch_inputs.map + ch_process_dna_tumor_out = ch_inputs.map { meta -> [meta, []] } ch_process_dna_normal_out = ch_inputs.map { meta -> [meta, []] } } @@ -679,7 +679,7 @@ workflow WGTS { } else { - ch_lilac_out = ch_inputes.map { meta -> [meta, []] } + ch_lilac_out = ch_inputs.map { meta -> [meta, []] } } From b90c572ad740e60bbadeccdfc7b006675ba4d322 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 16 Mar 2024 18:26:02 +1100 Subject: [PATCH 396/562] Update modules.json --- modules.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules.json b/modules.json index 13432f4a..44d7fd99 100644 --- a/modules.json +++ b/modules.json @@ -10,6 +10,11 @@ "git_sha": "90aef30f432332bdf0ce9f4b9004aa5d5c4960bb", "installed_by": ["modules"] }, + "gatk4/markduplicates": { + "branch": "master", + "git_sha": "e726b1730dff525bde4a6839e544dabfea4cd7fd", + "installed_by": ["modules"] + }, "samtools/dict": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", @@ -24,6 +29,11 @@ "branch": "master", "git_sha": "bbb99cb8d679555cc01c98766de7869f83283545", "installed_by": ["modules"] + }, + "samtools/sort": { + "branch": "master", + "git_sha": "d5d785b3d8b422cda9c6d84a23f629a8e9ff8cd8", + "installed_by": ["modules"] } } }, From 77b8bce2b86533b9ea2062f372261ed8b0b64c49 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 16 Mar 2024 18:32:37 +1100 Subject: [PATCH 397/562] Adjust indenting --- modules/local/bwa-mem2/mem/Dockerfile | 16 ++++---- subworkflows/local/read_alignment_dna/main.nf | 38 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/modules/local/bwa-mem2/mem/Dockerfile b/modules/local/bwa-mem2/mem/Dockerfile index 0a0bc7ea..ba36b89b 100644 --- a/modules/local/bwa-mem2/mem/Dockerfile +++ b/modules/local/bwa-mem2/mem/Dockerfile @@ -3,17 +3,17 @@ FROM docker.io/mambaorg/micromamba:1.5.6 USER root RUN \ - apt-get update && \ - apt-get install -y procps && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* + apt-get update && \ + apt-get install -y procps && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* USER mambauser RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'bwa-mem2 ==2.2.1' \ - 'sambamba ==1.0' && \ - micromamba clean --all --yes + micromamba install -y -n base -c bioconda -c conda-forge \ + 'bwa-mem2 ==2.2.1' \ + 'sambamba ==1.0' && \ + micromamba clean --all --yes ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/subworkflows/local/read_alignment_dna/main.nf b/subworkflows/local/read_alignment_dna/main.nf index 0fb9f21a..e5fd7590 100644 --- a/subworkflows/local/read_alignment_dna/main.nf +++ b/subworkflows/local/read_alignment_dna/main.nf @@ -81,29 +81,29 @@ workflow READ_ALIGNMENT_DNA { // Prepare outputs within conditional block ch_fastqs_ready = FASTP.out.fastq - .flatMap { meta_fastq, reads_fwd, reads_rev -> + .flatMap { meta_fastq, reads_fwd, reads_rev -> - def data = [reads_fwd, reads_rev] - .transpose() - .collect { fwd, rev -> + def data = [reads_fwd, reads_rev] + .transpose() + .collect { fwd, rev -> - def split_fwd = fwd.name.replaceAll('\\..+$', '') - def split_rev = rev.name.replaceAll('\\..+$', '') + def split_fwd = fwd.name.replaceAll('\\..+$', '') + def split_rev = rev.name.replaceAll('\\..+$', '') - assert split_fwd == split_rev + assert split_fwd == split_rev - // NOTE(SW): split allows meta_fastq_ready to be unique, which is required during reunite below - def meta_fastq_ready = [ - *:meta_fastq, - id: "${meta_fastq.id}_${split_fwd}", - split: split_fwd, - ] + // NOTE(SW): split allows meta_fastq_ready to be unique, which is required during reunite below + def meta_fastq_ready = [ + *:meta_fastq, + id: "${meta_fastq.id}_${split_fwd}", + split: split_fwd, + ] - return [meta_fastq_ready, fwd, rev] - } + return [meta_fastq_ready, fwd, rev] + } - return data - } + return data + } } else { @@ -111,8 +111,8 @@ workflow READ_ALIGNMENT_DNA { .map { meta_fastq, fastq_fwd, fastq_rev -> def meta_fastq_ready = [ - *:meta_fastq, - split: null, + *:meta_fastq, + split: null, ] return [meta_fastq_ready, fastq_fwd, fastq_rev] From bd6b304f841147875927467217b7cd1d35962be1 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 19 Mar 2024 09:48:40 +1100 Subject: [PATCH 398/562] Use standard container directive format for STAR --- modules/local/star/main.nf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/local/star/main.nf b/modules/local/star/main.nf index b58868ca..a211d9a7 100644 --- a/modules/local/star/main.nf +++ b/modules/local/star/main.nf @@ -2,7 +2,9 @@ process STAR { tag "${meta.id}" label 'process_high' - container 'quay.io/biocontainers/star:2.7.3a--0' + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/star:2.7.3a--0' : + 'quay.io/biocontainers/star:2.7.3a--0' }" input: tuple val(meta), path(fastq_fwd), path(fastq_rev) From c7f1774bc667b07db006aa6efee1ccc344b49478 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 19 Mar 2024 09:53:05 +1100 Subject: [PATCH 399/562] Add missing imports and subworkflow descriptions --- subworkflows/local/cuppa_prediction/main.nf | 1 + subworkflows/local/prepare_inputs/main.nf | 1 - subworkflows/local/prepare_reference/main.nf | 2 ++ subworkflows/local/read_alignment_dna/main.nf | 7 +++++++ subworkflows/local/read_alignment_rna/main.nf | 7 +++++++ subworkflows/local/read_processing/main.nf | 7 +++++++ 6 files changed, 24 insertions(+), 1 deletion(-) diff --git a/subworkflows/local/cuppa_prediction/main.nf b/subworkflows/local/cuppa_prediction/main.nf index 40eaae38..2b74a441 100644 --- a/subworkflows/local/cuppa_prediction/main.nf +++ b/subworkflows/local/cuppa_prediction/main.nf @@ -3,6 +3,7 @@ // import Constants +import Utils include { CUPPA } from '../../../modules/local/cuppa/main' diff --git a/subworkflows/local/prepare_inputs/main.nf b/subworkflows/local/prepare_inputs/main.nf index f6e6dfae..18abe8eb 100644 --- a/subworkflows/local/prepare_inputs/main.nf +++ b/subworkflows/local/prepare_inputs/main.nf @@ -8,7 +8,6 @@ // through running workflows/processes with 'setup'. Hence, this subworkflow // isn't used in the main pipeline and is only used for execution of tests. -import Constants import Utils workflow PREPARE_INPUTS { diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index f005623d..405c00a9 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -5,6 +5,8 @@ // NOTE(SW): BWA MEM2 indexes are required and are not created // TODO(SW): consider removing index creation since it's unlikely to be used, replace with documentation +import Constants + include { SAMTOOLS_FAIDX } from '../../../modules/nf-core/samtools/faidx/main' include { SAMTOOLS_DICT } from '../../../modules/nf-core/samtools/dict/main' include { BWA_INDEX } from '../../../modules/nf-core/bwa/index/main' diff --git a/subworkflows/local/read_alignment_dna/main.nf b/subworkflows/local/read_alignment_dna/main.nf index e5fd7590..01c16a56 100644 --- a/subworkflows/local/read_alignment_dna/main.nf +++ b/subworkflows/local/read_alignment_dna/main.nf @@ -1,3 +1,10 @@ +// +// Align DNA reads +// + +import Constants +import Utils + include { BWAMEM2_ALIGN } from '../../../modules/local/bwa-mem2/mem/main' include { FASTP } from '../../../modules/local/fastp/main' include { SAMBAMBA_INDEX } from '../../../modules/local/sambamba/index/main' diff --git a/subworkflows/local/read_alignment_rna/main.nf b/subworkflows/local/read_alignment_rna/main.nf index 61c79ec4..ca795e58 100644 --- a/subworkflows/local/read_alignment_rna/main.nf +++ b/subworkflows/local/read_alignment_rna/main.nf @@ -1,3 +1,10 @@ +// +// Align RNA reads +// + +import Constants +import Utils + include { GATK4_MARKDUPLICATES } from '../../../modules/nf-core/gatk4/markduplicates/main' include { SAMBAMBA_MERGE } from '../../../modules/local/sambamba/merge/main' include { SAMTOOLS_SORT } from '../../../modules/nf-core/samtools/sort/main' diff --git a/subworkflows/local/read_processing/main.nf b/subworkflows/local/read_processing/main.nf index 4d5597fc..2e67d213 100644 --- a/subworkflows/local/read_processing/main.nf +++ b/subworkflows/local/read_processing/main.nf @@ -1,3 +1,10 @@ +// +// Apply post-alignment processing +// + +import Constants +import Utils + include { MARKDUPS } from '../../../modules/local/markdups/main' workflow READ_PROCESSING { From 177bf6946444f27aba6f99e6e0094c97f82e47eb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 19 Mar 2024 18:52:17 +1100 Subject: [PATCH 400/562] Use Bioconda/BioContainers for bwa-mem2 module --- modules/local/bwa-mem2/mem/Dockerfile | 19 ------------------- modules/local/bwa-mem2/mem/environment.yml | 9 +++++++++ modules/local/bwa-mem2/mem/main.nf | 6 ++++-- 3 files changed, 13 insertions(+), 21 deletions(-) delete mode 100644 modules/local/bwa-mem2/mem/Dockerfile create mode 100644 modules/local/bwa-mem2/mem/environment.yml diff --git a/modules/local/bwa-mem2/mem/Dockerfile b/modules/local/bwa-mem2/mem/Dockerfile deleted file mode 100644 index ba36b89b..00000000 --- a/modules/local/bwa-mem2/mem/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM docker.io/mambaorg/micromamba:1.5.6 - -USER root - -RUN \ - apt-get update && \ - apt-get install -y procps && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -USER mambauser - -RUN \ - micromamba install -y -n base -c bioconda -c conda-forge \ - 'bwa-mem2 ==2.2.1' \ - 'sambamba ==1.0' && \ - micromamba clean --all --yes - -ENV PATH="/opt/conda/bin:/opt/conda/condabin:${PATH}" diff --git a/modules/local/bwa-mem2/mem/environment.yml b/modules/local/bwa-mem2/mem/environment.yml new file mode 100644 index 00000000..571dda57 --- /dev/null +++ b/modules/local/bwa-mem2/mem/environment.yml @@ -0,0 +1,9 @@ +name: bwa-mem2_mem +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::bwa-mem2=2.2.1 + - bioconda::samtools=1.19.2 + - bioconda::sambamba=1.0 diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index 2ae102b6..961791eb 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -2,8 +2,10 @@ process BWAMEM2_ALIGN { tag "${meta.id}" label 'process_high' - // TODO(SW): create BioContainers multi-package image when appropriate - container 'docker.io/scwatts/bwa-mem2:2.2.1' + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' : + 'quay.io/biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" input: tuple val(meta), path(reads_fwd), path(reads_rev) From 5c15bfa230414b4e3276ad5647f12395ac445677 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 26 Mar 2024 10:11:09 +1100 Subject: [PATCH 401/562] Use fixed GRIDSS container for VIRUSBreakend The BioContainers Docker image only provides BusyBox grep, which has poor performance compared to GNU grep and increases runtime by up to an hour. The current Bioconda CI infrastructure is unable to build a patched GRIDSS image at the moment, so I've made a temporary fix here instead to restore expected performance. --- modules/local/virusbreakend/Dockerfile | 43 ++++++++++++++++++++++++++ modules/local/virusbreakend/main.nf | 4 +-- 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 modules/local/virusbreakend/Dockerfile diff --git a/modules/local/virusbreakend/Dockerfile b/modules/local/virusbreakend/Dockerfile new file mode 100644 index 00000000..50fb19ff --- /dev/null +++ b/modules/local/virusbreakend/Dockerfile @@ -0,0 +1,43 @@ +FROM continuumio/miniconda3:23.5.2-0-alpine as build + +RUN \ + conda install conda-libmamba-solver + +RUN \ + echo -e > ~/.condarc '\ +solver: libmamba\n\ +channels:\n\ + - conda-forge\n\ + - bioconda\n\ + - defaults' + +RUN \ + conda create -y -p /env/ \ + 'gridss=2.13.2=h50ea8bc_3' \ + 'bash' \ + 'coreutils' \ + 'findutils' \ + 'gawk' \ + 'grep' \ + 'procps-ng' \ + 'time' \ + 'util-linux' \ + 'which' + +RUN \ + conda clean -yaf + +# Move Conda environment into distroless image +FROM gcr.io/distroless/base-debian11:latest + +COPY --from=build /env/ /env/ + +ENV PATH="/env/bin:${PATH}" +ENV LD_LIBRARY_PATH="/env/lib/:${LD_LIBRARY_PATH}" + +# Symlink system executables as required by VIRUSBreaked +SHELL ["/env/bin/bash", "-c"] +RUN \ + ln -s /env/bin/bash /bin/bash && \ + ln -s /env/bin/env /usr/bin/env && \ + ln -s /env/bin/time /usr/bin/time diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 64195c3c..9284e757 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -6,8 +6,8 @@ process VIRUSBREAKEND { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/gridss:2.13.2--h50ea8bc_3': - 'quay.io/biocontainers/gridss:2.13.2--h50ea8bc_3' }" + 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/singularity/gridss:2.13.2--0' : + 'quay.io/nf-core/gridss:2.13.2--0' }" input: tuple val(meta), path(bam) From a2c6921fe7ee3d7b1f4ee100b5924878a8f996c0 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 26 Mar 2024 12:41:04 +1100 Subject: [PATCH 402/562] Apply linting --- modules/local/virusbreakend/Dockerfile | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/modules/local/virusbreakend/Dockerfile b/modules/local/virusbreakend/Dockerfile index 50fb19ff..f3a41abb 100644 --- a/modules/local/virusbreakend/Dockerfile +++ b/modules/local/virusbreakend/Dockerfile @@ -1,31 +1,31 @@ FROM continuumio/miniconda3:23.5.2-0-alpine as build RUN \ - conda install conda-libmamba-solver + conda install conda-libmamba-solver RUN \ - echo -e > ~/.condarc '\ + echo -e > ~/.condarc '\ solver: libmamba\n\ channels:\n\ - - conda-forge\n\ - - bioconda\n\ - - defaults' + - conda-forge\n\ + - bioconda\n\ + - defaults' RUN \ - conda create -y -p /env/ \ - 'gridss=2.13.2=h50ea8bc_3' \ - 'bash' \ - 'coreutils' \ - 'findutils' \ - 'gawk' \ - 'grep' \ - 'procps-ng' \ - 'time' \ - 'util-linux' \ - 'which' + conda create -y -p /env/ \ + 'gridss=2.13.2=h50ea8bc_3' \ + 'bash' \ + 'coreutils' \ + 'findutils' \ + 'gawk' \ + 'grep' \ + 'procps-ng' \ + 'time' \ + 'util-linux' \ + 'which' RUN \ - conda clean -yaf + conda clean -yaf # Move Conda environment into distroless image FROM gcr.io/distroless/base-debian11:latest @@ -38,6 +38,6 @@ ENV LD_LIBRARY_PATH="/env/lib/:${LD_LIBRARY_PATH}" # Symlink system executables as required by VIRUSBreaked SHELL ["/env/bin/bash", "-c"] RUN \ - ln -s /env/bin/bash /bin/bash && \ - ln -s /env/bin/env /usr/bin/env && \ - ln -s /env/bin/time /usr/bin/time + ln -s /env/bin/bash /bin/bash && \ + ln -s /env/bin/env /usr/bin/env && \ + ln -s /env/bin/time /usr/bin/time From 4e4a6994c585609129ee61a53ab1a343cd49993a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 26 Mar 2024 19:37:53 +1100 Subject: [PATCH 403/562] Use standard BioContainers base for VIRUSBreakend Having distroless as the base Docker image for the VIRUSBreakend container was causing RepeatMasker to crash without an error/traceback when executing a system process. Switching to `quay.io/bioconda/base-glibc-busybox-bash:2.1.0` (the standard BioContainers base image) resolves the problem. --- modules/local/virusbreakend/Dockerfile | 27 +++++++++----------------- modules/local/virusbreakend/main.nf | 4 ++-- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/modules/local/virusbreakend/Dockerfile b/modules/local/virusbreakend/Dockerfile index f3a41abb..2d0742d8 100644 --- a/modules/local/virusbreakend/Dockerfile +++ b/modules/local/virusbreakend/Dockerfile @@ -14,30 +14,21 @@ channels:\n\ RUN \ conda create -y -p /env/ \ 'gridss=2.13.2=h50ea8bc_3' \ - 'bash' \ - 'coreutils' \ - 'findutils' \ - 'gawk' \ - 'grep' \ - 'procps-ng' \ - 'time' \ - 'util-linux' \ - 'which' + 'grep' + +# Install Dfam database required for RepeatMasker +RUN \ + conda install -y curl && \ + curl -s https://www.dfam.org/releases/Dfam_3.7/families/Dfam_curatedonly.h5.gz | \ + gzip -cd > /env/share/RepeatMasker/Libraries/Dfam.h5 RUN \ conda clean -yaf -# Move Conda environment into distroless image -FROM gcr.io/distroless/base-debian11:latest +# Move Conda environment into standard BioContainers base image +FROM quay.io/bioconda/base-glibc-busybox-bash:2.1.0 COPY --from=build /env/ /env/ ENV PATH="/env/bin:${PATH}" ENV LD_LIBRARY_PATH="/env/lib/:${LD_LIBRARY_PATH}" - -# Symlink system executables as required by VIRUSBreaked -SHELL ["/env/bin/bash", "-c"] -RUN \ - ln -s /env/bin/bash /bin/bash && \ - ln -s /env/bin/env /usr/bin/env && \ - ln -s /env/bin/time /usr/bin/time diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 9284e757..8302a974 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -6,8 +6,8 @@ process VIRUSBREAKEND { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/singularity/gridss:2.13.2--0' : - 'quay.io/nf-core/gridss:2.13.2--0' }" + 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/singularity/gridss:2.13.2--1' : + 'quay.io/nf-core/gridss:2.13.2--1' }" input: tuple val(meta), path(bam) From f4703e5f7d8381b21c1e4bc4ae1c1b1fde4d9cc4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 26 Mar 2024 20:34:14 +1100 Subject: [PATCH 404/562] Lint modules/local/virusbreakend/Dockerfile --- modules/local/virusbreakend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/virusbreakend/Dockerfile b/modules/local/virusbreakend/Dockerfile index 2d0742d8..f8cc9d06 100644 --- a/modules/local/virusbreakend/Dockerfile +++ b/modules/local/virusbreakend/Dockerfile @@ -20,7 +20,7 @@ RUN \ RUN \ conda install -y curl && \ curl -s https://www.dfam.org/releases/Dfam_3.7/families/Dfam_curatedonly.h5.gz | \ - gzip -cd > /env/share/RepeatMasker/Libraries/Dfam.h5 + gzip -cd > /env/share/RepeatMasker/Libraries/Dfam.h5 RUN \ conda clean -yaf From 9d61690a51cc8c2a4a476766e9a1eb03382764ef Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 27 Mar 2024 16:28:42 +1100 Subject: [PATCH 405/562] Improve naming for bwa-mem2 output BAMs --- modules/local/bwa-mem2/mem/main.nf | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index 961791eb..14c9daf9 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -23,6 +23,7 @@ process BWAMEM2_ALIGN { script: def read_group_tag = "@RG\\tID:${meta.read_group}\\tSM:${meta.sample_id}" + def output_fn = meta.split ? "${meta.split}.${meta.sample_id}.${meta.read_group}.bam" : "${meta.sample_id}.${meta.read_group}.bam" """ ln -fs \$(find -L ${genome_bwa_index} -type f) ./ @@ -44,7 +45,7 @@ process BWAMEM2_ALIGN { \\ sambamba sort \\ --nthreads ${task.cpus} \\ - --out ${meta.split}.${meta.sample_id}.${meta.read_group}.bam \\ + --out ${output_fn} \\ /dev/stdin cat <<-END_VERSIONS > versions.yml @@ -55,8 +56,10 @@ process BWAMEM2_ALIGN { """ stub: + def output_fn = meta.split ? "${meta.split}.${meta.sample_id}.${meta.read_group}.bam" : "${meta.sample_id}.${meta.read_group}.bam" + """ - touch ${meta.split}.${meta.sample_id}.${meta.read_group}.bam + touch ${output_fn} echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ From 7adfda2df4bb5e920b8902a8857cf628e5acdcfb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 3 Apr 2024 20:23:46 +1100 Subject: [PATCH 406/562] Apply @maxulysse recommendations Co-authored-by: Maxime U Garcia --- modules/local/virusbreakend/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 8302a974..b20c3492 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -6,8 +6,8 @@ process VIRUSBREAKEND { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/singularity/gridss:2.13.2--1' : - 'quay.io/nf-core/gridss:2.13.2--1' }" + 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/singularity/gridss:2.13.2--1': + 'nf-core/gridss:2.13.2--1' }" input: tuple val(meta), path(bam) From ae86ba99c6d3400f0597905fd3819ad2af8cd2d4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 3 Apr 2024 23:24:11 +1100 Subject: [PATCH 407/562] Update VIRUSBreakend process container directive --- modules/local/virusbreakend/main.nf | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index b20c3492..67b1a76e 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -5,9 +5,7 @@ process VIRUSBREAKEND { label 'process_high' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/singularity/gridss:2.13.2--1': - 'nf-core/gridss:2.13.2--1' }" + container "quay.io/nf-core/gridss:2.13.2--1" input: tuple val(meta), path(bam) From 7432c5527eb2fe22fa202e137c6103f53d9c8d8b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 3 Apr 2024 23:34:06 +1100 Subject: [PATCH 408/562] Do not qualify nf-core quay.io Docker URI --- modules/local/virusbreakend/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 67b1a76e..da93d763 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -5,7 +5,7 @@ process VIRUSBREAKEND { label 'process_high' conda "${moduleDir}/environment.yml" - container "quay.io/nf-core/gridss:2.13.2--1" + container "nf-core/gridss:2.13.2--1" input: tuple val(meta), path(bam) From 066c8d29b12b0e853f9ff979cfcab1528f4f855f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 15 Apr 2024 15:16:11 +1000 Subject: [PATCH 409/562] Use BAM index created during alignment --- modules/local/bwa-mem2/mem/main.nf | 4 +-- modules/local/sambamba/index/main.nf | 35 ------------------- subworkflows/local/read_alignment_dna/main.nf | 20 +---------- 3 files changed, 3 insertions(+), 56 deletions(-) diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index 14c9daf9..99e60d10 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -15,8 +15,8 @@ process BWAMEM2_ALIGN { path genome_bwa_index_biidx output: - tuple val(meta), path('*.bam'), emit: bam - path 'versions.yml' , emit: versions + tuple val(meta), path('*.bam'), path('*.bai'), emit: bam + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf index 56bb38af..e69de29b 100644 --- a/modules/local/sambamba/index/main.nf +++ b/modules/local/sambamba/index/main.nf @@ -1,35 +0,0 @@ -process SAMBAMBA_INDEX { - tag "${meta.id}" - - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/sambamba:1.0--h98b6b92_0' : - 'quay.io/biocontainers/sambamba:1.0--h98b6b92_0' }" - - input: - tuple val(meta), path(bam) - - output: - tuple val(meta), path('*bai'), emit: bai - path 'versions.yml' , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - """ - sambamba index \\ - --nthreads ${task.cpus} \\ - ${bam} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - sambamba: \$(sambamba --version 2>&1 | egrep '^sambamba' | head -n 1 | awk '{ print \$NF }') - END_VERSIONS - """ - - stub: - """ - touch ${bam}.bai - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml - """ -} diff --git a/subworkflows/local/read_alignment_dna/main.nf b/subworkflows/local/read_alignment_dna/main.nf index 01c16a56..fb0aaab4 100644 --- a/subworkflows/local/read_alignment_dna/main.nf +++ b/subworkflows/local/read_alignment_dna/main.nf @@ -7,7 +7,6 @@ import Utils include { BWAMEM2_ALIGN } from '../../../modules/local/bwa-mem2/mem/main' include { FASTP } from '../../../modules/local/fastp/main' -include { SAMBAMBA_INDEX } from '../../../modules/local/sambamba/index/main' workflow READ_ALIGNMENT_DNA { take: @@ -159,23 +158,6 @@ workflow READ_ALIGNMENT_DNA { ch_versions = ch_versions.mix(BWAMEM2_ALIGN.out.versions) - // - // MODULE: Sambamba index - // - SAMBAMBA_INDEX( - BWAMEM2_ALIGN.out.bam, - ) - - ch_versions = ch_versions.mix(SAMBAMBA_INDEX.out.versions) - - // Combine BAMs and BAIs - // channel: [ meta_bwa, sample_type, bam, bai ] - ch_bams_flat = WorkflowOncoanalyser.groupByMeta( - BWAMEM2_ALIGN.out.bam.map { meta_bwa, bam -> [meta_bwa, meta_bwa.sample_type] }, - BWAMEM2_ALIGN.out.bam, - SAMBAMBA_INDEX.out.bai, - ) - // Reunite BAMs // First, count expected BAMs per sample for non-blocking groupTuple op // channel: [ meta_count, group_size ] @@ -197,7 +179,7 @@ workflow READ_ALIGNMENT_DNA { ch_bams_united = ch_sample_fastq_counts .cross( // First element to match meta_count above for `cross` - ch_bams_flat.map { meta_bwa, sample_type, bam, bai -> [[key: meta_bwa.key, sample_type: sample_type], bam, bai] } + BWAMEM2_ALIGN.out.bam.map { meta_bwa, bam, bai -> [[key: meta_bwa.key, sample_type: meta_bwa.sample_type], bam, bai] } ) .map { count_tuple, bam_tuple -> From 0abc35f5a74f8d1b5ca7d46ce57741d64724a448 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 22 Apr 2024 11:09:23 +1000 Subject: [PATCH 410/562] Improve BAM index selection --- subworkflows/local/amber_profiling/main.nf | 4 ++-- subworkflows/local/bamtools_metrics/main.nf | 4 ++-- subworkflows/local/cobalt_profiling/main.nf | 4 ++-- subworkflows/local/flagstat_metrics/main.nf | 4 ++-- subworkflows/local/gridss_svprep_calling/main.nf | 4 ++-- subworkflows/local/lilac_calling/main.nf | 4 ++-- subworkflows/local/sage_calling/main.nf | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/subworkflows/local/amber_profiling/main.nf b/subworkflows/local/amber_profiling/main.nf index fe81787e..a4cb59f0 100644 --- a/subworkflows/local/amber_profiling/main.nf +++ b/subworkflows/local/amber_profiling/main.nf @@ -35,9 +35,9 @@ workflow AMBER_PROFILING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), + tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_DNA_NORMAL), + normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> diff --git a/subworkflows/local/bamtools_metrics/main.nf b/subworkflows/local/bamtools_metrics/main.nf index 2e3db8ec..e71ca2bb 100644 --- a/subworkflows/local/bamtools_metrics/main.nf +++ b/subworkflows/local/bamtools_metrics/main.nf @@ -31,7 +31,7 @@ workflow BAMTOOLS_METRICS { return [ meta, Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_DNA_TUMOR), + bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), ] } .branch { meta, bam, bai -> @@ -48,7 +48,7 @@ workflow BAMTOOLS_METRICS { return [ meta, Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_DNA_NORMAL), + bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, bam, bai -> diff --git a/subworkflows/local/cobalt_profiling/main.nf b/subworkflows/local/cobalt_profiling/main.nf index 6fb82561..13102dee 100644 --- a/subworkflows/local/cobalt_profiling/main.nf +++ b/subworkflows/local/cobalt_profiling/main.nf @@ -36,9 +36,9 @@ workflow COBALT_PROFILING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), + tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_DNA_NORMAL), + normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> diff --git a/subworkflows/local/flagstat_metrics/main.nf b/subworkflows/local/flagstat_metrics/main.nf index 668088dd..9f0a5f78 100644 --- a/subworkflows/local/flagstat_metrics/main.nf +++ b/subworkflows/local/flagstat_metrics/main.nf @@ -27,7 +27,7 @@ workflow FLAGSTAT_METRICS { return [ meta, Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_DNA_TUMOR), + bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), ] } .branch { meta, bam, bai -> @@ -44,7 +44,7 @@ workflow FLAGSTAT_METRICS { return [ meta, Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(bai, meta, Constants.INPUT.BAI_DNA_NORMAL), + bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, bam, bai -> diff --git a/subworkflows/local/gridss_svprep_calling/main.nf b/subworkflows/local/gridss_svprep_calling/main.nf index 23521059..48333057 100644 --- a/subworkflows/local/gridss_svprep_calling/main.nf +++ b/subworkflows/local/gridss_svprep_calling/main.nf @@ -52,9 +52,9 @@ workflow GRIDSS_SVPREP_CALLING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), + tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_DNA_NORMAL), + normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> diff --git a/subworkflows/local/lilac_calling/main.nf b/subworkflows/local/lilac_calling/main.nf index e40cd692..3110cc97 100644 --- a/subworkflows/local/lilac_calling/main.nf +++ b/subworkflows/local/lilac_calling/main.nf @@ -42,9 +42,9 @@ workflow LILAC_CALLING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), + tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_DNA_NORMAL), + normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> diff --git a/subworkflows/local/sage_calling/main.nf b/subworkflows/local/sage_calling/main.nf index 156c631b..33d815d0 100644 --- a/subworkflows/local/sage_calling/main.nf +++ b/subworkflows/local/sage_calling/main.nf @@ -45,9 +45,9 @@ workflow SAGE_CALLING { return [ meta, Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), + tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - Utils.selectCurrentOrExisting(normal_bai, meta, Constants.INPUT.BAI_DNA_NORMAL), + normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), ] } .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> From eb95b4f44abce9aeeb8b102e3f4253c55c5f2c3a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 22 Apr 2024 11:12:55 +1000 Subject: [PATCH 411/562] Include BAI in bwa-mem2/align stub --- modules/local/bwa-mem2/mem/main.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index 99e60d10..603f989d 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -60,6 +60,7 @@ process BWAMEM2_ALIGN { """ touch ${output_fn} + touch ${output_fn}.bai echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ From 4039507120d461fdb45884285be8e4fc66e35ad3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 22 Apr 2024 11:35:49 +1000 Subject: [PATCH 412/562] Adjust input selection logic --- lib/Utils.groovy | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index b785aa3a..7604a344 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -483,18 +483,20 @@ class Utils { // Misc public static getInput(meta, key) { - def result + def result = [] def (key_filetype, key_filetypes, key_sequencetypes) = key for (key_sample in [key_filetypes, key_sequencetypes].combinations()) { if (meta.containsKey(key_sample) && meta[key_sample].containsKey(key_filetype)) { - return meta[key_sample].getAt(key_filetype) + result = meta[key_sample].get(key_filetype) + break } } + return result } public static hasExistingInput(meta, key) { - return getInput(meta, key) !== null + return getInput(meta, key) != [] } public static selectCurrentOrExisting(val, meta, key) { From e8f6c99cbd9d8d982cddf2a627db63fac48d2ed3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 23 Apr 2024 11:26:00 +1000 Subject: [PATCH 413/562] Bump MarkDups to 1.1.5 --- modules/local/markdups/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index e9f17f5d..d4d0f443 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -3,8 +3,8 @@ process MARKDUPS { label 'process_medium' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.2--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-mark-dups:1.1.2--hdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.5--hdfd78af_0' : + 'quay.io/biocontainers/hmftools-mark-dups:1.1.5--hdfd78af_0' }" input: tuple val(meta), path(bams), path(bais) From ed8e1d172a4906291216a27fecd41e42d38921d2 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 23 Apr 2024 15:43:15 +1000 Subject: [PATCH 414/562] Remove Sambamba index module file --- modules/local/sambamba/index/main.nf | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 modules/local/sambamba/index/main.nf diff --git a/modules/local/sambamba/index/main.nf b/modules/local/sambamba/index/main.nf deleted file mode 100644 index e69de29b..00000000 From e0da20af67a2e9453410c6662becd6bb14f6ac72 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 23 Apr 2024 15:45:12 +1000 Subject: [PATCH 415/562] Add new meta.yaml --- modules/local/bwa-mem2/mem/meta.yml | 59 +++++++++++++++++++++++++ modules/local/fastp/meta.yml | 47 ++++++++++++++++++++ modules/local/markdups/meta.yml | 62 +++++++++++++++++++++++++++ modules/local/sambamba/merge/meta.yml | 38 ++++++++++++++++ modules/local/star/main.nf | 4 +- modules/local/star/meta.yml | 46 ++++++++++++++++++++ 6 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 modules/local/bwa-mem2/mem/meta.yml create mode 100644 modules/local/fastp/meta.yml create mode 100644 modules/local/markdups/meta.yml create mode 100644 modules/local/sambamba/merge/meta.yml create mode 100644 modules/local/star/meta.yml diff --git a/modules/local/bwa-mem2/mem/meta.yml b/modules/local/bwa-mem2/mem/meta.yml new file mode 100644 index 00000000..f8fb56b3 --- /dev/null +++ b/modules/local/bwa-mem2/mem/meta.yml @@ -0,0 +1,59 @@ +name: bwa-mem2_mem +description: The mem alignment algorithm of bwa-mem2 +keywords: + - bwa + - mem + - read alignment + - bwa-mem2 +tools: + - bwa-mem2: + description: Burrow-Wheeler Aligner for short-read alignment + homepage: https://github.com/bwa-mem2/bwa-mem2 + documentation: https://github.com/bwa-mem2/bwa-mem2 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - reads_fwd: + type: file + description: Forward reads FASTQ file + pattern: "*.{fastq.gz}" + - reads_rev: + type: file + description: Reverse reads FASTQ file + pattern: "*.{fastq.gz}" + - genome_fasta: + type: file + description: Reference genome assembly FASTA file + pattern: "*.{fa,fasta}" + - genome_bwa_index: + type: directory + description: bwa-mem1 index directory + - genome_bwa_index_bseq: + type: directory + description: bwa-mem2 bseq index file + pattern: "*.{0123}" + - genome_bwa_index_biidx: + type: directory + description: bwa-mem2 biidx index file + pattern: "*.{bwt.2bit.64}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - bam: + type: list + description: BAM and BAI file + pattern: "*.{bam,bam.bai}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" + - "@mkcmkc" diff --git a/modules/local/fastp/meta.yml b/modules/local/fastp/meta.yml new file mode 100644 index 00000000..23aa5fb6 --- /dev/null +++ b/modules/local/fastp/meta.yml @@ -0,0 +1,47 @@ +name: fastp +description: An ultra-fast all-in-one FASTQ preprocessor +keywords: + - fastp + - fastq + - processing + - quality control +tools: + - fastp: + description: An ultra-fast all-in-one FASTQ preprocessor + homepage: https://github.com/OpenGene/fastp + documentation: https://github.com/OpenGene/fastp + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - reads_fwd: + type: file + description: Forward reads FASTQ file + pattern: "*.{fastq.gz}" + - reads_rev: + type: file + description: Reverse reads FASTQ file + pattern: "*.{fastq.gz}" + - max_fastq_records: + type: integer + description: Maximum number of reads per file +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - fastq: + type: list + description: Forward and reverse FASTQ files + pattern: "*.{fastq.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" + - "@mkcmkc" diff --git a/modules/local/markdups/meta.yml b/modules/local/markdups/meta.yml new file mode 100644 index 00000000..a9297b68 --- /dev/null +++ b/modules/local/markdups/meta.yml @@ -0,0 +1,62 @@ +name: markdups +description: Identify and mark duplicate reads ifrom alignment data +keywords: + - duplicating marking + - markdups +tools: + - MarkDups: + description: Identify and mark duplicate reads ifrom alignment data + homepage: https://github.com/hartwigmedical/hmftools/tree/master/mark-dups + documentation: https://github.com/hartwigmedical/hmftools/tree/master/mark-dups + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - bams: + type: list + description: List BAM files + - bais: + type: list + description: List BAI files + - genome_fasta: + type: file + description: Reference genome assembly FASTA file + pattern: "*.{fa,fasta}" + - genome_ver: + type: string + description: Reference genome version + - genome_fai: + type: file + description: Reference genome assembly fai file + pattern: "*.{fai}" + - genome_dict: + type: file + description: Reference genome assembly dict file + pattern: "*.{dict}" + - unmap_regions: + type: file + description: Unmapped regions file + pattern: "*.{tsv}" + - has_umis: + type: boolean + description: Flag indicating presence of UMIs in reads +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - bam: + type: list + description: BAM and BAI file + pattern: "*.{bam,bam.bai}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" + - "@mkcmkc" diff --git a/modules/local/sambamba/merge/meta.yml b/modules/local/sambamba/merge/meta.yml new file mode 100644 index 00000000..c4424055 --- /dev/null +++ b/modules/local/sambamba/merge/meta.yml @@ -0,0 +1,38 @@ +name: sambamba_merge +description: Merge several BAM files into one +keywords: + - sambamba + - bam + - merge +tools: + - sambamba: + description: Tools for working with SAM/BAM data + homepage: https://github.com/biod/sambamba + documentation: https://lomereiter.github.io/sambamba/index.html + licence: ["GPL v2"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - bams: + type: list + description: List BAM files +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" + - "@mkcmkc" diff --git a/modules/local/star/main.nf b/modules/local/star/main.nf index a211d9a7..7aa4503f 100644 --- a/modules/local/star/main.nf +++ b/modules/local/star/main.nf @@ -7,7 +7,7 @@ process STAR { 'quay.io/biocontainers/star:2.7.3a--0' }" input: - tuple val(meta), path(fastq_fwd), path(fastq_rev) + tuple val(meta), path(reads_fwd), path(reads_rev) path genome_star_index output: @@ -20,7 +20,7 @@ process STAR { script: """ STAR \\ - --readFilesIn ${fastq_fwd} ${fastq_rev} \\ + --readFilesIn ${reads_fwd} ${reads_rev} \\ --genomeDir ${genome_star_index} \\ --runThreadN ${task.cpus} \\ --readFilesCommand zcat \\ diff --git a/modules/local/star/meta.yml b/modules/local/star/meta.yml new file mode 100644 index 00000000..0bbc3329 --- /dev/null +++ b/modules/local/star/meta.yml @@ -0,0 +1,46 @@ +name: star +description: An ultrafast universal RNA-seq aligner +keywords: + - rna-seq + - rna + - aligner + - star +tools: + - star: + description: An ultrafast universal RNA-seq aligner + homepage: https://github.com/alexdobin/STAR + documentation: https://github.com/alexdobin/STAR/blob/master/doc/STARmanual.pdf + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - reads_fwd: + type: file + description: Forward reads FASTQ file + pattern: "*.{fastq.gz}" + - reads_rev: + type: file + description: Reverse reads FASTQ file + pattern: "*.{fastq.gz}" + - genome_star_index: + type: directory + description: STAR index directory +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [id: 'sample_id', tumor_id: 'tumor_name', normal_id: 'normal_name'] + - bam: + type: file + description: BAM file + pattern: "*.{bam}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@scwatts" From b9823894c607b6e0ee9b1088f179804435148cf4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 24 Apr 2024 15:27:05 +1000 Subject: [PATCH 416/562] Adjust Hartwig genome data URLs --- conf/hmf_genomes.config | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/conf/hmf_genomes.config b/conf/hmf_genomes.config index e067a3a0..383e5f0b 100644 --- a/conf/hmf_genomes.config +++ b/conf/hmf_genomes.config @@ -10,26 +10,26 @@ params { genomes { 'GRCh37_hmf' { - fasta = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/Homo_sapiens.GRCh37.GATK.illumina.fasta" - fai = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" - dict = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" - bwa_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/0.7.17-r1188.tar.gz" - bwa_index_bseq = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.0123" - bwa_index_biidx = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64" - bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" - gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" - star_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh37_hmf/star_index/gencode_19/2.7.3a.tar.gz" + fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/Homo_sapiens.GRCh37.GATK.illumina.fasta" + fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" + dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" + bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/bwa_index/0.7.17-r1188.tar.gz" + bwa_index_bseq = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.0123" + bwa_index_biidx = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64" + bwa_index_image = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" + gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" + star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/star_index/gencode_19/2.7.3a.tar.gz" } 'GRCh38_hmf' { - fasta = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" - fai = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" - dict = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwa_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz" - bwa_index_bseq = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" - bwa_index_biidx = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" - bwa_index_image = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" - gridss_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" - star_index = "https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes/GRCh38_hmf/star_index/gencode_38/2.7.3a.tar.gz" + fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" + fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" + dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" + bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/bwa_index/0.7.17-r1188.tar.gz" + bwa_index_bseq = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" + bwa_index_biidx = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" + bwa_index_image = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" + gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" + star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/star_index/gencode_38/2.7.3a.tar.gz" } } } From 4a42093c0c68314f1badb74349daf3c103254bfa Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 24 Apr 2024 16:49:35 +1000 Subject: [PATCH 417/562] Adjust other reference data URLs --- lib/Constants.groovy | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Constants.groovy b/lib/Constants.groovy index 37c7ac75..cb827975 100644 --- a/lib/Constants.groovy +++ b/lib/Constants.groovy @@ -11,17 +11,17 @@ class Constants { static List PANELS_DEFINED = ['tso500'] - static String HMF_DATA_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_37--2.tar.gz' - static String HMF_DATA_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/hmftools/5.34_38--2.tar.gz' + static String HMF_DATA_37_PATH = 'https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/hmf_reference_data/hmftools/5.34_37--2.tar.gz' + static String HMF_DATA_38_PATH = 'https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/hmf_reference_data/hmftools/5.34_38--2.tar.gz' - static String TSO500_PANEL_37_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_37--1.tar.gz' - static String TSO500_PANEL_38_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/hmf_reference_data/panels/tso500_5.34_38--1.tar.gz' + static String TSO500_PANEL_37_PATH = 'https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/hmf_reference_data/panels/tso500_5.34_37--1.tar.gz' + static String TSO500_PANEL_38_PATH = 'https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/hmf_reference_data/panels/tso500_5.34_38--1.tar.gz' - static String VIRUSBREAKENDDB_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' + static String VIRUSBREAKENDDB_PATH = 'https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz' - static String HLA_SLICE_BED_GRCH38_ALT_PATH = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/umccr_reference_data/other/hla_slice/grch38_alt.plus_homologous.bed' + static String HLA_SLICE_BED_GRCH38_ALT_PATH = 'https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/other/hla_slice/grch38_alt.plus_homologous.bed' static Integer DEFAULT_ISOFOX_READ_LENGTH_WTS = 151 From d47abdc2eea9f36fbc4dd22fe550cba3c1f02605 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 26 Apr 2024 11:12:55 +1000 Subject: [PATCH 418/562] Give GHA CI workflow step more accurate name --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea5db625..5f875d9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ concurrency: jobs: test: - name: Run pipeline with test data + name: Run pipeline stubs # Only run on push if this is the nf-core dev branch (merged PRs) if: "${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/oncoanalyser') }}" runs-on: ubuntu-latest From f8db2cf8a845a0697b763c29dc06731b5bd28f49 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 28 Apr 2024 18:25:07 +1000 Subject: [PATCH 419/562] Implement reference data writing --- conf/hmf_genomes.config | 14 +- conf/modules.config | 12 + lib/Processes.groovy | 2 +- lib/Utils.groovy | 59 ++++- lib/WorkflowMain.groovy | 45 +++- main.nf | 3 - modules.json | 53 +++- modules/local/bwa-mem2/mem/main.nf | 2 - modules/local/bwa-mem2/mem/meta.yml | 8 - .../local/custom/write_reference_data/main.nf | 14 ++ modules/local/gridss/index/main.nf | 49 ++-- modules/local/svprep/assemble/main.nf | 6 +- modules/local/svprep/call/main.nf | 6 +- modules/local/svprep/preprocess/main.nf | 6 +- modules/local/virusbreakend/main.nf | 6 +- modules/nf-core/bwa/index/bwa-index.diff | 31 --- modules/nf-core/bwa/index/main.nf | 51 ---- .../nf-core/bwamem2/index/bwamem2-index.diff | 60 +++++ modules/nf-core/bwamem2/index/environment.yml | 7 + modules/nf-core/bwamem2/index/main.nf | 64 +++++ .../nf-core/{bwa => bwamem2}/index/meta.yml | 24 +- .../nf-core/bwamem2/index/tests/main.nf.test | 31 +++ .../bwamem2/index/tests/main.nf.test.snap | 47 ++++ modules/nf-core/bwamem2/index/tests/tags.yml | 2 + modules/nf-core/samtools/dict/main.nf | 6 +- .../nf-core/samtools/dict/samtools-dict.diff | 20 ++ modules/nf-core/samtools/faidx/main.nf | 8 +- .../samtools/faidx/samtools-faidx.diff | 22 ++ .../star/genomegenerate/environment.yml | 10 + modules/nf-core/star/genomegenerate/main.nf | 119 +++++++++ modules/nf-core/star/genomegenerate/meta.yml | 53 ++++ .../genomegenerate/star-genomegenerate.diff | 22 ++ .../star/genomegenerate/tests/main.nf.test | 115 +++++++++ .../genomegenerate/tests/main.nf.test.snap | 90 +++++++ .../star/genomegenerate/tests/tags.yml | 2 + nextflow.config | 19 +- nextflow_schema.json | 8 +- .../local/gridss_svprep_calling/main.nf | 8 - subworkflows/local/prepare_reference/main.nf | 232 +++++++++++------- subworkflows/local/read_alignment_dna/main.nf | 4 - .../local/virusbreakend_calling/main.nf | 4 - workflows/targeted.nf | 10 +- workflows/wgts.nf | 14 +- 43 files changed, 1051 insertions(+), 317 deletions(-) create mode 100644 modules/local/custom/write_reference_data/main.nf delete mode 100644 modules/nf-core/bwa/index/bwa-index.diff delete mode 100644 modules/nf-core/bwa/index/main.nf create mode 100644 modules/nf-core/bwamem2/index/bwamem2-index.diff create mode 100644 modules/nf-core/bwamem2/index/environment.yml create mode 100644 modules/nf-core/bwamem2/index/main.nf rename modules/nf-core/{bwa => bwamem2}/index/meta.yml (56%) create mode 100644 modules/nf-core/bwamem2/index/tests/main.nf.test create mode 100644 modules/nf-core/bwamem2/index/tests/main.nf.test.snap create mode 100644 modules/nf-core/bwamem2/index/tests/tags.yml create mode 100644 modules/nf-core/samtools/dict/samtools-dict.diff create mode 100644 modules/nf-core/samtools/faidx/samtools-faidx.diff create mode 100644 modules/nf-core/star/genomegenerate/environment.yml create mode 100644 modules/nf-core/star/genomegenerate/main.nf create mode 100644 modules/nf-core/star/genomegenerate/meta.yml create mode 100644 modules/nf-core/star/genomegenerate/star-genomegenerate.diff create mode 100644 modules/nf-core/star/genomegenerate/tests/main.nf.test create mode 100644 modules/nf-core/star/genomegenerate/tests/main.nf.test.snap create mode 100644 modules/nf-core/star/genomegenerate/tests/tags.yml diff --git a/conf/hmf_genomes.config b/conf/hmf_genomes.config index 383e5f0b..a3ba648b 100644 --- a/conf/hmf_genomes.config +++ b/conf/hmf_genomes.config @@ -13,22 +13,16 @@ params { fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/Homo_sapiens.GRCh37.GATK.illumina.fasta" fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" - bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/bwa_index/0.7.17-r1188.tar.gz" - bwa_index_bseq = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.0123" - bwa_index_biidx = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64" - bwa_index_image = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" - gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" + bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/bwa_index/2.2.1.tar.gz" + gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/gridss_index/2.13.2.tar.gz" star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/star_index/gencode_19/2.7.3a.tar.gz" } 'GRCh38_hmf' { fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/bwa_index/0.7.17-r1188.tar.gz" - bwa_index_bseq = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" - bwa_index_biidx = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" - bwa_index_image = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" - gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" + bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/bwa_index/2.2.1.tar.gz" + gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/gridss_index/2.13.2.tar.gz" star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/star_index/gencode_38/2.7.3a.tar.gz" } } diff --git a/conf/modules.config b/conf/modules.config index 04c2afab..cc09c657 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -12,6 +12,18 @@ process { + withName: 'WRITE_REFERENCE_DATA' { + def date = new java.util.Date().format('yyyyMMdd_HHmmss'); + publishDir = [ + path: { "${params.outdir}/reference_data/${workflow_version}/${date}" }, + mode: params.publish_dir_mode, + ] + } + + withName: 'STAR_GENOMEGENERATE' { + ext.args = '--genomeSAindexNbases 14 --sjdbOverhang 200 --genomeChrBinNbits 15' + } + withName: 'GATK4_MARKDUPLICATES' { publishDir = [ path: { "${params.outdir}" }, diff --git a/lib/Processes.groovy b/lib/Processes.groovy index f91fc606..cd50e858 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -4,7 +4,7 @@ import Utils class Processes { - public static getRunStages(include, exclude, manual_select, log) { + public static getRunStages(include, exclude, manual_select, log) { def processes = manual_select ? [] : Constants.Process.values().toList() def include_list = this.getProcessList(include, log) def exclude_list = this.getProcessList(exclude, log) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index f249e92c..dba43220 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -196,30 +196,31 @@ class Utils { public static void createStubPlaceholders(params) { def fps = [ - params.ref_data_genome_fasta, - params.ref_data_genome_fai, - params.ref_data_genome_dict, + params.ref_data_genome_alt, params.ref_data_genome_bwa_index, - params.ref_data_genome_bwa_index_image, - params.ref_data_genome_bwa_index_bseq, - params.ref_data_genome_bwa_index_biidx, + params.ref_data_genome_dict, + params.ref_data_genome_fai, + params.ref_data_genome_fasta, params.ref_data_genome_gridss_index, + params.ref_data_genome_gtf, params.ref_data_virusbreakenddb_path, ] - params.hmf_data_paths[params.genome_version] + params.hmf_data_paths[params.genome_version.toString()] .each { k, v -> fps << "${params.ref_data_hmf_data_path.replaceAll('/$', '')}/${v}" } if(params.panel !== null) { - params.panel_data_paths[params.panel][params.genome_version] + params.panel_data_paths[params.panel][params.genome_version.toString()] .each { k, v -> fps << "${params.ref_data_panel_data_path.replaceAll('/$', '')}/${v}" } } fps.each { fp_str -> + if (fp_str === null) return + def fp = Utils.getFileObject(fp_str) if (!fp_str || fp.exists()) return @@ -234,7 +235,7 @@ class Utils { } - public static void validateInput(inputs, run_config, log) { + public static void validateInput(inputs, run_config, params, log) { def sample_keys = [ [Constants.SampleType.TUMOR, Constants.SequenceType.DNA], @@ -314,6 +315,46 @@ class Utils { } } + + + // NOTE(SW): the follwing final config checks are performed here since they require additional information + // regarding processes that are run and also inputs + + def has_alt_contigs = params.genome_type == 'alt' + + // Ensure that custom genomes with ALT contigs that need indexes built have the required .alt file + def has_bwa_indexes = (params.ref_data_genome_bwa_index && params.ref_data_genome_gridss_index) + def has_alt_file = params.containsKey('ref_data_genome_alt') && params.ref_data_genome_alt + def run_bwa_or_gridss_index = run_config.stages.alignment && run_config.has_dna_fastq && !has_bwa_indexes + + if (run_bwa_or_gridss_index && has_alt_contigs && !has_alt_file) { + log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " The genome .alt file is required when building bwa-mem2 or GRIDSS indexes\n" + + " for reference genomes containing ALT contigs\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + // Refuse to create STAR index for reference genome containing ALTs, refer to Slack channel + def run_star_index = run_config.stages.alignment && run_config.has_rna_fastq && !params.ref_data_genome_star_index + + if (run_star_index && has_alt_contigs) { + log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Refusing to create the STAR index for a reference genome with ALT contigs.\n" + + " Please review https://github.com/alexdobin/STAR docs or contact us on Slack.\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + // Require that an input GTF file is provided when creating STAR index + if (run_star_index && !params.ref_data_genome_gtf) { + log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Creating a STAR index requires the appropriate genome transcript annotations\n" + + " as a GTF file. Please contact us on Slack for further information." + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + } static public getEnumFromString(s, e) { diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 2d7e5b87..70bfd903 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -1,8 +1,10 @@ // // This file holds several functions specific to the main.nf workflow in the nf-core/oncoanalyser pipeline // -import Utils +import nextflow.Nextflow + +import Utils class WorkflowMain { @@ -36,9 +38,9 @@ class WorkflowMain { } if (!params.containsKey('ref_hmf_data_path')) { - if (params.genome_version == '37') { + if (params.genome_version.toString() == '37') { params.ref_data_hmf_data_path = Constants.HMF_DATA_37_PATH - } else if (params.genome_version == '38') { + } else if (params.genome_version.toString() == '38') { params.ref_data_hmf_data_path = Constants.HMF_DATA_38_PATH } else { default_invalid = true @@ -65,9 +67,9 @@ class WorkflowMain { // Attempt to set default panel data path; make no assumption on valid 'panel' value if (!params.containsKey('panel')) { - if (params.panel == 'tso500' && params.genome_version == '37') { + if (params.panel == 'tso500' && params.genome_version.toString() == '37') { params.ref_data_panel_data_path = Constants.TSO500_PANEL_37_PATH - } else if (params.panel == 'tso500' && params.genome_version == '38') { + } else if (params.panel == 'tso500' && params.genome_version.toString() == '38') { params.ref_data_panel_data_path = Constants.TSO500_PANEL_38_PATH } } @@ -85,11 +87,17 @@ class WorkflowMain { } if (!params.containsKey('ref_data_hla_slice_bed') && stages.lilac) { - if (params.genome_version == '38' && params.genome_type == 'alt') { + if (params.genome_version.toString() == '38' && params.genome_type == 'alt') { params.ref_data_hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH } } + // Final point to set any default to avoid access to undefined parameters during nf-validation + if (!params.containsKey('panel')) { params.panel = null } + if (!params.containsKey('ref_data_genome_alt')) { params.ref_data_genome_alt = null } + if (!params.containsKey('ref_data_genome_gtf')) { params.ref_data_genome_gtf = null } + if (!params.containsKey('ref_data_hla_slice_bed')) { params.ref_data_hla_slice_bed = null } + } // @@ -192,6 +200,30 @@ class WorkflowMain { } + + // TODO(SW): implement additional requirements for ALT file + // disallow alt file when params.genome_type == no_alt + // require alt filename to be genome_fasta + '.alt' + if (params.ref_data_genome_alt !== null) { + if (params.genome_type != 'alt') { + log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Using a reference genome without ALT contigs but found an .alt file\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + + def ref_data_genome_alt_fn = nextflow.Nextflow.file(params.ref_data_genome_alt).name + def ref_data_genome_fasta_fn = nextflow.Nextflow.file(params.ref_data_genome_fasta).name + if (ref_data_genome_alt_fn != "${ref_data_genome_fasta_fn}.alt") { + log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Found .alt file with filename of ${ref_data_genome_alt_fn} but it is required to match\n" + + " reference genome FASTA filename stem: ${ref_data_genome_fasta_fn}.alt\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + System.exit(1) + } + } + + } public static getRunConfig(params, inputs, log) { @@ -212,6 +244,7 @@ class WorkflowMain { has_dna: inputs.any { Utils.hasTumorDna(it) }, has_rna: inputs.any { Utils.hasTumorRna(it) }, has_rna_fastq: inputs.any { Utils.hasTumorRnaFastq(it) }, + has_dna_fastq: inputs.any { Utils.hasTumorDnaFastq(it) || Utils.hasNormalDnaFastq(it) }, ] } } diff --git a/main.nf b/main.nf index 029a77e2..e91f8199 100644 --- a/main.nf +++ b/main.nf @@ -35,9 +35,6 @@ params.ref_data_genome_fasta = getGenomeAttribute('fasta') params.ref_data_genome_fai = getGenomeAttribute('fai') params.ref_data_genome_dict = getGenomeAttribute('dict') params.ref_data_genome_bwa_index = getGenomeAttribute('bwa_index') -params.ref_data_genome_bwa_index_image = getGenomeAttribute('bwa_index_image') -params.ref_data_genome_bwa_index_bseq = getGenomeAttribute('bwa_index_bseq') -params.ref_data_genome_bwa_index_biidx = getGenomeAttribute('bwa_index_biidx') params.ref_data_genome_gridss_index = getGenomeAttribute('gridss_index') params.ref_data_genome_star_index = getGenomeAttribute('star_index') diff --git a/modules.json b/modules.json index 44d7fd99..a6ebe96f 100644 --- a/modules.json +++ b/modules.json @@ -5,35 +5,58 @@ "https://github.com/nf-core/modules.git": { "modules": { "nf-core": { - "bwa/index": { + "bwamem2/index": { "branch": "master", - "git_sha": "90aef30f432332bdf0ce9f4b9004aa5d5c4960bb", - "installed_by": ["modules"] + "git_sha": "7081e04c18de9480948d34513a1c1e2d0fa9126d", + "installed_by": [ + "modules" + ], + "patch": "modules/nf-core/bwamem2/index/bwamem2-index.diff" }, "gatk4/markduplicates": { "branch": "master", "git_sha": "e726b1730dff525bde4a6839e544dabfea4cd7fd", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "samtools/dict": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ], + "patch": "modules/nf-core/samtools/dict/samtools-dict.diff" }, "samtools/faidx": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ], + "patch": "modules/nf-core/samtools/faidx/samtools-faidx.diff" }, "samtools/flagstat": { "branch": "master", "git_sha": "bbb99cb8d679555cc01c98766de7869f83283545", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "samtools/sort": { "branch": "master", "git_sha": "d5d785b3d8b422cda9c6d84a23f629a8e9ff8cd8", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] + }, + "star/genomegenerate": { + "branch": "master", + "git_sha": "a21faa6a3481af92a343a10926f59c189a2c16c9", + "installed_by": [ + "modules" + ], + "patch": "modules/nf-core/star/genomegenerate/star-genomegenerate.diff" } } }, @@ -42,20 +65,26 @@ "utils_nextflow_pipeline": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": ["subworkflows"] + "installed_by": [ + "subworkflows" + ] }, "utils_nfcore_pipeline": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": ["subworkflows"] + "installed_by": [ + "subworkflows" + ] }, "utils_nfvalidation_plugin": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": ["subworkflows"] + "installed_by": [ + "subworkflows" + ] } } } } } -} +} \ No newline at end of file diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index 603f989d..bbd4a6bc 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -11,8 +11,6 @@ process BWAMEM2_ALIGN { tuple val(meta), path(reads_fwd), path(reads_rev) path genome_fasta path genome_bwa_index - path genome_bwa_index_bseq - path genome_bwa_index_biidx output: tuple val(meta), path('*.bam'), path('*.bai'), emit: bam diff --git a/modules/local/bwa-mem2/mem/meta.yml b/modules/local/bwa-mem2/mem/meta.yml index f8fb56b3..af6d50a9 100644 --- a/modules/local/bwa-mem2/mem/meta.yml +++ b/modules/local/bwa-mem2/mem/meta.yml @@ -32,14 +32,6 @@ input: - genome_bwa_index: type: directory description: bwa-mem1 index directory - - genome_bwa_index_bseq: - type: directory - description: bwa-mem2 bseq index file - pattern: "*.{0123}" - - genome_bwa_index_biidx: - type: directory - description: bwa-mem2 biidx index file - pattern: "*.{bwt.2bit.64}" output: - meta: type: map diff --git a/modules/local/custom/write_reference_data/main.nf b/modules/local/custom/write_reference_data/main.nf new file mode 100644 index 00000000..72e01598 --- /dev/null +++ b/modules/local/custom/write_reference_data/main.nf @@ -0,0 +1,14 @@ +process WRITE_REFERENCE_DATA { + tag "${fp.name}" + + input: + path fp + val workflow_version + + output: + path fp, includeInputs: true + + script: + """ + """ +} diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 4cc51f24..98837904 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -11,30 +11,20 @@ process GRIDSS_INDEX { path genome_fasta path genome_fai path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image - val indices + path genome_alt output: - path '*.dict' , emit: dict, optional: true - path '*.img' , emit: img, optional: true - path '*.gridsscache', emit: index, optional: true - path 'versions.yml' , emit: versions + path 'gridss_index', emit: index + path 'versions.yml', emit: versions when: task.ext.when == null || task.ext.when script: def args = task.ext.args ?: '' - def sequence_dict_arg = indices.contains('samtools_dict') ? 'true' : 'false' - def bwa_index_image_arg = indices.contains('bwa_index_image') ? 'true' : 'false' - def gridss_index_arg = indices.contains('gridss_index') ? 'true' : 'false' """ - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ - - # Run + # Create indexes PrepareReference \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -XX:ParallelGCThreads=${task.cpus} \\ @@ -44,10 +34,22 @@ process GRIDSS_INDEX { -Dsamjdk.use_async_io_write_tribble=true \\ -Dsamjdk.buffer_size=4194304 \\ -Dsamjdk.async_io_read_threads=${task.cpus} \\ + ${args} \\ REFERENCE_SEQUENCE=${genome_fasta} \\ - CREATE_SEQUENCE_DICTIONARY=${sequence_dict_arg} \\ - CREATE_BWA_INDEX_IMAGE=${bwa_index_image_arg} \\ - CREATE_GRIDSS_REFERENCE_CACHE=${gridss_index_arg} + CREATE_SEQUENCE_DICTIONARY='false' \\ + CREATE_BWA_INDEX_IMAGE='true' \\ + CREATE_GRIDSS_REFERENCE_CACHE='true' + + # Move under single directory for output + mkdir -p gridss_index/ + mv ${genome_fasta.name}.{sa,pac,bwt,ann,amb} gridss_index/ + mv ${genome_fasta.name}.img gridss_index/ + mv ${genome_fasta.name}.gridsscache gridss_index/ + + # Include ALT file where necessary + if [[ -n "${genome_alt}" ]]; then + ln -s ../${genome_alt} gridss_index/; + fi; cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -57,9 +59,16 @@ process GRIDSS_INDEX { stub: """ - touch ${genome_fasta.name}.dict - touch ${genome_fasta.name}.img - touch ${genome_fasta.name}.gridsscache + mkdir -p gridss_index/ + touch gridss_index/${genome_fasta.name}.{sa,pac,bwt,ann,amb} + touch gridss_index/${genome_fasta.name}.img + touch gridss_index/${genome_fasta.name}.gridsscache + + # Include ALT file where necessary + if [[ -n "${genome_alt}" ]]; then + ln -s ../${genome_alt} gridss_index/; + fi; + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 77d0c01a..532909d2 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -13,8 +13,6 @@ process GRIDSS_ASSEMBLE { path genome_fasta path genome_fai path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image path genome_gridss_index path blocklist @@ -69,8 +67,8 @@ process GRIDSS_ASSEMBLE { shadow_input_directory \${preprocess_dir}; done - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + # Symlink indices next to assembly FASTA + ln -s \$(find -L ${genome_gridss_index} -type f) ./ # Run gridss_svprep \\ diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index c23ae6ac..56dd5833 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -13,8 +13,6 @@ process GRIDSS_CALL { path genome_fasta path genome_fai path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image path genome_gridss_index path blocklist @@ -67,8 +65,8 @@ process GRIDSS_CALL { } shadow_input_directory ${assemble_dir} - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + # Symlink indices next to assembly FASTA + ln -s \$(find -L ${genome_gridss_index} -type f) ./ # Run gridss_svprep \\ diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 4acf3adb..71a8ddef 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -13,8 +13,6 @@ process GRIDSS_PREPROCESS { path genome_fasta path genome_fai path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image path genome_gridss_index output: @@ -29,8 +27,8 @@ process GRIDSS_PREPROCESS { def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' """ - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + # Symlink indices next to assembly FASTA + ln -s \$(find -L ${genome_gridss_index} -type f) ./ gridss_svprep \\ ${args} \\ diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index da93d763..de689215 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -13,8 +13,6 @@ process VIRUSBREAKEND { path genome_fasta path genome_fai path genome_dict - path genome_bwa_index_dir, stageAs: 'bwa_index' - path genome_bwa_index_image path genome_gridss_index path virusbreakenddb @@ -30,8 +28,8 @@ process VIRUSBREAKEND { def args = task.ext.args ?: '' """ - # Symlink BWA indices next to assembly FASTA - ln -s \$(find -L ${genome_bwa_index_dir} -type f) ./ + # Symlink indices next to assembly FASTA + ln -s \$(find -L ${genome_gridss_index} -type f) ./ virusbreakend \\ --gridssargs "--jvmheap ${Math.round(task.memory.bytes * 0.95)}" \\ diff --git a/modules/nf-core/bwa/index/bwa-index.diff b/modules/nf-core/bwa/index/bwa-index.diff deleted file mode 100644 index 779bcd5f..00000000 --- a/modules/nf-core/bwa/index/bwa-index.diff +++ /dev/null @@ -1,31 +0,0 @@ -Changes in module 'nf-core/bwa/index' ---- modules/nf-core/bwa/index/main.nf -+++ modules/nf-core/bwa/index/main.nf -@@ -24,7 +24,7 @@ - bwa \\ - index \\ - $args \\ -- -p bwa/${fasta.baseName} \\ -+ -p bwa/${fasta.name} \\ - $fasta - - cat <<-END_VERSIONS > versions.yml -@@ -37,11 +37,11 @@ - """ - mkdir bwa - -- touch bwa/genome.amb -- touch bwa/genome.ann -- touch bwa/genome.bwt -- touch bwa/genome.pac -- touch bwa/genome.sa -+ touch bwa/genome.fasta.amb -+ touch bwa/genome.fasta.ann -+ touch bwa/genome.fasta.bwt -+ touch bwa/genome.fasta.pac -+ touch bwa/genome.fasta.sa - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - -************************************************************ diff --git a/modules/nf-core/bwa/index/main.nf b/modules/nf-core/bwa/index/main.nf deleted file mode 100644 index c305ffd9..00000000 --- a/modules/nf-core/bwa/index/main.nf +++ /dev/null @@ -1,51 +0,0 @@ -process BWA_INDEX { - tag "$fasta" - label 'process_single' - - conda (params.enable_conda ? "bioconda::bwa=0.7.17" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/bwa:0.7.17--hed695b0_7' : - 'quay.io/biocontainers/bwa:0.7.17--hed695b0_7' }" - - input: - tuple val(meta), path(fasta) - - output: - tuple val(meta), path(bwa) , emit: index - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - """ - mkdir bwa - bwa \\ - index \\ - $args \\ - -p bwa/${fasta.name} \\ - $fasta - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') - END_VERSIONS - """ - - stub: - """ - mkdir bwa - - touch bwa/genome.fasta.amb - touch bwa/genome.fasta.ann - touch bwa/genome.fasta.bwt - touch bwa/genome.fasta.pac - touch bwa/genome.fasta.sa - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') - END_VERSIONS - """ -} diff --git a/modules/nf-core/bwamem2/index/bwamem2-index.diff b/modules/nf-core/bwamem2/index/bwamem2-index.diff new file mode 100644 index 00000000..c2156e0b --- /dev/null +++ b/modules/nf-core/bwamem2/index/bwamem2-index.diff @@ -0,0 +1,60 @@ +Changes in module 'nf-core/bwamem2/index' +--- modules/nf-core/bwamem2/index/main.nf ++++ modules/nf-core/bwamem2/index/main.nf +@@ -8,11 +8,12 @@ + 'biocontainers/bwa-mem2:2.2.1--he513fc3_0' }" + + input: +- tuple val(meta), path(fasta) ++ path fasta ++ path alt + + output: +- tuple val(meta), path("bwamem2"), emit: index +- path "versions.yml" , emit: versions ++ path bwamem2 , emit: index ++ path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when +@@ -20,12 +21,18 @@ + script: + def prefix = task.ext.prefix ?: "${fasta}" + def args = task.ext.args ?: '' ++ + """ +- mkdir bwamem2 ++ mkdir -p bwamem2/ + bwa-mem2 \\ + index \\ + $args \\ + $fasta -p bwamem2/${prefix} ++ ++ # Include ALT file where necessary ++ if [[ -n "${alt}" ]]; then ++ ln -s ../${alt} bwamem2/; ++ fi; + + cat <<-END_VERSIONS > versions.yml + "${task.process}": +@@ -37,12 +44,17 @@ + def prefix = task.ext.prefix ?: "${fasta}" + + """ +- mkdir bwamem2 ++ mkdir -p bwamem2/ + touch bwamem2/${prefix}.0123 + touch bwamem2/${prefix}.ann + touch bwamem2/${prefix}.pac + touch bwamem2/${prefix}.amb + touch bwamem2/${prefix}.bwt.2bit.64 ++ ++ # Include ALT file where necessary ++ if [[ -n "${alt}" ]]; then ++ ln -s ../${alt} bwamem2/; ++ fi; + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + +************************************************************ diff --git a/modules/nf-core/bwamem2/index/environment.yml b/modules/nf-core/bwamem2/index/environment.yml new file mode 100644 index 00000000..26b43917 --- /dev/null +++ b/modules/nf-core/bwamem2/index/environment.yml @@ -0,0 +1,7 @@ +name: bwamem2_index +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::bwa-mem2=2.2.1 diff --git a/modules/nf-core/bwamem2/index/main.nf b/modules/nf-core/bwamem2/index/main.nf new file mode 100644 index 00000000..2c58c657 --- /dev/null +++ b/modules/nf-core/bwamem2/index/main.nf @@ -0,0 +1,64 @@ +process BWAMEM2_INDEX { + tag "$fasta" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bwa-mem2:2.2.1--he513fc3_0' : + 'biocontainers/bwa-mem2:2.2.1--he513fc3_0' }" + + input: + path fasta + path alt + + output: + path bwamem2 , emit: index + path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def prefix = task.ext.prefix ?: "${fasta}" + def args = task.ext.args ?: '' + + """ + mkdir -p bwamem2/ + bwa-mem2 \\ + index \\ + $args \\ + $fasta -p bwamem2/${prefix} + + # Include ALT file where necessary + if [[ -n "${alt}" ]]; then + ln -s ../${alt} bwamem2/; + fi; + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwamem2: \$(echo \$(bwa-mem2 version 2>&1) | sed 's/.* //') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${fasta}" + + """ + mkdir -p bwamem2/ + touch bwamem2/${prefix}.0123 + touch bwamem2/${prefix}.ann + touch bwamem2/${prefix}.pac + touch bwamem2/${prefix}.amb + touch bwamem2/${prefix}.bwt.2bit.64 + + # Include ALT file where necessary + if [[ -n "${alt}" ]]; then + ln -s ../${alt} bwamem2/; + fi; + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwamem2: \$(echo \$(bwa-mem2 version 2>&1) | sed 's/.* //') + END_VERSIONS + """ +} diff --git a/modules/nf-core/bwa/index/meta.yml b/modules/nf-core/bwamem2/index/meta.yml similarity index 56% rename from modules/nf-core/bwa/index/meta.yml rename to modules/nf-core/bwamem2/index/meta.yml index 2c6cfcd7..c14a1092 100644 --- a/modules/nf-core/bwa/index/meta.yml +++ b/modules/nf-core/bwamem2/index/meta.yml @@ -1,24 +1,23 @@ -name: bwa_index -description: Create BWA index for reference genome +name: bwamem2_index +description: Create BWA-mem2 index for reference genome keywords: - index - fasta - genome - reference tools: - - bwa: + - bwamem2: description: | - BWA is a software package for mapping DNA sequences against + BWA-mem2 is a software package for mapping DNA sequences against a large reference genome, such as the human genome. - homepage: http://bio-bwa.sourceforge.net/ - documentation: http://www.htslib.org/doc/samtools.html - arxiv: arXiv:1303.3997 - licence: ["GPL-3.0-or-later"] + homepage: https://github.com/bwa-mem2/bwa-mem2 + documentation: https://github.com/bwa-mem2/bwa-mem2#usage + licence: ["MIT"] input: - meta: type: map description: | - Groovy Map containing reference information. + Groovy Map containing sample information e.g. [ id:'test', single_end:false ] - fasta: type: file @@ -27,16 +26,17 @@ output: - meta: type: map description: | - Groovy Map containing reference information. + Groovy Map containing sample information e.g. [ id:'test', single_end:false ] - index: type: file description: BWA genome index files - pattern: "*.{amb,ann,bwt,pac,sa}" + pattern: "*.{0123,amb,ann,bwt.2bit.64,pac}" - versions: type: file description: File containing software versions pattern: "versions.yml" authors: - - "@drpatelh" + - "@maxulysse" +maintainers: - "@maxulysse" diff --git a/modules/nf-core/bwamem2/index/tests/main.nf.test b/modules/nf-core/bwamem2/index/tests/main.nf.test new file mode 100644 index 00000000..dbf11132 --- /dev/null +++ b/modules/nf-core/bwamem2/index/tests/main.nf.test @@ -0,0 +1,31 @@ +nextflow_process { + + name "Test Process BWAMEM2_INDEX" + tag "modules_nfcore" + tag "modules" + tag "bwamem2" + tag "bwamem2/index" + script "../main.nf" + process "BWAMEM2_INDEX" + + test("BWAMEM2 index") { + + when { + process { + """ + input[0] = [ + [id: 'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/nf-core/bwamem2/index/tests/main.nf.test.snap b/modules/nf-core/bwamem2/index/tests/main.nf.test.snap new file mode 100644 index 00000000..69b268ee --- /dev/null +++ b/modules/nf-core/bwamem2/index/tests/main.nf.test.snap @@ -0,0 +1,47 @@ +{ + "BWAMEM2 index": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + [ + "genome.fasta.0123:md5,b02870de80106104abcb03cd9463e7d8", + "genome.fasta.amb:md5,3a68b8b2287e07dd3f5f95f4344ba76e", + "genome.fasta.ann:md5,c32e11f6c859f166c7525a9c1d583567", + "genome.fasta.bwt.2bit.64:md5,d097a1b82dee375d41a1ea69895a9216", + "genome.fasta.pac:md5,983e3d2cd6f36e2546e6d25a0da78d66" + ] + ] + ], + "1": [ + "versions.yml:md5,9ffd13d12e7108ed15c58566bc4717d6" + ], + "index": [ + [ + { + "id": "test" + }, + [ + "genome.fasta.0123:md5,b02870de80106104abcb03cd9463e7d8", + "genome.fasta.amb:md5,3a68b8b2287e07dd3f5f95f4344ba76e", + "genome.fasta.ann:md5,c32e11f6c859f166c7525a9c1d583567", + "genome.fasta.bwt.2bit.64:md5,d097a1b82dee375d41a1ea69895a9216", + "genome.fasta.pac:md5,983e3d2cd6f36e2546e6d25a0da78d66" + ] + ] + ], + "versions": [ + "versions.yml:md5,9ffd13d12e7108ed15c58566bc4717d6" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.02.0" + }, + "timestamp": "2024-03-18T12:59:39.132616" + } +} \ No newline at end of file diff --git a/modules/nf-core/bwamem2/index/tests/tags.yml b/modules/nf-core/bwamem2/index/tests/tags.yml new file mode 100644 index 00000000..3953018e --- /dev/null +++ b/modules/nf-core/bwamem2/index/tests/tags.yml @@ -0,0 +1,2 @@ +bwamem2/index: + - modules/nf-core/bwamem2/index/** diff --git a/modules/nf-core/samtools/dict/main.nf b/modules/nf-core/samtools/dict/main.nf index 1b8a4f17..4a1522e9 100644 --- a/modules/nf-core/samtools/dict/main.nf +++ b/modules/nf-core/samtools/dict/main.nf @@ -8,11 +8,11 @@ process SAMTOOLS_DICT { 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" input: - tuple val(meta), path(fasta) + path fasta output: - tuple val(meta), path ("*.dict"), emit: dict - path "versions.yml" , emit: versions + path "*.dict" , emit: dict + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/nf-core/samtools/dict/samtools-dict.diff b/modules/nf-core/samtools/dict/samtools-dict.diff new file mode 100644 index 00000000..d80d13fb --- /dev/null +++ b/modules/nf-core/samtools/dict/samtools-dict.diff @@ -0,0 +1,20 @@ +Changes in module 'nf-core/samtools/dict' +--- modules/nf-core/samtools/dict/main.nf ++++ modules/nf-core/samtools/dict/main.nf +@@ -8,11 +8,11 @@ + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + + input: +- tuple val(meta), path(fasta) ++ path fasta + + output: +- tuple val(meta), path ("*.dict"), emit: dict +- path "versions.yml" , emit: versions ++ path "*.dict" , emit: dict ++ path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when + +************************************************************ diff --git a/modules/nf-core/samtools/faidx/main.nf b/modules/nf-core/samtools/faidx/main.nf index 2830963e..20c0e67e 100644 --- a/modules/nf-core/samtools/faidx/main.nf +++ b/modules/nf-core/samtools/faidx/main.nf @@ -8,12 +8,12 @@ process SAMTOOLS_FAIDX { 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" input: - tuple val(meta), path(fasta) + path fasta output: - tuple val(meta), path ("*.fai"), emit: fai - tuple val(meta), path ("*.gzi"), emit: gzi, optional: true - path "versions.yml" , emit: versions + path "*.fai" , emit: fai + path "*.gzi" , emit: gzi, optional: true + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/nf-core/samtools/faidx/samtools-faidx.diff b/modules/nf-core/samtools/faidx/samtools-faidx.diff new file mode 100644 index 00000000..aef567c6 --- /dev/null +++ b/modules/nf-core/samtools/faidx/samtools-faidx.diff @@ -0,0 +1,22 @@ +Changes in module 'nf-core/samtools/faidx' +--- modules/nf-core/samtools/faidx/main.nf ++++ modules/nf-core/samtools/faidx/main.nf +@@ -8,12 +8,12 @@ + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + + input: +- tuple val(meta), path(fasta) ++ path fasta + + output: +- tuple val(meta), path ("*.fai"), emit: fai +- tuple val(meta), path ("*.gzi"), emit: gzi, optional: true +- path "versions.yml" , emit: versions ++ path "*.fai" , emit: fai ++ path "*.gzi" , emit: gzi, optional: true ++ path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when + +************************************************************ diff --git a/modules/nf-core/star/genomegenerate/environment.yml b/modules/nf-core/star/genomegenerate/environment.yml new file mode 100644 index 00000000..791f255e --- /dev/null +++ b/modules/nf-core/star/genomegenerate/environment.yml @@ -0,0 +1,10 @@ +name: star_genomegenerate +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::samtools=1.18 + - bioconda::htslib=1.18 + - bioconda::star=2.7.10a + - conda-forge::gawk=5.1.0 diff --git a/modules/nf-core/star/genomegenerate/main.nf b/modules/nf-core/star/genomegenerate/main.nf new file mode 100644 index 00000000..1757318e --- /dev/null +++ b/modules/nf-core/star/genomegenerate/main.nf @@ -0,0 +1,119 @@ +process STAR_GENOMEGENERATE { + tag "$fasta" + label 'process_high' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:ded3841da0194af2701c780e9b3d653a85d27489-0' : + 'biocontainers/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:ded3841da0194af2701c780e9b3d653a85d27489-0' }" + + input: + path fasta + path gtf + + output: + path "star" , emit: index + path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def args_list = args.tokenize() + def memory = task.memory ? "--limitGenomeGenerateRAM ${task.memory.toBytes() - 100000000}" : '' + def include_gtf = gtf ? "--sjdbGTFfile $gtf" : '' + if (args_list.contains('--genomeSAindexNbases')) { + """ + mkdir star + STAR \\ + --runMode genomeGenerate \\ + --genomeDir star/ \\ + --genomeFastaFiles $fasta \\ + $include_gtf \\ + --runThreadN $task.cpus \\ + $memory \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + star: \$(STAR --version | sed -e "s/STAR_//g") + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') + END_VERSIONS + """ + } else { + """ + samtools faidx $fasta + NUM_BASES=`gawk '{sum = sum + \$2}END{if ((log(sum)/log(2))/2 - 1 > 14) {printf "%.0f", 14} else {printf "%.0f", (log(sum)/log(2))/2 - 1}}' ${fasta}.fai` + + mkdir star + STAR \\ + --runMode genomeGenerate \\ + --genomeDir star/ \\ + --genomeFastaFiles $fasta \\ + $include_gtf \\ + --runThreadN $task.cpus \\ + --genomeSAindexNbases \$NUM_BASES \\ + $memory \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + star: \$(STAR --version | sed -e "s/STAR_//g") + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') + END_VERSIONS + """ + } + + stub: + if (gtf) { + """ + mkdir star + touch star/Genome + touch star/Log.out + touch star/SA + touch star/SAindex + touch star/chrLength.txt + touch star/chrName.txt + touch star/chrNameLength.txt + touch star/chrStart.txt + touch star/exonGeTrInfo.tab + touch star/exonInfo.tab + touch star/geneInfo.tab + touch star/genomeParameters.txt + touch star/sjdbInfo.txt + touch star/sjdbList.fromGTF.out.tab + touch star/sjdbList.out.tab + touch star/transcriptInfo.tab + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + star: \$(STAR --version | sed -e "s/STAR_//g") + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') + END_VERSIONS + """ + } else { + """ + mkdir star + touch star/Genome + touch star/Log.out + touch star/SA + touch star/SAindex + touch star/chrLength.txt + touch star/chrName.txt + touch star/chrNameLength.txt + touch star/chrStart.txt + touch star/genomeParameters.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + star: \$(STAR --version | sed -e "s/STAR_//g") + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') + END_VERSIONS + """ + } +} diff --git a/modules/nf-core/star/genomegenerate/meta.yml b/modules/nf-core/star/genomegenerate/meta.yml new file mode 100644 index 00000000..1061e1b8 --- /dev/null +++ b/modules/nf-core/star/genomegenerate/meta.yml @@ -0,0 +1,53 @@ +name: star_genomegenerate +description: Create index for STAR +keywords: + - index + - fasta + - genome + - reference +tools: + - star: + description: | + STAR is a software package for mapping DNA sequences against + a large reference genome, such as the human genome. + homepage: https://github.com/alexdobin/STAR + manual: https://github.com/alexdobin/STAR/blob/master/doc/STARmanual.pdf + doi: 10.1093/bioinformatics/bts635 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: Fasta file of the reference genome + - meta2: + type: map + description: | + Groovy Map containing reference information + e.g. [ id:'test' ] + - gtf: + type: file + description: GTF file of the reference genome +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - index: + type: directory + description: Folder containing the star index files + pattern: "star" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@kevinmenden" + - "@drpatelh" +maintainers: + - "@kevinmenden" + - "@drpatelh" diff --git a/modules/nf-core/star/genomegenerate/star-genomegenerate.diff b/modules/nf-core/star/genomegenerate/star-genomegenerate.diff new file mode 100644 index 00000000..f7fbf966 --- /dev/null +++ b/modules/nf-core/star/genomegenerate/star-genomegenerate.diff @@ -0,0 +1,22 @@ +Changes in module 'nf-core/star/genomegenerate' +--- modules/nf-core/star/genomegenerate/main.nf ++++ modules/nf-core/star/genomegenerate/main.nf +@@ -8,12 +8,12 @@ + 'biocontainers/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:ded3841da0194af2701c780e9b3d653a85d27489-0' }" + + input: +- tuple val(meta), path(fasta) +- tuple val(meta2), path(gtf) ++ path fasta ++ path gtf + + output: +- tuple val(meta), path("star") , emit: index +- path "versions.yml" , emit: versions ++ path "star" , emit: index ++ path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when + +************************************************************ diff --git a/modules/nf-core/star/genomegenerate/tests/main.nf.test b/modules/nf-core/star/genomegenerate/tests/main.nf.test new file mode 100644 index 00000000..c17c8ba4 --- /dev/null +++ b/modules/nf-core/star/genomegenerate/tests/main.nf.test @@ -0,0 +1,115 @@ +nextflow_process { + + name "Test Process STAR_GENOMEGENERATE" + script "../main.nf" + process "STAR_GENOMEGENERATE" + tag "modules" + tag "modules_nfcore" + tag "star" + tag "star/genomegenerate" + + test("fasta_gtf") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test_fasta' ], + [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) ] + ]) + input[1] = Channel.of([ + [ id:'test_gtf' ], + [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.gtf', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.index[0][1]).listFiles().collect { it.getName() }.sort().toString()).match("fasta_gtf_index") }, + { assert snapshot(process.out.versions).match("fasta_gtf_versions") } + ) + } + } + + test("fasta_gtf_stub") { + + options '-stub' + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test_fasta' ], + [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) ] + ]) + input[1] = Channel.of([ + [ id:'test_gtf' ], + [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.gtf', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.index[0][1]).listFiles().collect { it.getName() }.sort().toString()).match("fasta_gtf_stub_index") }, + { assert snapshot(process.out.versions).match("fasta_gtf_stub_versions") } + ) + } + } + + test("fasta") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test_fasta' ], + [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) ] + ]) + input[1] = Channel.of([ [], [] ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.index[0][1]).listFiles().collect { it.getName() }.sort().toString()).match("fasta_index") }, + { assert snapshot(process.out.versions).match("fasta_versions") } + ) + } + + } + + test("fasta_stub") { + + options '-stub' + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test_fasta' ], + [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) ] + ]) + input[1] = Channel.of([ [], [] ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.index[0][1]).listFiles().collect { it.getName() }.sort().toString()).match("fasta_stub_index") }, + { assert snapshot(process.out.versions).match("fasta_stub_versions") } + ) + } + + } + +} diff --git a/modules/nf-core/star/genomegenerate/tests/main.nf.test.snap b/modules/nf-core/star/genomegenerate/tests/main.nf.test.snap new file mode 100644 index 00000000..5653d6e6 --- /dev/null +++ b/modules/nf-core/star/genomegenerate/tests/main.nf.test.snap @@ -0,0 +1,90 @@ +{ + "fasta_gtf_versions": { + "content": [ + [ + "versions.yml:md5,46b8f1f34bb7f23892cd1eb249ed4d7f" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-01T15:54:31.798555" + }, + "fasta_stub_versions": { + "content": [ + [ + "versions.yml:md5,46b8f1f34bb7f23892cd1eb249ed4d7f" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-01T15:55:07.521209" + }, + "fasta_gtf_stub_index": { + "content": [ + "[Genome, Log.out, SA, SAindex, chrLength.txt, chrName.txt, chrNameLength.txt, chrStart.txt, exonGeTrInfo.tab, exonInfo.tab, geneInfo.tab, genomeParameters.txt, sjdbInfo.txt, sjdbList.fromGTF.out.tab, sjdbList.out.tab, transcriptInfo.tab]" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-01T15:54:46.478098" + }, + "fasta_gtf_stub_versions": { + "content": [ + [ + "versions.yml:md5,46b8f1f34bb7f23892cd1eb249ed4d7f" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-01T15:54:46.491657" + }, + "fasta_index": { + "content": [ + "[Genome, Log.out, SA, SAindex, chrLength.txt, chrName.txt, chrNameLength.txt, chrStart.txt, genomeParameters.txt]" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-01T15:54:57.552329" + }, + "fasta_versions": { + "content": [ + [ + "versions.yml:md5,46b8f1f34bb7f23892cd1eb249ed4d7f" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-01T15:54:57.560541" + }, + "fasta_gtf_index": { + "content": [ + "[Genome, Log.out, SA, SAindex, chrLength.txt, chrName.txt, chrNameLength.txt, chrStart.txt, exonGeTrInfo.tab, exonInfo.tab, geneInfo.tab, genomeParameters.txt, sjdbInfo.txt, sjdbList.fromGTF.out.tab, sjdbList.out.tab, transcriptInfo.tab]" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-01T15:54:31.786814" + }, + "fasta_stub_index": { + "content": [ + "[Genome, Log.out, SA, SAindex, chrLength.txt, chrName.txt, chrNameLength.txt, chrStart.txt, genomeParameters.txt]" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-01T15:55:07.517472" + } +} \ No newline at end of file diff --git a/modules/nf-core/star/genomegenerate/tests/tags.yml b/modules/nf-core/star/genomegenerate/tests/tags.yml new file mode 100644 index 00000000..79f619bf --- /dev/null +++ b/modules/nf-core/star/genomegenerate/tests/tags.yml @@ -0,0 +1,2 @@ +star/genomegenerate: + - modules/nf-core/star/genomegenerate/** diff --git a/nextflow.config b/nextflow.config index fb6827a4..d45dcfde 100644 --- a/nextflow.config +++ b/nextflow.config @@ -38,6 +38,7 @@ params { gridss_config = null + prepare_reference_only = false create_stub_placeholders = false // Boilerplate options @@ -76,14 +77,13 @@ params { 'panel', 'panel_data_paths', 'ref_data', + 'ref_data_genome_alt', 'ref_data_genome_bwa_index', - 'ref_data_genome_bwa_index_biidx', - 'ref_data_genome_bwa_index_bseq', - 'ref_data_genome_bwa_index_image', 'ref_data_genome_dict', 'ref_data_genome_fai', 'ref_data_genome_fasta', 'ref_data_genome_gridss_index', + 'ref_data_genome_gtf', 'ref_data_genome_star_index', 'ref_data_hla_slice_bed', 'ref_data_hmf_data_path', @@ -273,6 +273,19 @@ report { trace { enabled = true file = "${params.outdir}/pipeline_info/execution_trace_${trace_timestamp}.txt" + + + + + + + overwrite = true + + + + + + } dag { enabled = true diff --git a/nextflow_schema.json b/nextflow_schema.json index d40e01af..b3454340 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -75,6 +75,12 @@ "description": "Pipeline processes to include.", "fa_icon": "fas fa-diagram-project" }, + "prepare_reference_only": { + "type": "boolean", + "description": "Prepare and write reference output only.", + "default": false, + "fa_icon": "fas fa-diagram-project" + }, "create_stub_placeholders": { "type": "boolean", "description": "Create placeholders for reference data during stub run.", @@ -138,7 +144,7 @@ "type": "string", "description": "Version of reference genome.", "fa_icon": "far fa-file-code", - "enum": ["37", "38"], + "enum": ["37", "38", 37, 38], "hidden": true }, "genome_type": { diff --git a/subworkflows/local/gridss_svprep_calling/main.nf b/subworkflows/local/gridss_svprep_calling/main.nf index 48333057..77bdb27a 100644 --- a/subworkflows/local/gridss_svprep_calling/main.nf +++ b/subworkflows/local/gridss_svprep_calling/main.nf @@ -25,8 +25,6 @@ workflow GRIDSS_SVPREP_CALLING { genome_version // channel: [mandatory] genome version genome_fai // channel: [mandatory] /path/to/genome_fai genome_dict // channel: [mandatory] /path/to/genome_dict - genome_bwa_index // channel: [mandatory] /path/to/genome_bwa_index_dir/ - genome_bwa_index_image // channel: [mandatory] /path/to/genome_bwa_index_image genome_gridss_index // channel: [mandatory] /path/to/genome_gridss_index gridss_blocklist // channel: [mandatory] /path/to/gridss_blocklist sv_prep_blocklist // channel: [mandatory] /path/to/sv_prep_blocklist @@ -190,8 +188,6 @@ workflow GRIDSS_SVPREP_CALLING { genome_fasta, genome_fai, genome_dict, - genome_bwa_index, - genome_bwa_index_image, genome_gridss_index, ) @@ -270,8 +266,6 @@ workflow GRIDSS_SVPREP_CALLING { genome_fasta, genome_fai, genome_dict, - genome_bwa_index, - genome_bwa_index_image, genome_gridss_index, gridss_blocklist, ) @@ -302,8 +296,6 @@ workflow GRIDSS_SVPREP_CALLING { genome_fasta, genome_fai, genome_dict, - genome_bwa_index, - genome_bwa_index_image, genome_gridss_index, gridss_blocklist, ) diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 54fa2d5d..9ee3a76c 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -2,22 +2,21 @@ // Prepare reference data as required // -// NOTE(SW): BWA MEM2 indexes are required and are not created -// TODO(SW): consider removing index creation since it's unlikely to be used, replace with documentation - import Constants -include { SAMTOOLS_FAIDX } from '../../../modules/nf-core/samtools/faidx/main' -include { SAMTOOLS_DICT } from '../../../modules/nf-core/samtools/dict/main' -include { BWA_INDEX } from '../../../modules/nf-core/bwa/index/main' +include { BWAMEM2_INDEX } from '../../../modules/nf-core/bwamem2/index/main' +include { SAMTOOLS_DICT } from '../../../modules/nf-core/samtools/dict/main' +include { SAMTOOLS_FAIDX } from '../../../modules/nf-core/samtools/faidx/main' +include { STAR_GENOMEGENERATE } from '../../../modules/nf-core/star/genomegenerate/main' -include { CUSTOM_EXTRACTTARBALL as DECOMP_BWA_INDEX } from '../../../modules/local/custom/extract_tarball/main' +include { CUSTOM_EXTRACTTARBALL as DECOMP_BWAMEM2_INDEX } from '../../../modules/local/custom/extract_tarball/main' +include { CUSTOM_EXTRACTTARBALL as DECOMP_GRIDSS_INDEX } from '../../../modules/local/custom/extract_tarball/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_HMF_DATA } from '../../../modules/local/custom/extract_tarball/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_PANEL_DATA } from '../../../modules/local/custom/extract_tarball/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_STAR_INDEX } from '../../../modules/local/custom/extract_tarball/main' include { CUSTOM_EXTRACTTARBALL as DECOMP_VIRUSBREAKEND_DB } from '../../../modules/local/custom/extract_tarball/main' -include { GRIDSS_INDEX as GRIDSS_BWA_INDEX_IMAGE } from '../../../modules/local/gridss/index/main' -include { GRIDSS_INDEX as GRIDSS_INDEX } from '../../../modules/local/gridss/index/main' +include { GRIDSS_INDEX } from '../../../modules/local/gridss/index/main' +include { WRITE_REFERENCE_DATA } from '../../../modules/local/custom/write_reference_data/main' workflow PREPARE_REFERENCE { take: @@ -31,118 +30,119 @@ workflow PREPARE_REFERENCE { // // Set some variables for brevity // - ch_genome_fasta = file(params.ref_data_genome_fasta) + ch_genome_fasta = Channel.fromPath(params.ref_data_genome_fasta) + ch_genome_version = Channel.value(params.genome_version) run_virusinterpreter = run_config.mode !== Constants.RunMode.TARGETED && run_config.stages.virusinterpreter // - // Create .fai and .dict for reference genome if required + // Set .fai and .dict indexes, create if required // - // The fai and dict files should always be present if using a genome preset. These are - // always created where they are not present without checking processes to run given they - // are used in numerous processes and have a neglibile cost to generate. - ch_genome_fai = params.ref_data_genome_fai ? file(params.ref_data_genome_fai) : [] - ch_genome_dict = params.ref_data_genome_dict ? file(params.ref_data_genome_dict) : [] + ch_genome_fai = getRefFileChannel('ref_data_genome_fai') if (!params.ref_data_genome_fai) { - SAMTOOLS_FAIDX([[:], ch_genome_fasta]) - ch_genome_fai = SAMTOOLS_FAIDX.out.fai.map { meta, fai -> fai } + SAMTOOLS_FAIDX(ch_genome_fasta) + ch_genome_fai = SAMTOOLS_FAIDX.out.fai ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions) } + + ch_genome_dict = getRefFileChannel('ref_data_genome_dict') if (!params.ref_data_genome_dict) { - SAMTOOLS_DICT([[:], ch_genome_fasta]) - ch_genome_dict = SAMTOOLS_DICT.out.dict.map { meta, dict -> dict } + SAMTOOLS_DICT(ch_genome_fasta) + ch_genome_dict = SAMTOOLS_DICT.out.dict ch_versions = ch_versions.mix(SAMTOOLS_DICT.out.versions) } // - // Create BWA index, BWA index image, and GRIDSS index for reference genome if required + // Set bwa-mem2 and GRIDSS indexes, unpack or create if required // - ch_genome_bwa_index = params.ref_data_genome_bwa_index ? file(params.ref_data_genome_bwa_index) : [] - ch_genome_bwa_index_image = params.ref_data_genome_gridss_index ? file(params.ref_data_genome_bwa_index_image) : [] - ch_genome_gridss_index = params.ref_data_genome_gridss_index ? file(params.ref_data_genome_gridss_index) : [] + ch_genome_bwa_index = getRefFileChannel('ref_data_genome_bwa_index') + ch_genome_gridss_index = getRefFileChannel('ref_data_genome_gridss_index') if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { - // NOTE(SW): the BWA index directory can be provided as a compressed tarball if (!params.ref_data_genome_bwa_index) { - BWA_INDEX([[:], ch_genome_fasta]) - ch_genome_bwa_index = BWA_INDEX.out.index.map { meta, index -> index } - ch_versions = ch_versions.mix(BWA_INDEX.out.versions) - } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { - ch_genome_bwa_index_inputs = [ - [id: 'bwa_index'], - file(params.ref_data_genome_bwa_index), - ] - DECOMP_BWA_INDEX(ch_genome_bwa_index_inputs) - ch_genome_bwa_index = DECOMP_BWA_INDEX.out.dir - } - if (!params.ref_data_genome_bwa_index_image) { - GRIDSS_BWA_INDEX_IMAGE( - ch_genome_fasta, - ch_genome_fai, - ch_genome_dict, - ch_genome_bwa_index, - [], - ['bwa_index_image'], + BWAMEM2_INDEX( + ch_genome_fasta, + params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], ) - ch_genome_bwa_index_image = GRIDSS_BWA_INDEX_IMAGE.out.img - ch_versions = ch_versions.mix(GRIDSS_BWA_INDEX_IMAGE.out.versions) + ch_genome_bwa_index = BWAMEM2_INDEX.out.index + ch_versions = ch_versions.mix(BWAMEM2_INDEX.out.versions) + + } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { + + ch_genome_bwa_index_inputs = Channel.fromPath(params.ref_data_genome_bwa_index) + .map { [[id: it.simpleName], it] } + + DECOMP_BWAMEM2_INDEX(ch_genome_bwa_index_inputs) + ch_genome_bwa_index = DECOMP_BWAMEM2_INDEX.out.dir + } + if (!params.ref_data_genome_gridss_index) { GRIDSS_INDEX( ch_genome_fasta, ch_genome_fai, ch_genome_dict, - ch_genome_bwa_index, - ch_genome_bwa_index_image, - ['gridss_index'], + params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], ) ch_genome_gridss_index = GRIDSS_INDEX.out.index ch_versions = ch_versions.mix(GRIDSS_INDEX.out.versions) } } - // Explicitly set BWA MEM2 index file inputs - ch_genome_bwa_index_bseq = file(params.ref_data_genome_bwa_index_bseq) - ch_genome_bwa_index_biidx = file(params.ref_data_genome_bwa_index_biidx) - // - // Decompress STAR index + // Set STAR index path, unpack or create if required // - ch_genome_star_index = params.ref_data_genome_star_index ? file(params.ref_data_genome_star_index) : [] - if (run_config.has_rna_fastq && run_config.stages.alignment && params.ref_data_genome_star_index.endsWith('.tar.gz')) { - ch_genome_star_index_inputs = [ - [id: 'star_index'], - file(params.ref_data_genome_star_index), - ] + ch_genome_star_index = getRefFileChannel('ref_data_genome_star_index') + if (run_config.has_rna_fastq && run_config.stages.alignment) { + if (!params.ref_data_genome_star_index) { + + STAR_GENOMEGENERATE( + ch_genome_fasta, + file(params.ref_data_genome_gtf), + ) + ch_genome_star_index = STAR_GENOMEGENERATE.out.index + ch_versions = ch_versions.mix(STAR_GENOMEGENERATE.out.versions) + + } else if (params.ref_data_genome_star_index.endsWith('.tar.gz')) { + + ch_genome_star_index_inputs = Channel.fromPath(params.ref_data_genome_star_index) + .map { [[id: it.simpleName], it] } + DECOMP_STAR_INDEX(ch_genome_star_index_inputs) ch_genome_star_index = DECOMP_STAR_INDEX.out.dir + + } } // - // Set VIRUSBreakend database path / stage, unpack if required + // Set VIRUSBreakend database path, unpack if required // ch_virusbreakenddb = Channel.empty() if (run_config.has_dna && run_virusinterpreter) { if (params.ref_data_virusbreakenddb_path.endsWith('.tar.gz')) { - ch_virusbreakenddb_inputs = [ - [id: 'virusbreakenddb'], - file(params.ref_data_virusbreakenddb_path), - ] + + ch_virusbreakenddb_inputs = Channel.fromPath(params.ref_data_virusbreakenddb_path) + .map { [[id: it.simpleName], it] } + DECOMP_VIRUSBREAKEND_DB(ch_virusbreakenddb_inputs) ch_virusbreakenddb = DECOMP_VIRUSBREAKEND_DB.out.dir + } else { - ch_virusbreakenddb = file(params.ref_data_virusbreakenddb_path) + + ch_virusbreakenddb = Channel.fromPath(params.ref_data_virusbreakenddb_path) + } } // - // Set HMF reference paths / stage, unpack if required + // Set HMF reference paths, unpack if required // - hmf_data_paths = params.hmf_data_paths[params.genome_version] + ch_hmf_data = Channel.empty() + hmf_data_paths = params.hmf_data_paths[params.genome_version.toString()] if (params.ref_data_hmf_data_path.endsWith('tar.gz')) { - ch_hmf_data_inputs = [ - [id: 'hmf_data'], - file(params.ref_data_hmf_data_path), - ] + + ch_hmf_data_inputs = Channel.fromPath(params.ref_data_hmf_data_path) + .map { [[id: it.simpleName], it] } + DECOMP_HMF_DATA(ch_hmf_data_inputs) ch_hmf_data = DECOMP_HMF_DATA.out.dir @@ -153,25 +153,23 @@ workflow PREPARE_REFERENCE { return createDataMap(hmf_data_paths, dirpath) } } else { - ch_hmf_data = createDataMap(hmf_data_paths, params.ref_data_hmf_data_path) + ch_hmf_data = Channel.value(createDataMap(hmf_data_paths, params.ref_data_hmf_data_path)) } // - // Set panel reference paths / stage, unpack if required + // Set panel reference paths, unpack if required // ch_panel_data = Channel.empty() if (run_config.mode === Constants.RunMode.TARGETED) { - // NOTE(SW): consider approach to implement custom panel support - panel_data_paths_versions = params.panel_data_paths[params.panel] - panel_data_paths = panel_data_paths_versions[params.genome_version] + panel_data_paths = panel_data_paths_versions[params.genome_version.toString()] if (params.ref_data_panel_data_path.endsWith('tar.gz')) { - ch_panel_data_inputs = [ - [id: 'panel_data'], - file(params.ref_data_panel_data_path), - ] + + ch_panel_data_inputs = Channel.fromPath(params.ref_data_panel_data_path) + .map { [[id: it.simpleName], it] } + DECOMP_PANEL_DATA(ch_panel_data_inputs) ch_panel_data = DECOMP_PANEL_DATA.out.dir @@ -182,29 +180,61 @@ workflow PREPARE_REFERENCE { return createDataMap(panel_data_paths, dirpath) } } else { - ch_panel_data = createDataMap(panel_data_paths, params.ref_data_panel_data_path) + ch_panel_data = Channel.value(createDataMap(panel_data_paths, params.ref_data_panel_data_path)) } } + if (params.prepare_reference_only) { + + // Create channel of data files to stage (if not already local) and write + ch_refdata = Channel.empty() + .mix( + ch_genome_fasta, + ch_genome_fai, + ch_genome_dict, + ch_genome_bwa_index, + ch_genome_gridss_index, + ch_genome_star_index, + ch_virusbreakenddb, + // Also include base paths for hmf_data and panel_data + Channel.empty() + .mix( + ch_hmf_data, + ch_panel_data, + ) + .map { getDataBaseDirectory(it) } + ) + + WRITE_REFERENCE_DATA( + ch_refdata, + workflow.manifest.version, + ) + + // Clear all stages to prevent running any analysis + run_config.stages = [:] + } + emit: - genome_fasta = ch_genome_fasta // path: genome_fasta - genome_fai = ch_genome_fai // path: genome_fai - genome_dict = ch_genome_dict // path: genome_dict - genome_bwa_index = ch_genome_bwa_index // path: genome_bwa_index - genome_bwa_index_bseq = ch_genome_bwa_index_bseq // path: genome_bwa_index_bseq - genome_bwa_index_biidx = ch_genome_bwa_index_biidx // path: genome_bwa_index_biidx - genome_bwa_index_image = ch_genome_bwa_index_image // path: genome_bwa_index_image - genome_gridss_index = ch_genome_gridss_index // path: genome_gridss_index - genome_star_index = ch_genome_star_index // path: genome_star_index - genome_version = params.genome_version // val: genome_version - - virusbreakenddb = ch_virusbreakenddb // path: VIRUSBreakend database + genome_fasta = ch_genome_fasta.first() // path: genome_fasta + genome_fai = ch_genome_fai.first() // path: genome_fai + genome_dict = ch_genome_dict.first() // path: genome_dict + genome_bwa_index = ch_genome_bwa_index.first() // path: genome_bwa_index + genome_gridss_index = ch_genome_gridss_index.first() // path: genome_gridss_index + genome_star_index = ch_genome_star_index.first() // path: genome_star_index + genome_version = ch_genome_version // val: genome_version + + virusbreakenddb = ch_virusbreakenddb.first() // path: VIRUSBreakend database hmf_data = ch_hmf_data // map: HMF data paths panel_data = ch_panel_data // map: Panel data paths versions = ch_versions // channel: [ versions.yml ] } +def getRefFileChannel(key) { + def fp = params.get(key) ? file(params.getAt(key)) : [] + return Channel.of(fp) +} + def createDataMap(entries, ref_data_path) { return entries .collectEntries { name, path -> @@ -217,3 +247,17 @@ def getRefdataFile(filepath, ref_data_path) { def data_path_noslash = ref_data_path.toString().replaceAll('/$', '') return file("${data_path_noslash}/${filepath}", checkIfExists: true) } + +def getDataBaseDirectory(data) { + def c = [] + data + .collect { it.value.toUriString().getChars() } + .transpose() + .findIndexOf { + def cs = it.unique() + if (cs.size() != 1) return true + c << cs.pop() + return false + } + return file("${c.join('')}") +} diff --git a/subworkflows/local/read_alignment_dna/main.nf b/subworkflows/local/read_alignment_dna/main.nf index fb0aaab4..0ec6fb04 100644 --- a/subworkflows/local/read_alignment_dna/main.nf +++ b/subworkflows/local/read_alignment_dna/main.nf @@ -16,8 +16,6 @@ workflow READ_ALIGNMENT_DNA { // Reference data genome_fasta // channel: [mandatory] /path/to/genome_fasta genome_bwa_index // channel: [mandatory] /path/to/genome_bwa_index_dir/ - genome_bwa_index_bseq // channel: [mandatory] /path/to/genome_bwa_index_binary_seq - genome_bwa_index_biidx // channel: [mandatory] /path/to/genome_bwa_index_bi-index // Params max_fastq_records // numeric: [mandatory] max number of FASTQ records per split @@ -152,8 +150,6 @@ workflow READ_ALIGNMENT_DNA { ch_bwa_inputs, genome_fasta, genome_bwa_index, - genome_bwa_index_bseq, - genome_bwa_index_biidx, ) ch_versions = ch_versions.mix(BWAMEM2_ALIGN.out.versions) diff --git a/subworkflows/local/virusbreakend_calling/main.nf b/subworkflows/local/virusbreakend_calling/main.nf index 198af3e4..3e210365 100644 --- a/subworkflows/local/virusbreakend_calling/main.nf +++ b/subworkflows/local/virusbreakend_calling/main.nf @@ -20,8 +20,6 @@ workflow VIRUSBREAKEND_CALLING { genome_fasta // channel: [mandatory] /path/to/genome_fasta genome_fai // channel: [mandatory] /path/to/genome_fai genome_dict // channel: [mandatory] /path/to/genome_dict - genome_bwa_index // channel: [mandatory] /path/to/genome_bwa_index/ - genome_bwa_index_image // channel: [mandatory] /path/to/genome_bwa_index_image genome_gridss_index // channel: [mandatory] /path/to/genome_gridss_index virusbreakenddb // channel: [mandatory] /path/to/virusbreakenddb/ virus_taxonomy_db // channel: [mandatory] /path/to/virus_taxonomy_db @@ -77,8 +75,6 @@ workflow VIRUSBREAKEND_CALLING { genome_fasta, genome_fai, genome_dict, - genome_bwa_index, - genome_bwa_index_image, genome_gridss_index, virusbreakenddb, ) diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 0bda31d8..1c8c5b01 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -16,7 +16,7 @@ inputs = Utils.parseInput(params.input, workflow.stubRun, log) run_config = WorkflowMain.getRunConfig(params, inputs, log) // Validate inputs -Utils.validateInput(inputs, run_config, log) +Utils.validateInput(inputs, run_config, params, log) // Check input path parameters to see if they exist def checkPathParamList = [ @@ -34,7 +34,7 @@ if (run_config.stages.gridss) { } if (run_config.stages.lilac) { - if (params.genome_version == '38' && params.genome_type == 'alt' && params.containsKey('ref_data_hla_slice_bed')) { + if (params.genome_version.toString() == '38' && params.genome_type == 'alt' && params.containsKey('ref_data_hla_slice_bed')) { checkPathParamList.add(params.ref_data_hla_slice_bed) } } @@ -115,8 +115,6 @@ workflow TARGETED { ch_inputs, ref_data.genome_fasta, ref_data.genome_bwa_index, - ref_data.genome_bwa_index_bseq, - ref_data.genome_bwa_index_biidx, params.max_fastq_records, ) @@ -172,7 +170,7 @@ workflow TARGETED { } else { - ch_process_dna_normal_out = ch_inputs.map + ch_process_dna_tumor_out = ch_inputs.map { meta -> [meta, []] } ch_process_dna_normal_out = ch_inputs.map { meta -> [meta, []] } } @@ -282,8 +280,6 @@ workflow TARGETED { ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, - ref_data.genome_bwa_index, - ref_data.genome_bwa_index_image, ref_data.genome_gridss_index, hmf_data.gridss_region_blocklist, hmf_data.sv_prep_blocklist, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 07e2605f..b2d5096b 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -15,7 +15,7 @@ inputs = Utils.parseInput(params.input, workflow.stubRun, log) run_config = WorkflowMain.getRunConfig(params, inputs, log) // Validate inputs -Utils.validateInput(inputs, run_config, log) +Utils.validateInput(inputs, run_config, params, log) // Check input path parameters to see if they exist def checkPathParamList = [ @@ -36,7 +36,7 @@ if (run_config.stages.virusinterpreter && run_config.mode !== Constants.RunMode. } if (run_config.stages.lilac) { - if (params.genome_version == '38' && params.genome_type == 'alt' && params.containsKey('ref_data_hla_slice_bed')) { + if (params.genome_version.toString() == '38' && params.genome_type == 'alt' && params.containsKey('ref_data_hla_slice_bed')) { checkPathParamList.add(params.ref_data_hla_slice_bed) } } @@ -104,6 +104,10 @@ workflow WGTS { ref_data = PREPARE_REFERENCE.out hmf_data = PREPARE_REFERENCE.out.hmf_data + ch_versions = ch_versions.mix( + PREPARE_REFERENCE.out.versions, + ) + // Set GRIDSS config gridss_config = params.gridss_config !== null ? file(params.gridss_config) : hmf_data.gridss_config @@ -120,8 +124,6 @@ workflow WGTS { ch_inputs, ref_data.genome_fasta, ref_data.genome_bwa_index, - ref_data.genome_bwa_index_bseq, - ref_data.genome_bwa_index_biidx, params.max_fastq_records, ) @@ -282,8 +284,6 @@ workflow WGTS { ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, - ref_data.genome_bwa_index, - ref_data.genome_bwa_index_image, ref_data.genome_gridss_index, hmf_data.gridss_region_blocklist, hmf_data.sv_prep_blocklist, @@ -693,8 +693,6 @@ workflow WGTS { ref_data.genome_fasta, ref_data.genome_fai, ref_data.genome_dict, - ref_data.genome_bwa_index, - ref_data.genome_bwa_index_image, ref_data.genome_gridss_index, ref_data.virusbreakenddb, hmf_data.virus_taxonomy_db, From 5ab10af8bbe8116846c09fadc1c9736c5202bf31 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 24 Apr 2024 17:19:56 +1000 Subject: [PATCH 420/562] Refactor reference data parameters --- conf/test.config | 2 +- conf/test_stub.config | 6 +- lib/Utils.groovy | 26 ++--- lib/WorkflowMain.groovy | 100 +++++++++---------- main.nf | 24 ++--- modules/local/linx/somatic/main.nf | 3 - modules/local/linx/somatic/meta.yml | 4 - nextflow.config | 59 +++++++---- nextflow_schema.json | 13 +-- subworkflows/local/linx_annotation/main.nf | 2 - subworkflows/local/prepare_reference/main.nf | 60 +++++------ tests/main.stub.nf.test | 10 +- workflows/targeted.nf | 11 +- workflows/wgts.nf | 13 +-- 14 files changed, 155 insertions(+), 178 deletions(-) diff --git a/conf/test.config b/conf/test.config index d9c81020..473d6a44 100644 --- a/conf/test.config +++ b/conf/test.config @@ -29,5 +29,5 @@ params { mode = 'wgts' genome = 'GRCh38_hmf' - virusbreakenddb_path = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/reference_data/virusbreakend/virusbreakenddb_test.tar.gz' + ref_data_virusbreakenddb_path = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/reference_data/virusbreakend/virusbreakenddb_test.tar.gz' } diff --git a/conf/test_stub.config b/conf/test_stub.config index a19120f3..9a068d4a 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -43,9 +43,9 @@ params { } - virusbreakenddb_path = "temp/virusbreakenddb_20210401/" - hmf_data_path = "temp/hmf_bundle_38/" - panel_data_path = "temp/panel_bundle/tso500_38/" + ref_data_virusbreakenddb_path = "temp/virusbreakenddb_20210401/" + ref_data_hmf_data_path = "temp/hmf_bundle_38/" + ref_data_panel_data_path = "temp/panel_bundle/tso500_38/" // Analysis config mode = 'wgts' diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 7604a344..e8fd6338 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -196,26 +196,26 @@ class Utils { public static void createStubPlaceholders(params) { def fps = [ - params.ref_data.genome_fasta, - params.ref_data.genome_fai, - params.ref_data.genome_dict, - params.ref_data.genome_bwa_index, - params.ref_data.genome_bwa_index_image, - params.ref_data.genome_bwa_index_bseq, - params.ref_data.genome_bwa_index_biidx, - params.ref_data.genome_gridss_index, - params.ref_data.virusbreakenddb_path, + params.ref_data_genome_fasta, + params.ref_data_genome_fai, + params.ref_data_genome_dict, + params.ref_data_genome_bwa_index, + params.ref_data_genome_bwa_index_image, + params.ref_data_genome_bwa_index_bseq, + params.ref_data_genome_bwa_index_biidx, + params.ref_data_genome_gridss_index, + params.ref_data_virusbreakenddb_path, ] - params.hmf_data_paths[params.ref_data.genome_version] + params.hmf_data_paths[params.ref_data_genome_version] .each { k, v -> - fps << "${params.hmf_data_path.replaceAll('/$', '')}/${v}" + fps << "${params.ref_data_hmf_data_path.replaceAll('/$', '')}/${v}" } if(params.panel !== null) { - params.panel_data_paths[params.panel][params.ref_data.genome_version] + params.panel_data_paths[params.panel][params.ref_data_genome_version] .each { k, v -> - fps << "${params.panel_data_path.replaceAll('/$', '')}/${v}" + fps << "${params.ref_data_panel_data_path.replaceAll('/$', '')}/${v}" } } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 6e9cb85c..91a2f979 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -15,34 +15,34 @@ class WorkflowMain { // Set defaults common to all run configuration - if (params.genome_version !== null) { - params.ref_data.genome_version = params.genome_version.toString() - } else if (Constants.GENOMES_VERSION_37.contains(params.genome)) { - params.ref_data.genome_version = '37' - } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { - params.ref_data.genome_version = '38' - } else { - default_invalid = true + if (!params.containsKey('ref_data_genome_version')) { + if (Constants.GENOMES_VERSION_37.contains(params.genome)) { + params.ref_data_genome_version = '37' + } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { + params.ref_data_genome_version = '38' + } else { + default_invalid = true + } } - if (params.genome_type !== null) { - params.ref_data.genome_type = params.genome_type - } else if (Constants.GENOMES_ALT.contains(params.genome)) { - params.ref_data.genome_type = 'alt' - } else if (Constants.GENOMES_DEFINED.contains(params.genome)) { - params.ref_data.genome_type = 'no_alt' - } else { - default_invalid = true + if (!params.containsKey('ref_data_genome_type')) { + if (Constants.GENOMES_ALT.contains(params.genome)) { + params.ref_data_genome_type = 'alt' + } else if (Constants.GENOMES_DEFINED.contains(params.genome)) { + params.ref_data_genome_type = 'no_alt' + } else { + default_invalid = true + } } - if (params.hmf_data_path !== null) { - params.ref_data.hmf_data_path = params.hmf_data_path - } else if (params.ref_data.genome_version == '37') { - params.ref_data.hmf_data_path = Constants.HMF_DATA_37_PATH - } else if (params.ref_data.genome_version == '38') { - params.ref_data.hmf_data_path = Constants.HMF_DATA_38_PATH - } else { - default_invalid = true + if (!params.containsKey('ref_hmf_data_path')) { + if (params.ref_data_genome_version == '37') { + params.ref_data_hmf_data_path = Constants.HMF_DATA_37_PATH + } else if (params.ref_data_genome_version == '38') { + params.ref_data_hmf_data_path = Constants.HMF_DATA_38_PATH + } else { + default_invalid = true + } } // Bad configuration, catch in validateParams @@ -64,13 +64,11 @@ class WorkflowMain { // Attempt to set default panel data path; make no assumption on valid 'panel' value - if (params.panel_data_path !== null) { - params.ref_data.panel_data_path = params.panel_data_path - } else if (params.panel !== null ) { - if (params.panel == 'tso500' && params.genome_version == '37') { - params.ref_data.panel_data_path = Constants.TSO500_PANEL_37_PATH - } else if (params.panel == 'tso500' && params.genome_version == '38') { - params.ref_data.panel_data_path = Constants.TSO500_PANEL_38_PATH + if (!params.containsKey('panel')) { + if (params.panel == 'tso500' && params.ref_data_genome_version == '37') { + params.ref_data_panel_data_path = Constants.TSO500_PANEL_37_PATH + } else if (params.panel == 'tso500' && params.ref_data_genome_version == '38') { + params.ref_data_panel_data_path = Constants.TSO500_PANEL_38_PATH } } } @@ -82,19 +80,13 @@ class WorkflowMain { log, ) - if (stages.virusinterpreter && run_mode === Constants.RunMode.WGTS) { - if (params.virusbreakenddb_path !== null) { - params.ref_data.virusbreakenddb_path = params.virusbreakenddb_path - } else { - params.ref_data.virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH - } + if (!params.containsKey('ref_data_virusbreakenddb_path') && stages.virusinterpreter && run_mode === Constants.RunMode.WGTS){ + params.ref_data_virusbreakenddb_path = Constants.VIRUSBREAKENDDB_PATH } - if (stages.lilac) { - if (params.hla_slice_bed !== null) { - params.ref_data.hla_slice_bed = params.hla_slice_bed - } else if (params.genome_version == '38' && params.genome_type == 'alt') { - params.ref_data.hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH + if (!params.containsKey('ref_data_hla_slice_bed') && stages.lilac) { + if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt') { + params.ref_data_hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH } } @@ -107,36 +99,36 @@ class WorkflowMain { // Common parameters - if (!params.ref_data.genome) { + if (!params.genome) { log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome must be set using the --genome CLI argument or in a configuration file.\n" + " Currently, the available genome are:\n" + " ${params.genomes.keySet().join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) - } else if (!params.genomes.containsKey(params.ref_data.genome)) { + } else if (!params.genomes.containsKey(params.genome)) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome '${params.ref_data.genome}' not found in any config files provided to the pipeline.\n" + + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + " Currently, the available genome are:\n" + " ${params.genomes.keySet().join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" System.exit(1) } - if (!Constants.GENOMES_SUPPORTED.contains(params.ref_data.genome)) { - if (!params.ref_data.force_genome) { - log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got ${params.ref_data.genome}" + + if (!Constants.GENOMES_SUPPORTED.contains(params.genome)) { + if (!params.ref_data_force_genome) { + log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got ${params.genome}" + ", please adjust the --genome argument accordingly or override with --force_genome." System.exit(1) } else { log.warn "currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but forcing to " + - "proceed with \"${params.ref_data.genome}\"" + "proceed with \"${params.genome}\"" } } - if (!params.ref_data.genome_version) { + if (!params.ref_data_genome_version) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome version wasn't provided and genome '${params.ref_data.genome}' is not defined in \n" + + " Genome version wasn't provided and genome '${params.genome}' is not defined in \n" + " genome version list.\n" + " Currently, the list of genomes in the version list include:\n" + " ${Constants.GENOMES_DEFINED.join(", ")}\n" + @@ -144,9 +136,9 @@ class WorkflowMain { System.exit(1) } - if (!params.ref_data.genome_type) { + if (!params.ref_data_genome_type) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome type wasn't provided and genome '${params.ref_data.genome}' is not defined in \n" + + " Genome type wasn't provided and genome '${params.genome}' is not defined in \n" + " genome type list.\n" + " Currently, the list of genomes in the type list include:\n" + " ${Constants.GENOMES_DEFINED.join(", ")}\n" + @@ -154,7 +146,7 @@ class WorkflowMain { System.exit(1) } - if (!params.ref_data.hmf_data_path) { + if (!params.ref_data_hmf_data_path) { log.error "ERROR: HMF data path wasn't provided" System.exit(1) } diff --git a/main.nf b/main.nf index e01b75fd..029a77e2 100644 --- a/main.nf +++ b/main.nf @@ -31,21 +31,15 @@ include { getGenomeAttribute } from './subworkflows/local/utils_nfcore_oncoanaly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -// Reference config lifted up into params.ref_data to conform to standards/linting -params.ref_data = [ - genome: params.genome, - force_genome: params.force_genome, -] - -params.ref_data.genome_fasta = getGenomeAttribute('fasta') -params.ref_data.genome_fai = getGenomeAttribute('fai') -params.ref_data.genome_dict = getGenomeAttribute('dict') -params.ref_data.genome_bwa_index = getGenomeAttribute('bwa_index') -params.ref_data.genome_bwa_index_image = getGenomeAttribute('bwa_index_image') -params.ref_data.genome_bwa_index_bseq = getGenomeAttribute('bwa_index_bseq') -params.ref_data.genome_bwa_index_biidx = getGenomeAttribute('bwa_index_biidx') -params.ref_data.genome_gridss_index = getGenomeAttribute('gridss_index') -params.ref_data.genome_star_index = getGenomeAttribute('star_index') +params.ref_data_genome_fasta = getGenomeAttribute('fasta') +params.ref_data_genome_fai = getGenomeAttribute('fai') +params.ref_data_genome_dict = getGenomeAttribute('dict') +params.ref_data_genome_bwa_index = getGenomeAttribute('bwa_index') +params.ref_data_genome_bwa_index_image = getGenomeAttribute('bwa_index_image') +params.ref_data_genome_bwa_index_bseq = getGenomeAttribute('bwa_index_bseq') +params.ref_data_genome_bwa_index_biidx = getGenomeAttribute('bwa_index_biidx') +params.ref_data_genome_gridss_index = getGenomeAttribute('gridss_index') +params.ref_data_genome_star_index = getGenomeAttribute('star_index') WorkflowMain.setParamsDefaults(params, log) WorkflowMain.validateParams(params, log) diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index fcfbb5dc..a826e94d 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -13,7 +13,6 @@ process LINX_SOMATIC { path ensembl_data_resources path known_fusion_data path driver_gene_panel - path gene_id_file output: tuple val(meta), path('linx_somatic/'), emit: annotation_dir @@ -24,7 +23,6 @@ process LINX_SOMATIC { script: def args = task.ext.args ?: '' - def gene_id_file_arg = gene_id_file ? "-gene_id_file ${gene_id_file}" : '' """ linx \\ @@ -33,7 +31,6 @@ process LINX_SOMATIC { -sample ${meta.sample_id} \\ -sv_vcf ${purple_dir}/${meta.sample_id}.purple.sv.vcf.gz \\ -purple_dir ${purple_dir} \\ - ${gene_id_file_arg} \\ -ref_genome_version ${genome_ver} \\ -ensembl_data_dir ${ensembl_data_resources} \\ -known_fusion_file ${known_fusion_data} \\ diff --git a/modules/local/linx/somatic/meta.yml b/modules/local/linx/somatic/meta.yml index 2a232313..7e8694dd 100644 --- a/modules/local/linx/somatic/meta.yml +++ b/modules/local/linx/somatic/meta.yml @@ -33,10 +33,6 @@ input: type: file description: Driver Gene Panel file pattern: "*.{csv}" - - gene_id_file: - type: file - description: Ensembl gene ID file (optional) - pattern: "*.{csv}" output: - meta: type: map diff --git a/nextflow.config b/nextflow.config index 2076f74d..55eb5396 100644 --- a/nextflow.config +++ b/nextflow.config @@ -14,7 +14,6 @@ params { // Workflow mode mode = null - panel = null // Process configuration processes_manual = false @@ -23,28 +22,23 @@ params { // Reference genome information; iGenomes is effectively disabled but retained for linting genome = null - genome_version = null - genome_type = null force_genome = false - igenomes_base = 's3://ngi-igenomes/igenomes' - igenomes_ignore = false + igenomes_ignore = true // Other reference data and config exposed to user on CLI - hmf_data_path = null - panel_data_path = null - virusbreakenddb_path = null - hla_slice_bed = null + max_fastq_records = 10000000 - max_fastq_records = 10000000 + isofox_counts = null + isofox_gc_ratios = null + isofox_gene_ids = null + isofox_tpm_norm = null + isofox_read_length = null + isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' - isofox_counts = null - isofox_gc_ratios = null - isofox_gene_ids = null - isofox_tpm_norm = null - isofox_read_length = null + gridss_config = null - gridss_config = null + create_stub_placeholders = false // Boilerplate options outdir = null @@ -57,11 +51,6 @@ params { help = false version = false - // Other workflow inputs and options - create_stub_placeholders = false - linx_gene_id_file = null - isofox_functions = 'TRANSCRIPT_COUNTS;ALT_SPLICE_JUNCTIONS;FUSIONS;RETAINED_INTRONS' - // Config options config_profile_name = null config_profile_description = null @@ -76,10 +65,36 @@ params { max_cpus = 16 max_time = '240.h' + // Parameter lint ignore list + // NOTE(SW): entries here are generally have conditional defaults or are for internal use only + lint_ignore = [ + 'lint_ignore', + 'genome_type', + 'genome_version', + 'genomes', + 'hmf_data_paths', + 'panel', + 'panel_data_paths', + 'ref_data', + 'ref_data_genome_bwa_index', + 'ref_data_genome_bwa_index_biidx', + 'ref_data_genome_bwa_index_bseq', + 'ref_data_genome_bwa_index_image', + 'ref_data_genome_dict', + 'ref_data_genome_fai', + 'ref_data_genome_fasta', + 'ref_data_genome_gridss_index', + 'ref_data_genome_star_index', + 'ref_data_hla_slice_bed', + 'ref_data_hmf_data_path', + 'ref_data_panel_data_path', + 'ref_data_virusbreakenddb_path', + ] + // Schema validation default options validationFailUnrecognisedParams = false validationLenientMode = true - validationSchemaIgnoreParams = 'genomes,igenomes_base,ref_data,hmf_data_paths,panel_data_paths' + validationSchemaIgnoreParams = "igenomes_base,${lint_ignore.join(',')}" validationShowHiddenParams = false validate_params = true diff --git a/nextflow_schema.json b/nextflow_schema.json index fcd6c864..d40e01af 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -91,11 +91,6 @@ "description": "Path to GRIDSS configuration file.", "fa_icon": "fas fa-cog" }, - "linx_gene_id_file": { - "type": "string", - "description": "Path to LINX gene ID file.", - "fa_icon": "fas fa-cog" - }, "isofox_read_length": { "description": "User defined RNA read length used for Isofox.", "fa_icon": "fas fa-cog" @@ -160,22 +155,22 @@ "hidden": true, "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe c lashes between custom parameters and those supplied in `igenomes.config`." }, - "hmf_data_path": { + "ref_data_hmf_data_path": { "type": "string", "description": "Path to HMF data.", "fa_icon": "far fa-folder-open" }, - "panel_data_path": { + "ref_data_panel_data_path": { "type": "string", "description": "Path to panel data.", "fa_icon": "far fa-folder-open" }, - "virusbreakenddb_path": { + "ref_data_virusbreakenddb_path": { "type": "string", "description": "Path to VIRUSBreakend database (directory or tarball).", "fa_icon": "far fa-file-code" }, - "hla_slice_bed": { + "ref_data_hla_slice_bed": { "format": "file-path", "pattern": "^\\S+\\.bed$", "description": "Path to HLA slice BED file.", diff --git a/subworkflows/local/linx_annotation/main.nf b/subworkflows/local/linx_annotation/main.nf index c8599584..6cf17747 100644 --- a/subworkflows/local/linx_annotation/main.nf +++ b/subworkflows/local/linx_annotation/main.nf @@ -19,7 +19,6 @@ workflow LINX_ANNOTATION { ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ known_fusion_data // channel: [mandatory] /path/to/known_fusion_data driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel - gene_id_file // channel: [optional] /path/to/linx_gene_id_file main: // Channel for versions.yml files @@ -128,7 +127,6 @@ workflow LINX_ANNOTATION { ensembl_data_resources, known_fusion_data, driver_gene_panel, - gene_id_file, ) ch_versions = ch_versions.mix(SOMATIC.out.versions) diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 405c00a9..613929af 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -31,7 +31,7 @@ workflow PREPARE_REFERENCE { // // Set some variables for brevity // - ch_genome_fasta = file(params.ref_data.genome_fasta) + ch_genome_fasta = file(params.ref_data_genome_fasta) run_virusinterpreter = run_config.mode !== Constants.RunMode.TARGETED && run_config.stages.virusinterpreter // @@ -40,14 +40,14 @@ workflow PREPARE_REFERENCE { // The fai and dict files should always be present if using a genome preset. These are // always created where they are not present without checking processes to run given they // are used in numerous processes and have a neglibile cost to generate. - ch_genome_fai = params.ref_data.genome_fai ? file(params.ref_data.genome_fai) : [] - ch_genome_dict = params.ref_data.genome_dict ? file(params.ref_data.genome_dict) : [] - if (!params.ref_data.genome_fai) { + ch_genome_fai = params.ref_data_genome_fai ? file(params.ref_data_genome_fai) : [] + ch_genome_dict = params.ref_data_genome_dict ? file(params.ref_data_genome_dict) : [] + if (!params.ref_data_genome_fai) { SAMTOOLS_FAIDX([[:], ch_genome_fasta]) ch_genome_fai = SAMTOOLS_FAIDX.out.fai.map { meta, fai -> fai } ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions) } - if (!params.ref_data.genome_dict) { + if (!params.ref_data_genome_dict) { SAMTOOLS_DICT([[:], ch_genome_fasta]) ch_genome_dict = SAMTOOLS_DICT.out.dict.map { meta, dict -> dict } ch_versions = ch_versions.mix(SAMTOOLS_DICT.out.versions) @@ -56,25 +56,25 @@ workflow PREPARE_REFERENCE { // // Create BWA index, BWA index image, and GRIDSS index for reference genome if required // - ch_genome_bwa_index = params.ref_data.genome_bwa_index ? file(params.ref_data.genome_bwa_index) : [] - ch_genome_bwa_index_image = params.ref_data.genome_gridss_index ? file(params.ref_data.genome_bwa_index_image) : [] - ch_genome_gridss_index = params.ref_data.genome_gridss_index ? file(params.ref_data.genome_gridss_index) : [] + ch_genome_bwa_index = params.ref_data_genome_bwa_index ? file(params.ref_data_genome_bwa_index) : [] + ch_genome_bwa_index_image = params.ref_data_genome_gridss_index ? file(params.ref_data_genome_bwa_index_image) : [] + ch_genome_gridss_index = params.ref_data_genome_gridss_index ? file(params.ref_data_genome_gridss_index) : [] if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { // NOTE(SW): the BWA index directory can be provided as a compressed tarball - if (!params.ref_data.genome_bwa_index) { + if (!params.ref_data_genome_bwa_index) { BWA_INDEX([[:], ch_genome_fasta]) ch_genome_bwa_index = BWA_INDEX.out.index.map { meta, index -> index } ch_versions = ch_versions.mix(BWA_INDEX.out.versions) - } else if (params.ref_data.genome_bwa_index.endsWith('.tar.gz')) { + } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { ch_genome_bwa_index_inputs = [ [id: 'bwa_index'], - file(params.ref_data.genome_bwa_index), + file(params.ref_data_genome_bwa_index), ] DECOMP_BWA_INDEX(ch_genome_bwa_index_inputs) ch_genome_bwa_index = DECOMP_BWA_INDEX.out.dir } - if (!params.ref_data.genome_bwa_index_image) { + if (!params.ref_data_genome_bwa_index_image) { GRIDSS_BWA_INDEX_IMAGE( ch_genome_fasta, ch_genome_fai, @@ -86,7 +86,7 @@ workflow PREPARE_REFERENCE { ch_genome_bwa_index_image = GRIDSS_BWA_INDEX_IMAGE.out.img ch_versions = ch_versions.mix(GRIDSS_BWA_INDEX_IMAGE.out.versions) } - if (!params.ref_data.genome_gridss_index) { + if (!params.ref_data_genome_gridss_index) { GRIDSS_INDEX( ch_genome_fasta, ch_genome_fai, @@ -101,17 +101,17 @@ workflow PREPARE_REFERENCE { } // Explicitly set BWA MEM2 index file inputs - ch_genome_bwa_index_bseq = file(params.ref_data.genome_bwa_index_bseq) - ch_genome_bwa_index_biidx = file(params.ref_data.genome_bwa_index_biidx) + ch_genome_bwa_index_bseq = file(params.ref_data_genome_bwa_index_bseq) + ch_genome_bwa_index_biidx = file(params.ref_data_genome_bwa_index_biidx) // // Decompress STAR index // - ch_genome_star_index = params.ref_data.genome_star_index ? file(params.ref_data.genome_star_index) : [] - if (run_config.has_rna_fastq && run_config.stages.alignment && params.ref_data.genome_star_index.endsWith('.tar.gz')) { + ch_genome_star_index = params.ref_data_genome_star_index ? file(params.ref_data_genome_star_index) : [] + if (run_config.has_rna_fastq && run_config.stages.alignment && params.ref_data_genome_star_index.endsWith('.tar.gz')) { ch_genome_star_index_inputs = [ [id: 'star_index'], - file(params.ref_data.genome_star_index), + file(params.ref_data_genome_star_index), ] DECOMP_STAR_INDEX(ch_genome_star_index_inputs) ch_genome_star_index = DECOMP_STAR_INDEX.out.dir @@ -122,26 +122,26 @@ workflow PREPARE_REFERENCE { // ch_virusbreakenddb = Channel.empty() if (run_config.has_dna && run_virusinterpreter) { - if (params.ref_data.virusbreakenddb_path.endsWith('.tar.gz')) { + if (params.ref_data_virusbreakenddb_path.endsWith('.tar.gz')) { ch_virusbreakenddb_inputs = [ [id: 'virusbreakenddb'], - file(params.ref_data.virusbreakenddb_path), + file(params.ref_data_virusbreakenddb_path), ] DECOMP_VIRUSBREAKEND_DB(ch_virusbreakenddb_inputs) ch_virusbreakenddb = DECOMP_VIRUSBREAKEND_DB.out.dir } else { - ch_virusbreakenddb = file(params.ref_data.virusbreakenddb_path) + ch_virusbreakenddb = file(params.ref_data_virusbreakenddb_path) } } // // Set HMF reference paths / stage, unpack if required // - hmf_data_paths = params.hmf_data_paths[params.ref_data.genome_version] - if (params.ref_data.hmf_data_path.endsWith('tar.gz')) { + hmf_data_paths = params.hmf_data_paths[params.ref_data_genome_version] + if (params.ref_data_hmf_data_path.endsWith('tar.gz')) { ch_hmf_data_inputs = [ [id: 'hmf_data'], - file(params.ref_data.hmf_data_path), + file(params.ref_data_hmf_data_path), ] DECOMP_HMF_DATA(ch_hmf_data_inputs) @@ -153,7 +153,7 @@ workflow PREPARE_REFERENCE { return createDataMap(hmf_data_paths, dirpath) } } else { - ch_hmf_data = createDataMap(hmf_data_paths, params.ref_data.hmf_data_path) + ch_hmf_data = createDataMap(hmf_data_paths, params.ref_data_hmf_data_path) } // @@ -165,12 +165,12 @@ workflow PREPARE_REFERENCE { // NOTE(SW): consider approach to implement custom panel support panel_data_paths_versions = params.panel_data_paths[params.panel] - panel_data_paths = panel_data_paths_versions[params.ref_data.genome_version] + panel_data_paths = panel_data_paths_versions[params.ref_data_genome_version] - if (params.ref_data.panel_data_path.endsWith('tar.gz')) { + if (params.ref_data_panel_data_path.endsWith('tar.gz')) { ch_panel_data_inputs = [ [id: 'panel_data'], - file(params.ref_data.panel_data_path), + file(params.ref_data_panel_data_path), ] DECOMP_PANEL_DATA(ch_panel_data_inputs) @@ -182,7 +182,7 @@ workflow PREPARE_REFERENCE { return createDataMap(panel_data_paths, dirpath) } } else { - ch_panel_data = createDataMap(panel_data_paths, params.ref_data.panel_data_path) + ch_panel_data = createDataMap(panel_data_paths, params.ref_data_panel_data_path) } } @@ -196,7 +196,7 @@ workflow PREPARE_REFERENCE { genome_bwa_index_image = ch_genome_bwa_index_image // path: genome_bwa_index_image genome_gridss_index = ch_genome_gridss_index // path: genome_gridss_index genome_star_index = ch_genome_star_index // path: genome_star_index - genome_version = params.ref_data.genome_version // val: genome_version + genome_version = params.ref_data_genome_version // val: genome_version virusbreakenddb = ch_virusbreakenddb // path: VIRUSBreakend database hmf_data = ch_hmf_data // map: HMF data paths diff --git a/tests/main.stub.nf.test b/tests/main.stub.nf.test index 3775d056..a4dc4a54 100644 --- a/tests/main.stub.nf.test +++ b/tests/main.stub.nf.test @@ -15,8 +15,8 @@ nextflow_pipeline { input "${baseDir}/tests/samplesheets/wgts.dna_rna.single.stub.csv" outdir "${outputDir}" - virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" - hmf_data_path "${workDir}/reference_data/hmf_data/" + ref_data_virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" + ref_data_hmf_data_path "${workDir}/reference_data/hmf_data/" max_cpus = 1 max_memory = "10.GB" @@ -44,9 +44,9 @@ nextflow_pipeline { input "${baseDir}/tests/samplesheets/targeted.tso500.dna_rna.single.stub.csv" outdir "${outputDir}" - virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" - hmf_data_path "${workDir}/reference_data/hmf_data/" - panel_data_path "${workDir}/reference_data/panel_data/" + ref_data_virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" + ref_data_hmf_data_path "${workDir}/reference_data/hmf_data/" + ref_data_panel_data_path "${workDir}/reference_data/panel_data/" max_cpus 1 max_memory "10.GB" diff --git a/workflows/targeted.nf b/workflows/targeted.nf index fc72b747..99dcc1c9 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -24,7 +24,6 @@ def checkPathParamList = [ params.isofox_gc_ratios, params.isofox_gene_ids, params.isofox_tpm_norm, - params.linx_gene_id_file, ] // Conditional requirements @@ -35,8 +34,8 @@ if (run_config.stages.gridss) { } if (run_config.stages.lilac) { - if (params.ref_data.genome_version == '38' && params.ref_data.genome_type == 'alt' && params.ref_data.containsKey('hla_slice_bed')) { - checkPathParamList.add(params.ref_data.hla_slice_bed) + if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && params.ref_data_containsKey('hla_slice_bed')) { + checkPathParamList.add(params.ref_data_hla_slice_bed) } } @@ -46,9 +45,6 @@ for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true // Check mandatory parameters if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } -// Create Path objects for some input files -linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : [] - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS @@ -512,7 +508,6 @@ workflow TARGETED { hmf_data.ensembl_data_resources, hmf_data.known_fusion_data, panel_data.driver_gene_panel, - linx_gene_id_file, ) ch_versions = ch_versions.mix(LINX_ANNOTATION.out.versions) @@ -613,7 +608,7 @@ workflow TARGETED { if (run_config.stages.lilac) { // Set HLA slice BED if provided in params - ref_data_hla_slice_bed = params.ref_data.containsKey('hla_slice_bed') ? params.ref_data.hla_slice_bed : [] + ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] LILAC_CALLING( ch_inputs, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 832988d9..9385979b 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -21,7 +21,6 @@ Utils.validateInput(inputs, run_config, log) def checkPathParamList = [ params.isofox_counts, params.isofox_gc_ratios, - params.linx_gene_id_file, ] // Conditional requirements @@ -33,12 +32,12 @@ if (run_config.stages.gridss) { // Mode check required as evaluated regardless of workflow selection if (run_config.stages.virusinterpreter && run_config.mode !== Constants.RunMode.TARGETED) { - checkPathParamList.add(params.virusbreakenddb_path) + checkPathParamList.add(params.ref_data_virusbreakenddb_path) } if (run_config.stages.lilac) { - if (params.ref_data.genome_version == '38' && params.ref_data.genome_type == 'alt' && params.ref_data.containsKey('hla_slice_bed')) { - checkPathParamList.add(params.ref_data.hla_slice_bed) + if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && params.ref_data_containsKey('hla_slice_bed')) { + checkPathParamList.add(params.ref_data_hla_slice_bed) } } @@ -48,9 +47,6 @@ for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true // Check mandatory parameters if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } -// Create Path objects for some input files -linx_gene_id_file = params.linx_gene_id_file ? file(params.linx_gene_id_file) : [] - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS @@ -511,7 +507,6 @@ workflow WGTS { hmf_data.ensembl_data_resources, hmf_data.known_fusion_data, hmf_data.driver_gene_panel, - linx_gene_id_file, ) ch_versions = ch_versions.mix(LINX_ANNOTATION.out.versions) @@ -658,7 +653,7 @@ workflow WGTS { if (run_config.stages.lilac) { // Use HLA slice BED if provided in params or set as default requirement - ref_data_hla_slice_bed = params.ref_data.containsKey('hla_slice_bed') ? params.ref_data.hla_slice_bed : [] + ref_data_hla_slice_bed = params.containsKey('ref_data_hla_slice_bed') ? params.ref_data_hla_slice_bed : [] LILAC_CALLING( ch_inputs, From fe192f9a9611817b8f413575537c8ff8401a4616 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 13:50:23 +1000 Subject: [PATCH 421/562] Fix variable names and config load order --- lib/Utils.groovy | 4 +-- lib/WorkflowMain.groovy | 28 ++++++++++---------- nextflow.config | 14 +++++----- subworkflows/local/prepare_reference/main.nf | 6 ++--- workflows/targeted.nf | 2 +- workflows/wgts.nf | 2 +- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index e8fd6338..f249e92c 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -207,13 +207,13 @@ class Utils { params.ref_data_virusbreakenddb_path, ] - params.hmf_data_paths[params.ref_data_genome_version] + params.hmf_data_paths[params.genome_version] .each { k, v -> fps << "${params.ref_data_hmf_data_path.replaceAll('/$', '')}/${v}" } if(params.panel !== null) { - params.panel_data_paths[params.panel][params.ref_data_genome_version] + params.panel_data_paths[params.panel][params.genome_version] .each { k, v -> fps << "${params.ref_data_panel_data_path.replaceAll('/$', '')}/${v}" } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 91a2f979..2d7e5b87 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -15,30 +15,30 @@ class WorkflowMain { // Set defaults common to all run configuration - if (!params.containsKey('ref_data_genome_version')) { + if (!params.containsKey('genome_version')) { if (Constants.GENOMES_VERSION_37.contains(params.genome)) { - params.ref_data_genome_version = '37' + params.genome_version = '37' } else if (Constants.GENOMES_VERSION_38.contains(params.genome)) { - params.ref_data_genome_version = '38' + params.genome_version = '38' } else { default_invalid = true } } - if (!params.containsKey('ref_data_genome_type')) { + if (!params.containsKey('genome_type')) { if (Constants.GENOMES_ALT.contains(params.genome)) { - params.ref_data_genome_type = 'alt' + params.genome_type = 'alt' } else if (Constants.GENOMES_DEFINED.contains(params.genome)) { - params.ref_data_genome_type = 'no_alt' + params.genome_type = 'no_alt' } else { default_invalid = true } } if (!params.containsKey('ref_hmf_data_path')) { - if (params.ref_data_genome_version == '37') { + if (params.genome_version == '37') { params.ref_data_hmf_data_path = Constants.HMF_DATA_37_PATH - } else if (params.ref_data_genome_version == '38') { + } else if (params.genome_version == '38') { params.ref_data_hmf_data_path = Constants.HMF_DATA_38_PATH } else { default_invalid = true @@ -65,9 +65,9 @@ class WorkflowMain { // Attempt to set default panel data path; make no assumption on valid 'panel' value if (!params.containsKey('panel')) { - if (params.panel == 'tso500' && params.ref_data_genome_version == '37') { + if (params.panel == 'tso500' && params.genome_version == '37') { params.ref_data_panel_data_path = Constants.TSO500_PANEL_37_PATH - } else if (params.panel == 'tso500' && params.ref_data_genome_version == '38') { + } else if (params.panel == 'tso500' && params.genome_version == '38') { params.ref_data_panel_data_path = Constants.TSO500_PANEL_38_PATH } } @@ -85,7 +85,7 @@ class WorkflowMain { } if (!params.containsKey('ref_data_hla_slice_bed') && stages.lilac) { - if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt') { + if (params.genome_version == '38' && params.genome_type == 'alt') { params.ref_data_hla_slice_bed = Constants.HLA_SLICE_BED_GRCH38_ALT_PATH } } @@ -116,7 +116,7 @@ class WorkflowMain { } if (!Constants.GENOMES_SUPPORTED.contains(params.genome)) { - if (!params.ref_data_force_genome) { + if (!params.force_genome) { log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got ${params.genome}" + ", please adjust the --genome argument accordingly or override with --force_genome." System.exit(1) @@ -126,7 +126,7 @@ class WorkflowMain { } } - if (!params.ref_data_genome_version) { + if (!params.genome_version) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome version wasn't provided and genome '${params.genome}' is not defined in \n" + " genome version list.\n" + @@ -136,7 +136,7 @@ class WorkflowMain { System.exit(1) } - if (!params.ref_data_genome_type) { + if (!params.genome_type) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome type wasn't provided and genome '${params.genome}' is not defined in \n" + " genome type list.\n" + diff --git a/nextflow.config b/nextflow.config index 55eb5396..fb6827a4 100644 --- a/nextflow.config +++ b/nextflow.config @@ -100,6 +100,13 @@ params { } +// Load igenomes.config if required +if (!params.igenomes_ignore) { + includeConfig 'conf/igenomes.config' +} else { + params.genomes = [:] +} + // Load base.config by default for all pipelines includeConfig 'conf/base.config' @@ -237,13 +244,6 @@ plugins { id 'nf-validation@1.1.3' // Validation of pipeline parameters and creation of an input channel from a sample sheet } -// 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/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 613929af..54fa2d5d 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -137,7 +137,7 @@ workflow PREPARE_REFERENCE { // // Set HMF reference paths / stage, unpack if required // - hmf_data_paths = params.hmf_data_paths[params.ref_data_genome_version] + hmf_data_paths = params.hmf_data_paths[params.genome_version] if (params.ref_data_hmf_data_path.endsWith('tar.gz')) { ch_hmf_data_inputs = [ [id: 'hmf_data'], @@ -165,7 +165,7 @@ workflow PREPARE_REFERENCE { // NOTE(SW): consider approach to implement custom panel support panel_data_paths_versions = params.panel_data_paths[params.panel] - panel_data_paths = panel_data_paths_versions[params.ref_data_genome_version] + panel_data_paths = panel_data_paths_versions[params.genome_version] if (params.ref_data_panel_data_path.endsWith('tar.gz')) { ch_panel_data_inputs = [ @@ -196,7 +196,7 @@ workflow PREPARE_REFERENCE { genome_bwa_index_image = ch_genome_bwa_index_image // path: genome_bwa_index_image genome_gridss_index = ch_genome_gridss_index // path: genome_gridss_index genome_star_index = ch_genome_star_index // path: genome_star_index - genome_version = params.ref_data_genome_version // val: genome_version + genome_version = params.genome_version // val: genome_version virusbreakenddb = ch_virusbreakenddb // path: VIRUSBreakend database hmf_data = ch_hmf_data // map: HMF data paths diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 99dcc1c9..3e47f617 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -34,7 +34,7 @@ if (run_config.stages.gridss) { } if (run_config.stages.lilac) { - if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && params.ref_data_containsKey('hla_slice_bed')) { + if (params.genome_version == '38' && params.genome_type == 'alt' && params.ref_data_containsKey('hla_slice_bed')) { checkPathParamList.add(params.ref_data_hla_slice_bed) } } diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 9385979b..9f48292b 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -36,7 +36,7 @@ if (run_config.stages.virusinterpreter && run_config.mode !== Constants.RunMode. } if (run_config.stages.lilac) { - if (params.ref_data_genome_version == '38' && params.ref_data_genome_type == 'alt' && params.ref_data_containsKey('hla_slice_bed')) { + if (params.genome_version == '38' && params.genome_type == 'alt' && params.ref_data_containsKey('hla_slice_bed')) { checkPathParamList.add(params.ref_data_hla_slice_bed) } } From a99b6ab44bc82d4e302370afc763adacd9112f16 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 14:55:59 +1000 Subject: [PATCH 422/562] Correct malformed variable name --- workflows/targeted.nf | 2 +- workflows/wgts.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 3e47f617..0bda31d8 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -34,7 +34,7 @@ if (run_config.stages.gridss) { } if (run_config.stages.lilac) { - if (params.genome_version == '38' && params.genome_type == 'alt' && params.ref_data_containsKey('hla_slice_bed')) { + if (params.genome_version == '38' && params.genome_type == 'alt' && params.containsKey('ref_data_hla_slice_bed')) { checkPathParamList.add(params.ref_data_hla_slice_bed) } } diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 9f48292b..07e2605f 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -36,7 +36,7 @@ if (run_config.stages.virusinterpreter && run_config.mode !== Constants.RunMode. } if (run_config.stages.lilac) { - if (params.genome_version == '38' && params.genome_type == 'alt' && params.ref_data_containsKey('hla_slice_bed')) { + if (params.genome_version == '38' && params.genome_type == 'alt' && params.containsKey('ref_data_hla_slice_bed')) { checkPathParamList.add(params.ref_data_hla_slice_bed) } } From 63452bcff31be4a6dbfc4597cd2d6ff15b539ca3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 15:39:18 +1000 Subject: [PATCH 423/562] Update default bwa-mem2 and GRIDSS index URLs --- conf/hmf_genomes.config | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/conf/hmf_genomes.config b/conf/hmf_genomes.config index a3ba648b..72c86930 100644 --- a/conf/hmf_genomes.config +++ b/conf/hmf_genomes.config @@ -13,16 +13,16 @@ params { fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/Homo_sapiens.GRCh37.GATK.illumina.fasta" fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" - bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/bwa_index/2.2.1.tar.gz" - gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/gridss_index/2.13.2.tar.gz" + bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/bwa_index/2.2.1.tar.gz" + gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/gridss_index/2.13.2.tar.gz" star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/star_index/gencode_19/2.7.3a.tar.gz" } 'GRCh38_hmf' { fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/bwa_index/2.2.1.tar.gz" - gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/gridss_index/2.13.2.tar.gz" + bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/bwa_index/2.2.1.tar.gz" + gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/gridss_index/2.13.2.tar.gz" star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/star_index/gencode_38/2.7.3a.tar.gz" } } From 906a81e51a196542c05922b15fd7315d67eb67f6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 16:59:26 +1000 Subject: [PATCH 424/562] Add container and label to write refdata process --- modules/local/custom/write_reference_data/main.nf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/local/custom/write_reference_data/main.nf b/modules/local/custom/write_reference_data/main.nf index 72e01598..b7f2e3b8 100644 --- a/modules/local/custom/write_reference_data/main.nf +++ b/modules/local/custom/write_reference_data/main.nf @@ -1,5 +1,10 @@ process WRITE_REFERENCE_DATA { tag "${fp.name}" + label 'process_single' + + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : + 'quay.io/nf-core/ubuntu:20.04' }" input: path fp From 150d85fe6367ce99ba62a7d9560e899141718a94 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 17:27:02 +1000 Subject: [PATCH 425/562] Ensure ref_data_panel_data_path is defined --- lib/WorkflowMain.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 70bfd903..8d929a4d 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -97,6 +97,7 @@ class WorkflowMain { if (!params.containsKey('ref_data_genome_alt')) { params.ref_data_genome_alt = null } if (!params.containsKey('ref_data_genome_gtf')) { params.ref_data_genome_gtf = null } if (!params.containsKey('ref_data_hla_slice_bed')) { params.ref_data_hla_slice_bed = null } + if (!params.containsKey('ref_data_panel_data_path')) { params.ref_data_panel_data_path = null } } From d61440c560c84467441256ae177b0ac000414b1e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 17:28:45 +1000 Subject: [PATCH 426/562] Improve names for decompressed refdata output dirs --- subworkflows/local/prepare_reference/main.nf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 9ee3a76c..902f3df8 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -69,7 +69,7 @@ workflow PREPARE_REFERENCE { } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { ch_genome_bwa_index_inputs = Channel.fromPath(params.ref_data_genome_bwa_index) - .map { [[id: it.simpleName], it] } + .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } DECOMP_BWAMEM2_INDEX(ch_genome_bwa_index_inputs) ch_genome_bwa_index = DECOMP_BWAMEM2_INDEX.out.dir @@ -105,7 +105,7 @@ workflow PREPARE_REFERENCE { } else if (params.ref_data_genome_star_index.endsWith('.tar.gz')) { ch_genome_star_index_inputs = Channel.fromPath(params.ref_data_genome_star_index) - .map { [[id: it.simpleName], it] } + .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } DECOMP_STAR_INDEX(ch_genome_star_index_inputs) ch_genome_star_index = DECOMP_STAR_INDEX.out.dir @@ -121,7 +121,7 @@ workflow PREPARE_REFERENCE { if (params.ref_data_virusbreakenddb_path.endsWith('.tar.gz')) { ch_virusbreakenddb_inputs = Channel.fromPath(params.ref_data_virusbreakenddb_path) - .map { [[id: it.simpleName], it] } + .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } DECOMP_VIRUSBREAKEND_DB(ch_virusbreakenddb_inputs) ch_virusbreakenddb = DECOMP_VIRUSBREAKEND_DB.out.dir @@ -141,7 +141,7 @@ workflow PREPARE_REFERENCE { if (params.ref_data_hmf_data_path.endsWith('tar.gz')) { ch_hmf_data_inputs = Channel.fromPath(params.ref_data_hmf_data_path) - .map { [[id: it.simpleName], it] } + .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } DECOMP_HMF_DATA(ch_hmf_data_inputs) @@ -168,7 +168,7 @@ workflow PREPARE_REFERENCE { if (params.ref_data_panel_data_path.endsWith('tar.gz')) { ch_panel_data_inputs = Channel.fromPath(params.ref_data_panel_data_path) - .map { [[id: it.simpleName], it] } + .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } DECOMP_PANEL_DATA(ch_panel_data_inputs) From 44a58b18abef3123819ad930ce8c38c07eb534dd Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 17:56:22 +1000 Subject: [PATCH 427/562] Add index name to decompressed refdata output dirs --- subworkflows/local/prepare_reference/main.nf | 29 +++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 902f3df8..1d9174f5 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -52,11 +52,10 @@ workflow PREPARE_REFERENCE { } // - // Set bwa-mem2 and GRIDSS indexes, unpack or create if required + // Set bwa-mem2 index, unpack or create if required // ch_genome_bwa_index = getRefFileChannel('ref_data_genome_bwa_index') - ch_genome_gridss_index = getRefFileChannel('ref_data_genome_gridss_index') - if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { + if (run_config.has_dna && run_config.stages.alignment) { if (!params.ref_data_genome_bwa_index) { BWAMEM2_INDEX( @@ -69,14 +68,21 @@ workflow PREPARE_REFERENCE { } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { ch_genome_bwa_index_inputs = Channel.fromPath(params.ref_data_genome_bwa_index) - .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } + .map { [[id: "bwa-mem2_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } DECOMP_BWAMEM2_INDEX(ch_genome_bwa_index_inputs) ch_genome_bwa_index = DECOMP_BWAMEM2_INDEX.out.dir } + } + // + // Set and GRIDSS index, unpack or create if required + // + ch_genome_gridss_index = getRefFileChannel('ref_data_genome_gridss_index') + if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { if (!params.ref_data_genome_gridss_index) { + GRIDSS_INDEX( ch_genome_fasta, ch_genome_fai, @@ -85,6 +91,15 @@ workflow PREPARE_REFERENCE { ) ch_genome_gridss_index = GRIDSS_INDEX.out.index ch_versions = ch_versions.mix(GRIDSS_INDEX.out.versions) + + } else if (params.ref_data_genome_gridss_index.endsWith('.tar.gz')) { + + ch_genome_gridss_index_inputs = Channel.fromPath(params.ref_data_genome_gridss_index) + .map { [[id: "gridss_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } + + DECOMP_GRIDSS_INDEX(ch_genome_gridss_index_inputs) + ch_genome_gridss_index = DECOMP_GRIDSS_INDEX.out.dir + } } @@ -105,7 +120,7 @@ workflow PREPARE_REFERENCE { } else if (params.ref_data_genome_star_index.endsWith('.tar.gz')) { ch_genome_star_index_inputs = Channel.fromPath(params.ref_data_genome_star_index) - .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } + .map { [[id: "star_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } DECOMP_STAR_INDEX(ch_genome_star_index_inputs) ch_genome_star_index = DECOMP_STAR_INDEX.out.dir @@ -141,7 +156,7 @@ workflow PREPARE_REFERENCE { if (params.ref_data_hmf_data_path.endsWith('tar.gz')) { ch_hmf_data_inputs = Channel.fromPath(params.ref_data_hmf_data_path) - .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } + .map { [[id: "hmf_data_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } DECOMP_HMF_DATA(ch_hmf_data_inputs) @@ -168,7 +183,7 @@ workflow PREPARE_REFERENCE { if (params.ref_data_panel_data_path.endsWith('tar.gz')) { ch_panel_data_inputs = Channel.fromPath(params.ref_data_panel_data_path) - .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } + .map { [[id: "panel_data_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } DECOMP_PANEL_DATA(ch_panel_data_inputs) From 1c2bd941bc77569b72fc0a1eae2390bc35abe70a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 19:40:53 +1000 Subject: [PATCH 428/562] Correct mistake in assets/samplesheet.csv Resolves #17. --- assets/samplesheet.csv | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 84d41336..157d28bf 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,12 +1,12 @@ group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath -subject_one__to__dna,subject_one,sample_a,tumor,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.bam +subject_one__to__dna,subject_one,sample_a,tumor,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.tumor.bam -subject_one__tn__dna,subject_one,sample_a,tumor,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.bam -subject_one__tn__dna,subject_one,sample_b,normal,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_b.bam +subject_one__tn__dna,subject_one,sample_a,tumor,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.tumor.bam +subject_one__tn__dna,subject_one,sample_b,normal,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_b.normal.bam -subject_one__tn__dna_rna,subject_one,sample_a,tumor,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.bam -subject_one__tn__dna_rna,subject_one,sample_b,normal,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_b.bam -subject_one__tn__dna_rna,subject_one,sample_c,tumor,bam,rna,/Users/stephen/repos/oncoanalyser/subject_one/sample_c.bam +subject_one__tn__dna_rna,subject_one,sample_a,tumor,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.tumor.bam +subject_one__tn__dna_rna,subject_one,sample_b,normal,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_b.normal.bam +subject_one__tn__dna_rna,subject_one,sample_c,tumor,rna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_c.tumor_rna.bam -subject_one__to__dna_rna,subject_one,sample_a,tumor,bam,dna,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.bam -subject_one__to__dna_rna,subject_one,sample_c,tumor,bam,rna,/Users/stephen/repos/oncoanalyser/subject_one/sample_c.bam +subject_one__to__dna_rna,subject_one,sample_a,tumor,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.tumor.bam +subject_one__to__dna_rna,subject_one,sample_c,tumor,rna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_c.tumor_rna.bam From b08399b1315a0e917d4541386d786533bfab7014 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 20:21:24 +1000 Subject: [PATCH 429/562] Ensure ref_data_virusbreakenddb_path is defined --- lib/WorkflowMain.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 8d929a4d..77def30b 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -98,6 +98,7 @@ class WorkflowMain { if (!params.containsKey('ref_data_genome_gtf')) { params.ref_data_genome_gtf = null } if (!params.containsKey('ref_data_hla_slice_bed')) { params.ref_data_hla_slice_bed = null } if (!params.containsKey('ref_data_panel_data_path')) { params.ref_data_panel_data_path = null } + if (!params.containsKey('ref_data_virusbreakenddb_path')) { params.ref_data_virusbreakenddb_path = null } } From 78f60f63096975d22696a029aa5168e91495f6ea Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 20:29:11 +1000 Subject: [PATCH 430/562] Only write reference data require for analysis --- subworkflows/local/prepare_reference/main.nf | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 1d9174f5..ae21312b 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -54,7 +54,7 @@ workflow PREPARE_REFERENCE { // // Set bwa-mem2 index, unpack or create if required // - ch_genome_bwa_index = getRefFileChannel('ref_data_genome_bwa_index') + ch_genome_bwa_index = Channel.empty() if (run_config.has_dna && run_config.stages.alignment) { if (!params.ref_data_genome_bwa_index) { @@ -73,13 +73,17 @@ workflow PREPARE_REFERENCE { DECOMP_BWAMEM2_INDEX(ch_genome_bwa_index_inputs) ch_genome_bwa_index = DECOMP_BWAMEM2_INDEX.out.dir + } else { + + ch_genome_bwa_index = getRefFileChannel('ref_data_genome_bwa_index') + } } // // Set and GRIDSS index, unpack or create if required // - ch_genome_gridss_index = getRefFileChannel('ref_data_genome_gridss_index') + ch_genome_gridss_index = Channel.empty() if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { if (!params.ref_data_genome_gridss_index) { @@ -100,13 +104,17 @@ workflow PREPARE_REFERENCE { DECOMP_GRIDSS_INDEX(ch_genome_gridss_index_inputs) ch_genome_gridss_index = DECOMP_GRIDSS_INDEX.out.dir + } else { + + ch_genome_gridss_index = getRefFileChannel('ref_data_genome_gridss_index') + } } // // Set STAR index path, unpack or create if required // - ch_genome_star_index = getRefFileChannel('ref_data_genome_star_index') + ch_genome_star_index = Channel.empty() if (run_config.has_rna_fastq && run_config.stages.alignment) { if (!params.ref_data_genome_star_index) { @@ -125,6 +133,10 @@ workflow PREPARE_REFERENCE { DECOMP_STAR_INDEX(ch_genome_star_index_inputs) ch_genome_star_index = DECOMP_STAR_INDEX.out.dir + } else { + + ch_genome_star_index = getRefFileChannel('ref_data_genome_star_index') + } } From 776dca2b8911226bf686b03fb5afaa9b318cc71c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 20:57:10 +1000 Subject: [PATCH 431/562] Fix panel data path default assignment --- lib/WorkflowMain.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 77def30b..1efa634c 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -66,7 +66,7 @@ class WorkflowMain { // Attempt to set default panel data path; make no assumption on valid 'panel' value - if (!params.containsKey('panel')) { + if (params.containsKey('panel')) { if (params.panel == 'tso500' && params.genome_version.toString() == '37') { params.ref_data_panel_data_path = Constants.TSO500_PANEL_37_PATH } else if (params.panel == 'tso500' && params.genome_version.toString() == '38') { From e9c00be049b8d297fec48e9a93b065a1b94af39c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 20:57:34 +1000 Subject: [PATCH 432/562] Use consistent spacing in prepare_reference.nf --- subworkflows/local/prepare_reference/main.nf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index ae21312b..db9b5c6f 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -179,8 +179,11 @@ workflow PREPARE_REFERENCE { def dirpath = dir_list[0].toUriString() return createDataMap(hmf_data_paths, dirpath) } + } else { + ch_hmf_data = Channel.value(createDataMap(hmf_data_paths, params.ref_data_hmf_data_path)) + } // @@ -206,8 +209,11 @@ workflow PREPARE_REFERENCE { def dirpath = dir_list[0].toUriString() return createDataMap(panel_data_paths, dirpath) } + } else { + ch_panel_data = Channel.value(createDataMap(panel_data_paths, params.ref_data_panel_data_path)) + } } From 18098c2c1c26d72ade542a1f8e5d6770f3f1ccae Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 1 May 2024 09:24:33 +1000 Subject: [PATCH 433/562] Set 'process_high_memory' label for bwa-mem2 index --- modules/nf-core/bwamem2/index/bwamem2-index.diff | 14 +++++++++++--- modules/nf-core/bwamem2/index/main.nf | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/modules/nf-core/bwamem2/index/bwamem2-index.diff b/modules/nf-core/bwamem2/index/bwamem2-index.diff index c2156e0b..3cd4bb0e 100644 --- a/modules/nf-core/bwamem2/index/bwamem2-index.diff +++ b/modules/nf-core/bwamem2/index/bwamem2-index.diff @@ -1,7 +1,15 @@ Changes in module 'nf-core/bwamem2/index' --- modules/nf-core/bwamem2/index/main.nf +++ modules/nf-core/bwamem2/index/main.nf -@@ -8,11 +8,12 @@ +@@ -1,6 +1,7 @@ + process BWAMEM2_INDEX { + tag "$fasta" + label 'process_single' ++ label 'process_high_memory' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? +@@ -8,11 +9,12 @@ 'biocontainers/bwa-mem2:2.2.1--he513fc3_0' }" input: @@ -17,7 +25,7 @@ Changes in module 'nf-core/bwamem2/index' when: task.ext.when == null || task.ext.when -@@ -20,12 +21,18 @@ +@@ -20,12 +22,18 @@ script: def prefix = task.ext.prefix ?: "${fasta}" def args = task.ext.args ?: '' @@ -37,7 +45,7 @@ Changes in module 'nf-core/bwamem2/index' cat <<-END_VERSIONS > versions.yml "${task.process}": -@@ -37,12 +44,17 @@ +@@ -37,12 +45,17 @@ def prefix = task.ext.prefix ?: "${fasta}" """ diff --git a/modules/nf-core/bwamem2/index/main.nf b/modules/nf-core/bwamem2/index/main.nf index 2c58c657..4d4f793c 100644 --- a/modules/nf-core/bwamem2/index/main.nf +++ b/modules/nf-core/bwamem2/index/main.nf @@ -1,6 +1,7 @@ process BWAMEM2_INDEX { tag "$fasta" label 'process_single' + label 'process_high_memory' conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? From fb709e56653ac6219788984a1bf786493f9c8bf9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 1 May 2024 11:54:55 +1000 Subject: [PATCH 434/562] Use bwa-mem2 for HLA read realignment --- .../custom/lilac_extract_and_index_contig/main.nf | 12 ++++++------ subworkflows/local/lilac_calling/main.nf | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index 3c22e136..4dd4ae64 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -2,10 +2,10 @@ process CUSTOM_EXTRACTCONTIG { tag "${contig_name}" label 'process_single' - conda "bwa=0.7.17 samtools=1.19.2" + conda "bwa-mem2=2.2.1 samtools=1.19.2" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-4908f45b5b676e6a2fed6b1977d445b16b7b8dee:2411d64e0a784487e81828123aaf68a549531e5c-0' : - 'quay.io/biocontainers/mulled-v2-4908f45b5b676e6a2fed6b1977d445b16b7b8dee:2411d64e0a784487e81828123aaf68a549531e5c-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' : + 'quay.io/biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" input: val contig_name @@ -15,7 +15,7 @@ process CUSTOM_EXTRACTCONTIG { output: path "*extracted.fa" , emit: contig - path "*extracted.fa.*", emit: bwa_indices + path "*extracted.fa.*", emit: bwa_index path 'versions.yml' , emit: versions when: @@ -29,11 +29,11 @@ process CUSTOM_EXTRACTCONTIG { -o ${contig_name}_extracted.fa \\ ${genome_fasta} \\ ${contig_name} - bwa index ${contig_name}_extracted.fa + bwa-mem2 index ${contig_name}_extracted.fa cat <<-END_VERSIONS > versions.yml "${task.process}": - bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + bwa-mem2: \$(bwa-mem2 version 2>/dev/null) samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') END_VERSIONS """ diff --git a/subworkflows/local/lilac_calling/main.nf b/subworkflows/local/lilac_calling/main.nf index 3110cc97..e73f77c3 100644 --- a/subworkflows/local/lilac_calling/main.nf +++ b/subworkflows/local/lilac_calling/main.nf @@ -131,7 +131,7 @@ workflow LILAC_CALLING { REALIGNREADS( SLICEBAM.out.bam, EXTRACTCONTIG.out.contig, - EXTRACTCONTIG.out.bwa_indices, + EXTRACTCONTIG.out.bwa_index, ) ch_versions = ch_versions.mix(REALIGNREADS.out.versions) From fe85940c315b12ebfabcbc47680104fde931ed24 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 1 May 2024 13:22:15 +1000 Subject: [PATCH 435/562] Create bwa-mem1 index prior to GRIDSS indexing --- modules.json | 47 ++++++---------- modules/nf-core/bwa/index/environment.yml | 7 +++ modules/nf-core/bwa/index/main.nf | 54 +++++++++++++++++++ modules/nf-core/bwa/index/meta.yml | 45 ++++++++++++++++ modules/nf-core/bwa/index/tests/main.nf.test | 33 ++++++++++++ .../nf-core/bwa/index/tests/main.nf.test.snap | 43 +++++++++++++++ modules/nf-core/bwa/index/tests/tags.yml | 2 + subworkflows/local/prepare_reference/main.nf | 7 +++ 8 files changed, 207 insertions(+), 31 deletions(-) create mode 100644 modules/nf-core/bwa/index/environment.yml create mode 100644 modules/nf-core/bwa/index/main.nf create mode 100644 modules/nf-core/bwa/index/meta.yml create mode 100644 modules/nf-core/bwa/index/tests/main.nf.test create mode 100644 modules/nf-core/bwa/index/tests/main.nf.test.snap create mode 100644 modules/nf-core/bwa/index/tests/tags.yml diff --git a/modules.json b/modules.json index a6ebe96f..00b8cadc 100644 --- a/modules.json +++ b/modules.json @@ -5,57 +5,48 @@ "https://github.com/nf-core/modules.git": { "modules": { "nf-core": { + "bwa/index": { + "branch": "master", + "git_sha": "6278bf9afd4a4b2d00fa6052250e73da3d91546f", + "installed_by": ["modules"] + }, "bwamem2/index": { "branch": "master", "git_sha": "7081e04c18de9480948d34513a1c1e2d0fa9126d", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/bwamem2/index/bwamem2-index.diff" }, "gatk4/markduplicates": { "branch": "master", "git_sha": "e726b1730dff525bde4a6839e544dabfea4cd7fd", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/dict": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/samtools/dict/samtools-dict.diff" }, "samtools/faidx": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/samtools/faidx/samtools-faidx.diff" }, "samtools/flagstat": { "branch": "master", "git_sha": "bbb99cb8d679555cc01c98766de7869f83283545", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/sort": { "branch": "master", "git_sha": "d5d785b3d8b422cda9c6d84a23f629a8e9ff8cd8", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "star/genomegenerate": { "branch": "master", "git_sha": "a21faa6a3481af92a343a10926f59c189a2c16c9", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/star/genomegenerate/star-genomegenerate.diff" } } @@ -65,26 +56,20 @@ "utils_nextflow_pipeline": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": [ - "subworkflows" - ] + "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": [ - "subworkflows" - ] + "installed_by": ["subworkflows"] }, "utils_nfvalidation_plugin": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": [ - "subworkflows" - ] + "installed_by": ["subworkflows"] } } } } } -} \ No newline at end of file +} diff --git a/modules/nf-core/bwa/index/environment.yml b/modules/nf-core/bwa/index/environment.yml new file mode 100644 index 00000000..5d3cb323 --- /dev/null +++ b/modules/nf-core/bwa/index/environment.yml @@ -0,0 +1,7 @@ +name: bwa_index +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::bwa=0.7.17 diff --git a/modules/nf-core/bwa/index/main.nf b/modules/nf-core/bwa/index/main.nf new file mode 100644 index 00000000..b81961a5 --- /dev/null +++ b/modules/nf-core/bwa/index/main.nf @@ -0,0 +1,54 @@ +process BWA_INDEX { + tag "$fasta" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bwa:0.7.17--hed695b0_7' : + 'biocontainers/bwa:0.7.17--hed695b0_7' }" + + input: + path fasta + + output: + path bwa_index , emit: index + path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def prefix = task.ext.prefix ?: "${fasta.name}" + def args = task.ext.args ?: '' + + """ + mkdir -p bwa_index/ + bwa \\ + index \\ + $args \\ + -p bwa_index/${prefix} \\ + $fasta + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${fasta.name}" + """ + mkdir -p bwa_index/ + + touch bwa_index/${prefix}.amb + touch bwa_index/${prefix}.ann + touch bwa_index/${prefix}.bwt + touch bwa_index/${prefix}.pac + touch bwa_index/${prefix}.sa + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/bwa/index/meta.yml b/modules/nf-core/bwa/index/meta.yml new file mode 100644 index 00000000..730628d0 --- /dev/null +++ b/modules/nf-core/bwa/index/meta.yml @@ -0,0 +1,45 @@ +name: bwa_index +description: Create BWA index for reference genome +keywords: + - index + - fasta + - genome + - reference +tools: + - bwa: + description: | + BWA is a software package for mapping DNA sequences against + a large reference genome, such as the human genome. + homepage: http://bio-bwa.sourceforge.net/ + documentation: http://www.htslib.org/doc/samtools.html + arxiv: arXiv:1303.3997 + licence: ["GPL-3.0-or-later"] +input: + - meta: + type: map + description: | + Groovy Map containing reference information. + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: Input genome fasta file +output: + - meta: + type: map + description: | + Groovy Map containing reference information. + e.g. [ id:'test', single_end:false ] + - index: + type: file + description: BWA genome index files + pattern: "*.{amb,ann,bwt,pac,sa}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@maxulysse" +maintainers: + - "@drpatelh" + - "@maxulysse" diff --git a/modules/nf-core/bwa/index/tests/main.nf.test b/modules/nf-core/bwa/index/tests/main.nf.test new file mode 100644 index 00000000..af33e73c --- /dev/null +++ b/modules/nf-core/bwa/index/tests/main.nf.test @@ -0,0 +1,33 @@ +nextflow_process { + + name "Test Process BWA_INDEX" + tag "modules_nfcore" + tag "modules" + tag "bwa" + tag "bwa/index" + script "../main.nf" + process "BWA_INDEX" + + test("BWA index") { + + when { + process { + """ + input[0] = [ + [id: 'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/bwa/index/tests/main.nf.test.snap b/modules/nf-core/bwa/index/tests/main.nf.test.snap new file mode 100644 index 00000000..e51ad5bf --- /dev/null +++ b/modules/nf-core/bwa/index/tests/main.nf.test.snap @@ -0,0 +1,43 @@ +{ + "BWA index": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + [ + "genome.amb:md5,3a68b8b2287e07dd3f5f95f4344ba76e", + "genome.ann:md5,c32e11f6c859f166c7525a9c1d583567", + "genome.bwt:md5,0469c30a1e239dd08f68afe66fde99da", + "genome.pac:md5,983e3d2cd6f36e2546e6d25a0da78d66", + "genome.sa:md5,ab3952cabf026b48cd3eb5bccbb636d1" + ] + ] + ], + "1": [ + "versions.yml:md5,0f20525da90e7489a7ebb02adca3265f" + ], + "index": [ + [ + { + "id": "test" + }, + [ + "genome.amb:md5,3a68b8b2287e07dd3f5f95f4344ba76e", + "genome.ann:md5,c32e11f6c859f166c7525a9c1d583567", + "genome.bwt:md5,0469c30a1e239dd08f68afe66fde99da", + "genome.pac:md5,983e3d2cd6f36e2546e6d25a0da78d66", + "genome.sa:md5,ab3952cabf026b48cd3eb5bccbb636d1" + ] + ] + ], + "versions": [ + "versions.yml:md5,0f20525da90e7489a7ebb02adca3265f" + ] + } + ], + "timestamp": "2023-10-17T17:20:20.180927714" + } +} \ No newline at end of file diff --git a/modules/nf-core/bwa/index/tests/tags.yml b/modules/nf-core/bwa/index/tests/tags.yml new file mode 100644 index 00000000..28bb483c --- /dev/null +++ b/modules/nf-core/bwa/index/tests/tags.yml @@ -0,0 +1,2 @@ +bwa/index: + - modules/nf-core/bwa/index/** diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index db9b5c6f..dc614595 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -5,6 +5,7 @@ import Constants include { BWAMEM2_INDEX } from '../../../modules/nf-core/bwamem2/index/main' +include { BWA_INDEX } from '../../../modules/nf-core/bwa/index/main' include { SAMTOOLS_DICT } from '../../../modules/nf-core/samtools/dict/main' include { SAMTOOLS_FAIDX } from '../../../modules/nf-core/samtools/faidx/main' include { STAR_GENOMEGENERATE } from '../../../modules/nf-core/star/genomegenerate/main' @@ -87,10 +88,16 @@ workflow PREPARE_REFERENCE { if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { if (!params.ref_data_genome_gridss_index) { + BWA_INDEX( + ch_genome_fasta, + ) + ch_versions = ch_versions.mix(BWA_INDEX.out.versions) + GRIDSS_INDEX( ch_genome_fasta, ch_genome_fai, ch_genome_dict, + BWA_INDEX.out.index, params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], ) ch_genome_gridss_index = GRIDSS_INDEX.out.index From 48cd0b0e4984c5e06795514b39e91b73352eefb0 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 1 May 2024 13:22:35 +1000 Subject: [PATCH 436/562] Update GRIDSS index module - add BWA index as input - update arguments for bioconda package --- modules/local/gridss/index/main.nf | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 98837904..b4bd6baf 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -11,6 +11,7 @@ process GRIDSS_INDEX { path genome_fasta path genome_fai path genome_dict + path genome_bwa_index path genome_alt output: @@ -24,16 +25,11 @@ process GRIDSS_INDEX { def args = task.ext.args ?: '' """ + # Symlink BWA indices next to assembly FASTA + ln -s \$(find -L ${genome_bwa_index} -type f) ./ + # Create indexes PrepareReference \\ - -Xmx${Math.round(task.memory.bytes * 0.95)} \\ - -XX:ParallelGCThreads=${task.cpus} \\ - -Dsamjdk.reference_fasta=${genome_fasta} \\ - -Dsamjdk.use_async_io_read_samtools=true \\ - -Dsamjdk.use_async_io_write_samtools=true \\ - -Dsamjdk.use_async_io_write_tribble=true \\ - -Dsamjdk.buffer_size=4194304 \\ - -Dsamjdk.async_io_read_threads=${task.cpus} \\ ${args} \\ REFERENCE_SEQUENCE=${genome_fasta} \\ CREATE_SEQUENCE_DICTIONARY='false' \\ From b317fef22d499946942c940300595e8373350560 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 1 May 2024 14:56:31 +1000 Subject: [PATCH 437/562] Fix GRIDSS index output --- modules/local/gridss/index/main.nf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index b4bd6baf..22e38955 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -38,10 +38,12 @@ process GRIDSS_INDEX { # Move under single directory for output mkdir -p gridss_index/ - mv ${genome_fasta.name}.{sa,pac,bwt,ann,amb} gridss_index/ mv ${genome_fasta.name}.img gridss_index/ mv ${genome_fasta.name}.gridsscache gridss_index/ + # Copy across BWA index + ln -s ../${genome_fasta.name}.{amb,ann,bwt,pac,sa} gridss_index/ + # Include ALT file where necessary if [[ -n "${genome_alt}" ]]; then ln -s ../${genome_alt} gridss_index/; From 855837aba6992213facdd6ee626f956745931325 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 1 May 2024 20:43:38 +1000 Subject: [PATCH 438/562] Include optional ALT file input for bwa-mem1 --- modules.json | 47 ++++++++++---- modules/nf-core/bwa/index/bwa-index.diff | 67 ++++++++++++++++++++ modules/nf-core/bwa/index/main.nf | 6 ++ subworkflows/local/prepare_reference/main.nf | 1 + 4 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 modules/nf-core/bwa/index/bwa-index.diff diff --git a/modules.json b/modules.json index 00b8cadc..440a6e9d 100644 --- a/modules.json +++ b/modules.json @@ -8,45 +8,62 @@ "bwa/index": { "branch": "master", "git_sha": "6278bf9afd4a4b2d00fa6052250e73da3d91546f", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ], + "patch": "modules/nf-core/bwa/index/bwa-index.diff" }, "bwamem2/index": { "branch": "master", "git_sha": "7081e04c18de9480948d34513a1c1e2d0fa9126d", - "installed_by": ["modules"], + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/bwamem2/index/bwamem2-index.diff" }, "gatk4/markduplicates": { "branch": "master", "git_sha": "e726b1730dff525bde4a6839e544dabfea4cd7fd", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "samtools/dict": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", - "installed_by": ["modules"], + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/samtools/dict/samtools-dict.diff" }, "samtools/faidx": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", - "installed_by": ["modules"], + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/samtools/faidx/samtools-faidx.diff" }, "samtools/flagstat": { "branch": "master", "git_sha": "bbb99cb8d679555cc01c98766de7869f83283545", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "samtools/sort": { "branch": "master", "git_sha": "d5d785b3d8b422cda9c6d84a23f629a8e9ff8cd8", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "star/genomegenerate": { "branch": "master", "git_sha": "a21faa6a3481af92a343a10926f59c189a2c16c9", - "installed_by": ["modules"], + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/star/genomegenerate/star-genomegenerate.diff" } } @@ -56,20 +73,26 @@ "utils_nextflow_pipeline": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": ["subworkflows"] + "installed_by": [ + "subworkflows" + ] }, "utils_nfcore_pipeline": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": ["subworkflows"] + "installed_by": [ + "subworkflows" + ] }, "utils_nfvalidation_plugin": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": ["subworkflows"] + "installed_by": [ + "subworkflows" + ] } } } } } -} +} \ No newline at end of file diff --git a/modules/nf-core/bwa/index/bwa-index.diff b/modules/nf-core/bwa/index/bwa-index.diff new file mode 100644 index 00000000..1fdcefb0 --- /dev/null +++ b/modules/nf-core/bwa/index/bwa-index.diff @@ -0,0 +1,67 @@ +Changes in module 'nf-core/bwa/index' +--- modules/nf-core/bwa/index/main.nf ++++ modules/nf-core/bwa/index/main.nf +@@ -8,25 +8,32 @@ + 'biocontainers/bwa:0.7.17--hed695b0_7' }" + + input: +- tuple val(meta), path(fasta) ++ path fasta ++ path alt + + output: +- tuple val(meta), path(bwa) , emit: index +- path "versions.yml" , emit: versions ++ path bwa_index , emit: index ++ path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when + + script: +- def prefix = task.ext.prefix ?: "${fasta.baseName}" ++ def prefix = task.ext.prefix ?: "${fasta.name}" + def args = task.ext.args ?: '' ++ + """ +- mkdir bwa ++ mkdir -p bwa_index/ + bwa \\ + index \\ + $args \\ +- -p bwa/${prefix} \\ ++ -p bwa_index/${prefix} \\ + $fasta ++ ++ # Include ALT file where necessary ++ if [[ -n "${alt}" ]]; then ++ ln -s ../${alt} bwa_index/; ++ fi; + + cat <<-END_VERSIONS > versions.yml + "${task.process}": +@@ -35,15 +42,15 @@ + """ + + stub: +- def prefix = task.ext.prefix ?: "${fasta.baseName}" ++ def prefix = task.ext.prefix ?: "${fasta.name}" + """ +- mkdir bwa ++ mkdir -p bwa_index/ + +- touch bwa/${prefix}.amb +- touch bwa/${prefix}.ann +- touch bwa/${prefix}.bwt +- touch bwa/${prefix}.pac +- touch bwa/${prefix}.sa ++ touch bwa_index/${prefix}.amb ++ touch bwa_index/${prefix}.ann ++ touch bwa_index/${prefix}.bwt ++ touch bwa_index/${prefix}.pac ++ touch bwa_index/${prefix}.sa + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + +************************************************************ diff --git a/modules/nf-core/bwa/index/main.nf b/modules/nf-core/bwa/index/main.nf index b81961a5..efb59703 100644 --- a/modules/nf-core/bwa/index/main.nf +++ b/modules/nf-core/bwa/index/main.nf @@ -9,6 +9,7 @@ process BWA_INDEX { input: path fasta + path alt output: path bwa_index , emit: index @@ -29,6 +30,11 @@ process BWA_INDEX { -p bwa_index/${prefix} \\ $fasta + # Include ALT file where necessary + if [[ -n "${alt}" ]]; then + ln -s ../${alt} bwa_index/; + fi; + cat <<-END_VERSIONS > versions.yml "${task.process}": bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index dc614595..e95abd4b 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -90,6 +90,7 @@ workflow PREPARE_REFERENCE { BWA_INDEX( ch_genome_fasta, + params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], ) ch_versions = ch_versions.mix(BWA_INDEX.out.versions) From 8ce2d6d324c8a61aa826b8768908d3107b10f1dc Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 07:26:00 +1000 Subject: [PATCH 439/562] Do not add ALT file during GRIDSS indexing This file should now be added upstream in the bwa-mem1 indexing process --- modules/local/gridss/index/main.nf | 11 ----------- subworkflows/local/prepare_reference/main.nf | 1 - 2 files changed, 12 deletions(-) diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 22e38955..918edf29 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -12,7 +12,6 @@ process GRIDSS_INDEX { path genome_fai path genome_dict path genome_bwa_index - path genome_alt output: path 'gridss_index', emit: index @@ -44,11 +43,6 @@ process GRIDSS_INDEX { # Copy across BWA index ln -s ../${genome_fasta.name}.{amb,ann,bwt,pac,sa} gridss_index/ - # Include ALT file where necessary - if [[ -n "${genome_alt}" ]]; then - ln -s ../${genome_alt} gridss_index/; - fi; - cat <<-END_VERSIONS > versions.yml "${task.process}": gridss: \$(CallVariants --version 2>&1 | sed 's/-gridss\$//') @@ -62,11 +56,6 @@ process GRIDSS_INDEX { touch gridss_index/${genome_fasta.name}.img touch gridss_index/${genome_fasta.name}.gridsscache - # Include ALT file where necessary - if [[ -n "${genome_alt}" ]]; then - ln -s ../${genome_alt} gridss_index/; - fi; - echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index e95abd4b..60c3f9c1 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -99,7 +99,6 @@ workflow PREPARE_REFERENCE { ch_genome_fai, ch_genome_dict, BWA_INDEX.out.index, - params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], ) ch_genome_gridss_index = GRIDSS_INDEX.out.index ch_versions = ch_versions.mix(GRIDSS_INDEX.out.versions) From 93d6a92db3f40c52cceb68c2bb8093fd7ce97447 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 12:36:15 +1000 Subject: [PATCH 440/562] Increase allocated memory for GRIDSS index process Pulled the process_medium_memory from metapep and applied to GRIDSS index. --- conf/base.config | 3 +++ modules/local/gridss/index/main.nf | 1 + 2 files changed, 4 insertions(+) diff --git a/conf/base.config b/conf/base.config index 222d22dd..e8443c5e 100644 --- a/conf/base.config +++ b/conf/base.config @@ -47,6 +47,9 @@ process { withLabel:process_long { time = { check_max( 20.h * task.attempt, 'time' ) } } + withLabel:process_medium_memory { + memory = { check_max( 50.GB * task.attempt, 'memory' ) } + } withLabel:process_high_memory { memory = { check_max( 200.GB * task.attempt, 'memory' ) } } diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 918edf29..4d30e5ef 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -1,6 +1,7 @@ process GRIDSS_INDEX { tag "${genome_fasta.name}" label 'process_single' + label 'process_medium_memory' conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? From bf26d4febf1ed9ca35e77dd224a57ea2d028ea68 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 13:07:45 +1000 Subject: [PATCH 441/562] Output ALT file in GRIDSS index if present --- modules/local/gridss/index/main.nf | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 4d30e5ef..340f4b4b 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -41,9 +41,14 @@ process GRIDSS_INDEX { mv ${genome_fasta.name}.img gridss_index/ mv ${genome_fasta.name}.gridsscache gridss_index/ - # Copy across BWA index + # Symlink BWA index files into output directory ln -s ../${genome_fasta.name}.{amb,ann,bwt,pac,sa} gridss_index/ + # Also include the ALT file if present + if [[ -e ${genome_fasta.name}.alt || -L ${genome_fasta.name}.alt ]]; then + ln -s ../${genome_fasta.name}.alt gridss_index/; + fi; + cat <<-END_VERSIONS > versions.yml "${task.process}": gridss: \$(CallVariants --version 2>&1 | sed 's/-gridss\$//') From c79cc5c5a45182d513594f9bec4ea70bf0f29485 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 18:37:56 +1000 Subject: [PATCH 442/562] Rename STAR index output directory --- modules/nf-core/star/genomegenerate/main.nf | 64 ++++++------- .../genomegenerate/star-genomegenerate.diff | 96 ++++++++++++++++++- 2 files changed, 127 insertions(+), 33 deletions(-) diff --git a/modules/nf-core/star/genomegenerate/main.nf b/modules/nf-core/star/genomegenerate/main.nf index 1757318e..494f3c16 100644 --- a/modules/nf-core/star/genomegenerate/main.nf +++ b/modules/nf-core/star/genomegenerate/main.nf @@ -12,7 +12,7 @@ process STAR_GENOMEGENERATE { path gtf output: - path "star" , emit: index + path "star_index" , emit: index path "versions.yml", emit: versions when: @@ -25,10 +25,10 @@ process STAR_GENOMEGENERATE { def include_gtf = gtf ? "--sjdbGTFfile $gtf" : '' if (args_list.contains('--genomeSAindexNbases')) { """ - mkdir star + mkdir -p star_index/ STAR \\ --runMode genomeGenerate \\ - --genomeDir star/ \\ + --genomeDir star_index/ \\ --genomeFastaFiles $fasta \\ $include_gtf \\ --runThreadN $task.cpus \\ @@ -47,10 +47,10 @@ process STAR_GENOMEGENERATE { samtools faidx $fasta NUM_BASES=`gawk '{sum = sum + \$2}END{if ((log(sum)/log(2))/2 - 1 > 14) {printf "%.0f", 14} else {printf "%.0f", (log(sum)/log(2))/2 - 1}}' ${fasta}.fai` - mkdir star + mkdir -p star_index/ STAR \\ --runMode genomeGenerate \\ - --genomeDir star/ \\ + --genomeDir star_index/ \\ --genomeFastaFiles $fasta \\ $include_gtf \\ --runThreadN $task.cpus \\ @@ -70,23 +70,23 @@ process STAR_GENOMEGENERATE { stub: if (gtf) { """ - mkdir star - touch star/Genome - touch star/Log.out - touch star/SA - touch star/SAindex - touch star/chrLength.txt - touch star/chrName.txt - touch star/chrNameLength.txt - touch star/chrStart.txt - touch star/exonGeTrInfo.tab - touch star/exonInfo.tab - touch star/geneInfo.tab - touch star/genomeParameters.txt - touch star/sjdbInfo.txt - touch star/sjdbList.fromGTF.out.tab - touch star/sjdbList.out.tab - touch star/transcriptInfo.tab + mkdir -p star_index/ + touch star_index/Genome + touch star_index/Log.out + touch star_index/SA + touch star_index/SAindex + touch star_index/chrLength.txt + touch star_index/chrName.txt + touch star_index/chrNameLength.txt + touch star_index/chrStart.txt + touch star_index/exonGeTrInfo.tab + touch star_index/exonInfo.tab + touch star_index/geneInfo.tab + touch star_index/genomeParameters.txt + touch star_index/sjdbInfo.txt + touch star_index/sjdbList.fromGTF.out.tab + touch star_index/sjdbList.out.tab + touch star_index/transcriptInfo.tab cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -97,16 +97,16 @@ process STAR_GENOMEGENERATE { """ } else { """ - mkdir star - touch star/Genome - touch star/Log.out - touch star/SA - touch star/SAindex - touch star/chrLength.txt - touch star/chrName.txt - touch star/chrNameLength.txt - touch star/chrStart.txt - touch star/genomeParameters.txt + mkdir -p star_index/ + touch star_index/Genome + touch star_index/Log.out + touch star_index/SA + touch star_index/SAindex + touch star_index/chrLength.txt + touch star_index/chrName.txt + touch star_index/chrNameLength.txt + touch star_index/chrStart.txt + touch star_index/genomeParameters.txt cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/star/genomegenerate/star-genomegenerate.diff b/modules/nf-core/star/genomegenerate/star-genomegenerate.diff index f7fbf966..4baf543a 100644 --- a/modules/nf-core/star/genomegenerate/star-genomegenerate.diff +++ b/modules/nf-core/star/genomegenerate/star-genomegenerate.diff @@ -13,10 +13,104 @@ Changes in module 'nf-core/star/genomegenerate' output: - tuple val(meta), path("star") , emit: index - path "versions.yml" , emit: versions -+ path "star" , emit: index ++ path "star_index" , emit: index + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when +@@ -25,10 +25,10 @@ + def include_gtf = gtf ? "--sjdbGTFfile $gtf" : '' + if (args_list.contains('--genomeSAindexNbases')) { + """ +- mkdir star ++ mkdir -p star_index/ + STAR \\ + --runMode genomeGenerate \\ +- --genomeDir star/ \\ ++ --genomeDir star_index/ \\ + --genomeFastaFiles $fasta \\ + $include_gtf \\ + --runThreadN $task.cpus \\ +@@ -47,10 +47,10 @@ + samtools faidx $fasta + NUM_BASES=`gawk '{sum = sum + \$2}END{if ((log(sum)/log(2))/2 - 1 > 14) {printf "%.0f", 14} else {printf "%.0f", (log(sum)/log(2))/2 - 1}}' ${fasta}.fai` + +- mkdir star ++ mkdir -p star_index/ + STAR \\ + --runMode genomeGenerate \\ +- --genomeDir star/ \\ ++ --genomeDir star_index/ \\ + --genomeFastaFiles $fasta \\ + $include_gtf \\ + --runThreadN $task.cpus \\ +@@ -70,23 +70,23 @@ + stub: + if (gtf) { + """ +- mkdir star +- touch star/Genome +- touch star/Log.out +- touch star/SA +- touch star/SAindex +- touch star/chrLength.txt +- touch star/chrName.txt +- touch star/chrNameLength.txt +- touch star/chrStart.txt +- touch star/exonGeTrInfo.tab +- touch star/exonInfo.tab +- touch star/geneInfo.tab +- touch star/genomeParameters.txt +- touch star/sjdbInfo.txt +- touch star/sjdbList.fromGTF.out.tab +- touch star/sjdbList.out.tab +- touch star/transcriptInfo.tab ++ mkdir -p star_index/ ++ touch star_index/Genome ++ touch star_index/Log.out ++ touch star_index/SA ++ touch star_index/SAindex ++ touch star_index/chrLength.txt ++ touch star_index/chrName.txt ++ touch star_index/chrNameLength.txt ++ touch star_index/chrStart.txt ++ touch star_index/exonGeTrInfo.tab ++ touch star_index/exonInfo.tab ++ touch star_index/geneInfo.tab ++ touch star_index/genomeParameters.txt ++ touch star_index/sjdbInfo.txt ++ touch star_index/sjdbList.fromGTF.out.tab ++ touch star_index/sjdbList.out.tab ++ touch star_index/transcriptInfo.tab + + cat <<-END_VERSIONS > versions.yml + "${task.process}": +@@ -97,16 +97,16 @@ + """ + } else { + """ +- mkdir star +- touch star/Genome +- touch star/Log.out +- touch star/SA +- touch star/SAindex +- touch star/chrLength.txt +- touch star/chrName.txt +- touch star/chrNameLength.txt +- touch star/chrStart.txt +- touch star/genomeParameters.txt ++ mkdir -p star_index/ ++ touch star_index/Genome ++ touch star_index/Log.out ++ touch star_index/SA ++ touch star_index/SAindex ++ touch star_index/chrLength.txt ++ touch star_index/chrName.txt ++ touch star_index/chrNameLength.txt ++ touch star_index/chrStart.txt ++ touch star_index/genomeParameters.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": ************************************************************ From 7a0d9a068bec181b6d1da738c1a0488922825c19 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 18:49:17 +1000 Subject: [PATCH 443/562] Rename bwa-mem2 index output directory --- .../nf-core/bwamem2/index/bwamem2-index.diff | 30 +++++++++++-------- modules/nf-core/bwamem2/index/main.nf | 24 +++++++-------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/modules/nf-core/bwamem2/index/bwamem2-index.diff b/modules/nf-core/bwamem2/index/bwamem2-index.diff index 3cd4bb0e..0fa349b5 100644 --- a/modules/nf-core/bwamem2/index/bwamem2-index.diff +++ b/modules/nf-core/bwamem2/index/bwamem2-index.diff @@ -20,8 +20,8 @@ Changes in module 'nf-core/bwamem2/index' output: - tuple val(meta), path("bwamem2"), emit: index - path "versions.yml" , emit: versions -+ path bwamem2 , emit: index -+ path "versions.yml", emit: versions ++ path "bwa-mem2_index", emit: index ++ path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when @@ -32,15 +32,16 @@ Changes in module 'nf-core/bwamem2/index' + """ - mkdir bwamem2 -+ mkdir -p bwamem2/ ++ mkdir -p bwa-mem2_index/ bwa-mem2 \\ index \\ $args \\ - $fasta -p bwamem2/${prefix} +- $fasta -p bwamem2/${prefix} ++ $fasta -p bwa-mem2_index/${prefix} + + # Include ALT file where necessary + if [[ -n "${alt}" ]]; then -+ ln -s ../${alt} bwamem2/; ++ ln -s ../${alt} bwa-mem2_index/; + fi; cat <<-END_VERSIONS > versions.yml @@ -50,16 +51,21 @@ Changes in module 'nf-core/bwamem2/index' """ - mkdir bwamem2 -+ mkdir -p bwamem2/ - touch bwamem2/${prefix}.0123 - touch bwamem2/${prefix}.ann - touch bwamem2/${prefix}.pac - touch bwamem2/${prefix}.amb - touch bwamem2/${prefix}.bwt.2bit.64 +- touch bwamem2/${prefix}.0123 +- touch bwamem2/${prefix}.ann +- touch bwamem2/${prefix}.pac +- touch bwamem2/${prefix}.amb +- touch bwamem2/${prefix}.bwt.2bit.64 ++ mkdir -p bwa-mem2_index/ ++ touch bwa-mem2_index/${prefix}.0123 ++ touch bwa-mem2_index/${prefix}.ann ++ touch bwa-mem2_index/${prefix}.pac ++ touch bwa-mem2_index/${prefix}.amb ++ touch bwa-mem2_index/${prefix}.bwt.2bit.64 + + # Include ALT file where necessary + if [[ -n "${alt}" ]]; then -+ ln -s ../${alt} bwamem2/; ++ ln -s ../${alt} bwa-mem2_index/; + fi; cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/bwamem2/index/main.nf b/modules/nf-core/bwamem2/index/main.nf index 4d4f793c..9c4171d8 100644 --- a/modules/nf-core/bwamem2/index/main.nf +++ b/modules/nf-core/bwamem2/index/main.nf @@ -13,8 +13,8 @@ process BWAMEM2_INDEX { path alt output: - path bwamem2 , emit: index - path "versions.yml", emit: versions + path "bwa-mem2_index", emit: index + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when @@ -24,15 +24,15 @@ process BWAMEM2_INDEX { def args = task.ext.args ?: '' """ - mkdir -p bwamem2/ + mkdir -p bwa-mem2_index/ bwa-mem2 \\ index \\ $args \\ - $fasta -p bwamem2/${prefix} + $fasta -p bwa-mem2_index/${prefix} # Include ALT file where necessary if [[ -n "${alt}" ]]; then - ln -s ../${alt} bwamem2/; + ln -s ../${alt} bwa-mem2_index/; fi; cat <<-END_VERSIONS > versions.yml @@ -45,16 +45,16 @@ process BWAMEM2_INDEX { def prefix = task.ext.prefix ?: "${fasta}" """ - mkdir -p bwamem2/ - touch bwamem2/${prefix}.0123 - touch bwamem2/${prefix}.ann - touch bwamem2/${prefix}.pac - touch bwamem2/${prefix}.amb - touch bwamem2/${prefix}.bwt.2bit.64 + mkdir -p bwa-mem2_index/ + touch bwa-mem2_index/${prefix}.0123 + touch bwa-mem2_index/${prefix}.ann + touch bwa-mem2_index/${prefix}.pac + touch bwa-mem2_index/${prefix}.amb + touch bwa-mem2_index/${prefix}.bwt.2bit.64 # Include ALT file where necessary if [[ -n "${alt}" ]]; then - ln -s ../${alt} bwamem2/; + ln -s ../${alt} bwa-mem2_index/; fi; cat <<-END_VERSIONS > versions.yml From f167cf6c2b926ab3a2287ed3a15d5f6749be3fc7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 20:49:59 +1000 Subject: [PATCH 444/562] Make PAVE genome version comparison more robust --- modules/local/pave/germline/main.nf | 4 ++-- modules/local/pave/somatic/main.nf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 8c297bda..1d85ada9 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -35,9 +35,9 @@ process PAVE_GERMLINE { script: def args = task.ext.args ?: '' def gnomad_args - if (genome_ver == '37') { + if (genome_ver.toString() == '37') { gnomad_args = "-gnomad_freq_file ${gnomad_resource}" - } else if (genome_ver == '38') { + } else if (genome_ver.toString() == '38') { gnomad_args = "-gnomad_freq_dir ${gnomad_resource}" } else { log.error "got bad genome version: ${genome_ver}" diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index dfecf48c..a2e782b9 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -35,10 +35,10 @@ process PAVE_SOMATIC { def pon_filters def gnomad_args - if (genome_ver == '37') { + if (genome_ver.toString() == '37') { pon_filters = 'HOTSPOT:10:5;PANEL:6:5;UNKNOWN:6:0' gnomad_args = "-gnomad_freq_file ${gnomad_resource}" - } else if (genome_ver == '38') { + } else if (genome_ver.toString() == '38') { pon_filters = 'HOTSPOT:5:5;PANEL:2:5;UNKNOWN:2:0' gnomad_args = "-gnomad_freq_dir ${gnomad_resource}" } else { From 45ddb0f789ab2d8844cafa7db06989f0bf9b4c78 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 21:42:46 +1000 Subject: [PATCH 445/562] Use STAR 2.7.3a for indexing --- .../star/genomegenerate/environment.yml | 5 +- modules/nf-core/star/genomegenerate/main.nf | 59 ++---- .../genomegenerate/star-genomegenerate.diff | 179 ++++++++++++------ 3 files changed, 141 insertions(+), 102 deletions(-) diff --git a/modules/nf-core/star/genomegenerate/environment.yml b/modules/nf-core/star/genomegenerate/environment.yml index 791f255e..9d03dd2e 100644 --- a/modules/nf-core/star/genomegenerate/environment.yml +++ b/modules/nf-core/star/genomegenerate/environment.yml @@ -4,7 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::samtools=1.18 - - bioconda::htslib=1.18 - - bioconda::star=2.7.10a - - conda-forge::gawk=5.1.0 + - bioconda::star=2.7.3a diff --git a/modules/nf-core/star/genomegenerate/main.nf b/modules/nf-core/star/genomegenerate/main.nf index 494f3c16..0b1964d9 100644 --- a/modules/nf-core/star/genomegenerate/main.nf +++ b/modules/nf-core/star/genomegenerate/main.nf @@ -4,8 +4,8 @@ process STAR_GENOMEGENERATE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:ded3841da0194af2701c780e9b3d653a85d27489-0' : - 'biocontainers/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:ded3841da0194af2701c780e9b3d653a85d27489-0' }" + 'https://depot.galaxyproject.org/singularity/star:2.7.3a--0' : + 'quay.io/biocontainers/star:2.7.3a--0' }" input: path fasta @@ -23,49 +23,24 @@ process STAR_GENOMEGENERATE { def args_list = args.tokenize() def memory = task.memory ? "--limitGenomeGenerateRAM ${task.memory.toBytes() - 100000000}" : '' def include_gtf = gtf ? "--sjdbGTFfile $gtf" : '' - if (args_list.contains('--genomeSAindexNbases')) { - """ - mkdir -p star_index/ - STAR \\ - --runMode genomeGenerate \\ - --genomeDir star_index/ \\ - --genomeFastaFiles $fasta \\ - $include_gtf \\ - --runThreadN $task.cpus \\ - $memory \\ - $args - cat <<-END_VERSIONS > versions.yml - "${task.process}": - star: \$(STAR --version | sed -e "s/STAR_//g") - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') - END_VERSIONS - """ - } else { - """ - samtools faidx $fasta - NUM_BASES=`gawk '{sum = sum + \$2}END{if ((log(sum)/log(2))/2 - 1 > 14) {printf "%.0f", 14} else {printf "%.0f", (log(sum)/log(2))/2 - 1}}' ${fasta}.fai` + """ + mkdir -p star_index/ - mkdir -p star_index/ - STAR \\ - --runMode genomeGenerate \\ - --genomeDir star_index/ \\ - --genomeFastaFiles $fasta \\ - $include_gtf \\ - --runThreadN $task.cpus \\ - --genomeSAindexNbases \$NUM_BASES \\ - $memory \\ - $args + STAR \\ + --runMode genomeGenerate \\ + --genomeDir star_index/ \\ + --genomeFastaFiles $fasta \\ + $include_gtf \\ + --runThreadN $task.cpus \\ + $memory \\ + $args - cat <<-END_VERSIONS > versions.yml - "${task.process}": - star: \$(STAR --version | sed -e "s/STAR_//g") - samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') - END_VERSIONS + cat <<-END_VERSIONS > versions.yml + "${task.process}": + star: \$(STAR --version | sed -e "s/STAR_//g") + END_VERSIONS """ - } stub: if (gtf) { @@ -92,7 +67,6 @@ process STAR_GENOMEGENERATE { "${task.process}": star: \$(STAR --version | sed -e "s/STAR_//g") samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') END_VERSIONS """ } else { @@ -112,7 +86,6 @@ process STAR_GENOMEGENERATE { "${task.process}": star: \$(STAR --version | sed -e "s/STAR_//g") samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') END_VERSIONS """ } diff --git a/modules/nf-core/star/genomegenerate/star-genomegenerate.diff b/modules/nf-core/star/genomegenerate/star-genomegenerate.diff index 4baf543a..ae33e85b 100644 --- a/modules/nf-core/star/genomegenerate/star-genomegenerate.diff +++ b/modules/nf-core/star/genomegenerate/star-genomegenerate.diff @@ -1,8 +1,26 @@ Changes in module 'nf-core/star/genomegenerate' +--- modules/nf-core/star/genomegenerate/environment.yml ++++ modules/nf-core/star/genomegenerate/environment.yml +@@ -4,7 +4,4 @@ + - bioconda + - defaults + dependencies: +- - bioconda::samtools=1.18 +- - bioconda::htslib=1.18 +- - bioconda::star=2.7.10a +- - conda-forge::gawk=5.1.0 ++ - bioconda::star=2.7.3a + --- modules/nf-core/star/genomegenerate/main.nf +++ modules/nf-core/star/genomegenerate/main.nf -@@ -8,12 +8,12 @@ - 'biocontainers/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:ded3841da0194af2701c780e9b3d653a85d27489-0' }" +@@ -4,16 +4,16 @@ + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? +- 'https://depot.galaxyproject.org/singularity/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:ded3841da0194af2701c780e9b3d653a85d27489-0' : +- 'biocontainers/mulled-v2-1fa26d1ce03c295fe2fdcf85831a92fbcbd7e8c2:ded3841da0194af2701c780e9b3d653a85d27489-0' }" ++ 'https://depot.galaxyproject.org/singularity/star:2.7.3a--0' : ++ 'quay.io/biocontainers/star:2.7.3a--0' }" input: - tuple val(meta), path(fasta) @@ -18,53 +36,42 @@ Changes in module 'nf-core/star/genomegenerate' when: task.ext.when == null || task.ext.when -@@ -25,10 +25,10 @@ +@@ -23,96 +23,69 @@ + def args_list = args.tokenize() + def memory = task.memory ? "--limitGenomeGenerateRAM ${task.memory.toBytes() - 100000000}" : '' def include_gtf = gtf ? "--sjdbGTFfile $gtf" : '' - if (args_list.contains('--genomeSAindexNbases')) { +- if (args_list.contains('--genomeSAindexNbases')) { ++ ++ """ ++ mkdir -p star_index/ ++ ++ STAR \\ ++ --runMode genomeGenerate \\ ++ --genomeDir star_index/ \\ ++ --genomeFastaFiles $fasta \\ ++ $include_gtf \\ ++ --runThreadN $task.cpus \\ ++ $memory \\ ++ $args ++ ++ cat <<-END_VERSIONS > versions.yml ++ "${task.process}": ++ star: \$(STAR --version | sed -e "s/STAR_//g") ++ END_VERSIONS """ - mkdir star -+ mkdir -p star_index/ - STAR \\ - --runMode genomeGenerate \\ -- --genomeDir star/ \\ -+ --genomeDir star_index/ \\ - --genomeFastaFiles $fasta \\ - $include_gtf \\ - --runThreadN $task.cpus \\ -@@ -47,10 +47,10 @@ - samtools faidx $fasta - NUM_BASES=`gawk '{sum = sum + \$2}END{if ((log(sum)/log(2))/2 - 1 > 14) {printf "%.0f", 14} else {printf "%.0f", (log(sum)/log(2))/2 - 1}}' ${fasta}.fai` - -- mkdir star -+ mkdir -p star_index/ - STAR \\ - --runMode genomeGenerate \\ +- STAR \\ +- --runMode genomeGenerate \\ - --genomeDir star/ \\ -+ --genomeDir star_index/ \\ - --genomeFastaFiles $fasta \\ - $include_gtf \\ - --runThreadN $task.cpus \\ -@@ -70,23 +70,23 @@ - stub: - if (gtf) { - """ -- mkdir star -- touch star/Genome -- touch star/Log.out -- touch star/SA -- touch star/SAindex -- touch star/chrLength.txt -- touch star/chrName.txt -- touch star/chrNameLength.txt -- touch star/chrStart.txt -- touch star/exonGeTrInfo.tab -- touch star/exonInfo.tab -- touch star/geneInfo.tab -- touch star/genomeParameters.txt -- touch star/sjdbInfo.txt -- touch star/sjdbList.fromGTF.out.tab -- touch star/sjdbList.out.tab -- touch star/transcriptInfo.tab +- --genomeFastaFiles $fasta \\ +- $include_gtf \\ +- --runThreadN $task.cpus \\ +- $memory \\ +- $args ++ ++ stub: ++ if (gtf) { ++ """ + mkdir -p star_index/ + touch star_index/Genome + touch star_index/Log.out @@ -85,20 +92,26 @@ Changes in module 'nf-core/star/genomegenerate' cat <<-END_VERSIONS > versions.yml "${task.process}": -@@ -97,16 +97,16 @@ + star: \$(STAR --version | sed -e "s/STAR_//g") + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') +- gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') + END_VERSIONS """ } else { """ +- samtools faidx $fasta +- NUM_BASES=`gawk '{sum = sum + \$2}END{if ((log(sum)/log(2))/2 - 1 > 14) {printf "%.0f", 14} else {printf "%.0f", (log(sum)/log(2))/2 - 1}}' ${fasta}.fai` +- - mkdir star -- touch star/Genome -- touch star/Log.out -- touch star/SA -- touch star/SAindex -- touch star/chrLength.txt -- touch star/chrName.txt -- touch star/chrNameLength.txt -- touch star/chrStart.txt -- touch star/genomeParameters.txt +- STAR \\ +- --runMode genomeGenerate \\ +- --genomeDir star/ \\ +- --genomeFastaFiles $fasta \\ +- $include_gtf \\ +- --runThreadN $task.cpus \\ +- --genomeSAindexNbases \$NUM_BASES \\ +- $memory \\ +- $args + mkdir -p star_index/ + touch star_index/Genome + touch star_index/Log.out @@ -112,5 +125,61 @@ Changes in module 'nf-core/star/genomegenerate' cat <<-END_VERSIONS > versions.yml "${task.process}": + star: \$(STAR --version | sed -e "s/STAR_//g") + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') +- gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') +- END_VERSIONS +- """ +- } +- +- stub: +- if (gtf) { +- """ +- mkdir star +- touch star/Genome +- touch star/Log.out +- touch star/SA +- touch star/SAindex +- touch star/chrLength.txt +- touch star/chrName.txt +- touch star/chrNameLength.txt +- touch star/chrStart.txt +- touch star/exonGeTrInfo.tab +- touch star/exonInfo.tab +- touch star/geneInfo.tab +- touch star/genomeParameters.txt +- touch star/sjdbInfo.txt +- touch star/sjdbList.fromGTF.out.tab +- touch star/sjdbList.out.tab +- touch star/transcriptInfo.tab +- +- cat <<-END_VERSIONS > versions.yml +- "${task.process}": +- star: \$(STAR --version | sed -e "s/STAR_//g") +- samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') +- gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') +- END_VERSIONS +- """ +- } else { +- """ +- mkdir star +- touch star/Genome +- touch star/Log.out +- touch star/SA +- touch star/SAindex +- touch star/chrLength.txt +- touch star/chrName.txt +- touch star/chrNameLength.txt +- touch star/chrStart.txt +- touch star/genomeParameters.txt +- +- cat <<-END_VERSIONS > versions.yml +- "${task.process}": +- star: \$(STAR --version | sed -e "s/STAR_//g") +- samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') +- gawk: \$(echo \$(gawk --version 2>&1) | sed 's/^.*GNU Awk //; s/, .*\$//') + END_VERSIONS + """ + } ************************************************************ From 88baaf60fd11fb51c32ba18022383bf36e4b0d8d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 3 May 2024 09:46:39 +1000 Subject: [PATCH 446/562] Use bwa-mem2 to realign HLA reads --- .../custom/lilac_realign_reads_lilac/main.nf | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf index a926254f..c9e02f0f 100644 --- a/modules/local/custom/lilac_realign_reads_lilac/main.nf +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -2,10 +2,10 @@ process CUSTOM_REALIGNREADS { tag "${meta.id}" label 'process_low' - conda "bwa=0.7.17 samtools=1.19.2 sambamba=1.0" + conda "bioconda::bwa-mem2=2.2.1 bioconda::samtools=1.19.2 bioconda::sambamba=1.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-4908f45b5b676e6a2fed6b1977d445b16b7b8dee:2411d64e0a784487e81828123aaf68a549531e5c-0' : - 'quay.io/biocontainers/mulled-v2-4908f45b5b676e6a2fed6b1977d445b16b7b8dee:2411d64e0a784487e81828123aaf68a549531e5c-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' : + 'quay.io/biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" input: tuple val(meta), path(bam), path(bai) @@ -30,20 +30,30 @@ process CUSTOM_REALIGNREADS { -0 ${meta.sample_id}_other.fastq.gz \\ -s ${meta.sample_id}_singleton.fastq.gz; - bwa mem \\ - -t${task.cpus} \\ + bwa-mem2 mem \\ -Y \\ + -t ${task.cpus} \\ ${reference} \\ ${meta.sample_id}_R1.fastq.gz \\ ${meta.sample_id}_R2.fastq.gz | \\ - samtools sort -T tmp -o ${bam.baseName}.realigned.bam - samtools index ${bam.baseName}.realigned.bam + \\ + sambamba view \\ + --sam-input \\ + --format bam \\ + --compression-level 0 \\ + --nthreads ${task.cpus} \\ + /dev/stdin | \\ + \\ + sambamba sort \\ + --nthreads ${task.cpus} \\ + --out ${bam.baseName}.realigned.bam \\ + /dev/stdin cat <<-END_VERSIONS > versions.yml "${task.process}": - bwa: \$(echo \$(bwa 2>&1) | sed 's/^.*Version: //; s/Contact:.*\$//') + bwa-mem2: \$(bwa-mem2 version 2>/dev/null) samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') - sambamba: \$(sambamba --version 2>&1 | sed -n '/sambamba/ s/^sambamba \\(.\\+\\)/\\1/p' | head -n1) + sambamba: \$(sambamba --version 2>&1 | egrep '^sambamba' | head -n 1 | awk '{ print \$NF }') END_VERSIONS """ From 008666d1f2b466b5b4e0d789ee716572f293dab8 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 3 May 2024 12:11:46 +1000 Subject: [PATCH 447/562] Clean up comments, whitespace, needed config --- lib/Processes.groovy | 2 +- lib/WorkflowMain.groovy | 4 ---- nextflow.config | 13 ------------- 3 files changed, 1 insertion(+), 18 deletions(-) diff --git a/lib/Processes.groovy b/lib/Processes.groovy index cd50e858..f91fc606 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -4,7 +4,7 @@ import Utils class Processes { - public static getRunStages(include, exclude, manual_select, log) { + public static getRunStages(include, exclude, manual_select, log) { def processes = manual_select ? [] : Constants.Process.values().toList() def include_list = this.getProcessList(include, log) def exclude_list = this.getProcessList(exclude, log) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 1efa634c..ae3ad687 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -202,10 +202,6 @@ class WorkflowMain { } - - // TODO(SW): implement additional requirements for ALT file - // disallow alt file when params.genome_type == no_alt - // require alt filename to be genome_fasta + '.alt' if (params.ref_data_genome_alt !== null) { if (params.genome_type != 'alt') { log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + diff --git a/nextflow.config b/nextflow.config index d45dcfde..597a2c82 100644 --- a/nextflow.config +++ b/nextflow.config @@ -273,19 +273,6 @@ report { trace { enabled = true file = "${params.outdir}/pipeline_info/execution_trace_${trace_timestamp}.txt" - - - - - - - overwrite = true - - - - - - } dag { enabled = true From 3adcfc6efd58dd1b639fdf32117015eb0093adbd Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 3 May 2024 13:24:43 +1000 Subject: [PATCH 448/562] Apply linting --- modules.json | 48 +++++-------------- subworkflows/local/prepare_reference/main.nf | 4 +- .../nf-core/utils_nfcore_pipeline/main.nf | 8 +++- 3 files changed, 22 insertions(+), 38 deletions(-) diff --git a/modules.json b/modules.json index 440a6e9d..be653409 100644 --- a/modules.json +++ b/modules.json @@ -8,62 +8,46 @@ "bwa/index": { "branch": "master", "git_sha": "6278bf9afd4a4b2d00fa6052250e73da3d91546f", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/bwa/index/bwa-index.diff" }, "bwamem2/index": { "branch": "master", "git_sha": "7081e04c18de9480948d34513a1c1e2d0fa9126d", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/bwamem2/index/bwamem2-index.diff" }, "gatk4/markduplicates": { "branch": "master", "git_sha": "e726b1730dff525bde4a6839e544dabfea4cd7fd", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/dict": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/samtools/dict/samtools-dict.diff" }, "samtools/faidx": { "branch": "master", "git_sha": "cf5b9c30a2adacc581793afb79fae5f5b50bed01", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/samtools/faidx/samtools-faidx.diff" }, "samtools/flagstat": { "branch": "master", "git_sha": "bbb99cb8d679555cc01c98766de7869f83283545", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/sort": { "branch": "master", "git_sha": "d5d785b3d8b422cda9c6d84a23f629a8e9ff8cd8", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "star/genomegenerate": { "branch": "master", "git_sha": "a21faa6a3481af92a343a10926f59c189a2c16c9", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/star/genomegenerate/star-genomegenerate.diff" } } @@ -73,26 +57,20 @@ "utils_nextflow_pipeline": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": [ - "subworkflows" - ] + "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": [ - "subworkflows" - ] + "git_sha": "92de218a329bfc9a9033116eb5f65fd270e72ba3", + "installed_by": ["subworkflows"] }, "utils_nfvalidation_plugin": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", - "installed_by": [ - "subworkflows" - ] + "installed_by": ["subworkflows"] } } } } } -} \ No newline at end of file +} diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 60c3f9c1..3d0ab042 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -60,8 +60,8 @@ workflow PREPARE_REFERENCE { if (!params.ref_data_genome_bwa_index) { BWAMEM2_INDEX( - ch_genome_fasta, - params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], + ch_genome_fasta, + params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], ) ch_genome_bwa_index = BWAMEM2_INDEX.out.index ch_versions = ch_versions.mix(BWAMEM2_INDEX.out.versions) diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index a8b55d6f..14558c39 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -65,9 +65,15 @@ def checkProfileProvided(nextflow_cli_args) { // Citation string for pipeline // def workflowCitation() { + def temp_doi_ref = "" + String[] manifest_doi = workflow.manifest.doi.tokenize(",") + // Using a loop to handle multiple DOIs + // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers + // Removing ` ` since the manifest.doi is a string and not a proper list + for (String doi_ref: manifest_doi) temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + "* The pipeline\n" + - " ${workflow.manifest.doi}\n\n" + + temp_doi_ref + "\n" + "* The nf-core framework\n" + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + "* Software dependencies\n" + From 103f2e7b261701d2443e7bf8fc81a7323ada6c58 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 16:32:35 +1000 Subject: [PATCH 449/562] Use nf-core indenting for subworkflows --- subworkflows/local/amber_profiling/main.nf | 128 ++-- subworkflows/local/bamtools_metrics/main.nf | 194 ++--- subworkflows/local/chord_prediction/main.nf | 130 ++-- subworkflows/local/cobalt_profiling/main.nf | 160 ++-- subworkflows/local/cuppa_prediction/main.nf | 212 +++--- subworkflows/local/flagstat_metrics/main.nf | 184 ++--- .../local/gridss_svprep_calling/main.nf | 696 +++++++++--------- subworkflows/local/gripss_filtering/main.nf | 308 ++++---- .../local/isofox_quantification/main.nf | 140 ++-- subworkflows/local/lilac_calling/main.nf | 360 ++++----- subworkflows/local/linx_annotation/main.nf | 268 +++---- subworkflows/local/linx_plotting/main.nf | 178 ++--- subworkflows/local/orange_reporting/main.nf | 430 +++++------ subworkflows/local/pave_annotation/main.nf | 310 ++++---- subworkflows/local/prepare_inputs/main.nf | 11 +- subworkflows/local/prepare_reference/main.nf | 392 +++++----- subworkflows/local/purple_calling/main.nf | 250 +++---- subworkflows/local/read_alignment_dna/main.nf | 331 ++++----- subworkflows/local/read_alignment_rna/main.nf | 387 +++++----- subworkflows/local/read_processing/main.nf | 205 +++--- subworkflows/local/sage_append/main.nf | 300 ++++---- subworkflows/local/sage_calling/main.nf | 344 ++++----- subworkflows/local/sigs_fitting/main.nf | 122 +-- .../local/virusbreakend_calling/main.nf | 270 +++---- 24 files changed, 3156 insertions(+), 3154 deletions(-) diff --git a/subworkflows/local/amber_profiling/main.nf b/subworkflows/local/amber_profiling/main.nf index a4cb59f0..179888bf 100644 --- a/subworkflows/local/amber_profiling/main.nf +++ b/subworkflows/local/amber_profiling/main.nf @@ -9,82 +9,82 @@ include { AMBER } from '../../../modules/local/amber/main' workflow AMBER_PROFILING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] - ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] - // Reference data - genome_version // channel: [mandatory] genome version - heterozygous_sites // channel: [optional] /path/to/heterozygous_sites - target_region_bed // channel: [optional] /path/to/target_region_bed + // Reference data + genome_version // channel: [mandatory] genome version + heterozygous_sites // channel: [optional] /path/to/heterozygous_sites + target_region_bed // channel: [optional] /path/to/target_region_bed main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() - // Select input sources and sort - // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai] - // channel: skip: [ meta ] - ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( - ch_tumor_bam, - ch_normal_bam, - ) - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - return [ - meta, - Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), - Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), - ] - } - .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.AMBER_DIR) - runnable: tumor_bam && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_amber, tumor_bam, normal_bam, tumor_bai, normal_bai ] - ch_amber_inputs = ch_inputs_sorted.runnable - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + // Select input sources and sort + // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai] + // channel: skip: [ meta ] + ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_bam, + ch_normal_bam, + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), + Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), + ] + } + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.AMBER_DIR) + runnable: tumor_bam && !has_existing + skip: true + return meta + } - def meta_amber = [ - key: meta.group_id, - id: meta.group_id, - tumor_id: Utils.getTumorDnaSampleName(meta), - ] + // Create process input channel + // channel: [ meta_amber, tumor_bam, normal_bam, tumor_bai, normal_bai ] + ch_amber_inputs = ch_inputs_sorted.runnable + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - if (normal_bam) { - meta_amber.normal_id = Utils.getNormalDnaSampleName(meta) - } + def meta_amber = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + ] - [meta_amber, tumor_bam, normal_bam, tumor_bai, normal_bai] + if (normal_bam) { + meta_amber.normal_id = Utils.getNormalDnaSampleName(meta) } - // Run process - AMBER( - ch_amber_inputs, - genome_version, - heterozygous_sites, - target_region_bed, - ) + [meta_amber, tumor_bam, normal_bam, tumor_bai, normal_bai] + } + + // Run process + AMBER( + ch_amber_inputs, + genome_version, + heterozygous_sites, + target_region_bed, + ) - ch_versions = ch_versions.mix(AMBER.out.versions) + ch_versions = ch_versions.mix(AMBER.out.versions) - // Set outputs, restoring original meta - // channel: [ meta, amber_dir ] - ch_outputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(AMBER.out.amber_dir, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) + // Set outputs, restoring original meta + // channel: [ meta, amber_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(AMBER.out.amber_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - amber_dir = ch_outputs // channel: [ meta, amber_dir ] + amber_dir = ch_outputs // channel: [ meta, amber_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/bamtools_metrics/main.nf b/subworkflows/local/bamtools_metrics/main.nf index e71ca2bb..6e16c412 100644 --- a/subworkflows/local/bamtools_metrics/main.nf +++ b/subworkflows/local/bamtools_metrics/main.nf @@ -9,109 +9,109 @@ include { BAMTOOLS } from '../../../modules/local/bamtools/main' workflow BAMTOOLS_METRICS { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] - ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_version // channel: [mandatory] genome version + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Sort inputs, separate by tumor and normal - // channel: runnable: [ meta, bam, bai ] - // channel: skip: [ meta ] - ch_inputs_tumor_sorted = ch_tumor_bam - .map { meta, bam, bai -> - return [ - meta, - Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), - ] - } - .branch { meta, bam, bai -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAMTOOLS_TUMOR) - runnable: bam && !has_existing - skip: true - return meta - } - - // channel: runnable: [ meta, bam, bai ] - // channel: skip: [ meta ] - ch_inputs_normal_sorted = ch_normal_bam - .map { meta, bam, bai -> - return [ - meta, - Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), - ] - } - .branch { meta, bam, bai -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAMTOOLS_NORMAL) - runnable: bam && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_bamtools, bam, bai ] - ch_bamtools_inputs = Channel.empty() - .mix( - ch_inputs_tumor_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bam, bai] }, - ch_inputs_normal_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getNormalDnaSample(meta), 'normal', bam, bai] }, - ) - .map { meta, meta_sample, sample_type, bam, bai -> - - def meta_bamtools = [ - key: meta.group_id, - id: "${meta.group_id}_${meta_sample.sample_id}", - sample_id: meta_sample.sample_id, - sample_type: sample_type, - ] - - return [meta_bamtools, bam, bai] - } - - // Run process - BAMTOOLS( - ch_bamtools_inputs, - genome_fasta, - genome_version, + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Sort inputs, separate by tumor and normal + // channel: runnable: [ meta, bam, bai ] + // channel: skip: [ meta ] + ch_inputs_tumor_sorted = ch_tumor_bam + .map { meta, bam, bai -> + return [ + meta, + Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), + ] + } + .branch { meta, bam, bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAMTOOLS_TUMOR) + runnable: bam && !has_existing + skip: true + return meta + } + + // channel: runnable: [ meta, bam, bai ] + // channel: skip: [ meta ] + ch_inputs_normal_sorted = ch_normal_bam + .map { meta, bam, bai -> + return [ + meta, + Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), + ] + } + .branch { meta, bam, bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAMTOOLS_NORMAL) + runnable: bam && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_bamtools, bam, bai ] + ch_bamtools_inputs = Channel.empty() + .mix( + ch_inputs_tumor_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bam, bai] }, + ch_inputs_normal_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getNormalDnaSample(meta), 'normal', bam, bai] }, + ) + .map { meta, meta_sample, sample_type, bam, bai -> + + def meta_bamtools = [ + key: meta.group_id, + id: "${meta.group_id}_${meta_sample.sample_id}", + sample_id: meta_sample.sample_id, + sample_type: sample_type, + ] + + return [meta_bamtools, bam, bai] + } + + // Run process + BAMTOOLS( + ch_bamtools_inputs, + genome_fasta, + genome_version, + ) + + ch_versions = ch_versions.mix(BAMTOOLS.out.versions) + + // Sort into a tumor and normal channel + ch_bamtools_out = BAMTOOLS.out.metrics + .branch { meta_bamtools, metrics -> + assert ['tumor', 'normal'].contains(meta_bamtools.sample_type) + tumor: meta_bamtools.sample_type == 'tumor' + normal: meta_bamtools.sample_type == 'normal' + placeholder: true + } + + // Set outputs, restoring original meta + // channel: [ meta, metrics ] + ch_somatic_metrics = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_bamtools_out.tumor, ch_inputs), + ch_inputs_tumor_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(BAMTOOLS.out.versions) - - // Sort into a tumor and normal channel - ch_bamtools_out = BAMTOOLS.out.metrics - .branch { meta_bamtools, metrics -> - assert ['tumor', 'normal'].contains(meta_bamtools.sample_type) - tumor: meta_bamtools.sample_type == 'tumor' - normal: meta_bamtools.sample_type == 'normal' - placeholder: true - } - - // Set outputs, restoring original meta - // channel: [ meta, metrics ] - ch_somatic_metrics = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(ch_bamtools_out.tumor, ch_inputs), - ch_inputs_tumor_sorted.skip.map { meta -> [meta, []] }, - ) - - ch_germline_metrics = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(ch_bamtools_out.normal, ch_inputs), - ch_inputs_normal_sorted.skip.map { meta -> [meta, []] }, - ) + ch_germline_metrics = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_bamtools_out.normal, ch_inputs), + ch_inputs_normal_sorted.skip.map { meta -> [meta, []] }, + ) emit: - somatic = ch_somatic_metrics // channel: [ meta, metrics ] - germline = ch_germline_metrics // channel: [ meta, metrics ] + somatic = ch_somatic_metrics // channel: [ meta, metrics ] + germline = ch_germline_metrics // channel: [ meta, metrics ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/chord_prediction/main.nf b/subworkflows/local/chord_prediction/main.nf index e482e5d2..a26d068f 100644 --- a/subworkflows/local/chord_prediction/main.nf +++ b/subworkflows/local/chord_prediction/main.nf @@ -9,87 +9,87 @@ include { CHORD } from '../../../modules/local/chord/main' workflow CHORD_PREDICTION { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_purple // channel: [mandatory] [ meta, purple_dir ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] - // Reference data - genome_version // channel: [mandatory] genome version + // Reference data + genome_version // channel: [mandatory] genome version main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources - // channel: [ meta, purple_dir ] - ch_inputs_selected = ch_purple - .map { meta, purple_dir -> - return [meta, Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR)] + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select input sources + // channel: [ meta, purple_dir ] + ch_inputs_selected = ch_purple + .map { meta, purple_dir -> + return [meta, Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR)] + } + + // Sort inputs + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_inputs_selected + .branch { meta, purple_dir -> + + def has_dna = Utils.hasTumorDna(meta) + + def tumor_id + def has_smlv_vcf + def has_sv_vcf + + if (has_dna) { + tumor_id = Utils.getTumorDnaSampleName(meta) + has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] + has_sv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") : [] } - // Sort inputs - // channel: runnable: [ meta, purple_dir ] - // channel: skip: [ meta ] - ch_inputs_sorted = ch_inputs_selected - .branch { meta, purple_dir -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.CHORD_DIR) - def has_dna = Utils.hasTumorDna(meta) + runnable: has_dna && purple_dir && has_smlv_vcf && has_sv_vcf && !has_existing + skip: true + return meta + } - def tumor_id - def has_smlv_vcf - def has_sv_vcf + // Create process input channel + // channel: [ meta_chord, smlv_vcf, sv_vcf ] + ch_chord_inputs = ch_inputs_sorted.runnable + .map { meta, purple_dir -> - if (has_dna) { - tumor_id = Utils.getTumorDnaSampleName(meta) - has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] - has_sv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") : [] - } + def tumor_id = Utils.getTumorDnaSampleName(meta) - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.CHORD_DIR) + def meta_chord = [ + key: meta.group_id, + id: meta.group_id, + sample_id: tumor_id, + ] - runnable: has_dna && purple_dir && has_smlv_vcf && has_sv_vcf && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_chord, smlv_vcf, sv_vcf ] - ch_chord_inputs = ch_inputs_sorted.runnable - .map { meta, purple_dir -> - - def tumor_id = Utils.getTumorDnaSampleName(meta) + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") - def meta_chord = [ - key: meta.group_id, - id: meta.group_id, - sample_id: tumor_id, - ] + return [meta_chord, smlv_vcf, sv_vcf] + } - def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.vcf.gz") + // Run process + CHORD( + ch_chord_inputs, + genome_version, + ) - return [meta_chord, smlv_vcf, sv_vcf] - } + ch_versions = ch_versions.mix(CHORD.out.versions) - // Run process - CHORD( - ch_chord_inputs, - genome_version, + // Set outputs, restoring original meta + // channel: [ meta, chord_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(CHORD.out.chord_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(CHORD.out.versions) - - // Set outputs, restoring original meta - // channel: [ meta, chord_dir ] - ch_outputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(CHORD.out.chord_dir, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - emit: - chord_dir = ch_outputs // channel: [ meta, chord_dir ] + chord_dir = ch_outputs // channel: [ meta, chord_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/cobalt_profiling/main.nf b/subworkflows/local/cobalt_profiling/main.nf index 13102dee..10b06485 100644 --- a/subworkflows/local/cobalt_profiling/main.nf +++ b/subworkflows/local/cobalt_profiling/main.nf @@ -9,95 +9,95 @@ include { COBALT } from '../../../modules/local/cobalt/main' workflow COBALT_PROFILING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] - ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] - // Reference data - gc_profile // channel: [mandatory] /path/to/gc_profile - diploid_bed // channel: [optional] /path/to/diploid_bed - target_region_normalisation // channel: [optional] /path/to/target_region_normalisation + // Reference data + gc_profile // channel: [mandatory] /path/to/gc_profile + diploid_bed // channel: [optional] /path/to/diploid_bed + target_region_normalisation // channel: [optional] /path/to/target_region_normalisation main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources and sort - // NOTE(SW): germline mode is not currently supported - // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai] - // channel: skip: [ meta ] - ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( - ch_tumor_bam, - ch_normal_bam, + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select input sources and sort + // NOTE(SW): germline mode is not currently supported + // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai] + // channel: skip: [ meta ] + ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_bam, + ch_normal_bam, + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), + Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), + ] + } + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.COBALT_DIR) + runnable_tn: tumor_bam && normal_bam && !has_existing + runnable_to: tumor_bam && !has_existing + skip: true + return meta + } + + // First set diploid BED input for tumor/normal and tumor only samples + // NOTE(SW): since the diploid BED is provided as a channel, I seem to be only able to include via channel ops + // channel: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai, diploid_bed ] + ch_inputs_runnable = Channel.empty() + .mix( + ch_inputs_sorted.runnable_tn.map { [*it, []] }, + ch_inputs_sorted.runnable_to.combine(diploid_bed), ) - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - return [ - meta, - Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), - Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), - ] - } - .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.COBALT_DIR) - runnable_tn: tumor_bam && normal_bam && !has_existing - runnable_to: tumor_bam && !has_existing - skip: true - return meta - } - // First set diploid BED input for tumor/normal and tumor only samples - // NOTE(SW): since the diploid BED is provided as a channel, I seem to be only able to include via channel ops - // channel: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai, diploid_bed ] - ch_inputs_runnable = Channel.empty() - .mix( - ch_inputs_sorted.runnable_tn.map { [*it, []] }, - ch_inputs_sorted.runnable_to.combine(diploid_bed), - ) - - // Create process input channel - // channel: sample_data: [ meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai ] - // channel: diploid_bed: [ diploid_bed ] - ch_cobalt_inputs = ch_inputs_runnable - .multiMap { meta, tumor_bam, tumor_bai, normal_bam, normal_bai, diploid_bed -> - - def meta_cobalt = [ - key: meta.group_id, - id: meta.group_id, - tumor_id: Utils.getTumorDnaSampleName(meta), - ] - - if (normal_bam) { - meta_cobalt.normal_id = Utils.getNormalDnaSampleName(meta) - } - - sample_data: [meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai] - diploid_bed: diploid_bed - } + // Create process input channel + // channel: sample_data: [ meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai ] + // channel: diploid_bed: [ diploid_bed ] + ch_cobalt_inputs = ch_inputs_runnable + .multiMap { meta, tumor_bam, tumor_bai, normal_bam, normal_bai, diploid_bed -> - // Run process - COBALT( - ch_cobalt_inputs.sample_data, - gc_profile, - ch_cobalt_inputs.diploid_bed, - target_region_normalisation, - ) + def meta_cobalt = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + ] - ch_versions = ch_versions.mix(COBALT.out.versions) + if (normal_bam) { + meta_cobalt.normal_id = Utils.getNormalDnaSampleName(meta) + } - // Set outputs, restoring original meta - // channel: [ meta, cobalt_dir ] - ch_outputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(COBALT.out.cobalt_dir, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) + sample_data: [meta_cobalt, tumor_bam, normal_bam, tumor_bai, normal_bai] + diploid_bed: diploid_bed + } + + // Run process + COBALT( + ch_cobalt_inputs.sample_data, + gc_profile, + ch_cobalt_inputs.diploid_bed, + target_region_normalisation, + ) + + ch_versions = ch_versions.mix(COBALT.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, cobalt_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(COBALT.out.cobalt_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - cobalt_dir = ch_outputs // channel: [ meta, cobalt_dir ] + cobalt_dir = ch_outputs // channel: [ meta, cobalt_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/cuppa_prediction/main.nf b/subworkflows/local/cuppa_prediction/main.nf index 2b74a441..5c839073 100644 --- a/subworkflows/local/cuppa_prediction/main.nf +++ b/subworkflows/local/cuppa_prediction/main.nf @@ -9,141 +9,141 @@ include { CUPPA } from '../../../modules/local/cuppa/main' workflow CUPPA_PREDICTION { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_isofox // channel: [mandatory] [ meta, isofox_dir ] - ch_purple // channel: [mandatory] [ meta, purple_dir ] - ch_linx // channel: [mandatory] [ meta, linx_annotation_dir ] - ch_virusinterpreter // channel: [mandatory] [ meta, virusinterpreter_dir ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_isofox // channel: [mandatory] [ meta, isofox_dir ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] + ch_linx // channel: [mandatory] [ meta, linx_annotation_dir ] + ch_virusinterpreter // channel: [mandatory] [ meta, virusinterpreter_dir ] - // Reference data - genome_version // channel: [mandatory] genome version - cuppa_resources // channel: [mandatory] /path/to/cuppa_resources/ + // Reference data + genome_version // channel: [mandatory] genome version + cuppa_resources // channel: [mandatory] /path/to/cuppa_resources/ main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources - // channel: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] - ch_inputs_selected = WorkflowOncoanalyser.groupByMeta( - ch_isofox, - ch_purple, - ch_linx, - ch_virusinterpreter, - ) - .map { meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir -> + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() - def inputs = [ - Utils.selectCurrentOrExisting(isofox_dir, meta, Constants.INPUT.ISOFOX_DIR), - Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), - Utils.selectCurrentOrExisting(linx_annotation_dir, meta, Constants.INPUT.LINX_ANNO_DIR_TUMOR), - Utils.selectCurrentOrExisting(virusinterpreter_dir, meta, Constants.INPUT.VIRUSINTERPRETER_DIR), - ] + // Select input sources + // channel: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] + ch_inputs_selected = WorkflowOncoanalyser.groupByMeta( + ch_isofox, + ch_purple, + ch_linx, + ch_virusinterpreter, + ) + .map { meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir -> - return [meta, *inputs] - } + def inputs = [ + Utils.selectCurrentOrExisting(isofox_dir, meta, Constants.INPUT.ISOFOX_DIR), + Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), + Utils.selectCurrentOrExisting(linx_annotation_dir, meta, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + Utils.selectCurrentOrExisting(virusinterpreter_dir, meta, Constants.INPUT.VIRUSINTERPRETER_DIR), + ] - // Sort inputs - // channel: runnable: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] - // channel: skip: [ meta ] - ch_inputs_sorted = ch_inputs_selected - .branch { meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir -> - - // Run the following: - // - tumor DNA and normal DNA - // - tumor DNA and normal DNA, and tumor RNA - // - tumor RNA only - // - // Do not run the following: - // - tumor DNA only - // - panel mode (controlled by excluded from targeted subworkflow) - // - // (run exclusions currently done basis for presence of normal DNA) - - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.CUPPA_DIR) - def has_normal_dna = Utils.hasNormalDna(meta) - - def has_runnable_inputs = isofox_dir || (purple_dir && linx_annotation_dir && has_normal_dna) - - runnable: has_runnable_inputs && !has_existing - skip: true - return meta - } + return [meta, *inputs] + } - // Create process input channel - // channel: sample_data: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] - // channel: classifer: [ classifier ] - ch_cuppa_inputs = ch_inputs_sorted.runnable - .multiMap{ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir -> + // Sort inputs + // channel: runnable: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_inputs_selected + .branch { meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir -> - def meta_cuppa = [ - key: meta.group_id, - id: meta.group_id, - ] + // Run the following: + // - tumor DNA and normal DNA + // - tumor DNA and normal DNA, and tumor RNA + // - tumor RNA only + // + // Do not run the following: + // - tumor DNA only + // - panel mode (controlled by excluded from targeted subworkflow) + // + // (run exclusions currently done basis for presence of normal DNA) - def has_tumor_dna = Utils.hasTumorDna(meta) - def has_normal_dna = Utils.hasNormalDna(meta) - def has_tumor_rna = Utils.hasTumorRna(meta) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.CUPPA_DIR) + def has_normal_dna = Utils.hasNormalDna(meta) - def has_dna_inputs = (purple_dir && linx_annotation_dir) - def has_rna_inputs = isofox_dir + def has_runnable_inputs = isofox_dir || (purple_dir && linx_annotation_dir && has_normal_dna) - def run_dna = has_dna_inputs && has_tumor_dna && has_normal_dna - def run_rna = has_rna_inputs && has_tumor_rna + runnable: has_runnable_inputs && !has_existing + skip: true + return meta + } - def classifier + // Create process input channel + // channel: sample_data: [ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir ] + // channel: classifer: [ classifier ] + ch_cuppa_inputs = ch_inputs_sorted.runnable + .multiMap{ meta, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir -> - if (run_dna && run_rna) { + def meta_cuppa = [ + key: meta.group_id, + id: meta.group_id, + ] - classifier = 'ALL' + def has_tumor_dna = Utils.hasTumorDna(meta) + def has_normal_dna = Utils.hasNormalDna(meta) + def has_tumor_rna = Utils.hasTumorRna(meta) - meta_cuppa.sample_id = Utils.getTumorDnaSampleName(meta) - meta_cuppa.sample_rna_id = Utils.getTumorRnaSampleName(meta) + def has_dna_inputs = (purple_dir && linx_annotation_dir) + def has_rna_inputs = isofox_dir - } else if (run_dna) { + def run_dna = has_dna_inputs && has_tumor_dna && has_normal_dna + def run_rna = has_rna_inputs && has_tumor_rna - classifier = 'DNA' + def classifier - meta_cuppa.sample_id = Utils.getTumorDnaSampleName(meta) + if (run_dna && run_rna) { - } else if (run_rna) { + classifier = 'ALL' - classifier = 'RNA' + meta_cuppa.sample_id = Utils.getTumorDnaSampleName(meta) + meta_cuppa.sample_rna_id = Utils.getTumorRnaSampleName(meta) - meta_cuppa.sample_id = Utils.getTumorRnaSampleName(meta) + } else if (run_dna) { - } else { + classifier = 'DNA' - assert false + meta_cuppa.sample_id = Utils.getTumorDnaSampleName(meta) - } + } else if (run_rna) { - sample_data: [meta_cuppa, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir] - classifier: classifier - } + classifier = 'RNA' - // Run process - CUPPA( - ch_cuppa_inputs.sample_data, - genome_version, - cuppa_resources, - ch_cuppa_inputs.classifier, - ) + meta_cuppa.sample_id = Utils.getTumorRnaSampleName(meta) - ch_versions = ch_versions.mix(CUPPA.out.versions) + } else { - // Set outputs, restoring original meta - // channel: [ meta, cuppa_dir ] - ch_outputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(CUPPA.out.cuppa_dir, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) + assert false + + } + + sample_data: [meta_cuppa, isofox_dir, purple_dir, linx_annotation_dir, virusinterpreter_dir] + classifier: classifier + } + + // Run process + CUPPA( + ch_cuppa_inputs.sample_data, + genome_version, + cuppa_resources, + ch_cuppa_inputs.classifier, + ) + + ch_versions = ch_versions.mix(CUPPA.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, cuppa_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(CUPPA.out.cuppa_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - cuppa_dir = ch_outputs // channel: [ meta, cuppa_dir ] + cuppa_dir = ch_outputs // channel: [ meta, cuppa_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/flagstat_metrics/main.nf b/subworkflows/local/flagstat_metrics/main.nf index 9f0a5f78..2ad4798a 100644 --- a/subworkflows/local/flagstat_metrics/main.nf +++ b/subworkflows/local/flagstat_metrics/main.nf @@ -9,103 +9,103 @@ include { SAMTOOLS_FLAGSTAT } from '../../../modules/nf-core/samtools/flagstat/m workflow FLAGSTAT_METRICS { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] - ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Sort inputs, separate by tumor and normal - // channel: runnable: [ meta, bam, bai ] - // channel: skip: [ meta ] - ch_inputs_tumor_sorted = ch_tumor_bam - .map { meta, bam, bai -> - return [ - meta, - Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), - ] - } - .branch { meta, bam, bai -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.FLAGSTAT_TUMOR) - runnable: bam && !has_existing - skip: true - return meta - } - - // channel: runnable: [ meta, bam, bai ] - // channel: skip: [ meta ] - ch_inputs_normal_sorted = ch_normal_bam - .map { meta, bam, bai -> - return [ - meta, - Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), - ] - } - .branch { meta, bam, bai -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.FLAGSTAT_NORMAL) - runnable: bam && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_flagstat, bam, bai ] - ch_flagstat_inputs = Channel.empty() - .mix( - ch_inputs_tumor_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bam, bai] }, - ch_inputs_normal_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getNormalDnaSample(meta), 'normal', bam, bai] }, - ) - .map { meta, meta_sample, sample_type, bam, bai -> - - def meta_flagstat = [ - key: meta.group_id, - id: "${meta.group_id}_${meta_sample.sample_id}", - sample_id: meta_sample.sample_id, - sample_type: sample_type, - ] - - return [meta_flagstat, bam, bai] - } - - // Run process - SAMTOOLS_FLAGSTAT( - ch_flagstat_inputs, + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Sort inputs, separate by tumor and normal + // channel: runnable: [ meta, bam, bai ] + // channel: skip: [ meta ] + ch_inputs_tumor_sorted = ch_tumor_bam + .map { meta, bam, bai -> + return [ + meta, + Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), + ] + } + .branch { meta, bam, bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.FLAGSTAT_TUMOR) + runnable: bam && !has_existing + skip: true + return meta + } + + // channel: runnable: [ meta, bam, bai ] + // channel: skip: [ meta ] + ch_inputs_normal_sorted = ch_normal_bam + .map { meta, bam, bai -> + return [ + meta, + Utils.selectCurrentOrExisting(bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), + ] + } + .branch { meta, bam, bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.FLAGSTAT_NORMAL) + runnable: bam && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_flagstat, bam, bai ] + ch_flagstat_inputs = Channel.empty() + .mix( + ch_inputs_tumor_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bam, bai] }, + ch_inputs_normal_sorted.runnable.map { meta, bam, bai -> [meta, Utils.getNormalDnaSample(meta), 'normal', bam, bai] }, + ) + .map { meta, meta_sample, sample_type, bam, bai -> + + def meta_flagstat = [ + key: meta.group_id, + id: "${meta.group_id}_${meta_sample.sample_id}", + sample_id: meta_sample.sample_id, + sample_type: sample_type, + ] + + return [meta_flagstat, bam, bai] + } + + // Run process + SAMTOOLS_FLAGSTAT( + ch_flagstat_inputs, + ) + + ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) + + // Sort into a tumor and normal channel + ch_flagstat_out = SAMTOOLS_FLAGSTAT.out.flagstat + .branch { meta_flagstat, flagstat -> + assert ['tumor', 'normal'].contains(meta_flagstat.sample_type) + tumor: meta_flagstat.sample_type == 'tumor' + normal: meta_flagstat.sample_type == 'normal' + placeholder: true + } + + // Set outputs, restoring original meta + // channel: [ meta, flagstat ] + ch_somatic_flagstat = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_flagstat_out.tumor, ch_inputs), + ch_inputs_tumor_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) - - // Sort into a tumor and normal channel - ch_flagstat_out = SAMTOOLS_FLAGSTAT.out.flagstat - .branch { meta_flagstat, flagstat -> - assert ['tumor', 'normal'].contains(meta_flagstat.sample_type) - tumor: meta_flagstat.sample_type == 'tumor' - normal: meta_flagstat.sample_type == 'normal' - placeholder: true - } - - // Set outputs, restoring original meta - // channel: [ meta, flagstat ] - ch_somatic_flagstat = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(ch_flagstat_out.tumor, ch_inputs), - ch_inputs_tumor_sorted.skip.map { meta -> [meta, []] }, - ) - - ch_germline_flagstat = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(ch_flagstat_out.normal, ch_inputs), - ch_inputs_normal_sorted.skip.map { meta -> [meta, []] }, - ) + ch_germline_flagstat = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_flagstat_out.normal, ch_inputs), + ch_inputs_normal_sorted.skip.map { meta -> [meta, []] }, + ) emit: - somatic = ch_somatic_flagstat // channel: [ meta, flagstat ] - germline = ch_germline_flagstat // channel: [ meta, flagstat ] + somatic = ch_somatic_flagstat // channel: [ meta, flagstat ] + germline = ch_germline_flagstat // channel: [ meta, flagstat ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/gridss_svprep_calling/main.nf b/subworkflows/local/gridss_svprep_calling/main.nf index 77bdb27a..59ec337e 100644 --- a/subworkflows/local/gridss_svprep_calling/main.nf +++ b/subworkflows/local/gridss_svprep_calling/main.nf @@ -15,369 +15,369 @@ include { SVPREP as SVPREP_TUMOR } from '../../../modules/loc workflow GRIDSS_SVPREP_CALLING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] - ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] - - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_version // channel: [mandatory] genome version - genome_fai // channel: [mandatory] /path/to/genome_fai - genome_dict // channel: [mandatory] /path/to/genome_dict - genome_gridss_index // channel: [mandatory] /path/to/genome_gridss_index - gridss_blocklist // channel: [mandatory] /path/to/gridss_blocklist - sv_prep_blocklist // channel: [mandatory] /path/to/sv_prep_blocklist - known_fusions // channel: [mandatory] /path/to/known_fusions - - // Params - gridss_config // channel: [optional] /path/to/gridss_config + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] + + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict + genome_gridss_index // channel: [mandatory] /path/to/genome_gridss_index + gridss_blocklist // channel: [mandatory] /path/to/gridss_blocklist + sv_prep_blocklist // channel: [mandatory] /path/to/sv_prep_blocklist + known_fusions // channel: [mandatory] /path/to/known_fusions + + // Params + gridss_config // channel: [optional] /path/to/gridss_config main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources and sort - // channel: runnable_tn: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] - // channel: runnable_to: [ meta, tumor_bam, tumor_bai ] - // channel: skip: [ meta ] - ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( - ch_tumor_bam, - ch_normal_bam, - ) - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - return [ - meta, - Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), - Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), - ] - } - .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIDSS_VCF) - - runnable_tn: tumor_bam && normal_bam && !has_existing - runnable_to: tumor_bam && !has_existing - return [meta, tumor_bam, tumor_bai] - skip: true - return meta - } - - // - // MODULE: SV Prep (tumor) - // - // Create process input channel - // channel: [ meta_svprep, bam_tumor, bai_tumor, [] ] - ch_svprep_tumor_inputs = Channel.empty() - .mix( - ch_inputs_sorted.runnable_to.map { [*it, [], []] }, - ch_inputs_sorted.runnable_tn, - ) - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - - def meta_svprep = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorDnaSampleName(meta), - sample_type: 'tumor', - // NOTE(SW): slightly redundant since we have this information then lose it with .mix above - group_size: normal_bam ? 2 : 1 - ] - - return [meta_svprep, tumor_bam, tumor_bai, []] - - } - - // Run process - SVPREP_TUMOR( - ch_svprep_tumor_inputs, - genome_fasta, - genome_version, - sv_prep_blocklist, - known_fusions, - 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument - ) - - ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) - - // channel: [ meta_gridss, bam_tumor, bam_tumor_filtered ] - ch_preprocess_inputs_tumor = WorkflowOncoanalyser.groupByMeta( - SVPREP_TUMOR.out.bam, - ch_svprep_tumor_inputs, - ) - .map { meta_svprep, bam_filtered, bam, bai, jnc_optional -> - return [meta_svprep, bam, bam_filtered] - } - - // - // MODULE: SV Prep (normal) - // - // Create process input channel - // channel: [ meta_svprep, bam_normal, bai_normal, junctions_tumor ] - ch_svprep_normal_inputs = WorkflowOncoanalyser.groupByMeta( + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select input sources and sort + // channel: runnable_tn: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] + // channel: runnable_to: [ meta, tumor_bam, tumor_bai ] + // channel: skip: [ meta ] + ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_bam, + ch_normal_bam, + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), + Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), + ] + } + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIDSS_VCF) + + runnable_tn: tumor_bam && normal_bam && !has_existing + runnable_to: tumor_bam && !has_existing + return [meta, tumor_bam, tumor_bai] + skip: true + return meta + } + + // + // MODULE: SV Prep (tumor) + // + // Create process input channel + // channel: [ meta_svprep, bam_tumor, bai_tumor, [] ] + ch_svprep_tumor_inputs = Channel.empty() + .mix( + ch_inputs_sorted.runnable_to.map { [*it, [], []] }, ch_inputs_sorted.runnable_tn, - // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_tn - WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs_sorted.runnable_tn.map { it[0] }) ) - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai, junctions_tumor -> - - def meta_svprep = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getNormalDnaSampleName(meta), - sample_type: 'normal', - group_size: 2, // Assumption holds since germline only is not supported and we source from runnable_tn - ] - - return [meta_svprep, normal_bam, normal_bai, junctions_tumor] - - } - - // Run process - SVPREP_NORMAL( - ch_svprep_normal_inputs, - genome_fasta, - genome_version, - sv_prep_blocklist, - known_fusions, - 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + + def meta_svprep = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), + sample_type: 'tumor', + // NOTE(SW): slightly redundant since we have this information then lose it with .mix above + group_size: normal_bam ? 2 : 1 + ] + + return [meta_svprep, tumor_bam, tumor_bai, []] + + } + + // Run process + SVPREP_TUMOR( + ch_svprep_tumor_inputs, + genome_fasta, + genome_version, + sv_prep_blocklist, + known_fusions, + 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument + ) + + ch_versions = ch_versions.mix(SVPREP_TUMOR.out.versions) + + // channel: [ meta_gridss, bam_tumor, bam_tumor_filtered ] + ch_preprocess_inputs_tumor = WorkflowOncoanalyser.groupByMeta( + SVPREP_TUMOR.out.bam, + ch_svprep_tumor_inputs, + ) + .map { meta_svprep, bam_filtered, bam, bai, jnc_optional -> + return [meta_svprep, bam, bam_filtered] + } + + // + // MODULE: SV Prep (normal) + // + // Create process input channel + // channel: [ meta_svprep, bam_normal, bai_normal, junctions_tumor ] + ch_svprep_normal_inputs = WorkflowOncoanalyser.groupByMeta( + ch_inputs_sorted.runnable_tn, + // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_tn + WorkflowOncoanalyser.restoreMeta(SVPREP_TUMOR.out.junctions, ch_inputs_sorted.runnable_tn.map { it[0] }) + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai, junctions_tumor -> + + def meta_svprep = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getNormalDnaSampleName(meta), + sample_type: 'normal', + group_size: 2, // Assumption holds since germline only is not supported and we source from runnable_tn + ] + + return [meta_svprep, normal_bam, normal_bai, junctions_tumor] + + } + + // Run process + SVPREP_NORMAL( + ch_svprep_normal_inputs, + genome_fasta, + genome_version, + sv_prep_blocklist, + known_fusions, + 'JUNCTIONS;BAM;FRAGMENT_LENGTH_DIST', // -write_types argument + ) + + ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) + + // channel: [ meta_gridss, bam_normal, bam_normal_filtered ] + ch_preprocess_inputs_normal = WorkflowOncoanalyser.groupByMeta( + SVPREP_NORMAL.out.bam, + ch_svprep_normal_inputs, + ) + // Switching meta name here from meta_svprep + .map { meta_gridss, bam_filtered, bam, bai, junctions -> + return [meta_gridss, bam, bam_filtered] + } + + // + // MODULE: GRIDSS preprocess + // + // Create process input channel + // channel: [ meta_gridss, bam, bam_filtered ] + ch_preprocess_inputs = Channel.empty() + .mix( + ch_preprocess_inputs_tumor, + ch_preprocess_inputs_normal, ) - - ch_versions = ch_versions.mix(SVPREP_NORMAL.out.versions) - - // channel: [ meta_gridss, bam_normal, bam_normal_filtered ] - ch_preprocess_inputs_normal = WorkflowOncoanalyser.groupByMeta( - SVPREP_NORMAL.out.bam, - ch_svprep_normal_inputs, - ) - // Switching meta name here from meta_svprep - .map { meta_gridss, bam_filtered, bam, bai, junctions -> - return [meta_gridss, bam, bam_filtered] - } - - // - // MODULE: GRIDSS preprocess - // - // Create process input channel - // channel: [ meta_gridss, bam, bam_filtered ] - ch_preprocess_inputs = Channel.empty() - .mix( - ch_preprocess_inputs_tumor, - ch_preprocess_inputs_normal, - ) - .map { meta_svprep, bam, bam_filtered -> - - def meta_gridss = [ - key: meta_svprep.key, - id: "${meta_svprep.id}__${meta_svprep.sample_id}", - sample_id: meta_svprep.sample_id, - sample_type: meta_svprep.sample_type, - group_size: meta_svprep.group_size, + .map { meta_svprep, bam, bam_filtered -> + + def meta_gridss = [ + key: meta_svprep.key, + id: "${meta_svprep.id}__${meta_svprep.sample_id}", + sample_id: meta_svprep.sample_id, + sample_type: meta_svprep.sample_type, + group_size: meta_svprep.group_size, + ] + + return [meta_gridss, bam, bam_filtered] + } + + // Run process + PREPROCESS( + ch_preprocess_inputs, + gridss_config, + genome_fasta, + genome_fai, + genome_dict, + genome_gridss_index, + ) + + ch_versions = ch_versions.mix(PREPROCESS.out.versions) + + // Gather BAMs and outputs from preprocessing for each tumor/normal and tumor only set + // channel: [key, [[meta_gridss, bam, bam_filtered, preprocess_dir], ...] ] + ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( + ch_preprocess_inputs, + PREPROCESS.out.preprocess_dir, + ) + .map { + def meta_gridss = it[0] + def other = it[1..-1] + [groupKey(meta_gridss.key, meta_gridss.group_size), [meta_gridss, *other]] + } + .groupTuple() + + // + // MODULE: GRIDSS assemble + // + // Create process input channel + // channel: tumor/normal: [ meta_gridss, [bams], [bams_filtered], [preprocess_dirs], [labels] ] + // channel: tumor only: [ meta_gridss, bam, bam_filtered, preprocess_dir, label ] + ch_assemble_inputs = ch_bams_and_preprocess + .map { key, entries -> + + assert entries.size() == 1 || entries.size() == 2 + + def tumor_entry = entries.find { e -> e[0].sample_type == 'tumor' } + def normal_entry = entries.find { e -> e[0].sample_type == 'normal' } + + assert tumor_entry !== null + + def (tmeta, tbam, tbam_filtered, tpreprocess) = tumor_entry + def meta_gridss = [ + // Effectively meta.group_id, and both are required. Reminder: + // * key: channel element grouping + // * id: task tag + key: tmeta.key, + id: tmeta.key, + ] + + def data = [] + + if (normal_entry === null) { + + data = [ + meta_gridss, + tbam, + tbam_filtered, + tpreprocess, + tmeta.sample_id, ] - return [meta_gridss, bam, bam_filtered] - } - - // Run process - PREPROCESS( - ch_preprocess_inputs, - gridss_config, - genome_fasta, - genome_fai, - genome_dict, - genome_gridss_index, - ) - - ch_versions = ch_versions.mix(PREPROCESS.out.versions) + } else { - // Gather BAMs and outputs from preprocessing for each tumor/normal and tumor only set - // channel: [key, [[meta_gridss, bam, bam_filtered, preprocess_dir], ...] ] - ch_bams_and_preprocess = WorkflowOncoanalyser.groupByMeta( - ch_preprocess_inputs, - PREPROCESS.out.preprocess_dir, - ) - .map { - def meta_gridss = it[0] - def other = it[1..-1] - [groupKey(meta_gridss.key, meta_gridss.group_size), [meta_gridss, *other]] - } - .groupTuple() - - // - // MODULE: GRIDSS assemble - // - // Create process input channel - // channel: tumor/normal: [ meta_gridss, [bams], [bams_filtered], [preprocess_dirs], [labels] ] - // channel: tumor only: [ meta_gridss, bam, bam_filtered, preprocess_dir, label ] - ch_assemble_inputs = ch_bams_and_preprocess - .map { key, entries -> - - assert entries.size() == 1 || entries.size() == 2 - - def tumor_entry = entries.find { e -> e[0].sample_type == 'tumor' } - def normal_entry = entries.find { e -> e[0].sample_type == 'normal' } - - assert tumor_entry !== null - - def (tmeta, tbam, tbam_filtered, tpreprocess) = tumor_entry - def meta_gridss = [ - // Effectively meta.group_id, and both are required. Reminder: - // * key: channel element grouping - // * id: task tag - key: tmeta.key, - id: tmeta.key, + def (nmeta, nbam, nbam_filtered, npreprocess) = normal_entry + data = [ + meta_gridss, + [nbam, tbam], + [nbam_filtered, tbam_filtered], + [npreprocess, tpreprocess], + [nmeta.sample_id, tmeta.sample_id], ] - def data = [] - - if (normal_entry === null) { - - data = [ - meta_gridss, - tbam, - tbam_filtered, - tpreprocess, - tmeta.sample_id, - ] - - } else { - - def (nmeta, nbam, nbam_filtered, npreprocess) = normal_entry - data = [ - meta_gridss, - [nbam, tbam], - [nbam_filtered, tbam_filtered], - [npreprocess, tpreprocess], - [nmeta.sample_id, tmeta.sample_id], - ] - - } - - return data } - // Run process - ASSEMBLE( - ch_assemble_inputs, - gridss_config, - genome_fasta, - genome_fai, - genome_dict, - genome_gridss_index, - gridss_blocklist, - ) - - ch_versions = ch_versions.mix(ASSEMBLE.out.versions) - - // - // MODULE: GRIDSS call - // - // Create process input channel - // channel: [ meta_gridss, [bams], [bams_filtered], assemble_dir, [labels] ] - ch_call_inputs = WorkflowOncoanalyser.groupByMeta( - ch_assemble_inputs, - ASSEMBLE.out.assemble_dir, - flatten: false, + return data + } + + // Run process + ASSEMBLE( + ch_assemble_inputs, + gridss_config, + genome_fasta, + genome_fai, + genome_dict, + genome_gridss_index, + gridss_blocklist, + ) + + ch_versions = ch_versions.mix(ASSEMBLE.out.versions) + + // + // MODULE: GRIDSS call + // + // Create process input channel + // channel: [ meta_gridss, [bams], [bams_filtered], assemble_dir, [labels] ] + ch_call_inputs = WorkflowOncoanalyser.groupByMeta( + ch_assemble_inputs, + ASSEMBLE.out.assemble_dir, + flatten: false, + ) + .map { data -> + def meta_gridss = data[0] + def (bams, bams_filtered, preprocess_dirs, labels) = data[1] + def (assemble_dir) = data[2] + return [meta_gridss, bams, bams_filtered, assemble_dir, labels] + } + + // Run process + CALL( + ch_call_inputs, + gridss_config, + genome_fasta, + genome_fai, + genome_dict, + genome_gridss_index, + gridss_blocklist, + ) + + ch_versions = ch_versions.mix(CALL.out.versions) + + // + // MODULE: SV Prep depth annotation + // + // Restore original meta, create process input channel + // channel: [ meta, [bams], [bais], vcf, [labels] ] + ch_depth_inputs_tn = WorkflowOncoanalyser.groupByMeta( + ch_inputs_sorted.runnable_tn, + // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_tn + WorkflowOncoanalyser.restoreMeta(CALL.out.vcf, ch_inputs_sorted.runnable_tn.map { it[0] }) + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai, vcf -> + return [ + meta, + [normal_bam, tumor_bam], + [normal_bai, tumor_bai], + vcf, + [Utils.getNormalDnaSampleName(meta), Utils.getTumorDnaSampleName(meta)], + ] + } + + // channel: [ meta, bam, bai, vcf, label ] + ch_depth_inputs_to = WorkflowOncoanalyser.groupByMeta( + ch_inputs_sorted.runnable_to, + // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_to + WorkflowOncoanalyser.restoreMeta(CALL.out.vcf, ch_inputs_sorted.runnable_to.map { it[0] }) + ) + .map { meta, tumor_bam, tumor_bai, vcf -> + return [ + meta, + tumor_bam, + tumor_bai, + vcf, + Utils.getTumorDnaSampleName(meta), + ] + } + + // channel: runnable_tn: [ meta_svprep, [bams], [bais], vcf, [labels] ] + // channel: runnable_to: [ meta_svprep, bam, bai, vcf, label ] + ch_depth_inputs = Channel.empty() + .mix( + ch_depth_inputs_tn, + ch_depth_inputs_to, ) - .map { data -> - def meta_gridss = data[0] - def (bams, bams_filtered, preprocess_dirs, labels) = data[1] - def (assemble_dir) = data[2] - return [meta_gridss, bams, bams_filtered, assemble_dir, labels] - } - - // Run process - CALL( - ch_call_inputs, - gridss_config, - genome_fasta, - genome_fai, - genome_dict, - genome_gridss_index, - gridss_blocklist, + .map { d -> + + def meta = d[0] + def fps = d[1..-1] + + def meta_svprep = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta) + ] + + return [meta_svprep, *fps] + } + + // Add depth annotations to calls + DEPTH_ANNOTATOR( + ch_depth_inputs, + genome_fasta, + genome_version, + ) + + ch_versions = ch_versions.mix(DEPTH_ANNOTATOR.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, gridss_vcf ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(DEPTH_ANNOTATOR.out.vcf, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(CALL.out.versions) - - // - // MODULE: SV Prep depth annotation - // - // Restore original meta, create process input channel - // channel: [ meta, [bams], [bais], vcf, [labels] ] - ch_depth_inputs_tn = WorkflowOncoanalyser.groupByMeta( - ch_inputs_sorted.runnable_tn, - // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_tn - WorkflowOncoanalyser.restoreMeta(CALL.out.vcf, ch_inputs_sorted.runnable_tn.map { it[0] }) - ) - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai, vcf -> - return [ - meta, - [normal_bam, tumor_bam], - [normal_bai, tumor_bai], - vcf, - [Utils.getNormalDnaSampleName(meta), Utils.getTumorDnaSampleName(meta)], - ] - } - - // channel: [ meta, bam, bai, vcf, label ] - ch_depth_inputs_to = WorkflowOncoanalyser.groupByMeta( - ch_inputs_sorted.runnable_to, - // NOTE(SW): this implicitly selects only entries present in ch_inputs_sorted.runnable_to - WorkflowOncoanalyser.restoreMeta(CALL.out.vcf, ch_inputs_sorted.runnable_to.map { it[0] }) - ) - .map { meta, tumor_bam, tumor_bai, vcf -> - return [ - meta, - tumor_bam, - tumor_bai, - vcf, - Utils.getTumorDnaSampleName(meta), - ] - } - - // channel: runnable_tn: [ meta_svprep, [bams], [bais], vcf, [labels] ] - // channel: runnable_to: [ meta_svprep, bam, bai, vcf, label ] - ch_depth_inputs = Channel.empty() - .mix( - ch_depth_inputs_tn, - ch_depth_inputs_to, - ) - .map { d -> - - def meta = d[0] - def fps = d[1..-1] - - def meta_svprep = [ - key: meta.group_id, - id: meta.group_id, - tumor_id: Utils.getTumorDnaSampleName(meta) - ] - - return [meta_svprep, *fps] - } - - // Add depth annotations to calls - DEPTH_ANNOTATOR( - ch_depth_inputs, - genome_fasta, - genome_version, - ) - - ch_versions = ch_versions.mix(DEPTH_ANNOTATOR.out.versions) - - // Set outputs, restoring original meta - // channel: [ meta, gridss_vcf ] - ch_outputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(DEPTH_ANNOTATOR.out.vcf, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - emit: - vcf = ch_outputs // channel: [ meta, vcf ] + vcf = ch_outputs // channel: [ meta, vcf ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/gripss_filtering/main.nf b/subworkflows/local/gripss_filtering/main.nf index 4d9bfcb2..324e6761 100644 --- a/subworkflows/local/gripss_filtering/main.nf +++ b/subworkflows/local/gripss_filtering/main.nf @@ -10,170 +10,170 @@ include { GRIPSS_SOMATIC as SOMATIC } from '../../../modules/local/gripss/soma workflow GRIPSS_FILTERING { take: - // Sample inputs - ch_inputs // channel: [mandatory] [ meta ] - ch_gridss // channel: [mandatory] [ meta, gridss_vcf ] - - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_version // channel: [mandatory] genome version - genome_fai // channel: [mandatory] /path/to/genome_fai - breakend_pon // channel: [mandatory] /path/to/breakend_pon - breakpoint_pon // channel: [mandatory] /path/to/breakpoint_pon - known_fusions // channel: [mandatory] /path/to/known_fusions - repeatmasker_annotations // channel: [mandatory] /path/to/repeatmasker_annotations - target_region_bed // channel: [optional] /path/to/target_region_bed + // Sample inputs + ch_inputs // channel: [mandatory] [ meta ] + ch_gridss // channel: [mandatory] [ meta, gridss_vcf ] + + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + breakend_pon // channel: [mandatory] /path/to/breakend_pon + breakpoint_pon // channel: [mandatory] /path/to/breakpoint_pon + known_fusions // channel: [mandatory] /path/to/known_fusions + repeatmasker_annotations // channel: [mandatory] /path/to/repeatmasker_annotations + target_region_bed // channel: [optional] /path/to/target_region_bed main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources and sort - // channel: runnable: [ meta, gridss_vcf ] - // channel: skip: [ meta ] - ch_inputs_sorted = ch_gridss - .map { meta, gridss_vcf -> - return [ - meta, - Utils.selectCurrentOrExisting(gridss_vcf, meta, Constants.INPUT.GRIDSS_VCF), - ] + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select input sources and sort + // channel: runnable: [ meta, gridss_vcf ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_gridss + .map { meta, gridss_vcf -> + return [ + meta, + Utils.selectCurrentOrExisting(gridss_vcf, meta, Constants.INPUT.GRIDSS_VCF), + ] + } + .branch { meta, gridss_vcf -> + runnable: gridss_vcf + skip: true + return meta + } + + // + // MODULE: GRIPSS germline + // + // Select inputs that are eligible to run + // channel: runnable: [ meta, gridss_vcf ] + // channel: skip: [ meta ] + ch_inputs_germline_sorted = ch_inputs_sorted.runnable + .branch { meta, gridss_vcf -> + def has_tumor_normal = Utils.hasTumorDna(meta) && Utils.hasNormalDna(meta) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIPSS_VCF_NORMAL) + + runnable: has_tumor_normal && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_gripss, gridss_vcf ] + ch_gripss_germline_inputs = ch_inputs_germline_sorted.runnable + .map { meta, gridss_vcf -> + + def meta_gripss = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + normal_id: Utils.getNormalDnaSampleName(meta), + ] + + return [meta_gripss, gridss_vcf] + } + + // Run process + GERMLINE( + ch_gripss_germline_inputs, + genome_fasta, + genome_version, + genome_fai, + breakend_pon, + breakpoint_pon, + known_fusions, + repeatmasker_annotations, + ) + + ch_versions = ch_versions.mix(GERMLINE.out.versions) + + // + // MODULE: GRIPSS somatic + // + // Select inputs that are eligible to run + // channel: runnable: [ meta, gridss_vcf ] + // channel: skip: [ meta ] + ch_inputs_somatic_sorted = ch_inputs_sorted.runnable + .branch { meta, gridss_vcf -> + def has_tumor = Utils.hasTumorDna(meta) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIPSS_VCF_TUMOR) + + runnable: has_tumor && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_gripss, gridss_vcf ] + ch_gripss_somatic_inputs = ch_inputs_somatic_sorted.runnable + .map { meta, gridss_vcf -> + + def meta_gripss = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + ] + + if (Utils.hasNormalDna(meta)) { + meta_gripss.normal_id = Utils.getNormalDnaSampleName(meta) } - .branch { meta, gridss_vcf -> - runnable: gridss_vcf - skip: true - return meta - } - - // - // MODULE: GRIPSS germline - // - // Select inputs that are eligible to run - // channel: runnable: [ meta, gridss_vcf ] - // channel: skip: [ meta ] - ch_inputs_germline_sorted = ch_inputs_sorted.runnable - .branch { meta, gridss_vcf -> - def has_tumor_normal = Utils.hasTumorDna(meta) && Utils.hasNormalDna(meta) - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIPSS_VCF_NORMAL) - - runnable: has_tumor_normal && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_gripss, gridss_vcf ] - ch_gripss_germline_inputs = ch_inputs_germline_sorted.runnable - .map { meta, gridss_vcf -> - def meta_gripss = [ - key: meta.group_id, - id: meta.group_id, - tumor_id: Utils.getTumorDnaSampleName(meta), - normal_id: Utils.getNormalDnaSampleName(meta), - ] - - return [meta_gripss, gridss_vcf] - } - - // Run process - GERMLINE( - ch_gripss_germline_inputs, - genome_fasta, - genome_version, - genome_fai, - breakend_pon, - breakpoint_pon, - known_fusions, - repeatmasker_annotations, + return [meta_gripss, gridss_vcf] + } + + // Run process + SOMATIC( + ch_gripss_somatic_inputs, + genome_fasta, + genome_version, + genome_fai, + breakend_pon, + breakpoint_pon, + known_fusions, + repeatmasker_annotations, + target_region_bed, + ) + + ch_versions = ch_versions.mix(SOMATIC.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, gripss_vcf, gripss_tbi ] + ch_somatic_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, ) - ch_versions = ch_versions.mix(GERMLINE.out.versions) - - // - // MODULE: GRIPSS somatic - // - // Select inputs that are eligible to run - // channel: runnable: [ meta, gridss_vcf ] - // channel: skip: [ meta ] - ch_inputs_somatic_sorted = ch_inputs_sorted.runnable - .branch { meta, gridss_vcf -> - def has_tumor = Utils.hasTumorDna(meta) - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.GRIPSS_VCF_TUMOR) - - runnable: has_tumor && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_gripss, gridss_vcf ] - ch_gripss_somatic_inputs = ch_inputs_somatic_sorted.runnable - .map { meta, gridss_vcf -> - - def meta_gripss = [ - key: meta.group_id, - id: meta.group_id, - tumor_id: Utils.getTumorDnaSampleName(meta), - ] - - if (Utils.hasNormalDna(meta)) { - meta_gripss.normal_id = Utils.getNormalDnaSampleName(meta) - } - - return [meta_gripss, gridss_vcf] - } + ch_somatic_unfiltered_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_unfiltered, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, + ) - // Run process - SOMATIC( - ch_gripss_somatic_inputs, - genome_fasta, - genome_version, - genome_fai, - breakend_pon, - breakpoint_pon, - known_fusions, - repeatmasker_annotations, - target_region_bed, + ch_germline_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, ) - ch_versions = ch_versions.mix(SOMATIC.out.versions) - - // Set outputs, restoring original meta - // channel: [ meta, gripss_vcf, gripss_tbi ] - ch_somatic_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), - ch_inputs_somatic_sorted.skip.map { meta -> [meta, [], []] }, - ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, - ) - - ch_somatic_unfiltered_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf_unfiltered, ch_inputs), - ch_inputs_somatic_sorted.skip.map { meta -> [meta, [], []] }, - ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, - ) - - ch_germline_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), - ch_inputs_germline_sorted.skip.map { meta -> [meta, [], []] }, - ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, - ) - - ch_germline_unfiltered_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_unfiltered, ch_inputs), - ch_inputs_germline_sorted.skip.map { meta -> [meta, [], []] }, - ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, - ) + ch_germline_unfiltered_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf_unfiltered, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, + ) emit: - somatic = ch_somatic_out // channel: [ meta, gripss_vcf, gripss_tbi ] - germline = ch_germline_out // channel: [ meta, gripss_vcf, gripss_tbi ] - somatic_unfiltered = ch_somatic_unfiltered_out // channel: [ meta, gripss_vcf, gripss_tbi ] - germline_unfiltered = ch_germline_unfiltered_out // channel: [ meta, gripss_vcf, gripss_tbi ] + somatic = ch_somatic_out // channel: [ meta, gripss_vcf, gripss_tbi ] + germline = ch_germline_out // channel: [ meta, gripss_vcf, gripss_tbi ] + somatic_unfiltered = ch_somatic_unfiltered_out // channel: [ meta, gripss_vcf, gripss_tbi ] + germline_unfiltered = ch_germline_unfiltered_out // channel: [ meta, gripss_vcf, gripss_tbi ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/isofox_quantification/main.nf b/subworkflows/local/isofox_quantification/main.nf index 8de357f9..5cb79e4b 100644 --- a/subworkflows/local/isofox_quantification/main.nf +++ b/subworkflows/local/isofox_quantification/main.nf @@ -9,88 +9,88 @@ include { ISOFOX } from '../../../modules/local/isofox/main' workflow ISOFOX_QUANTIFICATION { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_tumor_rna_bam // channel: [mandatory] [ meta, bam, bai ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_rna_bam // channel: [mandatory] [ meta, bam, bai ] - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_version // channel: [mandatory] genome version - genome_fai // channel: [mandatory] /path/to/genome_fai - ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ - isofox_counts // channel: [mandatory] /path/to/isofox_counts - isofox_gc_ratios // channel: [mandatory] /path/to/isofox_gc_ratios - isofox_gene_ids // channel: [optional] /path/to/gene_ids - isofox_tpm_norm // channel: [optional] /path/to/tpm_norm + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + isofox_counts // channel: [mandatory] /path/to/isofox_counts + isofox_gc_ratios // channel: [mandatory] /path/to/isofox_gc_ratios + isofox_gene_ids // channel: [optional] /path/to/gene_ids + isofox_tpm_norm // channel: [optional] /path/to/tpm_norm - // Params - isofox_functions // string: [optional] Isofox functions - isofox_read_length // string: [mandatory] Isofox read length + // Params + isofox_functions // string: [optional] Isofox functions + isofox_read_length // string: [mandatory] Isofox read length main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() - // Select input sources and sort - // channel: runnable: [ meta, tumor_bam, tumor_bai ] - // channel: skip: [ meta ] - ch_inputs_sorted = ch_tumor_rna_bam - .map { meta, tumor_bam, tumor_bai -> - return [ - meta, - Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_RNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_RNA_TUMOR), - ] - } - .branch { meta, tumor_bam, tumor_bai -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.ISOFOX_DIR) - runnable: tumor_bam && !has_existing - skip: true - return meta - } + // Select input sources and sort + // channel: runnable: [ meta, tumor_bam, tumor_bai ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_tumor_rna_bam + .map { meta, tumor_bam, tumor_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_RNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_RNA_TUMOR), + ] + } + .branch { meta, tumor_bam, tumor_bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.ISOFOX_DIR) + runnable: tumor_bam && !has_existing + skip: true + return meta + } - // Create process input channel - // channel: [ meta_isofox, tumor_bam, tumor_bai ] - ch_isofox_inputs = ch_inputs_sorted.runnable - .map { meta, tumor_bam, tumor_bai -> + // Create process input channel + // channel: [ meta_isofox, tumor_bam, tumor_bai ] + ch_isofox_inputs = ch_inputs_sorted.runnable + .map { meta, tumor_bam, tumor_bai -> - def meta_isofox = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorRnaSampleName(meta), - ] + def meta_isofox = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorRnaSampleName(meta), + ] - return [meta_isofox, tumor_bam, tumor_bai] - } + return [meta_isofox, tumor_bam, tumor_bai] + } - // Run process - ISOFOX( - ch_isofox_inputs, - isofox_functions, - isofox_read_length, - genome_fasta, - genome_version, - genome_fai, - ensembl_data_resources, - isofox_counts, - isofox_gc_ratios, - isofox_gene_ids, - isofox_tpm_norm, - ) + // Run process + ISOFOX( + ch_isofox_inputs, + isofox_functions, + isofox_read_length, + genome_fasta, + genome_version, + genome_fai, + ensembl_data_resources, + isofox_counts, + isofox_gc_ratios, + isofox_gene_ids, + isofox_tpm_norm, + ) - ch_versions = ch_versions.mix(ISOFOX.out.versions) + ch_versions = ch_versions.mix(ISOFOX.out.versions) - // Set outputs, restoring original meta - // channel: [ meta, isofox_dir ] - ch_outputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) + // Set outputs, restoring original meta + // channel: [ meta, isofox_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ISOFOX.out.isofox_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - isofox_dir = ch_outputs // channel: [ meta, isofox_dir ] + isofox_dir = ch_outputs // channel: [ meta, isofox_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/lilac_calling/main.nf b/subworkflows/local/lilac_calling/main.nf index e73f77c3..f267902e 100644 --- a/subworkflows/local/lilac_calling/main.nf +++ b/subworkflows/local/lilac_calling/main.nf @@ -12,213 +12,213 @@ include { LILAC } from '../../../modules/local/l workflow LILAC_CALLING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] - ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] - ch_tumor_rna_bam // channel: [mandatory] [ meta, bam, bai ] - ch_purple // channel: [mandatory] [ meta, purple_dir ] - - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_version // channel: [mandatory] genome version - genome_fai // channel: [mandatory] /path/to/genome_fai - lilac_resource_dir // channel: [mandatory] /path/to/lilac_resource_dir/ - hla_slice_bed // channel: [mandatory] /path/to/hla_slice_bed + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] + ch_tumor_rna_bam // channel: [mandatory] [ meta, bam, bai ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] + + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + lilac_resource_dir // channel: [mandatory] /path/to/lilac_resource_dir/ + hla_slice_bed // channel: [mandatory] /path/to/hla_slice_bed main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources and sort for DNA BAMs - // channel: runnable: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] - // channel: skip: [ meta ] - ch_dna_inputs_sorted = WorkflowOncoanalyser.groupByMeta( - ch_tumor_bam, - ch_normal_bam, - ) - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select input sources and sort for DNA BAMs + // channel: runnable: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] + // channel: skip: [ meta ] + ch_dna_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_bam, + ch_normal_bam, + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), + Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), + ] + } + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.LILAC_DIR) + + runnable: (tumor_bam || normal_bam) && !has_existing + skip: true + return meta + } + + // Realign reads mapping to HLA regions and homologus regions if using reference genome with ALT contigs + // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them to the three + // relevant HLA genes on chr6. All reads including those previously mapped to chr6 are realigned for + // consistency. + if (params.genome_type == 'alt') { + + // Flatten into BAM/BAI pairs, select inputs that are eligible to run + // channel: runnable: [ meta_extra, bam, bai ] + // channel: skip: [ meta_extra ] + ch_realign_inputs_sorted = ch_dna_inputs_sorted.runnable + .flatMap { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + + def tumor_sample_id = Utils.hasTumorDna(meta) ? Utils.getTumorDnaSampleName(meta) : [] + def normal_sample_id = Utils.hasNormalDna(meta) ? Utils.getNormalDnaSampleName(meta) : [] + return [ - meta, - Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), - Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), + [[key: meta.group_id, *:meta, sample_id: tumor_sample_id, sample_type: 'tumor'], tumor_bam, tumor_bai], + [[key: meta.group_id, *:meta, sample_id: normal_sample_id, sample_type: 'normal'], normal_bam, normal_bai], ] } - .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.LILAC_DIR) - - runnable: (tumor_bam || normal_bam) && !has_existing + .branch { meta_extra, bam, bai -> + runnable: bam && bai skip: true - return meta + return meta_extra } - // Realign reads mapping to HLA regions and homologus regions if using reference genome with ALT contigs - // NOTE(SW): the aim of this process is to take reads mapping to ALT contigs and align them to the three - // relevant HLA genes on chr6. All reads including those previously mapped to chr6 are realigned for - // consistency. - if (params.genome_type == 'alt') { - - // Flatten into BAM/BAI pairs, select inputs that are eligible to run - // channel: runnable: [ meta_extra, bam, bai ] - // channel: skip: [ meta_extra ] - ch_realign_inputs_sorted = ch_dna_inputs_sorted.runnable - .flatMap { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - - def tumor_sample_id = Utils.hasTumorDna(meta) ? Utils.getTumorDnaSampleName(meta) : [] - def normal_sample_id = Utils.hasNormalDna(meta) ? Utils.getNormalDnaSampleName(meta) : [] - - return [ - [[key: meta.group_id, *:meta, sample_id: tumor_sample_id, sample_type: 'tumor'], tumor_bam, tumor_bai], - [[key: meta.group_id, *:meta, sample_id: normal_sample_id, sample_type: 'normal'], normal_bam, normal_bai], - ] - } - .branch { meta_extra, bam, bai -> - runnable: bam && bai - skip: true - return meta_extra - } - - // - // MODULE: Custom BAM slice (LILAC) - // - // Create process input channel - // channel: [ meta_realign, bam, bai ] - ch_slice_inputs = ch_realign_inputs_sorted.runnable - .map { meta_extra, bam, bai -> - - def meta_realign = [ - key: meta_extra.group_id, - id: "${meta_extra.group_id}__${meta_extra.sample_id}", - sample_id: meta_extra.sample_id, - sample_type: meta_extra.sample_type, - ] - - return [meta_realign, bam, bai] - } - - // Run process - SLICEBAM( - ch_slice_inputs, - hla_slice_bed, - ) - - ch_versions = ch_versions.mix(SLICEBAM.out.versions) - - // - // MODULE: Custom extract contig (LILAC) - // - // Only run if we have runnable inputs, no blocking since operating only on input metas - ch_extract_contig_run = ch_realign_inputs_sorted.runnable - .toList() - .map { !it.isEmpty() } - - EXTRACTCONTIG( - 'chr6', - genome_fasta, - genome_fai, - ch_extract_contig_run, - ) + // + // MODULE: Custom BAM slice (LILAC) + // + // Create process input channel + // channel: [ meta_realign, bam, bai ] + ch_slice_inputs = ch_realign_inputs_sorted.runnable + .map { meta_extra, bam, bai -> + + def meta_realign = [ + key: meta_extra.group_id, + id: "${meta_extra.group_id}__${meta_extra.sample_id}", + sample_id: meta_extra.sample_id, + sample_type: meta_extra.sample_type, + ] - ch_versions = ch_versions.mix(EXTRACTCONTIG.out.versions) + return [meta_realign, bam, bai] + } - // - // MODULE: Custom realign reads (LILAC) - // - REALIGNREADS( - SLICEBAM.out.bam, - EXTRACTCONTIG.out.contig, - EXTRACTCONTIG.out.bwa_index, - ) + // Run process + SLICEBAM( + ch_slice_inputs, + hla_slice_bed, + ) - ch_versions = ch_versions.mix(REALIGNREADS.out.versions) - - // Separate all BAMs by sample type so they can be merged with desired order - // channel: [ < meta_extra OR meta_realign >, bam, bai ] - ch_slice_reunited_bams = Channel.empty() - .mix( - ch_realign_inputs_sorted.skip.map { meta_extra -> [meta_extra, [], []] }, - REALIGNREADS.out.bam, - ) - .branch { meta_ambiguous, bam, bai -> - tumor: meta_ambiguous.sample_type == 'tumor' - normal: meta_ambiguous.sample_type == 'normal' - } - - // Restore meta, pair tumor and normal BAMs - // channel: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] - ch_dna_inputs_ready = WorkflowOncoanalyser.groupByMeta( - WorkflowOncoanalyser.restoreMeta(ch_slice_reunited_bams.tumor, ch_inputs), - WorkflowOncoanalyser.restoreMeta(ch_slice_reunited_bams.normal, ch_inputs), - ) + ch_versions = ch_versions.mix(SLICEBAM.out.versions) - } else { + // + // MODULE: Custom extract contig (LILAC) + // + // Only run if we have runnable inputs, no blocking since operating only on input metas + ch_extract_contig_run = ch_realign_inputs_sorted.runnable + .toList() + .map { !it.isEmpty() } - // channel: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] - ch_dna_inputs_ready = ch_dna_inputs_sorted.runnable + EXTRACTCONTIG( + 'chr6', + genome_fasta, + genome_fai, + ch_extract_contig_run, + ) - } + ch_versions = ch_versions.mix(EXTRACTCONTIG.out.versions) // - // MODULE: LILAC + // MODULE: Custom realign reads (LILAC) // - // Create process input channel - // channel: [ meta_lilac, normal_dna_bam, normal_dna_bai, tumor_dna_bam, tumor_dna_bai, tumor_rna_bam, tumor_rna_bai, purple_dir ] - ch_lilac_inputs = WorkflowOncoanalyser.groupByMeta( - ch_dna_inputs_ready, - ch_tumor_rna_bam, - ch_purple, + REALIGNREADS( + SLICEBAM.out.bam, + EXTRACTCONTIG.out.contig, + EXTRACTCONTIG.out.bwa_index, ) - .map { meta, tbam_dna, tbai_dna, nbam_dna, nbai_dna, tbam_rna, tbai_rna, purple_dir -> - def meta_lilac = [ - key: meta.group_id, - id: meta.group_id, - ] + ch_versions = ch_versions.mix(REALIGNREADS.out.versions) + + // Separate all BAMs by sample type so they can be merged with desired order + // channel: [ < meta_extra OR meta_realign >, bam, bai ] + ch_slice_reunited_bams = Channel.empty() + .mix( + ch_realign_inputs_sorted.skip.map { meta_extra -> [meta_extra, [], []] }, + REALIGNREADS.out.bam, + ) + .branch { meta_ambiguous, bam, bai -> + tumor: meta_ambiguous.sample_type == 'tumor' + normal: meta_ambiguous.sample_type == 'normal' + } - if (Utils.hasTumorDna(meta)) { - meta_lilac.tumor_id = Utils.getTumorDnaSampleName(meta) - } + // Restore meta, pair tumor and normal BAMs + // channel: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] + ch_dna_inputs_ready = WorkflowOncoanalyser.groupByMeta( + WorkflowOncoanalyser.restoreMeta(ch_slice_reunited_bams.tumor, ch_inputs), + WorkflowOncoanalyser.restoreMeta(ch_slice_reunited_bams.normal, ch_inputs), + ) - if (Utils.hasNormalDna(meta)) { - meta_lilac.normal_id = Utils.getNormalDnaSampleName(meta) - } + } else { - return [ - meta_lilac, - nbam_dna, - nbai_dna, - tbam_dna, - tbai_dna, - tbam_rna, - tbai_rna, - Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), - ] + // channel: [ meta, tumor_dna_bam, tumor_dna_bai, normal_dna_bam, normal_dna_bai ] + ch_dna_inputs_ready = ch_dna_inputs_sorted.runnable + + } + + // + // MODULE: LILAC + // + // Create process input channel + // channel: [ meta_lilac, normal_dna_bam, normal_dna_bai, tumor_dna_bam, tumor_dna_bai, tumor_rna_bam, tumor_rna_bai, purple_dir ] + ch_lilac_inputs = WorkflowOncoanalyser.groupByMeta( + ch_dna_inputs_ready, + ch_tumor_rna_bam, + ch_purple, + ) + .map { meta, tbam_dna, tbai_dna, nbam_dna, nbai_dna, tbam_rna, tbai_rna, purple_dir -> + + def meta_lilac = [ + key: meta.group_id, + id: meta.group_id, + ] + + if (Utils.hasTumorDna(meta)) { + meta_lilac.tumor_id = Utils.getTumorDnaSampleName(meta) } - // Run process - LILAC( - ch_lilac_inputs, - genome_fasta, - genome_version, - lilac_resource_dir, - ) + if (Utils.hasNormalDna(meta)) { + meta_lilac.normal_id = Utils.getNormalDnaSampleName(meta) + } - ch_versions = ch_versions.mix(LILAC.out.versions) + return [ + meta_lilac, + nbam_dna, + nbai_dna, + tbam_dna, + tbai_dna, + tbam_rna, + tbai_rna, + Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), + ] + } - // Set outputs, restoring original meta - // channel: [ meta, amber_dir ] - ch_outputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(LILAC.out.lilac_dir, ch_inputs), - ch_dna_inputs_sorted.skip.map { meta -> [meta, []] }, - ) + // Run process + LILAC( + ch_lilac_inputs, + genome_fasta, + genome_version, + lilac_resource_dir, + ) + + ch_versions = ch_versions.mix(LILAC.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, amber_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(LILAC.out.lilac_dir, ch_inputs), + ch_dna_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - lilac_dir = ch_outputs // channel: [ meta, lilac_dir ] + lilac_dir = ch_outputs // channel: [ meta, lilac_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/linx_annotation/main.nf b/subworkflows/local/linx_annotation/main.nf index 6cf17747..0381a05c 100644 --- a/subworkflows/local/linx_annotation/main.nf +++ b/subworkflows/local/linx_annotation/main.nf @@ -10,147 +10,147 @@ include { LINX_SOMATIC as SOMATIC } from '../../../modules/local/linx/somatic/ workflow LINX_ANNOTATION { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_purple // channel: [mandatory] [ meta, purple_dir ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] - // Reference data - genome_version // channel: [mandatory] genome version - ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ - known_fusion_data // channel: [mandatory] /path/to/known_fusion_data - driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel + // Reference data + genome_version // channel: [mandatory] genome version + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + known_fusion_data // channel: [mandatory] /path/to/known_fusion_data + driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel main: - // Channel for versions.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources and sort - // channel: runnable: [ meta, purple_dir ] - // channel: skip: [ meta ] - ch_inputs_sorted = ch_purple - .map { meta, purple_dir -> - return [ - meta, - Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), - ] - } - .branch { meta, purple_dir -> - runnable: purple_dir - skip: true - return meta - } - - // - // MODULE: LINX germline annotation - // - // Select inputs that are eligible to run - // channel: runnable: [ meta, purple_dir ] - // channel: skip: [ meta ] - ch_inputs_germline_sorted = ch_inputs_sorted.runnable - .branch { meta, purple_dir -> - - def tumor_id = Utils.getTumorDnaSampleName(meta) - - def has_tumor_normal = Utils.hasTumorDna(meta) && Utils.hasNormalDna(meta) - def has_sv_germline_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.germline.vcf.gz") - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) - - runnable: has_tumor_normal && has_sv_germline_vcf && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta, sv_vcf ] - ch_linx_germline_inputs = ch_inputs_germline_sorted.runnable - .map { meta, purple_dir -> - - def tumor_id = Utils.getTumorDnaSampleName(meta) - - def meta_linx = [ - key: meta.group_id, - id: meta.group_id, - sample_id: tumor_id, - ] - - def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.germline.vcf.gz") - - return [meta_linx, sv_vcf] - } - - // Run process - GERMLINE( - ch_linx_germline_inputs, - genome_version, - ensembl_data_resources, - driver_gene_panel, + // Channel for versions.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select input sources and sort + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_purple + .map { meta, purple_dir -> + return [ + meta, + Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), + ] + } + .branch { meta, purple_dir -> + runnable: purple_dir + skip: true + return meta + } + + // + // MODULE: LINX germline annotation + // + // Select inputs that are eligible to run + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_germline_sorted = ch_inputs_sorted.runnable + .branch { meta, purple_dir -> + + def tumor_id = Utils.getTumorDnaSampleName(meta) + + def has_tumor_normal = Utils.hasTumorDna(meta) && Utils.hasNormalDna(meta) + def has_sv_germline_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.germline.vcf.gz") + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) + + runnable: has_tumor_normal && has_sv_germline_vcf && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta, sv_vcf ] + ch_linx_germline_inputs = ch_inputs_germline_sorted.runnable + .map { meta, purple_dir -> + + def tumor_id = Utils.getTumorDnaSampleName(meta) + + def meta_linx = [ + key: meta.group_id, + id: meta.group_id, + sample_id: tumor_id, + ] + + def sv_vcf = file(purple_dir).resolve("${tumor_id}.purple.sv.germline.vcf.gz") + + return [meta_linx, sv_vcf] + } + + // Run process + GERMLINE( + ch_linx_germline_inputs, + genome_version, + ensembl_data_resources, + driver_gene_panel, + ) + + ch_versions = ch_versions.mix(GERMLINE.out.versions) + + // + // MODULE: LINX somatic annotation + // + // Select inputs that are eligible to run + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_somatic_sorted = ch_inputs_sorted.runnable + .branch { meta, purple_dir -> + + def has_tumor = Utils.hasTumorDna(meta) + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) + + runnable: has_tumor && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta, purple_dir ] + ch_linx_somatic_inputs = ch_inputs_somatic_sorted.runnable + .map { meta, purple_dir -> + + def meta_linx = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), + ] + + return [meta_linx, purple_dir] + } + + // Run process + SOMATIC( + ch_linx_somatic_inputs, + genome_version, + ensembl_data_resources, + known_fusion_data, + driver_gene_panel, + ) + + ch_versions = ch_versions.mix(SOMATIC.out.versions) + + + // Set outputs, restoring original meta + // channel: [ meta, linx_annotation_dir ] + ch_somatic_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.annotation_dir, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(GERMLINE.out.versions) - - // - // MODULE: LINX somatic annotation - // - // Select inputs that are eligible to run - // channel: runnable: [ meta, purple_dir ] - // channel: skip: [ meta ] - ch_inputs_somatic_sorted = ch_inputs_sorted.runnable - .branch { meta, purple_dir -> - - def has_tumor = Utils.hasTumorDna(meta) - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) - - runnable: has_tumor && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta, purple_dir ] - ch_linx_somatic_inputs = ch_inputs_somatic_sorted.runnable - .map { meta, purple_dir -> - - def meta_linx = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorDnaSampleName(meta), - ] - - return [meta_linx, purple_dir] - } - - // Run process - SOMATIC( - ch_linx_somatic_inputs, - genome_version, - ensembl_data_resources, - known_fusion_data, - driver_gene_panel, + ch_germline_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.annotation_dir, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(SOMATIC.out.versions) - - - // Set outputs, restoring original meta - // channel: [ meta, linx_annotation_dir ] - ch_somatic_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(SOMATIC.out.annotation_dir, ch_inputs), - ch_inputs_somatic_sorted.skip.map { meta -> [meta, []] }, - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - - ch_germline_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(GERMLINE.out.annotation_dir, ch_inputs), - ch_inputs_germline_sorted.skip.map { meta -> [meta, []] }, - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - emit: - somatic = ch_somatic_out // channel: [ meta, linx_annotation_dir ] - germline = ch_germline_out // channel: [ meta, linx_annotation_dir ] + somatic = ch_somatic_out // channel: [ meta, linx_annotation_dir ] + germline = ch_germline_out // channel: [ meta, linx_annotation_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/linx_plotting/main.nf b/subworkflows/local/linx_plotting/main.nf index de4665a4..4b52da0f 100644 --- a/subworkflows/local/linx_plotting/main.nf +++ b/subworkflows/local/linx_plotting/main.nf @@ -10,101 +10,101 @@ include { LINX_VISUALISER as VISUALISER } from '../../../modules/local/linx/visu workflow LINX_PLOTTING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_annotations // channel: [mandatory] [ meta, annotation_dir ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_annotations // channel: [mandatory] [ meta, annotation_dir ] - // Reference data - genome_version // channel: [mandatory] genome version - ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + // Reference data + genome_version // channel: [mandatory] genome version + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ main: - // Channel for versions.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources and sort - // channel: runnable: [ meta, annotation_dir ] - // channel: skip: [ meta ] - ch_inputs_sorted = ch_annotations - .map { meta, annotation_dir -> - return [ - meta, - Utils.selectCurrentOrExisting(annotation_dir, meta, Constants.INPUT.LINX_ANNO_DIR_TUMOR), - ] - } - .branch { meta, annotation_dir -> - - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.LINX_PLOT_DIR_TUMOR) - - runnable: annotation_dir && !has_existing - skip: true - return meta - } - - // - // MODULE: LINX visualiser - // - // Create process input channel - // channel: [ meta_linx, annotation_dir ] - ch_linx_visualiser_inputs = ch_inputs_sorted.runnable - .map { meta, annotation_dir -> - - def meta_linx = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorDnaSampleName(meta), - ] - - return [meta_linx, annotation_dir] - } - - // Run process - VISUALISER( - ch_linx_visualiser_inputs, - genome_version, - ensembl_data_resources, - ) - - ch_versions = ch_versions.mix(VISUALISER.out.versions) - - // - // MODULE: gpgr LINX report - // - // Create process input channel - // channel: [ meta_gpgr, annotation_dir, visualiser_dir ] - ch_gpgr_linx_inputs = WorkflowOncoanalyser.groupByMeta( - ch_inputs_sorted.runnable, + // Channel for versions.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select input sources and sort + // channel: runnable: [ meta, annotation_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_annotations + .map { meta, annotation_dir -> + return [ + meta, + Utils.selectCurrentOrExisting(annotation_dir, meta, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + ] + } + .branch { meta, annotation_dir -> + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.LINX_PLOT_DIR_TUMOR) + + runnable: annotation_dir && !has_existing + skip: true + return meta + } + + // + // MODULE: LINX visualiser + // + // Create process input channel + // channel: [ meta_linx, annotation_dir ] + ch_linx_visualiser_inputs = ch_inputs_sorted.runnable + .map { meta, annotation_dir -> + + def meta_linx = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), + ] + + return [meta_linx, annotation_dir] + } + + // Run process + VISUALISER( + ch_linx_visualiser_inputs, + genome_version, + ensembl_data_resources, + ) + + ch_versions = ch_versions.mix(VISUALISER.out.versions) + + // + // MODULE: gpgr LINX report + // + // Create process input channel + // channel: [ meta_gpgr, annotation_dir, visualiser_dir ] + ch_gpgr_linx_inputs = WorkflowOncoanalyser.groupByMeta( + ch_inputs_sorted.runnable, + WorkflowOncoanalyser.restoreMeta(VISUALISER.out.plots, ch_inputs), + ) + .map { meta, annotation_dir, visualiser_dir -> + + def meta_gpgr_linx = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), + ] + + return [meta_gpgr_linx, annotation_dir, visualiser_dir] + } + + // Run process + REPORT( + ch_gpgr_linx_inputs, + ) + + ch_versions = ch_versions.mix(REPORT.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, visualiser_dir ] + ch_visualiser_dir_out = Channel.empty() + .mix( WorkflowOncoanalyser.restoreMeta(VISUALISER.out.plots, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - .map { meta, annotation_dir, visualiser_dir -> - - def meta_gpgr_linx = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorDnaSampleName(meta), - ] - - return [meta_gpgr_linx, annotation_dir, visualiser_dir] - } - - // Run process - REPORT( - ch_gpgr_linx_inputs, - ) - - ch_versions = ch_versions.mix(REPORT.out.versions) - - // Set outputs, restoring original meta - // channel: [ meta, visualiser_dir ] - ch_visualiser_dir_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(VISUALISER.out.plots, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) emit: - visualiser_dir = ch_visualiser_dir_out // channel: [ meta, visualiser_dir ] + visualiser_dir = ch_visualiser_dir_out // channel: [ meta, visualiser_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/orange_reporting/main.nf b/subworkflows/local/orange_reporting/main.nf index fcaada4c..451fa9d0 100644 --- a/subworkflows/local/orange_reporting/main.nf +++ b/subworkflows/local/orange_reporting/main.nf @@ -9,234 +9,234 @@ include { ORANGE } from '../../../modules/local/orange/main' workflow ORANGE_REPORTING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_bamtools_somatic // channel: [mandatory] [ meta, metrics ] - ch_bamtools_germline // channel: [mandatory] [ meta, metrics ] - ch_flagstat_somatic // channel: [mandatory] [ meta, metrics ] - ch_flagstat_germline // channel: [mandatory] [ meta, metrics ] - ch_sage_somatic // channel: [mandatory] [ meta, sage_dir ] - ch_sage_germline // channel: [mandatory] [ meta, sage_dir ] - ch_sage_somatic_append // channel: [mandatory] [ meta, sage_append_vcf ] - ch_sage_germline_append // channel: [mandatory] [ meta, sage_append_vcf ] - ch_purple // channel: [mandatory] [ meta, purple_dir ] - ch_linx_somatic_annotation // channel: [mandatory] [ meta, linx_annotation_dir ] - ch_linx_somatic_plot // channel: [mandatory] [ meta, linx_visualiser_dir ] - ch_linx_germline_annotation // channel: [mandatory] [ meta, linx_annotation_dir ] - ch_virusinterpreter // channel: [mandatory] [ meta, virusinterpreter_dir ] - ch_chord // channel: [mandatory] [ meta, chord_dir ] - ch_sigs // channel: [mandatory] [ meta, sigs_dir ] - ch_lilac // channel: [mandatory] [ meta, lilac_dir ] - ch_cuppa // channel: [mandatory] [ meta, cuppa_dir ] - ch_isofox // channel: [mandatory] [ meta, isofox_dir ] - - // Reference data - genome_version // channel: [mandatory] genome version - disease_ontology // channel: [mandatory] /path/to/disease_ontology - cohort_mapping // channel: [mandatory] /path/to/cohort_mapping - cohort_percentiles // channel: [mandatory] /path/to/cohort_percentiles - known_fusion_data // channel: [mandatory] /path/to/known_fusion_data - driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel - ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ - isofox_alt_sj // channel: [optional] /path/to/isofox_alt_sj - isofox_gene_distribution // channel: [optional] /path/to/isofox_gene_distribution + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_bamtools_somatic // channel: [mandatory] [ meta, metrics ] + ch_bamtools_germline // channel: [mandatory] [ meta, metrics ] + ch_flagstat_somatic // channel: [mandatory] [ meta, metrics ] + ch_flagstat_germline // channel: [mandatory] [ meta, metrics ] + ch_sage_somatic // channel: [mandatory] [ meta, sage_dir ] + ch_sage_germline // channel: [mandatory] [ meta, sage_dir ] + ch_sage_somatic_append // channel: [mandatory] [ meta, sage_append_vcf ] + ch_sage_germline_append // channel: [mandatory] [ meta, sage_append_vcf ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] + ch_linx_somatic_annotation // channel: [mandatory] [ meta, linx_annotation_dir ] + ch_linx_somatic_plot // channel: [mandatory] [ meta, linx_visualiser_dir ] + ch_linx_germline_annotation // channel: [mandatory] [ meta, linx_annotation_dir ] + ch_virusinterpreter // channel: [mandatory] [ meta, virusinterpreter_dir ] + ch_chord // channel: [mandatory] [ meta, chord_dir ] + ch_sigs // channel: [mandatory] [ meta, sigs_dir ] + ch_lilac // channel: [mandatory] [ meta, lilac_dir ] + ch_cuppa // channel: [mandatory] [ meta, cuppa_dir ] + ch_isofox // channel: [mandatory] [ meta, isofox_dir ] + + // Reference data + genome_version // channel: [mandatory] genome version + disease_ontology // channel: [mandatory] /path/to/disease_ontology + cohort_mapping // channel: [mandatory] /path/to/cohort_mapping + cohort_percentiles // channel: [mandatory] /path/to/cohort_percentiles + known_fusion_data // channel: [mandatory] /path/to/known_fusion_data + driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + isofox_alt_sj // channel: [optional] /path/to/isofox_alt_sj + isofox_gene_distribution // channel: [optional] /path/to/isofox_gene_distribution main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Set expected input ordering and size - input_expected_size = 18 - - dna_tumor_input_indexes = [ - 0, // bamtools_somatic - 2, // flagstat_somatic - 4, // sage_somatic - 8, // purple_dir - 9, // linx_somatic_annotation - 10, // linx_somatic_plot_dir - 15, // lilac_dir - ] - - dna_normal_input_indexes = [ - 1, // bamtools_germline - 3, // flagstat_germline - 5, // sage_germline - 11, // linx_germline_annotation - ] - - rna_tumor_input_indexes = [ - 6, // sage_somatic_append - 17, // isofox_dir - ] - - rna_sage_germline_append_index = 7 // sage_germline_append - - // Select input sources - // channel: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsage_append, nsage_append, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir ] - ch_inputs_selected = WorkflowOncoanalyser.groupByMeta( - ch_bamtools_somatic, - ch_bamtools_germline, - ch_flagstat_somatic, - ch_flagstat_germline, - ch_sage_somatic, - ch_sage_germline, - ch_sage_somatic_append, - ch_sage_germline_append, - ch_purple, - ch_linx_somatic_annotation, - ch_linx_somatic_plot, - ch_linx_germline_annotation, - ch_virusinterpreter, - ch_chord, - ch_sigs, - ch_lilac, - ch_cuppa, - ch_isofox, + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Set expected input ordering and size + input_expected_size = 18 + + dna_tumor_input_indexes = [ + 0, // bamtools_somatic + 2, // flagstat_somatic + 4, // sage_somatic + 8, // purple_dir + 9, // linx_somatic_annotation + 10, // linx_somatic_plot_dir + 15, // lilac_dir + ] + + dna_normal_input_indexes = [ + 1, // bamtools_germline + 3, // flagstat_germline + 5, // sage_germline + 11, // linx_germline_annotation + ] + + rna_tumor_input_indexes = [ + 6, // sage_somatic_append + 17, // isofox_dir + ] + + rna_sage_germline_append_index = 7 // sage_germline_append + + // Select input sources + // channel: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsage_append, nsage_append, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir ] + ch_inputs_selected = WorkflowOncoanalyser.groupByMeta( + ch_bamtools_somatic, + ch_bamtools_germline, + ch_flagstat_somatic, + ch_flagstat_germline, + ch_sage_somatic, + ch_sage_germline, + ch_sage_somatic_append, + ch_sage_germline_append, + ch_purple, + ch_linx_somatic_annotation, + ch_linx_somatic_plot, + ch_linx_germline_annotation, + ch_virusinterpreter, + ch_chord, + ch_sigs, + ch_lilac, + ch_cuppa, + ch_isofox, + ) + .map { d -> + + def meta = d[0] + def inputs = d[1..-1] + + assert inputs.size() == input_expected_size + + // NOTE(SW): avoiding further complexity with loops etc + + def inputs_selected = [ + Utils.selectCurrentOrExisting(inputs[0], meta, Constants.INPUT.BAMTOOLS_TUMOR), + Utils.selectCurrentOrExisting(inputs[1], meta, Constants.INPUT.BAMTOOLS_NORMAL), + Utils.selectCurrentOrExisting(inputs[2], meta, Constants.INPUT.FLAGSTAT_TUMOR), + Utils.selectCurrentOrExisting(inputs[3], meta, Constants.INPUT.FLAGSTAT_NORMAL), + Utils.selectCurrentOrExisting(inputs[4], meta, Constants.INPUT.SAGE_DIR_TUMOR), + Utils.selectCurrentOrExisting(inputs[5], meta, Constants.INPUT.SAGE_DIR_NORMAL), + Utils.selectCurrentOrExisting(inputs[6], meta, Constants.INPUT.SAGE_APPEND_VCF_TUMOR), + Utils.selectCurrentOrExisting(inputs[7], meta, Constants.INPUT.SAGE_APPEND_VCF_NORMAL), + Utils.selectCurrentOrExisting(inputs[8], meta, Constants.INPUT.PURPLE_DIR), + Utils.selectCurrentOrExisting(inputs[9], meta, Constants.INPUT.LINX_ANNO_DIR_TUMOR), + Utils.selectCurrentOrExisting(inputs[10], meta, Constants.INPUT.LINX_PLOT_DIR_TUMOR), + Utils.selectCurrentOrExisting(inputs[11], meta, Constants.INPUT.LINX_ANNO_DIR_NORMAL), + Utils.selectCurrentOrExisting(inputs[12], meta, Constants.INPUT.VIRUSINTERPRETER_DIR), + Utils.selectCurrentOrExisting(inputs[13], meta, Constants.INPUT.CHORD_DIR), + Utils.selectCurrentOrExisting(inputs[14], meta, Constants.INPUT.SIGS_DIR), + Utils.selectCurrentOrExisting(inputs[15], meta, Constants.INPUT.LILAC_DIR), + Utils.selectCurrentOrExisting(inputs[16], meta, Constants.INPUT.CUPPA_DIR), + Utils.selectCurrentOrExisting(inputs[17], meta, Constants.INPUT.ISOFOX_DIR), + ] + + return [meta, *inputs_selected] + } + + // Sort inputs + // channel: runnable: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsage_append, nsage_append, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_inputs_selected + .branch { d -> + + def meta = d[0] + def inputs = d[1..-1] + + def has_dna_tumor = dna_tumor_input_indexes + .collect { i -> inputs[i] } + .every() + + def has_rna_tumor = rna_tumor_input_indexes + .collect { i -> inputs[i] } + .every() + + runnable_dna_and_rna: has_dna_tumor && has_rna_tumor + runnable_dna: has_dna_tumor + skip: true + return meta + } + + // First set RNA reference files + // NOTE(SW): since the RNA reference files are provided as channels, I seem to be only able to include via channel ops + // channel: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsage_append, nsage_append, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir, isofox_alt_sj, isofox_gene_distribution ] + ch_inputs_runnable = Channel.empty() + .mix( + ch_inputs_sorted.runnable_dna.map { d -> [*d, [], []] }, + ch_inputs_sorted.runnable_dna_and_rna + .combine(isofox_alt_sj) + .combine(isofox_gene_distribution), ) - .map { d -> - - def meta = d[0] - def inputs = d[1..-1] - - assert inputs.size() == input_expected_size - - // NOTE(SW): avoiding further complexity with loops etc - - def inputs_selected = [ - Utils.selectCurrentOrExisting(inputs[0], meta, Constants.INPUT.BAMTOOLS_TUMOR), - Utils.selectCurrentOrExisting(inputs[1], meta, Constants.INPUT.BAMTOOLS_NORMAL), - Utils.selectCurrentOrExisting(inputs[2], meta, Constants.INPUT.FLAGSTAT_TUMOR), - Utils.selectCurrentOrExisting(inputs[3], meta, Constants.INPUT.FLAGSTAT_NORMAL), - Utils.selectCurrentOrExisting(inputs[4], meta, Constants.INPUT.SAGE_DIR_TUMOR), - Utils.selectCurrentOrExisting(inputs[5], meta, Constants.INPUT.SAGE_DIR_NORMAL), - Utils.selectCurrentOrExisting(inputs[6], meta, Constants.INPUT.SAGE_APPEND_VCF_TUMOR), - Utils.selectCurrentOrExisting(inputs[7], meta, Constants.INPUT.SAGE_APPEND_VCF_NORMAL), - Utils.selectCurrentOrExisting(inputs[8], meta, Constants.INPUT.PURPLE_DIR), - Utils.selectCurrentOrExisting(inputs[9], meta, Constants.INPUT.LINX_ANNO_DIR_TUMOR), - Utils.selectCurrentOrExisting(inputs[10], meta, Constants.INPUT.LINX_PLOT_DIR_TUMOR), - Utils.selectCurrentOrExisting(inputs[11], meta, Constants.INPUT.LINX_ANNO_DIR_NORMAL), - Utils.selectCurrentOrExisting(inputs[12], meta, Constants.INPUT.VIRUSINTERPRETER_DIR), - Utils.selectCurrentOrExisting(inputs[13], meta, Constants.INPUT.CHORD_DIR), - Utils.selectCurrentOrExisting(inputs[14], meta, Constants.INPUT.SIGS_DIR), - Utils.selectCurrentOrExisting(inputs[15], meta, Constants.INPUT.LILAC_DIR), - Utils.selectCurrentOrExisting(inputs[16], meta, Constants.INPUT.CUPPA_DIR), - Utils.selectCurrentOrExisting(inputs[17], meta, Constants.INPUT.ISOFOX_DIR), - ] - - return [meta, *inputs_selected] - } - // Sort inputs - // channel: runnable: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsage_append, nsage_append, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir ] - // channel: skip: [ meta ] - ch_inputs_sorted = ch_inputs_selected - .branch { d -> + // Create process input channel + // channel: sample_data: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsmlv_vcf, nsmlv_vcf, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir ] + // channel: isofox_alt_sj: [ isofox_alt_sj ] + // channel: isofox_gene_distribution: [ isofox_gene_distribution ] + ch_orange_inputs = ch_inputs_runnable + .multiMap { d -> + + def meta = d[0] + def inputs = d[1..-3] + + def isofox_alt_sj = d[-2] + def isofox_gene_distribution = d[-1] - def meta = d[0] - def inputs = d[1..-1] + def meta_orange = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + ] - def has_dna_tumor = dna_tumor_input_indexes - .collect { i -> inputs[i] } - .every() + def inputs_selected = inputs.clone() - def has_rna_tumor = rna_tumor_input_indexes - .collect { i -> inputs[i] } - .every() + // Require all normal DNA inputs to be present else clear them + def has_dna_normal = dna_normal_input_indexes + .collect { i -> inputs[i] } + .every() - runnable_dna_and_rna: has_dna_tumor && has_rna_tumor - runnable_dna: has_dna_tumor - skip: true - return meta + if (has_dna_normal) { + meta_orange.normal_dna_id = Utils.getNormalDnaSampleName(meta) + } else { + dna_normal_input_indexes.each { i -> inputs_selected[i] = [] } } - // First set RNA reference files - // NOTE(SW): since the RNA reference files are provided as channels, I seem to be only able to include via channel ops - // channel: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsage_append, nsage_append, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir, isofox_alt_sj, isofox_gene_distribution ] - ch_inputs_runnable = Channel.empty() - .mix( - ch_inputs_sorted.runnable_dna.map { d -> [*d, [], []] }, - ch_inputs_sorted.runnable_dna_and_rna - .combine(isofox_alt_sj) - .combine(isofox_gene_distribution), - ) - - // Create process input channel - // channel: sample_data: [ meta, tbt_metrics, nbt_metrics, tfs_metrics, nfs_metrics, tsage_dir, nsage_dir, tsmlv_vcf, nsmlv_vcf, purple_dir, tlinx_anno_dir, tlinx_plot_dir, nlinx_anno_dir, virusinterpreter_dir, chord_dir, sigs_dir, lilac_dir, cuppa_dir, isofox_dir ] - // channel: isofox_alt_sj: [ isofox_alt_sj ] - // channel: isofox_gene_distribution: [ isofox_gene_distribution ] - ch_orange_inputs = ch_inputs_runnable - .multiMap { d -> - - def meta = d[0] - def inputs = d[1..-3] - - def isofox_alt_sj = d[-2] - def isofox_gene_distribution = d[-1] - - def meta_orange = [ - key: meta.group_id, - id: meta.group_id, - tumor_id: Utils.getTumorDnaSampleName(meta), - ] - - def inputs_selected = inputs.clone() - - // Require all normal DNA inputs to be present else clear them - def has_dna_normal = dna_normal_input_indexes - .collect { i -> inputs[i] } - .every() - - if (has_dna_normal) { - meta_orange.normal_dna_id = Utils.getNormalDnaSampleName(meta) - } else { - dna_normal_input_indexes.each { i -> inputs_selected[i] = [] } - } - - // Require all tumor RNA inputs to be present else clear them - // SAGE append germline is only required when normal DNA is present - def rna_tumor_input_indexes_ready - if (has_dna_normal) { - rna_tumor_input_indexes_ready = [*rna_tumor_input_indexes, rna_sage_germline_append_index] - } else { - rna_tumor_input_indexes_ready = rna_tumor_input_indexes.clone() - } - - def has_rna_tumor = rna_tumor_input_indexes_ready - .collect { i -> inputs[i] } - .every() - - if (has_rna_tumor) { - meta_orange.tumor_rna_id = Utils.getTumorRnaSampleName(meta) - } else { - rna_tumor_input_indexes.each { i -> inputs_selected[i] = [] } - } - - assert inputs_selected.size() == input_expected_size - - sample_data: [meta_orange, *inputs_selected] - isofox_alt_sj: isofox_alt_sj - isofox_gene_distribution: isofox_gene_distribution + // Require all tumor RNA inputs to be present else clear them + // SAGE append germline is only required when normal DNA is present + def rna_tumor_input_indexes_ready + if (has_dna_normal) { + rna_tumor_input_indexes_ready = [*rna_tumor_input_indexes, rna_sage_germline_append_index] + } else { + rna_tumor_input_indexes_ready = rna_tumor_input_indexes.clone() } - // Run process - ORANGE( - ch_orange_inputs.sample_data, - genome_version, - disease_ontology, - cohort_mapping, - cohort_percentiles, - known_fusion_data, - driver_gene_panel, - ensembl_data_resources, - ch_orange_inputs.isofox_alt_sj, - ch_orange_inputs.isofox_gene_distribution, - "5.34 [oncoanalyser]", - ) + def has_rna_tumor = rna_tumor_input_indexes_ready + .collect { i -> inputs[i] } + .every() + + if (has_rna_tumor) { + meta_orange.tumor_rna_id = Utils.getTumorRnaSampleName(meta) + } else { + rna_tumor_input_indexes.each { i -> inputs_selected[i] = [] } + } - ch_versions = ch_versions.mix(ORANGE.out.versions) + assert inputs_selected.size() == input_expected_size + + sample_data: [meta_orange, *inputs_selected] + isofox_alt_sj: isofox_alt_sj + isofox_gene_distribution: isofox_gene_distribution + } + + // Run process + ORANGE( + ch_orange_inputs.sample_data, + genome_version, + disease_ontology, + cohort_mapping, + cohort_percentiles, + known_fusion_data, + driver_gene_panel, + ensembl_data_resources, + ch_orange_inputs.isofox_alt_sj, + ch_orange_inputs.isofox_gene_distribution, + "5.34 [oncoanalyser]", + ) + + ch_versions = ch_versions.mix(ORANGE.out.versions) emit: - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/pave_annotation/main.nf b/subworkflows/local/pave_annotation/main.nf index 1517f92e..2092581e 100644 --- a/subworkflows/local/pave_annotation/main.nf +++ b/subworkflows/local/pave_annotation/main.nf @@ -10,170 +10,170 @@ include { PAVE_SOMATIC as SOMATIC } from '../../../modules/local/pave/somatic/ workflow PAVE_ANNOTATION { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_sage_germline_vcf // channel: [mandatory] [ meta, sage_germline_vcf, sage_somatic_tbi ] - ch_sage_somatic_vcf // channel: [mandatory] [ meta, sage_somatic_vcf, sage_somatic_tbi ] - - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_version // channel: [mandatory] genome version - genome_fai // channel: [mandatory] /path/to/genome_fai - sage_pon // channel: [mandatory] /path/to/sage_pon - pon_artefacts // channel: [optional] /path/to/pon_artefacts - sage_blocklist_regions // channel: [mandatory] /path/to/sage_blocklist_regions - sage_blocklist_sites // channel: [mandatory] /path/to/sage_blocklist_sites - clinvar_annotations // channel: [mandatory] /path/to/clinvar_annotations - segment_mappability // channel: [mandatory] /path/to/segment_mappability - driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel - ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ - gnomad_resource // channel: [mandatory] /path/to/gnomad_resource + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_sage_germline_vcf // channel: [mandatory] [ meta, sage_germline_vcf, sage_somatic_tbi ] + ch_sage_somatic_vcf // channel: [mandatory] [ meta, sage_somatic_vcf, sage_somatic_tbi ] + + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + sage_pon // channel: [mandatory] /path/to/sage_pon + pon_artefacts // channel: [optional] /path/to/pon_artefacts + sage_blocklist_regions // channel: [mandatory] /path/to/sage_blocklist_regions + sage_blocklist_sites // channel: [mandatory] /path/to/sage_blocklist_sites + clinvar_annotations // channel: [mandatory] /path/to/clinvar_annotations + segment_mappability // channel: [mandatory] /path/to/segment_mappability + driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + gnomad_resource // channel: [mandatory] /path/to/gnomad_resource main: - // Channel for version.yml files - ch_versions = Channel.empty() - - // - // MODULE: PAVE germline - // - // Select input sources and sort - // channel: runnable: [ meta, sage_vcf, sage_tbi ] - // channel: skip: [ meta ] - ch_sage_germline_inputs_sorted = ch_sage_germline_vcf - .map { meta, sage_vcf, sage_tbi -> - return [ - meta, - Utils.selectCurrentOrExisting(sage_vcf, meta, Constants.INPUT.SAGE_VCF_NORMAL), - Utils.selectCurrentOrExisting(sage_tbi, meta, Constants.INPUT.SAGE_VCF_TBI_NORMAL), - ] - } - .branch { meta, sage_vcf, sage_tbi -> - - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PAVE_VCF_NORMAL) - - runnable: Utils.hasTumorDna(meta) && Utils.hasNormalDna(meta) && sage_vcf && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_pave, sage_vcf, sage_tbi ] - ch_pave_germline_inputs = ch_sage_germline_inputs_sorted.runnable - .map { meta, sage_vcf, sage_tbi -> - - def meta_pave = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorDnaSampleName(meta), - ] - - return [meta_pave, sage_vcf, sage_tbi] - } - - // Run process - GERMLINE( - ch_pave_germline_inputs, - genome_fasta, - genome_version, - genome_fai, - sage_blocklist_regions, - sage_blocklist_sites, - clinvar_annotations, - segment_mappability, - driver_gene_panel, - ensembl_data_resources, - gnomad_resource, - ) + // Channel for version.yml files + ch_versions = Channel.empty() + + // + // MODULE: PAVE germline + // + // Select input sources and sort + // channel: runnable: [ meta, sage_vcf, sage_tbi ] + // channel: skip: [ meta ] + ch_sage_germline_inputs_sorted = ch_sage_germline_vcf + .map { meta, sage_vcf, sage_tbi -> + return [ + meta, + Utils.selectCurrentOrExisting(sage_vcf, meta, Constants.INPUT.SAGE_VCF_NORMAL), + Utils.selectCurrentOrExisting(sage_tbi, meta, Constants.INPUT.SAGE_VCF_TBI_NORMAL), + ] + } + .branch { meta, sage_vcf, sage_tbi -> + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PAVE_VCF_NORMAL) - ch_versions = ch_versions.mix(GERMLINE.out.versions) - - // - // MODULE: PAVE somatic - // - // Select input sources and sort - // channel: runnable: [ meta, sage_vcf, sage_tbi ] - // channel: skip: [ meta ] - ch_sage_somatic_inputs_sorted = ch_sage_somatic_vcf - .map { meta, sage_vcf, sage_tbi -> - return [ - meta, - Utils.selectCurrentOrExisting(sage_vcf, meta, Constants.INPUT.SAGE_VCF_TUMOR), - Utils.selectCurrentOrExisting(sage_tbi, meta, Constants.INPUT.SAGE_VCF_TBI_TUMOR), - ] - } - .branch { meta, sage_vcf, sage_tbi -> - - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PAVE_VCF_TUMOR) - - runnable: Utils.hasTumorDna(meta) && sage_vcf && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_pave, sage_vcf, sage_tbi ] - ch_pave_somatic_inputs = ch_sage_somatic_inputs_sorted.runnable - .map { meta, sage_vcf, sage_tbi -> - - def meta_pave = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorDnaSampleName(meta), - ] - - return [meta_pave, sage_vcf, sage_tbi] - } - - // Set resource files according to run mode - // NOTE(SW): required since certain files can be used in germline and somatic depending on mode - // but want to avoid duplicating as multiple inputs - // NOTE(SW): this pattern should be used only sparingly; implicit config from workflows is prefered - sage_blocklist_regions_somatic = sage_blocklist_regions - sage_blocklist_sites_somatic = sage_blocklist_sites - clinvar_annotations_somatic = clinvar_annotations - run_mode = Utils.getEnumFromString(params.mode, Constants.RunMode) - if (run_mode === Constants.RunMode.WGTS) { - sage_blocklist_regions_somatic = [] - sage_blocklist_sites_somatic = [] - clinvar_annotations_somatic = [] + runnable: Utils.hasTumorDna(meta) && Utils.hasNormalDna(meta) && sage_vcf && !has_existing + skip: true + return meta } - // Run process - SOMATIC( - ch_pave_somatic_inputs, - genome_fasta, - genome_version, - genome_fai, - sage_pon, - pon_artefacts, - sage_blocklist_regions_somatic, - sage_blocklist_sites_somatic, - clinvar_annotations_somatic, - segment_mappability, - driver_gene_panel, - ensembl_data_resources, - gnomad_resource, - ) + // Create process input channel + // channel: [ meta_pave, sage_vcf, sage_tbi ] + ch_pave_germline_inputs = ch_sage_germline_inputs_sorted.runnable + .map { meta, sage_vcf, sage_tbi -> - ch_versions = ch_versions.mix(SOMATIC.out.versions) + def meta_pave = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), + ] - // Set outputs, restoring original meta - // channel: [ meta, pave_vcf ] - ch_somatic_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), - ch_sage_somatic_inputs_sorted.skip.map { meta -> [meta, []] }, - ) + return [meta_pave, sage_vcf, sage_tbi] + } - ch_germline_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), - ch_sage_germline_inputs_sorted.skip.map { meta -> [meta, []] }, - ) + // Run process + GERMLINE( + ch_pave_germline_inputs, + genome_fasta, + genome_version, + genome_fai, + sage_blocklist_regions, + sage_blocklist_sites, + clinvar_annotations, + segment_mappability, + driver_gene_panel, + ensembl_data_resources, + gnomad_resource, + ) + + ch_versions = ch_versions.mix(GERMLINE.out.versions) + + // + // MODULE: PAVE somatic + // + // Select input sources and sort + // channel: runnable: [ meta, sage_vcf, sage_tbi ] + // channel: skip: [ meta ] + ch_sage_somatic_inputs_sorted = ch_sage_somatic_vcf + .map { meta, sage_vcf, sage_tbi -> + return [ + meta, + Utils.selectCurrentOrExisting(sage_vcf, meta, Constants.INPUT.SAGE_VCF_TUMOR), + Utils.selectCurrentOrExisting(sage_tbi, meta, Constants.INPUT.SAGE_VCF_TBI_TUMOR), + ] + } + .branch { meta, sage_vcf, sage_tbi -> + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PAVE_VCF_TUMOR) + + runnable: Utils.hasTumorDna(meta) && sage_vcf && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_pave, sage_vcf, sage_tbi ] + ch_pave_somatic_inputs = ch_sage_somatic_inputs_sorted.runnable + .map { meta, sage_vcf, sage_tbi -> + + def meta_pave = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), + ] + + return [meta_pave, sage_vcf, sage_tbi] + } + + // Set resource files according to run mode + // NOTE(SW): required since certain files can be used in germline and somatic depending on mode + // but want to avoid duplicating as multiple inputs + // NOTE(SW): this pattern should be used only sparingly; implicit config from workflows is prefered + sage_blocklist_regions_somatic = sage_blocklist_regions + sage_blocklist_sites_somatic = sage_blocklist_sites + clinvar_annotations_somatic = clinvar_annotations + run_mode = Utils.getEnumFromString(params.mode, Constants.RunMode) + if (run_mode === Constants.RunMode.WGTS) { + sage_blocklist_regions_somatic = [] + sage_blocklist_sites_somatic = [] + clinvar_annotations_somatic = [] + } + + // Run process + SOMATIC( + ch_pave_somatic_inputs, + genome_fasta, + genome_version, + genome_fai, + sage_pon, + pon_artefacts, + sage_blocklist_regions_somatic, + sage_blocklist_sites_somatic, + clinvar_annotations_somatic, + segment_mappability, + driver_gene_panel, + ensembl_data_resources, + gnomad_resource, + ) + + ch_versions = ch_versions.mix(SOMATIC.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, pave_vcf ] + ch_somatic_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), + ch_sage_somatic_inputs_sorted.skip.map { meta -> [meta, []] }, + ) + + ch_germline_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), + ch_sage_germline_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - germline = ch_germline_out // channel: [ meta, pave_vcf ] - somatic = ch_somatic_out // channel: [ meta, pave_vcf ] + germline = ch_germline_out // channel: [ meta, pave_vcf ] + somatic = ch_somatic_out // channel: [ meta, pave_vcf ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/prepare_inputs/main.nf b/subworkflows/local/prepare_inputs/main.nf index 18abe8eb..8a10e735 100644 --- a/subworkflows/local/prepare_inputs/main.nf +++ b/subworkflows/local/prepare_inputs/main.nf @@ -12,14 +12,13 @@ import Utils workflow PREPARE_INPUTS { take: - input_fp_str + input_fp_str main: - - ch_inputs = Channel.fromList( - Utils.parseInput(input_fp_str, workflow.stubRun, log) - ) + ch_inputs = Channel.fromList( + Utils.parseInput(input_fp_str, workflow.stubRun, log) + ) emit: - inputs = ch_inputs // channel: [ meta ] + inputs = ch_inputs // channel: [ meta ] } diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 3d0ab042..1b1bf8d5 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -21,253 +21,253 @@ include { WRITE_REFERENCE_DATA } from '../../../modu workflow PREPARE_REFERENCE { take: - run_config // channel: [mandatory] run configuration + run_config // channel: [mandatory] run configuration main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // - // Set some variables for brevity - // - ch_genome_fasta = Channel.fromPath(params.ref_data_genome_fasta) - ch_genome_version = Channel.value(params.genome_version) - run_virusinterpreter = run_config.mode !== Constants.RunMode.TARGETED && run_config.stages.virusinterpreter - - // - // Set .fai and .dict indexes, create if required - // - ch_genome_fai = getRefFileChannel('ref_data_genome_fai') - if (!params.ref_data_genome_fai) { - SAMTOOLS_FAIDX(ch_genome_fasta) - ch_genome_fai = SAMTOOLS_FAIDX.out.fai - ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions) - } - - ch_genome_dict = getRefFileChannel('ref_data_genome_dict') - if (!params.ref_data_genome_dict) { - SAMTOOLS_DICT(ch_genome_fasta) - ch_genome_dict = SAMTOOLS_DICT.out.dict - ch_versions = ch_versions.mix(SAMTOOLS_DICT.out.versions) - } + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // + // Set some variables for brevity + // + ch_genome_fasta = Channel.fromPath(params.ref_data_genome_fasta) + ch_genome_version = Channel.value(params.genome_version) + run_virusinterpreter = run_config.mode !== Constants.RunMode.TARGETED && run_config.stages.virusinterpreter + + // + // Set .fai and .dict indexes, create if required + // + ch_genome_fai = getRefFileChannel('ref_data_genome_fai') + if (!params.ref_data_genome_fai) { + SAMTOOLS_FAIDX(ch_genome_fasta) + ch_genome_fai = SAMTOOLS_FAIDX.out.fai + ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions) + } + + ch_genome_dict = getRefFileChannel('ref_data_genome_dict') + if (!params.ref_data_genome_dict) { + SAMTOOLS_DICT(ch_genome_fasta) + ch_genome_dict = SAMTOOLS_DICT.out.dict + ch_versions = ch_versions.mix(SAMTOOLS_DICT.out.versions) + } + + // + // Set bwa-mem2 index, unpack or create if required + // + ch_genome_bwa_index = Channel.empty() + if (run_config.has_dna && run_config.stages.alignment) { + if (!params.ref_data_genome_bwa_index) { + + BWAMEM2_INDEX( + ch_genome_fasta, + params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], + ) + ch_genome_bwa_index = BWAMEM2_INDEX.out.index + ch_versions = ch_versions.mix(BWAMEM2_INDEX.out.versions) - // - // Set bwa-mem2 index, unpack or create if required - // - ch_genome_bwa_index = Channel.empty() - if (run_config.has_dna && run_config.stages.alignment) { - if (!params.ref_data_genome_bwa_index) { + } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { - BWAMEM2_INDEX( - ch_genome_fasta, - params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], - ) - ch_genome_bwa_index = BWAMEM2_INDEX.out.index - ch_versions = ch_versions.mix(BWAMEM2_INDEX.out.versions) + ch_genome_bwa_index_inputs = Channel.fromPath(params.ref_data_genome_bwa_index) + .map { [[id: "bwa-mem2_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } - } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { + DECOMP_BWAMEM2_INDEX(ch_genome_bwa_index_inputs) + ch_genome_bwa_index = DECOMP_BWAMEM2_INDEX.out.dir - ch_genome_bwa_index_inputs = Channel.fromPath(params.ref_data_genome_bwa_index) - .map { [[id: "bwa-mem2_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } + } else { - DECOMP_BWAMEM2_INDEX(ch_genome_bwa_index_inputs) - ch_genome_bwa_index = DECOMP_BWAMEM2_INDEX.out.dir + ch_genome_bwa_index = getRefFileChannel('ref_data_genome_bwa_index') - } else { + } + } + + // + // Set and GRIDSS index, unpack or create if required + // + ch_genome_gridss_index = Channel.empty() + if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { + if (!params.ref_data_genome_gridss_index) { + + BWA_INDEX( + ch_genome_fasta, + params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], + ) + ch_versions = ch_versions.mix(BWA_INDEX.out.versions) - ch_genome_bwa_index = getRefFileChannel('ref_data_genome_bwa_index') + GRIDSS_INDEX( + ch_genome_fasta, + ch_genome_fai, + ch_genome_dict, + BWA_INDEX.out.index, + ) + ch_genome_gridss_index = GRIDSS_INDEX.out.index + ch_versions = ch_versions.mix(GRIDSS_INDEX.out.versions) - } - } + } else if (params.ref_data_genome_gridss_index.endsWith('.tar.gz')) { - // - // Set and GRIDSS index, unpack or create if required - // - ch_genome_gridss_index = Channel.empty() - if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { - if (!params.ref_data_genome_gridss_index) { + ch_genome_gridss_index_inputs = Channel.fromPath(params.ref_data_genome_gridss_index) + .map { [[id: "gridss_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } - BWA_INDEX( - ch_genome_fasta, - params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], - ) - ch_versions = ch_versions.mix(BWA_INDEX.out.versions) + DECOMP_GRIDSS_INDEX(ch_genome_gridss_index_inputs) + ch_genome_gridss_index = DECOMP_GRIDSS_INDEX.out.dir - GRIDSS_INDEX( - ch_genome_fasta, - ch_genome_fai, - ch_genome_dict, - BWA_INDEX.out.index, - ) - ch_genome_gridss_index = GRIDSS_INDEX.out.index - ch_versions = ch_versions.mix(GRIDSS_INDEX.out.versions) + } else { - } else if (params.ref_data_genome_gridss_index.endsWith('.tar.gz')) { + ch_genome_gridss_index = getRefFileChannel('ref_data_genome_gridss_index') - ch_genome_gridss_index_inputs = Channel.fromPath(params.ref_data_genome_gridss_index) - .map { [[id: "gridss_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } + } + } + + // + // Set STAR index path, unpack or create if required + // + ch_genome_star_index = Channel.empty() + if (run_config.has_rna_fastq && run_config.stages.alignment) { + if (!params.ref_data_genome_star_index) { + + STAR_GENOMEGENERATE( + ch_genome_fasta, + file(params.ref_data_genome_gtf), + ) + ch_genome_star_index = STAR_GENOMEGENERATE.out.index + ch_versions = ch_versions.mix(STAR_GENOMEGENERATE.out.versions) - DECOMP_GRIDSS_INDEX(ch_genome_gridss_index_inputs) - ch_genome_gridss_index = DECOMP_GRIDSS_INDEX.out.dir + } else if (params.ref_data_genome_star_index.endsWith('.tar.gz')) { - } else { + ch_genome_star_index_inputs = Channel.fromPath(params.ref_data_genome_star_index) + .map { [[id: "star_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } - ch_genome_gridss_index = getRefFileChannel('ref_data_genome_gridss_index') + DECOMP_STAR_INDEX(ch_genome_star_index_inputs) + ch_genome_star_index = DECOMP_STAR_INDEX.out.dir - } - } + } else { - // - // Set STAR index path, unpack or create if required - // - ch_genome_star_index = Channel.empty() - if (run_config.has_rna_fastq && run_config.stages.alignment) { - if (!params.ref_data_genome_star_index) { + ch_genome_star_index = getRefFileChannel('ref_data_genome_star_index') - STAR_GENOMEGENERATE( - ch_genome_fasta, - file(params.ref_data_genome_gtf), - ) - ch_genome_star_index = STAR_GENOMEGENERATE.out.index - ch_versions = ch_versions.mix(STAR_GENOMEGENERATE.out.versions) + } + } - } else if (params.ref_data_genome_star_index.endsWith('.tar.gz')) { + // + // Set VIRUSBreakend database path, unpack if required + // + ch_virusbreakenddb = Channel.empty() + if (run_config.has_dna && run_virusinterpreter) { + if (params.ref_data_virusbreakenddb_path.endsWith('.tar.gz')) { - ch_genome_star_index_inputs = Channel.fromPath(params.ref_data_genome_star_index) - .map { [[id: "star_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } + ch_virusbreakenddb_inputs = Channel.fromPath(params.ref_data_virusbreakenddb_path) + .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } - DECOMP_STAR_INDEX(ch_genome_star_index_inputs) - ch_genome_star_index = DECOMP_STAR_INDEX.out.dir + DECOMP_VIRUSBREAKEND_DB(ch_virusbreakenddb_inputs) + ch_virusbreakenddb = DECOMP_VIRUSBREAKEND_DB.out.dir - } else { + } else { - ch_genome_star_index = getRefFileChannel('ref_data_genome_star_index') + ch_virusbreakenddb = Channel.fromPath(params.ref_data_virusbreakenddb_path) - } } + } + + // + // Set HMF reference paths, unpack if required + // + ch_hmf_data = Channel.empty() + hmf_data_paths = params.hmf_data_paths[params.genome_version.toString()] + if (params.ref_data_hmf_data_path.endsWith('tar.gz')) { + + ch_hmf_data_inputs = Channel.fromPath(params.ref_data_hmf_data_path) + .map { [[id: "hmf_data_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } + + DECOMP_HMF_DATA(ch_hmf_data_inputs) + + ch_hmf_data = DECOMP_HMF_DATA.out.dir + .collect() + .map { dir_list -> + assert dir_list.size() == 1 + def dirpath = dir_list[0].toUriString() + return createDataMap(hmf_data_paths, dirpath) + } - // - // Set VIRUSBreakend database path, unpack if required - // - ch_virusbreakenddb = Channel.empty() - if (run_config.has_dna && run_virusinterpreter) { - if (params.ref_data_virusbreakenddb_path.endsWith('.tar.gz')) { + } else { - ch_virusbreakenddb_inputs = Channel.fromPath(params.ref_data_virusbreakenddb_path) - .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } + ch_hmf_data = Channel.value(createDataMap(hmf_data_paths, params.ref_data_hmf_data_path)) - DECOMP_VIRUSBREAKEND_DB(ch_virusbreakenddb_inputs) - ch_virusbreakenddb = DECOMP_VIRUSBREAKEND_DB.out.dir + } - } else { + // + // Set panel reference paths, unpack if required + // + ch_panel_data = Channel.empty() + if (run_config.mode === Constants.RunMode.TARGETED) { - ch_virusbreakenddb = Channel.fromPath(params.ref_data_virusbreakenddb_path) + panel_data_paths_versions = params.panel_data_paths[params.panel] + panel_data_paths = panel_data_paths_versions[params.genome_version.toString()] - } - } + if (params.ref_data_panel_data_path.endsWith('tar.gz')) { - // - // Set HMF reference paths, unpack if required - // - ch_hmf_data = Channel.empty() - hmf_data_paths = params.hmf_data_paths[params.genome_version.toString()] - if (params.ref_data_hmf_data_path.endsWith('tar.gz')) { + ch_panel_data_inputs = Channel.fromPath(params.ref_data_panel_data_path) + .map { [[id: "panel_data_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } - ch_hmf_data_inputs = Channel.fromPath(params.ref_data_hmf_data_path) - .map { [[id: "hmf_data_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } + DECOMP_PANEL_DATA(ch_panel_data_inputs) - DECOMP_HMF_DATA(ch_hmf_data_inputs) - - ch_hmf_data = DECOMP_HMF_DATA.out.dir + ch_panel_data = DECOMP_PANEL_DATA.out.dir .collect() .map { dir_list -> assert dir_list.size() == 1 def dirpath = dir_list[0].toUriString() - return createDataMap(hmf_data_paths, dirpath) + return createDataMap(panel_data_paths, dirpath) } } else { - ch_hmf_data = Channel.value(createDataMap(hmf_data_paths, params.ref_data_hmf_data_path)) - - } - - // - // Set panel reference paths, unpack if required - // - ch_panel_data = Channel.empty() - if (run_config.mode === Constants.RunMode.TARGETED) { - - panel_data_paths_versions = params.panel_data_paths[params.panel] - panel_data_paths = panel_data_paths_versions[params.genome_version.toString()] - - if (params.ref_data_panel_data_path.endsWith('tar.gz')) { + ch_panel_data = Channel.value(createDataMap(panel_data_paths, params.ref_data_panel_data_path)) - ch_panel_data_inputs = Channel.fromPath(params.ref_data_panel_data_path) - .map { [[id: "panel_data_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } - - DECOMP_PANEL_DATA(ch_panel_data_inputs) - - ch_panel_data = DECOMP_PANEL_DATA.out.dir - .collect() - .map { dir_list -> - assert dir_list.size() == 1 - def dirpath = dir_list[0].toUriString() - return createDataMap(panel_data_paths, dirpath) - } - - } else { - - ch_panel_data = Channel.value(createDataMap(panel_data_paths, params.ref_data_panel_data_path)) - - } } - - if (params.prepare_reference_only) { - - // Create channel of data files to stage (if not already local) and write - ch_refdata = Channel.empty() - .mix( - ch_genome_fasta, - ch_genome_fai, - ch_genome_dict, - ch_genome_bwa_index, - ch_genome_gridss_index, - ch_genome_star_index, - ch_virusbreakenddb, - // Also include base paths for hmf_data and panel_data - Channel.empty() - .mix( - ch_hmf_data, - ch_panel_data, - ) - .map { getDataBaseDirectory(it) } - ) - - WRITE_REFERENCE_DATA( - ch_refdata, - workflow.manifest.version, + } + + if (params.prepare_reference_only) { + + // Create channel of data files to stage (if not already local) and write + ch_refdata = Channel.empty() + .mix( + ch_genome_fasta, + ch_genome_fai, + ch_genome_dict, + ch_genome_bwa_index, + ch_genome_gridss_index, + ch_genome_star_index, + ch_virusbreakenddb, + // Also include base paths for hmf_data and panel_data + Channel.empty() + .mix( + ch_hmf_data, + ch_panel_data, + ) + .map { getDataBaseDirectory(it) } ) - // Clear all stages to prevent running any analysis - run_config.stages = [:] - } + WRITE_REFERENCE_DATA( + ch_refdata, + workflow.manifest.version, + ) + + // Clear all stages to prevent running any analysis + run_config.stages = [:] + } emit: - genome_fasta = ch_genome_fasta.first() // path: genome_fasta - genome_fai = ch_genome_fai.first() // path: genome_fai - genome_dict = ch_genome_dict.first() // path: genome_dict - genome_bwa_index = ch_genome_bwa_index.first() // path: genome_bwa_index - genome_gridss_index = ch_genome_gridss_index.first() // path: genome_gridss_index - genome_star_index = ch_genome_star_index.first() // path: genome_star_index - genome_version = ch_genome_version // val: genome_version - - virusbreakenddb = ch_virusbreakenddb.first() // path: VIRUSBreakend database - hmf_data = ch_hmf_data // map: HMF data paths - panel_data = ch_panel_data // map: Panel data paths - - versions = ch_versions // channel: [ versions.yml ] + genome_fasta = ch_genome_fasta.first() // path: genome_fasta + genome_fai = ch_genome_fai.first() // path: genome_fai + genome_dict = ch_genome_dict.first() // path: genome_dict + genome_bwa_index = ch_genome_bwa_index.first() // path: genome_bwa_index + genome_gridss_index = ch_genome_gridss_index.first() // path: genome_gridss_index + genome_star_index = ch_genome_star_index.first() // path: genome_star_index + genome_version = ch_genome_version // val: genome_version + + virusbreakenddb = ch_virusbreakenddb.first() // path: VIRUSBreakend database + hmf_data = ch_hmf_data // map: HMF data paths + panel_data = ch_panel_data // map: Panel data paths + + versions = ch_versions // channel: [ versions.yml ] } def getRefFileChannel(key) { diff --git a/subworkflows/local/purple_calling/main.nf b/subworkflows/local/purple_calling/main.nf index 229e2fbb..48142ae9 100644 --- a/subworkflows/local/purple_calling/main.nf +++ b/subworkflows/local/purple_calling/main.nf @@ -9,137 +9,137 @@ include { PURPLE } from '../../../modules/local/purple/main' workflow PURPLE_CALLING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_amber // channel: [mandatory] [ meta, amber_dir ] - ch_cobalt // channel: [mandatory] [ meta, cobalt_dir ] - ch_smlv_somatic // channel: [mandatory] [ meta, pave_vcf ] - ch_smlv_germline // channel: [mandatory] [ meta, pave_vcf ] - ch_sv_somatic // channel: [mandatory] [ meta, gripss_vcf, gripss_tbi ] - ch_sv_germline // channel: [mandatory] [ meta, gripss_vcf, gripss_tbi ] - ch_sv_somatic_unfiltered // channel: [mandatory] [ meta, gripss_vcf, gripss_tbi ] - - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_version // channel: [mandatory] genome version - genome_fai // channel: [mandatory] /path/to/genome_fai - genome_dict // channel: [mandatory] /path/to/genome_dict - gc_profile // channel: [mandatory] /path/to/gc_profile - sage_known_hotspots_somatic // channel: [mandatory] /path/to/sage_known_hotspots_somatic - sage_known_hotspots_germline // channel: [optional] /path/to/sage_known_hotspots_germline - driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel - ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ - purple_germline_del // channel: [optional] /path/to/purple_germline_del - target_region_bed // channel: [optional] /path/to/target_region_bed - target_region_ratios // channel: [optional] /path/to/target_region_ratios - target_region_msi_indels // channel: [optional] /path/to/target_region_msi_indels + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_amber // channel: [mandatory] [ meta, amber_dir ] + ch_cobalt // channel: [mandatory] [ meta, cobalt_dir ] + ch_smlv_somatic // channel: [mandatory] [ meta, pave_vcf ] + ch_smlv_germline // channel: [mandatory] [ meta, pave_vcf ] + ch_sv_somatic // channel: [mandatory] [ meta, gripss_vcf, gripss_tbi ] + ch_sv_germline // channel: [mandatory] [ meta, gripss_vcf, gripss_tbi ] + ch_sv_somatic_unfiltered // channel: [mandatory] [ meta, gripss_vcf, gripss_tbi ] + + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict + gc_profile // channel: [mandatory] /path/to/gc_profile + sage_known_hotspots_somatic // channel: [mandatory] /path/to/sage_known_hotspots_somatic + sage_known_hotspots_germline // channel: [optional] /path/to/sage_known_hotspots_germline + driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + purple_germline_del // channel: [optional] /path/to/purple_germline_del + target_region_bed // channel: [optional] /path/to/target_region_bed + target_region_ratios // channel: [optional] /path/to/target_region_ratios + target_region_msi_indels // channel: [optional] /path/to/target_region_msi_indels main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources - // channel: [ meta, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] - ch_inputs_selected = WorkflowOncoanalyser.groupByMeta( - ch_amber, - ch_cobalt, - ch_sv_somatic, - ch_sv_somatic_unfiltered, - ch_sv_germline, - ch_smlv_somatic, - ch_smlv_germline, - ) - .map { d -> - - def meta = d[0] - - // NOTE(SW): avoiding further complexity with loops etc - - def inputs = [ - Utils.selectCurrentOrExisting(d[1], meta, Constants.INPUT.AMBER_DIR), - Utils.selectCurrentOrExisting(d[2], meta, Constants.INPUT.COBALT_DIR), - Utils.selectCurrentOrExisting(d[3], meta, Constants.INPUT.GRIPSS_VCF_TUMOR), - Utils.selectCurrentOrExisting(d[4], meta, Constants.INPUT.GRIPSS_VCF_TUMOR_TBI), - Utils.selectCurrentOrExisting(d[5], meta, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR), - Utils.selectCurrentOrExisting(d[6], meta, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR_TBI), - Utils.selectCurrentOrExisting(d[7], meta, Constants.INPUT.GRIPSS_VCF_NORMAL), - Utils.selectCurrentOrExisting(d[8], meta, Constants.INPUT.GRIPSS_VCF_NORMAL_TBI), - Utils.selectCurrentOrExisting(d[9], meta, Constants.INPUT.PAVE_VCF_TUMOR), - Utils.selectCurrentOrExisting(d[10], meta, Constants.INPUT.PAVE_VCF_NORMAL), - ] - - return [meta, *inputs] - } - - // Sort inputs - // channel: runnable: [ meta, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] - // channel: skip: [ meta ] - ch_inputs_sorted = ch_inputs_selected - .branch { d -> - def meta = d[0] - def amber_dir = d[1] - def cobalt_dir = d[2] - - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) - - runnable: amber_dir && cobalt_dir && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_purple, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] - ch_purple_inputs = ch_inputs_sorted.runnable - .map { d -> - - def meta = d[0] - def inputs = d[1..-1] - - def meta_purple = [ - key: meta.group_id, - id: meta.group_id, - tumor_id: Utils.getTumorDnaSampleName(meta), - ] - - if (Utils.hasNormalDna(meta)) { - meta_purple.normal_id = Utils.getNormalDnaSampleName(meta) - } - - return [meta_purple, *inputs] - + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select input sources + // channel: [ meta, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] + ch_inputs_selected = WorkflowOncoanalyser.groupByMeta( + ch_amber, + ch_cobalt, + ch_sv_somatic, + ch_sv_somatic_unfiltered, + ch_sv_germline, + ch_smlv_somatic, + ch_smlv_germline, + ) + .map { d -> + + def meta = d[0] + + // NOTE(SW): avoiding further complexity with loops etc + + def inputs = [ + Utils.selectCurrentOrExisting(d[1], meta, Constants.INPUT.AMBER_DIR), + Utils.selectCurrentOrExisting(d[2], meta, Constants.INPUT.COBALT_DIR), + Utils.selectCurrentOrExisting(d[3], meta, Constants.INPUT.GRIPSS_VCF_TUMOR), + Utils.selectCurrentOrExisting(d[4], meta, Constants.INPUT.GRIPSS_VCF_TUMOR_TBI), + Utils.selectCurrentOrExisting(d[5], meta, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR), + Utils.selectCurrentOrExisting(d[6], meta, Constants.INPUT.GRIPSS_UNFILTERED_VCF_TUMOR_TBI), + Utils.selectCurrentOrExisting(d[7], meta, Constants.INPUT.GRIPSS_VCF_NORMAL), + Utils.selectCurrentOrExisting(d[8], meta, Constants.INPUT.GRIPSS_VCF_NORMAL_TBI), + Utils.selectCurrentOrExisting(d[9], meta, Constants.INPUT.PAVE_VCF_TUMOR), + Utils.selectCurrentOrExisting(d[10], meta, Constants.INPUT.PAVE_VCF_NORMAL), + ] + + return [meta, *inputs] + } + + // Sort inputs + // channel: runnable: [ meta, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_inputs_selected + .branch { d -> + def meta = d[0] + def amber_dir = d[1] + def cobalt_dir = d[2] + + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.PURPLE_DIR) + + runnable: amber_dir && cobalt_dir && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_purple, amber_dir, cobalt_dir, sv_somatic_vcf, sv_somatic_tbi, sv_somatic_unfiltered_vcf, sv_somatic_unfiltered_tbi, sv_germline_vcf, sv_germline_tbi, smlv_somatic_vcf, smlv_germline_vcf ] + ch_purple_inputs = ch_inputs_sorted.runnable + .map { d -> + + def meta = d[0] + def inputs = d[1..-1] + + def meta_purple = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + ] + + if (Utils.hasNormalDna(meta)) { + meta_purple.normal_id = Utils.getNormalDnaSampleName(meta) } - // Run process - PURPLE( - ch_purple_inputs, - genome_fasta, - genome_version, - genome_fai, - genome_dict, - gc_profile, - sage_known_hotspots_somatic, - sage_known_hotspots_germline, - driver_gene_panel, - ensembl_data_resources, - purple_germline_del, - target_region_bed, - target_region_ratios, - target_region_msi_indels, + return [meta_purple, *inputs] + + } + + // Run process + PURPLE( + ch_purple_inputs, + genome_fasta, + genome_version, + genome_fai, + genome_dict, + gc_profile, + sage_known_hotspots_somatic, + sage_known_hotspots_germline, + driver_gene_panel, + ensembl_data_resources, + purple_germline_del, + target_region_bed, + target_region_ratios, + target_region_msi_indels, + ) + + ch_versions = ch_versions.mix(PURPLE.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, purple_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(PURPLE.out.purple_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(PURPLE.out.versions) - - // Set outputs, restoring original meta - // channel: [ meta, purple_dir ] - ch_outputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(PURPLE.out.purple_dir, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - emit: - purple_dir = ch_outputs // channel: [ meta, purple_dir ] + purple_dir = ch_outputs // channel: [ meta, purple_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/read_alignment_dna/main.nf b/subworkflows/local/read_alignment_dna/main.nf index 0ec6fb04..6632f921 100644 --- a/subworkflows/local/read_alignment_dna/main.nf +++ b/subworkflows/local/read_alignment_dna/main.nf @@ -10,208 +10,209 @@ include { FASTP } from '../../../modules/local/fastp/main' workflow READ_ALIGNMENT_DNA { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_bwa_index // channel: [mandatory] /path/to/genome_bwa_index_dir/ + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_bwa_index // channel: [mandatory] /path/to/genome_bwa_index_dir/ - // Params - max_fastq_records // numeric: [mandatory] max number of FASTQ records per split + // Params + max_fastq_records // numeric: [mandatory] max number of FASTQ records per split main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Sort inputs, separate by tumor and normal - // channel: [ meta ] - ch_inputs_tumor_sorted = ch_inputs - .branch { meta -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_TUMOR) - runnable: Utils.hasTumorDnaFastq(meta) && !has_existing - skip: true - } + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Sort inputs, separate by tumor and normal + // channel: [ meta ] + ch_inputs_tumor_sorted = ch_inputs + .branch { meta -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_TUMOR) + runnable: Utils.hasTumorDnaFastq(meta) && !has_existing + skip: true + } - ch_inputs_normal_sorted = ch_inputs - .branch { meta -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_NORMAL) - runnable: Utils.hasNormalDnaFastq(meta) && !has_existing - skip: true - } + ch_inputs_normal_sorted = ch_inputs + .branch { meta -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_NORMAL) + runnable: Utils.hasNormalDnaFastq(meta) && !has_existing + skip: true + } - // Create FASTQ input channel - // channel: [ meta_fastq, fastq_fwd, fastq_rev ] - ch_fastq_inputs = Channel.empty() - .mix( - ch_inputs_tumor_sorted.runnable.map { meta -> [meta, Utils.getTumorDnaSample(meta), 'tumor'] }, - ch_inputs_normal_sorted.runnable.map { meta -> [meta, Utils.getNormalDnaSample(meta), 'normal'] }, - ) - .flatMap { meta, meta_sample, sample_type -> - meta_sample - .getAt(Constants.FileType.FASTQ) - .collect { key, fps -> - def (library_id, lane) = key - - def meta_fastq = [ - key: meta.group_id, - id: "${meta.group_id}_${meta_sample.sample_id}", - sample_id: meta_sample.sample_id, - library_id: library_id, - lane: lane, - sample_type: sample_type, - ] + // Create FASTQ input channel + // channel: [ meta_fastq, fastq_fwd, fastq_rev ] + ch_fastq_inputs = Channel.empty() + .mix( + ch_inputs_tumor_sorted.runnable.map { meta -> [meta, Utils.getTumorDnaSample(meta), 'tumor'] }, + ch_inputs_normal_sorted.runnable.map { meta -> [meta, Utils.getNormalDnaSample(meta), 'normal'] }, + ) + .flatMap { meta, meta_sample, sample_type -> + meta_sample + .getAt(Constants.FileType.FASTQ) + .collect { key, fps -> + def (library_id, lane) = key + + def meta_fastq = [ + key: meta.group_id, + id: "${meta.group_id}_${meta_sample.sample_id}", + sample_id: meta_sample.sample_id, + library_id: library_id, + lane: lane, + sample_type: sample_type, + ] - return [meta_fastq, fps['fwd'], fps['rev']] - } - } + return [meta_fastq, fps['fwd'], fps['rev']] + } + } - // - // MODULE: fastp - // - // Split FASTQ into chunks if requested for distributed processing - // channel: [ meta_fastq_ready, fastq_fwd, fastq_fwd ] - ch_fastqs_ready = Channel.empty() - if (max_fastq_records > 0) { + // + // MODULE: fastp + // + // Split FASTQ into chunks if requested for distributed processing + // channel: [ meta_fastq_ready, fastq_fwd, fastq_fwd ] + ch_fastqs_ready = Channel.empty() + if (max_fastq_records > 0) { - // Run process - FASTP( - ch_fastq_inputs, - max_fastq_records, - ) + // Run process + FASTP( + ch_fastq_inputs, + max_fastq_records, + ) - ch_versions = ch_versions.mix(FASTP.out.versions) + ch_versions = ch_versions.mix(FASTP.out.versions) - // Prepare outputs within conditional block - ch_fastqs_ready = FASTP.out.fastq - .flatMap { meta_fastq, reads_fwd, reads_rev -> + // Prepare outputs within conditional block + ch_fastqs_ready = FASTP.out.fastq + .flatMap { meta_fastq, reads_fwd, reads_rev -> - def data = [reads_fwd, reads_rev] - .transpose() - .collect { fwd, rev -> + def data = [reads_fwd, reads_rev] + .transpose() + .collect { fwd, rev -> - def split_fwd = fwd.name.replaceAll('\\..+$', '') - def split_rev = rev.name.replaceAll('\\..+$', '') + def split_fwd = fwd.name.replaceAll('\\..+$', '') + def split_rev = rev.name.replaceAll('\\..+$', '') - assert split_fwd == split_rev + assert split_fwd == split_rev - // NOTE(SW): split allows meta_fastq_ready to be unique, which is required during reunite below - def meta_fastq_ready = [ - *:meta_fastq, - id: "${meta_fastq.id}_${split_fwd}", - split: split_fwd, - ] + // NOTE(SW): split allows meta_fastq_ready to be unique, which is required during reunite below + def meta_fastq_ready = [ + *:meta_fastq, + id: "${meta_fastq.id}_${split_fwd}", + split: split_fwd, + ] - return [meta_fastq_ready, fwd, rev] - } + return [meta_fastq_ready, fwd, rev] + } - return data - } + return data + } - } else { + } else { - ch_fastqs_ready = ch_fastq_inputs - .map { meta_fastq, fastq_fwd, fastq_rev -> + ch_fastqs_ready = ch_fastq_inputs + .map { meta_fastq, fastq_fwd, fastq_rev -> - def meta_fastq_ready = [ - *:meta_fastq, - split: null, - ] + def meta_fastq_ready = [ + *:meta_fastq, + split: null, + ] - return [meta_fastq_ready, fastq_fwd, fastq_rev] - } + return [meta_fastq_ready, fastq_fwd, fastq_rev] + } - } + } - // - // MODULE: BWA-MEM2 - // - // Create process input channel - // channel: [ meta_bwa, fastq_fwd, fastq_rev ] - ch_bwa_inputs = ch_fastqs_ready - .map { meta_fastq_ready, fastq_fwd, fastq_rev -> + // + // MODULE: BWA-MEM2 + // + // Create process input channel + // channel: [ meta_bwa, fastq_fwd, fastq_rev ] + ch_bwa_inputs = ch_fastqs_ready + .map { meta_fastq_ready, fastq_fwd, fastq_rev -> - def meta_bwa = [ - *:meta_fastq_ready, + def meta_bwa = [ + *:meta_fastq_ready, - // TODO(SW): understand target format - read_group: "${meta_fastq_ready.sample_id}.${meta_fastq_ready.library_id}.${meta_fastq_ready.lane}", + // TODO(SW): understand target format + read_group: "${meta_fastq_ready.sample_id}.${meta_fastq_ready.library_id}.${meta_fastq_ready.lane}", - ] + ] - return [meta_bwa, fastq_fwd, fastq_rev] - } + return [meta_bwa, fastq_fwd, fastq_rev] + } - // Run process - BWAMEM2_ALIGN( - ch_bwa_inputs, - genome_fasta, - genome_bwa_index, - ) + // Run process + BWAMEM2_ALIGN( + ch_bwa_inputs, + genome_fasta, + genome_bwa_index, + ) - ch_versions = ch_versions.mix(BWAMEM2_ALIGN.out.versions) + ch_versions = ch_versions.mix(BWAMEM2_ALIGN.out.versions) - // Reunite BAMs - // First, count expected BAMs per sample for non-blocking groupTuple op - // channel: [ meta_count, group_size ] - ch_sample_fastq_counts = ch_bwa_inputs - .map { meta_bwa, reads_fwd, reads_rev -> + // Reunite BAMs + // First, count expected BAMs per sample for non-blocking groupTuple op + // channel: [ meta_count, group_size ] + ch_sample_fastq_counts = ch_bwa_inputs + .map { meta_bwa, reads_fwd, reads_rev -> - def meta_count = [ - key: meta_bwa.key, - sample_type: meta_bwa.sample_type, - ] + def meta_count = [ + key: meta_bwa.key, + sample_type: meta_bwa.sample_type, + ] - return [meta_count, meta_bwa] - } - .groupTuple() - .map { meta_count, meta_bwas -> return [meta_count, meta_bwas.size()] } - - // Now, group with expected size then sort into tumor and normal channels - // channel: [ meta_group, [bam, ...], [bai, ...] ] - ch_bams_united = ch_sample_fastq_counts - .cross( - // First element to match meta_count above for `cross` - BWAMEM2_ALIGN.out.bam.map { meta_bwa, bam, bai -> [[key: meta_bwa.key, sample_type: meta_bwa.sample_type], bam, bai] } - ) - .map { count_tuple, bam_tuple -> - - def group_size = count_tuple[1] - def (meta_bam, bam, bai) = bam_tuple - - def meta_group = [ - *:meta_bam, - ] + return [meta_count, meta_bwa] + } + .groupTuple() + .map { meta_count, meta_bwas -> return [meta_count, meta_bwas.size()] } + + // Now, group with expected size then sort into tumor and normal channels + // channel: [ meta_group, [bam, ...], [bai, ...] ] + ch_bams_united = ch_sample_fastq_counts + .cross( + // First element to match meta_count above for `cross` + BWAMEM2_ALIGN.out.bam.map { meta_bwa, bam, bai -> [[key: meta_bwa.key, sample_type: meta_bwa.sample_type], bam, bai] } + ) + .map { count_tuple, bam_tuple -> - return tuple(groupKey(meta_group, group_size), bam, bai) - } - .groupTuple() - .branch { meta_group, bams, bais -> - assert ['tumor', 'normal'].contains(meta_group.sample_type) - tumor: meta_group.sample_type == 'tumor' - normal: meta_group.sample_type == 'normal' - placeholder: true - } + def group_size = count_tuple[1] + def (meta_bam, bam, bai) = bam_tuple + + def meta_group = [ + *:meta_bam, + ] + + return tuple(groupKey(meta_group, group_size), bam, bai) + } + .groupTuple() + .branch { meta_group, bams, bais -> + assert ['tumor', 'normal'].contains(meta_group.sample_type) + tumor: meta_group.sample_type == 'tumor' + normal: meta_group.sample_type == 'normal' + placeholder: true + } - // Set outputs, restoring original meta - // channel: [ meta, [bam, ...], [bai, ...] ] - ch_bam_tumor_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(ch_bams_united.tumor, ch_inputs), - ch_inputs_tumor_sorted.skip.map { meta -> [meta, [], []] }, - ) + // Set outputs, restoring original meta + // channel: [ meta, [bam, ...], [bai, ...] ] + ch_bam_tumor_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_bams_united.tumor, ch_inputs), + ch_inputs_tumor_sorted.skip.map { meta -> [meta, [], []] }, + ) - ch_bam_normal_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(ch_bams_united.normal, ch_inputs), - ch_inputs_normal_sorted.skip.map { meta -> [meta, [], []] }, - ) + ch_bam_normal_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_bams_united.normal, ch_inputs), + ch_inputs_normal_sorted.skip.map { meta -> [meta, [], []] }, + ) emit: - dna_tumor = ch_bam_tumor_out // channel: [ meta, [bam, ...], [bai, ...] ] - dna_normal = ch_bam_normal_out // channel: [ meta, [bam, ...], [bai, ...] ] - versions = ch_versions // channel: [ versions.yml ] + dna_tumor = ch_bam_tumor_out // channel: [ meta, [bam, ...], [bai, ...] ] + dna_normal = ch_bam_normal_out // channel: [ meta, [bam, ...], [bai, ...] ] + + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/read_alignment_rna/main.nf b/subworkflows/local/read_alignment_rna/main.nf index ca795e58..7565629b 100644 --- a/subworkflows/local/read_alignment_rna/main.nf +++ b/subworkflows/local/read_alignment_rna/main.nf @@ -12,205 +12,206 @@ include { STAR } from '../../../modules/local/star/main' workflow READ_ALIGNMENT_RNA { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] - // Reference data - genome_star_index // channel: [mandatory] /path/to/genome_star_index/ + // Reference data + genome_star_index // channel: [mandatory] /path/to/genome_star_index/ main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Sort inputs - // channel: [ meta ] - ch_inputs_sorted = ch_inputs - .branch { meta -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_RNA_TUMOR) - runnable: Utils.hasTumorRnaFastq(meta) && !has_existing - skip: true - } - - // Create FASTQ input channel - // channel: [ meta_fastq, fastq_fwd, fastq_rev ] - ch_fastq_inputs = ch_inputs_sorted.runnable - .flatMap { meta -> - def meta_sample = Utils.getTumorRnaSample(meta) - meta_sample - .getAt(Constants.FileType.FASTQ) - .collect { key, fps -> - def (library_id, lane) = key - - def meta_fastq = [ - key: meta.group_id, - id: "${meta.group_id}_${meta_sample.sample_id}", - sample_id: meta_sample.sample_id, - library_id: library_id, - lane: lane, - ] - - return [meta_fastq, fps['fwd'], fps['rev']] - } - } - - // - // MODULE: STAR - // - // Create process input channel - // channel: [ meta_star, fastq_fwd, fastq_rev ] - ch_star_inputs = ch_fastq_inputs - .map { meta_fastq, fastq_fwd, fastq_rev -> - def meta_star = [ - *:meta_fastq, - - - // TODO(SW): understand target format - read_group: "${meta_fastq.sample_id}.${meta_fastq.library_id}.${meta_fastq.lane}", - - - ] - - return [meta_star, fastq_fwd, fastq_rev] - } - - // Run process - STAR( - ch_star_inputs, - genome_star_index, + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Sort inputs + // channel: [ meta ] + ch_inputs_sorted = ch_inputs + .branch { meta -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_RNA_TUMOR) + runnable: Utils.hasTumorRnaFastq(meta) && !has_existing + skip: true + } + + // Create FASTQ input channel + // channel: [ meta_fastq, fastq_fwd, fastq_rev ] + ch_fastq_inputs = ch_inputs_sorted.runnable + .flatMap { meta -> + def meta_sample = Utils.getTumorRnaSample(meta) + meta_sample + .getAt(Constants.FileType.FASTQ) + .collect { key, fps -> + def (library_id, lane) = key + + def meta_fastq = [ + key: meta.group_id, + id: "${meta.group_id}_${meta_sample.sample_id}", + sample_id: meta_sample.sample_id, + library_id: library_id, + lane: lane, + ] + + return [meta_fastq, fps['fwd'], fps['rev']] + } + } + + // + // MODULE: STAR + // + // Create process input channel + // channel: [ meta_star, fastq_fwd, fastq_rev ] + ch_star_inputs = ch_fastq_inputs + .map { meta_fastq, fastq_fwd, fastq_rev -> + def meta_star = [ + *:meta_fastq, + + + // TODO(SW): understand target format + read_group: "${meta_fastq.sample_id}.${meta_fastq.library_id}.${meta_fastq.lane}", + + + ] + + return [meta_star, fastq_fwd, fastq_rev] + } + + // Run process + STAR( + ch_star_inputs, + genome_star_index, + ) + + ch_versions = ch_versions.mix(STAR.out.versions) + + // + // MODULE: SAMtools sort + // + // Create process input channel + // channel: [ meta_sort, bam ] + ch_sort_inputs = STAR.out.bam + .map { meta_star, bam -> + def meta_sort = [ + *:meta_star, + prefix: meta_star.read_group, + ] + + return [meta_sort, bam] + } + + // Run process + SAMTOOLS_SORT( + ch_sort_inputs, + ) + + ch_versions = ch_versions.mix(SAMTOOLS_SORT.out.versions) + + // + // MODULE: Sambamba merge + // + // Reunite BAMs + // First, count expected BAMs per sample for non-blocking groupTuple op + // channel: [ meta_count, group_size ] + ch_sample_fastq_counts = ch_star_inputs + .map { meta_star, reads_fwd, reads_rev -> + def meta_count = [key: meta_star.key] + return [meta_count, meta_star] + } + .groupTuple() + .map { meta_count, meta_stars -> return [meta_count, meta_stars.size()] } + + // Now, group with expected size then sort into tumor and normal channels + // channel: [ meta_group, [bam, ...] ] + ch_bams_united = ch_sample_fastq_counts + .cross( + // First element to match meta_count above for `cross` + SAMTOOLS_SORT.out.bam.map { meta_star, bam -> [[key: meta_star.key], bam] } ) - - ch_versions = ch_versions.mix(STAR.out.versions) - - // - // MODULE: SAMtools sort - // - // Create process input channel - // channel: [ meta_sort, bam ] - ch_sort_inputs = STAR.out.bam - .map { meta_star, bam -> - def meta_sort = [ - *:meta_star, - prefix: meta_star.read_group, - ] - - return [meta_sort, bam] - } - - // Run process - SAMTOOLS_SORT( - ch_sort_inputs, + .map { count_tuple, bam_tuple -> + + def group_size = count_tuple[1] + def (meta_bam, bam) = bam_tuple + + def meta_group = [ + *:meta_bam, + ] + + return tuple(groupKey(meta_group, group_size), bam) + } + .groupTuple() + + // Sort into merge-eligible BAMs (at least two BAMs required) + // channel: runnable: [ meta_group, [bam, ...] ] + // channel: skip: [ meta_group, bam ] + ch_bams_united_sorted = ch_bams_united + .branch { meta_group, bams -> + runnable: bams.size() > 1 + skip: true + return [meta_group, bams[0]] + } + + // Create process input channel + // channel: [ meta_merge, [bams, ...] ] + ch_merge_inputs = WorkflowOncoanalyser.restoreMeta(ch_bams_united_sorted.runnable, ch_inputs) + .map { meta, bams -> + def meta_merge = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorRnaSampleName(meta), + ] + return [meta_merge, bams] + } + + // Run process + SAMBAMBA_MERGE( + ch_merge_inputs, + ) + + ch_versions = ch_versions.mix(SAMBAMBA_MERGE.out.versions) + + // + // MODULE: GATK4 markduplicates + // + // Create process input channel + // channel: [ meta_markdups, bam ] + ch_markdups_inputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SAMBAMBA_MERGE.out.bam, ch_inputs), + WorkflowOncoanalyser.restoreMeta(ch_bams_united_sorted.skip, ch_inputs), ) - - ch_versions = ch_versions.mix(SAMTOOLS_SORT.out.versions) - - // - // MODULE: Sambamba merge - // - // Reunite BAMs - // First, count expected BAMs per sample for non-blocking groupTuple op - // channel: [ meta_count, group_size ] - ch_sample_fastq_counts = ch_star_inputs - .map { meta_star, reads_fwd, reads_rev -> - def meta_count = [key: meta_star.key] - return [meta_count, meta_star] - } - .groupTuple() - .map { meta_count, meta_stars -> return [meta_count, meta_stars.size()] } - - // Now, group with expected size then sort into tumor and normal channels - // channel: [ meta_group, [bam, ...] ] - ch_bams_united = ch_sample_fastq_counts - .cross( - // First element to match meta_count above for `cross` - SAMTOOLS_SORT.out.bam.map { meta_star, bam -> [[key: meta_star.key], bam] } - ) - .map { count_tuple, bam_tuple -> - - def group_size = count_tuple[1] - def (meta_bam, bam) = bam_tuple - - def meta_group = [ - *:meta_bam, - ] - - return tuple(groupKey(meta_group, group_size), bam) - } - .groupTuple() - - // Sort into merge-eligible BAMs (at least two BAMs required) - // channel: runnable: [ meta_group, [bam, ...] ] - // channel: skip: [ meta_group, bam ] - ch_bams_united_sorted = ch_bams_united - .branch { meta_group, bams -> - runnable: bams.size() > 1 - skip: true - return [meta_group, bams[0]] - } - - // Create process input channel - // channel: [ meta_merge, [bams, ...] ] - ch_merge_inputs = WorkflowOncoanalyser.restoreMeta(ch_bams_united_sorted.runnable, ch_inputs) - .map { meta, bams -> - def meta_merge = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorRnaSampleName(meta), - ] - return [meta_merge, bams] - } - - // Run process - SAMBAMBA_MERGE( - ch_merge_inputs, + .map { meta, bam -> + def meta_markdups = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorRnaSampleName(meta), + ] + return [meta_markdups, bam] + } + + // Run process + GATK4_MARKDUPLICATES( + ch_markdups_inputs, + [], + [], + ) + + ch_versions = ch_versions.mix(GATK4_MARKDUPLICATES.out.versions) + + // Combine BAMs and BAIs + // channel: [ meta, bam, bai ] + ch_bams_ready = WorkflowOncoanalyser.groupByMeta( + WorkflowOncoanalyser.restoreMeta(GATK4_MARKDUPLICATES.out.bam, ch_inputs), + WorkflowOncoanalyser.restoreMeta(GATK4_MARKDUPLICATES.out.bai, ch_inputs), + ) + + // Set outputs + // channel: [ meta, bam, bai ] + ch_bam_out = Channel.empty() + .mix( + ch_bams_ready, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, ) - ch_versions = ch_versions.mix(SAMBAMBA_MERGE.out.versions) - - // - // MODULE: GATK4 markduplicates - // - // Create process input channel - // channel: [ meta_markdups, bam ] - ch_markdups_inputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(SAMBAMBA_MERGE.out.bam, ch_inputs), - WorkflowOncoanalyser.restoreMeta(ch_bams_united_sorted.skip, ch_inputs), - ) - .map { meta, bam -> - def meta_markdups = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorRnaSampleName(meta), - ] - return [meta_markdups, bam] - } - - // Run process - GATK4_MARKDUPLICATES( - ch_markdups_inputs, - [], - [], - ) - - ch_versions = ch_versions.mix(GATK4_MARKDUPLICATES.out.versions) - - // Combine BAMs and BAIs - // channel: [ meta, bam, bai ] - ch_bams_ready = WorkflowOncoanalyser.groupByMeta( - WorkflowOncoanalyser.restoreMeta(GATK4_MARKDUPLICATES.out.bam, ch_inputs), - WorkflowOncoanalyser.restoreMeta(GATK4_MARKDUPLICATES.out.bai, ch_inputs), - ) - - // Set outputs - // channel: [ meta, bam, bai ] - ch_bam_out = Channel.empty() - .mix( - ch_bams_ready, - ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, - ) - emit: - rna_tumor = ch_bam_out // channel: [ meta, bam, bai ] - versions = ch_versions // channel: [ versions.yml ] + rna_tumor = ch_bam_out // channel: [ meta, bam, bai ] + + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/read_processing/main.nf b/subworkflows/local/read_processing/main.nf index 2e67d213..4a0967ca 100644 --- a/subworkflows/local/read_processing/main.nf +++ b/subworkflows/local/read_processing/main.nf @@ -9,114 +9,115 @@ include { MARKDUPS } from '../../../modules/local/markdups/main' workflow READ_PROCESSING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_dna_tumor // channel: [mandatory] [ meta, [bam, ...], [bai, ...] ] - ch_dna_normal // channel: [mandatory] [ meta, [bam, ...], [bai, ...] ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_dna_tumor // channel: [mandatory] [ meta, [bam, ...], [bai, ...] ] + ch_dna_normal // channel: [mandatory] [ meta, [bam, ...], [bai, ...] ] - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_ver // channel: [mandatory] genome version - genome_fai // channel: [mandatory] /path/to/genome_fai - genome_dict // channel: [mandatory] /path/to/genome_dict - unmap_regions // channel: [mandatory] /path/to/unmap_regions + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_ver // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict + unmap_regions // channel: [mandatory] /path/to/unmap_regions - // Params - has_umis // boolean: [mandatory] UMI processing flag + // Params + has_umis // boolean: [mandatory] UMI processing flag main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select and sort input sources, separating bytumor and normal - // channel: runnable: [ meta, [bam, ...], [bai, ...] ] - // channel: skip: [ meta ] - ch_inputs_tumor_sorted = ch_dna_tumor - .map { meta, bams, bais -> - return [ - meta, - Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_TUMOR) ? [Utils.getInput(meta, Constants.INPUT.BAM_DNA_TUMOR)] : bams, - Utils.hasExistingInput(meta, Constants.INPUT.BAI_DNA_TUMOR) ? [Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR)] : bais, - ] - } - .branch { meta, bams, bais -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR) - runnable: bams && !has_existing - skip: true - return meta - } - - ch_inputs_normal_sorted = ch_dna_normal - .map { meta, bams, bais -> - return [ - meta, - Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_NORMAL) ? [Utils.getInput(meta, Constants.INPUT.BAM_DNA_NORMAL)] : bams, - Utils.hasExistingInput(meta, Constants.INPUT.BAI_DNA_NORMAL) ? [Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL)] : bais, - ] - } - .branch { meta, bams, bais -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL) - runnable: bams && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_markdups, [bam, ...], [bai, ...] ] - ch_markdups_inputs = Channel.empty() - .mix( - ch_inputs_tumor_sorted.runnable.map { meta, bams, bais -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bams, bais] }, - ch_inputs_normal_sorted.runnable.map { meta, bams, bais -> [meta, Utils.getNormalDnaSample(meta), 'normal', bams, bais] }, - ) - .map { meta, meta_sample, sample_type, bams, bais -> - - def meta_markdups = [ - key: meta.group_id, - id: "${meta.group_id}_${meta_sample.sample_id}", - sample_id: meta_sample.sample_id, - sample_type: sample_type, - ] - - return [meta_markdups, bams, bais] - } - - // Run process - MARKDUPS( - ch_markdups_inputs, - genome_fasta, - genome_ver, - genome_fai, - genome_dict, - unmap_regions, - has_umis, + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select and sort input sources, separating bytumor and normal + // channel: runnable: [ meta, [bam, ...], [bai, ...] ] + // channel: skip: [ meta ] + ch_inputs_tumor_sorted = ch_dna_tumor + .map { meta, bams, bais -> + return [ + meta, + Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_TUMOR) ? [Utils.getInput(meta, Constants.INPUT.BAM_DNA_TUMOR)] : bams, + Utils.hasExistingInput(meta, Constants.INPUT.BAI_DNA_TUMOR) ? [Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR)] : bais, + ] + } + .branch { meta, bams, bais -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR) + runnable: bams && !has_existing + skip: true + return meta + } + + ch_inputs_normal_sorted = ch_dna_normal + .map { meta, bams, bais -> + return [ + meta, + Utils.hasExistingInput(meta, Constants.INPUT.BAM_DNA_NORMAL) ? [Utils.getInput(meta, Constants.INPUT.BAM_DNA_NORMAL)] : bams, + Utils.hasExistingInput(meta, Constants.INPUT.BAI_DNA_NORMAL) ? [Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL)] : bais, + ] + } + .branch { meta, bams, bais -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL) + runnable: bams && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_markdups, [bam, ...], [bai, ...] ] + ch_markdups_inputs = Channel.empty() + .mix( + ch_inputs_tumor_sorted.runnable.map { meta, bams, bais -> [meta, Utils.getTumorDnaSample(meta), 'tumor', bams, bais] }, + ch_inputs_normal_sorted.runnable.map { meta, bams, bais -> [meta, Utils.getNormalDnaSample(meta), 'normal', bams, bais] }, + ) + .map { meta, meta_sample, sample_type, bams, bais -> + + def meta_markdups = [ + key: meta.group_id, + id: "${meta.group_id}_${meta_sample.sample_id}", + sample_id: meta_sample.sample_id, + sample_type: sample_type, + ] + + return [meta_markdups, bams, bais] + } + + // Run process + MARKDUPS( + ch_markdups_inputs, + genome_fasta, + genome_ver, + genome_fai, + genome_dict, + unmap_regions, + has_umis, + ) + + // Sort into a tumor and normal channel + ch_markdups_out = MARKDUPS.out.bam + .branch { meta_markdups, bam, bai -> + assert ['tumor', 'normal'].contains(meta_markdups.sample_type) + tumor: meta_markdups.sample_type == 'tumor' + normal: meta_markdups.sample_type == 'normal' + placeholder: true + } + + // Set outputs, restoring original meta + // channel: [ meta, bam, bai ] + ch_bam_tumor_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_markdups_out.tumor, ch_inputs), + ch_inputs_tumor_sorted.skip.map { meta -> [meta, [], []] }, ) - // Sort into a tumor and normal channel - ch_markdups_out = MARKDUPS.out.bam - .branch { meta_markdups, bam, bai -> - assert ['tumor', 'normal'].contains(meta_markdups.sample_type) - tumor: meta_markdups.sample_type == 'tumor' - normal: meta_markdups.sample_type == 'normal' - placeholder: true - } - - // Set outputs, restoring original meta - // channel: [ meta, bam, bai ] - ch_bam_tumor_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(ch_markdups_out.tumor, ch_inputs), - ch_inputs_tumor_sorted.skip.map { meta -> [meta, [], []] }, - ) - - ch_bam_normal_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(ch_markdups_out.normal, ch_inputs), - ch_inputs_normal_sorted.skip.map { meta -> [meta, [], []] }, - ) + ch_bam_normal_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(ch_markdups_out.normal, ch_inputs), + ch_inputs_normal_sorted.skip.map { meta -> [meta, [], []] }, + ) emit: - dna_tumor = ch_bam_tumor_out // channel: [ meta, bam, bai ] - dna_normal = ch_bam_normal_out // channel: [ meta, bam, bai ] - versions = ch_versions // channel: [ versions.yml ] + dna_tumor = ch_bam_tumor_out // channel: [ meta, bam, bai ] + dna_normal = ch_bam_normal_out // channel: [ meta, bam, bai ] + + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/sage_append/main.nf b/subworkflows/local/sage_append/main.nf index 8dfee365..a7ded0be 100644 --- a/subworkflows/local/sage_append/main.nf +++ b/subworkflows/local/sage_append/main.nf @@ -10,163 +10,163 @@ include { SAGE_APPEND as GERMLINE } from '../../../modules/local/sage/append/mai workflow SAGE_APPEND { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_tumor_rna_bam // channel: [mandatory] [ meta, bam, bai ] - ch_purple_dir // channel: [mandatory] [ meta, purple_dir ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_rna_bam // channel: [mandatory] [ meta, bam, bai ] + ch_purple_dir // channel: [mandatory] [ meta, purple_dir ] - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_version // channel: [mandatory] genome version - genome_fai // channel: [mandatory] /path/to/genome_fai - genome_dict // channel: [mandatory] /path/to/genome_dict + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources and sort - // channel: runnable: [ meta, tumor_bam, tumor_bai, purple_dir ] - // channel: skip: [ meta ] - ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( - ch_tumor_rna_bam, - ch_purple_dir, - ) - .map { meta, tumor_bam, tumor_bai, purple_dir -> - return [ - meta, - Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_RNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_RNA_TUMOR), - Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), - ] - } - .branch { meta, tumor_bam, tumor_bai, purple_dir -> - runnable: tumor_bam && purple_dir - skip: true - return meta - } - - // - // MODULE: SAGE append germline - // - // Select inputs that are eligible to run - // channel: runnable: [ meta, tumor_bam, tumor_bai, purple_dir ] - // channel: skip: [ meta ] - ch_inputs_germline_sorted = ch_inputs_sorted.runnable - .branch { meta, tumor_bam, tumor_bai, purple_dir -> - - def tumor_dna_id = Utils.getTumorDnaSampleName(meta) - - def has_normal_dna = Utils.hasNormalDna(meta) - def has_tumor_rna = Utils.hasTumorRna(meta) - def has_smlv_germline = file(purple_dir).resolve("${tumor_dna_id}.purple.germline.vcf.gz") - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_APPEND_VCF_NORMAL) - - runnable: has_normal_dna && has_tumor_rna && has_smlv_germline && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_append, purple_smlv_vcf, tumor_bam, tumor_bai ] - ch_sage_append_germline_inputs = ch_inputs_germline_sorted.runnable - .map { meta, tumor_bam, tumor_bai, purple_dir -> - - def tumor_dna_id = Utils.getTumorDnaSampleName(meta) - - def meta_append = [ - key: meta.group_id, - id: meta.group_id, - tumor_rna_id: Utils.getTumorRnaSampleName(meta), - dna_id: Utils.getNormalDnaSampleName(meta), - ] - - def purple_smlv_vcf = file(purple_dir).resolve("${tumor_dna_id}.purple.germline.vcf.gz") - - return [meta_append, purple_smlv_vcf, tumor_bam, tumor_bai] - } - - // Run process - GERMLINE( - ch_sage_append_germline_inputs, - genome_fasta, - genome_version, - genome_fai, - genome_dict, + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select input sources and sort + // channel: runnable: [ meta, tumor_bam, tumor_bai, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_rna_bam, + ch_purple_dir, + ) + .map { meta, tumor_bam, tumor_bai, purple_dir -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_RNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_RNA_TUMOR), + Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), + ] + } + .branch { meta, tumor_bam, tumor_bai, purple_dir -> + runnable: tumor_bam && purple_dir + skip: true + return meta + } + + // + // MODULE: SAGE append germline + // + // Select inputs that are eligible to run + // channel: runnable: [ meta, tumor_bam, tumor_bai, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_germline_sorted = ch_inputs_sorted.runnable + .branch { meta, tumor_bam, tumor_bai, purple_dir -> + + def tumor_dna_id = Utils.getTumorDnaSampleName(meta) + + def has_normal_dna = Utils.hasNormalDna(meta) + def has_tumor_rna = Utils.hasTumorRna(meta) + def has_smlv_germline = file(purple_dir).resolve("${tumor_dna_id}.purple.germline.vcf.gz") + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_APPEND_VCF_NORMAL) + + runnable: has_normal_dna && has_tumor_rna && has_smlv_germline && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_append, purple_smlv_vcf, tumor_bam, tumor_bai ] + ch_sage_append_germline_inputs = ch_inputs_germline_sorted.runnable + .map { meta, tumor_bam, tumor_bai, purple_dir -> + + def tumor_dna_id = Utils.getTumorDnaSampleName(meta) + + def meta_append = [ + key: meta.group_id, + id: meta.group_id, + tumor_rna_id: Utils.getTumorRnaSampleName(meta), + dna_id: Utils.getNormalDnaSampleName(meta), + ] + + def purple_smlv_vcf = file(purple_dir).resolve("${tumor_dna_id}.purple.germline.vcf.gz") + + return [meta_append, purple_smlv_vcf, tumor_bam, tumor_bai] + } + + // Run process + GERMLINE( + ch_sage_append_germline_inputs, + genome_fasta, + genome_version, + genome_fai, + genome_dict, + ) + + ch_versions = ch_versions.mix(GERMLINE.out.versions) + + // + // MODULE: SAGE append somatic + // + // Select inputs that are eligible to run + // channel: runnable: [ meta, tumor_bam, tumor_bai, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_somatic_sorted = ch_inputs_sorted.runnable + .branch { meta, tumor_bam, tumor_bai, purple_dir -> + def tumor_dna_id = Utils.getTumorDnaSampleName(meta) + + def has_tumor_dna = Utils.hasTumorDna(meta) + def has_tumor_rna = Utils.hasTumorRna(meta) + def has_smlv_somatic = file(purple_dir).resolve("${tumor_dna_id}.purple.somatic.vcf.gz") + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_APPEND_VCF_TUMOR) + + runnable: has_tumor_dna && has_tumor_rna && has_smlv_somatic && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_append, purple_smlv_vcf, tumor_bam, tumor_bai ] + ch_sage_append_somatic_inputs = ch_inputs_somatic_sorted.runnable + .map { meta, tumor_bam, tumor_bai, purple_dir -> + + def tumor_dna_id = Utils.getTumorDnaSampleName(meta) + + def meta_append = [ + key: meta.group_id, + id: meta.group_id, + tumor_rna_id: Utils.getTumorRnaSampleName(meta), + dna_id: Utils.getTumorDnaSampleName(meta), + ] + + def purple_smlv_vcf = file(purple_dir).resolve("${tumor_dna_id}.purple.somatic.vcf.gz") + + return [meta_append, purple_smlv_vcf, tumor_bam, tumor_bai] + } + + // Run process + SOMATIC( + ch_sage_append_somatic_inputs, + genome_fasta, + genome_version, + genome_fai, + genome_dict, + ) + + ch_versions = ch_versions.mix(SOMATIC.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, sage_append_vcf ] + ch_somatic_vcf = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(GERMLINE.out.versions) - - // - // MODULE: SAGE append somatic - // - // Select inputs that are eligible to run - // channel: runnable: [ meta, tumor_bam, tumor_bai, purple_dir ] - // channel: skip: [ meta ] - ch_inputs_somatic_sorted = ch_inputs_sorted.runnable - .branch { meta, tumor_bam, tumor_bai, purple_dir -> - def tumor_dna_id = Utils.getTumorDnaSampleName(meta) - - def has_tumor_dna = Utils.hasTumorDna(meta) - def has_tumor_rna = Utils.hasTumorRna(meta) - def has_smlv_somatic = file(purple_dir).resolve("${tumor_dna_id}.purple.somatic.vcf.gz") - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_APPEND_VCF_TUMOR) - - runnable: has_tumor_dna && has_tumor_rna && has_smlv_somatic && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_append, purple_smlv_vcf, tumor_bam, tumor_bai ] - ch_sage_append_somatic_inputs = ch_inputs_somatic_sorted.runnable - .map { meta, tumor_bam, tumor_bai, purple_dir -> - - def tumor_dna_id = Utils.getTumorDnaSampleName(meta) - - def meta_append = [ - key: meta.group_id, - id: meta.group_id, - tumor_rna_id: Utils.getTumorRnaSampleName(meta), - dna_id: Utils.getTumorDnaSampleName(meta), - ] - - def purple_smlv_vcf = file(purple_dir).resolve("${tumor_dna_id}.purple.somatic.vcf.gz") - - return [meta_append, purple_smlv_vcf, tumor_bam, tumor_bai] - } - - // Run process - SOMATIC( - ch_sage_append_somatic_inputs, - genome_fasta, - genome_version, - genome_fai, - genome_dict, + ch_germline_vcf = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(SOMATIC.out.versions) - - // Set outputs, restoring original meta - // channel: [ meta, sage_append_vcf ] - ch_somatic_vcf = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), - ch_inputs_somatic_sorted.skip.map { meta -> [meta, []] }, - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - - ch_germline_vcf = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), - ch_inputs_germline_sorted.skip.map { meta -> [meta, []] }, - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - emit: - somatic_vcf = ch_somatic_vcf // channel: [ meta, sage_append_vcf ] - germline_vcf = ch_germline_vcf // channel: [ meta, sage_append_vcf ] + somatic_vcf = ch_somatic_vcf // channel: [ meta, sage_append_vcf ] + germline_vcf = ch_germline_vcf // channel: [ meta, sage_append_vcf ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/sage_calling/main.nf b/subworkflows/local/sage_calling/main.nf index 33d815d0..35a44d97 100644 --- a/subworkflows/local/sage_calling/main.nf +++ b/subworkflows/local/sage_calling/main.nf @@ -10,188 +10,188 @@ include { SAGE_SOMATIC as SOMATIC } from '../../../modules/local/sage/somatic/ workflow SAGE_CALLING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] - ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] - - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_version // channel: [mandatory] genome version - genome_fai // channel: [mandatory] /path/to/genome_fai - genome_dict // channel: [mandatory] /path/to/genome_dict - sage_known_hotspots_germline // channel: [optional] /path/to/sage_known_hotspots_germline - sage_known_hotspots_somatic // channel: [mandatory] /path/to/sage_known_hotspots_somatic - sage_actionable_panel // channel: [mandatory] /path/to/sage_actionable_panel - sage_coverage_panel // channel: [mandatory] /path/to/sage_coverage_panel - sage_highconf_regions // channel: [mandatory] /path/to/sage_highconf_regions - segment_mappability // channel: [mandatory] /path/to/segment_mappability - driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel - ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_normal_bam // channel: [mandatory] [ meta, bam, bai ] + + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_version // channel: [mandatory] genome version + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict + sage_known_hotspots_germline // channel: [optional] /path/to/sage_known_hotspots_germline + sage_known_hotspots_somatic // channel: [mandatory] /path/to/sage_known_hotspots_somatic + sage_actionable_panel // channel: [mandatory] /path/to/sage_actionable_panel + sage_coverage_panel // channel: [mandatory] /path/to/sage_coverage_panel + sage_highconf_regions // channel: [mandatory] /path/to/sage_highconf_regions + segment_mappability // channel: [mandatory] /path/to/segment_mappability + driver_gene_panel // channel: [mandatory] /path/to/driver_gene_panel + ensembl_data_resources // channel: [mandatory] /path/to/ensembl_data_resources/ main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Sort inputs - // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] - // channel: skip: [ meta ] - ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( - ch_tumor_bam, - ch_normal_bam, - ) - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - return [ - meta, - Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), - Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), - normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), - ] - } - .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - runnable: tumor_bam - skip: true - return meta - } - - // - // MODULE: SAGE germline - // - // Select inputs that are eligible to run - // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] - // channel: skip: [ meta ] - ch_inputs_germline_sorted = ch_inputs_sorted.runnable - .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - def has_tumor_normal = tumor_bam && normal_bam - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_VCF_NORMAL) - - runnable: has_tumor_normal && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai ] - ch_sage_germline_inputs = ch_inputs_germline_sorted.runnable - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - - def meta_sage = [ - key: meta.group_id, - id: meta.group_id, - tumor_id: Utils.getTumorDnaSampleName(meta), - normal_id: Utils.getNormalDnaSampleName(meta), - ] - - return [meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai] + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Sort inputs + // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] + // channel: skip: [ meta ] + ch_inputs_sorted = WorkflowOncoanalyser.groupByMeta( + ch_tumor_bam, + ch_normal_bam, + ) + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + tumor_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_TUMOR), + Utils.selectCurrentOrExisting(normal_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_NORMAL), + normal_bai ?: Utils.getInput(meta, Constants.INPUT.BAI_DNA_NORMAL), + ] + } + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + runnable: tumor_bam + skip: true + return meta + } + + // + // MODULE: SAGE germline + // + // Select inputs that are eligible to run + // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] + // channel: skip: [ meta ] + ch_inputs_germline_sorted = ch_inputs_sorted.runnable + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + def has_tumor_normal = tumor_bam && normal_bam + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_VCF_NORMAL) + + runnable: has_tumor_normal && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai ] + ch_sage_germline_inputs = ch_inputs_germline_sorted.runnable + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + + def meta_sage = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + normal_id: Utils.getNormalDnaSampleName(meta), + ] + + return [meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai] + } + + // Run process + GERMLINE( + ch_sage_germline_inputs, + genome_fasta, + genome_version, + genome_fai, + genome_dict, + sage_known_hotspots_germline, + sage_actionable_panel, + sage_coverage_panel, + sage_highconf_regions, + ensembl_data_resources, + ) + + ch_versions = ch_versions.mix(GERMLINE.out.versions) + + // + // MODULE: SAGE somatic + // + // Select inputs that are eligible to run + // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] + // channel: skip: [ meta ] + ch_inputs_somatic_sorted = ch_inputs_sorted.runnable + .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + def has_tumor = tumor_bam + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_VCF_TUMOR) + + runnable: has_tumor && !has_existing + skip: true + return meta + } + + // Create process input channel + // channel: tumor/normal: [ meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai ] + // channel: tumor only: [ meta_sage, tumor_bam, [], tumor_bai, [] ] + ch_sage_somatic_inputs = ch_inputs_somatic_sorted.runnable + .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> + + def meta_sage = [ + key: meta.group_id, + id: meta.group_id, + tumor_id: Utils.getTumorDnaSampleName(meta), + ] + + if (normal_bam) { + meta_sage.normal_id = Utils.getNormalDnaSampleName(meta) } - // Run process - GERMLINE( - ch_sage_germline_inputs, - genome_fasta, - genome_version, - genome_fai, - genome_dict, - sage_known_hotspots_germline, - sage_actionable_panel, - sage_coverage_panel, - sage_highconf_regions, - ensembl_data_resources, + return [meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai] + } + + // Run process + SOMATIC( + ch_sage_somatic_inputs, + genome_fasta, + genome_version, + genome_fai, + genome_dict, + sage_known_hotspots_somatic, + sage_actionable_panel, + sage_coverage_panel, + sage_highconf_regions, + ensembl_data_resources, + ) + + ch_versions = ch_versions.mix(SOMATIC.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, sage_vcf, sage_tbi ] + ch_somatic_vcf_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, ) - ch_versions = ch_versions.mix(GERMLINE.out.versions) - - // - // MODULE: SAGE somatic - // - // Select inputs that are eligible to run - // channel: runnable: [ meta, tumor_bam, tumor_bai, normal_bam, normal_bai ] - // channel: skip: [ meta ] - ch_inputs_somatic_sorted = ch_inputs_sorted.runnable - .branch { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - def has_tumor = tumor_bam - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SAGE_VCF_TUMOR) - - runnable: has_tumor && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: tumor/normal: [ meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai ] - // channel: tumor only: [ meta_sage, tumor_bam, [], tumor_bai, [] ] - ch_sage_somatic_inputs = ch_inputs_somatic_sorted.runnable - .map { meta, tumor_bam, tumor_bai, normal_bam, normal_bai -> - - def meta_sage = [ - key: meta.group_id, - id: meta.group_id, - tumor_id: Utils.getTumorDnaSampleName(meta), - ] - - if (normal_bam) { - meta_sage.normal_id = Utils.getNormalDnaSampleName(meta) - } - - return [meta_sage, tumor_bam, normal_bam, tumor_bai, normal_bai] - } + // channel: [ meta, sage_vcf, sage_tbi ] + ch_germline_vcf_out = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, [], []] }, + ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, + ) - // Run process - SOMATIC( - ch_sage_somatic_inputs, - genome_fasta, - genome_version, - genome_fai, - genome_dict, - sage_known_hotspots_somatic, - sage_actionable_panel, - sage_coverage_panel, - sage_highconf_regions, - ensembl_data_resources, + // channel: [ meta, sage_dir ] + ch_somatic_dir = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SOMATIC.out.sage_dir, ch_inputs), + ch_inputs_somatic_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(SOMATIC.out.versions) - - // Set outputs, restoring original meta - // channel: [ meta, sage_vcf, sage_tbi ] - ch_somatic_vcf_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(SOMATIC.out.vcf, ch_inputs), - ch_inputs_somatic_sorted.skip.map { meta -> [meta, [], []] }, - ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, - ) - - // channel: [ meta, sage_vcf, sage_tbi ] - ch_germline_vcf_out = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(GERMLINE.out.vcf, ch_inputs), - ch_inputs_germline_sorted.skip.map { meta -> [meta, [], []] }, - ch_inputs_sorted.skip.map { meta -> [meta, [], []] }, - ) - - // channel: [ meta, sage_dir ] - ch_somatic_dir = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(SOMATIC.out.sage_dir, ch_inputs), - ch_inputs_somatic_sorted.skip.map { meta -> [meta, []] }, - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - - // channel: [ meta, sage_dir ] - ch_germline_dir = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(GERMLINE.out.sage_dir, ch_inputs), - ch_inputs_germline_sorted.skip.map { meta -> [meta, []] }, - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) + // channel: [ meta, sage_dir ] + ch_germline_dir = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(GERMLINE.out.sage_dir, ch_inputs), + ch_inputs_germline_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, + ) emit: - germline_vcf = ch_germline_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] - somatic_vcf = ch_somatic_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] - germline_dir = ch_germline_dir // channel: [ meta, sage_dir ] - somatic_dir = ch_somatic_dir // channel: [ meta, sage_dir ] + germline_vcf = ch_germline_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] + somatic_vcf = ch_somatic_vcf_out // channel: [ meta, sage_vcf, sage_tbi ] + germline_dir = ch_germline_dir // channel: [ meta, sage_dir ] + somatic_dir = ch_somatic_dir // channel: [ meta, sage_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/sigs_fitting/main.nf b/subworkflows/local/sigs_fitting/main.nf index 41d2acb4..240ebc35 100644 --- a/subworkflows/local/sigs_fitting/main.nf +++ b/subworkflows/local/sigs_fitting/main.nf @@ -9,83 +9,83 @@ include { SIGS } from '../../../modules/local/sigs/main' workflow SIGS_FITTING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_purple // channel: [mandatory] [ meta, purple_dir ] + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] - // Reference data - sigs_signatures // channel: [mandatory] /path/to/sigs_signatures + // Reference data + sigs_signatures // channel: [mandatory] /path/to/sigs_signatures main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Select input sources - // channel: [ meta, purple_dir ] - ch_inputs_selected = ch_purple - .map { meta, purple_dir -> - return [meta, Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR)] + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Select input sources + // channel: [ meta, purple_dir ] + ch_inputs_selected = ch_purple + .map { meta, purple_dir -> + return [meta, Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR)] + } + + // Sort inputs + // channel: runnable: [ meta, purple_dir ] + // channel: skip: [ meta ] + ch_inputs_sorted = ch_inputs_selected + .branch { meta, purple_dir -> + + def has_dna = Utils.hasTumorDna(meta) + + def tumor_id + def has_smlv_vcf + if (has_dna) { + tumor_id = Utils.getTumorDnaSampleName(meta) + has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] } - // Sort inputs - // channel: runnable: [ meta, purple_dir ] - // channel: skip: [ meta ] - ch_inputs_sorted = ch_inputs_selected - .branch { meta, purple_dir -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SIGS_DIR) - def has_dna = Utils.hasTumorDna(meta) + runnable: has_dna && purple_dir && has_smlv_vcf && !has_existing + skip: true + return meta + } - def tumor_id - def has_smlv_vcf - if (has_dna) { - tumor_id = Utils.getTumorDnaSampleName(meta) - has_smlv_vcf = purple_dir ? file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") : [] - } + // Create process input channel + // channel: [ meta_sigs, smlv_vcf ] + ch_sigs_inputs = ch_inputs_sorted.runnable + .map { meta, purple_dir -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.SIGS_DIR) + def tumor_id = Utils.getTumorDnaSampleName(meta) - runnable: has_dna && purple_dir && has_smlv_vcf && !has_existing - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_sigs, smlv_vcf ] - ch_sigs_inputs = ch_inputs_sorted.runnable - .map { meta, purple_dir -> + def meta_sigs = [ + key: meta.group_id, + id: meta.group_id, + sample_id: tumor_id, + ] - def tumor_id = Utils.getTumorDnaSampleName(meta) + def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") - def meta_sigs = [ - key: meta.group_id, - id: meta.group_id, - sample_id: tumor_id, - ] + return [meta_sigs, smlv_vcf] + } - def smlv_vcf = file(purple_dir).resolve("${tumor_id}.purple.somatic.vcf.gz") + // Run process + SIGS( + ch_sigs_inputs, + sigs_signatures, + ) - return [meta_sigs, smlv_vcf] - } + ch_versions = ch_versions.mix(SIGS.out.versions) - // Run process - SIGS( - ch_sigs_inputs, - sigs_signatures, + // Set outputs, restoring original meta + // channel: [ meta, sigs_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(SIGS.out.sigs_dir, ch_inputs), + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(SIGS.out.versions) - - // Set outputs, restoring original meta - // channel: [ meta, sigs_dir ] - ch_outputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(SIGS.out.sigs_dir, ch_inputs), - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - emit: - sigs_dir = ch_outputs // channel: [ meta, sigs_dir ] + sigs_dir = ch_outputs // channel: [ meta, sigs_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/virusbreakend_calling/main.nf b/subworkflows/local/virusbreakend_calling/main.nf index 3e210365..ab5bb4fd 100644 --- a/subworkflows/local/virusbreakend_calling/main.nf +++ b/subworkflows/local/virusbreakend_calling/main.nf @@ -10,145 +10,145 @@ include { VIRUSINTERPRETER } from '../../../modules/local/virusinterpreter/main' workflow VIRUSBREAKEND_CALLING { take: - // Sample data - ch_inputs // channel: [mandatory] [ meta ] - ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] - ch_purple // channel: [mandatory] [ meta, purple_dir ] - ch_bamtools_somatic // channel: [mandatory] [ meta, metrics ] - - // Reference data - genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_fai // channel: [mandatory] /path/to/genome_fai - genome_dict // channel: [mandatory] /path/to/genome_dict - genome_gridss_index // channel: [mandatory] /path/to/genome_gridss_index - virusbreakenddb // channel: [mandatory] /path/to/virusbreakenddb/ - virus_taxonomy_db // channel: [mandatory] /path/to/virus_taxonomy_db - virus_reporting_db // channel: [mandatory] /path/to/virus_reporting_db - - // Params - gridss_config // channel: [optional] /path/to/gridss_config + // Sample data + ch_inputs // channel: [mandatory] [ meta ] + ch_tumor_bam // channel: [mandatory] [ meta, bam, bai ] + ch_purple // channel: [mandatory] [ meta, purple_dir ] + ch_bamtools_somatic // channel: [mandatory] [ meta, metrics ] + + // Reference data + genome_fasta // channel: [mandatory] /path/to/genome_fasta + genome_fai // channel: [mandatory] /path/to/genome_fai + genome_dict // channel: [mandatory] /path/to/genome_dict + genome_gridss_index // channel: [mandatory] /path/to/genome_gridss_index + virusbreakenddb // channel: [mandatory] /path/to/virusbreakenddb/ + virus_taxonomy_db // channel: [mandatory] /path/to/virus_taxonomy_db + virus_reporting_db // channel: [mandatory] /path/to/virus_reporting_db + + // Params + gridss_config // channel: [optional] /path/to/gridss_config main: - // Channel for version.yml files - // channel: [ versions.yml ] - ch_versions = Channel.empty() - - // Sort inputs - // NOTE(SW): VIRUSBreakend inputs are not allowed in the samplesheet, so aren't considered - // channel: [ meta, tumor_bam, tumor_bai ] - ch_inputs_sorted = ch_tumor_bam - .map { meta, tumor_bam, tumor_bai -> - return [ - meta, - Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), - Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), - ] - } - .branch { meta, tumor_bam, tumor_bai -> - def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.VIRUSINTERPRETER_DIR) - runnable: tumor_bam && !has_existing - skip: true - return meta - } - - // - // MODULE: VIRUSBreakend - // - // Create process input channel - // channel: [ meta_virus, tumor_bam ] - ch_virusbreakend_inputs = ch_inputs_sorted.runnable - .map { meta, tumor_bam, tumor_bai -> - - def meta_virus = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorDnaSampleName(meta), - ] - - return [meta_virus, tumor_bam] - } - - // Run process - VIRUSBREAKEND( - ch_virusbreakend_inputs, - gridss_config, - genome_fasta, - genome_fai, - genome_dict, - genome_gridss_index, - virusbreakenddb, + // Channel for version.yml files + // channel: [ versions.yml ] + ch_versions = Channel.empty() + + // Sort inputs + // NOTE(SW): VIRUSBreakend inputs are not allowed in the samplesheet, so aren't considered + // channel: [ meta, tumor_bam, tumor_bai ] + ch_inputs_sorted = ch_tumor_bam + .map { meta, tumor_bam, tumor_bai -> + return [ + meta, + Utils.selectCurrentOrExisting(tumor_bam, meta, Constants.INPUT.BAM_MARKDUPS_DNA_TUMOR), + Utils.selectCurrentOrExisting(tumor_bai, meta, Constants.INPUT.BAI_DNA_TUMOR), + ] + } + .branch { meta, tumor_bam, tumor_bai -> + def has_existing = Utils.hasExistingInput(meta, Constants.INPUT.VIRUSINTERPRETER_DIR) + runnable: tumor_bam && !has_existing + skip: true + return meta + } + + // + // MODULE: VIRUSBreakend + // + // Create process input channel + // channel: [ meta_virus, tumor_bam ] + ch_virusbreakend_inputs = ch_inputs_sorted.runnable + .map { meta, tumor_bam, tumor_bai -> + + def meta_virus = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), + ] + + return [meta_virus, tumor_bam] + } + + // Run process + VIRUSBREAKEND( + ch_virusbreakend_inputs, + gridss_config, + genome_fasta, + genome_fai, + genome_dict, + genome_gridss_index, + virusbreakenddb, + ) + + ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) + + // + // MODULE: Virus Interpreter + // + // Select input sources + // channel: [ meta, virus_tsv, purple_dir, metrics ] + ch_virusinterpreter_inputs_selected = WorkflowOncoanalyser.groupByMeta( + WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), + ch_purple, + ch_bamtools_somatic, + ) + .map { meta, virus_tsv, purple_dir, metrics -> + + def inputs = [ + virus_tsv, + Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), + Utils.selectCurrentOrExisting(metrics, meta, Constants.INPUT.BAMTOOLS_TUMOR), + ] + + return [meta, *inputs] + } + + // Sort inputs + // channel: [ meta, virus_tsv, purple_dir, metrics ] + // channel: skip: [ meta ] + ch_virusinterpreter_inputs_sorted = ch_virusinterpreter_inputs_selected + .branch { meta, virus_tsv, purple_dir, metrics -> + runnable: virus_tsv && purple_dir && metrics + skip: true + return meta + } + + // Create process input channel + // channel: [ meta_virus, virus_tsv, purple_dir, metrics ] + ch_virusinterpreter_inputs = ch_virusinterpreter_inputs_sorted.runnable + .map { d -> + + def meta = d[0] + def inputs = d[1..-1] + + def meta_virus = [ + key: meta.group_id, + id: meta.group_id, + sample_id: Utils.getTumorDnaSampleName(meta), + ] + + return [meta_virus, *inputs] + } + + // Run process + VIRUSINTERPRETER( + ch_virusinterpreter_inputs, + virus_taxonomy_db, + virus_reporting_db, + ) + + ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) + + // Set outputs, restoring original meta + // channel: [ meta, virusinterpreter_dir ] + ch_outputs = Channel.empty() + .mix( + WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter_dir, ch_inputs), + ch_virusinterpreter_inputs_sorted.skip.map { meta -> [meta, []] }, + ch_inputs_sorted.skip.map { meta -> [meta, []] }, ) - ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) - - // - // MODULE: Virus Interpreter - // - // Select input sources - // channel: [ meta, virus_tsv, purple_dir, metrics ] - ch_virusinterpreter_inputs_selected = WorkflowOncoanalyser.groupByMeta( - WorkflowOncoanalyser.restoreMeta(VIRUSBREAKEND.out.tsv, ch_inputs), - ch_purple, - ch_bamtools_somatic, - ) - .map { meta, virus_tsv, purple_dir, metrics -> - - def inputs = [ - virus_tsv, - Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), - Utils.selectCurrentOrExisting(metrics, meta, Constants.INPUT.BAMTOOLS_TUMOR), - ] - - return [meta, *inputs] - } - - // Sort inputs - // channel: [ meta, virus_tsv, purple_dir, metrics ] - // channel: skip: [ meta ] - ch_virusinterpreter_inputs_sorted = ch_virusinterpreter_inputs_selected - .branch { meta, virus_tsv, purple_dir, metrics -> - runnable: virus_tsv && purple_dir && metrics - skip: true - return meta - } - - // Create process input channel - // channel: [ meta_virus, virus_tsv, purple_dir, metrics ] - ch_virusinterpreter_inputs = ch_virusinterpreter_inputs_sorted.runnable - .map { d -> - - def meta = d[0] - def inputs = d[1..-1] - - def meta_virus = [ - key: meta.group_id, - id: meta.group_id, - sample_id: Utils.getTumorDnaSampleName(meta), - ] - - return [meta_virus, *inputs] - } - - // Run process - VIRUSINTERPRETER( - ch_virusinterpreter_inputs, - virus_taxonomy_db, - virus_reporting_db, - ) - - ch_versions = ch_versions.mix(VIRUSINTERPRETER.out.versions) - - // Set outputs, restoring original meta - // channel: [ meta, virusinterpreter_dir ] - ch_outputs = Channel.empty() - .mix( - WorkflowOncoanalyser.restoreMeta(VIRUSINTERPRETER.out.virusinterpreter_dir, ch_inputs), - ch_virusinterpreter_inputs_sorted.skip.map { meta -> [meta, []] }, - ch_inputs_sorted.skip.map { meta -> [meta, []] }, - ) - emit: - virusinterpreter_dir = ch_outputs // channel: [ meta, virusinterpreter_dir ] + virusinterpreter_dir = ch_outputs // channel: [ meta, virusinterpreter_dir ] - versions = ch_versions // channel: [ versions.yml ] + versions = ch_versions // channel: [ versions.yml ] } From 766bcb201c51395070ee6b1468f5bd803c9c51b9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 16:46:58 +1000 Subject: [PATCH 450/562] Remove quay.io qualifier from container URLs --- modules/local/amber/main.nf | 2 +- modules/local/bamtools/main.nf | 2 +- modules/local/bwa-mem2/mem/main.nf | 2 +- modules/local/chord/main.nf | 2 +- modules/local/cobalt/main.nf | 2 +- modules/local/cuppa/main.nf | 2 +- modules/local/custom/lilac_extract_and_index_contig/main.nf | 2 +- modules/local/custom/lilac_realign_reads_lilac/main.nf | 2 +- modules/local/custom/lilac_slice/main.nf | 2 +- modules/local/fastp/main.nf | 2 +- modules/local/gridss/index/main.nf | 2 +- modules/local/gripss/germline/main.nf | 2 +- modules/local/gripss/somatic/main.nf | 2 +- modules/local/isofox/main.nf | 2 +- modules/local/lilac/main.nf | 2 +- modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 2 +- modules/local/linxreport/main.nf | 2 +- modules/local/markdups/main.nf | 2 +- modules/local/orange/main.nf | 2 +- modules/local/pave/germline/main.nf | 2 +- modules/local/pave/somatic/main.nf | 2 +- modules/local/purple/main.nf | 2 +- modules/local/sage/append/main.nf | 2 +- modules/local/sage/germline/main.nf | 2 +- modules/local/sage/somatic/main.nf | 2 +- modules/local/sambamba/merge/main.nf | 2 +- modules/local/sigs/main.nf | 2 +- modules/local/star/main.nf | 2 +- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/depth_annotator/main.nf | 2 +- modules/local/svprep/preprocess/main.nf | 2 +- modules/local/svprep/svprep/main.nf | 2 +- modules/local/virusinterpreter/main.nf | 2 +- modules/nf-core/gatk4/markduplicates/main.nf | 2 +- modules/nf-core/samtools/dict/main.nf | 2 +- modules/nf-core/samtools/faidx/main.nf | 2 +- modules/nf-core/samtools/flagstat/main.nf | 2 +- modules/nf-core/samtools/sort/main.nf | 2 +- 41 files changed, 41 insertions(+), 41 deletions(-) diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index a360e0da..ebf0071e 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -5,7 +5,7 @@ process AMBER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-amber:4.0--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-amber:4.0--hdfd78af_0' }" + 'biocontainers/hmftools-amber:4.0--hdfd78af_0' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf index 64fa90c9..be436ace 100644 --- a/modules/local/bamtools/main.nf +++ b/modules/local/bamtools/main.nf @@ -5,7 +5,7 @@ process BAMTOOLS { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-bam-tools:1.2.1--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-bam-tools:1.2.1--hdfd78af_0' }" + 'biocontainers/hmftools-bam-tools:1.2.1--hdfd78af_0' }" input: tuple val(meta), path(bam), path(bai) diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index bbd4a6bc..9c44d086 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -5,7 +5,7 @@ process BWAMEM2_ALIGN { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' : - 'quay.io/biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" + 'biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" input: tuple val(meta), path(reads_fwd), path(reads_rev) diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf index 2fabc9a4..c2ed341b 100644 --- a/modules/local/chord/main.nf +++ b/modules/local/chord/main.nf @@ -5,7 +5,7 @@ process CHORD { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/r-chord:2.03--r43hdfd78af_0' : - 'quay.io/biocontainers/r-chord:2.03--r43hdfd78af_0' }" + 'biocontainers/r-chord:2.03--r43hdfd78af_0' }" input: tuple val(meta), path(smlv_vcf), path(sv_vcf) diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index 52a40eba..db549a26 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -5,7 +5,7 @@ process COBALT { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-cobalt:1.16--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-cobalt:1.16--hdfd78af_0' }" + 'biocontainers/hmftools-cobalt:1.16--hdfd78af_0' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index 213f9819..7f79adce 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -5,7 +5,7 @@ process CUPPA { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-cuppa:1.8.1--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-cuppa:1.8.1--hdfd78af_0' }" + 'biocontainers/hmftools-cuppa:1.8.1--hdfd78af_0' }" input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index 4dd4ae64..16aaa86c 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -5,7 +5,7 @@ process CUSTOM_EXTRACTCONTIG { conda "bwa-mem2=2.2.1 samtools=1.19.2" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' : - 'quay.io/biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" + 'biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" input: val contig_name diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf index c9e02f0f..8337ab0e 100644 --- a/modules/local/custom/lilac_realign_reads_lilac/main.nf +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -5,7 +5,7 @@ process CUSTOM_REALIGNREADS { conda "bioconda::bwa-mem2=2.2.1 bioconda::samtools=1.19.2 bioconda::sambamba=1.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' : - 'quay.io/biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" + 'biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" input: tuple val(meta), path(bam), path(bai) diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index b8013974..9a6e093a 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -5,7 +5,7 @@ process CUSTOM_SLICE { conda "samtools=1.19.2" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/samtools:1.19.2--h50ea8bc_0' : - 'quay.io/biocontainers/samtools:1.19.2--h50ea8bc_0' }" + 'biocontainers/samtools:1.19.2--h50ea8bc_0' }" input: tuple val(meta), path(bam), path(bai) diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index 8bd47159..1ab9408b 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -3,7 +3,7 @@ process FASTP { container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastp:0.23.4--hadf994f_2' : - 'quay.io/biocontainers/fastp:0.23.4--hadf994f_2' }" + 'biocontainers/fastp:0.23.4--hadf994f_2' }" input: tuple val(meta), path(reads_fwd), path(reads_rev) diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 340f4b4b..4fd7c346 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -6,7 +6,7 @@ process GRIDSS_INDEX { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/gridss:2.13.2--h50ea8bc_3' : - 'quay.io/biocontainers/gridss:2.13.2--h50ea8bc_3' }" + 'biocontainers/gridss:2.13.2--h50ea8bc_3' }" input: path genome_fasta diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index ef2e5242..795799b0 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -5,7 +5,7 @@ process GRIPSS_GERMLINE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-gripss:2.4--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-gripss:2.4--hdfd78af_0' }" + 'biocontainers/hmftools-gripss:2.4--hdfd78af_0' }" input: tuple val(meta), path(gridss_vcf) diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index 14f08944..839a5880 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -5,7 +5,7 @@ process GRIPSS_SOMATIC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-gripss:2.4--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-gripss:2.4--hdfd78af_0' }" + 'biocontainers/hmftools-gripss:2.4--hdfd78af_0' }" input: tuple val(meta), path(gridss_vcf) diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index cd215d70..16d1355b 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -5,7 +5,7 @@ process ISOFOX { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-isofox:1.7.1--hdfd78af_0': - 'quay.io/biocontainers/hmftools-isofox:1.7.1--hdfd78af_0' }" + 'biocontainers/hmftools-isofox:1.7.1--hdfd78af_0' }" input: tuple val(meta), path(bam), path(bai) diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 91936f07..74727df6 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -5,7 +5,7 @@ process LILAC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-lilac:1.6--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-lilac:1.6--hdfd78af_0' }" + 'biocontainers/hmftools-lilac:1.6--hdfd78af_0' }" input: tuple val(meta), path(normal_dna_bam), path(normal_dna_bai), path(tumor_dna_bam), path(tumor_dna_bai), path(tumor_rna_bam), path(tumor_rna_bai), path(purple_dir) diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 14efc84c..3bbbf5c1 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -5,7 +5,7 @@ process LINX_GERMLINE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': - 'quay.io/biocontainers/hmftools-linx:1.25--hdfd78af_0' }" + 'biocontainers/hmftools-linx:1.25--hdfd78af_0' }" input: tuple val(meta), path(sv_vcf) diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index a826e94d..729753bf 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -5,7 +5,7 @@ process LINX_SOMATIC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': - 'quay.io/biocontainers/hmftools-linx:1.25--hdfd78af_0' }" + 'biocontainers/hmftools-linx:1.25--hdfd78af_0' }" input: tuple val(meta), path(purple_dir) diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 5ff176c5..c98b2e58 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -5,7 +5,7 @@ process LINX_VISUALISER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': - 'quay.io/biocontainers/hmftools-linx:1.25--hdfd78af_0' }" + 'biocontainers/hmftools-linx:1.25--hdfd78af_0' }" input: tuple val(meta), path(linx_annotation_dir) diff --git a/modules/local/linxreport/main.nf b/modules/local/linxreport/main.nf index da526c1d..63b91012 100644 --- a/modules/local/linxreport/main.nf +++ b/modules/local/linxreport/main.nf @@ -5,7 +5,7 @@ process LINXREPORT { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/r-linxreport:1.0.0--r43hdfd78af_0' : - 'quay.io/biocontainers/r-linxreport:1.0.0--r43hdfd78af_0' }" + 'biocontainers/r-linxreport:1.0.0--r43hdfd78af_0' }" input: tuple val(meta), path(linx_annotation_dir), path(linx_visualiser_dir) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index d4d0f443..bc1812cf 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -4,7 +4,7 @@ process MARKDUPS { container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.5--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-mark-dups:1.1.5--hdfd78af_0' }" + 'biocontainers/hmftools-mark-dups:1.1.5--hdfd78af_0' }" input: tuple val(meta), path(bams), path(bais) diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index ed66236f..d23bf42d 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -5,7 +5,7 @@ process ORANGE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-orange:2.7.1--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-orange:2.7.1--hdfd78af_0' }" + 'biocontainers/hmftools-orange:2.7.1--hdfd78af_0' }" input: tuple val(meta), path(bam_metrics_somatic), path(bam_metrics_germline), path(flagstat_somatic), path(flagstat_germline), path(sage_somatic_dir), path(sage_germline_dir), path(smlv_somatic_vcf), path(smlv_germline_vcf), path(purple_dir), path(linx_somatic_anno_dir), path(linx_somatic_plot_dir), path(linx_germline_anno_dir), path(virusinterpreter_dir), path(chord_dir), path(sigs_dir), path(lilac_dir), path(cuppa_dir), path(isofox_dir) diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 1d85ada9..55fb3a49 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -9,7 +9,7 @@ process PAVE_GERMLINE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-pave:1.6--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-pave:1.6--hdfd78af_0' }" + 'biocontainers/hmftools-pave:1.6--hdfd78af_0' }" input: tuple val(meta), path(sage_vcf), path(sage_tbi) diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index a2e782b9..406a40fc 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -5,7 +5,7 @@ process PAVE_SOMATIC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-pave:1.6--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-pave:1.6--hdfd78af_0' }" + 'biocontainers/hmftools-pave:1.6--hdfd78af_0' }" input: tuple val(meta), path(sage_vcf), path(sage_tbi) diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 73fcdeba..6245f368 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -5,7 +5,7 @@ process PURPLE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-purple:4.0.2--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-purple:4.0.2--hdfd78af_0' }" + 'biocontainers/hmftools-purple:4.0.2--hdfd78af_0' }" input: tuple val(meta), path(amber), path(cobalt), path(sv_tumor_vcf), path(sv_tumor_tbi), path(sv_tumor_unfiltered_vcf), path(sv_tumor_unfiltered_tbi), path(sv_normal_vcf), path(sv_normal_tbi), path(smlv_tumor_vcf), path(smlv_normal_vcf) diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index 2540a13f..24f067ca 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -5,7 +5,7 @@ process SAGE_APPEND { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : - 'quay.io/biocontainers/hmftools-sage:3.4--hdfd78af_1' }" + 'biocontainers/hmftools-sage:3.4--hdfd78af_1' }" input: tuple val(meta), path(vcf), path(bam), path(bai) diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 7bb46f31..8a7e2618 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -5,7 +5,7 @@ process SAGE_GERMLINE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : - 'quay.io/biocontainers/hmftools-sage:3.4--hdfd78af_1' }" + 'biocontainers/hmftools-sage:3.4--hdfd78af_1' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 3b11a984..6d353b40 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -7,7 +7,7 @@ process SAGE_SOMATIC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : - 'quay.io/biocontainers/hmftools-sage:3.4--hdfd78af_1' }" + 'biocontainers/hmftools-sage:3.4--hdfd78af_1' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/sambamba/merge/main.nf b/modules/local/sambamba/merge/main.nf index 1bbb9646..78b89adb 100644 --- a/modules/local/sambamba/merge/main.nf +++ b/modules/local/sambamba/merge/main.nf @@ -3,7 +3,7 @@ process SAMBAMBA_MERGE { container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/sambamba:1.0--h98b6b92_0' : - 'quay.io/biocontainers/sambamba:1.0--h98b6b92_0' }" + 'biocontainers/sambamba:1.0--h98b6b92_0' }" input: tuple val(meta), path(bams) diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 56a011e9..8d125bcb 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -5,7 +5,7 @@ process SIGS { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sigs:1.2.1--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-sigs:1.2.1--hdfd78af_0' }" + 'biocontainers/hmftools-sigs:1.2.1--hdfd78af_0' }" input: tuple val(meta), path(smlv_vcf) diff --git a/modules/local/star/main.nf b/modules/local/star/main.nf index 7aa4503f..22f744a6 100644 --- a/modules/local/star/main.nf +++ b/modules/local/star/main.nf @@ -4,7 +4,7 @@ process STAR { container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/star:2.7.3a--0' : - 'quay.io/biocontainers/star:2.7.3a--0' }" + 'biocontainers/star:2.7.3a--0' }" input: tuple val(meta), path(reads_fwd), path(reads_rev) diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 532909d2..8242b429 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -5,7 +5,7 @@ process GRIDSS_ASSEMBLE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : - 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" + 'biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 56dd5833..f120885d 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -5,7 +5,7 @@ process GRIDSS_CALL { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : - 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" + 'biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 02858a86..137965d8 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -5,7 +5,7 @@ process SVPREP_DEPTH_ANNOTATOR { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : - 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" + 'biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" input: tuple val(meta), path(bams), path(bais), path(vcf), val(labels) diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 71a8ddef..b56e6b55 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -5,7 +5,7 @@ process GRIDSS_PREPROCESS { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : - 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" + 'biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" input: tuple val(meta), path(bam), path(bam_filtered) diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index b7a15ce8..daaa74b7 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -5,7 +5,7 @@ process SVPREP { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : - 'quay.io/biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" + 'biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" input: tuple val(meta), path(bam), path(bai), path(junctions) diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index 0d788545..2e3d8284 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -5,7 +5,7 @@ process VIRUSINTERPRETER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-virus-interpreter:1.3--hdfd78af_0' : - 'quay.io/biocontainers/hmftools-virus-interpreter:1.3--hdfd78af_0' }" + 'biocontainers/hmftools-virus-interpreter:1.3--hdfd78af_0' }" input: tuple val(meta), path(virus_tsv), path(purple_dir), path(wgs_metrics) diff --git a/modules/nf-core/gatk4/markduplicates/main.nf b/modules/nf-core/gatk4/markduplicates/main.nf index 356cac0f..7e0cffa7 100644 --- a/modules/nf-core/gatk4/markduplicates/main.nf +++ b/modules/nf-core/gatk4/markduplicates/main.nf @@ -5,7 +5,7 @@ process GATK4_MARKDUPLICATES { conda "bioconda::gatk4=4.4.0.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/gatk4:4.4.0.0--py36hdfd78af_0': - 'quay.io/biocontainers/gatk4:4.4.0.0--py36hdfd78af_0' }" + 'biocontainers/gatk4:4.4.0.0--py36hdfd78af_0' }" input: tuple val(meta), path(bam) diff --git a/modules/nf-core/samtools/dict/main.nf b/modules/nf-core/samtools/dict/main.nf index 4a1522e9..fb019510 100644 --- a/modules/nf-core/samtools/dict/main.nf +++ b/modules/nf-core/samtools/dict/main.nf @@ -5,7 +5,7 @@ process SAMTOOLS_DICT { conda (params.enable_conda ? "bioconda::samtools=1.16.1" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : - 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + 'biocontainers/samtools:1.16.1--h6899075_1' }" input: path fasta diff --git a/modules/nf-core/samtools/faidx/main.nf b/modules/nf-core/samtools/faidx/main.nf index 20c0e67e..75bfdb96 100644 --- a/modules/nf-core/samtools/faidx/main.nf +++ b/modules/nf-core/samtools/faidx/main.nf @@ -5,7 +5,7 @@ process SAMTOOLS_FAIDX { conda (params.enable_conda ? "bioconda::samtools=1.16.1" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : - 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + 'biocontainers/samtools:1.16.1--h6899075_1' }" input: path fasta diff --git a/modules/nf-core/samtools/flagstat/main.nf b/modules/nf-core/samtools/flagstat/main.nf index 74fbaa5d..610178dd 100644 --- a/modules/nf-core/samtools/flagstat/main.nf +++ b/modules/nf-core/samtools/flagstat/main.nf @@ -5,7 +5,7 @@ process SAMTOOLS_FLAGSTAT { conda "bioconda::samtools=1.16.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : - 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + 'biocontainers/samtools:1.16.1--h6899075_1' }" input: tuple val(meta), path(bam), path(bai) diff --git a/modules/nf-core/samtools/sort/main.nf b/modules/nf-core/samtools/sort/main.nf index 8aaf9a5b..18a3e1dc 100644 --- a/modules/nf-core/samtools/sort/main.nf +++ b/modules/nf-core/samtools/sort/main.nf @@ -5,7 +5,7 @@ process SAMTOOLS_SORT { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/samtools:1.18--h50ea8bc_1' : - 'quay.io/biocontainers/samtools:1.18--h50ea8bc_1' }" + 'biocontainers/samtools:1.18--h50ea8bc_1' }" input: tuple val(meta), path(bam) From 0335906bed2c2646b313f334afd8b37099ef22a8 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 16:49:38 +1000 Subject: [PATCH 451/562] Remove MRD/longitudinal subworkflow placeholder --- workflows/mrd.nf | 1 - 1 file changed, 1 deletion(-) delete mode 100644 workflows/mrd.nf diff --git a/workflows/mrd.nf b/workflows/mrd.nf deleted file mode 100644 index d43b9490..00000000 --- a/workflows/mrd.nf +++ /dev/null @@ -1 +0,0 @@ -// PLACEHOLDER From 1419fb9841d6588b1b056dc19c486a38def8469e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 17:06:17 +1000 Subject: [PATCH 452/562] Improve consistency of local modules --- modules/local/amber/main.nf | 1 + modules/local/bamtools/main.nf | 2 ++ modules/local/chord/main.nf | 3 +-- modules/local/cuppa/main.nf | 2 ++ modules/local/fastp/environment.yml | 7 +++++++ modules/local/fastp/main.nf | 11 ++++++----- modules/local/gripss/germline/main.nf | 1 + modules/local/gripss/somatic/main.nf | 1 + modules/local/isofox/main.nf | 1 + modules/local/lilac/main.nf | 1 + modules/local/linx/germline/main.nf | 1 + modules/local/linx/somatic/main.nf | 1 + modules/local/linx/visualiser/main.nf | 1 + modules/local/linxreport/main.nf | 1 + modules/local/markdups/environment.yml | 7 +++++++ modules/local/markdups/main.nf | 2 ++ modules/local/orange/main.nf | 2 ++ modules/local/pave/germline/main.nf | 1 + modules/local/pave/somatic/main.nf | 3 ++- modules/local/purple/main.nf | 1 + modules/local/sage/append/main.nf | 1 + modules/local/sage/germline/main.nf | 1 + modules/local/sage/somatic/main.nf | 2 +- modules/local/sambamba/merge/environment.yml | 7 +++++++ modules/local/sambamba/merge/main.nf | 8 ++++++++ modules/local/sigs/main.nf | 2 ++ modules/local/star/environment.yml | 7 +++++++ modules/local/star/main.nf | 4 ++++ modules/local/svprep/assemble/main.nf | 1 + modules/local/svprep/call/main.nf | 1 + modules/local/svprep/depth_annotator/main.nf | 1 + modules/local/svprep/preprocess/main.nf | 1 + modules/local/svprep/svprep/main.nf | 1 + modules/local/virusbreakend/main.nf | 2 ++ modules/local/virusinterpreter/main.nf | 2 ++ modules/nf-core/multiqc/environment.yml | 7 +++++++ 36 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 modules/local/fastp/environment.yml create mode 100644 modules/local/markdups/environment.yml create mode 100644 modules/local/sambamba/merge/environment.yml create mode 100644 modules/local/star/environment.yml create mode 100644 modules/nf-core/multiqc/environment.yml diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index ebf0071e..368a461e 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -52,6 +52,7 @@ process AMBER { """ mkdir -p amber/ touch amber/placeholder + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/bamtools/main.nf b/modules/local/bamtools/main.nf index be436ace..5b397403 100644 --- a/modules/local/bamtools/main.nf +++ b/modules/local/bamtools/main.nf @@ -26,6 +26,7 @@ process BAMTOOLS { bamtools \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ com.hartwig.hmftools.bamtools.metrics.BamMetrics \\ + ${args} \\ -sample ${meta.sample_id} \\ -bam_file ${bam} \\ -ref_genome ${genome_fasta} \\ @@ -44,6 +45,7 @@ process BAMTOOLS { stub: """ touch ${meta.sample_id}.wgsmetrics + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf index c2ed341b..bd835166 100644 --- a/modules/local/chord/main.nf +++ b/modules/local/chord/main.nf @@ -19,8 +19,6 @@ process CHORD { task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' - """ #!/usr/bin/env Rscript library('CHORD') @@ -82,6 +80,7 @@ process CHORD { mkdir -p chord/ touch chord/${meta.sample_id}_chord_signatures.txt touch chord/${meta.sample_id}_chord_prediction.txt + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index 7f79adce..f7ba8e08 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -46,6 +46,7 @@ process CUPPA { cuppa \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + ${args} \\ -sample ${meta.sample_id} \\ -sample_data_dir sample_data/ \\ -categories ${classifier} \\ @@ -76,6 +77,7 @@ process CUPPA { touch cuppa/${meta.sample_id}.cup.report.summary.png touch cuppa/${meta.sample_id}.cup.report.features.png touch cuppa/${meta.sample_id}.cuppa.chart.png + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/fastp/environment.yml b/modules/local/fastp/environment.yml new file mode 100644 index 00000000..70389e66 --- /dev/null +++ b/modules/local/fastp/environment.yml @@ -0,0 +1,7 @@ +name: fastp +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::fastp=0.23.4 diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index 1ab9408b..e12cf1c2 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -1,13 +1,15 @@ process FASTP { tag "${meta.id}" + label 'process_medium' + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastp:0.23.4--hadf994f_2' : 'biocontainers/fastp:0.23.4--hadf994f_2' }" input: tuple val(meta), path(reads_fwd), path(reads_rev) - val(max_fastq_records) + val max_fastq_records output: tuple val(meta), path('*_R1.fastp.fastq.gz'), path('*_R2.fastp.fastq.gz'), emit: fastq @@ -17,12 +19,11 @@ process FASTP { task.ext.when == null || task.ext.when script: - """ - # * do not apply trimming/clipping, already done in BCL convert - # * turn off all filtering - # * do not process umis, already done for us + def args = task.ext.args ?: '' + """ fastp \\ + ${args} \\ --in1 ${reads_fwd} \\ --in2 ${reads_rev} \\ --disable_quality_filtering \\ diff --git a/modules/local/gripss/germline/main.nf b/modules/local/gripss/germline/main.nf index 795799b0..8f28b7a5 100644 --- a/modules/local/gripss/germline/main.nf +++ b/modules/local/gripss/germline/main.nf @@ -57,6 +57,7 @@ process GRIPSS_GERMLINE { touch ${meta.normal_id}.gripss.filtered.germline.vcf.gz.tbi touch ${meta.normal_id}.gripss.germline.vcf.gz touch ${meta.normal_id}.gripss.germline.vcf.gz.tbi + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/gripss/somatic/main.nf b/modules/local/gripss/somatic/main.nf index 839a5880..24815d4d 100644 --- a/modules/local/gripss/somatic/main.nf +++ b/modules/local/gripss/somatic/main.nf @@ -62,6 +62,7 @@ process GRIPSS_SOMATIC { touch ${meta.tumor_id}.gripss.filtered.somatic.vcf.gz.tbi touch ${meta.tumor_id}.gripss.somatic.vcf.gz touch ${meta.tumor_id}.gripss.somatic.vcf.gz.tbi + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index 16d1355b..c987a988 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -68,6 +68,7 @@ process ISOFOX { """ mkdir -p isofox/ touch isofox/placeholder + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 74727df6..33a9c1c6 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -55,6 +55,7 @@ process LILAC { """ mkdir -p lilac/ touch lilac/placeholder + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 3bbbf5c1..515217ee 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -45,6 +45,7 @@ process LINX_GERMLINE { """ mkdir linx_germline/ touch linx_germline/placeholder + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 729753bf..9a33033d 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -48,6 +48,7 @@ process LINX_SOMATIC { """ mkdir linx_somatic/ touch linx_somatic/placeholder + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index c98b2e58..71b7628d 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -93,6 +93,7 @@ process LINX_VISUALISER { """ mkdir -p plots/{all,reportable}/ touch plots/{all,reportable}/placeholder + echo -e '${task.process}:\n stub: noversions\n' > versions.yml """ } diff --git a/modules/local/linxreport/main.nf b/modules/local/linxreport/main.nf index 63b91012..f3d3a55e 100644 --- a/modules/local/linxreport/main.nf +++ b/modules/local/linxreport/main.nf @@ -45,6 +45,7 @@ process LINXREPORT { stub: """ touch ${meta.sample_id}_linx.html + echo -e '${task.process}:\n stub: noversions\n' > versions.yml """ } diff --git a/modules/local/markdups/environment.yml b/modules/local/markdups/environment.yml new file mode 100644 index 00000000..6557fc27 --- /dev/null +++ b/modules/local/markdups/environment.yml @@ -0,0 +1,7 @@ +name: markdups +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::hmftools-mark-dups=1.1.5 diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index bc1812cf..c5dacc50 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -24,10 +24,12 @@ process MARKDUPS { task.ext.when == null || task.ext.when script: + def args = task.ext.args ?: '' def umi_flags = has_umis ? '-umi_enabled -umi_duplex -umi_duplex_delim +' : '' """ markdups \\ + ${args} \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ \\ -samtools \$(which samtools) \\ diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index d23bf42d..bff0d884 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -105,6 +105,7 @@ process ORANGE { --add-opens java.base/java.time=ALL-UNNAMED \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -jar \${orange_jar} \\ + ${args} \\ \\ -experiment_date \$(date +%y%m%d) \\ -add_disclaimer \\ @@ -156,6 +157,7 @@ process ORANGE { mkdir -p output/ touch output/${meta.tumor_id}.orange.json touch output/${meta.tumor_id}.orange.pdf + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 55fb3a49..adc54589 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -73,6 +73,7 @@ process PAVE_GERMLINE { stub: """ touch ${meta.sample_id}.sage.pave_germline.vcf.gz{,.tbi} + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 406a40fc..ccdeea62 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -32,7 +32,6 @@ process PAVE_SOMATIC { script: def args = task.ext.args ?: '' - def pon_filters def gnomad_args if (genome_ver.toString() == '37') { @@ -54,6 +53,7 @@ process PAVE_SOMATIC { """ pave \\ + ${args} \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ -sample ${meta.sample_id} \\ -vcf_file ${sage_vcf} \\ @@ -82,6 +82,7 @@ process PAVE_SOMATIC { stub: """ touch ${meta.sample_id}.sage.pave_somatic.vcf.gz{,.tbi} + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/purple/main.nf b/modules/local/purple/main.nf index 6245f368..b571bd07 100644 --- a/modules/local/purple/main.nf +++ b/modules/local/purple/main.nf @@ -98,6 +98,7 @@ process PURPLE { touch purple/${meta.tumor_id}.purple.somatic.vcf.gz touch purple/${meta.tumor_id}.purple.sv.germline.vcf.gz touch purple/${meta.tumor_id}.purple.sv.vcf.gz + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index 24f067ca..e0fadee0 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -46,6 +46,7 @@ process SAGE_APPEND { stub: """ touch "${meta.dna_id}.sage.append.vcf.gz" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 8a7e2618..847719d6 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -76,6 +76,7 @@ process SAGE_GERMLINE { touch germline/${meta.normal_id}.sage.bqr.png touch germline/${meta.normal_id}.sage.bqr.tsv touch germline/${meta.normal_id}.gene.coverage.tsv + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 6d353b40..12028be6 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -31,7 +31,6 @@ process SAGE_SOMATIC { script: def args = task.ext.args ?: '' - def reference_arg = meta.containsKey('normal_id') ? "-reference ${meta.normal_id}" : '' def reference_bam_arg = normal_bam ? "-reference_bam ${normal_bam}" : '' @@ -73,6 +72,7 @@ process SAGE_SOMATIC { touch somatic/${meta.tumor_id}.sage.bqr.tsv touch somatic/${meta.normal_id}.sage.bqr.png touch somatic/${meta.normal_id}.sage.bqr.tsv + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sambamba/merge/environment.yml b/modules/local/sambamba/merge/environment.yml new file mode 100644 index 00000000..e98f53f9 --- /dev/null +++ b/modules/local/sambamba/merge/environment.yml @@ -0,0 +1,7 @@ +name: sambamba_merge +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::sambamba=1.0 diff --git a/modules/local/sambamba/merge/main.nf b/modules/local/sambamba/merge/main.nf index 78b89adb..08e8c2af 100644 --- a/modules/local/sambamba/merge/main.nf +++ b/modules/local/sambamba/merge/main.nf @@ -1,5 +1,6 @@ process SAMBAMBA_MERGE { tag "${meta.id}" + label 'process_medium' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/sambamba:1.0--h98b6b92_0' : @@ -12,9 +13,15 @@ process SAMBAMBA_MERGE { tuple val(meta), path('*bam'), emit: bam path 'versions.yml' , emit: versions + when: + task.ext.when == null || task.ext.when + script: + def args = task.ext.args ?: '' + """ sambamba merge \\ + ${args} \\ --nthreads ${task.cpus} \\ ${meta.sample_id}.bam \\ ${bams} @@ -28,6 +35,7 @@ process SAMBAMBA_MERGE { stub: """ touch ${meta.sample_id}.bam + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/sigs/main.nf b/modules/local/sigs/main.nf index 8d125bcb..929bfda3 100644 --- a/modules/local/sigs/main.nf +++ b/modules/local/sigs/main.nf @@ -26,6 +26,7 @@ process SIGS { sigs \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + ${args} \\ -sample ${meta.sample_id} \\ -somatic_vcf_file ${smlv_vcf} \\ -signatures_file ${signatures} \\ @@ -41,6 +42,7 @@ process SIGS { """ mkdir -p sigs/ touch sigs/placeholder + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/star/environment.yml b/modules/local/star/environment.yml new file mode 100644 index 00000000..d48867c8 --- /dev/null +++ b/modules/local/star/environment.yml @@ -0,0 +1,7 @@ +name: star +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::star=2.7.3a diff --git a/modules/local/star/main.nf b/modules/local/star/main.nf index 22f744a6..8876187f 100644 --- a/modules/local/star/main.nf +++ b/modules/local/star/main.nf @@ -18,8 +18,11 @@ process STAR { task.ext.when == null || task.ext.when script: + def args = task.ext.args ?: '' + """ STAR \\ + ${args} \\ --readFilesIn ${reads_fwd} ${reads_rev} \\ --genomeDir ${genome_star_index} \\ --runThreadN ${task.cpus} \\ @@ -57,6 +60,7 @@ process STAR { stub: """ touch Aligned.out.bam + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 8242b429..075d82f5 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -97,6 +97,7 @@ process GRIDSS_ASSEMBLE { """ mkdir -p gridss_assemble/ touch gridss_assemble/placeholder + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index f120885d..2ed37f75 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -101,6 +101,7 @@ process GRIDSS_CALL { #CHROM POS ID REF ALT QUAL FILTER INFO . . . . . . . EOF + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 137965d8..5f4d43c1 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -51,6 +51,7 @@ process SVPREP_DEPTH_ANNOTATOR { """ touch ${meta.tumor_id}.gridss.vcf.gz touch ${meta.tumor_id}.gridss.vcf.gz.tbi + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index b56e6b55..fde547ba 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -54,6 +54,7 @@ process GRIDSS_PREPROCESS { """ mkdir -p gridss_preprocess/${meta.sample_id}.sv_prep.sorted.bam.gridss.working/ touch gridss_preprocess/${meta.sample_id}.sv_prep.sorted.bam.gridss.working/placeholder + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index daaa74b7..c0fabc23 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -59,6 +59,7 @@ process SVPREP { """ touch "${meta.sample_id}.sv_prep.sorted.bam" touch "${meta.sample_id}.sv_prep.junctions.tsv" + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index de689215..d7056d6f 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -32,6 +32,7 @@ process VIRUSBREAKEND { ln -s \$(find -L ${genome_gridss_index} -type f) ./ virusbreakend \\ + ${args} \\ --gridssargs "--jvmheap ${Math.round(task.memory.bytes * 0.95)}" \\ --threads ${task.cpus} \\ --db ${virusbreakenddb.toString().replaceAll("/\$", "")}/ \\ @@ -48,6 +49,7 @@ process VIRUSBREAKEND { stub: """ touch ${meta.sample_id}.virusbreakend.vcf ${meta.sample_id}.summary.tsv + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/virusinterpreter/main.nf b/modules/local/virusinterpreter/main.nf index 2e3d8284..fac520e8 100644 --- a/modules/local/virusinterpreter/main.nf +++ b/modules/local/virusinterpreter/main.nf @@ -27,6 +27,7 @@ process VIRUSINTERPRETER { virusinterpreter \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + ${args} \\ -sample ${meta.sample_id} \\ -purple_dir ${purple_dir} \\ -tumor_sample_wgs_metrics_file ${wgs_metrics} \\ @@ -45,6 +46,7 @@ process VIRUSINTERPRETER { """ mkdir -p virusinterpreter/ touch virusinterpreter/${meta.sample_id}.virus.annotated.tsv + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml new file mode 100644 index 00000000..ca39fb67 --- /dev/null +++ b/modules/nf-core/multiqc/environment.yml @@ -0,0 +1,7 @@ +name: multiqc +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::multiqc=1.21 From e11a3871eb634b1b2ac7bdc35d8595e852a117ec Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 2 May 2024 17:11:42 +1000 Subject: [PATCH 453/562] Rename local STAR module --- modules/local/star/{ => align}/environment.yml | 2 +- modules/local/star/{ => align}/main.nf | 2 +- modules/local/star/{ => align}/meta.yml | 2 +- subworkflows/local/read_alignment_rna/main.nf | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) rename modules/local/star/{ => align}/environment.yml (84%) rename modules/local/star/{ => align}/main.nf (98%) rename modules/local/star/{ => align}/meta.yml (98%) diff --git a/modules/local/star/environment.yml b/modules/local/star/align/environment.yml similarity index 84% rename from modules/local/star/environment.yml rename to modules/local/star/align/environment.yml index d48867c8..e694b27f 100644 --- a/modules/local/star/environment.yml +++ b/modules/local/star/align/environment.yml @@ -1,4 +1,4 @@ -name: star +name: star_align channels: - conda-forge - bioconda diff --git a/modules/local/star/main.nf b/modules/local/star/align/main.nf similarity index 98% rename from modules/local/star/main.nf rename to modules/local/star/align/main.nf index 8876187f..6694a23e 100644 --- a/modules/local/star/main.nf +++ b/modules/local/star/align/main.nf @@ -1,4 +1,4 @@ -process STAR { +process STAR_ALIGN { tag "${meta.id}" label 'process_high' diff --git a/modules/local/star/meta.yml b/modules/local/star/align/meta.yml similarity index 98% rename from modules/local/star/meta.yml rename to modules/local/star/align/meta.yml index 0bbc3329..19bb83c5 100644 --- a/modules/local/star/meta.yml +++ b/modules/local/star/align/meta.yml @@ -1,4 +1,4 @@ -name: star +name: star_align description: An ultrafast universal RNA-seq aligner keywords: - rna-seq diff --git a/subworkflows/local/read_alignment_rna/main.nf b/subworkflows/local/read_alignment_rna/main.nf index 7565629b..d6e920c9 100644 --- a/subworkflows/local/read_alignment_rna/main.nf +++ b/subworkflows/local/read_alignment_rna/main.nf @@ -8,7 +8,7 @@ import Utils include { GATK4_MARKDUPLICATES } from '../../../modules/nf-core/gatk4/markduplicates/main' include { SAMBAMBA_MERGE } from '../../../modules/local/sambamba/merge/main' include { SAMTOOLS_SORT } from '../../../modules/nf-core/samtools/sort/main' -include { STAR } from '../../../modules/local/star/main' +include { STAR_ALIGN } from '../../../modules/local/star/align/main' workflow READ_ALIGNMENT_RNA { take: @@ -55,7 +55,7 @@ workflow READ_ALIGNMENT_RNA { } // - // MODULE: STAR + // MODULE: STAR alignment // // Create process input channel // channel: [ meta_star, fastq_fwd, fastq_rev ] @@ -75,19 +75,19 @@ workflow READ_ALIGNMENT_RNA { } // Run process - STAR( + STAR_ALIGN( ch_star_inputs, genome_star_index, ) - ch_versions = ch_versions.mix(STAR.out.versions) + ch_versions = ch_versions.mix(STAR_ALIGN.out.versions) // // MODULE: SAMtools sort // // Create process input channel // channel: [ meta_sort, bam ] - ch_sort_inputs = STAR.out.bam + ch_sort_inputs = STAR_ALIGN.out.bam .map { meta_star, bam -> def meta_sort = [ *:meta_star, From 010c5cdc9213ecd840d86d6929441ce30b39222a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 3 May 2024 15:13:59 +1000 Subject: [PATCH 454/562] Set bwa-mem2 batch size for reproducibility Parameter value set to match Sarek default configuration. --- modules/local/bwa-mem2/mem/main.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index 9c44d086..4d894eb9 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -28,6 +28,7 @@ process BWAMEM2_ALIGN { bwa-mem2 mem \\ -Y \\ + -K 100000000 \\ -R '${read_group_tag}' \\ -t ${task.cpus} \\ ${genome_fasta} \\ From 9e65de35d955e065b21066bd96575370a156c18c Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Wed, 8 May 2024 13:59:03 +0000 Subject: [PATCH 455/562] Template update for nf-core/tools version 2.14.0 --- .editorconfig | 6 +- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/workflows/awsfulltest.yml | 10 +- .github/workflows/awstest.yml | 12 +- .github/workflows/ci.yml | 4 +- .github/workflows/download_pipeline.yml | 22 ++- .github/workflows/fix-linting.yml | 6 +- .github/workflows/linting.yml | 18 +- .github/workflows/linting_comment.yml | 2 +- .github/workflows/release-announcements.yml | 6 +- .nf-core.yml | 1 + .pre-commit-config.yaml | 3 + CHANGELOG.md | 2 +- README.md | 2 +- assets/email_template.html | 2 +- assets/multiqc_config.yml | 4 +- conf/base.config | 3 - conf/modules.config | 8 - conf/test.config | 2 +- conf/test_full.config | 2 +- docs/usage.md | 2 + modules.json | 4 +- modules/nf-core/fastqc/main.nf | 6 + nextflow.config | 180 +++++++++--------- nextflow_schema.json | 9 +- pyproject.toml | 15 -- .../main.nf | 16 +- .../nf-core/utils_nfcore_pipeline/main.nf | 8 +- workflows/oncoanalyser.nf | 46 +++-- 29 files changed, 227 insertions(+), 176 deletions(-) delete mode 100644 pyproject.toml diff --git a/.editorconfig b/.editorconfig index dd9ffa53..72dda289 100644 --- a/.editorconfig +++ b/.editorconfig @@ -28,10 +28,6 @@ indent_style = unset [/assets/email*] indent_size = unset -# ignore Readme -[README.md] -indent_style = unset - -# ignore python +# ignore python and markdown [*.{py,md}] indent_style = unset diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4fa4360a..19d3a06b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -18,7 +18,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/onco - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/oncoanalyser/tree/master/.github/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/oncoanalyser _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core lint`). -- [ ] Ensure the test suite passes (`nf-test test main.nf.test -profile test,docker`). +- [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). - [ ] Check for unexpected warnings in debug mode (`nextflow run . -profile debug,test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. - [ ] Output Documentation in `docs/output.md` is updated. diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 86245f5e..f8fecdac 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -8,12 +8,12 @@ on: types: [published] workflow_dispatch: jobs: - run-tower: + run-platform: name: Run AWS full tests if: github.repository == 'nf-core/oncoanalyser' runs-on: ubuntu-latest steps: - - name: Launch workflow via tower + - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@v2 # TODO nf-core: You can customise AWS full pipeline tests as required # Add full size test data (but still relatively small datasets for few samples) @@ -33,7 +33,7 @@ jobs: - uses: actions/upload-artifact@v4 with: - name: Tower debug log file + name: Seqera Platform debug log file path: | - tower_action_*.log - tower_action_*.json + seqera_platform_action_*.log + seqera_platform_action_*.json diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index 3996313a..1ddcaa95 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -5,13 +5,13 @@ name: nf-core AWS test on: workflow_dispatch: jobs: - run-tower: + run-platform: name: Run AWS tests if: github.repository == 'nf-core/oncoanalyser' runs-on: ubuntu-latest steps: - # Launch workflow using Tower CLI tool action - - name: Launch workflow via tower + # Launch workflow using Seqera Platform CLI tool action + - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@v2 with: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} @@ -27,7 +27,7 @@ jobs: - uses: actions/upload-artifact@v4 with: - name: Tower debug log file + name: Seqera Platform debug log file path: | - tower_action_*.log - tower_action_*.json + seqera_platform_action_*.log + seqera_platform_action_*.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38a7b6ac..af118503 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,10 +28,10 @@ jobs: - "latest-everything" steps: - name: Check out pipeline code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 + uses: nf-core/setup-nextflow@v2 with: version: "${{ matrix.NXF_VER }}" diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index 08622fd5..2d20d644 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -14,6 +14,8 @@ on: pull_request: types: - opened + - edited + - synchronize branches: - master pull_request_target: @@ -28,11 +30,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 + uses: nf-core/setup-nextflow@v2 - - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + - name: Disk space cleanup + uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 + + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: - python-version: "3.11" + python-version: "3.12" architecture: "x64" - uses: eWaterCycle/setup-singularity@931d4e31109e875b13309ae1d07c70ca8fbc8537 # v7 with: @@ -65,8 +70,17 @@ jobs: - name: Inspect download run: tree ./${{ env.REPOTITLE_LOWERCASE }} - - name: Run the downloaded pipeline + - name: Run the downloaded pipeline (stub) + id: stub_run_pipeline + continue-on-error: true env: NXF_SINGULARITY_CACHEDIR: ./ NXF_SINGULARITY_HOME_MOUNT: true run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -stub -profile test,singularity --outdir ./results + - name: Run the downloaded pipeline (stub run not supported) + id: run_pipeline + if: ${{ job.steps.stub_run_pipeline.status == failure() }} + env: + NXF_SINGULARITY_CACHEDIR: ./ + NXF_SINGULARITY_HOME_MOUNT: true + run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -profile test,singularity --outdir ./results diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix-linting.yml index fe37960c..02ca9338 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix-linting.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 with: token: ${{ secrets.nf_core_bot_auth_token }} @@ -32,9 +32,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} # Install and run pre-commit - - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: - python-version: 3.11 + python-version: "3.12" - name: Install pre-commit run: pip install pre-commit diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 073e1876..a3fb2541 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -14,12 +14,12 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - - name: Set up Python 3.11 - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + - name: Set up Python 3.12 + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: - python-version: 3.11 + python-version: "3.12" cache: "pip" - name: Install pre-commit @@ -32,14 +32,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 + uses: nf-core/setup-nextflow@v2 - - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: - python-version: "3.11" + python-version: "3.12" architecture: "x64" - name: Install dependencies @@ -60,7 +60,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4 with: name: linting-logs path: | diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index b706875f..40acc23f 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download lint results - uses: dawidd6/action-download-artifact@f6b0bace624032e30a85a8fd9c1a7f8f611f5737 # v3 + uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3 with: workflow: linting.yml workflow_conclusion: completed diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index d468aeaa..03ecfcf7 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -12,7 +12,7 @@ jobs: - name: get topics and convert to hashtags id: get_topics run: | - curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ' >> $GITHUB_OUTPUT + echo "topics=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ')" >> $GITHUB_OUTPUT - uses: rzr/fediverse-action@master with: @@ -25,13 +25,13 @@ jobs: Please see the changelog: ${{ github.event.release.html_url }} - ${{ steps.get_topics.outputs.GITHUB_OUTPUT }} #nfcore #openscience #nextflow #bioinformatics + ${{ steps.get_topics.outputs.topics }} #nfcore #openscience #nextflow #bioinformatics send-tweet: runs-on: ubuntu-latest steps: - - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: python-version: "3.10" - name: Install dependencies diff --git a/.nf-core.yml b/.nf-core.yml index 3805dc81..d6daa403 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1 +1,2 @@ repository_type: pipeline +nf_core_version: "2.14.0" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af57081f..4dc0f1dc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,6 +3,9 @@ repos: rev: "v3.1.0" hooks: - id: prettier + additional_dependencies: + - prettier@3.2.5 + - repo: https://github.com/editorconfig-checker/editorconfig-checker.python rev: "2.7.3" hooks: diff --git a/CHANGELOG.md b/CHANGELOG.md index a3f8ca48..41073ee0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.3.0 - [date] +## v0.3.1 - [date] Initial release of nf-core/oncoanalyser, created with the [nf-core](https://nf-co.re/) template. diff --git a/README.md b/README.md index 944a687d..45d4c5ef 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) -[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/oncoanalyser) +[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/oncoanalyser) [![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23oncoanalyser-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/oncoanalyser)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) diff --git a/assets/email_template.html b/assets/email_template.html index 0d1bf471..b906e78c 100644 --- a/assets/email_template.html +++ b/assets/email_template.html @@ -4,7 +4,7 @@ - + nf-core/oncoanalyser Pipeline Report diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 780ba33e..b51b57b8 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,8 +1,8 @@ report_comment: > - This report has been generated by the nf-core/oncoanalyser + This report has been generated by the nf-core/oncoanalyser analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-oncoanalyser-methods-description": diff --git a/conf/base.config b/conf/base.config index 5802f0f1..dcfaf248 100644 --- a/conf/base.config +++ b/conf/base.config @@ -59,7 +59,4 @@ process { errorStrategy = 'retry' maxRetries = 2 } - withName:CUSTOM_DUMPSOFTWAREVERSIONS { - cache = false - } } diff --git a/conf/modules.config b/conf/modules.config index e3ea8fa6..d203d2b6 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -22,14 +22,6 @@ process { ext.args = '--quiet' } - withName: CUSTOM_DUMPSOFTWAREVERSIONS { - publishDir = [ - path: { "${params.outdir}/pipeline_info" }, - mode: params.publish_dir_mode, - pattern: '*_versions.yml' - ] - } - withName: 'MULTIQC' { ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ diff --git a/conf/test.config b/conf/test.config index 42f23058..793c6971 100644 --- a/conf/test.config +++ b/conf/test.config @@ -22,7 +22,7 @@ params { // Input data // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = 'https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv' + input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv' // Genome references genome = 'R64-1-1' diff --git a/conf/test_full.config b/conf/test_full.config index 3a0c73e0..6caf464e 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -17,7 +17,7 @@ params { // Input data for full size test // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = 'https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_full_illumina_amplicon.csv' + input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_full_illumina_amplicon.csv' // Genome references genome = 'R64-1-1' diff --git a/docs/usage.md b/docs/usage.md index 39274fa8..1e383ce8 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -156,6 +156,8 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) - `apptainer` - A generic configuration profile to be used with [Apptainer](https://apptainer.org/) +- `wave` + - A generic configuration profile to enable [Wave](https://seqera.io/wave/) containers. Use together with one of the above (requires Nextflow ` 24.03.0-edge` or later). - `conda` - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter, Charliecloud, or Apptainer. diff --git a/modules.json b/modules.json index cdb223d3..a41f53a4 100644 --- a/modules.json +++ b/modules.json @@ -7,7 +7,7 @@ "nf-core": { "fastqc": { "branch": "master", - "git_sha": "f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c", + "git_sha": "285a50500f9e02578d90b3ce6382ea3c30216acd", "installed_by": ["modules"] }, "multiqc": { @@ -26,7 +26,7 @@ }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", + "git_sha": "92de218a329bfc9a9033116eb5f65fd270e72ba3", "installed_by": ["subworkflows"] }, "utils_nfvalidation_plugin": { diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 9e19a74c..d79f1c86 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -25,6 +25,11 @@ process FASTQC { 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(' ') + + def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB') + // FastQC memory value allowed range (100 - 10000) + def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) + """ printf "%s %s\\n" $rename_to | while read old_name new_name; do [ -f "\${new_name}" ] || ln -s \$old_name \$new_name @@ -33,6 +38,7 @@ process FASTQC { fastqc \\ $args \\ --threads $task.cpus \\ + --memory $fastqc_memory \\ $renamed_files cat <<-END_VERSIONS > versions.yml diff --git a/nextflow.config b/nextflow.config index f43fd275..09013c6d 100644 --- a/nextflow.config +++ b/nextflow.config @@ -16,7 +16,8 @@ params { genome = null igenomes_base = 's3://ngi-igenomes/igenomes/' igenomes_ignore = false - fasta = null// MultiQC options + + // MultiQC options multiqc_config = null multiqc_title = null multiqc_logo = null @@ -24,15 +25,16 @@ params { multiqc_methods_description = null // Boilerplate options - outdir = null - publish_dir_mode = 'copy' - email = null - email_on_fail = null - plaintext_email = false - monochrome_logs = false - hook_url = null - help = false - version = false + outdir = null + publish_dir_mode = 'copy' + email = null + email_on_fail = null + plaintext_email = false + monochrome_logs = false + hook_url = null + help = false + version = false + pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/' // Config options config_profile_name = null @@ -68,103 +70,109 @@ try { } // Load nf-core/oncoanalyser custom profiles from different institutions. -// Warning: Uncomment only if a pipeline-specific institutional config already exists on nf-core/configs! -// try { -// includeConfig "${params.custom_config_base}/pipeline/oncoanalyser.config" -// } catch (Exception e) { -// System.err.println("WARNING: Could not load nf-core/config/oncoanalyser profiles: ${params.custom_config_base}/pipeline/oncoanalyser.config") -// } +try { + includeConfig "${params.custom_config_base}/pipeline/oncoanalyser.config" +} catch (Exception e) { + System.err.println("WARNING: Could not load nf-core/config/oncoanalyser profiles: ${params.custom_config_base}/pipeline/oncoanalyser.config") +} profiles { debug { - dumpHashes = true - process.beforeScript = 'echo $HOSTNAME' - cleanup = false + dumpHashes = true + process.beforeScript = 'echo $HOSTNAME' + cleanup = false nextflow.enable.configProcessNamesValidation = true } conda { - conda.enabled = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - channels = ['conda-forge', 'bioconda', 'defaults'] - apptainer.enabled = false + conda.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + conda.channels = ['conda-forge', 'bioconda', 'defaults'] + apptainer.enabled = false } mamba { - conda.enabled = true - conda.useMamba = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - apptainer.enabled = false + conda.enabled = true + conda.useMamba = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + apptainer.enabled = false } docker { - docker.enabled = true - conda.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - apptainer.enabled = false - docker.runOptions = '-u $(id -u):$(id -g)' + docker.enabled = true + conda.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + apptainer.enabled = false + docker.runOptions = '-u $(id -u):$(id -g)' } arm { - docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' + docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' } singularity { - singularity.enabled = true - singularity.autoMounts = true - conda.enabled = false - docker.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - apptainer.enabled = false + singularity.enabled = true + singularity.autoMounts = true + conda.enabled = false + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + apptainer.enabled = false } podman { - podman.enabled = true - conda.enabled = false - docker.enabled = false - singularity.enabled = false - shifter.enabled = false - charliecloud.enabled = false - apptainer.enabled = false + podman.enabled = true + conda.enabled = false + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false + apptainer.enabled = false } shifter { - shifter.enabled = true - conda.enabled = false - docker.enabled = false - singularity.enabled = false - podman.enabled = false - charliecloud.enabled = false - apptainer.enabled = false + shifter.enabled = true + conda.enabled = false + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false + apptainer.enabled = false } charliecloud { - charliecloud.enabled = true - conda.enabled = false - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - apptainer.enabled = false + charliecloud.enabled = true + conda.enabled = false + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + apptainer.enabled = false } apptainer { - apptainer.enabled = true - apptainer.autoMounts = true - conda.enabled = false - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false + apptainer.enabled = true + apptainer.autoMounts = true + conda.enabled = false + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + wave { + apptainer.ociAutoPull = true + singularity.ociAutoPull = true + wave.enabled = true + wave.freeze = true + wave.strategy = 'conda,container' } gitpod { - executor.name = 'local' - executor.cpus = 4 - executor.memory = 8.GB + executor.name = 'local' + executor.cpus = 4 + executor.memory = 8.GB } test { includeConfig 'conf/test.config' } test_full { includeConfig 'conf/test_full.config' } @@ -228,10 +236,10 @@ manifest { name = 'nf-core/oncoanalyser' author = """Stephen Watts""" homePage = 'https://github.com/nf-core/oncoanalyser' - description = """A comprehensive cancer NGS analysis and reporting pipeline""" + description = """A comprehensive cancer DNA/RNA analysis and reporting pipeline""" mainScript = 'main.nf' nextflowVersion = '!>=23.04.0' - version = '0.3.0' + version = '0.3.1' doi = '' } diff --git a/nextflow_schema.json b/nextflow_schema.json index dcd5f029..034da9e5 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema", "$id": "https://raw.githubusercontent.com/nf-core/oncoanalyser/master/nextflow_schema.json", "title": "nf-core/oncoanalyser pipeline parameters", - "description": "A comprehensive cancer NGS analysis and reporting pipeline", + "description": "A comprehensive cancer DNA/RNA analysis and reporting pipeline", "type": "object", "definitions": { "input_output_options": { @@ -265,6 +265,13 @@ "description": "Validation of parameters in lenient more.", "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)." + }, + "pipelines_testdata_base_path": { + "type": "string", + "fa_icon": "far fa-check-circle", + "description": "Base URL or local path to location of pipeline test dataset files", + "default": "https://raw.githubusercontent.com/nf-core/test-datasets/", + "hidden": true } } } diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 56110621..00000000 --- a/pyproject.toml +++ /dev/null @@ -1,15 +0,0 @@ -# Config file for Python. Mostly used to configure linting of bin/*.py with Ruff. -# Should be kept the same as nf-core/tools to avoid fighting with template synchronisation. -[tool.ruff] -line-length = 120 -target-version = "py38" -cache-dir = "~/.cache/ruff" - -[tool.ruff.lint] -select = ["I", "E1", "E4", "E7", "E9", "F", "UP", "N"] - -[tool.ruff.lint.isort] -known-first-party = ["nf_core"] - -[tool.ruff.lint.per-file-ignores] -"__init__.py" = ["E402", "F401"] diff --git a/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf b/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf index bfdc184d..75da4d59 100644 --- a/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf @@ -140,6 +140,10 @@ workflow PIPELINE_COMPLETION { imNotification(summary_params, hook_url) } } + + workflow.onError { + log.error "Pipeline failed. Please refer to troubleshooting docs: https://nf-co.re/docs/usage/troubleshooting" + } } /* @@ -230,8 +234,16 @@ def methodsDescriptionText(mqc_methods_yaml) { meta["manifest_map"] = workflow.manifest.toMap() // Pipeline DOI - meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" - meta["nodoi_text"] = meta.manifest_map.doi ? "": "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " + if (meta.manifest_map.doi) { + // Using a loop to handle multiple DOIs + // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers + // Removing ` ` since the manifest.doi is a string and not a proper list + def temp_doi_ref = "" + String[] manifest_doi = meta.manifest_map.doi.tokenize(",") + for (String doi_ref: manifest_doi) temp_doi_ref += "(doi: ${doi_ref.replace("https://doi.org/", "").replace(" ", "")}), " + meta["doi_text"] = temp_doi_ref.substring(0, temp_doi_ref.length() - 2) + } else meta["doi_text"] = "" + meta["nodoi_text"] = meta.manifest_map.doi ? "" : "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " // Tool references meta["tool_citations"] = "" diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index a8b55d6f..14558c39 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -65,9 +65,15 @@ def checkProfileProvided(nextflow_cli_args) { // Citation string for pipeline // def workflowCitation() { + def temp_doi_ref = "" + String[] manifest_doi = workflow.manifest.doi.tokenize(",") + // Using a loop to handle multiple DOIs + // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers + // Removing ` ` since the manifest.doi is a string and not a proper list + for (String doi_ref: manifest_doi) temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + "* The pipeline\n" + - " ${workflow.manifest.doi}\n\n" + + temp_doi_ref + "\n" + "* The nf-core framework\n" + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + "* Software dependencies\n" + diff --git a/workflows/oncoanalyser.nf b/workflows/oncoanalyser.nf index adc6c5bd..54595767 100644 --- a/workflows/oncoanalyser.nf +++ b/workflows/oncoanalyser.nf @@ -40,22 +40,44 @@ workflow ONCOANALYSER { // Collate and save software versions // softwareVersionsToYAML(ch_versions) - .collectFile(storeDir: "${params.outdir}/pipeline_info", name: 'nf_core_pipeline_software_mqc_versions.yml', sort: true, newLine: true) - .set { ch_collated_versions } + .collectFile( + storeDir: "${params.outdir}/pipeline_info", + name: 'nf_core_pipeline_software_mqc_versions.yml', + sort: true, + newLine: true + ).set { ch_collated_versions } // // MODULE: MultiQC // - ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) - ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config, checkIfExists: true) : Channel.empty() - ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath(params.multiqc_logo, checkIfExists: true) : Channel.empty() - summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") - ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) - ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) - ch_methods_description = Channel.value(methodsDescriptionText(ch_multiqc_custom_methods_description)) - ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) - ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) - ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml', sort: false)) + ch_multiqc_config = Channel.fromPath( + "$projectDir/assets/multiqc_config.yml", checkIfExists: true) + ch_multiqc_custom_config = params.multiqc_config ? + Channel.fromPath(params.multiqc_config, checkIfExists: true) : + Channel.empty() + ch_multiqc_logo = params.multiqc_logo ? + Channel.fromPath(params.multiqc_logo, checkIfExists: true) : + Channel.empty() + + summary_params = paramsSummaryMap( + workflow, parameters_schema: "nextflow_schema.json") + ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) + + ch_multiqc_custom_methods_description = params.multiqc_methods_description ? + file(params.multiqc_methods_description, checkIfExists: true) : + file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) + ch_methods_description = Channel.value( + methodsDescriptionText(ch_multiqc_custom_methods_description)) + + ch_multiqc_files = ch_multiqc_files.mix( + ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) + ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) + ch_multiqc_files = ch_multiqc_files.mix( + ch_methods_description.collectFile( + name: 'methods_description_mqc.yaml', + sort: true + ) + ) MULTIQC ( ch_multiqc_files.collect(), From a35433709c9be07229af8d5815dae28486821f5e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 9 May 2024 09:19:35 +1000 Subject: [PATCH 456/562] Fix template-introduced linting breakage A template fix is discussed here: https://nfcore.slack.com/archives/CE5LG7WMB/p1715182664778019 --- .github/workflows/linting.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index a3fb2541..1fcafe88 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -20,7 +20,6 @@ jobs: uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: python-version: "3.12" - cache: "pip" - name: Install pre-commit run: pip install pre-commit From 6ca7b3e4fdac3ce0eb30190d6288bcd4689f00a6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 9 May 2024 09:32:11 +1000 Subject: [PATCH 457/562] Do not apply linting fix manually Doing so introduces another linting error indicating that the linting.yml GHA workflow has been modified. Instead, use a placeholder pyproject.toml file to avoid original issue. --- .github/workflows/linting.yml | 1 + pyproject.toml | 0 2 files changed, 1 insertion(+) create mode 100644 pyproject.toml diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 1fcafe88..a3fb2541 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -20,6 +20,7 @@ jobs: uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: python-version: "3.12" + cache: "pip" - name: Install pre-commit run: pip install pre-commit diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..e69de29b From da76ec42dea7d73fde80dd7e2a6eb739e3a24227 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 9 May 2024 11:42:31 +0000 Subject: [PATCH 458/562] Template update for nf-core/tools version 2.14.1 --- .github/workflows/linting.yml | 1 - .nf-core.yml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index a3fb2541..1fcafe88 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -20,7 +20,6 @@ jobs: uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: python-version: "3.12" - cache: "pip" - name: Install pre-commit run: pip install pre-commit diff --git a/.nf-core.yml b/.nf-core.yml index d6daa403..e0b85a77 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,2 +1,2 @@ repository_type: pipeline -nf_core_version: "2.14.0" +nf_core_version: "2.14.1" From c02df3ec74e7be9d0a66434ff92dd5ab4a00f146 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 10 May 2024 11:49:18 +1000 Subject: [PATCH 459/562] Bump SAGE to 3.4.3 --- modules/local/sage/append/environment.yml | 2 +- modules/local/sage/append/main.nf | 4 ++-- modules/local/sage/germline/environment.yml | 2 +- modules/local/sage/germline/main.nf | 4 ++-- modules/local/sage/somatic/environment.yml | 2 +- modules/local/sage/somatic/main.nf | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/local/sage/append/environment.yml b/modules/local/sage/append/environment.yml index 45fbf017..dd57ccbb 100644 --- a/modules/local/sage/append/environment.yml +++ b/modules/local/sage/append/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sage=3.4=hdfd78af_1 + - bioconda::hmftools-sage=3.4.3 diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index e0fadee0..98b4561e 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -4,8 +4,8 @@ process SAGE_APPEND { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : - 'biocontainers/hmftools-sage:3.4--hdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4.3--hdfd78af_0' : + 'biocontainers/hmftools-sage:3.4.3--hdfd78af_0' }" input: tuple val(meta), path(vcf), path(bam), path(bai) diff --git a/modules/local/sage/germline/environment.yml b/modules/local/sage/germline/environment.yml index 16793c78..1f44d1c5 100644 --- a/modules/local/sage/germline/environment.yml +++ b/modules/local/sage/germline/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sage=3.4=hdfd78af_1 + - bioconda::hmftools-sage=3.4.3 diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 847719d6..3e0eb1bc 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -4,8 +4,8 @@ process SAGE_GERMLINE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : - 'biocontainers/hmftools-sage:3.4--hdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4.3--hdfd78af_0' : + 'biocontainers/hmftools-sage:3.4.3--hdfd78af_0' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/sage/somatic/environment.yml b/modules/local/sage/somatic/environment.yml index e9ca7c06..35e0b137 100644 --- a/modules/local/sage/somatic/environment.yml +++ b/modules/local/sage/somatic/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sage=3.4=hdfd78af_1 + - bioconda::hmftools-sage=3.4.3 diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 12028be6..bdccaa5f 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -6,8 +6,8 @@ process SAGE_SOMATIC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4--hdfd78af_1' : - 'biocontainers/hmftools-sage:3.4--hdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4.3--hdfd78af_0' : + 'biocontainers/hmftools-sage:3.4.3--hdfd78af_0' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) From 7b41c496f27551d2cf7b78dd06c312d2f46837e3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 6 May 2024 10:08:36 +1000 Subject: [PATCH 460/562] Apply formatting fixes and other minor fixes --- modules/local/bwa-mem2/mem/main.nf | 7 ++++++ modules/local/cobalt/main.nf | 1 + modules/local/cuppa/meta.yml | 3 +++ modules/local/custom/extract_tarball/main.nf | 8 ++++++- .../lilac_extract_and_index_contig/main.nf | 6 ++++- .../custom/lilac_realign_reads_lilac/main.nf | 13 +++++++++-- modules/local/custom/lilac_slice/main.nf | 3 ++- .../local/custom/write_reference_data/main.nf | 3 +++ modules/local/gridss/index/main.nf | 4 ++-- modules/local/gridss/index/meta.yml | 22 +++---------------- modules/local/gripss/somatic/meta.yml | 2 +- modules/local/isofox/main.nf | 2 +- modules/local/lilac/main.nf | 1 + modules/local/linx/germline/main.nf | 2 +- modules/local/linx/somatic/main.nf | 2 +- modules/local/linx/visualiser/main.nf | 5 +++-- modules/local/linx/visualiser/meta.yml | 4 ++-- modules/local/markdups/main.nf | 3 ++- modules/local/orange/main.nf | 1 + modules/local/pave/germline/main.nf | 1 + modules/local/pave/germline/meta.yml | 4 ++++ modules/local/pave/somatic/main.nf | 3 ++- modules/local/pave/somatic/meta.yml | 4 ++++ modules/local/sage/germline/meta.yml | 4 ---- modules/local/sage/somatic/main.nf | 1 + modules/local/sage/somatic/meta.yml | 4 ---- modules/local/svprep/assemble/main.nf | 1 + modules/local/svprep/assemble/meta.yml | 7 ------ modules/local/svprep/call/main.nf | 1 + modules/local/svprep/call/meta.yml | 7 ------ modules/local/svprep/depth_annotator/main.nf | 3 ++- modules/local/svprep/preprocess/main.nf | 1 + modules/local/svprep/preprocess/meta.yml | 7 ------ modules/local/svprep/svprep/main.nf | 3 +++ modules/local/virusbreakend/meta.yml | 7 ------ subworkflows/local/prepare_reference/main.nf | 13 ++++++----- 36 files changed, 85 insertions(+), 78 deletions(-) diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index 9c44d086..8a5b8046 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -20,6 +20,10 @@ process BWAMEM2_ALIGN { task.ext.when == null || task.ext.when script: + def args = task.ext.args ?: '' + def args2 = task.ext.args2 ?: '' + def args3 = task.ext.args3 ?: '' + def read_group_tag = "@RG\\tID:${meta.read_group}\\tSM:${meta.sample_id}" def output_fn = meta.split ? "${meta.split}.${meta.sample_id}.${meta.read_group}.bam" : "${meta.sample_id}.${meta.read_group}.bam" @@ -27,6 +31,7 @@ process BWAMEM2_ALIGN { ln -fs \$(find -L ${genome_bwa_index} -type f) ./ bwa-mem2 mem \\ + ${args} \\ -Y \\ -R '${read_group_tag}' \\ -t ${task.cpus} \\ @@ -35,6 +40,7 @@ process BWAMEM2_ALIGN { ${reads_rev} | \\ \\ sambamba view \\ + ${args2} \\ --sam-input \\ --format bam \\ --compression-level 0 \\ @@ -42,6 +48,7 @@ process BWAMEM2_ALIGN { /dev/stdin | \\ \\ sambamba sort \\ + ${args3} \\ --nthreads ${task.cpus} \\ --out ${output_fn} \\ /dev/stdin diff --git a/modules/local/cobalt/main.nf b/modules/local/cobalt/main.nf index db549a26..b3142b70 100644 --- a/modules/local/cobalt/main.nf +++ b/modules/local/cobalt/main.nf @@ -53,6 +53,7 @@ process COBALT { """ mkdir -p cobalt/ touch cobalt/placeholder + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/cuppa/meta.yml b/modules/local/cuppa/meta.yml index 7518dac4..e2000a73 100644 --- a/modules/local/cuppa/meta.yml +++ b/modules/local/cuppa/meta.yml @@ -28,6 +28,9 @@ input: - virusinterpreter_dir: type: directory description: Virus Interpreter output directory (optional) + - genome_ver: + type: string + description: Reference genome version - cuppa_resources: type: directory description: CUPPA resource directory diff --git a/modules/local/custom/extract_tarball/main.nf b/modules/local/custom/extract_tarball/main.nf index 521860a5..c0b178fa 100644 --- a/modules/local/custom/extract_tarball/main.nf +++ b/modules/local/custom/extract_tarball/main.nf @@ -12,10 +12,16 @@ process CUSTOM_EXTRACTTARBALL { output: path "${meta.id}/", emit: dir + when: + task.ext.when == null || task.ext.when + script: + def args = task.ext.args ?: '' + """ mkdir -p ${meta.id}/ - tar -xzvf ${tarball} --strip-components 1 -C ${meta.id}/ + + tar ${args} -xzvf ${tarball} --strip-components 1 -C ${meta.id}/ """ stub: diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index 16aaa86c..b8e6bb75 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -23,13 +23,16 @@ process CUSTOM_EXTRACTCONTIG { script: def args = task.ext.args ?: '' + def args2 = task.ext.args2 ?: '' """ samtools faidx \\ + ${args} \\ -o ${contig_name}_extracted.fa \\ ${genome_fasta} \\ ${contig_name} - bwa-mem2 index ${contig_name}_extracted.fa + + bwa-mem2 index ${args2} ${contig_name}_extracted.fa cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -41,6 +44,7 @@ process CUSTOM_EXTRACTCONTIG { stub: """ touch ${contig_name}_extracted.fa ${contig_name}_extracted.fa.amb + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf index 8337ab0e..77757ccb 100644 --- a/modules/local/custom/lilac_realign_reads_lilac/main.nf +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -21,16 +21,22 @@ process CUSTOM_REALIGNREADS { script: def args = task.ext.args ?: '' + def args2 = task.ext.args2 ?: '' + def args3 = task.ext.args3 ?: '' + def args4 = task.ext.args4 ?: '' + def args5 = task.ext.args5 ?: '' """ - sambamba sort -n ${bam} -o ${meta.sample_id}_sorted.bam - samtools fastq -@${task.threads} ${meta.sample_id}_sorted.bam \\ + sambamba sort ${args} -n ${bam} -o ${meta.sample_id}_sorted.bam + + samtools fastq ${args2} -@${task.threads} ${meta.sample_id}_sorted.bam \\ -1 ${meta.sample_id}_R1.fastq.gz \\ -2 ${meta.sample_id}_R2.fastq.gz \\ -0 ${meta.sample_id}_other.fastq.gz \\ -s ${meta.sample_id}_singleton.fastq.gz; bwa-mem2 mem \\ + ${args3} \\ -Y \\ -t ${task.cpus} \\ ${reference} \\ @@ -38,6 +44,7 @@ process CUSTOM_REALIGNREADS { ${meta.sample_id}_R2.fastq.gz | \\ \\ sambamba view \\ + ${args4} \\ --sam-input \\ --format bam \\ --compression-level 0 \\ @@ -45,6 +52,7 @@ process CUSTOM_REALIGNREADS { /dev/stdin | \\ \\ sambamba sort \\ + ${args5} \\ --nthreads ${task.cpus} \\ --out ${bam.baseName}.realigned.bam \\ /dev/stdin @@ -60,6 +68,7 @@ process CUSTOM_REALIGNREADS { stub: """ touch ${bam.baseName}.realigned.bam ${bam.baseName}.realigned.bam.bai + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/custom/lilac_slice/main.nf b/modules/local/custom/lilac_slice/main.nf index 9a6e093a..0a86f06a 100644 --- a/modules/local/custom/lilac_slice/main.nf +++ b/modules/local/custom/lilac_slice/main.nf @@ -9,7 +9,7 @@ process CUSTOM_SLICE { input: tuple val(meta), path(bam), path(bai) - path(bed) + path bed output: tuple val(meta), path("*sliced.bam"), path("*sliced.bam.bai"), emit: bam @@ -41,6 +41,7 @@ process CUSTOM_SLICE { stub: """ touch ${bam.baseName}.sliced.bam ${bam.baseName}.sliced.bam.bai + echo -e '${task.process}:\\n stub: noversions\\n' > versions.yml """ } diff --git a/modules/local/custom/write_reference_data/main.nf b/modules/local/custom/write_reference_data/main.nf index b7f2e3b8..04a1151e 100644 --- a/modules/local/custom/write_reference_data/main.nf +++ b/modules/local/custom/write_reference_data/main.nf @@ -13,6 +13,9 @@ process WRITE_REFERENCE_DATA { output: path fp, includeInputs: true + when: + task.ext.when == null || task.ext.when + script: """ """ diff --git a/modules/local/gridss/index/main.nf b/modules/local/gridss/index/main.nf index 4fd7c346..d947daa6 100644 --- a/modules/local/gridss/index/main.nf +++ b/modules/local/gridss/index/main.nf @@ -15,8 +15,8 @@ process GRIDSS_INDEX { path genome_bwa_index output: - path 'gridss_index', emit: index - path 'versions.yml', emit: versions + path 'gridss_index/', emit: index + path 'versions.yml' , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/gridss/index/meta.yml b/modules/local/gridss/index/meta.yml index 9988df16..9f0ee56f 100644 --- a/modules/local/gridss/index/meta.yml +++ b/modules/local/gridss/index/meta.yml @@ -22,34 +22,18 @@ input: type: file description: Reference genome assembly dict file (optional) pattern: "*.{dict}" - - genome_bwa_index_dir: + - genome_bwa_index: type: directory description: Directory containing reference genome assembly BWA index (optional) - - genome_bwa_index_image: - type: file - description: Reference genome assembly BWA index img file (optional) - pattern: "*.{img}" - - indices: - type: string - description: List of indices to create output: - meta: type: map description: | Groovy Map containing sample information e.g. [id: 'sample_id'] - - dict: - type: file - description: Reference genome dictionary file - pattern: "*.{dict}" - - img: - type: file - description: Reference genome BWA index image file - pattern: "*.{img}" - index: - type: file - description: Reference genome GRIDSS index file - pattern: "*.{gridsscache}" + type: directory + description: Directory containing GRIDSS index - versions: type: file description: File containing software versions diff --git a/modules/local/gripss/somatic/meta.yml b/modules/local/gripss/somatic/meta.yml index 171a8d0b..878ef0e8 100644 --- a/modules/local/gripss/somatic/meta.yml +++ b/modules/local/gripss/somatic/meta.yml @@ -31,7 +31,7 @@ input: type: file description: Reference genome assembly fai file pattern: "*.{fai}" - - pon_breakend: + - pon_breakends: type: file description: GRIDSS breakend PON file pattern: "*.{bed.gz}" diff --git a/modules/local/isofox/main.nf b/modules/local/isofox/main.nf index c987a988..5e298ced 100644 --- a/modules/local/isofox/main.nf +++ b/modules/local/isofox/main.nf @@ -4,7 +4,7 @@ process ISOFOX { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-isofox:1.7.1--hdfd78af_0': + 'https://depot.galaxyproject.org/singularity/hmftools-isofox:1.7.1--hdfd78af_0' : 'biocontainers/hmftools-isofox:1.7.1--hdfd78af_0' }" input: diff --git a/modules/local/lilac/main.nf b/modules/local/lilac/main.nf index 33a9c1c6..b4517b31 100644 --- a/modules/local/lilac/main.nf +++ b/modules/local/lilac/main.nf @@ -22,6 +22,7 @@ process LILAC { script: def args = task.ext.args ?: '' + def sample_name = getSampleName(meta, tumor_dna_bam, normal_dna_bam) def normal_bam_arg = normal_dna_bam ? "-reference_bam ${normal_dna_bam}" : '' diff --git a/modules/local/linx/germline/main.nf b/modules/local/linx/germline/main.nf index 515217ee..c28491e3 100644 --- a/modules/local/linx/germline/main.nf +++ b/modules/local/linx/germline/main.nf @@ -4,7 +4,7 @@ process LINX_GERMLINE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': + 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0' : 'biocontainers/hmftools-linx:1.25--hdfd78af_0' }" input: diff --git a/modules/local/linx/somatic/main.nf b/modules/local/linx/somatic/main.nf index 9a33033d..310fbd9c 100644 --- a/modules/local/linx/somatic/main.nf +++ b/modules/local/linx/somatic/main.nf @@ -4,7 +4,7 @@ process LINX_SOMATIC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': + 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0' : 'biocontainers/hmftools-linx:1.25--hdfd78af_0' }" input: diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 71b7628d..9a22709e 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -4,7 +4,7 @@ process LINX_VISUALISER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0': + 'https://depot.galaxyproject.org/singularity/hmftools-linx:1.25--hdfd78af_0' : 'biocontainers/hmftools-linx:1.25--hdfd78af_0' }" input: @@ -21,6 +21,7 @@ process LINX_VISUALISER { script: def args = task.ext.args ?: '' + def args2 = task.ext.args2 ?: '' """ # NOTE(SW): the output plot directories are always required for ORANGE, which is straightfoward to handle with POSIX @@ -67,7 +68,7 @@ process LINX_VISUALISER { linx \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ com.hartwig.hmftools.linx.visualiser.SvVisualiser \\ - ${args} \\ + ${args2} \\ -sample ${meta.sample_id} \\ -vis_file_dir ${linx_annotation_dir} \\ -ref_genome_version ${genome_ver} \\ diff --git a/modules/local/linx/visualiser/meta.yml b/modules/local/linx/visualiser/meta.yml index d35d9182..d48c1fac 100644 --- a/modules/local/linx/visualiser/meta.yml +++ b/modules/local/linx/visualiser/meta.yml @@ -32,9 +32,9 @@ output: description: | Groovy Map containing sample information e.g. [id: 'sample_id'] - - visualiser_dir: + - plots: type: directory - description: LINX visualiser output directory + description: Directory containing output plots - versions: type: file description: File containing software versions diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index c5dacc50..90bf9696 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -25,12 +25,13 @@ process MARKDUPS { script: def args = task.ext.args ?: '' + def umi_flags = has_umis ? '-umi_enabled -umi_duplex -umi_duplex_delim +' : '' """ markdups \\ - ${args} \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + ${args} \\ \\ -samtools \$(which samtools) \\ -sambamba \$(which sambamba) \\ diff --git a/modules/local/orange/main.nf b/modules/local/orange/main.nf index bff0d884..0490df97 100644 --- a/modules/local/orange/main.nf +++ b/modules/local/orange/main.nf @@ -30,6 +30,7 @@ process ORANGE { script: def args = task.ext.args ?: '' + def pipeline_version_str = pipeline_version ?: 'not specified' def virus_dir_arg = virusinterpreter_dir ? "-virus_dir ${virusinterpreter_dir}" : '' diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index adc54589..b5cf7bdf 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -34,6 +34,7 @@ process PAVE_GERMLINE { script: def args = task.ext.args ?: '' + def gnomad_args if (genome_ver.toString() == '37') { gnomad_args = "-gnomad_freq_file ${gnomad_resource}" diff --git a/modules/local/pave/germline/meta.yml b/modules/local/pave/germline/meta.yml index 859e7fce..5d209cec 100644 --- a/modules/local/pave/germline/meta.yml +++ b/modules/local/pave/germline/meta.yml @@ -22,6 +22,10 @@ input: type: file description: SAGE VCF file pattern: "*.{vcf.gz}" + - sage_tbi: + type: file + description: SAGE VCF index file + pattern: "*.{tbi}" - genome_fasta: type: file description: Reference genome assembly FASTA file diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index ccdeea62..147f4dce 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -32,6 +32,7 @@ process PAVE_SOMATIC { script: def args = task.ext.args ?: '' + def pon_filters def gnomad_args if (genome_ver.toString() == '37') { @@ -53,8 +54,8 @@ process PAVE_SOMATIC { """ pave \\ - ${args} \\ -Xmx${Math.round(task.memory.bytes * 0.95)} \\ + ${args} \\ -sample ${meta.sample_id} \\ -vcf_file ${sage_vcf} \\ -ref_genome ${genome_fasta} \\ diff --git a/modules/local/pave/somatic/meta.yml b/modules/local/pave/somatic/meta.yml index 552537c4..399efd0c 100644 --- a/modules/local/pave/somatic/meta.yml +++ b/modules/local/pave/somatic/meta.yml @@ -23,6 +23,10 @@ input: type: file description: SAGE VCF file pattern: "*.{vcf.gz}" + - sage_tbi: + type: file + description: SAGE VCF index file + pattern: "*.{tbi}" - genome_fasta: type: file description: Reference genome assembly FASTA file diff --git a/modules/local/sage/germline/meta.yml b/modules/local/sage/germline/meta.yml index a1054388..1f7882e2 100644 --- a/modules/local/sage/germline/meta.yml +++ b/modules/local/sage/germline/meta.yml @@ -77,10 +77,6 @@ output: type: file description: VCF file pattern: "*.{vcf.gz}" - - vcf_filtered: - type: file - description: Filtered VCF file - pattern: "*.{vcf.gz}" - sage_dir: type: directory description: SAGE output directory diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 12028be6..e5a06296 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -31,6 +31,7 @@ process SAGE_SOMATIC { script: def args = task.ext.args ?: '' + def reference_arg = meta.containsKey('normal_id') ? "-reference ${meta.normal_id}" : '' def reference_bam_arg = normal_bam ? "-reference_bam ${normal_bam}" : '' diff --git a/modules/local/sage/somatic/meta.yml b/modules/local/sage/somatic/meta.yml index 9ce66ceb..912dc7a0 100644 --- a/modules/local/sage/somatic/meta.yml +++ b/modules/local/sage/somatic/meta.yml @@ -77,10 +77,6 @@ output: type: file description: SAGE VCF file pattern: "*.{vcf.gz}" - - vcf_filtered: - type: file - description: Filtered VCF file - pattern: "*.{vcf.gz}" - sage_dir: type: directory description: SAGE output directory diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 075d82f5..1f9a3957 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -25,6 +25,7 @@ process GRIDSS_ASSEMBLE { script: def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' def output_dirname = 'gridss_assemble' def labels_list = labels instanceof List ? labels : [labels] diff --git a/modules/local/svprep/assemble/meta.yml b/modules/local/svprep/assemble/meta.yml index 60541c7c..79c2c225 100644 --- a/modules/local/svprep/assemble/meta.yml +++ b/modules/local/svprep/assemble/meta.yml @@ -42,13 +42,6 @@ input: type: file description: Reference genome assembly dict file pattern: "*.{dict}" - - genome_bwa_index_dir: - type: directory - description: Directory containing reference genome assembly BWA index - - genome_bwa_index_image: - type: file - description: Reference genome assembly BWA index img file - pattern: "*.{img}" - genome_gridss_index: type: file description: Reference genome assembly GRIDSS index file diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 2ed37f75..ef5243b9 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -25,6 +25,7 @@ process GRIDSS_CALL { script: def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' def output_dirname = 'gridss_call' def labels_list = labels instanceof List ? labels : [labels] diff --git a/modules/local/svprep/call/meta.yml b/modules/local/svprep/call/meta.yml index 2838a46f..cc8c012e 100644 --- a/modules/local/svprep/call/meta.yml +++ b/modules/local/svprep/call/meta.yml @@ -42,13 +42,6 @@ input: type: file description: Reference genome assembly dict file pattern: "*.{dict}" - - genome_bwa_index_dir: - type: directory - description: Directory containing reference genome assembly BWA index - - genome_bwa_index_image: - type: file - description: Reference genome assembly BWA index img file - pattern: "*.{img}" - genome_gridss_index: type: file description: Reference genome assembly GRIDSS index file diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 5f4d43c1..2d7cb3be 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -14,7 +14,7 @@ process SVPREP_DEPTH_ANNOTATOR { output: tuple val(meta), path("${meta.tumor_id}.gridss.vcf.gz"), emit: vcf - path("${meta.tumor_id}.gridss.vcf.gz.tbi") , emit: tbi + path "${meta.tumor_id}.gridss.vcf.gz.tbi" , emit: tbi path 'versions.yml' , emit: versions when: @@ -22,6 +22,7 @@ process SVPREP_DEPTH_ANNOTATOR { script: def args = task.ext.args ?: '' + def labels_list = labels instanceof List ? labels : [labels] def labels_arg = labels_list.join(',') // NOTE(SW): Nextflow implicitly casts List to an atomic TaskPath, hence the required check below diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index fde547ba..4fa37b05 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -24,6 +24,7 @@ process GRIDSS_PREPROCESS { script: def args = task.ext.args ?: '' + def config_arg = gridss_config ? "--configuration ${gridss_config}" : '' """ diff --git a/modules/local/svprep/preprocess/meta.yml b/modules/local/svprep/preprocess/meta.yml index 90f1659c..017ce16a 100644 --- a/modules/local/svprep/preprocess/meta.yml +++ b/modules/local/svprep/preprocess/meta.yml @@ -38,13 +38,6 @@ input: type: file description: Reference genome assembly dict file pattern: "*.{dict}" - - genome_bwa_index_dir: - type: directory - description: Directory containing reference genome assembly BWA index - - genome_bwa_index_image: - type: file - description: Reference genome assembly BWA index img file - pattern: "*.{img}" - genome_gridss_index: type: file description: Reference genome assembly GRIDSS index file diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index c0fabc23..3b4477bd 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -25,6 +25,8 @@ process SVPREP { script: def args = task.ext.args ?: '' + def args2 = task.ext.args2 ?: '' + def write_types_arg = write_types ? "-write_types \'${write_types}\'" : '' def existing_juction_file_arg = junctions ? "-existing_junction_file ${junctions}" : '' @@ -44,6 +46,7 @@ process SVPREP { -output_dir ./ samtools sort \\ + ${args2} \\ -@ ${task.cpus} \\ -T ${meta.sample_id}.sv_prep.tmp \\ -o ${meta.sample_id}.sv_prep.sorted.bam \\ diff --git a/modules/local/virusbreakend/meta.yml b/modules/local/virusbreakend/meta.yml index b3f4c8c2..72629466 100644 --- a/modules/local/virusbreakend/meta.yml +++ b/modules/local/virusbreakend/meta.yml @@ -34,13 +34,6 @@ input: type: file description: Reference genome assembly dict file pattern: "*.{dict}" - - genome_bwa_index_dir: - type: directory - description: Directory containing reference genome assembly BWA index - - genome_bwa_index_image: - type: file - description: Reference genome assembly BWA index img file - pattern: "*.{img}" - genome_gridss_index: type: file description: Reference genome assembly GRIDSS index file diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 1b1bf8d5..121733a1 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -82,7 +82,7 @@ workflow PREPARE_REFERENCE { } // - // Set and GRIDSS index, unpack or create if required + // Set GRIDSS index, unpack or create if required // ch_genome_gridss_index = Channel.empty() if (run_config.has_dna && (run_config.stages.gridss || run_virusinterpreter)) { @@ -119,7 +119,7 @@ workflow PREPARE_REFERENCE { } // - // Set STAR index path, unpack or create if required + // Set STAR index , unpack or create if required // ch_genome_star_index = Channel.empty() if (run_config.has_rna_fastq && run_config.stages.alignment) { @@ -148,7 +148,7 @@ workflow PREPARE_REFERENCE { } // - // Set VIRUSBreakend database path, unpack if required + // Set VIRUSBreakend database, unpack if required // ch_virusbreakenddb = Channel.empty() if (run_config.has_dna && run_virusinterpreter) { @@ -168,7 +168,7 @@ workflow PREPARE_REFERENCE { } // - // Set HMF reference paths, unpack if required + // Set HMF reference data, unpack if required // ch_hmf_data = Channel.empty() hmf_data_paths = params.hmf_data_paths[params.genome_version.toString()] @@ -194,7 +194,7 @@ workflow PREPARE_REFERENCE { } // - // Set panel reference paths, unpack if required + // Set panel reference data, unpack if required // ch_panel_data = Channel.empty() if (run_config.mode === Constants.RunMode.TARGETED) { @@ -224,6 +224,9 @@ workflow PREPARE_REFERENCE { } } + // + // Write prepared reference data if requested + // if (params.prepare_reference_only) { // Create channel of data files to stage (if not already local) and write From 558e728729f0b5401e2bbe89de88439d6129ffc2 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 14 Mar 2024 17:08:41 +1100 Subject: [PATCH 461/562] First full pass of nf-core documentation --- README.md | 88 ++-- REFERENCE_DATA_STAGING.md | 94 ++++ ...829_wgts.orange_report.summary_section.png | Bin 0 -> 1135893 bytes docs/images/mqc_fastqc_adapter.png | Bin 23458 -> 0 bytes docs/images/mqc_fastqc_counts.png | Bin 33918 -> 0 bytes docs/images/mqc_fastqc_quality.png | Bin 55769 -> 0 bytes docs/output.md | 495 +++++++++++++++++- docs/usage.md | 259 ++++++++- examples/README.md | 109 ---- 9 files changed, 845 insertions(+), 200 deletions(-) create mode 100644 REFERENCE_DATA_STAGING.md create mode 100644 docs/images/COLO829_wgts.orange_report.summary_section.png delete mode 100755 docs/images/mqc_fastqc_adapter.png delete mode 100755 docs/images/mqc_fastqc_counts.png delete mode 100755 docs/images/mqc_fastqc_quality.png delete mode 100644 examples/README.md diff --git a/README.md b/README.md index efefee03..a8922177 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ [![GitHub Actions CI Status](https://github.com/nf-core/oncoanalyser/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/oncoanalyser/actions/workflows/ci.yml) -[![GitHub Actions Linting Status](https://github.com/nf-core/oncoanalyser/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/oncoanalyser/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/oncoanalyser/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) +[![GitHub Actions Linting Status](https://github.com/nf-core/oncoanalyser/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/oncoanalyser/actions/workflows/linting.yml) +[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/oncoanalyser/results) +[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) [![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A522.10.5-23aa62.svg)](https://www.nextflow.io/) @@ -15,35 +17,36 @@ [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) [![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/oncoanalyser) -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23oncoanalyser-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/oncoanalyser)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23oncoanalyser-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/oncoanalyser) +[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core) +[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core) +[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) ## Introduction -**nf-core/oncoanalyser** is a Nextflow implementation of the comprehensive cancer DNA and RNA analysis and reporting -workflow from the Hartwig Medical Foundation. For detailed information on each component of the Hartwig Medical -Foundation workflow, please refer to [hartwigmedical/hmftools](https://github.com/hartwigmedical/hmftools/). +**nf-core/oncoanalyser** is a Nextflow implementation of the comprehensive cancer DNA/RNA analysis and reporting +workflow from the Hartwig Medical Foundation. Both the Hartwig WGS/WTS workflow and targeted sequencing workflow are +available in oncoanalyser. The targeted sequencing workflow has built-in support for the TSO500 panel and can also run +custom panels with externally-generated normalisation data. -The oncoanalyser pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across -multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation -trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) -implementation of this pipeline uses one container per process which makes it much easier to maintain and update -software dependencies. Where possible, these processes have been submitted to and installed from -[nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to -everyone within the Nextflow community! +The key analysis results for each sample are summarised and presented in an ORANGE report (summary page excerpt shown +below from *[COLO829_wgts.orange_report.pdf](https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/other/example_report/COLO829_wgts.orange_report.pdf)*): -On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud -infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on -real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other -analysis sources. The results obtained from the full-sized test can be viewed on the [nf-core -website](https://nf-co.re/oncoanalyser/results). +

    + +For detailed information on each component of the Hartwig workflow, please refer to +[hartwigmedical/hmftools](https://github.com/hartwigmedical/hmftools/). ## Pipeline summary The following processes and tools can be run with oncoanalyser: -- SNV and MNV calling (`SAGE`, `PAVE`) -- SV calling (`SV Prep`, `GRIDSS`, `GRIPSS`, `PURPLE`, `LINX`) +- Simple DNA/RNA alignment (`bwa-mem2`, `STAR`) +- Post-alignment processing (`MarkDups`, `Picard MarkDuplicates`) +- SNV, MNV, and INDEL calling (`SAGE`, `PAVE`) - CNV calling (`AMBER`, `COBALT`, `PURPLE`) +- SV calling (`SvPrep`, `GRIDSS`, `GRIPSS`) +- SV event interpretation (`LINX`) - Transcript analysis (`Isofox`) - Oncoviral detection (`VIRUSBreakend`, `Virus Interpreter`) - HLA calling (`LILAC`) @@ -57,25 +60,25 @@ The following processes and tools can be run with oncoanalyser: > [!NOTE] > If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` before running the workflow on actual data. -Create a samplesheet containing your inputs: +Create a samplesheet with your inputs (WGS/WTS FASTQs in this example): -```text -group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath -P1__wgts,P1,SA,tumor,dna,bam,/path/to/SA.tumor.dna.wgs.bam -P1__wgts,P1,SB,tumor,rna,bam,/path/to/SB.tumor.rna.wts.bam -P1__wgts,P1,SC,normal,dna,bam,/path/to/SC.normal.dna.wgs.bam +```csv +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,info,filepath +P1__wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/SA.normal.dna.wgs.001.R2.fastq.gz +P1__wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/SB.tumor.dna.wgs.001.R2.fastq.gz +P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/SC.tumor.rna.wts.001.R1.fastq.gz;/path/to/SC.tumor.rna.wts.001.R2.fastq.gz ``` Launch oncoanalyser: ```bash nextflow run nf-core/oncoanalyser \ - -revision v0.3.1 \ - -profile docker \ - --mode wgts \ - --genome GRCh38_hmf \ - --input samplesheet.csv \ - --outdir output/ + -profile docker \ + -revision v0.3.1 \ + --mode wgts \ + --genome GRCh38_hmf \ + --input samplesheet.csv \ + --outdir output/ ``` > [!WARNING] @@ -90,16 +93,33 @@ To see the results of an example test run with a full size dataset refer to the For more details about the output files and reports, please refer to the [output documentation](https://nf-co.re/oncoanalyser/output). -## Version support +## Version information + +### Extended support -As oncoanalyser is used in clinical settings and is subject to accreditation standards in some instances, there is a -need for long-term stability and reliability for feature releases in order to meet operational requirements. This is +As oncoanalyser is used in clinical settings and subject to accreditation standards in some instances, there is a need +for long-term stability and reliability for feature releases in order to meet operational requirements. This is accomplished through long-term support of several nominated feature releases, which all receive bug fixes and security fixes during the period of extended support. Each release that is given extended support is allocated a separate long-lived git branch with the 'stable' prefix, e.g. `stable/1.2.x`, `stable/1.5.x`. Feature development otherwise occurs on the `main` branch. +Versions nominated to have current long-term support: + +* TBD + +### Release parity + +Versioning between oncoanalyser and hmftools naturally differ, however it is often necessary to relate the functional +equivalence of these two pieces of software. The functional/feature parity with regards to version releases are detailed +in the below table. + +| oncoanalyser | hmftools | +| --- | --- | +| 0.1.0 through 0.2.7 | 5.33 | +| 0.3.0 through 0.3.1 | 5.34 | + ## Credits The oncoanalyser pipeline was written by Stephen Watts while in the [Genomics Platform diff --git a/REFERENCE_DATA_STAGING.md b/REFERENCE_DATA_STAGING.md new file mode 100644 index 00000000..836ed785 --- /dev/null +++ b/REFERENCE_DATA_STAGING.md @@ -0,0 +1,94 @@ +# Reference data staging + +Download and unpack + +> All reference data is retrieved here, exclude unused files as desired; using GRCh38_hmf below + +```bash +base_url=https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes + +fps=' +genomes/GRCh37_hmf/Homo_sapiens.GRCh37.GATK.illumina.fasta +genomes/GRCh37_hmf/bwa_index/0.7.17-r1188.tar.gz +genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.0123 +genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64 +genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img +genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache +genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict +genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai +genomes/GRCh37_hmf/star_index/gencode_19/2.7.3a.tar.gz +genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna +genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz +genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123 +genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64 +genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img +genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache +genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict +genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai +genomes/GRCh38_hmf/star_index/gencode_38/2.7.3a.tar.gz +hmf_reference_data/hmftools/5.34_37--2.tar.gz +hmf_reference_data/hmftools/5.34_38--2.tar.gz +hmf_reference_data/panels/tso500_5.34_37--1.tar.gz +hmf_reference_data/panels/tso500_5.34_38--1.tar.gz +virusbreakend/virusbreakenddb_20210401.tar.gz +' + +parallel -j4 wget -c -x -nH -P reference_data/ ${base_url}/{} ::: ${fps} +find reference_data/ -name '*.tar.gz' | parallel -j0 'cd {//} && tar -xzvf {/}' +``` + +Create Nextflow config file for local reference data + +```bash +cat < refdata.local.config +params { + genomes { + 'GRCh37_hmf' { + fasta = "$(pwd)/genomes/GRCh37_hmf/Homo_sapiens.GRCh37.GATK.illumina.fasta" + fai = "$(pwd)/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" + dict = "$(pwd)/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" + bwa_index = "$(pwd)/genomes/GRCh37_hmf/bwa_index/0.7.17-r1188.tar.gz" + bwa_index_bseq = "$(pwd)/genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.0123" + bwa_index_biidx = "$(pwd)/genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64" + bwa_index_image = "$(pwd)/genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" + gridss_index = "$(pwd)/genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" + star_index = "$(pwd)/genomes/GRCh37_hmf/star_index/gencode_19/2.7.3a.tar.gz" + } + 'GRCh38_hmf' { + fasta = "$(pwd)/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" + fai = "$(pwd)/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" + dict = "$(pwd)/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" + bwa_index = "$(pwd)/reference_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188/" + bwa_index_bseq = "$(pwd)/reference_data/genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" + bwa_index_biidx = "$(pwd)/reference_data/genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" + bwa_index_image = "$(pwd)/reference_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" + gridss_index = "$(pwd)/reference_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" + star_index = "$(pwd)/reference_data/genomes/GRCh38_hmf/star_index/gencode_38/2.7.3a/" + } + } + + ref_data_hmf_data_path = "$(pwd)/reference_data/hmf_reference_data/hmftools/5.34_38--2/" + ref_data_panel_data_path = "$(pwd)/reference_data/hmf_reference_data/panels/tso500_5.34_38--1/" + ref_data_virusbreakenddb_path = "$(pwd)/reference_data/virusbreakend/virusbreakenddb_20210401/" +} +EOF +``` + +Run oncoanalyser with local reference data + +> Assumes existing samplesheet at `samplesheet.csv` + +```bash +nextflow run oncoanalyser/main.nf \ + \ + -config refdata.local.config \ + -profile docker \ + -revision v0.3.1 \ + \ + --mode targeted \ + --panel tso500 \ + --genome GRCh38_hmf \ + \ + --input samplesheet.csv \ + --outdir output/ +``` diff --git a/docs/images/COLO829_wgts.orange_report.summary_section.png b/docs/images/COLO829_wgts.orange_report.summary_section.png new file mode 100644 index 0000000000000000000000000000000000000000..a5b9e6fab6ba3696f321b0404119718a23ff5678 GIT binary patch literal 1135893 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

    KC$%%iJ)M!lheDAHNw1eBxGC8}qp!czFYi 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


    ONYD+>upugpQIq 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

    vL#C4OyxZ@P=Jb}EB01Vl{uZR&7J8;w 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%0Ax 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

    6RS_ew z>Q~6d6DEm~506>eFS6~!)wPLTw*lx~sS!IKnLrs^-?k4j^H#JsTbG3<;H~XPot;u*%{POcXQ;_vbYUi;w3KYn zu*nyTBR(Zux8E?=4F@jqxC7m8*K1R6(ZrF2FvvI}aXc+Z6m(DCV%KgnL-fs7>MA9C z)zwH|?~(04qWFdBvwD`%6yho0x6vs-mMaK+-Jic^0^}oIo2hrdHPElD zakc6AR^buny(DL>O`NZ}HSF0iuWz)zKcB4H4B#r2DyyifR=BKWy&q-m%YEF+fvTjQ zkoi8ICOU+ON1Z$D3hZPP8xuirlbNdlv@QMav>=7`oGl6HgjBeECg3Xy56{>Hjc_Tc z>3?iYkD9?Q+yX$oeSqXZPCmYR;t}WbAo?%Xr!iuVyH}r6Dd_O2jVcv267!5oom41F zVcDkxNKn)n^1D+devnQ3m*TpP(E4LRK_=!S&j9M6Mbhxw-nfE_?&C)G1|grYQwgx7 zDGD4|kNynZoi{Wg+2?^BP|5AY4&xY3Lt|u^%r9WwHX|k@g@TKbNEd%UzJsAoaPTc2 zC|~A*Pxtz++S{o3GQ@u`G2CLDQbl`PaxI(Mp;w3nTz8LoslIaSe zs40pfiXiY4gb0YTRMG#Bt#=I0ZQD+sn44_4v2AZ`+qP}nww-KjC-3vW zsCw((+aKoJ{HkWErss6`>2u(QZQqwFh-#>-lMcDS9dR!??*av-XX_=WD-E1ORp4f; zP{P=S{Co4oMD(EhK;=|+`~9{ikJ-u_{8hB_P56BVq4c!Wq$C}zv~NaJ4F<8vJhz07 zXhHSRZ;Z3Uc||omGt6H3ep$}qBrzi8a7(^?mOy)OGhBetB0}I$7@uF-08D-C0>Gp`W}D&tp{I=tX-#3vFeh*4KA+y?lFC*Pn17mVwqVfI5;?Rl zl|<2dsqvQHt1b}jWEUmFYB3v`&ec!8Qp38%ZO$;1K#+Z+^fZ3B#h2{>?JQzU7V`Jls9C18)RWxHyBp8hA{$uhkLHGh3Sw@rd(VwIoD~NX4@7e?bnx_nD`v zwzyY*-d-!dsR2<|C&ABGs{_ol?*W_diiBT35Gw4gJ-T6~%{7bH*HlL>qjydpDtfBm z!Q?zHA3V#Df>2s{Ipq!6Bu32e7i_8&EA;-@9MLm~O-zn4!0XMy+gxnE3y)~Z7_di` z_8FMQoqeDg*K7(hma{c27v`_Ikk=HU{1&4$Uy$cf{iJahj6p$w%@W5^BITdqHPE7| zuWB;OK>9~8jFad@)hh1rk7ul2-ILBREFUAxd^gcER2Q?&rnl;kkw3F7XU@df_x_BL%dGN z>HVDj9Nk>j`<{XeWHr2CGPk~mbSq306}*|ZT$mcO3^=DU{86n$h%;g?ep*q3%-97% zCZ*K3=8I*zLtym!hLR0ba%kvlYp~sGBQDy1f}UCy!TOzemzuUVu)5krEAwAsaEX`I zp7@`|)#%IL|1!qQzm@Lc=dU;0Z8dvqYwIYWT9ov{RCQ9}(+4agLQl`Dx0kay)z!KjDbypZmV)C? zHd{@$J0*_X8@~VMej#4mYmlv?V**xa$_)EK{GDX`n|-{0I>#@I0bl*xoAQtwRw(>m zU~@Zs0hf=8o-T2j{4=4=FOK)AudH150XGj?SY6Rg$oWgcIXMG#bR?7%NNr9c6j?w4 zv%Kyr50;6E!J1C#yJdiECn#1rB&}G3F^$61f)WU=CxT&d#-Rtjgr4;QC6EnDa_+dd zOE=?nEV`-V3wu6&P(^QN^ZVYQWiaT2ZmXAkng8h}-rFyxMtZbrRDmR`7fqTtlPyY& z3qgdNEyeQTIK{qdco8=>NE~Y5%aY0-FCv;9&=S(n9k`&;_lq)56;RZ44iKP)Eo=Nm zliNiR*8X?=QnbARirv9}eEsh_O8(a18#s_88N^cUH2Z7za`?~zLAjhB)->9Q+LM&6 z03xeZuGI7I(9XV?Q+neu9OWr-mMZ6RuJwG%%KXMr7O4DoQ9@&BkYyxL3y7wrX~j08 z(44D`Z+U_LpHfuy6ZWITyWw^kPm>IF8#zKELaZx{EEsBLX_q{I<-)=qZ~ezq>-bUc zsE-Tg0wNWU4Z_|ln_SHB9q6>SSYCU?AER(>dn-@Na-Pq|rd#vDQ8UdQ2=jW?Rha}R z;v_UYL}aw;G@vpQ#(ZP*+UG{jUkb4v7dhh1&Ec6qJZT#aKoH4BHEHEm?Bd&e+~`r? z`O2d4-TJfv{UEZKj#bS@%^RC&+LVC`vI@63&cZN0CxIw8F6dE55IfN0Z|}_7+Sa^WN!yTpx;EVrl#hHddKbFfezVdP0u43M$a6sfccgCbEn#aZPgd^V ztS!VWiih^lB8+A>|58=^;%I$;&bf*ilERoq^!QU}qpIL?LJ8Tc5Ce2PDT(6HERu1u zQZFXB)yC+6N>wDFEZ>U|0XMKyn<{jCU-qLVYUGY<*$hYpI!PylY16M9YSc_ELVwr< zmu-k1+?`0xzAasYF&6B7#*@Vp-4vSrfp;Up?D<@~&K@|0fchxzH77<4+)O^;zk|*c zg^W!|C~I_qEpuEhp7D-7_B!({6Gq8u3P7A)ji6D5w5mpw6ErdmVc9e$!)d6G{9RG> zJT#KFDsy}74f1V>xYe6V|LBn=;SDd0NX@oUxZe}*J?+yhDOydZl{|clnPnLKu-pWUh%tiVE4=S?eTjQ z*gk^ztANid(d1F#o{@6DqVV}+bbk4N;2jng8@v_gGPH?J4xhj14by8+EE2zCKf^-5 z2w$8zC7umr8Hp`|2QQ%(WR%^fu=eF6;S=-^)Wh}L+QutP73}sOa3iB4>s(zp{{_d( zfJGND4Wo<%Xr@O25}gE$4MC4I**VV^R!iI4G^e7R(26Y5f=FBJuSN(4Jip#m*Uw{H z6Mu$uW%o5FQ#YNL%HtCEn#p+S6L{~#?*~1I!W3@>TY$G{_nWtb1@+AeQ#M82A|-Tw zLCh`8?0bLcFD{}{E#MJxuBw;?^{g0qCXqxxy-9L)CU;}JWjS{Y; zf#_0#F;r@~itX)Uf8^3>mMlbU@e6pccK&z+oz%~!iL&hH8zbb-8&>>=am0w1A9EGu zhwx@3L4RpQ>ZfAtAMzbyP#_n@0vGJ;KqJ{7oG^c=dkmD%oL7n&3AR}gRY8McY@{r+ z6*EQ@w#X;w;hp_?>p3UaiDW;_{1Jv%++BY?9&n|cu<{PxV@#* z>S)i110eNYsfgQVvrWr7WLYhcGu$Lo1c^!j5&)oO{70uGMsBh(tfH_VZT z_^rI-TDziA6YU(pwK-cK!J5f}QA?C)KdURFRKGqQDYtHU7g+XV9-$mGDJ;eBxvc{Bo z+LgR+2)qGJ!Bkf$&KXX;?7w&?DjQQYY-SoPcq_+J+e_Y(aDy5K>wz+%Zt(nQ5W)#%*u3@q$Xj?o1YxA$JlKHe$28Dgj{^yZGekRH!7%NKH`r*jDxs zm*7}ud-1uOa(6w-p&}qaOM$DrcccyzI|8pCt{xakjDHHC8an;c^m^%Pa&34c)3YVe z?pFA1LfQe8x+Ul}yPNCoFN$Yy0&DtxzKM_evA`7R}6((XW8wczABTb`IS{pf|IlmxT?C9=K<5i%_C0{)< zhtOWAJTrNmj+A=sCv>{Mkpb=*$H*D?phT_Ex4aO13#UN7)rv_&?%adCAGx2hb%rk~ z=-!zvlR#BeZ0AoKxrj~5LaDXm25y_5PSn^n#iLYfHAxG};t+fro^`W*a>rY-4DW7i z5H@{z4G+krKi|2c#jyOAq1#o((VlYg!aA2Nt=ZVlLmO-j$_YH?M?%F5StBw$Lo1|z zM6nNM)ckqgf;eE^eZ?HJmxfMs2nBl1XePL#^>=-_xKg{9{3XTH%)-#L1f>+()9!)5 zWT=6>R2avtnB!>s=N(}Kt?)|cjB)ypKt#&xh;*&3kd&INdz=~huvF4HxjiCr6Ggm5 zN*Aq}Q|$uhFpIBEBpO)pP@YqAEAjS?y=@H6@sd_2b&@OunN#@NhubhG(f-(B+*QDr zP_S@XEZ}^`s7i7aJC8V|d{#=`l&s^6YQT3$WybWx4FD?>aW}M;GJxtROUzABeY?Al zoj@e7Z5(F>fRmpb&-*q<=IVX7nNw^%A`OiXwVY2-H*W;Ha8}_3!2_(RDybE1+I`>K z*w&`jwrSd**_VY-^m(V)q7)DV*;o@%=C9vbVh;iciSEFI4gTajAL2A&>?3*TSgiuS zYcicYaYmzj{wgAH{BsBk>ajM8pa*n2qfBVLEYi52*0AV`grhF)sR?BtaeGpk~WO)-k%QNpEjk$o--^j zkdexi9^J1lVL$jO=x>550}3&T7K<$rsfkYxHhsXp8*+sC-2|umKDm~dV^JD@k-EQf z?X?h4zV$U6e)lo%3BEzmwE8&PvT7cSoC8&z1muL}9SR@JCGJ(gvU})Ph{ncL9=={? zLJ5513qO~Qduom(+#hGXBda_6O3jh4)5#ySAId_BGzSc^UG2j<%XT#o)t8A^gSwvy z4zpVFOp0x(jjdS&o(0Neye>y%7e<9b8|Br?DoQkL3v~jPO*9D8JH0ZWR=y&SR^;a^ zTf!Vv&;(wg`b-7F8fP)%_>P_{MwmP0o%>P4Y z*FalTJ&FGr!;qn*A&B>7h9hntVU*iTi%nigH|Kg^EIVJ*sGTnRU_c6p&)oHY?1@eH zk<0(afv!fc-+RD1^2f^&qqn&vf#Cn3QIH-4L>zFbN=mNrvrG}2VwxVY(CTNk#)Vt7 zr{qTU;Y2J2n^i?bqd2AhIXGWo9^%<+a;#xh!atc7ZDAGQkQea%42y8G3ilGIY6~-r zxTY;k9MGJtkc&f{|H*-}yz4QBD2zCa{m|E392( zD1ziP*G143hf=QFuk&b*os!K&R+Cf6$1H!=tE(NW$w;0h%Yq6&(n*Co|od1Yz46^#^lvA=7Otd*|kln?F4 zTJrspHk06S{wQgW%yFcuq3VQK#Y((XX7^XQ(u~raUO+ADUDW4&<#u8Q>N9N z?c$A|Phj9ecvz!yPOYZ5s`UAjvJ4C-Xtg%uigxQsBI|^AOgzj?9iZ^x;rQKa=M&)C4eqbvqiIxr?ecd+JaCUz>d!j3(NOElSU^)wj2F1Lo zeLqco!bqKG9S2D>V{WIY6#I6~%?0et5V9fz2bG95__`cchQym^-ao^m-)5Pjbd!0X zG>70$$#&rhqaUNjE43#2VKD~=Pt3sy^`}TF#k1H?(uGEYxI{>q;%cU z*?9vpv!!R$S8@p$?DD)bO&SB0f|G8X$%vw4kia-qb!-YkU(QaX88qHs+|Mc4&A%W7&xB4@-`F?MfBxMd4zBorTJaR>N(g`j!D z$1Iu!EG^gmVDMOz>1knc1FdZ2Mnu?wM0r8YT#|L!!8?!y(n9VZgyL&8$mu z5o&G=>r7g3_(yorUBp8n9IY&&UM;;SU)-iI3KEnFhAl?k>{Dkv>Vd`^hdr&wg^_A}&gpgj41oA}9?-Pg!>{`H4N z5Gu!)l!k9MIYr;Hip$Ta+of!vDX`7@-jV=R`+ZJDp=Qq2d$))T4%icVx5xpy=wm6M zHZ9f&)l<fF5r-}(;&;SEv*WtC)LCL0elv}Tw-KdqR zq-|(Ao#UTso0Xx$0vwfsN`xMY*n>`260CtjyUlv8u3N^^F!IQLvXqC;i@siAq*?f7 z@c2MM*_nH@VR#Qfj8w>HI=dh3R)och3rqz0B63yhf}SaF1WI^jf+0<+fvr6vH)TlQ zpUQ5jKxC*uryFTCD|<9c`mS~G_;tQ68+>aNxa3i>R$T)1b}GgYr)p9>3;0J(o&r9B zBx$J?1EPO$w0l-G&Jz5gs6c+|0_cp4Eox8zcU*H|VhNR*Q)d`3Eq1Tph`gT>-4t&%xS<2L)~qh-*E=7Dm^rjI}64kyul*OG~f zt>eav6}2^;F&z@uMs!#Ot<>h$Lg@nKb3e`Dxf8c5YX=;U9}n5B+3Uif69~fOVnvF} zvR2|MAt%N=&X_%lT0|(%P{?$=jt;a7H2L{cC@t{7v2F_06OjM7fIXe&`?m{nvE^!W zF|b@bVgVv@Tq|L?k7S5K#;}j`9#y1A91$>=Y*Qo5swpW>9{6MC-agZ^6co6a!k=G~ zL;kj{XPB(s`>f>YO3Fvr@Jp0)+Axe`3-Hu~GF~stZ4oPWpmCJv1YhK-fvd8DLGGZz z94rZY3IZVv+14Iz&B3G}`oPF7Z|ygQp0})tC#l0}eR($`wIc%^mrWWJ`zdosyAmQz zUE5C*Bt!!sVkZ#rcqZ%H{=K-k=qz|+5ScfpVS2S`9%-I%-;!pBxlbWMoU)Y!Hq_iXQ1cN$W3lj4$=2dp;jH_9$r3L9$!NBYx0^GC%C)hKPhhEuMoEyHVRbGS#B?4&h@|{rt`l_mi-zP26D6 z&0E438!}gvzW%3aCrtMdT+f8!m+3>5OQlESnQQ_x)s|QE00Nx2RW1-(yR8XIjlh$= zO;^U(bsFG$vVYv?;nQ~X!+S!NbiPTkJp$n%cWut0lYbMfy7ziLUj$bxW?lXGYJ9(M zc_2?+xTgjDic?(_g-KU%Y4mpEJkehz1w}iu5Ezu#frQm-0l)+1jz8CM+b74J-Wzyl znEekvh5SUB8cf3~VQR)L2&Z@oA2!R`vOF0bSzV$+VQy9^_GJawwLoU1=ReNKbCvq0 z&!Xl|Dh{(0m43hYs|c-E@>ayT5ab17elc9iiwW4(ytHe__$Q3aTo)58K|9CT%;Oi= z6rEFLk;$G5FDYs^EI%bI+sJBe$jTqtIifc1L*ya!iA+P=lrLLVpk;z)Kb%tNw71L9 z+OYhKiSGz9O2h5b5M?~8Th!UNx~Gc^tM)C?BC`W^!E|NL$|*ifdOMh1ksU$xu4Cn7 z2~x)^$~EMfLbo`-AHT+*ae33r#sl|83v>{H3E^B(~~|Zu|8E>c4rk;_g-xxLRlXsrX`AiA$WUqppL*`V?%q{SYfRTrSL9ogCCr~#0z=dR#bFGnMAgsW zjaEViw@2^p6esf`dO8TbBdRviQToh`!dSO)!$rcP1gGDZRZ6##RGvo_+msy4c~^0% zftlmX`!U-OuZon=TN03M-I18h$SNH~4{;NYT(Y@mu{Uruu9(rjh$3%NrVzxS@$(gC z>>(Ssv8r~);04Qbol%MfRP4aZCuKT?6H5o7mY(orR)6#q5k+y_Ho>G3f(q8qvPJGa zS3w8Tm)g8JKck!iF14^JG&gf}=`T)YwhA?eoOe142mhC&gH}NwxYs<-Fty45JY4z4 z?8)6ccC@@A_#O0OrHJZ~ezcVDD_5phS663G6`PW!osn!AwV&n&d|_re#a73sO_H(V zlTE3%w3meFY+YQ@U|`0I`-6diN)fG$u43wKd-AxEx%`!4>N9A1HBB}G4ZWe~%l2G- z-+x~CRdAGWt#h0YZ)ex>4efG)jIe@L94vbsZ;Tx!kznySR@TNaVfQJpcBBC4d7Tw7{3dre4@zu`Zw&Sut*ny z-P;4iqsKu;j;f-f;tjrHs3rLS6^KgV(v@_TcJ_O8yq+Ci^^QSSToe%tofr>Vf#}?( z+*nR8r*D**f}YV0=eUUzN2XuR?*r(fh>ks_E{TavCB$BYXMWAmXd$>!b_dL536VMh zV|Oskss#@l6L2ma7gJSnzf3~yRJ(p$uj6NSMf0`>==<9f7+69!wfn#AosXV#*0!|N zX0!l!@F#U6GAO6*-EZl9IUR$yy#g6`waLt&gyXRqlM(S?_dMM&^+dn~JU-dB&uj8i ze%*<&jV4S3f7M~AZniyPxRJFT3K%Pcn{amz05j*C>xWVo!}vGQ<0N(p`*2r}EG9tR zweMdmj#=ZuWGCs~=l^(!mzF7sk4apR(dKDto@hG_;!Esh}h>-=;RRJH5Be1>n=P ziz$}xCE=Rk=OPqE(*?K`x=*bzSbb5AOVEM zzUdllDuEAQlP=5C3LS*d$d@R`pPVe^FrhyeQ+w^OaS#?;(!e`t!dgzTdRh*f6jJoT zbqp3DYym<7TIDPqgeDrz#*iWVndAIrKS9XXyhmQQ) z|EAGB0=Z?-I|-aD;yNj&wnW}WUV&B-rap@+q85Q1r4oVqxrHGWmhoGpkkp9Aevrrm z>lIy@-X99d0s%dHFq|Jwv`_^~MI3>BIl{h(10$%H#29~2_3rs+>7spu%-?_~0TLQR zwXi|KsB*?!wZAtLp_F6}<0b*Srr&Vf3xnI+{oiN2rKlCpgH2RoIa@+tAO;6y9VIM0 zYc<$5@?3LXX-RMHjZjDoJrbes!+k=FW#`Iu z7LD5CwDYAu&Fgf@gkr9uO#-DR2dXZCwl}#;G(?=r&VNj}azmY8OlB1>#G$|N>r z9-tEe)aM`L(&f^qh0&-5x9<;yYx&_V!6nkhY4Qd~(=mZgxQ>_&6=*lb3L*=3?Q|lZ zj#K&J(~lhH*Evh7UfXGdb^Ln0u8>S~B9rveS8lP_IhdLe{i-4E423%a8@;Yz9(T~D zR;cN`=`7(z0$FNg5hSp1E{;eEY8LF=cm{*{zGTVNVBt~^d z$7GJ2fmMQsM67Ceah@WwPaP994_abblA5Z$%3IBRso%J`_`zfP4|g)SVfSv4b7C&O zzc5xzDT}Jy@MQT+q5Z;%6Z_f=K8rtHH%Z#sPf>%UM|xKrstoBCi<#hXKkDR&butF1 znuL+r@$6$q)Q^&Q{`|G2$wY0#Hz+6Zy0fK|;#uo(A3N|iWxH?3?Ygi`kodbtB@m2U z`0TpGhHQ{c$(rXlh&=FDPtSp~HrM;E09Q&5s z9iFKCaAIdG@JWCnj9EX5Ep^1Ua`#mMqonF54*W;XC)zb+%|3*vSOc_Qj59)pvHP8U zLs)iNUzbO4M#eX;I>&eRR+aZQ_vdwKj)gMAR9!u|L`7%`Gk=KUVfM7=H~7`OA%M2qy3-32SH7KPPy#f)-X~d z=$*p`;7WanHeM@hfSX5FxA7T+%<&d0SbO=kzaEg3yOWRcfNkgL*~-}cgLjZbDzMP~ zoFZuqiP5rQ_8P_c8T&;ok)2Hzk{+d5N3Q}3!&cdr@}Yu@ic-< zXVhmSsO;0I5Bk}9Y`q2CdeYB#=b2=%%%6>=*paWXN|#z6MHf-;SJ zESCYRm?}qH5yiM*NUT~Q-N3+-^exsKJ{G(X%;r8cR1VQPIjWiUj*Kb}Jd*U@vYx-i zPfC@^L(9#+lh);x(4w3_0pJvMeTZb5gx(~R2?SHQV@8_T$8rnHSAs5SawTdBBaZQw zWo7Tq2B-@}s4}-DLpj}sX@gAS25OWs z3wLY z2&3;Wcg!P?ysqCcqX|8oM3}qXO2r)tnvM*Z5z()YZzVxl1f!0l4G@)W>PociZI^eab+Y@!2l^3i-yBQdAT$7tGS6-)P7pxq$`+F6k;wDw&npxyWqMbXEBKnFD|NOcu&7`S_LdgpSYL zLJWO5&zP7|`Oc8bV->|m96sliRUXTsz_JPlPA+G#3x66UAerT)s~guf4$5j2U9IHM zn!^)Kz}d(9Q4t%%CU}J^TZYb~*u0{_@q||7>>jJ<3dCSNDkk7K95OvJ+AHB6<^0?u zUWDUuLqG4PXi!&j0ZD^6{ROS{Y=4wW_X=8up}74PfUBG{>L>jShs=Y7v;+{6t0^QvJ zysh=Gdewf{m6X6&>P2qQ+e%OF{8fJy{`?zBi^|lF2{opTZ@=as;{s2P;aHBqM~{c_C@lt9CjYbFNFQWzkK(oMRt;R*N`0qhU5%|hNk71lB@p^`8ah_=e;CiMAiP$f@DhL8_;)(95M9hBDj14F(#)brdosZH9_cN3Q_mQ-7_Cl znTDh$&!!ypimC$%bQWWZP=$p;?)^-dUOuc}H%f#xUk_j!S1BN%Ysx$U>#eSu>+&&MJ3n=FRFodP!cYK3LE5+;iy{2W$9H1>3+Dk=7k8G z=8-8S!H~Y6lwf7^r-+L-8^MP#&lxP<@xbHWEJ>PYv0P&BKRY+y%p<#{A7lsagxn-T z3P(+vgf=Q%fEx`PG$dld9x#~9lH$q5K0-JcDRv>)+=A`94>oZHFWWFwvL6#97?C@; z%e_6DXcxz)rBcuyL;rGTfsLK8yKO9g{PJKfD`tay!$uvUZIZoJd}FIO>~_ls!Y=8s*uQ6jMH`&et%g@p`e9=Qi8@6knxLc!%Yk$ z2CG=KJ%J-@kKl6~Aq$X^j6DlOrb9oPIB97Nn?1VM`s==YQo=E_BIn4+Icm-BSc^Pc z*r&$4_?$~thgbIAsUJB5+K`o^f!f036JGVEYQoz@1R}X&^nT;Oy3j!b$qufS zeyFg;38^))(%+eaKUVsf`}E@ySXh)ajP19+!~4RMWBun&3VmIlApDNs^(>89wmL^NUSAl@;ONdYzy?DSyM30`>Kqrqmw$o!(HOS4 zj&-+6-(A%pC9(XQG~YDKjDcK&abfY3fN!gV_(bNY+@(;Pw~?sPqKkm0|EIg#kKfD?*a4SlG1KN6_~1=(J5WZ~SuQQZ1@-S$j~t;M=4woK zmqYXSfw*pg|2|Ns&huZfjQ`%NoUx$7!g?W@Tm1)`vh9w0%L)CoI|s%O8<|9brC`@Q z(S%Ct_DI2)#>-;; zI-Fl6OcMnss#+8;1Ff)E+rFeGqTMQFf?-c0HX14!-#-sl=L%^`pID)o;aB=$w3fFZ z^02`*GePOG0EV%Ws|>FCVMbp zo9*&4uYJH!NJfs-tXCVK(=mOJOg7m1%~LOd%sbvKw8b}oXd3GI2}vK@Vyd8qieS&h zrtgl&K%c$F@Pi_7^k}Zszg1B7zV?`z-~?dxOj&Axm$dvSLi1@8 zN83_QUsmH30_oF4y1m?=+q;y!8{%weYBFP;eWy<}!PIw#>a?busvO;$kT5(lkh^kwgggrPkc!=MdvKwkm_yH9#K_+dMi6RP%%o0A!m*Np=Qc zcSK&0MG_Ua0fp)0N9r1L0}JqC7m8tlYZS`}qxBP~yX=9}LrrX~g%BUdc$$Jb$?e?r zA3Gb^Jr>w-H#?Pm8*<`J@q&~9<@POxgj*~mI0)~L-V#+B6=`_~2Hk_0L-gr~77cen ziQF*X5127r(^j50cu$j*S=*cNXVXbFdA?ekA~aFfLy2q7O&l*F&hDwAG~a=-^_Wyx zg#@2B-hJQilfmz6M*F|o+JpFwAh8W{4}#x@iyMN2Z|QZ>tKMaPA6p2lUDg;IuBEO# zU@YRB*h((BpizUlfug$_K!K&(q1dZ5s6wMuGBE~;A<}wUy7AkdgjDg2c;rmt?OW&pUnv_jDSo=w0`+CS&%XnTElA@^=gmJ_c6z_ZV#Wk|{I|9Sbh?6ZU4KMmM8+K;gG7%^ z6?kO#r)qC5Xp%G<#B#5f6(sODL3oB4ruH3W?_FyK)BcoUqN(e!%f82br;8b09YYAl zIzao$8B?}Irn zRJ;9{XRR9e9WgQgF>2}E`1>XVC~#paI61QTPF`WoP6qq}*+vOp0wiReGT}a(jmEiWNXsMJGPwN?E0|=>Tzy*k@sfHS@ z3;E!SB2)^T`u+ee6kv&HVD9($50E@DF&Q}3L7g!YHuM*qcxVeuftoCjff;pDX&(6> zIKYyrs=OJ3oLm`7IU_C|O}w8hV(elr=!}fHuuS+zy*5Y_+<*WHfpC|fswI(#tOqzH zreYuV=7oVzPJ<^dX5i~*)KhHPz_kh2M*j`>IB!5KdSIwxA9<#g;R8|`8%f;g7IFTC zA#O$LgQaY9NWzKTulzzG^B`3PU-%FRn`nHmCPudS6r z0voB{{11B^6e6tvGsXWA+5Xq>lT%Z5bq?Y8w5F%S-V|pqZ4NnPxk<$rDW%DlnR+}^ zwC9+=)3plG_%ndQz|zoxqX}#XJ!g!8Zp>$($|PQd-d}WmJs;pMmMO1I3!V1*NkQL* ziUxKqCW=I{Kr2hi<5hLDGq?)OUN5n3nV-gnNVRGmQ5j#n-_)3QU~hN zr>~n|8V5@aGhLAEGgoU*P@2muNn)B=>uRlD9||gOdE@JpflmF-#MTeVNPV)+?TJD{ zKb+qf{ez71vw*lCM@+H*P2iV>?C}rJ7KSr-iUWLv1G+G|+G(P|!IZB$wY04mAt0@X z9?cK-lmef^#NY0@93n~4b*Ki@FByj%z5DL0#QP0Ecyias4Q95NSIAS}OMyi7ntM}H zBq1X=#ye)kC9_qdv`pT(2sclBU?pp{Z>k%D7H=}U>viv?3qtAeI^9iVeyN|RNYx`| zM^*S6Hh~$H94nn+y!f%pX>10{~Z3S>4C?RxxJcXjj~Czzx2{W$%{9>PYdv+z@*TMXd2=5+Y*4 z5+7mzO<(%z&d;_Vmk#b}(9It(;e!HH7%#7`v zjWd3&FC0&la?M(_!{_=u9$ED1TkjkbM~IpG(fY{$h9mD%)ZC88a0vjB=YP)HzM;UG zoQa8$#eNlr4r3waq%s1FSh1ZfZSl31j}L)_Si7HL;LC;Oyzk53+Zrt}+it(qtUk4L zCl3&7T8=Q4`F8%J~C^Nm($6oMG(Um|BHGzh($C#tEMCIObbWb_h2g zXV9o%0iN^LvZg;%u67wQmZ6n&rbZ)AXNXVtCCjiu76lD^>5@s=(!ZIO-2ZY3rtJT- z1^cr^edYCb!q%b6IbpdrplOX$@QgS!mTdsysnH+)G7FvZvr-TRcRFnS^Y=wy*T3oJGFVkBnmR#~%wclo+Zvw|*QhP&3(Cll#K{wt7mTIj$x_zm7k7iLJ9*Xf z1VS>j#uB`;RRzs1{=o?4Km_m`)I+QJ*CO+Lt*A3?5`-%FEnNHKRL#AKN8 zL{Eqm@?m5Ytq;q{7QC5;nF&k-^CZp-X4>873$9jfS*Dn9XQL6R&RL>%xoHSy`Xdi`zfFTVGgK zpGQ7laz5_oo?e`>t8$IX_|)1Y*zOY$WxvzU->~AEczxrh@gc_~&+NljX}XJxL+Ot- z^NAW7#;XHJQF;$&dB1h2+mEHDS1XrKBTrZ7en912CyZqdM1{C7*%W0{qIb_;s@b{X z7NYi$ZG4gI3E9079lWTs#joW{99(K{81fo3((2UdYKpd>mZu^`ekBFOP=aQC1i7JBYt zJYrB`_Q{JTQe@~glV@)b4SN@?jIOI_-NCuo5;F5d z-s_G35-iLIibgmV7607Y&|cdXw+jfzhyG& z2!Hf+0)VKu3vfH$SN#4^V}4=98A3(sh1OxCqWyNKf1P(`ig=ey5fXjCy;} zY%G7XQmoE|65F7Z?=852E8bko*d7*{D!08dZYLRX?M;2bkM3Eoui85=X93vraIRMZ zC-sIW3siwJGNP|Wk#7Lctm$cDrCJip$?Pl4(eeP>Z{-b^(u|R!Dhs~F{s_$_OEZ72S!JEu&~m(t*)Ay{bTaBbC#+JRZ8>UoAti}V7XhJ(_ddlPIV-K zQ_p~>$p3yJ!Mnoial7U}&MG$SS~v392`mCa6GK(mbaRe}x8RuaxQFDZW?k==yfrd3 zv$C>86svRcp-CWgqr`eMu||9^sx_3C;oxqA=6FVh0#Z5_Nj{MSf3n0l_qkJ&h3c$zmRkv^ZFiZ7th%HCCxtH=!C6bs0BO=oNG(I zj3VDJwZ2ncBRvaDA*=*Pm`-4SbX37$q^1?tKvKyC8&1ofND-*F4UOz@#_fPA#)2T% zdq91LtfCl4u5Vl3@B5}6MOx9{Nkn73nmL@X+mpRIEu8{n!>#~Ki#X3&y#Po{!M8|u zLgr3yaQ{1g8+S||q31PIugtD}Z>j2h`Q*?$FY$`S0Uo(3^>UqBREhZqEtp))4zFMZ zHF+(G^ysELqiG7W4ww+s zSgD|pLI@R#j6?ANPC0MxEK8YW&=olTdcRU$R+^)h1^R-^kzXSVa$P_zb?}@I5{yA0 zG?Cj&!RY!+6j~0IKzgx6x~$w%2(KtiP4n7NOUEv@Dv5vCO$1C%@drvA zDg0EXS*%zRjMU1GD9?QhA3^b;i^2BV&a6afr-XRty-E8cbJd+wEIMh%O6YV-PbkE< z;J~W^iqTg$2XlbV{j%Gutb*EZ`S&*?9kn5MJT%f|yLSwsM!QbRH%>}FQi5Dh_d7nH zKp(PxWEsTOvFd^AQgA;E(&BQ{M3CEpCHonhH1tCgNl3@oa9OF$aHpztYhNspI&%Pb zt$p|(I4n6iJEZG9nS^O`Pc=<=LW%`c_x>4G>!jsLII3#frBB}Z{njhUeWzhcN*0zV znS0w&H@)EL@tdsX}kLynHa%@b^ss?2R53oPS?bxS$+~adEN64glb0gV}&5M060D{mN;GNVuj(Rodfwhb8w8YrB# zVlPcSN!BUkIM&IFd-aypNz&1ZBOmY=b7nk>f;MYC6Ln63_3(v$zcb%j;dEFdd*34q z*Kl!S9j1{a4U3m$ZpeIkaco_;83mQkeX!5Q6|% zS7}^SaRrNPSD>TrbiMaKuyhl8Ge+R@Ke-u^f#+PG-kG-z-qUohj^^%>uZG8^E@fDl zDwtL!vYNZ|4al9&7c9q~H?b8>B~``@qO83p&U#<*qqO2#-n*jI9^JH8eIqF^A2ckI`h$4CGQ8BD{X!dCs22ltaLiFrf0*6`ph2Kn0*DKh>fQ^~n z!pVk$hTExr@=9?C>=}{H*xR0NFpX>PBXr+Uyc+k^RHKrQJ@H*1nWhuE9l?L7zR=<} z!D&zzQo9Nm+mh9)I#leA(#KUbhf7Q~sf+iu>@^nq=z{KLTStdgsjBkTSW;0xZ#^uzEr7P3l#&>frbI# zCAgYznf;YMo#oJOnEFTZ8iwK9?9X*?b%lisAFEnMCSMU$Sfh?-=pK3HSfB}FDjiUE0y(5wHvk>yvm;Zq>yYFRR_dD9$_4lXs zRI?ExqXLN>vBLF)EixGdOd8dWMA=720J7T6mN9E?GmfRS{b)z~P+{+cfo00}onW_i z!e_D>&MOSIimXz@{w3LAER+9936I4fP(s5oCu8+|Am0c)mnKmWWkF}>`Kfy<3ILlb zEBhe4f$UGfN3umMag#PdZ<&)m+O{npQa~512=u_ByKLN&IvMnor*crcqoq&B(yq@Z z{f{USUam$vM*#{|gU(2nh<9d@6G(GSX^zb?(V=S~oQEW~Zv?k9;Gw{mGJZ8*t z>3+ej`lU5w*=)+ciR(U*fOEHM$S6Mq#ZsQFQ8-Rus2YnGu4<@sZ)Bo5>ocFc#9lF+ z0|M>Om)7;Ml^#z%0uN8me~(@2Pe@iCKGRU3$F7#J*eBdSc@I8gTssVq0V6*tzrUCo zEU=|z99nQQC3NU4m7PZ`IZnPy2IN_f%61gK^ifVVvR{XHtm>Z34=dr)R(p95{ZjWS>ma#{sKxl=4re znELmgPF4}Z#s2K?Vk5k_Y`4rLm4y@M78w|ps@EL|=&2a|XWkPi{$EL@lTE6wH4}3WtodE>TcViu&0{F1RsKvp*>5DlPo%yo&70YHs zOJv#VSPW?P18-SsVS57i8O}eE90TtOIo7+orO7Bb73a7dN$LV5o|fI02Kk%Th1H4V zPnBgsXzRz_P8w4*L}kuxr%JDyGiMc(9IlMI--Cjujk@)xHCM+4KXAq%f`%dWkZ0$r z*_lkEesv>CwqldXbx$mR7rw^M4ac+oV!>!|t8Ar<{ zI#ARPQiaTTVh&Ma`J8n=HtqUZaB^ihKp)8*p&k$4fK%!M(b*Xoyj z*NuC>Vx_1FI-B%6P_g2umn_V$w|TMlnk>Ou>R@+GDqBF)EwOiae-gNEj_FWFd3X$>$9U#;#wbD~j1_k2mZ8Y2;DVNzJ4ptt^Q7pGq~_iT?5 z+8v``mch(tN@$#0F^LN1R=R)adKM(^yG$$zicq4G1~NgZFqZIm6=!i^3g7EYv2@HY zq7Ne_u^L7^p~&vaIeqj^XkU}i{7oY2rXR_oCwiY|7rFX@N?g%YpbDcOAWZ3Z)ENBH z!B1}HM>KBh%W!5U%zDXu-Tp65_j1f$$6**0{mo!n%UnKJs+c$hNnVuCp_y-|43~Xg zwItL>*r4{^T~S@5lVh#4;306<_w5t79fzZTQqn&JJ?-az`0(T0lT-j4=-ulrjlqgm z4h!W4K7r-y`Ju76VI3t7i#TJ%?3WXue~J%`{#qac_Q8tc%iSwG?XG3=@whh!)=(F8B_hZ4zAZAGL?W$j4k*Qj2U%t9_x_nCS4#^d%mEsF;3yCE zHWGgCy>_G_9(f^qcrdqu+tDaNr`RBgN8ZnxY(+K7D zJqDW9^6f!a9Ul+C+?)pHQhh>+ep~&eP``4k($looIHt zoTGiZ#Kq?r9i*mdOcJo{k4iV?BEd*V>O@J~qS_>*d_Q)R-+VEwYpzNQbqDiWnbsLt z_WA$G8L;1~M*MhPT$;?VDiGKs{+ALiHVU2GYm`>DW^D4;;}M}qfY`?KHuo^CK2WZC zS@PqIDf35Oge~s+2AqvQ;{H4SsCa=;V1B{J3xT`^x9c@MupFH7Z%C{FV zAWHe-FkWqB|3wg=9I-MRz=Su(0)&i;ry#Wg>FMcr{7gz4=03X>>{N<1^LFewaWf6= zo;gngNX!Gz_{J|sOZ(()Zay@pGfYnRN4&sIA^)Wvb{+cy3$Wn-2b~R6!YUvF{&cEY zcD8!v7zW;<`iA)Xq<}IjXrX%#Zs^rcEKH+eE9M>^Kf?ET>|>^%W>hZQAk)v{43S4! zKO?Q#+%&9jn7Q6?E;meGUed>~!K>#t<||I>L1oL|cjex=TyGh4$9I0fGG2k>27~lE z!F_Jfc{zS0hOi%;5Sw=P%bkdH>p+#P5vZ_@YW%#V38Cg<(XL>q!-B=K3Gd)~^(% zrF^OX*xe+4oeMNo8yfe0!081$XBXApE>8ergVADY?Llm;C!25^1FqocjzgcS5mWmM zlyajG_Mzqk|2#mKW*M_zn?SzwDWO0})j@NNHuU$;`UZXzaye`n&D{XbtLqz_yClnW zMgp~P(7|vasO^&)2e^qjyz(b!p-u07=0u=J!RG`aj13I2e-^UD#I-ku)HCNjJ6puw zo+if0!8l@uo8ln4f|f3fFRlcSspoZK*lue12BBb8`Js?#rz-D zk~5lTBEpsyOqnxD8>Ik!$V|H@(@B|`Ye&H)Od;K(V=lgFxwewa{$`x^_u}aw52|ZK<$&g}~(I`ySUFaY-UM+uV zwuZ2e0V5;9Z29rR(!TDnwwI1iUSc7Dcan-#VH1sV$Xxrn3de}`{MvwXqx}UFq!N_ikouOIEMwzTn=27 zTm%LF*Ut0#hRbY@C*SGIzQs>ZaKz%@TwsUq5^ja_+F70xYNtD~fa9BpW+;`T82D-U zj`7P15y7g_hxxz$JJsvhW1%2}_s})JfcL5&$+tju<`bsLjEH+R;|N;q6x>|>-xq&Y zq=-hywsB&)iI~{w(&-qUMZ0M?K{M71Hu<;9a&V|V(*rqGh6bHmErh zXYp*Le(9Mxr-1bM61+7-BB*HO2)=%_Ets>iTBY)_Z;U>7p;XE$e*BhMX^d?Om49}? zh0#{(kJNu+j0$|3JZBEioF0pK&^uPIuN>->(L)J@cd9&eSdj}A110t zk_|5EixGiw_S_U2-W`THL$gkb6SEZJTO=p@xxL~U)ahmDApnO3hFTu{KG=l2@E>x6 z3=vRQ(oxV$R>lUmSr2;Hq3YoHWgsX+nL}<6q9Z55ES1vJi86yAy!^xluhHmg{jhD6zm^HgDy0wm@OveTE*r>FPLTRrkH2Nn6Rhc&C3+nIH)*O;5HP`OhkXTK|)zEhHAY;1%k zdQ(f_T^#U6R~K9FI%}Ui5zNsndSip_ZGbPMm(nDU*Pvm<5acVrZt7Z06S9_ zBpHdf^V~0Yt0^?{opQtShn%N zCFGsPRm}0QL|P2C?|pO=C=A>K2TWp+ycK*?^|bE@69iJr!;;+kE2!Wkmx4T?tMx_$ zS^xIkqP6v312ErD_FJvHDth0A@+8F|F09xr58ZkK-ce6(!#{{V5Dew#NySzeeA;6C z9fz%~5w*3lgP^77h5G>v!<~RqD~H|g2|vQci$^VO?V`mq{Ie|!?a@}-)tC40$D2-{ zS2z)j1-sS`r+qXzxv685Rdi)pG>KsDnXC#66%jL3?clX8@Ck%f{SZ;`AFcQ34|n|%m7FGcLnrpP;Fax#+aaHjo3s0R@=0GvBso^!h$tkY)Ty*% zzgry||9F)yg3^<-o-M*>0B5+ilbn`MB>Vn2pZM0S0x9A-Rkde42wI~|#4{>i_8v+O zeX0c|lotaKS*vV=7`@X{O7qMITpl^Tf69yQV2?-7N7}ckV>b3-4r}`+r(l{=s~v(} zqpkCZE4F2s^S5}=Xi{T0dvXaP8&oW?d;cJ(mU^N3UVO>}a4e}C)`+RqAaX2|W>hg~ zoH8S{{DPY<=`qu`j7luC@?4vg z*Q4pk!q=pym5B+1c|xd?H5a8dx zlYK_B)Uk|o(<;yEg@DtXoDOlz5Due{n2P!I<3Ik(cn*sQ73L#vfG#ZJTsk@DZ|st+ zgj4RnVmoH_PQZUA)GBROYnqR-M^1}?a)**sZUiRIFbD~jvMqkjks5dx!?Xu&{`k70 zKm1q8xq^`-eP!!h z%!=4WkPn&9T`8 z+WLqr6%;8)r(9({YDKyLTofWM>dYv7vj;%c+xyE7#m|uj+I1l?ehWFh3b@eM`9~jY z-YCBtetrJx@OZk^R?OudF#LL8n%6;x0KKQ1`TK<YU7wBDisif_|MTuPho@ScbJksOh;zEu%K!ExQ5fEGAYG|&mudnZa z0cEaU*F2xUXko`08BZfiul!WMTX_QR(XKQoYJaM$`>|CHw?_Z}j+iQ?FHL-{!>wZ< zfXpKWG{q~L1#&E%lRNMOzrLVzctj1m!|9%WTQPw;no#$gbCfwtaczBb|74GoORBw- zt$(ZzpBddXH&le>XlPr>>UpDvu^tU--xMAv5N4Jxu&(AW|C{LK;$H73rH5_KrKQl= za1M8ds$O@z6^HX8E?owZ)A>%~*FD}<+nD6ke2073^_4=rVPCY+hPm1!jA%jlJ&b*5 zmj`rXXH2JOAc-UQ^bzP*s@eBFp^G`L`^TE;JBc`rgf)Znj0y%+8KFkGj_pK^IcZ^s z7n1f-M<5mimm~4k_2C$~EjX2C;RKQa;tk z=6Cv8So2oDbK3U{(YL3=R)=Es@`2;miQ~&e|0`_%DS?d$(jNf7->wu*Sjt{a$+FG7 zO)JuX)!zG;=m{Nm5x_fGj`HOWg$h&rQ57lbyhFk!Tj9odl*kC0 zNI0oTBQW~BCnS{t2Zfhpu#IsPYsH?tqE0pAh1qwk}i{ ziq+Ztt?W8uGfj%0ygt`lLU}j8C4>pdj5m8PW&Q*63Nw?%5hs~WDO#@;FkbHkL-7wn zpEX5gEmwt87_N1V>$@`#`j;?lm^vB*yJdETl@DV4azZm!t#eJENac{KffLlPKN+A5 z{R)3qSY{G8b450w@j14M^-9NjV<&rtm}jWun_#ya)e4Z`>HGMvbv7Rx`2x+r75)f{Y;)a!p8!w_m{XVH{0 zs^Qgo2fPD#w(N8$$-_`dYY6tUiZQl7jFPk}{s2%_LRhP$eIz+>9JZOEmyZlHt^-ckWJu3n3C*a_mO0b+xV?qG$_$+e^?um~ zDP;{~#00Dplv0Z4Z{-b4Or9Y~KOPaY1JD`B5B=m7q})OXi{P+fO{2>ir1V#1oj)LF zT|58EMDt|*WuBRP*noZ~?JJ$x=w$W0B6hdGGt|b40OO~m3BVo2Wd&xxSX8A~Y{sm- zfUfj>9i1sxvHT2|np7|v_Tpt4^d$>Z2)Hx;8qJ|~T*~g)r5`Y_<2~JmC0p0~in$Tw z;aBesJ@M)ndop&;$d;DW-}uGr^fw6>@ar7EhZda8G{lhGCs>)2B;H+;Ox|DkO-@-x zydrU*L|}&fX37>Ta6fLP9^U;qHwgNC&(MC<_lG@i*hXYWMAKso!(`7if3BQnV zZi{)z{qsSD5{vfD;Vy@P!ywM3kT+H2?-;q@5se(;qBIq>w*o+j%5g0?|c9o@^pJIjZeqAi%EzF|HX- z^GM6Ok9h-vCh__kx!6FA|GrbwHf|-Gn)d@6B(_n@mPkg2??J5q{@vQPul}}Y$WX0` zzGU|Xeb%E=g5}p~;=(VsJ;H`|E=$(+(nW1cbMwPJwjdO+S`JZhdIpBWcfsCkw8J~b zX6u4^ub`W>0`R!UyAaNci?K+XM{F-FAPA(*C;DGepm=(hoZtIjM`w2c?}T4`WBTe$ z&!DH_Cs3}q=dGTiGpuxCA5FyODOu0_yRA^S(>p`;snnUZRb-`;`|VWZnLeUduzN6k z3sLb#rEO?HrW&C;J>R9rKf&584emt^*Gv7N>v#Yc(&-NUJb*C7II{iDZOWoq-|P_> zQF{CGPw6{4yk0BkYVLKro+cm=GGoWI`X7spM^)0kQu#~!6SZKssPic!ClRQis8`Tn zR_?)u`z26w;uTve9>e-B#W*gGYs3ii7f+`pYF|k{04HyJAd*Bl~k%qQRaduIVf16LZUJQlzIz2|$>XK~R^bUQ2bEfoOx zdKZ7>J)O-vloI-w&nPbyxZAQ(s94-z)-;fyi&IZN97|ZVX{F8)LX=5vXzz|;31>z? zHfz6sg@c`@qM?j;J_IeE2dfVsXVt3(&10;?F{Ua|wfja;;WoQM@VS~zvVl#;XTb~R z=#cEjSS_Za5A8&-G_6@5&LW}p`caimqxSNI4ti{A>fF!yV11qk%Vo_s1V{+(^Wq_vmiCeI;<`6}i==eFSynB;{4Py)T-K1otItxdZpc&htJRd&(}G z%2EA(FiaF9!)ctXq+MOR@IW|;ENhcmKTt1b2_DoU9l1#J>LlIg4>V)w+kJqfxm8lw zF6B%u{h0bU(nwQG7v-sXUi@a#>V`7 zUL~;!;{vOgAYXIlXGEf7-wgMu?5}YwZZ)GCn(vO_GrvD>T~hoTCQLi#RNJON0%3!t z#+sFZdEm>7&nNGWK4CrQhIMANl(Ou4d2073l@oWWawxAEg-%hyL)OV68HKyQ+HEPN zGN?lT$lV(Yqub2llde@&=8>r==E4(SD6QyJM*BmT&`mid38O{k$j9!}rq?}kg>HIU zJyf@s5OQ6XC}Awd=~hN`WW0->1tnQ4P3MG_4?}v%a)l6~=A^K<19h}iDLD<%4D=mD z60Z~5ywx6#>0f;m5t@#u#Ic%bA9x#u;lHy+tbf8#o90Dd5bqxholiiUtb~^&#yL#{ zM<|?m99uG+tYLC^G$e6mOEgxgKSykTPqEtZ1GlPyEbubs3WTiMppUUw&gAav-uT6| zK61FZanr2sY?i)U!mS`UYl&+RixaHdll?mQq8#a+;^q?aiq|}9DJN5O+&Mb9n&tNV zMBjP=9UR859tiosL(f=vU^{xk@I6F2;p!(dG@$(4Bx1X$JA@M3u>N&J4;Fck;cc4W z&0o@%hB|?7##6rnz-hJ3v}Z8O|NEiNH=<0z>ZX3->uDExvnzEi)%5AL(o= zR}&yvev?pvD(ni8yH{zu$t9CHv2)lVk@K+Tm~7!LBNqVyyheI)nmIm$0$wpFAX|N6 zsDA@F`2p<8?7x(MEmGp*Ot*S{BmVvk@>Vsni)II7s+_la`sd-xRLk31TwHvhUG={K zH?o6w!8}FaDk*>%V_t`_GCZ(Hr=hJyv{xgrI1^)xh3`{;r~ealRg!DXB%_L}1MSI*nwQY7;&AUEVuJ|0lsf zh34D{3<+tj94e`>o6^CF>y}ZZpflb*ezQBWUO)o@1Ds9O$akgiULqJit_SDP2+III zZ@2H#VyrZckBT(gZ`APpqQ#Xb9_Isy@BQ6x=wt_~!VhZeF_B_O_K3&p1z*%fOekyn{_c7USV=MuC!dHSy(v8TXAPW{ z{LV6#Q_017b;x~s*B;m?Fcs=0Xw}eCm}f?)9l_ZSbN8EG3t~|vF&wio zOQofhB+3JtE44n86{u~Q?F3|LER|(jS=*Leol>41GLEyB6Hso!SOonFi;jmJzT+C$ z1e}R)bfaa3HE`}o&xjdy2DGy!s*kpj&X54R@H_-+O8@eSL={$(#5kPJ)THUN_jGTq z#CN2Sa+G*c*e$lnLL?~**R~Vghd~FLI+7$&lRSaMRSjFZOA7yM`5S?XlCL*n>J$bg z_ITGi|M>LX;jZ8%N^X9QK@KoXe3(Th^i%v0J7EVGFid4&91?Es;C5BeltB?A#;q-4 zq8LeYMVfKvlu2+lF_R~20z?Z=GryCyo0=Zr9gvv+4p}8olh&H=s~dTSBZG*&+*tGn z>v>>ia$|0ms2`;xPK_D3GVywE0dshgH~$-Hbc;-BN9^5^q*txM17A`s6G?FXw!!n-#PivSFBS+H_2*+2@+> z+TSJdevKodY%o^X(=SOPf&BfxO9`A$kk&5RSGH5NYcDsG@hXD^s z$+dATTp-5(HWwM8oJpi#Wf;pfi&9$>~>l>M8^=_LxJGD#LF! z|BXB(AFLDy2edXFuL{NDncVW1J6fGNYfp*+yB*g^vAT%vf?Pf)iFL)t)rD4p8Tkr?a=KyEQLOsnX$ z<c{6uL{&f{isLIj5&a@n^U&BoqBawLCFkvY)|Yqa#>Gkc1lr#-L}KI84uO z2v`H+;OdfN>MRcc*4ad=*UEqSAe|Ot{J_Yk-!;|Krm^&HGNVB8S{N$9f3_eo#cTt? zZ}!t!F@lYw^5;M6ZCN6{ptm5gkS;=c43Hr~T_8(OFKU}UCkX)~G-F8_T;OUjCr2D* zzYLO8snB4Lv~agEsFjCPC;9bos~!YnJ5DU>6SK=i0`hB!abfW5BBjv)rVb;m2;X&< z*1p#cF2yt&BV+VPTU3L5T4As!la0>gz;2R1hvjdDd<<@i->9CJ38)%|BrKr;5P>&h zx9tsFf==zTQsGf0itZ&sb0o`Brw>x34^e<&CT3$CPP=Y?5yePLvG+ptHjKG+47;?* zQ&};J8^Oc)ovAIhW)w7?AY{>mS)bznx{q=TWeOp?i5WVeuGcS2jN#Ri(MGhVMj{{i zysC(~u-kWOd4N$DR#+`~8~Jv^DWxf@gN`dG9AMM^pe60d|BCsCAV8OggB z6mKI6bkL$ZjeJFrNBSfX_l2#>aP}dvq|$OmJ|hxanktnvrI*w)>y3kB-|(fD;lb~e z$vp0USlmQN#?xLf>fI^&AsKo_$x5x}bn#eGZHo~H)wDTqNi%$pc3;bNH&gJd)_wt5 zsC?YSg{px)2`1IaZ8%fSv!1mb@-ff%5;L2w7ctvf)b|ulhg_Q8fi=hqe1!`K<#zoZ z_sjVaGm|gg-ZAMEa%DoIx@815q2<)rCfFM-cio>B@ zGwV%-MrdcZRE0cOpf#8`kZ|3Bq^IHs-AaI<%IooRsGz*AYr;fYL|K3P(9;Y-OE%gI zGE^0%i)Z|IyU*Ah2j0^mc?toa>+gDmhKFsv5mEG<{JEjbSm@Uq?^_#v z5>vMLB6_AO^=3);`=V3u`hTchE_Xl>L^Sb{r^Cx#uh6)4cWjsp;3tr0I zO^WV7>}4Bt&TL>ebLb6_I8?##Cs|g212qP2G&=$0;!6=QFU~S|e?#0sEPMa(KM54x z6XBP#+a9C&xf0Umi^5MMGqSH2JRt~$!21EJ+9sSDMXKtO=;3*ba5{;nYl=D%>(nA) z(}gigk|ydcRgV~^YM_gxnR$W^B~#E5InOzU-i3i}SU6leS zhd$lxw_LJS>Ku?g$&!hR$u#B+!q+I_@Iy^)&7JLHG6`(#z_-MTafb4h)-K!Uu<|Oq z(?J=dkutNcGF?dm`QC115@OCMU%(33XWA;Axyv z2t3}PL!NplgSIA(zvdL*oQ(1{a@i`cd{sQEVi(&t@lxw+=dz+shQxV=!A4?x;OVfZ z#(zb1@%~4`G9A%tWbP2okYD}*O6Wie`d`A5UI>xUjzIX6LNjnRa5^at+b-?7DZR!xkhIwB>j zia4s)ciTsOWKiiD>go;Y^3Pd&-FjMid3ljop%i1Z4*-E_0TGG*=i%(wKVtFwb^Dy| z!ft5nO^`BGUh%c2N2vI7mPJ-;BZQ~^%O>VT*HP_b zqT8?Gj<@|n4ny{E=R0Vzgh4UamP8}Hag%R6Esd4sHS*balzX9tIGUgT=D57&dX<=t z0;w<6IrY@RVaM3^0zi)4mwG`wshql8zTDJdyK8dejY2WEV|a2B&KQT`dT96n zUXE}qp5Sn;(R9`=787^^>Hk+q!^4K3(BXQ6#1+xr!O=VPX%eHt&8X(Tw68gr=P~Rt z6M-y9atp?}!g56N_r+is@H=? zt3k&g3JlJfod|sVVOAd#Dcd=T1cf5;um1ynYZ5Oij98hPh6Dlj>z?V>AP`Zdnj|9w zr55Xa4a&tGldUI&Af9+Fc#xj<9Vs3|E=XSW;gbRGM|0MgUSEdG1ReJ=%|e1us98J+ zDUCBs3rs^Rl=qUb?1&muD^J9ftDZr=N;JMX!hQajy< zy=Go=L!@9|!Hs3ZXfsMh#4Y!4d5CmtN&Gg5^~=oULAKEKS}4J6Lt-d~fl#QQP)6=# z>lM=*R{G$f`Xh@2ovaT3l)Hz-Q-p^SO+#lg^Fv#@q@Wlo2cj19V}*4CdBQ^M-U~*j z#9g|uAn^Diuoa(t_497Met{u6l{AKB5tT8HMO)O4&B9`aynvMrmMwz?m4^ivKuk6d z*{Oyh%}Ozz_NVvgut|$@J=B=jBsUI-I?~S@yOe{vG!NYX7+hoR(h6^?&v)Lc&*$_~ za(Y$;maT2k&OBKPFh7S?JAy0t!MwdD9=*}9SpX)A`!4)vjf4bbOY>^8#|gleCKG0j zRKUAQE`d5X(}H-#$WdW9uPW-7raE2V>l2oY?V;d^8MZamcmw3X`cQAs>7ho#fE^fs zMl}LveS|im6Y+=X1!>fEmm7}`P}M?8Q6TV}6FR(WKGjp9qKX3NUc{K1enozI&;Qq925~~qD`bpNW zQ~qeA~0;O@Tv6WDpZT(wF`=|DL~h{nf<7y=7SEix4YluNbbrSK#ubvY(M zxz9N68a=#U@Q;fI+?_f)m(36HMDcxMJ-74W_umWFe;lmVMCIN(e&OA0dn#8b4v;`J zu%^u#*?SYczcN|%Sm7sPA6sTJKg_+|ZYCUN2J|cC-=K!w86!P|ltDaZAFOo^M?v$i z1>+J8bA;{=@f2TDjtjBrKSP*zv|&*O!JV=CR8`sMZ~FRxp#FEH&#N)G>c zdzKWghES*I4e~yDDdVZ4Pr^>aRA+5-4MXk1?{=g|Kbon@Ieu&$)5aCSR)mMNO`F!+ zzGwTRQQoHkthYx^Vd>Bc8pQ(APM>Uhzj0Slwh9u;BP&8ZEfFmd``m`6?g-Kmv_!|6 zq&(hVA^C>h`~%(o7m0c%%Kj_;nEVK??y>mM9YRdpSu35mVBu z6>s5tC}yl|OeG!`PRiJ%rjjh!_1_Gi^fp7ah^5*%n^jxUJmW>HV1z5~%!9K9^cH>* zBk?1YCd19>3V|qDw_Kftfn^?9fqoF*V&&276ouG{tkv@`#Va5FH$zYNeh;}vS zIO6`%i0RmDU|2%(!yIo_1PyzshqnTc>Ws?YBV}9YTu=yJRod@t5oyCMgtJQKwltzX zIKu!QuIxo??Vu2^rNP|ZyKu--me+T|WAcbY&0xqov**MKBc@ zZN(+pFM6V4jbFsVzf^(PDrhyh9?d$?PmoZ{lZ-_50UtV(mw{8=#^OU^bzd)}C?sr7sB$+xW zRv4C2V3_9&3N~5Il*)n>Z468ZYZ+Jk{KOzZ&BbfGMFodvmDO)Nne zpD(PRt9ZM>#o~t0K!rJ`YfI2II`0Y12BN;-BV4Xtuh9LBW9Dk)rQieJk^dzY(X}9N z2QSNZUjgjHBp3w+0i*SAD6>Lj8|H#mZV-13Iy53$wTcF_XRrW4)75fgkRFd>g>+^B zv(eWk^7u(krRl}^BgfJN`Yop6sS{F-JI*22b0gDr47buwfcN)#t{6ch>5|Tr9jCD? zfU*roQv7A`|9Sz?!XZ^@k$mmZMEBnJ-h;ga%?XvpV^Bw@Q5Tf!-7A-KmM-El7y&?4 zU!7m+w-U>L*yjH|v%kn?)^;{e3WWRks0dJVEhb|PJ`*WymX2m;kB-k&``rG*(#K&;z>SK#qW0f!0$?kSc#7;U2yqu zobLx13_4$7y>;)a9Rm}b$k#jOD>?yke#VVUNdSnO8G*rFfAN45_CtWB_1A?X3?4qX^KE@4)`&tbG%90Ih!BFpKC8CeKyJBB)@jbNU(wzuOD}{ny_^@2mbf#LkP5| z4d3^M<3#*_K3)q@zs`^={cpC(3M@!4e=kdV5e`19v_i4|CV8CyE!Eo)rQ@B(-g+c? zct$ylK73-Yhr)O+k}(kIvXI?udViE5y)GHCD>cq33L#8WO+!(jjI5&(+I5CA3ZA>7 zY@42DsG9y*+gD6YZ>?igI|#tY_k6gcMG0jc25=R%|5$N2ZRZyEoBF)2YzYakCLpiPjS(RLY##$MH+rJlk z^`%f9@Kq}m2nCz37$wY_7ncP;#dP_^MHUZElAMIIQ!=RaNMk{Z6PNNyRycB3#4Kp6 z2zR6(GBp6cfG(D7ma_B?v!y+Dl@AixWXmj)At2(iH{1$eXe(wpn_Ecyq21V^@Pk4b zZi=w21JWV>-thAP&;o5s<&;8V;)!ml+1Lst699GPEp8l?dd?y;p;&&@|H1JZK_ntr z=vgaVU}M6ROZ+qA);ml{``o4L%MDCr--U2mkc4J*sfY0Kx&GjD_r_G{Rp9y_^W^!u zWF~j;`f#M=a=V<|>DL)_O5xZy z^!P;sPMJ_4lrjRefKJLg_d>MQ|5Ww=_vE8vjZyz#n+~7;;8E;2MSC(SGtErsOx8Pm zxMi2CCHyOiUe>46hYFUOtaX7h@>N_a))zUVNrIBENhx;uouVp!(-*g^ZQf4g5{Tkz zzjpc+w#wYMw|Z(&#v#qEsdxHttYpO^nv4?gK+|R*b_CViiny4$Pi^dRK%YYN4S8zY z(Bht9=bH0HZ@%_#j;B$wdb_X=Ql2uhjPU$}XGs;A1X32ZCXBybNnS3Ij?QcM8_B&k z>idjHX2%yfYZiAM>3MSur(b8t9ZuusMs+hMBzU6TrZTJ8(;p0~JRnAwD)7%}XXL6u zpzs^=cj$WeFR}WE0tu753nT4qUbO(L$;(Sz+QT8*M@)Jq}4m2 ziB=Fr(O9RFNm;2y3_zB$FgT>N5nF*KH*Hx*Rk~)Cw4Db_PH$RTUbGO*4|lJcX}3a( zPP8bsZ?dKAl&lhFSY#nV4bB>K5Z$T@nHKiYPjb43pRx-0OO?f{<$Qyo-32CQxg!}O zS)rb(-t%d#{waR4#xWJiZs!JZ9%};tvQq5SF(v_e=2=rHP7B@Xthew#!Bj4y*05Kx z)HmpO3B*sgZ{{0HrD9_m)R zbDI+_Bk4zuaWlb;8KNdKH&eGP%qXc^aa~gqGh?TZ$tlep*i5)A>r~OuSn0EZ#ARGa znBU*M8mbM&bgxj$UsH8cHgm1>cwPirrJbNaC@_+C4lsVPK+aEwB z&3*fi=9gSjo{*A_s%lE&Cc=dsjY0LT@Rq*{+IC;hN$wDw?&M@DjhnIobUg3wwOYA_ zcJ!c0oa7lH^I(U*S$9~ZzjzPi9gZ8~2iAB!_p@qxYf&8MbVWmZOpR?N(>{o$sk{eb zmF5&Lz(17wxD|M}>K8c$o8<39bF|#}i~NC3tfd5+g>}n=40?Y(Zxf;Qyh81}#F%%= z51>)mlEhWK1WT*RznN{Ji*Id zeT5zyYTdU|OhJ7bwgeTbjdgn^f4GFW zF_i)SKepa6IPx~?`kl!HolI=ow%M_5%_I}sPA0Z(+jcUsZQHh!)AxJo{qUUgT;Eci z>U4Fb_J8knt-XG4x&Q-}o%lZxu52px{wamSy@YFLEibs~)^kb9y>4<@948gdH(ei) zUrlp|;$6W`MkvQhCW&*WQ>B?Y!1ea%uXuud20cy{*%GFM7DcJNc~DrQ1AK-PCDn`; z{_CxQOwZ#Zdj1W2q&^jZ0K@30T) zT$%z#Cd|PLXmRWIjZQ(4A zrAHN8?S3uZ;XC8@9w(fqYt^&7O#xTZ%bQ}a_?zj~AgSd$dbn;>UQPJwxOiDmfM8Qv z$dbNjhjUhMHsi)8;@4}2_w>$at2&lPu%sIL)aMy(+AJ?A?B_9&e^I_7=pUwREDqe(6w4J(gU{xMQCKcE#faTnDCl# zuZNEz5!hTdDFNxWIB=w#M&XqRNA8|fTty2a96XWA&w=6=up?v{kbx}N^vfzh3k(T& zK8BylY=SFz;-@8YpQ{2tqS&-)B5Y6DUn=aXTSj6yBt$D$Ght&+K{0jpYO` z;?WBKmJ|lhu#wsmDVHc!pzP8V!W`k=5%*{)M@5rJ1;7t+rZY;3hr4&?D=#^%dY{!Y zQ3eolaQzn#rEEYK@{ljh1sy}U9;0PkS{$UM7G}jC76e;*5+Whq&`EAp9SUQC$dt?t zyueEjJj2elKf!qo!8^h-)9(`_u_WHTSYxp|(lAsiYgu*={qlAT(cBunb-reYD1uus z)dkgs$TA?BBvUuMhzqMN3&JfqGlFf``v*9`Ud><0W~LW1kq>2ns!+sWi)%o9`t&^_ zv0rq%{7=Pksti%fN?%jrPVPk(&ZU8Ub)jboB*K89$|vok;N?4*+F z2dBlq6ylSnmHw~MqDUU^=47zVv4>{N}sDIhDMUt z6G)yuX-kAn|8*wqFYG({jG#Mt!Xx9@DWACKf#l&zQDg<3+@HR52~pdlDJ>}R_iqIb z=*=4xvT#I1b*0zl?c-u#)NIDod{GN5?;|IbTC!#G*(UdU1bg)U-L;~ZtfhA$x_H_M z(4ZUgZ)eyMS-jB~k1;l+&w28cAXP-sOiX1G|G+{KBGLe9v=5fUA*b^NVJ_qE9)9Ytm`=|-@HQ9f{Gy;%ZSHd zC(%T^$UvuiJYiQ$^8b5Ah_>JOl_ROLwA~?#aRpA_6J&5Q_%i~*i*eolwAMWE$No&o z*8g|c@qq)t6l4D};2LT5i)Eg#n4PRo=R%o|QN#q%wO8y}oouHmv2o{7;o$29b-#Ny#^4;NPR2iHZ0^ zuD*37$>?@EdF^`9tgfg8tAsD;fHdGaS&f9-Q0=<5C9AO#0{1a7B%e+_TqL_E<-*R9zzou8!Ns`&3rBZ|!)&OV?~RGE6~ z)y;j}rf{eQS~alGCdXP56&b*sJ|pWKD(gA5#QnV%{g2Wd0@|#vNKSxgD3elwt3k*R z`HTee14OJZK$ehIi5hGNDU>)2%%bW^jkG{^GGsV z@FPz(9t|uFF)$#hHG>z&keq-$5=k?N6|xRCeIVj4AU1TwDmH_ikttPj#8QlwHq^0T zmPsuJCRjB}2HW0>(YHq<*bZOqFWRp^u|<#J8c#2bm=+Q`y=ol;i>~phrjWK87R$0c z{V$lo`FSMhWj`$kcu2`#+z{SKVu8DoHuel9c6D}sg{R1OiJInm7oYK%1juK!wV@|P zx}<&zf%B>;`Y+L-8-+>cVMxq$49QF(6nXxR2DSM{j3?Maa07;id7da#G)rfQ;_~AI zhnlHDg$_YKeRaz%hh9lf;JKRphH>KG?Mc=@@>Ndl8usXIQtN& zLHyb>Nwfl{kjum%lKTH0`0rF?zY*;%KPfjVhM;(om+f@LA`pz; zt-J@CtV9};4h?; z38yrcb&TAesI9q8o={X51-9}&#Ij9kgc0)tNh7?p1Zhr?RC3X|g5dfFLsNKfN{W!K zP9Uq>V}#(R*vU-H;{-Q#PU%juSE^wr9Kw%E*A{Vp3W>)~En@O<`ByDoYkzmZpt&zH z2r)1P1fUKtGmiqR7L(l^PGC<5A<(NjM@A1^Of4(oE-ek_tXc{uCI6rYd95$PMV!TX zdxR)sKb=#!QK-K!6y>LLy>2*Vt-20{l63@lafY+nbbguLRS})^`D%137n!(g=g_<8B<~1ROz7s~XU=~z{7M1-|G0pL z(9HfeLh@0O46NU=E8llJ658ND%k@UVd0@Xs8v*@PzYjzlBrT%3p$GZmu?oW%QqoH7p} zu)=&f%4HeTW*SE8%^(@o{&p)4RH4qc4X%*w@Z;Ox_c%T=S9q3Ay))IO3-B5gm3E|~ z15d#mW?<`Q#3_XE*#F!4h+PdBHwJ*x*>lTy7t3Zl-IexWrAmZXp7bURv(`dYsI8GU z(3F~NwXUQ;)uMBeiGsMQ9P(3ujnssl?Tg7{_ByZRUBk8lNzXV_X3F5ln@T=AazGgA5`5$oWW(3D4de=LrVuhLpPPbLr z#jc10f#o5o*PKp1ms!<{awr4*_0#W=Wz2AW9>Xw&LWDbdGgTcNaU<6{f1uH_YV z+}la*6pUgCcAkzaV!dP3EAhPxnvR z=vJbo-eRgkO}^Z977z^MnxA)=P75RivSSbDnqX|*g;hF z*m`zg{btUa(Yg`_%_A`rpcFqV$xV>j;=FAq7q?@Io4FobKAYUgfBzFB>O#g8Z`e8h9>v?xxU(7^q=Bvx zk|;|0yAybYdZqb=#FCH|Rb7Lxi*JrWI1y;1QZcS!%kc$TvF4$w>qZ#|w=12?q0O2E zl@4`w$olT4rDm@KI)4}xrJ$pOmU5CGNAC0)?PO8e`o|W?`hQo80_xUU~Dnhe{1+*~2RQp$U-^B%vPTM{CPlq6> zgU_;I0hl8gtoc?z;o7`8%lsKZww}6@lG1Is9M|1{ea`ozfoC?Silx7VYXVa4>DQg zW3{+)4gpo}s5H(L8BN&!NX_{GhqX73Lbt;9E@uogY$`_Onj zet6u&;L*oEaL-3Ka3)8^V(9I!xcCg-oM8a|h~+w(;$nG(T4?QaQrO@`BC4v?hgOO3 zVz_%ML%Tyx>W#WFuN9UGs+13xq7#SVzdqv_J})+R4QzdG+qj)oHoJbd9<8je@2{9- z8JU+wCTzRG7}DBhZn`-%yDM1G(vSUO6};ze(fUFCK-_bp zrV~Xn;HdA{F1wMM31-2`ZH5yhBxs!Kg^gVLXpgOb%H_ zSSvi?fKzwagq{e+0C#D!otMd3uv*7X3i%*c{-&u9sq?>*m=E9|v|#JSONe5cOe@7} z{}5GJ_ZBVL=}{WQC+oURfmvgc7n=$C${)%ct%A9Vh|kf#|(3+ExZ}rKBO6(6pW*acn~PL zyFjT%QBlXrlw0pF(l2lgDsnR?Fq%v9%0y389?4*wd^oX}5QSjVot=VqIyXiI{;@`~ zLF4hpp3^D21_-}hEdiVfM*UQiT;?gq2pRp1HDy`@UO5Esm+G zxY<{fTg^1KVku#|Y=G%se|4Qi>CTW(v@sMGuI^1WS0&r#?cFkt3Hu98>xfMemGgFYWRib*0c3>6 zQkTSrzH;Dku*2VC{s3Zow8C_@M9S96Z7$@X?l#}{33Pfp9^emWja(n&kClr4bNb%I)@)^dHNTUQn z4)7wkkWD<@=oUQTcOZf_sJZZF+}MG3g^K5hqIguOM@Uy*uLo@+44W-Nsp;gh`QK%0)8E^@BulcU zwe@`Agp((MulYd~7DzZ1->gEqp_lwZY3BxSM`UA@G5UYK0EU1<#D5Q?NNPuFoc4P# zw^DMO)x;bwiZ8arqo&~eb+sWSYBl8+q}5*uj@QV$FEDEAwZbW@-pO26Gj|}hn;1vM z?i00y=b)&wKbmyJH@z_>Fr+XQMm+^a{o65Qd&GuQSw4E1`Tzu#nH3I=JFU5_6Yn3l z54=emT_Z7szu1Ac$>?Y)-$dDqEK*pJknl_JawxFClql_M%dX095E27)N5#< zdw}g{KIBZI&8EqsU^@Qhr7r8Fb}C`N#Eh;Nw(Ro7sUj8=E^tB4Yt56pM-N~Lp%seo zz}$(=k4gPrh_BIcUl5EAqYoi!RS+sE1B=p=TVmzuD1a%dT3l3SvCmAx&h%rAq7m9K zzjkt4vRi`3Lk6sGvxOKBsSR-t7Cl^qC;&udGiE_XG0faZuEIaCYa@7!qCoZ2HD(D~ z`K!ne9>&cdN?OlVD`~5dkbs%|14>?3T2_kVf_ZXi|M7FKfVZ^N!wHBdS7!LTn%}t^ z*i-`Z!4+58nr*3auDb7!sb)RwzR)o#w*Bbv!-BEqt)9E4y6BvW-+be+y z9%fx|@{UV7-CYi94nQnL>)FCn)lzrWj0Mbb&}9@&cHt@U+RfyYs*ZAe+g_P^E*h(5 z6@9&uK(D>iOBA+Du&^}38Ev1XL=L{JQ@w+AcNKRdRc&Z20EnhIvj7!mMgY!J>N#mC zWsc08K6hQ#@Loy`ar^zUeDWex0GeEOcn+2epJ7x&Kp?a)omwrV1*h; zz3q<}Opyz2E{eX*Y#CiF+T%#v2~GPm8hlK@G+35p-1_Kf=MCLs=@>SgzWUW+hm{(- zB3l)kf~3mk&ydz4)qlN?wW}EX3MJ5IhAECda}u+;OuV^XxNATfx4v)^!fuDigkz&n z7)_k+I*%L-3#1`plUXA8`aOJas4LP8 z@e^GDfp2sA;xqZ=kn@)cbG zxTvAV16L4P6ci5Q{#}bmLnMn!)p7l6Dl~@*G`x4~aYbO_nNm(kfq_Q%Lj_;|r!>?l z=uP}D!wOa<+k$zb;RKqqJI{UH&Q7SsU*)I{^Op5aDaJ=Lc2Hh;;|~UAbf;7p3p`1K zSS9|ZK%(Y$>CZ`zKR!3=`wTt=;=R)Ho@rNnU#eZ#^)~qxzpbo88M?34X$veQV)sI9 zKUsTNvIU#43mD!5UZWWpIdmxUWsRJ}iZTs$4!RGNE+{(q>W4!oQITj$UaNftoR(@) z!SwBLXIY2t=1H-3oD)>Qg#>Yf{}>{8kmcS;MK3;B@wT-Da<_)xl!0k#i)8SHo;}zl zR|%qnFpsDqh=`mV2J+{&*5Eie!!*enB`PUtS;FR_Ul#I;ZuZbY!q=?kMi59FG^P97 z0HPFYc@`d)aHTl0{GQ%kFkc^*6^T)xUc6F#KU|zj?mM>>l1^RlIX#}|p?te9Kz?@!bKmr`L_1I!1ceEu@_z>)85^1+nF>*;n;Nocto+3H!gOpmDkfZZ_WVI_iN1>0r@CJlVl zFd;I;@!((YFegDh*CsL3$dAa0RDtA==w z$JN4A^2854B7#&W z(SHUL?BwkMmg70p^4nEku!A_Z4M7S>xc8symV0^B28L+uwW8~3;-X02If|q0NAKz? z|^=D&!2JhUqSmVec3sTRR?s_6#Q1vHlZCiNuK!mP@Jln|< zw&&AJwY}2~=GOD&*I4VB4NE0^jodB(vCWU)9qg;0YW~L1HQO6rv(&acknG6#Cd&i; z?tp<9+vz;g>0FxOcT-c%*KztV#bllwzBv6j$hsp&&k+0mq90fJdH!f9`d6SCctO(* zAy3D+kY!BHE3~1{x$NQibCJ7l95D#HlE6mwa`W?UeaCI!3h?B>FnX7HS-lUW5T-(=_c!<$jcih2e!W^K+s? zk0!h~^Qc)~%jv40IG=>9=fN59OVl9L)gk6`&)7VnfQIrq75Icc{WzPyLz3R|-@fNv z5Djr|QlK_Ee!5vgyLnJ$<_K)IhvZ^$STa-~t=7Elh^cy419Nv2Swsf*v(Pw43^XjFuIiyJ1#i2EGkHM6t(DiY}L{ZD`a2zYk`_*hRgI~DN-Gf?;s8Etu z04#Ud0Ybx1a7$F{heh}RzX{wu_w?2FsccE}zwY|WsTIt0y?&?a+$N#L!`v<<35(_; zWzL_*brXsNWwIibzVk3_D=u+|reqX#8z0$yV7^KCu`#Ugtd1ii#? z$`4yQ=h(fB=HoR0Y*3b923J5!QiLokRtw?XFd8Oywt%B&QU?i2V!R!K2CbU?fBkOb z3!kdSy=F-k(j4&^6wa$zf0u8yWrFAKXFq?0XFY|Z4zQITaHPT%r@)zLl#H|BOk7I0 zJh|%*lrys5c*E7$6-nH93^Q@zE@B0(#DF%ghd|_5Vx<|w#KnsGescOtCidby8gOdL zOQzdjC!H=ERZjb6(WINbha8BQ6?pl6+|w!RLmu01h$2sjt7O1u2{t&1ij6^N{|ASX zDdJu5T6d(?F@^5tZ!S1e!X*;Da&ux3Hx)K5Z ziT#K$y&kTrN~WHLSE-yyD=B*J{@!hJ0@@S`aAH?)DUD|$7-hrM=ci`Cm}0eS0-xiWGo5jXv$6B-)0_=n55r%M8|&npas#cRWXFFc2_y>~In zbobR>U9QjDQ(wp)hImT^F`e%)pwwl$aT338jV*tPV*iekgVhr`8d;MLNI zdYxbTC#mb(ZF;OBxxcabd+gG7&dJw#pTmAE!d5QnAC9-%kgNkBWOVU!=a5#z6(xb% z5h+ioo9@Z3hT*iF!Ik6dsyhC_X?wZ6gg&jG9$+(c(73BVOIW=&wGp1nOXS?GA#B`( zOsr)TS5`!Hyra)&!#P*?6*Ffd;n^h-O{syq(1`mQ_7(A%sQCjhnGQ&m*@eFdH!gGc zQp%7?&0;l48i4^jxm^@WQdw??Sd&?NW9r?vs$~n*5AGkASBZ$OdViJh_c)>ULN19b zFA6JLd4p*Ky`h+}x1%!YsDT0zW46W^EUrIRaCRP!Z0o}r**uPx4!QbCFddOJ!?bxJ ze?xqC&FaOJj>E2S{wr+3p?Ti%W!RK#%{~liIgtK`o-BT)tDiJ*d)fd+0E~_euDex# zq!q=6Wl|gf{z*!8thkiYtGBDAXh%c2X+rlPVt6;aP&1cgRiNF8S9;|t!z zSD>Kcm{_Kse+ZWfZ368i$Z^69>My`VwNy%aN0>I_$E-&Kec@B!O*l6t04o2~Iz%}x zn8t(N9z2@8Jvl8#llhf}&YJogJJDXf7eV~H$M|w@Roh9lp;JU7J~C1?JS5(t(*b=l zgZLV5odb;z%Egt?7IF$|*;wZz=xDWRgVHt;V+H|xJ6V`e^fW=JdB;SO2a*PVDj=HD zojE~zNejiHyApcv!+<(@Q@9n-BBJ+JRudDvTcFG&J`SOt;}ACAoJ}Qt$#vsL5W~iJ@FaU5xB6&Hr*_DMD z4~|Q6@wtl!V$;MeCLn|N?2sqoS;7u{7AB~aKgsR3<1A|3@)~{&qH*&ir)Js(r=gov zl1$Jlu>tbPP9NA6@1NscrT=@LlNGk8fz-qQd2Ruv;%r$wH?%8}85f!GLpi;oK4;dC#7a(3;uM1=zi#LrG|@gO6K^#tx5ntK>6@90`KHKHePT?P`m=| z!z=5G8_#gh+BIu7c^Fgq{9l^=OI@Qh)@cG*0TGE)@eA;6Z2@va0A&DtBy8H1z7T>k zwr2dE{~jy*lBo+#fb>vIy-V`qBc%wfXckTd9WutYu~!*7B2`cE8o!c6lR>saGKbmw zb8t%JG{A~;tIfhO_gV580^oNv(G%M(1 z(m-)j#wpRqWPELA(bjd+6el2S0x5e>Yxl*6SU=)Khq3!8ufXP~*`PifopzoVGiAnP`1bCimD z6{ko+2-93e7fAiOZWzBIkaPMg`Kp<9htuYQM=h}c2 z0TWB)aWrD4tPUdjlf%V^wjK(<(v;!d*|H}b4V((iu;J0~^`6SEKn>0xJ>pYtck3~v zfry1(1i73k4Pr#3aKXaX6}sa6SVM*4^|>hsYzPhg*04=m6d`E!FDS=XUorO+R^}Jj zGwo{y)jE(I0dTV3UN}}L0k!J@bO7%_ann}u33I_;vBkaCW*e;D4uIdG9a z7ni2xvuH%xy}MJIvwV<2a{#k5x}6i+)gX7Ci@!8O_n1fI-uwPNbXODZ&A`c9d{ad2 zevt&P+Ubmd$ldS9vdhLK5Z2{3tN1|o8tW!5=(ps~4ycFLj* zdpwg8fTx1UQm?4lZ{1P*eHNR;mZvq~aac;c(DS4j6V@R>_<3ss^4z>wNAdf>H#Yn| zdstC}qi38zj7|e!QD;Yzh)ep%9AvWjwS;SL0SS1dI@!Wo)N*%|N+#v@Cg=sX_ryp7 zuKc_1N0JC=NlkNR zVH=j?XP5?A4mRblM>4;s?__{v!q&0y1kRJa^6lD!elOhCi51y4060hj=(-1)Bq#?a z{;-joxj-*sWpq+0VI{MSic=CHNfaQebW+oGho)P0XTu#A^SPT5)jZ67-}BU&k4;PX z&0ny?kpiRjJj!5hK=H*%>u)(sh_fC$`&cd*+u}UDo2F3M;w*8lYAZ%fJWm9&sy}lS z?(wZG>^yD_m8l!mGRset??}oT-wESH3nG^MEmH^4Bf?f^Pnmxvx*6wTB`Dn2^ZQ#$ zT-t-GP?~zD#m80U^K3pA>xqfiE-yJ7l~PG)$lHyE2`J5THDSD9pB@Ta%M>JjmJQKl z{$VF+#!8iCn%ph_8&)MV%hCt6S>+IT?oiKt;wDx1m8t;t8DgCT)}j^>I0#nL zzBUj!7@~#N*wKIbaCZO7N39sBRxVnvInEU^f)zbfLR*LiP79Uv%2)Jlv1gc*JJpcK z2^X4-PCo~H`pR&TV?^IAv4_#9nF)>op`?pH4@plLZio}s5B2DE*&FJj8nNLhW+PxU zXKbEOH01jr7ufF*VDKWC&$!=Fa%YQ4_>saKx!`{3d1j&V-~BWKn;`%lUFQ6$S| z@y|~v(ybT#2(e+5p_{3U0gqeS)4OaT_Oq59z{fZR2wvCf9(jJCUTX(76wPeShUI-Z zH=JnHo81Mp-6>|(_ejO&-^hel&*mBM*ddnA&B^0`&FbceW^GDQHYX!TnB&!hv76X@ z>LZ@y0wtnvtr~bQYZ(e_Ox_pN%K->k;BUmgJZsTTn(;D9g~DZ~mTjmjvA-Y=An%&>s=q;z4H#nt!*n-u8z2 z(tqr@2a~(~j|E;q!#;fu1}mWa;bV_D9@EFe|9NeT1ZPOa`|64$2^}$*v~zZPtm^ z+g^i3$or29S&0c+P4bdOdZgEnU3j#kSdO77kr!8<$@5;=8%RC zp!>H&S3D|Ir)r^z@-00sH^8tYS&^U&sVL7#Z<{i89Pl!_T0(zpMY8FHlm|0;?q0jW zkG<<&arY*xn}EC?Ywd=8?ss~s>1!6TE)k`9nO>uYCX`Y-6T4yC34Lg2?PN{>u>ujB zZt<>ascRrCGseW_7*FdMmJtca6Ck&~qx1y>g7^sBz=au72K>_+BgA=^3bP2rJ%Q&i zle_*&B=f1;6OXS75*v)N21a>7^#Gmvr%ES`dE6vrtcJ^-t2p-`@{HUQ4uGnJb#Sn= zwKS30^M7%__C-!%2dB)w@H6qXsBh7nO8Ukg9TTgzk%p1^1T<9_WJ7MVpkT~eNl<}= zcg0>m6`;_} z3%;F8b0qjm`f;^=%fAepTV%VyRgxj5aX6>fhq_4Qx3OB zUgdyvi)p8BHxWz9r36DA>$BFeSWy+*{RnyZ>I7P%Ejb|5bAKV*1PS^{$;oc7C&eJG zT!KnbYR3)Rf=;OnXxSaClgPC!gUjGT$8di5{`M1pidwP+{BaQSB-(rY`Rm!M>M9D< zwm38_Ev0VMs;on(SV4PT^1krcZ0jhNpYeTwyB`2f<-d?)tM{Ox_5}kgbcy&KV3=6M zZ4Gf2vdH+IG6>$o1$MU_IqU=<8k05K+#^kFEVsS(w&?mBAK-4E`2Xp&`Z?j0R9fYI zUAxTeC=V|po7*unD2Khz8r5Ow8{hkU>i@yPNtyCW+ce2Cbp52|wZl$661nQ^HL3mx zQRbkxx4YnLTIe2fDKdHSxJ#3|x7$r4nWCHIF8CGa{PCdok2!!H#}m_$vRx{yXLKSpQ!9H6qY;akusQ=a|cz9;|n z(7m(fbH@RKfNdXo9W{5~JP5Dw{}Xu27dWi$zRTpfEPQg1=XJUTKgxE!RTz56;hlWL z;(dL)%iqm@|0KA6#j&{-cyIoKyKsIx;>!RvX8)Zx5kSxEIdZn!?p*(pQr+)SLd?DX z9lB`>Y9pTW+s{QP&}v4pnjG?mcw&T79OdmWOM5rsiv&irwWg5FM2L6WNaIE_lXkVj znrq^!cGULZw|2Kg6L-i?ugnFLBhB@$$@6PSefJxN5P#|+4hH2Z7bIemx6kNdVS@Iq z(9&+v$HDYJl0L9FaobFvPH4|FPs%=#IO0kxK17JG6rv=*RemIyhRS$efp%jBDGUR<=B2gk7=$W z=!raVlny66(U@pt^8l+?4zYBLyPAZit$#CgOg(3RGOh4j`6cwD5j@^IER%@)hKxmBQU&b$~1-H zR1!NkBe}yQCFd;CoA>gM=Y$_$Z0DKRc5ZJ=$$az38uuC?I z-oZXHuk%6`s>j*IbKkg{$Jr!aD${2=VqK~@6&*Q_4Tz&@kfclG3qv4nz7ag5GzX)l z;&@|aqhx9(RPxrVSZmnk&`-57)G?DPq-BLt||L9nl89p zc!HQX-QR-$Su(=5?MzfwVxc;&dbljf9pRx)4*ds#zX+t_aHsvI&-l%4$$};~bDJK( zEi$rpmXQe3mIAGsB&~qf6TURU#eV2n^Nw-wlbU|Vo4aZ01r>00-%IK6XQUyft8g!!A^~6={^`#|0K9JYqS)wie5Dm-Ou^e_jdPL)4xnl!Xh@s4%#y z$h=qqy4{|AZDtMPQ9WoQf1}!aUEqFkcQ)a?SitaI{0o-@mzmeiFY|YH_e;9X-Q3SB zrSipRsO~oePPbdqtRo~*G<1yQ;aglXG(}XRtCS;=~Ya1=1hn51CqLx#ab+0a6mmXa$Uo7M3lKH*qyIY(ba&@2ubPABYf3j?2bJ%bDwMx?VpvMPp8ci@=;CvkrKZW{){> z#+=v{hVZic$H%|r1hH?QZv}f^6R9l!+o*$XG*XU}q9rrp6DCW`MM}P*pcu~J3C_$G zpC4^e#;_}M0_Jn7It{;eS~6@3?d$?tOZxw%F1cN-W10+>!@8Lj*kVc1`K&i9P2O8o z0U|*Smmi_++S8i_Sr~RiREJzEuarx3_*JEiRz{;jdAqB3R!>jlzP&mHg3IxAZr@s9 zRLkNH-VkVJmdBSU@RR>I7SQHU+)-1mTzHa_Kp`j{bL;bL=InbKa$6b?qXbIATkO-GNC%itZEgF?9N8p79(|JH?EESJ4A zf5L*x?U|DOYV-9XJ8@=wtTVMZ8U22Za8us>3FGtpGIb{{@O9VhVaM$V`edNL$ss78 z8*=3yF%hj?l~{W6)3mVmj8zPUCQ@#Ji^V6aVt88ne86d)ZE1v(DkjT+2FWgi6ro|i zkRwftcWPkOY;xS^hqhOs9#4>~75+-e_nO8IiLY2?9l+}i4H5*GxZNY;#SYPT!ccK} zFh~oGU*9o#q)BP1J8&AkejWy5{PM(J*a)n5pfDdZwna6!{b4@jEW$0=LLWtv1Y4r{ zPe*DAk=SjbtFt6mX#5?FIKF443r$=qNXo%8hZpGj%6K@hZY%O#`5JMR5Enwp;P7y| z3D|d-a*nls{tw+;C}<~8lzJ!{`4YD`ix>Fp;uFkvC!t8V${R3JgouSvOe1o{XKreY zeH23NV3|S_H>0VOC~Ac*hF&E{(8{ltv>0JFYOzXa!M48(X8#LQ^H@%#p>QZ7vbHIz zQukldP%K*b@uhzj-8QLzL9(6&VN`A#AW`)AR2GzC5x+*bvQ*?3I>cy^H+pWBLcMN1wo90%vLTE z*=U+bnzS)WEiTS|5jJ^N*jSO(L0WBE4(;S`u2X0Y1jZNaHnPCP z=FF6VMSOK|Ge7#)?8JYU5FCN_&=N(Vt2Eh2!^~n0>2K7=E-U*gLT;XQ#h@!ri*99L zfP=!Oj1{>6x;?!3V_muqn`|ycf-)O&7C=tA_eZi_)86{BXtFW6-$@ozZMw}bfi2>+ z50hi%YQl;nK#+?I;OuYq>zt`O2PY>P5B>;HyB<1<`8 zz_X67ulo@48wZ_qd8hK*m*->%8Yv6aI+6jA2c8qQbq1KFSd;2x@mRu`Ki3%tS%Hj@ z@&S%ha`h>b%2y{vGo47)ielS8wRwyb283gv^zI)Wrn)#w4=+IEr zKvTo-hF~43FmE1E(`zowNPSrYFgOL`Wy^sQ9MJ=p#P&<{>qA@N_IMq#!X-PuZBZAo zr5^5N)b#SPrxY{Ne)qLX%2fLG_uP0X9l%_+{+ySBMv-=n?ZZ`mo8#J5KO^*{#3yU@J=RSJ)?1WOJ zWTfqWy=VGNb-z65x0gD-oPFJAe|w&O+iE^NQ)?%um*q?c{fdLn{m}a;!)Gr}mPi|J z^Q$}LHA?ntZ8@^e7A^0~{P!$g+g~fJEsluS&mLQ2@lf#B3nuW+v+_LuZz*jiRFd*j zN%QLS2n|VTVU(SyH0*SWLjl(?!?KatrfacGU5%j74coBz@qG@o_CM*y%u#*NyOPNp@DaSHW<6;fFbMe9tR? zT{i=ksTGVyog#(PC9HwDpM(g&m??iRW$p-(1OstM?yv5z#d}+4Q;MvpWp?K<4X%BQ zY9{^L)av`)ECG4NseBRelW%TA&c}2HeTbc$@>E#|jvr1^I{PFNs zEa{I0b@&`{B-#YRsM;0JxZNfL(UO5QZZ(Eq_oQM|Bmu#(lQH0t0NXvPF6?;e0GK6n-0TmSf_1S1!=MKVa_k2 zymlY{?$qv7NIf{bX9C~Bd}N$(u18&_Q520b$aL{udp!` zY^9QAT2Z`Bsd2^?139HbY}9tCD`G$Vt)$41;Nu2NV=K}^>Ss3?#?qQ|j8gc2 znEI-qI0L0w0)Y@9xVyUqcPF^JyZfTSA-KD{yR*0jcXxMpckbq#^H<#$9)R82+OMjo zr@LonZw*&J)s8mi(IGjsx;9h;4x{80yEbyTMS`r1WPMdJa*b<458zRT6Gc;fJx!ZPhJ0| z4e%`i19A7T76J#w&jzhvjHG?NFEYRHg;w^3K48cYY3T+I&>>2~?7QnxpqQ+9K`Vj1 zVojN{NWY%mq|kn8aJR>@{^}C{e)Q-#xPz;N2?fPga~qZURnQkP@4d+xPx~C7_#Ape zC1&hbQeETOgoH~GBzahF8_s8xO^UQY5#xaUKCVB7X{hUi!silvUXQBCFZqub)cH^t zvcluqq^f7G(p-ZKKm5Hb!q|i{HQ@o+-n%S5xzEz%lvQ5QcSHZ4(fYM|BN|s1XQcBL zVOc5|-i`vkD~^lKj$uY*3#ZQTtylgSWk+{>Vm#0qs74~A{rrp+4|F3VOQm`a5+!4t z+k)4o9o`#4&_oZ`%K?$%ENqH9o?dW?cG@k3$5We5^vsad1)fhi%oE|v+)tpndIX0fGXxv8#?83M#tN< z?Z|Y@r5ZfvNXd10JT9l-<+Gfl&cDSJXwjcT<=!!mozjXC@C&p{uObh#e3a%2bQtC> zf$vYT!33?5QZxSnTiY@qww%}VsDNVh^YWx;>$`TX`d)qZGfUU?{KJX9crBAtge^TV+wQb&Qb01i??4HB5XmP^70Lrz6j?PS`MjgwN`e;)s9BQS zZeyaf@KAUtNw0Tw%m4OUR}zy5g&w5F_9InIvLEOd%O>_ zP83SXR~pc$D31)TPetP`2bId^AEMWYMUxDY=dwujzF_jp3$bfg&PFMiwK#e2ILZ(ngF~97U4f~!kdMX)p^g_hq({b!3^BV+36-$UkDcSw z8H}>(P;R8@qEB8(`amP4@?sM=2p~m=XJc!w6x21W(CA|sU`#|RxQ_AWC+3GPU7MfL zRF{ie7=hg?CR8&os-|^a)2#TxcnG+x+8A^g{h?5)82M*+r;FIFE&~~%3{LWC=&Pn(+Hgt+Dlt~l%5KtIS!OOFs z+qV(~Zd^~!QVJ}j%UX*NnU|!N!k02HYV9WOg^f8El~Hjw$9aS`0>els#xe(hMR* zY!$*LL~gzFd#u}}&ReqlQ2veanC#I*PDqQEnA{4mT7%btj`<;I? zdG4;|;;Ly8t#L)pmL_%yUVg4VTojg1^=I*V#Hg+LRG8pEN!Bn_U*$usmfx;@rrv}2QB$&&mN45y~xhoijg>_3SE%FryUlKO_NT`Zsa#jXHQOFXv zwq4^Ot&=G26;s&n^C+#7P#5`?jK}dIw3Lc8qCSJ?mE*8Be{uH!;S(@N5nqo* zI*t@d2j9(K1p3#sXwNJEw~NCMUxz{mVemy}y;tm*5WuL4Jpavci}5{u(dBbT^)(udb`>dU0_!)7ZF@Z5-Om@}F17jxU7(I#3zdrO z*)wbVgwTVj&0K`&wsEa$NfRN$N+SgQd148vu9S8asxj_6lenu51pY9XBGcAl*_6av z1-q?&>DG^J=xp&tOszTG+u)QAy}D_i#Es&jCB(@b?Gn3Tg8)Bf6DE`&q)307Ig>Gs zC{}MXPO%QoGF=@lcWqr-7_}HWWr3O`OxS9ahWmd=poJK)`qI+_T#~RxsB^J+ZwEg>o1bfp9ODl7r-4j=kwY2c&B{s^~-sO)Ihd;%L zI4p_*Mt&f^B$gj{2>}17XOY#DL99|f2MO~;x_)cSKqok2Q4CQ}WSMHlIL3#vJ-R_hg(~4f>|Bz_7;rMdFet99ZdFkOTV$lO zU&f6Boxh#YQh@Swy*oU_6-LZ%LoSug5euT~^#ZtAeSJoRpk$E9@pwr1AyJ~=w$0Xy zc+$vrhMA8z410c0)@;O2g}>qYMR zUZdatq8!*L9)Q*O!tgkoLF9 z;*P7NXOJpYRE%}5hXXByI)VZ=yOgTdsj$08dR12zp)aOXPBQ7V4F%nSO<>R7;T~_X z(Rf6%25@OB8K#rq!Fc=imy8K<$jOz3lxqv&F%e84oy7dv{53Ef<6!F*?`K19wBVfC zBKlqK#dw{zUzuTpOMFg(wS>qz!9rPX$K9)7W14%z@ zrTEODi$PxhUF*w8J|-&+u}}d_h%(HMlOmEWT)`g^TfKdC~`8Mwbv z{%?v&!-ENdNm=bL>lku`A*DM?$Hzi0-@ZCR9ge{{xWGvTWMB*I)$9Ki|COH`f2VP1 zX&?<9O2QMiAzF4Ji;gi7!ypr*5h34`mydMkNU~ITnUneO~#eB z!SI7o1m6hLhiPdNzpT~!@GnaTf#7N#d@(ehV%2aB;&Hue=M=yB(pxr@uNR~cQpjc* zAL6-Ic#-)gN8uVcScdt1e4J*vkR|CNOlEM_9~^TX`mc_HUN<@_7VVHB_+5Vq%0B{_yP$tfr#@4V&AP0 zI}%Kf?Lle3zeIJ3?{;tcBYx$-@gJ8gvYM4tmr|ryAg`ob7p2-1v=T;YpR->hpN(9&`G@3Sj9=$qLL}sNmKtyJ|EB&HZ~ej zz_K|6EtRE^$@#NN9MB%yJVSPPP^+F`FF%u8bUL;m6~NW{0Jl+8@mNa^x*w!fzjo(B zY7g$9o0PXH<60)(v?;SN9tVK%Oe8LRE4WZ?VNV<}sraQHKUAAX1-BxCXMMidfKo%& z7P|aG>lmp~rwb+LE>2n>$yo-lk-1c{9CL90pmk#q8|cu4)A=sfYCU9~gRO!|r>8IM z?wir{a$odoVm!}ZcjTH_MMspaf6lfmghpr1hGPJv+8u}VQ%X>u%Kg})BCyM>;ss=g zzYYWScHB4v;HIxR3$O)-SpJ~SV0D}Og-#%?a{W$UEiI}{lcCblwgcP2R$xgL2W>}a zzNQ|*6FF!l$_f(wabQXquT@Ch9y;{LkzqjOs3aiyM2PdR%3v*WOj44EEFO{jF&yg; zkB&B~v-WiMlLgf-@3@oCSIC{+YNK6DZcaZqMRhSn594n;ew79EqM!hczIWV)5%Zp` z8WI$f*(t|1>gMClY=U&6qB4o~ocJ=Siu$-TMY-IKhkrv{f-H)YUCv<^-weWI9{GVe z?%THvZr5$TH$tv-Va!$8JgxKk4Ge_1*5=3?c2RrTw&uF>XDaww7lUC8QF=3dgN#f5 zH?k}_{+@E)%N@HRMpL@%h|XX7ke!H_i(;I%pnl9nIiT@kUx^B1vaOS)ha*Zuo0iex z15H0j$ot)gKMV+x2X)qY&z9}_jP|WLpg4OHh<5SwfHAu5^ID5Kw+4(^l%Io2JslgU|I9v>WwdV(s{C;NkInMxg z6&mfGAm@3OAEDda{dvd#$pH2iPw@8F8q335FyJs%6pAC}i&A8K76FH{2kPuIoNZuXSE zaX3BMw{_anUAC=tKBa%YkunhQu6!&jN){q-{=RrFPrCMs<{il5cCBoUkZL-0xV@M% z=rI4TvD#>(b?*%N`H$&UOKpL3@H4G=x4X>_py@T;wcL{AFVbauy>f3tZdG-7R9m&; zut)CWZj!d` zBAVw8QSYt1tJC0n-9I1bU;lhSC=Lnt1FqKDoq4zLyXY7Pt3q#;(v@#w(oi@^P;_v* zQF(cN8UBhjBj_#z!6M|lJ9Mxm8BWg%#d ze^}ofw>}zpvI~2eDG@W+Q+KwK+_L5Lg&5eq1?c7~>MOdHY zYla-b!U@|VF?eIz=@U#u;nC3RF*O&35PNCBtS7F{L_{EWIefJ$Z%+Ltj}sho%u+`y z$kF`zkk@2maPf@M{L|Yn92jF0$m7?z^c#lXcIusa4(cFQ7s_tJtY=bTvIvk5&C45J zDV@{75~ifx*c_|M|pys&Gbg zRExRZ5iuyl6MwrUCvFao$h?zpK!hmI5|J%<%z6N7UE=;Qk>%v4o)G2_LC{iNXI1gg zTB3n5gB_}hRN*07#XG`tusnreciz|qCXMF20U*#@zXphHY8%u%1-T5@a~pfIk_Z?j z3M4H=#u{U1jQw7E%JpNNun}90tEqvlN`>HLgcPZysNB4qQFV6887@d&^!JRI#JqH# zC0QjEX=MXY%4cK9>Xz`n=kY3%o zR;bl9H!I*rw?k?6OOP4B!kvoLFTN*{ouZ_383`J<)V?sdSQG6pU+2xRn+A-oU*6_C z>S8N&hW>g}Xup1CpXRKrgmqy$@N4;!Xu-PghZ6(3FynkA4Q~Xah$F=UZ53SrY=jDZ zO-D^4eV5hvXJ1g(G*EMg`KbM z)Zv$^*R5KvoBbW%-j?!ckGgF6RR1ZHN<0kAZfC5+_wQ6qP!Y zm#hoe=m%!0bdgHcGBNPjPaiKEtAV+>NLc@yt<A1a-^Z2*N%zyt~e(myMfGq;g9rkzZ~ThR$W3g7(icav!7?@S2^!B6I@ts4En&`U`fIu%%<^j4*Q*3Y8hTjzR*fTU zn|@Q(X%sn=RBY4qZy~hLFxG+@{8ES*2u?g3Scz%u!+#QW9%6`L$Q3>0y6f`Huc+jkmvRs+uBttwe9VLfs zy8(^`qeu;ZBpOUPOIL?hL6c#soHeAX<9kkuPpaxMKz@YG-L*DY%JZCmxNI$W4 zwi-_BLXtL^pctntiTLXa*9mwBRyw^tyS1)H77YWTsH}d|+V>6|)x@)k(j1&>eH*-E zYcM22CwK)&g=nM&{rW%=Uo8Wj#5j4qfNLd@dGEXnzO^jAwFFls!y;5~91{CfFT77D3-A-*%_IGZZXh`^2wnsFur$a~-RfB49x=p8(P{-%y1-oZH5N3* zUT$}ML!Aqq!9sySWix z?QfEKc>(cxk=^LwrD`51EecXa=v$T6@1B0SEArk!dKF~mP)X>P!FuKM@uP?TWr1AU zTVh*~Uvxgeaa7)gsg1;%fUo22irmP-sL*GmW!6YHEMw~^dMp)HDeC`qfb9rUIQMwX zWSGhk!PT12-Q{iKx%LuILgG!T6)eYcDhCqj*S!&_5-rtgHsCcS(pD_Bw`Xwf;sH$1 zfLmbmFa{djyk!6oeNkonr(g zffph&FKb|G3Iu7X5WzY(e}wDjJIDGsmy6LAz8j(qq$YKRZv#4~J|O(1xMnFU*rnUu`XcYUBSZTX zdK}cttJ@jxr3C^HgG`BLW#FCbN3V}Lf@xEniKgd$sz1;DK7&$~^1lp_jrV=BPbnRy z*N)M!RWkYfo8IT(XQ%1kJY{O&x94v!ug^zfd}AaCyiW6V{2*x7Vzbk|^?iw~np7mG zD1Pcek*hI!W!t#z*j&}E`bSVNJ8u#je_pNKGH3&}eV+R%R^tBt!}5P=AYhY(6d{co zwdY0jM~dEazaAmp*ENsHj|XpUi!GnKp1=q9O4TpF$r$iBXR;na9Q+z0`%Og4o-$GL ztsmoqjm_^EU>q?DS=^Ld9by3!CH4k_F4R!!EBdkWKZ^I(pkasGSL+yjCGe?G0xWL-C{}H|lNrBbJpnLD zWicd57A#Vhsiq-ovc+rMYiDTQtljm8Tcx>%7djX4o~lnjyXrlEu0%gxY;>GiWj&=c zFmkd24gW0bd0&S%Hn{9RZ?%B7;4D}BWGWR;UIkKQ5oW@#9M(78-otH$``j-k(4cKR zE*W{=>=Ia2FaCR#OWu)^-iL!ni}#Ka|G>ZEx3X#kWZ@8hSo~MUj;^+?ieg>r^nN_aZNC z0?nDTmji_yN~DY-NczIz5Xz@*aKC@|e;VB|$8;eyg_OKJp;?VheFC1I+dg2g^z5QqnMmeUYSt(7cO7-I5ie>5T8zbPn0l+q&~w*DlR*fjq!vk4tKlp|h>3Q~~e zgGI=Z20Zs;0gj=#F5xphA~VauU_AS=w+>G$6pf7Y&7wN&_JvXlh2j zI5gy*LA1yU=+`jupCNVE46gt5*uvM%eE*R}}B3r$rxV}Z9K2bnZgmF#p> zx0P8_--cTYGEn_cVq9hlv_4yhce}qsD~Bnc)`ETmj(ePEtFS{Na}1>GC62$9QU0rj zPqi;xpR^P!8>ecDa@|BR-`l`GF4PcGTTa2NNgE4~RV^)l1+%wy=KLKWi+xI&S8V! zMt~=jefYA4VAGAY=6hwQn^6~Ta`(is&F>li)JN5~!CNAO1A6wDyeUSxOp;WtFii@* zG&l~`2}2VTyE}Q*^uWIzeGp#FBu355X2&zIzh{wnVVP4-cp&*l&$if1Z!|BDot7F0UWA>{dfhsEOZ{9ew^d>quMI4m8g8SG}e5RcDj(-7rlLLBDw3UJj$o z8I6a;?=K~_r3~H2r83l79jLq<4%R~B8fv>e14lq-`<$Sm%$8R^xdKJmSIdm7Z&)<; z!TF}TlT3da87*-)Zr(NO(Nub9Qb9(Mq=Rp+Ok#m{2(`2z-@mXZ(rz_BjOcHs3t35# z%uyy%h$F-?+{H+)zpxDc>*kv?+f{thPp{Z=RNkFw{+EKXL8$TB$tUPAUEfJmwqosk zQuFyiI-@D|$FdgiJ7v=QV79zy7L+^kd&qfWcw3v)C6n&>ydG?R%z6i1pucAaC8+*| zsdSp=%J|>j4yn|rjhR8SQT6Z;glmJsvL2W(OkQ zZa!1y+~{T4|A-)4Nq}8?oYj_-mi~VU08n1aGTaX2i{Y&{0Z#5x(Y}3j-L5D5iio@I zZ3kDi&}p{6tel=7^S!3Z={@{kz~J)+!zUD^Y1HlxGOSLp*GG5W?QJ&hC(%6q;(~sP zC3q2harbxz6)O9aJFG0vlkU1xUJz2BUH?e-fx6gex-7f5qBD}3`2Dga*!j2~UE$%N z9}I7`EgCnz<*N{B0IGI4T>M3| z!)zHDX`pIbISTl17#H-|c=zf#*_g(%X6Uht{#rX{Erm`SdYwF1{E_d=poxx2m8j2e zi1gb5YjLubnWf-M>UNHwPNkfIHi)r8-Lws8CmG_d{98bLC9l|_T&ck8mS%78GTN!pseQ|=ES;d zuFJX~HooK@kbFSMT5z>sSXROh$U@Vgxr5RC*a_>psk7vcx9t|ZwROO$K z>bmYq;QB>9Ttl7EiPwoJx^e=75naX@Ct;Lv_CDq|AL)Xox|SmG&l~x`Y`VFVohWQ* z4EV7}pN>ul_hsL$wz3|AWiJ$HN6yF?dT4?;vxG@$!$6pXm8osi(Y_jV*E9Ha;NtWy z%8=j3Xdf$Bsdj)=7SgC3RlzZxzLzg>Hjrk8W$ckaMpZeZJJKa+ zB2;h!tmlv*p@1LO05BL{8Ul5$Aa^uI{&*H7^j3vL$bcG=0XCXxYvK*gy39IPlIEGh zEoY?E7)xfaN^~pS;~nU4WN3;dTGX?oacV&clB~1tAg?c^HZ3CFW|VgTyJ249e6!V9 zZ=ItOdm%v*bQW(HJF!`amD;G{FA~gj1+kL}(_Abxb6F`K@SqlJdYk_u6>~}NLPQn+3Ns-liXh# zP+Gxw9WLw6c9d~5P6s$IlPZo_0wzb6-J4{e2yiS=hH)-5rY0m)yeo1)lDL--Enh@k z1T!p8Es>o%cdg~@!g39qYuE<`!^F5U^l)=GN@n+64FUzV{2Lj8&7x$IA6=7bd~OVz zYn@F}>a*tgp*GUIRk@Y9TduJ#Oy_0$>A5ODuz#hMFa}2zUC;7G#fJn*A(i1!&8GZ@ z$!9PevsO~PjV(j4D#PTBng%UE_Y*IJuS7fdkRy87Bq15FYIWqhnbN81(^d4Ri z7@?jqSX564v-K_I0LT@_B1xuKX1{I)D^8p)XtNPg??V9Skj56Lw@#)CdZm%bT-?%^kWoeLI zTu4YG-4m7bbBC^BqXtOVSMa$31GvS4g7?2&(47LOiZtfJuB8!**)EK$+7ODJlDtij z5^7xnKM^qGYnab!KvV9$)=rYpV)ClEH7SYY?|ouT29` zsgc)fBmCpe=>GT~lOC$Lo}Yel-iE&b=TqCg0&#GSiXCd8RMz!lXEFr>?iMHw`&7+$ zeVvYur<*3p+j23qeijXEPsz9<;o=$N7&|~J4J|Outj$N`f*1B8))*VLCiz$@4q6RCyp{0L}-tA zTPQ+!dg3n)ubrG|2vu21=D+I>g)?b*PCT+6mj6IV&OiuS?yvzgIB~$+XwNr9iJh>uWrcVJ!DQZMHk74#PYJYQPd| zR@jLK!B2c<1RQ7yEE1T)xKosTbj;;yBzIH78FxA-?w>=QZvK>o(sBiRjw(xT9r%45i=6&NZ zPQJeqG6a_JE50K#InSR4+RJa)M&MIab@<*q=B<(PN^wCzr;4)c60y}c*ZCsB)YuFY z#5JhxKW;g7;dI!;De?NNV3Ue32Oi;cLuvHwQL{GITG+p0J)zt)LMl3j8k4(%HfP0bXMd(% zdVHnWHz+E)?tDaAYkMG^NxtwyMw&(*Y|SL~n0H}pvl%j(^2aeh+l=EN|tS}i|qJkQVo~6phzbpD$_)2|pD<15(RA_pqlg z8}Uj?xZc;?>@4=)7jMup;)>;kP1d;hra4{N!=#kKVy6NndmpOM< z)!F9!osU_G@ds7KJ%EnI!--7p#kv<8u;d&Dfw3S~%7GS~CwzY@?L#rWDt!pO44RMgmVLAtkZ~`Aqy9sy9Q637sym|axnXGW=3H`9 z^NiL6^SB!o)|GfXQ%*i(C5h+3M_Ml+=`%m7GAO#t#}a1_+Q8hc8J&N;4sv zeX-e+?!Ou9PYE2F*@xNKq`L(c&*8oM7#*}TXX+WoXid=_|6SO3nPZx&8)4<%l z)_9(=>c-wd5yi~m5X2o=ASDqnf5rs}xR7zn@O#ZsB*O0yxa%>y(b>WEWM|uNsynMT})$KCPPHKx#XpD`A;Ygq&P@yeDN5 zWq+NpiSD^U8*)G}i>g!xNL=b$%(}9P=-+_}PH27pOqPi2K-T!1NbiRtuVa+9SlJy5 zpLKVY7+oC4G7ynoxOE89uR*DP76;z0+1qHtwr6-TzccI2QBjWMjZb}vw$Zo=a2cR))c6*-?6GA zkea_x?USTQMEju-wm3g>N?8;xu{ve8RvA_PO_U%r9~ejG_$x#3tug_q-t_g&6uexi zdxWnds}C{1{ao9NnL4%%=jn6VWA-O!RWHvY@1e4a+CAGW?<<^(FCnxqH)LF$G$7U_ zoyllft?qtrU?OtYiXu9BX+g&GGJ1*sZH*wxXgO+UC<$dW=}h}rGV1IqEDjihN`^!% z9!m`U2ll}PY;2+aPFLkH<2An(2SOhz;|tVQp7%2gqrjrWiM0yv;prtT<2C8Rn9)u> z^n5TPpHM62d@w6)-?l*lH=L{w%|!iqI}|AB_LouwR$XU+%~G8?3Z1H;4Rl=Ihz2%A zokCVWDtfmSZ?FP3%fQ#tnsc?LU6B#)_n%sUpDA&__aVpnNMD{Liexjkj(5dMI!+Wl zZ4w?kF1@UmYQ7A%{MmP~nl_N;VHNh=A}nJ2-iOI8*8T|wbm|UmyDZeDoGKQr1;!s) z_U%DjN4 zM*H+8%CLp9zW;4s&nNBjVs%goGzE1n_qI${YiidAO0dN)wsuqkw-F{MQ zgDbMO!v6l{Q3)N7S#54NrNt>J8GD5g-?%P39?zD01$_8%7OJ&wQq*Qefh*5;y9_Qn z8et!uw}X7nFLz{zt!vK|T3+sk4sm)fiF!H;%j68$-*j5F8LE_h(JKt;H7lWi5Y~@4 z$Vf|9xpyV5p{VujA1qi}eXO@z%;Mk|(;3@rid6?S^}bsJZ9G|Nvp(CLj%Ny`lIiW_ z;>?ADr+c6cQ8KuB{wjN=iT5wDYBN-hLhb6tFBT!hPJcNjj67|n(d~|90_2v>lVIlx zQirz7!X7nF_t7U1!D*RUb0bkAQW5s4`?pwdPp`Wwb~s~foQhpV;eKNo!B#9p+=Vg3 z%Lk1R)Dz9;(i&)!n>g=i&*=I7<+DcygafBol9CTtvpKM*r;^4shD#WRQAyqOrmZa_ z7%PWlR67Yx;n>1z4ZaQ#{sGe(%?XqP83W|58^coU9l__h`lFtSexfK;akRNR@p@#{ zC-$@CJF~k19*+v2)joj>y8=6cW`~E@8=r{8i9)n55%D4cy0n^FeE3d`b;aM7XZ^A9 zf_@62!eWS&(f7Murx9BYuuxFcREZooK=U_Ci3RE`_&FzZ`Frw&T2|H-f*B$qP? zUJ#bs7Rue~KjJ{DV6_UV`2q+S$EfMW(T~ml#oaR&AI8DPf{j#Fu325~s0$&^Z80O8 zW~mLrW3yJiUn}ENyZ1ZWI%?ONIAo+zP7EQp<^3wAX|wwAOf-7il8>!o=~Z9JPu@<*5Z$Hqmf;=B&mq7NWShgN% z;RbdTw^Q)N)c<7xl2k?6Byi1VSyB-WOZrtBA^`#6)t>H3kl+;JJ2HXs&^cOvY(x9B z5Bx+4K?1-O!CmZa9gCB{dwbocb3#6o*g;ebV1@>{3Rpd82q+}B{l3U{$j+REB@84E z*_4hunon_P5a6VpJ$#IRbRTN9LaAMfT7&CN5oIP%bU^=Q8)YDaU~v9DKtrGv2eD^c z=sFE-o7niv{)X?g+4RBBC^&&;Lei18FDRMBwmjd=3uyJZqpXH&3zVUe1YGb`HOKnA zr5*n)QSCx~VFRKCEuf5#Bgx3bVPo}P`;)ErMzD>s&`u`6Wpkl9dQ|WDc?Y+J|Jewo z>M8D$x~;7SoIGD%-?w~^qW)!jir#3w-ZL~bbP{N_U>HeMwGdJyb>vvg*f`_HU4@(b zd>`K)v)nzF<-9h-FG_R-!7zGFfJdGH>7F$~e88I8LVc>|iRJUgQpFoANX)(_eKpDV zN4$8NLQdgzkF*s4!|eg*#S*+RpoFb_$CfyQ|>v z`g9_5xt%!PHl;}HYD?M#@RQjUJ6ipubC>hXUOAvsJ_E~}?z`p5P{s!hvo75?M~V;& zNhxazD3?8*qI}cBdK&r|6=~IjK;BOK`-s-r)ymempjfWL;eJQ>hbjoFnlI_mu%U5m z+@h`pm)*K+KWqW36@(P~nL=vK3;W-q^qvm+5vGu;Gw})ZVo?_QjqBAOz(6xMqgJ() zUUYev8)K(_eX*C8%PmIV81OjkCA5z^&9Wi&Cv{vaUs8?z}o)bP{_bMSUfOSa3fOB<+f9x5}&PH82$V!4UeE~JI z;b_Q4L{Y?du31449SG^LHvHiV=<>?7wq z1CZj1oGdm{$(%is?mMNmn|+J?S|xUbjJlDgc7<|8DBzW>q);tz#fbYx)^K-72BEXv zl8#c%riuCxpvm5DhNZrqmjzm z>B8*In5ju_xyf36QO^e+hb&bkCEOj~lln=5;$dY9fz(^ve4LLfgQh@<0HwO!En^#E zZCK^BTzyQVAGM*BtWuOj*T!KP>4UL$=VYMBu<<%B)xIlkIw(wg663DjYZxmOt4QUE z7Nc0oJ|0+k&WDJ~Ok;ePRV@j}c1Hp-|yfB<&Q*@va z23JE_>-!?TC|zl0usZkDg$iOOz>=_4CqY@gfI4v%0cea|7|Khi3LE6WYQyD#U1J8s zXIP>bS^Pl)l8e+{HgcqWt`%Hj2aJ$=Rb{T|>~SIppW(yury<4@2K=p>q1!U%Zt0pV zf5jL_7H-G5wN&N+Ii6phdz2bV22E&7PEb0uG2_N+XMF7`=DCuNtpSwD3Vw1|xd=$! zx7;G}uakDhbT4P5W>IngHaz>u2Ghe(ru%pHpDoVJW*6FG&lQE2R~*6=(Q);xhB)?l zu6W07wkC_2P5GV#oKw-Rn;sz#7sAPMB(E=sUS7!|4?s4$CUrl>>mdQ2b9T@ zlvY?cT7zqC7u&`eknULNJpEU99P#}I1&n7rFUau*{>5T;d;2ZO+z*$Bex=BVSEY{; zwJmH?qPkqND(=iD53BYIkvqmSl=H|DdS-dzMiu>!>oo4(=_wq8b9)khl(7aiUZF34 zGO?t`j7KX_Rt!Eu>@iIi{zHKq|8A{UCDUa3#gKHDwIw9POfD~Xl^$T@PKRO(6Ok;J zm+sV+9cV37l~uzc5K*!{brGT*C7E_m5s>SV?N&rG)coG4RsFOS?MaAKG=JjUdHsX} z#`Cgdl=(>Db;cN#&9e;nXiH<$Y_}^_Cia5-GnN=*(f_{Q?(tZL2ixY{{=WcLD1`yG z=saxZXnnppCZuj^X#hoHWeyCgH3dI7t(_rkV>y0iBLTdfc1N?_Ih- zMKnuqPW=96=?jf#FZ6~LsTE#(Oq+;5yk?qw0xxV^GC(M!oX~?=V)08xt3l#~fecbZ zEGF*o6ar3jwlvy>=V1TmA$dq=ee%_@Sq&iMb>lIo;;&|8mKLGo%U7f4cho$vAefNK;x!wtA!W^y=ATWj|tetr0{P# zb-b!ILpXzsj*gCFV`K7ZbhX~=?qObD1rD6j)>E}aGvGARgI}shikM9zvIdT*Dk@2g zvB`pCT765#AYg7F#UV$<0yJSGsg*GV#6ra@QRLDffN#|UC>SDw6*4>0`E=(T6}Qg6 zP2SgIC7jH+3aG@wmMjfXK(k5IX#XskM2>0g-auU{(y%1+N-}0f)m=#pv4d&V*^pBf z8F6ctsRDF0K*22X!Ed|LrExYzah}8;tv%KGxgXSxe-;>5$YGbkzn~kUIQOwtIROe+ z9r{`u!_PufC^+S;4G+>CmD{4MtVVW@rHQLYSmhhEU*eAR0+Fc!=fS<8sc@cXsG?(1V2yONYi_ry zmW**v5+*x2i;N+TLFHdpaL+_?Hf%Cf(889DQKIVlT}>@YT%d04JT%ew43-Yv?Xu|X zwZp%d!rG-dR;<=Bf<K8s3a7L@7xu`B<**)1e@OD0m#I-wfLC{ zNpj;xJ;KXl-?zLzdAsw3DqKmj32??)<1!|kQnWe4mVVnvZ?5j}hBjN2DTy@@p{ZkH zlxH^2j9@54jdJYFjC)|u;PXl|%l1kN4EN%>kTBZUQ_Y+CvEj0IHy6ggD{%9+V$GJC$vgV?Ml~Y{v1l=xvlvB*%z{n-4)ROG zNjRd~${bukz1}EyWR-p8C<5s*EbedB!-N@h9Ocb!jc;2^*SpDYT0Wa@G;6?+PwgM) zb!ufQl7%yA%?=$PNDQrCnunoC3WN0mMc=`eT1{@zIB#^ML6|jR8SS}c02)*9xh|Ch z>>V-ca@ptX-np>aG^jgWi~boqPQ9Iw^YSXMH^axpH8ymp!}(m^x9L3?PX~3yU!w51 zU6#*R02%4*cDnP|>=pb3;~qD2$0mn=`*&@x`Dk+S>NPr`WR28>wT4>f-Y*PS?zyM< z?dK1@C^jamg8FZL{zv!r&!hhzQ{Mm_ci8QnrfJmJw%ORWZQHgRXJflbV>E1Rqm6Cb zw(h_0{oXs@Gqah=X0kIo*_`K`pH6b(*a?RUCcJ)@=Z{I4sUt_Z2_w9b_NvR*{wP54 zYPkWuB%7Mt^jnje8088`lmti#F(zO(i-lc4*lGnt9NpR>$(j(x_6RQ5WKJDnMX|Az zNKjv>_Y4Cb^-m9>$1jn_%Vs=h%#L*$4e>)io@qV5GC9d9c9`*@HkELCNre2F_@>A= zT5O215Hywe8%VYM)8GXTp3%N4mi8;TAINnxm&Kx})o~!(ubZRsex+ltFiJS|hOadv zwH^__UFec?*n_*s%RA1Oy zg}Bni#>U2zpeNPd`F-_ML%LFZr|2`|)vSub)$Mx8Q%k_T%c{qQUvzAA;x$@q;;c2Y zQsI?f33-GpY)OI2;U&>9t1vu~8Ke$hf>ZB)ahcv5FRCG;Sr1@4$sr(ZXg44~5)Myc& z;4m05Z^-dbCeC0O7T;%Kl8`Pc{SLEC8oq2pQgz(zWvzN_@k6HR7C39{COVyJ)Gq%B z#|!@L4uc)>UxqIbHy5qpKm54X*$$@_AOs$edrLay0t$NC&V3Ml=3^3%X_cue zQ4cUbINBe87&CkPtxgM&ffxD;@4y-AMD5P$$gEwa zb-WQb$MC#H?6ik_tjN#^Uh9ru_L}GCo%I*08bKQ1AB}^+;(5s;o$>Z^Qv}gzWL&Rs z{euXYXpN-FXBVmRCs&Zqb!@CyjSJBVXBaTQR#Y^wX36CQY&&$)F&OwsRgMxoj-}%bj&Qp!>}?!0`sX5nI6pxiStfV5 zwNMn5`1kNO^!UBqVZjin^G0pEV?#{#4WdlPBk+Q9yW!+JlO3jM=*eH19KVeS?~ZXG z_@q>QoM?bG7G+_VMINn%wU;im_uJdsXT2$Hpse_B9>FdE6DT<@M+H>kz;(xlUsyOn zbHJZ7`M5Zi+K`%qFuN6Q;a?j1elb25ojyx0e)l&9n^%;%WLbYMYd92XagM1a^m~Ol;SFXKcJ5 zN-%m}RPoqf^oMpf2LwoLIxpaRRJHOpc>maV1pGr_0A@G?D$$b#FviY@_Ha^(q?`Hy z1^_(dSa%dTc;m2+I>`AT0Q(0yV(in$s(0wl+Lx&UnNbg2pSvgg4@E}wfmwMW(>=FR z^;dgyz(=CXvT@qL4<7f5`*j5noDpSvCDRK;wh<)yXm>(q$$({Xmn=p=*uNrFoWkn^#cH&yz25gL5bp#Zgjr2|6 zv;X%o%p}h#H97>?1iC89Uhb%=u;K>Mgl;!RS2itrP{e>71Ra57*(8M%r}ZIZ=QT|B zPjW}?tlBw@>|rsI9MMOovUE|{j0k(}+Gfx&4YF5C0dq=e5L%Ebt@DjDvY!KmU7o)2 zZ*wJeV!S{Ugih3Y5+u}x%uq-EB?)LW6on_x={~jdO#LiLGC?AUWlN0SP;?1WcP&03 z0;SEWy;!2cnD>Z$+=|&rN@jJ2Y}uOkNJ$bM#iKtpSo>v9sv7<5Xq%ex2=^>EWre%y zCKa`qe$W`?Dr%WI>-L5MRo@>NTgH(1zL(z2`#E6Mm{?Dfnsu~#h zGk0m9POgLb>K(wTRZ?c)EW!Yj+N_(b4CjKok*YAcy+;%tY0^VdmkyABwax88Z<2tj zl$%GeV08#tzh9bX*ovo`j!HJS`Ax4FC!}8MvOS@}y9h}&O%7cZQ zKR9NB#7tqN<2Jt)8J4(?%Hym01adf(;<|g`F_bEa|7TfW1YDWu(=W=>NT@3}O0b{W^kH>7g1A1-b`Qb!*k;RZLLXC4%n;&aC`XhclNE23LTpE%^Ju8+c7 z=od+h8((KyQw#)c3{Bm_L(FlvA#@6kjVN^-QAC>fsRj`bW)ZXS{1vsFUc#%|2~v)b zg*<8<7G@-Y?smgysFhk)r>7s6Gd|PvEt4E#YNK&;A3$$hFpj04EyWA?K{UT>Q6dH6 zuG3Etry(-XB2uZ|N-1^>mjLzVdn5sl|(e_DOH5IJjy$(krA2nYf7 z87BJtx@RX54T${a}Bl8YpqBG%4yb6=XIQ{tUO?kRd9N#Y@$25y&m{@I{ZE4x!G~CH#J1C z)An-jG!u)Pri&-w`uHtQ;E4>Z&Erfv>GwvB9j;E3?LJUUeUC;A^cznV{0^*$KqGBN z30T%#>lG(fE*pp)ZKQ?Irw3i#68x`uvippMqJZE-HIbAr`;orj3=W_i)YpJz0H~IG#F8SPk zC68O}K~DU3nR0!DqTjiEe9rJg?k$ea!LLSjkxFdK4hkW9DyG zuf9pC_JeP}e(p&3IDWHb%jWiLy>Z#V;T(7SUw%h#U7M=ta0I=@<_14GPMyocJu%Z7 zNv6a6;M?@{E$QHi#kV2j=SaU>^CYpZ6oyMG@*4GgybMuFt0X#U1E`XGc7QaAiTNoW z7EcogA|-=Y9+O&Cu~1Y;!sm;%9|hYqWRf-tV%^%030Z0USZ1|c%!>3IqGX3 zJJ?URbcE8E!P>-a#azc?I&yUvK0L;M(ra6vH#_+ z$qe=VlIS>$zQ2xKHUROt`&WNBg3)h`ElE7PLoWTH=EN2~t==VQ7jgG(;R%z;SxYRD zvL?)nb&n)`YzmJNxn@4D!h`I%EnBgmMzQdPNUCT~k8`}bB9vuoX%=#GbMwj8hInd- zvSbl7a(VN490;`#u23{$;bLUX!n*_~0-8FI$?_#6H1kOITu`lIb?+)GCju2ztzz%~ z*GU0qu>}$c&e;CtelL1^alok?9Vh!z*{b)WK;mE#8t*94jth4z)Frv^%dr!@4ZJi> zp``?>{#&p4(5G_pfO^enHmQmYvwkvZYTrH7tn^|l<`ufBS@^>E!bd&Q97gHK*?V2XTZ^^MUKqve`G= zI4xzy{T(*@JAYShnEhmQ9VkN1%X50b4m5>#q!?2UBsFCDup^g(Rg+80khpH>k676a z)wu^)$2r*0%dPz+SSamJF+E2|QSb&Z(deuJodPODlQHrtmoyRRKvFz_FG?7NZfI^a z-deVGNo7evtK)Mq?O=u18`2b!E}|-oEG+CY#cdp_E#XzB5i1qR{OvWitkXoI*#H6} z29H}~DOGkm2%cZxfAM!Vd}q_F1d)ocNH6RC6}6@J1`@%LBoHZXWE})J*AtB$iD#fQ zamemMadD~s3~*1hHOaA5H1g)l zw`GJ1zcB1eDB$(nwrPgaD;Mg&9J|8a`xWWt>!fYa4iPi9D0jD;UKs3`^Tqa1LMwtTa~3)2@tft0FM|{Y7NUhm zYTy}>WrcO42a&gFlu}wEjoK8LYSd2z;q!Job6fPI`!9>hjMKQ%&cR=@J=Q?&XX>or zUZ+^cyHcjL5!xJKl9i)VPu5zmy1$Z7Bc9Y-tC=#T%>tjETvTZ({~XZ!Tibmx8`R84 zqEQR4?Ip@$U;Eyss_XEtgL?&=zWZ@{{rS(fWk0P`wb$d2KiYTDAF21losSF$-Ye6C zj+vbu-&fRtL4Y!+Yx@vE zeru;X-M$gH-Ta(}M~V;e!?U}w+4P}GkGA!_$nvWS%^c0gS@nA+(35s;zDac5V&%RF zD=PrkK&PM~fJfZ+NcacYQatUQ5x!0l-W;Y8oV08FT6h930LLD$m8+s(#P|@tn?nJ3 z-+{7w^%C$Hj;XsbU;?P_3H6hj=NR;=lA~TuhXk%HesJaU6)zi)BfdVy8B8@B@FKq7 zZM>d+*}2D6;Qe#(aUK8$T3P;AubbU~Mj5=Mk|WE_#Dv%L;|;9cbrX#6qd!;g8{w(n zJ~scm!MjX}zrbtP>n-}kFU%YH_T0*_#z!wpM@PAQ<^N;o`IO7h{QUfE>21v=ym7G; z_L+~gHDu@P9OrYlCtLcmIo+~3V>diY#Hh$GRX`?T^Y_nD^o63&{@eV>kCo8na5PN> z4NiQ&t0OAaY8%4@kcM3$T``g#3|QJb{&S@yeSoAjJy(xK#9T(0ovS zn+;|epU-8}T0{ZwY(L&pDB3{A_wB3nWY)s%^eKll>ds|R7?(fOU7s=suPaT49=p1p zIdkosPfs=?{v5>TtRSmmn@n+QEzUeIH>%|+Zf+s+jtY3~<~m-iJzSCsT$7%9EfDyA z2-n8%NCtJ=aiwwfbIajz)Otf6Rfw>Ejo7IUIxv#p=-DH&iwP8m$6*s)6ja4P5;u|H z5P3h&%?g#o5a}ol^Em(JWR+>nMh3?=STP3l*;>zUpTcGen*W+KYUR(S7vnKh{CP~2 zOjaclwaIHlM{eykq0N9^Ok|Gzwu$&N#FRhVEZ;q~?3rw@M%FZ+gMU#cx+2Sr2+Nd= zZ_x3ZaIS$UNtvkG_}n0u3g6h$GN;NN%zhu2FsgB?W4R7YkUKvC=X72=&Gf~?RFbt= zO6M1`00$0?s0PU3Pv=<8G2!!k!*TY$0uON=X%EruS#9AL`&B(WEtMY_?idcnM2D0o z=2XS7x1L_i_JCJ_++^P_j6D-DQ+09;srm)gMLj!`(-ai;IezQ4G{+}BVuB3nkykyR zJL`;{EZkxA!B7lqJ6tuSLHmK9*vRyC3OxJ(k!3^oa8&8--A58b@4s3A zqE6WL8hD>}-p@h;H(R_#`=^l;Z8&tP&duGjCXq|#FdE))B|})!h)ECEHqHnpa7Lts z{9IzX`rS^ZL-_TiRqlMJ!{U-f$dvlw$Gv88Wvi7`9;n>D@c2L4PaBotx1O6!Tw(AD zg47FJkoe_~DdMg22kYpWR*S}~rOET}3)`b!Kw>s)$X%3_GC7~tbR5VZO9Y}My+Ssg z+2=lPOGICCbmSW7L3Zpg5BwqkC0f$?z_mLHM~!N%?}zSp3el+a<(HEk=ylz}X}X!W zX-~cV4@_g{y`R0`o7e9KSjf23dLj;1U}=iZqLs954qp_Jxu;R~7)uHD?LJo~_BJ8b zUjL$9NH9-L3>v$>cZH>0=>lm8*oH^EGLZbFQZ@M)E>Q;5!`YAfx_-u71?pC(8FT+5 z5rMvQIi1T8QE&lP&c6<;&bWx?EVkDqym{C;JVT59)WXWF67zZXi{j0Sd!8y+MIHjZ zP3OMx2Oj5JD@_{{TXs!?6e5p%)hK??4)N8UK>-`R<)y@ zMyQCvsNbd3zN@_I^RPB+?Z*EQ%J_|m>(4=_qdwd$Mb@7hp9O}_HiwPGgO4$T7q$0o zmE3KhwfI=XO=WukBJ;U zS_}<B7fc-XC9aXxqN#y$%fL^1mhn)B}@V z^aJzsSx*}u16|FV8-PF{a)6}k&cXjj+}odkeC5jPLzB2G;Gy^XLis=s{!FuT!f)#< z9+!6o>VO9m;(EZx@3%vsE_($=*mE5;GU&|*0U%Cp*^w1Nz_rvrxEl4KEgi^?_53p| zWkcTuB-YG7y%2s32{fA$NI`w-dX4%>6!@tAuv>ECVdWflcwes8S9-!6(i~5gcA(Ci z2BrsM>joTP0J!*lv-S^INsHOgr3dg3tt{z=zl?9v(*~)LT!5?pS9c26evGI@ zrny+$)fZzc#w1L?uQoNgHa$76KK1lyN0TouolA_WdwgsQk4OIXnb@{6_VlRdWy@n{ zwf*ZJrzW|MaINT~vs7Ur63DZ1GRl(mTV35Zz1|$Wp(#j?VG{P}e1K6*=k~II2ErG# ze$y0w4=uAoAmr@cjd|EUkM@dF1a^;g=x$)p4Afd>^n+~n<1ryV0T2=ie&JG$|7VX? ze<)H?(zJf!h8M+ryGx|Th$*B2c-2$lV=1jG7Aeugy?!XCY|cuy^2##^_C1kKu$-<} zf7$_U(*oES*j^ks!+MIU+1jdL1aLg^Y8v&w2?)|Oyff}eWZ66h)U4LUvN2<+GPJB~+#|U=#VDKEZSK2f zc@@B)OU8WqcJas!=(uTS%) zu3%n6uf?L(N7a6fVdG7HG&($hD9qiq8nRL z)qqWfra$PE^*cn0Ky0l`qPUY|knTnp$c0Kvx+KwBcym;0&H^!{>ACU{8)ZbuVT|Z( z)GpAt!ICC+_^7!;rN)%gFTHkkl6f`7(QInbIl{xj+v^nG3FVOqUaq_`Oi0WjCr_R^ z$IaE$RIA=zW$hBS|HCe3S)C40=fG zIx}@(c~=HzNCAnEQ}S`vBcjBj=80eyO5po)ec{LvAv9l!O z=oF?xqJd;ms+?|$5PEogUzQ`3gk+aLxTYbmyizioGmA=dl8UED-!PFvW7(hFtfGU< zx@N0yT!cz=MA{Skc4=(X6GKMe>DKUk{PMS}UqvVQ;^;8qKY!+IS_^W-^M>s(^*Ae@ z{(#RMLPui38-Sb5;$-iI78)~!7KP`CE{&k0ND(%zQ}u?#x>)P)iD`0T7Z98*rO+$W z?irOcwydxzP zlLVg`eLn_d`knr%U4JxfxX-yQ7L90MCm;qyWZAEdt892Z2Qjs%zqzd~Vs$;Vb@de( zc%KG2wW+%p>cG8qV0Lzy!d+(lVSK&GJpe9>9UtKJ5?|Iy5d}uin%2DKvN8XuC&CGQ zf0Fvzv+%i;jjY$2fTGr7ahnY4e*ZtQtKK?JG<*yS#HSKUg*qhldEMqPFnYEjTFT49 zKKMGFD?Ep}S~dVDzgJ}7s8!b$*wX&$@gOhCE%(^Z!BiFOz4695K$6WHdU__Nq5CtI z-wjDVPywD|{9;3&-=jcfIE^+!991B#j}U*LJpe*4F5b`Yuncl=eA@R3CO^2E27CK#LRsMxNTaU--Ua7vHaW zPPMvd1!c!}*F3K4lJm6B`*jO^uT+@4ToLed70@)4ijPq!Md)2E?^#NGZPYzq|5={M zba!7qvDiPmP2;jfmuH`Ew=KCR9S2A$&P*?Vd{36G1SKt7*UlSP$Y;-M*X9jMGgy$G z@bL4M>BE-ko8uIr4~2?Tm^X6C(3k5e&6WvnQey@JU$LWQf#ptGH@X1AI4wgRa z9<%`UX*eo#kj|n6IReQAka^ES6F&=3sTN2~QM{;Uk?i9sE6&Ja6_A%blKyZvR~6#7 z(2Jtj(LiX@Lifcxdj+~!Oys-CIyeM&zQ2n$i(kW`kEMAzx$=}8V~3s8HPaaWocivH zQ!5I0?5tT?8w0u3lv{kSk!!`bLmunu-AAQtgJbXrwSAo@b3ZnRfkh=35Bj@12kwP| z1QC(*X|^g$3ellNGC}E$yJT9fvx{r!+{Db8WrmZnW7NATw@u=O)5|-vHZ8|u_v8by zvjPS4cXQJ@2_3Iry<#`2TbZ5}B=%tag+gnK#0tq0q&5 z>Fwb&v}4WRW@O=lzl;|81gz>VRC$ zA2Q30tP+oQ!7d~Aq6}@@+y-B_0d*pI)}3SaT-@8zl2t6BU#PBoj_Y7W%U5ll`ME^O z6r8;3fOJ>ymc^HUDyyd+(VBjhN4KWi3+FYew2|E#(B9?aBWFQD!HE6K6p$Dh=XYuX z>~wjB>3Tou^6!WQDpuBChqtzkVxaXL?n5+i$3>4x9K)tH0-%@~7x8pFu6B|E3@ zG4w=S*YLW_i)FDeiAL8|>@Pv_Abuso@U9p>oeSfI!5^Hlbu>arOsVE9;wSyYBTiN0 zUe;_t?Wn5}bUj3Js*D`7Acls-e(~|#=zW1WzJHI=)i#eW6iM9_Hv@RX8 zAyVO^`?r1*4*QaWA^uVPhtn+)p0HtWSSgg?S@&;Ry2Xtw19#THMohY`jp3avQHHSS zn12kw`0nmOq!dZ@_u7(dgGfcuj9(@1C3}yj_NtBfCW% zmwd~^;JSRgYqtG07F9>CdDw~GzJ*N;zo}vOAk2O`8aIR@KM$968!`{UDl@*=etHr< z)2U8nzUi|E;@Q@goPhh>kdiPt;}ICfnsw6%S5=3)H@*ox2S!s@5#EC9F9BB9AI0|i zlU<@R@yF7XPSCo$V26@W)_+l+p|sj_>E>S zD{kq&H^JgstF*+uTw z1o~x8JT4#Lwp$QRECyRX0$#~YiWV-#;K5RsB0qX^yFaD~d)8bIB2QkeEd^%W^H)3O z#6rT1k}@)|i%SqxXz)qWraW`>ZY;L7@y!n)3QXFt3D%_*6p#-2wc;u{l~p&18`(Utj+|` zNj+1f75{sRVRv4~{-`;WfZO+x{-AY!Z&{HJqlFXe9_R+aHs4>)+unhF&i@=ldado$ zo>fDsQ)8+-I6#J=V;Ic-D7ZWP7+ADTM%-WE!zoRy@sn|7NU)YL0R1Xb7@Bv27|sM( zxijLE;Wtu56oHY1~w^fq*g)QMXRl0>iwlX%2ZpyA#T_ zW{WG+d~LD%?T)~rw!d1(xV7rV6WX>ecD@%}XdY{5Wn5-rhf4i>xbu#)&0e?)_e_+l z!3ht9e@h;o(?-8CX|Y-n7=pf>R zEk6&seF8E6G2Z?nHj9&wRBl$Pfnw2^>he{H8zi9fHPelXQkXkST7>)a9gZp{iUf}Y zaUoG8oHj@IJd-@mUZK+UF^N`+B0#`&OR3m!J+R7=h+7ZB8)NT4Lus`Bfc`r`_Cdna zo6`7b&Gl(wF1|kk@{#6{Q)s|Rv{WQnHblj4ft(t>%2mmM6nSO4baqzEUZfUel}V9O zDqFY{t5`ulFLkWD(~KZ*V@1JC{7)GbDJ39fjE}E-1a@RLVq95NgB@IQ?V!@eq^yQ}{O!ZW-uF9-`@X_B%lauyXcA&% z;ZSZe);}W*&dV-3Q$5&}QM4T#18Qf^nl?;W$(Cyt+C~E?Agw_+deC0zx+)@HS-+k$ zx!;twj47#f3<~8)i4=8!S}z+l85f5HpMA|F;18liaHmCnYZ#L8$tJ(5RH8*#B;DB` z=Cs+VF^%a7Bd+~aDbjl_1=haKUl@Z#G5CB$241f&wOz+2fULuKzGDxIhqx~jAr7yj z2j)B?Y9kW@jr1Fem{yY|PUxpdazmt9{9toUUhzn)N=~9K-c&O)wcb3FrW>`VxOo6Gcv)gkWNm3K*y5?6jOan$V z`{6hHfwU6AkV#+_z*XJwI)SLcr%S$o;l+ zAtxi{MQ@zTzd2*hrvQh_w*L(YU$3-k)aQD&UFPBG`oV^IxN0WlBwgl&j;)ERlA^gu zfaJ_J>5IznZ2V{%7M2s#4qN3s@TRzePEN}*8MZXtF5IoD$oc;TjpPmueR{imk z`-c7TSQkLk-%w3GW}f7+?w1z&^u$-@$3XR;^Jq;}LKVoZKiA@Q{0?vR^Az}_x$lwOn< zMRV%SquUD1NC}gO-@`$^EIxM(Cu>rBH*FQo8{QMbfuKWY&dGjz%z3 zx@M=QO%!+^7ykD(V94rR^(Q(nA~EMPCPa1Hu*uQQs)eP} zzKtg?C+A_;a4q+92UGGL_pl~JUiPO^t{o@k7m}cOkr(uxQ?U=?7_*SDlX_DSlvH|o zdV0NCObf|`Qu^`k?Z^aZu!Rdl3!@`Z31E)dql`PljBQZ}XVyi_$}*lY{SAZrP5f3r z;g~(mJ{lG+%OFzBjtP&N6rbQ%iQ`?bxX8GPm%ebHS?kF8Gxu)Tw(;gby0kV#&G>Kb za@kr)Ei^@c8vDTI{zE~t++=%NbZX2DQ4yM_@{Ua0ta+O}yzPM9xI?amffp#_@;>gf zKd&~GGTdh#hhX$>cm3)1zIqG|+#J(sjotVT#oikk<9@?sMR|-!R1l{t(9tiM z2Ta(h30FDKn(B#4>y<&v8H18m6K&o)2%xe;o25`PS2@<{roIwKkQB~`Ij8;`lWk=p@O4o}W zrIS9y>x_3Xg*w|9p6&alhO@xH#G*Nbx|X#r4nLdsxzt1=VJ2ox;km>xk<6ErOOrp| zhZhgQs)@t0X*^#oPW!GWvDhP+DYnvFy5;w9K^(tKgLX;${J#ovE>B#Aj)vx2+2VbM z^OBbKw9@qfweH1H{p@+4F+n-l{PX9}O`)fr2ZQZ9j*ZQ^1^pd?$1OzIKle7n6Z&50 zRMY=?8CclPSV`)Pa#<(W59F$$UvP=UwDv!MJ*x8p*^XFdniK4gr58*db_f=DH+46N zx4cQm`K)YSZaKAH((@MWKN&&w%mm{5u9^6Q(J?PJNYHrPiMrJShx*r_)Cc`cPW zV%$;%Ll0}y_oZ?LznHR*9rO}jH-*+&6uE)zI99((koEqC2wiO?%jvc5^ zexy)36aRA5+&XKvBg)QFmD0eo!NLBqEZ^C5gT;c8a4v7H!u^Mx6m^5d%ul^}Wqqfu z%q+Wb{EW>j)V7tyBB^x(*W`z9LV((IiVi__$mj{hka59dkhOpSHG(@?124KVNobpx zXq23+u?Y(5!E#CPZw4mJvD)h2aWPvIYlS`+F{}MlxWBoU^RYQH5K5>|ra%AiAjPlM z)Hh6zu^g1cnC;aYU^$>G8^JOU{;{x4n=2_{d8Bmz_tD3dKZ{JpEMwpnGNO{r)EudE zP!01tL*pCwtUPf6`C%ndeVPGkQ&V^5>oOJic|_4QDYQ!Vy)$Hh@$CHj_2wlM~ z^SJwPB4UC!cA5DFvvnvEa_Sf6U-8o-(&6*g60EInZ2J!kP3s&q>#KK9Q!jJx!^QJ3#z91Qu(WM)* z>Mo(@zcvxHgi1H;OYiy_J+(+pOCd3K*|NxQ1jd@Zv*q8CA#`BAdjC-899jBI2|a;O z+Csp5B8;^ei*MAxK18%s%*!J;7E9HHUZo>+uG8ytiso!Y;CGzxN^s9o)!oiz1>Y|} zc507!rR!N|Yp-u&vcsE05PKr@z+TBLMdt)=#H!HI$y){Wb}aM!1vt6rq0Q<*Ytvx% z4exs6{o$jJe#7Urb|?}eD<~+4kuBizrEB8jQQ&Rjb#CL8{$r`@U7_o63(YqcE==V8 zeJ_p6dpB=eTMcNB{xwMCktDs}c13Tnf_uK-|I8Wzw|2l>TKOI2q+zA&M@SfV1O$Qp z(JKj+%wT-fbbS7=7Jx+SWH`Df8kO~)#_2c*IuK4c4t;StAWUs(%TR(f$~6Sc+bV4_+WnZw0mC~v9)fw)MlJNOPV5CK{{BIb?;u4` z5>V)*`Jp)$2#YDm8)25@@^y>{VeHteN!aFB0g+z)Q0Tar?dtRD09)Lq)Y{z@ zQ$`l9!N!Yr_Hy(h9MgFGGHdl@hZUg=gtBG6Q@QrQub+gD27WD0JKic8l=-nAF3tEb z&dKmc7JiUggyiUXuo>4SnsoHjGLUd}Q&j^E{l%^`47h!A=DpY?`1y~IXnimM3F_LP zaj(@X74EGFMRDYAvgD&%hr5z)KRu9GA~_Culicw)R<{+C^Wa+saTIDI+^M1H;>FJ} zJw;fKyKmz5@pl0Tdt8Ou;1-UaKUsUVB;oBBp@@6B61qVeCd_=ON})$%`wP_5xt6{KAJBYSwgCD8HM$WTXWrsrDN@l_{1j-}~u8@x>s`u7yj0OM4%z)&3i z4u^p^sOu#>fJ%9x)BN?Q>q7wSk@0=3>nTV=`9CE|@luQ=WV3tPUp!iqt7A~Dt+#P` zP5Atr16&02M(Kmjh{e>%E+=CUZcq6saPa5}RyjgKt8Ea1CwYo*1wm2ZZdX-1yxziZlbxU5LRv0Vz(Srx>dPJfAvJw=gyT%wK+QaGDuUgmx18Uv|VCQ_EkxLblR+LWSE&bDt~ zIL#R>H@>M$xF-;{ibKM^fE?pxt4cZo*Ek~t6E46Pvs&OplSg&L97P^COV;n+?>;@4 z#^3NWwofEF4ZNZbE6YjX>gc97i6F)>b6HbYO15_x?y%5~3@~-5w!?P95ok6)Gc!w> zj>MJvPT{9fPNj6fCd9haptl??HfSnaD67~c5k;YBV9->8AIO;z(Hv)7-I5Kl>h` zmdBSHh`@l*U=^&b`FUC0(rG(rD|ox_quDBMHPWwb=u$D<)w+CmI1nWq7vG-sZ@e@T1i!Y|aNFvI=|!i+^|8(382#;4K}gp} zTe>m~IH8w{t@e9E$d8+`^ZiTTjq4fuK6UGin=f5;KQpe#mvK&?DgH378$KQc^xR40 znqNL9jq*N0t1K|8_@AkbK7AdnZg|T3;2Z4Gpr0ljTR3c56Dlq2|wWT`9oj#>q-Nj z7^jp3vG$EqsnX(ITq1}BZ$)-H$weE2WKc#^ex=tPFlD7Vor`a;tcppgNz-W1Yws?= zOTl&U7qFV!S!J9(g>ycwXW`lEk$9T)_Zp_)Pu%n&Dt)YcFG7tY%JB?(M(mQ{nhn8P zr4pB&Q~c_(>E)$-Y2iDOE@P9*S{D-NZ)gQ?=;HFj;O!WmokKp@hG|W+duGe;Vt~*! zdXTdsCca$A#2ZvrCQe)l%wcH0a9#c$UH|$c#O{EHjn@T(Tcm$;8bNx%okW0UM5BR7 zWJm|lApJWq4bm}hEH7TB`$n=u%#vYPb~VOvqG+E6&1|Q)g&&w_(l)k~o~T~<2rKWZ zF!htsILVo`V==!85F*1KbYuN~Sf_j%=^Cu4+Dt@7K;#pM;`RjdJEd9*FWGvg(f9j) z0Zt_&uiF_C;DrAXZD`5(1wwkq1C-E~e zdLuT{fiBzPZ0PsvU(JPy>cx+a=_iQyeoQZut(jh*2&L0Ow>d3On%XKmkMv&UY~hV# zjTXs7zi(I9=*Z1(1$!#+$5M$YRvK6950NwFs|vH@3_D{JU)O384;O}`;+Wx)&=Au! z_~!Yg9epR1@xb-AgO+Yq=1QA?Uh!hH(hO4OQZW3SeYRu!RU)j0n35-nW8^7IbZ*0JPi-P4M2I#S}FVNIoPKeoCr(LDjXdrlxFm!r9k*9$~aLJ z^65oAlGrqQW)NarD{LuVl#GWhL)sD?{ZuvAzX-{s79&A}GWM$u<%nlf_st06d`1fi7n^xxYaB|}aq8$lLorB}hMN`)3sLF)%0Zs9!h5=}VEkM#@}F-X2WOUGNO?bP2TIy-5pFIAfE)#4Vr^ zq-vui{b-ZCUdA;Q@X6>gkDJqUv_A)vV61Su{_#+gr6ZexQNqwZ^dynnGd}9LbxEpA zfFRW{(TBNFuzc~GNF$F~=5>;|_Zn|GD*kWZ%Q%OVRPW{51JbXB_%n8AJAAHarMn~F z?7{6YkmIDLR?Qu|DG{2apsZp}Vi-6qu272k#@-M0VlF~&>`&7C)P z+!*sAV)spn)hJ%EdKLxreQ9UsKjda1U09d)e=*?y@9QIMUW2*0b*2OU8)U%^ zsX9aTBx6j?vhQoK2PkP%c&K3tw!=k_W)F5|4>Co1FA!s;A=UD1=7hY^ioL36wa#cA z-2%>@lkDvf?oSa%pcJ!`;PsYO{ry$yeUF62CHp+re1mKnosQesyFtBG_Qa&f*Q%zQ z?5n>tV=RQ%7_lkgxyIi2I8a0m|y-Y1{V?-5(mTna-B*n4E*72rYT($>O(mCw z5`Sm~6g##x658{fMXgbp(-K=l{Fh6(mPb!WI($YT^G0V*lNEQoCyqPJq@7+q{09n0 z6hJPq`pW|?zBI!4c|{Up8X#3sb6lP>m!|(=>m8#bi@tr)4m!4-R8p~Rbc~Mej&0lO z*y*s7j?Ip3+qP}r>T}+G_x;~J^TV$FrE1jJdyKW#oIkOa;ABUerXiYX99PAi3F|mb zOh@oqBQ=^2+VCCoS2r!htm<6onL5>nq$K=Q&*NU%8JbhfPV-=qS5LH@d@OQ`VQcW1 zNw0wn5T=cr*s8_(&XY1mgOc=vP3X=iX-U3t(r};0aZcRbsi_|#{2TH2(6R-mvcd+a zy4NjRi>P}|9TjmMcj8cpwYf3=L26@Iag*pod+>aI4dd6Rv`yBcRN{2` zR(uUEAg4h^-{-yC`e}2cCCf3?S3sm$Wgot8ux6_10#NNWgKOx)M*xNbjlKe z24)nXm06L=<#den2nX#Brhr_Xygz5x$qGt-)WJ%`GT6U8kqz;eBmP5(o?HsKw6Q>^ zkN+(1{;PV4cD=);HN}=*qDy1}LspyZwsu)X>9!;r&$iYZun~)Fo@+C3r;qC;F!UPUEZ=QY&B4mqSqPp;8Jp2T=;+Q)^R z(g!lJu=8u5-+d#HxGgGwvdz(Z)k(*Wz}RRTW}8G@-xJ&S*=T1-g6~sz?)p!-^nM3O z#t*xIn?D7EAq|_ExJ$#tiuEo~$Z;niWtAhY1wvfDf=6H?o!+FgOe%Y2v{69zJWeAE ze!uG#>}gmXDj;tgB>oC^T(tr4eI{l;WF#3ek*j*y7j+^$d~Ld6dFqw}k4C={r!P_3OE!U>u-zS_5GEE{g5g=b^_(8C*6aS;4tsj& zFb#wH^i&h_VPUvP{>v9nRZGY!Lg_|1R)39Y!PQY zXf%LOA|)vYSo|{2 zo9)(<&%+{LKC3ScxQisMkvb?-E4}lD02$ERuq4d$8qX5)gtpJ?GjEFMCA|j&*Z(sY?S*MY z-@6?rgUxt7QdVVuFs50l+uk!NO>T-moB8rV{3BgE3W>OoTeTMv8WP{i|Bnv!c5Kyq zB0#P(@v-#~72KQJy@}@ek4dcSiN?*g`BvJ4kh*lSonMe1U*7r&8nV*K>7x7g=Sw5O za?8)=E7Xa5e}wLE2)hr0#tmRPw?BJIiC#uQv=yDL-XK?q?&Y=s*W|;EMcOaZmRe*p z`jCflRfy&ANCHGBtJZ?cZqu&N;MPQwGq}hkNvWwTmei)i12aoj&J2M!K>)p1t zJ8N-gZ(l<{A2tm#=*Q-*(vr(y*cP-Hl8bPUS)A5SlM;x!?;!)A^P-%5fXsjH5hps| zk<=^ow$s(#cF87Z_^(jNW_PZ8>*&<^6C%}_u^E0;>4?d5UUfbr)T*trPJetGs(t%d zc%0{Izw9R3Ja@Hd;J}Tp1c>2JqO+Y~)~ksc2z3hX{FznP&`LM;Y!Poj^T`9Q*-rlW z9ufqN%*xvurIh}vQw{&Gjj{cIaO{8g|ED?(sS3jL!h={}nWe;UEhD$>MK=*0yi{@F za7=JZ({8gO-6xD3T;mIl#b_RNy4rXXe->{ujav~_;8U8PEi2fOkoP=ZXM4bDR{W^c z>A!#BO5Bd>&*YbIJwPN7fov{DS;lofR?NG6gLyxaI@>QZ22t3F{YeUPW%zh_2Vao| zrCjeIZ-+UYu;qIj7Nw?#mMwaK;>|O-H#JG#Lj^n-=Y`%Tv4ocRMeG4_Wf+fE?Lv zE8bqhx%r|Oxxv>KsKUQP!csU-Sfg1H>cCbDvle*`6*>B&XHzL$@;u&uzs#sI$6!+b z;Cswb)GbTFPUNDT%xWJn4}QnJ3|z`Imi~F^26H8&NBWzYB5QETZhSXCjh5`TP-y z-~jTaH+L-I9dVy2o=)-gm?Qt^k%=|W|l-9Bmj z88Ze11{SqY-1Jd)zn5LKl8xYqvC0b}%lR&MWNwr-($u9MsitSFv!@_|H(D-+r3dl0 z;49(U0|$fbv;-1aDd%|W;clUs!lrxZ4+m7g!hmdxy@q4qy+?t8ty%<$pJe?=Rje=9 z`a3$rgFpB|^xTHK?eo8h!IllM>6HSuio<`H_}2z(%!om=wp@wdJflTmU%Ud_74 z3ifY%jMwa=`D*s4!8;w$U5w%0_3&+ogvIUORL+Jx2I3Qs4PC~1>kCeW=~ED&964*1 zSLyedYMb*5QOhFn{N#m02^H92pjEu>Top=qa`z4Ld5uvj zlU0_q`ZrK%E&6W`&Hq_<{@r!t%@yGhC??FGvnK$zquRq0Z6_C{w0u+Hk4-k7ju5kX zZh(}?f^R~x*rZjB2!U;(EK-QsMG83vcEvnR#N2{msX$(M-{oIUeL(;iZav~fNyXmR z3p<66st=jH8Su(k^4ERsC9B23N#L|oSh(*U+NPj$u-PB923l-xl&UXVFg5ci=rqA- zZuARv9ON864Az}J1rw)`r6b!boZRfU+PnRW-e7#AHNp1sppCD+U^M%Yb0l=M#en!tA@2&6-_l7Jstglp^XurH z?+rvxj2b_nnBP%8Ze(EWh-iVDDU(im%cX;`)?Q9g<|QRBsv|9;CoE7FIlc>jFzrx} z(a3cR&yqWxYZu2Q0o2DjbR#CPGM22N%l;q`YC$t8E|?~7XOZd@8r@nDnZhL3mF{(| z>fpi&f3~S`euFI~BI?e8T7y`^lobu#D6>CRK&C*fyzVhMrY*y`|5fq6)ciO)WRw?G zI4@+wL!K7!3)ZaUS(&$%ED@vanpLGu3NBj+6V|e|2jsjf;hcbU-ITYGDvqsmo>sTmgf@?lNFRu9=bnMDL z%&bG00SmJ3>O#1=EmZ%*ZJD@|q!2=C_b zv8THcG%ue0w!92(=G0v-5Xp*bX!Ny(KNtbEK_rgn?7k6|RifLx?;gJC*VnZku)Y^n zo%9WD9ekO^D5z%_X4$UC+t;FuftKe*t|rlig=|>$8$mis7zkB7{QNS!Gj=V zL6T7=kh3kf?-|!5|098Xwl}1mhoD|M%ZbbNimW7Sl8X5`7@E=AQfdpp`LH1u&C2Qe zQ*Z1ku&5B|vpEw*cqkF5(PNO2$EYV>QK^K;-muNlQ$dnkKk$8DEk-dK5{x7b{3oni*&pJ$U>&)U26S8RYcbJ|?SS zg&WN>cgHsUov=i;~ z+RJUbg#E;MK09rJYv0E@C{vh=pmx1OuGJ&v1r!Hh+Xh8VUZ6D84RJenipij-v46Ag z(y|U19jzOim~(B&qH{tB4Q0|YwLD>(w(*}HdNTB!MSFuluiVUmUX0%c(*AtqbJz)%drGc&{lUE!j-K{#QBjdf9E zxtguiD+;Nf9XI9FN_3gJ-JCQv`IKjBgVKVK7sLz(Cx4FmpI;b%)8hu3Ue==P*}IlG z7Rn)z3?M}DNXy5_j-=9NpH{@h&J_B{rb72c9z$X$UX{FpQesehd~Nco9cm(iLWQ! z7$&+DQ-FYx{)9eY{w}287y0M8 zT3@M*QAo;^hZKnol&>Dw`Ik#ohO1Py%YMJNebng$xkH}Q_u0dY0L+kg*5C?niAE;K z+B|eh67<;;aVSlEeO5O{a%NjK3(=nM%T&6@8TKdJ8{nK|w!S{Ild<9$)o^qQ#w+Eu zU!_A*wa(P|QRkgjqb$TA!RO)w%7pNQ*V0TVNGIk6NCsO{($`Vs^3}B!U8+#_w zOv!DafC0}>+TAN(D`{Gb@y;&r)IWk&@h7LHhu*ZJoI@c?mN+T^9~8*i1MW{P?*4f%9{_&U8TonP)yfmoYa zHqeKC04TEc*UKk2UT>%tzn0&;ZW^x!lkTefLz%$BR%ui2ia@eP=)6Wb)BS^+20F%} znr{$SxrZt?`g`?4bV*^17PpXCcl2E66-NLP@#Z~-13v9R!fX{ZSv~#%};W}9sarfFs_Jb7(1M@ z1PjE4IYA`A`xa{52rIxPTdhGxuZ|m9)>lCEYc_wv@bBVL$1Pl?im)vERL`gt&tOB! z1n!KrKOy38!9Gb5JXfhP6n(K`hp$B_Xw-y%6hj+q+a%q{Y|hmP7Pw}n{SEvg7q(ck z?s&As?q(?dl#47|dGEAL!6t?nY^vv%m~f3e4YzDhauQU`T~DU64bmpyf_cUQMRVC} zmA(=Bz&IVVESFWqXLb7XxS*jD2#dOP98#3{N_*s&kV~xC{87nf@E)7XaIbC<4vTP0?FM2(R;NC3}CFF6GWDA#yJps zQJP1-ebnc-gUNAf^@TLaRel&{dzSQ|b!OLsRO4}hE(vxfDQ3VVeL~`vc;L3#`%9mO zMuxSW68!6_90TjQo;}0U&6fSHaqpYkDFPX5Ud{uk{V9?CGBrb{0#NqNl9Zsjz8;N9 z6cyyI6itx~etj}xngKwUK`+Viv|=q%lp`*5abro}eh*`1>w!}CMWn|FDxW05k6TWn z?))~Mk#}$?B@-dVrNkRZ$uCT}6T3esALxW+hDbrkg7^0(iD?^M98skLs)1%_&1-69 zVBYMOW^%O=Go{NooUUIsVJZ-YM!A`Z|A^ERiQOywJ3I3Y9E&D2JEGGo$~%K|x<_(D zLvtL(V|0~G<9U!0`KQZ;Zr=k%3`Dl$F!=$Rp;4M$<^h$J-;9+)=%D+x>!e z+goC)g$+B{RiM9Fwnr$ozI!|qf*q=N9u+BqNcp&!dcmBA+-N`hRt(N=c8Mub$c`#ZYa&Kax`^> z3T0KbY`Y&m0eHBjmk2n^arevQ6GVL9&cZaPm&+&72SgU426a@7ILd#6sCCieQ6G1c zS9;z=m-zBzF#^F&^Z`~08fFz_KilvhJr;JN0_cLQGmEjHiucLi4m*RI?P0x4_8C~J z!{}1osm`~m^zvAh>S-`HG~EM#f6AN3Pk)))LHjT&O7l6eK)TT0(cE{i_~Bu-dX-2Y zbO|MDAWp78^%;q}L`j@7bUNGrBm#r%x<)S5^YDPRSm`T?b7wwx>0_IqgaSzvhRir+ z``F~{kyTNFRH24lfqC!wap+b^bZBAq>)L^>co91-JNsF*s`(#4bo$@?-~Sx^Vt9uP zCyud=&b~fpCbJ7lA%ZEAn3?)*YYNV|;Zoa^0=fRu88MJ&muOd~Iw4y4vN zwUwHBDn~7Vak(Oy_Pc|I6np_Q^hM%THRBq)@(C$byOQG{yNXXVuIdaSs`SU-n$Qz} zEF~M<`q#SUqzh;s4&75kO_g%p*sy zA#~!l6_KpbnNPRoDo(k2NdkiD4Exzk=tfM8a)2aRuR0Rcv2Zw{n zE-7QCAgHLKsrl9^`zAsqLg;Ib2bwm+=l)*LN>yk5gNboDvadzLMaNh^M?s=>Y?+>{ zZxw*81CGjLpU^{wG+sDn_RQ4{H4VmrspBE`tHt(3ryV$EwTj-3^yP}2K;YWn@?@G36&RpAoTpbFjU%eJtn*kiTp)N9PVIl1uo4>}AsxfvyU>V-C)T#;7 zf50?0gyQxU?{E4Gcm!%SAX!A2yWO1XCGAsNxq11p!gC3BRqB&P6iSxWnbTjt>-nZ4~Vc=5Q*=rSo) zx?5|@LEc>alVQF?7^8Gf(Z<^-*SS8%-$K*y&}{C0y_gH#&!B*@S=Cv8pHx1zV|6;G zbEBgCS?ejLm4TChV*XS7zQT3vbv6v|i? z)%~}TS-mnLOCX5bizt)qse%|#csvdAk%zaFuw0fBZMOxyVvetpElI0^QF+bhQ= zI)!1Qi)|6ldtyFoRfVpJ(=Pb_49aHX*#kQNzT;4?2)wo3Q z;H_;j=0KM#wDdl%T&8=JR>gJKF5SN)$k6}X>2N7Yc;26T4RZp1dJ%N1-?U;)*dQTn&@eJ{4RITJ2*0ndC%=~x==o7Ss$S~osy}X*<+zt zA_aHumk0)HJ!Z`W&dJggMh%xW&9DiofxX5pKuNN(!cUkIrd?e|aQ zY%=P6tp6hAOO_7B3+GeF5B!3$?G>z*ABSWxG-&!DzS>U0-Vl@HO#^=J8ivvC4p*OYt?~w4(5uI z#^=AqdhMo0J&hmi=Z_+!K*|M6C8QZ2@BMA+oS&6UsNaNy*0y zqIz*;vT?1=5Dk=#jqoU0t93I^cXTiTJ$Vna+)JDE2ML1_Rx3dReN9A3#$Ud{jKk`< zVNb7y*+L&T{&s=u)g4;29~PhrfFYAi%yX<)Vg#PsLZ6%uE+noL$FTp{mCeK@&y}jT z52qvl+(RF$SPj>TK2@fC9v{Qy`L#Qd8o{=2brGGp_Z!LIY2L-6A|)}nFM zi2K~YH-o_4?`8#p*b{}M7J-9vSkMpo6l$oI_KC3r<`w$rn0o9(fMc0lw^?*@0LQ3l z)!d=cFdPYqsff~k7QNUv=Ov5C(I)nxh(Axxfu3-#to{^`yvmuT**YGzA-ZNO+&UgH z3qRNK3ia{WA@Xp1m{zt}V~V}JJctPO$JZ^h_0bdOa!@fLtzk(o=S=-F;r+npMqZGt z(-AS3El*9X^98Q<{pl1+!oPPAEn&O?hiq zCjVElN*zHdN&o-yhPdL3HLV-&KR%S&P0G3aL@yb(AAG|XDk6kHzx{X^gaL3Z3v?S> zC8P_qQISJFb%?`=RHc#zd#`C7tA{RxjA0CN58(7DpmaX)SVepIK0gvqwfZJTOmJ+z zUr~+`mP06LM;=YU3sjB8_cI>~zJ`x4LwT_no(sO?-G0j%D9nEl{FHa!^u%m!5Arh# z8+c(DklIN`3JOB}?tBn`jbWG!a!812@xL(;k z8yMrXU==cORpJ>qxTgham>u4jqj z&@f`P_>b%CtpK>I0(n;R__VYj=N!2e05fwgQi&HL-{&>_p}udOmYoV%4$>} zg>xOltA&}4mj>{!YVipkdsXP(C?(yxe0;ilPLrCal|Go2W!qg$IFya|4v#Bu00zR&NSTYj(C zuq{}3F@=gby&>$D)Bcwr3~1ALcXe!>kiO*6SKQ_H&$>bzMdV_r<$~fkl-QdU)H~8n z-Q?8a#Lj2zCq#R!py_K6a?{-h5wAgrt5;0BXHcsRF>|v7zv`UZV~LLbA73-XWNQ+! z2_}rVSxhcW)2513$@UOYN3{WWv%~O>4{Z0U_CPHSe@o2Pzj6;{`n&BPme*jRBsluL zA8(Xgi-Yk1(U3jHPrTN}Z=G+Xm8*XCIlr0bm=l%v zB3Z*P>9$j{&GZE%P9)}dc)br(KZmS4q`!*_MWMmE+7LGS`BQE=Z*d*+`jR7HbJ*QD z`h}ci2nwmt=$~-;XkK(qM0@jp|HHdtbmysivC%F|P_=uUccM(RBZ7>KE(Vr;s8|uQ z)?C-WPwU3*V3^+A%%Pkp3k4yQ;5jxfI5>BQmi=g+Y%T?=;ce>vhJ^pC?7oPxr2g>r z%w_i8HPz6vCj zMT}(k(x^l35n1{Y{~AsQO}I^SPYP~2)q7sG)q_#WE?P+v$qe%5)e(ZELrd6 z#WVCnRLlvHCN8r3aW0j>Ml#CES0xGLj&VBtFlN&KI`j>w!s(w9`rJ4pZ$=rTM1}=N4fbU>y|0)5najzB z?j$L~N}n(UhdmSg>!(;_y(tGdGjoj;(}mvr4+jD4`xY{4SsC5A3%E=3sz(tPIb=eL z7ED-caHsHHRzg{a+HvdWJOAD(U6ps{@y5p@Dn%o#LZbYKuUSvH)3BU>AbAVsygr}#dG z;WXE)V#&n`(W))xXkH+IwFzowJdmKFi-+qpT$#Oyh4uh{I4Zeext3N3U^T<-v$BMJ zBSBvPVW?mMH*7Oyd3XH377M9u-LM-QqN6$O%OK_^I25y|Bv?6l2Xo$+1$#R@vG|Yv zD`#VW-z4ArWpS3uL$)NBjS;d|Pa;Q))css`24qdWOt5U3H<>A(#Vvcfra1wkRrx(U zBTF)F8tyE>VJ}qeX3ds&*7j*_0B<0j7Oloi(k-rk5EivKpu4)F_H66;lZo^*uRLDq zd7`p&hJ_2yy%BW#-IIYnPVQJhe%n{=1|!vkz8b;;T8X9XprnPz?G6I%L#RE@s_mJi zw;Rl{_14D=GHiPp%A*{;0iK|h)q=&`vSdowg2^p=r1r{8HrB!Vs zw^t|cP8kf}XRAM?V46x1;0FgQPaTDu@*3K!e^$qf7Y-~qQY{+HO6E@r>eZB#lx~ue zcC`L20{>CNoZ+r@U%`2@ke*|}H;dcZs4~BlvO-=A ziaB9ee{%iflYfFJ%1%0rbd4gg0@4YE04@9Jx`0Z6UlgtCdwx?03lidJ06k8<2)s1U9nSm zn9J|O7%+}ot~t1jq$CSqLEeGP54#n)f{=u2>Ly~)4r&Ptr`Y}-HtN|Vj)^Jde4@UM``)PrV@WsW=KR`Q$#)+oS7FQoshG|V)Jdt9F60jcD`0}c^{ zCHaaJg~>vM;O-kzmwp$2-iE|7zC(A|WdbIk?`{Qxy#4#PGDYA*6bp+LRI%7GJjA6G zrHd&k6k*-B%*Zs0_R6}ux#mwZMFiGX2eexmS|9>Le@~mf8!jJ6x?TuE;z$g z?vmBOw9N*c#2jLVYJR+}nm^MU>pI$iwxwZ)_wvs^Cuy13boG7>5sq>J!iZw@ZODq> z_j86Dl2mRBhKWhu)v|y6Fl%{)Wp~HvNbB|2s@oy=mXhUBJ|Od^yOzPK!|K-a80L@- zJc$-Av78hO^t>;(J=n|rA5d0LLzwtW5p3!WI=@1Dg@TzTZry z9u}K1=H3LG)76p*&XNi(%xZro#BWk%{8ORaF8q5U+fKi%R(YvRR8J zuFP(WP+LD^UKstvR&8oH91?ivu{Bj?hY&o{6yQt8`a&`Xss$FCF^{ZCMInNrQV~xN z@r%(T!^H`|EL(y+hw(NV^&oya;GHrx_iIU@P$gmfKwyaJZYEv+P7PAV=;`%j@`vee zcDZue+Y+C0)X;i`&&zP7Mm+{)W`{;jCNk1*EpSY6+8Wq7N8CVUyD8VJGcvm!vZ(&b z?FV-6fWI`TUv<3Gx4CWfu&ruXS%jranRsZLDr7*rfG=D2sH^yJOKa6()nh#>ImFt3 z(v2>yujkb@3a6K&hzWcs7tUZ2TTXwMV>4&B(rIq#nV9egN|h{VegDodYhDi zM@>!r%owetLkqh3&w373tXgnCe^#$ir+-a-(1hhU8ri53lrLpHj&IV*)suX^c%#@MzdqDoj{l_QByjs?aYUXeHE&~)@X2D#in3`5l^HR~G zrNY{at}*`A{m3rOjMay>y6gJsqvlCmm$7!BbBe4{-Y!h5Au3=LQH%p2shL0D?;rp& zimAQP>bGKLWJEirASw1zhHUwmGa@W7lcc`lm+EMco4Eu~Vof(ttTg8xu*ycNI-FzI z`V*+~;aR()S07!;?k!O4{J`XF)X87tg4Zr<+K{b%Kq|dPlg{q4`G9=;(tbx7ZhvtF zF`>NnJ81nAMVYSEt?b7dUgL*Bz7`9#L0s%-RM>GKlQ#aR_K90b> zsM!T+hl;(Ynu++f3B%Y&UFy%WPjF0Z*&B0^)lg$%P9v>kmNL%5rOP+0 zlLgR>I?jCixug|f{guXR=z@c0HRwS!K8-?@xd@Uyzijsg$IMl6gF16`C{bSF12;dN z?tr-9C*@Gx&Zt+^9k~fW^RYENnztzex0u78l@d6>+SU^645F7G7=OHdSqxsYAn3 zI(1TbDhk;Ycl`MnO}43TC+wmHfz}Q73%({Tb}5)j`Z%8EK6kg%|Alj2tWQers!~vj z)C+7(%TT9fW#y|S_emu-H?xjSGVZ+o_x9~b@IPc$=acJHnRa96XQ@9c?WhAO1HNpv!O_Yj|I#uk(YO zcLNe1ag?JhO^1cKDW=jhI4>~CF)jaL%e|Z)>(>8TfO%ji6Nj>IpTUH&dDPWAsC^H~ zYZ&f)3v&ENw!!x`)(tc8g3x&b*ZOd~un12Hd41&`vN>4_F@=2Hp{u3Allve#8aPx~!NX-1KEy zrkX}XlwNcnC`=$=GvLB$pOLejAH>x20&%rMMMw&Y{hn(gb+3<%cF@pP*^#2|oCCiy zdc+r7&sKuV`Ep9PVh$N6o#UOhk+hQ3Zj22{l?$ulkELIMa?2Lgs7%ENhuXb8FsvXf zSwFwzkf0im#6I-ehj39Kfta`iav~}XqxlHMj3C$N-yK=nyj{1;>Tk-N%im-0`%U8n z)RM-S7OCQw_Y9^1Domr3k5-`_639h~PLQI@{}k4FwYksvg7%HIm=#l&We9q%ou}jG z*i;v3hT*+UqFC6JmX&YO6GU-wkK5x_b=ukwY2BuN1j3hs_WhqKwS+uamDP|r9 zdR?p@5Qe)=7l}6mW&Y>Llr*Bc6-f`AF)nGcBzvsts>TB9HIlF_27A8dPZ_kC-!b!m z37n)Ng%|h(lnPX>Kl)And^P^XYQM_o%@_GtvDWjqN{g<~ z_?G2;Lu;<>-$F@!=<#EEB>3I1d@ktB@28$FqNi6#qt&P*Ft%nOoj_I|(8LLTZ`3%E z_;>O1cz-u3KkuAwv>TZ+PR|&)TE=0WHx)D^OIG#*4u?GnZ{Ay-+g<8cawot#zBEIh z^o}ldBgshzUiw0Rf36ckwCv5|2D5rMuQ0ovJDjc5ShEX zW0lp#FL)sBy4~XHf$toP2 z_iVG9-Et~Ze2C0C)~V@TdnwsZn61cuJUr9N{GDe+FcxLwsjc~wjkWh2w7htrQMYeT z5~uDx?o*>Jk&^0KCpv`cZTv|*t4+545-1eH_D&IibbUn>*W#OlGi;5iTaZ_V{6@zN z3o(00!cW4?+&mikNPQx*x(%u28TFm|kihlH>~4vC5{dI=@`zyT+NDxoT?du$Aur(aUVF4DAOVzjaGIWpRs{4l)gS=cPv30WE76qbGE}y4|1F3g^S;1m~Y3L zY3ZRcqBWT+5IqC=_?rZYAY+rDRY*z8X#MRqXD6Yba;k0G4n(EvGU0tDCa9=MK6vaA-) z$)}Jwa|V6D<{N@U%=7*@bWTk8*&SMYvxh5mik4kaKi$5tZjJp7fukdu(>cY%g+L%& z45Us^F^@_(jEf~~LtC)BB)jwCcCS3qWIKKg6jn@$NUcC;P30INUp8c?RX0C!08n6NCJtR zHb2ZSPJt9B#xY68&PCK>aQrd+`h|$#ZIzg`+9R;>CYG4pW*VtBZhu7 z@+2YMD;EkBS11c2#w1WaIt_{{!8C|jvP*3dWkpS%nB+x(XB^(9fOJm?MNNUX-!}*? zggS>v934S?4q(&S;>EJTSE$0QXww(+_4vcYVl!ENS`v*JQM5`v`huh_gsZ+736f$* z3W|>>IA+5(a)#(H4#bCaxiK*F{LAMV{*?T|#XB;@yL7fxYf+_0KF6{Bxof6C4gHK7n+tp&yf{tt1zbv1%%KZ8>AD};Kr!6P4TtnpW1x7W3UF8xD&f=5L_C)UlAeU z`-5O%vt#cH?H#c)tc9k!;5WO{ZFFWNp0QC#=}Lvl5Sh5oY=j$NV`V%_IqZuVy1I$V z*8`vTNnLC_QBfb^J;wKjN;J*uYiNmojD4YTS{i|5utZf6Nm3JgDSP=zyPDNc0jm+I z&?4#NHHH)AVEoJAk6*<7$DuW)`mgfLz4|w#3iFsDP{3H`VeWxh$y=jez}qYA%w}7x z3n4+!wGk}Ko0Ynz&T_tzM{H_V&!Z1bBEa@I>?l=_79*!Br`jiFkd0`J`iKN-2=+5>s+SJ+CGFj*{k$+`O7h_OtUh>6_9c1?2 zd+oIgaDbwWVzv*xQp#%f`$LV2j@_w?740~_iNb&zmxYw8p~@Ev`JD8g<4F6&FkOYh z_DHk}4Buw9x6|8hzGTvAo7J9kHt)lBD>N}w#at#It!Fc>}CB7!@2Z=noK$|RiLUg?$%oTDs;d|IJI=p`esqW&sO zmCzS$h1~gleNWkl5XXtJc5r`6OX#n5F)-Khg$?AT^m?Scx6X^vY>gJj<@iux!tPXV z9JrMDlr8qcI@g%g@EMBZDx(T1=yN2C?``4v*ALBov;iO4P zlGF~;aU7I269&=!U`lu08{nxV^K^zkNThz&H&laXLpvaIF7>Ri>tFU0Q@ToO zmrLfDpm@4nsn~y`E&wxZK4E5^Fx&M9ctl@teZdI@=JN3kXf!$8x2iXAeW&_ux6 z#(`rs)ZtEF%^WM#Fsq(O7}=|dEgKBX6M}!A?}YXh!I28q$0k5BLW~hU8Q1mIzdz#_ zuSy)lQvDs{)fk^A35Eb7uLl~GZeCJ~(HFN2kM^U69IB@D)0I zL%?>5w(rCfUEPLc2dvM>SZVMpI}5=?K{#En>WO5)s{F|Od{1Q39gDjF`UM)}7AwVGe^;af|ObgRC*@oxW=m9Iaz=b9~ zWS0kY6mWLdXr3A_IUs(~wPu)0Wm924010X6vOMnng)_hNiE<|A6P#D$A9nSHYHVDa z3oSF!!Ps9+L##RjwSsa<2&;!oU}ubF0ybe1>aN0IDmqsm*lL0peGdeF!6Pq<$7W36 zSdq+)Td2wIIrMqTx4JIa@)mRK&=Sevj{Y3b4wwGwv(1;c?7r2DKj_*P){xO3hW8U0 znc$vhlUt&wu6JRdVWo7$f>RCj6@{3;9As$9|G_F@_B4G%u|L@Alna~5203< zw244qgUK{ITCCqJ?N}o*_}!_HS$_2K+Qr@2!bUVckNoHnX$fTG$}J(oRx)2SeX$JG zDkvP(bA;AcgK-Y}X^uGCNhByRsf=SZ>?D(}mE5m$MaWTJPHGb`?`<%E=Xm}td#(lKJvvIJ&a z(86#%Lc1Q5azGVf)RJ%#xB*8wPTt=cgwiT*T$arDB`e8F01l`HQ`1i?r%u zT8t?iD8^f|YSR8S%PEb|U~04L!j5bQ$L@uX#rj(Ez4qZJH$VnZx`QQ0W>?fS0cFu1 zS!Y$;x@dn}^n04&g0%)Fphx$WGtMl$RnbVY9>|^9CiuEw?W0l(zOD5=Cx{J4_!|u_G3zAP+BcRqzWrYQ;isDQ^x`YC+ls z*zyaF>6D1%SDB*gKokIZvn=<}i+9`qV(Xpa;|jER;WlI#pD!umn=Cl#KEtiI^FCuCV`-46Sud2&K#i zT!tLZP-4MudPD_%-s>|zjqy`xlez&xL!j{Mhg{CV#)buJvu}=`dC1!q%gh~b$_c9w zQwRW+f>OcBX+So`Q}C>AF%d6}4XFqso6*5R#&;k0`t!be#P^=z`9(ETno3UqrJNmJ z%h=U!I~->r-tuc?a7fpBp0BZ>8+D-rp9pM>?=fVclxV@y?kcUD$MKSG@(M|EaoHj{k4{NpiAxABwO-g^H%0#*R+=pzqo~gB5~~w|AM92usS`w*R9WKLz=aL7Jt! zV#Q)ClU}H>tfCudIXdnFy${Cl2<+YM;q}HF`^hBe1Jmtw_&Thv*K5kfK4oAGj^xQy znT;v|Kxu6mcK-A~Jcs&7F78^}8lAnRb9PO8dP)th_JQu2eX5#Ge+^`7HZoM(c@-bSHv7! z{j?}euTjn9?3kxB*B6L9xNFrb#PUgWi9PTL#{v`XfbLZO?7NZm-SUj}W|rmFmB7I1zJVm7x$5kxi;4Sx<^FYOPJu_vcq{P2_HPn`Uio8tci|x2qrEBFOgX$m6 z4^GJv4-*B`i!4b-MKns-)Tj&TdQs)Sfhg{ylnTHAgzV$aKZ}ODY3*MAh%_4H3FS}+ zxWC;XnVI7NaS21^vTM=wi8GZUE##sKLH1xcWZ`53XMTZcmZaDl`agp8#h;})Pnlkc zNIG!k#M92;X0rr6N+RbQN+UBeY5SYkWlNj39b7_EJg?t)PD5mtvP1s_R?H8l#HsQZ zYl(2szz7KM%*8=3y9=U+3{Uc}bxOau3G`@2`CgNNK;e8jI{rGJSOAP>VZ9Oku&@NH z$=$5(;%jR2dPi>wbd=6T&YoFgzgtF$dzqQWogFjU#5eU0!O{~!W~^Q&&G|=^DhiUw z@Q=MXdy10J&v$KfSUqz=UQlH&EOw-oFvRej^c^L{>InIsL5$=le#)qGLiTffB~*09 zdXyDM*en=1c`w(EJU{7sSWe>mjqdnCOg=6;75`DLhu;O)0}Y~_i_+g`D2$bX=AHYh z;G$W1#Z>%OJ0{hMQ7a7Gtg)x2+}aLlV$@2OX8BhtSUo5$&ce*^pI0`sZXf;)%2T&Z zl3A0j2KmNm$mE|!LXLTcT*@e!)smK-f}U)_T`KeSma00O_@o6^Ydg!~HO;Q`r?Kzv zNEsQYCdU+pOoCQ!Ya)=u6Ldc)VEZ(2V?4B~sJ#U^KPYMb!B$^E%*B7N)u5-nMFK1Cf3DTj>jm)vCJ!lQ~D}v3KGBbaMxoa zZ{Qm>yu-vT@fgBjvmx&4H{?&MY`^>%w`<-9PzN_Ml7drRDHg-d!GWZ5-^U5mD>P0^ zDn*HgBdB1a76ZinT{@66IT@P5>>Uut}X@&v`6cByL&g8m2L7ri(xj!VMBi67Gc9X4AFyyLGe*u|<5*PBH6ha7m!YZsK{H7yCOoV8PN5Cih+uNio%>>je(6MPB>@AL}d}tQIK#{(CfXHC%MFb+I3LZ z;kW1Nn9wFUn$m;M$R;-veUNr7$4t6PKx zJe4V<$sW7V0xQBwm^faie9F<-@heZ$z{)B$P!~$?3lfc)KPDFoxEgC4quO!@fW+4) zVljn3Zvrs;1@0J(35*hP3pkb8`#L9(?{-0MyI}r|>_*pQEIsD-#(3!cVXt*|r;x>AHo&I92MTY!Lp#pPZcgm>!2b?D1v~^bQ zf?lqY$D6nAKkUnq_kR*ompGuPX&$$WY1^h>zkYGe`p8e_d_g=VvQ9Lm=4o|$14lOi z8%tl^yX5fwPJ$X7^1R~FyLEM}Trf~2JYLgR2*vSRzAy1;VKkGZG$zQ)Cf5b{WUjIeqTNS;3gcS|d4q17DVx<3!+&73YvqJINBzY^4 zv=Xo2DPK4hRSb5)1fmO{T!WP#mKi7XLV)S3!l+=-i`3u2svydT4vSFmVhF3$NNB2r z;U=T*-ZhwqH2fr!TwY%>b92Mfa_Jp`J%I>6mfX8jsd@4vI+)a*^?RZQk&QY!#Jp}$ zOBUO2;r%evgaKb0Is%S#DD9j<6P)T2-})1EmeBE9R`kAqW~dF+je1M%c;RBL8gHJn z3t0`kCqb~fCe%CPlW916he_H!x7n%>U8%#)lRyn3Wwi8Y=)av$z)X&d{7J}GEtg9| z2W3nT;*+}(mZjZlCi8>y4;CVvLj*xFPnieH3%+jOq`ZOM2 z&(LTZ+8cyhHH;aPK7_3!Jim9b{Tv}mfiU@o0U}_S|kNh&2kr6 zpuKI!p)An2nnPD$&`lbU=7@HG5weDS9W+$t941&40x93CCEyr?2Zgn6c_S9Zt7GKn zl4D}n9v*B-HO0ylQEwgM8k&noYXLyYU%zyV7t&vLc>W_6=f&83^NaXjTf0PJa7+xM znwna($1TObXoM=YQ-vtOh0;+Suh^)$L&+xPR>>S4yh`tz{I}E|YV75&4w$#k52nIc z3T0{vQrkZ+qlgTK`8*J#Yc$}6o6WQ5A^jJJ!v+MQ<$4JYZ=F`iINxbH3a6AVS>{G? z8(P1!S-Hnh1X!RpYRgPbqGa>-&G&nxD`P39=U0`jJ^8H z%w+;QTewA?Nwihj_sh^S!)5Qe1JaC|NGn``qL7M)wE@4w)h3~rk_^;8LuQg?8vhtE zksI$_NTIR~exIQ)|6S7T(Z?!n%>~=Trrz(uXZJcn2b2bsuvZ&j>6l93YO=>LgdGLI zDU*#X-(`%T><}q2k|a~2NmdBs4{e#qRw#R+DyXktJMiyI;!pS;J$KHMF(c`g<37nr zXO{MH_(uYy7Jt-^%fMFaeVL_H_?j2l*|U%>Zmd#}o*uk*pmE0OAUl>*rTu@j0MdMN z8hB$#MpW4RyJT|4bk01>tfWgoTM(Js6fv=+*x<1@pCPtx#_hidL6RocirwVeB7vU4 z`+5WpA5qZ+|HH-&oWcxP8dwh0fj`Ds`@m&D3opY7WljYw0=CJN=(l$Gutg>OkWP`9 zR$PL^BS(LbJ2XJ`f=nr2@mVPd*ZIqagK#J11s@{oWjDn=X26}QuovZc4v!u^t!-^* zU*Eo+El6i(TQKu@gpT5E(m-4?5>F_(y1G8y&B;F>6~u8qu5nFf^Np1$mkcgZ$&11S zFP2(XHOD#(q!r#B^ ze>deD?RgCOc200+@C7NEXv^o6Z7<|oX&FrtdoKlBaqqYKzNENzf!N@o9WM7b9cl`>RnI1y)`;ZGu#=Ac)xkFE>G}vO8_Kc%o-{?1|LrCqc`NKWbb+O!w|HngM{k` zm}_Hz8qUjXn?!3|CdtV>>W20vIcU+@D=020Tc90RN8hxB$D~!5V>$l>~CO8U^}yXI&584?qd*1=nojWZO> zs99^Wl1vqW1w+_eZF{G?t}AZVIpjNB{(YCERp?9MnK!nqzo6>A_AfhAvn!vI$0Vw+ zdEPJTGdzzi1Mg9bH#Ha3wRFbjC4GPYszSY!?@);l5ieX4W5ciiCXS}GV2z!&sE^3s z6!qx*cQSB9{ZE_^k#x#wacPOm?E*hbE==HkPM}Dy`m&9^9#`Fc|7q+_Y;*yB=~xZQ zL|#KDNcid|;c#@4&HIFtl}(=QH=%?MxI($aI5qVdhJk_MTzCEg6TkfZ zp2P3`Fc{khn9QI;;Wa|>3BqE>6YLlceY1;XrcOaGv>+7?8-jbuHM-6VD&I4alfWj=yWhgtOh~(QUI}+vT!S53FllzEmBZ+ z18Sn3Z`NSf3&GwKcD~jy-G-JaB>eihIeqyOu{^Ca%aO?5Ypw-ti=1ke(=4scR~s}Zg$brCuV>hEw;mmtWOIFBNceM+u)DU6>Fg1X;|JxgtgzVE@+ z)(p#D5rUBvQ^$^@gfV$akt?UMloL-$K7+H8-*M_pl@NoLE2!IuZ;RI3Aa&y!#PKYa zz96LU;EVR0CRTfuR-a`dR$|VBn|YP7mI+&^eeFR!RedcEyAIVLm+4n-+xgplr+KpO zX~C@vLITSpf2IpUkqLz;gp~TkHtgB9yJ4r!;rPZnWuP6WX(^b~;ZmxNe3O5zTTCk9 zx>!WisgAOdMRRs?p4zHKCLYPVuHJrd>CX*wgTj#~^_DR6jm(X@LAv0BmV~W>wa0YW zCE=GM{uSVfmVoPwYXIHVze=z2z#=@vB!iD}O=o%2miC5keV$wF>tC0#e1?|Hk6=kv z8Z)(10O9a#Y>)K$#bLtZ2=A*yl0oBlm8#s{*J^PgY^7?BBiFXVV-_q%y*;AMcMSDO zzwytfn^W)CwoTK6IA0=7A7`Ai^E(B zg(hN;&FvN8)1lGg7Sy6hKNj_$muWkxNGv!?jH zij!^Z#*l9=(-oGJ2|?f{lR(6>j45t-9%;ll6qex>hm9Dropjhq5D)zg-h9H{=IB(5 zE?X60#T`DT-s^|nJ4X`@_TK&b3NeF}VGJ7-5&mJ~AA`YCcZ7%7y6GMCHjEO?{1o>S zfH&q3j=%B9d^lM!)h_X7_lfBH19s^WMU7Tw0gtu7UxCLF`dont12(@Tt+X{&SJIhE zlHWGns%z8S$th(bM%to5w&49vw3ZId+7*Jbf<@RbmZ#@fqz$)3HjDAD*xx{C!E(Q*Pe3|tiJ9-mkbn_ev7-$T36;z>{dQbQy7=?zT+*Vx z#Z7pv?3#wg6D5$2&7@37N)mw1mOlkX&pPo(OiZ1LVaOxynrn6CL4o_GFSsI2V@T|M zN1ZIhh64xLHKgHvF__<`PyvFa5LaT2Nwt!Y)tOHwtC#)0<4|#4s`)RG;+*C!MHI9_h>`J#~kj_HpH; zHJ>*~Q;azuIwXn`?yn#=B_lZD6vm8c#W%Updzd=i!2b99k<}r}xkDO%VEcmqIlmW@;k{*V#aQ(`G8T|CUO``eCR-`KA4|OHIP)7hf*xk7m z6N903+DW>Kp(UZiJE?b9keyq6YYbA((5g#iJQbgQW}T`6FQI`s{0>C5GjI=aU{_FD z1v@WT`~>>an3`M>{~H_I#OMhPQI^0|NEDXl=GtBXuc;6yH6GT8NI!D;CVGE$%$c3X z{ZK<&+tkzr@{rI+kIIsaVDPC8RU@iZLx?_8bcvO$33wWK4^xFAwdsZkQstb(zg^*K zy_EsLl0_FRVGggAFgfJo@GB_C;Evf;z!-FUxuSS$zj!^Q5EVY@VJTJt^GTTJ7}f{9 z-(Z6TUY*YFGs2nnLZbYp5+;#iF1Tkeh-s;L;9*bAt?tZ77xjL0yCc%Gh}udN#E+rb z1^1H4hzMjtnWBtba;D%W2X$nlh5i(ETd7 zo_Ff_-ji;#b9ivjltxnS&lKY^KKfy9ooRw)^r4)}Y0H01cS2T8L`E9*wz zs%-}a$i^bc_^1gsHW`2LF@y*fmM&PT(4^$GHegm*UaN#h3!_as@l21q?)dp@k$#6NOS1X|W^X zgy*T4*6nR^QAs4WoFi5WE+tm=dg6EYZ)Q&yd0mz>Yym>8=MUO`V5?kKvk**VbyV9` z5~+o~wCTyi#YF|>&EIKT)W|pKJMG;`8qF272&J+)_Jc4Vd4-H zCFTHxNU6VkKYj!t{0KQ`Bs)n#cjsNiiRKu12172;Qn0h11QrRy35ltf9l-^_<-C~B zdUf+u;%&tUnGlKy#`bcBab&nV!Dh7woIwxAkbBpKSdEjUnqM8W+urM%>~e`t2Uf-8 zFMj($ibr{sh1Z<&7_WE(aG(!-fVlG-a4Nwft^|4qOHc?FHaCog7e-pd2B-jnbHRgc zMg9)CRg2ibl_4A7j!EnaO$EdQAQbF&Z_(M+{!~$0tE|X2-E=nVY)iD;!_17`v;LA+OGZSK+KZ)M z9%dDYr=+&s=dLq28YAAy3k*HJKGiYi%V!J9$!w{qIe=&$yA5FizQEF@EA7?gilt!z zPVt8%zwQ#<`R(0tovz4RD?!DON>{R^t_>&ySqy#DtA=>8NR8vimio@o385S+rFM;K z7QM3R^2IAO<);>|%tr{xz(vQj7tOtyn2@Ol?q>DM)EhamBO&|AnM*fKz0Q$?1Gbwx z_WM?00nz?967<=U?pEA|zX(oFl;OLh0iEb7|0e6r0M-9;cW!=ZY;0_H+=ml*+eThl zS=ojbc=|dNOJMBicvE9#ok(WrX_>zCTAkm%m$T?Aq>gCclf*&i_(LO#{mI}Qe?8~& z>O8e;;JU>aLdc$2NRnEz2zB~&f6t7{==yB0L7~@~%)%m|HuN|n^;f$KMns>Y2&eS9 zxBz+O(sbAX%Hld{)p{AU%f)dzT|qLpl{gsQkzjtIC~rZ3j5u@RaDHhi(gaJC5?B>R z2->~Lphxu|_FkT_2_>EE-GIs&6Vq)@q8y(nqU?91oNV_1OLO?9Co7r{8?6~2($Z!w zp7T;qvgRo)#+VRow(Q3PM$ za#s4Z&m{1W7!Q3`M2A{5LYzs;174&?Tii0*czP;pXDz7_?=uFdZl!UJVwErT+`PeN*)N?BCcGL!Q;aW_%$kS zR?!i!T;6e|4`TE? zOiGi&v0*q30;BtI&7lKLcjX7%zP^xLd*s9mXP0>wB#N&irmgP4W^1oM%p8nDdGo>P zHrF$8$v&u_{$oAojpxAZu-W^WrR%Y+YiOm;{PDfTiWS%UwW(9KZT(=m#<<=4!Bj4j zQz(%P*(cU1n{`4%SKHj!2cwAXTrI<_&UMo@Lx0eL2HfWbeWdI2 z5~lM5>KNHi^r0Xp{_~9>|MHVPf1Tp<{`Cp8VoV}2=t2s6cR@=)eD&3Mr4BLP*}+`M z@EPR)o7Z|!+K{fYk$$jt!}9rj`SDZwa7tN!-QYAy-u-s|$KZxL+T(pSseBGeY*1U` zekWb~<6esxwPY10;S*txR~&O_)g+BNLzj5NY{86sZA7~l4g&9bwt?db1X_}K#4g+o zwR&OdKPYWYmiqTU>F9s|ya)dLGj(d{>6zKsAOaz1X=!y@og*S5VE>I&xh!t6w)O8; z6DKD$R#sM(zkjo^vkyK!aqjN!#-aZ$Ocpil@7?2VnL7T(p9-a}Sv&T`V<;pK!N}Xf zQn?~)eNnnmnwXxf943bnHWQGz^j-MpFnq#yYKJYdu%V*-EqB$Mcgcb11pIgFq}?8W z;b{d(+6E(IKzpkS)xmP!WvgFJI#iOO#$j^7b$Z4vL{ip5{q$ce{9ykdgw= z-4kX(c=+Xl{eeMLKuyeo-G4!>J)X&@6hQmXFl9g%8cVZgPrQ_h0>;ADmElQRwC2+# zACwSH7ABl~>&YQYn`{WI+IF?#`j(OK7d^BnzD6qCL^L)F!1j{LRXW2hTx*jno1cBhW>4f<B$h&6m^p6O8A~YlKNP%BzlK22=PA)E&3LW?$fvVKD~n;UwuZ{x>mbL}4PLOx z`e?5Ia`rj{GPpWhW8C-(vj<-hk~-t&;fV)_tGc08MSW0zkp<`d?ZA5BZ84|SHKNof zS745?RfMPbQmR&-$?X!!8O!DMKvyE4!>^EjSsM5;KcYNu1- z1JBXe670=aL-d(COs*rem1rsR45{>l`t;z57jn(&#Pgtjm-WZtwpbpw-x<4(B)fW8QDq zL++QL32JC;93=3ZB(QzIq%V$an!qZnsjIs`TO|GOy(OWY*C9^39}=5@^xMJdu&2#qi&s&Dxh9?l zT_a7j!(K}tcUbCUiMx;D&Dx*3j)}oRD39!bv?9IK*WX$+vmJN#nV6@%lb0!t4;*Sa zrc4q-Bf^|8MA@T>+GA?fQ^Xv1AqVNd6DH(l^*DPfE<5Gxy z6@q|^VWfPC8s!8ArSH)Nn`0<}dH7V{4Y}Q>W}KlLF&*Ad!%rX_&sZn3z+WUZMZ%x> zf7m=Bg*jQ|Bn^8FEA{_H^>sv|IDB|)_X2>`-&q&}I_^nEs@Y=dz%KcOa$y1$Ng^5R zf0m@3QHGEyT{9h5cr0z&m})!M%KpQj95daPyLTFh_}y548*Rp-c4Q|{Q}h%38Y8%K zPvKSk;DQg5hi?)GgZ#5G!=dY0EN=-714?4c7ZW74o`%sDr4f!WPgQWX+cDuE9)_kK zgnirLYW~Opl*9rHTotV{<%wVBa?>T)LgSe|UKrFK6T-4Z7#MnX*xn+(!3-uu!EsA( z4du@E!hhw-n8p_Ar{9~`Tt3=f;twf|P(UuNt!ju==*g0EP{Pg;s$7Rc5wgNn^Lm>0!SVR>bU$d&?Fpgp>ZB|GB1%YsIh zf&qh7;>`S3iNsJd&nI7*5ltx$YZ6GP;cSK@&UC%@L$v6oMQQnvnVGq#zrX(wziH=# za!MD7%MIOUwNF(v&l!j5o2Jzg23=UpAN{uG0p<6Bm3EpF&v7`y(FjwmN3pytC=F}p zLvX*kS^P^SJRgvUPFmoq(xWS3WlQxt=C{KD_MBE$)^p!lxu@1#)#eb;;{dps*>z{tI+tbRD=IKjObcal`WmB&|rMA z-Rzv`?FI9D8}b_;A4iZ{mjs*E`o_#G)S$IL{_9(&fM51lDq}%|nW14oSy`EnO`TSi zqN@&8wy=BRZMJsM>Jz!Vk&&L?Hd{82?@4!cL2|AV>@bUTI&PpK zU)^4V25g{b;M;~9z^)zcM`T(SsQaw>_=gHU3M)tyd|3|d1M(v1C8NRs-LNp~#`Eu! zq*=#qGv!J|x;Fc`#NEupm|&3GVKkzZciV?F#k+C}lJSeH`8>D(>a_}gOfn{*p_PVs z%$FsFUwu{jDt2N32t}xevhgU>%~P^dl1F{pTZ&(i?vKbNa^=Lgo`EST8^tu?dLHC% zToO~YD%Ap4wL?F)l2WP)ZHw9n64HBX`PoK={Y##qZ9L?K4k5x_~gIfPQcml93ILei>;Zt|2}qo7aaNn?^craub9WKy8Nv z=MYDE1_KPoz^84P`!>7t{2P-`<1PK#pH^iUNh%SVzTi?pe!cS>JwmeXl$-g~ut!41 zi?dI|7H1C`!oZ=qZ=e?z6l(9kj^1$X9;gs&`3Zp<@DrClD5&JZCxIDhKaK7i_U;v- zNp?XkVR;==5KKo+Vl3&4;qI6Oozc=9 zOwW+>^T>czpZ-}F?_}a~w4;-y8Y{n$<4t0FbN|72aM|)L{QSC5b8$R`mRbMb`cwm)Df2?8D!pLsn>pk4@rjX-W~eRi|PD*@9!oarS`7Z0cqbnWC&Y zQ-FVE=WgbQnH6w`=#8OsbLg!^{z@Z~dm3rUUB=vv3ytcbr#7dHToK`hmssDD`JE5nL&mrS_B>~-* zk_6>LW_Q03z{C=dz$pu3PJ~kJ^bZGP;$|$9%=!cxAX-=(_9*hTvWgb8au+NGSjt-e zNy+w(6(gOm=`$B52OAFG-LZKObsL|y4YyK+F;(<*HOE)Z%>2yRa$Uj(vy^tZr_=l;IX?H$j)_m z^V7da|Bc+SQugX(tRIxYTkN?-(!Ln!Srz+bhpvEcF;}Y!vsSmF_O-cO`bSH&AbI$j zQBxC>Hi5M{cvEM9@>hm%#X040Gc-`JwV~4Aqh;;WD|eNj1vg)PZ*hGO;T*TMr^^lB zQMD$C7g&WYwmwAL71!xrQ*7HAXMH_a#a`rfJno$M;64ml9vlix^0bOe ziYR4YaG&|q21I27jGhi&9Xgt>gT($&r{UMuOH|8Ph8y7Gsb8DnZ0ZVy!}UK7TXFky z_6((vWI1`E^}-lxg-^(4A~>*tQnF&=*}~%xa#D#w(H`p+%aiQ3?NQ3RFg_3}1my7B zI!G_m=R19X9T=1$YnO~(mLA7GyN-1u8`~gNFjS#j`@XmJ%55EB=)xcjG_Qk+5 z{_kRi+^)e_r*=EGYyFHqP%Em~;|Z|?bn>1*Dcm$Be%IaKX0R^F0lRLsgAM)v%5vVf z&HfFd8B;eI_nP6nBm^aZc(pHU8}F={N6$eThnYPey^%yFcN|M{vIcc{B0kP|oDE1@ zcNJ@RahdFfaL0`K}J`$F+? z+$wN=YBHBA6P(jlAye>iA7UfCR8}+A)HuZOw#h0z^2Ri=rAG}8N-UUJzrmb8#Erox z{2wg<`V2qq{C^x**+~D>9f`4jG*bYgc0inNnOcR0)uohnkkMCryNLr3`K};!jpcWZ zrBb1)=dqsxZgV?)W_YrI3nG4<<7W}G|1>uy)w)=rne%oYv?Q(-wtO(xM7f_2s3Vd6 zj=?6cIzKDK-VHZ?o=3&K5DRY;D{mtwjU1KckqO2bwb5r6BUi6EvWp(Tmd7XJCD_%= zr!sPMjATL>xs7&hlf@VK=xqX=QS@R^)Bo)0=I7P4W9s(y3^*h5lY2Ssg6yVeK=Hlg z3AZ%WfOO>$0?ZQP6>L~+Ws03{1uPV6eYd~?1Is}Ev#Q`J0!SP$FCf7#{ z2E4ioe6|?rOv-gmxOU2JJ|u)2LYC$e#LUDFff5K&TfE>rl~h~fL=px~j_(~a8OwWi zB~U^OZe6}Gh;YI$ut#&CV10f&TkBpz-qj6vV+$UOimHn*-J)8gGn#W!r~pzPqTta! zNg-lRcBee%df_ep>>dCN#+%0@Mw&D(0)t1dKyNOC;2Q03As|Se)Z+?Wo^P?~M!iA3&dAE8?6hVx z8^upVu^S8gO&>&OSde7Iw9Q^x(E7y`p{*(^G<7O?>wkq`*~L z9iLB1{H|x=8?V{Z5sWh=5tK%%@se6iR1{}dKXH07&r+cP0rT~#P4UKx z(YZCjisc-q>(9R{%Kh7{5)tD5kHLn*oILW5XA;-@{^l-yuUsHJDx3uJ+2Mk`s=?aM z&VIYjP0=wZ;<_ZY{veZ5mVT0>i~@dql8{2OT;AOHKZEtP7=7vg2^)~=%!dJ%E}i}h zm;YjIV^h=KE|Xr&njwoD19k67P{rn`G354-^Z}`*ij?xyc$y1If^*YVJnrXdmrt`B ztWFD4qIv7}k2;per*$`gM0-b6#Q0I+mMHvJYr~i`1Y-AUDZ3BYNycc<_)ay$*h8M` zfZ3OxG9CH!4wksa1qH z#ZpDO9qwa^jgsifg9^2ou-D3v*L78pMD{=k#F3#2Z=7|*G$U_Z33@3_0!I3pCss*niO(EoQ;?jIzL+YI8uvZbc>TgHm1|>RmOf_57 zZ6@ToJP2mF=W3i48J3-YVGD*FEEZe@u=KPsbh1aNCxyck5rZl~`9l!mwp^i>C-g~% zCW(jSM9iz=mlA1MxZ!^FF?^Et10xSF{k|y)>jY(0kvP~GVeZiQKETY{b|28FRRMLv z^>lkxaj^*uqk~5AckDx&xk68lw&Kbz{NC z5=hvR9YLKPIb7 zO2?wwAELSpUC${79{}ohTeA#{(w>SCT8if`3esawr%}zPO;;VVU-IuW2U7@H+~%wA zB9!~~s{9R%qt(1KIjw_~L>%e>PYr|{ue^EbkBq%X@PLBC2F05zAx+KBftwqQ{6Erw zWyZ`eZyqKs`E?j9ZWh_Uevt+nzNs{+|Ko&e1^%Z)gH{Gz>>n1WS3Ly6hp-rQ44j;j zc8B7UimBgyi5l8UO`DyMQ9(%b_{0P=vjfvtYqt!c{_AIB=Q_fspSCsqaCpB(7$%I# zp;yM^ZAT>)MawJYT(fmrVP+}IsQElKf%vF{c#6Q|g36j$90(o=12#WT_5zY? zg0`oDOMOoi#R@*9WmMsd)#K5kVzkBOpM0*?qKqm1S%j|Vm}d9N<6%UomA`Ax>C`a~ zo+`RNX!EJ^S68P{{)z3_<+t6EishQ@&s zqmI+8s6p-K&VFONo!)nU(i_hw)G-5jzaby#G1eakWhBi~fpkWmLi5xCXTkr4R}7&s zN=1?y#Q_{6v~7vDC^C2<%(u8c)C>>GN3vK(iql+V6YfKA{<`G zc^L}Sv;2e8YeEdck`CSxc$_U>f0(Nzvet>TxKl+hy89D zId2H8G5wLC#>F0^bNiGme1GS06cfiFdR!0-e$OM6VI-Hp5g8IVHplM}9O~QugSeVA~CsjCX=+1K= zM4s?VNIE8d8H^F^ZgE_jeFp1#uXYd!s&X{KuOD=416>lfB}1bNbv!w`b(00d69-G3nn8hnf_IX= zqJ$zdMUph?6E#?Xo_Xm(Knn}Lg(McX^P27M_%M>DiL9j#@EM#21G$N-?EQya<1X}@Ys^Sl@Yenk^QB+- zBhJMl$)VphyziT0zr61YS|zhivwMJ9!AS2LZ#hd)G+zKH=PGDiYBrl#l2@^x52Obr z+2cR9CH?t(M;lGS4kN-UPCA=(G4*-@YMhXotQopyE?@v&tVpj4sTGRkOHQD^Xb}$t z-Z!Qy2SvGTUy1A~;QXzG`gliay1%!pOBXVU8mtihMoJ@;K?iAr&r9)?S!;kpV|=K+ zC`*2R1%!j3Ah7p&TYy|2Bw;!F&@4VNVK1_KML6>xH^a`sYWdN(*CjztMq@}~i#q&; zJZy&*jC}rUg?$e123Etu56eGRW2LlR{cY&_RscdjGz_^5e%ETU4?#ECu<7jJBCGHe zZG{ZsVH=HSl;|vfcch$0l;^EUt5IAUUP%6-){G-p@Nh#H6ld_0x~F@$>kgM?EylfX zRlswRWI+uf89r#A2<;ab=6n2nZr{&kOWC(IW>Gslna~_=2pFdBCx^=WvikpD}kkkSt$Q zKA-(a-VQk8t0*2uRcqaRWgm8PjH>neY^=9ltYFF!K5{-&?OhOEEV4g7?}?a+yu-)T zP_R80udgG8ehX?-ABc>ZRQDZon#!#+nvC%dF)}26p5@qE7c^or<>->7rROhNUcb4^ z_!?n;-Y*UNUHo}Jm6$PjeL_#&NHeU$1>W*E`h*;xO4s{&!{=0kbA74O%X0Na;Csg1 z=|}C=rF>cU6T6D32G;j_2*?c3D|sc6JxOH_wKMY9NlDVA0E+sJ*R38sb$|Y}ow?kk zfN69~y2yr_>^Y!NDK~C^+5yq?RVB4q|B+-475uOD-xqvZOSwvo%lnCGlFN3jxd-$W zfQN@S(fr=ES+aQvQaplKXBk=91hTlCe9-3qb6z72l+FvH;;uhlxE9YTeAwLgZaZ$% zgeG&pb(?VskrP)22QR=7tfASEcT0@@T-^rgvuQYt^zIlP=Lw5fEb@^Q>^MQJbc56) z=1rQXa4o2(G!~kH>RaOC1zqK)WE6F|@Z~&T>(Fo27oGN@B5E@yg4ALdf?V7Q65#$< zNlmYz5*NijH5CEawV@oNjc1I5HIF?FJOS)nd3

    dA=29BL5kXUa#56FD_9cIdRyN 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 diff --git a/docs/images/mqc_fastqc_quality.png b/docs/images/mqc_fastqc_quality.png deleted file mode 100755 index a4b89bf56ab2ba88cab87841916eb680a816deae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55769 zcmeFZRal$t)-Fn+z*nS{Vx>rm6qiDAOL2F1cMtAuDNvx0;#Q!zyE_zjcbDMqmSlzR zn{)pEI@tSUUwdu2)&Y>bJb7fuJ?=5a1EER^lGqq;F_4guu%)HMRFIHRN0E?_z5hZ+ zJaJ}X&O!Wm=At4gf>b&}x`%l4+)`Lx7zwEYjQMDcig^FRNlM!V3F)=#)7P^V3xFpQ z(!7JTn6R3s!6EcTteK|QPPjx@DDOv5T2*CXB}Z%z@|SP-DsObzPh`FaVcdV&m0)j; zcZ>LN@}*RhsyUw6to^1IV&KrBgSL*D84<+V=b92tLUGmkCzrla{Dr!*h^X~IGAQjM zyD9lfz=>mTe@ql{QdCq_QdAt=(BA&2YBUsY=dfzD{{p(Xxaz)h;YCF8?Ul%1e}5}@ zO@0yZuh)nND%kn8|Na%lH#NLM=KqYOnC|MbCw}whr}=*yP7H-Y`-r9qwQ2rq9Dz|0 zBdN65Kl4A$DgS>m=QkV7|7=EzGh^Yu&HaDh$NCi3wnS$c$@$FVUp#HFss7?l0LJ~{ z!`SL7tNPPP=8^Kq8)3(i@(qbit!IaRj$Duu3h(VXaI4Sdu3~_@H&ak|A1shtFJP;$ z&Ff|ziaT$FS{aiU@Te#m;Cp!+I*IbJ@XxAqIeeeH<$>FQ&-YdyTH@a_&X?%>7*prF zp2!e%;=M(CLssc(k6U1h(+Z6N7fk4b1$pU zx+k}@k}uu*?&UWT+g}Y#gV?3_XQkIe!hs%Suq9Q))|Tlh`Wr-J#)v6)bNt9IQZ-?zd%Hw*=ZrCzD^f-D3r^0KBi$+ip$`A6Mk<3rtrZFNxAf zKk90T99Gb#t7ndaGJ(*jcpaOR-2zFV|0MH`0H4>cX|8kH-A>yB@PzO5QPgAAeG<9~ z(7IdVikhJ^RFhx&6*~Cd*30U>;FKs>ES%nYuI$%8RM=1({ChUX}X7!Wu zAA=&In$O5ezi+pM8LtJ8`oW`oa28+E!&*f>9{W97;k4XXkIS^H4+UAGvZx7D{UOIK zH$}ZEkpj2NC%)GxA>My-R{)`xdTyO1fcg{J)!T^@lJhkw=vrQzj&$^Qa(I7Cu2xl- zg5af(2k=sEQGeBmBNF1c9B_MFCIG7eR|`T^)>Jws({-d$>S9rNoIs$o1qKW1U(s7gPai5(qrX(&Um zwy;AI@AZ}{%d9#&PBP>zwc8=%jgWWGH2jQp`DWYPw4k^T`^Nvelzg_m4tOygvshAx zSic)*_56B2$iwR{sdtKA-$NW8Cffewvz4#abf1JwCg*y2X*Lu~6edkmydt&um&!Yh;0Fgz!I z8S zXW#cIlDgIR7Kgd*mV>IL1+VdR*KujmVe6Bnrwi2`nyj5h(N`umHB#h26X zt}BBFa)TAfq5C^R?mPC5nk4!GljuO$+PG#|*B4a_2>^!?m-qb{I`I10^!40&Ah?Xo z5pt;rAZdrM_}>Q86li@(J8)D#f?(9Br`@U}FA1>Jx%%}~}bmH|q8K|Y!jaNAu?dYM~6 zRZJc^eBV;Y!Mnx?kn&2<<#2q|Pp)+P>ZBPmqA2KkX?Et2s&9LqBzZimIWVsmGYatA zRXt~RY=fjB;A5x~rSrZ2e#S!_7>vCGqC{9lj*|V8LTb}g!H@mpp{+Rn_v>x&(6H+J z7}nKf@B4Ld%Z-a7|M0=og<;D>XSx@Y&lV$4Ekin}o2SXK^<>^M{r+%K-I&?XE$nJSn(xJK4qrH|bnqfPU>4jm=e=x!oc#?Jke&g(g- zUucQtw<$SVY?d~P}!t-c2Lo8mx6d`@70 zvP5TBSUX%%C7-WOwciMN4WbKqP5B%ow3f{Z-jx6kgNKYV|^tpbL^<*qZ-A^30n?FBY*Hn_q~jp%0Mg-<>UCF!!;rL{!Y{b z*3Cv>f1?;licgf`G`bG-zLl-3R|wc#Q538g0z$S#C86oCbHSjNy?ANChiOIVH2rMI zG5nGlT3Axtm$CYA3AoOV^jpuMy|ROZ?T(T^1UI_*!$t2I@DM>^@!2%tQ*2Px;zGGh z02fo5-BK-N3cz|cST76mXYkO_egPK}#MwY7cUixalk{5k7n=LGIBj3hTJKhyeXzl~ zGo3fkBcT7$3Q6oSx65M@pbZ+YC;(b=HY>1%!!mZp6Fqznq0rpI#0pXZU|dVnIlk9-%u>~`h}VhYjz zmPod{6t5ndj-zKD=!WOo(!>9dq!*2ld8_8dca!LG1x9m|yPCUXkoxbbV)V`B^QlP* z2QLUMxOI2m3%(x6c>7K);Oa-%C(!K#N~N9Ef%3qRq9J)~x4KpV>itdW?%7A43LDIa z8X^^jrZk!ojDyDSMXww70zLApJntoe%=xcBD#D>RDy64nfaU_M6Z)d7V4v3O7+UfM zI23&xL2-PqOi$oj<6nQBorePGYWBHH+x}3PF;m>1({p~`Te}(*tYP8JcKw|ZaIa3W z5|KeaW+a1}*~V9jOh9(L$~YKYYcNd}*`l$FOU6yA(HR-(cSZ&9*~&v1R}oErionDF zkmE|SIb~(H=VJ$DZ4b&-CQ)fO@a_a4)*zSnmv493+6k&S(%z0p_QJ>psX^O_V9lhrb>BAr9 z#!w93wGILaXkvaRP39@H;n)|GB8ih{1e-l>kB{FBn1qGHL%+#NzbvY3$Xf&5Ir5z2 zPG9!I*3-qPiSN%$8O#PHBV)1VD}P1)O~7Dhj2?72@pBcduzphsN8H)`k=p3Wh%;_$ zOeXLMp7o@Qaw@rwstN}`?{)X08s5C`DQlRw*eDrX7{@P}7d8#NUz6uvKJSkcQF?Ne z6pViyWiT|=e=Doa?LjcWpUG)555Bnx)chgcgWJ97&2EQZf!xal z)p2nI02nbGF^RF>u>$hlk&33=WQ-^JoI>Si0u8 zV07Zbz#>r^qAXD{lBu!00RKml^p=Cv64=~UMF`M+kogAK za9tvbFb_5Czmu~*!Wcf7X4}nlOhFn>z@2UYs5e8zXiDYQ=Ox))S3>&zy2o(u2h5!JvYvSsLq$lAJ%%c;J%Lb@e5mEkCW z?eZ|Dux0i&Si?wGLD+e^#G`KKbCx{u6gsr?6jUM?pE*3wAGiPuHc1MIvY4|WVosn|)%172v_ zuJ9qyLTdW=-$|n#8!G@V$$7Z3oifYzxs!m`vv;S}RV*&e|L#YrvkJalcR(jP&|ivp zdX?VXKmoSP&tSH<4&P*Xc=vJz77}8-1B8!d0cW#BxWLd8o=iJfUfU`0+(QVsx$4{8 zM%dD+!cq1`U^-K(q~!|)T~eLAZia5FB+I+)`mCM=ATeKEa>FyeeU0P0N(2$?H5_a% z1c?1K;t}s!d86fx%Dsml&FIN>)%>u!tJSay-_BD*KV3b8rOY0MRDF}8&W3rMO8Cvd zq4No{`UQOiAyeW&=;8TZg&{D6<%2^Z z!|qE6iY8+BPguq9y#O>n~H+h-giBAsF%%~f&;2z zHSJ9+elB|j$&@GebI=dtreMMQ&ghri{%!G?7SS%=%2G0KqHH#RkD(za3ny=Hi$(=p zLGvS3B|d!WGOoC}J8#If=~Y0uQMxBB0Dao47Ri8W79ysyRyY66Fcmx+Tm-DB zhy25cx=95+#qc?ToUlOnSSf2{HM2o=*VzYQSjU+-RrVoQq-g{FF4Zg zE~D2d*8doXY~?Q)$%+d%R^R5T*Ja|j(efj$qMbfNU$|`D4f(?#^kdi{t)k*vJRUdL zlxcwb4m#}66CTp`2n9CPSQhv#x;!Mn5l~6yO6GGaT9+UCvj-#Cg^PfUgy(9?6bFXL zpNb`ZMW&HB#=RloUUl{4T*WAYN0#{>9S=giO>#Fy+5dV^K*r~FnE~_`y9;cG`R|Z< zoOm=C`0i!|j9q)!?A~%82Uz7BM!4{L-9s2&lDz;lp6G%f*Hh2|EjuF*ZTdWkb~fij z6_P^E5528|&KH1y9o-vpP$5xCn_I}+iK{MC;6&BY+8Fs=m!-n;b%SD?b{UHjMD=vl z=|HehRp36=l!l{Nb=j)%E)c-p>$yu+7f<0NCv?~F0Cqtaf)`7bVV&u>BhZse9N&i(A3$x{)K4e9C)`q;|M{`52%Ol-Fg#F@RhIVC{{nI!7gqddBASWD!btp-(BBw zy3b`l5s_nR2<)6q^Y+vd*eWbZ{zSIO{;S}l*pU8|lJn$|PvBuKUqx7+=-R09e`&ej zfx{|HP3Z%AGj5jsR!`dCO19@yQ~>yvW;*!(X7#4zWHpB}1(BEfJf?t!{10!5-z-JJ zQX-eGqE>l9_7%!}cZXT{YORv&H@6?!P^VBI%uu6V6=U2bfK z-nUhXzIRgAtSRD^1sRqBr@J>`*yP8cp7G0o-9a4q`1%ZFqkHR25(W(nc!>F8Rev?+ z2p#E#0X>$-*t{U__3WWm|LRC(^ku5R)_I#q+`)twhDXu$zH2tK)}SV;F#zE0@2 zg?0JR?v@D90Hrb{11&%10Dztc$r&o2>~^QX>Hg!vk;( z#!o$oW+d2aJ3E!HTRLmi#ku04&fiTkl>~TQ=DSMO6nU&V@0^f&T|`G#xX*^A`Jd~q zJ}%Ne)$q(Ccl0IwAN0|Wt_{zb<)PfG{R#-xbxpIXTB^TSg|zin6u zSh5q{v1O+fzBxjo@#?QW1SARF$04v2_)CFv*=aWK_yOuc#x(QJ=Ett;&FUqs;sfxq zCIB|&O^N=5HrZJJV02Sr(xjsQLk19jeTIiI@V|PQ~{$B-zwT*x3pGviT$60%8 zCF!>divF-$D){m87X$&aRcy6G_WdbycC+L(o9?%>1B5-W24q|AHU&J)RiTV0+o^D# zT@WW6EHpXfOd)pp&5q{s?`;3C`S)0Y*FJT?+vbC9;6s04-B?QK(}F_(bAgv9`a9z3 z6M28iWc~@r|2+7AU-9?vZT>GSHUD2*%^6Xwe{?i5`rX!MSZEWDhZAtQj+cwo7%6a? zSLc=zv`#AoZy(3i_dRGaga;nDKI!IPS|BN(j!XSr`)E`qYOKB0Wf*X2oba7V#{I5) zk=%1laIo%)G5j-l9>dPfyf>2it=GmbYZG{h1;(^o*K*Rh-V5gQHTu_th|#qnsfD#z z@N=S0eaEKKL8ivW8}}v!0nvu1qUJx#E)FXw=}JTjohk=?^dIb7E2n>IU)7z^yXKN5>F_agCUG}=!;#J&CZeBX*c`T6-#zh=YC zndemokzv74zo3(!G~OKC6xP?%!8h!~ZNg_vh8nM8JRn4`F)hCQXDep(R~_D}48xI{ zy4B6+;dRhGlsf5MLde2Kp_-kt&0xj4>3R zhquhEz2pj?@1^q#2>W9fj)Lo|e>Qu;f1NoyY^u>Q{MwRUOwH>_4=8z=h;cgr9=^=* z?xGoVzo&BQKig6XySlGE%#IRELH|3M`R8%$1||7_>z7ob{BH;Pi(>l!kOxD5aw~vz80WD^z{{}CSKKBaMsdz*X zg6)>mlPEl1p-B3iKpQu{PzB-uPdhWO{u5Cs7TY70bf2c^q^bito#+l%nrww;wH*q9 z9^AY$9%^s&xgT$p@9X{}TC>IZXEuYUIBot@Zd+L=dt8Ib>xM9s`UCq}w*sdfH-c>$0J>4`lZ*J!KJWf!Y{KJ18 zO*eu+eRMMb1qB7s`&Lme!UCS%p^vnj9Q2HvZ-t@@!T%j}87W(a>}+UdXigJcB$4Fw!o$e+tk>*3^i~SJOF4C(3^hQo`+k zUHc7b-*l>D~O}$@DWtwNsB+WB=I-1wY3B z)aL(26^f6bcMLQ!gU#$v8OoT`dO;}%ZkQ@+oL)F*{Gtk~zA0_h*@O(Wo!zyFkK)04I`B2uMsXC_I zU!z7c!RhYhJk8D~`gE!0=iP>pQ1&?a zB!)_?vR+2ekCH#{3X(;%F)T=$KuNw;e-z^P__rCKy7~zHo4Nd6PA>hsiCK;Rkg$~!x* z1oZ}mhF_&o*#{n_Gl6O4`E5MaZ`8*?L(y-2KH65;x&P}1M}c~Nt(r)Z&EUbuGWgb` zq7h*-WJ2sQ%Gao%mg#yU&%gCFZGLyHw3wSiqxS1=ra7 zhfVM<(E_q=xL(ERoMH|F6v6KtK8Lk~#`=qi2h8)gZN zpyUxJ+PA&F!GFW~&t>#~6y)_7(HpW8GA#0Jj)JnO8cp|o$d$>=w7`eLBf~3W4w@?I z3W{(h>8dd`6ru&FGa6{(H&J8WF#<6i9@Pa!~XE?j?N_|er(s~ zoQnPL+2qvYPfp!VWX_=|XJ`LT_K`)B)Hpg6`5Jj1h*XuWGaakV^^5GAL8 z1<+W`_)7+Y9;rgWz7UMAb3^H0$qF~P}9YX$|(l68N)eOTs+-Qe#c_pox#H>9Hd=PVCb?037 zc_zYv+uwJQsXssy&e|r6osX(3gtZO%F+;}1ED_{DN(OKVGEW(OEgOHy`z;Y7edqUg zys_WA|GWh3p==edvj;U(>@0s)K za$RXeodzH`gT9(d)4eY`^}kKtGx+twpn!(!VK&>E+`yXpuh(v|Wpi(xTH=d7h;v5M zR!OVLI0!YPL@|EdV)~92GWb13R$pt`GEOT?Qb3x8FL#*Qs?^3PjDp30bwiH;|K&TnmI{XS_VTuIA^Xnk) zsnw>~BEwGBj$xwjGp_8r=GxpTbLY>4v$JC!E~~?Hz8N?^Ndu^6cq%-o7f>+JKkXTPIu#nTp1%Bf8oJEn+~#k zN$lGfo=h(}gTm<=NmRx#HWubhurWa9!z_j0mirhQKozcX)o-MCKS+U+)JmbYr=O&@ zqxm_+j`#c2m5$2FzBZCB1j*|si#Xvy3^!Fg04#vUxMh?he_JB87X1Pu^@Js}Al%lvRC}tTS?07wM`*eC|2fyacbu0nu1^PZ>k4AuS6p2pa8h}3!lXb z7r_gjW1#8@siJi4P7|_X)OLVfrXKQ1D=O4MjItz#=B=8o?40SD-1vq-P6EOgSr>U~Z9S?C>u(HvJCbLw4qC ztop8mY8GXcZ~_~n((s%NJy11JVUEbad`sQH;>i#eZ%GutbswFi`1%Pt)KH$zcr%DNDbV>DfG#DbOi8HOuFJpN&gT2;Iw>eOv}O#o z4R?4w{O&%K5Vb8@eB}{yeS>?T6RABQWkJM`{;QZIfGnGhyGq@IV*-6knvpw|-p9>L z8_Al3s`00QS`2aOB3S!KJ6PoClJHk*^e<9Ad|2h$i@?&-W7MU;?%kal^yz-r<+G^1 z3ePEaFu4kt4B8S>_b4Tog*3~bz8YIp2aKD9eM`&~kMoKBWiRy9>3*ex{3JikcJ}Fb z%F|>X-1Il#2ykyN?PknmKS5VQ>R)oG6|@i!HKt@e_*{`e6InENts%!y^}F{k;`8W< zOrqN3znhy>Y9D=`Y^b~%VAL%YTfa)04G_FL@T75=u?EDHHkKYcahGyN8oqe$#fkN- zL8ZX;gEHG~1>0NUj1-Y$rY3Fo=O%*5W=W@_?&iwRXu`HWXo{>Xyp@Hhxe!iZ?z&aD z4#nffwZ_Qzzrns#X;7I)Zjo{zoMhLa+xqy$Lg_DE<4d}V4`)a2&!Cd8UrIb`$7hQ~ z=rk3pL_>uShe-#nDQLLow4nimpL(^LXX95){J{Vs+#}lAx7hhMZKMAmM z@F@}Uj3|<`r$;{V-DHE@vA-qpGrh)EZ5nLHWL(KsXXqLi6M2tSeldQ*-*^A#+2(TN zh$e0D&p8p<0o2}CZ?Hhg*9_EEM8poNPOG1Aa2MN4ah2O+F;TTtw>uGr!H)Gh>J2rH zXFLlZh85r9yE4=+UxGnHePi3;6^A7(&UUa7E_@yVU?4Y_-Fl<@d%Quv-C`T%DQ|3``&(L^MPUn-q&sCZ zIsW1CvgOQcUB>3?@6N76^$4n~f@AH|@$r9Ikk}0E6n$%+>4bIhw}NC?o0k^zHGQCq zxp%a2gBW2V&eD+hK-KcNgv_rD{9j9$3M3nTudV&qOyVhqdTQ*bNTlgAZR#YREPi=I zfkqQU1+uZ!r~ zapTZw$fVK7r9vJg-B@Ml62+w5DO-4xdbOHw%~CT+&0R2hKK6+*aN;}#xCcXC8`-rj z#;6lm-Bt>#;*zI)V_WakvCNkFRBe|M;i6nIt8_Sqf)GD$y4Ebet;_EQ-h36+-}Hwi z*G}Fgdp~G<3==(#xp-|EIBy&Mupf-xtXVY1eM0f9a^eqffibJ*| zFeh(6S1byR5ldEw}h82UX3!s5W0g3eUd%q+f2x+?Q9?AJ$OF(NzRM^O0ul)+F&srRw4rpP9NNM zC+6g5Exi}AgJU;t`_6WH(mrCoZ3b*c%ri})d9Ihd2^NoS7gwNk za5jd{cQ*6X&O$wBl|Mpu%G zfG|V3AiCEMp;(0hIdu;xI$DRF-Q+5CzoEklgGPL8%wa`qXo-C(ae{e2;oprIn(;Y@Rg$=FML#BVB8#k+Rsl+tItuyeq~L*%@f2v&d2@{8TD zM4U=vKs?;y0D1T4AlMAjt@pZ4y~b5b@2%c%N=e{S-}#nshr*)&pdIT`hWpYx&!zQe zjQd!}?*!y1TmKrsOhSFkV0&vQpSUeJ3^??Yn_vhJE!C@OqdrT8p(8U?oK zh4%j8J@{vmM&n5g*a{t_Z9=H#&%@^O?8k?dY_{BgDp+AGs7eel>=}gdqYj%0RVi$( zsT+LAc6Q%axVf$PzQhzC+57B3hfK@;tUU~41cfVo{!Kj}NUffe)J3ZeQ!*z(w z>Yf&dPaI1$fq6}(4-q#NuR(Tjuk+8QT?>!Z%}?WO-j#B?w@`gzPQ`$y$X_?XzFGTR zq4hP-)!S%(Z9A9kK-iSIk7=8q-+i=TuFWi-ym*_>eUoPt=U@$W&Du0xolIbxFcuds z4|Sb9PnETL$71WkID^fx}bZ->Qs>AzZ!# z)c%0bGRnt2(({R^w`7S zQ7`JPVihS~JElzLcg&Jdd}{iZFO;O*+4PfZg117qLHd0iCL@#g)Gf`g%DXKUr@=Yy zaQwqceMb;fi5;K|T|B z`ANT$P7xM#`E`EtzTje-z>i*~rOcq&w0y=+5+UNB=7_ZR+xavh$!gMiy9+D2V)I5) zXmTO4S339dDqho((|)vpY7L~`^o1fNL?K(C>SAW7+0tP}5O6WnD~RdrArPuwYBrFn z0t9YDTYbmUanM0m#&K`|H1tT-76<{b^1V|*ZWLDqsJ;U0k+kIi?txp3rqAApczcKB zo-dSweIHV#%4W#2=aTn${B1Sv+UK<<0kN}qKR$ZB4bCuBx0k6_9x~vVoKV+ z&(}WQ=Jfd5nXXxN3SCvQlpXd}JoI-|b2eC!WgJd}PGeu$0!A_7d^#zIInYxi2_?*Ae@&^G z$PDnH`PPs*7BM*M79tWQTA8;<+CjnjahNS z)TAw}dr@;mwFV9luiSC7%1XKG3xtoE5sB2~ygqfPHmK?D`3S&-UbuAZDCpu%&f(5$ zZ=tm6>C+h!4NRlD7~_9!xK|Rw7kh7$EdN8&O|Q*;*ZCaD z4jJd=S~Xv{DiBm!zi9n!b0}i$`%OoeZgb9z_M07f<{%w$=I`(F7_&6GM`$zITB8MB8N6Ln8`vU|&v^H% zzlI7CK3Iehb#r8caRv?DU*F)1A3F@2*T^{A{zQd`>S=|uUQsZ&KA$%6(}JuU$Osz{88r^rp+Wi2e{`0T9QV1?p4 za~L#5T~1-Vhe|5^Tiu~ICc2J`73V*Tefm#B~4=bveHUwyMjMBL|;cX%8)=8 zoFo#i&)!T+)w-21=sR3;km9s1*flcnP%RDC*F=Tm+O94aEg_pD%leF8vta2*Az+P5 zADCIRacf?WQ5yN&B7R1q%5=w5DPM1NI*8FkNSjOkOD-biO1n=>Yb5tgEnr6RP3U8p z5Y3K}dS=;@c)-P$KCeSaK>{xIyvtA`@hFg}FUHmS*FTS48)2aw_y`Ge$ znPdOp^4YsOOpB;eHiXpO*`L}sIyT{J3b~>{{`Hm*>q&-6fwqLN*}Hm*SJZr0npYDr z?=PMOu;BO2GP-?w@jR;0&XjsqFWugHNL(Ya_7gUH7>j4_c5%P9E#H1=OZjV-#{l0u_)~I>-0fUVyiYkdf9XWUa zM1Xd3e6i;hJ1jx+30m4J7u2Est`0T%J8*(f$K%%KjgCZsHvMO3bvqCnPh3H|?xQma z4rSbdWu=z(`9a-Vy*y?Xf&ekh=h1@{dte9L4d-_~uQ60YMb*`Oc8Afv+%Yp?VF6=U zBVxaZSM8}7nHB{T5Ec5;B(df4+%q?_-G3OE5S=3EkUl8VV4L_ckv;LF(c9jrKJ0u# zcUAY~BU|YBk+VVlfiscRFj_~_Mj8R6yWmfL^BTYEytrmUr|}&luY{yq2gBhj`^c5Z z^S(cSkrU0?2?&(}>)0c{^rSVWrQMSY%$yc?UR!hrcSNmq+0&B!svJ0?5C~GA8}c>6 zj3N{*t4OCfKpu_^evK+tV7fprL3p;sL9(|iBI7Pia)v6MwpCc}&x=Mz?g403Xl<e;viOll%5G z0F13z2bFa2Hzg%Djq*8s(f={4DAR z_VYbC*mT3k8^YwXI%jshm2GBx>{5ieUdx1_gq9OvdT$5b@dmgLq=((RU{ZK6<-f+T zm}DK>i(S6*_7hf2xOTX|1-7HO4%Lop@E&^79{! z@9zg?%&B$Nbb{u$4&`iUl7ECne{W^Zt*<`qAxIkdiPu5@9OKNSobC�)v~C(0C)c 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 M)78&qol`;+0Fu7JivR!s diff --git a/docs/output.md b/docs/output.md index 96f54478..73cd57bf 100644 --- a/docs/output.md +++ b/docs/output.md @@ -2,58 +2,499 @@ ## Introduction -This document describes the output produced by the pipeline. Most of the plots are taken from the MultiQC report, which summarises results at the end of the pipeline. +This document describes the output produced by the pipeline. The directories listed below will be created in the results +directory after the pipeline has finished. All paths are relative to the top-level results directory. -The directories listed below will be created in the results directory after the pipeline has finished. All paths are relative to the top-level results directory. - - +```text +output/ +│   +├── subject_1/ +│   ├── alignments/ +│   ├── amber/ +│   ├── bamtools/ +│   ├── chord/ +│   ├── cobalt/ +│   ├── cuppa/ +│   ├── flagstats/ +│   ├── gridss/ +│   ├── gripss/ +│   ├── isofox/ +│   ├── lilac/ +│   ├── linx/ +│   ├── orange/ +│   ├── pave/ +│   ├── purple/ +│   ├── sage/ +│   ├── sigs/ +│   ├── virusbreakend/ +│   └── virusinterpreter/ +│   +├── subject_2/ +│   └── ... +│   +... +│   +└── pipeline_info/ +``` ## Pipeline overview -The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: +- [Simple DNA/RNA alignment](#simple-dnarna-alignment) + - [bwa-mem2](#bwa-mem2) - DNA alignment + - [STAR](#star) - RNA alignment +- [Alignment post-processing](#alignment-post-processing) + - [MarkDups](#markdups) - General alignment processing + - [Picard Markduplicates](#picard-markduplicates) - Duplicate read marking +- [SNV, MNV, INDEL calling](#snv-mnv-indel-calling) + - [SAGE](#sage) - SNV, MNV, INDEL calling + - [PAVE](#pave) - Small variant annotation (transcript/coding effects) +- [SV calling](#sv-calling) + - [SvPrep](#svprep) - Read filtering for SV calling + - [GRIDSS](#gridss) - SV calling + - [GRIPSS](#gripss) - SV filtering and post-processing +- [CNV calling](#cnv-calling) + - [AMBER](#amber) - β-allele frequencies + - [COBALT](#cobalt) - Read depth ratios + - [PURPLE](#purple) - Purity/ploid estimation, variant annotation +- [SV event interpretation](#sv-event-interpretation) + - [LINX](#linx) - SV event clustering and annotation +- [Transcript analysis](#transcript-analysis) + - [Isofox](#isofox) - transcript counts, novel splicing and fusion calling +- [Oncoviral detection](#oncoviral-detection) + - [VIRUSBreakend](#virusbreakend) - viral content and integration calling + - [Virus Interpreter](#virus-interpreter) - oncoviral calling post-processing +- [HLA calling](#hla-calling) + - [LILAC](#lilac) - HLA calling +- [HRD status prediction](#hrd-status-prediction) + - [CHORD](#chord) - HRD status prediction +- [Mutational signature fitting](#mutation-signature-fitting) + - [Sigs](#sigs) - Mutational signature fitting +- [Tissue of origin prediction](#tissue-of-origin-prediction) + - [CUPPA](#cuppa) - Tissue of origin prediction +- [Report generation](#report-generation) + - [ORANGE](#orange) - Key results summary + - [linxreport](#linxreport) - Interactive LINX report +- [Pipeline information](#pipeline-information) - Workflow execution metrics + +### Simple DNA/RNA alignment + +Alignment functionality in oncoanalyser is simple and rigid, and exists only to meet the exact requirements of the +hmftools. + +#### bwa-mem2 + +[bwa-mem2](https://github.com/bwa-mem2/bwa-mem2) is a short-read mapping tool used to align reads to a large reference +sequences. In oncoanalyser, bwa-mem2 is used to align DNA reads to the human genome. + +*No outputs are published directly from bwa-mem2, see [MarkDups](#markdups) for the fully processed alignment outputs* + +#### STAR + +[STAR](https://github.com/alexdobin/STAR) is a specialised mapping to used to align RNA reads to a reference +transcriptome. + +*No outputs are published directly from STAR, see [Picard MarkDuplicates](#picard-markduplicates) for the fully processed alignment outputs* + +### Alignment post-processing + +#### MarkDups + +

    +Output files + +- `/alignments/dna/` + - `.duplicate_freq.tsv`: Normal DNA sample read duplicate frequencies. + - `.markdups.bam`: Normal DNA sample output read alignments. + - `.markdups.bam.bai`: Normal DNA sample output read alignments index. + - `.duplicate_freq.tsv`: Tumor DNA sample read duplicate frequencies. + - `.markdups.bam`: Tumor DNA sample output read alignments. + - `.markdups.bam.bai`: Tumor DNA sample output read alignments index. + +
    + +[MarkDups](https://github.com/hartwigmedical/hmftools/tree/master/mark-dups) applies various alignment post-processing +routines such as duplicate marking and unmapping of problematic regions. It can also handle UMIs when configured to do +so. + +*MarkDups is only run on DNA alignments* + +### Picard MarkDuplicates + +
    +Output files + +- `/alignments/rna/` + - `.md.bam`: Tumor RNA sample read alignments. + - `.md.bam.bai`: Tumor RNA sample read alignments index. + - `.md.metrics`: Tumor RNA sample read duplicate marking metrics. + +
    + +[Picard MarkDuplicates](https://gatk.broadinstitute.org/hc/en-us/articles/360037052812-MarkDuplicates-Picard) used to +mark duplicate reads following alignment. + +*Picard MarkDuplicates is only run on RNA alignments* + +### SNV, MNV, INDEL calling + +#### SAGE + +
    +Output files + +- `/sage/append/` + - `.sage.append.vcf.gz`: Tumor DNA sample small variant VCF with RNA data appended. + - `.sage.append.vcf.gz`: Normal DNA sample small variant VCF with RNA data appended.. + +- `/sage/somatic/` + - `.sage.bqr.png`: Normal DNA sample base quality recalibration metrics plot. + - `.sage.bqr.tsv`: Normal DNA sample base quality recalibration metrics. + - `.sage.bqr.png`: Tumor DNA sample base quality recalibration metrics plot. + - `.sage.bqr.tsv`: Tumor DNA sample base quality recalibration metrics. + - `.sage.exon.medians.tsv`: Tumor DNA sample exon median depths. + - `.sage.gene.coverage.tsv`: Tumor DNA sample gene coverages. + - `.sage.somatic.filtered.vcf.gz.tbi`: Tumor DNA sample filtered small variant calls index. + - `.sage.somatic.filtered.vcf.gz`: Tumor DNA sample filtered small variant calls. + - `.sage.somatic.vcf.gz.tbi`: Tumor DNA sample small variant calls index. + - `.sage.somatic.vcf.gz`: Tumor DNA sample small variant calls. + +- `/sage/germline/` + - `.sage.bqr.png`: Tumor DNA sample base quality recalibration metrics plot. + - `.sage.bqr.tsv`: Tumor DNA sample base quality recalibration metrics. + - `.sage.exon.medians.tsv`: Normal DNA sample exon median depths. + - `.sage.gene.coverage.tsv`: Normal DNA sample gene coverages. + - `.sage.bqr.png`: Normal DNA sample base quality recalibration metrics plot. + - `.sage.bqr.tsv`: Normal DNA sample base quality recalibration metrics. + - `.sage.germline.filtered.vcf.gz.tbi`: Normal DNA sample filtered small variant calls index. + - `.sage.germline.filtered.vcf.gz`: Normal DNA sample filtered small variant calls. + - `.sage.germline.vcf.gz.tbi`: Normal DNA sample small variant calls index. + - `.sage.germline.vcf.gz`: Normal DNA sample small variant calls. + +
    + +[SAGE](https://github.com/hartwigmedical/hmftools/tree/master/sage) is a SNV, MNV, and INDEL caller optimised for 100x +tumor and 40x normal. + +#### PAVE + +
    +Output files + +- `/pave/` + - `.sage.germline.filtered.pave.vcf.gz.tbi`: Annotated SAGE germline small variants index. + - `.sage.germline.filtered.pave.vcf.gz`: Annotated SAGE germline small variants. + - `.sage.somatic.filtered.pave.vcf.gz.tbi`: Annotated SAGE somatic small variants index. + - `.sage.somatic.filtered.pave.vcf.gz`: Annotated SAGE somatic small variants. + +
    + +[PAVE](https://github.com/hartwigmedical/hmftools/tree/master/pave) annotates variants called by SAGE with impact +information with regards to transcript and coding effects. + +### SV calling + +#### SvPrep + +[SvPrep](https://github.com/hartwigmedical/hmftools/tree/master/sv-prep) runs prior to SV calling to reducing runtime by +rapidly identifying reads that are likely to be involved in a SV event. + +*No outputs are published directly from SvPrep, see [GRIPSS](#gripss) for the fully processed SV calling outputs* + +#### GRIDSS + +
    +Output files + +- `/gridss/` + - `.gridss.vcf.gz`: GRIDSS structural variants. + - `.gridss.vcf.gz.tbi`: GRIDSS structural variants index. + +
    + +[GRIDSS](https://github.com/PapenfussLab/gridss) is a SV caller than uses both read support and local +breakend/breakpoint assemblies to call variants. + +#### GRIPSS + +
    +Output files + +- `/gripss/germline/` + - `.gripss.filtered.germline.vcf.gz`: Filtered GRIDSS germline structural variants. + - `.gripss.filtered.germline.vcf.gz.tbi`: Filtered GRIDSS germline structural variants index. + - `.gripss.germline.vcf.gz`: GRIDSS structural variants (GRIPSS filters set but not applied). + - `.gripss.germline.vcf.gz.tbi`: GRIDSS structural variants index (GRIPSS filters set but not applied). + +- `/gripss/somatic/` + - `.gripss.filtered.somatic.vcf.gz`: Filtered GRIDSS somatic structural variants. + - `.gripss.filtered.somatic.vcf.gz.tbi`: Filtered GRIDSS somatic structural variants index. + - `.gripss.somatic.vcf.gz`: GRIDSS structural variants (GRIPSS filters set but not applied). + - `.gripss.somatic.vcf.gz.tbi`: GRIDSS structural variants index (GRIPSS filters set but not applied). + +
    + +[GRIPSS](https://github.com/hartwigmedical/hmftools/tree/master/gripss) applies filter and post-processing to SV calls. + +### CNV calling + +#### AMBER + +
    +Output files + +- `/amber/` + - `amber.version`: AMBER version file. + - `.amber.baf.pcf`: Tumor DNA sample piecewise constant fit. + - `.amber.baf.tsv.gz`: Tumor DNA sample β-allele frequencies. + - `.amber.contamination.tsv`: Tumor DNA sample contamination TSV. + - `.amber.contamination.vcf.gz`: Tumor DNA sample contamination sites. + - `.amber.contamination.vcf.gz.tbi`: Tumor DNA sample contamination sites index. + - `.amber.qc`: AMBER QC file. + - `.amber.homozygousregion.tsv`: Normal DNA sample regions of homozygosity. + +
    + +[AMBER](https://github.com/hartwigmedical/hmftools/tree/master/amber) generates β-allele frequencies in tumor samples +for CNV calling in PURPLE. + +#### COBALT + +
    +Output files + +- `/cobalt/` + - `cobalt.version`: COBALT version file. + - `.cobalt.gc.median.tsv`: Tumor DNA sample GC median read depths. + - `.cobalt.ratio.pcf`: Tumor DNA sample piecewise constant fit. + - `.cobalt.ratio.tsv.gz`: Tumor DNA sample read counts and ratios (with reference or supposed diploid + regions). + - `.cobalt.gc.median.tsv`: Normal DNA sample GC median read depths. + - `.cobalt.ratio.median.tsv`: Normal DNA sample chromosome median ratios. + - `.cobalt.ratio.pcf`: Normal DNA sample piecewise constant fit. + +
    -- [FastQC](#fastqc) - Raw read QC -- [MultiQC](#multiqc) - Aggregate report describing results and QC from the whole pipeline -- [Pipeline information](#pipeline-information) - Report metrics generated during the workflow execution +[COBALT](https://github.com/hartwigmedical/hmftools/tree/master/cobalt) generates read depth ratios (or an estimation +for tumor-only) for CNV calling in PURPLE. -### FastQC +#### PURPLE
    Output files -- `fastqc/` - - `*_fastqc.html`: FastQC report containing quality metrics. - - `*_fastqc.zip`: Zip archive containing the FastQC report, tab-delimited data file and plot images. +- `/purple/` + - `circos/`: Circos plot data. + - `.purple.cnv.gene.tsv`: Somatic gene copy number. + - `.purple.cnv.somatic.tsv`: Copy number variant segments. + - `.purple.driver.catalog.germline.tsv`: Normal DNA sample driver catalogue. + - `.purple.driver.catalog.somatic.tsv`: Tumor DNA sample driver catalogue. + - `.purple.germline.deletion.tsv`: Normal DNA deletions. + - `.purple.germline.vcf.gz`: Normal DNA SAGE small variants with PURPLE annotations. + - `.purple.germline.vcf.gz.tbi`: Normal DNA SAGE small variants with PURPLE annotations index. + - `.purple.purity.range.tsv`: Purity/ploid model fit scores across a range of purity values. + - `.purple.purity.tsv`: Purity/ploidy summary. + - `.purple.qc`: PURPLE QC file. + - `.purple.segment.tsv`: Genomic copy number segments. + - `.purple.somatic.clonality.tsv`: Clonality peak model data. + - `.purple.somatic.hist.tsv`: Somatic variants histogram data. + - `.purple.somatic.vcf.gz`: Tumor DNA sample small variants with PURPLE annotations. + - `.purple.somatic.vcf.gz.tbi`: Tumor DNA sample small variants with PURPLE annotations index. + - `.purple.sv.germline.vcf.gz`: Germline structural variants with PURPLE annotations. + - `.purple.sv.germline.vcf.gz.tbi`: Germline structural variants with PURPLE annotations index. + - `.purple.sv.vcf.gz`: Somatic structural variants with PURPLE annotations. + - `.purple.sv.vcf.gz.tbi`: Somatic structural variants with PURPLE annotations. + - `plot/`: PURPLE plots. + - `purple.version`: PURPLE version file.
    -[FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your sequenced reads. It provides information about the quality score distribution across your reads, per base sequence content (%A/T/G/C), adapter contamination and overrepresented sequences. For further reading and documentation see the [FastQC help pages](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). +[PURPLE](https://github.com/hartwigmedical/hmftools/tree/master/purple) is a CNV caller that also infers tumor +purity/ploidy and annotates both small and structural variant calls with copy-number information. -![MultiQC - FastQC sequence counts plot](images/mqc_fastqc_counts.png) +### SV event interpretation -![MultiQC - FastQC mean quality scores plot](images/mqc_fastqc_quality.png) +#### LINX + +
    +Output files + +- `/linx/germline_annotations/` + - `linx.version`: LINX version file. + - `.linx.germline.breakend.tsv`: Normal DNA sample breakend data. + - `.linx.germline.clusters.tsv`: Normal DNA sample clustered events. + - `.linx.germline.disruption.tsv`: Normal DNA sample breakend data. + - `.linx.germline.driver.catalog.tsv`: Normal DNA sample driver catalogue. + - `.linx.germline.links.tsv`: Normal DNA sample cluster links. + - `.linx.germline.svs.tsv`: Normal DNA sample structural variants. + +- `/linx/somatic_annotations/` + - `linx.version`: LINX version file. + - `.linx.breakend.tsv`: Tumor DNA sample breakend data. + - `.linx.clusters.tsv`: Tumor DNA sample clustered events. + - `.linx.driver.catalog.tsv`: Tumor DNA sample driver catalogue. + - `.linx.drivers.tsv`: Tumor DNA sample LINX driver drivers. + - `.linx.fusion.tsv`: Tumor DNA sample fusions. + - `.linx.links.tsv`: Tumor DNA sample cluster links. + - `.linx.svs.tsv`: Tumor DNA sample structural variants. + - `.linx.vis_*`: Tumor DNA sample visualisation data. + +- `/linx/somatic_plots/` + - `all/*png`: All available tumor DNA sample cluster plots. + - `reportable/*png`: Driver-only tumor DNA sample cluster plots. + +
    -![MultiQC - FastQC adapter content plot](images/mqc_fastqc_adapter.png) +[LINX](https://github.com/hartwigmedical/hmftools/tree/master/linx) clusters PURPLE-annotated SVs into high-order events +and classifies these events within a biological context. Following clustering and interpretation, events are visualised +as LINX plots. -:::note -The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. -::: +### Transcript analysis -### MultiQC +#### Isofox
    Output files -- `multiqc/` - - `multiqc_report.html`: a standalone HTML file that can be viewed in your web browser. - - `multiqc_data/`: directory containing parsed statistics from the different tools used in the pipeline. - - `multiqc_plots/`: directory containing static images from the report in various formats. +- `/isofox/` + - `.isf.alt_splice_junc.csv`: Tumor RNA sample alternative splice junctions. + - `.isf.fusions.csv`: Tumor RNA sample fusions, unfiltered. + - `.isf.gene_collection.csv`: Tumor RNA sample gene-collection fragment counts. + - `.isf.gene_data.csv`: Tumor RNA sample gene fragment counts. + - `.isf.pass_fusions.csv`: Tumor RNA sample fusions, filtered. + - `.isf.retained_intron.csv`: Tumor RNA sample retained introns. + - `.isf.summary.csv`: Tumor RNA sample analysis summary file. + - `.isf.transcript_data.csv`: Tumor RNA sample transcript fragment counts.
    -[MultiQC](http://multiqc.info) is a visualization tool that generates a single HTML report summarising all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in the report data directory. +[Isofox](https://github.com/hartwigmedical/hmftools/tree/master/isofox) analyses RNA alignment data to quantify +transcripts, identify novel splice junctions, and caller fusions. + +### Oncoviral detection + +#### VIRUSBreakend + +
    +Output files + +- `/virusbreakend/` + - `.virusbreakend.vcf`: Tumor DNA sample viral integratino sites. + - `.virusbreakend.vcf.summary.tsv`: Tumor DNA sample analysis summary file. + +
    + +[VIRUSBreakend](VIRUSBreakend) detects the presence of oncoviruses and intergration sites in tumor samples. + +#### Virus Interpreter -Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQC. The pipeline has special steps which also allow the software versions to be reported in the MultiQC output for future traceability. For more information about how to use MultiQC reports, see . +
    +Output files + +- `/virusinterpreter/` + - `.virus.annotated.tsv`: Processed oncoviral call/annotation data. + +
    + +[Virus Interpreter](https://github.com/hartwigmedical/hmftools/tree/master/virus-interpreter) post-processing for +VIRUSBreakend calls that provides higher-level interpretation of data. + +### HLA calling + +#### LILAC + +
    +Output files + +- `/lilac/` + - `.lilac.candidates.coverage.tsv`: Coverage of high scoring candidates. + - `.lilac.qc.tsv`: LILAC qc file. + - `.lilac.tsv`: Analysis summary. + +
    + +[LILAC](https://github.com/hartwigmedical/hmftools/tree/master/lilac) calls HLA Class I and characterises allelic status +(copy-number alterations, somatic mutations) in the tumor sample. Analysis can also incorporate RNA data as an +indirectly measurement of allele expression. + +### HRD status prediction + +#### CHORD + +
    +Output files + +- `/chord/` + - `_chord_prediction.txt`: Tumor DNA sample analysis summary file. + - `_chord_signatures.txt`: Tumor DNA sample variant counts contributing to signatures. + +
    + +[CHORD](https://github.com/UMCUGenetics/CHORD) predicts the HRD status of a tumor using statistical inference on the +basis of relative somatic mutation counts. + +### Mutational signature fitting + +#### Sigs + +
    +Output files + +- `/sigs/` + - `.sig.allocation.tsv`: Tumor DNA sample signature allocations. + - `.sig.snv_counts.csv`: Tumor DNA sample variant counts contributing to signatures. + +
    + +[Sigs](https://github.com/hartwigmedical/hmftools/tree/master/sigs) fits defined COSMIC trinucleotide mutational +signatures to tumor sample data. + +### Tissue of origin prediction + +#### CUPPA + +
    +Output files + +- `/cuppa/` + - `_cup_report.pdf`: Combined figure of summary and feature plot. + - `.cup.data.csv`: Model feature scores. + - `.cup.report.features.png`: Feature plot. + - `.cup.report.summary.png`: Summary plot. + - `.cuppa.chart.png`: CUPPA chart plot. + - `.cuppa.conclusion.txt`: Prediction conclusion file. + +
    + +[CUPPA](https://github.com/hartwigmedical/hmftools/tree/master/cuppa) predicts tissue of origin for a given tumor sample +using DNA and/or RNA features generated by upstream hmftools components. + +### Report generation + +#### ORANGE + +
    +Output files + +- `/orange/` + - `.orange.json`: Aggregated report data. + - `.orange.pdf`: Static report PDF. + +
    + +[ORANGE](https://github.com/hartwigmedical/hmftools/tree/master/orange) summaries and integrates key results from +hmftool components into a single static PDF report. + +#### linxreport + +
    +Output files + +- `/linx/` + - `_linx.html`: Interactive HTML report. + +
    + +[linxreport](https://github.com/umccr/linxreport) generates an interactive report containing LINX annotations and plots. ### Pipeline information @@ -67,5 +508,3 @@ Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQ - Parameters used by the pipeline run: `params.json`. - -[Nextflow](https://www.nextflow.io/docs/latest/tracing.html) provides excellent functionality for generating various reports relevant to the running and execution of the pipeline. This will allow you to troubleshoot errors with the running of the pipeline, and also provide you with other information such as launch commands, run times and resource usage. diff --git a/docs/usage.md b/docs/usage.md index 1e383ce8..1c05e06a 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -6,62 +6,142 @@ ## Introduction - +The oncoanalyser pipeline typically runs from FASTQs or BAMs and supports two modes: (1) whole genome and/or +transcriptome, and (2) targeted panel. Launching an analysis requires only the creation of a samplesheet that describes +details of each input such as the sample type (tumor or normal), sequence type (DNA or RNA), and filepath. -## Samplesheet input +Various aspects of an oncoanalyser analysis can be configured to fit a range of needs, and many of these are considered +[advanced usage](#advanced-usage) of the pipeline. The most useful include: -You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row as shown in the examples below. +- precise process selection +- starting from existing data +- granular control over resource data -```bash ---input '[path to samplesheet file]' +These features enable oncoanalyser to be run in a highly flexible way. For example, an analysis can be run with existing +PURPLE data as the starting point and skip variant calling processes. Additionally, resource/reference data can staged +locally to optimise execution or modified to create user-defined driver gene panels. + +> [!WARNING] +> There are important requirements when using BAMs as input instead of FASTQs: +> - STAR must have been run with [specific +> parameters](https://github.com/hartwigmedical/hmftools/tree/master/isofox#a-note-on-alignment-and-multi-mapping), +> this is critical for WTS data, and +> - reads are expected to have been aligned to one of the Hartwig-distributed reference genomes (user-defined genomes may be used though are not recommended) + +## Supported analyses + +A variety of analyses are accessible in oncoanalyser and are implicitly run according to the data available in the +samplesheet. The supported analysis types for each workflow are listed below. + +| Input sequence data | WGS/WTS workflow | Targeted sequencing workflow\* | +| --- | :-: | :-: | +| • Tumor/normal DNA
    • Tumor RNA | :white_check_mark: | - | +| • Tumor only DNA
    • Tumor RNA | :white_check_mark: | :white_check_mark: | +| • Tumor/normal DNA | :white_check_mark: | - | +| • Tumor only DNA | :white_check_mark: | :white_check_mark: | +| • Tumor only RNA | :white_check_mark: | - | + +\* Supported analyses relate to the TSO500 panel only + +## Samplesheet + +A samplesheet that contains information of each input in CSV format is needed to run oncoanalyser. The required input +details and columns are [described below](#column-descriptions). + +The oncoanalyser pipeline also recognises several input filetypes, including intermediate output files generated during +execution such as the PURPLE output directory. The full list recognised input filetypes is available +[here](https://github.com/nf-core/oncoanalyser/blob/v0.3.1/lib/Constants.groovy#L56-L86). + +### Simple example + +#### FASTQ + +> [!NOTE] +> Currently only non-interleaved paired-end reads are accepted as FASTQ input + +```csv title="samplesheet.csv" +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,info,filepath +P1__wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P1.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.001.R2.fastq.gz +P1__wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P1.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.001.R2.fastq.gz +P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tumor.rna.wts.001.R1.fastq.gz;/path/to/P1.SC.tumor.rna.wts.001.R2.fastq.gz ``` -### Multiple runs of the same sample +#### BAM -The `sample` identifiers have to be the same when you have re-sequenced the same sample more than once e.g. to increase sequencing depth. The pipeline will concatenate the raw reads before performing any downstream analysis. Below is an example for the same sample sequenced across 3 lanes: +> [!NOTE] +> Inputs with the `bam` filetype will be processed by MarkDups as required by hmftools. Where an input BAM has already +> been processed by MarkDups, you can avoid needless reprocessing by setting `bam_markdups` as the filetype instead. +> +> Please note there are important requirements around the use of BAMs, see the warning above in the +> [Introduction](#introduction). ```csv title="samplesheet.csv" -sample,fastq_1,fastq_2 -CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz -CONTROL_REP1,AEG588A1_S1_L003_R1_001.fastq.gz,AEG588A1_S1_L003_R2_001.fastq.gz -CONTROL_REP1,AEG588A1_S1_L004_R1_001.fastq.gz,AEG588A1_S1_L004_R2_001.fastq.gz +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath +P1__wgts,P1,SA,normal,dna,bam,/path/to/P1.SA.normal.dna.wgs.bam +P1__wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam +P1__wgts,P1,SC,tumor,rna,bam,/path/to/P1.SC.tumor.rna.wts.bam ``` -### Full samplesheet +### Multiple lanes -The pipeline will auto-detect whether a sample is single- or paired-end using the information provided in the samplesheet. The samplesheet can have as many columns as you desire, however, there is a strict requirement for the first 3 columns to match those defined in the table below. +```csv title="samplesheet.csv" +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,info,filepath +P1__wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P1.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.001.R2.fastq.gz +P1__wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:002,/path/to/P1.SA.normal.dna.wgs.002.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.002.R2.fastq.gz +P1__wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P1.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.001.R2.fastq.gz +P1__wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:002,/path/to/P1.SB.tumor.dna.wgs.002.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.002.R2.fastq.gz +P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tumor.rna.wts.001.R1.fastq.gz;/path/to/P1.SC.tumor.rna.wts.001.R2.fastq.gz +``` -A final samplesheet file consisting of both single- and paired-end data may look something like the one below. This is for 6 samples, where `TREATMENT_REP3` has been sequenced twice. +### Multiple patients ```csv title="samplesheet.csv" -sample,fastq_1,fastq_2 -CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz -CONTROL_REP2,AEG588A2_S2_L002_R1_001.fastq.gz,AEG588A2_S2_L002_R2_001.fastq.gz -CONTROL_REP3,AEG588A3_S3_L002_R1_001.fastq.gz,AEG588A3_S3_L002_R2_001.fastq.gz -TREATMENT_REP1,AEG588A4_S4_L003_R1_001.fastq.gz, -TREATMENT_REP2,AEG588A5_S5_L003_R1_001.fastq.gz, -TREATMENT_REP3,AEG588A6_S6_L003_R1_001.fastq.gz, -TREATMENT_REP3,AEG588A6_S6_L004_R1_001.fastq.gz, +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,info,filepath +P1__wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P1.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.001.R2.fastq.gz +P1__wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P1.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.001.R2.fastq.gz +P2__wgts,P2,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P2.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P2.SA.normal.dna.wgs.001.R2.fastq.gz +P2__wgts,P2,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P2.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P2.SB.tumor.dna.wgs.001.R2.fastq.gz ``` -| Column | Description | -| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `sample` | Custom sample name. This entry will be identical for multiple sequencing libraries/runs from the same sample. Spaces in sample names are automatically converted to underscores (`_`). | -| `fastq_1` | Full path to FastQ file for Illumina short reads 1. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". | -| `fastq_2` | Full path to FastQ file for Illumina short reads 2. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". | +### Column descriptions -An [example samplesheet](../assets/samplesheet.csv) has been provided with the pipeline. +| Column | Description | +| --- | --- | +| group_id | Group ID for a set of samples and inputs | +| subject_id | Subject/patient ID | +| sample_id | Sample ID | +| sample_type | Sample type: `tumor`, `normal` | +| sequence_type | Sequence type: `dna`, `rna` | +| filetype | File type: e.g. `fastq`, `bam`, `bai` | +| filepath | Absolute filepath to input file (can be local filepath, URL, S3 URI) | + +The identifiers provided in the samplesheet are used to set output file paths: + +* `group_id`: top-level output directory for analysis files e.g. `output/COLO829_example/` +* tumor `sample_id`: output prefix for most filenames e.g. `COLO829T.purple.sv.vcf.gz` +* normal `sample_id`: output prefix for some filenames e.g. `COLO829R.cobalt.ratio.pcf` ## Running the pipeline The typical command for running the pipeline is as follows: ```bash -nextflow run nf-core/oncoanalyser --input ./samplesheet.csv --outdir ./results --genome GRCh37 -profile docker +nextflow run nf-core/oncoanalyser \ + -profile docker \ + -revision v0.3.1 \ + --mode \ + --genome \ + --input samplesheet.csv \ + --outdir ``` This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. +> [!NOTE] +> When oncoanalyser is run, it will retrieve all reference data it requires to perform the requested analysis. When +> running oncoanalyser more than once, it is strongly recommended to pre-stage reference data locally to avoid it being +> retrieved multiple times by oncoanalyser. See [Staging reference data](#staging-reference-data). + Note that the pipeline will create the following files in your working directory: ```bash @@ -118,6 +198,127 @@ To further assist in reproducbility, you can use share and re-use [parameter fil If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. ::: +## Advanced usage + +### Selecting processes + +Most of the major components in oncoanalyser can be skipped using `--processes_exclude` (the full list of available +processes can be view [here](https://github.com/nf-core/oncoanalyser/blob/v0.3.1/lib/Constants.groovy#L36-L54)). +Multiple processes can be given as comma-separated list. While there are some use-cases for this feature (e.g. skipping +resource intensive processes such as VIRUSBreakend), it becomes more powerful when combined with existing inputs as +described in the follow section. + +> [!WARNING] +> When skipping components, no checks are done to identify orphan processes in the execution DAG or for redundant +> processes. + +### Existing inputs + +The oncoanalyser pipeline has been designed to allow entry at arbiturary points and is particularly useful in +situtations where previous outputs exist and re-running oncoanalyser is desired (e.g. to subsequently execute an +optional sensor or use an upgrade component such as PURPLE). The primary advantage of this approach is that only the +required processes are executed, which can greatly reduce runtimes by skipping unneccessary processes. + +In order to effectively utilise this feature, existing inputs must be set in the [samplesheet](#samplesheet) and the +appropriate [processes selected](#selecting-processes). Take the below example where existing PURPLE inputs are used so +that all upstream variant calling can be skipped: + +```csv title='samplesheet.existing_purple.csv' +P1__wgts,P1,SA,normal,dna,bam,/path/to/P1.SA.normal.dna.wgs.bam +P1__wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam +P1__wgts,P1,SB,tumor,dna,purple_dir,/path/to/P1.purple_dir/ +``` + +> [!NOTE] +> The original source input file (i.e. BAM or FASTQ) must always be provided for oncoanalyser to infer the correct +> analysis type. + +And now run and skip variant calling: + +```bash +nextflow run nf-core/oncoanalyser \ + -profile docker \ + -revision v0.3.1 \ + --mode wgts \ + --processes_exclude amber,cobalt,gridss,gripss,sage,pave \ + --genome GRCh38_hmf \ + --input samplesheet.csv \ + --outdir output/ +``` + +> [!WARNING] +> Providing existing inputs will cause oncoanalyser to skip the corresponding process but *not any* of the upstream +> processes. + +### Configuring reference data + +All reference data can be configured as needed. These are defined in various locations: + +| Reference data | Filepath | Note | +| --- | --- | --- | +| hmftools resource files | `conf/hmf_data.config` | Paths relative to data bundle directory | +| panel resource files | `conf/panel_data.config` | Paths relative to data bundle directory | +| Genomes and indexes | `conf/hmf_genomes.config` | Absolute paths | + +To override hmftools resource files (e.g. driver gene panel), [stage the bundle](#staging-reference-data) locally then +copy in the desired file(s) and update `conf/hmf_data.config` accordingly. The local custom bundle must be provided to +oncoanalyser with the `--ref_data_hmf_data_path` CLI option. The same approach is followed for customising panel +resource files, configuring `conf/panel_data.config` and supplying with `--ref_data_panel_data_path` instead. + +The path or URI to the VIRUSBreakend database can also be explicitly set with `--ref_data_virusbreakenddb_path`. +Configuring custom genomes uses a different approach to align with the existing concepts in nf-core. + +#### Custom genomes + +It is strongly recommended to use the Hartwig-distributed reference genomes for alignments +([GRCh37](https://console.cloud.google.com/storage/browser/hmf-public/HMFtools-Resources/ref_genome/37) or +[GRCh38](https://console.cloud.google.com/storage/browser/hmf-public/HMFtools-Resources/ref_genome/38)). If there is no +other option than to use a custom genome, one can be configured with the following process: + +```text title='genome.custom.config' +params { + genomes { + CustomGenome { + fasta = "/path/to/CustomGenome/custom_genome.fa" + fai = "/path/to/CustomGenome/samtools_index/1.16/custom_genome.fa.fai" + dict = "/path/to/CustomGenome/samtools_index/1.16/custom_genome.fa.dict" + bwa_index = "/path/to/CustomGenome/bwa_index/0.7.17-r1188/" + bwa_index_bseq = "/path/to/CustomGenome/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" + bwa_index_biidx = "/path/to/CustomGenome/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" + bwa_index_image = "/path/to/CustomGenome/bwa_index_image/0.7.17-r1188/custom_genome.fa.img" + gridss_index = "/path/to/CustomGenome/gridss_index/2.13.2/custom_genome.fa.gridsscache" + star_index = "/path/to/CustomGenome/star_index/gencode_38/2.7.3a/" + } + } +} +``` + +Run a custom genome with the above configuration and below command + +```bash +nextflow run nf-core/oncoanalyser \ + -profile docker \ + -revision v0.3.1 \ + -config genome.custom.config \ + --mode wgts \ + \ + --genome CustomGenome \ + --genome_version <37|38> \ + --genome_type \ + --force_genome \ + \ + --input samplesheet.csv \ + --outdir output/ +``` + +> [!WARNING] +> RNA alignment with STAR must use an index generated from a matching Ensembl release version (GRCh37: v74; GRCh38: +> v104). + +#### Staging reference data + +Please refer to [REFERENCE_DATA.md](https://github.com/nf-core/oncoanalyser/REFERENCE_DATA.md). + ## Core Nextflow arguments :::note diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index 2d88ffdf..00000000 --- a/examples/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# Examples - -## Full - -| Filetype | Keyword | Description | Type | -| --- | --- | --- | --- | -| BAM (WGS) | `bam_wgs` | WGS read alignments | Required | -| BAM (WTS) | `bam_wts` | WTS read alignments | Optional | -| SV VCF | `vcf` | SV VCF produced by an external caller [_used to filter reads for GRIDSS_] | Optional | - -```text -id subject_name sample_name sample_type filetype filepath -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor bam_wgs /path/to/tumor_bam/sample_one_tumor.bam -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor bam_wts /path/to/tumor_bam/sample_one_tumor.rna.bam -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_sv /path/to/tumor_sv_vcf/sample_one_tumor.vcf.gz -SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal bam_wgs /path/to/normal_bam/sample_one_normal.bam -STWO-1 SUBJECT_TWO SAMPLE_TWO_TUMOR-1 tumor bam_wgs /path/to/tumor_bam/sample_two_tumor_one.bam -STWO-1 SUBJECT_TWO SAMPLE_TWO_NORMAL normal bam_wgs /path/to/normal_bam/sample_two_normal.bam -STWO-2 SUBJECT_TWO SAMPLE_TWO_TUMOR-2 tumor bam_wgs /path/to/tumor_bam/sample_two_tumor_two.bam -STWO-2 SUBJECT_TWO SAMPLE_TWO_NORMAL normal bam_wgs /path/to/normal_bam/sample_two_normal.bam -STRHEE-1 SUBJECT_THREE SAMPLE_THREE_TUMOR tumor bam_wgs /path/to/tumor_bam/sample_three_tumor.bam -STRHEE-1 SUBJECT_THREE SAMPLE_THREE_TUMOR tumor vcf_sv /path/to/tumor_sv_vcf/sample_three_tumor.vcf.gz -STRHEE-1 SUBJECT_THREE SAMPLE_THREE_NORMAL normal bam_wgs /path/to/normal_bam/sample_three_normal.bam -``` - -## GRIDSS - -See [Full section](#full) - -## PURPLE - -| Filetype | Keyword | Description | Type | -| --- | --- | --- | --- | -| AMBER directory | `amber_dir` | AMBER output directory | Required | -| COBALT directory | `cobalt_dir` | COBALT output directory | Required | -| GRIPSS SV VCF (hard filtered) | `vcf_sv_gripss_hard` | Hard filtered GRIPSS SV VCF | Required | -| GRIPSS SV VCF (soft filtered) | `vcf_sv_gripss_soft` | Soft filtered GRIPSS SV VCF | Required | -| SNV/MNV and INDEL VCF | `vcf_smlv` | Small SNV/MNV VCF | Optional | - -```text -id subject_name sample_name sample_type filetype filepath -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor amber_dir /path/to/amber_dir/ -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor cobalt_dir /path/to/cobalt_dir/ -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_sv_gripss_hard /path/to/tumor_gripss_hard_sv/sample_one_tumor.vcf.gz -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_sv_gripss_soft /path/to/tumor_gripss_soft_sv/sample_one_tumor.vcf.gz -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_smlv /path/to/tumor_smlv_vcf/sample_one_tumor.vcf.gz -SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal vcf_smlv /path/to/normal_smlv_vcf/sample_one_normal.vcf.gz -``` - -## LINX - -| Filetype | Keyword | Description | Type | -| --- | --- | --- | --- | -| PURPLE directory | `purple_dir` | PURPLE output directory [_LINX somatic_] | Required | -| GRIPSS SV VCF (hard filtered) | `vcf_sv_gripss_hard` | Hard filtered GRIPSS SV VCF [_LINX germline_] | Required | - -```text -id subject_name sample_name sample_type filetype filepath -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor purple_dir /path/to/purple_dir/ -SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal vcf_sv_gripss_hard /path/to/normal_gripss_hard_sv/sample_one_normal.vcf.gz -``` - -## GRIDSS-PURPLE-LINX - -| Filetype | Keyword | Description | Type | -| --- | --- | --- | --- | -| BAM (WGS) | `bam` | WGS read alignments | Required | -| SV VCF | `vcf_sv` | SV VCF produced by an external caller [_used to filter reads for GRIDSS_] | Optional | -| SNV/MNV and INDEL VCF | `vcf_smlv` | Small SNV/MNV VCF | Optional | - -```text -id subject_name sample_name sample_type filetype filepath -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor bam_wgs /path/to/tumor_bam/sample_one_tumor.bam -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_sv /path/to/tumor_sv_vcf/sample_one_tumor.vcf.gz -SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal bam_wgs /path/to/normal_bam/sample_one_normal.bam -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor vcf_smlv /path/to/tumor_smlv_vcf/sample_one_tumor.vcf.gz -SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal vcf_smlv /path/to/normal_smlv_vcf/sample_one_normal.vcf.gz -``` - - -## LILAC - -| Filetype | Keyword | Description | Type | -| --- | --- | --- | --- | -| BAM (WGS) | `bam_wgs` | WGS read alignments | Required | -| PURPLE directory | `purple_dir` | PURPLE output directory | Required | - -```text -id subject_name sample_name sample_type filetype filepath -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor bam_wgs /path/to/tumor_bam/sample_one_tumor.bam -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor purple_dir /path/to/purple_dir/ -SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal bam_wgs /path/to/normal_bam/sample_one_normal.bam -``` - -## TEAL - -| Filetype | Keyword | Description | Type | -| --- | --- | --- | --- | -| BAM (WGS) | `bam_wgs` | WGS read alignments | Required | -| COBALT directory | `cobalt_dir` | COBALT output directory | Required | -| PURPLE directory | `purple_dir` | PURPLE output directory | Required | - -```text -id subject_name sample_name sample_type filetype filepath -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor bam_wgs /path/to/tumor_bam/sample_one_tumor.bam -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor purple_dir /path/to/purple_dir/ -SONE-1 SUBJECT_ONE SAMPLE_ONE_TUMOR tumor cobalt_dir /path/to/cobalt_dir/ -SONE-1 SUBJECT_ONE SAMPLE_ONE_NORMAL normal bam_wgs /path/to/normal_bam/sample_one_normal.bam -``` From f0caef540685fc9226efc490e6449a8950d7f5a4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 15:00:48 +1100 Subject: [PATCH 462/562] Fix Cloudflare R2 base URL --- REFERENCE_DATA_STAGING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REFERENCE_DATA_STAGING.md b/REFERENCE_DATA_STAGING.md index 836ed785..a5c13065 100644 --- a/REFERENCE_DATA_STAGING.md +++ b/REFERENCE_DATA_STAGING.md @@ -5,7 +5,7 @@ Download and unpack > All reference data is retrieved here, exclude unused files as desired; using GRCh38_hmf below ```bash -base_url=https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/genomes +base_url=https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev fps=' genomes/GRCh37_hmf/Homo_sapiens.GRCh37.GATK.illumina.fasta From c610c0c7bd5da367c489c4d147d65472c0bca622 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 16:27:38 +1100 Subject: [PATCH 463/562] Apply prettier to docs --- README.md | 6 +++--- docs/output.md | 15 ++++++++++----- docs/usage.md | 35 ++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index a8922177..a4d978cd 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ available in oncoanalyser. The targeted sequencing workflow has built-in support custom panels with externally-generated normalisation data. The key analysis results for each sample are summarised and presented in an ORANGE report (summary page excerpt shown -below from *[COLO829_wgts.orange_report.pdf](https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/other/example_report/COLO829_wgts.orange_report.pdf)*): +below from _[COLO829_wgts.orange_report.pdf](https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/other/example_report/COLO829_wgts.orange_report.pdf)_):

    @@ -107,7 +107,7 @@ Each release that is given extended support is allocated a separate long-lived g Versions nominated to have current long-term support: -* TBD +- TBD ### Release parity @@ -116,7 +116,7 @@ equivalence of these two pieces of software. The functional/feature parity with in the below table. | oncoanalyser | hmftools | -| --- | --- | +| ------------------- | -------- | | 0.1.0 through 0.2.7 | 5.33 | | 0.3.0 through 0.3.1 | 5.34 | diff --git a/docs/output.md b/docs/output.md index 73cd57bf..a7eb0aff 100644 --- a/docs/output.md +++ b/docs/output.md @@ -86,14 +86,14 @@ hmftools. [bwa-mem2](https://github.com/bwa-mem2/bwa-mem2) is a short-read mapping tool used to align reads to a large reference sequences. In oncoanalyser, bwa-mem2 is used to align DNA reads to the human genome. -*No outputs are published directly from bwa-mem2, see [MarkDups](#markdups) for the fully processed alignment outputs* +_No outputs are published directly from bwa-mem2, see [MarkDups](#markdups) for the fully processed alignment outputs_ #### STAR [STAR](https://github.com/alexdobin/STAR) is a specialised mapping to used to align RNA reads to a reference transcriptome. -*No outputs are published directly from STAR, see [Picard MarkDuplicates](#picard-markduplicates) for the fully processed alignment outputs* +_No outputs are published directly from STAR, see [Picard MarkDuplicates](#picard-markduplicates) for the fully processed alignment outputs_ ### Alignment post-processing @@ -116,7 +116,7 @@ transcriptome. routines such as duplicate marking and unmapping of problematic regions. It can also handle UMIs when configured to do so. -*MarkDups is only run on DNA alignments* +_MarkDups is only run on DNA alignments_ ### Picard MarkDuplicates @@ -133,7 +133,7 @@ so. [Picard MarkDuplicates](https://gatk.broadinstitute.org/hc/en-us/articles/360037052812-MarkDuplicates-Picard) used to mark duplicate reads following alignment. -*Picard MarkDuplicates is only run on RNA alignments* +_Picard MarkDuplicates is only run on RNA alignments_ ### SNV, MNV, INDEL calling @@ -143,10 +143,12 @@ mark duplicate reads following alignment. Output files - `/sage/append/` + - `.sage.append.vcf.gz`: Tumor DNA sample small variant VCF with RNA data appended. - `.sage.append.vcf.gz`: Normal DNA sample small variant VCF with RNA data appended.. - `/sage/somatic/` + - `.sage.bqr.png`: Normal DNA sample base quality recalibration metrics plot. - `.sage.bqr.tsv`: Normal DNA sample base quality recalibration metrics. - `.sage.bqr.png`: Tumor DNA sample base quality recalibration metrics plot. @@ -198,7 +200,7 @@ information with regards to transcript and coding effects. [SvPrep](https://github.com/hartwigmedical/hmftools/tree/master/sv-prep) runs prior to SV calling to reducing runtime by rapidly identifying reads that are likely to be involved in a SV event. -*No outputs are published directly from SvPrep, see [GRIPSS](#gripss) for the fully processed SV calling outputs* +_No outputs are published directly from SvPrep, see [GRIPSS](#gripss) for the fully processed SV calling outputs_ #### GRIDSS @@ -220,6 +222,7 @@ breakend/breakpoint assemblies to call variants. Output files - `/gripss/germline/` + - `.gripss.filtered.germline.vcf.gz`: Filtered GRIDSS germline structural variants. - `.gripss.filtered.germline.vcf.gz.tbi`: Filtered GRIDSS germline structural variants index. - `.gripss.germline.vcf.gz`: GRIDSS structural variants (GRIPSS filters set but not applied). @@ -319,6 +322,7 @@ purity/ploidy and annotates both small and structural variant calls with copy-nu Output files - `/linx/germline_annotations/` + - `linx.version`: LINX version file. - `.linx.germline.breakend.tsv`: Normal DNA sample breakend data. - `.linx.germline.clusters.tsv`: Normal DNA sample clustered events. @@ -328,6 +332,7 @@ purity/ploidy and annotates both small and structural variant calls with copy-nu - `.linx.germline.svs.tsv`: Normal DNA sample structural variants. - `/linx/somatic_annotations/` + - `linx.version`: LINX version file. - `.linx.breakend.tsv`: Tumor DNA sample breakend data. - `.linx.clusters.tsv`: Tumor DNA sample clustered events. diff --git a/docs/usage.md b/docs/usage.md index 1c05e06a..b662fbad 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -23,23 +23,24 @@ locally to optimise execution or modified to create user-defined driver gene pan > [!WARNING] > There are important requirements when using BAMs as input instead of FASTQs: -> - STAR must have been run with [specific -> parameters](https://github.com/hartwigmedical/hmftools/tree/master/isofox#a-note-on-alignment-and-multi-mapping), -> this is critical for WTS data, and -> - reads are expected to have been aligned to one of the Hartwig-distributed reference genomes (user-defined genomes may be used though are not recommended) +> +> - STAR must have been run with [specific +> parameters](https://github.com/hartwigmedical/hmftools/tree/master/isofox#a-note-on-alignment-and-multi-mapping), +> this is critical for WTS data, and +> - reads are expected to have been aligned to one of the Hartwig-distributed reference genomes (user-defined genomes may be used though are not recommended) ## Supported analyses A variety of analyses are accessible in oncoanalyser and are implicitly run according to the data available in the samplesheet. The supported analysis types for each workflow are listed below. -| Input sequence data | WGS/WTS workflow | Targeted sequencing workflow\* | -| --- | :-: | :-: | -| • Tumor/normal DNA
    • Tumor RNA | :white_check_mark: | - | -| • Tumor only DNA
    • Tumor RNA | :white_check_mark: | :white_check_mark: | -| • Tumor/normal DNA | :white_check_mark: | - | -| • Tumor only DNA | :white_check_mark: | :white_check_mark: | -| • Tumor only RNA | :white_check_mark: | - | +| Input sequence data | WGS/WTS workflow | Targeted sequencing workflow\* | +| ----------------------------------- | :----------------: | :---------------------------------------: | +| • Tumor/normal DNA
    • Tumor RNA | :white_check_mark: | - | +| • Tumor only DNA
    • Tumor RNA | :white_check_mark: | :white_check_mark: | +| • Tumor/normal DNA | :white_check_mark: | - | +| • Tumor only DNA | :white_check_mark: | :white_check_mark: | +| • Tumor only RNA | :white_check_mark: | - | \* Supported analyses relate to the TSO500 panel only @@ -106,7 +107,7 @@ P2__wgts,P2,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P2.SB.tum ### Column descriptions | Column | Description | -| --- | --- | +| ------------- | -------------------------------------------------------------------- | | group_id | Group ID for a set of samples and inputs | | subject_id | Subject/patient ID | | sample_id | Sample ID | @@ -117,9 +118,9 @@ P2__wgts,P2,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P2.SB.tum The identifiers provided in the samplesheet are used to set output file paths: -* `group_id`: top-level output directory for analysis files e.g. `output/COLO829_example/` -* tumor `sample_id`: output prefix for most filenames e.g. `COLO829T.purple.sv.vcf.gz` -* normal `sample_id`: output prefix for some filenames e.g. `COLO829R.cobalt.ratio.pcf` +- `group_id`: top-level output directory for analysis files e.g. `output/COLO829_example/` +- tumor `sample_id`: output prefix for most filenames e.g. `COLO829T.purple.sv.vcf.gz` +- normal `sample_id`: output prefix for some filenames e.g. `COLO829R.cobalt.ratio.pcf` ## Running the pipeline @@ -247,7 +248,7 @@ nextflow run nf-core/oncoanalyser \ ``` > [!WARNING] -> Providing existing inputs will cause oncoanalyser to skip the corresponding process but *not any* of the upstream +> Providing existing inputs will cause oncoanalyser to skip the corresponding process but _not any_ of the upstream > processes. ### Configuring reference data @@ -255,7 +256,7 @@ nextflow run nf-core/oncoanalyser \ All reference data can be configured as needed. These are defined in various locations: | Reference data | Filepath | Note | -| --- | --- | --- | +| ----------------------- | ------------------------- | --------------------------------------- | | hmftools resource files | `conf/hmf_data.config` | Paths relative to data bundle directory | | panel resource files | `conf/panel_data.config` | Paths relative to data bundle directory | | Genomes and indexes | `conf/hmf_genomes.config` | Absolute paths | From 795562732a5ab48243c36fc292dc0fe042224dbb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 16:41:51 +1100 Subject: [PATCH 464/562] Link typo in docs/output.md --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index a7eb0aff..a93c665c 100644 --- a/docs/output.md +++ b/docs/output.md @@ -67,7 +67,7 @@ output/ - [LILAC](#lilac) - HLA calling - [HRD status prediction](#hrd-status-prediction) - [CHORD](#chord) - HRD status prediction -- [Mutational signature fitting](#mutation-signature-fitting) +- [Mutational signature fitting](#mutational-signature-fitting) - [Sigs](#sigs) - Mutational signature fitting - [Tissue of origin prediction](#tissue-of-origin-prediction) - [CUPPA](#cuppa) - Tissue of origin prediction From 04ba0684eb3f6a8096e4e9c318e8bde66076fa0c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 15 Mar 2024 17:05:01 +1100 Subject: [PATCH 465/562] Improve docs/usage.md --- docs/usage.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index b662fbad..24ba4fb5 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -49,8 +49,8 @@ samplesheet. The supported analysis types for each workflow are listed below. A samplesheet that contains information of each input in CSV format is needed to run oncoanalyser. The required input details and columns are [described below](#column-descriptions). -The oncoanalyser pipeline also recognises several input filetypes, including intermediate output files generated during -execution such as the PURPLE output directory. The full list recognised input filetypes is available +Several different input filetypes beyond FASTQ and BAM are recognised, including intermediate output files generated +during execution such as the PURPLE output directory. The full list of recognised input filetypes is available [here](https://github.com/nf-core/oncoanalyser/blob/v0.3.1/lib/Constants.groovy#L56-L86). ### Simple example @@ -114,6 +114,7 @@ P2__wgts,P2,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P2.SB.tum | sample_type | Sample type: `tumor`, `normal` | | sequence_type | Sequence type: `dna`, `rna` | | filetype | File type: e.g. `fastq`, `bam`, `bai` | +| info | Additional input information: `library_id`, `lane`, `cancer_type` | | filepath | Absolute filepath to input file (can be local filepath, URL, S3 URI) | The identifiers provided in the samplesheet are used to set output file paths: @@ -139,9 +140,9 @@ nextflow run nf-core/oncoanalyser \ This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. > [!NOTE] -> When oncoanalyser is run, it will retrieve all reference data it requires to perform the requested analysis. When -> running oncoanalyser more than once, it is strongly recommended to pre-stage reference data locally to avoid it being -> retrieved multiple times by oncoanalyser. See [Staging reference data](#staging-reference-data). +> Reference data will be retrieved by oncoanalyser for every analysis run. It is therefore strongly recommended when +> running multiple analyses to pre-stage reference data locally to avoid it being retrieved multiple times. See [Staging +> reference data](#staging-reference-data). Note that the pipeline will create the following files in your working directory: @@ -215,16 +216,17 @@ described in the follow section. ### Existing inputs -The oncoanalyser pipeline has been designed to allow entry at arbiturary points and is particularly useful in +The oncoanalyser pipeline has been designed to allow entry at arbitrary points, which is particularly useful in situtations where previous outputs exist and re-running oncoanalyser is desired (e.g. to subsequently execute an optional sensor or use an upgrade component such as PURPLE). The primary advantage of this approach is that only the -required processes are executed, which can greatly reduce runtimes by skipping unneccessary processes. +required processes are executed, reducing costs and runtimes by skipping unneccessary processes. In order to effectively utilise this feature, existing inputs must be set in the [samplesheet](#samplesheet) and the appropriate [processes selected](#selecting-processes). Take the below example where existing PURPLE inputs are used so that all upstream variant calling can be skipped: ```csv title='samplesheet.existing_purple.csv' +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath P1__wgts,P1,SA,normal,dna,bam,/path/to/P1.SA.normal.dna.wgs.bam P1__wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam P1__wgts,P1,SB,tumor,dna,purple_dir,/path/to/P1.purple_dir/ @@ -249,7 +251,7 @@ nextflow run nf-core/oncoanalyser \ > [!WARNING] > Providing existing inputs will cause oncoanalyser to skip the corresponding process but _not any_ of the upstream -> processes. +> processes. It is the responsibility of the user to skip all relevant processes. ### Configuring reference data @@ -257,14 +259,14 @@ All reference data can be configured as needed. These are defined in various loc | Reference data | Filepath | Note | | ----------------------- | ------------------------- | --------------------------------------- | -| hmftools resource files | `conf/hmf_data.config` | Paths relative to data bundle directory | -| panel resource files | `conf/panel_data.config` | Paths relative to data bundle directory | | Genomes and indexes | `conf/hmf_genomes.config` | Absolute paths | +| hmftools resource files | `conf/hmf_data.config` | Paths relative to data bundle directory | +| Panel resource files | `conf/panel_data.config` | Paths relative to data bundle directory | To override hmftools resource files (e.g. driver gene panel), [stage the bundle](#staging-reference-data) locally then -copy in the desired file(s) and update `conf/hmf_data.config` accordingly. The local custom bundle must be provided to -oncoanalyser with the `--ref_data_hmf_data_path` CLI option. The same approach is followed for customising panel -resource files, configuring `conf/panel_data.config` and supplying with `--ref_data_panel_data_path` instead. +copy in the user-created file(s) and update `conf/hmf_data.config` accordingly. The local custom bundle must be provided +to oncoanalyser with the `--ref_data_hmf_data_path` CLI option. The same approach is followed for customising panel +resource files but configuring `conf/panel_data.config` and supplying with `--ref_data_panel_data_path` instead. The path or URI to the VIRUSBreakend database can also be explicitly set with `--ref_data_virusbreakenddb_path`. Configuring custom genomes uses a different approach to align with the existing concepts in nf-core. From 92d5285fb2dcebe8d4b10866393bf87e9d2a0ea7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 19 Mar 2024 18:59:41 +1100 Subject: [PATCH 466/562] Correct and clarify development/stable branches --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a4d978cd..83e1ed8b 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,8 @@ accomplished through long-term support of several nominated feature releases, wh fixes during the period of extended support. Each release that is given extended support is allocated a separate long-lived git branch with the 'stable' prefix, e.g. -`stable/1.2.x`, `stable/1.5.x`. Feature development otherwise occurs on the `main` branch. +`stable/1.2.x`, `stable/1.5.x`. Feature development otherwise occurs on the `dev` branch with stable releases pushed to +`master`. Versions nominated to have current long-term support: From afacc486485e8bf54ef319a9fde1ee42f8c1cc55 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 30 Apr 2024 20:14:36 +1000 Subject: [PATCH 467/562] Update release parity versions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 83e1ed8b..dac5f459 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ in the below table. | oncoanalyser | hmftools | | ------------------- | -------- | | 0.1.0 through 0.2.7 | 5.33 | -| 0.3.0 through 0.3.1 | 5.34 | +| 0.3.0 through 0.4.5 | 5.34 | ## Credits From 2a8b218991355dad8cc4edb6f35443debb6eeac9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 3 May 2024 16:23:50 +1000 Subject: [PATCH 468/562] Update prepare reference data docs --- README.md | 2 +- REFERENCE_DATA_STAGING.md | 94 --------------------- docs/usage.md | 168 +++++++++++++++++++++++++++++++------- 3 files changed, 138 insertions(+), 126 deletions(-) delete mode 100644 REFERENCE_DATA_STAGING.md diff --git a/README.md b/README.md index dac5f459..8bd70dee 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Launch oncoanalyser: ```bash nextflow run nf-core/oncoanalyser \ -profile docker \ - -revision v0.3.1 \ + -revision 0.4.5 \ --mode wgts \ --genome GRCh38_hmf \ --input samplesheet.csv \ diff --git a/REFERENCE_DATA_STAGING.md b/REFERENCE_DATA_STAGING.md deleted file mode 100644 index a5c13065..00000000 --- a/REFERENCE_DATA_STAGING.md +++ /dev/null @@ -1,94 +0,0 @@ -# Reference data staging - -Download and unpack - -> All reference data is retrieved here, exclude unused files as desired; using GRCh38_hmf below - -```bash -base_url=https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev - -fps=' -genomes/GRCh37_hmf/Homo_sapiens.GRCh37.GATK.illumina.fasta -genomes/GRCh37_hmf/bwa_index/0.7.17-r1188.tar.gz -genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.0123 -genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64 -genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img -genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache -genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict -genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai -genomes/GRCh37_hmf/star_index/gencode_19/2.7.3a.tar.gz -genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna -genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz -genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123 -genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64 -genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img -genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache -genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict -genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai -genomes/GRCh38_hmf/star_index/gencode_38/2.7.3a.tar.gz -hmf_reference_data/hmftools/5.34_37--2.tar.gz -hmf_reference_data/hmftools/5.34_38--2.tar.gz -hmf_reference_data/panels/tso500_5.34_37--1.tar.gz -hmf_reference_data/panels/tso500_5.34_38--1.tar.gz -virusbreakend/virusbreakenddb_20210401.tar.gz -' - -parallel -j4 wget -c -x -nH -P reference_data/ ${base_url}/{} ::: ${fps} -find reference_data/ -name '*.tar.gz' | parallel -j0 'cd {//} && tar -xzvf {/}' -``` - -Create Nextflow config file for local reference data - -```bash -cat < refdata.local.config -params { - genomes { - 'GRCh37_hmf' { - fasta = "$(pwd)/genomes/GRCh37_hmf/Homo_sapiens.GRCh37.GATK.illumina.fasta" - fai = "$(pwd)/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" - dict = "$(pwd)/genomes/GRCh37_hmf/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" - bwa_index = "$(pwd)/genomes/GRCh37_hmf/bwa_index/0.7.17-r1188.tar.gz" - bwa_index_bseq = "$(pwd)/genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.0123" - bwa_index_biidx = "$(pwd)/genomes/GRCh37_hmf/bwa_index/2.2.1/Homo_sapiens.GRCh37.GATK.illumina.fasta.bwt.2bit.64" - bwa_index_image = "$(pwd)/genomes/GRCh37_hmf/bwa_index_image/0.7.17-r1188/Homo_sapiens.GRCh37.GATK.illumina.fasta.img" - gridss_index = "$(pwd)/genomes/GRCh37_hmf/gridss_index/2.13.2/Homo_sapiens.GRCh37.GATK.illumina.fasta.gridsscache" - star_index = "$(pwd)/genomes/GRCh37_hmf/star_index/gencode_19/2.7.3a.tar.gz" - } - 'GRCh38_hmf' { - fasta = "$(pwd)/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" - fai = "$(pwd)/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" - dict = "$(pwd)/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwa_index = "$(pwd)/reference_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188/" - bwa_index_bseq = "$(pwd)/reference_data/genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" - bwa_index_biidx = "$(pwd)/reference_data/genomes/GRCh38_hmf/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" - bwa_index_image = "$(pwd)/reference_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" - gridss_index = "$(pwd)/reference_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" - star_index = "$(pwd)/reference_data/genomes/GRCh38_hmf/star_index/gencode_38/2.7.3a/" - } - } - - ref_data_hmf_data_path = "$(pwd)/reference_data/hmf_reference_data/hmftools/5.34_38--2/" - ref_data_panel_data_path = "$(pwd)/reference_data/hmf_reference_data/panels/tso500_5.34_38--1/" - ref_data_virusbreakenddb_path = "$(pwd)/reference_data/virusbreakend/virusbreakenddb_20210401/" -} -EOF -``` - -Run oncoanalyser with local reference data - -> Assumes existing samplesheet at `samplesheet.csv` - -```bash -nextflow run oncoanalyser/main.nf \ - \ - -config refdata.local.config \ - -profile docker \ - -revision v0.3.1 \ - \ - --mode targeted \ - --panel tso500 \ - --genome GRCh38_hmf \ - \ - --input samplesheet.csv \ - --outdir output/ -``` diff --git a/docs/usage.md b/docs/usage.md index 24ba4fb5..52b9c663 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -51,7 +51,7 @@ details and columns are [described below](#column-descriptions). Several different input filetypes beyond FASTQ and BAM are recognised, including intermediate output files generated during execution such as the PURPLE output directory. The full list of recognised input filetypes is available -[here](https://github.com/nf-core/oncoanalyser/blob/v0.3.1/lib/Constants.groovy#L56-L86). +[here](https://github.com/nf-core/oncoanalyser/blob/0.4.5/lib/Constants.groovy#L58-L90). ### Simple example @@ -130,7 +130,7 @@ The typical command for running the pipeline is as follows: ```bash nextflow run nf-core/oncoanalyser \ -profile docker \ - -revision v0.3.1 \ + -revision 0.4.5 \ --mode \ --genome \ --input samplesheet.csv \ @@ -205,7 +205,7 @@ If you wish to share such profile (such as upload as supplementary material for ### Selecting processes Most of the major components in oncoanalyser can be skipped using `--processes_exclude` (the full list of available -processes can be view [here](https://github.com/nf-core/oncoanalyser/blob/v0.3.1/lib/Constants.groovy#L36-L54)). +processes can be view [here](https://github.com/nf-core/oncoanalyser/blob/0.4.5/lib/Constants.groovy#L36-L56)). Multiple processes can be given as comma-separated list. While there are some use-cases for this feature (e.g. skipping resource intensive processes such as VIRUSBreakend), it becomes more powerful when combined with existing inputs as described in the follow section. @@ -241,9 +241,9 @@ And now run and skip variant calling: ```bash nextflow run nf-core/oncoanalyser \ -profile docker \ - -revision v0.3.1 \ + -revision 0.4.5 \ --mode wgts \ - --processes_exclude amber,cobalt,gridss,gripss,sage,pave \ + --processes_exclude markdups,amber,cobalt,gridss,gripss,sage,pave \ --genome GRCh38_hmf \ --input samplesheet.csv \ --outdir output/ @@ -255,7 +255,7 @@ nextflow run nf-core/oncoanalyser \ ### Configuring reference data -All reference data can be configured as needed. These are defined in various locations: +All reference data can be configured as needed, and are defined in the following locations: | Reference data | Filepath | Note | | ----------------------- | ------------------------- | --------------------------------------- | @@ -263,34 +263,132 @@ All reference data can be configured as needed. These are defined in various loc | hmftools resource files | `conf/hmf_data.config` | Paths relative to data bundle directory | | Panel resource files | `conf/panel_data.config` | Paths relative to data bundle directory | -To override hmftools resource files (e.g. driver gene panel), [stage the bundle](#staging-reference-data) locally then -copy in the user-created file(s) and update `conf/hmf_data.config` accordingly. The local custom bundle must be provided -to oncoanalyser with the `--ref_data_hmf_data_path` CLI option. The same approach is followed for customising panel -resource files but configuring `conf/panel_data.config` and supplying with `--ref_data_panel_data_path` instead. +See the below sections for further details on customising reference data. -The path or URI to the VIRUSBreakend database can also be explicitly set with `--ref_data_virusbreakenddb_path`. -Configuring custom genomes uses a different approach to align with the existing concepts in nf-core. +#### Customising hmf data + +To override hmftools resource files, first [stage the bundle](#staging-reference-data) locally then copy in your +custom file under the bundle directory and create a new config with relevant file paths: + +```text title="hmf_data.custom.config" +params { + hmf_data_paths { + '38' { + driver_gene_panel = 'custom_files/DriverGenePanel.tsv' + sage_actionable_panel = 'custom_files/ActionableCodingPanel.bed.gz' + sage_coverage_panel = 'custom_files/CoverageCodingPanel.bed.gz' + } + } +} +``` + +To use these hmftools resource file overrides in oncoanalyser the local bundle directory must be provided with +`--ref_data_hmf_data_path`. + +#### Customise other data + +The path or URI to the VIRUSBreakend database can also be explicitly set with `--ref_data_virusbreakenddb_path`. There +are additional arguments to manually set various other reference data files, please review parameters documentation for +the complete list. + +#### Staging reference data + +Default reference data can be staged locally with oncoanalyser by providing a samplesheet for the desired analysis and +setting the `--prepare_reference_only` argument. The samplesheet and oncoanalyser configuration is used to determine the +revelant reference data to download. For example the following will download the GRCh38_hmf genome plus indices, +reference data, and databases required to run a WGTS analysis for tumor/normal DNA with tumor RNA: + +```csv title="samplesheet.csv" +group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath +P1__wgts,P1,SA,normal,dna,bam,/path/to/P1.SA.normal.dna.wgs.bam +P1__wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam +P1__wgts,P1,SC,tumor,rna,bam,/path/to/P1.SC.tumor.rna.wts.bam +``` + +```bash +nextflow run nf-core/oncoanalyser \ + -profile docker \ + -revision 0.4.5 \ + --mode wgts \ + --genome GRCh38_hmf \ + --prepare_reference_only \ + --input samplesheet.csv \ + --outdir prepare_reference/ +``` + +This process will download and unpack default reference data without running any analysis, and once complete the +prepared reference files can found in `./prepare_reference/reference_data/0.4.5//`. It is recommended to +remove the Nextflow work directory after staging data to free disk space. + +For oncoanalyser to use locally staged reference data a custom config can be used: + +```text title="refdata.local.config" +params { + + genomes { + GRCh38_hmf { + fasta = "/path/to/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" + fai = "/path/to/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" + dict = "/path/to/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" + bwa_index = "/path/to/bwa-mem2_index/" + gridss_index = "/path/to/gridss_index/" + star_index = "/path/to/star_index/" + } + } + + ref_data_hmf_data_path = "/path/to/hmftools_data/" + ref_data_panel_data_path = "/path/to/tso500_panel_data/" + ref_data_virusbreakenddb_path = "/path/to/virusbreakenddb/" +} +``` + +Specific reference files can also be downloaded directly from the hosting service with the corresponding URL. + +##### Reference data URLs + +_GRCh37 genome (Hartwig) [`GRCh37_hmf`]_ + +| Type | Name | +| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| FASTA | [Homo_sapiens.GRCh37.GATK.illumina.fasta](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/Homo_sapiens.GRCh37.GATK.illumina.fasta) | +| FASTA index | [Homo_sapiens.GRCh37.GATK.illumina.fasta.fai](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai) | +| FASTA seq dictionary | [Homo_sapiens.GRCh37.GATK.illumina.fasta.dict](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict) | +| bwa-mem2 index | [bwa_index/2.2.1.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/bwa_index/2.2.1.tar.gz) | +| GRIDSS index | [gridss_index/2.13.2.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/gridss_index/2.13.2.tar.gz) | +| STAR index | [star_index/gencode_19/2.7.3a.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/star_index/gencode_19/2.7.3a.tar.gz) | + +_GRCh37 genome (Hartwig) [`GRCh38_hmf`]_ + +| Type | Name | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| FASTA | [GCA_000001405.15_GRCh38_no_alt_analysis_set.fna](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna) | +| FASTA index | [GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai) | +| FASTA seq dictionary | [GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict) | +| bwa-mem2 index | [bwa_index/2.2.1.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/bwa_index/2.2.1.tar.gz) | +| GRIDSS index | [gridss_index/2.13.2.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/gridss_index/2.13.2.tar.gz) | +| STAR index | [star_index/gencode_38/2.7.3a.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/star_index/gencode_38/2.7.3a.tar.gz) | + +_Other reference data_ + +| Type | Name | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| hmftools data (GRCh37) | [hmftools/5.34_37--2.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/hmf_reference_data/hmftools/5.34_37--2.tar.gz) | +| hmftools data (GRCh38) | [hmftools/5.34_38--2.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/hmf_reference_data/hmftools/5.34_38--2.tar.gz) | +| TSO500 data (GRCh37) | [panels/tso500_5.34_37--1.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/hmf_reference_data/panels/tso500_5.34_37--1.tar.gz) | +| TSO500 data (GRCh38) | [panels/tso500_5.34_38--1.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/hmf_reference_data/panels/tso500_5.34_38--1.tar.gz) | +| HLA slice BED | [hla_slice/grch38_alt.plus_homologous.bed](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/other/hla_slice/grch38_alt.plus_homologous.bed) | +| VIRUSBreakend database | [virusbreakenddb_20210401.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/virusbreakend/virusbreakenddb_20210401.tar.gz) | #### Custom genomes -It is strongly recommended to use the Hartwig-distributed reference genomes for alignments -([GRCh37](https://console.cloud.google.com/storage/browser/hmf-public/HMFtools-Resources/ref_genome/37) or -[GRCh38](https://console.cloud.google.com/storage/browser/hmf-public/HMFtools-Resources/ref_genome/38)). If there is no -other option than to use a custom genome, one can be configured with the following process: +It is strongly recommended to use the Hartwig-distributed reference genomes for alignments (GRCh37_hmf or GRCh38_hmf). +If there is no other option than to use a custom genome, one can be configured with the following process: ```text title='genome.custom.config' params { genomes { CustomGenome { - fasta = "/path/to/CustomGenome/custom_genome.fa" - fai = "/path/to/CustomGenome/samtools_index/1.16/custom_genome.fa.fai" - dict = "/path/to/CustomGenome/samtools_index/1.16/custom_genome.fa.dict" - bwa_index = "/path/to/CustomGenome/bwa_index/0.7.17-r1188/" - bwa_index_bseq = "/path/to/CustomGenome/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.0123" - bwa_index_biidx = "/path/to/CustomGenome/bwa_index/2.2.1/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bwt.2bit.64" - bwa_index_image = "/path/to/CustomGenome/bwa_index_image/0.7.17-r1188/custom_genome.fa.img" - gridss_index = "/path/to/CustomGenome/gridss_index/2.13.2/custom_genome.fa.gridsscache" - star_index = "/path/to/CustomGenome/star_index/gencode_38/2.7.3a/" + fasta = "/path/to/custom_genome.fa" } } } @@ -301,7 +399,7 @@ Run a custom genome with the above configuration and below command ```bash nextflow run nf-core/oncoanalyser \ -profile docker \ - -revision v0.3.1 \ + -revision 0.4.5 \ -config genome.custom.config \ --mode wgts \ \ @@ -314,13 +412,21 @@ nextflow run nf-core/oncoanalyser \ --outdir output/ ``` -> [!WARNING] -> RNA alignment with STAR must use an index generated from a matching Ensembl release version (GRCh37: v74; GRCh38: -> v104). +Creation of a STAR index also requires transcript annotations, please use either of the following via the +`--ref_data_genome_gtf` option: -#### Staging reference data +- GRCh37: [GENCODE v38 (Ensembl v104) + annotations](https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_38/gencode.v38.annotation.gtf.gz) +- GRCh38: [GENCODE v37 (Ensembl v74) + annotations](https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_19/gencode.v19.annotation.gtf.gz) + +> [!WARNING] +> STAR index must use transcript annotations from Ensembl versions that match hmftoos resource data (GRCh37: v74; +> GRCh38: v104). -Please refer to [REFERENCE_DATA.md](https://github.com/nf-core/oncoanalyser/REFERENCE_DATA.md). +When creating indexes for reference genomes with alternative haplotypes, an ALT file must be provided with +`--ref_data_genome_alt`. Importantly, a STAR index will not be generated for reference genomes with alternative +haplotypes since this requires careful processing and is hence left to the user. ## Core Nextflow arguments From 7ece657487c6456555ac384e932db88301673b83 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 10 May 2024 11:23:16 +1000 Subject: [PATCH 469/562] Various documentation edits --- docs/usage.md | 93 +++++++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 52b9c663..71ebac28 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -15,11 +15,11 @@ Various aspects of an oncoanalyser analysis can be configured to fit a range of - precise process selection - starting from existing data -- granular control over resource data +- granular control over reference/resource files These features enable oncoanalyser to be run in a highly flexible way. For example, an analysis can be run with existing -PURPLE data as the starting point and skip variant calling processes. Additionally, resource/reference data can staged -locally to optimise execution or modified to create user-defined driver gene panels. +PURPLE data as the starting point and skip variant calling processes. Additionally, reference/resource files can be +staged locally to optimise execution or modified to create user-defined driver gene panels. > [!WARNING] > There are important requirements when using BAMs as input instead of FASTQs: @@ -31,7 +31,7 @@ locally to optimise execution or modified to create user-defined driver gene pan ## Supported analyses -A variety of analyses are accessible in oncoanalyser and are implicitly run according to the data available in the +A variety of analyses are accessible in oncoanalyser and are implicitly run according to the data described in the samplesheet. The supported analysis types for each workflow are listed below. | Input sequence data | WGS/WTS workflow | Targeted sequencing workflow\* | @@ -106,16 +106,16 @@ P2__wgts,P2,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P2.SB.tum ### Column descriptions -| Column | Description | -| ------------- | -------------------------------------------------------------------- | -| group_id | Group ID for a set of samples and inputs | -| subject_id | Subject/patient ID | -| sample_id | Sample ID | -| sample_type | Sample type: `tumor`, `normal` | -| sequence_type | Sequence type: `dna`, `rna` | -| filetype | File type: e.g. `fastq`, `bam`, `bai` | -| info | Additional input information: `library_id`, `lane`, `cancer_type` | -| filepath | Absolute filepath to input file (can be local filepath, URL, S3 URI) | +| Column | Description | +| ------------- | ------------------------------------------------------------------------------ | +| group_id | Group ID for a set of samples and inputs | +| subject_id | Subject/patient ID | +| sample_id | Sample ID | +| sample_type | Sample type: `tumor`, `normal` | +| sequence_type | Sequence type: `dna`, `rna` | +| filetype | File type: e.g. `fastq`, `bam`, `bai` | +| info | Additional input information: `library_id`, `lane`, `cancer_type` _[optional]_ | +| filepath | Absolute filepath to input file (can be local filepath, URL, S3 URI) | The identifiers provided in the samplesheet are used to set output file paths: @@ -137,7 +137,7 @@ nextflow run nf-core/oncoanalyser \ --outdir ``` -This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. +This will launch the pipeline with the `docker` configuration profile. See below for more information on profiles. > [!NOTE] > Reference data will be retrieved by oncoanalyser for every analysis run. It is therefore strongly recommended when @@ -194,7 +194,7 @@ First, go to the [nf-core/oncoanalyser releases page](https://github.com/nf-core This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. -To further assist in reproducbility, you can use share and re-use [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. +To further assist in reproducbility, you can share and re-use [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. :::tip If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. @@ -206,20 +206,20 @@ If you wish to share such profile (such as upload as supplementary material for Most of the major components in oncoanalyser can be skipped using `--processes_exclude` (the full list of available processes can be view [here](https://github.com/nf-core/oncoanalyser/blob/0.4.5/lib/Constants.groovy#L36-L56)). -Multiple processes can be given as comma-separated list. While there are some use-cases for this feature (e.g. skipping -resource intensive processes such as VIRUSBreakend), it becomes more powerful when combined with existing inputs as -described in the follow section. +Multiple processes can be given as a comma-separated list. While there are some use-cases for this feature (e.g. +skipping resource intensive processes such as VIRUSBreakend), it becomes more powerful when combined with existing +inputs as described in the following section. > [!WARNING] -> When skipping components, no checks are done to identify orphan processes in the execution DAG or for redundant +> When skipping components no checks are done to identify orphan processes in the execution DAG or for redundant > processes. ### Existing inputs The oncoanalyser pipeline has been designed to allow entry at arbitrary points, which is particularly useful in -situtations where previous outputs exist and re-running oncoanalyser is desired (e.g. to subsequently execute an +situations where previous outputs exist and re-running oncoanalyser is desired (e.g. to subsequently execute an optional sensor or use an upgrade component such as PURPLE). The primary advantage of this approach is that only the -required processes are executed, reducing costs and runtimes by skipping unneccessary processes. +required processes are executed, reducing costs and runtimes by skipping unnecessary processes. In order to effectively utilise this feature, existing inputs must be set in the [samplesheet](#samplesheet) and the appropriate [processes selected](#selecting-processes). Take the below example where existing PURPLE inputs are used so @@ -288,15 +288,15 @@ To use these hmftools resource file overrides in oncoanalyser the local bundle d #### Customise other data The path or URI to the VIRUSBreakend database can also be explicitly set with `--ref_data_virusbreakenddb_path`. There -are additional arguments to manually set various other reference data files, please review parameters documentation for -the complete list. +are additional arguments to manually set various other reference data files, please review the parameters documentation +for the complete list. #### Staging reference data Default reference data can be staged locally with oncoanalyser by providing a samplesheet for the desired analysis and -setting the `--prepare_reference_only` argument. The samplesheet and oncoanalyser configuration is used to determine the -revelant reference data to download. For example the following will download the GRCh38_hmf genome plus indices, -reference data, and databases required to run a WGTS analysis for tumor/normal DNA with tumor RNA: +setting the `--prepare_reference_only` argument. The samplesheet and oncoanalyser configuration will determine the +relevant reference data to download. For example the following command will download the `GRCh38_hmf` genome plus +indices, reference data, and databases required to run a WGTS analysis for tumor/normal DNA with tumor RNA: ```csv title="samplesheet.csv" group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath @@ -316,9 +316,9 @@ nextflow run nf-core/oncoanalyser \ --outdir prepare_reference/ ``` -This process will download and unpack default reference data without running any analysis, and once complete the -prepared reference files can found in `./prepare_reference/reference_data/0.4.5//`. It is recommended to -remove the Nextflow work directory after staging data to free disk space. +Executing the above command will download and unpack default reference data without running any analysis, and once +complete the prepared reference files can found in `./prepare_reference/reference_data/0.4.5//`. It is +recommended to remove the Nextflow work directory after staging data to free disk space. For oncoanalyser to use locally staged reference data a custom config can be used: @@ -357,7 +357,7 @@ _GRCh37 genome (Hartwig) [`GRCh37_hmf`]_ | GRIDSS index | [gridss_index/2.13.2.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/gridss_index/2.13.2.tar.gz) | | STAR index | [star_index/gencode_19/2.7.3a.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/star_index/gencode_19/2.7.3a.tar.gz) | -_GRCh37 genome (Hartwig) [`GRCh38_hmf`]_ +_GRCh38 genome (Hartwig) [`GRCh38_hmf`]_ | Type | Name | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | @@ -381,8 +381,9 @@ _Other reference data_ #### Custom genomes -It is strongly recommended to use the Hartwig-distributed reference genomes for alignments (GRCh37_hmf or GRCh38_hmf). -If there is no other option than to use a custom genome, one can be configured with the following process: +It is strongly recommended to use a Hartwig-distributed reference genome for alignments and subsequent analysis +(`GRCh37_hmf` or `GRCh38_hmf`). Where it is not feasible to do so, a custom genome can instead be used by providing the +relevant FASTA file in a configuration file: ```text title='genome.custom.config' params { @@ -394,7 +395,13 @@ params { } ``` -Run a custom genome with the above configuration and below command +Each index required for the analysis will first be created before running the rest of oncoanalyser with the following +command: + +> [!NOTE] +> In a process similar to [staging reference data](#staging-reference-data), you can first generate the required indexes +> by setting `--prepare_reference_only` and then provide the prepared reference files to oncoanalyser through a custom +> config file. This avoids having to regenerate indexes for each new analysis. ```bash nextflow run nf-core/oncoanalyser \ @@ -412,8 +419,8 @@ nextflow run nf-core/oncoanalyser \ --outdir output/ ``` -Creation of a STAR index also requires transcript annotations, please use either of the following via the -`--ref_data_genome_gtf` option: +Creation of a STAR index also requires transcript annotations, please provide either of the following GTF files via the +`--ref_data_genome_gtf` option after decompressing: - GRCh37: [GENCODE v38 (Ensembl v104) annotations](https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_38/gencode.v38.annotation.gtf.gz) @@ -421,10 +428,10 @@ Creation of a STAR index also requires transcript annotations, please use either annotations](https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_19/gencode.v19.annotation.gtf.gz) > [!WARNING] -> STAR index must use transcript annotations from Ensembl versions that match hmftoos resource data (GRCh37: v74; +> STAR index must use transcript annotations from Ensembl versions that match hmftools resource data (GRCh37: v74; > GRCh38: v104). -When creating indexes for reference genomes with alternative haplotypes, an ALT file must be provided with +When creating indexes for reference genomes with alternative haplotypes, an ALT file must be given with `--ref_data_genome_alt`. Importantly, a STAR index will not be generated for reference genomes with alternative haplotypes since this requires careful processing and is hence left to the user. @@ -449,7 +456,7 @@ The pipeline also dynamically loads configurations from [https://github.com/nf-c Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! They are loaded in sequence, so later profiles can overwrite earlier profiles. -If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer enviroment. +If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer environment. - `test` - A profile with a complete configuration for automated testing @@ -489,13 +496,13 @@ Whilst the default requirements set within the pipeline will hopefully work for To change the resource requests, please see the [max resources](https://nf-co.re/docs/usage/configuration#max-resources) and [tuning workflow resources](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources) section of the nf-core website. -### Custom Containers +### Custom containers In some cases you may wish to change which container or conda environment a step of the pipeline uses for a particular tool. By default nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However in some cases the pipeline specified version maybe out of date. To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/usage/configuration#updating-tool-versions) section of the nf-core website. -### Custom Tool Arguments +### Custom tool arguments A pipeline might not always support every possible argument or option of a particular tool used in pipeline. Fortunately, nf-core pipelines provide some freedom to users to insert additional parameters that the pipeline does not include by default. @@ -509,13 +516,13 @@ See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack) on the [`#configs` channel](https://nfcore.slack.com/channels/configs). -## Azure Resource Requests +## Azure resource requests To be used with the `azurebatch` profile by specifying the `-profile azurebatch`. We recommend providing a compute `params.vm_type` of `Standard_D16_v3` VMs by default but these options can be changed if required. Note that the choice of VM size depends on your quota and the overall workload during the analysis. -For a thorough list, please refer the [Azure Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/sizes). +For a thorough list, please refer to the [Azure Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/sizes). ## Running in the background From 672678132318d8ac6ef08366ca544ba3670b77c3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 10 May 2024 17:48:30 +1000 Subject: [PATCH 470/562] Update pipeline tests --- conf/test.config | 11 +++++++++-- conf/test_full.config | 14 +++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/conf/test.config b/conf/test.config index 473d6a44..f8b9eab8 100644 --- a/conf/test.config +++ b/conf/test.config @@ -10,6 +10,12 @@ ---------------------------------------------------------------------------------------- */ +process { + withName: 'PURPLE' { + ext.args = '-min_purity 1 -max_purity 1 -min_ploidy 2 -max_ploidy 2' + } +} + params { config_profile_name = 'Test profile' config_profile_description = 'Minimal test dataset to check pipeline function' @@ -18,16 +24,17 @@ params { // execution. validationSchemaIgnoreParams = 'genomes,hmf_data_paths,panel_data_paths' + // NOTE(SW): incompatible with GHA given size of reference data // Limit resources so that this can run on GitHub Actions max_cpus = 1 max_memory = '8.GB' max_time = '6.h' // Input data - input = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/other/samplesheet.colo829_mini.dna_rna.grch38_hmf.csv' + input = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/simulated_reads/24.0/samplesheets/fastq_eval.subject_a-subject_b.wgts.tndna_trna.1.csv' mode = 'wgts' genome = 'GRCh38_hmf' - ref_data_virusbreakenddb_path = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/reference_data/virusbreakend/virusbreakenddb_test.tar.gz' + ref_data_virusbreakenddb_path = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/virusbreakend/virusbreakenddb_test-24.04.0.tar.gz' } diff --git a/conf/test_full.config b/conf/test_full.config index 6caf464e..ecd38c6d 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -10,15 +10,19 @@ ---------------------------------------------------------------------------------------- */ +process { + withName: 'PURPLE' { + ext.args = '-min_purity 1 -max_purity 1 -min_ploidy 2 -max_ploidy 2' + } +} + params { config_profile_name = 'Full test profile' config_profile_description = 'Full test dataset to check pipeline function' // Input data for full size test - // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) - // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_full_illumina_amplicon.csv' + input = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/simulated_reads/24.0/samplesheets/fastq_eval.subject_a-subject_b.wgts.tndna_trna.1.csv' - // Genome references - genome = 'R64-1-1' + mode = 'wgts' + genome = 'GRCh38_hmf' } From 7eedd642b04c9c4ea9f7034c64f156efded1d2cb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 10 May 2024 17:54:51 +1000 Subject: [PATCH 471/562] Remove schema ignore param from test profiles --- conf/test.config | 4 ---- conf/test_stub.config | 4 ---- 2 files changed, 8 deletions(-) diff --git a/conf/test.config b/conf/test.config index f8b9eab8..9e2a5cf5 100644 --- a/conf/test.config +++ b/conf/test.config @@ -20,10 +20,6 @@ params { config_profile_name = 'Test profile' config_profile_description = 'Minimal test dataset to check pipeline function' - // Defined here to be accessible within a workflow script; downloaded manually prior to process - // execution. - validationSchemaIgnoreParams = 'genomes,hmf_data_paths,panel_data_paths' - // NOTE(SW): incompatible with GHA given size of reference data // Limit resources so that this can run on GitHub Actions max_cpus = 1 diff --git a/conf/test_stub.config b/conf/test_stub.config index 9a068d4a..4b8970de 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -14,10 +14,6 @@ params { config_profile_name = 'Stub test profile' config_profile_description = 'Stub test dataset to check pipeline function' - // Defined here to be accessible within a workflow script; downloaded manually prior to process - // execution. - validationSchemaIgnoreParams = 'genomes,hmf_data_paths,panel_data_paths' - // Limit resources so that this can run on GitHub Actions max_cpus = 1 max_memory = '8.GB' From d7d8922eef794987586a3dcf4a2ce7da1d5aa438 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 11 May 2024 12:19:24 +1000 Subject: [PATCH 472/562] Adjust pipeline test config, comments --- conf/test.config | 10 ++++++---- conf/test_full.config | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/conf/test.config b/conf/test.config index 9e2a5cf5..9eb1b174 100644 --- a/conf/test.config +++ b/conf/test.config @@ -20,17 +20,19 @@ params { config_profile_name = 'Test profile' config_profile_description = 'Minimal test dataset to check pipeline function' - // NOTE(SW): incompatible with GHA given size of reference data + // NOTE(SW): incompatible with GHA given size of reference data, STAR align requires ~30 GB memory // Limit resources so that this can run on GitHub Actions max_cpus = 1 - max_memory = '8.GB' + max_memory = '30.GB' max_time = '6.h' // Input data input = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/simulated_reads/24.0/samplesheets/fastq_eval.subject_a-subject_b.wgts.tndna_trna.1.csv' + // Reference data + ref_data_virusbreakenddb_path = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/virusbreakend/virusbreakenddb_test-24.04.0.tar.gz' + + // Analysis config mode = 'wgts' genome = 'GRCh38_hmf' - - ref_data_virusbreakenddb_path = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/virusbreakend/virusbreakenddb_test-24.04.0.tar.gz' } diff --git a/conf/test_full.config b/conf/test_full.config index ecd38c6d..a8f9afa0 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -23,6 +23,7 @@ params { // Input data for full size test input = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/simulated_reads/24.0/samplesheets/fastq_eval.subject_a-subject_b.wgts.tndna_trna.1.csv' + // Analysis config mode = 'wgts' genome = 'GRCh38_hmf' } From 311c1bf08a35d02b3fc5355bcd297cfad437d05f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 13 May 2024 13:23:45 +1000 Subject: [PATCH 473/562] Add tool entries to CITATIONS.md --- CITATIONS.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/CITATIONS.md b/CITATIONS.md index ce2448db..19dc7afc 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -10,6 +10,62 @@ ## Pipeline tools +- [BCFtools](https://doi.org/10.1093/gigascience/giab008) + + > Danecek, P., Bonfield, J. K., Liddle, J., Marshall, J., Ohan, V., Pollard, M. O., Whitwham, A., Keane, T., McCarthy, S. A., Davies, R. M., & Li, H. (2021). Twelve years of SAMtools and BCFtools. GigaScience, 10(2), giab008. https://doi.org/10.1093/gigascience/giab008 + +- [BWA](https://doi.org/10.1093/bioinformatics/btp324) + + > Li, H., & Durbin, R. (2009). Fast and accurate short read alignment with Burrows–Wheeler transform. Bioinformatics, 25(14), 1754–1760. https://doi.org/10.1093/bioinformatics/btp324 + +- [bwa-mem2](https://doi.org/10.1109/IPDPS.2019.00041) + + > Vasimuddin, Md., Misra, S., Li, H., & Aluru, S. (2019). Efficient Architecture-Aware Acceleration of BWA-MEM for Multicore Systems. 2019 IEEE International Parallel and Distributed Processing Symposium (IPDPS), 314–324. https://doi.org/10.1109/IPDPS.2019.00041 + +- [CHORD](https://doi.org/10.1038/s41467-020-19406-4) + + > Nguyen, L., W. M. Martens, J., Van Hoeck, A., & Cuppen, E. (2020). Pan-cancer landscape of homologous recombination deficiency. Nature Communications, 11(1), 5584. https://doi.org/10.1038/s41467-020-19406-4 + +- [fastp](https://doi.org/10.1093/bioinformatics/bty560) + + > Chen, S., Zhou, Y., Chen, Y., & Gu, J. (2018). fastp: An ultra-fast all-in-one FASTQ preprocessor. Bioinformatics, 34(17), i884–i890. https://doi.org/10.1093/bioinformatics/bty560 + +- [GATK](https://doi.org/10.1093/bioinformatics/btp324) + + > McKenna, A., Hanna, M., Banks, E., Sivachenko, A., Cibulskis, K., Kernytsky, A., Garimella, K., Altshuler, D., Gabriel, S., Daly, M., & DePristo, M. A. (2010). The Genome Analysis Toolkit: A MapReduce framework for analyzing next-generation DNA sequencing data. Genome Research, 20(9), 1297–1303. https://doi.org/10.1101/gr.107524.110 + +- [GRIDSS2](https://doi.org/10.1186/s13059-021-02423-x) + + > Cameron, D. L., Baber, J., Shale, C., Valle-Inclan, J. E., Besselink, N., van Hoeck, A., Janssen, R., Cuppen, E., Priestley, P., & Papenfuss, A. T. (2021). GRIDSS2: Comprehensive characterisation of somatic structural variation using single breakend variants and structural variant phasing. Genome Biology, 22(1), Article 1. https://doi.org/10.1186/s13059-021-02423-x + +- [LILAC](https://doi.org/10.1038/s41588-023-01367-1) + + > Martínez-Jiménez, F., Priestley, P., Shale, C., Baber, J., Rozemuller, E., & Cuppen, E. (2023). Genetic immune escape landscape in primary and metastatic cancer. Nature Genetics, 55(5), 820–831. https://doi.org/10.1038/s41588-023-01367-1 + +- [LINX](https://doi.org/10.1016/j.xgen.2022.100112) + + > Shale, C., Cameron, D. L., Baber, J., Wong, M., Cowley, M. J., Papenfuss, A. T., Cuppen, E., & Priestley, P. (2022). Unscrambling cancer genomes via integrated analysis of structural variation and copy number. Cell Genomics, 2(4). https://doi.org/10.1016/j.xgen.2022.100112 + +- [PURPLE](https://doi.org/10.1038/s41586-019-1689-y) + + > Priestley, P., Baber, J., Lolkema, M. P., Steeghs, N., de Bruijn, E., Shale, C., Duyvesteyn, K., Haidari, S., van Hoeck, A., Onstenk, W., Roepman, P., Voda, M., Bloemendal, H. J., Tjan-Heijnen, V. C. G., van Herpen, C. M. L., Labots, M., Witteveen, P. O., Smit, E. F., Sleijfer, S., … Cuppen, E. (2019). Pan-cancer whole-genome analyses of metastatic solid tumours. Nature, 575(7781), 210–216. https://doi.org/10.1038/s41586-019-1689-y + +- [Sambamba](https://doi.org/10.1093/bioinformatics/btv098) + + > Tarasov, A., Vilella, A. J., Cuppen, E., Nijman, I. J., & Prins, P. (2015). Sambamba: Fast processing of NGS alignment formats. Bioinformatics, 31(12), 2032–2034. https://doi.org/10.1093/bioinformatics/btv098 + +- [SAMtools](https://doi.org/10.1093/gigascience/giab008) + + > Danecek, P., Bonfield, J. K., Liddle, J., Marshall, J., Ohan, V., Pollard, M. O., Whitwham, A., Keane, T., McCarthy, S. A., Davies, R. M., & Li, H. (2021). Twelve years of SAMtools and BCFtools. GigaScience, 10(2), giab008. https://doi.org/10.1093/gigascience/giab008 + +- [STAR](https://doi.org/10.1093/bioinformatics/bts635) + + > Dobin, A., Davis, C. A., Schlesinger, F., Drenkow, J., Zaleski, C., Jha, S., Batut, P., Chaisson, M., & Gingeras, T. R. (2013). STAR: Ultrafast universal RNA-seq aligner. Bioinformatics, 29(1), 15–21. https://doi.org/10.1093/bioinformatics/bts635 + +- [VIRUSBreakend](https://doi.org/10.1093/bioinformatics/btab343) + + > Cameron, D. L., Jacobs, N., Roepman, P., Priestley, P., Cuppen, E., & Papenfuss, A. T. (2021). VIRUSBreakend: Viral Integration Recognition Using Single Breakends. Bioinformatics, 37(19), 3115–3119. https://doi.org/10.1093/bioinformatics/btab343 + ## Software packaging/containerisation tools - [Anaconda](https://anaconda.com) From 1344a9e2c17482362adc52908407cab9d41d8d52 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 15 May 2024 11:49:37 +1000 Subject: [PATCH 474/562] Remove unused ref params from test_stub profile --- conf/test_stub.config | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/conf/test_stub.config b/conf/test_stub.config index 4b8970de..b0a99ed0 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -29,11 +29,8 @@ params { fasta = "temp/GRCh38.fasta" fai = "temp/GRCh38.fai" dict = "temp/GRCh38.dict" - bwa_index = "temp/GRCh38_bwa/" - bwa_index_image = "temp/GRCh38.img" - bwa_index_bseq = "temp/GRCh38.fasta.0123" - bwa_index_biidx = "temp/GRCh38.fasta.bwt.2bit.64" - gridss_index = "temp/GRCh38.gridsscache" + bwa_index = "temp/GRCh38_bwa-mem2_index/" + gridss_index = "temp/GRCh38_gridss_index/" star_index = "temp/GRCh38_star_index/" } From 24cc1adf14e1c53dd15ff7b4120cc94493570dc4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 15 May 2024 11:28:00 +1000 Subject: [PATCH 475/562] Use test_stub profile in download_pipline GHA wfl --- .github/workflows/download_pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index 2d20d644..c87f0bd4 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -76,7 +76,7 @@ jobs: env: NXF_SINGULARITY_CACHEDIR: ./ NXF_SINGULARITY_HOME_MOUNT: true - run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -stub -profile test,singularity --outdir ./results + run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -stub -profile test_stub,singularity --outdir ./results - name: Run the downloaded pipeline (stub run not supported) id: run_pipeline if: ${{ job.steps.stub_run_pipeline.status == failure() }} From a6b8d156a8c6ca9ac53d620c8a764d6b84ac7f76 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 15 May 2024 13:32:50 +1000 Subject: [PATCH 476/562] Remove non-stub run from download_pipeline CI --- .github/workflows/download_pipeline.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index c87f0bd4..d09995d0 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -77,10 +77,3 @@ jobs: NXF_SINGULARITY_CACHEDIR: ./ NXF_SINGULARITY_HOME_MOUNT: true run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -stub -profile test_stub,singularity --outdir ./results - - name: Run the downloaded pipeline (stub run not supported) - id: run_pipeline - if: ${{ job.steps.stub_run_pipeline.status == failure() }} - env: - NXF_SINGULARITY_CACHEDIR: ./ - NXF_SINGULARITY_HOME_MOUNT: true - run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -profile test,singularity --outdir ./results From 3c706c0a363b8d0701a1e73988e34026c75cf8d2 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 16 May 2024 16:30:56 +1000 Subject: [PATCH 477/562] Remove duplicate tests --- nf-test.config | 8 --- tests/main.stub.nf.test | 66 ------------------ tests/main.stub.nf.test.config | 14 ---- .../targeted.tso500.dna_rna.single.stub.csv | 3 - tests/samplesheets/wgts.dna_rna.single.csv | 4 -- .../samplesheets/wgts.dna_rna.single.stub.csv | 4 -- .../local/amber_profiling.nf.test | 43 ------------ .../local/bamtools_metrics.nf.test | 43 ------------ .../local/chord_prediction.nf.test | 42 ----------- .../local/cobalt_profiling.nf.test | 43 ------------ .../local/cuppa_prediction.nf.test | 46 ------------- .../local/flagstat_metrics.nf.test | 40 ----------- .../local/gridss_svprep_calling.nf.test | 51 -------------- .../local/gripss_filtering.nf.test | 50 -------------- .../local/isofox_quantification.nf.test | 50 -------------- .../subworkflows/local/lilac_calling.nf.test | 46 ------------- .../local/linx_annotation.nf.test | 46 ------------- .../subworkflows/local/linx_plotting.nf.test | 43 ------------ .../local/orange_reporting.nf.test | 67 ------------------ .../local/pave_annotation.nf.test | 62 ----------------- .../subworkflows/local/purple_calling.nf.test | 69 ------------------- tests/subworkflows/local/sage_append.nf.test | 45 ------------ tests/subworkflows/local/sage_calling.nf.test | 52 -------------- .../subworkflows/local/sigs_fittings.nf.test | 42 ----------- .../local/virusbreakend_calling.nf.test | 52 -------------- 25 files changed, 1031 deletions(-) delete mode 100644 nf-test.config delete mode 100644 tests/main.stub.nf.test delete mode 100644 tests/main.stub.nf.test.config delete mode 100644 tests/samplesheets/targeted.tso500.dna_rna.single.stub.csv delete mode 100644 tests/samplesheets/wgts.dna_rna.single.csv delete mode 100644 tests/samplesheets/wgts.dna_rna.single.stub.csv delete mode 100644 tests/subworkflows/local/amber_profiling.nf.test delete mode 100644 tests/subworkflows/local/bamtools_metrics.nf.test delete mode 100644 tests/subworkflows/local/chord_prediction.nf.test delete mode 100644 tests/subworkflows/local/cobalt_profiling.nf.test delete mode 100644 tests/subworkflows/local/cuppa_prediction.nf.test delete mode 100644 tests/subworkflows/local/flagstat_metrics.nf.test delete mode 100644 tests/subworkflows/local/gridss_svprep_calling.nf.test delete mode 100644 tests/subworkflows/local/gripss_filtering.nf.test delete mode 100644 tests/subworkflows/local/isofox_quantification.nf.test delete mode 100644 tests/subworkflows/local/lilac_calling.nf.test delete mode 100644 tests/subworkflows/local/linx_annotation.nf.test delete mode 100644 tests/subworkflows/local/linx_plotting.nf.test delete mode 100644 tests/subworkflows/local/orange_reporting.nf.test delete mode 100644 tests/subworkflows/local/pave_annotation.nf.test delete mode 100644 tests/subworkflows/local/purple_calling.nf.test delete mode 100644 tests/subworkflows/local/sage_append.nf.test delete mode 100644 tests/subworkflows/local/sage_calling.nf.test delete mode 100644 tests/subworkflows/local/sigs_fittings.nf.test delete mode 100644 tests/subworkflows/local/virusbreakend_calling.nf.test diff --git a/nf-test.config b/nf-test.config deleted file mode 100644 index b3869b6d..00000000 --- a/nf-test.config +++ /dev/null @@ -1,8 +0,0 @@ -config { - testsDir "tests/" - workDir ".nf-test" - configFile "" - stage { - symlink 'test_data/' - } -} diff --git a/tests/main.stub.nf.test b/tests/main.stub.nf.test deleted file mode 100644 index a4dc4a54..00000000 --- a/tests/main.stub.nf.test +++ /dev/null @@ -1,66 +0,0 @@ -nextflow_pipeline { - - name "Pipeline end-to-end stub-run" - script "main.nf" - config "tests/main.stub.nf.test.config" - options "-stub-run --create_stub_placeholders" - - test("WGTS GRCh38") { - - when { - params { - mode "wgts" - genome "GRCh38_hmf" - - input "${baseDir}/tests/samplesheets/wgts.dna_rna.single.stub.csv" - outdir "${outputDir}" - - ref_data_virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" - ref_data_hmf_data_path "${workDir}/reference_data/hmf_data/" - - max_cpus = 1 - max_memory = "10.GB" - - // NOTE(SW): create new variable for nf-test workDir so that we can use in genomes config - nfTestWorkDir = workDir - } - - } - - then { - assert workflow.success - } - - } - - test("Targeted (TSO500) GRCh38") { - - when { - params { - mode "targeted" - panel "tso500" - genome "GRCh38_hmf" - - input "${baseDir}/tests/samplesheets/targeted.tso500.dna_rna.single.stub.csv" - outdir "${outputDir}" - - ref_data_virusbreakenddb_path "${workDir}/reference_data/virusbreakenddb_20210401/" - ref_data_hmf_data_path "${workDir}/reference_data/hmf_data/" - ref_data_panel_data_path "${workDir}/reference_data/panel_data/" - - max_cpus 1 - max_memory "10.GB" - - // NOTE(SW): create new variable for nf-test workDir so that we can use in genomes config - nfTestWorkDir = workDir - } - - } - - then { - assert workflow.success - } - - } - -} diff --git a/tests/main.stub.nf.test.config b/tests/main.stub.nf.test.config deleted file mode 100644 index cec6b687..00000000 --- a/tests/main.stub.nf.test.config +++ /dev/null @@ -1,14 +0,0 @@ -params { - genomes { - - 'GRCh38_hmf' { - fasta = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" - fai = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" - dict = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwa_index = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188.tar.gz" - bwa_index_image = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img" - gridss_index = "${params.nfTestWorkDir}/reference_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache" - } - - } -} diff --git a/tests/samplesheets/targeted.tso500.dna_rna.single.stub.csv b/tests/samplesheets/targeted.tso500.dna_rna.single.stub.csv deleted file mode 100644 index e4bb193b..00000000 --- a/tests/samplesheets/targeted.tso500.dna_rna.single.stub.csv +++ /dev/null @@ -1,3 +0,0 @@ -group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath -SONE-1,SUBJECT_ONE,SAMPLE_ONE_TUMOR,tumor,dna,bam,/Users/stephen/repos/hmftools_pipeline/temp/sample/sample_one_tumor.bam -SONE-1,SUBJECT_ONE,SAMPLE_ONE_TUMOR_WTS,tumor,rna,bam,/Users/stephen/repos/hmftools_pipeline/temp/sample/sample_one_tumor.wts.bam diff --git a/tests/samplesheets/wgts.dna_rna.single.csv b/tests/samplesheets/wgts.dna_rna.single.csv deleted file mode 100644 index 6682d60b..00000000 --- a/tests/samplesheets/wgts.dna_rna.single.csv +++ /dev/null @@ -1,4 +0,0 @@ -group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath -COLO829,COLO829,COLO829v003T,tumor,dna,bam,meta/test_data/sample_data/COLO829T.bam -COLO829,COLO829,COLO829v003R,normal,dna,bam,meta/test_data/sample_data/COLO829R.bam -COLO829,COLO829,PTC_NebRNA230605,tumor,rna,bam,meta/test_data/sample_data/PTC_NebRNA230605.md.mini.bam diff --git a/tests/samplesheets/wgts.dna_rna.single.stub.csv b/tests/samplesheets/wgts.dna_rna.single.stub.csv deleted file mode 100644 index c31f787c..00000000 --- a/tests/samplesheets/wgts.dna_rna.single.stub.csv +++ /dev/null @@ -1,4 +0,0 @@ -group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath -SONE-1,SUBJECT_ONE,SAMPLE_ONE_TUMOR,tumor,dna,bam,/Users/stephen/repos/hmftools_pipeline/temp/sample/sample_one_tumor.bam -SONE-1,SUBJECT_ONE,SAMPLE_ONE_NORMAL,normal,dna,bam,/Users/stephen/repos/hmftools_pipeline/temp/sample/sample_one_normal.bam -SONE-1,SUBJECT_ONE,SAMPLE_ONE_TUMOR_WTS,tumor,rna,bam,/Users/stephen/repos/hmftools_pipeline/temp/sample/sample_one_tumor.wts.bam diff --git a/tests/subworkflows/local/amber_profiling.nf.test b/tests/subworkflows/local/amber_profiling.nf.test deleted file mode 100644 index 4bb0c0b9..00000000 --- a/tests/subworkflows/local/amber_profiling.nf.test +++ /dev/null @@ -1,43 +0,0 @@ -nextflow_workflow { - - name "Test AMBER subworkflow" - script "subworkflows/local/amber_profiling/main.nf" - workflow "AMBER_PROFILING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = '38' - input[2] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/copy_number/AmberGermlineSites.38.tsv.gz' - input[3] = [] - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/bamtools_metrics.nf.test b/tests/subworkflows/local/bamtools_metrics.nf.test deleted file mode 100644 index c88d29e5..00000000 --- a/tests/subworkflows/local/bamtools_metrics.nf.test +++ /dev/null @@ -1,43 +0,0 @@ -nextflow_workflow { - - name "Test BamTools subworkflow" - script "subworkflows/local/bamtools_metrics/main.nf" - workflow "BAMTOOLS_METRICS" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - // NOTE(SW): BamTools fails when using a single thread - max_cpus = 2 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[2] = '38' - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/chord_prediction.nf.test b/tests/subworkflows/local/chord_prediction.nf.test deleted file mode 100644 index b381a37a..00000000 --- a/tests/subworkflows/local/chord_prediction.nf.test +++ /dev/null @@ -1,42 +0,0 @@ -nextflow_workflow { - - name "Test CHORD subworkflow" - script "subworkflows/local/chord_prediction/main.nf" - workflow "CHORD_PREDICTION" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[2] = '38' - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/cobalt_profiling.nf.test b/tests/subworkflows/local/cobalt_profiling.nf.test deleted file mode 100644 index 3191a6fa..00000000 --- a/tests/subworkflows/local/cobalt_profiling.nf.test +++ /dev/null @@ -1,43 +0,0 @@ -nextflow_workflow { - - name "Test COBALT subworkflow" - script "subworkflows/local/cobalt_profiling/main.nf" - workflow "COBALT_PROFILING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/copy_number/GC_profile.1000bp.38.cnp' - input[2] = [] - input[3] = [] - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/cuppa_prediction.nf.test b/tests/subworkflows/local/cuppa_prediction.nf.test deleted file mode 100644 index 2a237e1c..00000000 --- a/tests/subworkflows/local/cuppa_prediction.nf.test +++ /dev/null @@ -1,46 +0,0 @@ -nextflow_workflow { - - name "Test CUPPA subworkflow" - script "subworkflows/local/cuppa_prediction/main.nf" - workflow "CUPPA_PREDICTION" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/isofox/')) - input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[3] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx/somatic_annotations/')) - input[4] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/virusinterpreter/')) - input[5] = '38' - input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/cuppa/' - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/flagstat_metrics.nf.test b/tests/subworkflows/local/flagstat_metrics.nf.test deleted file mode 100644 index 4fb000de..00000000 --- a/tests/subworkflows/local/flagstat_metrics.nf.test +++ /dev/null @@ -1,40 +0,0 @@ -nextflow_workflow { - - name "Test flagstat subworkflow" - script "subworkflows/local/flagstat_metrics/main.nf" - workflow "FLAGSTAT_METRICS" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/gridss_svprep_calling.nf.test b/tests/subworkflows/local/gridss_svprep_calling.nf.test deleted file mode 100644 index 5ee0f058..00000000 --- a/tests/subworkflows/local/gridss_svprep_calling.nf.test +++ /dev/null @@ -1,51 +0,0 @@ -nextflow_workflow { - - name "Test SvPrep subworkflow" - script "subworkflows/local/gridss_svprep_calling/main.nf" - workflow "GRIDSS_SVPREP_CALLING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[2] = '38' - input[3] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' - input[5] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188/' - input[6] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img' - input[7] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache' - input[8] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/gridss_blacklist.38.bed.gz' - input[9] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/sv_prep_blacklist.38.bed' - input[10] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/known_fusions.38.bedpe' - input[11] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/gridss.properties' - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/gripss_filtering.nf.test b/tests/subworkflows/local/gripss_filtering.nf.test deleted file mode 100644 index 24b06252..00000000 --- a/tests/subworkflows/local/gripss_filtering.nf.test +++ /dev/null @@ -1,50 +0,0 @@ -nextflow_workflow { - - name "Test GRIPSS subworkflow" - script "subworkflows/local/gripss_filtering/main.nf" - workflow "GRIPSS_FILTERING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - // NOTE(SW): BamTools fails when using a single thread - max_cpus = 2 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/gridss/depth_annotator/COLO829v003T.gridss.vcf.gz')) - input[2] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[3] = '38' - input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/sgl_pon.38.bed.gz' - input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/sv_pon.38.bedpe.gz' - input[7] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/known_fusions.38.bedpe' - input[8] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/repeat_mask_data.38.fa.gz' - input[9] = [] - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/isofox_quantification.nf.test b/tests/subworkflows/local/isofox_quantification.nf.test deleted file mode 100644 index f8e2624e..00000000 --- a/tests/subworkflows/local/isofox_quantification.nf.test +++ /dev/null @@ -1,50 +0,0 @@ -nextflow_workflow { - - name "Test Isofox subworkflow" - script "subworkflows/local/isofox_quantification/main.nf" - workflow "ISOFOX_QUANTIFICATION" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[2] = '38' - input[3] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[4] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' - input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/rna_pipeline/read_151_exp_counts.csv' - input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/rna_pipeline/read_100_exp_gc_ratios.csv' - input[7] = [] - input[8] = [] - input[9] = '' - input[10] = 151 - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/lilac_calling.nf.test b/tests/subworkflows/local/lilac_calling.nf.test deleted file mode 100644 index da3176d4..00000000 --- a/tests/subworkflows/local/lilac_calling.nf.test +++ /dev/null @@ -1,46 +0,0 @@ -nextflow_workflow { - - name "Test LILAC subworkflow" - script "subworkflows/local/lilac_calling/main.nf" - workflow "LILAC_CALLING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[2] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[3] = '38' - input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/immune/' - input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/other/lilac/hla.38.bed' - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/linx_annotation.nf.test b/tests/subworkflows/local/linx_annotation.nf.test deleted file mode 100644 index 8e50231f..00000000 --- a/tests/subworkflows/local/linx_annotation.nf.test +++ /dev/null @@ -1,46 +0,0 @@ -nextflow_workflow { - - name "Test LINX annotation subworkflow" - script "subworkflows/local/linx_annotation/main.nf" - workflow "LINX_ANNOTATION" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[2] = '38' - input[3] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' - input[4] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/known_fusion_data.38.csv' - input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/DriverGenePanel.38.tsv' - input[6] = [] - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/linx_plotting.nf.test b/tests/subworkflows/local/linx_plotting.nf.test deleted file mode 100644 index b95db69d..00000000 --- a/tests/subworkflows/local/linx_plotting.nf.test +++ /dev/null @@ -1,43 +0,0 @@ -nextflow_workflow { - - name "Test LINX plotting subworkflow" - script "subworkflows/local/linx_plotting/main.nf" - workflow "LINX_PLOTTING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx/somatic_annotations/')) - input[2] = '38' - input[3] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/orange_reporting.nf.test b/tests/subworkflows/local/orange_reporting.nf.test deleted file mode 100644 index dce14f08..00000000 --- a/tests/subworkflows/local/orange_reporting.nf.test +++ /dev/null @@ -1,67 +0,0 @@ -nextflow_workflow { - - name "Test ORANGE subworkflow" - script "subworkflows/local/orange_reporting/main.nf" - workflow "ORANGE_REPORTING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/bamtools/COLO829v003T.wgsmetrics')) - input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/bamtools/COLO829v003R.wgsmetrics')) - input[3] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/flagstats/COLO829v003T.flagstat')) - input[4] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/flagstats/COLO829v003R.flagstat')) - input[5] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/sage/somatic/')) - input[6] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/sage/germline/')) - input[7] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/sage/append/COLO829v003T.sage.append.vcf.gz')) - input[8] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/sage/append/COLO829v003R.sage.append.vcf.gz')) - input[9] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[10] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx/somatic_annotations/')) - input[11] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx/somatic_plots/')) - input[12] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/linx/germline_annotations/')) - input[13] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/virusinterpreter/')) - input[14] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/chord/')) - input[15] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/sigs/')) - input[16] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/lilac/')) - input[17] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/cuppa/')) - input[18] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/isofox/')) - input[19] = '38' - input[20] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/disease_ontology/doid.json' - input[21] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/orange/cohort_mapping.tsv' - input[22] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/orange/cohort_percentiles.tsv' - input[23] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/known_fusion_data.38.csv' - input[24] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/DriverGenePanel.38.tsv' - input[25] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' - input[26] = Channel.of('${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/rna_pipeline/isofox.hmf_3444.alt_sj_cohort.38.csv') - input[27] = Channel.of('${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/rna_pipeline/isofox.hmf_3444.gene_distribution.38.csv') - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/pave_annotation.nf.test b/tests/subworkflows/local/pave_annotation.nf.test deleted file mode 100644 index 8e9f95f8..00000000 --- a/tests/subworkflows/local/pave_annotation.nf.test +++ /dev/null @@ -1,62 +0,0 @@ -nextflow_workflow { - - name "Test PAVE subworkflow" - script "subworkflows/local/pave_annotation/main.nf" - workflow "PAVE_ANNOTATION" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - mode = "wgts" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of([ - '${baseDir}/test_data/module_data/sage/somatic/COLO829v003T.sage.somatic.vcf.gz', - '${baseDir}/test_data/module_data/sage/somatic/COLO829v003T.sage.somatic.vcf.gz.tbi', - ])) - input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of([ - '${baseDir}/test_data/module_data/sage/germline/COLO829v003T.sage.germline.vcf.gz', - '${baseDir}/test_data/module_data/sage/germline/COLO829v003T.sage.germline.vcf.gz.tbi', - ])) - input[3] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[4] = '38' - input[5] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/SageGermlinePon.98x.38.tsv.gz' - input[7] = [] - input[8] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownBlacklist.germline.38.bed' - input[9] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownBlacklist.germline.38.vcf.gz' - input[10] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/clinvar.38.vcf.gz' - input[11] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/mappability_150.38.bed.gz' - input[12] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/DriverGenePanel.38.tsv' - input[13] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' - input[14] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/gnomad/' - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/purple_calling.nf.test b/tests/subworkflows/local/purple_calling.nf.test deleted file mode 100644 index 0cf27c7f..00000000 --- a/tests/subworkflows/local/purple_calling.nf.test +++ /dev/null @@ -1,69 +0,0 @@ -nextflow_workflow { - - name "Test PURPLE subworkflow" - script "subworkflows/local/purple_calling/main.nf" - workflow "PURPLE_CALLING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/amber/')) - input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/cobalt/')) - input[3] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/pave/COLO829v003T.sage.somatic.pave.vcf.gz')) - input[4] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/pave/COLO829v003T.sage.germline.pave.vcf.gz')) - input[5] = PREPARE_INPUTS.out.inputs.combine(Channel.of([ - '${baseDir}/test_data/module_data/gripss/somatic/COLO829v003T.gripss.filtered.somatic.vcf.gz', - '${baseDir}/test_data/module_data/gripss/somatic/COLO829v003T.gripss.filtered.somatic.vcf.gz.tbi', - ])) - input[6] = PREPARE_INPUTS.out.inputs.combine(Channel.of([ - '${baseDir}/test_data/module_data/gripss/germline/COLO829v003T.gripss.filtered.germline.vcf.gz', - '${baseDir}/test_data/module_data/gripss/germline/COLO829v003T.gripss.filtered.germline.vcf.gz.tbi', - ])) - input[7] = PREPARE_INPUTS.out.inputs.combine(Channel.of([ - '${baseDir}/test_data/module_data/gripss/somatic/COLO829v003T.gripss.somatic.vcf.gz', - '${baseDir}/test_data/module_data/gripss/somatic/COLO829v003T.gripss.somatic.vcf.gz.tbi', - ])) - input[8] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[9] = '38' - input[10] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[11] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' - input[12] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/copy_number/GC_profile.1000bp.38.cnp' - input[13] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.somatic.38.vcf.gz' - input[14] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.germline.38.vcf.gz' - input[15] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/DriverGenePanel.38.tsv' - input[16] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' - input[17] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/copy_number/cohort_germline_del_freq.38.csv' - input[18] = [] - input[19] = [] - input[20] = [] - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/sage_append.nf.test b/tests/subworkflows/local/sage_append.nf.test deleted file mode 100644 index 26f80460..00000000 --- a/tests/subworkflows/local/sage_append.nf.test +++ /dev/null @@ -1,45 +0,0 @@ -nextflow_workflow { - - name "Test SAGE append subworkflow" - script "subworkflows/local/sage_append/main.nf" - workflow "SAGE_APPEND" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[2] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[3] = '38' - input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[5] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/sage_calling.nf.test b/tests/subworkflows/local/sage_calling.nf.test deleted file mode 100644 index 65c803d0..00000000 --- a/tests/subworkflows/local/sage_calling.nf.test +++ /dev/null @@ -1,52 +0,0 @@ -nextflow_workflow { - - name "Test SAGE calling subworkflow" - script "subworkflows/local/sage_calling/main.nf" - workflow "SAGE_CALLING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[2] = '38' - input[3] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' - input[5] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.somatic.38.vcf.gz' - input[6] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/KnownHotspots.germline.38.vcf.gz' - input[7] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/ActionableCodingPanel.38.bed.gz' - input[8] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/CoverageCodingPanel.38.bed.gz' - input[9] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_nosomaticdel_noCENorHET7.bed.gz' - input[10] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/variants/mappability_150.38.bed.gz' - input[11] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/DriverGenePanel.38.tsv' - input[12] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/common/ensembl_data/' - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/sigs_fittings.nf.test b/tests/subworkflows/local/sigs_fittings.nf.test deleted file mode 100644 index 0d7e9cc8..00000000 --- a/tests/subworkflows/local/sigs_fittings.nf.test +++ /dev/null @@ -1,42 +0,0 @@ -nextflow_workflow { - - name "Test Sigs subworkflow" - script "subworkflows/local/sigs_fitting/main.nf" - workflow "SIGS_FITTING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[2] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/sigs/snv_cosmic_signatures.csv' - """ - } - } - - then { - assert workflow.success - } - - } -} diff --git a/tests/subworkflows/local/virusbreakend_calling.nf.test b/tests/subworkflows/local/virusbreakend_calling.nf.test deleted file mode 100644 index b353c4a5..00000000 --- a/tests/subworkflows/local/virusbreakend_calling.nf.test +++ /dev/null @@ -1,52 +0,0 @@ -nextflow_workflow { - - name "Test VIRUSBreakend subworkflow" - script "subworkflows/local/virusbreakend_calling/main.nf" - workflow "VIRUSBREAKEND_CALLING" - profile "docker" - - test("WGTS COLO829 mini") { - - setup { - run("PREPARE_INPUTS") { - script "subworkflows/local/prepare_inputs/main.nf" - process { - """ - input[0] = '${baseDir}/tests/samplesheets/wgts.dna_rna.single.csv' - """ - } - } - } - - when { - params { - outdir = "${outputDir}" - - max_cpus = 1 - max_memory = "10.GB" - } - workflow { - """ - input[0] = PREPARE_INPUTS.out.inputs - input[1] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/purple/')) - input[2] = PREPARE_INPUTS.out.inputs.combine(Channel.of('${baseDir}/test_data/module_data/bamtools/COLO829v003T.wgsmetrics')) - input[3] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna' - input[4] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai' - input[5] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict' - input[6] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/bwa_index/0.7.17-r1188/' - input[7] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/bwa_index_image/0.7.17-r1188/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.img' - input[8] = '${baseDir}/test_data/reference_data/genomes/GRCh38_hmf/gridss_index/2.13.2/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.gridsscache' - input[9] = '${baseDir}/test_data/reference_data/other/virusbreakenddb_test/' - input[10] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/virusinterpreter/taxonomy_db.tsv' - input[11] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/virusinterpreter/virus_reporting_db.tsv' - input[12] = '${baseDir}/test_data/reference_data/hmf_reference_data/hmftools/5.34_38--0/dna_pipeline/sv/gridss.properties' - """ - } - } - - then { - assert workflow.success - } - - } -} From 30b0e721052f8265e07efae22ee531918f279749 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 16 May 2024 17:31:13 +1000 Subject: [PATCH 478/562] Do not split FASTQs during tests --- conf/test.config | 5 +++-- conf/test_full.config | 5 +++-- conf/test_stub.config | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/conf/test.config b/conf/test.config index 9eb1b174..666424da 100644 --- a/conf/test.config +++ b/conf/test.config @@ -33,6 +33,7 @@ params { ref_data_virusbreakenddb_path = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/virusbreakend/virusbreakenddb_test-24.04.0.tar.gz' // Analysis config - mode = 'wgts' - genome = 'GRCh38_hmf' + mode = 'wgts' + genome = 'GRCh38_hmf' + max_fastq_records = 0 } diff --git a/conf/test_full.config b/conf/test_full.config index a8f9afa0..c719a30b 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -24,6 +24,7 @@ params { input = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/simulated_reads/24.0/samplesheets/fastq_eval.subject_a-subject_b.wgts.tndna_trna.1.csv' // Analysis config - mode = 'wgts' - genome = 'GRCh38_hmf' + mode = 'wgts' + genome = 'GRCh38_hmf' + max_fastq_records = 0 } diff --git a/conf/test_stub.config b/conf/test_stub.config index b0a99ed0..f72a9c79 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -41,7 +41,7 @@ params { ref_data_panel_data_path = "temp/panel_bundle/tso500_38/" // Analysis config - mode = 'wgts' - genome = 'GRCh38_hmf' + mode = 'wgts' + genome = 'GRCh38_hmf' create_stub_placeholders = true } From b9b726f61315aacbdd68901dfec76dae08bc73a6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 17 May 2024 08:48:18 +1000 Subject: [PATCH 479/562] Update docs/usage.md Co-authored-by: Cassie Litchfield --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 71ebac28..e20c807e 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -71,7 +71,7 @@ P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tum > [!NOTE] > Inputs with the `bam` filetype will be processed by MarkDups as required by hmftools. Where an input BAM has already -> been processed by MarkDups, you can avoid needless reprocessing by setting `bam_markdups` as the filetype instead. +> been processed by [HMF mark duplicates](https://github.com/hartwigmedical/hmftools/blob/master/mark-dups/README.md), you can avoid needless reprocessing by setting `bam_markdups` as the filetype instead. > > Please note there are important requirements around the use of BAMs, see the warning above in the > [Introduction](#introduction). From 6fb3d8d684c10b6a3eabc85ccf6b796a4c3c67aa Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 17 May 2024 08:48:26 +1000 Subject: [PATCH 480/562] Update docs/usage.md Co-authored-by: Cassie Litchfield --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index e20c807e..af59a2ab 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -27,7 +27,7 @@ staged locally to optimise execution or modified to create user-defined driver g > - STAR must have been run with [specific > parameters](https://github.com/hartwigmedical/hmftools/tree/master/isofox#a-note-on-alignment-and-multi-mapping), > this is critical for WTS data, and -> - reads are expected to have been aligned to one of the Hartwig-distributed reference genomes (user-defined genomes may be used though are not recommended) +> - reads are expected to have been aligned to one of the Hartwig-distributed reference genomes ([user-defined genomes may be used](#custom-genomes) though are not recommended) ## Supported analyses From 5e4ccdb88c2d01ed101fa0595c8767b657581757 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 17 May 2024 10:04:51 +1000 Subject: [PATCH 481/562] Further clarify MarkDups function, requirements --- docs/usage.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index af59a2ab..ffff4e08 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -71,9 +71,13 @@ P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tum > [!NOTE] > Inputs with the `bam` filetype will be processed by MarkDups as required by hmftools. Where an input BAM has already -> been processed by [HMF mark duplicates](https://github.com/hartwigmedical/hmftools/blob/master/mark-dups/README.md), you can avoid needless reprocessing by setting `bam_markdups` as the filetype instead. +> been processed specifically by [HMF +> MarkDups](https://github.com/hartwigmedical/hmftools/blob/master/mark-dups/README.md), you can avoid needless +> reprocessing by setting `bam_markdups` as the filetype instead. It is important to understand that duplicate marking +> by other tools (e.g. GATK) cannot be used as a substitute since HMF MarkDups performs key operations beyond just +> duplicate marking. > -> Please note there are important requirements around the use of BAMs, see the warning above in the +> Please note there are other essential requirements around the use of BAMs as inputs, see the warning above in the > [Introduction](#introduction). ```csv title="samplesheet.csv" From f1fe44d8b3e1f0c55c14ab9d2ce06c8bde348c51 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 16 May 2024 16:07:04 +1000 Subject: [PATCH 482/562] Rename bwa-mem2 index variables --- conf/hmf_genomes.config | 24 +++++----- conf/test_stub.config | 12 ++--- lib/Utils.groovy | 5 ++- main.nf | 12 ++--- modules/local/bwa-mem2/mem/main.nf | 4 +- modules/local/bwa-mem2/mem/meta.yml | 4 +- .../lilac_extract_and_index_contig/main.nf | 2 +- nextflow.config | 2 +- subworkflows/local/lilac_calling/main.nf | 2 +- subworkflows/local/prepare_reference/main.nf | 44 +++++++++---------- subworkflows/local/read_alignment_dna/main.nf | 28 ++++++------ workflows/targeted.nf | 2 +- workflows/wgts.nf | 2 +- 13 files changed, 72 insertions(+), 71 deletions(-) diff --git a/conf/hmf_genomes.config b/conf/hmf_genomes.config index 72c86930..1e2998f8 100644 --- a/conf/hmf_genomes.config +++ b/conf/hmf_genomes.config @@ -10,20 +10,20 @@ params { genomes { 'GRCh37_hmf' { - fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/Homo_sapiens.GRCh37.GATK.illumina.fasta" - fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" - dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" - bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/bwa_index/2.2.1.tar.gz" - gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/gridss_index/2.13.2.tar.gz" - star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/star_index/gencode_19/2.7.3a.tar.gz" + fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/Homo_sapiens.GRCh37.GATK.illumina.fasta" + fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" + dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" + bwamem2_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/bwa-mem2_index/2.2.1.tar.gz" + gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/gridss_index/2.13.2.tar.gz" + star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/star_index/gencode_19/2.7.3a.tar.gz" } 'GRCh38_hmf' { - fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" - fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" - dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwa_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/bwa_index/2.2.1.tar.gz" - gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/gridss_index/2.13.2.tar.gz" - star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/star_index/gencode_38/2.7.3a.tar.gz" + fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" + fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" + dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" + bwamem2_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/bwa-mem2_index/2.2.1.tar.gz" + gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/gridss_index/2.13.2.tar.gz" + star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/star_index/gencode_38/2.7.3a.tar.gz" } } } diff --git a/conf/test_stub.config b/conf/test_stub.config index b0a99ed0..ee1d5d7a 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -26,12 +26,12 @@ params { genomes { 'GRCh38_hmf' { - fasta = "temp/GRCh38.fasta" - fai = "temp/GRCh38.fai" - dict = "temp/GRCh38.dict" - bwa_index = "temp/GRCh38_bwa-mem2_index/" - gridss_index = "temp/GRCh38_gridss_index/" - star_index = "temp/GRCh38_star_index/" + fasta = "temp/GRCh38.fasta" + fai = "temp/GRCh38.fai" + dict = "temp/GRCh38.dict" + bwamem2_index = "temp/GRCh38_bwa-mem2_index/" + gridss_index = "temp/GRCh38_gridss_index/" + star_index = "temp/GRCh38_star_index/" } } diff --git a/lib/Utils.groovy b/lib/Utils.groovy index dba43220..0601ed8f 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -197,12 +197,13 @@ class Utils { def fps = [ params.ref_data_genome_alt, - params.ref_data_genome_bwa_index, + params.ref_data_genome_bwamem2_index, params.ref_data_genome_dict, params.ref_data_genome_fai, params.ref_data_genome_fasta, params.ref_data_genome_gridss_index, params.ref_data_genome_gtf, + params.ref_data_genome_star_index, params.ref_data_virusbreakenddb_path, ] @@ -323,7 +324,7 @@ class Utils { def has_alt_contigs = params.genome_type == 'alt' // Ensure that custom genomes with ALT contigs that need indexes built have the required .alt file - def has_bwa_indexes = (params.ref_data_genome_bwa_index && params.ref_data_genome_gridss_index) + def has_bwa_indexes = (params.ref_data_genome_bwamem2_index && params.ref_data_genome_gridss_index) def has_alt_file = params.containsKey('ref_data_genome_alt') && params.ref_data_genome_alt def run_bwa_or_gridss_index = run_config.stages.alignment && run_config.has_dna_fastq && !has_bwa_indexes diff --git a/main.nf b/main.nf index e91f8199..7fdb0419 100644 --- a/main.nf +++ b/main.nf @@ -31,12 +31,12 @@ include { getGenomeAttribute } from './subworkflows/local/utils_nfcore_oncoanaly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -params.ref_data_genome_fasta = getGenomeAttribute('fasta') -params.ref_data_genome_fai = getGenomeAttribute('fai') -params.ref_data_genome_dict = getGenomeAttribute('dict') -params.ref_data_genome_bwa_index = getGenomeAttribute('bwa_index') -params.ref_data_genome_gridss_index = getGenomeAttribute('gridss_index') -params.ref_data_genome_star_index = getGenomeAttribute('star_index') +params.ref_data_genome_fasta = getGenomeAttribute('fasta') +params.ref_data_genome_fai = getGenomeAttribute('fai') +params.ref_data_genome_dict = getGenomeAttribute('dict') +params.ref_data_genome_bwamem2_index = getGenomeAttribute('bwamem2_index') +params.ref_data_genome_gridss_index = getGenomeAttribute('gridss_index') +params.ref_data_genome_star_index = getGenomeAttribute('star_index') WorkflowMain.setParamsDefaults(params, log) WorkflowMain.validateParams(params, log) diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index 8a5b8046..d1c9ba81 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -10,7 +10,7 @@ process BWAMEM2_ALIGN { input: tuple val(meta), path(reads_fwd), path(reads_rev) path genome_fasta - path genome_bwa_index + path genome_bwamem2_index output: tuple val(meta), path('*.bam'), path('*.bai'), emit: bam @@ -28,7 +28,7 @@ process BWAMEM2_ALIGN { def output_fn = meta.split ? "${meta.split}.${meta.sample_id}.${meta.read_group}.bam" : "${meta.sample_id}.${meta.read_group}.bam" """ - ln -fs \$(find -L ${genome_bwa_index} -type f) ./ + ln -fs \$(find -L ${genome_bwamem2_index} -type f) ./ bwa-mem2 mem \\ ${args} \\ diff --git a/modules/local/bwa-mem2/mem/meta.yml b/modules/local/bwa-mem2/mem/meta.yml index af6d50a9..da61d816 100644 --- a/modules/local/bwa-mem2/mem/meta.yml +++ b/modules/local/bwa-mem2/mem/meta.yml @@ -29,9 +29,9 @@ input: type: file description: Reference genome assembly FASTA file pattern: "*.{fa,fasta}" - - genome_bwa_index: + - genome_bwamem2_index: type: directory - description: bwa-mem1 index directory + description: bwa-mem2 index directory output: - meta: type: map diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index b8e6bb75..a9afd212 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -15,7 +15,7 @@ process CUSTOM_EXTRACTCONTIG { output: path "*extracted.fa" , emit: contig - path "*extracted.fa.*", emit: bwa_index + path "*extracted.fa.*", emit: bwamem2_index path 'versions.yml' , emit: versions when: diff --git a/nextflow.config b/nextflow.config index f76c321a..656b89bb 100644 --- a/nextflow.config +++ b/nextflow.config @@ -78,7 +78,7 @@ params { 'panel_data_paths', 'ref_data', 'ref_data_genome_alt', - 'ref_data_genome_bwa_index', + 'ref_data_genome_bwamem2_index', 'ref_data_genome_dict', 'ref_data_genome_fai', 'ref_data_genome_fasta', diff --git a/subworkflows/local/lilac_calling/main.nf b/subworkflows/local/lilac_calling/main.nf index f267902e..62e43abe 100644 --- a/subworkflows/local/lilac_calling/main.nf +++ b/subworkflows/local/lilac_calling/main.nf @@ -131,7 +131,7 @@ workflow LILAC_CALLING { REALIGNREADS( SLICEBAM.out.bam, EXTRACTCONTIG.out.contig, - EXTRACTCONTIG.out.bwa_index, + EXTRACTCONTIG.out.bwamem2_index, ) ch_versions = ch_versions.mix(REALIGNREADS.out.versions) diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 121733a1..85f5366b 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -55,28 +55,28 @@ workflow PREPARE_REFERENCE { // // Set bwa-mem2 index, unpack or create if required // - ch_genome_bwa_index = Channel.empty() + ch_genome_bwamem2_index = Channel.empty() if (run_config.has_dna && run_config.stages.alignment) { - if (!params.ref_data_genome_bwa_index) { + if (!params.ref_data_genome_bwamem2_index) { BWAMEM2_INDEX( ch_genome_fasta, params.ref_data_genome_alt ? file(params.ref_data_genome_alt) : [], ) - ch_genome_bwa_index = BWAMEM2_INDEX.out.index + ch_genome_bwamem2_index = BWAMEM2_INDEX.out.index ch_versions = ch_versions.mix(BWAMEM2_INDEX.out.versions) - } else if (params.ref_data_genome_bwa_index.endsWith('.tar.gz')) { + } else if (params.ref_data_genome_bwamem2_index.endsWith('.tar.gz')) { - ch_genome_bwa_index_inputs = Channel.fromPath(params.ref_data_genome_bwa_index) + ch_genome_bwamem2_index_inputs = Channel.fromPath(params.ref_data_genome_bwamem2_index) .map { [[id: "bwa-mem2_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } - DECOMP_BWAMEM2_INDEX(ch_genome_bwa_index_inputs) - ch_genome_bwa_index = DECOMP_BWAMEM2_INDEX.out.dir + DECOMP_BWAMEM2_INDEX(ch_genome_bwamem2_index_inputs) + ch_genome_bwamem2_index = DECOMP_BWAMEM2_INDEX.out.dir } else { - ch_genome_bwa_index = getRefFileChannel('ref_data_genome_bwa_index') + ch_genome_bwamem2_index = getRefFileChannel('ref_data_genome_bwamem2_index') } } @@ -235,7 +235,7 @@ workflow PREPARE_REFERENCE { ch_genome_fasta, ch_genome_fai, ch_genome_dict, - ch_genome_bwa_index, + ch_genome_bwamem2_index, ch_genome_gridss_index, ch_genome_star_index, ch_virusbreakenddb, @@ -258,19 +258,19 @@ workflow PREPARE_REFERENCE { } emit: - genome_fasta = ch_genome_fasta.first() // path: genome_fasta - genome_fai = ch_genome_fai.first() // path: genome_fai - genome_dict = ch_genome_dict.first() // path: genome_dict - genome_bwa_index = ch_genome_bwa_index.first() // path: genome_bwa_index - genome_gridss_index = ch_genome_gridss_index.first() // path: genome_gridss_index - genome_star_index = ch_genome_star_index.first() // path: genome_star_index - genome_version = ch_genome_version // val: genome_version - - virusbreakenddb = ch_virusbreakenddb.first() // path: VIRUSBreakend database - hmf_data = ch_hmf_data // map: HMF data paths - panel_data = ch_panel_data // map: Panel data paths - - versions = ch_versions // channel: [ versions.yml ] + genome_fasta = ch_genome_fasta.first() // path: genome_fasta + genome_fai = ch_genome_fai.first() // path: genome_fai + genome_dict = ch_genome_dict.first() // path: genome_dict + genome_bwamem2_index = ch_genome_bwamem2_index.first() // path: genome_bwa-mem2_index + genome_gridss_index = ch_genome_gridss_index.first() // path: genome_gridss_index + genome_star_index = ch_genome_star_index.first() // path: genome_star_index + genome_version = ch_genome_version // val: genome_version + + virusbreakenddb = ch_virusbreakenddb.first() // path: VIRUSBreakend database + hmf_data = ch_hmf_data // map: HMF data paths + panel_data = ch_panel_data // map: Panel data paths + + versions = ch_versions // channel: [ versions.yml ] } def getRefFileChannel(key) { diff --git a/subworkflows/local/read_alignment_dna/main.nf b/subworkflows/local/read_alignment_dna/main.nf index 6632f921..795bdc73 100644 --- a/subworkflows/local/read_alignment_dna/main.nf +++ b/subworkflows/local/read_alignment_dna/main.nf @@ -15,7 +15,7 @@ workflow READ_ALIGNMENT_DNA { // Reference data genome_fasta // channel: [mandatory] /path/to/genome_fasta - genome_bwa_index // channel: [mandatory] /path/to/genome_bwa_index_dir/ + genome_bwamem2_index // channel: [mandatory] /path/to/genome_bwa-mem2_index_dir/ // Params max_fastq_records // numeric: [mandatory] max number of FASTQ records per split @@ -128,11 +128,11 @@ workflow READ_ALIGNMENT_DNA { // MODULE: BWA-MEM2 // // Create process input channel - // channel: [ meta_bwa, fastq_fwd, fastq_rev ] - ch_bwa_inputs = ch_fastqs_ready + // channel: [ meta_bwamem2, fastq_fwd, fastq_rev ] + ch_bwamem2_inputs = ch_fastqs_ready .map { meta_fastq_ready, fastq_fwd, fastq_rev -> - def meta_bwa = [ + def meta_bwamem2 = [ *:meta_fastq_ready, @@ -142,14 +142,14 @@ workflow READ_ALIGNMENT_DNA { ] - return [meta_bwa, fastq_fwd, fastq_rev] + return [meta_bwamem2, fastq_fwd, fastq_rev] } // Run process BWAMEM2_ALIGN( - ch_bwa_inputs, + ch_bwamem2_inputs, genome_fasta, - genome_bwa_index, + genome_bwamem2_index, ) ch_versions = ch_versions.mix(BWAMEM2_ALIGN.out.versions) @@ -157,25 +157,25 @@ workflow READ_ALIGNMENT_DNA { // Reunite BAMs // First, count expected BAMs per sample for non-blocking groupTuple op // channel: [ meta_count, group_size ] - ch_sample_fastq_counts = ch_bwa_inputs - .map { meta_bwa, reads_fwd, reads_rev -> + ch_sample_fastq_counts = ch_bwamem2_inputs + .map { meta_bwamem2, reads_fwd, reads_rev -> def meta_count = [ - key: meta_bwa.key, - sample_type: meta_bwa.sample_type, + key: meta_bwamem2.key, + sample_type: meta_bwamem2.sample_type, ] - return [meta_count, meta_bwa] + return [meta_count, meta_bwamem2] } .groupTuple() - .map { meta_count, meta_bwas -> return [meta_count, meta_bwas.size()] } + .map { meta_count, metas_bwamem2 -> return [meta_count, metas_bwamem2.size()] } // Now, group with expected size then sort into tumor and normal channels // channel: [ meta_group, [bam, ...], [bai, ...] ] ch_bams_united = ch_sample_fastq_counts .cross( // First element to match meta_count above for `cross` - BWAMEM2_ALIGN.out.bam.map { meta_bwa, bam, bai -> [[key: meta_bwa.key, sample_type: meta_bwa.sample_type], bam, bai] } + BWAMEM2_ALIGN.out.bam.map { meta_bwamem2, bam, bai -> [[key: meta_bwamem2.key, sample_type: meta_bwamem2.sample_type], bam, bai] } ) .map { count_tuple, bam_tuple -> diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 1c8c5b01..c6193c2f 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -114,7 +114,7 @@ workflow TARGETED { READ_ALIGNMENT_DNA( ch_inputs, ref_data.genome_fasta, - ref_data.genome_bwa_index, + ref_data.genome_bwamem2_index, params.max_fastq_records, ) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index b2d5096b..188ff68c 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -123,7 +123,7 @@ workflow WGTS { READ_ALIGNMENT_DNA( ch_inputs, ref_data.genome_fasta, - ref_data.genome_bwa_index, + ref_data.genome_bwamem2_index, params.max_fastq_records, ) From 5ea55f58a908b468562f4215700b372cdefd5b73 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 17 May 2024 10:48:10 +1000 Subject: [PATCH 483/562] Use correct bwa-mem2 pointers in usage.md --- docs/usage.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index ffff4e08..76030cf8 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -334,7 +334,7 @@ params { fasta = "/path/to/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" fai = "/path/to/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" dict = "/path/to/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwa_index = "/path/to/bwa-mem2_index/" + bwa-mem2_index = "/path/to/bwa-mem2_index/" gridss_index = "/path/to/gridss_index/" star_index = "/path/to/star_index/" } @@ -357,7 +357,7 @@ _GRCh37 genome (Hartwig) [`GRCh37_hmf`]_ | FASTA | [Homo_sapiens.GRCh37.GATK.illumina.fasta](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/Homo_sapiens.GRCh37.GATK.illumina.fasta) | | FASTA index | [Homo_sapiens.GRCh37.GATK.illumina.fasta.fai](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai) | | FASTA seq dictionary | [Homo_sapiens.GRCh37.GATK.illumina.fasta.dict](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict) | -| bwa-mem2 index | [bwa_index/2.2.1.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/bwa_index/2.2.1.tar.gz) | +| bwa-mem2 index | [bwa-mem2_index/2.2.1.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/bwa-mem2_index/2.2.1.tar.gz) | | GRIDSS index | [gridss_index/2.13.2.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/gridss_index/2.13.2.tar.gz) | | STAR index | [star_index/gencode_19/2.7.3a.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/star_index/gencode_19/2.7.3a.tar.gz) | @@ -368,7 +368,7 @@ _GRCh38 genome (Hartwig) [`GRCh38_hmf`]_ | FASTA | [GCA_000001405.15_GRCh38_no_alt_analysis_set.fna](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna) | | FASTA index | [GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai) | | FASTA seq dictionary | [GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict) | -| bwa-mem2 index | [bwa_index/2.2.1.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/bwa_index/2.2.1.tar.gz) | +| bwa-mem2 index | [bwa-mem2_index/2.2.1.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/bwa-mem2_index/2.2.1.tar.gz) | | GRIDSS index | [gridss_index/2.13.2.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/gridss_index/2.13.2.tar.gz) | | STAR index | [star_index/gencode_38/2.7.3a.tar.gz](https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/star_index/gencode_38/2.7.3a.tar.gz) | From 112d23909f8af1d9c332ea0c3a7c9ad6fbe3e48d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 17 May 2024 10:53:22 +1000 Subject: [PATCH 484/562] Correct typo usage.md --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 76030cf8..add8c752 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -334,7 +334,7 @@ params { fasta = "/path/to/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" fai = "/path/to/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" dict = "/path/to/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwa-mem2_index = "/path/to/bwa-mem2_index/" + bwamem2_index = "/path/to/bwa-mem2_index/" gridss_index = "/path/to/gridss_index/" star_index = "/path/to/star_index/" } From 521e2dfccbdfc4d76a84eeb3ba921fc7284b5e7f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 18 May 2024 13:02:26 +1000 Subject: [PATCH 485/562] Change admonition style to fix rendering --- docs/usage.md | 115 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 40 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index add8c752..33e2324c 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -21,13 +21,17 @@ These features enable oncoanalyser to be run in a highly flexible way. For examp PURPLE data as the starting point and skip variant calling processes. Additionally, reference/resource files can be staged locally to optimise execution or modified to create user-defined driver gene panels. -> [!WARNING] -> There are important requirements when using BAMs as input instead of FASTQs: -> -> - STAR must have been run with [specific -> parameters](https://github.com/hartwigmedical/hmftools/tree/master/isofox#a-note-on-alignment-and-multi-mapping), -> this is critical for WTS data, and -> - reads are expected to have been aligned to one of the Hartwig-distributed reference genomes ([user-defined genomes may be used](#custom-genomes) though are not recommended) +:::danger + +When starting from BAMs rather than FASTQ it is expected that: + +- RNA read alignments are generated with STAR using [specific + parameters](https://github.com/hartwigmedical/hmftools/tree/master/isofox#a-note-on-alignment-and-multi-mapping), this + is __critical__ for WTS data, and +- reads are aligned to a Hartwig-distributed reference genome ([custom genomes](#custom-genomes) can be used but are not + recommended) + +::: ## Supported analyses @@ -57,8 +61,11 @@ during execution such as the PURPLE output directory. The full list of recognise #### FASTQ -> [!NOTE] -> Currently only non-interleaved paired-end reads are accepted as FASTQ input +:::note + +Currently only non-interleaved paired-end reads are accepted as FASTQ input. + +::: ```csv title="samplesheet.csv" group_id,subject_id,sample_id,sample_type,sequence_type,filetype,info,filepath @@ -69,16 +76,21 @@ P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tum #### BAM -> [!NOTE] -> Inputs with the `bam` filetype will be processed by MarkDups as required by hmftools. Where an input BAM has already -> been processed specifically by [HMF -> MarkDups](https://github.com/hartwigmedical/hmftools/blob/master/mark-dups/README.md), you can avoid needless -> reprocessing by setting `bam_markdups` as the filetype instead. It is important to understand that duplicate marking -> by other tools (e.g. GATK) cannot be used as a substitute since HMF MarkDups performs key operations beyond just -> duplicate marking. -> -> Please note there are other essential requirements around the use of BAMs as inputs, see the warning above in the -> [Introduction](#introduction). +:::note + +Inputs with the `bam` filetype will be processed by MarkDups as required by hmftools. Where an input BAM has already +been processed specifically by [HMF +MarkDups](https://github.com/hartwigmedical/hmftools/blob/master/mark-dups/README.md), you can avoid needless +reprocessing by setting `bam_markdups` as the filetype instead. It is important to understand that duplicate marking by +other tools (e.g. GATK) cannot be used as a substitute since HMF MarkDups performs key operations beyond just duplicate +marking. + +
    + +Please note there are other essential requirements around the use of BAMs as inputs, see the warning above in the +[Introduction](#introduction). + +::: ```csv title="samplesheet.csv" group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath @@ -143,10 +155,13 @@ nextflow run nf-core/oncoanalyser \ This will launch the pipeline with the `docker` configuration profile. See below for more information on profiles. -> [!NOTE] -> Reference data will be retrieved by oncoanalyser for every analysis run. It is therefore strongly recommended when -> running multiple analyses to pre-stage reference data locally to avoid it being retrieved multiple times. See [Staging -> reference data](#staging-reference-data). +:::note + +Reference data will be retrieved by oncoanalyser for every analysis run. It is therefore strongly recommended when +running multiple analyses to pre-stage reference data locally to avoid it being retrieved multiple times. See [Staging +reference data](#staging-reference-data). + +::: Note that the pipeline will create the following files in your working directory: @@ -162,7 +177,12 @@ If you wish to repeatedly use the same parameters for multiple runs, rather than Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. :::warning -Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). + +Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must +only be used for [tuning process resource +specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such +as output directories), or module arguments (args). + ::: The above pipeline run specified with a params file in yaml format: @@ -214,9 +234,12 @@ Multiple processes can be given as a comma-separated list. While there are some skipping resource intensive processes such as VIRUSBreakend), it becomes more powerful when combined with existing inputs as described in the following section. -> [!WARNING] -> When skipping components no checks are done to identify orphan processes in the execution DAG or for redundant -> processes. +:::warning + +When skipping components no checks are done to identify orphan processes in the execution DAG or for redundant +processes. + +::: ### Existing inputs @@ -236,9 +259,12 @@ P1__wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam P1__wgts,P1,SB,tumor,dna,purple_dir,/path/to/P1.purple_dir/ ``` -> [!NOTE] -> The original source input file (i.e. BAM or FASTQ) must always be provided for oncoanalyser to infer the correct -> analysis type. +:::note + +The original source input file (i.e. BAM or FASTQ) must always be provided for oncoanalyser to infer the correct +analysis type. + +::: And now run and skip variant calling: @@ -253,9 +279,12 @@ nextflow run nf-core/oncoanalyser \ --outdir output/ ``` -> [!WARNING] -> Providing existing inputs will cause oncoanalyser to skip the corresponding process but _not any_ of the upstream -> processes. It is the responsibility of the user to skip all relevant processes. +:::warning + +Providing existing inputs will cause oncoanalyser to skip the corresponding process but _not any_ of the upstream +processes. It is the responsibility of the user to skip all relevant processes. + +::: ### Configuring reference data @@ -402,10 +431,13 @@ params { Each index required for the analysis will first be created before running the rest of oncoanalyser with the following command: -> [!NOTE] -> In a process similar to [staging reference data](#staging-reference-data), you can first generate the required indexes -> by setting `--prepare_reference_only` and then provide the prepared reference files to oncoanalyser through a custom -> config file. This avoids having to regenerate indexes for each new analysis. +:::note + +In a process similar to [staging reference data](#staging-reference-data), you can first generate the required indexes +by setting `--prepare_reference_only` and then provide the prepared reference files to oncoanalyser through a custom +config file. This avoids having to regenerate indexes for each new analysis. + +::: ```bash nextflow run nf-core/oncoanalyser \ @@ -431,9 +463,12 @@ Creation of a STAR index also requires transcript annotations, please provide ei - GRCh38: [GENCODE v37 (Ensembl v74) annotations](https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_19/gencode.v19.annotation.gtf.gz) -> [!WARNING] -> STAR index must use transcript annotations from Ensembl versions that match hmftools resource data (GRCh37: v74; -> GRCh38: v104). +:::warning + +STAR index must use transcript annotations from Ensembl versions that match hmftools resource data (GRCh37: v74; GRCh38: +v104). + +::: When creating indexes for reference genomes with alternative haplotypes, an ALT file must be given with `--ref_data_genome_alt`. Importantly, a STAR index will not be generated for reference genomes with alternative From 2a0f2bffa8f6fed36a0131edcebf34f4b11273ac Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 18 May 2024 14:20:44 +1000 Subject: [PATCH 486/562] Add known issue section to README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 8bd70dee..bf4aa9f9 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,10 @@ in the below table. | 0.1.0 through 0.2.7 | 5.33 | | 0.3.0 through 0.4.5 | 5.34 | +## Known issues + +- MarkDups error processing hard-clipped supplementary alignments ([#37](https://github.com/nf-core/oncoanalyser/issues/37)) + ## Credits The oncoanalyser pipeline was written by Stephen Watts while in the [Genomics Platform From c46b9bb8c62491a73a86bcbcf180b4e45e9053f7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sat, 18 May 2024 14:28:27 +1000 Subject: [PATCH 487/562] Apply Prettier linting to usage.md --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 33e2324c..08952c6d 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -27,7 +27,7 @@ When starting from BAMs rather than FASTQ it is expected that: - RNA read alignments are generated with STAR using [specific parameters](https://github.com/hartwigmedical/hmftools/tree/master/isofox#a-note-on-alignment-and-multi-mapping), this - is __critical__ for WTS data, and + is **critical** for WTS data, and - reads are aligned to a Hartwig-distributed reference genome ([custom genomes](#custom-genomes) can be used but are not recommended) From 52610fe69ea6e1d53426abc5e1c06ff5c3351517 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Sun, 19 May 2024 08:02:44 +1000 Subject: [PATCH 488/562] Improve wording for known issue entry in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bf4aa9f9..9f012bc8 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ in the below table. ## Known issues -- MarkDups error processing hard-clipped supplementary alignments ([#37](https://github.com/nf-core/oncoanalyser/issues/37)) +- MarkDups may encounter a fatal error processing hard-clipped supplementary alignments ([#37](https://github.com/nf-core/oncoanalyser/issues/37)) ## Credits From b411125689e7ec292e4a69b8903142f26fea70c6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 20 May 2024 12:15:54 +1000 Subject: [PATCH 489/562] Fix display of ORANGE report screencap on website --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f012bc8..97ac6d25 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ custom panels with externally-generated normalisation data. The key analysis results for each sample are summarised and presented in an ORANGE report (summary page excerpt shown below from _[COLO829_wgts.orange_report.pdf](https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/other/example_report/COLO829_wgts.orange_report.pdf)_): -

    +

    For detailed information on each component of the Hartwig workflow, please refer to [hartwigmedical/hmftools](https://github.com/hartwigmedical/hmftools/). From 6dc8459bc69bc9cf09a5f7df8c4410c69055601a Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 20 May 2024 14:09:41 +1000 Subject: [PATCH 490/562] Make README.md adminitions compatible with website --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 97ac6d25..73510f08 100644 --- a/README.md +++ b/README.md @@ -82,8 +82,7 @@ nextflow run nf-core/oncoanalyser \ ``` > [!WARNING] -> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; -> see [docs](https://nf-co.re/usage/configuration#custom-configuration-files). +> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/usage/configuration#custom-configuration-files). For more details and further functionality, please refer to the [usage documentation](https://nf-co.re/oncoanalyser/usage) and the [parameter documentation](https://nf-co.re/oncoanalyser/parameters). From 437e72e2cc17d9a3a2e2ac377c2449616ade4527 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 21 May 2024 13:28:36 +1000 Subject: [PATCH 491/562] Only create bwa-mem2 index if FASTQ inputs present --- subworkflows/local/prepare_reference/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 85f5366b..7b086827 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -56,7 +56,7 @@ workflow PREPARE_REFERENCE { // Set bwa-mem2 index, unpack or create if required // ch_genome_bwamem2_index = Channel.empty() - if (run_config.has_dna && run_config.stages.alignment) { + if (run_config.has_dna_fastq && run_config.stages.alignment) { if (!params.ref_data_genome_bwamem2_index) { BWAMEM2_INDEX( From d1bc96a684f09142b298ad8f29715cd989a65369 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 22 May 2024 11:20:36 +1000 Subject: [PATCH 492/562] Use all available threads for fastp process --- modules/local/fastp/main.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/local/fastp/main.nf b/modules/local/fastp/main.nf index e12cf1c2..0690204c 100644 --- a/modules/local/fastp/main.nf +++ b/modules/local/fastp/main.nf @@ -31,6 +31,7 @@ process FASTP { --disable_adapter_trimming \\ --disable_trim_poly_g \\ --split_by_lines ${4 * max_fastq_records} \\ + --thread ${task.cpus} \\ --out1 ${meta.sample_id}_${meta.library_id}_${meta.lane}_R1.fastp.fastq.gz \\ --out2 ${meta.sample_id}_${meta.library_id}_${meta.lane}_R2.fastp.fastq.gz From 69f4d3cbccfc390da2e897ab39a246824687f037 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 27 May 2024 17:46:34 +1000 Subject: [PATCH 493/562] Adjust test_stub.config usage comment --- conf/test_stub.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/test_stub.config b/conf/test_stub.config index 55b2460b..34906f4c 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/oncoanalyser -profile test, --outdir + nextflow run nf-core/oncoanalyser -profile test_stub -stub --outdir ---------------------------------------------------------------------------------------- */ From 56f9058d3ffcfd07127c77b09e4397160a2588e9 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 27 May 2024 17:47:19 +1000 Subject: [PATCH 494/562] Update .nf-core.yml lint rule skip list --- .nf-core.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.nf-core.yml b/.nf-core.yml index 2a7a7413..12d00da0 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -3,7 +3,6 @@ lint: actions_ci: False multiqc_config: False files_exist: - - lib/NfcoreTemplate.groovy - lib/Utils.groovy - lib/WorkflowMain.groovy - lib/WorkflowOncoanalyser.groovy From 138d900b2e6d6c75c8513f61f411984d883f895e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 27 May 2024 17:48:29 +1000 Subject: [PATCH 495/562] Correct typo in docs/output.md --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index a93c665c..e2a75b72 100644 --- a/docs/output.md +++ b/docs/output.md @@ -145,7 +145,7 @@ _Picard MarkDuplicates is only run on RNA alignments_ - `/sage/append/` - `.sage.append.vcf.gz`: Tumor DNA sample small variant VCF with RNA data appended. - - `.sage.append.vcf.gz`: Normal DNA sample small variant VCF with RNA data appended.. + - `.sage.append.vcf.gz`: Normal DNA sample small variant VCF with RNA data appended. - `/sage/somatic/` From d925a44456163d216d1bdb9c2e527b9ded3a9cae Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 27 May 2024 18:15:07 +1000 Subject: [PATCH 496/562] Replace System.exit with Nextflow.exit --- lib/Processes.groovy | 10 +++--- lib/Utils.groovy | 51 ++++++++++++++--------------- lib/WorkflowMain.groovy | 26 +++++++-------- lib/WorkflowOncoanalyser.groovy | 2 +- modules/local/pave/germline/main.nf | 4 ++- modules/local/pave/somatic/main.nf | 4 ++- 6 files changed, 51 insertions(+), 46 deletions(-) diff --git a/lib/Processes.groovy b/lib/Processes.groovy index f91fc606..480e10bb 100644 --- a/lib/Processes.groovy +++ b/lib/Processes.groovy @@ -1,3 +1,5 @@ +import nextflow.Nextflow + import Constants import Utils @@ -29,8 +31,8 @@ class Processes { return Constants.Process.valueOf(name.toUpperCase()) } catch(java.lang.IllegalArgumentException e) { def processes_str = Processes.getProcessNames().join('\n - ') - log.error "\nERROR: recieved invalid process: '${name}'. Valid options are:\n - ${processes_str}" - System.exit(1) + log.error "recieved invalid process: '${name}'. Valid options are:\n - ${processes_str}" + Nextflow.exit(1) } } .unique() @@ -45,8 +47,8 @@ class Processes { if (processes_shared) { def processes_shared_str = processes_shared.join('\n - ') def message_base = 'the following processes was found in the include and the exclude list' - log.error "\nERROR: ${message_base}:\n - ${processes_shared_str}" - System.exit(1) + log.error "${message_base}:\n - ${processes_shared_str}" + Nextflow.exit(1) } } diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 0601ed8f..38fae00c 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -26,7 +26,7 @@ class Utils { // Add subject id if absent or check if current matches existing if (meta.containsKey('subject_id') && meta.subject_id != it.subject_id) { log.error "got unexpected subject name for ${group_id} ${meta.subject_id}: ${it.subject_id}" - System.exit(1) + Nextflow.exit(1) } else { meta.subject_id = it.subject_id } @@ -36,7 +36,7 @@ class Utils { if (!sample_type_enum) { def sample_type_str = Utils.getEnumNames(Constants.SampleType).join('\n - ') log.error "received invalid sample type: '${it.sample_type}'. Valid options are:\n - ${sample_type_str}" - System.exit(1) + Nextflow.exit(1) } // Sequence type @@ -44,7 +44,7 @@ class Utils { if (!sequence_type_enum) { def sequence_type_str = Utils.getEnumNames(Constants.SequenceType).join('\n - ') log.error "received invalid sequence type: '${it.sequence_type}'. Valid options are:\n - ${sequence_type_str}" - System.exit(1) + Nextflow.exit(1) } // Filetype @@ -52,7 +52,7 @@ class Utils { if (!filetype_enum) { def filetype_str = Utils.getEnumNames(Constants.FileType).join('\n - ') log.error "received invalid file type: '${it.filetype}'. Valid options are:\n - ${filetype_str}" - System.exit(1) + Nextflow.exit(1) } def sample_key = [sample_type_enum, sequence_type_enum] @@ -60,12 +60,12 @@ class Utils { if (meta_sample.sample_id != it.sample_id) { log.error "got unexpected sample name for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${it.sample_id}" - System.exit(1) + Nextflow.exit(1) } if (meta_sample.containsKey(filetype_enum) & filetype_enum != Constants.FileType.FASTQ) { log.error "got duplicate file for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${filetype_enum}" - System.exit(1) + Nextflow.exit(1) } // Info data @@ -81,12 +81,12 @@ class Utils { if (!info_field_enum) { def info_field_str = Utils.getEnumNames(Constants.InfoField).join('\n - ') log.error "received invalid info field: '${k}'. Valid options are:\n - ${info_field_str}" - System.exit(1) + Nextflow.exit(1) } if (info_data.containsKey(info_field_enum)) { log.error "got duplicate info field for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${info_field_enum}" - System.exit(1) + Nextflow.exit(1) } info_data[info_field_enum] = v @@ -105,12 +105,12 @@ class Utils { if (!info_data.containsKey(Constants.InfoField.LIBRARY_ID)) { log.error "missing 'library_id' info field for ${group_id} ${sample_type_enum}/${sequence_type_enum}" - System.exit(1) + Nextflow.exit(1) } if (!info_data.containsKey(Constants.InfoField.LANE)) { log.error "missing 'lane' info field for ${group_id} ${sample_type_enum}/${sequence_type_enum}" - System.exit(1) + Nextflow.exit(1) } def (fwd, rev) = it.filepath.tokenize(';') @@ -118,7 +118,7 @@ class Utils { if (meta_sample.containsKey(fastq_key)) { log.error "got duplicate lane + library_id data for ${group_id} ${sample_type_enum}/${sequence_type_enum}: ${fastq_key}" - System.exit(1) + Nextflow.exit(1) } if (!meta_sample.containsKey(filetype_enum)) { @@ -179,7 +179,7 @@ class Utils { if (!index_fp.exists() && !stub_run) { def (sample_type, sequence_type) = sample_key log.error "no index provided or found for ${meta.group_id} ${sample_type}/${sequence_type}: ${key}: ${fp}" - System.exit(1) + Nextflow.exit(1) } meta[sample_key][index_enum] = index_fp @@ -262,7 +262,7 @@ class Utils { log.error "no BAMs nor BAM_MARKDUPs nor FASTQs provided for ${meta.group_id} ${sample_type}/${sequence_type}\n\n" + "NB: BAMs or BAM_MARKDUPs or FASTQs are always required as they are the basis to determine input sample type." - System.exit(1) + Nextflow.exit(1) } } @@ -274,7 +274,7 @@ class Utils { if (Utils.hasNormalDna(meta)) { log.error "targeted mode is not compatible with the normal DNA BAM provided for ${meta.group_id}\n\n" + "The targeted workflow supports only tumor DNA BAMs (and tumor RNA BAMs for TSO500)" - System.exit(1) + Nextflow.exit(1) } // Do not allow only tumor RNA @@ -282,22 +282,22 @@ class Utils { log.error "targeted mode is not compatible with only tumor RNA provided for ${meta.group_id}\n\n" + "The targeted workflow requires tumor DNA and can optionally take tumor RNA, depending on " + "the configured panel." - System.exit(1) + Nextflow.exit(1) } // Restrict tumor RNA inputs to the TSO500 panel if (Utils.hasTumorRnaBam(meta) && run_config.panel != 'tso500') { def panel = run_config.panel.toUpperCase() - "Only the TSO500 panel supports tumor RNA analysis" - System.exit(1) + log.error "only the TSO500 panel supports tumor RNA analysis but got: ${panel}" + Nextflow.exit(1) } } // Do not allow normal DNA only if (Utils.hasNormalDna(meta) && !Utils.hasTumorDna(meta)) { - log.error "germline only mode not supported, found only a normal DNA BAM for ${meta.group_id}\n" - System.exit(1) + log.error "germline only mode not supported, found only a normal DNA BAM for ${meta.group_id}" + Nextflow.exit(1) } // Enforce unique samples names within groups @@ -310,9 +310,8 @@ class Utils { def key_strs = keys.collect { sample_type, sequence_type -> "${sample_type}/${sequence_type}" } return " * ${sample_id}: ${key_strs.join(", ")}" } - log.error "duplicate sample names found for ${meta.group_id}:\n\n" + - "${duplicate_message_strs.join("\n")}" - System.exit(1) + log.error "duplicate sample names found for ${meta.group_id}:\n\n${duplicate_message_strs.join("\n")}" + Nextflow.exit(1) } } @@ -333,7 +332,7 @@ class Utils { " The genome .alt file is required when building bwa-mem2 or GRIDSS indexes\n" + " for reference genomes containing ALT contigs\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } // Refuse to create STAR index for reference genome containing ALTs, refer to Slack channel @@ -344,7 +343,7 @@ class Utils { " Refusing to create the STAR index for a reference genome with ALT contigs.\n" + " Please review https://github.com/alexdobin/STAR docs or contact us on Slack.\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } // Require that an input GTF file is provided when creating STAR index @@ -353,7 +352,7 @@ class Utils { " Creating a STAR index requires the appropriate genome transcript annotations\n" + " as a GTF file. Please contact us on Slack for further information." "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } } @@ -383,7 +382,7 @@ class Utils { if (!run_mode_enum) { def run_modes_str = Utils.getEnumNames(Constants.RunMode).join('\n - ') log.error "recieved an invalid run mode: '${run_mode}'. Valid options are:\n - ${run_modes_str}" - System.exit(1) + Nextflow.exit(1) } return run_mode_enum } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index ae3ad687..56047a62 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -115,21 +115,21 @@ class WorkflowMain { " Currently, the available genome are:\n" + " ${params.genomes.keySet().join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } else if (!params.genomes.containsKey(params.genome)) { log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + " Currently, the available genome are:\n" + " ${params.genomes.keySet().join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } if (!Constants.GENOMES_SUPPORTED.contains(params.genome)) { if (!params.force_genome) { - log.error "ERROR: currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got ${params.genome}" + + log.error "currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but got ${params.genome}" + ", please adjust the --genome argument accordingly or override with --force_genome." - System.exit(1) + Nextflow.exit(1) } else { log.warn "currently only the GRCh37_hmf and GRCh38_hmf genomes are supported but forcing to " + "proceed with \"${params.genome}\"" @@ -143,7 +143,7 @@ class WorkflowMain { " Currently, the list of genomes in the version list include:\n" + " ${Constants.GENOMES_DEFINED.join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } if (!params.genome_type) { @@ -153,12 +153,12 @@ class WorkflowMain { " Currently, the list of genomes in the type list include:\n" + " ${Constants.GENOMES_DEFINED.join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } if (!params.ref_data_hmf_data_path) { - log.error "ERROR: HMF data path wasn't provided" - System.exit(1) + log.error "HMF data path wasn't provided" + Nextflow.exit(1) } // Run configuration specific parameters @@ -171,7 +171,7 @@ class WorkflowMain { " Currently, the available run modes are:\n" + " - ${run_modes}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } def run_mode = Utils.getRunMode(params.mode, log) @@ -187,7 +187,7 @@ class WorkflowMain { " Currently, the available panels are:\n" + " - ${panels}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } else if (!Constants.PANELS_DEFINED.contains(params.panel)) { @@ -196,7 +196,7 @@ class WorkflowMain { " The ${params.panel} is not defined. Currently, the available panels are:\n" + " - ${panels}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } @@ -207,7 +207,7 @@ class WorkflowMain { log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Using a reference genome without ALT contigs but found an .alt file\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } def ref_data_genome_alt_fn = nextflow.Nextflow.file(params.ref_data_genome_alt).name @@ -217,7 +217,7 @@ class WorkflowMain { " Found .alt file with filename of ${ref_data_genome_alt_fn} but it is required to match\n" + " reference genome FASTA filename stem: ${ref_data_genome_fasta_fn}.alt\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.exit(1) } } diff --git a/lib/WorkflowOncoanalyser.groovy b/lib/WorkflowOncoanalyser.groovy index 97f0a030..b4701e1f 100755 --- a/lib/WorkflowOncoanalyser.groovy +++ b/lib/WorkflowOncoanalyser.groovy @@ -59,7 +59,7 @@ class WorkflowOncoanalyser { } } else { System.err.println "ERROR: got bad flatten_mode: ${flatten_mode}" - System.exit(1) + Nextflow.exit(1) } } diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index b5cf7bdf..738a9c34 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -2,6 +2,8 @@ // - https://github.com/hartwigmedical/pipeline5/blob/v5.33/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveGermline.java#L36-L41 // - https://github.com/hartwigmedical/pipeline5/blob/v5.33/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L31-L43 +import nextflow.Nextflow + process PAVE_GERMLINE { tag "${meta.id}" label 'process_medium' @@ -42,7 +44,7 @@ process PAVE_GERMLINE { gnomad_args = "-gnomad_freq_dir ${gnomad_resource}" } else { log.error "got bad genome version: ${genome_ver}" - System.exit(1) + Nextflow.exit(1) } """ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 147f4dce..2079364e 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -1,3 +1,5 @@ +import nextflow.Nextflow + process PAVE_SOMATIC { tag "${meta.id}" label 'process_medium' @@ -43,7 +45,7 @@ process PAVE_SOMATIC { gnomad_args = "-gnomad_freq_dir ${gnomad_resource}" } else { log.error "got bad genome version: ${genome_ver}" - System.exit(1) + Nextflow.exit(1) } // Targeted mode From 644927c31f1918e738d8093b3ca99e6b33978ada Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 27 May 2024 18:17:52 +1000 Subject: [PATCH 497/562] Further standardise variable naming --- modules/local/amber/main.nf | 4 ++-- modules/local/cuppa/main.nf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index 368a461e..df181414 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -9,7 +9,7 @@ process AMBER { input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) - val ref_genome_ver + val genome_ver path heterozygous_sites path target_region_bed @@ -37,7 +37,7 @@ process AMBER { ${reference_arg} \\ ${reference_bam_arg} \\ ${target_regions_bed_arg} \\ - -ref_genome_version ${ref_genome_ver} \\ + -ref_genome_version ${genome_ver} \\ -loci ${heterozygous_sites} \\ -threads ${task.cpus} \\ -output_dir amber/ diff --git a/modules/local/cuppa/main.nf b/modules/local/cuppa/main.nf index f7ba8e08..8a4971f6 100644 --- a/modules/local/cuppa/main.nf +++ b/modules/local/cuppa/main.nf @@ -9,7 +9,7 @@ process CUPPA { input: tuple val(meta), path(isofox_dir), path(purple_dir), path(linx_dir), path(virusinterpreter_dir) - val ref_genome_ver + val genome_ver path cuppa_resources, stageAs: 'cuppa_reference_data' val classifier @@ -51,7 +51,7 @@ process CUPPA { -sample_data_dir sample_data/ \\ -categories ${classifier} \\ -ref_data_dir ${cuppa_resources} \\ - -ref_genome_version ${ref_genome_ver} \\ + -ref_genome_version ${genome_ver} \\ -create_pdf \\ -output_dir cuppa/ From 448a9889dbf474879b783926262b2737f536f763 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 27 May 2024 18:19:39 +1000 Subject: [PATCH 498/562] Make output tarball channel name more descriptive --- modules/local/custom/extract_tarball/main.nf | 2 +- subworkflows/local/prepare_reference/main.nf | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/local/custom/extract_tarball/main.nf b/modules/local/custom/extract_tarball/main.nf index c0b178fa..9e7a9129 100644 --- a/modules/local/custom/extract_tarball/main.nf +++ b/modules/local/custom/extract_tarball/main.nf @@ -10,7 +10,7 @@ process CUSTOM_EXTRACTTARBALL { tuple val(meta), path(tarball) output: - path "${meta.id}/", emit: dir + path "${meta.id}/", emit: extracted_dir when: task.ext.when == null || task.ext.when diff --git a/subworkflows/local/prepare_reference/main.nf b/subworkflows/local/prepare_reference/main.nf index 7b086827..29479dd2 100644 --- a/subworkflows/local/prepare_reference/main.nf +++ b/subworkflows/local/prepare_reference/main.nf @@ -72,7 +72,7 @@ workflow PREPARE_REFERENCE { .map { [[id: "bwa-mem2_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } DECOMP_BWAMEM2_INDEX(ch_genome_bwamem2_index_inputs) - ch_genome_bwamem2_index = DECOMP_BWAMEM2_INDEX.out.dir + ch_genome_bwamem2_index = DECOMP_BWAMEM2_INDEX.out.extracted_dir } else { @@ -109,7 +109,7 @@ workflow PREPARE_REFERENCE { .map { [[id: "gridss_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } DECOMP_GRIDSS_INDEX(ch_genome_gridss_index_inputs) - ch_genome_gridss_index = DECOMP_GRIDSS_INDEX.out.dir + ch_genome_gridss_index = DECOMP_GRIDSS_INDEX.out.extracted_dir } else { @@ -138,7 +138,7 @@ workflow PREPARE_REFERENCE { .map { [[id: "star_index_${it.name.replaceAll('\\.tar\\.gz$', '')}"], it] } DECOMP_STAR_INDEX(ch_genome_star_index_inputs) - ch_genome_star_index = DECOMP_STAR_INDEX.out.dir + ch_genome_star_index = DECOMP_STAR_INDEX.out.extracted_dir } else { @@ -158,7 +158,7 @@ workflow PREPARE_REFERENCE { .map { [[id: it.name.replaceAll('\\.tar\\.gz$', '')], it] } DECOMP_VIRUSBREAKEND_DB(ch_virusbreakenddb_inputs) - ch_virusbreakenddb = DECOMP_VIRUSBREAKEND_DB.out.dir + ch_virusbreakenddb = DECOMP_VIRUSBREAKEND_DB.out.extracted_dir } else { @@ -179,7 +179,7 @@ workflow PREPARE_REFERENCE { DECOMP_HMF_DATA(ch_hmf_data_inputs) - ch_hmf_data = DECOMP_HMF_DATA.out.dir + ch_hmf_data = DECOMP_HMF_DATA.out.extracted_dir .collect() .map { dir_list -> assert dir_list.size() == 1 @@ -209,7 +209,7 @@ workflow PREPARE_REFERENCE { DECOMP_PANEL_DATA(ch_panel_data_inputs) - ch_panel_data = DECOMP_PANEL_DATA.out.dir + ch_panel_data = DECOMP_PANEL_DATA.out.extracted_dir .collect() .map { dir_list -> assert dir_list.size() == 1 From 84afa4d17364815cf167284c1e377c6747f24b32 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 28 May 2024 09:38:38 +1000 Subject: [PATCH 499/562] Bump MarkDups 1.1.5 to Bioconda build hdfd78af_1 --- modules/local/markdups/environment.yml | 2 +- modules/local/markdups/main.nf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/markdups/environment.yml b/modules/local/markdups/environment.yml index 6557fc27..b910e500 100644 --- a/modules/local/markdups/environment.yml +++ b/modules/local/markdups/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-mark-dups=1.1.5 + - bioconda::hmftools-mark-dups=1.1.5=hdfd78af_1 diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 90bf9696..42c10394 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -3,8 +3,8 @@ process MARKDUPS { label 'process_medium' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.5--hdfd78af_0' : - 'biocontainers/hmftools-mark-dups:1.1.5--hdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.5--hdfd78af_1' : + 'biocontainers/hmftools-mark-dups:1.1.5--hdfd78af_1' }" input: tuple val(meta), path(bams), path(bais) From 8295f1ee248f662fef70d47149e1774d1fdedfd0 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 28 May 2024 09:50:15 +1000 Subject: [PATCH 500/562] Bump SvPrep to 1.2.4 --- modules/local/svprep/assemble/environment.yml | 2 +- modules/local/svprep/assemble/main.nf | 4 ++-- modules/local/svprep/call/environment.yml | 2 +- modules/local/svprep/call/main.nf | 4 ++-- modules/local/svprep/depth_annotator/environment.yml | 2 +- modules/local/svprep/depth_annotator/main.nf | 4 ++-- modules/local/svprep/preprocess/environment.yml | 2 +- modules/local/svprep/preprocess/main.nf | 4 ++-- modules/local/svprep/svprep/environment.yml | 2 +- modules/local/svprep/svprep/main.nf | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/modules/local/svprep/assemble/environment.yml b/modules/local/svprep/assemble/environment.yml index 744167d9..ff1c9e1a 100644 --- a/modules/local/svprep/assemble/environment.yml +++ b/modules/local/svprep/assemble/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sv-prep=1.2.3=hdfd78af_1 + - bioconda::hmftools-sv-prep=1.2.4 diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 1f9a3957..d205b09f 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -4,8 +4,8 @@ process GRIDSS_ASSEMBLE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : - 'biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.4--hdfd78af_0' : + 'biocontainers/hmftools-sv-prep:1.2.4--hdfd78af_0' }" input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) diff --git a/modules/local/svprep/call/environment.yml b/modules/local/svprep/call/environment.yml index 8961a674..90d888f4 100644 --- a/modules/local/svprep/call/environment.yml +++ b/modules/local/svprep/call/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sv-prep=1.2.3=hdfd78af_1 + - bioconda::hmftools-sv-prep=1.2.4 diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index ef5243b9..ef28f83a 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -4,8 +4,8 @@ process GRIDSS_CALL { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : - 'biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.4--hdfd78af_0' : + 'biocontainers/hmftools-sv-prep:1.2.4--hdfd78af_0' }" input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) diff --git a/modules/local/svprep/depth_annotator/environment.yml b/modules/local/svprep/depth_annotator/environment.yml index c715d41a..dc6c4f3c 100644 --- a/modules/local/svprep/depth_annotator/environment.yml +++ b/modules/local/svprep/depth_annotator/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sv-prep=1.2.3=hdfd78af_1 + - bioconda::hmftools-sv-prep=1.2.4 diff --git a/modules/local/svprep/depth_annotator/main.nf b/modules/local/svprep/depth_annotator/main.nf index 2d7cb3be..0a75529e 100644 --- a/modules/local/svprep/depth_annotator/main.nf +++ b/modules/local/svprep/depth_annotator/main.nf @@ -4,8 +4,8 @@ process SVPREP_DEPTH_ANNOTATOR { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : - 'biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.4--hdfd78af_0' : + 'biocontainers/hmftools-sv-prep:1.2.4--hdfd78af_0' }" input: tuple val(meta), path(bams), path(bais), path(vcf), val(labels) diff --git a/modules/local/svprep/preprocess/environment.yml b/modules/local/svprep/preprocess/environment.yml index 6a1e5fd0..6414c016 100644 --- a/modules/local/svprep/preprocess/environment.yml +++ b/modules/local/svprep/preprocess/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sv-prep=1.2.3=hdfd78af_1 + - bioconda::hmftools-sv-prep=1.2.4 diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index 4fa37b05..ed3f3430 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -4,8 +4,8 @@ process GRIDSS_PREPROCESS { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : - 'biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.4--hdfd78af_0' : + 'biocontainers/hmftools-sv-prep:1.2.4--hdfd78af_0' }" input: tuple val(meta), path(bam), path(bam_filtered) diff --git a/modules/local/svprep/svprep/environment.yml b/modules/local/svprep/svprep/environment.yml index 5fb5d9c9..9435340f 100644 --- a/modules/local/svprep/svprep/environment.yml +++ b/modules/local/svprep/svprep/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sv-prep=1.2.3=hdfd78af_1 + - bioconda::hmftools-sv-prep=1.2.4 diff --git a/modules/local/svprep/svprep/main.nf b/modules/local/svprep/svprep/main.nf index 3b4477bd..bba5bc5a 100644 --- a/modules/local/svprep/svprep/main.nf +++ b/modules/local/svprep/svprep/main.nf @@ -4,8 +4,8 @@ process SVPREP { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.3--hdfd78af_1' : - 'biocontainers/hmftools-sv-prep:1.2.3--hdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sv-prep:1.2.4--hdfd78af_0' : + 'biocontainers/hmftools-sv-prep:1.2.4--hdfd78af_0' }" input: tuple val(meta), path(bam), path(bai), path(junctions) From 610ea8a3045109e2450be0cc5806538147095391 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 28 May 2024 09:54:35 +1000 Subject: [PATCH 501/562] Bump bwa-mem2 container build and update Conda env - update Conda environments to use fixed Sambamba Bioconda package - new container build also uses fixed Sambamba package --- modules/local/bwa-mem2/mem/environment.yml | 2 +- modules/local/bwa-mem2/mem/main.nf | 4 ++-- modules/local/custom/lilac_extract_and_index_contig/main.nf | 4 ++-- modules/local/custom/lilac_realign_reads_lilac/main.nf | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/local/bwa-mem2/mem/environment.yml b/modules/local/bwa-mem2/mem/environment.yml index 571dda57..8ae51aa4 100644 --- a/modules/local/bwa-mem2/mem/environment.yml +++ b/modules/local/bwa-mem2/mem/environment.yml @@ -6,4 +6,4 @@ channels: dependencies: - bioconda::bwa-mem2=2.2.1 - bioconda::samtools=1.19.2 - - bioconda::sambamba=1.0 + - bioconda::sambamba=1.0.1 diff --git a/modules/local/bwa-mem2/mem/main.nf b/modules/local/bwa-mem2/mem/main.nf index d1c9ba81..2a8ac501 100644 --- a/modules/local/bwa-mem2/mem/main.nf +++ b/modules/local/bwa-mem2/mem/main.nf @@ -4,8 +4,8 @@ process BWAMEM2_ALIGN { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' : - 'biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:4163e62e1daead7b7ea0228baece715bec295c22-0' : + 'biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:4163e62e1daead7b7ea0228baece715bec295c22-0' }" input: tuple val(meta), path(reads_fwd), path(reads_rev) diff --git a/modules/local/custom/lilac_extract_and_index_contig/main.nf b/modules/local/custom/lilac_extract_and_index_contig/main.nf index a9afd212..f55ccb10 100644 --- a/modules/local/custom/lilac_extract_and_index_contig/main.nf +++ b/modules/local/custom/lilac_extract_and_index_contig/main.nf @@ -4,8 +4,8 @@ process CUSTOM_EXTRACTCONTIG { conda "bwa-mem2=2.2.1 samtools=1.19.2" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' : - 'biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:4163e62e1daead7b7ea0228baece715bec295c22-0' : + 'biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:4163e62e1daead7b7ea0228baece715bec295c22-0' }" input: val contig_name diff --git a/modules/local/custom/lilac_realign_reads_lilac/main.nf b/modules/local/custom/lilac_realign_reads_lilac/main.nf index 77757ccb..33ddd63a 100644 --- a/modules/local/custom/lilac_realign_reads_lilac/main.nf +++ b/modules/local/custom/lilac_realign_reads_lilac/main.nf @@ -2,10 +2,10 @@ process CUSTOM_REALIGNREADS { tag "${meta.id}" label 'process_low' - conda "bioconda::bwa-mem2=2.2.1 bioconda::samtools=1.19.2 bioconda::sambamba=1.0" + conda "bioconda::bwa-mem2=2.2.1 bioconda::samtools=1.19.2 bioconda::sambamba=1.0.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' : - 'biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:544519c4a0ff7e9616a3b44afde1f143c52f10c3-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:4163e62e1daead7b7ea0228baece715bec295c22-0' : + 'biocontainers/mulled-v2-4dde50190ae599f2bb2027cb2c8763ea00fb5084:4163e62e1daead7b7ea0228baece715bec295c22-0' }" input: tuple val(meta), path(bam), path(bai) From ab9518bec6f493d38e716aa552755963c9d30ef7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 28 May 2024 09:56:43 +1000 Subject: [PATCH 502/562] Bump Sambamba to 1.0.1 --- modules/local/sambamba/merge/environment.yml | 2 +- modules/local/sambamba/merge/main.nf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/sambamba/merge/environment.yml b/modules/local/sambamba/merge/environment.yml index e98f53f9..1e158af2 100644 --- a/modules/local/sambamba/merge/environment.yml +++ b/modules/local/sambamba/merge/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::sambamba=1.0 + - bioconda::sambamba=1.0.1 diff --git a/modules/local/sambamba/merge/main.nf b/modules/local/sambamba/merge/main.nf index 08e8c2af..b8b3828f 100644 --- a/modules/local/sambamba/merge/main.nf +++ b/modules/local/sambamba/merge/main.nf @@ -3,8 +3,8 @@ process SAMBAMBA_MERGE { label 'process_medium' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/sambamba:1.0--h98b6b92_0' : - 'biocontainers/sambamba:1.0--h98b6b92_0' }" + 'https://depot.galaxyproject.org/singularity/sambamba:1.0.1--h6f6fda4_0' : + 'biocontainers/sambamba:1.0.1--h6f6fda4_0' }" input: tuple val(meta), path(bams) From 3a6ebfc065ec9100b2751b2dd2d72b824a2d420b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 27 May 2024 18:22:57 +1000 Subject: [PATCH 503/562] Bump version to 1.0.0 for initial release --- .bumpversion.cfg | 2 +- README.md | 2 +- docs/usage.md | 14 +++++++------- nextflow.config | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index ed583aa7..eb4c5b1c 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.3.1 +current_version = 1.0.0 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P[a-z0-9+]+) diff --git a/README.md b/README.md index 73510f08..cbce0809 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Launch oncoanalyser: ```bash nextflow run nf-core/oncoanalyser \ -profile docker \ - -revision 0.4.5 \ + -revision 1.0.0 \ --mode wgts \ --genome GRCh38_hmf \ --input samplesheet.csv \ diff --git a/docs/usage.md b/docs/usage.md index 08952c6d..0514d59d 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -55,7 +55,7 @@ details and columns are [described below](#column-descriptions). Several different input filetypes beyond FASTQ and BAM are recognised, including intermediate output files generated during execution such as the PURPLE output directory. The full list of recognised input filetypes is available -[here](https://github.com/nf-core/oncoanalyser/blob/0.4.5/lib/Constants.groovy#L58-L90). +[here](https://github.com/nf-core/oncoanalyser/blob/1.0.0/lib/Constants.groovy#L58-L90). ### Simple example @@ -146,7 +146,7 @@ The typical command for running the pipeline is as follows: ```bash nextflow run nf-core/oncoanalyser \ -profile docker \ - -revision 0.4.5 \ + -revision 1.0.0 \ --mode \ --genome \ --input samplesheet.csv \ @@ -229,7 +229,7 @@ If you wish to share such profile (such as upload as supplementary material for ### Selecting processes Most of the major components in oncoanalyser can be skipped using `--processes_exclude` (the full list of available -processes can be view [here](https://github.com/nf-core/oncoanalyser/blob/0.4.5/lib/Constants.groovy#L36-L56)). +processes can be view [here](https://github.com/nf-core/oncoanalyser/blob/1.0.0/lib/Constants.groovy#L36-L56)). Multiple processes can be given as a comma-separated list. While there are some use-cases for this feature (e.g. skipping resource intensive processes such as VIRUSBreakend), it becomes more powerful when combined with existing inputs as described in the following section. @@ -271,7 +271,7 @@ And now run and skip variant calling: ```bash nextflow run nf-core/oncoanalyser \ -profile docker \ - -revision 0.4.5 \ + -revision 1.0.0 \ --mode wgts \ --processes_exclude markdups,amber,cobalt,gridss,gripss,sage,pave \ --genome GRCh38_hmf \ @@ -341,7 +341,7 @@ P1__wgts,P1,SC,tumor,rna,bam,/path/to/P1.SC.tumor.rna.wts.bam ```bash nextflow run nf-core/oncoanalyser \ -profile docker \ - -revision 0.4.5 \ + -revision 1.0.0 \ --mode wgts \ --genome GRCh38_hmf \ --prepare_reference_only \ @@ -350,7 +350,7 @@ nextflow run nf-core/oncoanalyser \ ``` Executing the above command will download and unpack default reference data without running any analysis, and once -complete the prepared reference files can found in `./prepare_reference/reference_data/0.4.5//`. It is +complete the prepared reference files can found in `./prepare_reference/reference_data/1.0.0//`. It is recommended to remove the Nextflow work directory after staging data to free disk space. For oncoanalyser to use locally staged reference data a custom config can be used: @@ -442,7 +442,7 @@ config file. This avoids having to regenerate indexes for each new analysis. ```bash nextflow run nf-core/oncoanalyser \ -profile docker \ - -revision 0.4.5 \ + -revision 1.0.0 \ -config genome.custom.config \ --mode wgts \ \ diff --git a/nextflow.config b/nextflow.config index 656b89bb..dd58e5d8 100644 --- a/nextflow.config +++ b/nextflow.config @@ -292,7 +292,7 @@ manifest { description = """A comprehensive cancer DNA/RNA analysis and reporting pipeline""" mainScript = 'main.nf' nextflowVersion = '!>=22.10.5' - version = '0.3.1' + version = '1.0.0' doi = '' } From be33799f0ce0e8b7e28550d18156d70c95c4467b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 29 May 2024 10:24:38 +1000 Subject: [PATCH 504/562] Fix usage.md MarkDups link --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 0514d59d..57d0de04 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -80,7 +80,7 @@ P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tum Inputs with the `bam` filetype will be processed by MarkDups as required by hmftools. Where an input BAM has already been processed specifically by [HMF -MarkDups](https://github.com/hartwigmedical/hmftools/blob/master/mark-dups/README.md), you can avoid needless +MarkDups](https://github.com/hartwigmedical/hmftools/blob/mark-dups-v1.1.5/mark-dups/README.md), you can avoid needless reprocessing by setting `bam_markdups` as the filetype instead. It is important to understand that duplicate marking by other tools (e.g. GATK) cannot be used as a substitute since HMF MarkDups performs key operations beyond just duplicate marking. From 177a26f2bc0a7df8d0953ae74e8a612c0ee9215d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 31 May 2024 20:12:34 +1000 Subject: [PATCH 505/562] Bump MarkDups to 1.1.7 --- modules/local/markdups/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 42c10394..649f85a3 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -3,8 +3,8 @@ process MARKDUPS { label 'process_medium' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.5--hdfd78af_1' : - 'biocontainers/hmftools-mark-dups:1.1.5--hdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.7--hdfd78af_0' : + 'biocontainers/hmftools-mark-dups:1.1.7--hdfd78af_0' }" input: tuple val(meta), path(bams), path(bais) From 8d19bff32d37574f3801bc2a518a0ee61bc8eda6 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 31 May 2024 20:14:26 +1000 Subject: [PATCH 506/562] Update README.md known issues section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cbce0809..926ca174 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ in the below table. ## Known issues -- MarkDups may encounter a fatal error processing hard-clipped supplementary alignments ([#37](https://github.com/nf-core/oncoanalyser/issues/37)) +There are currently no known issues. ## Credits From 85765b1b1ab75fea09c8d98ddec610d23879c064 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Mon, 3 Jun 2024 18:39:24 +1000 Subject: [PATCH 507/562] Quote absolute paths used in directory shadowing --- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/main.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index d205b09f..08bdb91e 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -58,7 +58,7 @@ process GRIDSS_ASSEMBLE { # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers symlinkpath=\$(realpath \${filepath_src}) - ln -s \${symlinkpath} \${filepath_dst}; + ln -s "\${symlinkpath}" \${filepath_dst}; done if [[ -L "\${src##*/}" ]]; then rm "\${src}" diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index ef28f83a..3cbb62c4 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -58,7 +58,7 @@ process GRIDSS_CALL { # NOTE(SW): ideally we would get the relative path using the --relative-to but this is only # supported for GNU realpath and fails for others such as BusyBox, which is used in Biocontainers symlinkpath=\$(realpath \${filepath_src}) - ln -s \${symlinkpath} \${filepath_dst}; + ln -s "\${symlinkpath}" \${filepath_dst}; done if [[ -L "\${src##*/}" ]]; then rm "\${src}" From fc04fef2be92d8eb4e94f865fa12576ea382d072 Mon Sep 17 00:00:00 2001 From: Cassie Litchfield Date: Tue, 4 Jun 2024 15:42:24 +0200 Subject: [PATCH 508/562] symlink specific gridss index files genome_gridss_index folder may contain additional files that are staged by nextflow if they are part of the inputs (e.g. someone might have the .dict file in this folder if they created it via gridss.PrepareReference). This causes an error when we try to symlink the entire contents of the folder. Could we change this line to symlink the specific files of interest? --- modules/local/virusbreakend/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index d7056d6f..6aee96f7 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -29,7 +29,7 @@ process VIRUSBREAKEND { """ # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -type f) ./ + ln -s \$(find -L ${genome_gridss_index} -type f -name *.gridsscache -o -name *.img) ./ virusbreakend \\ ${args} \\ From fb49fd0b2eb73c065d7ab888a12a37f497eca8d5 Mon Sep 17 00:00:00 2001 From: casslitch Date: Wed, 5 Jun 2024 11:10:18 +0200 Subject: [PATCH 509/562] Explicitly define all gridss index files to be symlinked Accomodates users using externally created GRIDSS indexes that may contain clashing file names. --- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/preprocess/main.nf | 2 +- modules/local/virusbreakend/main.nf | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 08bdb91e..0ef0cf36 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -69,7 +69,7 @@ process GRIDSS_ASSEMBLE { done # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -type f) ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwa\|img\|alt\)') ./ # Run gridss_svprep \\ diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 3cbb62c4..fd0121d8 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -67,7 +67,7 @@ process GRIDSS_CALL { shadow_input_directory ${assemble_dir} # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -type f) ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwa\|img\|alt\)') ./ # Run gridss_svprep \\ diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index ed3f3430..cd9ee75c 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -29,7 +29,7 @@ process GRIDSS_PREPROCESS { """ # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -type f) ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwa\|img\|alt\)') ./ gridss_svprep \\ ${args} \\ diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 6aee96f7..9384ca22 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -29,7 +29,7 @@ process VIRUSBREAKEND { """ # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -type f -name *.gridsscache -o -name *.img) ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwa\|img\|alt\)') ./ virusbreakend \\ ${args} \\ From 296f5d83d89a5cbfe4ad67c6ac10153af24f63b9 Mon Sep 17 00:00:00 2001 From: casslitch Date: Wed, 5 Jun 2024 14:16:36 +0200 Subject: [PATCH 510/562] Fixed typo in find command --- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/preprocess/main.nf | 2 +- modules/local/virusbreakend/main.nf | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 0ef0cf36..bdcf88a0 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -69,7 +69,7 @@ process GRIDSS_ASSEMBLE { done # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwa\|img\|alt\)') ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwt\|img\|alt\)') ./ # Run gridss_svprep \\ diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index fd0121d8..5afcac73 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -67,7 +67,7 @@ process GRIDSS_CALL { shadow_input_directory ${assemble_dir} # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwa\|img\|alt\)') ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwt\|img\|alt\)') ./ # Run gridss_svprep \\ diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index cd9ee75c..ffc1200e 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -29,7 +29,7 @@ process GRIDSS_PREPROCESS { """ # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwa\|img\|alt\)') ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwt\|img\|alt\)') ./ gridss_svprep \\ ${args} \\ diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 9384ca22..225e26b0 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -29,7 +29,7 @@ process VIRUSBREAKEND { """ # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwa\|img\|alt\)') ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwt\|img\|alt\)') ./ virusbreakend \\ ${args} \\ From d0a920f9a0d7fea27abfcb2a595728b5170a1780 Mon Sep 17 00:00:00 2001 From: casslitch Date: Wed, 5 Jun 2024 16:22:45 +0200 Subject: [PATCH 511/562] Fixed regex string in find command Escaped back-slashes. --- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/preprocess/main.nf | 2 +- modules/local/virusbreakend/main.nf | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index bdcf88a0..8d18a515 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -69,7 +69,7 @@ process GRIDSS_ASSEMBLE { done # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwt\|img\|alt\)') ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\\.\\(amb\\|ann\\|pac\\|gridsscache\\|sa\\|bwt\\|img\\|alt\\)') ./ # Run gridss_svprep \\ diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 5afcac73..775df9c6 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -67,7 +67,7 @@ process GRIDSS_CALL { shadow_input_directory ${assemble_dir} # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwt\|img\|alt\)') ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\\.\\(amb\\|ann\\|pac\\|gridsscache\\|sa\\|bwt\\|img\\|alt\\)') ./ # Run gridss_svprep \\ diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index ffc1200e..c3313ee8 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -29,7 +29,7 @@ process GRIDSS_PREPROCESS { """ # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwt\|img\|alt\)') ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\\.\\(amb\\|ann\\|pac\\|gridsscache\\|sa\\|bwt\\|img\\|alt\\)') ./ gridss_svprep \\ ${args} \\ diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 225e26b0..93f90c1f 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -29,7 +29,7 @@ process VIRUSBREAKEND { """ # Symlink indices next to assembly FASTA - ln -s \$(find -L ${genome_gridss_index} -regex '.*\.\(amb\|ann\|pac\|gridsscache\|sa\|bwt\|img\|alt\)') ./ + ln -s \$(find -L ${genome_gridss_index} -regex '.*\\.\\(amb\\|ann\\|pac\\|gridsscache\\|sa\\|bwt\\|img\\|alt\\)') ./ virusbreakend \\ ${args} \\ From e85c08176a137ae49a19095aa52fe0a1316f8a60 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 6 Jun 2024 13:58:31 +1000 Subject: [PATCH 512/562] Add BAI placeholder in read processing out channel --- workflows/targeted.nf | 4 ++-- workflows/wgts.nf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/workflows/targeted.nf b/workflows/targeted.nf index c6193c2f..6c056ab2 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -170,8 +170,8 @@ workflow TARGETED { } else { - ch_process_dna_tumor_out = ch_inputs.map { meta -> [meta, []] } - ch_process_dna_normal_out = ch_inputs.map { meta -> [meta, []] } + ch_process_dna_tumor_out = ch_inputs.map { meta -> [meta, [], []] } + ch_process_dna_normal_out = ch_inputs.map { meta -> [meta, [], []] } } diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 188ff68c..27e729ce 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -176,8 +176,8 @@ workflow WGTS { } else { - ch_process_dna_tumor_out = ch_inputs.map { meta -> [meta, []] } - ch_process_dna_normal_out = ch_inputs.map { meta -> [meta, []] } + ch_process_dna_tumor_out = ch_inputs.map { meta -> [meta, [], []] } + ch_process_dna_normal_out = ch_inputs.map { meta -> [meta, [], []] } } From 9c81e3e0ca740024e1d88f4c15b280b17b2ef666 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 7 Jun 2024 14:39:09 +1000 Subject: [PATCH 513/562] Bump AMBER to 4.0.1 --- modules/local/amber/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/amber/main.nf b/modules/local/amber/main.nf index df181414..84b33026 100644 --- a/modules/local/amber/main.nf +++ b/modules/local/amber/main.nf @@ -4,8 +4,8 @@ process AMBER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-amber:4.0--hdfd78af_0' : - 'biocontainers/hmftools-amber:4.0--hdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/hmftools-amber:4.0.1--hdfd78af_0' : + 'biocontainers/hmftools-amber:4.0.1--hdfd78af_0' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) From 15a981048fa6a523d4fd4f7b159f76d49bad66b5 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 12 Jun 2024 13:26:37 +1000 Subject: [PATCH 514/562] Bump SAGE to 3.4.4 --- modules/local/sage/append/main.nf | 4 ++-- modules/local/sage/germline/main.nf | 4 ++-- modules/local/sage/somatic/main.nf | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/local/sage/append/main.nf b/modules/local/sage/append/main.nf index 98b4561e..a00d96d1 100644 --- a/modules/local/sage/append/main.nf +++ b/modules/local/sage/append/main.nf @@ -4,8 +4,8 @@ process SAGE_APPEND { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4.3--hdfd78af_0' : - 'biocontainers/hmftools-sage:3.4.3--hdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4.4--hdfd78af_0' : + 'biocontainers/hmftools-sage:3.4.4--hdfd78af_0' }" input: tuple val(meta), path(vcf), path(bam), path(bai) diff --git a/modules/local/sage/germline/main.nf b/modules/local/sage/germline/main.nf index 3e0eb1bc..a79155e3 100644 --- a/modules/local/sage/germline/main.nf +++ b/modules/local/sage/germline/main.nf @@ -4,8 +4,8 @@ process SAGE_GERMLINE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4.3--hdfd78af_0' : - 'biocontainers/hmftools-sage:3.4.3--hdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4.4--hdfd78af_0' : + 'biocontainers/hmftools-sage:3.4.4--hdfd78af_0' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) diff --git a/modules/local/sage/somatic/main.nf b/modules/local/sage/somatic/main.nf index 787fcb5e..fc7f282c 100644 --- a/modules/local/sage/somatic/main.nf +++ b/modules/local/sage/somatic/main.nf @@ -6,8 +6,8 @@ process SAGE_SOMATIC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4.3--hdfd78af_0' : - 'biocontainers/hmftools-sage:3.4.3--hdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/hmftools-sage:3.4.4--hdfd78af_0' : + 'biocontainers/hmftools-sage:3.4.4--hdfd78af_0' }" input: tuple val(meta), path(tumor_bam), path(normal_bam), path(tumor_bai), path(normal_bai) From 3a701ec235804cdcfb36855209f958b402ecbe75 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 13 Jun 2024 13:03:43 +1000 Subject: [PATCH 515/562] Correct MarkDups version in Conda env and docs URL --- docs/usage.md | 2 +- modules/local/markdups/environment.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 57d0de04..d0677b8f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -80,7 +80,7 @@ P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tum Inputs with the `bam` filetype will be processed by MarkDups as required by hmftools. Where an input BAM has already been processed specifically by [HMF -MarkDups](https://github.com/hartwigmedical/hmftools/blob/mark-dups-v1.1.5/mark-dups/README.md), you can avoid needless +MarkDups](https://github.com/hartwigmedical/hmftools/blob/mark-dups-v1.1.7/mark-dups/README.md), you can avoid needless reprocessing by setting `bam_markdups` as the filetype instead. It is important to understand that duplicate marking by other tools (e.g. GATK) cannot be used as a substitute since HMF MarkDups performs key operations beyond just duplicate marking. diff --git a/modules/local/markdups/environment.yml b/modules/local/markdups/environment.yml index b910e500..9fa2cb52 100644 --- a/modules/local/markdups/environment.yml +++ b/modules/local/markdups/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-mark-dups=1.1.5=hdfd78af_1 + - bioconda::hmftools-mark-dups=1.1.7 From c0b8155fc5a6eca005c7e76c5f370e6a54794825 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 19 Jun 2024 18:10:34 +1000 Subject: [PATCH 516/562] Add type for isofox_read_length in schema --- nextflow_schema.json | 1 + 1 file changed, 1 insertion(+) diff --git a/nextflow_schema.json b/nextflow_schema.json index b3454340..82b3f6cb 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -98,6 +98,7 @@ "fa_icon": "fas fa-cog" }, "isofox_read_length": { + "type": "integer", "description": "User defined RNA read length used for Isofox.", "fa_icon": "fas fa-cog" }, From ecbf5403698dc0ee9c51e5974ef20d616ab8b3f3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 5 Jul 2024 11:42:43 +1000 Subject: [PATCH 517/562] Include 1.0.0 version in release parity table --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 926ca174..994263c5 100644 --- a/README.md +++ b/README.md @@ -111,14 +111,14 @@ Versions nominated to have current long-term support: ### Release parity -Versioning between oncoanalyser and hmftools naturally differ, however it is often necessary to relate the functional +Versioning between `oncoanalyser` and hmftools naturally differ, however it is often necessary to relate the functional equivalence of these two pieces of software. The functional/feature parity with regards to version releases are detailed in the below table. | oncoanalyser | hmftools | | ------------------- | -------- | | 0.1.0 through 0.2.7 | 5.33 | -| 0.3.0 through 0.4.5 | 5.34 | +| 0.3.0 through 1.0.0 | 5.34 | ## Known issues From d36f8b059743d421ad864cfbbc2378029edcba00 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 5 Jul 2024 11:43:20 +1000 Subject: [PATCH 518/562] Remove TODO in methods_description_template.yml --- assets/methods_description_template.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml index 6bb8cb5b..822724fb 100644 --- a/assets/methods_description_template.yml +++ b/assets/methods_description_template.yml @@ -3,8 +3,6 @@ description: "Suggested text and references to use when describing pipeline usag section_name: "nf-core/oncoanalyser Methods Description" section_href: "https://github.com/nf-core/oncoanalyser" plot_type: "html" -## TODO nf-core: Update the HTML below to your preferred methods description, e.g. add publication citation for this pipeline -## You inject any metadata in the Nextflow '${workflow}' object data: |

    Methods

    From dcf919e8d87426860d027e7fa8a8729b23ef10c5 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 5 Jul 2024 11:43:41 +1000 Subject: [PATCH 519/562] Adjust filepaths in assets/samplesheet.csv --- assets/samplesheet.csv | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 157d28bf..1a8d4b39 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,12 +1,12 @@ group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath -subject_one__to__dna,subject_one,sample_a,tumor,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.tumor.bam +subject_one__to__dna,subject_one,sample_a,tumor,dna,bam,/path/to/subject_one/sample_a.tumor.bam -subject_one__tn__dna,subject_one,sample_a,tumor,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.tumor.bam -subject_one__tn__dna,subject_one,sample_b,normal,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_b.normal.bam +subject_one__tn__dna,subject_one,sample_a,tumor,dna,bam,/path/to/subject_one/sample_a.tumor.bam +subject_one__tn__dna,subject_one,sample_b,normal,dna,bam,/path/to/subject_one/sample_b.normal.bam -subject_one__tn__dna_rna,subject_one,sample_a,tumor,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.tumor.bam -subject_one__tn__dna_rna,subject_one,sample_b,normal,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_b.normal.bam -subject_one__tn__dna_rna,subject_one,sample_c,tumor,rna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_c.tumor_rna.bam +subject_one__tn__dna_rna,subject_one,sample_a,tumor,dna,bam,/path/to/subject_one/sample_a.tumor.bam +subject_one__tn__dna_rna,subject_one,sample_b,normal,dna,bam,/path/to/subject_one/sample_b.normal.bam +subject_one__tn__dna_rna,subject_one,sample_c,tumor,rna,bam,/path/to/subject_one/sample_c.tumor_rna.bam -subject_one__to__dna_rna,subject_one,sample_a,tumor,dna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_a.tumor.bam -subject_one__to__dna_rna,subject_one,sample_c,tumor,rna,bam,/Users/stephen/repos/oncoanalyser/subject_one/sample_c.tumor_rna.bam +subject_one__to__dna_rna,subject_one,sample_a,tumor,dna,bam,/path/to/subject_one/sample_a.tumor.bam +subject_one__to__dna_rna,subject_one,sample_c,tumor,rna,bam,/path/to/subject_one/sample_c.tumor_rna.bam From dd4f868e81c2c4ba29b2d7661da15592b32ce72c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 5 Jul 2024 11:44:12 +1000 Subject: [PATCH 520/562] Simplify target parameter definitions --- conf/targeted_parameters.config | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/conf/targeted_parameters.config b/conf/targeted_parameters.config index bb4899e7..c02575be 100644 --- a/conf/targeted_parameters.config +++ b/conf/targeted_parameters.config @@ -1,6 +1,4 @@ -process.'withName:^.*:COBALT_PROFILING:COBALT'.ext.args = [ - '-pcf_gamma 50', -].join(' ').trim() +process.'withName:^.*:COBALT_PROFILING:COBALT'.ext.args = '-pcf_gamma 50' process.'withName:^.*:SAGE_CALLING:SOMATIC'.ext.args = [ '-high_depth_mode', From 882cb6c68f4060da3307cb6b70da27ca27f1c51e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 5 Jul 2024 11:44:58 +1000 Subject: [PATCH 521/562] Fix templated version in usage.md --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index d0677b8f..9cbcb2a0 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -214,7 +214,7 @@ nextflow pull nf-core/oncoanalyser It is a good idea to specify a pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. -First, go to the [nf-core/oncoanalyser releases page](https://github.com/nf-core/oncoanalyser/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. +First, go to the [nf-core/oncoanalyser releases page](https://github.com/nf-core/oncoanalyser/releases) and find the latest pipeline version - numeric only (eg. `1.0.0`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.0.0`. Of course, you can switch to another version by changing the number after the `-r` flag. This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. From 204d75bfd8981922ef8e763101ccf4f779139a59 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 5 Jul 2024 11:46:15 +1000 Subject: [PATCH 522/562] Fix grammar and clarify usage.md --- docs/usage.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 9cbcb2a0..fbbb7a0f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -229,7 +229,7 @@ If you wish to share such profile (such as upload as supplementary material for ### Selecting processes Most of the major components in oncoanalyser can be skipped using `--processes_exclude` (the full list of available -processes can be view [here](https://github.com/nf-core/oncoanalyser/blob/1.0.0/lib/Constants.groovy#L36-L56)). +processes can be viewed [here](https://github.com/nf-core/oncoanalyser/blob/1.0.0/lib/Constants.groovy#L36-L56)). Multiple processes can be given as a comma-separated list. While there are some use-cases for this feature (e.g. skipping resource intensive processes such as VIRUSBreakend), it becomes more powerful when combined with existing inputs as described in the following section. @@ -243,10 +243,11 @@ processes. ### Existing inputs -The oncoanalyser pipeline has been designed to allow entry at arbitrary points, which is particularly useful in -situations where previous outputs exist and re-running oncoanalyser is desired (e.g. to subsequently execute an -optional sensor or use an upgrade component such as PURPLE). The primary advantage of this approach is that only the -required processes are executed, reducing costs and runtimes by skipping unnecessary processes. +The `oncoanalyser` pipeline has been designed to allow entry at arbitrary points, which is particularly useful in +situations where previous outputs exist and re-running `oncoanalyser` is desired (e.g. to subsequently execute an +optional sensor/workflow or re-run an analysis with an upgraded tool such as PURPLE). The primary advantage of this +approach is that only the required processes are executed, reducing costs and runtimes by skipping unnecessary +processes. In order to effectively utilise this feature, existing inputs must be set in the [samplesheet](#samplesheet) and the appropriate [processes selected](#selecting-processes). Take the below example where existing PURPLE inputs are used so From 02431cae8e79bcec9f1ab6aadd9a748a5fd7badd Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 5 Jul 2024 11:48:58 +1000 Subject: [PATCH 523/562] Add backticks to in text usage of oncoanalyser --- README.md | 10 +++++----- docs/output.md | 4 ++-- docs/usage.md | 36 ++++++++++++++++++------------------ 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 994263c5..f0e49dc0 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ For detailed information on each component of the Hartwig workflow, please refer ## Pipeline summary -The following processes and tools can be run with oncoanalyser: +The following processes and tools can be run with `oncoanalyser`: - Simple DNA/RNA alignment (`bwa-mem2`, `STAR`) - Post-alignment processing (`MarkDups`, `Picard MarkDuplicates`) @@ -69,7 +69,7 @@ P1__wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/SB.tumor. P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/SC.tumor.rna.wts.001.R1.fastq.gz;/path/to/SC.tumor.rna.wts.001.R2.fastq.gz ``` -Launch oncoanalyser: +Launch `oncoanalyser`: ```bash nextflow run nf-core/oncoanalyser \ @@ -96,7 +96,7 @@ For more details about the output files and reports, please refer to the ### Extended support -As oncoanalyser is used in clinical settings and subject to accreditation standards in some instances, there is a need +As `oncoanalyser` is used in clinical settings and subject to accreditation standards in some instances, there is a need for long-term stability and reliability for feature releases in order to meet operational requirements. This is accomplished through long-term support of several nominated feature releases, which all receive bug fixes and security fixes during the period of extended support. @@ -126,7 +126,7 @@ There are currently no known issues. ## Credits -The oncoanalyser pipeline was written by Stephen Watts while in the [Genomics Platform +The `oncoanalyser` pipeline was written by Stephen Watts while in the [Genomics Platform Group](https://mdhs.unimelb.edu.au/centre-for-cancer-research/our-research/genomics-platform-group) at the [University of Melbourne Centre for Cancer Research](https://mdhs.unimelb.edu.au/centre-for-cancer-research). @@ -146,7 +146,7 @@ channel](https://nfcore.slack.com/channels/oncoanalyser) (you can join with [thi ## Citations -You can cite the oncoanalyser zenodo record for a specific version using the following doi: +You can cite the `oncoanalyser` zenodo record for a specific version using the following doi: [10.5281/zenodo.XXXXXXX](https://doi.org/10.5281/zenodo.XXXXXXX) An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) diff --git a/docs/output.md b/docs/output.md index e2a75b72..d1cdfb15 100644 --- a/docs/output.md +++ b/docs/output.md @@ -78,13 +78,13 @@ output/ ### Simple DNA/RNA alignment -Alignment functionality in oncoanalyser is simple and rigid, and exists only to meet the exact requirements of the +Alignment functionality in `oncoanalyser` is simple and rigid, and exists only to meet the exact requirements of the hmftools. #### bwa-mem2 [bwa-mem2](https://github.com/bwa-mem2/bwa-mem2) is a short-read mapping tool used to align reads to a large reference -sequences. In oncoanalyser, bwa-mem2 is used to align DNA reads to the human genome. +sequences. In `oncoanalyser`, bwa-mem2 is used to align DNA reads to the human genome. _No outputs are published directly from bwa-mem2, see [MarkDups](#markdups) for the fully processed alignment outputs_ diff --git a/docs/usage.md b/docs/usage.md index fbbb7a0f..ebc975ba 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -6,20 +6,20 @@ ## Introduction -The oncoanalyser pipeline typically runs from FASTQs or BAMs and supports two modes: (1) whole genome and/or +The `oncoanalyser` pipeline typically runs from FASTQs or BAMs and supports two modes: (1) whole genome and/or transcriptome, and (2) targeted panel. Launching an analysis requires only the creation of a samplesheet that describes details of each input such as the sample type (tumor or normal), sequence type (DNA or RNA), and filepath. -Various aspects of an oncoanalyser analysis can be configured to fit a range of needs, and many of these are considered -[advanced usage](#advanced-usage) of the pipeline. The most useful include: +Various aspects of an `oncoanalyser` analysis can be configured to fit a range of needs, and many of these are +considered [advanced usage](#advanced-usage) of the pipeline. The most useful include: - precise process selection - starting from existing data - granular control over reference/resource files -These features enable oncoanalyser to be run in a highly flexible way. For example, an analysis can be run with existing -PURPLE data as the starting point and skip variant calling processes. Additionally, reference/resource files can be -staged locally to optimise execution or modified to create user-defined driver gene panels. +These features enable `oncoanalyser` to be run in a highly flexible way. For example, an analysis can be run with +existing PURPLE data as the starting point and skip variant calling processes. Additionally, reference/resource files +can be staged locally to optimise execution or modified to create user-defined driver gene panels. :::danger @@ -35,7 +35,7 @@ When starting from BAMs rather than FASTQ it is expected that: ## Supported analyses -A variety of analyses are accessible in oncoanalyser and are implicitly run according to the data described in the +A variety of analyses are accessible in `oncoanalyser` and are implicitly run according to the data described in the samplesheet. The supported analysis types for each workflow are listed below. | Input sequence data | WGS/WTS workflow | Targeted sequencing workflow\* | @@ -50,7 +50,7 @@ samplesheet. The supported analysis types for each workflow are listed below. ## Samplesheet -A samplesheet that contains information of each input in CSV format is needed to run oncoanalyser. The required input +A samplesheet that contains information of each input in CSV format is needed to run `oncoanalyser`. The required input details and columns are [described below](#column-descriptions). Several different input filetypes beyond FASTQ and BAM are recognised, including intermediate output files generated @@ -157,7 +157,7 @@ This will launch the pipeline with the `docker` configuration profile. See below :::note -Reference data will be retrieved by oncoanalyser for every analysis run. It is therefore strongly recommended when +Reference data will be retrieved by `oncoanalyser` for every analysis run. It is therefore strongly recommended when running multiple analyses to pre-stage reference data locally to avoid it being retrieved multiple times. See [Staging reference data](#staging-reference-data). @@ -228,7 +228,7 @@ If you wish to share such profile (such as upload as supplementary material for ### Selecting processes -Most of the major components in oncoanalyser can be skipped using `--processes_exclude` (the full list of available +Most of the major components in `oncoanalyser` can be skipped using `--processes_exclude` (the full list of available processes can be viewed [here](https://github.com/nf-core/oncoanalyser/blob/1.0.0/lib/Constants.groovy#L36-L56)). Multiple processes can be given as a comma-separated list. While there are some use-cases for this feature (e.g. skipping resource intensive processes such as VIRUSBreakend), it becomes more powerful when combined with existing @@ -262,7 +262,7 @@ P1__wgts,P1,SB,tumor,dna,purple_dir,/path/to/P1.purple_dir/ :::note -The original source input file (i.e. BAM or FASTQ) must always be provided for oncoanalyser to infer the correct +The original source input file (i.e. BAM or FASTQ) must always be provided for `oncoanalyser` to infer the correct analysis type. ::: @@ -282,7 +282,7 @@ nextflow run nf-core/oncoanalyser \ :::warning -Providing existing inputs will cause oncoanalyser to skip the corresponding process but _not any_ of the upstream +Providing existing inputs will cause `oncoanalyser` to skip the corresponding process but _not any_ of the upstream processes. It is the responsibility of the user to skip all relevant processes. ::: @@ -316,7 +316,7 @@ params { } ``` -To use these hmftools resource file overrides in oncoanalyser the local bundle directory must be provided with +To use these hmftools resource file overrides in `oncoanalyser` the local bundle directory must be provided with `--ref_data_hmf_data_path`. #### Customise other data @@ -327,8 +327,8 @@ for the complete list. #### Staging reference data -Default reference data can be staged locally with oncoanalyser by providing a samplesheet for the desired analysis and -setting the `--prepare_reference_only` argument. The samplesheet and oncoanalyser configuration will determine the +Default reference data can be staged locally with `oncoanalyser` by providing a samplesheet for the desired analysis and +setting the `--prepare_reference_only` argument. The samplesheet and `oncoanalyser` configuration will determine the relevant reference data to download. For example the following command will download the `GRCh38_hmf` genome plus indices, reference data, and databases required to run a WGTS analysis for tumor/normal DNA with tumor RNA: @@ -354,7 +354,7 @@ Executing the above command will download and unpack default reference data with complete the prepared reference files can found in `./prepare_reference/reference_data/1.0.0//`. It is recommended to remove the Nextflow work directory after staging data to free disk space. -For oncoanalyser to use locally staged reference data a custom config can be used: +For `oncoanalyser` to use locally staged reference data a custom config can be used: ```text title="refdata.local.config" params { @@ -429,13 +429,13 @@ params { } ``` -Each index required for the analysis will first be created before running the rest of oncoanalyser with the following +Each index required for the analysis will first be created before running the rest of `oncoanalyser` with the following command: :::note In a process similar to [staging reference data](#staging-reference-data), you can first generate the required indexes -by setting `--prepare_reference_only` and then provide the prepared reference files to oncoanalyser through a custom +by setting `--prepare_reference_only` and then provide the prepared reference files to `oncoanalyser` through a custom config file. This avoids having to regenerate indexes for each new analysis. ::: From bbf66f6c46ac8aa20d022cd8e68c453ff05ec71e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 5 Jul 2024 11:59:48 +1000 Subject: [PATCH 524/562] Update .bumpversion.cfg --- .bumpversion.cfg | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index eb4c5b1c..079dcdaa 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -9,5 +9,17 @@ search = version = '{current_version}' replace = version = '{new_version}' [bumpversion:file:README.md] -search = -revision v{current_version} -replace = -revision v{new_version} +search = -revision {current_version} +replace = -revision {new_version} + +[bumpversion:file (example commands):docs/usage.md] +search = -revision {current_version} +replace = -revision {new_version} + +[bumpversion:file (urls):docs/usage.md] +search = /{current_version}/ +replace = /{new_version}/ + +[bumpversion:file (templated example):docs/usage.md] +search = {current_version}` +replace = {new_version}` From 8479d6959b13f185b8ccfe2ba291770d30d88d9d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 11 Jul 2024 09:09:22 +1000 Subject: [PATCH 525/562] Do not use hardcoded absolute path for ref genomes --- conf/hmf_genomes.config | 24 ++++++++++++------------ nextflow.config | 2 ++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/conf/hmf_genomes.config b/conf/hmf_genomes.config index 1e2998f8..0e4a6aa5 100644 --- a/conf/hmf_genomes.config +++ b/conf/hmf_genomes.config @@ -10,20 +10,20 @@ params { genomes { 'GRCh37_hmf' { - fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/Homo_sapiens.GRCh37.GATK.illumina.fasta" - fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" - dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" - bwamem2_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/bwa-mem2_index/2.2.1.tar.gz" - gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.1/gridss_index/2.13.2.tar.gz" - star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh37_hmf/24.0/star_index/gencode_19/2.7.3a.tar.gz" + fasta = "${params.hmf_genome_base}/GRCh37_hmf/24.0/Homo_sapiens.GRCh37.GATK.illumina.fasta" + fai = "${params.hmf_genome_base}/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.fai" + dict = "${params.hmf_genome_base}/GRCh37_hmf/24.0/samtools_index/1.16/Homo_sapiens.GRCh37.GATK.illumina.fasta.dict" + bwamem2_index = "${params.hmf_genome_base}/GRCh37_hmf/24.1/bwa-mem2_index/2.2.1.tar.gz" + gridss_index = "${params.hmf_genome_base}/GRCh37_hmf/24.1/gridss_index/2.13.2.tar.gz" + star_index = "${params.hmf_genome_base}/GRCh37_hmf/24.0/star_index/gencode_19/2.7.3a.tar.gz" } 'GRCh38_hmf' { - fasta = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" - fai = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" - dict = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" - bwamem2_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/bwa-mem2_index/2.2.1.tar.gz" - gridss_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.1/gridss_index/2.13.2.tar.gz" - star_index = "https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes/GRCh38_hmf/24.0/star_index/gencode_38/2.7.3a.tar.gz" + fasta = "${params.hmf_genome_base}/GRCh38_hmf/24.0/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna" + fai = "${params.hmf_genome_base}/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.fai" + dict = "${params.hmf_genome_base}/GRCh38_hmf/24.0/samtools_index/1.16/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.dict" + bwamem2_index = "${params.hmf_genome_base}/GRCh38_hmf/24.1/bwa-mem2_index/2.2.1.tar.gz" + gridss_index = "${params.hmf_genome_base}/GRCh38_hmf/24.1/gridss_index/2.13.2.tar.gz" + star_index = "${params.hmf_genome_base}/GRCh38_hmf/24.0/star_index/gencode_38/2.7.3a.tar.gz" } } } diff --git a/nextflow.config b/nextflow.config index dd58e5d8..21529327 100644 --- a/nextflow.config +++ b/nextflow.config @@ -25,6 +25,7 @@ params { force_genome = false igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = true + hmf_genome_base = 'https://pub-cf6ba01919994c3cbd354659947f74d8.r2.dev/genomes' // Other reference data and config exposed to user on CLI max_fastq_records = 10000000 @@ -73,6 +74,7 @@ params { 'genome_type', 'genome_version', 'genomes', + 'hmf_genome_base', 'hmf_data_paths', 'panel', 'panel_data_paths', From 1fc84ed1dc433b4d00682d9f4ec5bef831baa26b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 11 Jul 2024 09:55:36 +1000 Subject: [PATCH 526/562] Remove obsolete NOTE --- workflows/targeted.nf | 1 - 1 file changed, 1 deletion(-) diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 6c056ab2..ab1c4460 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -148,7 +148,6 @@ workflow TARGETED { ch_process_dna_normal_out = Channel.empty() if (run_config.stages.markdups) { - // NOTE(SW/MC): hardcoded for initial testing purposes has_umis = run_config.panel.equalsIgnoreCase('tso500') READ_PROCESSING( From 3a15fb9d6f0c1e344d29aa5084085c8396a3bf5b Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 11 Jul 2024 09:38:49 +1000 Subject: [PATCH 527/562] Use more consistent SAGE calling subworkflow args --- subworkflows/local/sage_calling/main.nf | 2 +- workflows/targeted.nf | 2 +- workflows/wgts.nf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subworkflows/local/sage_calling/main.nf b/subworkflows/local/sage_calling/main.nf index 35a44d97..9cc81222 100644 --- a/subworkflows/local/sage_calling/main.nf +++ b/subworkflows/local/sage_calling/main.nf @@ -20,8 +20,8 @@ workflow SAGE_CALLING { genome_version // channel: [mandatory] genome version genome_fai // channel: [mandatory] /path/to/genome_fai genome_dict // channel: [mandatory] /path/to/genome_dict - sage_known_hotspots_germline // channel: [optional] /path/to/sage_known_hotspots_germline sage_known_hotspots_somatic // channel: [mandatory] /path/to/sage_known_hotspots_somatic + sage_known_hotspots_germline // channel: [optional] /path/to/sage_known_hotspots_germline sage_actionable_panel // channel: [mandatory] /path/to/sage_actionable_panel sage_coverage_panel // channel: [mandatory] /path/to/sage_coverage_panel sage_highconf_regions // channel: [mandatory] /path/to/sage_highconf_regions diff --git a/workflows/targeted.nf b/workflows/targeted.nf index ab1c4460..f0b5649d 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -351,8 +351,8 @@ workflow TARGETED { ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, - [], // sage_known_hotspots_germline hmf_data.sage_known_hotspots_somatic, + [], // sage_known_hotspots_germline panel_data.sage_actionable_panel, panel_data.sage_coverage_panel, hmf_data.sage_highconf_regions, diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 27e729ce..9facc5ac 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -356,8 +356,8 @@ workflow WGTS { ref_data.genome_version, ref_data.genome_fai, ref_data.genome_dict, - hmf_data.sage_known_hotspots_germline, hmf_data.sage_known_hotspots_somatic, + hmf_data.sage_known_hotspots_germline, hmf_data.sage_actionable_panel, hmf_data.sage_coverage_panel, hmf_data.sage_highconf_regions, From 2e37b3098e51ba2daffe0138766f84ac0992d1b1 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 11 Jul 2024 09:54:50 +1000 Subject: [PATCH 528/562] Use more readable format in targeted params config --- conf/targeted_parameters.config | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/conf/targeted_parameters.config b/conf/targeted_parameters.config index c02575be..6345042a 100644 --- a/conf/targeted_parameters.config +++ b/conf/targeted_parameters.config @@ -1,8 +1,14 @@ -process.'withName:^.*:COBALT_PROFILING:COBALT'.ext.args = '-pcf_gamma 50' +process { + withName: '^.*COBALT_PROFILING:COBALT' { + ext.args = '-pcf_gamma 50' + } -process.'withName:^.*:SAGE_CALLING:SOMATIC'.ext.args = [ - '-high_depth_mode', - '-hard_min_tumor_vaf 0.002', - '-hotspot_min_tumor_vaf 0.015', - '-panel_min_tumor_qual 150', -].join(' ').trim() + withName: '^.*:SAGE_CALLING:SOMATIC' { + ext.args = [ + '-high_depth_mode', + '-hard_min_tumor_vaf 0.002', + '-hotspot_min_tumor_vaf 0.015', + '-panel_min_tumor_qual 150', + ].join(' ').trim() + } +} From 404efef9f4acef53c62c0060d3af349ae3b99701 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 17 Jul 2024 15:01:38 +1000 Subject: [PATCH 529/562] Move GRIDSS config input to last process input pos --- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/assemble/meta.yml | 6 +++--- modules/local/svprep/call/main.nf | 2 +- modules/local/svprep/call/meta.yml | 6 +++--- modules/local/svprep/preprocess/main.nf | 2 +- modules/local/svprep/preprocess/meta.yml | 6 +++--- modules/local/virusbreakend/main.nf | 2 +- modules/local/virusbreakend/meta.yml | 6 +++--- subworkflows/local/gridss_svprep_calling/main.nf | 6 +++--- subworkflows/local/virusbreakend_calling/main.nf | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 8d18a515..4c8955b8 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -9,12 +9,12 @@ process GRIDSS_ASSEMBLE { input: tuple val(meta), path(bams), path(bams_filtered), path(preprocess_dirs), val(labels) - path gridss_config path genome_fasta path genome_fai path genome_dict path genome_gridss_index path blocklist + path gridss_config output: tuple val(meta), path('gridss_assemble/'), emit: assemble_dir diff --git a/modules/local/svprep/assemble/meta.yml b/modules/local/svprep/assemble/meta.yml index 79c2c225..1a71333d 100644 --- a/modules/local/svprep/assemble/meta.yml +++ b/modules/local/svprep/assemble/meta.yml @@ -27,9 +27,6 @@ input: - labels: type: list description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - - gridss_config: - type: file - description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly FASTA file @@ -50,6 +47,9 @@ input: type: file description: GRIDSS blocklist file pattern: "*.{bed.gz}" + - gridss_config: + type: file + description: GRIDSS configuration file (optional) output: - meta: type: map diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index 775df9c6..eeec1b5c 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -9,12 +9,12 @@ process GRIDSS_CALL { input: tuple val(meta), path(bams), path(bams_filtered), path(assemble_dir), val(labels) - path gridss_config path genome_fasta path genome_fai path genome_dict path genome_gridss_index path blocklist + path gridss_config output: tuple val(meta), path('gridss_call/sv.svprep.gridss.vcf.gz'), emit: vcf diff --git a/modules/local/svprep/call/meta.yml b/modules/local/svprep/call/meta.yml index cc8c012e..da81cdb5 100644 --- a/modules/local/svprep/call/meta.yml +++ b/modules/local/svprep/call/meta.yml @@ -27,9 +27,6 @@ input: - labels: type: list description: List of labels corresponding to BAMs and GRIDSS preprocess output directories - - gridss_config: - type: file - description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly FASTA file @@ -50,6 +47,9 @@ input: type: file description: GRIDSS blocklist file pattern: "*.{bed.gz}" + - gridss_config: + type: file + description: GRIDSS configuration file (optional) output: - meta: type: map diff --git a/modules/local/svprep/preprocess/main.nf b/modules/local/svprep/preprocess/main.nf index c3313ee8..525fa43a 100644 --- a/modules/local/svprep/preprocess/main.nf +++ b/modules/local/svprep/preprocess/main.nf @@ -9,11 +9,11 @@ process GRIDSS_PREPROCESS { input: tuple val(meta), path(bam), path(bam_filtered) - path gridss_config path genome_fasta path genome_fai path genome_dict path genome_gridss_index + path gridss_config output: tuple val(meta), path("gridss_preprocess/${meta.sample_id}.sv_prep.sorted.bam.gridss.working/"), emit: preprocess_dir diff --git a/modules/local/svprep/preprocess/meta.yml b/modules/local/svprep/preprocess/meta.yml index 017ce16a..dd63074b 100644 --- a/modules/local/svprep/preprocess/meta.yml +++ b/modules/local/svprep/preprocess/meta.yml @@ -23,9 +23,6 @@ input: type: file description: Filtered BAM file pattern: "*.{bam}" - - gridss_config: - type: file - description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly FASTA file @@ -42,6 +39,9 @@ input: type: file description: Reference genome assembly GRIDSS index file pattern: "*.{gridsscache}" + - gridss_config: + type: file + description: GRIDSS configuration file (optional) output: - meta: type: map diff --git a/modules/local/virusbreakend/main.nf b/modules/local/virusbreakend/main.nf index 93f90c1f..ae262ef8 100644 --- a/modules/local/virusbreakend/main.nf +++ b/modules/local/virusbreakend/main.nf @@ -9,12 +9,12 @@ process VIRUSBREAKEND { input: tuple val(meta), path(bam) - path gridss_config path genome_fasta path genome_fai path genome_dict path genome_gridss_index path virusbreakenddb + path gridss_config output: tuple val(meta), path("*.summary.tsv"), emit: tsv diff --git a/modules/local/virusbreakend/meta.yml b/modules/local/virusbreakend/meta.yml index 72629466..a61ff589 100644 --- a/modules/local/virusbreakend/meta.yml +++ b/modules/local/virusbreakend/meta.yml @@ -19,9 +19,6 @@ input: type: file description: BAM file pattern: "*.{bam}" - - gridss_config: - type: file - description: GRIDSS configuration file (optional) - genome_fasta: type: file description: Reference genome assembly FASTA file @@ -41,6 +38,9 @@ input: - virusbreakenddb: type: directory description: VIRUSBreakend database directory + - gridss_config: + type: file + description: GRIDSS configuration file (optional) output: - meta: type: map diff --git a/subworkflows/local/gridss_svprep_calling/main.nf b/subworkflows/local/gridss_svprep_calling/main.nf index 59ec337e..4811f741 100644 --- a/subworkflows/local/gridss_svprep_calling/main.nf +++ b/subworkflows/local/gridss_svprep_calling/main.nf @@ -184,11 +184,11 @@ workflow GRIDSS_SVPREP_CALLING { // Run process PREPROCESS( ch_preprocess_inputs, - gridss_config, genome_fasta, genome_fai, genome_dict, genome_gridss_index, + gridss_config, ) ch_versions = ch_versions.mix(PREPROCESS.out.versions) @@ -262,12 +262,12 @@ workflow GRIDSS_SVPREP_CALLING { // Run process ASSEMBLE( ch_assemble_inputs, - gridss_config, genome_fasta, genome_fai, genome_dict, genome_gridss_index, gridss_blocklist, + gridss_config, ) ch_versions = ch_versions.mix(ASSEMBLE.out.versions) @@ -292,12 +292,12 @@ workflow GRIDSS_SVPREP_CALLING { // Run process CALL( ch_call_inputs, - gridss_config, genome_fasta, genome_fai, genome_dict, genome_gridss_index, gridss_blocklist, + gridss_config, ) ch_versions = ch_versions.mix(CALL.out.versions) diff --git a/subworkflows/local/virusbreakend_calling/main.nf b/subworkflows/local/virusbreakend_calling/main.nf index ab5bb4fd..bd73af0e 100644 --- a/subworkflows/local/virusbreakend_calling/main.nf +++ b/subworkflows/local/virusbreakend_calling/main.nf @@ -71,12 +71,12 @@ workflow VIRUSBREAKEND_CALLING { // Run process VIRUSBREAKEND( ch_virusbreakend_inputs, - gridss_config, genome_fasta, genome_fai, genome_dict, genome_gridss_index, virusbreakenddb, + gridss_config, ) ch_versions = ch_versions.mix(VIRUSBREAKEND.out.versions) From 584b3efc34421dd798fc66929adcf36b8aecc96f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 17 Jul 2024 15:02:23 +1000 Subject: [PATCH 530/562] Correct typo --- modules/local/linx/visualiser/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/linx/visualiser/main.nf b/modules/local/linx/visualiser/main.nf index 9a22709e..951ea1dc 100644 --- a/modules/local/linx/visualiser/main.nf +++ b/modules/local/linx/visualiser/main.nf @@ -29,7 +29,7 @@ process LINX_VISUALISER { # used in the plot directory to force FusionFS to create the directory as ORANGE will treat the placeholder as a PNG # and fail. Optional outputs are possible but requires further channel logic and output to detect when complete. # Instead I place the two plot output directories under a parent directory, only operating on that to allow use of a - # placeholder and support empty outputs when using FusionFS. Handing missing/non-existent directories are deferred + # placeholder and support empty outputs when using FusionFS. Handling missing/non-existent directories are deferred # to downstream processes, bypassing the need to implement further channel operations. mkdir -p plots/ From e32340094fe23f35ddd64be28dad7219afea68c5 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 17 Jul 2024 15:03:10 +1000 Subject: [PATCH 531/562] Indicate NOTE author --- modules/local/svprep/assemble/main.nf | 2 +- modules/local/svprep/call/main.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/svprep/assemble/main.nf b/modules/local/svprep/assemble/main.nf index 4c8955b8..498930ef 100644 --- a/modules/local/svprep/assemble/main.nf +++ b/modules/local/svprep/assemble/main.nf @@ -44,7 +44,7 @@ process GRIDSS_ASSEMBLE { """ # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation - # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + # NOTE(SW): for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present shadow_input_directory() { src=\${1} dst="${output_dirname}/work/\${src##*/}" diff --git a/modules/local/svprep/call/main.nf b/modules/local/svprep/call/main.nf index eeec1b5c..b5ea5973 100644 --- a/modules/local/svprep/call/main.nf +++ b/modules/local/svprep/call/main.nf @@ -44,7 +44,7 @@ process GRIDSS_CALL { """ # Create shadow directory with file symlinks of GRIDSS 'working' dir to prevent cache invalidation - # NOTE: for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present + # NOTE(SW): for reasons that elude me, NF doesn't always stage in the workingdir; remove if it is present shadow_input_directory() { src=\${1} dst="${output_dirname}/" From 4d9b223f8561f7d46ffbb3dfb6281fc9c4b7a597 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 17 Jul 2024 16:34:03 +1000 Subject: [PATCH 532/562] Provide more informative error for bad run mode --- main.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.nf b/main.nf index 7fdb0419..8fda1aab 100644 --- a/main.nf +++ b/main.nf @@ -80,7 +80,8 @@ workflow NFCORE_ONCOANALYSER { } else if (run_mode === Constants.RunMode.TARGETED) { TARGETED() } else { - assert false + log.error("recieved bad run mode: ${run_mode}") + Nextflow.exit(1) } } From 989fbb26277f0caf7849ac7f9d35df82a4146b1c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 17 Jul 2024 16:45:39 +1000 Subject: [PATCH 533/562] Remove obsolete TODOs --- subworkflows/local/read_alignment_dna/main.nf | 5 ----- subworkflows/local/read_alignment_rna/main.nf | 5 ----- 2 files changed, 10 deletions(-) diff --git a/subworkflows/local/read_alignment_dna/main.nf b/subworkflows/local/read_alignment_dna/main.nf index 795bdc73..18764169 100644 --- a/subworkflows/local/read_alignment_dna/main.nf +++ b/subworkflows/local/read_alignment_dna/main.nf @@ -134,12 +134,7 @@ workflow READ_ALIGNMENT_DNA { def meta_bwamem2 = [ *:meta_fastq_ready, - - - // TODO(SW): understand target format read_group: "${meta_fastq_ready.sample_id}.${meta_fastq_ready.library_id}.${meta_fastq_ready.lane}", - - ] return [meta_bwamem2, fastq_fwd, fastq_rev] diff --git a/subworkflows/local/read_alignment_rna/main.nf b/subworkflows/local/read_alignment_rna/main.nf index d6e920c9..2a9b7876 100644 --- a/subworkflows/local/read_alignment_rna/main.nf +++ b/subworkflows/local/read_alignment_rna/main.nf @@ -63,12 +63,7 @@ workflow READ_ALIGNMENT_RNA { .map { meta_fastq, fastq_fwd, fastq_rev -> def meta_star = [ *:meta_fastq, - - - // TODO(SW): understand target format read_group: "${meta_fastq.sample_id}.${meta_fastq.library_id}.${meta_fastq.lane}", - - ] return [meta_star, fastq_fwd, fastq_rev] From feca3597d86314029d980e22aa6a2da0b8dc21d3 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 17 Jul 2024 18:16:08 +1000 Subject: [PATCH 534/562] Apply typo correction Co-authored-by: Simon Pearce <24893913+SPPearce@users.noreply.github.com> --- main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.nf b/main.nf index 8fda1aab..91add502 100644 --- a/main.nf +++ b/main.nf @@ -80,7 +80,7 @@ workflow NFCORE_ONCOANALYSER { } else if (run_mode === Constants.RunMode.TARGETED) { TARGETED() } else { - log.error("recieved bad run mode: ${run_mode}") + log.error("received bad run mode: ${run_mode}") Nextflow.exit(1) } From 0d8faa2a7042cd2893049851d7f53e135bd94de8 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 18 Jul 2024 13:42:15 +1000 Subject: [PATCH 535/562] Demote double underscores to single underscores --- docs/usage.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index ebc975ba..084cfcee 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -69,9 +69,9 @@ Currently only non-interleaved paired-end reads are accepted as FASTQ input. ```csv title="samplesheet.csv" group_id,subject_id,sample_id,sample_type,sequence_type,filetype,info,filepath -P1__wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P1.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.001.R2.fastq.gz -P1__wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P1.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.001.R2.fastq.gz -P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tumor.rna.wts.001.R1.fastq.gz;/path/to/P1.SC.tumor.rna.wts.001.R2.fastq.gz +P1_wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P1.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.001.R2.fastq.gz +P1_wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P1.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.001.R2.fastq.gz +P1_wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tumor.rna.wts.001.R1.fastq.gz;/path/to/P1.SC.tumor.rna.wts.001.R2.fastq.gz ``` #### BAM @@ -94,30 +94,30 @@ Please note there are other essential requirements around the use of BAMs as inp ```csv title="samplesheet.csv" group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath -P1__wgts,P1,SA,normal,dna,bam,/path/to/P1.SA.normal.dna.wgs.bam -P1__wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam -P1__wgts,P1,SC,tumor,rna,bam,/path/to/P1.SC.tumor.rna.wts.bam +P1_wgts,P1,SA,normal,dna,bam,/path/to/P1.SA.normal.dna.wgs.bam +P1_wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam +P1_wgts,P1,SC,tumor,rna,bam,/path/to/P1.SC.tumor.rna.wts.bam ``` ### Multiple lanes ```csv title="samplesheet.csv" group_id,subject_id,sample_id,sample_type,sequence_type,filetype,info,filepath -P1__wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P1.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.001.R2.fastq.gz -P1__wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:002,/path/to/P1.SA.normal.dna.wgs.002.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.002.R2.fastq.gz -P1__wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P1.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.001.R2.fastq.gz -P1__wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:002,/path/to/P1.SB.tumor.dna.wgs.002.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.002.R2.fastq.gz -P1__wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tumor.rna.wts.001.R1.fastq.gz;/path/to/P1.SC.tumor.rna.wts.001.R2.fastq.gz +P1_wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P1.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.001.R2.fastq.gz +P1_wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:002,/path/to/P1.SA.normal.dna.wgs.002.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.002.R2.fastq.gz +P1_wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P1.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.001.R2.fastq.gz +P1_wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:002,/path/to/P1.SB.tumor.dna.wgs.002.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.002.R2.fastq.gz +P1_wgts,P1,SC,tumor,rna,fastq,library_id:SC_library;lane:001,/path/to/P1.SC.tumor.rna.wts.001.R1.fastq.gz;/path/to/P1.SC.tumor.rna.wts.001.R2.fastq.gz ``` ### Multiple patients ```csv title="samplesheet.csv" group_id,subject_id,sample_id,sample_type,sequence_type,filetype,info,filepath -P1__wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P1.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.001.R2.fastq.gz -P1__wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P1.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.001.R2.fastq.gz -P2__wgts,P2,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P2.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P2.SA.normal.dna.wgs.001.R2.fastq.gz -P2__wgts,P2,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P2.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P2.SB.tumor.dna.wgs.001.R2.fastq.gz +P1_wgts,P1,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P1.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P1.SA.normal.dna.wgs.001.R2.fastq.gz +P1_wgts,P1,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P1.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P1.SB.tumor.dna.wgs.001.R2.fastq.gz +P2_wgts,P2,SA,normal,dna,fastq,library_id:SA_library;lane:001,/path/to/P2.SA.normal.dna.wgs.001.R1.fastq.gz;/path/to/P2.SA.normal.dna.wgs.001.R2.fastq.gz +P2_wgts,P2,SB,tumor,dna,fastq,library_id:SB_library;lane:001,/path/to/P2.SB.tumor.dna.wgs.001.R1.fastq.gz;/path/to/P2.SB.tumor.dna.wgs.001.R2.fastq.gz ``` ### Column descriptions @@ -255,9 +255,9 @@ that all upstream variant calling can be skipped: ```csv title='samplesheet.existing_purple.csv' group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath -P1__wgts,P1,SA,normal,dna,bam,/path/to/P1.SA.normal.dna.wgs.bam -P1__wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam -P1__wgts,P1,SB,tumor,dna,purple_dir,/path/to/P1.purple_dir/ +P1_wgts,P1,SA,normal,dna,bam,/path/to/P1.SA.normal.dna.wgs.bam +P1_wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam +P1_wgts,P1,SB,tumor,dna,purple_dir,/path/to/P1.purple_dir/ ``` :::note @@ -334,9 +334,9 @@ indices, reference data, and databases required to run a WGTS analysis for tumor ```csv title="samplesheet.csv" group_id,subject_id,sample_id,sample_type,sequence_type,filetype,filepath -P1__wgts,P1,SA,normal,dna,bam,/path/to/P1.SA.normal.dna.wgs.bam -P1__wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam -P1__wgts,P1,SC,tumor,rna,bam,/path/to/P1.SC.tumor.rna.wts.bam +P1_wgts,P1,SA,normal,dna,bam,/path/to/P1.SA.normal.dna.wgs.bam +P1_wgts,P1,SB,tumor,dna,bam,/path/to/P1.SB.tumor.dna.wgs.bam +P1_wgts,P1,SC,tumor,rna,bam,/path/to/P1.SC.tumor.rna.wts.bam ``` ```bash From 4e9a2124f4e60085a69a0c012a076212bc823161 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 18 Jul 2024 13:46:02 +1000 Subject: [PATCH 536/562] Use better halt/error in PAVE process --- modules/local/pave/germline/main.nf | 5 +---- modules/local/pave/somatic/main.nf | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/modules/local/pave/germline/main.nf b/modules/local/pave/germline/main.nf index 738a9c34..fdbdeead 100644 --- a/modules/local/pave/germline/main.nf +++ b/modules/local/pave/germline/main.nf @@ -2,8 +2,6 @@ // - https://github.com/hartwigmedical/pipeline5/blob/v5.33/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveGermline.java#L36-L41 // - https://github.com/hartwigmedical/pipeline5/blob/v5.33/cluster/src/main/java/com/hartwig/pipeline/tertiary/pave/PaveArguments.java#L31-L43 -import nextflow.Nextflow - process PAVE_GERMLINE { tag "${meta.id}" label 'process_medium' @@ -43,8 +41,7 @@ process PAVE_GERMLINE { } else if (genome_ver.toString() == '38') { gnomad_args = "-gnomad_freq_dir ${gnomad_resource}" } else { - log.error "got bad genome version: ${genome_ver}" - Nextflow.exit(1) + error "got bad genome version: ${genome_ver}" } """ diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index 2079364e..cb747971 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -1,5 +1,3 @@ -import nextflow.Nextflow - process PAVE_SOMATIC { tag "${meta.id}" label 'process_medium' @@ -44,8 +42,7 @@ process PAVE_SOMATIC { pon_filters = 'HOTSPOT:5:5;PANEL:2:5;UNKNOWN:2:0' gnomad_args = "-gnomad_freq_dir ${gnomad_resource}" } else { - log.error "got bad genome version: ${genome_ver}" - Nextflow.exit(1) + error "got bad genome version: ${genome_ver}" } // Targeted mode From 879d7d5851aa7325279d6ac73916e321af253694 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 18 Jul 2024 13:50:49 +1000 Subject: [PATCH 537/562] Update params YAML example in usage.md --- docs/usage.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 084cfcee..4fdbce58 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -191,12 +191,13 @@ The above pipeline run specified with a params file in yaml format: nextflow run nf-core/oncoanalyser -profile docker -params-file params.yaml ``` -with `params.yaml` containing: +with `params.yaml` containing the following as an example: ```yaml +mode: 'wgts' +genome: 'GRCh38_hmf' input: './samplesheet.csv' outdir: './results/' -genome: 'GRCh37' <...> ``` From 828c8ee486475d006b006977f2750dccf31a886d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 18 Jul 2024 13:54:11 +1000 Subject: [PATCH 538/562] Update indicated location of software versions --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 4fdbce58..06b04237 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -217,7 +217,7 @@ It is a good idea to specify a pipeline version when running the pipeline on you First, go to the [nf-core/oncoanalyser releases page](https://github.com/nf-core/oncoanalyser/releases) and find the latest pipeline version - numeric only (eg. `1.0.0`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.0.0`. Of course, you can switch to another version by changing the number after the `-r` flag. -This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. +This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, in the `/pipeline_info/software_versions.yml` file. To further assist in reproducbility, you can share and re-use [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. From 7545745a4c23ba3169b64e104a2264e4209eef6d Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 18 Jul 2024 13:58:03 +1000 Subject: [PATCH 539/562] Minor improvements to nextflow_schema.json --- nextflow_schema.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 82b3f6cb..a64d8932 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -47,11 +47,12 @@ "mode": { "type": "string", "description": "Workflow run mode.", - "fa_icon": "fas fa-diagram-project" + "fa_icon": "fas fa-diagram-project", + "pattern": "^(wgts|targeted)" }, "panel": { "type": "string", - "description": "Name of pane to use.", + "description": "Name of panel to use.", "fa_icon": "fas fa-book" }, "force_genome": { From a779453226c7e961c3626983de37dee0d75863f4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 18 Jul 2024 16:35:48 +1000 Subject: [PATCH 540/562] Fix grammar in usage.md --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 06b04237..7a386b91 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -320,7 +320,7 @@ params { To use these hmftools resource file overrides in `oncoanalyser` the local bundle directory must be provided with `--ref_data_hmf_data_path`. -#### Customise other data +#### Customising other data The path or URI to the VIRUSBreakend database can also be explicitly set with `--ref_data_virusbreakenddb_path`. There are additional arguments to manually set various other reference data files, please review the parameters documentation From b4523d1ab2d9c1a6fcd3d27a6ddc5c9f22a022a4 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 18 Jul 2024 16:36:38 +1000 Subject: [PATCH 541/562] Add note on sequencing depth to usage.md --- docs/usage.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/usage.md b/docs/usage.md index 7a386b91..2699b4be 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -48,6 +48,17 @@ samplesheet. The supported analysis types for each workflow are listed below. \* Supported analyses relate to the TSO500 panel only +:::note + +The default settings of `oncoanalyser` will accommodate typical sequencing depths for sample inputs and each individual +tool is generally sequencing depth agnostic. However, variant calling is optimised for 100x tumor and 40x normal when +invoked in `wgts` mode and expects sparse high-depth read data characteristic of panel sequencing when run in `targeted` +mode. For atypical input sequence data you may consult the [hmftools +documentation](https://github.com/hartwigmedical/hmftools) and [configure](#custom-tool-arguments) `oncoanalyser` +accordingly. + +::: + ## Samplesheet A samplesheet that contains information of each input in CSV format is needed to run `oncoanalyser`. The required input From c1b1fce6bd3f0793e66c3374abf63026c9c9dc13 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 19 Jul 2024 17:28:14 +1000 Subject: [PATCH 542/562] Improve fenced codeblock syntax highlight --- docs/output.md | 2 +- docs/usage.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/output.md b/docs/output.md index d1cdfb15..5197066e 100644 --- a/docs/output.md +++ b/docs/output.md @@ -5,7 +5,7 @@ This document describes the output produced by the pipeline. The directories listed below will be created in the results directory after the pipeline has finished. All paths are relative to the top-level results directory. -```text +```tree output/ │   ├── subject_1/ diff --git a/docs/usage.md b/docs/usage.md index 2699b4be..31aa71c3 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -316,7 +316,7 @@ See the below sections for further details on customising reference data. To override hmftools resource files, first [stage the bundle](#staging-reference-data) locally then copy in your custom file under the bundle directory and create a new config with relevant file paths: -```text title="hmf_data.custom.config" +```groovy title="hmf_data.custom.config" params { hmf_data_paths { '38' { @@ -368,7 +368,7 @@ recommended to remove the Nextflow work directory after staging data to free dis For `oncoanalyser` to use locally staged reference data a custom config can be used: -```text title="refdata.local.config" +```groovy title="refdata.local.config" params { genomes { @@ -431,7 +431,7 @@ It is strongly recommended to use a Hartwig-distributed reference genome for ali (`GRCh37_hmf` or `GRCh38_hmf`). Where it is not feasible to do so, a custom genome can instead be used by providing the relevant FASTA file in a configuration file: -```text title='genome.custom.config' +```groovy title='genome.custom.config' params { genomes { CustomGenome { From 2b4e521275f0c450ce414290f2fab87b970a199c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 19 Jul 2024 17:28:36 +1000 Subject: [PATCH 543/562] Use correct AMBER version in conda env file --- modules/local/amber/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/amber/environment.yml b/modules/local/amber/environment.yml index dbe8bf6c..f5e73626 100644 --- a/modules/local/amber/environment.yml +++ b/modules/local/amber/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-amber=4.0 + - bioconda::hmftools-amber=4.0.1 From 58b75d46d2487fe15b40e266a7d012fa2cb24f95 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 19 Jul 2024 17:29:26 +1000 Subject: [PATCH 544/562] Pin Tar version in extracttarball conda env --- modules/local/custom/extract_tarball/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/custom/extract_tarball/main.nf b/modules/local/custom/extract_tarball/main.nf index 9e7a9129..e956b0ad 100644 --- a/modules/local/custom/extract_tarball/main.nf +++ b/modules/local/custom/extract_tarball/main.nf @@ -1,7 +1,7 @@ process CUSTOM_EXTRACTTARBALL { label 'process_single' - conda "conda-forge::tar" + conda "conda-forge::tar=1.34" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : 'quay.io/nf-core/ubuntu:20.04' }" From f142fa6c09a55d9244c3d5ef837d485e3afdb993 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 31 Jul 2024 15:35:16 +1000 Subject: [PATCH 545/562] Add summary note on pipeline function in README.md --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f0e49dc0..8fa4a863 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,13 @@ ## Introduction **nf-core/oncoanalyser** is a Nextflow implementation of the comprehensive cancer DNA/RNA analysis and reporting -workflow from the Hartwig Medical Foundation. Both the Hartwig WGS/WTS workflow and targeted sequencing workflow are -available in oncoanalyser. The targeted sequencing workflow has built-in support for the TSO500 panel and can also run -custom panels with externally-generated normalisation data. +workflow from the Hartwig Medical Foundation (HMF). The workflow starts from FASTQ or BAM and calls genomic variants, +analyses transcript data, infers important biomarkers and features (e.g. TMB, HRD, mutational signatures, HLA alleles, +oncoviral content, tissue of origin, etc), annotates and interprets results in the clinical context, and more. + +Both the Hartwig WGS/WTS workflow and targeted sequencing workflow are available in oncoanalyser. The targeted +sequencing workflow has built-in support for the TSO500 panel and can also run custom panels with externally-generated +normalisation data. The key analysis results for each sample are summarised and presented in an ORANGE report (summary page excerpt shown below from _[COLO829_wgts.orange_report.pdf](https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/other/example_report/COLO829_wgts.orange_report.pdf)_): From c0d6b071d5900e8f6427f70eaf7e3732b09cef44 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 31 Jul 2024 15:35:37 +1000 Subject: [PATCH 546/562] Correct Conda GRIDSS build version --- modules/local/gridss/index/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/gridss/index/environment.yml b/modules/local/gridss/index/environment.yml index 3f1fee42..ed9cb011 100644 --- a/modules/local/gridss/index/environment.yml +++ b/modules/local/gridss/index/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::gridss=2.13.2=hdfd78af_3 + - bioconda::gridss=2.13.2=h50ea8bc_3 From 7394aa2761aed98270c221404e067096139627b5 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 31 Jul 2024 15:35:53 +1000 Subject: [PATCH 547/562] Correct Conda SAGE version --- modules/local/sage/append/environment.yml | 2 +- modules/local/sage/germline/environment.yml | 2 +- modules/local/sage/somatic/environment.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/sage/append/environment.yml b/modules/local/sage/append/environment.yml index dd57ccbb..e6f84927 100644 --- a/modules/local/sage/append/environment.yml +++ b/modules/local/sage/append/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sage=3.4.3 + - bioconda::hmftools-sage=3.4.4 diff --git a/modules/local/sage/germline/environment.yml b/modules/local/sage/germline/environment.yml index 1f44d1c5..40abd45c 100644 --- a/modules/local/sage/germline/environment.yml +++ b/modules/local/sage/germline/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sage=3.4.3 + - bioconda::hmftools-sage=3.4.4 diff --git a/modules/local/sage/somatic/environment.yml b/modules/local/sage/somatic/environment.yml index 35e0b137..5befb17f 100644 --- a/modules/local/sage/somatic/environment.yml +++ b/modules/local/sage/somatic/environment.yml @@ -4,4 +4,4 @@ channels: - bioconda - defaults dependencies: - - bioconda::hmftools-sage=3.4.3 + - bioconda::hmftools-sage=3.4.4 From b660853e9f1ef509957215a5e16aa3e6ebd0dc3f Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 31 Jul 2024 15:36:19 +1000 Subject: [PATCH 548/562] Comment out any hint of citations --- .../local/utils_nfcore_oncoanalyser_pipeline/main.nf | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf b/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf index f52693ff..f36242b9 100644 --- a/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_oncoanalyser_pipeline/main.nf @@ -176,9 +176,12 @@ def genomeExistsError() { // Generate methods description for MultiQC // def toolCitationText() { - // TODO nf-core: Optionally add in-text citation tools to this list. - // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "Tool (Foo et al. 2023)" : "", - // Uncomment function in methodsDescriptionText to render in MultiQC report + def error_string = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " The toolCitationText function is not currently implemented and should not be used." + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + error(error_string) + + /* def citation_text = [ "Tools used in the workflow included:", "FastQC (Andrews 2010),", @@ -187,6 +190,7 @@ def toolCitationText() { ].join(' ').trim() return citation_text + */ } def toolBibliographyText() { From a6b5cc2e9f61b18b4347c3198e1835af0829b294 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 31 Jul 2024 15:38:10 +1000 Subject: [PATCH 549/562] Use the HMF abbreviation more in README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8fa4a863..89e4062d 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ workflow from the Hartwig Medical Foundation (HMF). The workflow starts from FAS analyses transcript data, infers important biomarkers and features (e.g. TMB, HRD, mutational signatures, HLA alleles, oncoviral content, tissue of origin, etc), annotates and interprets results in the clinical context, and more. -Both the Hartwig WGS/WTS workflow and targeted sequencing workflow are available in oncoanalyser. The targeted -sequencing workflow has built-in support for the TSO500 panel and can also run custom panels with externally-generated +Both the HMF WGS/WTS workflow and targeted sequencing workflow are available in oncoanalyser. The targeted sequencing +workflow has built-in support for the TSO500 panel and can also run custom panels with externally-generated normalisation data. The key analysis results for each sample are summarised and presented in an ORANGE report (summary page excerpt shown @@ -38,7 +38,7 @@ below from _[COLO829_wgts.orange_report.pdf](https://pub-29f2e5b2b7384811bdbbcba

    -For detailed information on each component of the Hartwig workflow, please refer to +For detailed information on each component of the HMF workflow, please refer to [hartwigmedical/hmftools](https://github.com/hartwigmedical/hmftools/). ## Pipeline summary From 76cb7802529b70e07aa6a8fcf1ac01913a336ea2 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 31 Jul 2024 16:02:56 +1000 Subject: [PATCH 550/562] Update input samplesheet URL for tests --- conf/test.config | 2 +- conf/test_full.config | 2 +- conf/test_stub.config | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/conf/test.config b/conf/test.config index 666424da..c9ede07f 100644 --- a/conf/test.config +++ b/conf/test.config @@ -27,7 +27,7 @@ params { max_time = '6.h' // Input data - input = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/simulated_reads/24.0/samplesheets/fastq_eval.subject_a-subject_b.wgts.tndna_trna.1.csv' + input = 'https://github.com/nf-core/test-datasets/raw/oncoanalyser/samplesheet/fastq_eval.subject_a.wgts.tndna_trna.minimal.csv' // Reference data ref_data_virusbreakenddb_path = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/virusbreakend/virusbreakenddb_test-24.04.0.tar.gz' diff --git a/conf/test_full.config b/conf/test_full.config index c719a30b..a2bd6f4c 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -21,7 +21,7 @@ params { config_profile_description = 'Full test dataset to check pipeline function' // Input data for full size test - input = 'https://pub-349bcb8decb44bf7acbddf90b270a061.r2.dev/simulated_reads/24.0/samplesheets/fastq_eval.subject_a-subject_b.wgts.tndna_trna.1.csv' + input = 'https://github.com/nf-core/test-datasets/raw/oncoanalyser/samplesheet/fastq_eval.subject_a.wgts.tndna_trna.minimal.csv' // Analysis config mode = 'wgts' diff --git a/conf/test_stub.config b/conf/test_stub.config index 34906f4c..0a8b47ff 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -20,7 +20,7 @@ params { max_time = '6.h' // Input data - input = 'https://pub-29f2e5b2b7384811bdbbcba44f8b5083.r2.dev/oncoanalyser/test_data/other/samplesheet.colo829_mini.dna_rna.grch38_hmf.stub.csv' + input = 'https://github.com/nf-core/test-datasets/raw/oncoanalyser/samplesheet/fastq_eval.subject_a.wgts.tndna_trna.minimal.csv' // Reference data genomes { From 3a835c630eb580ea1339672f2c5af2336b49c8df Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 31 Jul 2024 18:38:52 +1000 Subject: [PATCH 551/562] Fix MarkDups URLs --- docs/output.md | 6 +++--- modules/local/markdups/meta.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/output.md b/docs/output.md index 5197066e..1d9ac032 100644 --- a/docs/output.md +++ b/docs/output.md @@ -112,9 +112,9 @@ _No outputs are published directly from STAR, see [Picard MarkDuplicates](#picar -[MarkDups](https://github.com/hartwigmedical/hmftools/tree/master/mark-dups) applies various alignment post-processing -routines such as duplicate marking and unmapping of problematic regions. It can also handle UMIs when configured to do -so. +[MarkDups](https://github.com/hartwigmedical/hmftools/tree/mark-dups-v1.1.7/mark-dups) applies various alignment +post-processing routines such as duplicate marking and unmapping of problematic regions. It can also handle UMIs when +configured to do so. _MarkDups is only run on DNA alignments_ diff --git a/modules/local/markdups/meta.yml b/modules/local/markdups/meta.yml index a9297b68..b621748f 100644 --- a/modules/local/markdups/meta.yml +++ b/modules/local/markdups/meta.yml @@ -6,8 +6,8 @@ keywords: tools: - MarkDups: description: Identify and mark duplicate reads ifrom alignment data - homepage: https://github.com/hartwigmedical/hmftools/tree/master/mark-dups - documentation: https://github.com/hartwigmedical/hmftools/tree/master/mark-dups + homepage: https://github.com/hartwigmedical/hmftools/tree/mark-dups-v1.1.7/mark-dups + documentation: https://github.com/hartwigmedical/hmftools/tree/mark-dups-v1.1.7/mark-dups licence: ["GPL v3"] input: - meta: From 3f7d8181be655d72bfbd750871e67b4f0e90110c Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 31 Jul 2024 19:10:48 +1000 Subject: [PATCH 552/562] Use stub samplesheet for test_stub profile --- conf/test_stub.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/test_stub.config b/conf/test_stub.config index 0a8b47ff..a8dd8d3b 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -20,7 +20,7 @@ params { max_time = '6.h' // Input data - input = 'https://github.com/nf-core/test-datasets/raw/oncoanalyser/samplesheet/fastq_eval.subject_a.wgts.tndna_trna.minimal.csv' + input = 'https://github.com/nf-core/test-datasets/raw/oncoanalyser/samplesheet/fastq_eval.subject_a.wgts.tndna_trna.minimal.stub.csv' // Reference data genomes { From f876e1844c895ce77a8ca4665893ec3508180959 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 31 Jul 2024 19:21:17 +1000 Subject: [PATCH 553/562] Switch to BAM inputs for test_stub samplesheet --- conf/test_stub.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/test_stub.config b/conf/test_stub.config index a8dd8d3b..e7d08d0a 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -20,7 +20,7 @@ params { max_time = '6.h' // Input data - input = 'https://github.com/nf-core/test-datasets/raw/oncoanalyser/samplesheet/fastq_eval.subject_a.wgts.tndna_trna.minimal.stub.csv' + input = 'https://github.com/nf-core/test-datasets/raw/oncoanalyser/samplesheet/bam_eval.subject_a.wgts.tndna_trna.minimal.stub.csv' // Reference data genomes { From 7ec0f399d0c8ffce106b53b6aece974bdd9db690 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Tue, 6 Aug 2024 10:16:04 +1000 Subject: [PATCH 554/562] Allow RNA BAM from samplesheet as input to LILAC --- subworkflows/local/lilac_calling/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/lilac_calling/main.nf b/subworkflows/local/lilac_calling/main.nf index 62e43abe..5ee68fd4 100644 --- a/subworkflows/local/lilac_calling/main.nf +++ b/subworkflows/local/lilac_calling/main.nf @@ -193,8 +193,8 @@ workflow LILAC_CALLING { nbai_dna, tbam_dna, tbai_dna, - tbam_rna, - tbai_rna, + Utils.selectCurrentOrExisting(tbam_rna, meta, Constants.INPUT.BAM_RNA_TUMOR), + Utils.selectCurrentOrExisting(tbai_rna, meta, Constants.INPUT.BAI_RNA_TUMOR), Utils.selectCurrentOrExisting(purple_dir, meta, Constants.INPUT.PURPLE_DIR), ] } From 9c0c2870dd92be2bad03c1c38b6324fde55c5d49 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 7 Aug 2024 07:43:19 +1000 Subject: [PATCH 555/562] Add panel param null check in param validation --- lib/WorkflowMain.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 56047a62..b82be562 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -178,7 +178,7 @@ class WorkflowMain { if (run_mode === Constants.RunMode.TARGETED) { - if (!params.containsKey('panel')) { + if (!params.containsKey('panel') || params.panel === null) { def panels = Constants.PANELS_DEFINED.join('\n - ') log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + From 21a0bc95e36f04ff6c9d4c9ff93a11cc0fd67252 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Wed, 7 Aug 2024 07:44:05 +1000 Subject: [PATCH 556/562] Adjust missing panel param error message --- lib/WorkflowMain.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index b82be562..fcf73d9a 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -182,9 +182,9 @@ class WorkflowMain { def panels = Constants.PANELS_DEFINED.join('\n - ') log.error "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " A panel is required to be set using the --panel CLI argument or in a \n" + - " configuration file.\n" + - " Currently, the available panels are:\n" + + " A panel is required to be set using the --panel CLI argument or in a\n" + + " configuration file when running in targeted mode.\n" + + " Currently, the available built-in panels are:\n" + " - ${panels}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" Nextflow.exit(1) From 1e9cb5de54da8a1fbdc972d438356f8b7a0d4846 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 8 Aug 2024 10:42:31 +1000 Subject: [PATCH 557/562] Add missing conda directive to MarkDups process Thanks to @AidanJFlynn for reporting --- modules/local/markdups/main.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/local/markdups/main.nf b/modules/local/markdups/main.nf index 649f85a3..93e791bc 100644 --- a/modules/local/markdups/main.nf +++ b/modules/local/markdups/main.nf @@ -2,6 +2,7 @@ process MARKDUPS { tag "${meta.id}" label 'process_medium' + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/hmftools-mark-dups:1.1.7--hdfd78af_0' : 'biocontainers/hmftools-mark-dups:1.1.7--hdfd78af_0' }" From 41b962ef8c5ec37e412e3d6fcfbd9bc7bbb997ad Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Aug 2024 12:48:13 +1000 Subject: [PATCH 558/562] Update PAVE somatic command --- modules/local/pave/somatic/main.nf | 9 +-------- modules/local/pave/somatic/meta.yml | 8 -------- subworkflows/local/pave_annotation/main.nf | 18 +----------------- 3 files changed, 2 insertions(+), 33 deletions(-) diff --git a/modules/local/pave/somatic/main.nf b/modules/local/pave/somatic/main.nf index cb747971..fe4e1896 100644 --- a/modules/local/pave/somatic/main.nf +++ b/modules/local/pave/somatic/main.nf @@ -14,8 +14,6 @@ process PAVE_SOMATIC { path genome_fai path sage_pon path pon_artefacts - path sage_blocklist_regions - path sage_blocklist_sites path clinvar_annotations path segment_mappability path driver_gene_panel @@ -47,9 +45,6 @@ process PAVE_SOMATIC { // Targeted mode def pon_artefact_arg = pon_artefacts ? "-pon_artefact_file ${pon_artefacts}" : '' - def sage_blocklist_regions_arg = sage_blocklist_regions ? "-blacklist_bed ${sage_blocklist_regions}" : '' - def sage_blocklist_sites_arg = sage_blocklist_sites ? "-blacklist_vcf ${sage_blocklist_sites}" : '' - def clinvar_annotations = clinvar_annotations ? "-clinvar_vcf ${clinvar_annotations}" : '' """ pave \\ @@ -62,12 +57,10 @@ process PAVE_SOMATIC { -pon_file ${sage_pon} \\ -pon_filters "${pon_filters}" \\ ${pon_artefact_arg} \\ - ${clinvar_annotations} \\ + -clinvar_vcf ${clinvar_annotations} \\ -driver_gene_panel ${driver_gene_panel} \\ -mappability_bed ${segment_mappability} \\ -ensembl_data_dir ${ensembl_data_resources} \\ - ${sage_blocklist_regions_arg} \\ - ${sage_blocklist_sites_arg} \\ ${gnomad_args} \\ -read_pass_only \\ -threads ${task.cpus} \\ diff --git a/modules/local/pave/somatic/meta.yml b/modules/local/pave/somatic/meta.yml index 399efd0c..af814d51 100644 --- a/modules/local/pave/somatic/meta.yml +++ b/modules/local/pave/somatic/meta.yml @@ -45,14 +45,6 @@ input: - pon_artefacts: type: file description: Taregeted sequencing PON artefacts file (optional) - - sage_blocklist_regions: - type: file - description: SAGE regions blocklist file - pattern: "*.{bed}" - - sage_blocklist_sites: - type: file - description: SAGE sites blocklist file - pattern: "*.{vcf.gz}" - clinvar_annotations: type: file description: ClinVar annotations VCF file diff --git a/subworkflows/local/pave_annotation/main.nf b/subworkflows/local/pave_annotation/main.nf index 2092581e..f5a1f50f 100644 --- a/subworkflows/local/pave_annotation/main.nf +++ b/subworkflows/local/pave_annotation/main.nf @@ -124,20 +124,6 @@ workflow PAVE_ANNOTATION { return [meta_pave, sage_vcf, sage_tbi] } - // Set resource files according to run mode - // NOTE(SW): required since certain files can be used in germline and somatic depending on mode - // but want to avoid duplicating as multiple inputs - // NOTE(SW): this pattern should be used only sparingly; implicit config from workflows is prefered - sage_blocklist_regions_somatic = sage_blocklist_regions - sage_blocklist_sites_somatic = sage_blocklist_sites - clinvar_annotations_somatic = clinvar_annotations - run_mode = Utils.getEnumFromString(params.mode, Constants.RunMode) - if (run_mode === Constants.RunMode.WGTS) { - sage_blocklist_regions_somatic = [] - sage_blocklist_sites_somatic = [] - clinvar_annotations_somatic = [] - } - // Run process SOMATIC( ch_pave_somatic_inputs, @@ -146,9 +132,7 @@ workflow PAVE_ANNOTATION { genome_fai, sage_pon, pon_artefacts, - sage_blocklist_regions_somatic, - sage_blocklist_sites_somatic, - clinvar_annotations_somatic, + clinvar_annotations, segment_mappability, driver_gene_panel, ensembl_data_resources, From b333f11af216b0c77f4f93af059180233418c268 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Aug 2024 12:49:10 +1000 Subject: [PATCH 559/562] Use consistent casing --- modules/local/chord/main.nf | 4 ++-- modules/local/linxreport/main.nf | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/chord/main.nf b/modules/local/chord/main.nf index bd835166..91816c2e 100644 --- a/modules/local/chord/main.nf +++ b/modules/local/chord/main.nf @@ -70,8 +70,8 @@ process CHORD { sink('versions.yml') writeLines('"${task.process}":') - writeLines(paste(' CHORD:', packageVersion('CHORD'))) - writeLines(paste(' mutSigExtractor:', packageVersion('mutSigExtractor'))) + writeLines(paste(' chord:', packageVersion('CHORD'))) + writeLines(paste(' mutsigextractor:', packageVersion('mutSigExtractor'))) sink() """ diff --git a/modules/local/linxreport/main.nf b/modules/local/linxreport/main.nf index f3d3a55e..0757ac75 100644 --- a/modules/local/linxreport/main.nf +++ b/modules/local/linxreport/main.nf @@ -37,7 +37,7 @@ process LINXREPORT { cat <<-END_VERSIONS > versions.yml "${task.process}": - R: \$(R --version | head -n1 | sed 's/^R version \\([0-9.]\\+\\).\\+/\\1/') + r: \$(R --version | head -n1 | sed 's/^R version \\([0-9.]\\+\\).\\+/\\1/') linxreport: \$(linxreport.R --version) END_VERSIONS """ From 5c3ca3af025fc5e199913676e5dc73976ff148d7 Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Aug 2024 12:49:58 +1000 Subject: [PATCH 560/562] Add missed outputs into versions channel --- subworkflows/local/read_processing/main.nf | 2 ++ workflows/targeted.nf | 2 ++ 2 files changed, 4 insertions(+) diff --git a/subworkflows/local/read_processing/main.nf b/subworkflows/local/read_processing/main.nf index 4a0967ca..673d202e 100644 --- a/subworkflows/local/read_processing/main.nf +++ b/subworkflows/local/read_processing/main.nf @@ -92,6 +92,8 @@ workflow READ_PROCESSING { has_umis, ) + ch_versions = ch_versions.mix(MARKDUPS.out.versions) + // Sort into a tumor and normal channel ch_markdups_out = MARKDUPS.out.bam .branch { meta_markdups, bam, bai -> diff --git a/workflows/targeted.nf b/workflows/targeted.nf index f0b5649d..f2d4f0ba 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -99,6 +99,8 @@ workflow TARGETED { hmf_data = PREPARE_REFERENCE.out.hmf_data panel_data = PREPARE_REFERENCE.out.panel_data + ch_versions = ch_versions.mix(PREPARE_REFERENCE.out.versions) + // Set GRIDSS config gridss_config = params.gridss_config !== null ? file(params.gridss_config) : hmf_data.gridss_config From 8a87acebc84381285a0b584e7a669a0c494556fb Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Thu, 15 Aug 2024 12:50:13 +1000 Subject: [PATCH 561/562] Use consistent version mix invoke format --- workflows/wgts.nf | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/workflows/wgts.nf b/workflows/wgts.nf index 9facc5ac..0541966d 100644 --- a/workflows/wgts.nf +++ b/workflows/wgts.nf @@ -104,9 +104,7 @@ workflow WGTS { ref_data = PREPARE_REFERENCE.out hmf_data = PREPARE_REFERENCE.out.hmf_data - ch_versions = ch_versions.mix( - PREPARE_REFERENCE.out.versions, - ) + ch_versions = ch_versions.mix(PREPARE_REFERENCE.out.versions) // Set GRIDSS config gridss_config = params.gridss_config !== null ? file(params.gridss_config) : hmf_data.gridss_config From 21770a390abd80434e46d72cf64d52e9c79c4a1e Mon Sep 17 00:00:00 2001 From: Stephen Watts Date: Fri, 23 Aug 2024 10:17:25 +1000 Subject: [PATCH 562/562] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09612f63..0d2bcdbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 1.0.0 - [date] +## [[1.0.0](https://github.com/nf-core/oncoanalyser/releases/tag/1.0.0)] Pied Currawong - 2024-08-26 Initial release of nf-core/oncoanalyser, created with the [nf-core](https://nf-co.re/) template.

    Data was processed using nf-core/oncoanalyser v${workflow.manifest.version} ${doi_text} of the nf-core collection of workflows (Ewels et al., 2020), utilising reproducible software environments from the Bioconda (Grüning et al., 2018) and Biocontainers (da Veiga Leprevost et al., 2017) projects.

    R5S;*y0>LC{N5nC!ho>-Fy}=M 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�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

    Data was processed using nf-core/oncoanalyser v${workflow.manifest.version} ${doi_text} of the nf-core collection of workflows (Ewels et al., 2020).

    \n" + for (param in group_params.keySet()) { + summary_section += "
    $param
    ${group_params.get(param) ?: 'N/A'}
    \n" + } + summary_section += "