From 22377432a2293d38c94fb3358831c264f24c4643 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Mon, 27 Dec 2021 18:04:26 +0100 Subject: [PATCH 01/60] Include changes for template update --- .gitattributes | 2 + .github/CONTRIBUTING.md | 38 +- .github/ISSUE_TEMPLATE/bug_report.md | 63 -- .github/ISSUE_TEMPLATE/bug_report.yml | 52 ++ .github/ISSUE_TEMPLATE/config.yml | 1 - .github/ISSUE_TEMPLATE/feature_request.md | 32 - .github/ISSUE_TEMPLATE/feature_request.yml | 11 + .github/workflows/awsfulltest.yml | 4 +- .github/workflows/awstest.yml | 4 +- .github/workflows/ci.yml | 43 +- .github/workflows/linting_comment.yml | 1 + CITATIONS.md | 2 +- README.md | 59 +- assets/multiqc_config.yaml | 2 +- assets/nf-core-mhcquant_logo.png | Bin 17995 -> 0 bytes assets/nf-core-mhcquant_logo_light.png | 9 + assets/sendmail_template.txt | 4 +- bin/scrape_software_versions.py | 36 - conf/base.config | 8 +- conf/modules.config | 275 +++++-- conf/test.config | 4 +- docs/images/nf-core-mhcquant_logo.png | Bin 34566 -> 0 bytes docs/images/nf-core-mhcquant_logo_dark.png | 0 docs/images/nf-core-mhcquant_logo_light.png | Bin 0 -> 72389 bytes docs/output.md | 195 +---- docs/usage.md | 40 + lib/NfcoreSchema.groovy | 26 +- lib/NfcoreTemplate.groovy | 30 +- lib/Utils.groovy | 7 - lib/WorkflowMain.groovy | 10 +- modules.json | 6 +- modules/local/functions.nf | 2 + modules/local/get_software_versions.nf | 34 - modules/local/samplesheet_check.nf | 27 +- .../custom/dumpsoftwareversions/functions.nf | 78 -- .../custom/dumpsoftwareversions/main.nf | 95 +-- .../custom/dumpsoftwareversions/meta.yml | 1 + .../templates/dumpsoftwareversions.py | 89 +++ modules/nf-core/modules/multiqc/functions.nf | 78 -- modules/nf-core/modules/multiqc/main.nf | 24 +- nextflow.config | 9 +- nextflow_schema.json | 32 +- subworkflows/local/input_check.nf | 12 +- workflows/mhcquant.nf | 719 +++++++++--------- 44 files changed, 929 insertions(+), 1235 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml delete mode 100644 assets/nf-core-mhcquant_logo.png create mode 100644 assets/nf-core-mhcquant_logo_light.png delete mode 100755 bin/scrape_software_versions.py delete mode 100644 docs/images/nf-core-mhcquant_logo.png create mode 100644 docs/images/nf-core-mhcquant_logo_dark.png create mode 100644 docs/images/nf-core-mhcquant_logo_light.png delete mode 100644 modules/local/get_software_versions.nf delete mode 100644 modules/nf-core/modules/custom/dumpsoftwareversions/functions.nf create mode 100644 modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py delete mode 100644 modules/nf-core/modules/multiqc/functions.nf diff --git a/.gitattributes b/.gitattributes index 7fe55006..050bb120 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,3 @@ *.config linguist-language=nextflow +modules/nf-core/** linguist-generated +subworkflows/nf-core/** linguist-generated diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 05fd627c..1312f3db 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -68,16 +68,13 @@ 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 flags/options to `nextflow.config` with a default (see below). -5. Add any new flags/options to `nextflow_schema.json` with help text (with `nf-core schema build`). -6. Add any new flags/options to the help message (for integer/text parameters, print to help the corresponding `nextflow.config` parameter). -7. Add sanity checks for all relevant parameters. -8. Add any new software to the `scrape_software_versions.py` script in `bin/` and the version command to the `scrape_software_versions` process in `main.nf`. -9. Do local tests that the new code works properly and as expected. -10. Add a new test command in `.github/workflow/ci.yml`. -11. If applicable add a [MultiQC](https://https://multiqc.info/) module. -12. Update MultiQC config `assets/multiqc_config.yaml` so relevant suffixes, name clean up, General Statistics Table column order, and module figures are in the right order. -13. Optional: Add any descriptions of MultiQC report sections and output files to `docs/output.md`. +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.yaml` 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 @@ -102,27 +99,6 @@ Please use the following naming schemes, to make it easy to understand what is g 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]` -### Software version reporting - -If you add a new tool to the pipeline, please ensure you add the information of the tool to the `get_software_version` process. - -Add to the script block of the process, something like the following: - -```bash - --version &> v_.txt 2>&1 || true -``` - -or - -```bash - --help | head -n 1 &> v_.txt 2>&1 || true -``` - -You then need to edit the script `bin/scrape_software_versions.py` to: - -1. Add a Python regex for your tool's `--version` output (as in stored in the `v_.txt` file), to ensure the version is reported as a `v` and the version number e.g. `v2.1.1` -2. Add a HTML entry to the `OrderedDict` for formatting in MultiQC. - ### 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.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index ea229fab..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -name: Bug report -about: Report something that is broken or incorrect -labels: bug ---- - - - -## Check Documentation - -I have checked the following places for your error: - -- [ ] [nf-core website: troubleshooting](https://nf-co.re/usage/troubleshooting) -- [ ] [nf-core/mhcquant pipeline documentation](https://nf-co.re/mhcquant/usage) - -## Description of the bug - - - -## Steps to reproduce - -Steps to reproduce the behaviour: - -1. Command line: -2. See error: - -## Expected behaviour - - - -## Log files - -Have you provided the following extra information/files: - -- [ ] The command used to run the pipeline -- [ ] The `.nextflow.log` file - -## System - -- Hardware: -- Executor: -- OS: -- Version - -## Nextflow Installation - -- Version: - -## Container engine - -- Engine: -- version: - -## Additional context - - diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..816a6f87 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,52 @@ + +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/mhcquant pipeline documentation](https://nf-co.re/mhcquant/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/mhcquant _(eg. 1.1, 1.5, 1.8.2)_ diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index c283b9b4..51b0d6a8 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,3 @@ -blank_issues_enabled: false contact_links: - name: Join nf-core url: https://nf-co.re/join diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 7a90e846..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for the nf-core/mhcquant pipeline -labels: enhancement ---- - - - -## Is your feature request related to a problem? Please describe - - - - - -## Describe the solution you'd like - - - -## Describe alternatives you've considered - - - -## Additional context - - diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..747f7388 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,11 @@ +name: Feature request +description: Suggest an idea for the nf-core/mhcquant 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/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 6c6c71d7..00ac8dfd 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -20,11 +20,11 @@ jobs: access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} pipeline: ${{ github.repository }} - revision: ${{ github.sha } } + revision: ${{ github.sha }} workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/mhcquant/work-${{ github.sha }} parameters: | { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/mhcquant/results-${{ github.sha }}" } - profiles: test,aws_tower + profiles: test_full,aws_tower pre_run_script: 'export NXF_VER=21.10.3' diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index acc6f70b..15e5b355 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Launch workflow via tower uses: nf-core/tower-action@v2 - + with: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} @@ -22,7 +22,7 @@ jobs: workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/mhcquant/work-${{ github.sha }} parameters: | { - "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/mhcquant/results-${{ github.sha }}" + "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/mhcquant/results-test-${{ github.sha }}" } profiles: test,aws_tower pre_run_script: 'export NXF_VER=21.10.3' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 510e8f01..967c9917 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,8 +8,9 @@ on: release: types: [published] -# Uncomment if we need an edge release of Nextflow again -# env: NXF_EDGE: 1 +env: + NXF_ANSI_LOG: false + CAPSULE_LOG: none jobs: test: @@ -17,20 +18,26 @@ jobs: # 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/mhcquant') }} runs-on: ubuntu-latest - env: - NXF_VER: ${{ matrix.nxf_ver }} - NXF_ANSI_LOG: false strategy: matrix: - # Nextflow versions: check pipeline minimum and current latest - nxf_ver: ['21.10.3', ''] + # Nextflow versions + include: + # Test pipeline minimum Nextflow version + - NXF_VER: '21.10.3' + NXF_EDGE: '' + # Test latest edge release of Nextflow + - NXF_VER: '' + NXF_EDGE: '1' steps: - name: Check out pipeline code uses: actions/checkout@v2 - name: Install Nextflow env: - CAPSULE_LOG: none + NXF_VER: ${{ matrix.NXF_VER }} + # Uncomment only if the edge release is more recent than the latest stable release + # See https://github.com/nextflow-io/nextflow/issues/2467 + # NXF_EDGE: ${{ matrix.NXF_EDGE }} run: | wget -qO- get.nextflow.io | bash sudo mv nextflow /usr/local/bin/ @@ -38,23 +45,3 @@ jobs: - name: Run pipeline with test data run: | nextflow run ${GITHUB_WORKSPACE} -profile test,docker - - test_additional_params: - name: Run pipeline with additional params - # 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/mhcquant') }} - runs-on: ubuntu-latest - env: - NXF_VER: ${{ matrix.nxf_ver }} - NXF_ANSI_LOG: false - steps: - - name: Check out pipeline code - uses: actions/checkout@v2 - - - name: Install Nextflow - run: | - wget -qO- get.nextflow.io | bash - sudo mv nextflow /usr/local/bin/ - - name: Run pipeline with additional params - run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,docker --predict_class_1 --predict_class_2 --predict_RT diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 90f03c6f..44d72994 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -15,6 +15,7 @@ jobs: uses: dawidd6/action-download-artifact@v2 with: workflow: linting.yml + workflow_conclusion: completed - name: Get PR number id: pr_number diff --git a/CITATIONS.md b/CITATIONS.md index 68d4abe9..fdf7a5dc 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -22,7 +22,7 @@ * [OpenMS](https://pubmed.ncbi.nlm.nih.gov/27575624/) > Röst H, Sachsenberg T, Aiche S, Bielow C, Weisser H, Aicheler F, Andreotti S, Ehrlich HC, Gutenbrunner P, Kenar E, Liang X, Nahnsen S, Nilse L, Pfeuffer J, Rosenberger G, Rurik M, Schmitt U, Veit J, Walzer M, Wojnar D, Wolski WE, Schilling O, Choudhary JS, Malmström L, Aebersold R, Reinert K, Kohlbacher O. OpenMS: a flexible open-source software platform for mass spectrometry data analysis. Nat Methods 13, 741–748 (2016). doi: 10.1038/nmeth.3959. PubMed PMID: 27575624 -* [MultiQC](https://www.ncbi.nlm.nih.gov/pubmed/27312411/) +* [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 2a9651db..3833be3a 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -# ![nf-core/mhcquant](docs/images/nf-core-mhcquant_logo.png) +# ![nf-core/mhcquant](docs/images/nf-core-mhcquant_logo_light.png#gh-light-mode-only) ![nf-core/mhcquant](docs/images/nf-core-mhcquant_logo_dark.png#gh-dark-mode-only) [![GitHub Actions CI Status](https://github.com/nf-core/mhcquant/workflows/nf-core%20CI/badge.svg)](https://github.com/nf-core/mhcquant/actions?query=workflow%3A%22nf-core+CI%22) [![GitHub Actions Linting Status](https://github.com/nf-core/mhcquant/workflows/nf-core%20linting/badge.svg)](https://github.com/nf-core/mhcquant/actions?query=workflow%3A%22nf-core+linting%22) [![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/mhcquant/results) -[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.5407955-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.5407955) +[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.1569910-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.1569910) [![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg?labelColor=000000)](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/) @@ -37,16 +37,19 @@ On release, automated continuous integration tests run the pipeline on a full-si 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/), [`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 _(please only use [`Conda`](https://conda.io/miniconda.html) as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles))_. +2. Install any of [`Docker`](https://docs.docker.com/engine/installation/), [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/), [`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 _(please only use [`Conda`](https://conda.io/miniconda.html) 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: ```console - nextflow run nf-core/mhcquant -profile test, + nextflow run nf-core/mhcquant -profile test,YOURPROFILE ``` + 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` then the pipeline will auto-detect this and attempt to download the Singularity images directly as opposed to performing a conversion from Docker images. If you are persistently observing issues downloading Singularity images directly due to timeout or network issues then please use the `--singularity_pull_docker_container` parameter to pull and convert the Docker image instead. Alternatively, it is highly recommended to use the [`nf-core download`](https://nf-co.re/tools/#downloading-pipelines-for-offline-use) command to pre-download all of the required containers before running the pipeline and to set the [`NXF_SINGULARITY_CACHEDIR` or `singularity.cacheDir`](https://www.nextflow.io/docs/latest/singularity.html?#singularity-docker-hub) Nextflow options to be able to store and re-use the images from a central location for future pipeline runs. + > * If you are using `singularity` and are persistently observing issues downloading Singularity images directly due to timeout or network issues, then you can use the `--singularity_pull_docker_container` parameter to pull and convert the Docker image instead. Alternatively, you can 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! @@ -60,34 +63,24 @@ On release, automated continuous integration tests run the pipeline on a full-si --refine_fdr_on_predicted_subset ``` -See [usage docs](https://nf-co.re/mhcquant/usage) for all of the available options when running the pipeline. - -## Pipeline Summary - -By default, the pipeline currently performs the following: - -* Protein database addition by mutated genome variants (`Fred2 Immunoinformatics Toolbox`) -* Database search ('Comet') -* False discovery rate estimation ('Percolator') -* Retention time alignment ('OpenMS-MapAlignerIdentification') -* Targeted peptide quantification ('OpenMS-FeatureFinderIdentification') -* MHC peptide affinity prediction ('MHCFlurry','MHCNuggets') - ## Documentation -The nf-core/mhcquant pipeline comes with documentation about the pipeline: [usage](https://nf-co.re/mhcquant/usage) and [output](https://nf-co.re/mhcquant/output). +The nf-core/mhcquant pipeline comes with documentation about the pipeline [usage](https://nf-co.re/mhcquant/usage), [parameters](https://nf-co.re/mhcquant/parameters) and [output](https://nf-co.re/mhcquant/output). ## Credits -We thank the following people for their extensive assistance in the development -of this pipeline: - -* Leon Bichmann (@Leon-Bichmann) -* Lukas Heumos (@Zethson) -* Alexander Peltzer (@apeltzer) - -The pipeline was converted to Nextflow DSL2 by Marissa Dubbelaar (@marissaDubbelaar) - +nf-core/mhcquant was originally written by [Leon Bichmann](https://github.com/Leon-Bichmann) from the [Kohlbacher Lab](https://kohlbacherlab.org/).The pipeline was re-written in Nextflow DSL2 and is primarily maintained by [Marissa Dubbelaar](https://github.com/marissaDubbelaar) from [Clinical Collaboration Unit Translational Immunology](https://www.medizin.uni-tuebingen.de/en-de/das-klinikum/einrichtungen/kliniken/medizinische-klinik/kke-translationale-immunologie) and [Quantitative Biology Center](https://uni-tuebingen.de/forschung/forschungsinfrastruktur/zentrum-fuer-quantitative-biologie-qbic/) in Tübingen. + +Helpful contributors: + - [Lukas Heumos](https://github.com/Zethson) + - [Alexander Peltzer](https://github.com/apeltzer) + - [Maxime Garcia](https://github.com/maxulysse) + - [Gisela Gabernet](https://github.com/ggabernet) + - [Leon Kuchenbecker](https://github.com/lkuchenb) + - [Phil Ewels](https://github.com/ewels) + - [Christian Fufezan](https://github.com/fu) + - [Sven Fillinger](https://github.com/sven1103) + - [Kevin Menden](https://github.com/KevinMenden) ## Contributions and Support If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). @@ -96,14 +89,12 @@ For further information or help, don't hesitate to get in touch on the [Slack `# ## Citations -If you use `nf-core/mhcquant` for your analysis, please cite it using the following doi: [10.5281/zenodo.5407955](https://doi.org/10.5281/zenodo.5407955) and the corresponding manuscript: +If you use nf-core/mhcquant for your analysis, please cite it using the following doi: [10.5281/zenodo.1569910](https://doi.org/10.5281/zenodo.1569910) and the corresponding manuscript: > **MHCquant: Automated and Reproducible Data Analysis for Immunopeptidomics** > -> Leon Bichmann, Annika Nelde, Michael Ghosh, Lukas Heumos, Christopher Mohr, Alexander Peltzer, Leon Kuchenbecker, Timo Sachsenberg, Juliane S. Walz, Stefan Stevanović, Hans-Georg Rammensee & Oliver Kohlbacher -> -> Journal of Proteome Research 2019 18 (11), 3876-3884 -> DOI: 10.1021/acs.jproteome.9b00313 +> Leon Bichmann, Annika Nelde, Michael Ghosh, Lukas Heumos, Christopher Mohr, Alexander Peltzer, Leon Kuchenbecker, Timo Sachsenberg, Juliane S. Walz, Stefan Stevanović, Hans-Georg Rammensee & Oliver Kohlbacher> +> _Journal of Proteome Research_ 2019 18 (11), 3876-3884. doi: [10.1021/acs.jproteome.9b00313](https://pubs.acs.org/doi/10.1021/acs.jproteome.9b00313) An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. @@ -141,4 +132,4 @@ In addition, references of tools and data used in this pipeline are as follows: > > O'Donnell T.J., _Cell Syst._ 2018 Jul 25;7(1):129-132.e4. doi: 10.1016/j.cels.2018.05.014. Epub 2018 Jun 27. > -> Shao X.M., _Cancer Immunol Res._ 2020 Mar;8(3):396-408. doi: 10.1158/2326-6066.CIR-19-0464. Epub 2019 Dec 23. +> Shao X.M., _Cancer Immunol Res._ 2020 Mar;8(3):396-408. doi: 10.1158/2326-6066.CIR-19-0464. Epub 2019 Dec 23. \ No newline at end of file diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index a0e5fa3c..76398921 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -1,7 +1,7 @@ report_comment: > This report has been generated by the nf-core/mhcquant analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: software_versions: order: -1000 diff --git a/assets/nf-core-mhcquant_logo.png b/assets/nf-core-mhcquant_logo.png deleted file mode 100644 index 378f944c65e9238589cf8bcf27fa7ffe4db42d06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17995 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≷9+?1_az}B%ky%m&+2jGNYrnHeWNtQXh^2!)Bj& z_qn(Ceqlr9inCnJEm~TiCNl4Bt#ceM3s^~TnOD_xD7Db%ohS7lzv0$CZu5Bz%Xx>w zBhq}s94m6zg~eSuy?3%-HM|DG;Hl5*Dy9eQTVmqs<-9{*(@`t4+$sWOz81jdju3dJ z*T}~cM~{(y4!PI1|A@T5=p$;=QRkh6E0#@j{dI?VYyu_J+@; z&^sF4_7;e#m=ZDLg>MVqXFOZ9M!YxpVfTRbt3UoecX-l3tW<6b<{eyMm+(rDH(-Zw z@|n|$9xF0kJMpVfNNt{jm20e6bUvPcpuEISna9-6{nXdo!nq@0D<&|i^!gmNY`NQK zC#_NBF$aKn--GsD>0DM%Kr};2hg}2{%o1(+dAEKl z#fl}eI(ri+5i%P{XQ$h~CKHp?3M#6&Fl)&9J3Ex5tpiX6hU=e)-R6=<0p~lb7@R_t)L)vEIo|#6b{;IPB)Q>NEnbqy6qKSIYw) zikA-#7a9oPzJ1FYQ02aegBo@*%~BkVn4Rv>>9kFq*Q@c@$+OUojw&)<>{|?4yIg7p zfw-gGUL)}{ThBXbsenT}#~-<>IO|l%fGD-k5IO-<)|KHf%NDK70A2i<>O=JGV{Jdv3gs@B_cUZ`&sPIFR((g?y>P zw2S@ypU;`U9-HTSanUD+xg#_apB#BuMqdfk_MBf^E|8Lcy7^lgbU0yX}U8-1O%?r$LiD&eqV+ zoH8{X-6{*5bgxa)^WDjT+yII#@8++XGkpU9H^+pa;i+eklaoi!+c)8~cwYqTl}f*R zM}$i)978GKo|%=^v3Db#LjaOncipo8Ub1UaT3YmL{n~mQuw}ezAJI4;2=Sjz8do9P z>IclZ_;b-^VZkQ-UeIk|ekWrUGY%k@WDkMzN&fxd`Q|wW8&Q&phf>SkeJB#07wKV4 zZ07+7!FGXG@D^VnS6mmAsGdgBTqBlr+30W3RDr{3JW|p5h1f8!!2!K7Ubla&qsQ@& zT;{{fde&{KMO?csD1L9T2_0hDPVpBFHv|zwp(vY1rt*;c5=RJb($;EvbyggT^mDsO zr|)Ahh6wv+H)+aR17S(-&&Qj;mSo4e>+cPR{${R7xD*lr(8Fqg{!^K8S1?!o6RkwJ z$@-r!+jBL{YinyX$pcxF)@quXq0qi~XtJ@tn2`~cTae@NirD^QQ}SGd`@x*)YG+ve zR=Uqfo)US)vMWEO`{BYTZDYSlsF~E|_d$#1t0fg^sAhxMpxER4GmQyn-5=3yc6j5Q=H^Kq)szVal5ke>K zI)vY_?x16|??MqVDUs1zaeY|(D&}WH`J&@}ZlB-v%0AvTyN7~#S97un!VkNWqQ=Hv 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 H3I6{8DYf}D diff --git a/assets/nf-core-mhcquant_logo_light.png b/assets/nf-core-mhcquant_logo_light.png new file mode 100644 index 00000000..dee3db82 --- /dev/null +++ b/assets/nf-core-mhcquant_logo_light.png @@ -0,0 +1,9 @@ + + + + 508 Resource Limit Is Reached + +

Resource Limit Is Reached

+The website is temporarily unable to service your request as it exceeded resource limit. +Please try again later. + diff --git a/assets/sendmail_template.txt b/assets/sendmail_template.txt index 43aaddfb..f3b6b8cf 100644 --- a/assets/sendmail_template.txt +++ b/assets/sendmail_template.txt @@ -12,9 +12,9 @@ $email_html Content-Type: image/png;name="nf-core-mhcquant_logo.png" Content-Transfer-Encoding: base64 Content-ID: -Content-Disposition: inline; filename="nf-core-mhcquant_logo.png" +Content-Disposition: inline; filename="nf-core-mhcquant_logo_light.png" -<% out << new File("$projectDir/assets/nf-core-mhcquant_logo.png"). +<% out << new File("$projectDir/assets/nf-core-mhcquant_logo_light.png"). bytes. encodeBase64(). toString(). diff --git a/bin/scrape_software_versions.py b/bin/scrape_software_versions.py deleted file mode 100755 index 44a9c393..00000000 --- a/bin/scrape_software_versions.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import os - -results = {} -version_files = [x for x in os.listdir(".") if x.endswith(".version.txt")] -for version_file in version_files: - - software = version_file.replace(".version.txt", "") - if software == "pipeline": - software = "nf-core/mhcquant" - - with open(version_file) as fin: - version = fin.read().strip() - results[software] = version - -# Dump to YAML -print( - """ -id: 'software_versions' -section_name: 'nf-core/mhcquant Software Versions' -section_href: 'https://github.com/nf-core/mhcquant' -plot_type: 'html' -description: 'are collected at run time from the software output.' -data: | -
-""" -) -for k, v in sorted(results.items()): - print("
{}
{}
".format(k, v)) -print("
") - -# Write out as tsv file: -with open("software_versions.tsv", "w") as f: - for k, v in sorted(results.items()): - f.write("{}\t{}\n".format(k, v)) diff --git a/conf/base.config b/conf/base.config index bf02eda6..6ef3aa50 100644 --- a/conf/base.config +++ b/conf/base.config @@ -1,4 +1,3 @@ - /* ======================================================================================== nf-core/mhcquant Nextflow base config file @@ -11,9 +10,9 @@ process { - cpus = { check_max( 1 * task.attempt, 'cpus' ) } + cpus = { check_max( 1 * task.attempt, 'cpus' ) } memory = { check_max( 4.GB * task.attempt, 'memory' ) } - time = { check_max( 2.h * task.attempt, 'time' ) } + time = { check_max( 2.h * task.attempt, 'time' ) } errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } maxRetries = 1 @@ -49,4 +48,7 @@ process { errorStrategy = 'retry' maxRetries = 2 } + withName:CUSTOM_DUMPSOFTWAREVERSIONS { + cache = false + } } diff --git a/conf/modules.config b/conf/modules.config index 5f31dc23..7c4c8995 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -1,84 +1,235 @@ /* ======================================================================================== - Config file for defining DSL2 per module options + Config file for defining DSL2 per module options and publishing paths ======================================================================================== Available keys to override module options: - args = Additional arguments appended to command in module. - args2 = Second set of arguments appended to command in module (multi-tool modules). - args3 = Third set of arguments appended to command in module (multi-tool modules). - publish_dir = Directory to publish results. - publish_by_meta = Groovy list of keys available in meta map to append as directories to "publish_dir" path - If publish_by_meta = true - Value of ${meta['id']} is appended as a directory to "publish_dir" path - If publish_by_meta = ['id', 'custompath'] - If "id" is in meta map and "custompath" isn't then "${meta['id']}/custompath/" - is appended as a directory to "publish_dir" path - If publish_by_meta = false / null - No directories are appended to "publish_dir" path - publish_files = Groovy map where key = "file_ext" and value = "directory" to publish results for that file extension - The value of "directory" is appended to the standard "publish_dir" path as defined above. - If publish_files = null (unspecified) - All files are published. - If publish_files = false - No files are published. - suffix = File name suffix for output files. + 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. ---------------------------------------------------------------------------------------- */ -params { - modules { +process { - 'generate_proteins_from_vcf' { - args= "-t ${params.variant_annotation_style} -r ${params.variant_reference}" - } + publishDir = [ + path: { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" }, + mode: 'copy', + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] - 'multiqc' { - args = '' - publish_dir = "multiqc/" - } + withName: SAMPLESHEET_CHECK { + publishDir = [ + path: { "${params.outdir}/pipeline_info" }, + mode: 'copy', + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + + withName: CUSTOM_DUMPSOFTWAREVERSIONS { + publishDir = [ + path: { "${params.outdir}/pipeline_info" }, + mode: 'copy', + pattern: '*_versions.yml' + ] + } + +} - 'openms_map_aligner_identification' { - args = "-model:type linear -algorithm:max_rt_shift ${params.max_rt_alignment_shift} " - } +//TODO: change the setup +process { + withName: GENERATE_PROTEINS_FROM_VCF { + ext.args = [ + "-t ${params.variant_annotation_style}", + "-r ${params.variant_reference}", + params.variant_indel_filter ? "-fINDEL" : "", + params.variant_frameshift_filter ? "-fFS" : "", + params.variant_snp_filter ? "-fSNP" : "" + ] + publishDir = [ + path: { "${params.outdir}" }, + mode: 'copy', + pattern: '*.fasta' + ] + } + + withName: OPENMS_MAPALIGNERIDENTIFICATION { + ext.args = [ + "-model:type linear", + "-algorithm:max_rt_shift ${params.max_rt_alignment_shift}" + ] + publishDir = [ enabled: false ] + } + + withName: OPENMS_COMETADAPTER { + ext.args = [ + "-precursor_mass_tolerance ${params.precursor_mass_tolerance}", + "-fragment_mass_tolerance ${params.fragment_mass_tolerance}", + "-fragment_bin_offset ${params.fragment_bin_offset}", + "-num_hits ${params.num_hits}", + "-digest_mass_range ${params.digest_mass_range}", + "-max_variable_mods_in_peptide ${params.number_mods}", + "-missed_cleavages 0", + "-precursor_charge ${params.prec_charge}", + "-activation_method ${params.activation_method}", + "-variable_modifications ${params.variable_mods.tokenize(',').collect { "'${it}'" }.join(" ") }", + "-fixed_modifications ${params.fixed_mods.tokenize(',').collect { "'${it}'"}.join(" ")}", + "-enzyme '${params.enzyme}'", + "-spectrum_batch_size ${params.spectrum_batch_size}", + params.use_x_ions ? "-use_X_ions true" : "", + params.use_z_ions ? "-use_Z_ions true" : "", + params.use_a_ions ? "-use_A_ions true" : "", + params.use_c_ions ? "-use_C_ions true" : "", + params.use_NL_ions ? "-use_NL_ions true" : "", + params.remove_precursor_peak ? "-remove_precursor_peak yes" : "" + ] + publishDir = [ enabled: false ] + } - 'openms_comet_adapter' { - args = "-precursor_mass_tolerance ${params.precursor_mass_tolerance} -fragment_mass_tolerance ${params.fragment_mass_tolerance} -fragment_bin_offset ${params.fragment_bin_offset} -num_hits ${params.num_hits} -digest_mass_range ${params.digest_mass_range} -max_variable_mods_in_peptide ${params.number_mods} -missed_cleavages 0 -precursor_charge ${params.prec_charge} -activation_method ${params.activation_method} -variable_modifications ${params.variable_mods.tokenize(',').collect { "'${it}'" }.join(" ") } -fixed_modifications ${params.fixed_mods.tokenize(',').collect { "'${it}'"}.join(" ")} -enzyme '${params.enzyme}' -spectrum_batch_size ${params.spectrum_batch_size} " - } + withName: OPENMS_IDFILTER_FOR_ALIGNMENT { + ext.args = [ + "-remove_decoys", + "-precursor:length '${params.peptide_min_length}:${params.peptide_max_length}'", + "-delete_unreferenced_peptide_hits", + (params.fdr_threshold == '0.01') ? "-score:pep 0.05" : "-score:pep " + params.fdr_threshold + ] + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } - 'openms_id_filter' { - args = "-remove_decoys -precursor:length '${params.peptide_min_length}:${params.peptide_max_length}' -delete_unreferenced_peptide_hits " - } + withName: OPENMS_IDFILTER_REFINED { + ext.args = [ + "-remove_decoys", + "-precursor:length '${params.peptide_min_length}:${params.peptide_max_length}'", + "-delete_unreferenced_peptide_hits", + (params.fdr_threshold == '0.01') ? "-score:pep 0.05" : "-score:pep " + params.fdr_threshold + ] + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } - 'openms_id_filter_refiner' { - args = "-remove_decoys -precursor:length '${params.peptide_min_length}:${params.peptide_max_length}' -delete_unreferenced_peptide_hits " - suffix = "perc_subset_filtered" - } + withName: OPENMS_IDFILTER_Q_VALUE { + ext.suffix = { "${meta.id}_filtered" } + ext.args = [ + "-remove_decoys", + "-precursor:length '${params.peptide_min_length}:${params.peptide_max_length}'", + "-delete_unreferenced_peptide_hits", + (params.fdr_threshold == '0.01') ? "-score:pep 0.05" : "-score:pep " + params.fdr_threshold + ] + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } - 'openms_id_filter_whitelist' { - args = "-whitelist:ignore_modifications -whitelist:peptides " - suffix = "pred_filtered" - } + withName: OPENMS_IDFILTER_PSMS { + ext.suffix = { "${meta.id}_pred_filtered" } + ext.args = [ + "-whitelist:ignore_modifications", + "-whitelist:peptides" + ] + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } - 'openms_mztab_exporter_perc' { - suffix = "all_ids_merged_psm_perc_filtered" - } + withName: OPENMS_MZTABEXPORTERPERC { + ext.suffix = { "${meta.sample}_${meta.condition}_all_ids_merged_psm_perc_filtered" } + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.mzTab' + ] + } - 'openms_mztab_exporter_psm' { - suffix = "all_ids_merged" - } + withName: OPENMS_MZTABEXPORTERPSM { + ext.suffix = { "${meta.sample}_${meta.condition}_all_ids_merged" } + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.mzTab' + ] + } - 'openms_percolator_adapter' { - args = "-seed 4711 -trainFDR 0.05 -testFDR 0.05 -enzyme no_enzyme -subset_max_train ${params.subset_max_train} -doc ${params.description_correct_features} " - suffix = "all_ids_merged_psm_perc" - } + withName: OPENMS_PERCOLATORADAPTER { + ext.suffix = { "${meta.id}_all_ids_merged_psm_perc" } + ext.args = [ + "-seed 4711", + "-trainFDR 0.05", + "-testFDR 0.05", + "-enzyme no_enzyme", + "-subset_max_train ${params.subset_max_train}", + "-doc ${params.description_correct_features} ", + (params.fdr_level != 'psm-level-fdrs') ? "-" + params.fdr_level : "" + ] + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } - 'openms_percolator_adapter_refine' { - args = "-seed 4711 -trainFDR 0.05 -testFDR 0.05 -enzyme no_enzyme -subset_max_train ${params.subset_max_train} -doc ${params.description_correct_features} " - suffix = "perc_subset" - } + withName: OPENMS_PERCOLATORADAPTER_KLAMMER { + ext.suffix = { "${meta.id}_all_ids_merged_psm_perc" } + ext.args = [ + "-seed 4711", + "-trainFDR 0.05", + "-testFDR 0.05", + "-enzyme no_enzyme", + "-subset_max_train ${params.subset_max_train}", + "-doc ${params.description_correct_features} ", + (params.fdr_level != 'psm-level-fdrs') ? "-" + params.fdr_level : "", + "-klammer" + ] + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } - 'openms_rt_predict_peptides' { - suffix = "_id_files_for_rt_prediction_RTpredicted" - } + withName: REFINE_FDR_ON_PREDICTED_SUBSET:OPENMS_PERCOLATORADAPTER { + ext.suffix = { "${meta.id}_perc_subset" } + ext.args = [ + "-seed 4711", + "-trainFDR 0.05", + "-testFDR 0.05", + "-enzyme no_enzyme", + "-subset_max_train ${params.subset_max_train}", + "-doc ${params.description_correct_features} ", + (params.fdr_level != 'psm-level-fdrs') ? "-" + params.fdr_level : "" + ] + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } - 'openms_rt_predict_neo_epitopes' { - suffix = "_txt_file_for_rt_prediction_RTpredicted" - } + withName: OPENMS_RTPREDICT_FOUND_PEPTIDES { + ext.suffix = { "${meta.sample}_id_files_for_rt_prediction_RTpredicted" } + publishDir = [ + path: { "${params.outdir}/RT_prediction" }, + mode: 'copy', + pattern: '*.csv' + ] + } + withName: OPENMS_RTPREDICT_NEOEPITOPES { + ext.suffix = { "${meta.sample}_txt_file_for_rt_prediction_RTpredicted" } + publishDir = [ + path: { "${params.outdir}/RT_prediction" }, + mode: 'copy', + pattern: '*.csv' + ] } -} +} \ No newline at end of file diff --git a/conf/test.config b/conf/test.config index 8a830171..34296e61 100644 --- a/conf/test.config +++ b/conf/test.config @@ -16,8 +16,8 @@ params { // Limit resources so that this can run on GitHub Actions max_cpus = 2 - max_memory = 6.GB - max_time = 6.h + max_memory = '6.GB' + max_time = '6.h' // Input data fasta = 'https://raw.githubusercontent.com/nf-core/test-datasets/mhcquant/test.fasta' diff --git a/docs/images/nf-core-mhcquant_logo.png b/docs/images/nf-core-mhcquant_logo.png deleted file mode 100644 index d7d6801b65a571cd3900c3a1641ff8912f15e07d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34566 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 NNlsNZU)t#X{{b~Nz;*xt diff --git a/docs/images/nf-core-mhcquant_logo_dark.png b/docs/images/nf-core-mhcquant_logo_dark.png new file mode 100644 index 00000000..e69de29b diff --git a/docs/images/nf-core-mhcquant_logo_light.png b/docs/images/nf-core-mhcquant_logo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..6c1dcf663cb645d2364ff4d87ceadfb4b1a43ef9 GIT binary patch literal 72389 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�ev`Q}H7y#R1zKkC5n?0_OP7^FqWWeXhX0t0pNK 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

)bNtXB<>| z?zw$VG?;}cA_WMLuWxkpU`bqq^-gI`l!vzyJIgmqm5DEFjm;@^zl*oW_s|8wm8e*b zz0XFbT9w}8+|d^`xK_6-vkAYgt=Keh)4pg{f8qatTnp1$c}kL8Q8Mn_uNQo(tIlKi zpX6ZQc^`-|an(4vp*vd)^SNh=Ro#iKRpvBh@*kGgjw6S?q%KHqoeH6(_1wIA`lV^z zAiRs`A3r0$<3C?@`aE7#*py0h!ZV&RT$9)V_a4o83@+F_%Eo_IXpu`p#0RmnkYKV6>PRTk%i$*vH0e2KA$-EIE^&JXaojXAE*53ZKr9x)`Qum z7UB9BUT@5(waVq@friz=*QwcTSIWnOG4BIs|6G-zA;m{oOAc}4!>le3X(;(rUNgef z(7*5!tt5aZn8P0!173!kFHC$!crh8;jTxMQSIE;}csC5F6Vx;H$&(nH3E%(&HAh^MAf}e0nfSMQPOniL_ z7j57+Bi!(wmiNfn2t9a|2C1x>?Ls7;Mf~#%uyxQ4XbR0iiZG~93)7HJPQ|COV0;>D z#;*;}%i>vM=bScHgBHF=!NCGns4A2;tr8_sKh_4a@ zt{B5ZWXgYDXOdJtuC%DBe?Lald9&;{9%iclNek+#CCvfe_-`5NJW@!FZA`&&O&=p9 zUwlVLYHm&ldOFGYwv^64tn!6!H32EqrT>2?b9bz=kKq{R5PdaZBW0#`LK1sQ18{uJjq4Q*}wb*uTa%(>{4%;VK01*KSq zh^qcE(^@tu>pk>REghc5E4ZPCWk%EaO%C z&%%0tbPv5YmqdT&R)}mL3i4XV6jvmR@TXK!7qX{ZJj;Gln!(~06Vc5%7Z>XGw*|CW z{3(&T7JDu_+<_&!Qbi0h)Zwm?Xj;_}Cbifn__LJbIWH-7#rR}P@spEbTfxO^XYW%M zhJEnJEAHE}H`p5>4E?|@|MY1)YOBU;fR@a2X-nTo)!{n3Xe8yyJAvAW=7UAr+^*hFU0;)||N9fTIy zB@~>=9fZueR+b%uo2$%=%7YAE@|9h4K3Gnr3xsLX&S#8Hmt95P4}F2SFI?k!cZE44 z^2&Ay?B%9a<(R{>NER!X`!cultn!S|gQPK!EeGM-a%y_zD!WSZ*gKbs4pw(8pY<-^ zZBJZw0{4iaQ9^ zT8kD}ql$!cJZi)g!$|5ll7vYeP!8VLd+Mk=2qkg8GX(MjA-$f&*W^R5TcrikeH_3g z2RzjTDrfB$SYPI)M3L--)_uH^7i!obxP{DPi zM5t48>!<|&hzBc#kyj=3dbup07F$XBsm!&;-|?ih7;FeG61KWhHgd-0#CxaI2<~64 zohOXU9U8pb+TZb2+zY+0l&eo_^T46u{q~Ue|CxIAMORWHakreaG}#%Q%Wu`*Og7GV zU(<`Cn@pWKnelXBd)xB7O*ED&nM^4DsVG+&`L>C}E7;)|eoNuO5us;xlLaK?UPnWL z9oIsOax`n6NWdBgeD0uZkVvFNYZ%?+(*c2XdpL?3?WayfRx`iGtCGnq$3sx;Vx(au zeMO66%Z|@fLcKSiZ}rdp!ka9fSR9_AmJ&!TPG)LeAcVXh*qv(ZH>Fx_p?Z7S7nWz) z)ey*k3!|#s(e?>@K9M-NqOo)0su5>}F+r^NmaMFtnvw_?(x_3SS5a+IXoVT<|7f5n z-$buLmMlGF3C@o%cq8VqPK?AJsprrN^WyKE4no3s8pPF}Mx72q;$0I|xYfakYG_Gc z357U>Rwm+~cQ?0o5ZVLAvyHORs^qFRX=&JXjNyp<-C>)ib3q~29*v;gHnL2YMhrPvbt=vSuYW4(cr@f z8=UnNlqNf&edfv)#HSxS=HRS5$s<37`H)w=WnJZkdw)=f6Q~4HzGpHu=cCi6ALdP1 zOCr9WAv56gk*@9&ED&R5pq8^O508?s7~M)Fejy@&lnCqs11Ju?5*TNoMVw8rVifFj zD0Up1el31t94lNCfFJZE_M$Bg$??f}Y%#sOy>j30VgauF7cy3Jc`~NLc@mm zb8?LBF*sBh>XCT{wRV0tuIBgEOClz^!hqnpS-}56WzSQ*Z%VqH3wb{?>5ydo4tnPU zxyUu-egF3R#hbM+cj|mFzLvWi^Qho&TOYdh=><&`I1208d#|_`Ht* zfRdAjL*2={gxY5jye5M9Fzx%{!{{ykj`IBreyhrM>4S#a(B$UT4niMF_`CmYdt<}! zv8TF&?0Y&h^K-)qPt6Bqvdv`30^U!{lAW*_lN~5#lp;HEsikw`{me=8=mP$JDi?Wt zpa#P;VlYn}B(4JBW&+~lL7B{A@a#9uw?wkCvgxV=oB4M7kt}3Vvit@|LV5W!K?I|L z;3>H|#C-&2vSf0SPNeU_A;)l4Y=bTzbFMEopMuqayJ>Lz%MeuS)id4_(^6#Vsx^#o zqJb}O-d?j;t$TRbuU`6g@^K<|lER|I)?xgC5t-FXN4tI4sFc_8?ck z_s6pNjh^u1IPD}Zwz6z0QHJgOnmH*Tb6H$7o)*DF6c6r@K!6SodT)WI{mhGGYJ}Iv z!G7g_coQcvliHBmNaKOzCs7eL*ZUIhBH6^Vh1?Ut9Hgq~`^Uy{HQT9hx&FUXSiT-x%ApC;r_aezH z5*`hvJZYm4$ztvx)wS-`9#1_?{hdO*b6x)e;_Sl70nEZD-K&s5e7azHJS6&nIr0Jy z?hX=4@T`nG|L}!jp#>f|MKlg4`HoU`vDo%oI}t>JFDa7b*?2-Xjg7j)tL_sR)!fA4 z23JD&1o4a40%LCb>_Aj+KL-dDo6-q&IyRM3Vtl zU6Y4%0zY5B3a3h_CFR^*rw14cAhz554#zc6UOiEcHj1tR-a)J!uynF>Gtjm(L5vac zkXVJ}Py~5D=3bgQMWH~wV;yehqYQ&q*5boqKlP*5;s z`X$CJ`Am|30f|^+vYK=ms{$_?=mVJC$3(L1Ny~P_IR~dzTaL2&%qKA?v&>rSREbn1 zkzOFc&M>~dF3>-o5p){uFYMDUgU?T*?8t2ujbV>sTsYHiSGuKX-cIu3QDPS6oVyA4EfZW2Xu4$^yXXbD|MOyt_HljBV9W z6`249m?4$_7Z3xlgJsFO8%4&}bYl3;ZyYtwQ0-PxX`kA^+oQ_p*x74by-6~1385-` za4&r=N%(~UHR7s(Dk}VPdPzeDZiiDz89;xt4p`a7Tg6>H)D3wmCj|!yibe7T{AVh; z*4=`{Lh%R{UP?R~u#_Hh;B9SUj(aupz6921>-B58q3%Q7{#bHcIb^a=%!{q|0`7%`CQcJU~7Riz({dUF&@K;~-%)}AK|MpP z6Vq)quNDoPAyEd~Zbr-yWc;Z)i+Ff@&0EFP-0rD^+#qCOLB+7J0{)#VaJAHF?AKT} z(v`Yr>SbyflDqkG5@ggM7A>wpIw7u#q*V7aSJ^-QJIP#+3%@TSRBw}~2Sq{JXiSHN zCvYnL$RPDV$sdq;5H!BCyKVExK{i3sTToWE`yQkVVmeuft0<@iSmwbkZ&W0`8Hq}1 z8pY?Q4kVmBAl-6C3703W%N+{L$2-ptYO!Xr_!s~_mYIKk#TD0f#l(r)50*1O zT~}6fshz-2@bN`%=&ax6Q3Rtco!>Xw+yDk&7V_`#v@)#s*R1XPkO;Kw|0ka~6a zdfJPaG8moV6TDf9k{=LetjpsNUZc}^*~h?omwZo}fmCQuOonx^b(n-}IZ3?t4W_#PZ236ID--qTq5GeclbvmU%r!C#T|19f7bM={LI z<$K@Ay!9H!DU!u7g?@d<%}CWobKJz-j;*zV=OZy49x4J6K894zlL`2^25M^|_z#AL zXRIxR;0&gwh`h+Me|Am;a4OM@*YSZ%LB0eoh2dUNAF~gb%BmMX2lz)ubQF>z&k;|v zXuXMHT#4$qC6F(|-5iTQ5?njvOXssIn6VZBhjT-nLXa_9J10)*#OMc(E~FW4_y!tr zpyow~JQ9{b<=G(42t7}_U*5Jis{Ng*(?eYKObubVVF;gk1;H1)`_hAs*i5FhyV1qL zn_mH!s86VWez=1m?V;$Vt0F!bK8UlrJ+X$$yoR+V$RpVdzGVrSVUrMb0r)I=BJkO% z_;ZL~1d55oZ&JGEJ7*n_=(lfD$}1Lk%(0H%06I0>{Em<8P@p2|9wmtwi94%en3joo zs5BV`Jf6IO|8BL{_3tX)rCp({-nhh}lkUihBo@j<`rW%CNRvD3+-zQN=HxCtvKuP| zNIYrR(!Tx^zCmRB+hK=BhiGvJBknGgf?KLqy8EO(XPvTw#;&~3B2aSu>7@gR1*ApI z0LrjP!rn1=%VhYywzo8Vfkez_K2wE(bANl+7!(j-Sw4~|2#VgPke%2TlsM#>2O zLM}42U(mDn^%}D32eRO)0Fs^#4_|RAO#u$wk7Qv?pvUbXdt{J;J3n6>YPP3zAc%2| zPvr-S$1_O%i!FnFDWk38P|nv@7)5NtM)P?EpeFjkip85!G?Z>Kt`3TKiU>k@Ntcr2 z#P?Bns)Ks){v6ddC*TseBo`@*_fg`m*AQz7*N~vkU=p*%bz-r|l&0E^;EHG2hogJ7 zCu*dN>lLXcfPHZSc%61JbC4yDBXEzmnAxoc&$#U`**7>xwezv8^?kb+LEiUk*vCQ< z7L||Hhfe6z;xo~-EvoBw=Vec1^%8ZRv&%|J+Be~9bP{&_y^J(7RzC_{lIY+z4=tj@ z<}I-`VGYH;h+>$^M(_cWr_3@9AZT<{dA$!Xh+&&#MKY6opZk-mKsA(SpLEx<$y^Cn z4gkx||C00p3n8eH*|2aioZK-IBa-L-fWcVn}SELDwx)Jllb2CHe3m@i&x>cGr9Ixs~!M zOG^|wxxkH`PTJTw$Vx6q7Ax79yy+6I=BgXb-)k6Y82cgezic&j=wqQLOON1tK{+=X zpWj+L2-Kss&cf)H4VjJEQG?~4_z1!Cfu8!z!_~*+8S%dTn}^P&d(*_}T)uaQKEDMB z0M~w`LHBpvNQK~#Louu+Jzk=+1pSQ(JmX9iy~{1i%Eh*0F-nab-tJ2*b{NC1GBZkm z<5WTuPy?R>lK%5c)Rw5S8C1f%69VqqvsTC+|9xOtHLX(Gm(+n1R|+kgDIR!cZe^SRw}7d z;1&em1-gDV6g*@e4JNquZCras|!I3mmu2_8wnNe^b(RX!YgJmR@kpN_+ke zN`AvRg&|j zlt6_`N3vKGh+P?G>H$^=Hk26yRz|@`CzS8?a?UqmvhMU)n#Q*q&hVAJM7=7`g@9pe z89^<=G(sm_Xlz7mRswoTyYz60oQcfIC5`WJn*c#XDC%LR1XncX@lk5zthKr8aWR6g z*hz(MArpKerN|aCl=H|}N;ULiw!VkJdB6UT&f3!vDrVG_N30uZJ*3FGavst7@RE(% zQ3-P_&_?8bq2tAqnG~n{@01>-qa3GMUVkVib@76t>i+aY#M?422j6bHc9ILyvS*B> zQQ;hTorEx+5%Ejntqj?MpK@L-A>*grn3}Xmf~eL9A<3fu@V^M${v%Mb`npo{-kWab zY$g4;waJ-CY5_)}&t6?C)$H8ON*&Z{gA*WkD2AnI$WqGr+dDx4Jha4IECI7ORlX%xLkM2S>PMcfQAoTHXiHgre$Ng``C+UO#Tf z%h)nwFM(vfd1`y)$+e<9#vF(0WB#2seWeOrC8+#Sznrt;aTFq+VHge(W zrLULV-9kwxSkZvb=A>{4q$?@Los{c>y!(<4Z}}x7H_1eA)Vm2%hAVvAq&Gr=X3qss z%ZI$*`HOR832P|h_`UCt@YeCB?vDk`1ijIFpj0~S;5t0+y?on^xUzWvD01NIzw-6X zg!GOMi0ue9#H92NEiey6Cu+B^icR#ZYNp@eiUFO?Nfr7Ruph>k>z8L==o+C44y|SzJlM0I*>xbKB8ipr}PC$Vq1>q1lcQUVmYSy6QkL>A*e-!H* zE^(h_rDTROBbAFN7eq_a_1wd0CwYNzI#a@`n-!AuwhhFxQXr+>8N&+;k^;lb@8IM0MP++-^ot&?qrdT% z@mt^g{?3Z;HrZm^T9}sx)ecIrLxK@CD-D*|m9|IDBSIvWPqVHyJ{kM@xVB3677f>}YM!uoen+4Oz@ixxU4lLhmdnA5_Cq zn!eQCP6VBdu#5-q++!n15F&4}luzs{UuR55zOLgFrsna*>NC!J?Cp@C$r2nxuAoQ6_@4>i!6BY@q3nq~DerN>eBtm6*u#Q`uY>m(|fJDWc zpd*|pqn5K+7*%^nTL*KYS_V1t6%vq`ecJ&{84B}oF zCzG?le%RKJAo5Za*j|fNy}S>y9=!0XA^r$uwZD_MT)i18>}k80A($6~-0{+6T>DhH z))3w`G*u{EYE@%Bnl`c);H`-I_l(mxT>~H9CT$R>H^+UeV*&En!Rqu z{b+UcK~w&8PUYTj?1*4Qo4e_xVehcV!aJ`ri#6`$VfW$Z)xp#{#z~hsQAf`=ZCNL{JQMT4Pss0(=nZcMfFg6F79R(b&tT1 zA~R(|O243sb%AyG9^}`bKkgKq*>=nPf)x~SUzz6ij(RZ7+V`Tx0@d|mcE1L^^tM(30<+-Ybq|(J5AS4>HfrK@Y`q@59{K__?e~yDbZ00uR4!EC zK}u!5t72Q@REmf9ef}1&kj+`|1rPau?7e4LlUcL|nt*}|f?biOV*m?CliqYJ5NRre zDoq50&=Eo}I)Vj36X{I^3xNQN^cF?INK-JOH;EuM5PH8WI&)^uzx(I@y2r;y5Wa7J zd#}CL+H1Yt(sRHIR6g2vmEp8~O7hQ0Q64&M71Tgsk88tNxxjo(9wx)T0h`sq| z-+jmooBMZ@jiGE-*gmkv>kNj=$T}!&4M)q(!55f5%Z(GcosT4|d|E3xdyAi^_C4q; z-mLDspr#q(TccKSJ#BnhR;b8*{Z>RnPqytFwsGD-TNp#bd~s#i@=Zn>R7dH{odG=V zEjzmG0iC_F<2Rmjc+ASz?Bd+@Z*OVGv|S$U|1kgPmh`ofW5=THE9z!_r)ylSkINmZ1eWMzwCF?zSCFis*iGcFi`k zYD=a;zP)a#hGVoFP-V@y~+3k@TTvlC%f2$OI1P|G!^I-{prsVWfnhL*D9WuEG%F7halz!ZH2XpvsY<8@T%rm|I`2-QE9YwBdfg%fW9$(nl(O?t55KAGXo_5OGBX>O5ee z>X2!iLc%>qsO@~@TR_ML0$K|v5B~j+Z-XZ3o5>z)T}C(v0e*llqgNKp-Eg{*5A|0* za<18?&8I8>;bgP1eyIPeVV6zR(~z|V$Sak@8~e9UPY2vTq7giE9C)-O%hip^;sG0q zn?R{ueXMvHcK`jfjpbhcYWY%|4Sh)Oyjk++AF^4UKJs^(+4fE2+V>^HJOD{^$uWQc zGc8OLb2!x_h4&{4#$9rmpN_eE<-zZ6L5yAaT^M%c44@vI$$NXG4@G~lQ? zQ1jJdXoSk|Iayzu;h8L6^SB^KADru%fK^5<&PHzwc9=}oZC)Wov z(Aznjh8hwGeV1L!rn3pS=9Pw?1%V~VN_7_$8riDzVs9;OJ_7*iwpb|r%io-WckJe- z?mly63|@PGIaZWERDWP0FVU32W;rZvc|`?WL|U7$|4Jos-R-tlW*J|GY2AHs0Po8n zRtq0#a*n5$p2B9Ek=6p8>Q@(5J!_;HOFuY*ag)gpoBI~hPo&OvtvIV&zgzw26|p?$ z(zHzdk>^&nIy}~@-!qeaL_x8nnZ~*H z2KEIjY%o)87k{WB#N%ZhMt9B#dA6OI872iRt}gNKTdQ5w$_@Xd2(85>8L3o07)K!YN35gNuhpA z5vW2wE_wWWHp<2B|1n3l4a_u!VnH|{i!bt%YnAb%N!Sr?Mi5WuTx zAuV+a^foQtuzcdW`_WqoDE1YzpRs5DO&b$SS!5p}OyNo;9^+I9r&h&LD;`zhv~Sd? zz2y3=sA)4{!6R8p%x4W@FAaitre`9|0MuV1C$P#H4JcDIAH#r-*z}LhANJ3 z?DXA4t=*P22ki}NDuR6f=RWFZZ$tB-lYo1doxj2k!8Lb-s)5|VkRi$Yf4IQH z6Jg=y%x8h>Q>UzTZ$_Wue{%|{r~(|C>%!x=M;6X;YDstxe`qh^r#wIOyVBSWm4-r? z#xrHt?@j#z+uL*v`E|av^@Vz$oVvd1dm~#VOlB$i{FWQt|x3nFm;wmG}C^^gF$RQ)szPcNIzX*)8cAU33D>toh^o2)UUD zJV0dXXuleH2p(B?p`Sz+p50g#aWtZzPXJhMkFNlAigfDu!Qvh<$*oe^*m|7v5$ImI(ekqptUsbJZw?uUV$yoS}2*z*x zZTt)8ET3e9Re7e)_1FFsnurlt+~2w8XL)|Cv|t#!TkHI`kNIvf!wGVvZXPgk^q#9)a9 zqH6Ihko*+P)l%1cU|@v&@XoZels|00fy=BPq%{6#w=bYK1_uVo z!ieE3f}H6?@D{5azSlQq%x*@b)~x(4!!fQf^DI!={eb&np*cAxBZPJq$D1^8Q#fdH zqoWd$lF0doQ3p!*-~htB%}6mNMb8HRFgc))Zq6z0l%pTQWNbRuS4QTDsMjs;E0?EsWx95j3)lAkr$ zmC0QQ$>39MBr<=P2ILG6Fr^BB$Qc>-pzQF<3Xe~uv(TD{?%EK@GFG7E>1_Ii!DNX* z-wiQRH}h=Ow*NADB}`Q@`(Z9;FG2wF5X;|2YViXQ(r_x?hR>`D;SSv89-k?+jo7Rk z4U@aKmT_gZ;PJPk5U}8orR18h0!V}C#MDA^H6nVm5ICa-tjOHG)mdrhFSeCG6bk_* z_kM#Ft}`skdSVE)YLG_{RzX+DW(hg~CGvw%V|LA2qlY=ih`J&hdft29CAJH=P=()` z@rXCK!26GLQ0v}@J+_eWKH-j>x*YwMaOyZKi{b1XnL_=iz@J{VA9ryObU!xbMwSD~ z$L0m@dH~+pm79@%=vMk;%a*Ae_FSk1|FOi!<^9ik)1FgS!ZN~MvgsqE-aUL8knz+% zrnQl))P7=;*g)WNS6sco_F zsz#FOfrB)?>@avw)t`NREzb@MBY^qaqbLIULEL2*+b5YLQ(BUazPZT<_}!?3N3)^= zzrX3}-6<$_T>;b$-Ts{mxNFy&EYr>~IQ9WV^mRK+zrE~kOWyK&sv?iF`KbHNcI%>`HH$9clWjKJX)SGdi2#sW@rE4i}NNd4r5`( z_e=}IHKX&*7*~8|$HEVADk+EhSP75@Ls&bBYwr#fF}$szj|A?7;~dUz@0W~&Ow(TB zeP6eXTE(j+IxP+xs^aZ-v|Zl5c$K5OUsM?FpATIUN9q|l#O$VuOQmA+20@J-W$zqH z&G!kv()bp_`RGEiPOE+Y0Hn8PYUow~DXJgz<)Le)^6$N#hLZS7*YBL^cnIiuL1C z(;-I(_Yeot3_^o!A2?+rV!bw|ubu#W{~BRb0_bG6UOwPKq9NV1K*nwa#FSqSM~RMsjgh_c!>TDDpmBN}#eqSF%RByk^2#rQHCc_}eXwFovIg_z1{g*nWowrk8 zi)V*+trQE-G2GZ)eagSj&K2*?-Nds^kMD!+%(Du0XU@9@leTgqy$C@?=^NjEB`Qza$^UxYd${8xC-wZ@1!Zh)^p?;Me zS$%EAC8UCP>I<|6o5>ffTYZWrHhPr%9msU~;_^`7v0M+n-*_>5XwA4y__Q2%@!b5> z#QM@{>)uDLqFM6hq>;Xj>*XPqW1Ef9#NzeW+1jtB0}c}*6S|U9Nf}*PVSR| zvsZPPQ@ejx7)%!(q3K`+rQ%cN*y3ZUAb5Swnr>F>STLKS8UVAG^AZp6Z&=^_EAw-H z+UY0Y;3!BjStr-ENG%%sTwOMbu4!t#)Y$X((WqAb=F??8YegFCjT7sB_eYqmT1@9L51FJ9KLB(GViOb&$As4U5E zxU7W41#ml6vMBb(gY%}_1A)f7k`c5OO1qAH9+p0^W$pLD4O-ac{b}_!MWun74JV?CWyyAokyp_3QE*%Ddx*1*JnD0J#AYDMwV`G3C<- zr5#{wH$d@c{|1>^gP*zvO&@QCC{$)3Mb$dU7YF|yp&##m1EIq^^a~jOHHVDhQZkYy z0=x({24D*Z`P$gAETKp~pNX=xyim_!N6x?33UhG$>$)SGyAMm?2gUa(WpJdIp}gmD zT1Wclz}FRk^y!rT9fYhIAC#zLiCMY(_x0b0=N=hmCmRB_WNn4)1v1}p_&)=`WvOhJ z{4QTm&^jm$Lt(?TGgLCe%Xa%ZhM31@CjJf~*3vR}LOm5m_WC8(T)Y9k@p!Hm&aiY# zMIgeA;r|xD3&dX+f1N&yvzTyA$lzS z*4GX;-yY#uRTIT?oK{BNIya52Le_%`WFPk8XNU6d_NN8fZY8p6-SMM-8$%} zW(`W$ZwO;#Gx%+vfZ!jF{{OBqYXFMn-*Rk_uRN?;k4=L`WG1eNPR&9dWy$JaH2PG$FtTaLSF*Xuph4H_${RUwUdoF7A^Q&7ki~V znOz4qL(Yrcoe3)q|G5Kw`#)CU012;k|2I(hb#Dz+2JbG{iF|0qTX6)i*2h1{1hLxM zHq8jFPTAizJZn1NoPR-3P#~~&+3C3gTQTbaQ^EcBU}glE%zSsUgn7|91y&)!`kSc+ zot8RT@btbO8QrANh~e{o#?a~c0LvH6xh`9FcH5h+zH>0UJFJ^iLBja!HWb<^H|}e) zjc{nR%J`9EEpUNC*upuS7Lvvm@;yKLl=6Q}3X;AAE*7@&OX9xOSIzzG&A(2aYePh* z9^kjy2^%oeMMGnuOdqM8lsJUeq^%`dH~#)tKXDd_H&=(mfp>(j@O*Kw+FP` zO(*~?26T>puj3SG?y5MF55VE$@Z)?36fBt};0f=MjXlt}F0|^N#$9t>?F0)K)JR(X zeGf`bCss6~HOD3mL*5UL;?zAJ(Zk%vHPM2v2cj0noyDGzY4(EP!=7cuUw#c7S!2rt)E5;OdqrIDSgu zLvJ5I^Q!iCpCVVu&1=r8W#?NSf&BRIdo%6*L>l?#ktLsOgwfveP!a=0Y{k>SsrO*g zvE(7yv%hFPnv2-ic4Vb^ZLsA+3(8$+DitE3ns!kFH2VJ-=HMUN1V3_g7<+~}#}p^j zpZh?eQ_d1PA=B7F#@r&66!suA8rh}?397S0e|)xVg?M+9Z zmE2p7Mby-5_!WPKEs7fV?}${^O9v1d$f5I4xhbO}@6kzxd4&|JrOP&>kqj2h&0b6hnjM3Le^+ z$)XY?*|{>z*>VtiLPPn@MKHNAXn-Jk2ikg$g=&ZCBa9)jxbaLr{wDRW{S0kcWn$-K z>l3a9gVWG~%fZ}EwZh%&hG#XJ@4E6m+iRElLL`ieQ5MK9Cv>!IE*AXjJ*M{2zN%~^F+Q%6pWh@8`TGD)Vm<{JP7p) zl?~hcPO02$H+;gkTz_KOn&m~OlmDJt#Mk1wv0suW)Df(;I6`8WPuI^9n z$QSUvn8IlY^Zm2mn~V(;S9HjhBgYuBs~baJUXi=plJi^X{rCRPUjiCxzb`w~Z0hfn zWbKrw_GzFoR9+6@2tg)qA6KE{G`3znE7$KO;@$;*^Jq7!@bSNU30jRfpue{z^FRx% z6 z5lu+-Q`P(Y&kD0*J|$ObN?$!312?MZ(hKBC1xD{C=wMY5$)7y7L@9y7IdiSXD<&*aDpLG9<57UX1CftLX_0v5i)*lOf z@515e!robJEnHb&eeite*i4pLVL3aMQCv_kZ#ib#H|&Q%AVRlZUPQuI)}Q}>eBbd^ z1%b%-CXRNaUM@7fJ}vAO_=+RcXO%A=eKe+SPoHU`9pV zV*%g1w%&!D4>(qoiHw5uzrrz$1Hs(*53{jceES)m21g|R{A zkKv^zZuWOEl52rhE0NV+smJ;AYT(F{Pqjcv zm9l+LUR#v|!|!3C2B#1)M{q18#37tPGp}pg@akc-Me$o0zm6n2;drh-$gLJzQs8Tf zo?AGCty>OwJU6T@lPo#L(3~Hx7rvC+6PFX@MiSh>@g!@GHK!$+V^@lY`w$3c9n6G| z=QW+&D?M)}=h9@lxhzxYiL_3^t^}kJRX(aOPq@Bv zSaH%~iRsbZB@@*(Og5RUnpiDoN3=ehVmHqrMrnIq3`d3%@PX7atGw;ooaai5<#*qx zv{hhoVyG^B92~A%oF_qt7NX~ny` zDz~r*SD?W@>8PryN0}15>4fLJUb3$07pOMQcvSP&r^#ix>}JXurf}YR@C8c2UNI!M zK5S;VNMh9w@d%Yg-0jt`JcHz`(rAks4EUjZ*S2=>?d>&T;^%K9>s)+xb- z-lBbDb1lP-66Vo8CL8&~l0bJFmPa%+8?V+^uWB>6rIaw8TeJ8Mu4RwrqKrkC z0`ZcOd2!8aHW*CGBl_XN>3)=h-PlF7%0h01NcjC2D$dTgxp9a270g^MO7drlZCGlb z*-E33hHv0ge|x;9=+X<+@byLY`1_T7>UEOZ%zLP~g9om4L~ibka9DH=au4^Kj1(}L zaQ!^*aNudBr)rf{m1Ra`-2joOhHlbh<_jE6P?s_{uQD|%cJRGXYGhxjOc@5Z_0io- zMj29%@#RW4f08n_olv=HZv4aa4=}0@zFLPl!rhl{wB5$8!FP4NhKxN8Hd|*zY54KOM z>m^aIY3kCCbiQrs4t7iSzAnXUd`5`n>-cId<}|Hy&SJNR!kx4U*^_Rq!a0Y?+a$2(c@#J_T|>h8 z?-p{_5`+%DB65lF1JWpgacQRQ%brD z{wm%kdARv%Kugl}iUiI({B<|4oyl~^UwQYgEFw=2M0D`E@#r;AxjVYV#LB+$&psvo zpo_3-ieC_2>VMOx8d*>!L`d)VvK%V*Z#HU=qYo-w+LeF)3)`_(XG=^<9KB0+Pmo^U zXN`dO^P)@c_+r#j=tOvXBvDzJ0=WZ+=ep)IcflfUU}gRY-{&Ix8@Zw0=Ud&H-F1~; zJ{$R?=Sljv<#cXdX*Wi)gAbH+4L_B$+xERRkXC&;Efbmz_m4v!&q)bZ>`Q zdA3(-%*&|)Y1nQ_>T5>P$M`O}?2ft!Bg_dk#gVl>GYp1L z^ag9kWu72Ra!%kYZNgt)%`OoR!&JYpX)W@8?r&YSC)niJ zV9^dxYe4qJjPMF8gEJ5Z;VAF$$s0W@7c%1#wt${_jc#K?e zgjmOihgTr;r1#GRp_{r}3}^BsDdqTz&)oVvFNi`3bWVb*oW1SI7C}BENxu+hO7Roo z=o8d_hoj5Bmr7OV9om%{U>dt0ITNzQSfe}9XU*p#Yrb|duM2V3Z?0raq1*jkPTiK z?HMdSSA|herrVJU>-{;?tBK0;6j|`c9HSPidiSXHGvN|Ts&_}OUwz!4#TP56QS2o! z*;R!S)?&V(b!rAgn96yT+hZ0L-(o@(ht~SyiORAy2bu_kWU3O+!bB7I?msPC&C1{4 z4#Y-Guf%wG_Mj_Zi zU9IL~&P$)Dnpz7yok}X?UEq2Dov+%;uUKU1A@}g&pT-kuw|;rlp5RcI^r@OF{Bet_ zVwB?RC1(`HTz44tRH3R<=zIA)I4g)z%~D>=BYf)tHV5I6_qkW9&8Ho9vo>PEBf}8$ zQfz4&)qI!j{j+gx<}&w*b>E}P>=2AP~GLZl863+6AIjG9k7}Y!AqH1Vm$`mYqwd&c@s7$biInMsT z%97p3GnAZDMWlL8EQ7Dx@EPJ(B+G2$e zC|)xvB7CW$r-E2^l+tY9o*PPit5DN0WL!jZ9TBv@KjhO$obtGlz3$$y62c&kKIW_S zNKL%%Fs$gDXHKX%Ny&@f^X6bAd|Eg}l-ouO&1_8YMe%yYGZ}#Dbk~n(7XV zofvQX@Mq0;Dhu*|xau%paNjP(&GE>}VdhfM!G|f1@N+4g$PyI=prew^e?4Bq`s!Bt zckb-7sU1o@4{%t#v4~&g-jEj`7u6yLmQj+9q{?jEqtt(mEwV83j2M+gbTFcp6IQ+O z(Ws@@C8quLDG7AR>`{%V6HA#yAu9|+pUI0}w|x?1^wof{s*6!8!0mXEPHf61Zp6|h zpN$tdpZx5uZuL!NOOgR5fH+D*uLr=z)O&oNuWmb``IOj{M{E}H!>yJlC0U@?gYX-s z82vFp4r@~kHJ7-Yg$hZdlP=FEWDnw3J@FeDjN}0>Yw=@)3j*l`!m14>D3ho+D#(Et z`mjwy9I9h9GXSOBN# z+h4wrGsW)Abz(K2L>w(4E)NiwAD}kk>D&1@KJoXDRp-J?u~ zOyuUW_2J%RJe`D@Yr}Z^Fr>WfR#RQvZ{ph?X0HkKsc<85l+)59(<#_YdysC%;W0(7iBrd>bP2P@U0GAqTaKYI7p3f#4)Jng@)n!WXG@r$7zQk_zwWl975!OzDj;= zM;uKiE|XAJI?Q=gbo3c_>#=by<|xtM7PGW|%TYy|^0Jm{Ya)a3zKpNdWk&XzTALbD zw+^yDF0MPiSs=BLQ($|knI%NViN$447d^=En5 z5ZRyE4dkB_eT=EmM$`>0W*j;->4OfpwMyk7%1XAA1LF|+g+L0ua`4KAc-VB=Brm=~ zVcT~1Vxs>A)r#x3U<#}3(T>X72=PY&-tvPVxcgG_a*m&WB4NFnD&lU4Z!@GOCAT5+ z=k^4*KO!oVh`o<&toqtSlrp?f)|RPH==w3i*39D+;V5(Zm&=%x6neE-X$fwh$v%v? zGp165VonffRpBKR9-%M{soAiDq4yMzQ>vlbCn{Ir;gnVeZKSH>Z)D;Uja_IG(r`JKBSm211Feae5n$@#ehhAM0rv*L(Q zR236hGQ_B5;U3vJtfp>N(l|R(htfl|vz=U4%p@uYR9s%v+QmB%YIoBHQ~3h71ym#U zCWT|)de00!CF-G>#(W&N!cdsPY+`Rx`ljLxoRAUiBf7T*U_YHtU(vnhm_Dk?CmFEK zxsF_xgSTX%eh)86){qkgff#tqeEatkaJlLtR3v$I)khyU{(qqN4Iw zxPA5me3-fV%CiXaU*n%H@syO{9*JCEP0fPrpX48b2+e}?#u`&mL==L@<~ur|mQs2T z8(}bNk~Iy@wgC=dcG8w0YsMG&JJ=Xm8e%lMf6XomMsBjg`CKCOxGj<@P4r_|| zWi#|mj^*VZ&o)GoIgYI&@-KpE!g~*gN=zpbm9ubnF_$rU+RT|sFS1M)@ujGr+pexH zE%jzLYm2PC{L@F&F9eg)sj?+s#OH&YG{QL^z|!m?SoR_eqT7{1m#93eV}Y4?Mbyw@ zW>glihH*go1?2di4-rExkyyTRElQgyhIwAHJ=;bm+z_6UUL=>g7A%*`wK zxCI`h^F3n>^()Nan>iuSn6ZO(>vwM6@NTXGXG?QT9m{&VXCi-@iyZ5hLaIdce>ykk4;~g9x6V%OF5E+GLasVbb}1gHop0R%&axcio760v~g2KPGl zng_f)?q`olVWG}CP=O$_$G;PmGk&?PsGlighruO`^1FI7l@$` z2fz?p{R1(k1AB~WE~72m{vG2LN~4Q4jZ~L}`Lo$XM&$Fn0c~gtQ6W!09JkT=NXTKb zBlww##7-*fvZgFz9as%v08J^G7~q6S0f)(NPmH>o4Z` zhP9b6s>fvp0wHx-?8Cy*oclfKljDMHh}anL53g&nr*gu3&_Zo0=Oi(64JiH56!uss zj8yJPJTeh^X-K88oby~`u$_s?;l4H?IK)o?;yy%gASyrqHH%VQs1R}VFI3*duRAC7 zn4f!^j9eYILqSvt(yGaylKS7n zc(Q+fg#N;wV)l2JTYZum+->yL5i&Px zKVEqeKX1#*KPaTp8k36be-x<1CZ(V$=I8rsKZbgd`+mN}tLDQ**%)Tl6dppX3<@NO!;F(I08xiDK#g{~%d7jrjEZ2>jYeH&|?)9*$A5|%2 z`B1*w7;Kpg)CVxp+E`IU!`CCMsh_huIu(?Id*m|zhC7>p95d;O;DZAafv9R&N8uvt zs!%Sf^L8crrYb&BdF8g^RdF)`tQBVvR^wQCFrkDJI^m^>$JPxFLE+*#=Gz@(v%{LP zSQfm)+5vBYo=27TEtZMZ$P0;m)A&Q$)l24S#AaHXf0;^^n%dM*{?DceQ7$(ER?ZxUH`k1nEDYkl;E$pwc~`UsTvOU^M=$^ zT4y8F$A+#KnF**3HOgMJdY@Uj&54lH7{NGt&h+97ZrSZPw;#>%>2BkK)=8DBHHbgV z9o+EQ_^SzYF21IP6RrCNaJDcr<3+Ie`dA%fREu4F!F|DYyq=0U-lRV!Zm;TMm58rH8qFzx}=+o-6 zn*SPgGawv&&FTfw2j!;~j@}-v<*Ap$EW$K3x(C%%kb1Z*Q*FkFiKsT{FT10JM5FszPd_{k zh0{<~mZadsN~MZc+g$;YI}LDNX=WjLYr9EH}b~-qbL~ zh*>HV0XS{lJiM8SWnI~~KQ6K^gpc!PGn)AqO8-Gv+C#;1Ti`W&U_M6hK%T}38xBY`_#I{G5BsQ0i*Ns>(RScr6$rCh25m$W5sh`(yEN@>9N z_e>Vs8X=i7K>%eS-Kyx6c;j*5+-7V zanoVm>Q##UActO8qzD(%)caH#D*22NWl|JglwaVmV)k__{DO#|E!JhE=wTL-K)9Mr zkC172HZ)aHQdr~}puW;wrEe?-2;)LAO}$H{K@CIQj1HEfoR@wSfSN4s$u5|^gsD!V zn^t=1d;?4^hQ5YA=|bwEDmB|=69-{OLh2X&JtGeAx{xe-2Zn`WiA2=K0g<~$z5=+n zE=38DFYs(O;(su%ug{DuiB*dS@`)EJmlKT>iG_vpdn;wd3y5YT?&R z%A0-iZEtBO(Vi5=!Lhx3M!0Fd;J&6$`P(`_AJ7)oA4{>lHg9M0Zdd}{TYML@SXATN zINdZ2txv4Y81dzYLsN+_&vy*F_dKG<5h`4|FI*paOUu2;Y(Ytqh;<@MBisckO623Y zhzQ0qH=#)VN&2E11^YfgHg_L$2<4VbERfw3lDd;{o+kox${2w8Y;={{+1G9|1hra> zb%-p*EowJ8SiUBcmuDgeQlxc)096Gco|TOUn&MV z`PgD7l=#$ZpbTieqP=NW1OM$bTcL4(bnXk`93K}%SW_%g==)`Jt}KSq zI`yOaj-Bw*_0k9LqUrMQ?T^vx__=84-b8ra>1q;|L_XNo^y*whoSZvb|WXecx# zCuY(*RS1DDc&i6z(r!zCDM*}m@IAfQPwTWb$1<=a-Fbln8Z~LjHrWKUYR&}xOeMSX zbB_ml+Hd-blL!@x6yrkLx&d~A)*DvTWx}yqNbAfXbW5I{wi_uD>((2b*EdpDE=iIN zbO@aA)hNirJ$-nCWT6zip(Zcni`w=Su`pDNs(wO;Xt8QD3mDlWHtu4CohYMqE{OWM zhkNMq=%KCU0%a(>&9J<#q_tZ303e1gc7lMeI$T4H(=OP~z$*cW!D>WU8JOls3WDj} zuJm#S3M@dTTRiYBE>^_b0z>p*;>2^6hdNop1im*oka2ETDMD z!tG5)RBApSl0?6GbAsQch1jFe1n~@MHO8_r`0B?sW4x+(%{Kc$rQJ$MYv|`>Tg=K` zuKuy1Vb{w(v@j$)$bCNsut`*nPF}sggXy2HJjOK==v4LGp9ODZm4QMOSsFqyex}%M zC3TiMmp{85;1C|89ZV`LVxi^Ixg7Jro5J*KQF+bz)Q;o+W>ED13`g~WZ?0!K_jsc^ z`^99PO~;U;WL1(&kJpCBGurc%8S&?@QB&G{pWn32HWmCO1cj-44dXcs+6Lv$vRKGmFZi9E)u^xVAw=P zSf9BaOlI}50D=(JC-hu6wDbm_sEVpHrg*aB?T9Q<_#yaEoRu+ig!yFi2YC_e`^1Md5LV-w2w5u=vQXWbCfWB@g^c(0!cJ(+ z@qFznNf~yVZ$gq^05$R)T?N--2P?OCJuURn45y~LfuXh@eI)BRxU~9&`^5LA1ZfMz z0RVvb{{ga}Zi|UE=B{=9GD?lAa4hLQb%QDOP^JyPhVUh z=~d*J)volqIdqjH^znP%M<_^zQj~~*;h)Y%chbJ<+xNM6eurFmNCFzjU>5i}r941pAj7&=g!0x*`uLX_5-tVM{?P)gBE~AEYIL$o6MG*13E3T0-J+tY zSrE`{{OG+tp4PdJk{nCPC>R8zWHKfNpB7|ijMuzVdyNZinipBBg37+~ws^WeG`3`$ zQaK9mTbdBnENSK3o!;Q16boqkGpA}U9x&Dn@L&iCP7sebDOOSw$hwuQi$qpOi-ScbNzDO{^tL^j5h<5hEUQBjjROu^6U0`F}DIDd}AK@RxW z>&#q+AR=^SHVnlJL1M``go4bEU-f4_1`h6`i`a>1!qrw-3_*~SEtCX#y1O+S2Do9& zK&VCXn)K0BG{v@QsvOvBWR-Vx;wzLGeNxKGX ziD!Bq(^t%~ebTWyCPI0iFO{Wbl)7a!jQY7S5Q4gX0$UJ8k?(n@L?9{ZLT*!1PMFbs zkM-yLd0mr%a8BGCT=gx2(A}nt@?t9rG9t;>l#CAZQ5 ztDy>!tz?;%Ks+ZLj@7swRo#lyW5wVx9~5_F4=v!kdts1mfe4Tq_V-p+f*I}0bKI~K zL==cizJ`URjuZtoM(L$)d!ad z-Mg{@aQ3_iMjzK_o;5l-Af;LabD6jA?K;IK1xF^BbAG<*T{<{%8l4Chk>dGq+}{nJ z(hwvrjKG6TWZ@Z9ap9&5Ua|{Ge<}3}G_9#wZT1o`5`aTDoLl>6bE9GNFc%n+?lLI< z%-yPKMDQu0ExHXp=c4Ne%ZAq6VVK#02Cr=M&FYA|?|I$bg~3yAn}&!+6_mS9rr5r- zUrWu~a@%{sH7aeuKw>ozRw>w>K!*}Nf3bz3MT4X*rIu$sPxp>aZ>fY03a2Cf3oaQg;hV zR^xyOYZ)P$%4yCOLd9#=T;>XC^I}Uk83N>3sTW)b+2`QI*&ah{4=cU$-S1oKJbd3= zd4n{e?RlOdz$O22tP{?^pZ$%4o`dd+LnZH9HNXi&*69xuJgCeAY4b z1IT^DiO^6eGL&+nniqJ;LH_3$2rlrKG4RGK09&2rbYp>@@iC=)AMOn{L9@cE8!$ga zzAprDdN-68TsT|qU@3|90JRcHIFW-AyS8Zv-yoG1_2);L_fD`Z4;fWjI-eb3Yp1Gci3~Y} z_2VIIpOB`@iD<$w*ia}-CUr%Q*#t*Xz}(5 z^hv-e5%JGe0ys?$!4BHh-b7l5Llm4X&Bh_hrmAFF553mCuXbNh{TM%#9Qg}iL3)GB zoiyIgCN2akNOQtBiUA+9o@S|r#pM)MXXrr=7ga$poWvq4HZ3^momd4Q#P=SKPcGdX z{Ny|0X#ue_=DIOHLpCxgPh(!JqkOXD1f`eOc|3>cbVt}^`~S?Nqe}&0;oE29ZPMiD z*O)csg~pQRc;4MKq)MZsp!<6VD?lKOF0Fs`=|dQr)0%+gbtE9NXr`%zKmaWRtbrf!57`Z&OXF9~0JVKP;FS)+J(yQ6VIM zQ>kMM%ETc=9rT7ZWmGp+6oRY9zj@v6Me_{|3a7FO$J66o*1u{($@TNww4zB>B|2Bn z6N9f7w93=-Y}}Qz>(tAYQKdDD1Yz4Ugw$E6!O2hfa#T(gl*hIn>mZL0Y%R}$@rR*~ z+Be?HD!ZN-QUTf2@pQ!lvvWP18W7vjBybc(DlR6Ttan$N%0i_XZQ?*6c;Wy+CXZfO zG}RMZ;K@I|g1`DzWfMWRcyF*ew4ey_a-y;{We~4=n6kuIG+?$_MRreIlf?=r#@mHw zPpEnsy(>)jA^I!=k+TP2Ve8M_G{MC8&7OcOhi)!=Q)qAM5%sMa>Z^CaL__8x>gh2p z&{Zmwnw1x(uL>vLr6!;--rjg#v87g&FfOR_SnUqL(vSVm5;uZlTa8&WgOBPxGW7O+ zvjtQhESkgaGV8RHqjr6wh)xTpsIK>^L+Yn1RsCJV2#AixV3ECgALAd4P-D|Psd}gySYUw4> z-vX0DQ)-ow35N$?^fCl;iyLEyPE)ec0@`_GGg;?b z|FEoc&s<97Ov9(m=-wncBYX6G(Ta@Y7DOl&bi2PNV6WHZXWA3-Furx03EDG=1+@0S z8c?&Lj5A>!j_C5eNhO{HUx1g9IDMhB__DO*_G@jr4#_p=drEukrl79jsTy zylAi%G?>X_;#XMx{R5-kE$kQ`a6K{#j~6HBN629Tm)b*c@+QrUx8@rG-POhY0>5g zTnC{bg$7v=zPPSk27x$j?D`qJ+ygFHG_GWqLVGD|&d-C(X%dOR-A$r27n<1kty>_j zf6Xmk=Jx;7-nWNCxwd`ZqNbIitq7?MDk+;48N1c0XfjxBM)pKlYN*UG$+mi0ict5I zO=4PEjZB0TnX!wcDVrt{#vrD~cC2ig7@PMTJ4FVrXjFb|A8A%qiak^`ITLnrXmIA4E{K>>wa!xOhss~xXqWVUkQxFP}r%)EIQgk>EvWmCL zHggKg_f=`DEXZ|zfc`qf$>QInPXrq|xwCQ*h^k;i%%BU{7lhzuEtf%JZvT%20B6WQ zg%qN8fG7NR(smb;>>PV|^)r{15rQv;u2*y&4Y znD=*)5oa6z@re4rIM1cliJ2ZpN2(=uOEZ0#Z;b{gN_0xKIVdk4(sCkDeP=Ns=VxXJ4-~ke_DfE&4wh4lEB;a2@JazJuNB z^`Zi-G~{_~`~^(v4OhdpRI8hUH&_TH26gmnw7T$8{*-%4ow11xaff;g+TA;XdaNg8 z<8BL{C-?!gGxmb4rWzKFr`~aun#PCmU68S-8I+Krd_)H6*;oN*(E=MYn>KTJA#gr$ zR|gN#GfmFtzH=o^oEAruX1;|JrV{s^?Ek;GRNL2$IbV#e`_}jb9ynWviOySvIU?xD%P)s@4C__q%o&RKr@ zn#%R7YWwyqzW!RJ+S&TBg2Jy?U+ce)QLEoX`za#g*4Aaqv(r|6p7>KuPEKzBFZ-{q z8mnFT>(!NMD-F{K+J4^JEw^{k1_xP>bR(j3`HUB8(|=b;+E0&m=bviftz8>ADJs7( zGMjsv?|{~6hy9A`_!d>rK<~M97(mAkl#;x)!8kpUIJO+l+NZBtRC=xWfXInxa~;Y$ z@|jQOLgmYhb%m=6J<9UqQFAShJ4<3m-Y)69E2?0zt=jn6+EYS2SRQPAka9XH$NXnG zSo-T?1tirdKBS&|==z-JeRcfC-8i|T!hkhVp)YS~w8`zpRV_1%pdb}ZoGjVgtEXvY zn>e#9$x(iJXtx<#@=9d+i0z3Adb!Xj8FM)c^kaQ{hhEu}RXf$yy<+OFD^!_N#E-FT zYoXH>X4=l>M`x#HQ;}|-YBLsr1#|mKTZtIbpXT_<$P`~Ld(1I%3&sSf_~=2vxcC`?wleAf_%6rFAFM`X=&n5QU9o$j07-c(%8N^w!BHOP`B6`9`V ziEy|oq!Or?Ak{Qy3#8O5J@WlTV+DM$sfo$dw2Afl9M~(Dt4W)w?_XK4pS*o9>57Ji zy4MxHFC`|>I6IhkE=zVt`)+*K&p0_-e|1m{&!mb0d0UdRCMuCI*2~@O6v&UXLx-$| z$~|dWvQ?{R>0FuQ;eT;u9NWrmFl~Np_@M!4Gh`JwfGICw3y-~q`}nT2u${4!8;e@_ zDO#nWl*GOEkC>Wpqp+o0bRAQZwoM&Xp-{cUzVV8FLcls+MGyE2CVE z`|oSjl@F=sGwi2Kah&|?3NPO9URF1)!be2`UC`27n~LAuBt8q^Y4I6MmJiBHXe?~_ zawN#?0wqR^{g9on42Buf^BaW!kSb+Q;O2WN$6FW{2O2L~3A5fBN+#ba8+!d1tbw@}&l(&$@pRsJ4Smpi}Vu%n{a9)31 zLI2%=l(25FFp{(ZwqPOMdg|NoNPdZ57blX+lx*3MBRQs)u zy@OntZ_V24qJoswWB&Z#iwuW|weUMtGkgks(3t>Y;Csi_!*nu;_3t)lcmDS7c4z@))tw68Dnvh>3A**_G6I6U#3*<4k3dmw!_whQx9=d!|11g+!7ybc zvAClUALUQED${kN;lk>0dtR%%70676J`SmIvO%0QsOsv7*Sg%n`#X`Uz{20^I{HQO zXhb+AaorL8+(V{^Deg5ZhiP`aWmIQsG_9DJ^WtU@kvbX|SpMw-m1yBbS=#0;714L` z%)!67o0A_fH{KE)m#VNci3(?t$Eu)OL>8cv&%PF!;*hHCP;Cd^q1T%xt4S7fnpUf{ zNe!y$3YnI713IcI?SjAe9K`g3wB%l`q0Jm1X6(T&CH*-Lpbwm>NUCoAHGb&3#p4xJ)dsvGf+#WTf+^^(w27JxQy_eo)#-vH>sY5tiaMo|{*|_&AyiKz+)J6~ zFlAmV9LgluW4zRdLF?Y5F;Cem8p)94JxNlXaNR49A|~Q3t$+hqWOTlS+2tZ-&Z0r) z;NQ&Y&&+8TwDQo{OKzIN0jlR60m?OXd_7`xJIcJ_HLgwYlU2AyDbvFQ_cAnxX@U)V z->)WHe~Qf#iAatE!f*JERyetRa9^zr+UujXKNcd=a0kixp^y4(om5REVk?scX2i*1 z?g@xVW&B2*-^Q6gG={<3Z%_-+jr4|Nl8>R4xlFo-x*Y5v+Kkf(JE+qASU6F%RWc*t znl712=gKHl1G4RCe+!_zbZBW6YXAfy{1xzF)&jQ2^^1y7H+?uGH1=YcgG0ngqpX_i zjx;E(K90_~qbYvdF9X#<#xH?t<1nYyd8j@a__bh*N9oqU$5()5jZ21USYXn#E2WqB zorya^S&Ho04@ypXcwhn4Bw3)4mv~t?uayIZO$*D_JsS0`Nfw=PCPw-kJ`W1)o^KAb zhB+{2Q~EW&6~d^ zNU`>pX{AX$qT@<~PRBJGzVOeQuGR6|UN#d+EPu=tS>oP>K4hvBCqXW$477=^Gxa%F z_%q#g44#VZ*yclyL*PoB{J`C-09EN0oD$UB zo09yZaa3e#8947LHF&ORTWjMLG$0{!IdoPE|Fy)Bnf{d~3)OZBgyvK}4O4t2+70~3 zD->}8zSYk*Neib99bOUH%nC>1JZun$`|#&OrVn$loj6%R(4too#?GLmUTn(A?V;!1 zCfbcjyFE%P#b@wDi+jwu9UM;`(*VlGVr#1Btp?tq{$glEfFM;qb5JI$rZbs|3ovLA z`m}eR{!r1lLA_^_yE!1{=wqgjb*wUpwoI^5ZBc7O2uO0wn+f;xzQy%SrqBALX_a?g zD&4Ot1|70sjSUUE<3ke_419EaJMMpC6DOge0lGp2P%xCPLJT=iw5VWqxe=q&a|GiT z2|o0sjp;#Uq6#dhJ&Rml)n{af3FEU!^+5t$7*RcQ03zU-kHK&`a5r_}f+dA5X5v`P zC?gKl$j-Oxb<_H);1#p6ib&5&Xx}Vmg@5$E*pru4lzXvneOz&?;r1Gu`6iCT&Zx|l-Q1wJY??XPT`GIbn_oTxkfv&dk*Q6mE*&DOX9%3} znRG$d<-USh%QV3OfboawkkA!?Fq~sVW30IRl%%CciPS@5AF#U)K1t^NzVUtrzENGh z*NY+sBPYjTIJ@?%PduI4K%spQ7s`sc1lO*-iKmQp!TT9cc%Tq8@pJds zO&e4Pl8G%NsJQ`$tYnp;nckO6;H}zIa)$pkO}nieCJ#@!F-A7-8Wue&=`+cNipO<} zHl_&h@yk1(H0>((&v-O$IBRj{ezZH0&5~$kUEa}t)Ea~I+;FD}z&de!NkeA>iRHO$ zt7jRNT<^Gv$~P0Ulbd-{;WC{Y;{A~-w}!CI>Oo+|G($m7S*~r{xe_Yi5rSAs5_-x9sHCWdC-oB1)?J}T@(nmTP-Koh<1qGBHuCCFGBh2fS?bPGBBB>NLUF_oXbR`ger4ix zGS|8+j`h7`eq#FN`FXA8Rx2}WOj?c^HY@;5*|}_y5IgmzS2)EByIjOf#0Pg{6%WCz zXvKQJAoZGta8KjmSK~@%+MK@i7@y7?g66D!YWFKa?=7A=f|?OqjuQhciAwrI8zyUPDUYdVV}#a zNO3834eP(#@FVfWNNoy@49>GREcJ0!e-4UN znS*7iJJSejzRr~~yKV}uiz=exZ`y&4ykR|l|K4MidwEBQif^9Ib~4=S!@+nA9OH9k z{Q3(BA1}nT8!b`?Q*TXF8x{(qM6S!KqJ~68w7VuaOu^@_i~!cs`i2&K#U9*CCFc~Y zI>)w~0jk`2fObDh>OLaTj5$~fb<63cS{$$<5fTj?WyDME-==Syved$8)tE4 zV)9z}$FWlr{c2}dcD3+_#%2XgV0rI_;&&=BGMhOULTos7DvGG?NQ9cs1nj(4x=Fh~ z*wJ3@kw&d}8RKNQMWp^0YNZutJuFJ(^681&tO^pl%yEd?JqtYKpgvxZ+Dv^dS-x-&eSd(KdCN#HHfos|_ zZK=4!P#HFxO*?s5p(9)^IUqf+Mm!a^AJwFF27MiWNN|mx{kvDFj;fXHF%F4;EE`e_ zwiT~m7aw&FjG$x(X@tb@FLrc36BPbrBSO47$Zn@zafx;Hv{*O3m3Nn z!0$TV;)@rVlRwMvAlTal zxA(8qccG5r$L_X8$+b49NNo)nNn3_s0-TjU*}Dj1wOms#`572Fj_~r>`G-Ck^h*W%v1Q9nM%X_KIs7lh@3L46QK^Gu)TJkE{hB;pAJwm!RW}9C+q& z4?H{`@hSzcAMyIalAu_tl!0sHHcI}rymG070Bzi-C<zl}%}BB!%V1K;D{J8ZaBIU^?54)2SP5V5Y*0rJz&tX{67o4P>K458g1UZLZ$6@{%k|rqNS~esGjM9uq<)`x2u&e zOi(cR6^uK9MHabg?{jk?bS&cZgbLzOHMWo(*f1b6(F)`Bs{suwH90ocLZsN98m-My zwGn!00y|y@SKrKnK{Bv9Ga95QFO&X-jDHLvl9$e4TEa$ zPmD9*qW%(9Z00mc1BmhkyOm7zGgmq26`3~;iQa=lzB4KE<4nQYISf=M{(K~OnpwpM#TXL*4=OVWXLxSFm^s{BY5*V)8688q2J1ZL$~ z)twGwY+&~5@A+)BECkrOn7+Ui+A~#A{URfD<{OaZ2$gXTc%K4{uF0>O8of;(`_Z5~qZ&CS{CkJ%4=U^th%CZqyU)ETrJ zlv5jy9~p`sMTb=~t~?`qFpkKZ022_#20_}CA|A4>z!R+cJ${>2r6~@B@N5@QvUc$v z1g3-&Xe)!1GZtG9h>q(_HT~F>)v5;?#jOYMQ7pDy5^EiQmWQ{*;V?5XZ+)1WRTW(~ z2Z~l8rx!xA#`~o=TSJ3bvOJu6m+e^B4~B=#aQ)WVv;8~m$5LyHiJiqltZ6hv2K%v< z@Awd5TvV`~74E>;@)t%&ruEhWkt!Zm?}bPLZRR8@Z|#5aFiR4KxBMA2SqMwg2Xg?f zq1@J z9?7&yC-EVqdm>PGP59tbsH(N_;wqNp3f{x&$F}Zbt!@Xn$PdG#Sk2#`q+kBXhxr31 z?^3USrL!f^fD>|`0P{6ZCt1*vDgTNGJTOR8c7_%hr z2@mK-HvT6*LmA>4C6gC>)y&V<3L~Jla9-abk%JBtX6u443vONa^VHtS zTLActHE*69Hy@*yTvvFKsN~Cru?3%cw&v#Z@tN)XN(AdK*}`@%}q%{+<$iLbpT@Bye~6+^pwI<`!zoIoZ698AQxKR|9N`@qq0Nb8NfP)Y;WZG+ zNzyL$N5ueFZzSHRBt$F^ILtkPw6+7(_I$69*SGxvQ_o{%ls?CPJh^?YOe@ZcOz}mH z4DBYu0;!%>xOZw4aSE+dhjYgF&IXy>i?xEA&4%luEmzYGgrao(#%8`1kDrpDP-E4? zhZLA;TF{P6Gn}HX@GjP&UsM+&K9E&|km72E42=IYOleSAm>#O&MD^tHcR7q{;yrHW z?5{p$rptk4BR#tLZ(J~tK%$Bt8LgAGTw5D+)ACk8hcfA!sG^KbPZQ`E*~Oml0OW=U zfhU!2id$Zi$8H)CVf;H>98BYP`E4Jvc*?HS$1ShYb|H<YMbE*AO1MoAG(1$y;m`i$ny$tYRXkxka3)cNPSZ@*CMJo zPq`QJfiDaZbJDuTJ=HS&8=ye>3O{mQWbBt22t%1e#m#7^F2~GU{w>0 zV*O!gj3~;5s=NA3%z?CT0cmeS^ACD2tDkYZJ23vvAyf>xVesRAr))(O2-Hg5<~xny z-WEz;pZ{%TYS$m6dUo*hJvz6RA7`jig|(#-_ksw)Cm1?^X>{U-LY@| zl~yoKh*|pzBfy8FR_3rrp{X7%)8eeV>~n5BR0~G=LHf^@+FitU7!{3Ugo}DshKL*C zVi|!ImKM0CRMvyO4g<2cCF#*;pU9bwDsFwb_7BG=Ker^j# z$d=rB5w>S3WLmIIZ;m0X(VjhzzTC%-+K$c1hD9H5$;XBXiyydb=FjfSGCDiN9K4Ek zI5hSY>p%$p(6+w__`pGH%842sMp1Tjg_^5@i0~tB$8Fkg3uds=-~dWq8zN&2?wNk` zWjBY!PpeD(jx$zERC7NgyoFjMr=K9%$+?ymXQiVP=7jPTSL}XuJB^_cxto)g8Rua| z49Sj&=H~seWJ6yymTo)7xg41U6;({7k3|?QCU7acMTl*#Rv zC7DT6f?mGFmPjN1&*h#B!*`KI9`Ogwj4V_lqZpT(!uXMsZ3lN8m1d!QXy%5^c5ftp z7W5lsmXNi#Oc#({3wJ|Z5BV_B#*dY3Vb0lyn(GgR=of& z#l{KC=wH5=X6#@f+M`;zdut3cy2VYD$Mn?6jwQn#1g(qm zv!UqvH#ee$x1w1->aysI|IjX0r{(8iyWNX*l zBW%-a%B(vT=1T5Itp-Ko*0D0iKorPpDk-g5E4r041CgTnEgWuq-#5w3^h33d*6k+R z1BB+V#~jL0^5|DZcy|z+5?G5}W6bk@1cNkLreR5h10`&o(wf(9X^ofP8u7Pwy85xV z+TK}o@9!GOTKO1e@WPuW*?z1{^^}3>XQx87OTEtx>n(>4+10M=^`Ry;mLTN0(`L>G zO{;~~LGyd&(ThR#cJ#yfZzjSfpvzU)BqKkCDt=b8dQpJ^Btx-QG=Znzo!{9zkM0Bm zISm`#$roN%kR=%}a7o{>mQVQYoG!X#qnY74m2VcIqq8B9#J#B!^{zKE!VQqOtIx)8 zU1#EXt)AI_R>$% z$7i1t4*aWJt2Mgfd)P^a>Q>3dSRsQv2eG4)8pCyqzRgq>nlj z(@Pw$N$(TUH`xvgG4Day6XueMAre--1 zLz-Or>WSG=oH|q8``v~ZvY(-6EZzvQz)zh&e;&hRyNb-*&y1FjmLJ`5CMa&CYvBC6 zS#xMgif;!x`(|W{wuq!5CH}(e4_A_U_}5;f$8i|KJO6pLMKA1W;ZJ?de}0z|;vYKv z;EsRj@c*KN)kOJd -``` +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. 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. @@ -14,184 +10,30 @@ The directories listed below will be created in the results directory after the The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: -* [General](#general) - * [Quantification](#quantification) - * [Intermediate results](#intermediate-results) -* [VCF](#vcf) -* [Class prediction](#class-prediction) - * [Class (1|2) bindings](#class-12-bindings) -* [Rotation time prediction](#rotation-time-prediction) -* [Workflow reporting and documentation](#workflow-reporting-and-documentation) - * [MultiQC](#multiqc) - * [Pipeline information](#pipeline-information) - -## General - -### Quantification - -

-Output files - -* `*.tsv` : If `--skip_quantification` is not specified. - -
- -The CSV output file is a table containing all information extracted from a database search throughout the pipeline. See the [OpenMS](https://www.openms.de/) or PSI documentation for more information about [annotated scores and format](https://abibuilder.informatik.uni-tuebingen.de/archive/openms/Documentation/release/latest/html/TOPP_TextExporter.html). - -MAP contains information about the different mzML files that were provided initially - -```bash -#MAP id filename label size -``` - -RUN contains information about the search that was performed on each run - -```bash -#RUN run_id score_type score_direction date_time search_engine_version parameters -``` - -PROTEIN contains information about the protein ids corresponding to the peptides that were detected (No protein inference was performed) - -```bash -#PROTEIN score rank accession protein_description coverage sequence -``` - -UNASSIGNEDPEPTIDE contains information about PSMs that were identified but couldn't be quantified to a precursor feature on MS Level 1 - -```bash -#UNASSIGNEDPEPTIDE rt mz score rank sequence charge aa_before aa_after score_type search_identifier accessions FFId_category feature_id file_origin map_index spectrum_reference COMET:IonFrac COMET:deltCn COMET:deltLCn COMET:lnExpect COMET:lnNumSP COMET:lnRankSP MS:1001491 MS:1001492 MS:1001493 MS:1002252 MS:1002253 MS:1002254 MS:1002255 MS:1002256 MS:1002257 MS:1002258 MS:1002259 num_matched_peptides protein_references target_decoy -``` +* [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 -CONSENSUS contains information about precursor features that were identified in multiple runs (eg. run 1-3 in this case) - -```bash -#CONSENSUS rt_cf mz_cf intensity_cf charge_cf width_cf quality_cf rt_0 mz_0 intensity_0 charge_0 width_0 rt_1 mz_1 intensity_1 charge_1 width_1 rt_2 mz_2 intensity_2 charge_2 width_2 rt_3 mz_3 intensity_3 charge_3 width_3 -``` - -PEPTIDE contains information about peptide hits that were identified and correspond to the consensus features described below - -```bash -#PEPTIDE rt mz score rank sequence charge aa_before aa_after score_type search_identifier accessions FFId_category fea -``` - -### Intermediate results - -
-Output files - -* `Intermediate_Results/` - * `*merged_psm_perc_filtered.mzTab` : If `--refine_fdr_on_predicted_subset` is specified, consists of the hits (filtered by q-value) - * `*.mztab` : mztab file generated by the OpenMS MzTabExporter command, the community standard format for sharing mass spectrometry search results - * `*.featureXML` : If `--skip_quantification` is not specified, then this file is generated by the OpenMS FeatureFinderIdentification command - * `*fdr_filtered.idXML`: If `--skip_quantification` is not specified, then this file is generated by the OpenMS IDFilter command - * `*all_ids_merged_psm_perc*.idXML`: idXML files are generated when `--refine_fdr_on_predicted_subset` is specified - * `*peptide_filtered.idXML`: If `--refine_fdr_on_predicted_subset` is specified, then this file consists of the PSMs prediction outcome - * `*perc_subset.idXML`: If `--refine_fdr_on_predicted_subset` is specified, then this file is the outcome of the second percolator run, generated by the OpenMS PercolatorAdapter - -
- -This folder contains the intermediate results from various steps of the MHCquant pipeline (e.g. (un)filtered PSMs, aligned mzMLs, features) - -The output mzTab contains many columns annotating the most important information - here are a few outpointed: - -```bash -PEP sequence accession best_search_engine_score[1] retention_time charge mass_to_charge peptide_abundance_study_variable[1] -``` - -Most important to know that in this format we annotated the q-value of each peptide identification in the `best_seach_engine_score[1]` column and peptide quantities in the peptide_abundance_study_variable` columns. - -[mzTab](http://www.psidev.info/mztab) is a light-weight format to report mass spectrometry search results. It provides all important information about identified peptide hits and is compatible with the PRIDE Archive - proteomics data repository. - -## VCF - -### Reference fasta +### FastQC
Output files -* `*_vcf.fasta`: If `--include_proteins_from_vcf` is specified, then this fasta is created for the respective sample +* `fastqc/` + * `*_fastqc.html`: FastQC report containing quality metrics. + * `*_fastqc.zip`: Zip archive containing the FastQC report, tab-delimited data file and plot images.
-The fasta database including mutated proteins used for the database search -### Neoepitopes +[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/). -These CSV files list all of the theoretically possible neoepitope sequences from the variants specified in the vcf and neoepitopes that are found during the mass spectrometry search, independant of binding predictions, respectively +![MultiQC - FastQC sequence counts plot](images/mqc_fastqc_counts.png) -#### found_neoepitopes +![MultiQC - FastQC mean quality scores plot](images/mqc_fastqc_quality.png) -
-Output files - -* `class_1_bindings/` - * `*found_neoepitopes_class1.csv`: Generated when `--include_proteins_from_vcf` and `--predict_class_1` are specified - -* `class_2_bindings/` - * `*found_neoepitopes_class2.csv`: Generated when `--include_proteins_from_vcf` and `--predict_class_2` are specified - -
- -This CSV which lists all neoepitopes that are found during the mass spectrometry search, independant of binding predictions -The format is as follows: - -```bash -peptide sequence geneID -``` - -#### vcf_neoepitopes - -
-Output files - -* `class_1_bindings/` - * `*vcf_neoepitopes_class1.csv`: Generated when `--include_proteins_from_vcf` and `--predict_class_1` are specified - -* `class_2_bindings/` - * `*vcf_neoepitopes_class2.csv`: Generated when `--include_proteins_from_vcf` and `--predict_class_2` are specified - -
- -This CSV fils contains all theoretically possible neoepitope sequences from the variants that were specified in the vcf -The format is shown below - -```bash -Sequence Antigen ID Variants -``` - -## Class prediction - -### Class (1|2) bindings - -
-Output files - -* `class_1_bindings/` - * `*predicted_peptides_class_1.csv`: If `--predict_class_1` is specified, then this CSV is generated - -* `class_2_bindings/` - * `*predicted_peptides_class_2.csv`: If `--predict_class_2` is specified, then this CSV is generated - -
- -This folder containing the binding predictions of all detected class 1 or 2 peptides and all theoretically possible neoepitope sequences -The prediction outputs are comma-separated table (CSV) for each allele, listing each peptide sequence and its corresponding predicted affinity scores: - -```bash -peptide allele prediction prediction_low prediction_high prediction_percentile -``` - -## Rotation time prediction - -
-Output files - -* `RT_prediction` - * `*id_RTpredicted.csv`: If `--predict_RT` is specified, the rotation time found peptides are provided - * `*txt_RTpredicted.csv`: If `--predict_RT` is specified, the rotation time predicted neoepitopes are provided - -
+![MultiQC - FastQC adapter content plot](images/mqc_fastqc_adapter.png) -## Workflow reporting and documentation +> **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. ### MultiQC @@ -201,12 +43,13 @@ peptide allele prediction prediction_low prediction_high prediction_pe * `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 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. +[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. -The pipeline has special steps which allow the software versions to be reported in the MultiQC output for future traceability. For more information about how to use MultiQC reports, see . +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 @@ -215,9 +58,9 @@ The pipeline has special steps which allow the software versions to be reported * `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.tsv`. - * Reformatted sample-sheet files used as input to the pipeline: `samplesheet.valid.csv`. + * 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 provide you with other information such as launch commands, run times and resource usage. +[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 879ed17d..46fe3631 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -14,6 +14,7 @@ - [`-resume`](#-resume) - [Custom configuration](#custom-configuration) - [Resource requests](#resource-requests) + - [Updating containers](#updating-containers) - [nf-core/configs](#nf-core-configs) - [Running in the background](#running-in-the-background) - [Nextflow memory requirements](#nextflow-memory-requirements) @@ -202,6 +203,45 @@ process { > **NB:** We specify just the process name i.e. `STAR_ALIGN` in the config file and not the full task name string that is printed to screen in the error message or on the terminal whilst the pipeline is running i.e. `RNASEQ:ALIGN_STAR:STAR_ALIGN`. You may get a warning suggesting that the process selector isn't recognised but you can ignore that if the process name has been specified correctly. This is something that needs to be fixed upstream in core Nextflow. +### 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. diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy index 8d6920dd..40ab65f2 100755 --- a/lib/NfcoreSchema.groovy +++ b/lib/NfcoreSchema.groovy @@ -105,9 +105,13 @@ class NfcoreSchema { // 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'] + } } } @@ -155,7 +159,7 @@ class NfcoreSchema { println '' log.error 'ERROR: Validation of pipeline parameters failed!' JSONObject exceptionJSON = e.toJSON() - printExceptions(exceptionJSON, params_json, log) + printExceptions(exceptionJSON, params_json, log, enums) println '' has_error = true } @@ -202,7 +206,7 @@ class NfcoreSchema { } def type = '[' + group_params.get(param).type + ']' def description = group_params.get(param).description - def defaultValue = group_params.get(param).default ? " [default: " + group_params.get(param).default.toString() + "]" : '' + 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 @@ -260,13 +264,12 @@ class NfcoreSchema { // Get pipeline parameters defined in JSON Schema def Map params_summary = [:] - def blacklist = ['hostnames'] 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) && !blacklist.contains(param)) { + 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 @@ -330,7 +333,7 @@ class NfcoreSchema { // // Loop over nested exceptions and print the causingException // - private static void printExceptions(ex_json, params_json, log) { + 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/ @@ -346,11 +349,20 @@ class NfcoreSchema { else { def param = ex_json['pointerToViolation'] - ~/^#\// def param_val = params_json[param].toString() - log.error "* --${param}: ${ex_json['message']} (${param_val})" + 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) + printExceptions(ex, params_json, log, enums) } } diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 44551e0a..2fc0a9b9 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -19,27 +19,16 @@ class NfcoreTemplate { } // - // Check params.hostnames + // Warn if a -profile or Nextflow config has not been provided to run the pipeline // - public static void hostName(workflow, params, log) { - Map colors = logColours(params.monochrome_logs) - if (params.hostnames) { - try { - def hostname = "hostname".execute().text.trim() - params.hostnames.each { prof, hnames -> - hnames.each { hname -> - if (hostname.contains(hname) && !workflow.profile.contains(prof)) { - log.info "=${colors.yellow}====================================================${colors.reset}=\n" + - "${colors.yellow}WARN: You are running with `-profile $workflow.profile`\n" + - " but your machine hostname is ${colors.white}'$hostname'${colors.reset}.\n" + - " ${colors.yellow_bold}Please use `-profile $prof${colors.reset}`\n" + - "=${colors.yellow}====================================================${colors.reset}=" - } - } - } - } catch (Exception e) { - log.warn "[$workflow.manifest.name] Could not determine 'hostname' - skipping check. Reason: ${e.message}." - } + 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 " } } @@ -168,7 +157,6 @@ class NfcoreTemplate { log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" } } else { - hostName(workflow, params, log) log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" } } diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 18173e98..1b88aec0 100644 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -37,11 +37,4 @@ class Utils { "===================================================================================" } } - - // - // Join module args with appropriate spacing - // - public static String joinModuleArgs(args_list) { - return ' ' + args_list.join(' ') - } } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index d12756c7..e98f65c1 100644 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -9,10 +9,8 @@ class WorkflowMain { // public static String citation(workflow) { return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + - "* The pipeline publication\n" + - " https://doi.org/10.1021/acs.jproteome.9b00313\n\n" + "* The pipeline\n" + - " https://doi.org/10.5281/zenodo.1569909\n\n" + + " https://doi.org/10.5281/zenodo.1569910\n\n" + "* The nf-core framework\n" + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + "* Software dependencies\n" + @@ -62,6 +60,9 @@ class WorkflowMain { // 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) @@ -70,9 +71,6 @@ class WorkflowMain { // Check AWS batch settings NfcoreTemplate.awsBatch(workflow, params) - // Check the hostnames against configured profiles - NfcoreTemplate.hostName(workflow, params, log) - // Check input has been provided if (!params.input) { log.error "Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.tsv'" diff --git a/modules.json b/modules.json index 554d418c..1d7e0f6a 100644 --- a/modules.json +++ b/modules.json @@ -4,11 +4,11 @@ "repos": { "nf-core/modules": { "custom/dumpsoftwareversions": { - "git_sha": "3aacd46da2b221ed47aaa05c413a828538d2c2ae" + "git_sha": "20d8250d9f39ddb05dfb437603aaf99b5c0b2b41" }, "multiqc": { - "git_sha": "3aacd46da2b221ed47aaa05c413a828538d2c2ae" + "git_sha": "20d8250d9f39ddb05dfb437603aaf99b5c0b2b41" } } } -} +} \ No newline at end of file diff --git a/modules/local/functions.nf b/modules/local/functions.nf index 2405335a..83397ff9 100644 --- a/modules/local/functions.nf +++ b/modules/local/functions.nf @@ -1,3 +1,5 @@ +//TODO: find a solution for the hasExtension function + // // Utility functions used in nf-core DSL2 module files // diff --git a/modules/local/get_software_versions.nf b/modules/local/get_software_versions.nf deleted file mode 100644 index 647ea324..00000000 --- a/modules/local/get_software_versions.nf +++ /dev/null @@ -1,34 +0,0 @@ -// Import generic module functions -include { saveFiles } from './functions' - -params.options = [:] -options = initOptions(params.options) - -process GET_SOFTWARE_VERSIONS { - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'pipeline_info', meta:[:], publish_by_meta:[]) } - - conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/python:3.8.3" - } else { - container "quay.io/biocontainers/python:3.8.3" - } - - cache false - - input: - path versions - - output: - path "software_versions.tsv" , emit: tsv - path 'software_versions_mqc.yaml', emit: yaml - - script: // This script is bundled with the pipeline, in nf-core/mhcquant/bin/ - """ - echo $workflow.manifest.version > pipeline.version.txt - echo $workflow.nextflow.version > nextflow.version.txt - scrape_software_versions.py &> software_versions_mqc.yaml - """ -} diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf index 15a9665a..9fe13398 100644 --- a/modules/local/samplesheet_check.nf +++ b/modules/local/samplesheet_check.nf @@ -1,28 +1,17 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process SAMPLESHEET_CHECK { tag "$samplesheet" - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'pipeline_info', meta:[:], publish_by_meta:[]) } conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/python:3.8.3" - } else { - container "quay.io/biocontainers/python:3.8.3" - } + 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 + path samplesheet output: - path '*.csv' , emit: csv - path "versions.yml", emit: versions + path '*.csv' , emit: csv + path "versions.yml", emit: versions script: // This script is bundled with the pipeline, in nf-core/mhcquant/bin/ """ @@ -31,8 +20,8 @@ process SAMPLESHEET_CHECK { samplesheet.valid.csv cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: - python: \$(echo \$(python --version | sed 's/Python //g')) + "${task.process}": + python: \$(python --version | sed 's/Python //g') END_VERSIONS """ } diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/functions.nf b/modules/nf-core/modules/custom/dumpsoftwareversions/functions.nf deleted file mode 100644 index 85628ee0..00000000 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/functions.nf +++ /dev/null @@ -1,78 +0,0 @@ -// -// Utility functions used in nf-core DSL2 module files -// - -// -// Extract name of software tool from process name using $task.process -// -def getSoftwareName(task_process) { - return task_process.tokenize(':')[-1].tokenize('_')[0].toLowerCase() -} - -// -// Extract name of module from process name using $task.process -// -def getProcessName(task_process) { - return task_process.tokenize(':')[-1] -} - -// -// Function to initialise default values and to generate a Groovy Map of available options for nf-core modules -// -def initOptions(Map args) { - def Map options = [:] - options.args = args.args ?: '' - options.args2 = args.args2 ?: '' - options.args3 = args.args3 ?: '' - options.publish_by_meta = args.publish_by_meta ?: [] - options.publish_dir = args.publish_dir ?: '' - options.publish_files = args.publish_files - options.suffix = args.suffix ?: '' - return options -} - -// -// Tidy up and join elements of a list to return a path string -// -def getPathFromList(path_list) { - def paths = path_list.findAll { item -> !item?.trim().isEmpty() } // Remove empty entries - paths = paths.collect { it.trim().replaceAll("^[/]+|[/]+\$", "") } // Trim whitespace and trailing slashes - return paths.join('/') -} - -// -// Function to save/publish module results -// -def saveFiles(Map args) { - def ioptions = initOptions(args.options) - def path_list = [ ioptions.publish_dir ?: args.publish_dir ] - - // Do not publish versions.yml unless running from pytest workflow - if (args.filename.equals('versions.yml') && !System.getenv("NF_CORE_MODULES_TEST")) { - return null - } - if (ioptions.publish_by_meta) { - def key_list = ioptions.publish_by_meta instanceof List ? ioptions.publish_by_meta : args.publish_by_meta - for (key in key_list) { - if (args.meta && key instanceof String) { - def path = key - if (args.meta.containsKey(key)) { - path = args.meta[key] instanceof Boolean ? "${key}_${args.meta[key]}".toString() : args.meta[key] - } - path = path instanceof String ? path : '' - path_list.add(path) - } - } - } - if (ioptions.publish_files instanceof Map) { - for (ext in ioptions.publish_files) { - if (args.filename.endsWith(ext.key)) { - def ext_list = path_list.collect() - ext_list.add(ext.value) - return "${getPathFromList(ext_list)}/$args.filename" - } - } - } else if (ioptions.publish_files == null) { - return "${getPathFromList(path_list)}/$args.filename" - } -} diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf b/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf index faf2073f..934bb467 100644 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf @@ -1,22 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process CUSTOM_DUMPSOFTWAREVERSIONS { label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'pipeline_info', meta:[:], publish_by_meta:[]) } // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container conda (params.enable_conda ? "bioconda::multiqc=1.11" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/multiqc:1.11--pyhdfd78af_0" - } else { - container "quay.io/biocontainers/multiqc:1.11--pyhdfd78af_0" - } + 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 @@ -27,80 +16,6 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { path "versions.yml" , emit: versions script: - """ - #!/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) - - module_versions = {} - module_versions["${getProcessName(task.process)}"] = { - 'python': platform.python_version(), - 'yaml': yaml.__version__ - } - - with open("$versions") as f: - workflow_versions = yaml.load(f, Loader=yaml.BaseLoader) | module_versions - - workflow_versions["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(workflow_versions) - } - - with open("software_versions.yml", 'w') as f: - yaml.dump(workflow_versions, 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(module_versions, f, default_flow_style=False) - """ + 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 index c8310e35..5b5b8a60 100644 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml +++ b/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml @@ -31,3 +31,4 @@ output: 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/multiqc/functions.nf b/modules/nf-core/modules/multiqc/functions.nf deleted file mode 100644 index 85628ee0..00000000 --- a/modules/nf-core/modules/multiqc/functions.nf +++ /dev/null @@ -1,78 +0,0 @@ -// -// Utility functions used in nf-core DSL2 module files -// - -// -// Extract name of software tool from process name using $task.process -// -def getSoftwareName(task_process) { - return task_process.tokenize(':')[-1].tokenize('_')[0].toLowerCase() -} - -// -// Extract name of module from process name using $task.process -// -def getProcessName(task_process) { - return task_process.tokenize(':')[-1] -} - -// -// Function to initialise default values and to generate a Groovy Map of available options for nf-core modules -// -def initOptions(Map args) { - def Map options = [:] - options.args = args.args ?: '' - options.args2 = args.args2 ?: '' - options.args3 = args.args3 ?: '' - options.publish_by_meta = args.publish_by_meta ?: [] - options.publish_dir = args.publish_dir ?: '' - options.publish_files = args.publish_files - options.suffix = args.suffix ?: '' - return options -} - -// -// Tidy up and join elements of a list to return a path string -// -def getPathFromList(path_list) { - def paths = path_list.findAll { item -> !item?.trim().isEmpty() } // Remove empty entries - paths = paths.collect { it.trim().replaceAll("^[/]+|[/]+\$", "") } // Trim whitespace and trailing slashes - return paths.join('/') -} - -// -// Function to save/publish module results -// -def saveFiles(Map args) { - def ioptions = initOptions(args.options) - def path_list = [ ioptions.publish_dir ?: args.publish_dir ] - - // Do not publish versions.yml unless running from pytest workflow - if (args.filename.equals('versions.yml') && !System.getenv("NF_CORE_MODULES_TEST")) { - return null - } - if (ioptions.publish_by_meta) { - def key_list = ioptions.publish_by_meta instanceof List ? ioptions.publish_by_meta : args.publish_by_meta - for (key in key_list) { - if (args.meta && key instanceof String) { - def path = key - if (args.meta.containsKey(key)) { - path = args.meta[key] instanceof Boolean ? "${key}_${args.meta[key]}".toString() : args.meta[key] - } - path = path instanceof String ? path : '' - path_list.add(path) - } - } - } - if (ioptions.publish_files instanceof Map) { - for (ext in ioptions.publish_files) { - if (args.filename.endsWith(ext.key)) { - def ext_list = path_list.collect() - ext_list.add(ext.value) - return "${getPathFromList(ext_list)}/$args.filename" - } - } - } else if (ioptions.publish_files == null) { - return "${getPathFromList(path_list)}/$args.filename" - } -} diff --git a/modules/nf-core/modules/multiqc/main.nf b/modules/nf-core/modules/multiqc/main.nf index 0861aa59..3dceb162 100644 --- a/modules/nf-core/modules/multiqc/main.nf +++ b/modules/nf-core/modules/multiqc/main.nf @@ -1,21 +1,10 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process MULTIQC { label 'process_medium' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:getSoftwareName(task.process), meta:[:], publish_by_meta:[]) } conda (params.enable_conda ? 'bioconda::multiqc=1.11' : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/multiqc:1.11--pyhdfd78af_0" - } else { - container "quay.io/biocontainers/multiqc:1.11--pyhdfd78af_0" - } + 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 multiqc_files @@ -27,12 +16,13 @@ process MULTIQC { path "versions.yml" , emit: versions script: + def args = task.ext.args ?: '' """ - multiqc -f $options.args . + multiqc -f $args . cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: - ${getSoftwareName(task.process)}: \$( multiqc --version | sed -e "s/multiqc, version //g" ) + "${task.process}": + multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) END_VERSIONS """ } diff --git a/nextflow.config b/nextflow.config index f895cfc9..a81f4762 100644 --- a/nextflow.config +++ b/nextflow.config @@ -14,7 +14,6 @@ params { input = "sample_sheet.tsv" outdir = './results' fasta = "data/*.fasta" - publish_dir_mode = 'copy' // References genomes = null @@ -25,7 +24,7 @@ params { predict_class_1 = false predict_class_2 = false refine_fdr_on_predicted_subset = false - schema_ignore_params = 'genome,input_paths' + schema_ignore_params = 'genome' skip_decoy_generation = false subset_affinity_threshold = 500 variant_annotation_style = "SNPEFF" @@ -180,10 +179,14 @@ profiles { } // 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 @@ -214,7 +217,7 @@ manifest { description = 'Identify and quantify peptides from mass spectrometry raw data' mainScript = 'main.nf' nextflowVersion = '!>=21.10.3' - version = '2.1.0' + version = '2.1.1dev' } // Function to ensure that resource requirements don't go beyond diff --git a/nextflow_schema.json b/nextflow_schema.json index 31e20e0c..6a906eea 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -382,12 +382,6 @@ "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" }, - "hostnames": { - "type": "string", - "description": "Institutional configs hostname.", - "hidden": true, - "fa_icon": "fas fa-users-cog" - }, "config_profile_name": { "type": "string", "description": "Institutional config name.", @@ -461,24 +455,7 @@ "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.", @@ -539,13 +516,6 @@ "description": "Run this workflow with Conda. You can also use '-profile conda' instead of providing this parameter.", "hidden": true, "fa_icon": "fas fa-bacon" - }, - "singularity_pull_docker_container": { - "type": "boolean", - "description": "Instead of directly downloading Singularity images for use with Singularity, force the workflow to pull and convert Docker containers instead.", - "hidden": true, - "fa_icon": "fas fa-toolbox", - "help_text": "This may be useful for example if you are unable to directly pull Singularity containers to run the pipeline due to http/https proxy issues." } } } diff --git a/subworkflows/local/input_check.nf b/subworkflows/local/input_check.nf index 1c3ccc2e..05002623 100644 --- a/subworkflows/local/input_check.nf +++ b/subworkflows/local/input_check.nf @@ -2,24 +2,22 @@ // Check input samplesheet and get read channels // -params.options = [:] - -include { SAMPLESHEET_CHECK } from '../../modules/local/samplesheet_check' addParams(options: [:]) +include { SAMPLESHEET_CHECK } from '../../modules/local/samplesheet_check' workflow INPUT_CHECK { take: - samplesheet // file: /path/to/samplesheet.csv + samplesheet // file: /path/to/samplesheet.csv main: - SAMPLESHEET_CHECK ( samplesheet ) + SAMPLESHEET_CHECK ( samplesheet ) .csv .splitCsv ( header:true, sep:"\t" ) .map { get_samplesheet_paths(it) } .set { reads } emit: - reads // channel: [ val(meta), [ reads ] ] - versions = SAMPLESHEET_CHECK.out.versions // channel: [ versions.yml ] + reads // channel: [ val(meta), [ reads ] ] + versions = SAMPLESHEET_CHECK.out.versions // channel: [ versions.yml ] } // Function to get list of [ meta, filenames ] diff --git a/workflows/mhcquant.nf b/workflows/mhcquant.nf index 818c0389..62abdcc7 100644 --- a/workflows/mhcquant.nf +++ b/workflows/mhcquant.nf @@ -64,100 +64,100 @@ ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multi ======================================================================================== */ // Don't overwrite global params.modules, create a copy instead and use that within the main script. -def modules = params.modules.clone() - -def multiqc_options = modules['multiqc'] -multiqc_options.args += params.multiqc_title ? Utils.joinModuleArgs(["--title \"$params.multiqc_title\""]) : '' - -def generate_proteins_from_vcf_options = modules['generate_proteins_from_vcf'] -generate_proteins_from_vcf_options.args += params.variant_indel_filter ? Utils.joinModuleArgs(['-fINDEL']) : '' -generate_proteins_from_vcf_options.args += params.variant_frameshift_filter ? Utils.joinModuleArgs(['-fFS']) : '' -generate_proteins_from_vcf_options.args += params.variant_snp_filter ? Utils.joinModuleArgs(['-fSNP']) : '' - -def openms_comet_adapter_options = modules['openms_comet_adapter'] -openms_comet_adapter_options.args += params.use_x_ions ? Utils.joinModuleArgs(['-use_X_ions true']) : '' -openms_comet_adapter_options.args += params.use_z_ions ? Utils.joinModuleArgs(['-use_Z_ions true']) : '' -openms_comet_adapter_options.args += params.use_a_ions ? Utils.joinModuleArgs(['-use_A_ions true']) : '' -openms_comet_adapter_options.args += params.use_c_ions ? Utils.joinModuleArgs(['-use_C_ions true']) : '' -openms_comet_adapter_options.args += params.use_NL_ions ? Utils.joinModuleArgs(['-use_NL_ions true']) : '' -openms_comet_adapter_options.args += params.remove_precursor_peak ? Utils.joinModuleArgs(['-remove_precursor_peak yes']) : '' - -def openms_id_filter_options = modules['openms_id_filter'] -def openms_id_filter_refiner_options = modules['openms_id_filter_refiner'] -def openms_id_filter_for_alignment_options = openms_id_filter_options.clone() -def openms_id_filter_whitelist_options = modules['openms_id_filter_whitelist'] -openms_id_filter_options.args += " -score:pep " + params.fdr_threshold -openms_id_filter_refiner_options.args += " -score:pep " + params.fdr_threshold -openms_id_filter_for_alignment_options.args += " -score:pep " + (params.fdr_threshold == '0.01') ? Utils.joinModuleArgs(['-score:pep 0.05']) : Utils.joinModuleArgs(['-score:pep ' + params.fdr_threshold]) -def openms_id_filter_qvalue_options = openms_id_filter_options.clone() -openms_id_filter_qvalue_options.suffix = "filtered" - -def openms_map_aligner_identification_options = modules['openms_map_aligner_identification'] -def openms_mztab_exporter_perc_options = modules['openms_mztab_exporter_perc'] -def openms_mztab_exporter_psm_options = modules['openms_mztab_exporter_psm'] -def openms_percolator_adapter_options = modules['openms_percolator_adapter'] -def openms_percolator_adapter_refine_options = modules['openms_percolator_adapter_refine'] -openms_percolator_adapter_options.args += (params.fdr_level != 'psm-level-fdrs') ? Utils.joinModuleArgs(['-'+params.fdr_level]) : '' -openms_percolator_adapter_refine_options.args += (params.fdr_level != 'psm-level-fdrs') ? Utils.joinModuleArgs(['-'+params.fdr_level]) : '' -def openms_percolator_adapter_klammer_options = openms_percolator_adapter_options.clone() -openms_percolator_adapter_klammer_options.args += " -klammer" - -def openms_rt_predict_peptides_options = modules['openms_rt_predict_peptides'] -def openms_rt_predict_neo_epitopes_options = modules['openms_rt_predict_neo_epitopes'] +//def modules = params.modules.clone() + +//def multiqc_options = modules['multiqc'] +//multiqc_options.args += params.multiqc_title ? Utils.joinModuleArgs(["--title \"$params.multiqc_title\""]) : '' +// +//def generate_proteins_from_vcf_options = modules['generate_proteins_from_vcf'] +//generate_proteins_from_vcf_options.args += params.variant_indel_filter ? Utils.joinModuleArgs(['-fINDEL']) : '' +//generate_proteins_from_vcf_options.args += params.variant_frameshift_filter ? Utils.joinModuleArgs(['-fFS']) : '' +//generate_proteins_from_vcf_options.args += params.variant_snp_filter ? Utils.joinModuleArgs(['-fSNP']) : '' +// +//def openms_comet_adapter_options = modules['openms_comet_adapter'] +//openms_comet_adapter_options.args += params.use_x_ions ? Utils.joinModuleArgs(['-use_X_ions true']) : '' +//openms_comet_adapter_options.args += params.use_z_ions ? Utils.joinModuleArgs(['-use_Z_ions true']) : '' +//openms_comet_adapter_options.args += params.use_a_ions ? Utils.joinModuleArgs(['-use_A_ions true']) : '' +//openms_comet_adapter_options.args += params.use_c_ions ? Utils.joinModuleArgs(['-use_C_ions true']) : '' +//openms_comet_adapter_options.args += params.use_NL_ions ? Utils.joinModuleArgs(['-use_NL_ions true']) : '' +//openms_comet_adapter_options.args += params.remove_precursor_peak ? Utils.joinModuleArgs(['-remove_precursor_peak yes']) : '' +// +//def openms_id_filter_options = modules['openms_id_filter'] +//def openms_id_filter_refiner_options = modules['openms_id_filter_refiner'] +//def openms_id_filter_for_alignment_options = openms_id_filter_options.clone() +//def openms_id_filter_whitelist_options = modules['openms_id_filter_whitelist'] +//openms_id_filter_options.args += " -score:pep " + params.fdr_threshold +//openms_id_filter_refiner_options.args += " -score:pep " + params.fdr_threshold +//openms_id_filter_for_alignment_options.args += " -score:pep " + (params.fdr_threshold == '0.01') ? Utils.joinModuleArgs(['-score:pep 0.05']) : Utils.joinModuleArgs(['-score:pep ' + params.fdr_threshold]) +//def openms_id_filter_qvalue_options = openms_id_filter_options.clone() +//openms_id_filter_qvalue_options.suffix = "filtered" +// +//def openms_map_aligner_identification_options = modules['openms_map_aligner_identification'] +//def openms_mztab_exporter_perc_options = modules['openms_mztab_exporter_perc'] +//def openms_mztab_exporter_psm_options = modules['openms_mztab_exporter_psm'] +//def openms_percolator_adapter_options = modules['openms_percolator_adapter'] +//def openms_percolator_adapter_refine_options = modules['openms_percolator_adapter_refine'] +//openms_percolator_adapter_options.args += (params.fdr_level != 'psm-level-fdrs') ? Utils.joinModuleArgs(['-'+params.fdr_level]) : '' +//openms_percolator_adapter_refine_options.args += (params.fdr_level != 'psm-level-fdrs') ? Utils.joinModuleArgs(['-'+params.fdr_level]) : '' +//def openms_percolator_adapter_klammer_options = openms_percolator_adapter_options.clone() +//openms_percolator_adapter_klammer_options.args += " -klammer" +// +//def openms_rt_predict_peptides_options = modules['openms_rt_predict_peptides'] +//def openms_rt_predict_neo_epitopes_options = modules['openms_rt_predict_neo_epitopes'] //////////////////////////////////////////////////// /* -- CREATE CHANNELS -- */ //////////////////////////////////////////////////// -include { hasExtension } from '../modules/local/functions' - -include { INPUT_CHECK } from '../subworkflows/local/input_check' addParams( options: [:] ) -include { GENERATE_PROTEINS_FROM_VCF } from '../modules/local/generate_proteins_from_vcf' addParams( options: generate_proteins_from_vcf_options ) -include { OPENMS_DECOYDATABASE } from '../modules/local/openms_decoydatabase' addParams( options: [:] ) -include { OPENMS_THERMORAWFILEPARSER } from '../modules/local/openms_thermorawfileparser' addParams( options: [:] ) -include { OPENMS_PEAKPICKERHIRES } from '../modules/local/openms_peakpickerhires' addParams( options: [:] ) -include { OPENMS_COMETADAPTER } from '../modules/local/openms_cometadapter' addParams( options: openms_comet_adapter_options ) -include { OPENMS_PEPTIDEINDEXER } from '../modules/local/openms_peptideindexer' addParams( options: [:] ) -include { OPENMS_FALSEDISCOVERYRATE } from '../modules/local/openms_falsediscoveryrate' addParams( options: [:] ) -include { OPENMS_IDFILTER as OPENMS_IDFILTER_FOR_ALIGNMENT }from '../modules/local/openms_idfilter' addParams( options: openms_id_filter_for_alignment_options ) -include { OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE } from '../modules/local/openms_idfilter' addParams( options: openms_id_filter_qvalue_options ) -include { OPENMS_MAPALIGNERIDENTIFICATION } from '../modules/local/openms_mapaligneridentification' addParams( options: openms_map_aligner_identification_options ) - -include { - OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERMZML - OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERIDXML } from '../modules/local/openms_maprttransformer' addParams( options: [:] ) - -include { OPENMS_IDMERGER } from '../modules/local/openms_idmerger' addParams( options: [:] ) -include { OPENMS_PSMFEATUREEXTRACTOR } from '../modules/local/openms_psmfeatureextractor' addParams( options: [:] ) -include { OPENMS_PERCOLATORADAPTER } from '../modules/local/openms_percolatoradapter' addParams( options: openms_percolator_adapter_options ) -include { OPENMS_PERCOLATORADAPTER as OPENMS_PERCOLATORADAPTER_KLAMMER } from '../modules/local/openms_percolatoradapter' addParams( options: openms_percolator_adapter_klammer_options ) - -include { REFINE_FDR_ON_PREDICTED_SUBSET } from '../subworkflows/local/refine_fdr_on_predicted_subset' addParams( exporter_prec_options : openms_mztab_exporter_perc_options, exporter_psm_options : openms_mztab_exporter_psm_options, run_percolator_options : openms_percolator_adapter_refine_options, whitelist_filter_options: openms_id_filter_whitelist_options, filter_options: openms_id_filter_refiner_options) - -include { OPENMS_FEATUREFINDERIDENTIFICATION } from '../modules/local/openms_featurefinderidentification' addParams( options: [:] ) -include { OPENMS_FEATURELINKERUNLABELEDKD } from '../modules/local/openms_featurelinkerunlabeledkd' addParams( options: [:] ) -include { OPENMS_IDCONFLICTRESOLVER } from '../modules/local/openms_idconflictresolver' addParams( options: [:] ) -include { OPENMS_TEXTEXPORTER } from '../modules/local/openms_textexporter' addParams( options: [:] ) -include { OPENMS_MZTABEXPORTER } from '../modules/local/openms_mztabexporter' addParams( options: [:] ) - -include { MHCFLURRY_PREDICTPEPTIDESCLASS1 } from '../modules/local/mhcflurry_predictpeptidesclass1' addParams( options: [:] ) -include { MHCNUGGETS_PEPTIDESCLASS2PRE } from '../modules/local/mhcnuggets_peptidesclass2pre' addParams( options: [:] ) -include { MHCNUGGETS_PREDICTPEPTIDESCLASS2 } from '../modules/local/mhcnuggets_predictpeptidesclass2' addParams( options: [:] ) -include { MHCNUGGETS_PEPTIDESCLASS2POST } from '../modules/local/mhcnuggets_peptidesclass2post' addParams( options: [:] ) -include { PREDICT_POSSIBLE_NEOEPITOPES } from '../modules/local/predict_possible_neoepitopes' addParams( options: [:] ) -include { PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES } from '../modules/local/predict_possible_class_2_neoepitopes' addParams( options: [:] ) -include { RESOLVE_FOUND_NEOEPITOPES } from '../modules/local/resolve_found_neoepitopes' addParams( options: [:] ) -include { RESOLVE_FOUND_CLASS_2_NEOEPITOPES } from '../modules/local/resolve_found_class_2_neoepitopes' addParams( options: [:] ) -include { MHCFLURRY_PREDICTNEOEPITOPESCLASS1 } from '../modules/local/mhcflurry_predictneoepitopesclass1' addParams( options: [:] ) -include { MHCNUGGETS_NEOEPITOPESCLASS2RE } from '../modules/local/mhcnuggets_neoepitopesclass2pre' addParams( options: [:] ) -include { MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 } from '../modules/local/mhcnuggets_predictneoepitopesclass2' addParams( options: [:] ) -include { MHCNUGGETS_NEOEPITOPESCLASS2POST } from '../modules/local/mhcnuggets_neoepitopesclass2post' addParams( options: [:] ) - -include { OPENMS_RTMODEL } from '../modules/local/openms_rtmodel' addParams( options: [:] ) -include { OPENMS_RTPREDICT as OPENMS_RTPREDICT_FOUND_PEPTIDES} from '../modules/local/openms_rtpredict' addParams( options: openms_rt_predict_peptides_options ) -include { OPENMS_RTPREDICT as OPENMS_RTPREDICT_NEOEPITOPES} from '../modules/local/openms_rtpredict' addParams( options: openms_rt_predict_neo_epitopes_options ) - -include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' addParams( options: [publish_files : ['_versions.yml':'']] ) -include { MULTIQC } from '../modules/nf-core/modules/multiqc/main' addParams( options: multiqc_options ) +//include { hasExtension } from '../modules/local/functions' + +include { INPUT_CHECK } from '../subworkflows/local/input_check' +//include { GENERATE_PROTEINS_FROM_VCF } from '../modules/local/generate_proteins_from_vcf' addParams( options: generate_proteins_from_vcf_options ) +//include { OPENMS_DECOYDATABASE } from '../modules/local/openms_decoydatabase' addParams( options: [:] ) +//include { OPENMS_THERMORAWFILEPARSER } from '../modules/local/openms_thermorawfileparser' addParams( options: [:] ) +//include { OPENMS_PEAKPICKERHIRES } from '../modules/local/openms_peakpickerhires' addParams( options: [:] ) +//include { OPENMS_COMETADAPTER } from '../modules/local/openms_cometadapter' addParams( options: openms_comet_adapter_options ) +//include { OPENMS_PEPTIDEINDEXER } from '../modules/local/openms_peptideindexer' addParams( options: [:] ) +//include { OPENMS_FALSEDISCOVERYRATE } from '../modules/local/openms_falsediscoveryrate' addParams( options: [:] ) +//include { OPENMS_IDFILTER as OPENMS_IDFILTER_FOR_ALIGNMENT } from '../modules/local/openms_idfilter' addParams( options: openms_id_filter_for_alignment_options ) +//include { OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE } from '../modules/local/openms_idfilter' addParams( options: openms_id_filter_qvalue_options ) +//include { OPENMS_MAPALIGNERIDENTIFICATION } from '../modules/local/openms_mapaligneridentification' addParams( options: openms_map_aligner_identification_options ) +// +//include { +// OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERMZML +// OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERIDXML } from '../modules/local/openms_maprttransformer' addParams( options: [:] ) +// +//include { OPENMS_IDMERGER } from '../modules/local/openms_idmerger' addParams( options: [:] ) +//include { OPENMS_PSMFEATUREEXTRACTOR } from '../modules/local/openms_psmfeatureextractor' addParams( options: [:] ) +//include { OPENMS_PERCOLATORADAPTER } from '../modules/local/openms_percolatoradapter' addParams( options: openms_percolator_adapter_options ) +//include { OPENMS_PERCOLATORADAPTER as OPENMS_PERCOLATORADAPTER_KLAMMER } from '../modules/local/openms_percolatoradapter' addParams( options: openms_percolator_adapter_klammer_options ) +// +//include { REFINE_FDR_ON_PREDICTED_SUBSET } from '../subworkflows/local/refine_fdr_on_predicted_subset' addParams( exporter_prec_options : openms_mztab_exporter_perc_options, exporter_psm_options : openms_mztab_exporter_psm_options, run_percolator_options : openms_percolator_adapter_refine_options, whitelist_filter_options: openms_id_filter_whitelist_options, filter_options: openms_id_filter_refiner_options) +// +//include { OPENMS_FEATUREFINDERIDENTIFICATION } from '../modules/local/openms_featurefinderidentification' addParams( options: [:] ) +//include { OPENMS_FEATURELINKERUNLABELEDKD } from '../modules/local/openms_featurelinkerunlabeledkd' addParams( options: [:] ) +//include { OPENMS_IDCONFLICTRESOLVER } from '../modules/local/openms_idconflictresolver' addParams( options: [:] ) +//include { OPENMS_TEXTEXPORTER } from '../modules/local/openms_textexporter' addParams( options: [:] ) +//include { OPENMS_MZTABEXPORTER } from '../modules/local/openms_mztabexporter' addParams( options: [:] ) +// +//include { MHCFLURRY_PREDICTPEPTIDESCLASS1 } from '../modules/local/mhcflurry_predictpeptidesclass1' addParams( options: [:] ) +//include { MHCNUGGETS_PEPTIDESCLASS2PRE } from '../modules/local/mhcnuggets_peptidesclass2pre' addParams( options: [:] ) +//include { MHCNUGGETS_PREDICTPEPTIDESCLASS2 } from '../modules/local/mhcnuggets_predictpeptidesclass2' addParams( options: [:] ) +//include { MHCNUGGETS_PEPTIDESCLASS2POST } from '../modules/local/mhcnuggets_peptidesclass2post' addParams( options: [:] ) +//include { PREDICT_POSSIBLE_NEOEPITOPES } from '../modules/local/predict_possible_neoepitopes' addParams( options: [:] ) +//include { PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES } from '../modules/local/predict_possible_class_2_neoepitopes' addParams( options: [:] ) +//include { RESOLVE_FOUND_NEOEPITOPES } from '../modules/local/resolve_found_neoepitopes' addParams( options: [:] ) +//include { RESOLVE_FOUND_CLASS_2_NEOEPITOPES } from '../modules/local/resolve_found_class_2_neoepitopes' addParams( options: [:] ) +//include { MHCFLURRY_PREDICTNEOEPITOPESCLASS1 } from '../modules/local/mhcflurry_predictneoepitopesclass1' addParams( options: [:] ) +//include { MHCNUGGETS_NEOEPITOPESCLASS2RE } from '../modules/local/mhcnuggets_neoepitopesclass2pre' addParams( options: [:] ) +//include { MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 } from '../modules/local/mhcnuggets_predictneoepitopesclass2' addParams( options: [:] ) +//include { MHCNUGGETS_NEOEPITOPESCLASS2POST } from '../modules/local/mhcnuggets_neoepitopesclass2post' addParams( options: [:] ) +// +//include { OPENMS_RTMODEL } from '../modules/local/openms_rtmodel' addParams( options: [:] ) +//include { OPENMS_RTPREDICT as OPENMS_RTPREDICT_FOUND_PEPTIDES} from '../modules/local/openms_rtpredict' addParams( options: openms_rt_predict_peptides_options ) +//include { OPENMS_RTPREDICT as OPENMS_RTPREDICT_NEOEPITOPES} from '../modules/local/openms_rtpredict' addParams( options: openms_rt_predict_neo_epitopes_options ) +// +include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' //addParams( options: [publish_files : ['_versions.yml':'']] ) +include { MULTIQC } from '../modules/nf-core/modules/multiqc/main' //addParams( options: multiqc_options ) //////////////////////////////////////////////////// /* -- RUN MAIN WORKFLOW -- */ @@ -170,6 +170,8 @@ workflow MHCQUANT { .reads .set { ch_samples_from_sheet } + ch_versions = ch_versions.mix(INPUT_CHECK.out.versions) + ch_samples_from_sheet .branch { meta, filename -> @@ -191,279 +193,279 @@ workflow MHCQUANT { // A warning message will be given when the format differs from the '.raw' or '.mzML' extention ms_files.other.subscribe { row -> log.warn("Unknown format for entry " + row[3] + " in provided sample sheet, line will be ignored."); exit 1 } - if ( params.include_proteins_from_vcf ) { - // Combine the vcf information with the meta information - ch_vcf = input_fasta - .map{ it -> [it[0].sample, it[0], it[1]] } - .join( ch_vcf_from_sheet ) - .map(it -> [it[1], it[2], it[3]]) - // If specified translate variants to proteins and include in reference fasta - GENERATE_PROTEINS_FROM_VCF( ch_vcf ) - ch_versions = ch_versions.mix(GENERATE_PROTEINS_FROM_VCF.out.versions.first().ifEmpty(null)) - ch_fasta_file = GENERATE_PROTEINS_FROM_VCF.out.vcf_fasta - } else { - ch_fasta_file = input_fasta - } - - if (!params.skip_decoy_generation) { - // Generate reversed decoy database - OPENMS_DECOYDATABASE(ch_fasta_file) - ch_versions = ch_versions.mix(OPENMS_DECOYDATABASE.out.versions.first().ifEmpty(null)) - ch_decoy_db = OPENMS_DECOYDATABASE.out.decoy - } else { - ch_decoy_db = ch_fasta_file - } - - // Raw file conversion - OPENMS_THERMORAWFILEPARSER(ms_files.raw) - ch_versions = ch_versions.mix(OPENMS_THERMORAWFILEPARSER.out.versions.first().ifEmpty(null)) - - if ( params.run_centroidisation ) { - // Optional: Run Peak Picking as Preprocessing - OPENMS_PEAKPICKERHIRES(ms_files.mzml) - ch_versions = ch_versions.mix(OPENMS_PEAKPICKERHIRES.out.versions.first().ifEmpty(null)) - ch_mzml_file = OPENMS_PEAKPICKERHIRES.out.mzml - } else { - ch_mzml_file = ms_files.mzml - } - - // Run comet database search - OPENMS_COMETADAPTER( - OPENMS_THERMORAWFILEPARSER.out.mzml - .mix(ch_mzml_file) - .join(ch_decoy_db, remainder:true)) - ch_versions = ch_versions.mix(OPENMS_COMETADAPTER.out.versions.first().ifEmpty(null)) - - // Index decoy and target hits - OPENMS_PEPTIDEINDEXER(OPENMS_COMETADAPTER.out.idxml.join(ch_decoy_db)) - ch_versions = ch_versions.mix(OPENMS_PEPTIDEINDEXER.out.versions.first().ifEmpty(null)) - - if(!params.skip_quantification) { - // Calculate fdr for id based alignment - OPENMS_FALSEDISCOVERYRATE(OPENMS_PEPTIDEINDEXER.out.idxml) - ch_versions = ch_versions.mix(OPENMS_FALSEDISCOVERYRATE.out.versions.first().ifEmpty(null)) - // Filter fdr for id based alignment - OPENMS_IDFILTER_FOR_ALIGNMENT(OPENMS_FALSEDISCOVERYRATE.out.idxml - .flatMap { it -> [tuple(it[0], it[1], null)]}) - ch_versions = ch_versions.mix(OPENMS_IDFILTER_FOR_ALIGNMENT.out.versions.first().ifEmpty(null)) - - ch_grouped_fdr_filtered = OPENMS_IDFILTER_FOR_ALIGNMENT.out.idxml - .map { - meta, raw -> - [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] - } - .groupTuple(by: [0]) - - // Compute alignment rt transformatio - OPENMS_MAPALIGNERIDENTIFICATION(ch_grouped_fdr_filtered) - ch_versions = ch_versions.mix(OPENMS_MAPALIGNERIDENTIFICATION.out.versions.first().ifEmpty(null)) - // Intermediate step to join RT transformation files with mzml and idxml channels - ms_files.mzml - .mix(OPENMS_THERMORAWFILEPARSER.out.mzml) - .mix(ch_mzml_file) - .join( - OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml - .transpose() - .flatMap { - meta, trafoxml -> - ident = trafoxml.baseName.split('_-_')[0] - [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] - }, by: [0] ) - .set { joined_trafos_mzmls } - - OPENMS_PEPTIDEINDEXER.out.idxml - .join( - OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml - .transpose() - .flatMap { - meta, trafoxml -> - ident = trafoxml.baseName.split('_-_')[0] - [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] - }, by: [0] ) - .set { joined_trafos_ids } - - // Align mzML files using trafoXMLs - OPENMS_MAPRTTRANSFORMERMZML(joined_trafos_mzmls) - ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERMZML.out.versions.first().ifEmpty(null)) - // Align unfiltered idXMLfiles using trafoXMLs - OPENMS_MAPRTTRANSFORMERIDXML(joined_trafos_ids) - ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERIDXML.out.versions.first().ifEmpty(null)) - ch_proceeding_idx = OPENMS_MAPRTTRANSFORMERIDXML.out.aligned - .map { - meta, raw -> - [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] - } - .groupTuple(by: [0]) - - } else { - ch_proceeding_idx = OPENMS_PEPTIDEINDEXER.out.idxml - .map { - meta, raw -> - [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] - } - .groupTuple(by: [0]) - } - - // Merge aligned idXMLfiles - OPENMS_IDMERGER(ch_proceeding_idx) - ch_versions = ch_versions.mix(OPENMS_IDMERGER.out.versions.first().ifEmpty(null)) - // Extract PSM features for Percolator - OPENMS_PSMFEATUREEXTRACTOR(OPENMS_IDMERGER.out.idxml) - ch_versions = ch_versions.mix(OPENMS_PSMFEATUREEXTRACTOR.out.versions.first().ifEmpty(null)) - // Run Percolator - if (params.description_correct_features > 0 && params.klammer) { - OPENMS_PERCOLATORADAPTER_KLAMMER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) - ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER_KLAMMER.out.versions.first().ifEmpty(null)) - ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER_KLAMMER.out.idxml - - } else { - OPENMS_PERCOLATORADAPTER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) - ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions.first().ifEmpty(null)) - ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER.out.idxml - } - - // Filter by percolator q-value - OPENMS_IDFILTER_Q_VALUE(ch_percolator_adapter_outcome.flatMap { it -> [tuple(it[0], it[1], null)]}) - ch_versions = ch_versions.mix(OPENMS_IDFILTER_Q_VALUE.out.versions.first().ifEmpty(null)) - - // Refine_fdr_on_predicted_subset - if ( params.refine_fdr_on_predicted_subset && params.predict_class_1 ) { - // Run the following subworkflow - REFINE_FDR_ON_PREDICTED_SUBSET ( - OPENMS_IDFILTER_Q_VALUE.out.idxml, - OPENMS_PSMFEATUREEXTRACTOR.out.idxml, - peptides_class_1_alleles - ) - ch_versions = ch_versions.mix(REFINE_FDR_ON_PREDICTED_SUBSET.out.versions.first().ifEmpty(null)) - - // Define the outcome of the paramer to a fixed variable - filter_q_value = REFINE_FDR_ON_PREDICTED_SUBSET.out.filter_refined_q_value.flatMap { it -> [ tuple(it[0].sample, it[0], it[1]) ] } - } else { - // Make sure that the columns that consists of the ID's, sample names and the idXML file names are returned - filter_q_value = OPENMS_IDFILTER_Q_VALUE.out.idxml.map{ it -> [it[0].sample, it[0], it[1]] } - } - - if ( !params.skip_quantification) { - // Combining the necessary information into one channel - OPENMS_IDFILTER_FOR_ALIGNMENT.out[0] - .join( OPENMS_MAPRTTRANSFORMERMZML.out[0], by: [0] ) - .map { it -> [it[0].sample, it[0], it[1], it[2]] } - .combine( filter_q_value , by: [0] ) - .map { it -> [it[1], it[2], it[3], it[5]] } - .set{ joined_mzmls_ids_quant } - // Quantify identifications using targeted feature extraction - OPENMS_FEATUREFINDERIDENTIFICATION(joined_mzmls_ids_quant) - ch_versions = ch_versions.mix(OPENMS_FEATUREFINDERIDENTIFICATION.out.versions.first().ifEmpty(null)) - // Link extracted features - OPENMS_FEATURELINKERUNLABELEDKD( - OPENMS_FEATUREFINDERIDENTIFICATION.out.featurexml - .flatMap { - meta, raw -> - [[[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw]] - } - .groupTuple(by:[0])) - ch_versions = ch_versions.mix(OPENMS_FEATURELINKERUNLABELEDKD.out.versions.first().ifEmpty(null)) - // Resolve conflicting ids matching to the same feature - OPENMS_IDCONFLICTRESOLVER(OPENMS_FEATURELINKERUNLABELEDKD.out.consensusxml) - ch_versions = ch_versions.mix(OPENMS_IDCONFLICTRESOLVER.out.versions.first().ifEmpty(null)) - // Export all information as text to csv - OPENMS_TEXTEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) - ch_versions = ch_versions.mix(OPENMS_TEXTEXPORTER.out.versions.first().ifEmpty(null)) - // Export all information as mzTab - OPENMS_MZTABEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) - ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTER.out.versions.first().ifEmpty(null)) - } - - ////////////////////////////////////////////////////////////////////////////////////////////// - // TODO: Replacement of custom scripts with epytope - ch_predicted_possible_neoepitopes = Channel.empty() - if ( params.predict_class_1 & !params.skip_quantification ) { - // If specified predict peptides using MHCFlurry - MHCFLURRY_PREDICTPEPTIDESCLASS1( - OPENMS_MZTABEXPORTER.out.mztab - .map{ it -> [it[0].sample, it[0], it[1]] } - .combine( peptides_class_1_alleles, by:0) - .map( it -> [it[1], it[2], it[3]]) - ) - ch_versions = ch_versions.mix(MHCFLURRY_PREDICTPEPTIDESCLASS1.out.versions.first().ifEmpty(null)) - if ( params.include_proteins_from_vcf ) { - // Predict all possible neoepitopes from vcf - PREDICT_POSSIBLE_NEOEPITOPES(peptides_class_1_alleles.join(ch_vcf_from_sheet, by:0, remainder:true)) - ch_versions = ch_versions.mix(PREDICT_POSSIBLE_NEOEPITOPES.out.versions.first().ifEmpty(null)) - ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_NEOEPITOPES.out.csv - // Resolve found neoepitopes - RESOLVE_FOUND_NEOEPITOPES( - OPENMS_MZTABEXPORTER.out.mztab - .map{ it -> [it[0].sample, it[0], it[1]] } - .combine( ch_predicted_possible_neoepitopes, by:0, remainder:true) - .map( it -> [it[1], it[2], it[3]]) - ) - ch_versions = ch_versions.mix(RESOLVE_FOUND_NEOEPITOPES.out.versions.first().ifEmpty(null)) - // Predict class 1 neoepitopes MHCFlurry - MHCFLURRY_PREDICTNEOEPITOPESCLASS1(peptides_class_1_alleles.join(RESOLVE_FOUND_NEOEPITOPES.out.csv, by:0)) - ch_versions = ch_versions.mix(MHCFLURRY_PREDICTNEOEPITOPESCLASS1.out.versions.first().ifEmpty(null)) - } - } - - ch_predicted_possible_neoepitopes_II = Channel.empty() - if ( params.predict_class_2 & !params.skip_quantification ) { - // Preprocess found peptides for MHCNuggets prediction class 2 - MHCNUGGETS_PEPTIDESCLASS2PRE(OPENMS_MZTABEXPORTER.out.mztab) - ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2PRE.out.versions.first().ifEmpty(null)) - // Predict found peptides using MHCNuggets class 2 - MHCNUGGETS_PREDICTPEPTIDESCLASS2( - MHCNUGGETS_PEPTIDESCLASS2PRE.out.preprocessed - .map{ it -> [it[0].sample, it[0], it[1]] } - .join(peptides_class_2_alleles, by:0) - .map( it -> [it[1], it[2], it[3]]) - ) - ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.versions.first().ifEmpty(null)) - // Postprocess predicted MHCNuggets peptides class 2 - MHCNUGGETS_PEPTIDESCLASS2POST( MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.csv.join(MHCNUGGETS_PEPTIDESCLASS2PRE.out.geneID, by:0) ) - ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2POST.out.versions.first().ifEmpty(null)) - - if ( params.include_proteins_from_vcf ) { - // Predict all possible class 2 neoepitopes from vcf - PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES(peptides_class_2_alleles.join(ch_vcf_from_sheet, by:0, remainder:true)) - ch_versions = ch_versions.mix(PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) - ch_predicted_possible_neoepitopes_II = PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.csv - // Resolve found class 2 neoepitopes - RESOLVE_FOUND_CLASS_2_NEOEPITOPES( - OPENMS_MZTABEXPORTER.out.mztab - .map{ it -> [it[0].sample, it[1]] } - .combine( ch_predicted_possible_neoepitopes_II, by:0, remainder:true) - ) - ch_versions = ch_versions.mix(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) - // Preprocess resolved neoepitopes in a format that MHCNuggets understands - MHCNUGGETS_NEOEPITOPESCLASS2RE(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv) - ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2RE.out.versions.first().ifEmpty(null)) - // Predict class 2 MHCNuggets - MHCNUGGETS_PREDICTNEOEPITOPESCLASS2(MHCNUGGETS_NEOEPITOPESCLASS2RE.out.preprocessed.join(peptides_class_2_alleles, by:0)) - ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTNEOEPITOPESCLASS2.out.versions.first().ifEmpty(null)) - // Class 2 MHCNuggets Postprocessing - MHCNUGGETS_NEOEPITOPESCLASS2POST(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv.join(PREDICT_NEOEPITOPES_MHCNUGGETS_CLASS_2.out.csv, by:0)) - ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2POST.out.versions.first().ifEmpty(null)) - } - } - ////////////////////////////////////////////////////////////////////////////////////////////// - if ( params.predict_RT ) { - filter_q_value = filter_q_value.map{ it -> [it[1], it[2]] } - // Train Retention Times Predictor - OPENMS_RTMODEL(filter_q_value) - ch_versions = ch_versions.mix(OPENMS_RTMODEL.out.versions.first().ifEmpty(null)) - // Retention Times Predictor Found Peptides - OPENMS_RTPREDICT_FOUND_PEPTIDES(filter_q_value.join(OPENMS_RTMODEL.out.complete, by:[0])) - ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) - // Retention Times Predictor possible Neoepitopes - OPENMS_RTPREDICT_NEOEPITOPES(ch_predicted_possible_neoepitopes.mix(ch_predicted_possible_neoepitopes_II).join(OPENMS_RTMODEL.out.complete, by:[0])) - ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) - } +// if ( params.include_proteins_from_vcf ) { +// // Combine the vcf information with the meta information +// ch_vcf = input_fasta +// .map{ it -> [it[0].sample, it[0], it[1]] } +// .join( ch_vcf_from_sheet ) +// .map(it -> [it[1], it[2], it[3]]) +// // If specified translate variants to proteins and include in reference fasta +// GENERATE_PROTEINS_FROM_VCF( ch_vcf ) +// ch_versions = ch_versions.mix(GENERATE_PROTEINS_FROM_VCF.out.versions.first().ifEmpty(null)) +// ch_fasta_file = GENERATE_PROTEINS_FROM_VCF.out.vcf_fasta +// } else { +// ch_fasta_file = input_fasta +// } +// +// if (!params.skip_decoy_generation) { +// // Generate reversed decoy database +// OPENMS_DECOYDATABASE(ch_fasta_file) +// ch_versions = ch_versions.mix(OPENMS_DECOYDATABASE.out.versions.first().ifEmpty(null)) +// ch_decoy_db = OPENMS_DECOYDATABASE.out.decoy +// } else { +// ch_decoy_db = ch_fasta_file +// } +// +// // Raw file conversion +// OPENMS_THERMORAWFILEPARSER(ms_files.raw) +// ch_versions = ch_versions.mix(OPENMS_THERMORAWFILEPARSER.out.versions.first().ifEmpty(null)) +// +// if ( params.run_centroidisation ) { +// // Optional: Run Peak Picking as Preprocessing +// OPENMS_PEAKPICKERHIRES(ms_files.mzml) +// ch_versions = ch_versions.mix(OPENMS_PEAKPICKERHIRES.out.versions.first().ifEmpty(null)) +// ch_mzml_file = OPENMS_PEAKPICKERHIRES.out.mzml +// } else { +// ch_mzml_file = ms_files.mzml +// } +// +// // Run comet database search +// OPENMS_COMETADAPTER( +// OPENMS_THERMORAWFILEPARSER.out.mzml +// .mix(ch_mzml_file) +// .join(ch_decoy_db, remainder:true)) +// ch_versions = ch_versions.mix(OPENMS_COMETADAPTER.out.versions.first().ifEmpty(null)) +// +// // Index decoy and target hits +// OPENMS_PEPTIDEINDEXER(OPENMS_COMETADAPTER.out.idxml.join(ch_decoy_db)) +// ch_versions = ch_versions.mix(OPENMS_PEPTIDEINDEXER.out.versions.first().ifEmpty(null)) +// +// if(!params.skip_quantification) { +// // Calculate fdr for id based alignment +// OPENMS_FALSEDISCOVERYRATE(OPENMS_PEPTIDEINDEXER.out.idxml) +// ch_versions = ch_versions.mix(OPENMS_FALSEDISCOVERYRATE.out.versions.first().ifEmpty(null)) +// // Filter fdr for id based alignment +// OPENMS_IDFILTER_FOR_ALIGNMENT(OPENMS_FALSEDISCOVERYRATE.out.idxml +// .flatMap { it -> [tuple(it[0], it[1], null)]}) +// ch_versions = ch_versions.mix(OPENMS_IDFILTER_FOR_ALIGNMENT.out.versions.first().ifEmpty(null)) +// +// ch_grouped_fdr_filtered = OPENMS_IDFILTER_FOR_ALIGNMENT.out.idxml +// .map { +// meta, raw -> +// [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] +// } +// .groupTuple(by: [0]) +// +// // Compute alignment rt transformatio +// OPENMS_MAPALIGNERIDENTIFICATION(ch_grouped_fdr_filtered) +// ch_versions = ch_versions.mix(OPENMS_MAPALIGNERIDENTIFICATION.out.versions.first().ifEmpty(null)) +// // Intermediate step to join RT transformation files with mzml and idxml channels +// ms_files.mzml +// .mix(OPENMS_THERMORAWFILEPARSER.out.mzml) +// .mix(ch_mzml_file) +// .join( +// OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml +// .transpose() +// .flatMap { +// meta, trafoxml -> +// ident = trafoxml.baseName.split('_-_')[0] +// [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] +// }, by: [0] ) +// .set { joined_trafos_mzmls } +// +// OPENMS_PEPTIDEINDEXER.out.idxml +// .join( +// OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml +// .transpose() +// .flatMap { +// meta, trafoxml -> +// ident = trafoxml.baseName.split('_-_')[0] +// [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] +// }, by: [0] ) +// .set { joined_trafos_ids } +// +// // Align mzML files using trafoXMLs +// OPENMS_MAPRTTRANSFORMERMZML(joined_trafos_mzmls) +// ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERMZML.out.versions.first().ifEmpty(null)) +// // Align unfiltered idXMLfiles using trafoXMLs +// OPENMS_MAPRTTRANSFORMERIDXML(joined_trafos_ids) +// ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERIDXML.out.versions.first().ifEmpty(null)) +// ch_proceeding_idx = OPENMS_MAPRTTRANSFORMERIDXML.out.aligned +// .map { +// meta, raw -> +// [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] +// } +// .groupTuple(by: [0]) +// +// } else { +// ch_proceeding_idx = OPENMS_PEPTIDEINDEXER.out.idxml +// .map { +// meta, raw -> +// [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] +// } +// .groupTuple(by: [0]) +// } +// +// // Merge aligned idXMLfiles +// OPENMS_IDMERGER(ch_proceeding_idx) +// ch_versions = ch_versions.mix(OPENMS_IDMERGER.out.versions.first().ifEmpty(null)) +// // Extract PSM features for Percolator +// OPENMS_PSMFEATUREEXTRACTOR(OPENMS_IDMERGER.out.idxml) +// ch_versions = ch_versions.mix(OPENMS_PSMFEATUREEXTRACTOR.out.versions.first().ifEmpty(null)) +// // Run Percolator +// if (params.description_correct_features > 0 && params.klammer) { +// OPENMS_PERCOLATORADAPTER_KLAMMER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) +// ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER_KLAMMER.out.versions.first().ifEmpty(null)) +// ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER_KLAMMER.out.idxml +// +// } else { +// OPENMS_PERCOLATORADAPTER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) +// ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions.first().ifEmpty(null)) +// ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER.out.idxml +// } +// +// // Filter by percolator q-value +// OPENMS_IDFILTER_Q_VALUE(ch_percolator_adapter_outcome.flatMap { it -> [tuple(it[0], it[1], null)]}) +// ch_versions = ch_versions.mix(OPENMS_IDFILTER_Q_VALUE.out.versions.first().ifEmpty(null)) +// +// // Refine_fdr_on_predicted_subset +// if ( params.refine_fdr_on_predicted_subset && params.predict_class_1 ) { +// // Run the following subworkflow +// REFINE_FDR_ON_PREDICTED_SUBSET ( +// OPENMS_IDFILTER_Q_VALUE.out.idxml, +// OPENMS_PSMFEATUREEXTRACTOR.out.idxml, +// peptides_class_1_alleles +// ) +// ch_versions = ch_versions.mix(REFINE_FDR_ON_PREDICTED_SUBSET.out.versions.first().ifEmpty(null)) +// +// // Define the outcome of the paramer to a fixed variable +// filter_q_value = REFINE_FDR_ON_PREDICTED_SUBSET.out.filter_refined_q_value.flatMap { it -> [ tuple(it[0].sample, it[0], it[1]) ] } +// } else { +// // Make sure that the columns that consists of the ID's, sample names and the idXML file names are returned +// filter_q_value = OPENMS_IDFILTER_Q_VALUE.out.idxml.map{ it -> [it[0].sample, it[0], it[1]] } +// } +// +// if ( !params.skip_quantification) { +// // Combining the necessary information into one channel +// OPENMS_IDFILTER_FOR_ALIGNMENT.out[0] +// .join( OPENMS_MAPRTTRANSFORMERMZML.out[0], by: [0] ) +// .map { it -> [it[0].sample, it[0], it[1], it[2]] } +// .combine( filter_q_value , by: [0] ) +// .map { it -> [it[1], it[2], it[3], it[5]] } +// .set{ joined_mzmls_ids_quant } +// // Quantify identifications using targeted feature extraction +// OPENMS_FEATUREFINDERIDENTIFICATION(joined_mzmls_ids_quant) +// ch_versions = ch_versions.mix(OPENMS_FEATUREFINDERIDENTIFICATION.out.versions.first().ifEmpty(null)) +// // Link extracted features +// OPENMS_FEATURELINKERUNLABELEDKD( +// OPENMS_FEATUREFINDERIDENTIFICATION.out.featurexml +// .flatMap { +// meta, raw -> +// [[[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw]] +// } +// .groupTuple(by:[0])) +// ch_versions = ch_versions.mix(OPENMS_FEATURELINKERUNLABELEDKD.out.versions.first().ifEmpty(null)) +// // Resolve conflicting ids matching to the same feature +// OPENMS_IDCONFLICTRESOLVER(OPENMS_FEATURELINKERUNLABELEDKD.out.consensusxml) +// ch_versions = ch_versions.mix(OPENMS_IDCONFLICTRESOLVER.out.versions.first().ifEmpty(null)) +// // Export all information as text to csv +// OPENMS_TEXTEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) +// ch_versions = ch_versions.mix(OPENMS_TEXTEXPORTER.out.versions.first().ifEmpty(null)) +// // Export all information as mzTab +// OPENMS_MZTABEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) +// ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTER.out.versions.first().ifEmpty(null)) +// } +// +// ////////////////////////////////////////////////////////////////////////////////////////////// +// // TODO: Replacement of custom scripts with epytope +// ch_predicted_possible_neoepitopes = Channel.empty() +// if ( params.predict_class_1 & !params.skip_quantification ) { +// // If specified predict peptides using MHCFlurry +// MHCFLURRY_PREDICTPEPTIDESCLASS1( +// OPENMS_MZTABEXPORTER.out.mztab +// .map{ it -> [it[0].sample, it[0], it[1]] } +// .combine( peptides_class_1_alleles, by:0) +// .map( it -> [it[1], it[2], it[3]]) +// ) +// ch_versions = ch_versions.mix(MHCFLURRY_PREDICTPEPTIDESCLASS1.out.versions.first().ifEmpty(null)) +// if ( params.include_proteins_from_vcf ) { +// // Predict all possible neoepitopes from vcf +// PREDICT_POSSIBLE_NEOEPITOPES(peptides_class_1_alleles.join(ch_vcf_from_sheet, by:0, remainder:true)) +// ch_versions = ch_versions.mix(PREDICT_POSSIBLE_NEOEPITOPES.out.versions.first().ifEmpty(null)) +// ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_NEOEPITOPES.out.csv +// // Resolve found neoepitopes +// RESOLVE_FOUND_NEOEPITOPES( +// OPENMS_MZTABEXPORTER.out.mztab +// .map{ it -> [it[0].sample, it[0], it[1]] } +// .combine( ch_predicted_possible_neoepitopes, by:0, remainder:true) +// .map( it -> [it[1], it[2], it[3]]) +// ) +// ch_versions = ch_versions.mix(RESOLVE_FOUND_NEOEPITOPES.out.versions.first().ifEmpty(null)) +// // Predict class 1 neoepitopes MHCFlurry +// MHCFLURRY_PREDICTNEOEPITOPESCLASS1(peptides_class_1_alleles.join(RESOLVE_FOUND_NEOEPITOPES.out.csv, by:0)) +// ch_versions = ch_versions.mix(MHCFLURRY_PREDICTNEOEPITOPESCLASS1.out.versions.first().ifEmpty(null)) +// } +// } +// +// ch_predicted_possible_neoepitopes_II = Channel.empty() +// if ( params.predict_class_2 & !params.skip_quantification ) { +// // Preprocess found peptides for MHCNuggets prediction class 2 +// MHCNUGGETS_PEPTIDESCLASS2PRE(OPENMS_MZTABEXPORTER.out.mztab) +// ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2PRE.out.versions.first().ifEmpty(null)) +// // Predict found peptides using MHCNuggets class 2 +// MHCNUGGETS_PREDICTPEPTIDESCLASS2( +// MHCNUGGETS_PEPTIDESCLASS2PRE.out.preprocessed +// .map{ it -> [it[0].sample, it[0], it[1]] } +// .join(peptides_class_2_alleles, by:0) +// .map( it -> [it[1], it[2], it[3]]) +// ) +// ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.versions.first().ifEmpty(null)) +// // Postprocess predicted MHCNuggets peptides class 2 +// MHCNUGGETS_PEPTIDESCLASS2POST( MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.csv.join(MHCNUGGETS_PEPTIDESCLASS2PRE.out.geneID, by:0) ) +// ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2POST.out.versions.first().ifEmpty(null)) +// +// if ( params.include_proteins_from_vcf ) { +// // Predict all possible class 2 neoepitopes from vcf +// PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES(peptides_class_2_alleles.join(ch_vcf_from_sheet, by:0, remainder:true)) +// ch_versions = ch_versions.mix(PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) +// ch_predicted_possible_neoepitopes_II = PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.csv +// // Resolve found class 2 neoepitopes +// RESOLVE_FOUND_CLASS_2_NEOEPITOPES( +// OPENMS_MZTABEXPORTER.out.mztab +// .map{ it -> [it[0].sample, it[1]] } +// .combine( ch_predicted_possible_neoepitopes_II, by:0, remainder:true) +// ) +// ch_versions = ch_versions.mix(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) +// // Preprocess resolved neoepitopes in a format that MHCNuggets understands +// MHCNUGGETS_NEOEPITOPESCLASS2RE(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv) +// ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2RE.out.versions.first().ifEmpty(null)) +// // Predict class 2 MHCNuggets +// MHCNUGGETS_PREDICTNEOEPITOPESCLASS2(MHCNUGGETS_NEOEPITOPESCLASS2RE.out.preprocessed.join(peptides_class_2_alleles, by:0)) +// ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTNEOEPITOPESCLASS2.out.versions.first().ifEmpty(null)) +// // Class 2 MHCNuggets Postprocessing +// MHCNUGGETS_NEOEPITOPESCLASS2POST(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv.join(PREDICT_NEOEPITOPES_MHCNUGGETS_CLASS_2.out.csv, by:0)) +// ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2POST.out.versions.first().ifEmpty(null)) +// } +// } +// ////////////////////////////////////////////////////////////////////////////////////////////// +// if ( params.predict_RT ) { +// filter_q_value = filter_q_value.map{ it -> [it[1], it[2]] } +// // Train Retention Times Predictor +// OPENMS_RTMODEL(filter_q_value) +// ch_versions = ch_versions.mix(OPENMS_RTMODEL.out.versions.first().ifEmpty(null)) +// // Retention Times Predictor Found Peptides +// OPENMS_RTPREDICT_FOUND_PEPTIDES(filter_q_value.join(OPENMS_RTMODEL.out.complete, by:[0])) +// ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) +// // Retention Times Predictor possible Neoepitopes +// OPENMS_RTPREDICT_NEOEPITOPES(ch_predicted_possible_neoepitopes.mix(ch_predicted_possible_neoepitopes_II).join(OPENMS_RTMODEL.out.complete, by:[0])) +// ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) +// } // // MODULE: Pipeline reporting // CUSTOM_DUMPSOFTWAREVERSIONS ( - ch_versions.unique().collectFile() + ch_versions.unique().collectFile(name: 'collated_versions.yml') ) // @@ -484,6 +486,7 @@ workflow MHCQUANT { ) multiqc_report = MULTIQC.out.report.toList() + ch_versions = ch_versions.mix(MULTIQC.out.versions) } } From 047c3f5c1410fe968ab776db53f8352e2fedccb8 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Mon, 27 Dec 2021 22:31:45 +0100 Subject: [PATCH 02/60] Changes for the nf core template (version 2.2) --- assets/nf-core-mhcquant_logo_light.png | Bin 288 -> 10923 bytes conf/modules.config | 189 ++++- docs/images/nf-core-mhcquant_logo_dark.png | Bin 0 -> 72464 bytes modules/local/functions.nf | 86 --- modules/local/generate_proteins_from_vcf.nf | 32 +- .../mhcflurry_predictneoepitopesclass1.nf | 25 +- .../local/mhcflurry_predictpeptidesclass1.nf | 22 +- modules/local/mhcflurry_predictpsms.nf | 22 +- .../local/mhcnuggets_neoepitopesclass2post.nf | 21 +- .../local/mhcnuggets_neoepitopesclass2pre.nf | 26 +- .../local/mhcnuggets_peptidesclass2post.nf | 22 +- modules/local/mhcnuggets_peptidesclass2pre.nf | 22 +- .../mhcnuggets_predictneoepitopesclass2.nf | 26 +- .../local/mhcnuggets_predictpeptidesclass2.nf | 22 +- modules/local/openms_cometadapter.nf | 41 +- modules/local/openms_decoydatabase.nf | 19 +- modules/local/openms_falsediscoveryrate.nf | 19 +- .../openms_featurefinderidentification.nf | 26 +- .../local/openms_featurelinkerunlabeledkd.nf | 22 +- modules/local/openms_idconflictresolver.nf | 19 +- modules/local/openms_idfilter.nf | 28 +- modules/local/openms_idmerger.nf | 19 +- .../local/openms_mapaligneridentification.nf | 22 +- modules/local/openms_maprttransformer.nf | 19 +- modules/local/openms_mztabexporter.nf | 27 +- modules/local/openms_peakpickerhires.nf | 19 +- modules/local/openms_peptideindexer.nf | 19 +- modules/local/openms_percolatoradapter.nf | 26 +- modules/local/openms_psmfeatureextractor.nf | 27 +- modules/local/openms_rtmodel.nf | 19 +- modules/local/openms_rtpredict.nf | 23 +- modules/local/openms_textexporter.nf | 23 +- modules/local/openms_thermorawfileparser.nf | 20 +- .../predict_possible_class_2_neoepitopes.nf | 22 +- modules/local/predict_possible_neoepitopes.nf | 22 +- .../resolve_found_class_2_neoepitopes.nf | 43 +- modules/local/resolve_found_neoepitopes.nf | 22 +- nextflow.config | 161 ++--- nextflow_schema.json | 6 +- .../local/refine_fdr_on_predicted_subset.nf | 26 +- workflows/mhcquant.nf | 681 ++++++++---------- 41 files changed, 788 insertions(+), 1147 deletions(-) delete mode 100644 modules/local/functions.nf diff --git a/assets/nf-core-mhcquant_logo_light.png b/assets/nf-core-mhcquant_logo_light.png index dee3db82069b61e9a5380d940355f47ff565057c..c470ddb2869736380dac734457e364fcde9d5c18 100644 GIT binary patch literal 10923 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�T}NMPo;TYNb>*T?FG6HJV!YDOCHY zk){I&hTqOX4z*GHh^*0^dl1wIn{z|#z%4Xs%|mMRN{G_wDsarfiJVHemKxcL*nPRd zelef~3K^k4p+B_iGK`V*Cf|$lA6RQv_Hv)XXRXOfeU4g!ER!vJCUz4NeN`ytCrj36 zlb4JTB!g4}uBSKV&QhcyqXR2mSj18&RpnM`mYe34b!WGe6LvrecNs7e&;^+z*mo5j z!&NsW9fBIH{E>g&x#E~8OBR5?Xw;jk!o0)8&)hm09sHf1ig&Pv=JE;r{aOec;4sLR zsnMLi=DX*cSjv_jctuw2x6<7tC-Kiw(ZA|*O0)Ul zNnVV|K%5h)2n~8G=zk;qWrp9yYYNcf72#d`dMxRc=G0OROO9*bO^T(@z)MG1qc2T| zpv_npZv{!3GG4Y$-}9&aqMKpmUPp4v2j8n`px?HNseNj|+fp3ei|%pnU7?4YMhJ08@fMaYhnaSqi_KX$Gnf%edqBiI#9!xGdbAUl{u^ z_@%+_*Yg>9J4Q73Kyq+>YN+~`;&z_Bd3>r(Zt;=u-EX=TywIck-#)5kUPwKeaEy=|^!7IhTX<3;ibT*rb=e3NK|d|7eD? z9kJDX{~;Xgk^Opj6-u_(M3~M}Sm}LCQDsyoqDTA7_8DmXFDfZ>d@(w@EjtYn(+!O~ z+f6mY7w$Fs8L0>U_hl%n6bhp&RXkh~a@h>!GJLX!uL%=3?5E7#lZ%uneHV2#+Q8Fe zITjKcaiRz=_=COa2!bSu-qW1e7f1l$Rgo`q=Q4dOuexjkR2EKW5T`Q4F|R(Fi;G$8 zI#sRCCOPvO^S+A{zE-L*TG*MjmPx8f167DSeugbs>yj|OD@)Dp*3s%3`1W~MwjvRU zdB&0i*X|NgKKCDEmZyTQeT>2tCpfGpp(stuYLk`S=OChcFA8>Us_YvGkxQx7i2gw;yBVSVV37p>I@s zVrrD-%IZBI10r8v&_=eW(IRVhv?j(pqdDcGP7R`)5)PA{5q2Cusa@+E z=Fxu$aDcr&o})Q=Dxm+uFs>z5*>g0MPVDYQQ9mugh1y=bC27dLs@fNVXFYm16Gt+- zgl}IgoYn5g;cDC4yiAl0`gPkjh-n4_VLg=qBM_{j>?njHEwoqk zeMF9$4l+7d%S)@^Koo`fG@6qi5l+lDrj0o2K%+2eauyKi#dZkV6p6by^Zi|xFU_IK zSPIbg#B-AzthwN(89WRv_~(y4*ZVU(fkkT)G?&jQ=cxI zG6lE)%d{-nHg{X+@Z}Ix*MaV#iiCWmn0>>p*#K)h2(I!^cda8M9N$BnDL>Z)^)YiI zwtbXQWW5eMC5kMEQaH|YOQDIY*f5-~xO0@9KRZvG$A*erRi;4>uv_eW2y@K=lRBi} z5X|=wFH0$b=&=tRG-^2hr2geHhckwYq`$YuH(@T5i@ONd5R|`^=M(3{z&H*I4Tp>q+TqN#yzLe8frA75DJ_1w@YkD@mc9F; zqy)l1l&X%Oz+4BXkL~Yh#gWJJDxlrII#2ZZ^{6pFb4$5rEqUE!D1{M*GGk} zBqslT32Br2t$tTI<*mcP2{%;g z){c$6=VZ~JW$aIF^RBF)ekVIoCR1u(%vgj_!xwiN3(FhkrL~Sziw5ro2`|F|0zQAc zTD#ALUUn;YmglyKrA_ck^+@-I^3*d;d%qN}D&vWnxTwD91Xsht$Ty6%BkyQzOVdlQ z2JN-#C7QF1c$~Yo5%)I9(_2`7R&8)$7$09uTwmDRdFxsoAFVUHK=Z;xQGb-DYr)}u z5{KyCwnz97PLDKBlh6XoNGon_)?9NH+5eW#{Xf{12_OTdq9LU0WQmew%f64hh3-UVLfNJgvL$5SCJK`> zA!HwnkbU0<-!ty}?*0A#2j3q)^LSL~x?b0Lo%1};^E~Hud30G{n|;rrJqQGX9eq*r z3If4GMIac)SeW1^XB+Oyz(2d)FPeKI5FDRqf9PVxISwNbM-gbvb4GqilYODj-uPY< zTVL@qjV>IPW~-A{;W*8Eoy9)#^v%=tci3VQpIj8~EBHG?QY-B&UuoCaa>2VA4#&=k zyX({Sy{A}Pzsxtu1$gA{KO8e5q$PP?p3l=>zW({)wqpk$a@9+7)JYq+2XDVUlz!#~ zIz1q3qsO3q!n@fsEA+?JrD=z(?DCYAg*8_TYika$bmw!K-9C-szi$wZ`h(2>eRERt z|GuXA;{W{c4$wpbF<-|zGC*d(>qqMqqtZ~Dl{NbA9W?|)hPB9nLxEva|c9P2i9&AODy z*ZY*gDa7UlY_w>Zr%#BT6ZXS&Ad%9Iv}_U$&|$v&8nGDDwe}#Kb(Bt?<;$&*7_n(jgL!Tmaz<}H4lZP7b)?&Kb(QX)HEoZ7yQDXL@osSW1w8AQ^n=fRur|+= zZB|#(?jc5wLxI})NE_Wu7hOTFr6Kc(_0|OwcY;W;_i){C#Fw|Rf6Bo<=`(U=azq2M zwJtWdmeJA`5r6%0uCoV4|6As=6L{7h9fBn0A-gOUn*$EvlWojS3ecN{{_h%dxJK&I zyfa!-JUI=MkKCg!{nx&be+_w?)Nh0jeL;yolh9D@X3#1rK!4nRU+DP1ySZ!!HwR)X z#faW%h5Ht1+ig9FIsd=gBf-_+6Di_!tNEUFFDz#)2i>#O*?)@|;i1AAxfe(`^!(!o zsn2|*iJXbk45@nml`;&w%gx(&PZ7VN`^}Vf?XkDo(J9CwAb{{3b(Xmk*X1+Z#{mM}`&+4cnuAmWq?bQ6WB9 zaa^SzMrnPiu5f`h)M|DsjNPGae*W$_+rOTeWu&1LOSQ(vvyF*v9|Z)VlvQfJTVF`Y zM}|J5bkmI}U5yr9dj&p-ez&kmfB1PV=fC$J{sQ1AMzW&cp_&qvpHZ%%U0)>I_}L=L z0EA+WfhxhP!(L(=s^w8DyNxg+RsY`hQ#t_W)gNCdz5xcOBWECZimFd-uL1n*zv-j+v;Lv9zG$1KQZ$`?UU5=04q10c^jtS z9`W873OnqzByTVn!JF~FkN~LG=8@Yzu@!>oc^=vo9MY|sy$O_Dv=8U1kD%`SFXW7T zJF}m1VqAQ@uH(PP+J2$|TX$X^d&lzgG+;LaZe8J!Z_k9E>x->b(e+uW5JPo#a-xCR zE0OT@Pg1;m3osEFj|-MG`#e2kFux8P627Om^aIQdMP=i)yn4fN)US{NY77yKkzBd~ z|KacJPSy>4{rv@{AiCBL_kDb*d}dpcs37Kl1HU1lSMtUS_nPy)#sBb5yJZ4P?LO(V zIRIb@asBSU-XbnuB}ufz-3d*|7QA>@7wg;HETvl9(S;dI|IagLxd8wbII1^RAb5Jc zAE|C}tAK?23Y$jH>!RQ36iA7g^pvR+GjKuD#F?+nQvBjLt^@LaXlLJPaBMYFy>--8 z5G|ubgU-E+jx>aOVi$0ewBQ;kb4n-uNggv_T4w6c4{Y>KwV|zLRchS**oEkf9{$1A zM3%y?Q7N3&&j#0UY)~8cr_LF-=cRJJ&VRztmO{;5G+jnx58e>ONd94~j&Ixsc4}0OUQOL*W;+6a!&Tq|9z2#al zh?7nC|0CRvI(36kh#QXDeCP(~EKc>9FBsuD#b9%BCZ&iUre+w)Xp{7QaP407gLsv<(; z+@D<*EoPze29h8om9)F=|L?BrH*d?Jx6JVsRgUbh5p4gf6&+th(9266n+)hJzb6F< zHunG7{)KbJe{*HWZ1i5tvDbgRMS#?Z67e^N)!ZcDp2PpUr#2SdJT<%y70j8o+W+f0 zwVX@-n?2zB4kQcVz2Tq2@-m>wzp8-Lx8+4!O8C!GOjECs73;mD!_M4{wg>)rM*5a1 zSfzoUws?FLQFrmr*3WG;qw==rb|?i+FMa&K@Mb(j9N-&VFt zmAETSW6|yeu?Na!N=Iz=&(XoK48(!Eaf|djiyqKZh~xO4F(8S zIfdS~@jvfGKG(1CHpgb`jE=SGLCfVx*_HjX;l3aS_2-I|!#d1kZNTK>V2<#{dgaz2 z_^i$u%V-<%=c1?j6-6qzaikJq@*m=CKTsX8-@xp_d}K)+ z2VGK(8oGF?Ec*X*jiy(3E|kK{%G&t;)7FWK7Rrq7TI)>?*Jc72F#e}OA|Hz5 ztW1bN|?jo@KdBojhpNU>% z-f?(F`o`G@K$4#>uU3KaSjG>TQf`N$Fny#^u`E3d0Oqr5^!OX-txXE(kh*qHh4DjO+aD360sV|C#Ix8^lXz@$?0WUQ}ut_ ze@FEhgu@war#&|WU#4i@R zjbEE?T1RoZ8kAUh&7G+B{m_4>H&=^MqmrM2WkTJJq2AORI0PdI3OE**FC?e<(Sz;6Jj%4DkZ!Wqk zqtq&|_^lmxwEg~I*@LsPp*{OZp57^dW={9C@pMV>%M%DK8o|aIy2)cH1zx(SyyoAe z{j`l^>{f=yQ#4I@qs9E)#<>XQ=2L;ofy@c?wweIb_k&AulL0PR{KdN-gNn54-@o$i z&doP+Q_8b}@GqCpwqT4OX08zw(>Ob3EF3W)Q$`_o-06(#zMlR zAxmhvQ1mUkcP1$;9dUpgB7aA5>88DDxd>jNzI#WPea}0r%RF|~vr>NUGR-8*sr!Nt z1TnPqvaNdytK+CvSp21eB6oh8NpF*YNzhp5|Cofqu9lOae2B(xzrShy{#Ngd1x106 zD%jDAIUVe242$D!Xq2@wqcm5x1a&g$MS_>nxi3b&6;3;Y^1`Nn0W zGfLDy=<~8~Rg;ET@TM(Rn=fOudAR|hC=C1F2hk`-u023*pG=9SJgNg%E_k&+h>zam=Z<`FP$ z_R)&Kbr-{n@iujnw|-73X$$7w>12}9^ec>Y=O4BztuGeOb>C+oOEZG*!xc(VDb#`L z5a&^6(dH%`t6D?J6YJZcLks$gTLIyIN5%G>ZD=~{3)mE}9*7{kr-h(zv3n&?_pWa9 z^n;y#Z&q^vKaEv1_BcgU(FsQ|{mO|_QLmhs4!!*^tb+iwCcGnP{vFxQ9B;8K}M6CnqW-y=7YQEzcmOeA( zvv^kls3*Y5($bD{{*KPs#b=1i(5FVK-<{1Go!+hpk5Y46*&=nWSe(UR!A8`^hw)|tNQWhKtw>83=%pvA7H~JP~rF>uj|tL??j4pB|DJNJ)Oxz z&eK*-fNl=U|Cr&CQ;na?Pn zl(O%{prhJwt?_{NQePs40o`A$sOJ09>%dD@nkARO5=kO+o6Fjn1OF7hAmfa_?nH;v zeK+i~hVW3=wk*fFE{j0&>S7;bt)B9Tq*VD|f8=P2ZHv3v@o9d(wVAZpcg^z1TJ5Wu z%D|rLk+hM%?6McltMkL5TT9VXe%<1(J@b!9*2~nUxQ2%2+q?7sb{2znTkmn3Ctgy3 z={SgDj9g3Ne7 z^2F)}2-;kh>3k6|7`9wB+PjdZUGpnOYR24EDtS&erDniqvU%ILlaF+(>z$sxJtu$V zqW{|bnUdt1^*0)TNClC#&ClaXHKul-fCi=A0j8hF-<`;wJmdF|GmvOt`Zy#W?VF`- zO#KP~Q3p|R_yW*JGUYc?O6RU|`PHC@*KcnvY=?{!Sf`clZgWbg9N)+>%dYqO3ef+359xQ++Gal!gOi${hxYNmGSsEhII%zL8y^A*)PAqZxc zuwyoWgP$E%U9X_XEAH4o4cl4eDHAO9M!D{$(dSSoIF+xwSj-Fn4yXFAlQ>1o2y z+_pUmTUdrF{VAc$S$9WwVjvxX$I&$H@DaRS4e6M>q=Pa|vz%YsLRK`1c9+)Iv?`ZQ zd}Q$LM6Il*j5N1C$gWCG>myZ85fqX$78e|5bmo77OB-~U>6l=6fhjbh)x#2OWtRIh z!Y+!D_Dq*GK>Hyl&cD!yj*f=2}3E@3EFTO2z0c;!yTc472rqp2k6 zWct>Jnvl*0!76fD+)6;fJ#>gXF%LA4L@WmbTeI0X0>SoRB6V`74oI<(o2dZbjkb)Z&P}P+a2TNSKKa978EawIP z$`{A4{TyD&F|OXz^McZerTRmfe(*YA>kcAAQ5>9a1DdpXr*{{ofUaH~??(!r5TIwu z1RVniQpY=-CR$;G9|*HQX^#6=f!g>sYO~q+xZ2-w!+(1gmw0>F(PHRe&$7CDp-5BH zlpMR+wRo{L;3Ypjh>opUD=WqrSkn?4bdo5NR`}nfAo4xva0#L?x;VbMHM}#rQ?%b) znUU>0n0J&&dZV%yqT3~#I((3svu`7ELp@O1MtQv!nTY>gu1o3)=?Qy`_gzxHke#*t zobnB_|BK;eJ1EEQ@*yX_pmz8;<()y%7Zj+J&~YyJV!($Ic&-FT)x+W=3rOYb8_7K@ zQ#I6Grl^3=)eQ?pmZ&+SPJs>TEAe7}<#{q~ZM=TLWjA@BXB_l7DWHb3ueixKqvxe` zMrjYg7`8Z-)MI;hw7(K)|0~LjIVOhTGuuNgT75~#@CR)XvC+4 z4x~SttI+o>`bMgra1*rYv~BmgR<0X#%}kl)y)vXtPKV_X+fHk4W*~*Wdk$*5na*7( z@$W6b`f?2O5In*Z(@}cgwe~#x5-0JU9fRJxfW~55G<6XCFUj^zqWIt!c zQKJJ2=di8kFk7Gpzn26QdKi|c-lGK@v*c+Hl5w2?sWI4k?4=DX-wPL4ptp|qoo77! z!+unCbe?3rq^B|ut_hi6Dc<}hoK8)8F*PnZvs6!8lcx6$)$Ao5+wr$6B*F#sI|=A7 z6yiA$o1nWg6%KDZmpA!Vz4kiN{Pl`U(8N}gjk~d1H|b+u$Z%7GPC-}pS{U(z} ztwP9u2kUmJdT7t++E+|(eBHdDVN7y^bcv_+TL+;&HJep+UBq^^D$$I!eFp51jJCc? zQ)!3t^gyLKzJcdIrCdc@n=7+AW)$97c(=K|`kGI2rq{<3duM$p-ljCO(CdTOyFCYW z=R=qEx0vJ=Vcm5PVNX4F7^Q}B#9;3)3lOSCm@ ztMtT_GQ1*C{JQhdnUOQWHM!_tIO_HBQ#rXBq>x`1n5)Elu`J4a-pEr+)Pk6QOxIA^JP0e(KXwuE|`VWtG3{__00i}S3YpbVfy5ZZum;KC1H zJ0kSJY2(D{g?uR1*U~fynTuagf{_KBIrXH@#3xO(IRXqwz|F`18B1uPL2TeC#%Z35 zFXgU(YfFc)#nsWh!zf9i}W{u zd+uC&PN8XOF+lgM7mN_AyjW=4Kfs&pN|>*{JJ4K9pqj}$r**+-Oq z9tBeMQy#eb&pArub5oJ7Ys#8}9Af^aKtctOU#-ZRE6U7lFIFG`0`M5fdDW_ke`bR_ zjDn@q(^U66*!C+ZS!vMZN)g?Fp*3!~?Hjk%pzY)XtzaYh;{T)VEM$BfM@xpK4l^cp zrw}gCSe0JmcM+t~U$DxLc6frV#+km1P;D%~RlY=;N{GKN_L^bwF4!75)7Yh)BuHyz zr3C2p?_R~SLKQn^qC4M&4tejzb>Ifg%Geo60o!|lM~N=zty9DXoazTqe~VtG?-UN( zkH>}hh?N~B8ezwg9p$t&kJ6?MUIS8D*u;OW@~;-`x7YYl=`30m zO0!n_d>=0ssMx1)+7lyv|7Ql6B{}t;RLuKa3rzN6mVgQ@BFytb8N$M69dPT5P-XROe_Xl_1 zD{q0SZjVMKQR=`$^~f451<(0=nU*PUA3|M{BRcECnCaWje8@I!`za*}ym;Tr656Cn zMYRm-?p;QiA{>PE@+>b5`_L^cOyDKJfzO&T((?DIwvR9ByRrZzg9v{3|E@A@;4Rz<2Ta|1ztE7p#5In;-kWS-PSCr4% zZOcJ>pe8aMOd4CZl3`>eb$zxq+ENr%0D6Aha9ZZvy3Owj0R@{kHIA1_W(q z4cub$!_rc(sJ~F)B3e6iLcjrRvPV}76Ez;B(jxHQ$MuxJO9R0Jd3uw8A1n~*9o_jj zu;x=$PXC=GOJ&ALTCbu%0`*%r{5T~HsSemFF;Z^ys5+rBkV0wxr)fKo1AVz27Fw&8 z3>s>9w=Q65-IagvI70e14JomP*P16TVrML25M!p?NCYo)AlI6azR#Lz6Ai-IzRR?( z4+agr(5xfTKs3peZ)u(gG`169WT^In|8Lr19pT}kL>j}s9dTEo6RwyHaHvC1OYW2# z%*U}0mMYktxyYpzJK?o1WDm5dST8Xb7-TZ*Fozk!zyOgU^EXcjhbS$xX8R-oOK`l`(pIO-}*r1to^ zyoS-;qLpAVg-A06KDKWvRf+zz>Etb}FEkQp z&?Y-#gxOsu4=7RV0hlPJlHrA+N4ipRxEG7x^<#oju*?AKN`CLM5^zU0)YNWpAHD~x8*;i6hn7?O762%8|>0#8?9E6Zt>!AKdA zGYia($+%%IWyVaiW^zK8+03y7#BpphZPSFYRU!>SV|ANol+nKd#!}=Uzy=fDz?4N^ zEC+mc_VGiM3avQpCWMv-RE8u9JFPOr?X-Se-xpeuI*jk@O}>l_rzk*F%*P4d?F(uykl(@_0BwS z6pW!{!@xhsi-R0_&0HD5rUE{y&g#GO<4W$CNT$Kd|J=h?1315cZK6>Oz>u&9k`S`b zyMeMcABH>fV*dW){AUNYJRp_6LMoX#IgcYICch6Y_Fnl18f;Yx zZ!8)drgi4?f$MfP`Ja>9*+b#Us!~SVDVGxhw#nwrtndJg9Q4!0$bY85{+05E$_zP+ zRbWx}UFa^pqcL(rA9oRSQsoC5?po8V&nXf_(+C))8b_%Cu!@zX(+04`BA|{~c8(`< zWN$wZZ1Sgp;{8opoA{5c{&%EK+rhGE*?TVz+jdDQ0mQ>tfRZ>wVdqG#qxJFCTq4sH z(ru@Dd5r*BZ3{amio+5zkg%vu%2Hy|_Z;Gm441DJu2 zGyTqdaGf-WVKaTz=%m}(X&Xr%K`NC)^N<+VGtb_6n*~dM&!CO!r$Nq|K+FTN zkm}6tCe5@y2{6P`6w8g>V`s79xJiTg7yTn!!#0Ou278Dc zTz3&N&k{RHnv6!M^ zvX$722lC#wnVH{0a)SLw)Dt(tvS3EvgR3n5PucK&S5JcAMD`00tRTBO{zU= zGD@cO=DpEAluw7n#RteL?Vb9*8&gTg5dxO^0(y6)iS|(NuZ2v%Awe}A8(Opq#Hh>E zjX3Lqbn#o_&`icn)4d(GR3kR4t{weB#H)`l8D{h;V=0%*nUnOZt=8uF3_OyPqa&6*S$#_aDav))vWx_L{XZo4t&A?M)M{HCA{jL4V#eKVT>y!);0mq3p$g(rU zYaG91{)Vs>BR5)u>(*BXHW~&P6hq4F*@aIn9f@yve3lbgCPf@rl$?1yTKWo7U>R8^ z)HfQtaQAhur)$TI{|Ke?<_5NMl_C!CXlN7PUM#Lb-_^!e@Rl6p?i7O@*AzSgW4|5c z*bGb;_LJ{{-~s3&#x#IbQ>MonJw4YImVEL&A}!o3r;u@={^l;1yOrhyY0QGlk25@} zyuzG}IItHYYg+y}jI~u_A?MV}q`+*SfYhlRlZrN1flxg!8*GjB+#FpS&zN=|!repv zS)k;&OP%yN56kjUW&y#}(9JnFP!Y^+65ISzbbT*eTWo`QYB5W3Ej`JuhHf@kH>hHtQR0qEVF9#DPEwf{yE)^XDor9t|be-j5 zR}k$hRA3}H>Xj~ly4dVBu&P}4!}Hw3g>TQ!oQ|6&g`O)9eI`n)nN?`i3koSPe&snM zBO*1eguip{%!isPU!|{(zwVGSNf!+O^iN&aM&BVrv92!$^Ov491V9d2Vy$qLiZ+RL zwuPGQ!Xn|mZIe#qTKxEt#?4z;^-J@wp!D7Qj6GMaEH{Ex^|<|I?Se*b-W1xptEU@i zuNb+24jCBs++5o8W&lrNZrv)}~WAi?GMJxqw4 zFwx!C^G<)h9tjPluh^Q|KFmWcHzoYz)?l_E-}3F6l4oCy>?{kfV>R3YI>K?M-fZ}t z{v0OP9;j-AogQ8Tntjot)-vi)gp`_gQCLYKg{b$@e;0s_q+tgi!n9ghT}%gMaFP%A zZCpPpQUC7yHrKucN-!Gbq@P4QJ+@qJEFB4w{1(bdWb2Cr?2Rw4{&R zsCjizvWlqIK&nSsPb+2IdOPT=9pK0SFByPfcTf5aHK8*j(AJ?U*d}Y`;ioRer<4I& zw-*hkh<%`~r7Hs*U(}rH8@=y5gbZuHg2;N?f9@y#;=C}rS%TkjAHUvw3lg$mTqs>p znyaeycM)0?P@*`V5ejczVJYe`Vc>}6xatics7*S)rs!9uypo}^G`g8?m>&ayx6z$1 z2MstI0|4@cocQ>8OK_#&5;xO~0r1fvS4w)6&dPm1^o z^>H~q4}`8rdGoybVhMYf6-lCebov`kMd$wiyzS}8?D5?XuLPRKeWFPl3xD}?H~PAiQ6%hn@v@V8KAY(HV!$9_J!iunqAQSDHPvJudfRO zm{f48*xPy!llb%Wg5E;b#scpKj&J2^3Dzr!{&QkV_0k>>HN|EJ;0rzaVx|+NN+4L!I;HFE3-Q~t zN1bpM=+^~polMa~OG-kJ`jV%Oa08d_R*anZGDh8o_uQXbc?Yj-kFFKn=ekaiyUudw zYx>2QlR_8X>^rfg)e@6stb5^mkwwuni<kp<7fK8 zz!ltfsQ z&^SfLEdev9yni1b-IB3V;$7HpqxA(T}lT@Sl zJ?aH~C#ew^NxjOC3L6d1R((~BnlwLL`l6ERY0ssl@?;@0R`!t?#utlc`!Sr;;>F|c z!KJlg!5lN_A%e$Y7BHUQS;MlfGtVZTJ8;cj;LV;^B#NmtA}EV=Ja_J(wl4!8L&@7! z;kr1{xx-<3mZM`IO~{Q$Ba6+Mxx11x%U%p)LW`OWy$x2X1n}lXL(I+`N@KFwZ0g;` z!^^Ce+bhrT9}0J8v&qP$wBMFps-=rTwPwHk6e+%{8Xk0)^th1~6>fPG`%1B{st*NG z{%DfwAMe7?%^forD>^qwP{H^zWZ!9Pq~G^Brx5eaX|Ij8^;Vg-Sk5v&Fm0)fpdFU_ zWVkU*iB(ZtZ)hTnli66B#fr2vUsaD66)W*wt-@cs^2{m5JZp7!bb8f9G3#^8NYm{tF zva2;UHP;(*Ppu2s?l-&6uf0qfBn0;LY&z}b6R(l)u0JH;TF|aUXlOLu)wJrzGrKPP zsD?4<6icdhE(1FB4Z4!WPtKn>%1gO$G3JZMjn)C7?SrYjneASOW=ov*hVCjo&XStj z5#~^th7Q`hmPIsdVS4wT<5&S_b`FD4`>~YH>N_KCGk#kIpEC?&8otJi=9c~bnJTzJ z*xpi~aP65J$j(_X>S_ye8{N&UcSq5uMqpHz2#kPvcSEi`6kEoSt=tC_V|qv0ME zRSR<;sump4-Tl}%cluwfMo&fZZMttn2~S52$4<3a4W$;92nDCtMzi()=>2+VUTm^i zRLXyBTjhi^BJV{)V%ee9i`gx`wuiMfH66Ul{;IPKi%yLd8>aY?afCFdy#t!4B}e_M zp+2PCZU0?sn`F%%S(&rPW+llku+>AQvMi|*^)DRMOE)Ho6!D6F`cr4vkp-Mid+|(G zXjG9!)(k!QtL!6E+Xume?+p{D&+y%EQJ&xu+K|2>@bYi{1Qx*x>S$DVLF0;kNwW-| zQ#EN80Y#NUl#ed556zbNLE{A3Lcvtw5N(c0ToY_GZ+oHf8*3jr- zcU4l)mL?W8KNi|x8S=q}d7y8;Fm-#n#y6_g$X;)id;AQq)SH>~UpLRso3o#p;k36V5~xWZ^(2qW?@8c7WTDZOgiqOFQnod`K`efz37_H-_&v49Pd6i3pNh`yDHpGheV}_%N^fX{5?$1PJNZID@!vt+qzugC zd(z!@N!s<1mNP4&z@6p2%9uv_9DuW2O*w_k9J2jFJWj);tAS)5CsEQ z{CVt+=-!g0N9+nzN{va7TSI6bI$MeEB2S3s`lSbg+TZZrSD zE&9B~ghcDP!E@n(+P`9q@jD|t#Isi)I^kYvbL$m~vgx3##m zEDld4d2 z1Y-gxyn@1cNuM;0__;VMg7P1Cd=O~4tCCLIawGOeSF8F~S*&G0)h$N!=<@&u&)!?pAt4_o|Sx(@D9E zjlU*83X%7aiy(6a@3$~bob?8-KSaJqxge;QJa`kcyYu<#HP^WTJp>pTCtrYd?p;u?6^%gp67f|dYyfOYcozXpEHPY zbvvi9@vWT5IVz1c+69U%Ph57W7&M$?Kx;TP3 zSLNN$%#KkOCy(S!7ME7CuS(ZR-0SPOEgO0xqJigNpnY5Vvn|MJ^YdGjUjGA8n>=(K zh;3=8;a{MJ=XoFC=H_OF2-8tdFy%Gw&BV$+GGMOe;I~V@pjCT?oK2W$MQ(jN8Y!#f zg#pd+qH=8E(8MXBjXGYP8m7vx%8%K;ohGP*6r4XAIbFyhEIjI^l|6|=;7g#qorUst zz>>MLvi%n7XY^rD9*irUYZo9Le>5~?yfmbD`8U@%lrJXg%LZ&f&^9K$gAt9MdPJ5+vaH}}Nz~x*qUd@M~AQk8a zv~LKG_f3QerlW&$yq|jDL{EcDUWm@EgoSF}5IkrI-)W*UHE!V7mFQPhOyBd3e}2$G z7vOb`ODozuoXh-WYA(Zpay~!1nlGpYJ$+I?gDU5$hHbQS?fTSW#*u*aKu*hmmG@Dd zoTMkUPi$rTPhq>3GcK;(oH_7p$8IGZ! zV}sUx>L8NN*)2)CLO4px-4spl%$wn*$tSw|2evyKaxFrC+v)0OD39v8AyU+p)Hc3A+*FwTUz((r zy=uRe!bzp~r_<9s>H6%*Qyo00i6nV|qYK#vtBP2xQ3W&xCfp_c^ z?uS*vr^gs|hL9fR$C0rY2>1+i4j=d8aVRgKs}dpc_$O3_m}_H$-!XdcA?E4ZMb=d|O-!W9v2ho*so2kFFm;5A1U(<41cEwqu zE$lh)FGrHWmamLEO>266Zey~r=n`xTt63stL{|>qBdHFpeqS)L9Q8OtAL0)#G3`59 z{K`o#VTD18x&Kl~4R_4nSzlOW^5=ZvksRMUA;UsIGxa+PKmmOt*vr#k!(eR>F|tVb z6wVMzmvl4vLOqr<2&FfaN)tf^%~ze?1+4@UJ{yf1zZ2T{rWakY_wt;hZkmWHlWh{AB{YzV$u%)6=Sg3)dA{hoY{1FO(<0%S>xeM zf$SqeXf{ND>wvJIkuRf;A{Eua3`Dg7jc@S8?9}>^ESTW>Mrt zhOdPxDq#vGhrS(Va_><~geaDc59(U8QYGALF`RrMUQ015)6|mC(MNX(+TD+Z8A3PW zJNW$v<{yn2NwXDX7ZKK6`z%C09QyW+um&5l5eemYvHr0)Ml#oZZ;YX@>?|MrG$1xJ zA|f&enzLP7+_Ax$7jb^OXXD>a3fC=|kV(C}RXtjfqIyFEbX!MagB>oFZmiLWc7Hu{ zb&BZRBiPgxYbJhsf!EAEVN$@3U7Q=1t7Y7N+_RNXa=wM-G~Sj=Kxem5Z-UI^o(+15 zPh=`aNWIhP%8&+1;q?=lZG0K+?M@b0X~{6?M~w|nMz1Jc`0rf+qAmw&?3LRlHS0-} z*z2n~GL!X!bfoMnT^TumKYA+t+Tt2#%O>lhn0t*waRThtE_re8D;Un6S;*&FtrS7-Ivw^yPPd zPY1~s99g+oIB+BLLBL#FT#DBh%@20p8(z$4;KKX-#}kB2nT}*X44zc`Nk{z+rJNax zfUjA2S0XSlIjo!3hetsNZ7UVr8#nAaP= zsqSZ`MtMj4y(&SL14Gw8^XhExQ|ts>z7fXM=-~V^y}9y7L<_5Hm9?WKOE``e;P8p)u7u9F`S?rr#=fpotmm%zCwWxfq%4b|wLUV3V)Zd_PlS3g%2 zBmb{JmF=MQMwR~A$U6O9Sp{;}d1l3-PRAxJe~^M@R0s&ZI3U7#}Ly{HD4m?Y} zSzvDP;395SfFhP6t8@;zQbDN5(YQEu4Fr`EnEhr(lDYr7z}QXXR}4k^3L8b=+*r)y8T`efi$l($KF%Sl0_WHgoFyDoc1bUq%20cGWVFiUwz}v!9AJ{ngDFnTnDYl+L&STi2toA z!t~ary;>T&GP1>Tx8DnIM9k)gl5tdG*Z^Zle*3M2SR_0n3UI>hj$*Z(TVf}VK$1_` z;+9Adb`$cD9sfjwW1zj1e6_wOfz7vh^ z{SvjQV)i?;7NEv`P=;o1Z>2pjm)A~Z3B-!d9VB$N*n4mztn!DlJCrna_R|gM$3Ep&J01k_LQ%0MnwU z4kNIR$Xf9A81MZt{-R+s>FAu;k3zyH^@ex}CEtf7$7{sfkf>Va`)mfF0#ZwwCqRMb zoQassTYG>Pd}^@h?+a6mJKVS2z~>5Kg<%2}Yl|CT`32(>$Cqy34Jc-}l6_{ccVCR8 zdV{F8SzcumQTs$;oBD%+gjytLRh^}Bli2~w_NGBl_ngCQ7~l1^d2fm6FPlX1#B9EV z$z)`zJ%$q)j+^_0F3yjA_L}V@u=b?;gmm>K>m07k*K!1W1ujTP=6owM1+m3{`Gf}3 zpgVcNV#-)NkIuwAeC*?X@*xNq^ULGZJ9Pc*l`q?GE$6bxuz>4tl1B*gzJ}*f?W0$H zGS}^)2%F45l4bDy_$5PPu8N^1xrD!bwK_XGd7h7XYmPa@Ik-r`Z;G;bXXJ0^&DPtp zB@8v^ssr36b@YUc--zXEI#>nU!erB}BIJUm=EM4`T56tQ{<$}k^yC{fQX6C=mq1t2 zSX;KYel+ZAWNM?I^UHQ?Z<%NC5|x)RmsU@%Mg%`bj*?d72yl>!{Nj}a5mlKLBHtvZ zxqfaby~Qznlm~$7CRn`qj-l+y04iv_Z^p*^lgCrzIi*q?d{Ro)fbyr8MThhtCdLHT zFzOwN_;-1bJ^Ko;Zh8|O9o`}khOpP#lDE{%<&14OSFiAZca9Oy`-wy~$ z#s1BfU=rAV7NCMKwq!0;a3Sl^d^nZ>=2%0}Zwb6H1qY@8JJXt+MDI9MqAf9Opkpr4=mWIQn|}}GpnI-VvsCpK34Rq-FnIWl{e-{ zAJ_es0GegBxs2F7@Ps}(E0sw5T}QG*eear+u7;rIXnjvJcX+an94UB!jT+|7!n#xT zZnyAokH?P?${<9VZ#qzWl5Pr|e{;QgS91Yq*VMMK6^n4L7&U<3=~*$O z1>QcH>JQz{k-$OxeviGQjyV0D9>MnIaz_AN<#a?{l=bgG;`w)n{boO>ri5&~z=fN5 zAF@2`w+-}jF(>`-eUsEKSGfduo0P%FY?S+;0t~GiOE<_rdLy@TdAMU<>Ec$|$Sb*? z5k`+J13eyibHr?VIVF5@rUB^p2-B(wa^@uK(()q)X0)$8-qeZkYx13mu3r?of9jTd+_IE0(% zR=d zOW^$dpxmTLx)q@)!$7*h*mDP*ZvPd*_5)ViPfn~;?mvjr#d{i&-NbE{BMAdrxsG~j zvp*iqQtU>48dzdQPgr}$BVU3F}LH=gUUkdJYeHIs;IkBZGuxhzIX?}HrgME|d zVeB9xsF(MRrY4il13~W0#|mc5TyROpfh% z`#V40h}e+JaM30b-hi6;OS&7jt9g4^o*ZK*FiEN7P@D5NT>bfoXVBheb1m};Gjsp( z%ICKjX3fEmS2$^BEZ34iWfVeR1RAy|TE-%ep7&s!=XWo`gX+g-?cg#wU&&b+_;;aF zNN?zBu14dQr?ZN-%Y}szXl34@pg*O1cerD&;FRTjmwi-sYf#6J*NqDuY!ju-V|BD4 z1a0$ba5^RA-TI#6sF2Vw;Ljd2P}qFzid@39u>JI3vX4x`eVM7UkN6nyADT~VbrZB~ zaT{hFk?GXP;uUF&Q9W1A+A(XI(JG;GU++oGSJ@x4l>cgf1jCG>Wz)sr`(Tac!!h<- z_#$X~>qW-$iyEh8F~h*ZY!L>ik&5>$jtKA`D0`axtPGPF~`6RK~}Y!+h23d9noJ#FO~eCb0uRU6-p zq)41QAX3%)T;-g#BqA4KeRgZrY&&_`#_-ODH_eap`m%kF21gJmy54>FTk6jVAX!qE zDA_09(Ya5s59p!%(YxAuPY}d0;EBfC(t#<-g65V~@xRBdgoK#3_V9-Ms<_e?tm*KR zCeq9O=>Ull7q=@@sKg*{{{r&~gz!yfcb-`nG6(rpi2g2?+FL4X+3cP1l3RPAkTo@K zO9Y-+<0%&3@F55I=_Y&kZ;4UUW`~e6K_4owwK; z&&o=SI(Ol&%Wb}^`o%j4KBhOcn|x)0zu>V1CAx4rZKKqgVGSoKqY2UBOmaxJXGBs& z@B@exh-w~_otHP4R3|9$K40vJuaU^Rh{a=mll{|{I%9;;U zwX9G2n{a7$S{SUurmu2o6;jl7w=h)yeC0szgipYCjek9XT+hBIowX5sNt2D%XJ~Cv zA5-4Z`rA8@{=c>1$YR;xupdh)zVhor9z`s^xV%Jyungj~Q_KQJ4@W~kx5?OM2CDB) zI*WSr3n`mkKA@kHkO=b_5bfMCEi3xAMcxsI{1{6gQ}a7QWAc=`hx)$=y7l#-B^9_~ zMi8Vhga6epcy4QTV)kQ@c+vdf4!V=B%Kr96W3>BlaMc}-kr+amlI#*2BROG|i?3I55TtQ) zW%s}Bn$UU3d&UVaUMRf??#zsstqV2|7dsey+a#7%5wxL*?~yU~idLfhiiwY~*Pe6Y zL<7}Lp*61rT;t<&1)*_t4G2yP=C1IH{I!{&lS>I(%PecS#Z-q>SPmc+PcK;1eEMNA zZkw%=b(NX??r7xt{ERi6P&XPhyZ-E1YDGSz=GSHtSc#qd0tQtfs3UMVA3TqZQ0?-W zCo19DcFyHD_TF#NCyT=|utxRoi8?}lappOU_BY|K@vtM9*W zcs*_wQCj=;uI;WhPj+!ks!ph+q@_cwhoIz9lBusH#s<#%O(u@g)=ZauWV0veh+nw( z5n(r=3C`RMDI%(hqyD@T|Ngk5%p@Z-qa-9`U9&PPWJIht~eS3T%`U+?oe=XsvzdCu!~0ZzFw<|LdY zG}^=-nwp*VLs21bZ~s=EY%V9MAPJ!MrS)vGX9<^aTt$zwVL(?QU13>^YPU%wW%c9J zUHz&B)#UJaC8S}6a{*H}roJU0Cv`w32}c`VIrg5DgIjnDU+WW4zoD*Ip)z}Q%Uv9T z_hu8PLhMb&-Q{{4;j4UB9@9RUTPIcK3!eUM!3q}vV`9ZD6LDr%Jtw+3o%yvhXGrmY zJL%Pgug++k`9O6A)}>+KTXU;IBXK>EY-26E+;*%_n>aY)hb0bTvop`Mv(kDlP=39j z9^*;2&4d%3GsrO0kpG>tcC4VvMfgu8hTt2YAd1IFl>IdeG^bCytLhFYeGdm(y(6%_ zL{djNLV}0FLVvT*+p*-QWRR0)dwV{ye+)ieC&kUEl8I;l@D+k&vW0UQw*PBCNdSq7 z0)1~P^I$JFBs``5{b(n`*B|Q7lIx^OR`@=LXL-jbGyisyr4HI( zIkeSlmA8fxzy^45s;^6XaC0_eb80~`0i`pWHQc=-A(fWUc`7)=>Xso%Ot#8b(?8RO z=xD#noI);3?J4BU{;^#m;pIT)9j)g{K}@fV2eVH;)0R1&sTFnTScXMvJ+J9Ykv$zH zuO72~cMX+@LLr<-bK?Cdt}^cj;*UK{tVk>AHPWq{WQF`PV>dWOcw;#&{(vtLCW%j#t zJhLj+#9iQcCOfPS3b-O-tz-VwZxKJn8Fts98-B(41uBA~G88}g$l<*sq(b4HFdB)w zHn}0|geEhkq{w_hzjXM*S#!$IeMq(X&m=uwiYc0}*;Q-#?%dH#{N5;LbPg-woCV}1 zY6r+>MNE-wQKpk2@MG=Ys#dqas01mC8`psOB`4iWe#9iSAPvyebRkurV@dJ8CshKj zToT~hp1X-65*tk!%)NXSA1Ei~CG{an2Dg+1x$T){5Afdc!z8|o!;2_;AI@vR`{C$fmI z8sP~kYb<|4DaQZ!*O}C_;SU0Bh?aSTUxmZO(RG~LJll)%==f241w*mpnbl1L1AV4g zN@s5JHjNhhyVIAQg)=3+CKXLc9)Tjj+xT7`^6xXE6`HjtOF5OSm93Bvn#@KXvSR}K zy5rmhHH+;T)f6L}^BP(>h5y$^6e$rgkO% z^c4O03;FCFt?k!41}9YjK|glfTd=k}Wo&cu49dx>RI_QTRT*Uz$?~j=5qEK(?K+xY z;fIO#zF)tzx7%kk3odR3gT}9&$pi<6{DyWs2=ujnHiIq*3Hhti<5yLVaH9D-lYuO{ z#1eZp9Bcs1u2Cws6Ky2(k938aZbDnO3L*DnG-V4Bc{liS=_#on;29wwCeY)?*u)Q2 zpToN@A~{10z$rV3_3r|y%*04S;SsXX4pruPi>Igvt|}Yo{nZl0T*38EX4Ro2CS&r;CG>Ak ze9duSN83ZaM}tS+o~}=dhmSsU$8oVMw_lp7*G1IzqzY@`!va^T<}-Gu2D~obXMh4d zUDcr9ZZ19~ycDUi(}fhK%cTOxw13}cdmclc@2ZD6byVMqngwx4Uaweitwz1Bf=^<9 z)};YhNqvj>um`D|AY+FLMbYr2(GVDSNFET0OSn()skOZ@nsfYv<-Mgp5GtiK_hxkF ziLRF%m->cOG9?UhWo}fW$Ty6<__#9*G@qxj61?;@Gzz#yeZd_Hp*fY5vo*S+429gB z#hmb{KLyXO)q|fy_`mE5gWlhRMkAKJcF0pz|6C0u=djw55#90{TdxY(Jo}Ajr7Ep4 z)79&7Qo`P8Gk?QBLFQG0uFLBl*rMhUlpL*Sr$_vBymbTWW@CpeEoT#6R_!r1-IdDL z$6v(to6>-+rXIXF$(<*PawnBjA40Ue3qxfp;K*;Px#c=OQ5s4!ZD&0&8>~t0EA3^UlOy@KrXO0dI z1jz>88ET%~B3j+$uUhO{QXzMx5S8DNN<}4yzghyY8kBGsW8oSj@1Coe@VFRy-!kM?1WEBcjU4cZqMs?BZIrI2m2WIJjb@DRgfyq zt2C@6s#SNg-B&?)`}8?(kGAsZi9HUx$G)AJ*c~IzH%iM~=1yV~-MpJ!$RY{n@)r3L zCY0$k3WQ76g6n$Fsb_`8BGn4lydc>d5I2)cr@Wx}T!@iC(hty>Or0+fBUK9-USe`wP&@J zQqi@mHu!~da@v}OiFScK9P0f-PU!U5fhIQ@#45~343>gtAXwTO%ht}}bRgvJA%+bOSmg_@eV zTD(Jxb=v(`2K@;c6TitF&*`s%5X@1pSJyn?;kE65PUsR@|GF-%NeL_@$j_g=1B51NH@_-xy>}5rN$4$J z`fr#nL@iR{+E&>U%LQ_RfYL(n&0kZ%Yvl756{X%n4+cZidw;mOgCGX0sY4ca*(tQxz#d!ayH1V--}sjN&-QDA2GX zI~0^w#3WEhKDK;1;)mzg&JPeg-lS6IAIPjYp{ll+eArK{@{=jIF{XY!1==yEpgQ6C zlLa2MFb}ompJDhLx==v7pytHeQkt%(s)5UQA+%;2K*3L1Oi9VX7tab9;YdoS2=wNc~m?1lG-xI$f{`D1SHw{V3eHxqt%2-G9#17}85{9%b} zE)VNgs$zVR^WSPrIY}QBe(y8`ceB-gmtNwNc`tM{+`O;3G-o{Q?)y2pAm=rf}{A%R1aKg2;}hEsP& z%9pPX`yHtF_=SFB>~Tk?32Pj@Gg%30+wu@%juU10@E!S~W@JnE7JrLuTJN&vd5Tby z?rrH|WMEVQAU2nkRqx}kofY|r@Q=$xN%_~AJqroJty6(A3wXeuo-rr-YL|DONL<9e z$FFWY)Cr0NTUd1>SUWBgI#h~&+4z|;#VD4W0c&C$%Ql0J3}$O3;mZ{AX4$xyE}`Mu z7kk>O-*v~PF69-ByY3KiNk%osJx9{}`PRG2r5i7-Vz$;v=u%o`@ih;6n+G;!Ytr|; zI@giMcsl+3-i&<|U~g}gd;lInnrxTytx5IC<-Ca#UbEWJliLu$m*!3z<<&XIL=~2G z+)H=dqK`tXg5Y@lJ<6=wBL)@7JZ$E!lLz>e@(}oaBiMPjyza-(HF3c&xI%YKm zeFIDr`1?lg2|n@Ljk)Jgf*<}4r(oRYPhKyNtvSob?Xv~#fa{y6c_Idb;ORU~7kYYY zBG_4yns2Zqe8DwWJb{Y z7XpuH0aw0E5qsES4f!jYd=b z-Eq?!Qf8l@O?dF_m0|}-C$l)~^=K~YdlR32m6kz7YL>ll-7YkesS*QGv6JA9we-cdlN$=Kj1?!@<^Cf9{x%-!wj!4eB zb%WKr`y|?QpLAK)R%IhgW2lGf$m_=1C%sB#=%2gqn-M)(HJV4so-_((E@6dI!U9G} z;P?oab25}Gd#v+B6F`Jf;afRd*j(eQnrJ?8{O2{qJkcE>e~fdhpT+@6E$6sl(r5R{ z`-0G>x6A_pt?r_uJz+{#&j<2TU0V_S<_kpwlzbCq{wg)>n#*Y5aY+?Q19Zb`LqWz7p6L=Z>7OB@$kd zIhI)-A0WSBs@}YXMPVJhu#)w9&TF;!@=ux~cKICo{j2I*MTX?Bqdu_!CW%-*1XCxF z=Od^FiyfaNhb)YW^v+MWC>WA6)1lt3xn>wEobv<1Q9McSucAz1LTJIFIYDU{4!4=L zN!c4!Qo5*Ge=9`oDwL{L`RKzPPqWRPwGCu|QR*s$1Q%M~l3h;|HH4!^f;yf?kiaS^tcd{C;d_38;F;m{B3Rp!~p??b|49-GXUbsz&nno;5jefTa>pdN*^>M)5E@+SrZIrm@zKz+*iZfKs&b~{p zZ`FUVoQvHph6p7rGpOMV&UD{@W1wT2fGIIL}dEV=FI(g6xJ!dMSm;n4+i0-^C7G+ z0g{r{^!+c*b=yox{kExv0zOLa1ki6aYg@uV$@4F9fJj`Kd()b$lQmDL2L9dlFTc?^_g`7K9-%+mg*Cb?Y`vzlQ}P|| zp9_tJ|2RsnoJBQ$i3>zpb8hY6e~77=5~di~pyb(P>L<41?JHQxM49ayG{#_2)ng%l zGc+UXfn(cdqeAGkgHI@=f7Mc`ed=r9ol^;#ST#Wd_&X@2xxM2-z$2dw0v-`sUQzLm z{>hDp4-~D_GA>UXnB3Z$y|uX-c1^?MmHw8>numX`cx?Qm5j~Ez;T4$%u6nVQY?-WV z<{){eU%0A- zyem&6;(Y#fszHx@M3b8L3vd~qpGXXIp5^bOK2g5rbIyWwqe}87^UTZg^$rW8rNA+8 zW;Ltwgc6~R;5bfIx0--tDEVK|m-y7^o>Wy93b{`Q|e zPs9Gf$-V?ZJ$v%3I^zlD;!(;ik(95|%hk<_>*tvkMID-0tEWdJ;bwoUf91|K6&-9S zr9uhKWk-On86B}%^p#Uyjkwq7>4IbYtwQjQQ5|CSDTw^ zYSidY$GFN0r;Yb`nfummq0il&dMV#z3s}c5!JPA z8Vl+&^L1-lR!f_rw9XG}O76RK)kJIID3qsOTVBDETVxSJSfI^1pwB@(3Rut&xS6P* z>qU;^7HiaVmMr?e`_9om^!zz1J)BI2n;m8H3`M)-lvLZG#(!u<$pxe%H^}wEj#({??(XydRl1rjK*XuKCd_tZy6V ztx~t=`lq_=-jW2;IwK=|LbM|6j#-^*wcg1V*%e>T72E2_u<=t%&=fi)DBu?mBtUws z;i9lpJ_LLOY=G4v%zmio!**Q6Q>kG4z5DE*yi^l*8+%=4oN^xVR?nCRhX06Qq&bsZ zCXg@-5kl1@#pqwkbzSM=L%e1e*j>$mDsQ2uIQWiPN-N&w%ms75JGVAxZ;h;0zhduP zE}XpBZ*y$2VlZJ`H}TKY#=;LZc>LG&(gT3aKk+WxOChP`{;vbLosXrv6lX7@27*z1 zd)qsSA|6y@!Y#LUip8oLvP1;;0?$K%u9rfgzzT?TpZ)%={SRRN4?X)TXgF`Gh7}@v zV;s!}IGf^1 zPW+(mn{6^N{2{>PYO;F%+c(NJ;o~civnW!?Z5&;+M5Y=&8s51OXNw(cGA*hW73BP) z%T_ODm-BXL!l%^qpnTcGNFl*k`wg)f&Z9*!Xj$LuSRH&!eBw3BY|zUjoQr@M$w8xp zs1+!4)cZZE4kKWo<=5!hl-zH^*vMULb_>0uQKlFeWioXn5Vt@;8@e;x1OZyfY7&f$ zaMQQ-Y6xK)nM~Cz`Y}&6(i}Q3<8Q;QRlM8kr;*D>zukaZA6@|K=P$1z(;78M*JcZM zTip4#Kh95OH7ibSVVjk_R>?y}bve!pyr=sdt@URw%d)cmwa%d3Exx_eb9&o`tk0rU zPPHE7497-S#p%4rbrh&&MBD^4)cY9)Dd-|}mjmfGFR9E=t_fXb?pqXj9n#x+VLz$n zHi$6*@n@EM#0kew+>zF4e7okG{Q9O0$5N<@jQeNvw_K)}4LVkRg@v0ucd9X z`S5EdF7Exhl_Rx*_TSZgo#w{%m8bWuZg ztgc019ba>K(j%Mbs@W#Lqs+SOlMJ`s9nVMb4!Sqz^sH{byt-+SvcyM3K$#yL$I1yr zsR|pQ#CQ#ufZq0?@RCQR2OJ(gI!B;H28RUcqPXCUHkevPMRuk{OWW-W&pKYSBI_+W zCQjcAb$+fgS30FA`|YT16~|6svb#uM_JvKi8!}jRg*x+#y`FGw^HuGZ1P|ZNt*T?Z zRdQUytx#Lm+>eWI#Z~v2rbwJ>xKZS?+UPo8UDLsGxu!U6Nw*?K1EkcZraa?&zeRww zT|CZ{GghyR+B4)SIay^Mf&o0I+fY%NFP^=QX+Oe_MTo&cQW) zIMhLZ{lebq=Lz|xW*=%?1cbY+Qo@KyB7O5Bs|(s3FfBLCdusWeMi<>#f2AByV{?(7 z92{oT4oX}jswr|aNOdIdJYmfGzPrioEO0;6Eu9UlPV4b ziu|+$=Jy%J{GW4bY|%yCAWUTeI};u)N#S!em3dvFrCMCl8fOt|rtzm!VCM9I(D_l^ z`9oZbguiz0JF!)AkLtQ=`JV|(6HFDxW^s2e?zu%O+a%JOd9*-naV;U~RP5&y%BiiX zJN|sG+MCTc8Zz2iTjdi5gn;PnP2StDYI~k<{5#uGR~#L{XbjY5v7h*d3HHE0-Ux^c z90t2?@fl|EC~p7G_Q)pTGlEQ`|4$u3NJI!b|AOqKWaUH%NmzYY#iQw$%SGpW?q9Aq zjx%`7FyXg$pL+fL!KAM1+Hc9ikO@?nxLGb$?vw{sufb9ZndpLvMC&vl0g0RF6EmN4OVa zQO8iGLiWq%)i-|l?u)|p#%;|CgDKlRhEaD?e@)1@A*a$ErGL0Ci&Z>r&6Fu_q{VA$ zH*VEBHa7~(3A!4F^2^sHk;Zy))QzQF(sO%^Y@BDSsBWPYHlK>~$|{N6Ga2@Cnj+D` zO_y=kzrFa(05ZYzOaf>3o+lD5nbW_UGfbLz@5AuRB0>aiD$my_x!mmLEi}&ct_R3F zCDn*jr5(aB5d8av1skP;(d;?yIQ_I9Ndk`OxI211;j24zx||L^qP_5C!^^kmO5cxp z-?~aiZK5@~$c)DmK8{&$22vJcqO^XlhRt^v4^MdvA+t)fY=oFdNAV=5s{Q?n{qyxU z`6E)^K*d5IwkB@oV6e#_;P<$;ZT&b&kBF*+@fgsCf={6d*HNg zAaWklq8n1v@$B9Gwc9GW+Y=ty$59-MJ6SIk8)Dzxuc9S*icfpwY!9^&>rGI#2WkFi zXk#wxUvryV#uZ;8DP%ikikgW}hi{jHw$ zF5{Q(t)(y62aosDEB%}XM793J-IQ_^)gp5+Aj`Nra3}GW-f3S5%^AjE-^jLtQvW zD3&vgUn7C0sAUlVRQfAOAt+9kT@U z(>AiAH986JWv#QX6ldQ}Dr>b)xl*0KK!L3IG;hT@^QVbO_ySYN8m+F!C*|U7*W(70 z{6!Q3T2d6gXPfHdG1(o~oH+w0_zKpe5!%^%H%>i^GHaK-ixSZ5n>`>T5v>rn+?7vG z!o(4uKzTosm%x^Ai3d3EKMZbbfW7A<1JG|#PU_ARDl*w6uCNd5X!+nmd_ka~uciL| z-XEVGCO7%zLfuEl*RhL=vzA+*UEl`mA>~5B`CD9T{PC!f#w95`ZT*WbJMs<{X8Ayj z;zJe8qyy|)wEi&sw!aB!m+`$O@LqkD;@cJV6IBJ@=?CMH`?u%@evokvXbjRvhb$;T07BT@Lo7B9CYdbH>_BY3NBb3as9>thHxO_39gNd`Im z=4Pj#h>oyaD$ykVA*}IZ)#OCuR@jD_nN74N4ti*wsY%R}iAq`BQCbyE6CS$~*smI& z0Z#bVrZu*jNA$Ryr#Lx9g@q5TvhG-#;d(CVhyCsk-oZ|IP-y97$9%ka&>ED}^XwFZ zKbh8Z&M5C5f~N}9ZY~|2>XJX6*?7d^yL5i67h@;k*kISXE#!xz0xIOC)jSPH{nQwl z*(NbE>n&B0SQL3Dk3hVc#lUzZ)N}Gn-tacxYT`^&NFo%R?%)3WePX$UjH>h7H}-nH z;}^9~Toi3LpXzg`fAJ^&Mb)`vOA4#H>4Wek~NvKFASd6^{u(Tf2U$W_Y!2{z>#NX$6CW=BeeR3h*6jRB02Y# z?k1$gKMv)NTyBxYj%!x@ygn=1De(U9lwC{`uw8G2L?d!|V#?8*$V2KJpHc zzHx8ki#90aR%FNg%y$N!WzAkqXl1J$UTtdC@OyoEh|gi(y~GaY*zTQFd5JoCMjf>) zr?VCH<-`B%uU*k-!R-TsdyZ)J1;p~FjxHVoS3?qb@%O+~Teu`7D#)&OvvodbLu>c@ z!_N*g_mnmZBlwcukR-u$x!Mrqm5{m8xz3ggwMO-vb8d%ph9O9KGWtP!27mYEJ`8l5 z*#iVq`9m}=oMQ3gIaE#&KM1pO!K9E-R!SVC={L=0K@>nQ@Z#*BJzvUrc%%L zG>m|G5<1{=zi51$2{ZFimOxT|O2sEAS$+TSF(fk3+Wh&9bI=@h5#RfGci~oP&#S#AevWICIxCN_hI29A7eF)k2F5yB9dXNR#5NI%o-W!na34b-Q-rjSy9os65X89V#sUFRn+g%>S8Tq$6)qWWB z1fd}I!J)q1f%R>SdjqvX_x^);WjOv+D7cmxWSJpD_K|V>uG=%-W2_t03bLCZhLlQU>Bhz5{~)TYvc&tR78nKRh99XE3tXQ?n?~d851Sx3YSH_-9``3c;64 z%p~OgynWFK1$YUaEC;4!nwK=UEz2A%?wPq^LLLqq{Vn&yt5tWGH=1`BmU`o|1=o}@ z>#&T=$C5eOxzxYVyk|GBXWNd_yZJv$m^vfTf@>18T$!^2`c5N$@%yhblR#;L+u@=6!EAKlovC}?-v zLz$e)a9H9e)$rGuKrUl;_OpGrhB*S%tGkD$=UchcC~MAFSt?GekgMrXvvIIr=A}J) zj@_cvJwCg{+ zB8p?}qKno;M82Y7jy~5#99=5sa6onq9yHV~*F{V`RN`*f^TC1jhOds(pVC#=+r#qy z@KzHT6tO4iYj<><@K2#IHeB0G1aV3{+R*JO@AE{Hy3@FsnFy}c&&29wlbA?e^=Li2 ziDTKSD&#p)OA$28B@#4QRIPMf#Mj|V1V3qX(do38uC5N8$K6)oRHJp4ZTB{DmR!jN zL*)fMwe5E=uYHUI|8r%M|GV(2iz~V`OTX^EB4LdY5@ycGi%7-x7_{Nl>KFbr{9z+Z zt!?4u)a>5L@udY49JAuIoKMw_9}c;vZAq8%sVn-F?~P2qo*_~nO8n0YULh37-ze8f zA+NpaeQ)_vC(l60ewQ6AYvr(88RdR6`hjk#>&*1C8KT@vE!+wxnZuTtG3Rkl2Q0DGId zr9M_}ih<>RBWl$j3J?l>fGA%y$!H=Xm@yRTOb~(MYrkd!iPi%V89cmp{{`VzH9zuf zQ&Ff6F^gF?|a~Sn5cEm3t6J~fM3XY7+V)=nB&sKZ&}$ztRx|{#Rq-_aRwSFldD}#EXPh~z=h1}I#b&- zfr`QK)9yF$Jn**N-J;9&(p5Z7H(R(P9dCasb>Qh2%S5O&QDz`Wq*izqM`$w;PvAxn ze`mL6S8iEHEmPK9Avg;>SEpT;3wic6E5Kpszl}wdIfVR{4<=GoR?X2K+AMZ?WH`B} zs(QurP^zeSCW2_}70qk=!UDtqkq!L+>zno#W{@Q=-R#bP)i`*gyCeA|`^hGP6OSJ` z@n1#4=KlQwui3Jdi6AL`eA~Jzg;X#k;yCUFr``0BH<}3}u*a%}jxu2MqDZF0ikz+3 zQ|o3tA1`dGR2^)#nPyT~`f9A_Mjrpa*aBqlj~0?E5?s5U!PCp^fWPad4`%c92aln~ zuoG~kfJj0`l{A4enUS4~x|!Kok&wrZ9p$k^X?bKi*^ulCZ|;MC=Htj|SG_@$%+8+v zqmueU2G5IyXK;1g%Lv;%h_3DqA$7^~b`szleTIjY=yqfOju}p`3$Loc!enla(GMUW z>Pc#a)8r5na>|Q;Mr4e>VoaGIx^(>Scu5nJs%p+b^p# zT3z&tQ=s!DjqOJXj_G47wSY@pbqwq$7pSeHR3+8Ka_xrwL3wE!br zA4J=KIZE_)#si3l89YzqSUmmQp4k@_41bjEf9RYIkoCD^LJ=KQ>et%ok5QE!x|s=i zSQ;}A+1ky_Es(db9g+qSpOQzf5(V37h)3L!UzWb&ZGRsqkRfA_bFhvQj)=JJch1gT za&g3L%|!C@LS0EyQ zw{mZBN3#^w7t9@H&ZMKv+1It&MJzsHDXw1j-%9<=&;@L?$*k<}jP~r^6kjU{hxv}p zgj5NH;iZPEH~miC1veL04`>~??qV0e%(QKFc!4*!IU*Bzv66p@ME(dbH@?pVCQ4sH zDn?`e8MHe3N)l;d8v6GZbph z+Fjea&!E!>Cz7 zboZ(JGWi=sfF`O}HKlapZjoQ0hpK9?cEHKGnwba-14tzrvFJf$-s0mtU%={^3?8)H z3NjJ3|9kx4je&Z1xn=}S&O5)reMl|2>a>-RqR{Vdbi-*QRxodg@X7{+DJOe3Be=~H z?Jk~K3LH4Ol*a&e*W1o;vQT2Ie@8D(Y{=d)`T=~j8ugzy4SVf~Iz7gn^^EI(6#;+^ z7Txq~s`$fvIaU&ZIhFa{HjH-v!w9T2l6X%B~588?4m93 zew^t;Gp;OsFS3x;#CJK_>1GhtQ3DS1I&Vvww1_odEgg6FatrKrHV05jIKAy=IGL>+ zTxx1K`Kgs#Ay;s%6V9|QlhT~%$jfBXb&$6W{Sb2nQs=ekIa`;VZofdwOd0!@MxyAi z|69Ry;Hxe=ak2P0&zJEk!QqJ|O|*hxzRC7Kr^R~%ev$|Bwo~BpW+D{H5l*ina-PDE zN#t3u+6eOqn%9Z>_13HXGZ8G_0fv(S0P$|B^RV;a6ZM%xRoe`>!7G!Ghdyo``lm8r zMbce?u;l*G#LPF#xY&Xbc1{=(7~V@>nA50*r`!mNe4~8O1)!?bcm>P&R9=C^OhZig zte-gY>@Rc3?sEka`<=%QuU1E{k-Q}>42yWJ5@_sSzFdIuvX0uTS)vjMlNAcX$Cfl5 zBDPQTE$@%x^3O}1xO)m9hyjyD2x&`>=`u@=U2i@+rJYyrAi2+6Bx7U5>L57hoob^?J>&z;4csS% zbI6M1G+oI4M(XEc_!mZ@7vBP5#_(W0+IVVtpRcnrKoHpt z6r#PSvdfnharF>DNldBk1%PeVQ3}xGoH|@lB;E=2jmZ&1Haw8j|+zX_>HG-(<~sV6I|htqA$I3j5zGcCl;u0uG{uM z|Gj~Eeq?~)iGgn^($3%w((v!0_J4@Mw421z@oFjO^B`u7q_veh0A)D&iqj%N(>h9* zaYx%as-AY6f5l5>y>FcJB~4BcBJfZ!tcF1=bW?J#hI3n?OGx~&L-d0RB~>+^$u#il zB}E)1CLWwpsxs>_a9C5uoeB6CXJyRX>Y(};Lk$lVH%#EA1O*xgnFxDFiJw)C z7Aa<1Xw4!Y3%6i&OOD)UK`>Q&EM*YjG4;pe%;f&JA<%Ze5f$8F+{u7_X4!^YH*lRn zewH5|=+UlZsH5`xB;j)|Ag#`Cknh2b7_ebH6J5mJ7u35Kym1hWWKs!p#RJ2zCMI@W z8)K@Snn?Sm>3Ph2(Ek0_M4%qWFwoN>bMq%8m=WC!1dD~b8|I^%w<)rA$(-2y3zuE4 zgwg(FHNkrTX^m;|58YIsvXS_*Y-<`$7D4#>>X>yj($;#`xi z6I|QUbuhvs`%b!lh`_NuF(A?KZVRvjV*~!^m}*=yM{-JCs>&obTJ_b+9!R-f*0)pF z_$QLOEvod`KQe&zkpIY!%(xdpDo=$k6_5(~s3pZ!(I{=+X(mKj;<%-@mzTI!{qTdf#V+vp^O5V=d=79&`&sawRPYJ!v z=w-yXbHX|*AP{W%P>*$XWKs;VYb@6pzQp`mRpMrM2fLQ|?feuUPdCi1`M*_^L5Gt; zN%)ADxlyHM67oBQeO`>>ZC@g}6tQHRvxE5%bod_WGVTO>nU|~Tzd`Q%2I6q8q)CC| z7SR}bH^AhiG1C$&ffI_0a&CJXP9F9v%w-hs1}q=at_bA`nR%ZD3ibdhBV9~&rVPsr zDUMR_`oJ<|)){TKs!^SQrs?lOFMJQ^J*jDSsJ`**4O1t<6@+;NP9+_=J|xFe`#Za5 zo`c3W*r7s>y?++Py3ZDT6x^^+?kLUGE|Il>Mbv?&KMK+q>B5 zfF&I{$<-DJ|!X zrt@b4iBkpw+AgXO6+;-Y-2azC#WH&4Q?G4&g(Ji6vi2d;(e7t~+{3yPdDTA|w{q9N zwvP$h9IeBw?@G3Cn_or!#-GRe?C%Zl6)kZl9-Mz;8K{uy&Ct_@8M!BMWuyUPoXKNv zE3#sZgA~!J*}X6{lWsaoJ6;=S|FNBkdhu5!6HQh^40`Yf{5X?^xj$9r+1%C&@GociCCZHLy$~R^{#>$ z_HY$x(bI8Be)*Fd>`4Z0SVxT=7ev$z*Vms@|HOR} z^sCspkZ_(L1+s{l!(S7h=ce0WFZ?b;oD-1NwKIao_U*awCJZ4eX?;mtn$>N!W8IZ!i3X{K%0 zk*|_euD>=gC~d|azi$f0w1}(XrE*09N!1PeeyZl%)4zO+-tAU*pH92k{pb$pgixzV z6`9uIZqPd0x?u>*<3ps8Zl1x#FKVIOc3RH7j4n0)SF>yqbP?EA@@;3gFg;cEMEH!P zpdzJ;D@~7Z-w&u^U4_RA$^CDLo46Pp9ynSoE;;I72=k@sd+ZfVM2?6gjUcBv(6_x80ZXi8Pwbz5 z#S1y^>D113Xi)S#WN^Of_N@1s6BkCN(V5Z$bZYsT7Ri3>m`)$awJl+RhdCF zsZbz{J*SoP(Qs>8B6te1xyABf4QoJhLa$q0l@@{EQK~0mNt4;JTz$W$^o;${+AcDE zZzR=4WB|Po#4nUp{m5@kRY;^g0J+l0-h~=H$9B?o`GE^9=qrL zqMF4gIpNC1|Mqv(C-4Jo3-U%c6$BA`_Z1)4=m*O18v6T1LfHt`C%Wizq!_%!^7?#v zFH2a^XABb|i@SScXHtIvEproDf%C6qJ}z#U!v8Y7uEV`io5ayaJdt8CDlh+`j@gaw zM--lCK1x(6=jFBr5?sN~MXb-APCW<+z=>pfELWL^;bd6gw2B9n1<%SCNFvuiRR$=q zdP=TDX%@}XEmTjx^2B;NB};)$?e>iZ<&8atu?g}Jtqtg)l&M|%YUk?{O*YBrNZ^Jn z!22jxvMjsZ|4NGB{oI1DXml*ldfy1$5|+Ask$QMO@Cx!i5ff-!XV|&yY#E(4I)$^5 z;}7ct-yFRZ*UB8=sPQe03M@E;Wze#iE26p#fB0tTpFD4u$ZNML4G_n!!w!|PG_VgE zJK_C@(GNI&U+7Z`*e;}$dd5e6)o{`^sOP_88~q#hfd8Yd%;D@^oD9&kCN4hl<^(;} zcXrFkZ0sMiG>ekJtcR3%reT_I8rkQ>w#&~g{#Q2tMI!Fffy~l-#`AAV;yeuwB;jZd zU_`7z9?BkSLaWy-pz0+yi9-*z!%tp3pp&Uv@*-LpOEIfZS3O130A(RLaR5{i+?oW< zh;d*PY<3^_5M%sy$1Cu<&GzEWp_fL!-2}}{MLGJxd|*6Ipgqfh*Up{ES>G+VG}!D7 zdTR zKqe2GxHkLnv#AdCIlFRVPY2k=ae$LZ2;4=CHQ_DoJt76YFKH(BZCSF#7$Pu*el-GY@IZ;GROP949E|>oHec z=kt0mkyEX>(vsEz$r&4)MNN0!)+!(n%QXAy&hWQS;tUSQM<1phetSu+b=aj9vER09 z&S~aYcrdKhlItbByE@lc@6%u^sqrN*!Txv&vy{WH<!rYPQ~4)b$t1 z|CPP%A-wGp#KK?Sk=d~V+7NX_EWLLBcDhg7%>Pn+BHT0xf`wggtg`>fm2jw?^AVTA zBVJ!|tFIuh|8phJL4i-h;})VO?#m0byXxxt*yKR1&A5%E{N^7S#`=33otyza+Do4@ z)9^2SB-upVTSNT}9&NYhIOy*09VqsN1Ga<#1WX47kTX(G_&GK{%Hu++6aNF02Wmj8 zNwml%lq=N4|C-^dU?ohWap;5qt*jR_v?dB+_G0nqS=Xc51hqg>A^w>i+WkPg>b;W zK+sFgqH5TmB^mass4Jjgf5E6`|JHCw9?>&7Jc#oU_QAJ%2qG=}u#t!GZ3wGB8_AbH zZ{+ip$p{01;^5`vKY*IxZrkF}M;19X+^zXjfd1>Qi_#G{2E z1S$J|M(Rll1ZDHtm5U&ix^dB0;2H+_s;L`2zo&Yq?~gBS-#>H>L~kZUblzDHtbfOX z_ZrTjK7d{Vl6G6x=fJ0Ib-KQ}sCv7@+{B|rNZ@@cUO^!8;HTU?=l(o)4F#DTYwzdw+2{Y+t*=tj02Yuk!gh$G8!s#mdf_0{?$iZ zkk)lE4>M)ZRZu0~$FW0rF!mE`K~B``Z@yUoq_GThGeZV_Uf};*9+2!$KR^c4Pa^_u zif^y?gGoED)GeOepU4`eWfQ>(V^=+;(C z*DQ)y^PM+G@zUX8Jrn!cvbcXa^yE3a%|a;Infe48c!|{$HGukZ$d0!C3Kk86O|>^Ld62e#x_av+Ajw5%%X(J52!2M?mzPVMpf5o zCkFm27P#)d=_(;Mzm(>PZ(lS|Fp2lyP4$VydtqL8{vUhq71h+fy@3W0upsERAkr)W zR76muH{GZhX$l1CMVb(Ll@7WE8=#34sTKrT5I`~XKr{+QnvD(tBnko{6zT2G=-%h- z^L8KZ+x@_}S9(y{78O;^# z1#t9YBQ!BfmAwnx;L->Bd%v)T3q>c-${xJ&Tlk3#?HR|9qffN6E6+mMn==e~Yc`Jw z_C7HU3B@}L0;HL0^Q*nY~E{PO`9oZmCW&zf8v zAASVXt`Ga8JPc0pc?*4w!fvTe_=TNd(wv)BNrkb%M>4QDaIU_(-Y{fWIS=;R{|P zks?=31YLms9KH$}8_u{<;ZAgxOcR#@v#$+mz3wv}Tw&%eVcD3T7uMhcM|f7bQk1y! zO;`+xk&hEt$!Uo}ZHX z;q#NEl4Zl!c{hU_X>fyrjQfL4u4(G<%rfITKXMpZ{;smz!{YWo4jX)^i z8uqa`#p66L;HJEf{$zNP%!P?)gLB-u?+DE&$8wme{16N3jy(?`}Ubl{%ye z#8g>ahE0%=x99|Mb>;od=aY~Af^JELVo$jjS;1myhTm$Eu8m;DboMpf=8EEq`Qs=R zTxl|(R&{EyZ26X;=4HBmQTV$E<7q;t{_gt=!u`dDwn4K(k>TwOzr6Sl?u%LaGBG{b ziobLAMtrt8%paSc@dyKs`%CtO8QJ3*!o8301qn^8Rct-s7K?5&1(?GOurr^J8b)#C z-E6)vss;K%Rn8mq+kv4uUnQOMk-$;%3dcTqKG=DYyy`^eFBC?!S$-6e|CHg#g z`uoC1YqjSCkY&9VM;MhWngK0jt?aJt3LC>X;e2&dWtuU3Rw8BX!na+;>g}pWO)%LDsskb-aa7J?@{*(&7>iKwg%7Ie9+HVO%#+w(ega=7ynb!_Xv@Bods?`c@%Nbf5zg8Iep0zgq zWwka@^yFq9H|M5Q(rUA4+B40uzS*Hk~g*nT{<&rQ9jubUq+ZXC*#yHndHcsrAOLOJvS_PNSU|j>5bV5$8Mrfdg zCtYuY@we|y#^0QCZZ)MH%uzHXuIe`nM9z#ZD6NJJt~N|v`uN3}f77aMKAZ47`MYy- zWAB+zegF!0dt}E@=#1Nb*X_`Gctq|R&!@Z|o+*^|{bv_IOrcq_e*u#^!#;vxWbscQ zO7i8l3uiw0|I-maiOODbzrlaL#J#6Fcy?~;QZ4J-+lXa12Y-Xl#GCwgyWV3-U`!)@ z7@oFH)J7*hmoU{|5f0vt19+O`e=$n|gNj?mG>zLS+9J=x5#6 z^>j(O>cZggby*pxG3nnu$Zmi)geGei|h$&xUr0WC8OK;dm(b z1ZSAh#qKhWE8ML|ZE#N<(CqDm(db;`aQ?~ZSPLM`R4A^n+@LC}dcue~PkyxB8ctDLC7EbW^5bK+l^O!(s7kz8*V~cs6 zejm7*nCQN|1yG0@rbG~B$YpwZ?yUTy!@f}^Fqkp|#WCG}UT{C7ApJXWRrjnm{$5RB zixJK>zYQ6b9N*ad(YsfV^y*aj%4RbcF2mOev89!pt{CB+y+;5u|XUJfhT| zDmyFRuiXC*X3-uVD>29eNj($$-@@#=hxFiACt##4;i}lG<@wd#q+7rGokmyTx=cRx zV;Fhfh|>L-66t6iP8RpAev!@fXZo2G>S82p2kZxoAS=7`0mUIN#_Q>YkL65FXnz3g zK%NFbWz!|z0GDd~m16S-76l(R^N8_V{n7ix6^jz&N&tEi14-f@Fv!M4c=&_tP9e(v zDA_Y}m(PUX0irG)-4v!!l>G>F9MXS*qN40hJm-*53=VfxZfEb&r~nh&H3`?yad?V_ z8{44HzYV${s^tz$ss`^BPH$uXgxU8Y{aMjk@Hh$3`YzEg$KeYM&GOM&TuGKUV@p9%OdwN}%L{A+&O9k#VTT=9FxLrERsOAUzY*XCb1*LAb|F;{ld zq5=Df`XO?%Y-B?TqC}zfdTcIN^4qq{C-S3}I0eAFH}lJnks&j3tggGVwV&lu(tBnm zn7ILys`5tSpcTwy7dBh09rSkfj(4VSZ{3<-gj$8_GXyuo;GN@oCZOL{?{5XyP2p^Y z3U6Y&&0&y0Ngd|Ta~cl~L;utNtOt7^!j$MjFzlYtp=fauUYU12Pm4-E@9{JEBE-Vu zYiBTPg9FHAI!Smv2c}+^x{g+Fz@f#4IbQh5e!oL zdq8u8LZk>CIeZc0RsW+LWhS29dZr=DFG?G<mxG8@ACqC0k7K ze7I-GDZI1cuz2Fvthnqm?8l*-z-2kpxeNFVK8>4iUY3VEHh@W8(FV)$DmC5T7A?Wv zINMq-2~EuYWkc|YW68i^dJO%-M8EtA=YiAzponwk4(1RZ9Ot&;PUlburlKBBJq!N* z&Axc`=;3xrSC|5bT0^M(t0i3{ib%peExk`;KOxQD4@1&tW6(`WB)eTpzqpd_t6JMIpQ-!F*#qWWY{G?P4ax!MJZQkqhMV5+t3@eq zymDw_d;jIIXbQdK#LOZ1d}P>ya@Y4x2;7S)sfsQGfAi5(ok) z&r1C97mI1{HKEUwdR9|f{nrSt>Gg-=K#L7wT=OAot8DZxwQO__HHtH6DyyrEvHJ#69Pk-`9G#1;W~cZ~UX!u$d+zd5;S=jV@zs5*Czu~1s{%J-e2PYr?~9d-4v#YWnef5;rMioi0GaT&K~q?mCBRsvKW_mn!orj zw~3*HltI__sNv=UR0z;j?X$6`k6&FBbWV7@dsT&7`B>?*3!V>mPgHC#|ERBte@SF7 z7i6APK>fT@eZE3!BT}R?=P^;yCUaZhi}* z8pD&|RMBT`A}(dic|`wHqZCTQ6}9r{4k0fl(tv07rVK)aO`x7g_4XOi=M8-GocbjbM%{^~cs2WPB{9a!P47F9fRP!&l`Jt^qBIWTEr_C!k zYqUBP6JtZhQKqV2#a{lmk3aV0=FiwAoG^a( zuU};q&k0CX)(EX^fpT?qB}vN$rG6Qvgd@dUJ6^VWj7FC6%nQj?yk&aY>EoT#VkT-2 zdOTShSzO7B85pn9aLkX?M4gRISHzGy-LPw`QkE;zZnEX)jL0(y*4BTLHVoeb8ti4% zlDN)h+@8zZTKBZX$c(pN*lg*g^1+W+?#IM%Bk;nbCiPQ_Z~dUxKtrCA2Z-K~Gxto; z+5ICVs3+opLYfH8Zo2_4j)x35ns;RNEb)`pPS1d~z?InugUADy_qN`%^NS9)?Dbk0 z?CTuK%6)bO@mv?tTH9Crb|r?m+G}B#Xh}rpEi7g=c#ZXe?Q4`1c==H>9V3e3^S!GH zL%wV6@u9)}6U~bg=shoJINr{_ZP3y(>SgdSdt9iyX<|6J7A` zg1>Kxj>{b4gk@B|{wYZ3u-kL|SQ1A*py*rAqg)K`#OVZ`?c)E{D*uvr_g<%aT{8k0q|1za$B;ljujt&_od&zE>^YCDal+~1JW1hBXnFrel(!9*)hROATAcf4J2X& z7XM=qeuxLbEBbKjoTzEAb6nxg=RQ%j5HPzLzWwau1t$DU=omq+r8A&A*p@K`z3vXy z=m)YRkE4(?Q{kwh&8gV4T^j$D<%>64c|w2hWX092CS}1cUUupd&%{qqBzprtFzdf} zSLoY7835&(@mRqEd7dbouIO=>%|72HhX6D!#*YK~QEt~)2lnU()uFb^)6e*F} zd)r;%0%1xhXbP1dtrgIrvs?6Ehlbt17M|uC;{aO1oW8DlL-|qFKX*UIMd`p~Vk-_R zTKrALvV+J-USr2EV749Y`kgxvGXOeOLbY(V!33f`A=ZBrl;GJxIMZ0rl%@nLzkeSj zn*%^oZ2ub=Bh{rbB{o2Z_ri`!=K3)1Wc20Zy?p-ALloWSzjs`I`RhNvWJConWmnVg zS#yps5D8y;{HS7tMC+u@rvsg+>U$&WWn;s$w#_#ekbfegKk=i?W}mGSNg(u&YpbsfiZ*$ROl<5ov7`IP z#67c&3gXNH%3Sub1N!a1@?p$@+skQ`=a3KCBj`nl)=zsDuN{cgS1^0TgwMmh3|{u> z#}x;7h~|V*zlhyO|LUf#ei{>s{h!$C8Qz7N`Mo{-OZ}T+BklsFjNMFbngC|)u^QSn z0dPzgt~H*5)n1gkYffxM9z>S z1M=tT*t4JffiGIRuz3YM$LU64Zr51J5!Gy123uc!)2-WRo6_obijzrN*b(Sqg0^L5 zYkdDT$ow*hg6YnMhUf&qJp1KgB-4V3b2iFthZa4hNaCZ6{Fo}zq&e_gz}rzuoVgr+ z*Zcy%Irkre4^&nNSR&v5V)fs&V&VX+$d6RI!%?1w?7?n5Ce@Yg)bP0(M`Pb-!0bfXnh$At)V7G#e}N0>8f8& z1IZ*UyiF%|EPgfXl`YDJV~KA8+Mf3Fo9C@I^nf)r8S5|}zxT2K4tFL{{b~ZrJFbXM z4ELv#Cr|ftLr@7n*5+vi>X=iCvt^wD$86U3py#{I+G@jdBWvGth-0??H|IlB;L6Ut zk9RMt>_`z#m%kCoLxtxHz{=R4{DPVa{RiphJJhkvYZZL1vj@;bBDT4GLDSIN;F zlm983P{OaN!j{Ii55aMA+NOQlo@aJ z*7*+yL3pC^tX1nhrL!+b}4VTvaxl~hiajSGU=%4=uME8+nXnrpgeE+Z*GC= z#{DVsWP5@+=ZN;f$wziXKw$uO8zP{*BW6@`)|p9CF_?<|F#4C&+gyY{@y0pG0`3LjfF%H2y_f0XONE(ghN4w7|uxB2

OTl^R>Y5|0ubnEBlYm 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

  • ?}CO!L0z*^A@={?YWj=CVBPBAbASac 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 BtD*n^ literal 0 HcmV?d00001 diff --git a/modules/local/functions.nf b/modules/local/functions.nf deleted file mode 100644 index 83397ff9..00000000 --- a/modules/local/functions.nf +++ /dev/null @@ -1,86 +0,0 @@ -//TODO: find a solution for the hasExtension function - -// -// Utility functions used in nf-core DSL2 module files -// - -// -// Extract name of software tool from process name using $task.process -// -def getSoftwareName(task_process) { - return task_process.tokenize(':')[-1].tokenize('_')[0].toLowerCase() -} - -// -// Extract name of module from process name using $task.process -// -def getProcessName(task_process) { - return task_process.tokenize(':')[-1] -} - -// -// Function to initialise default values and to generate a Groovy Map of available options for nf-core modules -// -def initOptions(Map args) { - def Map options = [:] - options.args = args.args ?: '' - options.args2 = args.args2 ?: '' - options.args3 = args.args3 ?: '' - options.publish_by_meta = args.publish_by_meta ?: [] - options.publish_dir = args.publish_dir ?: '' - options.publish_files = args.publish_files - options.suffix = args.suffix ?: '' - return options -} - -// -// Tidy up and join elements of a list to return a path string -// -def getPathFromList(path_list) { - def paths = path_list.findAll { item -> !item?.trim().isEmpty() } // Remove empty entries - paths = paths.collect { it.trim().replaceAll("^[/]+|[/]+\$", "") } // Trim whitespace and trailing slashes - return paths.join('/') -} - -// -// Function to save/publish module results -// -def saveFiles(Map args) { - def ioptions = initOptions(args.options) - def path_list = [ ioptions.publish_dir ?: args.publish_dir ] - - // Do not publish versions.yml unless running from pytest workflow - if (args.filename.equals('versions.yml') && !System.getenv("NF_CORE_MODULES_TEST")) { - return null - } - if (ioptions.publish_by_meta) { - def key_list = ioptions.publish_by_meta instanceof List ? ioptions.publish_by_meta : args.publish_by_meta - for (key in key_list) { - if (args.meta && key instanceof String) { - def path = key - if (args.meta.containsKey(key)) { - path = args.meta[key] instanceof Boolean ? "${key}_${args.meta[key]}".toString() : args.meta[key] - } - path = path instanceof String ? path : '' - path_list.add(path) - } - } - } - if (ioptions.publish_files instanceof Map) { - for (ext in ioptions.publish_files) { - if (args.filename.endsWith(ext.key)) { - def ext_list = path_list.collect() - ext_list.add(ext.value) - return "${getPathFromList(ext_list)}/$args.filename" - } - } - } else if (ioptions.publish_files == null) { - return "${getPathFromList(path_list)}/$args.filename" - } -} -/* - * Function to check the file extension - */ -def hasExtension(it, extension) { - it.toString().toLowerCase().endsWith(extension.toLowerCase()) -} diff --git a/modules/local/generate_proteins_from_vcf.nf b/modules/local/generate_proteins_from_vcf.nf index 2be51a72..e756eac8 100644 --- a/modules/local/generate_proteins_from_vcf.nf +++ b/modules/local/generate_proteins_from_vcf.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles } from './functions' - -params.options = [:] -options = initOptions(params.options) - process GENERATE_PROTEINS_FROM_VCF { tag "$meta" label 'process_medium' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'.', publish_id:meta.id) } - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } else { - container "quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" input: tuple val(meta), path(fasta), path(vcf) @@ -27,16 +15,24 @@ process GENERATE_PROTEINS_FROM_VCF { path "*.version.txt" , emit: version script: - def prefix = options.suffix ? "${fasta.baseName}_${options.suffix}" : "${fasta.baseName}_added_vcf" + def prefix = task.ext.suffix ? "${fasta.baseName}_${task.ext.suffix}" : "${fasta.baseName}_added_vcf" + def args = task.ext.args ?: '' + + def indel = params.variant_indel_filter ? "-fINDEL" : "" + def frameshift = params.variant_frameshift_filter ? "-fFS" : "" + def snp = params.variant_snp_filter ? "-fSNP" : "" """ variants2fasta.py -v $vcf \\ -f $fasta \\ -o $meta.sample_${prefix}.fasta \\ - $options.args + $args \\ + $indel \\ + $frameshift \\ + $snp cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + "${task.process}": fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) diff --git a/modules/local/mhcflurry_predictneoepitopesclass1.nf b/modules/local/mhcflurry_predictneoepitopesclass1.nf index 37c938cc..7f7bb575 100644 --- a/modules/local/mhcflurry_predictneoepitopesclass1.nf +++ b/modules/local/mhcflurry_predictneoepitopesclass1.nf @@ -1,24 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process MHCFLURRY_PREDICTNEOEPITOPESCLASS1 { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'class_1_bindings', publish_id:'class_1_bindings') } - - conda (params.enable_conda ? "bioconda::mhcflurry=1.4.3" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mhcflurry:1.4.3--py_0" - } else { - container "quay.io/biocontainers/mhcflurry:1.4.3--py_0" - } - + conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" input: tuple val(meta), val(allotypes), path(neoepitopes) @@ -28,14 +15,14 @@ process MHCFLURRY_PREDICTNEOEPITOPESCLASS1 { path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${neoepitopes}_${meta}_${options.suffix}" : "${neoepitopes}_${meta}_predicted_neoepitopes_class_1" + def prefix = task.ext.suffix ? "${neoepitopes}_${meta}_${task.ext.suffix}" : "${neoepitopes}_${meta}_predicted_neoepitopes_class_1" """ mhcflurry-downloads --quiet fetch models_class1 mhcflurry_neoepitope_binding_prediction.py '$allotypes' ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) END_VERSIONS """ diff --git a/modules/local/mhcflurry_predictpeptidesclass1.nf b/modules/local/mhcflurry_predictpeptidesclass1.nf index a5509ed0..79e7b36a 100644 --- a/modules/local/mhcflurry_predictpeptidesclass1.nf +++ b/modules/local/mhcflurry_predictpeptidesclass1.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process MHCFLURRY_PREDICTPEPTIDESCLASS1 { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'class_1_bindings', publish_id:'class_1_bindings') } - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } else { - container "quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" input: tuple val(meta), path(mztab), val(alleles) @@ -27,14 +15,14 @@ process MHCFLURRY_PREDICTPEPTIDESCLASS1 { path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta.id}_${options.suffix}" : "${meta.id}_predicted_peptides_class_1" + def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}_predicted_peptides_class_1" """ mhcflurry-downloads --quiet fetch models_class1 mhcflurry_predict_mztab.py '$alleles' $mztab ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/mhcflurry_predictpsms.nf b/modules/local/mhcflurry_predictpsms.nf index 469b061b..d53e0a93 100644 --- a/modules/local/mhcflurry_predictpsms.nf +++ b/modules/local/mhcflurry_predictpsms.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process MHCFLURRY_PREDICTPSMS { tag "$meta" label 'process_medium' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'Intermediate_Results', publish_id:'Intermediate_Results') } - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } else { - container "quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" input: tuple val(meta), path(perc_mztab), path(psm_mztab), val(allotypes) @@ -27,14 +15,14 @@ process MHCFLURRY_PREDICTPSMS { path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta.id}_${options.suffix}" : "${meta.id}_peptide_filter" + def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}_peptide_filter" """ mhcflurry-downloads --quiet fetch models_class1 mhcflurry_predict_mztab_for_filtering.py ${params.subset_affinity_threshold} '$allotypes' $perc_mztab $psm_mztab ${prefix}.idXML cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/mhcnuggets_neoepitopesclass2post.nf b/modules/local/mhcnuggets_neoepitopesclass2post.nf index 90eeead8..375d0288 100644 --- a/modules/local/mhcnuggets_neoepitopesclass2post.nf +++ b/modules/local/mhcnuggets_neoepitopesclass2post.nf @@ -1,24 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process MHCNUGGETS_NEOEPITOPESCLASS2POST { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'class_2_bindings', publish_id:'class_2_bindings') } - conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0" - } else { - container "quay.io/biocontainers/mhcnuggets:2.3.2--py_0" - } - + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : + 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" input: tuple val(meta), path(neoepitopes), path(predicted) @@ -33,7 +20,7 @@ process MHCNUGGETS_NEOEPITOPESCLASS2POST { postprocess_neoepitopes_mhcnuggets.py --input $predicted --neoepitopes $neoepitopes cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) END_VERSIONS """ diff --git a/modules/local/mhcnuggets_neoepitopesclass2pre.nf b/modules/local/mhcnuggets_neoepitopesclass2pre.nf index 98d0f503..6db6aa85 100644 --- a/modules/local/mhcnuggets_neoepitopesclass2pre.nf +++ b/modules/local/mhcnuggets_neoepitopesclass2pre.nf @@ -1,39 +1,27 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - -process MHCNUGGETS_NEOEPITOPESCLASS2RE { +process MHCNUGGETS_NEOEPITOPESCLASS2PRE { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'class_2_bindings', publish_id:'class_2_bindings') } - conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0" - } else { - container "quay.io/biocontainers/mhcnuggets:2.3.2--py_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : + 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" input: tuple val(meta), path(neoepitopes) output: tuple val(meta), path("*${prefix}"), emit: preprocessed - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta}_${options.suffix}" : "${meta}_mhcnuggets_preprocessed" + def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_mhcnuggets_preprocessed" """ preprocess_neoepitopes_mhcnuggets.py --neoepitopes $neoepitopes --output ${prefix} cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) END_VERSIONS """ diff --git a/modules/local/mhcnuggets_peptidesclass2post.nf b/modules/local/mhcnuggets_peptidesclass2post.nf index 0af8cb0f..743433ff 100644 --- a/modules/local/mhcnuggets_peptidesclass2post.nf +++ b/modules/local/mhcnuggets_peptidesclass2post.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process MHCNUGGETS_PEPTIDESCLASS2POST { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'class_2_bindings', publish_id:'class_2_bindings') } - conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0" - } else { - container "quay.io/biocontainers/mhcnuggets:2.3.2--py_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : + 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" input: tuple val(meta), path(peptides), path(peptide_to_geneID) @@ -27,7 +15,7 @@ process MHCNUGGETS_PEPTIDESCLASS2POST { path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta.sample}_${options.suffix}" : "${meta.sample}_postprocessed" + def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}" : "${meta.sample}_postprocessed" """ postprocess_peptides_mhcnuggets.py --input $peptides \\ @@ -35,7 +23,7 @@ process MHCNUGGETS_PEPTIDESCLASS2POST { --output ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) END_VERSIONS """ diff --git a/modules/local/mhcnuggets_peptidesclass2pre.nf b/modules/local/mhcnuggets_peptidesclass2pre.nf index 665749e9..941f9178 100644 --- a/modules/local/mhcnuggets_peptidesclass2pre.nf +++ b/modules/local/mhcnuggets_peptidesclass2pre.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process MHCNUGGETS_PEPTIDESCLASS2PRE { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'class_2_bindings', publish_id:'class_2_bindings') } - conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0" - } else { - container "quay.io/biocontainers/mhcnuggets:2.3.2--py_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : + 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" input: tuple val(meta), path(mztab) @@ -28,14 +16,14 @@ process MHCNUGGETS_PEPTIDESCLASS2PRE { path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta.sample}_${options.suffix}_peptides" : "${meta.sample}_preprocessed_mhcnuggets_peptides" + def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}_peptides" : "${meta.sample}_preprocessed_mhcnuggets_peptides" """ preprocess_peptides_mhcnuggets.py --mztab $mztab \\ --output ${prefix} cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) END_VERSIONS """ diff --git a/modules/local/mhcnuggets_predictneoepitopesclass2.nf b/modules/local/mhcnuggets_predictneoepitopesclass2.nf index 446ee885..caa89781 100644 --- a/modules/local/mhcnuggets_predictneoepitopesclass2.nf +++ b/modules/local/mhcnuggets_predictneoepitopesclass2.nf @@ -1,33 +1,21 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'class_2_bindings', publish_id:'class_2_bindings') } - - conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2--py_0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0" - } else { - container "quay.io/biocontainers/mhcnuggets:2.3.2--py_0" - } + conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : + 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" input: tuple val(meta), path(neoepitopes), val(alleles) output: tuple val(meta), path("*${prefix}"), emit: csv - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta}_${options.suffix}" : "${meta}_predicted_neoepitopes_class_2" + def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_predicted_neoepitopes_class_2" """ mhcnuggets_predict_peptides.py --peptides $neoepitopes \\ @@ -35,7 +23,7 @@ process MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 { --output ${prefix} cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) END_VERSIONS """ diff --git a/modules/local/mhcnuggets_predictpeptidesclass2.nf b/modules/local/mhcnuggets_predictpeptidesclass2.nf index f85c8208..3d7e8597 100644 --- a/modules/local/mhcnuggets_predictpeptidesclass2.nf +++ b/modules/local/mhcnuggets_predictpeptidesclass2.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process MHCNUGGETS_PREDICTPEPTIDESCLASS2 { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'class_2_bindings', publish_id:'class_2_bindings') } - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } else { - container "quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" input: tuple val(meta), path(peptides), val(alleles) @@ -27,7 +15,7 @@ process MHCNUGGETS_PREDICTPEPTIDESCLASS2 { path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta.sample}_${options.suffix}_class_2" : "${meta.sample}_predicted_peptides_class_2" + def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}_class_2" : "${meta.sample}_predicted_peptides_class_2" """ mhcnuggets_predict_peptides.py --peptides $peptides \\ @@ -35,7 +23,7 @@ process MHCNUGGETS_PREDICTPEPTIDESCLASS2 { --output ${prefix} cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/openms_cometadapter.nf b/modules/local/openms_cometadapter.nf index ad49aa2b..51340612 100644 --- a/modules/local/openms_cometadapter.nf +++ b/modules/local/openms_cometadapter.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_COMETADAPTER { tag "$meta.id" label 'process_high' conda (params.enable_conda ? "bioconda::openms-thirdparty=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms-thirdparty:2.6.0--0" - } else { - container "quay.io/biocontainers/openms-thirdparty:2.6.0--0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms-thirdparty:2.6.0--0' : + 'quay.io/biocontainers/openms-thirdparty:2.6.0--0' }" input: tuple val(meta), path(mzml), path(fasta) @@ -23,18 +15,33 @@ process OPENMS_COMETADAPTER { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${mzml.baseName}_${options.suffix}" : "${mzml.baseName}" - + def prefix = task.ext.suffix ? "${mzml.baseName}_${task.ext.suffix}" : "${mzml.baseName}" + def args = task.ext.args ?: '' + + def mods = params.fixed_mods != " " ? "-fixed_modifications ${params.fixed_mods.tokenize(',').collect { "'${it}'"}.join(" ")}" : "" + def xions = params.use_x_ions ? "-use_X_ions true" : "" + def zions = params.use_z_ions ? "-use_Z_ions true" : "" + def aions = params.use_a_ions ? "-use_A_ions true" : "" + def cions = params.use_c_ions ? "-use_C_ions true" : "" + def nlions = params.use_NL_ions ? "-use_NL_ions true" : "" + def remove_precursor = params.remove_precursor_peak ? "-remove_precursor_peak yes" : "" + """ CometAdapter -in $mzml \\ -out ${prefix}.idXML \\ -database $fasta \\ -threads $task.cpus \\ - $options.args - + $args \\ + $mods \\ + $xions \\ + $zions \\ + $aions \\ + $cions \\ + $nlions \\ + $remove_precursor + cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_decoydatabase.nf b/modules/local/openms_decoydatabase.nf index 2f9ebc4a..6cf537af 100644 --- a/modules/local/openms_decoydatabase.nf +++ b/modules/local/openms_decoydatabase.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_DECOYDATABASE { tag "$meta.id" label 'process_medium' conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(fasta) @@ -23,8 +15,7 @@ process OPENMS_DECOYDATABASE { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${fasta.baseName}_${options.suffix}" : "${fasta.baseName}_decoy" + def prefix = task.ext.suffix ? "${fasta.baseName}_${task.ext.suffix}" : "${fasta.baseName}_decoy" """ DecoyDatabase -in $fasta \\ @@ -33,7 +24,7 @@ process OPENMS_DECOYDATABASE { -decoy_string_position prefix cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_falsediscoveryrate.nf b/modules/local/openms_falsediscoveryrate.nf index c25d7058..5ed4a831 100644 --- a/modules/local/openms_falsediscoveryrate.nf +++ b/modules/local/openms_falsediscoveryrate.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_FALSEDISCOVERYRATE { tag "$meta.id" label 'process_low' conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(idxml) @@ -23,8 +15,7 @@ process OPENMS_FALSEDISCOVERYRATE { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${idxml.baseName}_${options.suffix}" : "${idxml.baseName}_fdr" + def prefix = task.ext.suffix ? "${idxml.baseName}_${task.ext.suffix}" : "${idxml.baseName}_fdr" """ FalseDiscoveryRate -in $idxml \\ @@ -33,7 +24,7 @@ process OPENMS_FALSEDISCOVERYRATE { -threads $task.cpus cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_featurefinderidentification.nf b/modules/local/openms_featurefinderidentification.nf index eacb21a3..0ef9bbab 100644 --- a/modules/local/openms_featurefinderidentification.nf +++ b/modules/local/openms_featurefinderidentification.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_FEATUREFINDERIDENTIFICATION { tag "$meta.id" label 'process_medium' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'Intermediate_Results', publish_id:'Intermediate_Results') } - conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(id_quant_int), path(mzml), path(id_quant) @@ -27,8 +15,7 @@ process OPENMS_FEATUREFINDERIDENTIFICATION { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${meta.sample}_${options.suffix}" : "${meta.sample}_${meta.id}" + def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}" : "${meta.sample}_${meta.id}" if (!params.quantification_fdr){ arguments = "-id $id_quant" @@ -40,11 +27,10 @@ process OPENMS_FEATUREFINDERIDENTIFICATION { FeatureFinderIdentification -in $mzml \\ -out ${prefix}.featureXML \\ -threads $task.cpus \\ - ${arguments} \\ - $options.args + ${arguments} cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_featurelinkerunlabeledkd.nf b/modules/local/openms_featurelinkerunlabeledkd.nf index ad8db0ba..9861e2b6 100644 --- a/modules/local/openms_featurelinkerunlabeledkd.nf +++ b/modules/local/openms_featurelinkerunlabeledkd.nf @@ -1,23 +1,12 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) process OPENMS_FEATURELINKERUNLABELEDKD { tag "$meta.id" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'Intermediate_Results', publish_id:'Intermediate_Results') } - conda (params.enable_conda ? "bioconda::openms-thirdparty=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms-thirdparty:2.6.0--0" - } else { - container "quay.io/biocontainers/openms-thirdparty:2.6.0--0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms-thirdparty:2.6.0--0' : + 'quay.io/biocontainers/openms-thirdparty:2.6.0--0' }" input: tuple val(meta), path(features) @@ -27,8 +16,7 @@ process OPENMS_FEATURELINKERUNLABELEDKD { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${meta.id}_${options.suffix}" : "${meta.id}_all_features_merged" + def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}_all_features_merged" """ FeatureLinkerUnlabeledKD -in $features \\ @@ -36,7 +24,7 @@ process OPENMS_FEATURELINKERUNLABELEDKD { -threads $task.cpus cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_idconflictresolver.nf b/modules/local/openms_idconflictresolver.nf index 5053c53b..7f46ef46 100644 --- a/modules/local/openms_idconflictresolver.nf +++ b/modules/local/openms_idconflictresolver.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_IDCONFLICTRESOLVER { tag "$meta.id" label 'process_low' conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(consensus) @@ -23,8 +15,7 @@ process OPENMS_IDCONFLICTRESOLVER { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${meta.id}_${options.suffix}" : "${meta.id}_resolved" + def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}_resolved" """ IDConflictResolver -in $consensus \\ @@ -32,7 +23,7 @@ process OPENMS_IDCONFLICTRESOLVER { -threads $task.cpus cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_idfilter.nf b/modules/local/openms_idfilter.nf index b59321a0..6ca3f798 100644 --- a/modules/local/openms_idfilter.nf +++ b/modules/local/openms_idfilter.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_IDFILTER { tag "$meta.id" label 'process_medium' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'Intermediate_Results', publish_id:'Intermediate_Results') } - conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(idxml), file(peptide_filter) @@ -27,9 +15,9 @@ process OPENMS_IDFILTER { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def whitelist = "$peptide_filter" - def prefix = options.suffix ? "${idxml.baseName}_${options.suffix}" : "${meta.id}_-_idx_fdr_filtered" + def whitelist = "$peptide_filter" + def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}_-_idx_fdr_filtered" + def args = task.ext.args ?: '' if (whitelist == "input.2") { whitelist = " " @@ -39,11 +27,11 @@ process OPENMS_IDFILTER { IDFilter -in $idxml \\ -out ${prefix}.idXML \\ -threads $task.cpus \\ - $options.args \\ + $args \\ $whitelist cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_idmerger.nf b/modules/local/openms_idmerger.nf index 289d250b..43cafffb 100644 --- a/modules/local/openms_idmerger.nf +++ b/modules/local/openms_idmerger.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_IDMERGER { tag "$meta.id" label 'process_low' conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(aligned) @@ -23,8 +15,7 @@ process OPENMS_IDMERGER { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${aligned.baseName}_${options.suffix}" : "${meta.sample}_${meta.condition}_all_ids_merged" + def prefix = task.ext.suffix ? "${meta.sample}_${meta.condition}_${task.ext.suffix}" : "${meta.sample}_${meta.condition}_all_ids_merged" """ IDMerger -in $aligned \\ @@ -34,7 +25,7 @@ process OPENMS_IDMERGER { -merge_proteins_add_PSMs cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_mapaligneridentification.nf b/modules/local/openms_mapaligneridentification.nf index 80ac9ba3..c4729e05 100644 --- a/modules/local/openms_mapaligneridentification.nf +++ b/modules/local/openms_mapaligneridentification.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_MAPALIGNERIDENTIFICATION { tag "$meta.id" label 'process_low' conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(idxml) @@ -23,16 +15,16 @@ process OPENMS_MAPALIGNERIDENTIFICATION { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def out_names = idxml.collect { it.baseName+'.trafoXML' }.join(' ') + def out_names = idxml.collect { it.baseName+'.trafoXML' }.join(' ') + def args = task.ext.args ?: '' """ MapAlignerIdentification -in $idxml \\ -trafo_out ${out_names} \\ - $options.args + $args cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_maprttransformer.nf b/modules/local/openms_maprttransformer.nf index 171bc744..7a4f2c42 100644 --- a/modules/local/openms_maprttransformer.nf +++ b/modules/local/openms_maprttransformer.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_MAPRTTRANSFORMER { tag "$meta.id" label 'process_low' conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(alignment_file), path(trafoxml) @@ -23,8 +15,7 @@ process OPENMS_MAPRTTRANSFORMER { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def fileExt = alignment_file.collect { it.name.tokenize("\\.")[1] }.join(' ') + def fileExt = alignment_file.collect { it.name.tokenize("\\.")[1] }.join(' ') """ MapRTTransformer -in $alignment_file \\ @@ -33,7 +24,7 @@ process OPENMS_MAPRTTRANSFORMER { -threads $task.cpus cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_mztabexporter.nf b/modules/local/openms_mztabexporter.nf index bfdcece6..fa94896a 100644 --- a/modules/local/openms_mztabexporter.nf +++ b/modules/local/openms_mztabexporter.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_MZTABEXPORTER { tag "$meta.id" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'Intermediate_Results', publish_id:'Intermediate_Results') } - conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(mztab) @@ -27,16 +15,17 @@ process OPENMS_MZTABEXPORTER { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${meta.sample}_${meta.condition}_${options.suffix}" : "${meta.sample}_${meta.condition}" + def prefix = task.ext.suffix ? "${meta.sample}_${meta.condition}_${task.ext.suffix}" : "${meta.sample}_${meta.condition}" + def args = task.ext.args ?: '' """ MzTabExporter -in $mztab \\ -out ${prefix}.mzTab \\ - -threads $task.cpus + -threads $task.cpus \\ + $args cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_peakpickerhires.nf b/modules/local/openms_peakpickerhires.nf index 76718e40..1f20ff87 100644 --- a/modules/local/openms_peakpickerhires.nf +++ b/modules/local/openms_peakpickerhires.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_PEAKPICKERHIRES { tag "$meta.id" label 'process_medium' conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(mzml) @@ -23,8 +15,7 @@ process OPENMS_PEAKPICKERHIRES { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${mzml.baseName}_${options.suffix}" : "${mzml.baseName}" + def prefix = task.ext.suffix ? "${mzml.baseName}_${task.ext.suffix}" : "${mzml.baseName}" """ PeakPickerHiRes -in $mzml \\ @@ -32,7 +23,7 @@ process OPENMS_PEAKPICKERHIRES { -algorithm:ms_levels ${params.pick_ms_levels} cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_peptideindexer.nf b/modules/local/openms_peptideindexer.nf index 935bfa23..198c777f 100644 --- a/modules/local/openms_peptideindexer.nf +++ b/modules/local/openms_peptideindexer.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_PEPTIDEINDEXER { tag "$meta.id" label 'process_low' conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(idxml), path(fasta) @@ -23,8 +15,7 @@ process OPENMS_PEPTIDEINDEXER { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${idxml.baseName}_${options.suffix}" : "${idxml.baseName}_idx" + def prefix = task.ext.suffix ? "${idxml.baseName}_${task.ext.suffix}" : "${idxml.baseName}_idx" """ PeptideIndexer -in $idxml \\ @@ -35,7 +26,7 @@ process OPENMS_PEPTIDEINDEXER { -enzyme:specificity none cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_percolatoradapter.nf b/modules/local/openms_percolatoradapter.nf index e9a07e5c..69a0c99c 100644 --- a/modules/local/openms_percolatoradapter.nf +++ b/modules/local/openms_percolatoradapter.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_PERCOLATORADAPTER { tag "$meta.id" label 'process_high' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'Intermediate_Results', publish_id:'Intermediate_Results') } - conda (params.enable_conda ? "bioconda::openms-thirdparty=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms-thirdparty:2.6.0--0" - } else { - container "quay.io/biocontainers/openms-thirdparty:2.6.0--0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms-thirdparty:2.6.0--0' : + 'quay.io/biocontainers/openms-thirdparty:2.6.0--0' }" input: tuple val(meta), path(psm) @@ -27,17 +15,17 @@ process OPENMS_PERCOLATORADAPTER { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${meta.id}_${options.suffix}" : "${meta.id}" + def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}" + def args = task.ext.args ?: '' """ OMP_NUM_THREADS=$task.cpus \\ PercolatorAdapter -in $psm \\ -out ${prefix}.idXML \\ - $options.args + $args cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_psmfeatureextractor.nf b/modules/local/openms_psmfeatureextractor.nf index bc8fc3e3..141580b8 100644 --- a/modules/local/openms_psmfeatureextractor.nf +++ b/modules/local/openms_psmfeatureextractor.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_PSMFEATUREEXTRACTOR { tag "$meta.id" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'Intermediate_Results', publish_id:'Intermediate_Results') } - conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(merged) @@ -27,16 +15,17 @@ process OPENMS_PSMFEATUREEXTRACTOR { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${merged.baseName}_${options.suffix}" : "${merged.baseName}_psm" + def prefix = task.ext.suffix ? "${merged.baseName}_${task.ext.suffix}" : "${merged.baseName}_psm" + def args = task.ext.args ?: '' """ PSMFeatureExtractor -in $merged \\ -out ${prefix}.idXML \\ - -threads $task.cpus + -threads $task.cpus \\ + $args cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_rtmodel.nf b/modules/local/openms_rtmodel.nf index 79687b59..57d8387c 100644 --- a/modules/local/openms_rtmodel.nf +++ b/modules/local/openms_rtmodel.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_RTMODEL { tag "$meta.id" label 'process_medium' conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(rt_training) @@ -23,8 +15,7 @@ process OPENMS_RTMODEL { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${meta.sample}_${options.suffix}" : "${meta.sample}" + def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}" : "${meta.sample}" """ RTModel -in $rt_training \\ @@ -34,7 +25,7 @@ process OPENMS_RTMODEL { -out_oligo_trainset ${prefix}_trainset.txt cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_rtpredict.nf b/modules/local/openms_rtpredict.nf index 31f95c9f..1803641f 100644 --- a/modules/local/openms_rtpredict.nf +++ b/modules/local/openms_rtpredict.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_RTPREDICT { tag "$meta.id" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'RT_prediction', publish_id:'RT_prediction') } - conda (params.enable_conda ? "bioconda::openms-thirdparty=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms-thirdparty:2.6.0--0" - } else { - container "quay.io/biocontainers/openms-thirdparty:2.6.0--0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms-thirdparty:2.6.0--0' : + 'quay.io/biocontainers/openms-thirdparty:2.6.0--0' }" input: tuple val(meta), path(idxml), path(rt_model), path(rt_params), path(trainset) @@ -27,8 +15,7 @@ process OPENMS_RTPREDICT { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${meta.sample}_${options.suffix}" : "${meta.sample}_RTpredicted" + def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}" : "${meta.sample}_RTpredicted" """ RTPredict -in_id $idxml \\ @@ -38,7 +25,7 @@ process OPENMS_RTPREDICT { -out_text:file ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_textexporter.nf b/modules/local/openms_textexporter.nf index 075dc1d5..e4312965 100644 --- a/modules/local/openms_textexporter.nf +++ b/modules/local/openms_textexporter.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_TEXTEXPORTER { tag "$meta.id" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'.', publish_id:'') } - conda (params.enable_conda ? "bioconda::openms=2.6.0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0" - } else { - container "quay.io/biocontainers/openms:2.6.0--h4afb90d_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/openms:2.6.0--h4afb90d_0' : + 'quay.io/biocontainers/openms:2.6.0--h4afb90d_0' }" input: tuple val(meta), path(consensus_resolved) @@ -27,8 +15,7 @@ process OPENMS_TEXTEXPORTER { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${meta.id}_${options.suffix}" : "${meta.id}" + def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}" """ TextExporter -in $consensus_resolved \\ @@ -39,7 +26,7 @@ process OPENMS_TEXTEXPORTER { -id:peptides_only cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_thermorawfileparser.nf b/modules/local/openms_thermorawfileparser.nf index 166cde7e..2e3ba9cb 100644 --- a/modules/local/openms_thermorawfileparser.nf +++ b/modules/local/openms_thermorawfileparser.nf @@ -1,19 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process OPENMS_THERMORAWFILEPARSER { tag "$meta.id" label 'process_medium' conda (params.enable_conda ? "bioconda::thermorawfileparser::1.3.4" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/thermorawfileparser:1.3.4--ha8f3691_0" - } else { - container "quay.io/biocontainers/thermorawfileparser:1.3.4--ha8f3691_0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/thermorawfileparser:1.3.4--ha8f3691_0' : + 'quay.io/biocontainers/thermorawfileparser:1.3.4--ha8f3691_0' }" input: tuple val(meta), path(rawfile) @@ -23,15 +15,15 @@ process OPENMS_THERMORAWFILEPARSER { path "versions.yml" , emit: versions script: - def software = getSoftwareName(task.process) - def prefix = options.suffix ? "${rawfile.baseName}_${options.suffix}" : "${rawfile.baseName}" + def prefix = task.ext.suffix ? "${rawfile.baseName}_${task.ext.suffix}" : "${rawfile.baseName}" """ ThermoRawFileParser.sh -i=$rawfile \\ -f=2 \\ -b=${prefix}.mzML + cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: thermorawfileparser: \$(ThermoRawFileParser.sh --version) END_VERSIONS """ diff --git a/modules/local/predict_possible_class_2_neoepitopes.nf b/modules/local/predict_possible_class_2_neoepitopes.nf index 11162f1c..9668ceb4 100644 --- a/modules/local/predict_possible_class_2_neoepitopes.nf +++ b/modules/local/predict_possible_class_2_neoepitopes.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'.', publish_id:'') } - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } else { - container "quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" input: tuple val(meta), val(alleles), path(vcf) @@ -28,7 +16,7 @@ process PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta}_${options.suffix}" : "${meta}_vcf_neoepitopes_class2" + def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_vcf_neoepitopes_class2" """ vcf_neoepitope_predictor.py -t ${params.variant_annotation_style} \\ @@ -40,7 +28,7 @@ process PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES { -o ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/predict_possible_neoepitopes.nf b/modules/local/predict_possible_neoepitopes.nf index e775e982..a799d1e2 100644 --- a/modules/local/predict_possible_neoepitopes.nf +++ b/modules/local/predict_possible_neoepitopes.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process PREDICT_POSSIBLE_NEOEPITOPES { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'.', publish_id:'') } - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } else { - container "quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" input: tuple val(meta), val(alleles), path(vcf) @@ -28,7 +16,7 @@ process PREDICT_POSSIBLE_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta}_${options.suffix}" : "${meta}_vcf_neoepitopes_class1" + def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_vcf_neoepitopes_class1" """ vcf_neoepitope_predictor.py \\ @@ -40,7 +28,7 @@ process PREDICT_POSSIBLE_NEOEPITOPES { -o ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/resolve_found_class_2_neoepitopes.nf b/modules/local/resolve_found_class_2_neoepitopes.nf index 80fd21c5..33b0e8ef 100644 --- a/modules/local/resolve_found_class_2_neoepitopes.nf +++ b/modules/local/resolve_found_class_2_neoepitopes.nf @@ -1,25 +1,12 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) process RESOLVE_FOUND_CLASS_2_NEOEPITOPES { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'class_2_bindings', publish_id:'class_2_bindings') } - - echo true - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } else { - container "quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" input: tuple val(meta), path(mztab), path(neoepitopes) @@ -29,19 +16,19 @@ process RESOLVE_FOUND_CLASS_2_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta}_${options.suffix}" : "${meta}_found_neoepitopes_class_2" + def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_found_neoepitopes_class_2" """ - resolve_neoepitopes.py -n $neoepitopes \\ - -m $mztab \\ - -f csv \\ - -o ${prefix} - - cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: - mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) - mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) - fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) - END_VERSIONS + resolve_neoepitopes.py -n $neoepitopes \\ + -m $mztab \\ + -f csv \\ + -o ${prefix} + + cat <<-END_VERSIONS > versions.yml + ${task.process}: + mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) + mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) + fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) + END_VERSIONS """ } diff --git a/modules/local/resolve_found_neoepitopes.nf b/modules/local/resolve_found_neoepitopes.nf index ece53e31..e5a5f2f7 100644 --- a/modules/local/resolve_found_neoepitopes.nf +++ b/modules/local/resolve_found_neoepitopes.nf @@ -1,23 +1,11 @@ -// Import generic module functions -include { initOptions; saveFiles; getSoftwareName; getProcessName } from './functions' - -params.options = [:] -options = initOptions(params.options) - process RESOLVE_FOUND_NEOEPITOPES { tag "$meta" label 'process_low' - publishDir "${params.outdir}", - mode: params.publish_dir_mode, - saveAs: { filename -> saveFiles(filename:filename, options:params.options, publish_dir:'class_1_bindings', publish_id:'class_1_bindings') } - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } else { - container "quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0" - } + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" input: tuple val(meta), path(mztab), path(neoepitopes) @@ -27,7 +15,7 @@ process RESOLVE_FOUND_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = options.suffix ? "${meta}_${options.suffix}" : "${meta}_found_neoepitopes_class_1" + def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_found_neoepitopes_class_1" """ resolve_neoepitopes.py -n $neoepitopes \\ @@ -36,7 +24,7 @@ process RESOLVE_FOUND_NEOEPITOPES { -o ${prefix} cat <<-END_VERSIONS > versions.yml - ${getProcessName(task.process)}: + ${task.process}: mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//')) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/nextflow.config b/nextflow.config index a81f4762..a0c691b3 100644 --- a/nextflow.config +++ b/nextflow.config @@ -10,101 +10,98 @@ params { // Workflow flags - help = false - input = "sample_sheet.tsv" - outdir = './results' - fasta = "data/*.fasta" - - // References - genomes = null - - // Workflow options - allele_sheet = false - include_proteins_from_vcf = false - predict_class_1 = false - predict_class_2 = false + help = false + input = "sample_sheet.tsv" + outdir = './results' + fasta = "data/*.fasta" + + // References + genomes = null + + // Workflow options + allele_sheet = null + include_proteins_from_vcf = false + predict_class_1 = false + predict_class_2 = false refine_fdr_on_predicted_subset = false - schema_ignore_params = 'genome' - skip_decoy_generation = false - subset_affinity_threshold = 500 - variant_annotation_style = "SNPEFF" - variant_frameshift_filter = false - variant_indel_filter = false - variant_reference = "GRCH38" - variant_snp_filter = false + schema_ignore_params = 'genome' + skip_decoy_generation = false + subset_affinity_threshold = 500 + variant_annotation_style = "SNPEFF" + variant_frameshift_filter = false + variant_indel_filter = false + variant_reference = "GRCH38" + variant_snp_filter = false // MultiQC options - skip_multiqc = false - multiqc_config = null - multiqc_title = null - max_multiqc_email_size = '25.MB' + skip_multiqc = false + multiqc_config = null + multiqc_title = null + max_multiqc_email_size = '25.MB' // Workflow defaults - activation_method = 'ALL' - description_correct_features = 0 - digest_mass_range = "800:2500" - enzyme = 'unspecific cleavage' - fdr_threshold = 0.01 - fdr_level = 'peptide_level_fdrs' - fixed_mods = '' - fragment_bin_offset = 0 - fragment_mass_tolerance = 0.02 - klammer = false - max_rt_alignment_shift = 300 - number_mods = 3 - num_hits = 1 - peptide_min_length = 8 - peptide_max_length = 12 - pick_ms_levels = 2 - predict_RT = false - prec_charge = '2:3' - precursor_mass_tolerance = 5 - quantification_fdr = false - quantification_min_prob = 0 + activation_method = 'ALL' + description_correct_features = 0 + digest_mass_range = "800:2500" + enzyme = 'unspecific cleavage' + fdr_threshold = 0.01 + fdr_level = 'peptide_level_fdrs' + fixed_mods = ' ' + fragment_bin_offset = 0 + fragment_mass_tolerance = 0.02 + klammer = false + max_rt_alignment_shift = 300 + number_mods = 3 + num_hits = 1 + peptide_min_length = 8 + peptide_max_length = 12 + pick_ms_levels = 2 + predict_RT = false + prec_charge = '2:3' + precursor_mass_tolerance = 5 + quantification_fdr = null + quantification_min_prob = 0 refine_fdr_on_predicted_subset = false - remove_precursor_peak = false - run_centroidisation = false - skip_quantification = false - spectrum_batch_size = 500 - subset_max_train = 0 - tracedir = "${params.outdir}/pipeline_info" - use_x_ions = false - use_z_ions = false - use_a_ions = false - use_c_ions = false - use_NL_ions = false - variable_mods = 'Oxidation (M)' - vcf_sheet = false + remove_precursor_peak = false + run_centroidisation = false + skip_quantification = false + spectrum_batch_size = 500 + subset_max_train = 0 + tracedir = "${params.outdir}/pipeline_info" + use_x_ions = false + use_z_ions = false + use_a_ions = false + use_c_ions = false + use_NL_ions = false + variable_mods = 'Oxidation (M)' + vcf_sheet = null // Boilerplate options - outdir = './results' - tracedir = "${params.outdir}/pipeline_info" - publish_dir_mode = 'copy' - 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,modules' - enable_conda = false - singularity_pull_docker_container = false + outdir = './results' + tracedir = "${params.outdir}/pipeline_info" + 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,modules' + enable_conda = false // Config options - custom_config_version = 'master' - custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" - hostnames = [:] - config_profile_description = null - config_profile_contact = null - config_profile_url = null - config_profile_name = 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 - max_memory = '128.GB' - max_cpus = 16 - max_time = '240.h' + max_memory = '128.GB' + max_cpus = 16 + max_time = '240.h' } // Load base.config by default for all pipelines diff --git a/nextflow_schema.json b/nextflow_schema.json index 6a906eea..3fb0806f 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -197,7 +197,7 @@ "remove_precursor_peak": { "type": "boolean", "description": "Include precursor ions into the peptide spectrum matching", - "default": true + "default": false }, "spectrum_batch_size": { "type": "integer", @@ -328,12 +328,12 @@ "variant_indel_filter": { "type": "boolean", "description": "Specify whether insertions and deletions should not be considered for variant translation", - "default": true + "default": false }, "variant_frameshift_filter": { "type": "boolean", "description": "Specify whether frameshifts should not be considered for variant translation", - "default": true + "default": false }, "variant_snp_filter": { "type": "boolean", diff --git a/subworkflows/local/refine_fdr_on_predicted_subset.nf b/subworkflows/local/refine_fdr_on_predicted_subset.nf index b786d649..4a025b07 100644 --- a/subworkflows/local/refine_fdr_on_predicted_subset.nf +++ b/subworkflows/local/refine_fdr_on_predicted_subset.nf @@ -2,25 +2,13 @@ * Perform an additional step where the process are collected * that are called when the paramater "refine_fdr_on_predicted_subset" is provided */ - -params.exporter_prec_options = [:] -params.exporter_psm_options = [:] -params.percolator_adapter_refine_options = [:] -params.whitelist_filter_options = [:] -params.filter_options = [:] - -def openms_mztab_exporter_prec_options = params.exporter_prec_options.clone() -def openms_mztab_exporter_psm_options = params.exporter_psm_options.clone() -def openms_percolator_adapter_options = params.percolator_adapter_refine_options.clone() -def openms_id_filter_psms_options = params.whitelist_filter_options.clone() -def openms_id_filter_qvalue_options = params.filter_options.clone() - -include { OPENMS_MZTABEXPORTER as OPENMS_MZTABEXPORTERPERC } from '../../modules/local/openms_mztabexporter' addParams( options: openms_mztab_exporter_prec_options ) -include { OPENMS_MZTABEXPORTER as OPENMS_MZTABEXPORTERPSM } from '../../modules/local/openms_mztabexporter' addParams( options: openms_mztab_exporter_psm_options ) -include { MHCFLURRY_PREDICTPSMS } from '../../modules/local/mhcflurry_predictpsms' addParams( options: [:] ) -include { OPENMS_PERCOLATORADAPTER } from '../../modules/local/openms_percolatoradapter' addParams( options: openms_percolator_adapter_options ) -include { OPENMS_IDFILTER as OPENMS_IDFILTER_PSMS } from '../../modules/local/openms_idfilter' addParams( options: openms_id_filter_psms_options ) -include { OPENMS_IDFILTER as OPENMS_IDFILTER_REFINED } from '../../modules/local/openms_idfilter' addParams( options: openms_id_filter_qvalue_options ) + +include { OPENMS_MZTABEXPORTER as OPENMS_MZTABEXPORTERPERC } from '../../modules/local/openms_mztabexporter' +include { OPENMS_MZTABEXPORTER as OPENMS_MZTABEXPORTERPSM } from '../../modules/local/openms_mztabexporter' +include { MHCFLURRY_PREDICTPSMS } from '../../modules/local/mhcflurry_predictpsms' +include { OPENMS_PERCOLATORADAPTER } from '../../modules/local/openms_percolatoradapter' +include { OPENMS_IDFILTER as OPENMS_IDFILTER_PSMS } from '../../modules/local/openms_idfilter' +include { OPENMS_IDFILTER as OPENMS_IDFILTER_REFINED } from '../../modules/local/openms_idfilter' workflow REFINE_FDR_ON_PREDICTED_SUBSET { // Define the input parameters diff --git a/workflows/mhcquant.nf b/workflows/mhcquant.nf index 62abdcc7..e5c9c2e4 100644 --- a/workflows/mhcquant.nf +++ b/workflows/mhcquant.nf @@ -57,107 +57,63 @@ if (params.include_proteins_from_vcf) { ch_multiqc_config = file("$projectDir/assets/multiqc_config.yaml", checkIfExists: true) ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config) : Channel.empty() - /* ======================================================================================== - IMPORT LOCAL MODULES/SUBWORKFLOWS + CREATE CHANNELS ======================================================================================== */ -// Don't overwrite global params.modules, create a copy instead and use that within the main script. -//def modules = params.modules.clone() - -//def multiqc_options = modules['multiqc'] -//multiqc_options.args += params.multiqc_title ? Utils.joinModuleArgs(["--title \"$params.multiqc_title\""]) : '' -// -//def generate_proteins_from_vcf_options = modules['generate_proteins_from_vcf'] -//generate_proteins_from_vcf_options.args += params.variant_indel_filter ? Utils.joinModuleArgs(['-fINDEL']) : '' -//generate_proteins_from_vcf_options.args += params.variant_frameshift_filter ? Utils.joinModuleArgs(['-fFS']) : '' -//generate_proteins_from_vcf_options.args += params.variant_snp_filter ? Utils.joinModuleArgs(['-fSNP']) : '' -// -//def openms_comet_adapter_options = modules['openms_comet_adapter'] -//openms_comet_adapter_options.args += params.use_x_ions ? Utils.joinModuleArgs(['-use_X_ions true']) : '' -//openms_comet_adapter_options.args += params.use_z_ions ? Utils.joinModuleArgs(['-use_Z_ions true']) : '' -//openms_comet_adapter_options.args += params.use_a_ions ? Utils.joinModuleArgs(['-use_A_ions true']) : '' -//openms_comet_adapter_options.args += params.use_c_ions ? Utils.joinModuleArgs(['-use_C_ions true']) : '' -//openms_comet_adapter_options.args += params.use_NL_ions ? Utils.joinModuleArgs(['-use_NL_ions true']) : '' -//openms_comet_adapter_options.args += params.remove_precursor_peak ? Utils.joinModuleArgs(['-remove_precursor_peak yes']) : '' -// -//def openms_id_filter_options = modules['openms_id_filter'] -//def openms_id_filter_refiner_options = modules['openms_id_filter_refiner'] -//def openms_id_filter_for_alignment_options = openms_id_filter_options.clone() -//def openms_id_filter_whitelist_options = modules['openms_id_filter_whitelist'] -//openms_id_filter_options.args += " -score:pep " + params.fdr_threshold -//openms_id_filter_refiner_options.args += " -score:pep " + params.fdr_threshold -//openms_id_filter_for_alignment_options.args += " -score:pep " + (params.fdr_threshold == '0.01') ? Utils.joinModuleArgs(['-score:pep 0.05']) : Utils.joinModuleArgs(['-score:pep ' + params.fdr_threshold]) -//def openms_id_filter_qvalue_options = openms_id_filter_options.clone() -//openms_id_filter_qvalue_options.suffix = "filtered" -// -//def openms_map_aligner_identification_options = modules['openms_map_aligner_identification'] -//def openms_mztab_exporter_perc_options = modules['openms_mztab_exporter_perc'] -//def openms_mztab_exporter_psm_options = modules['openms_mztab_exporter_psm'] -//def openms_percolator_adapter_options = modules['openms_percolator_adapter'] -//def openms_percolator_adapter_refine_options = modules['openms_percolator_adapter_refine'] -//openms_percolator_adapter_options.args += (params.fdr_level != 'psm-level-fdrs') ? Utils.joinModuleArgs(['-'+params.fdr_level]) : '' -//openms_percolator_adapter_refine_options.args += (params.fdr_level != 'psm-level-fdrs') ? Utils.joinModuleArgs(['-'+params.fdr_level]) : '' -//def openms_percolator_adapter_klammer_options = openms_percolator_adapter_options.clone() -//openms_percolator_adapter_klammer_options.args += " -klammer" -// -//def openms_rt_predict_peptides_options = modules['openms_rt_predict_peptides'] -//def openms_rt_predict_neo_epitopes_options = modules['openms_rt_predict_neo_epitopes'] - -//////////////////////////////////////////////////// -/* -- CREATE CHANNELS -- */ -//////////////////////////////////////////////////// -//include { hasExtension } from '../modules/local/functions' include { INPUT_CHECK } from '../subworkflows/local/input_check' -//include { GENERATE_PROTEINS_FROM_VCF } from '../modules/local/generate_proteins_from_vcf' addParams( options: generate_proteins_from_vcf_options ) -//include { OPENMS_DECOYDATABASE } from '../modules/local/openms_decoydatabase' addParams( options: [:] ) -//include { OPENMS_THERMORAWFILEPARSER } from '../modules/local/openms_thermorawfileparser' addParams( options: [:] ) -//include { OPENMS_PEAKPICKERHIRES } from '../modules/local/openms_peakpickerhires' addParams( options: [:] ) -//include { OPENMS_COMETADAPTER } from '../modules/local/openms_cometadapter' addParams( options: openms_comet_adapter_options ) -//include { OPENMS_PEPTIDEINDEXER } from '../modules/local/openms_peptideindexer' addParams( options: [:] ) -//include { OPENMS_FALSEDISCOVERYRATE } from '../modules/local/openms_falsediscoveryrate' addParams( options: [:] ) -//include { OPENMS_IDFILTER as OPENMS_IDFILTER_FOR_ALIGNMENT } from '../modules/local/openms_idfilter' addParams( options: openms_id_filter_for_alignment_options ) -//include { OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE } from '../modules/local/openms_idfilter' addParams( options: openms_id_filter_qvalue_options ) -//include { OPENMS_MAPALIGNERIDENTIFICATION } from '../modules/local/openms_mapaligneridentification' addParams( options: openms_map_aligner_identification_options ) -// -//include { -// OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERMZML -// OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERIDXML } from '../modules/local/openms_maprttransformer' addParams( options: [:] ) -// -//include { OPENMS_IDMERGER } from '../modules/local/openms_idmerger' addParams( options: [:] ) -//include { OPENMS_PSMFEATUREEXTRACTOR } from '../modules/local/openms_psmfeatureextractor' addParams( options: [:] ) -//include { OPENMS_PERCOLATORADAPTER } from '../modules/local/openms_percolatoradapter' addParams( options: openms_percolator_adapter_options ) -//include { OPENMS_PERCOLATORADAPTER as OPENMS_PERCOLATORADAPTER_KLAMMER } from '../modules/local/openms_percolatoradapter' addParams( options: openms_percolator_adapter_klammer_options ) -// -//include { REFINE_FDR_ON_PREDICTED_SUBSET } from '../subworkflows/local/refine_fdr_on_predicted_subset' addParams( exporter_prec_options : openms_mztab_exporter_perc_options, exporter_psm_options : openms_mztab_exporter_psm_options, run_percolator_options : openms_percolator_adapter_refine_options, whitelist_filter_options: openms_id_filter_whitelist_options, filter_options: openms_id_filter_refiner_options) -// -//include { OPENMS_FEATUREFINDERIDENTIFICATION } from '../modules/local/openms_featurefinderidentification' addParams( options: [:] ) -//include { OPENMS_FEATURELINKERUNLABELEDKD } from '../modules/local/openms_featurelinkerunlabeledkd' addParams( options: [:] ) -//include { OPENMS_IDCONFLICTRESOLVER } from '../modules/local/openms_idconflictresolver' addParams( options: [:] ) -//include { OPENMS_TEXTEXPORTER } from '../modules/local/openms_textexporter' addParams( options: [:] ) -//include { OPENMS_MZTABEXPORTER } from '../modules/local/openms_mztabexporter' addParams( options: [:] ) -// -//include { MHCFLURRY_PREDICTPEPTIDESCLASS1 } from '../modules/local/mhcflurry_predictpeptidesclass1' addParams( options: [:] ) -//include { MHCNUGGETS_PEPTIDESCLASS2PRE } from '../modules/local/mhcnuggets_peptidesclass2pre' addParams( options: [:] ) -//include { MHCNUGGETS_PREDICTPEPTIDESCLASS2 } from '../modules/local/mhcnuggets_predictpeptidesclass2' addParams( options: [:] ) -//include { MHCNUGGETS_PEPTIDESCLASS2POST } from '../modules/local/mhcnuggets_peptidesclass2post' addParams( options: [:] ) -//include { PREDICT_POSSIBLE_NEOEPITOPES } from '../modules/local/predict_possible_neoepitopes' addParams( options: [:] ) -//include { PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES } from '../modules/local/predict_possible_class_2_neoepitopes' addParams( options: [:] ) -//include { RESOLVE_FOUND_NEOEPITOPES } from '../modules/local/resolve_found_neoepitopes' addParams( options: [:] ) -//include { RESOLVE_FOUND_CLASS_2_NEOEPITOPES } from '../modules/local/resolve_found_class_2_neoepitopes' addParams( options: [:] ) -//include { MHCFLURRY_PREDICTNEOEPITOPESCLASS1 } from '../modules/local/mhcflurry_predictneoepitopesclass1' addParams( options: [:] ) -//include { MHCNUGGETS_NEOEPITOPESCLASS2RE } from '../modules/local/mhcnuggets_neoepitopesclass2pre' addParams( options: [:] ) -//include { MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 } from '../modules/local/mhcnuggets_predictneoepitopesclass2' addParams( options: [:] ) -//include { MHCNUGGETS_NEOEPITOPESCLASS2POST } from '../modules/local/mhcnuggets_neoepitopesclass2post' addParams( options: [:] ) -// -//include { OPENMS_RTMODEL } from '../modules/local/openms_rtmodel' addParams( options: [:] ) -//include { OPENMS_RTPREDICT as OPENMS_RTPREDICT_FOUND_PEPTIDES} from '../modules/local/openms_rtpredict' addParams( options: openms_rt_predict_peptides_options ) -//include { OPENMS_RTPREDICT as OPENMS_RTPREDICT_NEOEPITOPES} from '../modules/local/openms_rtpredict' addParams( options: openms_rt_predict_neo_epitopes_options ) -// -include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' //addParams( options: [publish_files : ['_versions.yml':'']] ) -include { MULTIQC } from '../modules/nf-core/modules/multiqc/main' //addParams( options: multiqc_options ) +include { GENERATE_PROTEINS_FROM_VCF } from '../modules/local/generate_proteins_from_vcf' +include { OPENMS_DECOYDATABASE } from '../modules/local/openms_decoydatabase' +include { OPENMS_THERMORAWFILEPARSER } from '../modules/local/openms_thermorawfileparser' +include { OPENMS_PEAKPICKERHIRES } from '../modules/local/openms_peakpickerhires' +include { OPENMS_COMETADAPTER } from '../modules/local/openms_cometadapter' +include { OPENMS_PEPTIDEINDEXER } from '../modules/local/openms_peptideindexer' +include { OPENMS_FALSEDISCOVERYRATE } from '../modules/local/openms_falsediscoveryrate' +include { + OPENMS_IDFILTER as OPENMS_IDFILTER_FOR_ALIGNMENT + OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE } from '../modules/local/openms_idfilter' +include { OPENMS_MAPALIGNERIDENTIFICATION } from '../modules/local/openms_mapaligneridentification' + +include { + OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERMZML + OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERIDXML } from '../modules/local/openms_maprttransformer' + +include { OPENMS_IDMERGER } from '../modules/local/openms_idmerger' +include { OPENMS_PSMFEATUREEXTRACTOR } from '../modules/local/openms_psmfeatureextractor' +include { + OPENMS_PERCOLATORADAPTER + OPENMS_PERCOLATORADAPTER as OPENMS_PERCOLATORADAPTER_KLAMMER } from '../modules/local/openms_percolatoradapter' + +include { REFINE_FDR_ON_PREDICTED_SUBSET } from '../subworkflows/local/refine_fdr_on_predicted_subset' + +include { OPENMS_FEATUREFINDERIDENTIFICATION } from '../modules/local/openms_featurefinderidentification' +include { OPENMS_FEATURELINKERUNLABELEDKD } from '../modules/local/openms_featurelinkerunlabeledkd' +include { OPENMS_IDCONFLICTRESOLVER } from '../modules/local/openms_idconflictresolver' +include { OPENMS_TEXTEXPORTER } from '../modules/local/openms_textexporter' +include { OPENMS_MZTABEXPORTER } from '../modules/local/openms_mztabexporter' + +include { MHCFLURRY_PREDICTPEPTIDESCLASS1 } from '../modules/local/mhcflurry_predictpeptidesclass1' +include { MHCNUGGETS_PEPTIDESCLASS2PRE } from '../modules/local/mhcnuggets_peptidesclass2pre' +include { MHCNUGGETS_PREDICTPEPTIDESCLASS2 } from '../modules/local/mhcnuggets_predictpeptidesclass2' +include { MHCNUGGETS_PEPTIDESCLASS2POST } from '../modules/local/mhcnuggets_peptidesclass2post' +include { PREDICT_POSSIBLE_NEOEPITOPES } from '../modules/local/predict_possible_neoepitopes' +include { PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES } from '../modules/local/predict_possible_class_2_neoepitopes' +include { RESOLVE_FOUND_NEOEPITOPES } from '../modules/local/resolve_found_neoepitopes' +include { RESOLVE_FOUND_CLASS_2_NEOEPITOPES } from '../modules/local/resolve_found_class_2_neoepitopes' +include { MHCFLURRY_PREDICTNEOEPITOPESCLASS1 } from '../modules/local/mhcflurry_predictneoepitopesclass1' +include { MHCNUGGETS_NEOEPITOPESCLASS2PRE } from '../modules/local/mhcnuggets_neoepitopesclass2pre' +include { MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 } from '../modules/local/mhcnuggets_predictneoepitopesclass2' +include { MHCNUGGETS_NEOEPITOPESCLASS2POST } from '../modules/local/mhcnuggets_neoepitopesclass2post' + +include { OPENMS_RTMODEL } from '../modules/local/openms_rtmodel' +include { + OPENMS_RTPREDICT as OPENMS_RTPREDICT_FOUND_PEPTIDES + OPENMS_RTPREDICT as OPENMS_RTPREDICT_NEOEPITOPES} from '../modules/local/openms_rtpredict' + +include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' +include { MULTIQC } from '../modules/nf-core/modules/multiqc/main' //////////////////////////////////////////////////// /* -- RUN MAIN WORKFLOW -- */ @@ -193,273 +149,273 @@ workflow MHCQUANT { // A warning message will be given when the format differs from the '.raw' or '.mzML' extention ms_files.other.subscribe { row -> log.warn("Unknown format for entry " + row[3] + " in provided sample sheet, line will be ignored."); exit 1 } -// if ( params.include_proteins_from_vcf ) { -// // Combine the vcf information with the meta information -// ch_vcf = input_fasta -// .map{ it -> [it[0].sample, it[0], it[1]] } -// .join( ch_vcf_from_sheet ) -// .map(it -> [it[1], it[2], it[3]]) -// // If specified translate variants to proteins and include in reference fasta -// GENERATE_PROTEINS_FROM_VCF( ch_vcf ) -// ch_versions = ch_versions.mix(GENERATE_PROTEINS_FROM_VCF.out.versions.first().ifEmpty(null)) -// ch_fasta_file = GENERATE_PROTEINS_FROM_VCF.out.vcf_fasta -// } else { -// ch_fasta_file = input_fasta -// } -// -// if (!params.skip_decoy_generation) { -// // Generate reversed decoy database -// OPENMS_DECOYDATABASE(ch_fasta_file) -// ch_versions = ch_versions.mix(OPENMS_DECOYDATABASE.out.versions.first().ifEmpty(null)) -// ch_decoy_db = OPENMS_DECOYDATABASE.out.decoy -// } else { -// ch_decoy_db = ch_fasta_file -// } -// -// // Raw file conversion -// OPENMS_THERMORAWFILEPARSER(ms_files.raw) -// ch_versions = ch_versions.mix(OPENMS_THERMORAWFILEPARSER.out.versions.first().ifEmpty(null)) -// -// if ( params.run_centroidisation ) { -// // Optional: Run Peak Picking as Preprocessing -// OPENMS_PEAKPICKERHIRES(ms_files.mzml) -// ch_versions = ch_versions.mix(OPENMS_PEAKPICKERHIRES.out.versions.first().ifEmpty(null)) -// ch_mzml_file = OPENMS_PEAKPICKERHIRES.out.mzml -// } else { -// ch_mzml_file = ms_files.mzml -// } -// -// // Run comet database search -// OPENMS_COMETADAPTER( -// OPENMS_THERMORAWFILEPARSER.out.mzml -// .mix(ch_mzml_file) -// .join(ch_decoy_db, remainder:true)) -// ch_versions = ch_versions.mix(OPENMS_COMETADAPTER.out.versions.first().ifEmpty(null)) -// -// // Index decoy and target hits -// OPENMS_PEPTIDEINDEXER(OPENMS_COMETADAPTER.out.idxml.join(ch_decoy_db)) -// ch_versions = ch_versions.mix(OPENMS_PEPTIDEINDEXER.out.versions.first().ifEmpty(null)) -// -// if(!params.skip_quantification) { -// // Calculate fdr for id based alignment -// OPENMS_FALSEDISCOVERYRATE(OPENMS_PEPTIDEINDEXER.out.idxml) -// ch_versions = ch_versions.mix(OPENMS_FALSEDISCOVERYRATE.out.versions.first().ifEmpty(null)) -// // Filter fdr for id based alignment -// OPENMS_IDFILTER_FOR_ALIGNMENT(OPENMS_FALSEDISCOVERYRATE.out.idxml -// .flatMap { it -> [tuple(it[0], it[1], null)]}) -// ch_versions = ch_versions.mix(OPENMS_IDFILTER_FOR_ALIGNMENT.out.versions.first().ifEmpty(null)) -// -// ch_grouped_fdr_filtered = OPENMS_IDFILTER_FOR_ALIGNMENT.out.idxml -// .map { -// meta, raw -> -// [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] -// } -// .groupTuple(by: [0]) -// -// // Compute alignment rt transformatio -// OPENMS_MAPALIGNERIDENTIFICATION(ch_grouped_fdr_filtered) -// ch_versions = ch_versions.mix(OPENMS_MAPALIGNERIDENTIFICATION.out.versions.first().ifEmpty(null)) -// // Intermediate step to join RT transformation files with mzml and idxml channels -// ms_files.mzml -// .mix(OPENMS_THERMORAWFILEPARSER.out.mzml) -// .mix(ch_mzml_file) -// .join( -// OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml -// .transpose() -// .flatMap { -// meta, trafoxml -> -// ident = trafoxml.baseName.split('_-_')[0] -// [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] -// }, by: [0] ) -// .set { joined_trafos_mzmls } -// -// OPENMS_PEPTIDEINDEXER.out.idxml -// .join( -// OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml -// .transpose() -// .flatMap { -// meta, trafoxml -> -// ident = trafoxml.baseName.split('_-_')[0] -// [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] -// }, by: [0] ) -// .set { joined_trafos_ids } -// -// // Align mzML files using trafoXMLs -// OPENMS_MAPRTTRANSFORMERMZML(joined_trafos_mzmls) -// ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERMZML.out.versions.first().ifEmpty(null)) -// // Align unfiltered idXMLfiles using trafoXMLs -// OPENMS_MAPRTTRANSFORMERIDXML(joined_trafos_ids) -// ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERIDXML.out.versions.first().ifEmpty(null)) -// ch_proceeding_idx = OPENMS_MAPRTTRANSFORMERIDXML.out.aligned -// .map { -// meta, raw -> -// [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] -// } -// .groupTuple(by: [0]) -// -// } else { -// ch_proceeding_idx = OPENMS_PEPTIDEINDEXER.out.idxml -// .map { -// meta, raw -> -// [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] -// } -// .groupTuple(by: [0]) -// } -// -// // Merge aligned idXMLfiles -// OPENMS_IDMERGER(ch_proceeding_idx) -// ch_versions = ch_versions.mix(OPENMS_IDMERGER.out.versions.first().ifEmpty(null)) -// // Extract PSM features for Percolator -// OPENMS_PSMFEATUREEXTRACTOR(OPENMS_IDMERGER.out.idxml) -// ch_versions = ch_versions.mix(OPENMS_PSMFEATUREEXTRACTOR.out.versions.first().ifEmpty(null)) -// // Run Percolator -// if (params.description_correct_features > 0 && params.klammer) { -// OPENMS_PERCOLATORADAPTER_KLAMMER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) -// ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER_KLAMMER.out.versions.first().ifEmpty(null)) -// ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER_KLAMMER.out.idxml -// -// } else { -// OPENMS_PERCOLATORADAPTER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) -// ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions.first().ifEmpty(null)) -// ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER.out.idxml -// } -// -// // Filter by percolator q-value -// OPENMS_IDFILTER_Q_VALUE(ch_percolator_adapter_outcome.flatMap { it -> [tuple(it[0], it[1], null)]}) -// ch_versions = ch_versions.mix(OPENMS_IDFILTER_Q_VALUE.out.versions.first().ifEmpty(null)) -// -// // Refine_fdr_on_predicted_subset -// if ( params.refine_fdr_on_predicted_subset && params.predict_class_1 ) { -// // Run the following subworkflow -// REFINE_FDR_ON_PREDICTED_SUBSET ( -// OPENMS_IDFILTER_Q_VALUE.out.idxml, -// OPENMS_PSMFEATUREEXTRACTOR.out.idxml, -// peptides_class_1_alleles -// ) -// ch_versions = ch_versions.mix(REFINE_FDR_ON_PREDICTED_SUBSET.out.versions.first().ifEmpty(null)) -// -// // Define the outcome of the paramer to a fixed variable -// filter_q_value = REFINE_FDR_ON_PREDICTED_SUBSET.out.filter_refined_q_value.flatMap { it -> [ tuple(it[0].sample, it[0], it[1]) ] } -// } else { -// // Make sure that the columns that consists of the ID's, sample names and the idXML file names are returned -// filter_q_value = OPENMS_IDFILTER_Q_VALUE.out.idxml.map{ it -> [it[0].sample, it[0], it[1]] } -// } -// -// if ( !params.skip_quantification) { -// // Combining the necessary information into one channel -// OPENMS_IDFILTER_FOR_ALIGNMENT.out[0] -// .join( OPENMS_MAPRTTRANSFORMERMZML.out[0], by: [0] ) -// .map { it -> [it[0].sample, it[0], it[1], it[2]] } -// .combine( filter_q_value , by: [0] ) -// .map { it -> [it[1], it[2], it[3], it[5]] } -// .set{ joined_mzmls_ids_quant } -// // Quantify identifications using targeted feature extraction -// OPENMS_FEATUREFINDERIDENTIFICATION(joined_mzmls_ids_quant) -// ch_versions = ch_versions.mix(OPENMS_FEATUREFINDERIDENTIFICATION.out.versions.first().ifEmpty(null)) -// // Link extracted features -// OPENMS_FEATURELINKERUNLABELEDKD( -// OPENMS_FEATUREFINDERIDENTIFICATION.out.featurexml -// .flatMap { -// meta, raw -> -// [[[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw]] -// } -// .groupTuple(by:[0])) -// ch_versions = ch_versions.mix(OPENMS_FEATURELINKERUNLABELEDKD.out.versions.first().ifEmpty(null)) -// // Resolve conflicting ids matching to the same feature -// OPENMS_IDCONFLICTRESOLVER(OPENMS_FEATURELINKERUNLABELEDKD.out.consensusxml) -// ch_versions = ch_versions.mix(OPENMS_IDCONFLICTRESOLVER.out.versions.first().ifEmpty(null)) -// // Export all information as text to csv -// OPENMS_TEXTEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) -// ch_versions = ch_versions.mix(OPENMS_TEXTEXPORTER.out.versions.first().ifEmpty(null)) -// // Export all information as mzTab -// OPENMS_MZTABEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) -// ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTER.out.versions.first().ifEmpty(null)) -// } -// -// ////////////////////////////////////////////////////////////////////////////////////////////// -// // TODO: Replacement of custom scripts with epytope -// ch_predicted_possible_neoepitopes = Channel.empty() -// if ( params.predict_class_1 & !params.skip_quantification ) { -// // If specified predict peptides using MHCFlurry -// MHCFLURRY_PREDICTPEPTIDESCLASS1( -// OPENMS_MZTABEXPORTER.out.mztab -// .map{ it -> [it[0].sample, it[0], it[1]] } -// .combine( peptides_class_1_alleles, by:0) -// .map( it -> [it[1], it[2], it[3]]) -// ) -// ch_versions = ch_versions.mix(MHCFLURRY_PREDICTPEPTIDESCLASS1.out.versions.first().ifEmpty(null)) -// if ( params.include_proteins_from_vcf ) { -// // Predict all possible neoepitopes from vcf -// PREDICT_POSSIBLE_NEOEPITOPES(peptides_class_1_alleles.join(ch_vcf_from_sheet, by:0, remainder:true)) -// ch_versions = ch_versions.mix(PREDICT_POSSIBLE_NEOEPITOPES.out.versions.first().ifEmpty(null)) -// ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_NEOEPITOPES.out.csv -// // Resolve found neoepitopes -// RESOLVE_FOUND_NEOEPITOPES( -// OPENMS_MZTABEXPORTER.out.mztab -// .map{ it -> [it[0].sample, it[0], it[1]] } -// .combine( ch_predicted_possible_neoepitopes, by:0, remainder:true) -// .map( it -> [it[1], it[2], it[3]]) -// ) -// ch_versions = ch_versions.mix(RESOLVE_FOUND_NEOEPITOPES.out.versions.first().ifEmpty(null)) -// // Predict class 1 neoepitopes MHCFlurry -// MHCFLURRY_PREDICTNEOEPITOPESCLASS1(peptides_class_1_alleles.join(RESOLVE_FOUND_NEOEPITOPES.out.csv, by:0)) -// ch_versions = ch_versions.mix(MHCFLURRY_PREDICTNEOEPITOPESCLASS1.out.versions.first().ifEmpty(null)) -// } -// } -// -// ch_predicted_possible_neoepitopes_II = Channel.empty() -// if ( params.predict_class_2 & !params.skip_quantification ) { -// // Preprocess found peptides for MHCNuggets prediction class 2 -// MHCNUGGETS_PEPTIDESCLASS2PRE(OPENMS_MZTABEXPORTER.out.mztab) -// ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2PRE.out.versions.first().ifEmpty(null)) -// // Predict found peptides using MHCNuggets class 2 -// MHCNUGGETS_PREDICTPEPTIDESCLASS2( -// MHCNUGGETS_PEPTIDESCLASS2PRE.out.preprocessed -// .map{ it -> [it[0].sample, it[0], it[1]] } -// .join(peptides_class_2_alleles, by:0) -// .map( it -> [it[1], it[2], it[3]]) -// ) -// ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.versions.first().ifEmpty(null)) -// // Postprocess predicted MHCNuggets peptides class 2 -// MHCNUGGETS_PEPTIDESCLASS2POST( MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.csv.join(MHCNUGGETS_PEPTIDESCLASS2PRE.out.geneID, by:0) ) -// ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2POST.out.versions.first().ifEmpty(null)) -// -// if ( params.include_proteins_from_vcf ) { -// // Predict all possible class 2 neoepitopes from vcf -// PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES(peptides_class_2_alleles.join(ch_vcf_from_sheet, by:0, remainder:true)) -// ch_versions = ch_versions.mix(PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) -// ch_predicted_possible_neoepitopes_II = PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.csv -// // Resolve found class 2 neoepitopes -// RESOLVE_FOUND_CLASS_2_NEOEPITOPES( -// OPENMS_MZTABEXPORTER.out.mztab -// .map{ it -> [it[0].sample, it[1]] } -// .combine( ch_predicted_possible_neoepitopes_II, by:0, remainder:true) -// ) -// ch_versions = ch_versions.mix(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) -// // Preprocess resolved neoepitopes in a format that MHCNuggets understands -// MHCNUGGETS_NEOEPITOPESCLASS2RE(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv) -// ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2RE.out.versions.first().ifEmpty(null)) -// // Predict class 2 MHCNuggets -// MHCNUGGETS_PREDICTNEOEPITOPESCLASS2(MHCNUGGETS_NEOEPITOPESCLASS2RE.out.preprocessed.join(peptides_class_2_alleles, by:0)) -// ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTNEOEPITOPESCLASS2.out.versions.first().ifEmpty(null)) -// // Class 2 MHCNuggets Postprocessing -// MHCNUGGETS_NEOEPITOPESCLASS2POST(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv.join(PREDICT_NEOEPITOPES_MHCNUGGETS_CLASS_2.out.csv, by:0)) -// ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2POST.out.versions.first().ifEmpty(null)) -// } -// } -// ////////////////////////////////////////////////////////////////////////////////////////////// -// if ( params.predict_RT ) { -// filter_q_value = filter_q_value.map{ it -> [it[1], it[2]] } -// // Train Retention Times Predictor -// OPENMS_RTMODEL(filter_q_value) -// ch_versions = ch_versions.mix(OPENMS_RTMODEL.out.versions.first().ifEmpty(null)) -// // Retention Times Predictor Found Peptides -// OPENMS_RTPREDICT_FOUND_PEPTIDES(filter_q_value.join(OPENMS_RTMODEL.out.complete, by:[0])) -// ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) -// // Retention Times Predictor possible Neoepitopes -// OPENMS_RTPREDICT_NEOEPITOPES(ch_predicted_possible_neoepitopes.mix(ch_predicted_possible_neoepitopes_II).join(OPENMS_RTMODEL.out.complete, by:[0])) -// ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) -// } + if ( params.include_proteins_from_vcf ) { + // Combine the vcf information with the meta information + ch_vcf = input_fasta + .map{ it -> [it[0].sample, it[0], it[1]] } + .join( ch_vcf_from_sheet ) + .map(it -> [it[1], it[2], it[3]]) + // If specified translate variants to proteins and include in reference fasta + GENERATE_PROTEINS_FROM_VCF( ch_vcf ) + ch_versions = ch_versions.mix(GENERATE_PROTEINS_FROM_VCF.out.versions.first().ifEmpty(null)) + ch_fasta_file = GENERATE_PROTEINS_FROM_VCF.out.vcf_fasta + } else { + ch_fasta_file = input_fasta + } + + if (!params.skip_decoy_generation) { + // Generate reversed decoy database + OPENMS_DECOYDATABASE(ch_fasta_file) + ch_versions = ch_versions.mix(OPENMS_DECOYDATABASE.out.versions.first().ifEmpty(null)) + ch_decoy_db = OPENMS_DECOYDATABASE.out.decoy + } else { + ch_decoy_db = ch_fasta_file + } + + // Raw file conversion + OPENMS_THERMORAWFILEPARSER(ms_files.raw) + ch_versions = ch_versions.mix(OPENMS_THERMORAWFILEPARSER.out.versions.first().ifEmpty(null)) + + if ( params.run_centroidisation ) { + // Optional: Run Peak Picking as Preprocessing + OPENMS_PEAKPICKERHIRES(ms_files.mzml) + ch_versions = ch_versions.mix(OPENMS_PEAKPICKERHIRES.out.versions.first().ifEmpty(null)) + ch_mzml_file = OPENMS_PEAKPICKERHIRES.out.mzml + } else { + ch_mzml_file = ms_files.mzml + } + + // Run comet database search + OPENMS_COMETADAPTER( + OPENMS_THERMORAWFILEPARSER.out.mzml + .mix(ch_mzml_file) + .join(ch_decoy_db, remainder:true)) + ch_versions = ch_versions.mix(OPENMS_COMETADAPTER.out.versions.first().ifEmpty(null)) + + // Index decoy and target hits + OPENMS_PEPTIDEINDEXER(OPENMS_COMETADAPTER.out.idxml.join(ch_decoy_db)) + ch_versions = ch_versions.mix(OPENMS_PEPTIDEINDEXER.out.versions.first().ifEmpty(null)) + + if(!params.skip_quantification) { + // Calculate fdr for id based alignment + OPENMS_FALSEDISCOVERYRATE(OPENMS_PEPTIDEINDEXER.out.idxml) + ch_versions = ch_versions.mix(OPENMS_FALSEDISCOVERYRATE.out.versions.first().ifEmpty(null)) + // Filter fdr for id based alignment + OPENMS_IDFILTER_FOR_ALIGNMENT(OPENMS_FALSEDISCOVERYRATE.out.idxml + .flatMap { it -> [tuple(it[0], it[1], null)]}) + ch_versions = ch_versions.mix(OPENMS_IDFILTER_FOR_ALIGNMENT.out.versions.first().ifEmpty(null)) + + ch_grouped_fdr_filtered = OPENMS_IDFILTER_FOR_ALIGNMENT.out.idxml + .map { + meta, raw -> + [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] + } + .groupTuple(by: [0]) + + // Compute alignment rt transformatio + OPENMS_MAPALIGNERIDENTIFICATION(ch_grouped_fdr_filtered) + ch_versions = ch_versions.mix(OPENMS_MAPALIGNERIDENTIFICATION.out.versions.first().ifEmpty(null)) + // Intermediate step to join RT transformation files with mzml and idxml channels + ms_files.mzml + .mix(OPENMS_THERMORAWFILEPARSER.out.mzml) + .mix(ch_mzml_file) + .join( + OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml + .transpose() + .flatMap { + meta, trafoxml -> + ident = trafoxml.baseName.split('_-_')[0] + [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] + }, by: [0] ) + .set { joined_trafos_mzmls } + + OPENMS_PEPTIDEINDEXER.out.idxml + .join( + OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml + .transpose() + .flatMap { + meta, trafoxml -> + ident = trafoxml.baseName.split('_-_')[0] + [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] + }, by: [0] ) + .set { joined_trafos_ids } + + // Align mzML files using trafoXMLs + OPENMS_MAPRTTRANSFORMERMZML(joined_trafos_mzmls) + ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERMZML.out.versions.first().ifEmpty(null)) + // Align unfiltered idXMLfiles using trafoXMLs + OPENMS_MAPRTTRANSFORMERIDXML(joined_trafos_ids) + ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERIDXML.out.versions.first().ifEmpty(null)) + ch_proceeding_idx = OPENMS_MAPRTTRANSFORMERIDXML.out.aligned + .map { + meta, raw -> + [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] + } + .groupTuple(by: [0]) + + } else { + ch_proceeding_idx = OPENMS_PEPTIDEINDEXER.out.idxml + .map { + meta, raw -> + [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] + } + .groupTuple(by: [0]) + } + + // Merge aligned idXMLfiles + OPENMS_IDMERGER(ch_proceeding_idx) + ch_versions = ch_versions.mix(OPENMS_IDMERGER.out.versions.first().ifEmpty(null)) + // Extract PSM features for Percolator + OPENMS_PSMFEATUREEXTRACTOR(OPENMS_IDMERGER.out.idxml) + ch_versions = ch_versions.mix(OPENMS_PSMFEATUREEXTRACTOR.out.versions.first().ifEmpty(null)) + // Run Percolator + if (params.description_correct_features > 0 && params.klammer) { + OPENMS_PERCOLATORADAPTER_KLAMMER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) + ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER_KLAMMER.out.versions.first().ifEmpty(null)) + ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER_KLAMMER.out.idxml + + } else { + OPENMS_PERCOLATORADAPTER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) + ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions.first().ifEmpty(null)) + ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER.out.idxml + } + + // Filter by percolator q-value + OPENMS_IDFILTER_Q_VALUE(ch_percolator_adapter_outcome.flatMap { it -> [tuple(it[0], it[1], null)]}) + ch_versions = ch_versions.mix(OPENMS_IDFILTER_Q_VALUE.out.versions.first().ifEmpty(null)) + + // Refine_fdr_on_predicted_subset + if ( params.refine_fdr_on_predicted_subset && params.predict_class_1 ) { + // Run the following subworkflow + REFINE_FDR_ON_PREDICTED_SUBSET ( + OPENMS_IDFILTER_Q_VALUE.out.idxml, + OPENMS_PSMFEATUREEXTRACTOR.out.idxml, + peptides_class_1_alleles + ) + ch_versions = ch_versions.mix(REFINE_FDR_ON_PREDICTED_SUBSET.out.versions.first().ifEmpty(null)) + + // Define the outcome of the paramer to a fixed variable + filter_q_value = REFINE_FDR_ON_PREDICTED_SUBSET.out.filter_refined_q_value.flatMap { it -> [ tuple(it[0].sample, it[0], it[1]) ] } + } else { + // Make sure that the columns that consists of the ID's, sample names and the idXML file names are returned + filter_q_value = OPENMS_IDFILTER_Q_VALUE.out.idxml.map{ it -> [it[0].sample, it[0], it[1]] } + } + + if ( !params.skip_quantification) { + // Combining the necessary information into one channel + OPENMS_IDFILTER_FOR_ALIGNMENT.out[0] + .join( OPENMS_MAPRTTRANSFORMERMZML.out[0], by: [0] ) + .map { it -> [it[0].sample, it[0], it[1], it[2]] } + .combine( filter_q_value , by: [0] ) + .map { it -> [it[1], it[2], it[3], it[5]] } + .set{ joined_mzmls_ids_quant } + // Quantify identifications using targeted feature extraction + OPENMS_FEATUREFINDERIDENTIFICATION(joined_mzmls_ids_quant) + ch_versions = ch_versions.mix(OPENMS_FEATUREFINDERIDENTIFICATION.out.versions.first().ifEmpty(null)) + // Link extracted features + OPENMS_FEATURELINKERUNLABELEDKD( + OPENMS_FEATUREFINDERIDENTIFICATION.out.featurexml + .flatMap { + meta, raw -> + [[[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw]] + } + .groupTuple(by:[0])) + ch_versions = ch_versions.mix(OPENMS_FEATURELINKERUNLABELEDKD.out.versions.first().ifEmpty(null)) + // Resolve conflicting ids matching to the same feature + OPENMS_IDCONFLICTRESOLVER(OPENMS_FEATURELINKERUNLABELEDKD.out.consensusxml) + ch_versions = ch_versions.mix(OPENMS_IDCONFLICTRESOLVER.out.versions.first().ifEmpty(null)) + // Export all information as text to csv + OPENMS_TEXTEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) + ch_versions = ch_versions.mix(OPENMS_TEXTEXPORTER.out.versions.first().ifEmpty(null)) + // Export all information as mzTab + OPENMS_MZTABEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) + ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTER.out.versions.first().ifEmpty(null)) + } + + ////////////////////////////////////////////////////////////////////////////////////////////// + // TODO: Replacement of custom scripts with epytope + ch_predicted_possible_neoepitopes = Channel.empty() + if ( params.predict_class_1 & !params.skip_quantification ) { + // If specified predict peptides using MHCFlurry + MHCFLURRY_PREDICTPEPTIDESCLASS1( + OPENMS_MZTABEXPORTER.out.mztab + .map{ it -> [it[0].sample, it[0], it[1]] } + .combine( peptides_class_1_alleles, by:0) + .map( it -> [it[1], it[2], it[3]]) + ) + ch_versions = ch_versions.mix(MHCFLURRY_PREDICTPEPTIDESCLASS1.out.versions.first().ifEmpty(null)) + if ( params.include_proteins_from_vcf ) { + // Predict all possible neoepitopes from vcf + PREDICT_POSSIBLE_NEOEPITOPES(peptides_class_1_alleles.join(ch_vcf_from_sheet, by:0, remainder:true)) + ch_versions = ch_versions.mix(PREDICT_POSSIBLE_NEOEPITOPES.out.versions.first().ifEmpty(null)) + ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_NEOEPITOPES.out.csv + // Resolve found neoepitopes + RESOLVE_FOUND_NEOEPITOPES( + OPENMS_MZTABEXPORTER.out.mztab + .map{ it -> [it[0].sample, it[0], it[1]] } + .combine( ch_predicted_possible_neoepitopes, by:0, remainder:true) + .map( it -> [it[1], it[2], it[3]]) + ) + ch_versions = ch_versions.mix(RESOLVE_FOUND_NEOEPITOPES.out.versions.first().ifEmpty(null)) + // Predict class 1 neoepitopes MHCFlurry + MHCFLURRY_PREDICTNEOEPITOPESCLASS1(peptides_class_1_alleles.join(RESOLVE_FOUND_NEOEPITOPES.out.csv, by:0)) + ch_versions = ch_versions.mix(MHCFLURRY_PREDICTNEOEPITOPESCLASS1.out.versions.first().ifEmpty(null)) + } + } + + ch_predicted_possible_neoepitopes_II = Channel.empty() + if ( params.predict_class_2 & !params.skip_quantification ) { + // Preprocess found peptides for MHCNuggets prediction class 2 + MHCNUGGETS_PEPTIDESCLASS2PRE(OPENMS_MZTABEXPORTER.out.mztab) + ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2PRE.out.versions.first().ifEmpty(null)) + // Predict found peptides using MHCNuggets class 2 + MHCNUGGETS_PREDICTPEPTIDESCLASS2( + MHCNUGGETS_PEPTIDESCLASS2PRE.out.preprocessed + .map{ it -> [it[0].sample, it[0], it[1]] } + .join(peptides_class_2_alleles, by:0) + .map( it -> [it[1], it[2], it[3]]) + ) + ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.versions.first().ifEmpty(null)) + // Postprocess predicted MHCNuggets peptides class 2 + MHCNUGGETS_PEPTIDESCLASS2POST( MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.csv.join(MHCNUGGETS_PEPTIDESCLASS2PRE.out.geneID, by:0) ) + ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2POST.out.versions.first().ifEmpty(null)) + + if ( params.include_proteins_from_vcf ) { + // Predict all possible class 2 neoepitopes from vcf + PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES(peptides_class_2_alleles.join(ch_vcf_from_sheet, by:0, remainder:true)) + ch_versions = ch_versions.mix(PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) + ch_predicted_possible_neoepitopes_II = PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.csv + // Resolve found class 2 neoepitopes + RESOLVE_FOUND_CLASS_2_NEOEPITOPES( + OPENMS_MZTABEXPORTER.out.mztab + .map{ it -> [it[0].sample, it[1]] } + .combine( ch_predicted_possible_neoepitopes_II, by:0, remainder:true) + ) + ch_versions = ch_versions.mix(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) + // Preprocess resolved neoepitopes in a format that MHCNuggets understands + MHCNUGGETS_NEOEPITOPESCLASS2PRE(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv) + ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2PRE.out.versions.first().ifEmpty(null)) + // Predict class 2 MHCNuggets + MHCNUGGETS_PREDICTNEOEPITOPESCLASS2(MHCNUGGETS_NEOEPITOPESCLASS2PRE.out.preprocessed.join(peptides_class_2_alleles, by:0)) + ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTNEOEPITOPESCLASS2.out.versions.first().ifEmpty(null)) + // Class 2 MHCNuggets Postprocessing + MHCNUGGETS_NEOEPITOPESCLASS2POST(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv.join(PREDICT_NEOEPITOPES_MHCNUGGETS_CLASS_2.out.csv, by:0)) + ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2POST.out.versions.first().ifEmpty(null)) + } + } + ////////////////////////////////////////////////////////////////////////////////////////////// + if ( params.predict_RT ) { + filter_q_value = filter_q_value.map{ it -> [it[1], it[2]] } + // Train Retention Times Predictor + OPENMS_RTMODEL(filter_q_value) + ch_versions = ch_versions.mix(OPENMS_RTMODEL.out.versions.first().ifEmpty(null)) + // Retention Times Predictor Found Peptides + OPENMS_RTPREDICT_FOUND_PEPTIDES(filter_q_value.join(OPENMS_RTMODEL.out.complete, by:[0])) + ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) + // Retention Times Predictor possible Neoepitopes + OPENMS_RTPREDICT_NEOEPITOPES(ch_predicted_possible_neoepitopes.mix(ch_predicted_possible_neoepitopes_II).join(OPENMS_RTMODEL.out.complete, by:[0])) + ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) + } // // MODULE: Pipeline reporting @@ -488,7 +444,6 @@ workflow MHCQUANT { multiqc_report = MULTIQC.out.report.toList() ch_versions = ch_versions.mix(MULTIQC.out.versions) } - } /* From 3b53033a157aefb606ee6071e8c97175783e0df0 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Tue, 28 Dec 2021 15:36:52 +0100 Subject: [PATCH 03/60] Resolve markdown and editorConfig conflicts as well as inclusion of the right doi --- README.md | 12 +++++++----- conf/modules.config | 18 +++++++----------- docs/usage.md | 7 ++++--- lib/WorkflowMain.groovy | 2 +- .../local/mhcnuggets_neoepitopesclass2post.nf | 4 ++-- .../local/mhcnuggets_neoepitopesclass2pre.nf | 4 ++-- modules/local/mhcnuggets_peptidesclass2post.nf | 4 ++-- modules/local/mhcnuggets_peptidesclass2pre.nf | 4 ++-- modules/local/openms_cometadapter.nf | 6 +++--- .../openms_featurefinderidentification.nf | 2 +- modules/local/openms_thermorawfileparser.nf | 2 +- .../local/resolve_found_class_2_neoepitopes.nf | 2 +- nextflow.config | 6 +++--- nextflow_schema.json | 2 +- .../local/refine_fdr_on_predicted_subset.nf | 2 +- workflows/mhcquant.nf | 9 +++++---- 16 files changed, 43 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 3833be3a..3f42061f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![GitHub Actions CI Status](https://github.com/nf-core/mhcquant/workflows/nf-core%20CI/badge.svg)](https://github.com/nf-core/mhcquant/actions?query=workflow%3A%22nf-core+CI%22) [![GitHub Actions Linting Status](https://github.com/nf-core/mhcquant/workflows/nf-core%20linting/badge.svg)](https://github.com/nf-core/mhcquant/actions?query=workflow%3A%22nf-core+linting%22) [![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/mhcquant/results) -[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.1569910-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.1569910) +[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.1569909-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.1569909) [![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg?labelColor=000000)](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/) @@ -81,6 +81,7 @@ Helpful contributors: - [Christian Fufezan](https://github.com/fu) - [Sven Fillinger](https://github.com/sven1103) - [Kevin Menden](https://github.com/KevinMenden) + ## Contributions and Support If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). @@ -89,12 +90,13 @@ For further information or help, don't hesitate to get in touch on the [Slack `# ## Citations -If you use nf-core/mhcquant for your analysis, please cite it using the following doi: [10.5281/zenodo.1569910](https://doi.org/10.5281/zenodo.1569910) and the corresponding manuscript: +If you use nf-core/mhcquant for your analysis, please cite it using the following doi: [10.5281/zenodo.1569909](https://doi.org/10.5281/zenodo.1569909) and the corresponding manuscript: > **MHCquant: Automated and Reproducible Data Analysis for Immunopeptidomics** > -> Leon Bichmann, Annika Nelde, Michael Ghosh, Lukas Heumos, Christopher Mohr, Alexander Peltzer, Leon Kuchenbecker, Timo Sachsenberg, Juliane S. Walz, Stefan Stevanović, Hans-Georg Rammensee & Oliver Kohlbacher> -> _Journal of Proteome Research_ 2019 18 (11), 3876-3884. doi: [10.1021/acs.jproteome.9b00313](https://pubs.acs.org/doi/10.1021/acs.jproteome.9b00313) +> Leon Bichmann, Annika Nelde, Michael Ghosh, Lukas Heumos, Christopher Mohr, Alexander Peltzer, Leon Kuchenbecker, Timo Sachsenberg, Juliane S. Walz, Stefan Stevanović, Hans-Georg Rammensee & Oliver Kohlbacher +> +> _Journal of Proteome Research_ 2019 18 (11), 3876-3884. doi: [10.1021/acs.jproteome.9b00313](https://pubs.acs.org/doi/10.1021/acs.jproteome.9b00313) An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. @@ -132,4 +134,4 @@ In addition, references of tools and data used in this pipeline are as follows: > > O'Donnell T.J., _Cell Syst._ 2018 Jul 25;7(1):129-132.e4. doi: 10.1016/j.cels.2018.05.014. Epub 2018 Jun 27. > -> Shao X.M., _Cancer Immunol Res._ 2020 Mar;8(3):396-408. doi: 10.1158/2326-6066.CIR-19-0464. Epub 2019 Dec 23. \ No newline at end of file +> Shao X.M., _Cancer Immunol Res._ 2020 Mar;8(3):396-408. doi: 10.1158/2326-6066.CIR-19-0464. Epub 2019 Dec 23. diff --git a/conf/modules.config b/conf/modules.config index 2d02b936..08713916 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -36,7 +36,6 @@ process { } -//TODO: change the setup process { withName: GENERATE_PROTEINS_FROM_VCF { @@ -69,7 +68,7 @@ process { "-max_variable_mods_in_peptide ${params.number_mods}", "-missed_cleavages 0", "-precursor_charge ${params.prec_charge}", - "-activation_method ${params.activation_method}", + "-activation_method ${params.activation_method}", "-variable_modifications ${params.variable_mods.tokenize(',').collect { "'${it}'" }.join(" ") }", "-enzyme '${params.enzyme}'", "-spectrum_batch_size ${params.spectrum_batch_size}" @@ -159,7 +158,7 @@ process { "-testFDR 0.05", "-enzyme no_enzyme", "-subset_max_train ${params.subset_max_train}", - "-doc ${params.description_correct_features} ", + "-doc ${params.description_correct_features} ", (params.fdr_level != 'psm-level-fdrs') ? "-" + params.fdr_level : "" ].join(' ').trim() publishDir = [ @@ -177,8 +176,8 @@ process { "-testFDR 0.05", "-enzyme no_enzyme", "-subset_max_train ${params.subset_max_train}", - "-doc ${params.description_correct_features} ", - (params.fdr_level != 'psm-level-fdrs') ? "-" + params.fdr_level : "", + "-doc ${params.description_correct_features} ", + (params.fdr_level != 'psm-level-fdrs') ? "-" + params.fdr_level : "", "-klammer" ] publishDir = [ @@ -186,7 +185,7 @@ process { mode: 'copy', pattern: '*.idXML' ] - } + } withName: REFINE_FDR_ON_PREDICTED_SUBSET:OPENMS_PERCOLATORADAPTER { ext.suffix = { "perc_subset" } @@ -196,7 +195,7 @@ process { "-testFDR 0.05", "-enzyme no_enzyme", "-subset_max_train ${params.subset_max_train}", - "-doc ${params.description_correct_features} ", + "-doc ${params.description_correct_features} ", (params.fdr_level != 'psm-level-fdrs') ? "-" + params.fdr_level : "" ].join(' ').trim() publishDir = [ @@ -275,7 +274,7 @@ process { pattern: '*_peptides' ] } - + withName: MHCNUGGETS_PREDICTPEPTIDESCLASS2 { publishDir = [ path: { "${params.outdir}/class_2_bindings" }, @@ -339,8 +338,6 @@ process { } process { - - if ( params.predict_RT ) { withName: OPENMS_RTPREDICT_FOUND_PEPTIDES { ext.suffix = { "id_files_for_rt_prediction_RTpredicted" } @@ -359,6 +356,5 @@ process { pattern: '*.csv' ] } - } } \ No newline at end of file diff --git a/docs/usage.md b/docs/usage.md index 46fe3631..11cf718a 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -211,7 +211,7 @@ The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementatio 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: + - For Docker: ```nextflow process { @@ -221,7 +221,7 @@ The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementatio } ``` - * For Singularity: + - For Singularity: ```nextflow process { @@ -231,7 +231,7 @@ The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementatio } ``` - * For Conda: + - For Conda: ```nextflow process { @@ -242,6 +242,7 @@ The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementatio ``` > **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. diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index e98f65c1..84cd43ca 100644 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -10,7 +10,7 @@ class WorkflowMain { public static String citation(workflow) { return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + "* The pipeline\n" + - " https://doi.org/10.5281/zenodo.1569910\n\n" + + " https://doi.org/10.5281/zenodo.1569909\n\n" + "* The nf-core framework\n" + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + "* Software dependencies\n" + diff --git a/modules/local/mhcnuggets_neoepitopesclass2post.nf b/modules/local/mhcnuggets_neoepitopesclass2post.nf index 375d0288..1953cb36 100644 --- a/modules/local/mhcnuggets_neoepitopesclass2post.nf +++ b/modules/local/mhcnuggets_neoepitopesclass2post.nf @@ -4,8 +4,8 @@ process MHCNUGGETS_NEOEPITOPESCLASS2POST { conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : - 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" + 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : + 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" input: tuple val(meta), path(neoepitopes), path(predicted) diff --git a/modules/local/mhcnuggets_neoepitopesclass2pre.nf b/modules/local/mhcnuggets_neoepitopesclass2pre.nf index 6db6aa85..e166725b 100644 --- a/modules/local/mhcnuggets_neoepitopesclass2pre.nf +++ b/modules/local/mhcnuggets_neoepitopesclass2pre.nf @@ -4,8 +4,8 @@ process MHCNUGGETS_NEOEPITOPESCLASS2PRE { conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : - 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" + 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : + 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" input: tuple val(meta), path(neoepitopes) diff --git a/modules/local/mhcnuggets_peptidesclass2post.nf b/modules/local/mhcnuggets_peptidesclass2post.nf index 743433ff..505f6b40 100644 --- a/modules/local/mhcnuggets_peptidesclass2post.nf +++ b/modules/local/mhcnuggets_peptidesclass2post.nf @@ -4,8 +4,8 @@ process MHCNUGGETS_PEPTIDESCLASS2POST { conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : - 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" + 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : + 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" input: tuple val(meta), path(peptides), path(peptide_to_geneID) diff --git a/modules/local/mhcnuggets_peptidesclass2pre.nf b/modules/local/mhcnuggets_peptidesclass2pre.nf index 941f9178..5a8db231 100644 --- a/modules/local/mhcnuggets_peptidesclass2pre.nf +++ b/modules/local/mhcnuggets_peptidesclass2pre.nf @@ -4,8 +4,8 @@ process MHCNUGGETS_PEPTIDESCLASS2PRE { conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : - 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" + 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : + 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" input: tuple val(meta), path(mztab) diff --git a/modules/local/openms_cometadapter.nf b/modules/local/openms_cometadapter.nf index 51340612..a9d369c9 100644 --- a/modules/local/openms_cometadapter.nf +++ b/modules/local/openms_cometadapter.nf @@ -17,7 +17,7 @@ process OPENMS_COMETADAPTER { script: def prefix = task.ext.suffix ? "${mzml.baseName}_${task.ext.suffix}" : "${mzml.baseName}" def args = task.ext.args ?: '' - + def mods = params.fixed_mods != " " ? "-fixed_modifications ${params.fixed_mods.tokenize(',').collect { "'${it}'"}.join(" ")}" : "" def xions = params.use_x_ions ? "-use_X_ions true" : "" def zions = params.use_z_ions ? "-use_Z_ions true" : "" @@ -25,7 +25,7 @@ process OPENMS_COMETADAPTER { def cions = params.use_c_ions ? "-use_C_ions true" : "" def nlions = params.use_NL_ions ? "-use_NL_ions true" : "" def remove_precursor = params.remove_precursor_peak ? "-remove_precursor_peak yes" : "" - + """ CometAdapter -in $mzml \\ -out ${prefix}.idXML \\ @@ -39,7 +39,7 @@ process OPENMS_COMETADAPTER { $cions \\ $nlions \\ $remove_precursor - + cat <<-END_VERSIONS > versions.yml ${task.process}: openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') diff --git a/modules/local/openms_featurefinderidentification.nf b/modules/local/openms_featurefinderidentification.nf index 0ef9bbab..6de5ebd7 100644 --- a/modules/local/openms_featurefinderidentification.nf +++ b/modules/local/openms_featurefinderidentification.nf @@ -27,7 +27,7 @@ process OPENMS_FEATUREFINDERIDENTIFICATION { FeatureFinderIdentification -in $mzml \\ -out ${prefix}.featureXML \\ -threads $task.cpus \\ - ${arguments} + ${arguments} cat <<-END_VERSIONS > versions.yml ${task.process}: diff --git a/modules/local/openms_thermorawfileparser.nf b/modules/local/openms_thermorawfileparser.nf index 2e3ba9cb..38f6f829 100644 --- a/modules/local/openms_thermorawfileparser.nf +++ b/modules/local/openms_thermorawfileparser.nf @@ -21,7 +21,7 @@ process OPENMS_THERMORAWFILEPARSER { ThermoRawFileParser.sh -i=$rawfile \\ -f=2 \\ -b=${prefix}.mzML - + cat <<-END_VERSIONS > versions.yml ${task.process}: thermorawfileparser: \$(ThermoRawFileParser.sh --version) diff --git a/modules/local/resolve_found_class_2_neoepitopes.nf b/modules/local/resolve_found_class_2_neoepitopes.nf index 33b0e8ef..98582f7b 100644 --- a/modules/local/resolve_found_class_2_neoepitopes.nf +++ b/modules/local/resolve_found_class_2_neoepitopes.nf @@ -16,7 +16,7 @@ process RESOLVE_FOUND_CLASS_2_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_found_neoepitopes_class_2" + def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_found_neoepitopes_class_2" """ resolve_neoepitopes.py -n $neoepitopes \\ diff --git a/nextflow.config b/nextflow.config index a0c691b3..dffeafb2 100644 --- a/nextflow.config +++ b/nextflow.config @@ -15,10 +15,10 @@ params { outdir = './results' fasta = "data/*.fasta" - // References + // References genomes = null - // Workflow options + // Workflow options allele_sheet = null include_proteins_from_vcf = false predict_class_1 = false @@ -176,7 +176,7 @@ profiles { } // 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. +// 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 { diff --git a/nextflow_schema.json b/nextflow_schema.json index 3fb0806f..bad36a54 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -455,7 +455,7 @@ "description": "Display help text.", "fa_icon": "fas fa-question-circle", "hidden": true - }, + }, "email_on_fail": { "type": "string", "description": "Email address for completion summary, only when pipeline fails.", diff --git a/subworkflows/local/refine_fdr_on_predicted_subset.nf b/subworkflows/local/refine_fdr_on_predicted_subset.nf index 4a025b07..fe35389d 100644 --- a/subworkflows/local/refine_fdr_on_predicted_subset.nf +++ b/subworkflows/local/refine_fdr_on_predicted_subset.nf @@ -2,7 +2,7 @@ * Perform an additional step where the process are collected * that are called when the paramater "refine_fdr_on_predicted_subset" is provided */ - + include { OPENMS_MZTABEXPORTER as OPENMS_MZTABEXPORTERPERC } from '../../modules/local/openms_mztabexporter' include { OPENMS_MZTABEXPORTER as OPENMS_MZTABEXPORTERPSM } from '../../modules/local/openms_mztabexporter' include { MHCFLURRY_PREDICTPSMS } from '../../modules/local/mhcflurry_predictpsms' diff --git a/workflows/mhcquant.nf b/workflows/mhcquant.nf index e5c9c2e4..f3609e3a 100644 --- a/workflows/mhcquant.nf +++ b/workflows/mhcquant.nf @@ -71,7 +71,7 @@ include { OPENMS_PEAKPICKERHIRES } from include { OPENMS_COMETADAPTER } from '../modules/local/openms_cometadapter' include { OPENMS_PEPTIDEINDEXER } from '../modules/local/openms_peptideindexer' include { OPENMS_FALSEDISCOVERYRATE } from '../modules/local/openms_falsediscoveryrate' -include { +include { OPENMS_IDFILTER as OPENMS_IDFILTER_FOR_ALIGNMENT OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE } from '../modules/local/openms_idfilter' include { OPENMS_MAPALIGNERIDENTIFICATION } from '../modules/local/openms_mapaligneridentification' @@ -82,8 +82,8 @@ include { include { OPENMS_IDMERGER } from '../modules/local/openms_idmerger' include { OPENMS_PSMFEATUREEXTRACTOR } from '../modules/local/openms_psmfeatureextractor' -include { - OPENMS_PERCOLATORADAPTER +include { + OPENMS_PERCOLATORADAPTER OPENMS_PERCOLATORADAPTER as OPENMS_PERCOLATORADAPTER_KLAMMER } from '../modules/local/openms_percolatoradapter' include { REFINE_FDR_ON_PREDICTED_SUBSET } from '../subworkflows/local/refine_fdr_on_predicted_subset' @@ -108,7 +108,7 @@ include { MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 } from include { MHCNUGGETS_NEOEPITOPESCLASS2POST } from '../modules/local/mhcnuggets_neoepitopesclass2post' include { OPENMS_RTMODEL } from '../modules/local/openms_rtmodel' -include { +include { OPENMS_RTPREDICT as OPENMS_RTPREDICT_FOUND_PEPTIDES OPENMS_RTPREDICT as OPENMS_RTPREDICT_NEOEPITOPES} from '../modules/local/openms_rtpredict' @@ -215,6 +215,7 @@ workflow MHCQUANT { // Compute alignment rt transformatio OPENMS_MAPALIGNERIDENTIFICATION(ch_grouped_fdr_filtered) ch_versions = ch_versions.mix(OPENMS_MAPALIGNERIDENTIFICATION.out.versions.first().ifEmpty(null)) + OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml.view() // Intermediate step to join RT transformation files with mzml and idxml channels ms_files.mzml .mix(OPENMS_THERMORAWFILEPARSER.out.mzml) From ceda89ff7943c1f12f99f67f8fc5bdf18cbd2238 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Tue, 28 Dec 2021 15:41:01 +0100 Subject: [PATCH 04/60] Resolve editorConfig issues --- conf/modules.config | 5 +++++ modules/local/mhcnuggets_predictneoepitopesclass2.nf | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 08713916..f1a68a32 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -266,7 +266,9 @@ process { // Peptide prediction (class 2) process { + if ( params.predict_class_2 & !params.skip_quantification ) { + withName: MHCNUGGETS_PEPTIDESCLASS2PRE { publishDir = [ path: { "${params.outdir}/class_2_bindings" }, @@ -293,6 +295,7 @@ process { } if ( params.predict_class_2 & !params.skip_quantification & params.include_proteins_from_vcf ) { + withName: PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES { publishDir = [ path: { "${params.outdir}" }, @@ -338,7 +341,9 @@ process { } process { + if ( params.predict_RT ) { + withName: OPENMS_RTPREDICT_FOUND_PEPTIDES { ext.suffix = { "id_files_for_rt_prediction_RTpredicted" } publishDir = [ diff --git a/modules/local/mhcnuggets_predictneoepitopesclass2.nf b/modules/local/mhcnuggets_predictneoepitopesclass2.nf index caa89781..1b09754a 100644 --- a/modules/local/mhcnuggets_predictneoepitopesclass2.nf +++ b/modules/local/mhcnuggets_predictneoepitopesclass2.nf @@ -4,8 +4,8 @@ process MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 { conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : - 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" + 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : + 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" input: tuple val(meta), path(neoepitopes), val(alleles) From 3992d5f2e0d6877ac1d3a8fd216aa354cc3452d5 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Tue, 28 Dec 2021 15:42:50 +0100 Subject: [PATCH 05/60] Resolve editorConfig issues --- conf/modules.config | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index f1a68a32..4c7edcba 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -224,7 +224,6 @@ process { } } -// Peptide prediction (class 1) process { if ( params.predict_class_1 & !params.skip_quantification ) { @@ -264,7 +263,7 @@ process { } } -// Peptide prediction (class 2) + process { if ( params.predict_class_2 & !params.skip_quantification ) { @@ -343,7 +342,7 @@ process { process { if ( params.predict_RT ) { - + withName: OPENMS_RTPREDICT_FOUND_PEPTIDES { ext.suffix = { "id_files_for_rt_prediction_RTpredicted" } publishDir = [ From 0f0d72aa041a9479b79d85ea0be3aa2990a068c1 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Tue, 28 Dec 2021 15:44:31 +0100 Subject: [PATCH 06/60] Added a new line at the end of the file --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 4c7edcba..a6e65a20 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -361,4 +361,4 @@ process { ] } } -} \ No newline at end of file +} From e98ca286d00600677c8435ea1c36c491fc8d4783 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 29 Dec 2021 11:09:51 +0100 Subject: [PATCH 07/60] Adjusted the output.md and added into to the changelog --- CHANGELOG.md | 15 +++++ docs/output.md | 175 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 178 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fe851e9..9d183fe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # nf-core/mhcquant: Changelog +## v2.1.1 nfcore/mhcquant "Silver Titanium Ostrich" - 2021/mm/dd + +### `Added` + +- Included the newest nf-core template (version 2.2) +- Adjustment of the README, including all contributors + +### `Fixed` + +- Changed parameters in the nextflow_schema.json to be in coherence with the nextflow.config + +### `Dependencies` + +### `Deprecated` + ## v2.1.0 nf-core/mhcquant "Olive Tin Hamster" - 2021/12/09 ### `Added` diff --git a/docs/output.md b/docs/output.md index af413c7b..780c3982 100644 --- a/docs/output.md +++ b/docs/output.md @@ -10,30 +10,181 @@ The directories listed below will be created in the results directory after the 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 +* [General](#general) + * [Quantification](#quantification) + * [Intermediate results](#intermediate-results) +* [VCF](#vcf) +* [Class prediction](#class-prediction) + * [Class (1|2) bindings](#class-12-bindings) +* [Rotation time prediction](#rotation-time-prediction) +* [Workflow reporting and documentation](#workflow-reporting-and-documentation) + * [MultiQC](#multiqc) + * [Pipeline information](#pipeline-information) -### FastQC +## General + +### Quantification + +
    +Output files + +* `*.tsv` : If `--skip_quantification` is not specified. + +
    + +The CSV output file is a table containing all information extracted from a database search throughout the pipeline. See the [OpenMS](https://www.openms.de/) or PSI documentation for more information about [annotated scores and format](https://abibuilder.informatik.uni-tuebingen.de/archive/openms/Documentation/release/latest/html/TOPP_TextExporter.html). + +MAP contains information about the different mzML files that were provided initially + +```bash +#MAP id filename label size +``` + +RUN contains information about the search that was performed on each run + +```bash +#RUN run_id score_type score_direction date_time search_engine_version parameters +``` + +PROTEIN contains information about the protein ids corresponding to the peptides that were detected (No protein inference was performed) + +```bash +#PROTEIN score rank accession protein_description coverage sequence +``` + +UNASSIGNEDPEPTIDE contains information about PSMs that were identified but couldn't be quantified to a precursor feature on MS Level 1 + +```bash +#UNASSIGNEDPEPTIDE rt mz score rank sequence charge aa_before aa_after score_type search_identifier accessions FFId_category feature_id file_origin map_index spectrum_reference COMET:IonFrac COMET:deltCn COMET:deltLCn COMET:lnExpect COMET:lnNumSP COMET:lnRankSP MS:1001491 MS:1001492 MS:1001493 MS:1002252 MS:1002253 MS:1002254 MS:1002255 MS:1002256 MS:1002257 MS:1002258 MS:1002259 num_matched_peptides protein_references target_decoy +``` + +CONSENSUS contains information about precursor features that were identified in multiple runs (eg. run 1-3 in this case) + +```bash +#CONSENSUS rt_cf mz_cf intensity_cf charge_cf width_cf quality_cf rt_0 mz_0 intensity_0 charge_0 width_0 rt_1 mz_1 intensity_1 charge_1 width_1 rt_2 mz_2 intensity_2 charge_2 width_2 rt_3 mz_3 intensity_3 charge_3 width_3 +``` + +PEPTIDE contains information about peptide hits that were identified and correspond to the consensus features described below + +```bash +#PEPTIDE rt mz score rank sequence charge aa_before aa_after score_type search_identifier accessions FFId_category fea +``` + +### Intermediate results + +
    +Output files + +* `Intermediate_Results/` + * `*merged_psm_perc_filtered.mzTab` : If `--refine_fdr_on_predicted_subset` is specified, consists of the hits (filtered by q-value) + * `*.mztab` : mztab file generated by the OpenMS MzTabExporter command, the community standard format for sharing mass spectrometry search results + * `*.featureXML` : If `--skip_quantification` is not specified, then this file is generated by the OpenMS FeatureFinderIdentification command + * `*fdr_filtered.idXML`: If `--skip_quantification` is not specified, then this file is generated by the OpenMS IDFilter command + * `*all_ids_merged_psm_perc*.idXML`: idXML files are generated when `--refine_fdr_on_predicted_subset` is specified + * `*peptide_filtered.idXML`: If `--refine_fdr_on_predicted_subset` is specified, then this file consists of the PSMs prediction outcome + * `*perc_subset.idXML`: If `--refine_fdr_on_predicted_subset` is specified, then this file is the outcome of the second percolator run, generated by the OpenMS PercolatorAdapter + +
    + +This folder contains the intermediate results from various steps of the MHCquant pipeline (e.g. (un)filtered PSMs, aligned mzMLs, features) + +The output mzTab contains many columns annotating the most important information - here are a few outpointed: + +```bash +PEP sequence accession best_search_engine_score[1] retention_time charge mass_to_charge peptide_abundance_study_variable[1] +``` + +Most important to know that in this format we annotated the q-value of each peptide identification in the `best_seach_engine_score[1]` column and peptide quantities in the peptide_abundance_study_variable` columns. +[mzTab](http://www.psidev.info/mztab) is a light-weight format to report mass spectrometry search results. It provides all important information about identified peptide hits and is compatible with the PRIDE Archive - proteomics data repository. + +## VCF + +### Reference fasta + +
    +Output files + +* `*_vcf.fasta`: If `--include_proteins_from_vcf` is specified, then this fasta is created for the respective sample + +
    +The fasta database including mutated proteins used for the database search + +### Neoepitopes + +These CSV files list all of the theoretically possible neoepitope sequences from the variants specified in the vcf and neoepitopes that are found during the mass spectrometry search, independant of binding predictions, respectively + +#### found_neoepitopes + +
    +Output files + +* `class_1_bindings/` + * `*found_neoepitopes_class1.csv`: Generated when `--include_proteins_from_vcf` and `--predict_class_1` are specified + +* `class_2_bindings/` + * `*found_neoepitopes_class2.csv`: Generated when `--include_proteins_from_vcf` and `--predict_class_2` are specified + +
    + +This CSV which lists all neoepitopes that are found during the mass spectrometry search, independant of binding predictions +The format is as follows: + +```bash +peptide sequence geneID +``` + +#### vcf_neoepitopes
    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. +* `class_1_bindings/` + * `*vcf_neoepitopes_class1.csv`: Generated when `--include_proteins_from_vcf` and `--predict_class_1` are specified + +* `class_2_bindings/` + * `*vcf_neoepitopes_class2.csv`: Generated when `--include_proteins_from_vcf` and `--predict_class_2` are specified
    -[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/). +This CSV fils contains all theoretically possible neoepitope sequences from the variants that were specified in the vcf +The format is shown below + +```bash +Sequence Antigen ID Variants +``` -![MultiQC - FastQC sequence counts plot](images/mqc_fastqc_counts.png) +## Class prediction -![MultiQC - FastQC mean quality scores plot](images/mqc_fastqc_quality.png) +### Class (1|2) bindings -![MultiQC - FastQC adapter content plot](images/mqc_fastqc_adapter.png) +
    +Output files + +* `class_1_bindings/` + * `*predicted_peptides_class_1.csv`: If `--predict_class_1` is specified, then this CSV is generated + +* `class_2_bindings/` + * `*predicted_peptides_class_2.csv`: If `--predict_class_2` is specified, then this CSV is generated + +
    -> **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. +This folder containing the binding predictions of all detected class 1 or 2 peptides and all theoretically possible neoepitope sequences +The prediction outputs are comma-separated table (CSV) for each allele, listing each peptide sequence and its corresponding predicted affinity scores: + +```bash +peptide allele prediction prediction_low prediction_high prediction_percentile +``` + +## Rotation time prediction + +
    +Output files + +* `RT_prediction` + * `*id_RTpredicted.csv`: If `--predict_RT` is specified, the rotation time found peptides are provided + * `*txt_RTpredicted.csv`: If `--predict_RT` is specified, the rotation time predicted neoepitopes are provided + +
    ### MultiQC From 13108e336c1a92e2729e897fe36c1368c871ab82 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 29 Dec 2021 15:45:03 +0100 Subject: [PATCH 08/60] remove view and increment modules.config --- conf/modules.config | 200 +++++++++++++++++++++++++++--------------- workflows/mhcquant.nf | 1 - 2 files changed, 127 insertions(+), 74 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index a6e65a20..554e126a 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -50,6 +50,18 @@ process { ] } + withName: OPENMS_DECOYDATABASE { + publishDir = [ enabled: false ] + } + + withName: OPENMS_THERMORAWFILEPARSER { + publishDir = [ enabled: false ] + } + + withName: OPENMS_PEAKPICKERHIRES { + publishDir = [ enabled: false ] + } + withName: OPENMS_MAPALIGNERIDENTIFICATION { ext.args = [ "-model:type linear", @@ -76,6 +88,14 @@ process { publishDir = [ enabled: false ] } + withName: OPENMS_PEPTIDEINDEXER { + publishDir = [ enabled: false ] + } + + withName: OPENMS_FALSEDISCOVERYRATE { + publishDir = [ enabled: false ] + } + withName: OPENMS_IDFILTER_FOR_ALIGNMENT { ext.args = [ "-remove_decoys", @@ -90,18 +110,20 @@ process { ] } - withName: OPENMS_IDFILTER_REFINED { - ext.args = [ - "-remove_decoys", - "-precursor:length '${params.peptide_min_length}:${params.peptide_max_length}'", - "-delete_unreferenced_peptide_hits", - (params.fdr_threshold == '0.01') ? "-score:pep 0.05" : "-score:pep " + params.fdr_threshold - ].join(' ').trim() - publishDir = [ - path: { "${params.outdir}/Intermediate_Results" }, - mode: 'copy', - pattern: '*.idXML' - ] + withName: OPENMS_MAPRTTRANSFORMERMZML { + publishDir = [ enabled: false ] + } + + withName: OPENMS_MAPRTTRANSFORMERIDXML { + publishDir = [ enabled: false ] + } + + withName: OPENMS_IDMERGER { + publishDir = [ enabled: false ] + } + + withName: OPENMS_PSMFEATUREEXTRACTOR { + publishDir = [ enabled: false ] } withName: OPENMS_IDFILTER_Q_VALUE { @@ -119,35 +141,8 @@ process { ] } - withName: OPENMS_IDFILTER_PSMS { - ext.suffix = { "pred_filtered" } - ext.args = [ - "-whitelist:ignore_modifications", - "-whitelist:peptides" - ].join(' ').trim() - publishDir = [ - path: { "${params.outdir}/Intermediate_Results" }, - mode: 'copy', - pattern: '*.idXML' - ] - } - - withName: OPENMS_MZTABEXPORTERPERC { - ext.suffix = { "all_ids_merged_psm_perc_filtered" } - publishDir = [ - path: { "${params.outdir}/Intermediate_Results" }, - mode: 'copy', - pattern: '*.mzTab' - ] - } - - withName: OPENMS_MZTABEXPORTERPSM { - ext.suffix = { "all_ids_merged" } - publishDir = [ - path: { "${params.outdir}/Intermediate_Results" }, - mode: 'copy', - pattern: '*.mzTab' - ] + withName: OPENMS_MZTABEXPORTER { + publishDir = [ enabled: false ] } withName: OPENMS_PERCOLATORADAPTER { @@ -187,43 +182,98 @@ process { ] } - withName: REFINE_FDR_ON_PREDICTED_SUBSET:OPENMS_PERCOLATORADAPTER { - ext.suffix = { "perc_subset" } - ext.args = [ - "-seed 4711", - "-trainFDR 0.05", - "-testFDR 0.05", - "-enzyme no_enzyme", - "-subset_max_train ${params.subset_max_train}", - "-doc ${params.description_correct_features} ", - (params.fdr_level != 'psm-level-fdrs') ? "-" + params.fdr_level : "" - ].join(' ').trim() - publishDir = [ - path: { "${params.outdir}/Intermediate_Results" }, - mode: 'copy', - pattern: '*.idXML' - ] + withName: OPENMS_FEATUREFINDERIDENTIFICATION { + publishDir = [ enabled: false ] } - withName: OPENMS_RTPREDICT_FOUND_PEPTIDES { - ext.suffix = { "id_files_for_rt_prediction_RTpredicted" } - publishDir = [ - path: { "${params.outdir}/RT_prediction" }, - mode: 'copy', - pattern: '*.csv' - ] + withName: OPENMS_FEATURELINKERUNLABELEDKD { + publishDir = [ enabled: false ] } - withName: OPENMS_RTPREDICT_NEOEPITOPES { - ext.suffix = { "txt_file_for_rt_prediction_RTpredicted" } - publishDir = [ - path: { "${params.outdir}/RT_prediction" }, - mode: 'copy', - pattern: '*.csv' - ] + withName: OPENMS_IDCONFLICTRESOLVER { + publishDir = [ enabled: false ] + } + + withName: OPENMS_TEXTEXPORTER { + publishDir = [ enabled: false ] + } +} + + +// Refine on predicted subset +process { + + if ( params.refine_fdr_on_predicted_subset && params.predict_class_1 ) { + withName: OPENMS_MZTABEXPORTERPERC { + ext.suffix = { "all_ids_merged_psm_perc_filtered" } + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.mzTab' + ] + } + + withName: OPENMS_MZTABEXPORTERPSM { + ext.suffix = { "all_ids_merged" } + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.mzTab' + ] + } + + withName: MHCFLURRY_PREDICTPSMS { + publishDir = [ enabled: false ] + } + + withName: REFINE_FDR_ON_PREDICTED_SUBSET:OPENMS_PERCOLATORADAPTER { + ext.suffix = { "perc_subset" } + ext.args = [ + "-seed 4711", + "-trainFDR 0.05", + "-testFDR 0.05", + "-enzyme no_enzyme", + "-subset_max_train ${params.subset_max_train}", + "-doc ${params.description_correct_features} ", + (params.fdr_level != 'psm-level-fdrs') ? "-" + params.fdr_level : "" + ].join(' ').trim() + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } + + withName: OPENMS_IDFILTER_PSMS { + ext.suffix = { "pred_filtered" } + ext.args = [ + "-whitelist:ignore_modifications", + "-whitelist:peptides" + ].join(' ').trim() + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } + + withName: OPENMS_IDFILTER_REFINED { + ext.args = [ + "-remove_decoys", + "-precursor:length '${params.peptide_min_length}:${params.peptide_max_length}'", + "-delete_unreferenced_peptide_hits", + (params.fdr_threshold == '0.01') ? "-score:pep 0.05" : "-score:pep " + params.fdr_threshold + ].join(' ').trim() + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } } } +// Class I prediction process { if ( params.predict_class_1 & !params.skip_quantification ) { @@ -253,7 +303,7 @@ process { ] } - withName: RESOLVE_FOUND_NEOEPITOPES { + withName: MHCFLURRY_PREDICTNEOEPITOPESCLASS1 { publishDir = [ path: {"${params.outdir}/class_1_bindings"}, mode: 'copy', @@ -263,7 +313,7 @@ process { } } - +// Class II prediction process { if ( params.predict_class_2 & !params.skip_quantification ) { @@ -343,6 +393,10 @@ process { if ( params.predict_RT ) { + withName: OPENMS_RTMODEL { + publishDir = [ enabled: false ] + } + withName: OPENMS_RTPREDICT_FOUND_PEPTIDES { ext.suffix = { "id_files_for_rt_prediction_RTpredicted" } publishDir = [ diff --git a/workflows/mhcquant.nf b/workflows/mhcquant.nf index f3609e3a..6b98d652 100644 --- a/workflows/mhcquant.nf +++ b/workflows/mhcquant.nf @@ -215,7 +215,6 @@ workflow MHCQUANT { // Compute alignment rt transformatio OPENMS_MAPALIGNERIDENTIFICATION(ch_grouped_fdr_filtered) ch_versions = ch_versions.mix(OPENMS_MAPALIGNERIDENTIFICATION.out.versions.first().ifEmpty(null)) - OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml.view() // Intermediate step to join RT transformation files with mzml and idxml channels ms_files.mzml .mix(OPENMS_THERMORAWFILEPARSER.out.mzml) From a096777c1affa4eada5649b04768132ba3d16920 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Mon, 3 Jan 2022 11:03:21 +0100 Subject: [PATCH 09/60] Include a publish directory for the exported files --- conf/modules.config | 59 ++++++--------------------------------------- 1 file changed, 8 insertions(+), 51 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 554e126a..9aa2da31 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -50,18 +50,6 @@ process { ] } - withName: OPENMS_DECOYDATABASE { - publishDir = [ enabled: false ] - } - - withName: OPENMS_THERMORAWFILEPARSER { - publishDir = [ enabled: false ] - } - - withName: OPENMS_PEAKPICKERHIRES { - publishDir = [ enabled: false ] - } - withName: OPENMS_MAPALIGNERIDENTIFICATION { ext.args = [ "-model:type linear", @@ -88,14 +76,6 @@ process { publishDir = [ enabled: false ] } - withName: OPENMS_PEPTIDEINDEXER { - publishDir = [ enabled: false ] - } - - withName: OPENMS_FALSEDISCOVERYRATE { - publishDir = [ enabled: false ] - } - withName: OPENMS_IDFILTER_FOR_ALIGNMENT { ext.args = [ "-remove_decoys", @@ -110,22 +90,6 @@ process { ] } - withName: OPENMS_MAPRTTRANSFORMERMZML { - publishDir = [ enabled: false ] - } - - withName: OPENMS_MAPRTTRANSFORMERIDXML { - publishDir = [ enabled: false ] - } - - withName: OPENMS_IDMERGER { - publishDir = [ enabled: false ] - } - - withName: OPENMS_PSMFEATUREEXTRACTOR { - publishDir = [ enabled: false ] - } - withName: OPENMS_IDFILTER_Q_VALUE { ext.suffix = { "filtered" } ext.args = [ @@ -140,11 +104,7 @@ process { pattern: '*.idXML' ] } - - withName: OPENMS_MZTABEXPORTER { - publishDir = [ enabled: false ] - } - + withName: OPENMS_PERCOLATORADAPTER { ext.suffix = { "all_ids_merged_psm_perc" } ext.args = [ @@ -182,21 +142,18 @@ process { ] } - withName: OPENMS_FEATUREFINDERIDENTIFICATION { + withName: 'OPENMS_DECOYDATABASE|OPENMS_THERMORAWFILEPARSER|OPENMS_PEAKPICKERHIRES|OPENMS_PEPTIDEINDEXER|OPENMS_FALSEDISCOVERYRATE|OPENMS_IDMERGER|OPENMS_PSMFEATUREEXTRACTOR|OPENMS_MAPRTTRANSFORMER.*ML|OPENMS_FEATURE.*|OPENMS_IDCONFLICTRESOLVER' { publishDir = [ enabled: false ] } - withName: OPENMS_FEATURELINKERUNLABELEDKD { - publishDir = [ enabled: false ] - } - - withName: OPENMS_IDCONFLICTRESOLVER { - publishDir = [ enabled: false ] + withName: 'OPENMS_.*EXPORTER' { + publishDir = [ + path: { "${params.outdir}/" }, + mode: 'copy', + pattern: '*.idXML' + ] } - withName: OPENMS_TEXTEXPORTER { - publishDir = [ enabled: false ] - } } From 3e3f6c5fc6224c69ad5d7f59f1f8fa091441b9ad Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Mon, 3 Jan 2022 13:09:19 +0100 Subject: [PATCH 10/60] Include the results of the psm feature extractor --- conf/modules.config | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 9aa2da31..799ef200 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -142,7 +142,15 @@ process { ] } - withName: 'OPENMS_DECOYDATABASE|OPENMS_THERMORAWFILEPARSER|OPENMS_PEAKPICKERHIRES|OPENMS_PEPTIDEINDEXER|OPENMS_FALSEDISCOVERYRATE|OPENMS_IDMERGER|OPENMS_PSMFEATUREEXTRACTOR|OPENMS_MAPRTTRANSFORMER.*ML|OPENMS_FEATURE.*|OPENMS_IDCONFLICTRESOLVER' { + withName: OPENMS_PSMFEATUREEXTRACTOR { + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' + ] + } + + withName: 'OPENMS_DECOYDATABASE|OPENMS_THERMORAWFILEPARSER|OPENMS_PEAKPICKERHIRES|OPENMS_PEPTIDEINDEXER|OPENMS_FALSEDISCOVERYRATE|OPENMS_IDMERGER|OPENMS_MAPRTTRANSFORMER.*ML|OPENMS_FEATURE.*|OPENMS_IDCONFLICTRESOLVER' { publishDir = [ enabled: false ] } From f8c1a115fdff500bce80d90bbaf1635b738e4ee5 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Tue, 4 Jan 2022 08:39:14 +0100 Subject: [PATCH 11/60] Alter the pattern to save the outcome of the textexporter to the toplevel position of the results folder --- conf/modules.config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 799ef200..4f4d63e8 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -150,15 +150,15 @@ process { ] } - withName: 'OPENMS_DECOYDATABASE|OPENMS_THERMORAWFILEPARSER|OPENMS_PEAKPICKERHIRES|OPENMS_PEPTIDEINDEXER|OPENMS_FALSEDISCOVERYRATE|OPENMS_IDMERGER|OPENMS_MAPRTTRANSFORMER.*ML|OPENMS_FEATURE.*|OPENMS_IDCONFLICTRESOLVER' { + withName: 'OPENMS_DECOYDATABASE|OPENMS_THERMORAWFILEPARSER|OPENMS_PEAKPICKERHIRES|OPENMS_PEPTIDEINDEXER|OPENMS_FALSEDISCOVERYRATE|OPENMS_IDMERGER|OPENMS_MAPRTTRANSFORMER.*ML|OPENMS_FEATURE.*|OPENMS_IDCONFLICTRESOLVER|OPENMS_MZTABEXPORTER' { publishDir = [ enabled: false ] } - withName: 'OPENMS_.*EXPORTER' { + withName: 'OPENMS_TEXTEXPORTER' { publishDir = [ path: { "${params.outdir}/" }, mode: 'copy', - pattern: '*.idXML' + pattern: '*.tsv' ] } From f35bcd6a2ae14890e35c5bd866da6d94b09e1c71 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:14:16 +0100 Subject: [PATCH 12/60] Include subworkflow for the vcf to protein handling --- subworkflows/local/include_proteins.nf | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 subworkflows/local/include_proteins.nf diff --git a/subworkflows/local/include_proteins.nf b/subworkflows/local/include_proteins.nf new file mode 100644 index 00000000..b47050ee --- /dev/null +++ b/subworkflows/local/include_proteins.nf @@ -0,0 +1,36 @@ +/* + * Perform the necessary steps to make the data uniform for further processing + */ + +include { GENERATE_PROTEINS_FROM_VCF } from '../../modules/local/generate_proteins_from_vcf' + +workflow INCLUDE_PROTEINS { + take: + input_fasta + + main: + ch_versions = Channel.empty() + + // Variant + vcf_sheet = file(params.vcf_sheet, checkIfExists: true) + + Channel.from( vcf_sheet ) + .splitCsv(header: ['Sample', 'VCF_FileName'], sep:'\t', skip: 1) + .map { col -> tuple("${col.Sample}", file("${col.VCF_FileName}"),) } + .set { ch_vcf_from_sheet } + + // Combine the vcf information with the meta information + ch_vcf = input_fasta + .map{ it -> [it[0].sample, it[0], it[1]] } + .combine( ch_vcf_from_sheet, by: 0 ) + .map(it -> [it[1], it[2], it[3]]) + // If specified translate variants to proteins and include in reference fasta + GENERATE_PROTEINS_FROM_VCF( ch_vcf ) + ch_versions = ch_versions.mix(GENERATE_PROTEINS_FROM_VCF.out.versions.first().ifEmpty(null)) + + emit: + // Define the information that is returned by this workflow + versions = ch_versions + ch_vcf_from_sheet = ch_vcf_from_sheet + ch_fasta_file = GENERATE_PROTEINS_FROM_VCF.out.vcf_fasta +} \ No newline at end of file From d09e8eba2ce1f47a3d679525e1fcc019499aa7f7 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:14:42 +0100 Subject: [PATCH 13/60] Include subworkflow for the pre-quantification step --- subworkflows/local/pre_quantification.nf | 94 ++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 subworkflows/local/pre_quantification.nf diff --git a/subworkflows/local/pre_quantification.nf b/subworkflows/local/pre_quantification.nf new file mode 100644 index 00000000..76ef1d63 --- /dev/null +++ b/subworkflows/local/pre_quantification.nf @@ -0,0 +1,94 @@ +/* + * Perform the quantification of the samples when the parameter --skip_quantification is not provided + */ + +include { OPENMS_FALSEDISCOVERYRATE } from '../../modules/local/openms_falsediscoveryrate' +include { OPENMS_IDFILTER as OPENMS_IDFILTER_FOR_ALIGNMENT } from '../../modules/local/openms_idfilter' +include { OPENMS_TEXTEXPORTER as OPENMS_TEXTEXPORTER_PSMS } from '../../modules/local/openms_textexporter' +include { OPENMS_MAPALIGNERIDENTIFICATION } from '../../modules/local/openms_mapaligneridentification' +include { + OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERMZML + OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERIDXML } from '../../modules/local/openms_maprttransformer' + + +workflow PRE_QUANTIFICATION { + take: + indexed_hits + ch_mzml_file + mzml_files + raw_files + + main: + ch_versions = Channel.empty() + // Calculate fdr for id based alignment + OPENMS_FALSEDISCOVERYRATE(indexed_hits) + ch_versions = ch_versions.mix(OPENMS_FALSEDISCOVERYRATE.out.versions.first().ifEmpty(null)) + // Filter fdr for id based alignment + OPENMS_IDFILTER_FOR_ALIGNMENT(OPENMS_FALSEDISCOVERYRATE.out.idxml + .flatMap { it -> [tuple(it[0], it[1], null)]}) + ch_versions = ch_versions.mix(OPENMS_IDFILTER_FOR_ALIGNMENT.out.versions.first().ifEmpty(null)) + // Write the content to a PSMs file + OPENMS_TEXTEXPORTER_PSMS( + OPENMS_IDFILTER_FOR_ALIGNMENT.out.idxml + .flatMap { + meta, idxml -> + ident = idxml.baseName.split('_-_')[1] + [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], idxml]] + } + ) + // Group samples together if they are replicates + ch_grouped_fdr_filtered = OPENMS_IDFILTER_FOR_ALIGNMENT.out.idxml + .map { + meta, raw -> + [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] + } + .groupTuple(by: [0]) + // Compute alignment rt transformatio + OPENMS_MAPALIGNERIDENTIFICATION(ch_grouped_fdr_filtered) + ch_versions = ch_versions.mix(OPENMS_MAPALIGNERIDENTIFICATION.out.versions.first().ifEmpty(null)) + // Intermediate step to join RT transformation files with mzml and idxml channels + //ms_files.mzml + mzml_files + .mix(raw_files) + .mix(ch_mzml_file) + .join( + OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml + .transpose() + .flatMap { + meta, trafoxml -> + ident = trafoxml.baseName.split('_-_')[0] + [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] + }, by: [0] ) + .set { joined_trafos_mzmls } + + indexed_hits + .join( + OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml + .transpose() + .flatMap { + meta, trafoxml -> + ident = trafoxml.baseName.split('_-_')[0] + [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] + }, by: [0] ) + .set { joined_trafos_ids } + // Align mzML files using trafoXMLs + OPENMS_MAPRTTRANSFORMERMZML(joined_trafos_mzmls) + ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERMZML.out.versions.first().ifEmpty(null)) + // Align unfiltered idXMLfiles using trafoXMLs + OPENMS_MAPRTTRANSFORMERIDXML(joined_trafos_ids) + ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERIDXML.out.versions.first().ifEmpty(null)) + ch_proceeding_idx = OPENMS_MAPRTTRANSFORMERIDXML.out.aligned + .map { + meta, raw -> + [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] + } + .groupTuple(by: [0]) + + emit: + // Define the information that is returned by this workflow + versions = ch_versions + ch_proceeding_idx + aligned_mzml = OPENMS_MAPRTTRANSFORMERMZML.out.aligned + psms_outcome = OPENMS_IDFILTER_FOR_ALIGNMENT.out.idxml + +} \ No newline at end of file From e1172076d3af85ebc25248a677bdb0292249385c Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:14:56 +0100 Subject: [PATCH 14/60] Include subworkflow for the post-quantification step --- subworkflows/local/post_quantification.nf | 51 +++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 subworkflows/local/post_quantification.nf diff --git a/subworkflows/local/post_quantification.nf b/subworkflows/local/post_quantification.nf new file mode 100644 index 00000000..fcd10630 --- /dev/null +++ b/subworkflows/local/post_quantification.nf @@ -0,0 +1,51 @@ +/* + * Perform the quantification of the samples when the parameter --skip_quantification is not provided + */ + +include { OPENMS_FEATUREFINDERIDENTIFICATION } from '../../modules/local/openms_featurefinderidentification' +include { OPENMS_FEATURELINKERUNLABELEDKD } from '../../modules/local/openms_featurelinkerunlabeledkd' +include { OPENMS_IDCONFLICTRESOLVER } from '../../modules/local/openms_idconflictresolver' +include { OPENMS_TEXTEXPORTER } from '../../modules/local/openms_textexporter' +include { OPENMS_MZTABEXPORTER } from '../../modules/local/openms_mztabexporter' + +workflow POST_QUANTIFICATION { + take: + psms_outcome + aligned_mzml + filter_q_value + + main: + ch_versions = Channel.empty() + // Combining the necessary information into one channel + psms_outcome + .join( aligned_mzml, by: [0] ) + .map { it -> [it[0].sample, it[0], it[1], it[2]] } + .combine( filter_q_value , by: [0] ) + .map { it -> [it[1], it[2], it[3], it[5]] } + .set{ joined_mzmls_ids_quant } + // Quantify identifications using targeted feature extraction + OPENMS_FEATUREFINDERIDENTIFICATION(joined_mzmls_ids_quant) + ch_versions = ch_versions.mix(OPENMS_FEATUREFINDERIDENTIFICATION.out.versions.first().ifEmpty(null)) + // Link extracted features + OPENMS_FEATURELINKERUNLABELEDKD( + OPENMS_FEATUREFINDERIDENTIFICATION.out.featurexml + .flatMap { + meta, raw -> + [[[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw]] + } + .groupTuple(by:[0])) + ch_versions = ch_versions.mix(OPENMS_FEATURELINKERUNLABELEDKD.out.versions.first().ifEmpty(null)) + // Resolve conflicting ids matching to the same feature + OPENMS_IDCONFLICTRESOLVER(OPENMS_FEATURELINKERUNLABELEDKD.out.consensusxml) + ch_versions = ch_versions.mix(OPENMS_IDCONFLICTRESOLVER.out.versions.first().ifEmpty(null)) + // Export all information as text to csv + OPENMS_TEXTEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) + ch_versions = ch_versions.mix(OPENMS_TEXTEXPORTER.out.versions.first().ifEmpty(null)) + // Export all information as mzTab + OPENMS_MZTABEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) + ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTER.out.versions.first().ifEmpty(null)) + emit: + // Define the information that is returned by this workflow + versions = ch_versions + mztab = OPENMS_MZTABEXPORTER.out.mztab +} \ No newline at end of file From 9bbc36affc839012b7299811648254d012907c00 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:15:37 +0100 Subject: [PATCH 15/60] Create subworkflow for the prediction of class 1 --- subworkflows/local/predict_class1.nf | 50 ++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 subworkflows/local/predict_class1.nf diff --git a/subworkflows/local/predict_class1.nf b/subworkflows/local/predict_class1.nf new file mode 100644 index 00000000..e3687704 --- /dev/null +++ b/subworkflows/local/predict_class1.nf @@ -0,0 +1,50 @@ +/* + * Perform the class 1 prediction when the parameter --predict_class_1 is provided and --skip_quantification is not + */ + +include { MHCFLURRY_PREDICTPEPTIDESCLASS1 } from '../../modules/local/mhcflurry_predictpeptidesclass1' +include { PREDICT_POSSIBLE_NEOEPITOPES } from '../../modules/local/predict_possible_neoepitopes' +include { RESOLVE_FOUND_NEOEPITOPES } from '../../modules/local/resolve_found_neoepitopes' +include { MHCFLURRY_PREDICTNEOEPITOPESCLASS1 } from '../../modules/local/mhcflurry_predictneoepitopesclass1' + +workflow PREDICT_CLASS1 { + take: + mztab + peptides_class_1_alleles + ch_vcf_from_sheet + + main: + ch_versions = Channel.empty() + ch_predicted_possible_neoepitopes = Channel.empty() + + // If specified predict peptides using MHCFlurry + MHCFLURRY_PREDICTPEPTIDESCLASS1( + mztab + .map{ it -> [it[0].sample, it[0], it[1]] } + .combine( peptides_class_1_alleles, by:0) + .map( it -> [it[1], it[2], it[3]]) + ) + ch_versions = ch_versions.mix(MHCFLURRY_PREDICTPEPTIDESCLASS1.out.versions.first().ifEmpty(null)) + if ( params.include_proteins_from_vcf ) { + // Predict all possible neoepitopes from vcf + PREDICT_POSSIBLE_NEOEPITOPES(peptides_class_1_alleles.combine(ch_vcf_from_sheet, by:0)) + ch_versions = ch_versions.mix(PREDICT_POSSIBLE_NEOEPITOPES.out.versions.first().ifEmpty(null)) + ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_NEOEPITOPES.out.csv + // Resolve found neoepitopes + RESOLVE_FOUND_NEOEPITOPES( + mztab + .map{ it -> [it[0].sample, it[0], it[1]] } + .combine( ch_predicted_possible_neoepitopes, by:0) + .map( it -> [it[1], it[2], it[3]]) + ) + ch_versions = ch_versions.mix(RESOLVE_FOUND_NEOEPITOPES.out.versions.first().ifEmpty(null)) + // Predict class 1 neoepitopes MHCFlurry + MHCFLURRY_PREDICTNEOEPITOPESCLASS1(peptides_class_1_alleles.join(RESOLVE_FOUND_NEOEPITOPES.out.csv, by:0)) + ch_versions = ch_versions.mix(MHCFLURRY_PREDICTNEOEPITOPESCLASS1.out.versions.first().ifEmpty(null)) + } + + emit: + // Define the information that is returned by this workflow + versions = ch_versions + ch_predicted_possible_neoepitopes = ch_predicted_possible_neoepitopes +} \ No newline at end of file From 3a943a5a370dfd02fb61b18ff04ec0bbb2e56745 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:15:44 +0100 Subject: [PATCH 16/60] Create subworkflow for the prediction of class 2 --- subworkflows/local/predict_class2.nf | 65 ++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 subworkflows/local/predict_class2.nf diff --git a/subworkflows/local/predict_class2.nf b/subworkflows/local/predict_class2.nf new file mode 100644 index 00000000..e4f4fa9c --- /dev/null +++ b/subworkflows/local/predict_class2.nf @@ -0,0 +1,65 @@ +/* + * Perform the class 2 prediction when the parameter --predict_class_2 is provided and --skip_quantification is not + */ + +include { MHCNUGGETS_PEPTIDESCLASS2PRE } from '../../modules/local/mhcnuggets_peptidesclass2pre' +include { MHCNUGGETS_PREDICTPEPTIDESCLASS2 } from '../../modules/local/mhcnuggets_predictpeptidesclass2' +include { MHCNUGGETS_PEPTIDESCLASS2POST } from '../../modules/local/mhcnuggets_peptidesclass2post' +include { PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES } from '../../modules/local/predict_possible_class_2_neoepitopes' +include { RESOLVE_FOUND_CLASS_2_NEOEPITOPES } from '../../modules/local/resolve_found_class_2_neoepitopes' +include { MHCNUGGETS_NEOEPITOPESCLASS2PRE } from '../../modules/local/mhcnuggets_neoepitopesclass2pre' +include { MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 } from '../../modules/local/mhcnuggets_predictneoepitopesclass2' +include { MHCNUGGETS_NEOEPITOPESCLASS2POST } from '../../modules/local/mhcnuggets_neoepitopesclass2post' + +workflow PREDICT_CLASS2 { + take: + mztab + peptides_class_2_alleles + ch_vcf_from_sheet + + main: + ch_versions = Channel.empty() + ch_predicted_possible_neoepitopes = Channel.empty() + + // Preprocess found peptides for MHCNuggets prediction class 2 + MHCNUGGETS_PEPTIDESCLASS2PRE(mztab) + ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2PRE.out.versions.first().ifEmpty(null)) + // Predict found peptides using MHCNuggets class 2 + MHCNUGGETS_PREDICTPEPTIDESCLASS2( + MHCNUGGETS_PEPTIDESCLASS2PRE.out.preprocessed + .map{ it -> [it[0].sample, it[0], it[1]] } + .join(peptides_class_2_alleles, by:0) + .map( it -> [it[1], it[2], it[3]]) + ) + ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.versions.first().ifEmpty(null)) + // Postprocess predicted MHCNuggets peptides class 2 + MHCNUGGETS_PEPTIDESCLASS2POST( MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.csv.join(MHCNUGGETS_PEPTIDESCLASS2PRE.out.geneID, by:0) ) + ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2POST.out.versions.first().ifEmpty(null)) + if ( params.include_proteins_from_vcf ) { + // Predict all possible class 2 neoepitopes from vcf + PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES(peptides_class_2_alleles.combine(ch_vcf_from_sheet, by:0)) + ch_versions = ch_versions.mix(PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) + ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.csv + // Resolve found class 2 neoepitopes + RESOLVE_FOUND_CLASS_2_NEOEPITOPES( + mztab + .map{ it -> [it[0].sample, it[1]] } + .combine( ch_predicted_possible_neoepitopes, by:0) + ) + ch_versions = ch_versions.mix(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) + // Preprocess resolved neoepitopes in a format that MHCNuggets understands + MHCNUGGETS_NEOEPITOPESCLASS2PRE(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv) + ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2PRE.out.versions.first().ifEmpty(null)) + // Predict class 2 MHCNuggets + MHCNUGGETS_PREDICTNEOEPITOPESCLASS2(MHCNUGGETS_NEOEPITOPESCLASS2PRE.out.preprocessed.join(peptides_class_2_alleles, by:0)) + ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTNEOEPITOPESCLASS2.out.versions.first().ifEmpty(null)) + // Class 2 MHCNuggets Postprocessing + MHCNUGGETS_NEOEPITOPESCLASS2POST(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv.join(MHCNUGGETS_PREDICTNEOEPITOPESCLASS2.out.csv, by:0)) + ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2POST.out.versions.first().ifEmpty(null)) + } + + emit: + // Define the information that is returned by this workflow + versions = ch_versions + ch_predicted_possible_neoepitopes = ch_predicted_possible_neoepitopes +} \ No newline at end of file From 26ac105d6a083c8c77f7d30a3131628e7bb9a14f Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:16:00 +0100 Subject: [PATCH 17/60] Create subworkflow for the prediction of the rt --- subworkflows/local/predict_rt.nf | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 subworkflows/local/predict_rt.nf diff --git a/subworkflows/local/predict_rt.nf b/subworkflows/local/predict_rt.nf new file mode 100644 index 00000000..bcd6d54e --- /dev/null +++ b/subworkflows/local/predict_rt.nf @@ -0,0 +1,33 @@ +/* + * Perform the Retention time prediction when the parameter --predict_RT is provided + */ + +include { OPENMS_RTMODEL } from '../../modules/local/openms_rtmodel' +include { + OPENMS_RTPREDICT as OPENMS_RTPREDICT_FOUND_PEPTIDES + OPENMS_RTPREDICT as OPENMS_RTPREDICT_NEOEPITOPES} from '../../modules/local/openms_rtpredict' + + +workflow PREDICT_RT { + take: + filter_q_value + ch_predicted_possible_neoepitopes + ch_predicted_possible_neoepitopes_II + + main: + ch_versions = Channel.empty() + + // Train Retention Times Predictor + OPENMS_RTMODEL(filter_q_value) + ch_versions = ch_versions.mix(OPENMS_RTMODEL.out.versions.first().ifEmpty(null)) + // Retention Times Predictor Found Peptides + OPENMS_RTPREDICT_FOUND_PEPTIDES(filter_q_value.join(OPENMS_RTMODEL.out.complete, by:[0])) + ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) + // Retention Times Predictor possible Neoepitopes + OPENMS_RTPREDICT_NEOEPITOPES(ch_predicted_possible_neoepitopes.mix(ch_predicted_possible_neoepitopes_II).join(OPENMS_RTMODEL.out.complete, by:[0])) + ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) + + emit: + // Define the information that is returned by this workflow + versions = ch_versions +} \ No newline at end of file From 07558a6e8fb6106ce91698835d7153279a7a673c Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:17:43 +0100 Subject: [PATCH 18/60] include minor changes and rename refine_fdr_on_predicted_subset to refine_fdr --- subworkflows/local/refine_fdr.nf | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 subworkflows/local/refine_fdr.nf diff --git a/subworkflows/local/refine_fdr.nf b/subworkflows/local/refine_fdr.nf new file mode 100644 index 00000000..d630a47e --- /dev/null +++ b/subworkflows/local/refine_fdr.nf @@ -0,0 +1,52 @@ +/* + * Perform an additional step where the process are collected + * that are called when the parameter "refine_fdr" is provided + */ + +include { OPENMS_MZTABEXPORTER as OPENMS_MZTABEXPORTERPERC } from '../../modules/local/openms_mztabexporter' +include { OPENMS_MZTABEXPORTER as OPENMS_MZTABEXPORTERPSM } from '../../modules/local/openms_mztabexporter' +include { MHCFLURRY_PREDICTPSMS } from '../../modules/local/mhcflurry_predictpsms' +include { OPENMS_PERCOLATORADAPTER } from '../../modules/local/openms_percolatoradapter' +include { OPENMS_IDFILTER as OPENMS_IDFILTER_PSMS } from '../../modules/local/openms_idfilter' +include { OPENMS_IDFILTER as OPENMS_IDFILTER_REFINED } from '../../modules/local/openms_idfilter' + +workflow REFINE_FDR { + // Define the input parameters + take: + filtered_perc_output + psm_features + classI_alleles + + main: + ch_versions = Channel.empty() + // Export filtered percolator results as mztab + OPENMS_MZTABEXPORTERPERC( filtered_perc_output ) + ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTERPERC.out.versions) + // Export psm results as mztab + OPENMS_MZTABEXPORTERPSM( psm_features ) + ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTERPSM.out.versions) + // Predict psm results using mhcflurry to shrink search space + MHCFLURRY_PREDICTPSMS( + OPENMS_MZTABEXPORTERPERC.out.mztab + .join( OPENMS_MZTABEXPORTERPSM.out.mztab, by:[0] ) + .map{ it -> [it[0].sample, it[0], it[1], it[2]] } + .combine( classI_alleles, by:0) + .map(it -> [it[1], it[2], it[3], it[4]]) + ) + ch_versions = ch_versions.mix(MHCFLURRY_PREDICTPSMS.out.versions) + + // Filter psm results by shrinked search space + OPENMS_IDFILTER_PSMS(psm_features.combine( MHCFLURRY_PREDICTPSMS.out.idxml, by: [0] )) + ch_versions = ch_versions.mix(OPENMS_IDFILTER_PSMS.out.versions) + // Recompute percolator fdr on shrinked search space + OPENMS_PERCOLATORADAPTER( OPENMS_IDFILTER_PSMS.out.idxml ) + ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions) + // Filter results by refined fdr + OPENMS_IDFILTER_REFINED(OPENMS_PERCOLATORADAPTER.out.idxml.flatMap { it -> [tuple(it[0], it[1], null)]}) + //TODO: does this needs to overwrite the tsv files as well? + ch_versions = ch_versions.mix(OPENMS_IDFILTER_REFINED.out.versions) + emit: + // Define the information that is returned by this workflow + filter_refined_q_value = OPENMS_IDFILTER_REFINED.out.idxml + versions = ch_versions +} From eadbac238b56902816e621a820f2e23d37ecd6f2 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:18:01 +0100 Subject: [PATCH 19/60] include minor changes and rename refine_fdr_on_predicted_subset to refine_fdr --- .../local/refine_fdr_on_predicted_subset.nf | 51 ------------------- 1 file changed, 51 deletions(-) delete mode 100644 subworkflows/local/refine_fdr_on_predicted_subset.nf diff --git a/subworkflows/local/refine_fdr_on_predicted_subset.nf b/subworkflows/local/refine_fdr_on_predicted_subset.nf deleted file mode 100644 index fe35389d..00000000 --- a/subworkflows/local/refine_fdr_on_predicted_subset.nf +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Perform an additional step where the process are collected - * that are called when the paramater "refine_fdr_on_predicted_subset" is provided - */ - -include { OPENMS_MZTABEXPORTER as OPENMS_MZTABEXPORTERPERC } from '../../modules/local/openms_mztabexporter' -include { OPENMS_MZTABEXPORTER as OPENMS_MZTABEXPORTERPSM } from '../../modules/local/openms_mztabexporter' -include { MHCFLURRY_PREDICTPSMS } from '../../modules/local/mhcflurry_predictpsms' -include { OPENMS_PERCOLATORADAPTER } from '../../modules/local/openms_percolatoradapter' -include { OPENMS_IDFILTER as OPENMS_IDFILTER_PSMS } from '../../modules/local/openms_idfilter' -include { OPENMS_IDFILTER as OPENMS_IDFILTER_REFINED } from '../../modules/local/openms_idfilter' - -workflow REFINE_FDR_ON_PREDICTED_SUBSET { - // Define the input parameters - take: - filtered_perc_output - psm_features - classI_alleles - - main: - ch_versions = Channel.empty() - // Export filtered percolator results as mztab - OPENMS_MZTABEXPORTERPERC( filtered_perc_output ) - ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTERPERC.out.versions) - // Export psm results as mztab - OPENMS_MZTABEXPORTERPSM( psm_features ) - ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTERPSM.out.versions) - // Predict psm results using mhcflurry to shrink search space - MHCFLURRY_PREDICTPSMS( - OPENMS_MZTABEXPORTERPERC.out.mztab - .join( OPENMS_MZTABEXPORTERPSM.out.mztab, by:[0] ) - .map{ it -> [it[0].sample, it[0], it[1], it[2]] } - .combine( classI_alleles, by:0) - .map(it -> [it[1], it[2], it[3], it[4]]) - ) - ch_versions = ch_versions.mix(MHCFLURRY_PREDICTPSMS.out.versions) - - // Filter psm results by shrinked search space - OPENMS_IDFILTER_PSMS(psm_features.combine( MHCFLURRY_PREDICTPSMS.out.idxml, by: [0] )) - ch_versions = ch_versions.mix(OPENMS_IDFILTER_PSMS.out.versions) - // Recompute percolator fdr on shrinked search space - OPENMS_PERCOLATORADAPTER( OPENMS_IDFILTER_PSMS.out.idxml ) - ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions) - // Filter results by refined fdr - OPENMS_IDFILTER_REFINED(OPENMS_PERCOLATORADAPTER.out.idxml.flatMap { it -> [tuple(it[0], it[1], null)]}) - ch_versions = ch_versions.mix(OPENMS_IDFILTER_REFINED.out.versions) - emit: - // Define the information that is returned by this workflow - filter_refined_q_value = OPENMS_IDFILTER_REFINED.out.idxml - versions = ch_versions -} From 5da6e1beb2aaaab855c323982317b18f38228559 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:20:12 +0100 Subject: [PATCH 20/60] change output file name (removing duplicated _vcf) --- bin/variants2fasta.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bin/variants2fasta.py b/bin/variants2fasta.py index d564d450..5597f5bb 100755 --- a/bin/variants2fasta.py +++ b/bin/variants2fasta.py @@ -197,17 +197,15 @@ def main(): #generate proteins proteins = generate_proteins_from_transcripts(transcripts) - print(proteins) - #write fasta file - with open(args.output.replace('.fasta','_vcf.fasta'), "w") as f: + with open(args.output, "w") as f: for p in proteins: f.write('>' + str(p.transcript_id) + '|' + str(p.vars) + '_var_' + '\n') f.write(str(p)+ '\n') #concatenate fasta file with fasta reference - op=open(args.output.replace('.fasta','_vcf.fasta')) + op=open(args.output) opr1=op.read() op.close() From 0df5cb5303abab67e04df4cd9358a17ef904daae Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:31:59 +0100 Subject: [PATCH 21/60] Include error messages for both the --allele_sheet and --vcf_sheet when they are not provided --- lib/WorkflowMhcquant.groovy | 53 ++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/lib/WorkflowMhcquant.groovy b/lib/WorkflowMhcquant.groovy index b9450083..3250f203 100644 --- a/lib/WorkflowMhcquant.groovy +++ b/lib/WorkflowMhcquant.groovy @@ -34,46 +34,79 @@ class WorkflowMhcquant { if (params.quantification_fdr) { enabledFDRWarn(log) } - } + // Allele sheet + if ( ( params.predict_class_1 || params.predict_class_2 ) && !params.allele_sheet) { + // If no allele sheet is provided + noAllelesError(log) + System.exit(1) + } + + if ( params.include_proteins_from_vcf && !params.vcf_sheet) { + // If no vcf sheet is provided + noVcfError(log) + System.exit(1) + } + } // // Print a warning when the output directory is undefined // private static void outdirWarn(log) { - log.warn "=============================================================================\n" + + log.warn "======================================================================================================\n" + " Results into \'./results\'.\n" + " If you want to define a result directory, please use the --outdir option" + - "=============================================================================" + "======================================================================================================" } // // Print a warning when the parameter skip_decoy_generation is used // private static void skipDecoyWarn(log) { - log.warn "=============================================================================\n" + + log.warn "================================================================================================\n" + " Be aware: skipping decoy generation will prevent generating variants and subset FDR refinement\n" + " Decoys have to be named with DECOY_ as prefix in your fasta database\n" + - "===================================================================================" + "======================================================================================================" } // // Print a warning when the parameter skip_decoy_generation is used // private static void klammerConflictWarn(log) { - log.warn "=============================================================================\n" + + log.warn "================================================================================================\n" + " Quantification FDR enabled\n" + - "===================================================================================" + "======================================================================================================" } // // Print a warning when the parameter skip_decoy_generation is used // private static void enabledFDRWarn(log) { - log.warn "=============================================================================\n" + - " Klammer was specified, but description of correct features was still 0. Please provide a description of correct features greater than 0.\n" + + log.warn "================================================================================================\n" + + " Klammer was specified, but description of correct features was still 0\n."+ + " Please provide a description of correct features greater than 0.\n" + " Klammer has been turned off!\n" + - "===================================================================================" + "======================================================================================================" + } + + // + // Print an error when the no allele_sheet is provided + // + private static void noAllelesError(log) { + log.error "======================================================================================================\n" + + " --predict_class_1 or --predict_class_2 was used but no allele sheet has been provided. \n" + + " Make sure you have used the '--allele_sheet' option and include an allele sheet.\n" + + "======================================================================================================" + } + + // + // Print an error when there is no vcf_sheet provided + // + private static void noVcfError(log) { + log.error "======================================================================================================\n" + + " --include_proteins_from_vcf was used but no vcf sheet has been provided. \n" + + " Make sure you have used the '--vcf_sheet' option and include an vcf sheet.\n" + + "======================================================================================================" } // From 560af2a277eaae2a033e4c109f839619561783ae Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:35:21 +0100 Subject: [PATCH 22/60] Include parameters in the ext.args for GENERATE_PROTEINS_FROM_VCF, Remove OPENMS_PERCOLATORADAPTER_KLAMMER, include parameter for OPENMS_TEXTEXPORTER, and add OPENMS_TEXTEXPORTER_PSMS --- conf/modules.config | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 4f4d63e8..0240dd2b 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -41,7 +41,10 @@ process { withName: GENERATE_PROTEINS_FROM_VCF { ext.args = [ "-t ${params.variant_annotation_style}", - "-r ${params.variant_reference}" + "-r ${params.variant_reference}", + params.variant_indel_filter ? "-fINDEL" : "", + params.variant_frameshift_filter ? "-fFS" : "", + params.variant_snp_filter ? "-fSNP" : "" ].join(' ').trim() publishDir = [ path: { "${params.outdir}" }, @@ -123,25 +126,6 @@ process { ] } - withName: OPENMS_PERCOLATORADAPTER_KLAMMER { - ext.suffix = { "all_ids_merged_psm_perc" } - ext.args = [ - "-seed 4711", - "-trainFDR 0.05", - "-testFDR 0.05", - "-enzyme no_enzyme", - "-subset_max_train ${params.subset_max_train}", - "-doc ${params.description_correct_features} ", - (params.fdr_level != 'psm-level-fdrs') ? "-" + params.fdr_level : "", - "-klammer" - ] - publishDir = [ - path: { "${params.outdir}/Intermediate_Results" }, - mode: 'copy', - pattern: '*.idXML' - ] - } - withName: OPENMS_PSMFEATUREEXTRACTOR { publishDir = [ path: { "${params.outdir}/Intermediate_Results" }, @@ -155,13 +139,23 @@ process { } withName: 'OPENMS_TEXTEXPORTER' { + ext.args = [ + "-id:add_metavalues 0" + ].join(' ').trim() publishDir = [ path: { "${params.outdir}/" }, mode: 'copy', pattern: '*.tsv' - ] + ] } + withName: 'OPENMS_TEXTEXPORTER_PSMS' { + publishDir = [ + path: { "${params.outdir}/PSMs" }, + mode: 'copy', + pattern: '*.tsv' + ] + } } From b3428dffa28dbabadc53f59da592e342a0e8ac48 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:37:20 +0100 Subject: [PATCH 23/60] adjust the version output and remove the parameters here (provided in args) --- modules/local/generate_proteins_from_vcf.nf | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/modules/local/generate_proteins_from_vcf.nf b/modules/local/generate_proteins_from_vcf.nf index e756eac8..89c151d1 100644 --- a/modules/local/generate_proteins_from_vcf.nf +++ b/modules/local/generate_proteins_from_vcf.nf @@ -12,24 +12,17 @@ process GENERATE_PROTEINS_FROM_VCF { output: tuple val(meta), path("*.fasta"), emit: vcf_fasta - path "*.version.txt" , emit: version + path "versions.yml" , emit: versions script: def prefix = task.ext.suffix ? "${fasta.baseName}_${task.ext.suffix}" : "${fasta.baseName}_added_vcf" def args = task.ext.args ?: '' - def indel = params.variant_indel_filter ? "-fINDEL" : "" - def frameshift = params.variant_frameshift_filter ? "-fFS" : "" - def snp = params.variant_snp_filter ? "-fSNP" : "" - """ variants2fasta.py -v $vcf \\ -f $fasta \\ - -o $meta.sample_${prefix}.fasta \\ - $args \\ - $indel \\ - $frameshift \\ - $snp + -o ${meta.sample}_${prefix}.fasta \\ + $args cat <<-END_VERSIONS > versions.yml "${task.process}": From f4c0061afeac0a0c87b58b8bbf044059796b6407 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:37:55 +0100 Subject: [PATCH 24/60] Change output with .csv extention --- modules/local/mhcnuggets_neoepitopesclass2pre.nf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/local/mhcnuggets_neoepitopesclass2pre.nf b/modules/local/mhcnuggets_neoepitopesclass2pre.nf index e166725b..0f08a551 100644 --- a/modules/local/mhcnuggets_neoepitopesclass2pre.nf +++ b/modules/local/mhcnuggets_neoepitopesclass2pre.nf @@ -11,14 +11,16 @@ process MHCNUGGETS_NEOEPITOPESCLASS2PRE { tuple val(meta), path(neoepitopes) output: - tuple val(meta), path("*${prefix}"), emit: preprocessed + tuple val(meta), path("*.csv") , emit: preprocessed path "versions.yml" , emit: versions script: def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_mhcnuggets_preprocessed" """ - preprocess_neoepitopes_mhcnuggets.py --neoepitopes $neoepitopes --output ${prefix} + preprocess_neoepitopes_mhcnuggets.py \\ + --neoepitopes $neoepitopes \\ + --output ${prefix}.csv cat <<-END_VERSIONS > versions.yml ${task.process}: From 985b734109deac569d18f343f1ba7579d68a395b Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:40:28 +0100 Subject: [PATCH 25/60] change prefix --- modules/local/openms_idfilter.nf | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/local/openms_idfilter.nf b/modules/local/openms_idfilter.nf index 6ca3f798..bb091491 100644 --- a/modules/local/openms_idfilter.nf +++ b/modules/local/openms_idfilter.nf @@ -16,7 +16,10 @@ process OPENMS_IDFILTER { script: def whitelist = "$peptide_filter" - def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}_-_idx_fdr_filtered" + + + + def prefix = task.ext.suffix ? "${meta.id}_-_${idxml.baseName}_${task.ext.suffix}" : "${meta.id}_-_${idxml.baseName}_filtered" def args = task.ext.args ?: '' if (whitelist == "input.2") { From 38d9efc1bda22b142820ade7787f0b3c60114aa5 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:40:48 +0100 Subject: [PATCH 26/60] change prefix --- modules/local/openms_peptideindexer.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/openms_peptideindexer.nf b/modules/local/openms_peptideindexer.nf index 198c777f..33510165 100644 --- a/modules/local/openms_peptideindexer.nf +++ b/modules/local/openms_peptideindexer.nf @@ -15,7 +15,7 @@ process OPENMS_PEPTIDEINDEXER { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${idxml.baseName}_${task.ext.suffix}" : "${idxml.baseName}_idx" + def prefix = task.ext.suffix ? "${idxml.baseName}_${task.ext.suffix}" : "${idxml.baseName}_-_idx" """ PeptideIndexer -in $idxml \\ From 728de77daf5b5e0e92a04b5f90ce2336b0f31b2f Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:41:37 +0100 Subject: [PATCH 27/60] Include if-else statement for the klammer parameter --- modules/local/openms_percolatoradapter.nf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/local/openms_percolatoradapter.nf b/modules/local/openms_percolatoradapter.nf index 69a0c99c..1d4566e7 100644 --- a/modules/local/openms_percolatoradapter.nf +++ b/modules/local/openms_percolatoradapter.nf @@ -17,11 +17,13 @@ process OPENMS_PERCOLATORADAPTER { script: def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}" def args = task.ext.args ?: '' + def klammer = (params.description_correct_features > 0 && params.klammer) ? "-klammer" : "" """ OMP_NUM_THREADS=$task.cpus \\ PercolatorAdapter -in $psm \\ -out ${prefix}.idXML \\ + $klammer \\ $args cat <<-END_VERSIONS > versions.yml From 32a550e0b1f9346201c6aa384f8f6ebc17175a86 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:42:44 +0100 Subject: [PATCH 28/60] Add the args definition --- modules/local/openms_textexporter.nf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/local/openms_textexporter.nf b/modules/local/openms_textexporter.nf index e4312965..09412aa5 100644 --- a/modules/local/openms_textexporter.nf +++ b/modules/local/openms_textexporter.nf @@ -16,14 +16,15 @@ process OPENMS_TEXTEXPORTER { script: def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}" + def args = task.ext.args ?: '' """ TextExporter -in $consensus_resolved \\ -out ${prefix}.tsv \\ -threads $task.cpus \\ -id:add_hit_metavalues 0 \\ - -id:add_metavalues 0 \\ - -id:peptides_only + -id:peptides_only \\ + $args cat <<-END_VERSIONS > versions.yml ${task.process}: From b7281a583cc4915f853e08bf0224a3f9ca737385 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:43:32 +0100 Subject: [PATCH 29/60] Add proper output values to make sure that no errors are returned --- modules/local/predict_possible_class_2_neoepitopes.nf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/predict_possible_class_2_neoepitopes.nf b/modules/local/predict_possible_class_2_neoepitopes.nf index 9668ceb4..f7efb8ca 100644 --- a/modules/local/predict_possible_class_2_neoepitopes.nf +++ b/modules/local/predict_possible_class_2_neoepitopes.nf @@ -11,9 +11,9 @@ process PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES { tuple val(meta), val(alleles), path(vcf) output: - tuple val(meta), path("*.csv") , emit: csv - tuple val(meta), path("${prefix}.txt"), emit: txt - path "versions.yml" , emit: versions + tuple val(meta), path("*.csv"), emit: csv + tuple val(meta), path("*.txt"), emit: txt + path "versions.yml" , emit: versions script: def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_vcf_neoepitopes_class2" From e9d2ea9d17d8dd2ff57906cd365cf3e4a604bcd3 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:43:51 +0100 Subject: [PATCH 30/60] Add proper output values to make sure that no errors are returned --- modules/local/predict_possible_neoepitopes.nf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/predict_possible_neoepitopes.nf b/modules/local/predict_possible_neoepitopes.nf index a799d1e2..0247921b 100644 --- a/modules/local/predict_possible_neoepitopes.nf +++ b/modules/local/predict_possible_neoepitopes.nf @@ -11,9 +11,9 @@ process PREDICT_POSSIBLE_NEOEPITOPES { tuple val(meta), val(alleles), path(vcf) output: - tuple val(meta), path("${prefix}.csv"), emit: csv - tuple val(meta), path("${prefix}.txt"), emit: txt - path "versions.yml" , emit: versions + tuple val(meta), path("*.csv"), emit: csv + tuple val(meta), path("*.txt"), emit: txt + path "versions.yml" , emit: versions script: def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_vcf_neoepitopes_class1" From d8767d0c5f30905afbd7d6818213d8f979576edd Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:44:18 +0100 Subject: [PATCH 31/60] use the proper meta annotation --- modules/local/resolve_found_neoepitopes.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/resolve_found_neoepitopes.nf b/modules/local/resolve_found_neoepitopes.nf index e5a5f2f7..50f4d6f5 100644 --- a/modules/local/resolve_found_neoepitopes.nf +++ b/modules/local/resolve_found_neoepitopes.nf @@ -1,5 +1,5 @@ process RESOLVE_FOUND_NEOEPITOPES { - tag "$meta" + tag "$meta.sample" label 'process_low' conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) @@ -15,7 +15,7 @@ process RESOLVE_FOUND_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_found_neoepitopes_class_1" + def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}" : "${meta.sample}_found_neoepitopes_class_1" """ resolve_neoepitopes.py -n $neoepitopes \\ From 707862ce719a4f81c93e1fd4154bf596bc0e4795 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:46:47 +0100 Subject: [PATCH 32/60] change the container to resolve enviromental issues --- modules/local/mhcnuggets_predictneoepitopesclass2.nf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/local/mhcnuggets_predictneoepitopesclass2.nf b/modules/local/mhcnuggets_predictneoepitopesclass2.nf index 1b09754a..80ac61ee 100644 --- a/modules/local/mhcnuggets_predictneoepitopesclass2.nf +++ b/modules/local/mhcnuggets_predictneoepitopesclass2.nf @@ -2,17 +2,17 @@ process MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 { tag "$meta" label 'process_low' - conda (params.enable_conda ? "bioconda::mhcnuggets=2.3.2" : null) + conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mhcnuggets:2.3.2--py_0' : - 'quay.io/biocontainers/mhcnuggets:2.3.2--py_0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" input: tuple val(meta), path(neoepitopes), val(alleles) output: - tuple val(meta), path("*${prefix}"), emit: csv - path "versions.yml" , emit: versions + tuple val(meta), path("*.csv"), emit: csv + path "versions.yml" , emit: versions script: def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_predicted_neoepitopes_class_2" @@ -20,7 +20,7 @@ process MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 { """ mhcnuggets_predict_peptides.py --peptides $neoepitopes \\ --alleles '$alleles' \\ - --output ${prefix} + --output ${prefix}.csv cat <<-END_VERSIONS > versions.yml ${task.process}: From 00e0ff00721cbba1364ea257e9219b83a24b1d92 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:48:56 +0100 Subject: [PATCH 33/60] Add a pattern for the vcf_sheet --- nextflow_schema.json | 1 + 1 file changed, 1 insertion(+) diff --git a/nextflow_schema.json b/nextflow_schema.json index bad36a54..458c0282 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -206,6 +206,7 @@ }, "vcf_sheet": { "type": "string", + "pattern": "^\\S+\\.tsv$", "description": "Specify a .tsv file containing the information about genomic variants (vcf files < v.4.2) for each sample.", "help_text": "| Sample | VCF_FileName |\n| -------------| :---------------------:|\n| MM15_Melanom | data/MM15_variants.vcf |\n| MM17_Melanom | data/MM17_variants.vcf |" } From 3b9cc3dc9513b8800fff14682b53f77e1adc5c0c Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:49:21 +0100 Subject: [PATCH 34/60] Adjust the workflow to include the subworkflows --- workflows/mhcquant.nf | 324 ++++++++++++------------------------------ 1 file changed, 87 insertions(+), 237 deletions(-) diff --git a/workflows/mhcquant.nf b/workflows/mhcquant.nf index 6b98d652..ea6fe664 100644 --- a/workflows/mhcquant.nf +++ b/workflows/mhcquant.nf @@ -39,15 +39,6 @@ if (params.predict_class_1 || params.predict_class_2) { } } -// Variant -if (params.include_proteins_from_vcf) { - vcf_sheet = file(params.vcf_sheet, checkIfExists: true) - Channel.from( vcf_sheet ) - .splitCsv(header: ['Sample', 'VCF_FileName'], sep:'\t', skip: 1) - .map { col -> tuple("${col.Sample}", file("${col.VCF_FileName}"),) } - .set { ch_vcf_from_sheet } - } - /* ======================================================================================== CONFIG FILES @@ -63,58 +54,33 @@ ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multi ======================================================================================== */ -include { INPUT_CHECK } from '../subworkflows/local/input_check' -include { GENERATE_PROTEINS_FROM_VCF } from '../modules/local/generate_proteins_from_vcf' +// +// MODULE: Loaded from modules/local/ +// include { OPENMS_DECOYDATABASE } from '../modules/local/openms_decoydatabase' include { OPENMS_THERMORAWFILEPARSER } from '../modules/local/openms_thermorawfileparser' include { OPENMS_PEAKPICKERHIRES } from '../modules/local/openms_peakpickerhires' include { OPENMS_COMETADAPTER } from '../modules/local/openms_cometadapter' include { OPENMS_PEPTIDEINDEXER } from '../modules/local/openms_peptideindexer' -include { OPENMS_FALSEDISCOVERYRATE } from '../modules/local/openms_falsediscoveryrate' -include { - OPENMS_IDFILTER as OPENMS_IDFILTER_FOR_ALIGNMENT - OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE } from '../modules/local/openms_idfilter' -include { OPENMS_MAPALIGNERIDENTIFICATION } from '../modules/local/openms_mapaligneridentification' - -include { - OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERMZML - OPENMS_MAPRTTRANSFORMER as OPENMS_MAPRTTRANSFORMERIDXML } from '../modules/local/openms_maprttransformer' - +include { OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE } from '../modules/local/openms_idfilter' include { OPENMS_IDMERGER } from '../modules/local/openms_idmerger' include { OPENMS_PSMFEATUREEXTRACTOR } from '../modules/local/openms_psmfeatureextractor' -include { - OPENMS_PERCOLATORADAPTER - OPENMS_PERCOLATORADAPTER as OPENMS_PERCOLATORADAPTER_KLAMMER } from '../modules/local/openms_percolatoradapter' - -include { REFINE_FDR_ON_PREDICTED_SUBSET } from '../subworkflows/local/refine_fdr_on_predicted_subset' - -include { OPENMS_FEATUREFINDERIDENTIFICATION } from '../modules/local/openms_featurefinderidentification' -include { OPENMS_FEATURELINKERUNLABELEDKD } from '../modules/local/openms_featurelinkerunlabeledkd' -include { OPENMS_IDCONFLICTRESOLVER } from '../modules/local/openms_idconflictresolver' -include { OPENMS_TEXTEXPORTER } from '../modules/local/openms_textexporter' -include { OPENMS_MZTABEXPORTER } from '../modules/local/openms_mztabexporter' - -include { MHCFLURRY_PREDICTPEPTIDESCLASS1 } from '../modules/local/mhcflurry_predictpeptidesclass1' -include { MHCNUGGETS_PEPTIDESCLASS2PRE } from '../modules/local/mhcnuggets_peptidesclass2pre' -include { MHCNUGGETS_PREDICTPEPTIDESCLASS2 } from '../modules/local/mhcnuggets_predictpeptidesclass2' -include { MHCNUGGETS_PEPTIDESCLASS2POST } from '../modules/local/mhcnuggets_peptidesclass2post' -include { PREDICT_POSSIBLE_NEOEPITOPES } from '../modules/local/predict_possible_neoepitopes' -include { PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES } from '../modules/local/predict_possible_class_2_neoepitopes' -include { RESOLVE_FOUND_NEOEPITOPES } from '../modules/local/resolve_found_neoepitopes' -include { RESOLVE_FOUND_CLASS_2_NEOEPITOPES } from '../modules/local/resolve_found_class_2_neoepitopes' -include { MHCFLURRY_PREDICTNEOEPITOPESCLASS1 } from '../modules/local/mhcflurry_predictneoepitopesclass1' -include { MHCNUGGETS_NEOEPITOPESCLASS2PRE } from '../modules/local/mhcnuggets_neoepitopesclass2pre' -include { MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 } from '../modules/local/mhcnuggets_predictneoepitopesclass2' -include { MHCNUGGETS_NEOEPITOPESCLASS2POST } from '../modules/local/mhcnuggets_neoepitopesclass2post' - -include { OPENMS_RTMODEL } from '../modules/local/openms_rtmodel' -include { - OPENMS_RTPREDICT as OPENMS_RTPREDICT_FOUND_PEPTIDES - OPENMS_RTPREDICT as OPENMS_RTPREDICT_NEOEPITOPES} from '../modules/local/openms_rtpredict' - +include { OPENMS_PERCOLATORADAPTER } from '../modules/local/openms_percolatoradapter' include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' include { MULTIQC } from '../modules/nf-core/modules/multiqc/main' +// +// SUBWORKFLOW: Consisting of a mix of local and nf-core/modules +// +include { INPUT_CHECK } from '../subworkflows/local/input_check' +include { INCLUDE_PROTEINS } from '../subworkflows/local/include_proteins' +include { PRE_QUANTIFICATION } from '../subworkflows/local/pre_quantification' +include { REFINE_FDR } from '../subworkflows/local/refine_fdr' +include { POST_QUANTIFICATION } from '../subworkflows/local/post_quantification' +include { PREDICT_CLASS1 } from '../subworkflows/local/predict_class1' +include { PREDICT_CLASS2 } from '../subworkflows/local/predict_class2' +include { PREDICT_RT } from '../subworkflows/local/predict_rt' + //////////////////////////////////////////////////// /* -- RUN MAIN WORKFLOW -- */ //////////////////////////////////////////////////// @@ -122,6 +88,7 @@ workflow MHCQUANT { ch_versions = Channel.empty() + // Subworkflow: preparation_files INPUT_CHECK( params.input ) .reads .set { ch_samples_from_sheet } @@ -138,6 +105,8 @@ workflow MHCQUANT { other : true } .set { ms_files } + // A warning message will be given when the format differs from the '.raw' or '.mzML' extention + ms_files.other.subscribe { row -> log.warn("Unknown format for entry " + row[3] + " in provided sample sheet, line will be ignored."); exit 1 } // Input fasta file Channel.fromPath( params.fasta ) @@ -146,21 +115,15 @@ workflow MHCQUANT { .ifEmpty { exit 1, "params.fasta was empty - no input file supplied" } .set { input_fasta } - // A warning message will be given when the format differs from the '.raw' or '.mzML' extention - ms_files.other.subscribe { row -> log.warn("Unknown format for entry " + row[3] + " in provided sample sheet, line will be ignored."); exit 1 } - if ( params.include_proteins_from_vcf ) { - // Combine the vcf information with the meta information - ch_vcf = input_fasta - .map{ it -> [it[0].sample, it[0], it[1]] } - .join( ch_vcf_from_sheet ) - .map(it -> [it[1], it[2], it[3]]) - // If specified translate variants to proteins and include in reference fasta - GENERATE_PROTEINS_FROM_VCF( ch_vcf ) - ch_versions = ch_versions.mix(GENERATE_PROTEINS_FROM_VCF.out.versions.first().ifEmpty(null)) - ch_fasta_file = GENERATE_PROTEINS_FROM_VCF.out.vcf_fasta + // Include the proteins from the vcf file to the fasta file + INCLUDE_PROTEINS( input_fasta ) + ch_versions = ch_versions.mix(INCLUDE_PROTEINS.out.versions.first().ifEmpty(null)) + ch_fasta_file = INCLUDE_PROTEINS.out.ch_fasta_file + ch_vcf_from_sheet = INCLUDE_PROTEINS.out.ch_vcf_from_sheet } else { ch_fasta_file = input_fasta + ch_vcf_from_sheet = Channel.empty() } if (!params.skip_decoy_generation) { @@ -196,63 +159,18 @@ workflow MHCQUANT { OPENMS_PEPTIDEINDEXER(OPENMS_COMETADAPTER.out.idxml.join(ch_decoy_db)) ch_versions = ch_versions.mix(OPENMS_PEPTIDEINDEXER.out.versions.first().ifEmpty(null)) + // + // SUBWORKFLOW: Pre-process step for the quantification of the data + // if(!params.skip_quantification) { - // Calculate fdr for id based alignment - OPENMS_FALSEDISCOVERYRATE(OPENMS_PEPTIDEINDEXER.out.idxml) - ch_versions = ch_versions.mix(OPENMS_FALSEDISCOVERYRATE.out.versions.first().ifEmpty(null)) - // Filter fdr for id based alignment - OPENMS_IDFILTER_FOR_ALIGNMENT(OPENMS_FALSEDISCOVERYRATE.out.idxml - .flatMap { it -> [tuple(it[0], it[1], null)]}) - ch_versions = ch_versions.mix(OPENMS_IDFILTER_FOR_ALIGNMENT.out.versions.first().ifEmpty(null)) - - ch_grouped_fdr_filtered = OPENMS_IDFILTER_FOR_ALIGNMENT.out.idxml - .map { - meta, raw -> - [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] - } - .groupTuple(by: [0]) - - // Compute alignment rt transformatio - OPENMS_MAPALIGNERIDENTIFICATION(ch_grouped_fdr_filtered) - ch_versions = ch_versions.mix(OPENMS_MAPALIGNERIDENTIFICATION.out.versions.first().ifEmpty(null)) - // Intermediate step to join RT transformation files with mzml and idxml channels - ms_files.mzml - .mix(OPENMS_THERMORAWFILEPARSER.out.mzml) - .mix(ch_mzml_file) - .join( - OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml - .transpose() - .flatMap { - meta, trafoxml -> - ident = trafoxml.baseName.split('_-_')[0] - [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] - }, by: [0] ) - .set { joined_trafos_mzmls } - - OPENMS_PEPTIDEINDEXER.out.idxml - .join( - OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml - .transpose() - .flatMap { - meta, trafoxml -> - ident = trafoxml.baseName.split('_-_')[0] - [[[id:ident, sample:meta.sample, condition:meta.condition, ext:meta.ext], trafoxml]] - }, by: [0] ) - .set { joined_trafos_ids } - - // Align mzML files using trafoXMLs - OPENMS_MAPRTTRANSFORMERMZML(joined_trafos_mzmls) - ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERMZML.out.versions.first().ifEmpty(null)) - // Align unfiltered idXMLfiles using trafoXMLs - OPENMS_MAPRTTRANSFORMERIDXML(joined_trafos_ids) - ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERIDXML.out.versions.first().ifEmpty(null)) - ch_proceeding_idx = OPENMS_MAPRTTRANSFORMERIDXML.out.aligned - .map { - meta, raw -> - [[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw] - } - .groupTuple(by: [0]) - + PRE_QUANTIFICATION( + OPENMS_PEPTIDEINDEXER.out.idxml, + ch_mzml_file, + ms_files.mzml, + OPENMS_THERMORAWFILEPARSER.out.mzml + ) + ch_proceeding_idx = PRE_QUANTIFICATION.out.ch_proceeding_idx + ch_versions = ch_versions.mix(PRE_QUANTIFICATION.out.versions.first().ifEmpty(null)) } else { ch_proceeding_idx = OPENMS_PEPTIDEINDEXER.out.idxml .map { @@ -269,152 +187,84 @@ workflow MHCQUANT { OPENMS_PSMFEATUREEXTRACTOR(OPENMS_IDMERGER.out.idxml) ch_versions = ch_versions.mix(OPENMS_PSMFEATUREEXTRACTOR.out.versions.first().ifEmpty(null)) // Run Percolator - if (params.description_correct_features > 0 && params.klammer) { - OPENMS_PERCOLATORADAPTER_KLAMMER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) - ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER_KLAMMER.out.versions.first().ifEmpty(null)) - ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER_KLAMMER.out.idxml - - } else { - OPENMS_PERCOLATORADAPTER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) - ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions.first().ifEmpty(null)) - ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER.out.idxml - } - + OPENMS_PERCOLATORADAPTER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) + ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions.first().ifEmpty(null)) + ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER.out.idxml + // } // Filter by percolator q-value OPENMS_IDFILTER_Q_VALUE(ch_percolator_adapter_outcome.flatMap { it -> [tuple(it[0], it[1], null)]}) ch_versions = ch_versions.mix(OPENMS_IDFILTER_Q_VALUE.out.versions.first().ifEmpty(null)) - // Refine_fdr_on_predicted_subset + // + // SUBWORKFLOW: Refine the FDR values on the predicted subset + // if ( params.refine_fdr_on_predicted_subset && params.predict_class_1 ) { // Run the following subworkflow - REFINE_FDR_ON_PREDICTED_SUBSET ( + REFINE_FDR ( OPENMS_IDFILTER_Q_VALUE.out.idxml, OPENMS_PSMFEATUREEXTRACTOR.out.idxml, peptides_class_1_alleles ) - ch_versions = ch_versions.mix(REFINE_FDR_ON_PREDICTED_SUBSET.out.versions.first().ifEmpty(null)) - + ch_versions = ch_versions.mix(REFINE_FDR.out.versions.first().ifEmpty(null)) // Define the outcome of the paramer to a fixed variable - filter_q_value = REFINE_FDR_ON_PREDICTED_SUBSET.out.filter_refined_q_value.flatMap { it -> [ tuple(it[0].sample, it[0], it[1]) ] } + filter_q_value = REFINE_FDR.out.filter_refined_q_value.flatMap { it -> [ tuple(it[0].sample, it[0], it[1]) ] } } else { // Make sure that the columns that consists of the ID's, sample names and the idXML file names are returned filter_q_value = OPENMS_IDFILTER_Q_VALUE.out.idxml.map{ it -> [it[0].sample, it[0], it[1]] } } + // + // SUBWORKFLOW: Perform the post quantification step + // if ( !params.skip_quantification) { - // Combining the necessary information into one channel - OPENMS_IDFILTER_FOR_ALIGNMENT.out[0] - .join( OPENMS_MAPRTTRANSFORMERMZML.out[0], by: [0] ) - .map { it -> [it[0].sample, it[0], it[1], it[2]] } - .combine( filter_q_value , by: [0] ) - .map { it -> [it[1], it[2], it[3], it[5]] } - .set{ joined_mzmls_ids_quant } - // Quantify identifications using targeted feature extraction - OPENMS_FEATUREFINDERIDENTIFICATION(joined_mzmls_ids_quant) - ch_versions = ch_versions.mix(OPENMS_FEATUREFINDERIDENTIFICATION.out.versions.first().ifEmpty(null)) - // Link extracted features - OPENMS_FEATURELINKERUNLABELEDKD( - OPENMS_FEATUREFINDERIDENTIFICATION.out.featurexml - .flatMap { - meta, raw -> - [[[id:meta.sample + "_" + meta.condition, sample:meta.sample, condition:meta.condition, ext:meta.ext], raw]] - } - .groupTuple(by:[0])) - ch_versions = ch_versions.mix(OPENMS_FEATURELINKERUNLABELEDKD.out.versions.first().ifEmpty(null)) - // Resolve conflicting ids matching to the same feature - OPENMS_IDCONFLICTRESOLVER(OPENMS_FEATURELINKERUNLABELEDKD.out.consensusxml) - ch_versions = ch_versions.mix(OPENMS_IDCONFLICTRESOLVER.out.versions.first().ifEmpty(null)) - // Export all information as text to csv - OPENMS_TEXTEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) - ch_versions = ch_versions.mix(OPENMS_TEXTEXPORTER.out.versions.first().ifEmpty(null)) - // Export all information as mzTab - OPENMS_MZTABEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) - ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTER.out.versions.first().ifEmpty(null)) + POST_QUANTIFICATION ( + PRE_QUANTIFICATION.out.psms_outcome, + PRE_QUANTIFICATION.out.aligned_mzml, + filter_q_value + ) + ch_versions = ch_versions.mix(POST_QUANTIFICATION.out.versions.first().ifEmpty(null)) } ////////////////////////////////////////////////////////////////////////////////////////////// - // TODO: Replacement of custom scripts with epytope - ch_predicted_possible_neoepitopes = Channel.empty() + // + // SUBWORKFLOW: Predict class I (neoepitopes) + // if ( params.predict_class_1 & !params.skip_quantification ) { - // If specified predict peptides using MHCFlurry - MHCFLURRY_PREDICTPEPTIDESCLASS1( - OPENMS_MZTABEXPORTER.out.mztab - .map{ it -> [it[0].sample, it[0], it[1]] } - .combine( peptides_class_1_alleles, by:0) - .map( it -> [it[1], it[2], it[3]]) - ) - ch_versions = ch_versions.mix(MHCFLURRY_PREDICTPEPTIDESCLASS1.out.versions.first().ifEmpty(null)) - if ( params.include_proteins_from_vcf ) { - // Predict all possible neoepitopes from vcf - PREDICT_POSSIBLE_NEOEPITOPES(peptides_class_1_alleles.join(ch_vcf_from_sheet, by:0, remainder:true)) - ch_versions = ch_versions.mix(PREDICT_POSSIBLE_NEOEPITOPES.out.versions.first().ifEmpty(null)) - ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_NEOEPITOPES.out.csv - // Resolve found neoepitopes - RESOLVE_FOUND_NEOEPITOPES( - OPENMS_MZTABEXPORTER.out.mztab - .map{ it -> [it[0].sample, it[0], it[1]] } - .combine( ch_predicted_possible_neoepitopes, by:0, remainder:true) - .map( it -> [it[1], it[2], it[3]]) - ) - ch_versions = ch_versions.mix(RESOLVE_FOUND_NEOEPITOPES.out.versions.first().ifEmpty(null)) - // Predict class 1 neoepitopes MHCFlurry - MHCFLURRY_PREDICTNEOEPITOPESCLASS1(peptides_class_1_alleles.join(RESOLVE_FOUND_NEOEPITOPES.out.csv, by:0)) - ch_versions = ch_versions.mix(MHCFLURRY_PREDICTNEOEPITOPESCLASS1.out.versions.first().ifEmpty(null)) - } + PREDICT_CLASS1 ( + POST_QUANTIFICATION.out.mztab, + peptides_class_1_alleles, + INCLUDE_PROTEINS.out.ch_vcf_from_sheet + ) + ch_versions = ch_versions.mix(PREDICT_CLASS1.out.versions.first().ifEmpty(null)) + ch_predicted_possible_neoepitopes = PREDICT_CLASS1.out.ch_predicted_possible_neoepitopes + } else { + ch_predicted_possible_neoepitopes = Channel.empty() } - ch_predicted_possible_neoepitopes_II = Channel.empty() + // + // SUBWORKFLOW: Predict class II (neoepitopes) + // if ( params.predict_class_2 & !params.skip_quantification ) { - // Preprocess found peptides for MHCNuggets prediction class 2 - MHCNUGGETS_PEPTIDESCLASS2PRE(OPENMS_MZTABEXPORTER.out.mztab) - ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2PRE.out.versions.first().ifEmpty(null)) - // Predict found peptides using MHCNuggets class 2 - MHCNUGGETS_PREDICTPEPTIDESCLASS2( - MHCNUGGETS_PEPTIDESCLASS2PRE.out.preprocessed - .map{ it -> [it[0].sample, it[0], it[1]] } - .join(peptides_class_2_alleles, by:0) - .map( it -> [it[1], it[2], it[3]]) + PREDICT_CLASS2 ( + POST_QUANTIFICATION.out.mztab, + peptides_class_2_alleles, + INCLUDE_PROTEINS.out.ch_vcf_from_sheet ) - ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.versions.first().ifEmpty(null)) - // Postprocess predicted MHCNuggets peptides class 2 - MHCNUGGETS_PEPTIDESCLASS2POST( MHCNUGGETS_PREDICTPEPTIDESCLASS2.out.csv.join(MHCNUGGETS_PEPTIDESCLASS2PRE.out.geneID, by:0) ) - ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2POST.out.versions.first().ifEmpty(null)) - - if ( params.include_proteins_from_vcf ) { - // Predict all possible class 2 neoepitopes from vcf - PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES(peptides_class_2_alleles.join(ch_vcf_from_sheet, by:0, remainder:true)) - ch_versions = ch_versions.mix(PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) - ch_predicted_possible_neoepitopes_II = PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.csv - // Resolve found class 2 neoepitopes - RESOLVE_FOUND_CLASS_2_NEOEPITOPES( - OPENMS_MZTABEXPORTER.out.mztab - .map{ it -> [it[0].sample, it[1]] } - .combine( ch_predicted_possible_neoepitopes_II, by:0, remainder:true) - ) - ch_versions = ch_versions.mix(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) - // Preprocess resolved neoepitopes in a format that MHCNuggets understands - MHCNUGGETS_NEOEPITOPESCLASS2PRE(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv) - ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2PRE.out.versions.first().ifEmpty(null)) - // Predict class 2 MHCNuggets - MHCNUGGETS_PREDICTNEOEPITOPESCLASS2(MHCNUGGETS_NEOEPITOPESCLASS2PRE.out.preprocessed.join(peptides_class_2_alleles, by:0)) - ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTNEOEPITOPESCLASS2.out.versions.first().ifEmpty(null)) - // Class 2 MHCNuggets Postprocessing - MHCNUGGETS_NEOEPITOPESCLASS2POST(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv.join(PREDICT_NEOEPITOPES_MHCNUGGETS_CLASS_2.out.csv, by:0)) - ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2POST.out.versions.first().ifEmpty(null)) - } + ch_versions = ch_versions.mix(PREDICT_CLASS2.out.versions.first().ifEmpty(null)) + ch_predicted_possible_neoepitopes_II = PREDICT_CLASS2.out.ch_predicted_possible_neoepitopes + } else { + ch_predicted_possible_neoepitopes_II = Channel.empty() } ////////////////////////////////////////////////////////////////////////////////////////////// + // + // SUBWORKFLOW: Predict retention time + // if ( params.predict_RT ) { - filter_q_value = filter_q_value.map{ it -> [it[1], it[2]] } - // Train Retention Times Predictor - OPENMS_RTMODEL(filter_q_value) - ch_versions = ch_versions.mix(OPENMS_RTMODEL.out.versions.first().ifEmpty(null)) - // Retention Times Predictor Found Peptides - OPENMS_RTPREDICT_FOUND_PEPTIDES(filter_q_value.join(OPENMS_RTMODEL.out.complete, by:[0])) - ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) - // Retention Times Predictor possible Neoepitopes - OPENMS_RTPREDICT_NEOEPITOPES(ch_predicted_possible_neoepitopes.mix(ch_predicted_possible_neoepitopes_II).join(OPENMS_RTMODEL.out.complete, by:[0])) - ch_versions = ch_versions.mix(OPENMS_RTPREDICT_FOUND_PEPTIDES.out.versions.first().ifEmpty(null)) + PREDICT_RT ( + filter_q_value.map{ it -> [it[1], it[2]] }, + ch_predicted_possible_neoepitopes, + ch_predicted_possible_neoepitopes_II + ) } // From c29f14430fbec01564a0caa3e5f7ce25a6fc41ce Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:50:39 +0100 Subject: [PATCH 35/60] Clean up file --- modules/local/openms_idfilter.nf | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/local/openms_idfilter.nf b/modules/local/openms_idfilter.nf index bb091491..82b7d1d6 100644 --- a/modules/local/openms_idfilter.nf +++ b/modules/local/openms_idfilter.nf @@ -16,9 +16,6 @@ process OPENMS_IDFILTER { script: def whitelist = "$peptide_filter" - - - def prefix = task.ext.suffix ? "${meta.id}_-_${idxml.baseName}_${task.ext.suffix}" : "${meta.id}_-_${idxml.baseName}_filtered" def args = task.ext.args ?: '' From 3b208d733d08193a93fe235b1770f6ca98e4c1ba Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:57:40 +0100 Subject: [PATCH 36/60] minor changes to clarify the input --- nextflow_schema.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nextflow_schema.json b/nextflow_schema.json index 458c0282..4ffb8977 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -53,6 +53,7 @@ "fasta": { "type": "string", "fa_icon": "fas fa-dna", + "pattern": ".fasta$", "description": "Input FASTA protein database", "help_text": "If you have no genome reference available, the pipeline can build one using a FASTA file. This requires additional time and resources, so it's better to use a pre-build index if possible." }, @@ -114,6 +115,7 @@ }, "fragment_bin_offset": { "type": "integer", + "default": 0, "description": "Specify the fragment bin offset used for the comet database search.", "help_text": "For High-Resolution instruments a fragment bin offset of 0 is recommended. (See the Comet parameter documentation: eg. 0)" }, @@ -288,6 +290,7 @@ "properties": { "allele_sheet": { "type": "string", + "pattern": "^\\S+\\.tsv$", "description": "Specify a .tsv file containing the MHC alleles of your probes as well as their metadata such as SampleID.", "help_text": "| Sample | HLA_Alleles_Class_1 | HLA_Alleles_Class_2 |\n| -------------| :----------------------------------------------:| ------------------------------------------:|\n| MM15_Melanom | A* 03:01;A* 68:01;B* 27:05;B* 35:03;C* 02:02;C* 04:01 |HLA-DRB1* 01:01;HLA-DQB1* 03:19;HLA-DQA1* 05:01|\n| MM17_Melanom | A* 02:01;B* 07:01;B* 26:01;C* 11:01;C* 01:01 |HLA-DRB1* 01:02;HLA-DRB3* 02:02;HLA-DRB4* 01:03|\n" }, From c598506d77aaa122d8d8fa77289ec83af5a30290 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 17:58:46 +0100 Subject: [PATCH 37/60] Incremented the CHANGELOG --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d183fe1..0198bdfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,20 @@ # nf-core/mhcquant: Changelog -## v2.1.1 nfcore/mhcquant "Silver Titanium Ostrich" - 2021/mm/dd +## v2.2 nfcore/mhcquant "Silver Titanium Ostrich" - 2021/mm/dd ### `Added` - Included the newest nf-core template (version 2.2) - Adjustment of the README, including all contributors +- Inclusion of the PSMs files (tsv format) per replicates in `results/PSMs` +- Include check in WorkflowMhcquant, to determine if the allele and vcf sheet has been provided under specific circumstances ### `Fixed` - Changed parameters in the nextflow_schema.json to be in coherence with the nextflow.config +- Error that was raised in generate_proteins_from_vcf +- Problems that were detected in predict_possible_neoepitopes and predict_possible_class_2_neoepitopes +- Error that occured in mhcnuggets_predictneoepitopesclass2 (faulty container set up) ### `Dependencies` From 4605f7ac40abe59f4d87fb97e24420a85a141477 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 18:00:24 +0100 Subject: [PATCH 38/60] Incremented the CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0198bdfb..b09ae8b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # nf-core/mhcquant: Changelog -## v2.2 nfcore/mhcquant "Silver Titanium Ostrich" - 2021/mm/dd +## v2.2.0 nfcore/mhcquant "Silver Titanium Ostrich" - 2021/mm/dd ### `Added` From eca0827c9e061ee991100047e7a67d2b33b2d7ba Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 18:09:25 +0100 Subject: [PATCH 39/60] Resolve issues EditorConfig --- conf/modules.config | 10 +++++----- lib/WorkflowMhcquant.groovy | 2 +- modules/local/generate_proteins_from_vcf.nf | 2 +- subworkflows/local/include_proteins.nf | 4 ++-- subworkflows/local/post_quantification.nf | 2 +- subworkflows/local/pre_quantification.nf | 5 ++--- subworkflows/local/predict_class1.nf | 6 +++--- subworkflows/local/predict_class2.nf | 6 +++--- subworkflows/local/predict_rt.nf | 6 +++--- workflows/mhcquant.nf | 10 +++++----- 10 files changed, 26 insertions(+), 27 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 0240dd2b..fd4fcce2 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -107,7 +107,7 @@ process { pattern: '*.idXML' ] } - + withName: OPENMS_PERCOLATORADAPTER { ext.suffix = { "all_ids_merged_psm_perc" } ext.args = [ @@ -127,10 +127,10 @@ process { } withName: OPENMS_PSMFEATUREEXTRACTOR { - publishDir = [ - path: { "${params.outdir}/Intermediate_Results" }, - mode: 'copy', - pattern: '*.idXML' + publishDir = [ + path: { "${params.outdir}/Intermediate_Results" }, + mode: 'copy', + pattern: '*.idXML' ] } diff --git a/lib/WorkflowMhcquant.groovy b/lib/WorkflowMhcquant.groovy index 3250f203..10d5fc98 100644 --- a/lib/WorkflowMhcquant.groovy +++ b/lib/WorkflowMhcquant.groovy @@ -83,7 +83,7 @@ class WorkflowMhcquant { // private static void enabledFDRWarn(log) { log.warn "================================================================================================\n" + - " Klammer was specified, but description of correct features was still 0\n."+ + " Klammer was specified, but description of correct features was still 0\n."+ " Please provide a description of correct features greater than 0.\n" + " Klammer has been turned off!\n" + "======================================================================================================" diff --git a/modules/local/generate_proteins_from_vcf.nf b/modules/local/generate_proteins_from_vcf.nf index 89c151d1..5874e60c 100644 --- a/modules/local/generate_proteins_from_vcf.nf +++ b/modules/local/generate_proteins_from_vcf.nf @@ -22,7 +22,7 @@ process GENERATE_PROTEINS_FROM_VCF { variants2fasta.py -v $vcf \\ -f $fasta \\ -o ${meta.sample}_${prefix}.fasta \\ - $args + $args cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/subworkflows/local/include_proteins.nf b/subworkflows/local/include_proteins.nf index b47050ee..3235cc9c 100644 --- a/subworkflows/local/include_proteins.nf +++ b/subworkflows/local/include_proteins.nf @@ -7,7 +7,7 @@ include { GENERATE_PROTEINS_FROM_VCF } from workflow INCLUDE_PROTEINS { take: input_fasta - + main: ch_versions = Channel.empty() @@ -33,4 +33,4 @@ workflow INCLUDE_PROTEINS { versions = ch_versions ch_vcf_from_sheet = ch_vcf_from_sheet ch_fasta_file = GENERATE_PROTEINS_FROM_VCF.out.vcf_fasta -} \ No newline at end of file +} diff --git a/subworkflows/local/post_quantification.nf b/subworkflows/local/post_quantification.nf index fcd10630..d59c03f9 100644 --- a/subworkflows/local/post_quantification.nf +++ b/subworkflows/local/post_quantification.nf @@ -48,4 +48,4 @@ workflow POST_QUANTIFICATION { // Define the information that is returned by this workflow versions = ch_versions mztab = OPENMS_MZTABEXPORTER.out.mztab -} \ No newline at end of file +} diff --git a/subworkflows/local/pre_quantification.nf b/subworkflows/local/pre_quantification.nf index 76ef1d63..7c44d85d 100644 --- a/subworkflows/local/pre_quantification.nf +++ b/subworkflows/local/pre_quantification.nf @@ -17,7 +17,7 @@ workflow PRE_QUANTIFICATION { ch_mzml_file mzml_files raw_files - + main: ch_versions = Channel.empty() // Calculate fdr for id based alignment @@ -90,5 +90,4 @@ workflow PRE_QUANTIFICATION { ch_proceeding_idx aligned_mzml = OPENMS_MAPRTTRANSFORMERMZML.out.aligned psms_outcome = OPENMS_IDFILTER_FOR_ALIGNMENT.out.idxml - -} \ No newline at end of file +} diff --git a/subworkflows/local/predict_class1.nf b/subworkflows/local/predict_class1.nf index e3687704..a2764285 100644 --- a/subworkflows/local/predict_class1.nf +++ b/subworkflows/local/predict_class1.nf @@ -12,11 +12,11 @@ workflow PREDICT_CLASS1 { mztab peptides_class_1_alleles ch_vcf_from_sheet - + main: ch_versions = Channel.empty() ch_predicted_possible_neoepitopes = Channel.empty() - + // If specified predict peptides using MHCFlurry MHCFLURRY_PREDICTPEPTIDESCLASS1( mztab @@ -47,4 +47,4 @@ workflow PREDICT_CLASS1 { // Define the information that is returned by this workflow versions = ch_versions ch_predicted_possible_neoepitopes = ch_predicted_possible_neoepitopes -} \ No newline at end of file +} diff --git a/subworkflows/local/predict_class2.nf b/subworkflows/local/predict_class2.nf index e4f4fa9c..93efc72a 100644 --- a/subworkflows/local/predict_class2.nf +++ b/subworkflows/local/predict_class2.nf @@ -16,10 +16,10 @@ workflow PREDICT_CLASS2 { mztab peptides_class_2_alleles ch_vcf_from_sheet - + main: ch_versions = Channel.empty() - ch_predicted_possible_neoepitopes = Channel.empty() + ch_predicted_possible_neoepitopes = Channel.empty() // Preprocess found peptides for MHCNuggets prediction class 2 MHCNUGGETS_PEPTIDESCLASS2PRE(mztab) @@ -62,4 +62,4 @@ workflow PREDICT_CLASS2 { // Define the information that is returned by this workflow versions = ch_versions ch_predicted_possible_neoepitopes = ch_predicted_possible_neoepitopes -} \ No newline at end of file +} diff --git a/subworkflows/local/predict_rt.nf b/subworkflows/local/predict_rt.nf index bcd6d54e..894eddf9 100644 --- a/subworkflows/local/predict_rt.nf +++ b/subworkflows/local/predict_rt.nf @@ -1,5 +1,5 @@ /* - * Perform the Retention time prediction when the parameter --predict_RT is provided + * Perform the Retention time prediction when the parameter --predict_RT is provided */ include { OPENMS_RTMODEL } from '../../modules/local/openms_rtmodel' @@ -13,7 +13,7 @@ workflow PREDICT_RT { filter_q_value ch_predicted_possible_neoepitopes ch_predicted_possible_neoepitopes_II - + main: ch_versions = Channel.empty() @@ -30,4 +30,4 @@ workflow PREDICT_RT { emit: // Define the information that is returned by this workflow versions = ch_versions -} \ No newline at end of file +} diff --git a/workflows/mhcquant.nf b/workflows/mhcquant.nf index ea6fe664..5d7b7015 100644 --- a/workflows/mhcquant.nf +++ b/workflows/mhcquant.nf @@ -233,7 +233,7 @@ workflow MHCQUANT { PREDICT_CLASS1 ( POST_QUANTIFICATION.out.mztab, peptides_class_1_alleles, - INCLUDE_PROTEINS.out.ch_vcf_from_sheet + ch_vcf_from_sheet ) ch_versions = ch_versions.mix(PREDICT_CLASS1.out.versions.first().ifEmpty(null)) ch_predicted_possible_neoepitopes = PREDICT_CLASS1.out.ch_predicted_possible_neoepitopes @@ -248,20 +248,20 @@ workflow MHCQUANT { PREDICT_CLASS2 ( POST_QUANTIFICATION.out.mztab, peptides_class_2_alleles, - INCLUDE_PROTEINS.out.ch_vcf_from_sheet + ch_vcf_from_sheet ) ch_versions = ch_versions.mix(PREDICT_CLASS2.out.versions.first().ifEmpty(null)) ch_predicted_possible_neoepitopes_II = PREDICT_CLASS2.out.ch_predicted_possible_neoepitopes } else { - ch_predicted_possible_neoepitopes_II = Channel.empty() + ch_predicted_possible_neoepitopes_II = Channel.empty() } ////////////////////////////////////////////////////////////////////////////////////////////// // // SUBWORKFLOW: Predict retention time // if ( params.predict_RT ) { - PREDICT_RT ( - filter_q_value.map{ it -> [it[1], it[2]] }, + PREDICT_RT ( + filter_q_value.map{ it -> [it[1], it[2]] }, ch_predicted_possible_neoepitopes, ch_predicted_possible_neoepitopes_II ) From 494e4a664347bd38272392cde0c65d762690c67e Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 18:11:14 +0100 Subject: [PATCH 40/60] Clean mhcquant.nf --- workflows/mhcquant.nf | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/workflows/mhcquant.nf b/workflows/mhcquant.nf index 5d7b7015..5f22c2f0 100644 --- a/workflows/mhcquant.nf +++ b/workflows/mhcquant.nf @@ -88,11 +88,12 @@ workflow MHCQUANT { ch_versions = Channel.empty() - // Subworkflow: preparation_files + // + // SUBWORKFLOW: Check the input file + // INPUT_CHECK( params.input ) .reads .set { ch_samples_from_sheet } - ch_versions = ch_versions.mix(INPUT_CHECK.out.versions) ch_samples_from_sheet @@ -104,7 +105,6 @@ workflow MHCQUANT { return [ meta, filename ] other : true } .set { ms_files } - // A warning message will be given when the format differs from the '.raw' or '.mzML' extention ms_files.other.subscribe { row -> log.warn("Unknown format for entry " + row[3] + " in provided sample sheet, line will be ignored."); exit 1 } @@ -115,6 +115,9 @@ workflow MHCQUANT { .ifEmpty { exit 1, "params.fasta was empty - no input file supplied" } .set { input_fasta } + // + // SUBWORKFLOW: Include protein information + // if ( params.include_proteins_from_vcf ) { // Include the proteins from the vcf file to the fasta file INCLUDE_PROTEINS( input_fasta ) @@ -138,7 +141,6 @@ workflow MHCQUANT { // Raw file conversion OPENMS_THERMORAWFILEPARSER(ms_files.raw) ch_versions = ch_versions.mix(OPENMS_THERMORAWFILEPARSER.out.versions.first().ifEmpty(null)) - if ( params.run_centroidisation ) { // Optional: Run Peak Picking as Preprocessing OPENMS_PEAKPICKERHIRES(ms_files.mzml) @@ -147,14 +149,12 @@ workflow MHCQUANT { } else { ch_mzml_file = ms_files.mzml } - // Run comet database search OPENMS_COMETADAPTER( OPENMS_THERMORAWFILEPARSER.out.mzml .mix(ch_mzml_file) .join(ch_decoy_db, remainder:true)) ch_versions = ch_versions.mix(OPENMS_COMETADAPTER.out.versions.first().ifEmpty(null)) - // Index decoy and target hits OPENMS_PEPTIDEINDEXER(OPENMS_COMETADAPTER.out.idxml.join(ch_decoy_db)) ch_versions = ch_versions.mix(OPENMS_PEPTIDEINDEXER.out.versions.first().ifEmpty(null)) @@ -225,7 +225,6 @@ workflow MHCQUANT { ch_versions = ch_versions.mix(POST_QUANTIFICATION.out.versions.first().ifEmpty(null)) } - ////////////////////////////////////////////////////////////////////////////////////////////// // // SUBWORKFLOW: Predict class I (neoepitopes) // @@ -255,7 +254,7 @@ workflow MHCQUANT { } else { ch_predicted_possible_neoepitopes_II = Channel.empty() } - ////////////////////////////////////////////////////////////////////////////////////////////// + // // SUBWORKFLOW: Predict retention time // From 22f3a15c38a8bf06bb62c7aa549300bbef6ad6a2 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Fri, 7 Jan 2022 18:13:59 +0100 Subject: [PATCH 41/60] Resolve typo in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b09ae8b6..5d6a5667 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ - Changed parameters in the nextflow_schema.json to be in coherence with the nextflow.config - Error that was raised in generate_proteins_from_vcf - Problems that were detected in predict_possible_neoepitopes and predict_possible_class_2_neoepitopes -- Error that occured in mhcnuggets_predictneoepitopesclass2 (faulty container set up) +- Error that occurred in mhcnuggets_predictneoepitopesclass2 (faulty container set up) ### `Dependencies` From a127641b266c35b51a6ea6c2b0a12f73413fff39 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Mon, 10 Jan 2022 15:25:22 +0100 Subject: [PATCH 42/60] Change the ext.suffix to ext.prefix --- conf/modules.config | 24 +++++++++---------- modules/local/generate_proteins_from_vcf.nf | 2 +- .../mhcflurry_predictneoepitopesclass1.nf | 2 +- .../local/mhcflurry_predictpeptidesclass1.nf | 2 +- modules/local/mhcflurry_predictpsms.nf | 2 +- .../local/mhcnuggets_neoepitopesclass2pre.nf | 2 +- .../local/mhcnuggets_peptidesclass2post.nf | 2 +- modules/local/mhcnuggets_peptidesclass2pre.nf | 2 +- .../mhcnuggets_predictneoepitopesclass2.nf | 2 +- .../local/mhcnuggets_predictpeptidesclass2.nf | 2 +- modules/local/openms_cometadapter.nf | 2 +- modules/local/openms_decoydatabase.nf | 2 +- modules/local/openms_falsediscoveryrate.nf | 2 +- .../openms_featurefinderidentification.nf | 2 +- .../local/openms_featurelinkerunlabeledkd.nf | 2 +- modules/local/openms_idconflictresolver.nf | 2 +- modules/local/openms_idfilter.nf | 2 +- modules/local/openms_idmerger.nf | 2 +- modules/local/openms_maprttransformer.nf | 3 ++- modules/local/openms_mztabexporter.nf | 2 +- modules/local/openms_peakpickerhires.nf | 2 +- modules/local/openms_peptideindexer.nf | 2 +- modules/local/openms_percolatoradapter.nf | 2 +- modules/local/openms_psmfeatureextractor.nf | 4 ++-- modules/local/openms_rtmodel.nf | 2 +- modules/local/openms_rtpredict.nf | 2 +- modules/local/openms_textexporter.nf | 2 +- modules/local/openms_thermorawfileparser.nf | 2 +- .../predict_possible_class_2_neoepitopes.nf | 2 +- modules/local/predict_possible_neoepitopes.nf | 2 +- .../resolve_found_class_2_neoepitopes.nf | 2 +- modules/local/resolve_found_neoepitopes.nf | 2 +- subworkflows/local/refine_fdr.nf | 1 - 33 files changed, 45 insertions(+), 45 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index fd4fcce2..31ca01fc 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -94,7 +94,7 @@ process { } withName: OPENMS_IDFILTER_Q_VALUE { - ext.suffix = { "filtered" } + ext.prefix = { "${meta.id}_filtered" } ext.args = [ "-remove_decoys", "-precursor:length '${params.peptide_min_length}:${params.peptide_max_length}'", @@ -109,7 +109,7 @@ process { } withName: OPENMS_PERCOLATORADAPTER { - ext.suffix = { "all_ids_merged_psm_perc" } + ext.prefix = { "${meta.id}_all_ids_merged_psm_perc" } ext.args = [ "-seed 4711", "-trainFDR 0.05", @@ -164,7 +164,7 @@ process { if ( params.refine_fdr_on_predicted_subset && params.predict_class_1 ) { withName: OPENMS_MZTABEXPORTERPERC { - ext.suffix = { "all_ids_merged_psm_perc_filtered" } + ext.prefix = { "${meta.sample}_${meta.condition}_all_ids_merged_psm_perc_filtered" } publishDir = [ path: { "${params.outdir}/Intermediate_Results" }, mode: 'copy', @@ -173,7 +173,7 @@ process { } withName: OPENMS_MZTABEXPORTERPSM { - ext.suffix = { "all_ids_merged" } + ext.prefix = { "${meta.sample}_${meta.condition}_all_ids_merged" } publishDir = [ path: { "${params.outdir}/Intermediate_Results" }, mode: 'copy', @@ -186,7 +186,7 @@ process { } withName: REFINE_FDR_ON_PREDICTED_SUBSET:OPENMS_PERCOLATORADAPTER { - ext.suffix = { "perc_subset" } + ext.prefix = { "${meta.id}_perc_subset" } ext.args = [ "-seed 4711", "-trainFDR 0.05", @@ -204,7 +204,7 @@ process { } withName: OPENMS_IDFILTER_PSMS { - ext.suffix = { "pred_filtered" } + ext.prefix = { "${meta.id}_pred_filtered" } ext.args = [ "-whitelist:ignore_modifications", "-whitelist:peptides" @@ -321,20 +321,20 @@ process { } withName: MHCNUGGETS_NEOEPITOPESCLASS2PRE { - ext.suffix = { "mhcnuggets_preprocessed" } + ext.prefix = { "${meta}_mhcnuggets_preprocessed" } publishDir = [ path: { "${params.outdir}/class_2_bindings" }, mode: 'copy', - pattern: '*${ext.suffix}' + pattern: '*${ext.prefix}' ] } withName: MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 { - ext.suffix = { "predicted_neoepitopes_class_2" } + ext.prefix = { "${meta}_predicted_neoepitopes_class_2" } publishDir = [ path: { "${params.outdir}/class_2_bindings" }, mode: 'copy', - pattern: '*${ext.suffix}' + pattern: '*${ext.prefix}' ] } @@ -357,7 +357,7 @@ process { } withName: OPENMS_RTPREDICT_FOUND_PEPTIDES { - ext.suffix = { "id_files_for_rt_prediction_RTpredicted" } + ext.prefix = { "${meta.sample}_id_files_for_rt_prediction_RTpredicted" } publishDir = [ path: { "${params.outdir}/RT_prediction" }, mode: 'copy', @@ -366,7 +366,7 @@ process { } withName: OPENMS_RTPREDICT_NEOEPITOPES { - ext.suffix = { "txt_file_for_rt_prediction_RTpredicted" } + ext.prefix = { "${meta.sample}_txt_file_for_rt_prediction_RTpredicted" } publishDir = [ path: { "${params.outdir}/RT_prediction" }, mode: 'copy', diff --git a/modules/local/generate_proteins_from_vcf.nf b/modules/local/generate_proteins_from_vcf.nf index 5874e60c..428dafcf 100644 --- a/modules/local/generate_proteins_from_vcf.nf +++ b/modules/local/generate_proteins_from_vcf.nf @@ -15,7 +15,7 @@ process GENERATE_PROTEINS_FROM_VCF { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${fasta.baseName}_${task.ext.suffix}" : "${fasta.baseName}_added_vcf" + def prefix = task.ext.prefix ?: "${fasta.baseName}_added_vcf" def args = task.ext.args ?: '' """ diff --git a/modules/local/mhcflurry_predictneoepitopesclass1.nf b/modules/local/mhcflurry_predictneoepitopesclass1.nf index 7f7bb575..e7fa60d3 100644 --- a/modules/local/mhcflurry_predictneoepitopesclass1.nf +++ b/modules/local/mhcflurry_predictneoepitopesclass1.nf @@ -15,7 +15,7 @@ process MHCFLURRY_PREDICTNEOEPITOPESCLASS1 { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${neoepitopes}_${meta}_${task.ext.suffix}" : "${neoepitopes}_${meta}_predicted_neoepitopes_class_1" + def prefix = task.ext.suffix ?: "${neoepitopes}_${meta}_predicted_neoepitopes_class_1" """ mhcflurry-downloads --quiet fetch models_class1 diff --git a/modules/local/mhcflurry_predictpeptidesclass1.nf b/modules/local/mhcflurry_predictpeptidesclass1.nf index 79e7b36a..0683f407 100644 --- a/modules/local/mhcflurry_predictpeptidesclass1.nf +++ b/modules/local/mhcflurry_predictpeptidesclass1.nf @@ -15,7 +15,7 @@ process MHCFLURRY_PREDICTPEPTIDESCLASS1 { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}_predicted_peptides_class_1" + def prefix = task.ext.suffix ?: "${meta.id}_predicted_peptides_class_1" """ mhcflurry-downloads --quiet fetch models_class1 diff --git a/modules/local/mhcflurry_predictpsms.nf b/modules/local/mhcflurry_predictpsms.nf index d53e0a93..e32171b6 100644 --- a/modules/local/mhcflurry_predictpsms.nf +++ b/modules/local/mhcflurry_predictpsms.nf @@ -15,7 +15,7 @@ process MHCFLURRY_PREDICTPSMS { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}_peptide_filter" + def prefix = task.ext.suffix ?: "${meta.id}_peptide_filter" """ mhcflurry-downloads --quiet fetch models_class1 diff --git a/modules/local/mhcnuggets_neoepitopesclass2pre.nf b/modules/local/mhcnuggets_neoepitopesclass2pre.nf index 0f08a551..0b20feee 100644 --- a/modules/local/mhcnuggets_neoepitopesclass2pre.nf +++ b/modules/local/mhcnuggets_neoepitopesclass2pre.nf @@ -15,7 +15,7 @@ process MHCNUGGETS_NEOEPITOPESCLASS2PRE { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_mhcnuggets_preprocessed" + def prefix = task.ext.prefix ?: "${meta}_mhcnuggets_preprocessed" """ preprocess_neoepitopes_mhcnuggets.py \\ diff --git a/modules/local/mhcnuggets_peptidesclass2post.nf b/modules/local/mhcnuggets_peptidesclass2post.nf index 505f6b40..c793a4e6 100644 --- a/modules/local/mhcnuggets_peptidesclass2post.nf +++ b/modules/local/mhcnuggets_peptidesclass2post.nf @@ -15,7 +15,7 @@ process MHCNUGGETS_PEPTIDESCLASS2POST { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}" : "${meta.sample}_postprocessed" + def prefix = task.ext.prefix ?: "${meta.sample}_postprocessed" """ postprocess_peptides_mhcnuggets.py --input $peptides \\ diff --git a/modules/local/mhcnuggets_peptidesclass2pre.nf b/modules/local/mhcnuggets_peptidesclass2pre.nf index 5a8db231..6e9f082b 100644 --- a/modules/local/mhcnuggets_peptidesclass2pre.nf +++ b/modules/local/mhcnuggets_peptidesclass2pre.nf @@ -16,7 +16,7 @@ process MHCNUGGETS_PEPTIDESCLASS2PRE { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}_peptides" : "${meta.sample}_preprocessed_mhcnuggets_peptides" + def prefix = task.ext.prefix ?: "${meta.sample}_preprocessed_mhcnuggets_peptides" """ preprocess_peptides_mhcnuggets.py --mztab $mztab \\ diff --git a/modules/local/mhcnuggets_predictneoepitopesclass2.nf b/modules/local/mhcnuggets_predictneoepitopesclass2.nf index 80ac61ee..3f3cc4c2 100644 --- a/modules/local/mhcnuggets_predictneoepitopesclass2.nf +++ b/modules/local/mhcnuggets_predictneoepitopesclass2.nf @@ -15,7 +15,7 @@ process MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_predicted_neoepitopes_class_2" + def prefix = task.ext.prefix ?: "${meta}_predicted_neoepitopes_class_2" """ mhcnuggets_predict_peptides.py --peptides $neoepitopes \\ diff --git a/modules/local/mhcnuggets_predictpeptidesclass2.nf b/modules/local/mhcnuggets_predictpeptidesclass2.nf index 3d7e8597..edcd7fc5 100644 --- a/modules/local/mhcnuggets_predictpeptidesclass2.nf +++ b/modules/local/mhcnuggets_predictpeptidesclass2.nf @@ -15,7 +15,7 @@ process MHCNUGGETS_PREDICTPEPTIDESCLASS2 { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}_class_2" : "${meta.sample}_predicted_peptides_class_2" + def prefix = task.ext.prefix ?: "${meta.sample}_predicted_peptides_class_2" """ mhcnuggets_predict_peptides.py --peptides $peptides \\ diff --git a/modules/local/openms_cometadapter.nf b/modules/local/openms_cometadapter.nf index a9d369c9..49304e2d 100644 --- a/modules/local/openms_cometadapter.nf +++ b/modules/local/openms_cometadapter.nf @@ -15,7 +15,7 @@ process OPENMS_COMETADAPTER { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${mzml.baseName}_${task.ext.suffix}" : "${mzml.baseName}" + def prefix = task.ext.prefix ?: "${mzml.baseName}" def args = task.ext.args ?: '' def mods = params.fixed_mods != " " ? "-fixed_modifications ${params.fixed_mods.tokenize(',').collect { "'${it}'"}.join(" ")}" : "" diff --git a/modules/local/openms_decoydatabase.nf b/modules/local/openms_decoydatabase.nf index 6cf537af..7b74286c 100644 --- a/modules/local/openms_decoydatabase.nf +++ b/modules/local/openms_decoydatabase.nf @@ -15,7 +15,7 @@ process OPENMS_DECOYDATABASE { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${fasta.baseName}_${task.ext.suffix}" : "${fasta.baseName}_decoy" + def prefix = task.ext.prefix ?: "${fasta.baseName}_decoy" """ DecoyDatabase -in $fasta \\ diff --git a/modules/local/openms_falsediscoveryrate.nf b/modules/local/openms_falsediscoveryrate.nf index 5ed4a831..7f1d9801 100644 --- a/modules/local/openms_falsediscoveryrate.nf +++ b/modules/local/openms_falsediscoveryrate.nf @@ -15,7 +15,7 @@ process OPENMS_FALSEDISCOVERYRATE { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${idxml.baseName}_${task.ext.suffix}" : "${idxml.baseName}_fdr" + def prefix = task.ext.prefix ?: "${idxml.baseName}_fdr" """ FalseDiscoveryRate -in $idxml \\ diff --git a/modules/local/openms_featurefinderidentification.nf b/modules/local/openms_featurefinderidentification.nf index 6de5ebd7..ba45096b 100644 --- a/modules/local/openms_featurefinderidentification.nf +++ b/modules/local/openms_featurefinderidentification.nf @@ -15,7 +15,7 @@ process OPENMS_FEATUREFINDERIDENTIFICATION { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}" : "${meta.sample}_${meta.id}" + def prefix = task.ext.prefix ?: "${meta.sample}_${meta.id}" if (!params.quantification_fdr){ arguments = "-id $id_quant" diff --git a/modules/local/openms_featurelinkerunlabeledkd.nf b/modules/local/openms_featurelinkerunlabeledkd.nf index 9861e2b6..42be036a 100644 --- a/modules/local/openms_featurelinkerunlabeledkd.nf +++ b/modules/local/openms_featurelinkerunlabeledkd.nf @@ -16,7 +16,7 @@ process OPENMS_FEATURELINKERUNLABELEDKD { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}_all_features_merged" + def prefix = task.ext.prefix ?: "${meta.id}_all_features_merged" """ FeatureLinkerUnlabeledKD -in $features \\ diff --git a/modules/local/openms_idconflictresolver.nf b/modules/local/openms_idconflictresolver.nf index 7f46ef46..59bcdc14 100644 --- a/modules/local/openms_idconflictresolver.nf +++ b/modules/local/openms_idconflictresolver.nf @@ -15,7 +15,7 @@ process OPENMS_IDCONFLICTRESOLVER { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}_resolved" + def prefix = task.ext.prefix ?: "${meta.id}_resolved" """ IDConflictResolver -in $consensus \\ diff --git a/modules/local/openms_idfilter.nf b/modules/local/openms_idfilter.nf index 82b7d1d6..bffc71b0 100644 --- a/modules/local/openms_idfilter.nf +++ b/modules/local/openms_idfilter.nf @@ -16,7 +16,7 @@ process OPENMS_IDFILTER { script: def whitelist = "$peptide_filter" - def prefix = task.ext.suffix ? "${meta.id}_-_${idxml.baseName}_${task.ext.suffix}" : "${meta.id}_-_${idxml.baseName}_filtered" + def prefix = task.ext.prefix ?: "${meta.id}_-_${idxml.baseName}_filtered" def args = task.ext.args ?: '' if (whitelist == "input.2") { diff --git a/modules/local/openms_idmerger.nf b/modules/local/openms_idmerger.nf index 43cafffb..1ca1bf73 100644 --- a/modules/local/openms_idmerger.nf +++ b/modules/local/openms_idmerger.nf @@ -15,7 +15,7 @@ process OPENMS_IDMERGER { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.sample}_${meta.condition}_${task.ext.suffix}" : "${meta.sample}_${meta.condition}_all_ids_merged" + def prefix = task.ext.prefix ?: "${meta.sample}_${meta.condition}_all_ids_merged" """ IDMerger -in $aligned \\ diff --git a/modules/local/openms_maprttransformer.nf b/modules/local/openms_maprttransformer.nf index 7a4f2c42..aa7048a0 100644 --- a/modules/local/openms_maprttransformer.nf +++ b/modules/local/openms_maprttransformer.nf @@ -15,12 +15,13 @@ process OPENMS_MAPRTTRANSFORMER { path "versions.yml" , emit: versions script: + def prefix = task.ext.prefix ?: "${meta.id}_aligned" def fileExt = alignment_file.collect { it.name.tokenize("\\.")[1] }.join(' ') """ MapRTTransformer -in $alignment_file \\ -trafo_in $trafoxml \\ - -out ${meta.id}_aligned.${fileExt} \\ + -out ${prefix}.${fileExt} \\ -threads $task.cpus cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/openms_mztabexporter.nf b/modules/local/openms_mztabexporter.nf index fa94896a..34844f65 100644 --- a/modules/local/openms_mztabexporter.nf +++ b/modules/local/openms_mztabexporter.nf @@ -15,7 +15,7 @@ process OPENMS_MZTABEXPORTER { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.sample}_${meta.condition}_${task.ext.suffix}" : "${meta.sample}_${meta.condition}" + def prefix = task.ext.prefix ?: "${meta.sample}_${meta.condition}" def args = task.ext.args ?: '' """ diff --git a/modules/local/openms_peakpickerhires.nf b/modules/local/openms_peakpickerhires.nf index 1f20ff87..7f56b9d1 100644 --- a/modules/local/openms_peakpickerhires.nf +++ b/modules/local/openms_peakpickerhires.nf @@ -15,7 +15,7 @@ process OPENMS_PEAKPICKERHIRES { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${mzml.baseName}_${task.ext.suffix}" : "${mzml.baseName}" + def prefix = task.ext.prefix ?: "${mzml.baseName}" """ PeakPickerHiRes -in $mzml \\ diff --git a/modules/local/openms_peptideindexer.nf b/modules/local/openms_peptideindexer.nf index 33510165..694f8b88 100644 --- a/modules/local/openms_peptideindexer.nf +++ b/modules/local/openms_peptideindexer.nf @@ -15,7 +15,7 @@ process OPENMS_PEPTIDEINDEXER { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${idxml.baseName}_${task.ext.suffix}" : "${idxml.baseName}_-_idx" + def prefix = task.ext.prefix ?: "${idxml.baseName}_-_idx" """ PeptideIndexer -in $idxml \\ diff --git a/modules/local/openms_percolatoradapter.nf b/modules/local/openms_percolatoradapter.nf index 1d4566e7..728043a6 100644 --- a/modules/local/openms_percolatoradapter.nf +++ b/modules/local/openms_percolatoradapter.nf @@ -15,7 +15,7 @@ process OPENMS_PERCOLATORADAPTER { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}" + def prefix = task.ext.prefix ?: "${meta.id}" def args = task.ext.args ?: '' def klammer = (params.description_correct_features > 0 && params.klammer) ? "-klammer" : "" diff --git a/modules/local/openms_psmfeatureextractor.nf b/modules/local/openms_psmfeatureextractor.nf index 141580b8..5dcdd6e1 100644 --- a/modules/local/openms_psmfeatureextractor.nf +++ b/modules/local/openms_psmfeatureextractor.nf @@ -15,8 +15,8 @@ process OPENMS_PSMFEATUREEXTRACTOR { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${merged.baseName}_${task.ext.suffix}" : "${merged.baseName}_psm" - def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${merged.baseName}_psm" + def args = task.ext.args ?: '' """ PSMFeatureExtractor -in $merged \\ diff --git a/modules/local/openms_rtmodel.nf b/modules/local/openms_rtmodel.nf index 57d8387c..c1c7a8ee 100644 --- a/modules/local/openms_rtmodel.nf +++ b/modules/local/openms_rtmodel.nf @@ -15,7 +15,7 @@ process OPENMS_RTMODEL { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}" : "${meta.sample}" + def prefix = task.ext.prefix ?: "${meta.sample}" """ RTModel -in $rt_training \\ diff --git a/modules/local/openms_rtpredict.nf b/modules/local/openms_rtpredict.nf index 1803641f..6bd1ad50 100644 --- a/modules/local/openms_rtpredict.nf +++ b/modules/local/openms_rtpredict.nf @@ -15,7 +15,7 @@ process OPENMS_RTPREDICT { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}" : "${meta.sample}_RTpredicted" + def prefix = task.ext.prefix ?: "${meta.sample}_RTpredicted" """ RTPredict -in_id $idxml \\ diff --git a/modules/local/openms_textexporter.nf b/modules/local/openms_textexporter.nf index 09412aa5..629437c8 100644 --- a/modules/local/openms_textexporter.nf +++ b/modules/local/openms_textexporter.nf @@ -15,7 +15,7 @@ process OPENMS_TEXTEXPORTER { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.id}_${task.ext.suffix}" : "${meta.id}" + def prefix = task.ext.prefix ?: "${meta.id}" def args = task.ext.args ?: '' """ diff --git a/modules/local/openms_thermorawfileparser.nf b/modules/local/openms_thermorawfileparser.nf index 38f6f829..37d2734d 100644 --- a/modules/local/openms_thermorawfileparser.nf +++ b/modules/local/openms_thermorawfileparser.nf @@ -15,7 +15,7 @@ process OPENMS_THERMORAWFILEPARSER { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${rawfile.baseName}_${task.ext.suffix}" : "${rawfile.baseName}" + def prefix = task.ext.prefix ?: "${rawfile.baseName}" """ ThermoRawFileParser.sh -i=$rawfile \\ diff --git a/modules/local/predict_possible_class_2_neoepitopes.nf b/modules/local/predict_possible_class_2_neoepitopes.nf index f7efb8ca..329be610 100644 --- a/modules/local/predict_possible_class_2_neoepitopes.nf +++ b/modules/local/predict_possible_class_2_neoepitopes.nf @@ -16,7 +16,7 @@ process PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_vcf_neoepitopes_class2" + def prefix = task.ext.prefix ?: "${meta}_vcf_neoepitopes_class2" """ vcf_neoepitope_predictor.py -t ${params.variant_annotation_style} \\ diff --git a/modules/local/predict_possible_neoepitopes.nf b/modules/local/predict_possible_neoepitopes.nf index 0247921b..f24db0e0 100644 --- a/modules/local/predict_possible_neoepitopes.nf +++ b/modules/local/predict_possible_neoepitopes.nf @@ -16,7 +16,7 @@ process PREDICT_POSSIBLE_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_vcf_neoepitopes_class1" + def prefix = task.ext.prefix ?: "${meta}_vcf_neoepitopes_class1" """ vcf_neoepitope_predictor.py \\ diff --git a/modules/local/resolve_found_class_2_neoepitopes.nf b/modules/local/resolve_found_class_2_neoepitopes.nf index 98582f7b..8a6ad4d4 100644 --- a/modules/local/resolve_found_class_2_neoepitopes.nf +++ b/modules/local/resolve_found_class_2_neoepitopes.nf @@ -16,7 +16,7 @@ process RESOLVE_FOUND_CLASS_2_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta}_${task.ext.suffix}" : "${meta}_found_neoepitopes_class_2" + def prefix = task.ext.prefix ?: "${meta}_found_neoepitopes_class_2" """ resolve_neoepitopes.py -n $neoepitopes \\ diff --git a/modules/local/resolve_found_neoepitopes.nf b/modules/local/resolve_found_neoepitopes.nf index 50f4d6f5..0f5432d4 100644 --- a/modules/local/resolve_found_neoepitopes.nf +++ b/modules/local/resolve_found_neoepitopes.nf @@ -15,7 +15,7 @@ process RESOLVE_FOUND_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = task.ext.suffix ? "${meta.sample}_${task.ext.suffix}" : "${meta.sample}_found_neoepitopes_class_1" + def prefix = task.ext.prefix ?: "${meta.sample}_found_neoepitopes_class_1" """ resolve_neoepitopes.py -n $neoepitopes \\ diff --git a/subworkflows/local/refine_fdr.nf b/subworkflows/local/refine_fdr.nf index d630a47e..162ab9b9 100644 --- a/subworkflows/local/refine_fdr.nf +++ b/subworkflows/local/refine_fdr.nf @@ -43,7 +43,6 @@ workflow REFINE_FDR { ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions) // Filter results by refined fdr OPENMS_IDFILTER_REFINED(OPENMS_PERCOLATORADAPTER.out.idxml.flatMap { it -> [tuple(it[0], it[1], null)]}) - //TODO: does this needs to overwrite the tsv files as well? ch_versions = ch_versions.mix(OPENMS_IDFILTER_REFINED.out.versions) emit: // Define the information that is returned by this workflow From 93bb9415468e057c57a175bea28eebeb34d3daad Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 14:10:54 +0100 Subject: [PATCH 43/60] Remove space in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f42061f..b71cfe63 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ For further information or help, don't hesitate to get in touch on the [Slack `# ## Citations -If you use nf-core/mhcquant for your analysis, please cite it using the following doi: [10.5281/zenodo.1569909](https://doi.org/10.5281/zenodo.1569909) and the corresponding manuscript: +If you use nf-core/mhcquant for your analysis, please cite it using the following doi: [10.5281/zenodo.1569909](https://doi.org/10.5281/zenodo.1569909) and the corresponding manuscript: > **MHCquant: Automated and Reproducible Data Analysis for Immunopeptidomics** > From 46bf05cc8b9fcc8c8472769df9fc277ce884093b Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 14:12:01 +0100 Subject: [PATCH 44/60] Remove duplicate entry of schema_ignore_params and change to the proper version --- nextflow.config | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nextflow.config b/nextflow.config index dffeafb2..86ab4be6 100644 --- a/nextflow.config +++ b/nextflow.config @@ -86,7 +86,6 @@ params { help = false validate_params = true show_hidden_params = false - schema_ignore_params = 'genomes,modules' enable_conda = false // Config options @@ -214,7 +213,7 @@ manifest { description = 'Identify and quantify peptides from mass spectrometry raw data' mainScript = 'main.nf' nextflowVersion = '!>=21.10.3' - version = '2.1.1dev' + version = '2.2.0' } // Function to ensure that resource requirements don't go beyond @@ -248,4 +247,4 @@ def check_max(obj, type) { return obj } } -} +} \ No newline at end of file From 612928d012aa6e1bbf379d59ed1233dd3078d48f Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 14:13:17 +0100 Subject: [PATCH 45/60] Resolve potential problem with OPENMS_TEXTEXPORTER --- conf/modules.config | 4 ++-- subworkflows/local/post_quantification.nf | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 31ca01fc..b8c5056a 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -138,7 +138,7 @@ process { publishDir = [ enabled: false ] } - withName: 'OPENMS_TEXTEXPORTER' { + withName: 'OPENMS_TEXTEXPORTER_CSV' { ext.args = [ "-id:add_metavalues 0" ].join(' ').trim() @@ -185,7 +185,7 @@ process { publishDir = [ enabled: false ] } - withName: REFINE_FDR_ON_PREDICTED_SUBSET:OPENMS_PERCOLATORADAPTER { + withName: REFINE_FDR:OPENMS_PERCOLATORADAPTER { ext.prefix = { "${meta.id}_perc_subset" } ext.args = [ "-seed 4711", diff --git a/subworkflows/local/post_quantification.nf b/subworkflows/local/post_quantification.nf index d59c03f9..3d9ffbae 100644 --- a/subworkflows/local/post_quantification.nf +++ b/subworkflows/local/post_quantification.nf @@ -5,7 +5,7 @@ include { OPENMS_FEATUREFINDERIDENTIFICATION } from '../../modules/local/openms_featurefinderidentification' include { OPENMS_FEATURELINKERUNLABELEDKD } from '../../modules/local/openms_featurelinkerunlabeledkd' include { OPENMS_IDCONFLICTRESOLVER } from '../../modules/local/openms_idconflictresolver' -include { OPENMS_TEXTEXPORTER } from '../../modules/local/openms_textexporter' +include { OPENMS_TEXTEXPORTER as OPENMS_TEXTEXPORTER_CSV } from '../../modules/local/openms_textexporter' include { OPENMS_MZTABEXPORTER } from '../../modules/local/openms_mztabexporter' workflow POST_QUANTIFICATION { @@ -39,8 +39,8 @@ workflow POST_QUANTIFICATION { OPENMS_IDCONFLICTRESOLVER(OPENMS_FEATURELINKERUNLABELEDKD.out.consensusxml) ch_versions = ch_versions.mix(OPENMS_IDCONFLICTRESOLVER.out.versions.first().ifEmpty(null)) // Export all information as text to csv - OPENMS_TEXTEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) - ch_versions = ch_versions.mix(OPENMS_TEXTEXPORTER.out.versions.first().ifEmpty(null)) + OPENMS_TEXTEXPORTER_CSV(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) + ch_versions = ch_versions.mix(OPENMS_TEXTEXPORTER_CSV.out.versions.first().ifEmpty(null)) // Export all information as mzTab OPENMS_MZTABEXPORTER(OPENMS_IDCONFLICTRESOLVER.out.consensusxml) ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTER.out.versions.first().ifEmpty(null)) From 6d9e9a8a3880e9a766a49883cfaba5ff3a74ea67 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 14:13:50 +0100 Subject: [PATCH 46/60] Include the referenceto the pipeline publication again --- lib/WorkflowMain.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 84cd43ca..c34a530f 100644 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -9,6 +9,8 @@ class WorkflowMain { // public static String citation(workflow) { return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + + "* The pipeline publication\n" + + " https://doi.org/10.1021/acs.jproteome.9b00313\n\n" + "* The pipeline\n" + " https://doi.org/10.5281/zenodo.1569909\n\n" + "* The nf-core framework\n" + From 687bcf11de7f2fdca0113440b029204539dca45f Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 14:38:22 +0100 Subject: [PATCH 47/60] Include other PR and linting suggestions --- modules/local/mhcflurry_predictneoepitopesclass1.nf | 2 +- modules/local/mhcflurry_predictpeptidesclass1.nf | 2 +- modules/local/mhcflurry_predictpsms.nf | 2 +- modules/local/mhcnuggets_neoepitopesclass2post.nf | 2 +- modules/local/mhcnuggets_neoepitopesclass2pre.nf | 2 +- modules/local/mhcnuggets_peptidesclass2post.nf | 2 +- modules/local/mhcnuggets_peptidesclass2pre.nf | 2 +- .../local/mhcnuggets_predictneoepitopesclass2.nf | 2 +- modules/local/mhcnuggets_predictpeptidesclass2.nf | 2 +- modules/local/openms_cometadapter.nf | 2 +- modules/local/openms_falsediscoveryrate.nf | 2 +- modules/local/openms_featurefinderidentification.nf | 13 +++++++------ modules/local/openms_featurelinkerunlabeledkd.nf | 3 +-- modules/local/openms_idconflictresolver.nf | 2 +- modules/local/openms_idfilter.nf | 2 +- modules/local/openms_idmerger.nf | 2 +- modules/local/openms_mapaligneridentification.nf | 2 +- modules/local/openms_maprttransformer.nf | 2 +- modules/local/openms_mztabexporter.nf | 2 +- modules/local/openms_peakpickerhires.nf | 2 +- modules/local/openms_peptideindexer.nf | 2 +- modules/local/openms_percolatoradapter.nf | 2 +- modules/local/openms_psmfeatureextractor.nf | 2 +- modules/local/openms_rtmodel.nf | 2 +- modules/local/openms_rtpredict.nf | 2 +- modules/local/openms_textexporter.nf | 2 +- modules/local/openms_thermorawfileparser.nf | 2 +- .../local/predict_possible_class_2_neoepitopes.nf | 2 +- modules/local/predict_possible_neoepitopes.nf | 2 +- modules/local/resolve_found_class_2_neoepitopes.nf | 2 +- modules/local/resolve_found_neoepitopes.nf | 2 +- nextflow.config | 2 +- 32 files changed, 38 insertions(+), 38 deletions(-) diff --git a/modules/local/mhcflurry_predictneoepitopesclass1.nf b/modules/local/mhcflurry_predictneoepitopesclass1.nf index e7fa60d3..da1d48ef 100644 --- a/modules/local/mhcflurry_predictneoepitopesclass1.nf +++ b/modules/local/mhcflurry_predictneoepitopesclass1.nf @@ -22,7 +22,7 @@ process MHCFLURRY_PREDICTNEOEPITOPESCLASS1 { mhcflurry_neoepitope_binding_prediction.py '$allotypes' ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) END_VERSIONS """ diff --git a/modules/local/mhcflurry_predictpeptidesclass1.nf b/modules/local/mhcflurry_predictpeptidesclass1.nf index 0683f407..040caff2 100644 --- a/modules/local/mhcflurry_predictpeptidesclass1.nf +++ b/modules/local/mhcflurry_predictpeptidesclass1.nf @@ -22,7 +22,7 @@ process MHCFLURRY_PREDICTPEPTIDESCLASS1 { mhcflurry_predict_mztab.py '$alleles' $mztab ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/mhcflurry_predictpsms.nf b/modules/local/mhcflurry_predictpsms.nf index e32171b6..9f65adf7 100644 --- a/modules/local/mhcflurry_predictpsms.nf +++ b/modules/local/mhcflurry_predictpsms.nf @@ -22,7 +22,7 @@ process MHCFLURRY_PREDICTPSMS { mhcflurry_predict_mztab_for_filtering.py ${params.subset_affinity_threshold} '$allotypes' $perc_mztab $psm_mztab ${prefix}.idXML cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/mhcnuggets_neoepitopesclass2post.nf b/modules/local/mhcnuggets_neoepitopesclass2post.nf index 1953cb36..92760a25 100644 --- a/modules/local/mhcnuggets_neoepitopesclass2post.nf +++ b/modules/local/mhcnuggets_neoepitopesclass2post.nf @@ -20,7 +20,7 @@ process MHCNUGGETS_NEOEPITOPESCLASS2POST { postprocess_neoepitopes_mhcnuggets.py --input $predicted --neoepitopes $neoepitopes cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) END_VERSIONS """ diff --git a/modules/local/mhcnuggets_neoepitopesclass2pre.nf b/modules/local/mhcnuggets_neoepitopesclass2pre.nf index 0b20feee..3f466f27 100644 --- a/modules/local/mhcnuggets_neoepitopesclass2pre.nf +++ b/modules/local/mhcnuggets_neoepitopesclass2pre.nf @@ -23,7 +23,7 @@ process MHCNUGGETS_NEOEPITOPESCLASS2PRE { --output ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) END_VERSIONS """ diff --git a/modules/local/mhcnuggets_peptidesclass2post.nf b/modules/local/mhcnuggets_peptidesclass2post.nf index c793a4e6..48f901b7 100644 --- a/modules/local/mhcnuggets_peptidesclass2post.nf +++ b/modules/local/mhcnuggets_peptidesclass2post.nf @@ -23,7 +23,7 @@ process MHCNUGGETS_PEPTIDESCLASS2POST { --output ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) END_VERSIONS """ diff --git a/modules/local/mhcnuggets_peptidesclass2pre.nf b/modules/local/mhcnuggets_peptidesclass2pre.nf index 6e9f082b..d2ad8c60 100644 --- a/modules/local/mhcnuggets_peptidesclass2pre.nf +++ b/modules/local/mhcnuggets_peptidesclass2pre.nf @@ -23,7 +23,7 @@ process MHCNUGGETS_PEPTIDESCLASS2PRE { --output ${prefix} cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) END_VERSIONS """ diff --git a/modules/local/mhcnuggets_predictneoepitopesclass2.nf b/modules/local/mhcnuggets_predictneoepitopesclass2.nf index 3f3cc4c2..31ab6961 100644 --- a/modules/local/mhcnuggets_predictneoepitopesclass2.nf +++ b/modules/local/mhcnuggets_predictneoepitopesclass2.nf @@ -23,7 +23,7 @@ process MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 { --output ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) END_VERSIONS """ diff --git a/modules/local/mhcnuggets_predictpeptidesclass2.nf b/modules/local/mhcnuggets_predictpeptidesclass2.nf index edcd7fc5..d41207cb 100644 --- a/modules/local/mhcnuggets_predictpeptidesclass2.nf +++ b/modules/local/mhcnuggets_predictpeptidesclass2.nf @@ -23,7 +23,7 @@ process MHCNUGGETS_PREDICTPEPTIDESCLASS2 { --output ${prefix} cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/openms_cometadapter.nf b/modules/local/openms_cometadapter.nf index 49304e2d..7f43043d 100644 --- a/modules/local/openms_cometadapter.nf +++ b/modules/local/openms_cometadapter.nf @@ -41,7 +41,7 @@ process OPENMS_COMETADAPTER { $remove_precursor cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_falsediscoveryrate.nf b/modules/local/openms_falsediscoveryrate.nf index 7f1d9801..3e934bd0 100644 --- a/modules/local/openms_falsediscoveryrate.nf +++ b/modules/local/openms_falsediscoveryrate.nf @@ -24,7 +24,7 @@ process OPENMS_FALSEDISCOVERYRATE { -threads $task.cpus cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_featurefinderidentification.nf b/modules/local/openms_featurefinderidentification.nf index ba45096b..086614c4 100644 --- a/modules/local/openms_featurefinderidentification.nf +++ b/modules/local/openms_featurefinderidentification.nf @@ -16,12 +16,13 @@ process OPENMS_FEATUREFINDERIDENTIFICATION { script: def prefix = task.ext.prefix ?: "${meta.sample}_${meta.id}" + def arguments = params.quantification_fdr ? "-id $id_quant_int -id_ext $id_quant -svm:min_prob ${params.quantification_min_prob}" : "-id $id_quant" - if (!params.quantification_fdr){ - arguments = "-id $id_quant" - } else { - arguments = "-id $id_quant_int -id_ext $id_quant -svm:min_prob ${params.quantification_min_prob}" - } + //if (!params.quantification_fdr){ + // arguments = "-id $id_quant" + //} else { + // arguments = "-id $id_quant_int -id_ext $id_quant -svm:min_prob ${params.quantification_min_prob}" + //} """ FeatureFinderIdentification -in $mzml \\ @@ -30,7 +31,7 @@ process OPENMS_FEATUREFINDERIDENTIFICATION { ${arguments} cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_featurelinkerunlabeledkd.nf b/modules/local/openms_featurelinkerunlabeledkd.nf index 42be036a..61276b64 100644 --- a/modules/local/openms_featurelinkerunlabeledkd.nf +++ b/modules/local/openms_featurelinkerunlabeledkd.nf @@ -1,4 +1,3 @@ - process OPENMS_FEATURELINKERUNLABELEDKD { tag "$meta.id" label 'process_low' @@ -24,7 +23,7 @@ process OPENMS_FEATURELINKERUNLABELEDKD { -threads $task.cpus cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_idconflictresolver.nf b/modules/local/openms_idconflictresolver.nf index 59bcdc14..2bf8f16d 100644 --- a/modules/local/openms_idconflictresolver.nf +++ b/modules/local/openms_idconflictresolver.nf @@ -23,7 +23,7 @@ process OPENMS_IDCONFLICTRESOLVER { -threads $task.cpus cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_idfilter.nf b/modules/local/openms_idfilter.nf index bffc71b0..2908b7d7 100644 --- a/modules/local/openms_idfilter.nf +++ b/modules/local/openms_idfilter.nf @@ -31,7 +31,7 @@ process OPENMS_IDFILTER { $whitelist cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_idmerger.nf b/modules/local/openms_idmerger.nf index 1ca1bf73..623b11a0 100644 --- a/modules/local/openms_idmerger.nf +++ b/modules/local/openms_idmerger.nf @@ -25,7 +25,7 @@ process OPENMS_IDMERGER { -merge_proteins_add_PSMs cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_mapaligneridentification.nf b/modules/local/openms_mapaligneridentification.nf index c4729e05..d9ece728 100644 --- a/modules/local/openms_mapaligneridentification.nf +++ b/modules/local/openms_mapaligneridentification.nf @@ -24,7 +24,7 @@ process OPENMS_MAPALIGNERIDENTIFICATION { $args cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_maprttransformer.nf b/modules/local/openms_maprttransformer.nf index aa7048a0..618e72b2 100644 --- a/modules/local/openms_maprttransformer.nf +++ b/modules/local/openms_maprttransformer.nf @@ -25,7 +25,7 @@ process OPENMS_MAPRTTRANSFORMER { -threads $task.cpus cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_mztabexporter.nf b/modules/local/openms_mztabexporter.nf index 34844f65..a24fd829 100644 --- a/modules/local/openms_mztabexporter.nf +++ b/modules/local/openms_mztabexporter.nf @@ -25,7 +25,7 @@ process OPENMS_MZTABEXPORTER { $args cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_peakpickerhires.nf b/modules/local/openms_peakpickerhires.nf index 7f56b9d1..5441b2cd 100644 --- a/modules/local/openms_peakpickerhires.nf +++ b/modules/local/openms_peakpickerhires.nf @@ -23,7 +23,7 @@ process OPENMS_PEAKPICKERHIRES { -algorithm:ms_levels ${params.pick_ms_levels} cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_peptideindexer.nf b/modules/local/openms_peptideindexer.nf index 694f8b88..7d850dca 100644 --- a/modules/local/openms_peptideindexer.nf +++ b/modules/local/openms_peptideindexer.nf @@ -26,7 +26,7 @@ process OPENMS_PEPTIDEINDEXER { -enzyme:specificity none cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_percolatoradapter.nf b/modules/local/openms_percolatoradapter.nf index 728043a6..01538745 100644 --- a/modules/local/openms_percolatoradapter.nf +++ b/modules/local/openms_percolatoradapter.nf @@ -27,7 +27,7 @@ process OPENMS_PERCOLATORADAPTER { $args cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_psmfeatureextractor.nf b/modules/local/openms_psmfeatureextractor.nf index 5dcdd6e1..e6272f70 100644 --- a/modules/local/openms_psmfeatureextractor.nf +++ b/modules/local/openms_psmfeatureextractor.nf @@ -25,7 +25,7 @@ process OPENMS_PSMFEATUREEXTRACTOR { $args cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_rtmodel.nf b/modules/local/openms_rtmodel.nf index c1c7a8ee..c16c2f0f 100644 --- a/modules/local/openms_rtmodel.nf +++ b/modules/local/openms_rtmodel.nf @@ -25,7 +25,7 @@ process OPENMS_RTMODEL { -out_oligo_trainset ${prefix}_trainset.txt cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_rtpredict.nf b/modules/local/openms_rtpredict.nf index 6bd1ad50..481905b7 100644 --- a/modules/local/openms_rtpredict.nf +++ b/modules/local/openms_rtpredict.nf @@ -25,7 +25,7 @@ process OPENMS_RTPREDICT { -out_text:file ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_textexporter.nf b/modules/local/openms_textexporter.nf index 629437c8..3d771255 100644 --- a/modules/local/openms_textexporter.nf +++ b/modules/local/openms_textexporter.nf @@ -27,7 +27,7 @@ process OPENMS_TEXTEXPORTER { $args cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') END_VERSIONS """ diff --git a/modules/local/openms_thermorawfileparser.nf b/modules/local/openms_thermorawfileparser.nf index 37d2734d..b585be4a 100644 --- a/modules/local/openms_thermorawfileparser.nf +++ b/modules/local/openms_thermorawfileparser.nf @@ -23,7 +23,7 @@ process OPENMS_THERMORAWFILEPARSER { -b=${prefix}.mzML cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": thermorawfileparser: \$(ThermoRawFileParser.sh --version) END_VERSIONS """ diff --git a/modules/local/predict_possible_class_2_neoepitopes.nf b/modules/local/predict_possible_class_2_neoepitopes.nf index 329be610..b0253e5d 100644 --- a/modules/local/predict_possible_class_2_neoepitopes.nf +++ b/modules/local/predict_possible_class_2_neoepitopes.nf @@ -28,7 +28,7 @@ process PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES { -o ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/predict_possible_neoepitopes.nf b/modules/local/predict_possible_neoepitopes.nf index f24db0e0..7fafbdbc 100644 --- a/modules/local/predict_possible_neoepitopes.nf +++ b/modules/local/predict_possible_neoepitopes.nf @@ -28,7 +28,7 @@ process PREDICT_POSSIBLE_NEOEPITOPES { -o ${prefix}.csv cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/resolve_found_class_2_neoepitopes.nf b/modules/local/resolve_found_class_2_neoepitopes.nf index 8a6ad4d4..39c0b374 100644 --- a/modules/local/resolve_found_class_2_neoepitopes.nf +++ b/modules/local/resolve_found_class_2_neoepitopes.nf @@ -25,7 +25,7 @@ process RESOLVE_FOUND_CLASS_2_NEOEPITOPES { -o ${prefix} cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/modules/local/resolve_found_neoepitopes.nf b/modules/local/resolve_found_neoepitopes.nf index 0f5432d4..bdc0cfd1 100644 --- a/modules/local/resolve_found_neoepitopes.nf +++ b/modules/local/resolve_found_neoepitopes.nf @@ -24,7 +24,7 @@ process RESOLVE_FOUND_NEOEPITOPES { -o ${prefix} cat <<-END_VERSIONS > versions.yml - ${task.process}: + "${task.process}": mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//')) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) diff --git a/nextflow.config b/nextflow.config index 86ab4be6..444aeeae 100644 --- a/nextflow.config +++ b/nextflow.config @@ -24,7 +24,7 @@ params { predict_class_1 = false predict_class_2 = false refine_fdr_on_predicted_subset = false - schema_ignore_params = 'genome' + schema_ignore_params = 'genomes' skip_decoy_generation = false subset_affinity_threshold = 500 variant_annotation_style = "SNPEFF" From c5d51c4a541c914d31c73d73714e4596983d224a Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 14:39:57 +0100 Subject: [PATCH 48/60] Remove commented code in OPENMS_FEATUREFINDERIDENTIFICATION --- modules/local/openms_featurefinderidentification.nf | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/local/openms_featurefinderidentification.nf b/modules/local/openms_featurefinderidentification.nf index 086614c4..02211102 100644 --- a/modules/local/openms_featurefinderidentification.nf +++ b/modules/local/openms_featurefinderidentification.nf @@ -18,12 +18,6 @@ process OPENMS_FEATUREFINDERIDENTIFICATION { def prefix = task.ext.prefix ?: "${meta.sample}_${meta.id}" def arguments = params.quantification_fdr ? "-id $id_quant_int -id_ext $id_quant -svm:min_prob ${params.quantification_min_prob}" : "-id $id_quant" - //if (!params.quantification_fdr){ - // arguments = "-id $id_quant" - //} else { - // arguments = "-id $id_quant_int -id_ext $id_quant -svm:min_prob ${params.quantification_min_prob}" - //} - """ FeatureFinderIdentification -in $mzml \\ -out ${prefix}.featureXML \\ From a42794f83cc7f0de855feca2826ec7c9fd009892 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 14:41:11 +0100 Subject: [PATCH 49/60] Add newline to nextflow.conflig --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index 444aeeae..9db0570e 100644 --- a/nextflow.config +++ b/nextflow.config @@ -247,4 +247,4 @@ def check_max(obj, type) { return obj } } -} \ No newline at end of file +} From 03c885df4c29ea70a0c96eb316ae2807b9ae95d3 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 16:00:54 +0100 Subject: [PATCH 50/60] Change process names for the prediction of the (neoepitopes class 1 and 2) --- conf/modules.config | 8 ++-- .../predict_possible_class_2_neoepitopes.nf | 37 ------------------- modules/local/predict_possible_neoepitopes.nf | 37 ------------------- .../resolve_found_class_2_neoepitopes.nf | 34 ----------------- modules/local/resolve_found_neoepitopes.nf | 33 ----------------- subworkflows/local/predict_class1.nf | 16 ++++---- subworkflows/local/predict_class2.nf | 18 ++++----- 7 files changed, 21 insertions(+), 162 deletions(-) delete mode 100644 modules/local/predict_possible_class_2_neoepitopes.nf delete mode 100644 modules/local/predict_possible_neoepitopes.nf delete mode 100644 modules/local/resolve_found_class_2_neoepitopes.nf delete mode 100644 modules/local/resolve_found_neoepitopes.nf diff --git a/conf/modules.config b/conf/modules.config index b8c5056a..4dd79612 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -246,7 +246,7 @@ process { } if ( params.predict_class_1 & !params.skip_quantification & params.include_proteins_from_vcf ) { - withName: PREDICT_POSSIBLE_NEOEPITOPES { + withName: PREDICT_POSSIBLE_CLASS1_NEOEPITOPES { publishDir = [ path: {"${params.outdir}/"}, mode: 'copy', @@ -254,7 +254,7 @@ process { ] } - withName: RESOLVE_FOUND_NEOEPITOPES { + withName: RESOLVE_FOUND_CLASS_1_NEOEPITOPES { publishDir = [ path: {"${params.outdir}/class_1_bindings"}, mode: 'copy', @@ -304,7 +304,7 @@ process { if ( params.predict_class_2 & !params.skip_quantification & params.include_proteins_from_vcf ) { - withName: PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES { + withName: PREDICT_POSSIBLE_CLASS2_NEOEPITOPES { publishDir = [ path: { "${params.outdir}" }, mode: 'copy', @@ -312,7 +312,7 @@ process { ] } - withName: RESOLVE_FOUND_CLASS_2_NEOEPITOPES { + withName: RESOLVE_FOUND_CLASS2_NEOEPITOPES { publishDir = [ path: { "${params.outdir}/class_2_bindings" }, mode: 'copy', diff --git a/modules/local/predict_possible_class_2_neoepitopes.nf b/modules/local/predict_possible_class_2_neoepitopes.nf deleted file mode 100644 index b0253e5d..00000000 --- a/modules/local/predict_possible_class_2_neoepitopes.nf +++ /dev/null @@ -1,37 +0,0 @@ -process PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES { - tag "$meta" - label 'process_low' - - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" - - input: - tuple val(meta), val(alleles), path(vcf) - - output: - tuple val(meta), path("*.csv"), emit: csv - tuple val(meta), path("*.txt"), emit: txt - path "versions.yml" , emit: versions - - script: - def prefix = task.ext.prefix ?: "${meta}_vcf_neoepitopes_class2" - - """ - vcf_neoepitope_predictor.py -t ${params.variant_annotation_style} \\ - -r ${params.variant_reference} \\ - -a '$alleles' \\ - -minl ${params.peptide_min_length} \\ - -maxl ${params.peptide_max_length} \\ - -v $vcf \\ - -o ${prefix}.csv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) - mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) - fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) - END_VERSIONS - """ -} diff --git a/modules/local/predict_possible_neoepitopes.nf b/modules/local/predict_possible_neoepitopes.nf deleted file mode 100644 index 7fafbdbc..00000000 --- a/modules/local/predict_possible_neoepitopes.nf +++ /dev/null @@ -1,37 +0,0 @@ -process PREDICT_POSSIBLE_NEOEPITOPES { - tag "$meta" - label 'process_low' - - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" - - input: - tuple val(meta), val(alleles), path(vcf) - - output: - tuple val(meta), path("*.csv"), emit: csv - tuple val(meta), path("*.txt"), emit: txt - path "versions.yml" , emit: versions - - script: - def prefix = task.ext.prefix ?: "${meta}_vcf_neoepitopes_class1" - - """ - vcf_neoepitope_predictor.py \\ - -t ${params.variant_annotation_style} \\ - -r ${params.variant_reference} \\ - -a '$alleles' -minl ${params.peptide_min_length} \\ - -maxl ${params.peptide_max_length} \\ - -v $vcf \\ - -o ${prefix}.csv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) - mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) - fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) - END_VERSIONS - """ -} diff --git a/modules/local/resolve_found_class_2_neoepitopes.nf b/modules/local/resolve_found_class_2_neoepitopes.nf deleted file mode 100644 index 39c0b374..00000000 --- a/modules/local/resolve_found_class_2_neoepitopes.nf +++ /dev/null @@ -1,34 +0,0 @@ - -process RESOLVE_FOUND_CLASS_2_NEOEPITOPES { - tag "$meta" - label 'process_low' - - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" - - input: - tuple val(meta), path(mztab), path(neoepitopes) - - output: - tuple val(meta), path("*.csv"), emit: csv - path "versions.yml" , emit: versions - - script: - def prefix = task.ext.prefix ?: "${meta}_found_neoepitopes_class_2" - - """ - resolve_neoepitopes.py -n $neoepitopes \\ - -m $mztab \\ - -f csv \\ - -o ${prefix} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) - mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) - fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) - END_VERSIONS - """ -} diff --git a/modules/local/resolve_found_neoepitopes.nf b/modules/local/resolve_found_neoepitopes.nf deleted file mode 100644 index bdc0cfd1..00000000 --- a/modules/local/resolve_found_neoepitopes.nf +++ /dev/null @@ -1,33 +0,0 @@ -process RESOLVE_FOUND_NEOEPITOPES { - tag "$meta.sample" - label 'process_low' - - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" - - input: - tuple val(meta), path(mztab), path(neoepitopes) - - output: - tuple val(meta), path("*.csv"), emit: csv - path "versions.yml" , emit: versions - - script: - def prefix = task.ext.prefix ?: "${meta.sample}_found_neoepitopes_class_1" - - """ - resolve_neoepitopes.py -n $neoepitopes \\ - -m $mztab \\ - -f csv \\ - -o ${prefix} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) - mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//')) - fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) - END_VERSIONS - """ -} diff --git a/subworkflows/local/predict_class1.nf b/subworkflows/local/predict_class1.nf index a2764285..ca709d42 100644 --- a/subworkflows/local/predict_class1.nf +++ b/subworkflows/local/predict_class1.nf @@ -3,8 +3,8 @@ */ include { MHCFLURRY_PREDICTPEPTIDESCLASS1 } from '../../modules/local/mhcflurry_predictpeptidesclass1' -include { PREDICT_POSSIBLE_NEOEPITOPES } from '../../modules/local/predict_possible_neoepitopes' -include { RESOLVE_FOUND_NEOEPITOPES } from '../../modules/local/resolve_found_neoepitopes' +include { PREDICT_POSSIBLE_CLASS1_NEOEPITOPES } from '../../modules/local/predict_possible_class1_neoepitopes' +include { RESOLVE_FOUND_CLASS1_NEOEPITOPES } from '../../modules/local/resolve_found_class1_neoepitopes' include { MHCFLURRY_PREDICTNEOEPITOPESCLASS1 } from '../../modules/local/mhcflurry_predictneoepitopesclass1' workflow PREDICT_CLASS1 { @@ -27,19 +27,19 @@ workflow PREDICT_CLASS1 { ch_versions = ch_versions.mix(MHCFLURRY_PREDICTPEPTIDESCLASS1.out.versions.first().ifEmpty(null)) if ( params.include_proteins_from_vcf ) { // Predict all possible neoepitopes from vcf - PREDICT_POSSIBLE_NEOEPITOPES(peptides_class_1_alleles.combine(ch_vcf_from_sheet, by:0)) - ch_versions = ch_versions.mix(PREDICT_POSSIBLE_NEOEPITOPES.out.versions.first().ifEmpty(null)) - ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_NEOEPITOPES.out.csv + PREDICT_POSSIBLE_CLASS1_NEOEPITOPES(peptides_class_1_alleles.combine(ch_vcf_from_sheet, by:0)) + ch_versions = ch_versions.mix(PREDICT_POSSIBLE_CLASS1_NEOEPITOPES.out.versions.first().ifEmpty(null)) + ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_CLASS1_NEOEPITOPES.out.csv // Resolve found neoepitopes - RESOLVE_FOUND_NEOEPITOPES( + RESOLVE_FOUND_CLASS1_NEOEPITOPES( mztab .map{ it -> [it[0].sample, it[0], it[1]] } .combine( ch_predicted_possible_neoepitopes, by:0) .map( it -> [it[1], it[2], it[3]]) ) - ch_versions = ch_versions.mix(RESOLVE_FOUND_NEOEPITOPES.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(RESOLVE_FOUND_CLASS1_NEOEPITOPES.out.versions.first().ifEmpty(null)) // Predict class 1 neoepitopes MHCFlurry - MHCFLURRY_PREDICTNEOEPITOPESCLASS1(peptides_class_1_alleles.join(RESOLVE_FOUND_NEOEPITOPES.out.csv, by:0)) + MHCFLURRY_PREDICTNEOEPITOPESCLASS1(peptides_class_1_alleles.join(RESOLVE_FOUND_CLASS1_NEOEPITOPES.out.csv, by:0)) ch_versions = ch_versions.mix(MHCFLURRY_PREDICTNEOEPITOPESCLASS1.out.versions.first().ifEmpty(null)) } diff --git a/subworkflows/local/predict_class2.nf b/subworkflows/local/predict_class2.nf index 93efc72a..3513f854 100644 --- a/subworkflows/local/predict_class2.nf +++ b/subworkflows/local/predict_class2.nf @@ -5,8 +5,8 @@ include { MHCNUGGETS_PEPTIDESCLASS2PRE } from '../../modules/local/mhcnuggets_peptidesclass2pre' include { MHCNUGGETS_PREDICTPEPTIDESCLASS2 } from '../../modules/local/mhcnuggets_predictpeptidesclass2' include { MHCNUGGETS_PEPTIDESCLASS2POST } from '../../modules/local/mhcnuggets_peptidesclass2post' -include { PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES } from '../../modules/local/predict_possible_class_2_neoepitopes' -include { RESOLVE_FOUND_CLASS_2_NEOEPITOPES } from '../../modules/local/resolve_found_class_2_neoepitopes' +include { PREDICT_POSSIBLE_CLASS2_NEOEPITOPES } from '../../modules/local/predict_possible_class2_neoepitopes' +include { RESOLVE_FOUND_CLASS2_NEOEPITOPES } from '../../modules/local/resolve_found_class2_neoepitopes' include { MHCNUGGETS_NEOEPITOPESCLASS2PRE } from '../../modules/local/mhcnuggets_neoepitopesclass2pre' include { MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 } from '../../modules/local/mhcnuggets_predictneoepitopesclass2' include { MHCNUGGETS_NEOEPITOPESCLASS2POST } from '../../modules/local/mhcnuggets_neoepitopesclass2post' @@ -37,24 +37,24 @@ workflow PREDICT_CLASS2 { ch_versions = ch_versions.mix(MHCNUGGETS_PEPTIDESCLASS2POST.out.versions.first().ifEmpty(null)) if ( params.include_proteins_from_vcf ) { // Predict all possible class 2 neoepitopes from vcf - PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES(peptides_class_2_alleles.combine(ch_vcf_from_sheet, by:0)) - ch_versions = ch_versions.mix(PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) - ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_CLASS_2_NEOEPITOPES.out.csv + PREDICT_POSSIBLE_CLASS2_NEOEPITOPES(peptides_class_2_alleles.combine(ch_vcf_from_sheet, by:0)) + ch_versions = ch_versions.mix(PREDICT_POSSIBLE_CLASS2_NEOEPITOPES.out.versions.first().ifEmpty(null)) + ch_predicted_possible_neoepitopes = PREDICT_POSSIBLE_CLASS2_NEOEPITOPES.out.csv // Resolve found class 2 neoepitopes - RESOLVE_FOUND_CLASS_2_NEOEPITOPES( + RESOLVE_FOUND_CLASS2_NEOEPITOPES( mztab .map{ it -> [it[0].sample, it[1]] } .combine( ch_predicted_possible_neoepitopes, by:0) ) - ch_versions = ch_versions.mix(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(RESOLVE_FOUND_CLASS2_NEOEPITOPES.out.versions.first().ifEmpty(null)) // Preprocess resolved neoepitopes in a format that MHCNuggets understands - MHCNUGGETS_NEOEPITOPESCLASS2PRE(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv) + MHCNUGGETS_NEOEPITOPESCLASS2PRE(RESOLVE_FOUND_CLASS2_NEOEPITOPES.out.csv) ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2PRE.out.versions.first().ifEmpty(null)) // Predict class 2 MHCNuggets MHCNUGGETS_PREDICTNEOEPITOPESCLASS2(MHCNUGGETS_NEOEPITOPESCLASS2PRE.out.preprocessed.join(peptides_class_2_alleles, by:0)) ch_versions = ch_versions.mix(MHCNUGGETS_PREDICTNEOEPITOPESCLASS2.out.versions.first().ifEmpty(null)) // Class 2 MHCNuggets Postprocessing - MHCNUGGETS_NEOEPITOPESCLASS2POST(RESOLVE_FOUND_CLASS_2_NEOEPITOPES.out.csv.join(MHCNUGGETS_PREDICTNEOEPITOPESCLASS2.out.csv, by:0)) + MHCNUGGETS_NEOEPITOPESCLASS2POST(RESOLVE_FOUND_CLASS2_NEOEPITOPES.out.csv.join(MHCNUGGETS_PREDICTNEOEPITOPESCLASS2.out.csv, by:0)) ch_versions = ch_versions.mix(MHCNUGGETS_NEOEPITOPESCLASS2POST.out.versions.first().ifEmpty(null)) } From 01728411740dd8fe005f8e8d83fff7387c506a34 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 16:10:27 +0100 Subject: [PATCH 51/60] Include the new modules --- .../predict_possible_class1_neoepitopes.nf | 37 +++++++++++++++++++ .../predict_possible_class2_neoepitopes.nf | 37 +++++++++++++++++++ .../local/resolve_found_class1_neoepitopes.nf | 33 +++++++++++++++++ .../local/resolve_found_class2_neoepitopes.nf | 34 +++++++++++++++++ 4 files changed, 141 insertions(+) create mode 100644 modules/local/predict_possible_class1_neoepitopes.nf create mode 100644 modules/local/predict_possible_class2_neoepitopes.nf create mode 100644 modules/local/resolve_found_class1_neoepitopes.nf create mode 100644 modules/local/resolve_found_class2_neoepitopes.nf diff --git a/modules/local/predict_possible_class1_neoepitopes.nf b/modules/local/predict_possible_class1_neoepitopes.nf new file mode 100644 index 00000000..0426d124 --- /dev/null +++ b/modules/local/predict_possible_class1_neoepitopes.nf @@ -0,0 +1,37 @@ +process PREDICT_POSSIBLE_CLASS1_NEOEPITOPES { + tag "$meta" + label 'process_low' + + conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + + input: + tuple val(meta), val(alleles), path(vcf) + + output: + tuple val(meta), path("*.csv"), emit: csv + tuple val(meta), path("*.txt"), emit: txt + path "versions.yml" , emit: versions + + script: + def prefix = task.ext.prefix ?: "${meta}_vcf_neoepitopes_class1" + + """ + vcf_neoepitope_predictor.py \\ + -t ${params.variant_annotation_style} \\ + -r ${params.variant_reference} \\ + -a '$alleles' -minl ${params.peptide_min_length} \\ + -maxl ${params.peptide_max_length} \\ + -v $vcf \\ + -o ${prefix}.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) + mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) + fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) + END_VERSIONS + """ +} diff --git a/modules/local/predict_possible_class2_neoepitopes.nf b/modules/local/predict_possible_class2_neoepitopes.nf new file mode 100644 index 00000000..af06e86c --- /dev/null +++ b/modules/local/predict_possible_class2_neoepitopes.nf @@ -0,0 +1,37 @@ +process PREDICT_POSSIBLE_CLASS2_NEOEPITOPES { + tag "$meta" + label 'process_low' + + conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + + input: + tuple val(meta), val(alleles), path(vcf) + + output: + tuple val(meta), path("*.csv"), emit: csv + tuple val(meta), path("*.txt"), emit: txt + path "versions.yml" , emit: versions + + script: + def prefix = task.ext.prefix ?: "${meta}_vcf_neoepitopes_class2" + + """ + vcf_neoepitope_predictor.py -t ${params.variant_annotation_style} \\ + -r ${params.variant_reference} \\ + -a '$alleles' \\ + -minl ${params.peptide_min_length} \\ + -maxl ${params.peptide_max_length} \\ + -v $vcf \\ + -o ${prefix}.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) + mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) + fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) + END_VERSIONS + """ +} diff --git a/modules/local/resolve_found_class1_neoepitopes.nf b/modules/local/resolve_found_class1_neoepitopes.nf new file mode 100644 index 00000000..ed2b302b --- /dev/null +++ b/modules/local/resolve_found_class1_neoepitopes.nf @@ -0,0 +1,33 @@ +process RESOLVE_FOUND_CLASS1_NEOEPITOPES { + tag "$meta.sample" + label 'process_low' + + conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + + input: + tuple val(meta), path(mztab), path(neoepitopes) + + output: + tuple val(meta), path("*.csv"), emit: csv + path "versions.yml" , emit: versions + + script: + def prefix = task.ext.prefix ?: "${meta.sample}_found_neoepitopes_class_1" + + """ + resolve_neoepitopes.py -n $neoepitopes \\ + -m $mztab \\ + -f csv \\ + -o ${prefix} + + cat <<-END_VERSIONS > versions.yml + ${task.process}: + mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) + mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//')) + fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) + END_VERSIONS + """ +} diff --git a/modules/local/resolve_found_class2_neoepitopes.nf b/modules/local/resolve_found_class2_neoepitopes.nf new file mode 100644 index 00000000..2f8e510f --- /dev/null +++ b/modules/local/resolve_found_class2_neoepitopes.nf @@ -0,0 +1,34 @@ + +process RESOLVE_FOUND_CLASS2_NEOEPITOPES { + tag "$meta" + label 'process_low' + + conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : + 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + + input: + tuple val(meta), path(mztab), path(neoepitopes) + + output: + tuple val(meta), path("*.csv"), emit: csv + path "versions.yml" , emit: versions + + script: + def prefix = task.ext.prefix ?: "${meta}_found_neoepitopes_class_2" + + """ + resolve_neoepitopes.py -n $neoepitopes \\ + -m $mztab \\ + -f csv \\ + -o ${prefix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) + mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) + fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) + END_VERSIONS + """ +} From 726ff12943b41fd5e8e71362ea17e4dbfb066f69 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 16:36:43 +0100 Subject: [PATCH 52/60] Include the tests with additional parameters again --- .github/workflows/ci.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 967c9917..dde5a265 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,3 +45,36 @@ jobs: - name: Run pipeline with test data run: | nextflow run ${GITHUB_WORKSPACE} -profile test,docker + + test_additional_params: + name: Run pipeline with additional params + # 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/mhcquant') }} + runs-on: ubuntu-latest + strategy: + matrix: + # Nextflow versions + include: + # Test pipeline minimum Nextflow version + - NXF_VER: '21.10.3' + NXF_EDGE: '' + # Test latest edge release of Nextflow + - NXF_VER: '' + NXF_EDGE: '1' + steps: + - name: Check out pipeline code + uses: actions/checkout@v2 + + - name: Install Nextflow + env: + NXF_VER: ${{ matrix.NXF_VER }} + # Uncomment only if the edge release is more recent than the latest stable release + # See https://github.com/nextflow-io/nextflow/issues/2467 + # NXF_EDGE: ${{ matrix.NXF_EDGE }} + run: | + wget -qO- get.nextflow.io | bash + sudo mv nextflow /usr/local/bin/ + + - name: Run pipeline with additional params + run: | + nextflow run ${GITHUB_WORKSPACE} -profile test,docker --predict_class_1 --predict_class_2 --predict_RT From a4af646222531a65cd785d365b3b581f35edb1a6 Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Wed, 12 Jan 2022 16:37:03 +0100 Subject: [PATCH 53/60] Update fred2 version 2.0.6 -> 2.0.7 --- CHANGELOG.md | 5 ++++- modules/local/generate_proteins_from_vcf.nf | 6 +++--- modules/local/mhcflurry_predictneoepitopesclass1.nf | 6 +++--- modules/local/mhcflurry_predictpeptidesclass1.nf | 6 +++--- modules/local/mhcflurry_predictpsms.nf | 6 +++--- modules/local/mhcnuggets_predictneoepitopesclass2.nf | 6 +++--- modules/local/mhcnuggets_predictpeptidesclass2.nf | 6 +++--- modules/local/predict_possible_class1_neoepitopes.nf | 6 +++--- modules/local/predict_possible_class2_neoepitopes.nf | 6 +++--- modules/local/resolve_found_class1_neoepitopes.nf | 6 +++--- modules/local/resolve_found_class2_neoepitopes.nf | 8 ++++---- 11 files changed, 35 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d6a5667..2c104e80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,10 +13,13 @@ - Changed parameters in the nextflow_schema.json to be in coherence with the nextflow.config - Error that was raised in generate_proteins_from_vcf -- Problems that were detected in predict_possible_neoepitopes and predict_possible_class_2_neoepitopes +- Problems that were detected in predict_possible_class1_neoepitopes and predict_possible_class2_neoepitopes - Error that occurred in mhcnuggets_predictneoepitopesclass2 (faulty container set up) ### `Dependencies` +| Dependency | Old version | New version | +| --------------------- | ----------- | ----------- | +| `fred2` | 2.0.6 | 2.0.7 | ### `Deprecated` diff --git a/modules/local/generate_proteins_from_vcf.nf b/modules/local/generate_proteins_from_vcf.nf index 428dafcf..2d86d99b 100644 --- a/modules/local/generate_proteins_from_vcf.nf +++ b/modules/local/generate_proteins_from_vcf.nf @@ -2,10 +2,10 @@ process GENERATE_PROTEINS_FROM_VCF { tag "$meta" label 'process_medium' - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : + 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" input: tuple val(meta), path(fasta), path(vcf) diff --git a/modules/local/mhcflurry_predictneoepitopesclass1.nf b/modules/local/mhcflurry_predictneoepitopesclass1.nf index da1d48ef..08e64aba 100644 --- a/modules/local/mhcflurry_predictneoepitopesclass1.nf +++ b/modules/local/mhcflurry_predictneoepitopesclass1.nf @@ -2,10 +2,10 @@ process MHCFLURRY_PREDICTNEOEPITOPESCLASS1 { tag "$meta" label 'process_low' - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : + 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" input: tuple val(meta), val(allotypes), path(neoepitopes) diff --git a/modules/local/mhcflurry_predictpeptidesclass1.nf b/modules/local/mhcflurry_predictpeptidesclass1.nf index 040caff2..93e9ab79 100644 --- a/modules/local/mhcflurry_predictpeptidesclass1.nf +++ b/modules/local/mhcflurry_predictpeptidesclass1.nf @@ -2,10 +2,10 @@ process MHCFLURRY_PREDICTPEPTIDESCLASS1 { tag "$meta" label 'process_low' - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : + 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" input: tuple val(meta), path(mztab), val(alleles) diff --git a/modules/local/mhcflurry_predictpsms.nf b/modules/local/mhcflurry_predictpsms.nf index 9f65adf7..8065590f 100644 --- a/modules/local/mhcflurry_predictpsms.nf +++ b/modules/local/mhcflurry_predictpsms.nf @@ -2,10 +2,10 @@ process MHCFLURRY_PREDICTPSMS { tag "$meta" label 'process_medium' - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : + 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" input: tuple val(meta), path(perc_mztab), path(psm_mztab), val(allotypes) diff --git a/modules/local/mhcnuggets_predictneoepitopesclass2.nf b/modules/local/mhcnuggets_predictneoepitopesclass2.nf index 31ab6961..263fffa9 100644 --- a/modules/local/mhcnuggets_predictneoepitopesclass2.nf +++ b/modules/local/mhcnuggets_predictneoepitopesclass2.nf @@ -2,10 +2,10 @@ process MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 { tag "$meta" label 'process_low' - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : + 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" input: tuple val(meta), path(neoepitopes), val(alleles) diff --git a/modules/local/mhcnuggets_predictpeptidesclass2.nf b/modules/local/mhcnuggets_predictpeptidesclass2.nf index d41207cb..2481d379 100644 --- a/modules/local/mhcnuggets_predictpeptidesclass2.nf +++ b/modules/local/mhcnuggets_predictpeptidesclass2.nf @@ -2,10 +2,10 @@ process MHCNUGGETS_PREDICTPEPTIDESCLASS2 { tag "$meta" label 'process_low' - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : + 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" input: tuple val(meta), path(peptides), val(alleles) diff --git a/modules/local/predict_possible_class1_neoepitopes.nf b/modules/local/predict_possible_class1_neoepitopes.nf index 0426d124..08dc72ad 100644 --- a/modules/local/predict_possible_class1_neoepitopes.nf +++ b/modules/local/predict_possible_class1_neoepitopes.nf @@ -2,10 +2,10 @@ process PREDICT_POSSIBLE_CLASS1_NEOEPITOPES { tag "$meta" label 'process_low' - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : + 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" input: tuple val(meta), val(alleles), path(vcf) diff --git a/modules/local/predict_possible_class2_neoepitopes.nf b/modules/local/predict_possible_class2_neoepitopes.nf index af06e86c..7b04dc56 100644 --- a/modules/local/predict_possible_class2_neoepitopes.nf +++ b/modules/local/predict_possible_class2_neoepitopes.nf @@ -2,10 +2,10 @@ process PREDICT_POSSIBLE_CLASS2_NEOEPITOPES { tag "$meta" label 'process_low' - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : + 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" input: tuple val(meta), val(alleles), path(vcf) diff --git a/modules/local/resolve_found_class1_neoepitopes.nf b/modules/local/resolve_found_class1_neoepitopes.nf index ed2b302b..99b4df8b 100644 --- a/modules/local/resolve_found_class1_neoepitopes.nf +++ b/modules/local/resolve_found_class1_neoepitopes.nf @@ -2,10 +2,10 @@ process RESOLVE_FOUND_CLASS1_NEOEPITOPES { tag "$meta.sample" label 'process_low' - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : + 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" input: tuple val(meta), path(mztab), path(neoepitopes) diff --git a/modules/local/resolve_found_class2_neoepitopes.nf b/modules/local/resolve_found_class2_neoepitopes.nf index 2f8e510f..7af38193 100644 --- a/modules/local/resolve_found_class2_neoepitopes.nf +++ b/modules/local/resolve_found_class2_neoepitopes.nf @@ -2,11 +2,11 @@ process RESOLVE_FOUND_CLASS2_NEOEPITOPES { tag "$meta" label 'process_low' - - conda (params.enable_conda ? "bioconda::fred2=2.0.6 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) + + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' : - 'quay.io/biocontainers/mulled-v2-689ae0756dd82c61400782baaa8a7a1c2289930d:a9e10ca22d4cbcabf6b54f0fb5d766ea16bb171e-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : + 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" input: tuple val(meta), path(mztab), path(neoepitopes) From 3abe10b3ea6e9707d8ce3594acd545f0f000911e Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Thu, 13 Jan 2022 17:39:30 +0100 Subject: [PATCH 54/60] Make class 1 and 2 uniform for the resolve found and predict possible neoepitopes --- .../predict_possible_class2_neoepitopes.nf | 37 ------------------- ...pes.nf => predict_possible_neoepitopes.nf} | 7 ++-- .../local/resolve_found_class1_neoepitopes.nf | 33 ----------------- ...itopes.nf => resolve_found_neoepitopes.nf} | 11 +++--- subworkflows/local/predict_class1.nf | 8 ++-- subworkflows/local/predict_class2.nf | 16 ++++---- 6 files changed, 21 insertions(+), 91 deletions(-) delete mode 100644 modules/local/predict_possible_class2_neoepitopes.nf rename modules/local/{predict_possible_class1_neoepitopes.nf => predict_possible_neoepitopes.nf} (92%) delete mode 100644 modules/local/resolve_found_class1_neoepitopes.nf rename modules/local/{resolve_found_class2_neoepitopes.nf => resolve_found_neoepitopes.nf} (90%) diff --git a/modules/local/predict_possible_class2_neoepitopes.nf b/modules/local/predict_possible_class2_neoepitopes.nf deleted file mode 100644 index 7b04dc56..00000000 --- a/modules/local/predict_possible_class2_neoepitopes.nf +++ /dev/null @@ -1,37 +0,0 @@ -process PREDICT_POSSIBLE_CLASS2_NEOEPITOPES { - tag "$meta" - label 'process_low' - - conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : - 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" - - input: - tuple val(meta), val(alleles), path(vcf) - - output: - tuple val(meta), path("*.csv"), emit: csv - tuple val(meta), path("*.txt"), emit: txt - path "versions.yml" , emit: versions - - script: - def prefix = task.ext.prefix ?: "${meta}_vcf_neoepitopes_class2" - - """ - vcf_neoepitope_predictor.py -t ${params.variant_annotation_style} \\ - -r ${params.variant_reference} \\ - -a '$alleles' \\ - -minl ${params.peptide_min_length} \\ - -maxl ${params.peptide_max_length} \\ - -v $vcf \\ - -o ${prefix}.csv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) - mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) - fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) - END_VERSIONS - """ -} diff --git a/modules/local/predict_possible_class1_neoepitopes.nf b/modules/local/predict_possible_neoepitopes.nf similarity index 92% rename from modules/local/predict_possible_class1_neoepitopes.nf rename to modules/local/predict_possible_neoepitopes.nf index 08dc72ad..c4192643 100644 --- a/modules/local/predict_possible_class1_neoepitopes.nf +++ b/modules/local/predict_possible_neoepitopes.nf @@ -1,4 +1,4 @@ -process PREDICT_POSSIBLE_CLASS1_NEOEPITOPES { +process PREDICT_POSSIBLE_NEOEPITOPES { tag "$meta" label 'process_low' @@ -16,13 +16,14 @@ process PREDICT_POSSIBLE_CLASS1_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = task.ext.prefix ?: "${meta}_vcf_neoepitopes_class1" + def prefix = task.ext.prefix ?: "${meta}_vcf_neoepitopes" """ vcf_neoepitope_predictor.py \\ -t ${params.variant_annotation_style} \\ -r ${params.variant_reference} \\ - -a '$alleles' -minl ${params.peptide_min_length} \\ + -a '$alleles' \\ + -minl ${params.peptide_min_length} \\ -maxl ${params.peptide_max_length} \\ -v $vcf \\ -o ${prefix}.csv diff --git a/modules/local/resolve_found_class1_neoepitopes.nf b/modules/local/resolve_found_class1_neoepitopes.nf deleted file mode 100644 index 99b4df8b..00000000 --- a/modules/local/resolve_found_class1_neoepitopes.nf +++ /dev/null @@ -1,33 +0,0 @@ -process RESOLVE_FOUND_CLASS1_NEOEPITOPES { - tag "$meta.sample" - label 'process_low' - - conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : - 'quay.io/biocontainers/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' }" - - input: - tuple val(meta), path(mztab), path(neoepitopes) - - output: - tuple val(meta), path("*.csv"), emit: csv - path "versions.yml" , emit: versions - - script: - def prefix = task.ext.prefix ?: "${meta.sample}_found_neoepitopes_class_1" - - """ - resolve_neoepitopes.py -n $neoepitopes \\ - -m $mztab \\ - -f csv \\ - -o ${prefix} - - cat <<-END_VERSIONS > versions.yml - ${task.process}: - mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) - mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//')) - fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) - END_VERSIONS - """ -} diff --git a/modules/local/resolve_found_class2_neoepitopes.nf b/modules/local/resolve_found_neoepitopes.nf similarity index 90% rename from modules/local/resolve_found_class2_neoepitopes.nf rename to modules/local/resolve_found_neoepitopes.nf index 7af38193..ce5bb7f4 100644 --- a/modules/local/resolve_found_class2_neoepitopes.nf +++ b/modules/local/resolve_found_neoepitopes.nf @@ -1,8 +1,7 @@ - -process RESOLVE_FOUND_CLASS2_NEOEPITOPES { +process RESOLVE_FOUND_NEOEPITOPES { tag "$meta" label 'process_low' - + conda (params.enable_conda ? "bioconda::fred2=2.0.7 bioconda::mhcflurry=1.4.3 bioconda::mhcnuggets=2.3.2" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-c3f301504f7fa2e7bf81c3783de19a9990ea3001:12b1b9f040fd92a80629d58f8a558dde4820eb15-0' : @@ -16,7 +15,7 @@ process RESOLVE_FOUND_CLASS2_NEOEPITOPES { path "versions.yml" , emit: versions script: - def prefix = task.ext.prefix ?: "${meta}_found_neoepitopes_class_2" + def prefix = task.ext.prefix ?: "${meta}_found_neoepitopes" """ resolve_neoepitopes.py -n $neoepitopes \\ @@ -25,9 +24,9 @@ process RESOLVE_FOUND_CLASS2_NEOEPITOPES { -o ${prefix} cat <<-END_VERSIONS > versions.yml - "${task.process}": + ${task.process}: mhcflurry: \$(echo \$(mhcflurry-predict --version 2>&1 | sed 's/^mhcflurry //; s/ .*\$//') ) - mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//' )) + mhcnuggets: \$(echo \$(python -c "import pkg_resources; print('mhcnuggets' + pkg_resources.get_distribution('mhcnuggets').version)" | sed 's/^mhcnuggets//; s/ .*\$//')) fred2: \$(echo \$(python -c "import pkg_resources; print('fred2' + pkg_resources.get_distribution('Fred2').version)" | sed 's/^fred2//; s/ .*\$//')) END_VERSIONS """ diff --git a/subworkflows/local/predict_class1.nf b/subworkflows/local/predict_class1.nf index ca709d42..70532717 100644 --- a/subworkflows/local/predict_class1.nf +++ b/subworkflows/local/predict_class1.nf @@ -2,10 +2,10 @@ * Perform the class 1 prediction when the parameter --predict_class_1 is provided and --skip_quantification is not */ -include { MHCFLURRY_PREDICTPEPTIDESCLASS1 } from '../../modules/local/mhcflurry_predictpeptidesclass1' -include { PREDICT_POSSIBLE_CLASS1_NEOEPITOPES } from '../../modules/local/predict_possible_class1_neoepitopes' -include { RESOLVE_FOUND_CLASS1_NEOEPITOPES } from '../../modules/local/resolve_found_class1_neoepitopes' -include { MHCFLURRY_PREDICTNEOEPITOPESCLASS1 } from '../../modules/local/mhcflurry_predictneoepitopesclass1' +include { MHCFLURRY_PREDICTPEPTIDESCLASS1 } from '../../modules/local/mhcflurry_predictpeptidesclass1' +include { PREDICT_POSSIBLE_NEOEPITOPES as PREDICT_POSSIBLE_CLASS1_NEOEPITOPES } from '../../modules/local/predict_possible_neoepitopes' +include { RESOLVE_FOUND_NEOEPITOPES as RESOLVE_FOUND_CLASS1_NEOEPITOPES } from '../../modules/local/resolve_found_neoepitopes' +include { MHCFLURRY_PREDICTNEOEPITOPESCLASS1 } from '../../modules/local/mhcflurry_predictneoepitopesclass1' workflow PREDICT_CLASS1 { take: diff --git a/subworkflows/local/predict_class2.nf b/subworkflows/local/predict_class2.nf index 3513f854..4baa282d 100644 --- a/subworkflows/local/predict_class2.nf +++ b/subworkflows/local/predict_class2.nf @@ -2,14 +2,14 @@ * Perform the class 2 prediction when the parameter --predict_class_2 is provided and --skip_quantification is not */ -include { MHCNUGGETS_PEPTIDESCLASS2PRE } from '../../modules/local/mhcnuggets_peptidesclass2pre' -include { MHCNUGGETS_PREDICTPEPTIDESCLASS2 } from '../../modules/local/mhcnuggets_predictpeptidesclass2' -include { MHCNUGGETS_PEPTIDESCLASS2POST } from '../../modules/local/mhcnuggets_peptidesclass2post' -include { PREDICT_POSSIBLE_CLASS2_NEOEPITOPES } from '../../modules/local/predict_possible_class2_neoepitopes' -include { RESOLVE_FOUND_CLASS2_NEOEPITOPES } from '../../modules/local/resolve_found_class2_neoepitopes' -include { MHCNUGGETS_NEOEPITOPESCLASS2PRE } from '../../modules/local/mhcnuggets_neoepitopesclass2pre' -include { MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 } from '../../modules/local/mhcnuggets_predictneoepitopesclass2' -include { MHCNUGGETS_NEOEPITOPESCLASS2POST } from '../../modules/local/mhcnuggets_neoepitopesclass2post' +include { MHCNUGGETS_PEPTIDESCLASS2PRE } from '../../modules/local/mhcnuggets_peptidesclass2pre' +include { MHCNUGGETS_PREDICTPEPTIDESCLASS2 } from '../../modules/local/mhcnuggets_predictpeptidesclass2' +include { MHCNUGGETS_PEPTIDESCLASS2POST } from '../../modules/local/mhcnuggets_peptidesclass2post' +include { PREDICT_POSSIBLE_NEOEPITOPES as PREDICT_POSSIBLE_CLASS2_NEOEPITOPES } from '../../modules/local/predict_possible_neoepitopes' +include { RESOLVE_FOUND_NEOEPITOPES as RESOLVE_FOUND_CLASS2_NEOEPITOPES } from '../../modules/local/resolve_found_neoepitopes' +include { MHCNUGGETS_NEOEPITOPESCLASS2PRE } from '../../modules/local/mhcnuggets_neoepitopesclass2pre' +include { MHCNUGGETS_PREDICTNEOEPITOPESCLASS2 } from '../../modules/local/mhcnuggets_predictneoepitopesclass2' +include { MHCNUGGETS_NEOEPITOPESCLASS2POST } from '../../modules/local/mhcnuggets_neoepitopesclass2post' workflow PREDICT_CLASS2 { take: From 602bb03f2d980a2ec5fbfbae939ca1ebd3726dea Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Thu, 13 Jan 2022 17:42:16 +0100 Subject: [PATCH 55/60] Adjust the PREDICT_POSSIBLE* and RESOLVE_FOUND* processes --- conf/modules.config | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 4dd79612..882dfb29 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -247,14 +247,16 @@ process { if ( params.predict_class_1 & !params.skip_quantification & params.include_proteins_from_vcf ) { withName: PREDICT_POSSIBLE_CLASS1_NEOEPITOPES { + ext.prefix = { "${meta}_vcf_neoepitopes" } publishDir = [ - path: {"${params.outdir}/"}, - mode: 'copy', - pattern: '*.csv' + path: {"${params.outdir}/class_1_bindings"}, + mode: 'copy', + pattern: '*.csv' ] } - withName: RESOLVE_FOUND_CLASS_1_NEOEPITOPES { + withName: RESOLVE_FOUND_CLASS1_NEOEPITOPES { + ext.prefix = { "${meta.sample}_found_neoepitopes" } publishDir = [ path: {"${params.outdir}/class_1_bindings"}, mode: 'copy', @@ -306,7 +308,7 @@ process { withName: PREDICT_POSSIBLE_CLASS2_NEOEPITOPES { publishDir = [ - path: { "${params.outdir}" }, + path: { "${params.outdir}/class_2_bindings" }, mode: 'copy', pattern: '*.csv' ] From 8ea5bca5c25ecab7afe47efb97919153df71ff9a Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Thu, 13 Jan 2022 17:42:58 +0100 Subject: [PATCH 56/60] Change the specification of the parameters --- modules/local/openms_thermorawfileparser.nf | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/local/openms_thermorawfileparser.nf b/modules/local/openms_thermorawfileparser.nf index b585be4a..b2541369 100644 --- a/modules/local/openms_thermorawfileparser.nf +++ b/modules/local/openms_thermorawfileparser.nf @@ -18,9 +18,10 @@ process OPENMS_THERMORAWFILEPARSER { def prefix = task.ext.prefix ?: "${rawfile.baseName}" """ - ThermoRawFileParser.sh -i=$rawfile \\ - -f=2 \\ - -b=${prefix}.mzML + ThermoRawFileParser.sh \\ + -i $rawfile \\ + -f 2 \\ + -b ${prefix}.mzML cat <<-END_VERSIONS > versions.yml "${task.process}": From 849b906e285cc55cc094bd27eb09926d41ad053b Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Thu, 13 Jan 2022 17:44:52 +0100 Subject: [PATCH 57/60] Change the versioning of the different processes, clean format --- workflows/mhcquant.nf | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/workflows/mhcquant.nf b/workflows/mhcquant.nf index 5f22c2f0..94384ca8 100644 --- a/workflows/mhcquant.nf +++ b/workflows/mhcquant.nf @@ -121,7 +121,7 @@ workflow MHCQUANT { if ( params.include_proteins_from_vcf ) { // Include the proteins from the vcf file to the fasta file INCLUDE_PROTEINS( input_fasta ) - ch_versions = ch_versions.mix(INCLUDE_PROTEINS.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(INCLUDE_PROTEINS.out.versions.ifEmpty(null)) ch_fasta_file = INCLUDE_PROTEINS.out.ch_fasta_file ch_vcf_from_sheet = INCLUDE_PROTEINS.out.ch_vcf_from_sheet } else { @@ -132,7 +132,7 @@ workflow MHCQUANT { if (!params.skip_decoy_generation) { // Generate reversed decoy database OPENMS_DECOYDATABASE(ch_fasta_file) - ch_versions = ch_versions.mix(OPENMS_DECOYDATABASE.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(OPENMS_DECOYDATABASE.out.versions.ifEmpty(null)) ch_decoy_db = OPENMS_DECOYDATABASE.out.decoy } else { ch_decoy_db = ch_fasta_file @@ -140,11 +140,11 @@ workflow MHCQUANT { // Raw file conversion OPENMS_THERMORAWFILEPARSER(ms_files.raw) - ch_versions = ch_versions.mix(OPENMS_THERMORAWFILEPARSER.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(OPENMS_THERMORAWFILEPARSER.out.versions.ifEmpty(null)) if ( params.run_centroidisation ) { // Optional: Run Peak Picking as Preprocessing OPENMS_PEAKPICKERHIRES(ms_files.mzml) - ch_versions = ch_versions.mix(OPENMS_PEAKPICKERHIRES.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(OPENMS_PEAKPICKERHIRES.out.versions.ifEmpty(null)) ch_mzml_file = OPENMS_PEAKPICKERHIRES.out.mzml } else { ch_mzml_file = ms_files.mzml @@ -154,10 +154,10 @@ workflow MHCQUANT { OPENMS_THERMORAWFILEPARSER.out.mzml .mix(ch_mzml_file) .join(ch_decoy_db, remainder:true)) - ch_versions = ch_versions.mix(OPENMS_COMETADAPTER.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(OPENMS_COMETADAPTER.out.versions.ifEmpty(null)) // Index decoy and target hits OPENMS_PEPTIDEINDEXER(OPENMS_COMETADAPTER.out.idxml.join(ch_decoy_db)) - ch_versions = ch_versions.mix(OPENMS_PEPTIDEINDEXER.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(OPENMS_PEPTIDEINDEXER.out.versions.ifEmpty(null)) // // SUBWORKFLOW: Pre-process step for the quantification of the data @@ -170,7 +170,7 @@ workflow MHCQUANT { OPENMS_THERMORAWFILEPARSER.out.mzml ) ch_proceeding_idx = PRE_QUANTIFICATION.out.ch_proceeding_idx - ch_versions = ch_versions.mix(PRE_QUANTIFICATION.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(PRE_QUANTIFICATION.out.versions.ifEmpty(null)) } else { ch_proceeding_idx = OPENMS_PEPTIDEINDEXER.out.idxml .map { @@ -182,18 +182,17 @@ workflow MHCQUANT { // Merge aligned idXMLfiles OPENMS_IDMERGER(ch_proceeding_idx) - ch_versions = ch_versions.mix(OPENMS_IDMERGER.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(OPENMS_IDMERGER.out.versions.ifEmpty(null)) // Extract PSM features for Percolator OPENMS_PSMFEATUREEXTRACTOR(OPENMS_IDMERGER.out.idxml) - ch_versions = ch_versions.mix(OPENMS_PSMFEATUREEXTRACTOR.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(OPENMS_PSMFEATUREEXTRACTOR.out.versions.ifEmpty(null)) // Run Percolator OPENMS_PERCOLATORADAPTER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) - ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions.ifEmpty(null)) ch_percolator_adapter_outcome = OPENMS_PERCOLATORADAPTER.out.idxml - // } // Filter by percolator q-value OPENMS_IDFILTER_Q_VALUE(ch_percolator_adapter_outcome.flatMap { it -> [tuple(it[0], it[1], null)]}) - ch_versions = ch_versions.mix(OPENMS_IDFILTER_Q_VALUE.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(OPENMS_IDFILTER_Q_VALUE.out.versions.ifEmpty(null)) // // SUBWORKFLOW: Refine the FDR values on the predicted subset @@ -205,7 +204,7 @@ workflow MHCQUANT { OPENMS_PSMFEATUREEXTRACTOR.out.idxml, peptides_class_1_alleles ) - ch_versions = ch_versions.mix(REFINE_FDR.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(REFINE_FDR.out.versions.ifEmpty(null)) // Define the outcome of the paramer to a fixed variable filter_q_value = REFINE_FDR.out.filter_refined_q_value.flatMap { it -> [ tuple(it[0].sample, it[0], it[1]) ] } } else { @@ -222,7 +221,7 @@ workflow MHCQUANT { PRE_QUANTIFICATION.out.aligned_mzml, filter_q_value ) - ch_versions = ch_versions.mix(POST_QUANTIFICATION.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(POST_QUANTIFICATION.out.versions.ifEmpty(null)) } // @@ -234,7 +233,7 @@ workflow MHCQUANT { peptides_class_1_alleles, ch_vcf_from_sheet ) - ch_versions = ch_versions.mix(PREDICT_CLASS1.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(PREDICT_CLASS1.out.versions.ifEmpty(null)) ch_predicted_possible_neoepitopes = PREDICT_CLASS1.out.ch_predicted_possible_neoepitopes } else { ch_predicted_possible_neoepitopes = Channel.empty() @@ -249,7 +248,7 @@ workflow MHCQUANT { peptides_class_2_alleles, ch_vcf_from_sheet ) - ch_versions = ch_versions.mix(PREDICT_CLASS2.out.versions.first().ifEmpty(null)) + ch_versions = ch_versions.mix(PREDICT_CLASS2.out.versions.ifEmpty(null)) ch_predicted_possible_neoepitopes_II = PREDICT_CLASS2.out.ch_predicted_possible_neoepitopes } else { ch_predicted_possible_neoepitopes_II = Channel.empty() From 470da54d7407e9446d37af547e3ec9f3b6020fff Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Thu, 13 Jan 2022 17:58:05 +0100 Subject: [PATCH 58/60] Resolve linting conflict --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c104e80..1bec0316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - Error that occurred in mhcnuggets_predictneoepitopesclass2 (faulty container set up) ### `Dependencies` + | Dependency | Old version | New version | | --------------------- | ----------- | ----------- | | `fred2` | 2.0.6 | 2.0.7 | From 2a3edbd72833b55e2ea6059112457ca00f6b73cd Mon Sep 17 00:00:00 2001 From: marissaDubbelaar Date: Thu, 13 Jan 2022 18:41:14 +0100 Subject: [PATCH 59/60] Change the concatenating step --- bin/variants2fasta.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/bin/variants2fasta.py b/bin/variants2fasta.py index 5597f5bb..33c63f26 100755 --- a/bin/variants2fasta.py +++ b/bin/variants2fasta.py @@ -205,19 +205,16 @@ def main(): #concatenate fasta file with fasta reference - op=open(args.output) - opr1=op.read() - op.close() + with open(args.output) as op: + opr1 = op.read() - op=open(args.fasta_ref) - opr2=op.read() - op.close() + with open(args.fasta_ref) as op: + opr2 = op.read() - concat=opr1+opr2 + concat = opr1+opr2 - op=open(args.output,'w') - op.write(concat) - op.close() + with open(args.output, "w") as op: + op.write(concat) else: sys.stderr.write("At least a vcf file or a protein id file has to be provided.\n") From 7714e55b5c130ec6b3da2bc6388d6fca392e4384 Mon Sep 17 00:00:00 2001 From: Marissa Dubbelaar <71317334+marissaDubbelaar@users.noreply.github.com> Date: Fri, 14 Jan 2022 16:28:49 +0100 Subject: [PATCH 60/60] Add date of the version to CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bec0316..b493caef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # nf-core/mhcquant: Changelog -## v2.2.0 nfcore/mhcquant "Silver Titanium Ostrich" - 2021/mm/dd +## v2.2.0 nfcore/mhcquant "Silver Titanium Ostrich" - 2021/01/14 ### `Added`