From 8e1c9938c121105ed897ee70ba2b0458f06033a9 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 30 Aug 2022 13:31:19 +0000 Subject: [PATCH 01/56] Template update for nf-core/tools version 2.5 --- .editorconfig | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 3 +- .github/workflows/ci.yml | 23 ++------ .github/workflows/linting.yml | 38 +++++++++++-- CHANGELOG.md | 2 +- CITATION.cff | 56 +++++++++++++++++++ README.md | 21 +++---- assets/email_template.txt | 1 - bin/check_samplesheet.py | 41 +++++++------- conf/base.config | 5 ++ docs/usage.md | 12 ++-- lib/WorkflowMain.groovy | 9 ++- lib/WorkflowNanoseq.groovy | 5 +- main.nf | 2 +- modules.json | 22 +++++--- .../templates/dumpsoftwareversions.py | 14 +++-- nextflow.config | 23 +++++++- 17 files changed, 186 insertions(+), 93 deletions(-) create mode 100644 CITATION.cff diff --git a/.editorconfig b/.editorconfig index b6b31907..b78de6e6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,7 +8,7 @@ trim_trailing_whitespace = true indent_size = 4 indent_style = space -[*.{md,yml,yaml,html,css,scss,js}] +[*.{md,yml,yaml,html,css,scss,js,cff}] indent_size = 2 # These files are edited and tested upstream in nf-core/modules diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e7000854..329a6614 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,8 +15,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/nano - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! - - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/nanoseq/tree/master/.github/CONTRIBUTING.md) - - [ ] If necessary, also make a PR on the nf-core/nanoseq _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/nanoseq/tree/master/.github/CONTRIBUTING.md)- [ ] If necessary, also make a PR on the nf-core/nanoseq _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88e2cfcd..f60b77e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,6 @@ on: env: NXF_ANSI_LOG: false - CAPSULE_LOG: none jobs: test: @@ -20,27 +19,17 @@ jobs: 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" + NXF_VER: + - "21.10.3" + - "latest-everything" 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/ + uses: nf-core/setup-nextflow@v1 + with: + version: "${{ matrix.NXF_VER }}" - name: Run pipeline with test data # TODO nf-core: You can customise CI pipeline run tests as required diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 77358dee..8a5ce69b 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -35,6 +35,36 @@ jobs: - name: Run Prettier --check run: prettier --check ${GITHUB_WORKSPACE} + PythonBlack: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Check code lints with Black + uses: psf/black@stable + + # If the above check failed, post a comment on the PR explaining the failure + - name: Post PR comment + if: failure() + uses: mshick/add-pr-comment@v1 + with: + message: | + ## Python linting (`black`) is failing + + To keep the code consistent with lots of contributors, we run automated code consistency checks. + To fix this CI test, please run: + + * Install [`black`](https://black.readthedocs.io/en/stable/): `pip install black` + * Fix formatting errors in your pipeline: `black .` + + Once you push these changes the test should pass, and you can hide this comment :+1: + + We highly recommend setting up Black in your code editor so that this formatting is done automatically on save. Ask about it on Slack for help! + + Thanks again for your contribution! + repo-token: ${{ secrets.GITHUB_TOKEN }} + allow-repeats: false + nf-core: runs-on: ubuntu-latest steps: @@ -42,15 +72,11 @@ jobs: uses: actions/checkout@v2 - name: Install Nextflow - env: - CAPSULE_LOG: none - run: | - wget -qO- get.nextflow.io | bash - sudo mv nextflow /usr/local/bin/ + uses: nf-core/setup-nextflow@v1 - uses: actions/setup-python@v3 with: - python-version: "3.6" + python-version: "3.7" architecture: "x64" - name: Install dependencies diff --git a/CHANGELOG.md b/CHANGELOG.md index bbaaa186..9a649bfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v2.0.1 - [date] +## v3.0.0 - [date] Initial release of nf-core/nanoseq, created with the [nf-core](https://nf-co.re/) template. diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 00000000..4533e2f2 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,56 @@ +cff-version: 1.2.0 +message: "If you use `nf-core tools` in your work, please cite the `nf-core` publication" +authors: + - family-names: Ewels + given-names: Philip + - family-names: Peltzer + given-names: Alexander + - family-names: Fillinger + given-names: Sven + - family-names: Patel + given-names: Harshil + - family-names: Alneberg + given-names: Johannes + - family-names: Wilm + given-names: Andreas + - family-names: Ulysse Garcia + given-names: Maxime + - family-names: Di Tommaso + given-names: Paolo + - family-names: Nahnsen + given-names: Sven +title: "The nf-core framework for community-curated bioinformatics pipelines." +version: 2.4.1 +doi: 10.1038/s41587-020-0439-x +date-released: 2022-05-16 +url: https://github.com/nf-core/tools +prefered-citation: + type: article + authors: + - family-names: Ewels + given-names: Philip + - family-names: Peltzer + given-names: Alexander + - family-names: Fillinger + given-names: Sven + - family-names: Patel + given-names: Harshil + - family-names: Alneberg + given-names: Johannes + - family-names: Wilm + given-names: Andreas + - family-names: Ulysse Garcia + given-names: Maxime + - family-names: Di Tommaso + given-names: Paolo + - family-names: Nahnsen + given-names: Sven + doi: 10.1038/s41587-020-0439-x + journal: nature biotechnology + start: 276 + end: 278 + title: "The nf-core framework for community-curated bioinformatics pipelines." + issue: 3 + volume: 38 + year: 2020 + url: https://dx.doi.org/10.1038/s41587-020-0439-x diff --git a/README.md b/README.md index 862914d4..569efb78 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,14 @@ # ![nf-core/nanoseq](docs/images/nf-core-nanoseq_logo_light.png#gh-light-mode-only) ![nf-core/nanoseq](docs/images/nf-core-nanoseq_logo_dark.png#gh-dark-mode-only) -[![GitHub Actions CI Status](https://github.com/nf-core/nanoseq/workflows/nf-core%20CI/badge.svg)](https://github.com/nf-core/nanoseq/actions?query=workflow%3A%22nf-core+CI%22) -[![GitHub Actions Linting Status](https://github.com/nf-core/nanoseq/workflows/nf-core%20linting/badge.svg)](https://github.com/nf-core/nanoseq/actions?query=workflow%3A%22nf-core+linting%22) -[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?logo=Amazon%20AWS)](https://nf-co.re/nanoseq/results) -[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8)](https://doi.org/10.5281/zenodo.XXXXXXX) +[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/nanoseq/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg)](https://www.nextflow.io/) -[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?logo=anaconda)](https://docs.conda.io/en/latest/) -[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?logo=docker)](https://www.docker.com/) -[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg)](https://sylabs.io/docs/) +[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) +[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) +[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) [![Launch on Nextflow Tower](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/nanoseq) -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23nanoseq-4A154B?logo=slack)](https://nfcore.slack.com/channels/nanoseq) -[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?logo=twitter)](https://twitter.com/nf_core) -[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?logo=youtube)](https://www.youtube.com/c/nf-core) +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23nanoseq-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/nanoseq)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) ## Introduction @@ -25,7 +20,7 @@ The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool -On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources. The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/nanoseq/results). +On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources.The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/nanoseq/results). ## Pipeline summary @@ -42,7 +37,7 @@ On release, automated continuous integration tests run the pipeline on a full-si 3. Download the pipeline and test it on a minimal dataset with a single command: - ```console + ```bash nextflow run nf-core/nanoseq -profile test,YOURPROFILE --outdir ``` @@ -57,7 +52,7 @@ On release, automated continuous integration tests run the pipeline on a full-si - ```console + ```bash nextflow run nf-core/nanoseq --input samplesheet.csv --outdir --genome GRCh37 -profile ``` diff --git a/assets/email_template.txt b/assets/email_template.txt index 88c70f16..5814aa9b 100644 --- a/assets/email_template.txt +++ b/assets/email_template.txt @@ -6,7 +6,6 @@ `._,._,' nf-core/nanoseq v${version} ---------------------------------------------------- - Run Name: $runName <% if (success){ diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 3652c63c..9a8b8962 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -11,7 +11,6 @@ from collections import Counter from pathlib import Path - logger = logging.getLogger() @@ -79,13 +78,15 @@ def validate_and_transform(self, row): def _validate_sample(self, row): """Assert that the sample name exists and convert spaces to underscores.""" - assert len(row[self._sample_col]) > 0, "Sample input is required." + if len(row[self._sample_col]) <= 0: + raise AssertionError("Sample input is required.") # Sanitize samples slightly. row[self._sample_col] = row[self._sample_col].replace(" ", "_") def _validate_first(self, row): """Assert that the first FASTQ entry is non-empty and has the right format.""" - assert len(row[self._first_col]) > 0, "At least the first FASTQ file is required." + if len(row[self._first_col]) <= 0: + raise AssertionError("At least the first FASTQ file is required.") self._validate_fastq_format(row[self._first_col]) def _validate_second(self, row): @@ -97,36 +98,34 @@ def _validate_pair(self, row): """Assert that read pairs have the same file extension. Report pair status.""" if row[self._first_col] and row[self._second_col]: row[self._single_col] = False - assert ( - Path(row[self._first_col]).suffixes[-2:] == Path(row[self._second_col]).suffixes[-2:] - ), "FASTQ pairs must have the same file extensions." + if Path(row[self._first_col]).suffixes[-2:] != Path(row[self._second_col]).suffixes[-2:]: + raise AssertionError("FASTQ pairs must have the same file extensions.") else: row[self._single_col] = True def _validate_fastq_format(self, filename): """Assert that a given filename has one of the expected FASTQ extensions.""" - assert any(filename.endswith(extension) for extension in self.VALID_FORMATS), ( - f"The FASTQ file has an unrecognized extension: {filename}\n" - f"It should be one of: {', '.join(self.VALID_FORMATS)}" - ) + if not any(filename.endswith(extension) for extension in self.VALID_FORMATS): + raise AssertionError( + f"The FASTQ file has an unrecognized extension: {filename}\n" + f"It should be one of: {', '.join(self.VALID_FORMATS)}" + ) def validate_unique_samples(self): """ Assert that the combination of sample name and FASTQ filename is unique. - In addition to the validation, also rename the sample if more than one sample, - FASTQ file combination exists. + In addition to the validation, also rename all samples to have a suffix of _T{n}, where n is the + number of times the same sample exist, but with different FASTQ files, e.g., multiple runs per experiment. """ - assert len(self._seen) == len(self.modified), "The pair of sample name and FASTQ must be unique." - if len({pair[0] for pair in self._seen}) < len(self._seen): - counts = Counter(pair[0] for pair in self._seen) - seen = Counter() - for row in self.modified: - sample = row[self._sample_col] - seen[sample] += 1 - if counts[sample] > 1: - row[self._sample_col] = f"{sample}_T{seen[sample]}" + if len(self._seen) != len(self.modified): + raise AssertionError("The pair of sample name and FASTQ must be unique.") + seen = Counter() + for row in self.modified: + sample = row[self._sample_col] + seen[sample] += 1 + row[self._sample_col] = f"{sample}_T{seen[sample]}" def read_head(handle, num_lines=10): diff --git a/conf/base.config b/conf/base.config index ba9cb8b0..94e77639 100644 --- a/conf/base.config +++ b/conf/base.config @@ -26,6 +26,11 @@ process { // adding in your local modules too. // TODO nf-core: Customise requirements for specific processes. // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors + withLabel:process_single { + cpus = { check_max( 1 , 'cpus' ) } + memory = { check_max( 6.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } + } withLabel:process_low { cpus = { check_max( 2 * task.attempt, 'cpus' ) } memory = { check_max( 12.GB * task.attempt, 'memory' ) } diff --git a/docs/usage.md b/docs/usage.md index f9b7aaeb..642fd017 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -12,7 +12,7 @@ You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row as shown in the examples below. -```console +```bash --input '[path to samplesheet file]' ``` @@ -56,7 +56,7 @@ An [example samplesheet](../assets/samplesheet.csv) has been provided with the p The typical command for running the pipeline is as follows: -```console +```bash nextflow run nf-core/nanoseq --input samplesheet.csv --outdir --genome GRCh37 -profile docker ``` @@ -64,9 +64,9 @@ This will launch the pipeline with the `docker` configuration profile. See below Note that the pipeline will create the following files in your working directory: -```console +```bash work # Directory containing the nextflow working files - # Finished results in specified location (defined with --outdir) + # Finished results in specified location (defined with --outdir) .nextflow_log # Log file from Nextflow # Other nextflow hidden files, eg. history of pipeline runs and old logs. ``` @@ -75,7 +75,7 @@ work # Directory containing the nextflow working files When you run the above command, Nextflow automatically pulls the pipeline code from GitHub and stores it as a cached version. When running the pipeline after this, it will always use the cached version if available - even if the pipeline has been updated since. To make sure that you're running the latest version of the pipeline, make sure that you regularly update the cached version of the pipeline: -```console +```bash nextflow pull nf-core/nanoseq ``` @@ -251,6 +251,6 @@ Some HPC setups also allow you to run nextflow within a cluster job submitted yo In some cases, the Nextflow Java virtual machines can start to request a large amount of memory. We recommend adding the following line to your environment to limit this (typically in `~/.bashrc` or `~./bash_profile`): -```console +```bash NXF_OPTS='-Xms1g -Xmx4g' ``` diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 9ad8f1ae..20c7ed32 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -59,6 +59,7 @@ 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 @@ -78,17 +79,15 @@ class WorkflowMain { System.exit(1) } } - // // Get attribute from genome config file e.g. fasta // - public static String getGenomeAttribute(params, attribute) { - def val = '' + public static Object getGenomeAttribute(params, attribute) { if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { if (params.genomes[ params.genome ].containsKey(attribute)) { - val = params.genomes[ params.genome ][ attribute ] + return params.genomes[ params.genome ][ attribute ] } } - return val + return null } } diff --git a/lib/WorkflowNanoseq.groovy b/lib/WorkflowNanoseq.groovy index 25a920e9..f71f85d1 100755 --- a/lib/WorkflowNanoseq.groovy +++ b/lib/WorkflowNanoseq.groovy @@ -10,6 +10,7 @@ class WorkflowNanoseq { public static void initialise(params, log) { genomeExistsError(params, log) + if (!params.fasta) { log.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." System.exit(1) @@ -41,9 +42,7 @@ class WorkflowNanoseq { yaml_file_text += "data: |\n" yaml_file_text += "${summary_section}" return yaml_file_text - } - - // + }// // Exit pipeline if incorrect --genome key provided // private static void genomeExistsError(params, log) { diff --git a/main.nf b/main.nf index afc83081..889ce148 100644 --- a/main.nf +++ b/main.nf @@ -4,7 +4,7 @@ nf-core/nanoseq ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Github : https://github.com/nf-core/nanoseq - Website: https://nf-co.re/nanoseq +Website: https://nf-co.re/nanoseq Slack : https://nfcore.slack.com/channels/nanoseq ---------------------------------------------------------------------------------------- */ diff --git a/modules.json b/modules.json index f50f9428..35e1bb01 100644 --- a/modules.json +++ b/modules.json @@ -3,14 +3,20 @@ "homePage": "https://github.com/nf-core/nanoseq", "repos": { "nf-core/modules": { - "custom/dumpsoftwareversions": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "fastqc": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "multiqc": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" + "git_url": "https://github.com/nf-core/modules.git", + "modules": { + "custom/dumpsoftwareversions": { + "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", + "branch": "master" + }, + "fastqc": { + "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", + "branch": "master" + }, + "multiqc": { + "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", + "branch": "master" + } } } } diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py index d1390392..787bdb7b 100644 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -1,9 +1,10 @@ #!/usr/bin/env python -import yaml import platform from textwrap import dedent +import yaml + def _make_versions_html(versions): html = [ @@ -58,11 +59,12 @@ def _make_versions_html(versions): 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. " - ) + if versions_by_module[module] != process_versions: + raise AssertionError( + "We assume that software versions are the same between all modules. " + "If you see this error-message it means you discovered an edge-case " + "and should open an issue in nf-core/tools. " + ) except KeyError: versions_by_module[module] = process_versions diff --git a/nextflow.config b/nextflow.config index f0a21191..285286e3 100644 --- a/nextflow.config +++ b/nextflow.config @@ -13,11 +13,11 @@ params { // Input options input = null + // References genome = null igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false - // MultiQC options multiqc_config = null multiqc_title = null @@ -37,6 +37,7 @@ params { schema_ignore_params = 'genomes' enable_conda = false + // Config options custom_config_version = 'master' custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" @@ -45,6 +46,7 @@ params { config_profile_url = null config_profile_name = null + // Max resource options // Defaults only, expecting to be overwritten max_memory = '128.GB' @@ -72,6 +74,7 @@ try { // } + profiles { debug { process.beforeScript = 'echo $HOSTNAME' } conda { @@ -82,6 +85,15 @@ profiles { shifter.enabled = false charliecloud.enabled = false } + mamba { + params.enable_conda = true + conda.useMamba = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } docker { docker.enabled = true docker.userEmulation = true @@ -119,10 +131,16 @@ profiles { podman.enabled = false shifter.enabled = false } + gitpod { + executor.name = 'local' + executor.cpus = 16 + executor.memory = 60.GB + } test { includeConfig 'conf/test.config' } test_full { includeConfig 'conf/test_full.config' } } + // Load igenomes.config if required if (!params.igenomes_ignore) { includeConfig 'conf/igenomes.config' @@ -130,6 +148,7 @@ if (!params.igenomes_ignore) { params.genomes = [:] } + // Export these variables to prevent local Python/R libraries from conflicting with those in the container // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. @@ -169,7 +188,7 @@ manifest { description = 'A pipeline to demultiplex, QC and map Nanopore data' mainScript = 'main.nf' nextflowVersion = '!>=21.10.3' - version = '2.0.1' + version = '3.0.0' } // Load modules.config for DSL2 module specific options From 00f40b75fa054f1a0f200767b6a13b3171a910cd Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 1 Sep 2022 13:29:59 +0000 Subject: [PATCH 02/56] Template update for nf-core/tools version 2.5.1 --- bin/check_samplesheet.py | 9 ++++++--- pyproject.toml | 10 ++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 pyproject.toml diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 9a8b8962..11b15572 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -98,7 +98,9 @@ def _validate_pair(self, row): """Assert that read pairs have the same file extension. Report pair status.""" if row[self._first_col] and row[self._second_col]: row[self._single_col] = False - if Path(row[self._first_col]).suffixes[-2:] != Path(row[self._second_col]).suffixes[-2:]: + first_col_suffix = Path(row[self._first_col]).suffixes[-2:] + second_col_suffix = Path(row[self._second_col]).suffixes[-2:] + if first_col_suffix != second_col_suffix: raise AssertionError("FASTQ pairs must have the same file extensions.") else: row[self._single_col] = True @@ -157,7 +159,7 @@ def sniff_format(handle): handle.seek(0) sniffer = csv.Sniffer() if not sniffer.has_header(peek): - logger.critical(f"The given sample sheet does not appear to contain a header.") + logger.critical("The given sample sheet does not appear to contain a header.") sys.exit(1) dialect = sniffer.sniff(peek) return dialect @@ -195,7 +197,8 @@ def check_samplesheet(file_in, file_out): reader = csv.DictReader(in_handle, dialect=sniff_format(in_handle)) # Validate the existence of the expected header columns. if not required_columns.issubset(reader.fieldnames): - logger.critical(f"The sample sheet **must** contain the column headers: {', '.join(required_columns)}.") + req_cols = ", ".join(required_columns) + logger.critical(f"The sample sheet **must** contain these column headers: {req_cols}.") sys.exit(1) # Validate each row. checker = RowChecker() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..0d62beb6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +# Config file for Python. Mostly used to configure linting of bin/check_samplesheet.py with Black. +# Should be kept the same as nf-core/tools to avoid fighting with template synchronisation. +[tool.black] +line-length = 120 +target_version = ["py37", "py38", "py39", "py310"] + +[tool.isort] +profile = "black" +known_first_party = ["nf_core"] +multi_line_output = 3 From 4cbba456b4a073db7965cdea9b0a16c76d5ddbeb Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 4 Oct 2022 21:53:57 +0000 Subject: [PATCH 03/56] Template update for nf-core/tools version 2.6 --- .github/workflows/awsfulltest.yml | 4 ++ .github/workflows/awstest.yml | 4 ++ .prettierignore | 1 + CITATION.cff | 8 +-- assets/adaptivecard.json | 67 +++++++++++++++++++ assets/methods_description_template.yml | 25 +++++++ assets/multiqc_config.yml | 6 +- docs/usage.md | 8 +++ lib/NfcoreTemplate.groovy | 55 +++++++++++++++ lib/Utils.groovy | 21 ++++-- lib/WorkflowNanoseq.groovy | 19 ++++++ main.nf | 3 +- modules.json | 27 ++++---- .../custom/dumpsoftwareversions/main.nf | 8 +-- .../custom/dumpsoftwareversions/meta.yml | 0 .../templates/dumpsoftwareversions.py | 0 modules/nf-core/{modules => }/fastqc/main.nf | 12 ++++ modules/nf-core/{modules => }/fastqc/meta.yml | 0 modules/nf-core/modules/multiqc/main.nf | 31 --------- modules/nf-core/multiqc/main.nf | 53 +++++++++++++++ .../nf-core/{modules => }/multiqc/meta.yml | 15 +++++ nextflow.config | 5 +- nextflow_schema.json | 18 +++++ workflows/nanoseq.nf | 26 ++++--- 24 files changed, 345 insertions(+), 71 deletions(-) create mode 100644 assets/adaptivecard.json create mode 100644 assets/methods_description_template.yml mode change 100755 => 100644 lib/Utils.groovy rename modules/nf-core/{modules => }/custom/dumpsoftwareversions/main.nf (79%) rename modules/nf-core/{modules => }/custom/dumpsoftwareversions/meta.yml (100%) rename modules/nf-core/{modules => }/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py (100%) rename modules/nf-core/{modules => }/fastqc/main.nf (85%) rename modules/nf-core/{modules => }/fastqc/meta.yml (100%) delete mode 100644 modules/nf-core/modules/multiqc/main.nf create mode 100644 modules/nf-core/multiqc/main.nf rename modules/nf-core/{modules => }/multiqc/meta.yml (73%) diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index fc6eba92..29ec7466 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -28,3 +28,7 @@ jobs: "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/nanoseq/results-${{ github.sha }}" } profiles: test_full,aws_tower + - uses: actions/upload-artifact@v3 + with: + name: Tower debug log file + path: tower_action_*.log diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index 024728e8..84272f0e 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -23,3 +23,7 @@ jobs: "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/nanoseq/results-test-${{ github.sha }}" } profiles: test,aws_tower + - uses: actions/upload-artifact@v3 + with: + name: Tower debug log file + path: tower_action_*.log diff --git a/.prettierignore b/.prettierignore index d0e7ae58..eb74a574 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ email_template.html +adaptivecard.json .nextflow* work/ data/ diff --git a/CITATION.cff b/CITATION.cff index 4533e2f2..017666c0 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -13,8 +13,8 @@ authors: given-names: Johannes - family-names: Wilm given-names: Andreas - - family-names: Ulysse Garcia - given-names: Maxime + - family-names: Garcia + given-names: Maxime Ulysse - family-names: Di Tommaso given-names: Paolo - family-names: Nahnsen @@ -39,8 +39,8 @@ prefered-citation: given-names: Johannes - family-names: Wilm given-names: Andreas - - family-names: Ulysse Garcia - given-names: Maxime + - family-names: Garcia + given-names: Maxime Ulysse - family-names: Di Tommaso given-names: Paolo - family-names: Nahnsen diff --git a/assets/adaptivecard.json b/assets/adaptivecard.json new file mode 100644 index 00000000..71ce75e7 --- /dev/null +++ b/assets/adaptivecard.json @@ -0,0 +1,67 @@ +{ + "type": "message", + "attachments": [ + { + "contentType": "application/vnd.microsoft.card.adaptive", + "contentUrl": null, + "content": { + "\$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "msteams": { + "width": "Full" + }, + "type": "AdaptiveCard", + "version": "1.2", + "body": [ + { + "type": "TextBlock", + "size": "Large", + "weight": "Bolder", + "color": "<% if (success) { %>Good<% } else { %>Attention<%} %>", + "text": "nf-core/nanoseq v${version} - ${runName}", + "wrap": true + }, + { + "type": "TextBlock", + "spacing": "None", + "text": "Completed at ${dateComplete} (duration: ${duration})", + "isSubtle": true, + "wrap": true + }, + { + "type": "TextBlock", + "text": "<% if (success) { %>Pipeline completed successfully!<% } else { %>Pipeline completed with errors. The full error message was: ${errorReport}.<% } %>", + "wrap": true + }, + { + "type": "TextBlock", + "text": "The command used to launch the workflow was as follows:", + "wrap": true + }, + { + "type": "TextBlock", + "text": "${commandLine}", + "isSubtle": true, + "wrap": true + } + ], + "actions": [ + { + "type": "Action.ShowCard", + "title": "Pipeline Configuration", + "card": { + "type": "AdaptiveCard", + "\$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "body": [ + { + "type": "FactSet", + "facts": [<% out << summary.collect{ k,v -> "{\"title\": \"$k\", \"value\" : \"$v\"}"}.join(",\n") %> + ] + } + ] + } + } + ] + } + } + ] +} diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml new file mode 100644 index 00000000..48cd5fa1 --- /dev/null +++ b/assets/methods_description_template.yml @@ -0,0 +1,25 @@ +id: "nf-core-nanoseq-methods-description" +description: "Suggested text and references to use when describing pipeline usage within the methods section of a publication." +section_name: "nf-core/nanoseq Methods Description" +section_href: "https://github.com/nf-core/nanoseq" +plot_type: "html" +## TODO nf-core: Update the HTML below to your prefered methods description, e.g. add publication citation for this pipeline +## You inject any metadata in the Nextflow '${workflow}' object +data: | +

Methods

+

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

+

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

+
${workflow.commandLine}
+

References

+
    +
  • Di Tommaso, P., Chatzou, M., Floden, E. W., Barja, P. P., Palumbo, E., & Notredame, C. (2017). Nextflow enables reproducible computational workflows. Nature Biotechnology, 35(4), 316-319. https://doi.org/10.1038/nbt.3820
  • +
  • Ewels, P. A., Peltzer, A., Fillinger, S., Patel, H., Alneberg, J., Wilm, A., Garcia, M. U., Di Tommaso, P., & Nahnsen, S. (2020). The nf-core framework for community-curated bioinformatics pipelines. Nature Biotechnology, 38(3), 276-278. https://doi.org/10.1038/s41587-020-0439-x
  • +
+
+
Notes:
+
    + ${nodoi_text} +
  • The command above does not include parameters contained in any configs or profiles that may have been used. Ensure the config file is also uploaded with your publication!
  • +
  • You should also cite all software used within this run. Check the "Software Versions" of this report to get version information.
  • +
+
diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 49c53cbb..6433de0e 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -3,9 +3,11 @@ report_comment: > analysis pipeline. For information about how to interpret these results, please see the documentation. report_section_order: - software_versions: + "nf-core-nanoseq-methods-description": order: -1000 - "nf-core-nanoseq-summary": + software_versions: order: -1001 + "nf-core-nanoseq-summary": + order: -1002 export_plots: true diff --git a/docs/usage.md b/docs/usage.md index 642fd017..19b6e74f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -237,6 +237,14 @@ See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack) on the [`#configs` channel](https://nfcore.slack.com/channels/configs). +## Azure Resource Requests + +To be used with the `azurebatch` profile by specifying the `-profile azurebatch`. +We recommend providing a compute `params.vm_type` of `Standard_D16_v3` VMs by default but these options can be changed if required. + +Note that the choice of VM size depends on your quota and the overall workload during the analysis. +For a thorough list, please refer the [Azure Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/sizes). + ## Running in the background Nextflow handles job submissions and supervises the running jobs. The Nextflow process must run until the pipeline is finished. diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 2fc0a9b9..27feb009 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -145,6 +145,61 @@ class NfcoreTemplate { output_tf.withWriter { w -> w << email_txt } } + // + // Construct and send adaptive card + // https://adaptivecards.io + // + public static void adaptivecard(workflow, params, summary_params, projectDir, log) { + def hook_url = params.hook_url + + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['start'] = workflow.start + misc_fields['complete'] = workflow.complete + misc_fields['scriptfile'] = workflow.scriptFile + misc_fields['scriptid'] = workflow.scriptId + if (workflow.repository) misc_fields['repository'] = workflow.repository + if (workflow.commitId) misc_fields['commitid'] = workflow.commitId + if (workflow.revision) misc_fields['revision'] = workflow.revision + misc_fields['nxf_version'] = workflow.nextflow.version + misc_fields['nxf_build'] = workflow.nextflow.build + misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp + + def msg_fields = [:] + msg_fields['version'] = workflow.manifest.version + msg_fields['runName'] = workflow.runName + msg_fields['success'] = workflow.success + msg_fields['dateComplete'] = workflow.complete + msg_fields['duration'] = workflow.duration + msg_fields['exitStatus'] = workflow.exitStatus + msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + msg_fields['errorReport'] = (workflow.errorReport ?: 'None') + msg_fields['commandLine'] = workflow.commandLine + msg_fields['projectDir'] = workflow.projectDir + msg_fields['summary'] = summary << misc_fields + + // Render the JSON template + def engine = new groovy.text.GStringTemplateEngine() + def hf = new File("$projectDir/assets/adaptivecard.json") + def json_template = engine.createTemplate(hf).make(msg_fields) + def json_message = json_template.toString() + + // POST + def post = new URL(hook_url).openConnection(); + post.setRequestMethod("POST") + post.setDoOutput(true) + post.setRequestProperty("Content-Type", "application/json") + post.getOutputStream().write(json_message.getBytes("UTF-8")); + def postRC = post.getResponseCode(); + if (! postRC.equals(200)) { + log.warn(post.getErrorStream().getText()); + } + } + // // Print pipeline summary on completion // diff --git a/lib/Utils.groovy b/lib/Utils.groovy old mode 100755 new mode 100644 index 28567bd7..8d030f4e --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -21,19 +21,26 @@ class Utils { } // Check that all channels are present - def required_channels = ['conda-forge', 'bioconda', 'defaults'] - def conda_check_failed = !required_channels.every { ch -> ch in channels } + // This channel list is ordered by required channel priority. + def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] + def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean // Check that they are in the right order - conda_check_failed |= !(channels.indexOf('conda-forge') < channels.indexOf('bioconda')) - conda_check_failed |= !(channels.indexOf('bioconda') < channels.indexOf('defaults')) + def channel_priority_violation = false + def n = required_channels_in_order.size() + for (int i = 0; i < n - 1; i++) { + channel_priority_violation |= !(channels.indexOf(required_channels_in_order[i]) < channels.indexOf(required_channels_in_order[i+1])) + } - if (conda_check_failed) { + if (channels_missing | channel_priority_violation) { log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " There is a problem with your Conda configuration!\n\n" + " You will need to set-up the conda-forge and bioconda channels correctly.\n" + - " Please refer to https://bioconda.github.io/user/install.html#set-up-channels\n" + - " NB: The order of the channels matters!\n" + + " Please refer to https://bioconda.github.io/\n" + + " The observed channel order is \n" + + " ${channels}\n" + + " but the following channel order is required:\n" + + " ${required_channels_in_order}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" } } diff --git a/lib/WorkflowNanoseq.groovy b/lib/WorkflowNanoseq.groovy index f71f85d1..1903c55d 100755 --- a/lib/WorkflowNanoseq.groovy +++ b/lib/WorkflowNanoseq.groovy @@ -2,6 +2,8 @@ // This file holds several functions specific to the workflow/nanoseq.nf in the nf-core/nanoseq pipeline // +import groovy.text.SimpleTemplateEngine + class WorkflowNanoseq { // @@ -42,6 +44,23 @@ class WorkflowNanoseq { yaml_file_text += "data: |\n" yaml_file_text += "${summary_section}" return yaml_file_text + } + + public static String methodsDescriptionText(run_workflow, mqc_methods_yaml) { + // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file + def meta = [:] + meta.workflow = run_workflow.toMap() + meta["manifest_map"] = run_workflow.manifest.toMap() + + meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" + meta["nodoi_text"] = meta.manifest_map.doi ? "": "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " + + def methods_text = mqc_methods_yaml.text + + def engine = new SimpleTemplateEngine() + def description_html = engine.createTemplate(methods_text).make(meta) + + return description_html }// // Exit pipeline if incorrect --genome key provided // diff --git a/main.nf b/main.nf index 889ce148..3ba1e4f1 100644 --- a/main.nf +++ b/main.nf @@ -4,7 +4,8 @@ nf-core/nanoseq ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Github : https://github.com/nf-core/nanoseq -Website: https://nf-co.re/nanoseq + + Website: https://nf-co.re/nanoseq Slack : https://nfcore.slack.com/channels/nanoseq ---------------------------------------------------------------------------------------- */ diff --git a/modules.json b/modules.json index 35e1bb01..8bda1bc5 100644 --- a/modules.json +++ b/modules.json @@ -2,20 +2,21 @@ "name": "nf-core/nanoseq", "homePage": "https://github.com/nf-core/nanoseq", "repos": { - "nf-core/modules": { - "git_url": "https://github.com/nf-core/modules.git", + "https://github.com/nf-core/modules.git": { "modules": { - "custom/dumpsoftwareversions": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", - "branch": "master" - }, - "fastqc": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", - "branch": "master" - }, - "multiqc": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", - "branch": "master" + "nf-core": { + "custom/dumpsoftwareversions": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "fastqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "multiqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + } } } } diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf similarity index 79% rename from modules/nf-core/modules/custom/dumpsoftwareversions/main.nf rename to modules/nf-core/custom/dumpsoftwareversions/main.nf index 327d5100..cebb6e05 100644 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -1,11 +1,11 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { - label 'process_low' + label 'process_single' // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda (params.enable_conda ? "bioconda::multiqc=1.11" : null) + conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.11--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.11--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" input: path versions diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/custom/dumpsoftwareversions/meta.yml similarity index 100% rename from modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml rename to modules/nf-core/custom/dumpsoftwareversions/meta.yml diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py similarity index 100% rename from modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py rename to modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py diff --git a/modules/nf-core/modules/fastqc/main.nf b/modules/nf-core/fastqc/main.nf similarity index 85% rename from modules/nf-core/modules/fastqc/main.nf rename to modules/nf-core/fastqc/main.nf index ed6b8c50..05730368 100644 --- a/modules/nf-core/modules/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -44,4 +44,16 @@ process FASTQC { END_VERSIONS """ } + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.html + touch ${prefix}.zip + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) + END_VERSIONS + """ } diff --git a/modules/nf-core/modules/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml similarity index 100% rename from modules/nf-core/modules/fastqc/meta.yml rename to modules/nf-core/fastqc/meta.yml diff --git a/modules/nf-core/modules/multiqc/main.nf b/modules/nf-core/modules/multiqc/main.nf deleted file mode 100644 index 1264aac1..00000000 --- a/modules/nf-core/modules/multiqc/main.nf +++ /dev/null @@ -1,31 +0,0 @@ -process MULTIQC { - label 'process_medium' - - conda (params.enable_conda ? 'bioconda::multiqc=1.12' : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.12--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.12--pyhdfd78af_0' }" - - input: - path multiqc_files - - output: - path "*multiqc_report.html", emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - """ - multiqc -f $args . - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS - """ -} diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf new file mode 100644 index 00000000..a8159a57 --- /dev/null +++ b/modules/nf-core/multiqc/main.nf @@ -0,0 +1,53 @@ +process MULTIQC { + label 'process_single' + + conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" + + input: + path multiqc_files, stageAs: "?/*" + path(multiqc_config) + path(extra_multiqc_config) + path(multiqc_logo) + + output: + path "*multiqc_report.html", emit: report + path "*_data" , emit: data + path "*_plots" , optional:true, emit: plots + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config = multiqc_config ? "--config $multiqc_config" : '' + def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + """ + multiqc \\ + --force \\ + $args \\ + $config \\ + $extra_config \\ + . + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) + END_VERSIONS + """ + + stub: + """ + touch multiqc_data + touch multiqc_plots + touch multiqc_report.html + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) + END_VERSIONS + """ +} diff --git a/modules/nf-core/modules/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml similarity index 73% rename from modules/nf-core/modules/multiqc/meta.yml rename to modules/nf-core/multiqc/meta.yml index 6fa891ef..ebc29b27 100644 --- a/modules/nf-core/modules/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -12,11 +12,25 @@ tools: homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ licence: ["GPL-3.0-or-later"] + input: - multiqc_files: type: file description: | List of reports / files recognised by MultiQC, for example the html and zip output of FastQC + - multiqc_config: + type: file + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + - extra_multiqc_config: + type: file + description: Second optional config yml for MultiQC. Will override common sections in multiqc_config. + pattern: "*.{yml,yaml}" + - multiqc_logo: + type: file + description: Optional logo file for MultiQC + pattern: "*.{png}" + output: - report: type: file @@ -38,3 +52,4 @@ authors: - "@abhi18av" - "@bunop" - "@drpatelh" + - "@jfy133" diff --git a/nextflow.config b/nextflow.config index 285286e3..82df95cf 100644 --- a/nextflow.config +++ b/nextflow.config @@ -21,7 +21,9 @@ params { // MultiQC options multiqc_config = null multiqc_title = null + multiqc_logo = null max_multiqc_email_size = '25.MB' + multiqc_methods_description = null // Boilerplate options outdir = null @@ -31,6 +33,7 @@ params { email_on_fail = null plaintext_email = false monochrome_logs = false + hook_url = null help = false validate_params = true show_hidden_params = false @@ -74,7 +77,6 @@ try { // } - profiles { debug { process.beforeScript = 'echo $HOSTNAME' } conda { @@ -189,6 +191,7 @@ manifest { mainScript = 'main.nf' nextflowVersion = '!>=21.10.3' version = '3.0.0' + doi = '' } // Load modules.config for DSL2 module specific options diff --git a/nextflow_schema.json b/nextflow_schema.json index a073376c..a7dbb3eb 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -213,12 +213,30 @@ "fa_icon": "fas fa-palette", "hidden": true }, + "hook_url": { + "type": "string", + "description": "Incoming hook URL for messaging service", + "fa_icon": "fas fa-people-group", + "help_text": "Incoming hook URL for messaging service. Currently, only MS Teams is supported.", + "hidden": true + }, "multiqc_config": { "type": "string", "description": "Custom config file to supply to MultiQC.", "fa_icon": "fas fa-cog", "hidden": true }, + "multiqc_logo": { + "type": "string", + "description": "Custom logo file to supply to MultiQC. File name must also be set in the MultiQC config file", + "fa_icon": "fas fa-image", + "hidden": true + }, + "multiqc_methods_description": { + "type": "string", + "description": "Custom MultiQC yaml file containing HTML including a methods description.", + "fa_icon": "fas fa-cog" + }, "tracedir": { "type": "string", "description": "Directory to keep pipeline Nextflow logs and reports.", diff --git a/workflows/nanoseq.nf b/workflows/nanoseq.nf index c93e9bf5..a4fe77f7 100644 --- a/workflows/nanoseq.nf +++ b/workflows/nanoseq.nf @@ -23,8 +23,10 @@ if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input sample ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -ch_multiqc_config = file("$projectDir/assets/multiqc_config.yml", checkIfExists: true) -ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config) : Channel.empty() +ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) +ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath( params.multiqc_config, checkIfExists: true ) : Channel.empty() +ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath( params.multiqc_logo, checkIfExists: true ) : Channel.empty() +ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -46,9 +48,9 @@ include { INPUT_CHECK } from '../subworkflows/local/input_check' // // MODULE: Installed directly from nf-core/modules // -include { FASTQC } from '../modules/nf-core/modules/fastqc/main' -include { MULTIQC } from '../modules/nf-core/modules/multiqc/main' -include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' +include { FASTQC } from '../modules/nf-core/fastqc/main' +include { MULTIQC } from '../modules/nf-core/multiqc/main' +include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -89,15 +91,20 @@ workflow NANOSEQ { workflow_summary = WorkflowNanoseq.paramsSummaryMultiqc(workflow, summary_params) ch_workflow_summary = Channel.value(workflow_summary) + methods_description = WorkflowNanoseq.methodsDescriptionText(workflow, ch_multiqc_custom_methods_description) + ch_methods_description = Channel.value(methods_description) + ch_multiqc_files = Channel.empty() - ch_multiqc_files = ch_multiqc_files.mix(Channel.from(ch_multiqc_config)) - ch_multiqc_files = ch_multiqc_files.mix(ch_multiqc_custom_config.collect().ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) + ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(CUSTOM_DUMPSOFTWAREVERSIONS.out.mqc_yml.collect()) ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it[1]}.ifEmpty([])) MULTIQC ( - ch_multiqc_files.collect() + ch_multiqc_files.collect(), + ch_multiqc_config.collect().ifEmpty([]), + ch_multiqc_custom_config.collect().ifEmpty([]), + ch_multiqc_logo.collect().ifEmpty([]) ) multiqc_report = MULTIQC.out.report.toList() ch_versions = ch_versions.mix(MULTIQC.out.versions) @@ -114,6 +121,9 @@ workflow.onComplete { NfcoreTemplate.email(workflow, params, summary_params, projectDir, log, multiqc_report) } NfcoreTemplate.summary(workflow, params, log) + if (params.hook_url) { + NfcoreTemplate.adaptivecard(workflow, params, summary_params, projectDir, log) + } } /* From 63b2610f094bbeb3316b97530ea785a336f634a7 Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Fri, 18 Nov 2022 14:30:43 +0000 Subject: [PATCH 04/56] fix: fix jaffal mapping --- conf/test_bc_nodx.config | 2 +- conf/test_nobc_nodx_noaln.config | 2 +- modules/local/get_jaffal_ref.nf | 2 +- modules/local/jaffal.nf | 1 - subworkflows/local/rna_fusions_jaffal.nf | 15 +++++++++------ workflows/nanoseq.nf | 10 +++++++--- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/conf/test_bc_nodx.config b/conf/test_bc_nodx.config index 7ca3d308..70617e7c 100644 --- a/conf/test_bc_nodx.config +++ b/conf/test_bc_nodx.config @@ -23,7 +23,7 @@ params { kit = 'SQK-DCS108' skip_demultiplexing = true skip_quantification = true - skip_fusion_analysis= true + skip_fusion_analysis= false skip_modification_analysis=true // This variable is just for reference and isnt actually required for the tests diff --git a/conf/test_nobc_nodx_noaln.config b/conf/test_nobc_nodx_noaln.config index abec7b05..2b77e328 100644 --- a/conf/test_nobc_nodx_noaln.config +++ b/conf/test_nobc_nodx_noaln.config @@ -22,6 +22,6 @@ params { skip_basecalling = true skip_demultiplexing = true skip_alignment = true - skip_fusion_analysis= true + skip_fusion_analysis= false skip_modification_analysis=true } diff --git a/modules/local/get_jaffal_ref.nf b/modules/local/get_jaffal_ref.nf index 16c96b82..6ce0b329 100644 --- a/modules/local/get_jaffal_ref.nf +++ b/modules/local/get_jaffal_ref.nf @@ -6,7 +6,7 @@ process GET_JAFFAL_REF { 'biocontainers/biocontainers:v1.2.0_cv1' }" output: - path "for_jaffal.tar.gz" , emit: ch_jaffal_ref + tuple val(null), path("for_jaffal.tar.gz") , emit: ch_jaffal_ref script: """ diff --git a/modules/local/jaffal.nf b/modules/local/jaffal.nf index 96905a03..0ebeff98 100644 --- a/modules/local/jaffal.nf +++ b/modules/local/jaffal.nf @@ -1,5 +1,4 @@ process JAFFAL { - tag "$meta.id" echo true label 'process_medium' diff --git a/subworkflows/local/rna_fusions_jaffal.nf b/subworkflows/local/rna_fusions_jaffal.nf index 2cef2997..0fd7e32c 100644 --- a/subworkflows/local/rna_fusions_jaffal.nf +++ b/subworkflows/local/rna_fusions_jaffal.nf @@ -8,7 +8,7 @@ include { JAFFAL } from '../../modules/local/jaffal' workflow RNA_FUSIONS_JAFFAL { take: - ch_sample + ch_sample_simple jaffal_ref_dir main: @@ -25,15 +25,18 @@ workflow RNA_FUSIONS_JAFFAL { * Untar jaffel reference */ UNTAR( GET_JAFFAL_REF.out.ch_jaffal_ref ) - ch_jaffal_ref_dir = UNTAR.out.untar + UNTAR.out.untar + .map { it -> [ it[1] ]} + .set { ch_jaffal_ref_dir } + + ch_jaffal_ref_dir.view() + } - ch_sample - .map { it -> [ it[0], it[6] ]} - .set { ch_jaffal_input } + ch_sample_simple.view() /* * Align current signals to reference with jaffel */ - JAFFAL( ch_jaffal_input, ch_jaffal_ref_dir ) + JAFFAL( ch_sample_simple, ch_jaffal_ref_dir ) } diff --git a/workflows/nanoseq.nf b/workflows/nanoseq.nf index d55c9376..f56cbf9b 100644 --- a/workflows/nanoseq.nf +++ b/workflows/nanoseq.nf @@ -15,8 +15,8 @@ checkPathParamList = [ params.input, params.multiqc_config ] for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } // Check mandatory parameters (missing protocol or profile will exit the run.) -if (params.input) { - ch_input = file(params.input) +if (params.input) { + ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } @@ -484,7 +484,11 @@ workflow NANOSEQ{ /* * SUBWORKFLOW: RNA_FUSIONS_JAFFAL */ - RNA_FUSIONS_JAFFAL( ch_sample, params.jaffal_ref_dir ) + ch_fastq + .map { it -> [ it[0], it[1] ] } + .set { ch_fastq_simple } + + RNA_FUSIONS_JAFFAL( ch_fastq_simple, params.jaffal_ref_dir ) } /* From 25d1206d88b42061ab0735ce367c50e11d5cbafe Mon Sep 17 00:00:00 2001 From: christopher-hakkaart Date: Wed, 7 Dec 2022 15:04:29 +1300 Subject: [PATCH 05/56] Fixing schema --- nextflow_schema.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index c82a5fa8..16ac9e84 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,7 +10,10 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": ["input", "protocol"], + "required": [ + "input", + "protocol" + ], "properties": { "input": { "type": "string", @@ -25,11 +28,12 @@ }, "protocol": { "type": "string", - "description": "Path to comma-separated file containing information about the samples in the experiment.", + "description": "Input sample type. Valid options: 'DNA', 'cDNA', and 'directRNA'.", "format": "file-path", "mimetype": "text/csv", "schema": "assets/schema_input.json", - "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re//usage#samplesheet-input)." + "help_text": "You will need to specify a protocol based on the sample input type. Valid options are 'DNA', 'cDNA', and 'directRNA'.", + "fa_icon": "fas fa-dna" }, "outdir": { "type": "string", From 554f9f3dd1f236e280374a65277185102e2ae1d1 Mon Sep 17 00:00:00 2001 From: christopher-hakkaart Date: Wed, 7 Dec 2022 15:09:43 +1300 Subject: [PATCH 06/56] Prettier --- nextflow_schema.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 16ac9e84..7115a286 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,10 +10,7 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": [ - "input", - "protocol" - ], + "required": ["input", "protocol"], "properties": { "input": { "type": "string", From 43ebc811598e0c0383863c13039d06bc43a05b83 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 8 Dec 2022 13:12:44 +0000 Subject: [PATCH 07/56] Template update for nf-core/tools version 2.7.1 --- .devcontainer/devcontainer.json | 27 +++++++++++++ .gitattributes | 1 + .github/CONTRIBUTING.md | 16 ++++++++ .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .github/workflows/ci.yml | 8 +++- .github/workflows/fix-linting.yml | 6 +-- .github/workflows/linting.yml | 18 +++++---- .github/workflows/linting_comment.yml | 2 +- .prettierignore | 2 + CITATION.cff | 56 --------------------------- README.md | 4 +- assets/slackreport.json | 34 ++++++++++++++++ docs/usage.md | 24 +++++++----- lib/NfcoreSchema.groovy | 1 - lib/NfcoreTemplate.groovy | 41 +++++++++++++++----- lib/WorkflowMain.groovy | 18 ++++++--- modules.json | 9 +++-- modules/local/samplesheet_check.nf | 4 ++ nextflow.config | 12 ++++-- nextflow_schema.json | 8 +++- workflows/nanoseq.nf | 11 +++--- 21 files changed, 193 insertions(+), 111 deletions(-) create mode 100644 .devcontainer/devcontainer.json delete mode 100644 CITATION.cff create mode 100644 assets/slackreport.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..ea27a584 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,27 @@ +{ + "name": "nfcore", + "image": "nfcore/gitpod:latest", + "remoteUser": "gitpod", + + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Set *default* container specific settings.json values on container create. + "settings": { + "python.defaultInterpreterPath": "/opt/conda/bin/python", + "python.linting.enabled": true, + "python.linting.pylintEnabled": true, + "python.formatting.autopep8Path": "/opt/conda/bin/autopep8", + "python.formatting.yapfPath": "/opt/conda/bin/yapf", + "python.linting.flake8Path": "/opt/conda/bin/flake8", + "python.linting.pycodestylePath": "/opt/conda/bin/pycodestyle", + "python.linting.pydocstylePath": "/opt/conda/bin/pydocstyle", + "python.linting.pylintPath": "/opt/conda/bin/pylint" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": ["ms-python.python", "ms-python.vscode-pylance", "nf-core.nf-core-extensionpack"] + } + } +} diff --git a/.gitattributes b/.gitattributes index 050bb120..7a2dabc2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ *.config linguist-language=nextflow +*.nf.test linguist-language=nextflow modules/nf-core/** linguist-generated subworkflows/nf-core/** linguist-generated diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a66e3acd..30e08528 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -101,3 +101,19 @@ If you are using a new feature from core Nextflow, you may bump the minimum requ ### Images and figures For overview images and other documents we follow the nf-core [style guidelines and examples](https://nf-co.re/developers/design_guidelines). + +## GitHub Codespaces + +This repo includes a devcontainer configuration which will create a GitHub Codespaces for Nextflow development! This is an online developer environment that runs in your browser, complete with VSCode and a terminal. + +To get started: + +- Open the repo in [Codespaces](https://github.com/nf-core/nanoseq/codespaces) +- Tools installed + - nf-core + - Nextflow + +Devcontainer specs: + +- [DevContainer config](.devcontainer/devcontainer.json) +- [Dockerfile](.devcontainer/Dockerfile) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index dfcd7148..ec79522f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -42,7 +42,7 @@ body: attributes: label: System information description: | - * Nextflow version _(eg. 21.10.3)_ + * Nextflow version _(eg. 22.10.1)_ * Hardware _(eg. HPC, Desktop, Cloud)_ * Executor _(eg. slurm, local, awsbatch)_ * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter or Charliecloud)_ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f60b77e4..c0c15616 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,10 @@ on: env: NXF_ANSI_LOG: false +concurrency: + group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" + cancel-in-progress: true + jobs: test: name: Run pipeline with test data @@ -20,11 +24,11 @@ jobs: strategy: matrix: NXF_VER: - - "21.10.3" + - "22.10.1" - "latest-everything" steps: - name: Check out pipeline code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Nextflow uses: nf-core/setup-nextflow@v1 diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix-linting.yml index 18e9c23f..f512acd6 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix-linting.yml @@ -24,7 +24,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 - name: Install Prettier run: npm install -g prettier @prettier/plugin-php @@ -34,9 +34,9 @@ jobs: id: prettier_status run: | if prettier --check ${GITHUB_WORKSPACE}; then - echo "::set-output name=result::pass" + echo "name=result::pass" >> $GITHUB_OUTPUT else - echo "::set-output name=result::fail" + echo "name=result::fail" >> $GITHUB_OUTPUT fi - name: Run 'prettier --write' diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 8a5ce69b..858d622e 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -4,6 +4,8 @@ name: nf-core linting # that the code meets the nf-core guidelines. on: push: + branches: + - dev pull_request: release: types: [published] @@ -12,9 +14,9 @@ jobs: EditorConfig: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 - name: Install editorconfig-checker run: npm install -g editorconfig-checker @@ -25,9 +27,9 @@ jobs: Prettier: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 - name: Install Prettier run: npm install -g prettier @@ -38,7 +40,7 @@ jobs: PythonBlack: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Check code lints with Black uses: psf/black@stable @@ -69,12 +71,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Nextflow uses: nf-core/setup-nextflow@v1 - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v4 with: python-version: "3.7" architecture: "x64" @@ -97,7 +99,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: linting-logs path: | diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 04758f61..39635186 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -18,7 +18,7 @@ jobs: - name: Get PR number id: pr_number - run: echo "::set-output name=pr_number::$(cat linting-logs/PR_number.txt)" + run: echo "name=pr_number::$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - name: Post PR comment uses: marocchino/sticky-pull-request-comment@v2 diff --git a/.prettierignore b/.prettierignore index eb74a574..437d763d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,6 @@ email_template.html adaptivecard.json +slackreport.json .nextflow* work/ data/ @@ -8,3 +9,4 @@ results/ testing/ testing* *.pyc +bin/ diff --git a/CITATION.cff b/CITATION.cff deleted file mode 100644 index 017666c0..00000000 --- a/CITATION.cff +++ /dev/null @@ -1,56 +0,0 @@ -cff-version: 1.2.0 -message: "If you use `nf-core tools` in your work, please cite the `nf-core` publication" -authors: - - family-names: Ewels - given-names: Philip - - family-names: Peltzer - given-names: Alexander - - family-names: Fillinger - given-names: Sven - - family-names: Patel - given-names: Harshil - - family-names: Alneberg - given-names: Johannes - - family-names: Wilm - given-names: Andreas - - family-names: Garcia - given-names: Maxime Ulysse - - family-names: Di Tommaso - given-names: Paolo - - family-names: Nahnsen - given-names: Sven -title: "The nf-core framework for community-curated bioinformatics pipelines." -version: 2.4.1 -doi: 10.1038/s41587-020-0439-x -date-released: 2022-05-16 -url: https://github.com/nf-core/tools -prefered-citation: - type: article - authors: - - family-names: Ewels - given-names: Philip - - family-names: Peltzer - given-names: Alexander - - family-names: Fillinger - given-names: Sven - - family-names: Patel - given-names: Harshil - - family-names: Alneberg - given-names: Johannes - - family-names: Wilm - given-names: Andreas - - family-names: Garcia - given-names: Maxime Ulysse - - family-names: Di Tommaso - given-names: Paolo - - family-names: Nahnsen - given-names: Sven - doi: 10.1038/s41587-020-0439-x - journal: nature biotechnology - start: 276 - end: 278 - title: "The nf-core framework for community-curated bioinformatics pipelines." - issue: 3 - volume: 38 - year: 2020 - url: https://dx.doi.org/10.1038/s41587-020-0439-x diff --git a/README.md b/README.md index 569efb78..a2333c95 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/nanoseq/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg)](https://www.nextflow.io/) +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A522.10.1-23aa62.svg)](https://www.nextflow.io/) [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) @@ -31,7 +31,7 @@ On release, automated continuous integration tests run the pipeline on a full-si ## Quick Start -1. Install [`Nextflow`](https://www.nextflow.io/docs/latest/getstarted.html#installation) (`>=21.10.3`) +1. Install [`Nextflow`](https://www.nextflow.io/docs/latest/getstarted.html#installation) (`>=22.10.1`) 2. Install any of [`Docker`](https://docs.docker.com/engine/installation/), [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/) (you can follow [this tutorial](https://singularity-tutorial.github.io/01-installation/)), [`Podman`](https://podman.io/), [`Shifter`](https://nersc.gitlab.io/development/shifter/how-to-use/) or [`Charliecloud`](https://hpc.github.io/charliecloud/) for full pipeline reproducibility _(you can use [`Conda`](https://conda.io/miniconda.html) both to install Nextflow itself and also to manage software within pipelines. Please only use it within pipelines as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles))_. diff --git a/assets/slackreport.json b/assets/slackreport.json new file mode 100644 index 00000000..043d02f2 --- /dev/null +++ b/assets/slackreport.json @@ -0,0 +1,34 @@ +{ + "attachments": [ + { + "fallback": "Plain-text summary of the attachment.", + "color": "<% if (success) { %>good<% } else { %>danger<%} %>", + "author_name": "sanger-tol/readmapping v${version} - ${runName}", + "author_icon": "https://www.nextflow.io/docs/latest/_static/favicon.ico", + "text": "<% if (success) { %>Pipeline completed successfully!<% } else { %>Pipeline completed with errors<% } %>", + "fields": [ + { + "title": "Command used to launch the workflow", + "value": "```${commandLine}```", + "short": false + } + <% + if (!success) { %> + , + { + "title": "Full error message", + "value": "```${errorReport}```", + "short": false + }, + { + "title": "Pipeline configuration", + "value": "<% out << summary.collect{ k,v -> k == "hook_url" ? "_${k}_: (_hidden_)" : ( ( v.class.toString().contains('Path') || ( v.class.toString().contains('String') && v.contains('/') ) ) ? "_${k}_: `${v}`" : (v.class.toString().contains('DateTime') ? ("_${k}_: " + v.format(java.time.format.DateTimeFormatter.ofLocalizedDateTime(java.time.format.FormatStyle.MEDIUM))) : "_${k}_: ${v}") ) }.join(",\n") %>", + "short": false + } + <% } + %> + ], + "footer": "Completed at <% out << dateComplete.format(java.time.format.DateTimeFormatter.ofLocalizedDateTime(java.time.format.FormatStyle.MEDIUM)) %> (duration: ${duration})" + } + ] +} diff --git a/docs/usage.md b/docs/usage.md index 19b6e74f..7f82bc67 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -83,9 +83,9 @@ nextflow pull nf-core/nanoseq It is a good idea to specify a pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. -First, go to the [nf-core/nanoseq releases page](https://github.com/nf-core/nanoseq/releases) and find the latest version number - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. +First, go to the [nf-core/nanoseq releases page](https://github.com/nf-core/nanoseq/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. -This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. +This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. ## Core Nextflow arguments @@ -95,7 +95,7 @@ This version number will be logged in reports when you run the pipeline, so that Use this parameter to choose a configuration profile. Profiles can give configuration presets for different compute environments. -Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Conda) - see below. When using Biocontainers, most of these software packaging methods pull Docker containers from quay.io e.g [FastQC](https://quay.io/repository/biocontainers/fastqc) except for Singularity which directly downloads Singularity images via https hosted by the [Galaxy project](https://depot.galaxyproject.org/singularity/) and Conda which downloads and installs software locally from [Bioconda](https://bioconda.github.io/). +Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Conda) - see below. > We highly recommend the use of Docker or Singularity containers for full pipeline reproducibility, however when this is not possible, Conda is also supported. @@ -104,8 +104,11 @@ The pipeline also dynamically loads configurations from [https://github.com/nf-c Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! They are loaded in sequence, so later profiles can overwrite earlier profiles. -If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended. +If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer enviroment. +- `test` + - A profile with a complete configuration for automated testing + - Includes links to test data so needs no other parameters - `docker` - A generic configuration profile to be used with [Docker](https://docker.com/) - `singularity` @@ -118,9 +121,6 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) - `conda` - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter or Charliecloud. -- `test` - - A profile with a complete configuration for automated testing - - Includes links to test data so needs no other parameters ### `-resume` @@ -169,8 +169,14 @@ Work dir: Tip: you can replicate the issue by changing to the process work dir and entering the command `bash .command.run` ``` +#### For beginners + +A first step to bypass this error, you could try to increase the amount of CPUs, memory, and time for the whole pipeline. Therefor you can try to increase the resource for the parameters `--max_cpus`, `--max_memory`, and `--max_time`. Based on the error above, you have to increase the amount of memory. Therefore you can go to the [parameter documentation of rnaseq](https://nf-co.re/rnaseq/3.9/parameters) and scroll down to the `show hidden parameter` button to get the default value for `--max_memory`. In this case 128GB, you than can try to run your pipeline again with `--max_memory 200GB -resume` to skip all process, that were already calculated. If you can not increase the resource of the complete pipeline, you can try to adapt the resource for a single process as mentioned below. + +#### Advanced option on process level + To bypass this error you would need to find exactly which resources are set by the `STAR_ALIGN` process. The quickest way is to search for `process STAR_ALIGN` in the [nf-core/rnaseq Github repo](https://github.com/nf-core/rnaseq/search?q=process+STAR_ALIGN). -We have standardised the structure of Nextflow DSL2 pipelines such that all module files will be present in the `modules/` directory and so, based on the search results, the file we want is `modules/nf-core/software/star/align/main.nf`. +We have standardised the structure of Nextflow DSL2 pipelines such that all module files will be present in the `modules/` directory and so, based on the search results, the file we want is `modules/nf-core/star/align/main.nf`. If you click on the link to that file you will notice that there is a `label` directive at the top of the module that is set to [`label process_high`](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/modules/nf-core/software/star/align/main.nf#L9). The [Nextflow `label`](https://www.nextflow.io/docs/latest/process.html#label) directive allows us to organise workflow processes in separate groups which can be referenced in a configuration file to select and configure subset of processes having similar computing requirements. The default values for the `process_high` label are set in the pipeline's [`base.config`](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L33-L37) which in this case is defined as 72GB. @@ -189,7 +195,7 @@ process { > > If you get a warning suggesting that the process selector isn't recognised check that the process name has been specified correctly. -### Updating containers +### Updating containers (advanced users) 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`. diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy index b3d092f8..33cd4f6e 100755 --- a/lib/NfcoreSchema.groovy +++ b/lib/NfcoreSchema.groovy @@ -46,7 +46,6 @@ class NfcoreSchema { 'quiet', 'syslog', 'v', - 'version', // Options for `nextflow run` command 'ansi', diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 27feb009..25a0a74a 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -32,6 +32,25 @@ class NfcoreTemplate { } } + // + // Generate version string + // + public static String version(workflow) { + String version_string = "" + + if (workflow.manifest.version) { + def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' + version_string += "${prefix_v}${workflow.manifest.version}" + } + + if (workflow.commitId) { + def git_shortsha = workflow.commitId.substring(0, 7) + version_string += "-g${git_shortsha}" + } + + return version_string + } + // // Construct and send completion email // @@ -61,7 +80,7 @@ class NfcoreTemplate { misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp def email_fields = [:] - email_fields['version'] = workflow.manifest.version + email_fields['version'] = NfcoreTemplate.version(workflow) email_fields['runName'] = workflow.runName email_fields['success'] = workflow.success email_fields['dateComplete'] = workflow.complete @@ -146,10 +165,10 @@ class NfcoreTemplate { } // - // Construct and send adaptive card - // https://adaptivecards.io + // Construct and send a notification to a web server as JSON + // e.g. Microsoft Teams and Slack // - public static void adaptivecard(workflow, params, summary_params, projectDir, log) { + public static void IM_notification(workflow, params, summary_params, projectDir, log) { def hook_url = params.hook_url def summary = [:] @@ -170,7 +189,7 @@ class NfcoreTemplate { misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp def msg_fields = [:] - msg_fields['version'] = workflow.manifest.version + msg_fields['version'] = NfcoreTemplate.version(workflow) msg_fields['runName'] = workflow.runName msg_fields['success'] = workflow.success msg_fields['dateComplete'] = workflow.complete @@ -178,13 +197,16 @@ class NfcoreTemplate { msg_fields['exitStatus'] = workflow.exitStatus msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') msg_fields['errorReport'] = (workflow.errorReport ?: 'None') - msg_fields['commandLine'] = workflow.commandLine + msg_fields['commandLine'] = workflow.commandLine.replaceFirst(/ +--hook_url +[^ ]+/, "") msg_fields['projectDir'] = workflow.projectDir msg_fields['summary'] = summary << misc_fields // Render the JSON template def engine = new groovy.text.GStringTemplateEngine() - def hf = new File("$projectDir/assets/adaptivecard.json") + // Different JSON depending on the service provider + // Defaults to "Adaptive Cards" (https://adaptivecards.io), except Slack which has its own format + def json_path = hook_url.contains("hooks.slack.com") ? "slackreport.json" : "adaptivecard.json" + def hf = new File("$projectDir/assets/${json_path}") def json_template = engine.createTemplate(hf).make(msg_fields) def json_message = json_template.toString() @@ -209,7 +231,7 @@ class NfcoreTemplate { if (workflow.stats.ignoredCount == 0) { log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" + log.info "-${colors.purple}[$workflow.manifest.name]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" } } else { log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" @@ -297,6 +319,7 @@ class NfcoreTemplate { // public static String logo(workflow, monochrome_logs) { Map colors = logColours(monochrome_logs) + String workflow_version = NfcoreTemplate.version(workflow) String.format( """\n ${dashedLine(monochrome_logs)} @@ -305,7 +328,7 @@ class NfcoreTemplate { ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} ${colors.green}`._,._,\'${colors.reset} - ${colors.purple} ${workflow.manifest.name} v${workflow.manifest.version}${colors.reset} + ${colors.purple} ${workflow.manifest.name} ${workflow_version}${colors.reset} ${dashedLine(monochrome_logs)} """.stripIndent() ) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 20c7ed32..b548b431 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -19,7 +19,7 @@ class WorkflowMain { } // - // Print help to screen if required + // Generate help string // public static String help(workflow, params, log) { def command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh37 -profile docker" @@ -32,7 +32,7 @@ class WorkflowMain { } // - // Print parameter summary log to screen + // Generate parameter summary log string // public static String paramsSummaryLog(workflow, params, log) { def summary_log = '' @@ -53,15 +53,21 @@ class WorkflowMain { System.exit(0) } - // Validate workflow parameters via the JSON schema - if (params.validate_params) { - NfcoreSchema.validateParameters(workflow, params, log) + // Print workflow version and exit on --version + if (params.version) { + String workflow_version = NfcoreTemplate.version(workflow) + log.info "${workflow.manifest.name} ${workflow_version}" + System.exit(0) } // Print parameter summary log to screen - log.info paramsSummaryLog(workflow, params, log) + // Validate workflow parameters via the JSON schema + if (params.validate_params) { + NfcoreSchema.validateParameters(workflow, params, log) + } + // Check that a -profile or Nextflow config has been provided to run the pipeline NfcoreTemplate.checkConfigProvided(workflow, log) diff --git a/modules.json b/modules.json index 8bda1bc5..b877da7d 100644 --- a/modules.json +++ b/modules.json @@ -7,15 +7,18 @@ "nf-core": { "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "installed_by": ["modules"] }, "fastqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "installed_by": ["modules"] } } } diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf index 9aaecf0c..ec199b75 100644 --- a/modules/local/samplesheet_check.nf +++ b/modules/local/samplesheet_check.nf @@ -1,5 +1,6 @@ process SAMPLESHEET_CHECK { tag "$samplesheet" + label 'process_single' conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? @@ -13,6 +14,9 @@ process SAMPLESHEET_CHECK { path '*.csv' , emit: csv path "versions.yml", emit: versions + when: + task.ext.when == null || task.ext.when + script: // This script is bundled with the pipeline, in nf-core/nanoseq/bin/ """ check_samplesheet.py \\ diff --git a/nextflow.config b/nextflow.config index 82df95cf..729681d0 100644 --- a/nextflow.config +++ b/nextflow.config @@ -35,6 +35,7 @@ params { monochrome_logs = false hook_url = null help = false + version = false validate_params = true show_hidden_params = false schema_ignore_params = 'genomes' @@ -81,6 +82,7 @@ profiles { debug { process.beforeScript = 'echo $HOSTNAME' } conda { params.enable_conda = true + conda.enabled = true docker.enabled = false singularity.enabled = false podman.enabled = false @@ -89,6 +91,7 @@ profiles { } mamba { params.enable_conda = true + conda.enabled = true conda.useMamba = true docker.enabled = false singularity.enabled = false @@ -104,6 +107,9 @@ profiles { shifter.enabled = false charliecloud.enabled = false } + arm { + docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' + } singularity { singularity.enabled = true singularity.autoMounts = true @@ -185,11 +191,11 @@ dag { manifest { name = 'nf-core/nanoseq' - author = 'Chelsea Sawyer, Yuk Kei Wan' + author = """Chelsea Sawyer, Yuk Kei Wan""" homePage = 'https://github.com/nf-core/nanoseq' - description = 'A pipeline to demultiplex, QC and map Nanopore data' + description = """A pipeline to demultiplex, QC and map Nanopore data""" mainScript = 'main.nf' - nextflowVersion = '!>=21.10.3' + nextflowVersion = '!>=22.10.1' version = '3.0.0' doi = '' } diff --git a/nextflow_schema.json b/nextflow_schema.json index a7dbb3eb..1c581ab3 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -176,6 +176,12 @@ "fa_icon": "fas fa-question-circle", "hidden": true }, + "version": { + "type": "boolean", + "description": "Display version and exit.", + "fa_icon": "fas fa-question-circle", + "hidden": true + }, "publish_dir_mode": { "type": "string", "default": "copy", @@ -217,7 +223,7 @@ "type": "string", "description": "Incoming hook URL for messaging service", "fa_icon": "fas fa-people-group", - "help_text": "Incoming hook URL for messaging service. Currently, only MS Teams is supported.", + "help_text": "Incoming hook URL for messaging service. Currently, MS Teams and Slack are supported.", "hidden": true }, "multiqc_config": { diff --git a/workflows/nanoseq.nf b/workflows/nanoseq.nf index a4fe77f7..76a78f16 100644 --- a/workflows/nanoseq.nf +++ b/workflows/nanoseq.nf @@ -82,7 +82,7 @@ workflow NANOSEQ { ch_versions = ch_versions.mix(FASTQC.out.versions.first()) CUSTOM_DUMPSOFTWAREVERSIONS ( - ch_versions.unique().collectFile(name: 'collated_versions.yml') + ch_versions.unique{ it.text }.collectFile(name: 'collated_versions.yml') ) // @@ -102,12 +102,11 @@ workflow NANOSEQ { MULTIQC ( ch_multiqc_files.collect(), - ch_multiqc_config.collect().ifEmpty([]), - ch_multiqc_custom_config.collect().ifEmpty([]), - ch_multiqc_logo.collect().ifEmpty([]) + ch_multiqc_config.toList(), + ch_multiqc_custom_config.toList(), + ch_multiqc_logo.toList() ) multiqc_report = MULTIQC.out.report.toList() - ch_versions = ch_versions.mix(MULTIQC.out.versions) } /* @@ -122,7 +121,7 @@ workflow.onComplete { } NfcoreTemplate.summary(workflow, params, log) if (params.hook_url) { - NfcoreTemplate.adaptivecard(workflow, params, summary_params, projectDir, log) + NfcoreTemplate.IM_notification(workflow, params, summary_params, projectDir, log) } } From 2bf280eda818185ee998ccd63fbf30ba3e0b8a83 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Mon, 19 Dec 2022 12:06:30 +0000 Subject: [PATCH 08/56] Template update for nf-core/tools version 2.7.2 --- .github/workflows/fix-linting.yml | 4 +- .github/workflows/linting_comment.yml | 2 +- lib/WorkflowMain.groovy | 2 +- modules.json | 6 +- modules/local/samplesheet_check.nf | 2 +- .../custom/dumpsoftwareversions/main.nf | 2 +- .../templates/dumpsoftwareversions.py | 99 ++++++++++--------- modules/nf-core/fastqc/main.nf | 40 +++----- modules/nf-core/multiqc/main.nf | 2 +- nextflow.config | 3 - nextflow_schema.json | 6 -- workflows/nanoseq.nf | 2 +- 12 files changed, 82 insertions(+), 88 deletions(-) mode change 100644 => 100755 modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix-linting.yml index f512acd6..7adc1caf 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix-linting.yml @@ -34,9 +34,9 @@ jobs: id: prettier_status run: | if prettier --check ${GITHUB_WORKSPACE}; then - echo "name=result::pass" >> $GITHUB_OUTPUT + echo "result=pass" >> $GITHUB_OUTPUT else - echo "name=result::fail" >> $GITHUB_OUTPUT + echo "result=fail" >> $GITHUB_OUTPUT fi - name: Run 'prettier --write' diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 39635186..0bbcd30f 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -18,7 +18,7 @@ jobs: - name: Get PR number id: pr_number - run: echo "name=pr_number::$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT + run: echo "pr_number=$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - name: Post PR comment uses: marocchino/sticky-pull-request-comment@v2 diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index b548b431..a239b3f6 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -72,7 +72,7 @@ class WorkflowMain { NfcoreTemplate.checkConfigProvided(workflow, log) // Check that conda channels are set-up correctly - if (params.enable_conda) { + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { Utils.checkCondaChannels(log) } diff --git a/modules.json b/modules.json index b877da7d..aa2690b0 100644 --- a/modules.json +++ b/modules.json @@ -7,17 +7,17 @@ "nf-core": { "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", "installed_by": ["modules"] }, "fastqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", "installed_by": ["modules"] } } diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf index ec199b75..e479b5d5 100644 --- a/modules/local/samplesheet_check.nf +++ b/modules/local/samplesheet_check.nf @@ -2,7 +2,7 @@ process SAMPLESHEET_CHECK { tag "$samplesheet" label 'process_single' - conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) + conda "conda-forge::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' }" diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf index cebb6e05..3df21765 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -2,7 +2,7 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { label 'process_single' // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) + conda "bioconda::multiqc=1.13" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py old mode 100644 new mode 100755 index 787bdb7b..e55b8d43 --- a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -1,5 +1,9 @@ #!/usr/bin/env python + +"""Provide functions to merge multiple versions.yml files.""" + + import platform from textwrap import dedent @@ -7,6 +11,7 @@ def _make_versions_html(versions): + """Generate a tabular HTML output of all versions for MultiQC.""" html = [ dedent( """\\ @@ -45,47 +50,53 @@ def _make_versions_html(versions): return "\\n".join(html) -versions_this_module = {} -versions_this_module["${task.process}"] = { - "python": platform.python_version(), - "yaml": yaml.__version__, -} - -with open("$versions") as f: - versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module - -# aggregate versions by the module name (derived from fully-qualified process name) -versions_by_module = {} -for process, process_versions in versions_by_process.items(): - module = process.split(":")[-1] - try: - if versions_by_module[module] != process_versions: - raise AssertionError( - "We assume that software versions are the same between all modules. " - "If you see this error-message it means you discovered an edge-case " - "and should open an issue in nf-core/tools. " - ) - except KeyError: - versions_by_module[module] = process_versions - -versions_by_module["Workflow"] = { - "Nextflow": "$workflow.nextflow.version", - "$workflow.manifest.name": "$workflow.manifest.version", -} - -versions_mqc = { - "id": "software_versions", - "section_name": "${workflow.manifest.name} Software Versions", - "section_href": "https://github.com/${workflow.manifest.name}", - "plot_type": "html", - "description": "are collected at run time from the software output.", - "data": _make_versions_html(versions_by_module), -} - -with open("software_versions.yml", "w") as f: - yaml.dump(versions_by_module, f, default_flow_style=False) -with open("software_versions_mqc.yml", "w") as f: - yaml.dump(versions_mqc, f, default_flow_style=False) - -with open("versions.yml", "w") as f: - yaml.dump(versions_this_module, f, default_flow_style=False) +def main(): + """Load all version files and generate merged output.""" + versions_this_module = {} + versions_this_module["${task.process}"] = { + "python": platform.python_version(), + "yaml": yaml.__version__, + } + + with open("$versions") as f: + versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module + + # aggregate versions by the module name (derived from fully-qualified process name) + versions_by_module = {} + for process, process_versions in versions_by_process.items(): + module = process.split(":")[-1] + try: + if versions_by_module[module] != process_versions: + raise AssertionError( + "We assume that software versions are the same between all modules. " + "If you see this error-message it means you discovered an edge-case " + "and should open an issue in nf-core/tools. " + ) + except KeyError: + versions_by_module[module] = process_versions + + versions_by_module["Workflow"] = { + "Nextflow": "$workflow.nextflow.version", + "$workflow.manifest.name": "$workflow.manifest.version", + } + + versions_mqc = { + "id": "software_versions", + "section_name": "${workflow.manifest.name} Software Versions", + "section_href": "https://github.com/${workflow.manifest.name}", + "plot_type": "html", + "description": "are collected at run time from the software output.", + "data": _make_versions_html(versions_by_module), + } + + with open("software_versions.yml", "w") as f: + yaml.dump(versions_by_module, f, default_flow_style=False) + with open("software_versions_mqc.yml", "w") as f: + yaml.dump(versions_mqc, f, default_flow_style=False) + + with open("versions.yml", "w") as f: + yaml.dump(versions_this_module, f, default_flow_style=False) + + +if __name__ == "__main__": + main() diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 05730368..9ae58381 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -2,7 +2,7 @@ process FASTQC { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::fastqc=0.11.9" : null) + conda "bioconda::fastqc=0.11.9" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastqc:0.11.9--0' : 'quay.io/biocontainers/fastqc:0.11.9--0' }" @@ -20,30 +20,22 @@ process FASTQC { script: def args = task.ext.args ?: '' - // Add soft-links to original FastQs for consistent naming in pipeline def prefix = task.ext.prefix ?: "${meta.id}" - if (meta.single_end) { - """ - [ ! -f ${prefix}.fastq.gz ] && ln -s $reads ${prefix}.fastq.gz - fastqc $args --threads $task.cpus ${prefix}.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ - } else { - """ - [ ! -f ${prefix}_1.fastq.gz ] && ln -s ${reads[0]} ${prefix}_1.fastq.gz - [ ! -f ${prefix}_2.fastq.gz ] && ln -s ${reads[1]} ${prefix}_2.fastq.gz - fastqc $args --threads $task.cpus ${prefix}_1.fastq.gz ${prefix}_2.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ - } + // Make list of old name and new name pairs to use for renaming in the bash while loop + def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] } + def rename_to = old_new_pairs*.join(' ').join(' ') + def renamed_files = old_new_pairs.collect{ old_name, new_name -> new_name }.join(' ') + """ + printf "%s %s\\n" $rename_to | while read old_name new_name; do + [ -f "\${new_name}" ] || ln -s \$old_name \$new_name + done + fastqc $args --threads $task.cpus $renamed_files + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) + END_VERSIONS + """ stub: def prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index a8159a57..68f66bea 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,7 +1,7 @@ process MULTIQC { label 'process_single' - conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) + conda "bioconda::multiqc=1.13" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" diff --git a/nextflow.config b/nextflow.config index 729681d0..65a10e10 100644 --- a/nextflow.config +++ b/nextflow.config @@ -39,7 +39,6 @@ params { validate_params = true show_hidden_params = false schema_ignore_params = 'genomes' - enable_conda = false // Config options @@ -81,7 +80,6 @@ try { profiles { debug { process.beforeScript = 'echo $HOSTNAME' } conda { - params.enable_conda = true conda.enabled = true docker.enabled = false singularity.enabled = false @@ -90,7 +88,6 @@ profiles { charliecloud.enabled = false } mamba { - params.enable_conda = true conda.enabled = true conda.useMamba = true docker.enabled = false diff --git a/nextflow_schema.json b/nextflow_schema.json index 1c581ab3..cbf56f58 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -263,12 +263,6 @@ "description": "Show all params when using `--help`", "hidden": true, "help_text": "By default, parameters set as _hidden_ in the schema are not shown on the command line when a user runs with `--help`. Specifying this option will tell the pipeline to show all parameters." - }, - "enable_conda": { - "type": "boolean", - "description": "Run this workflow with Conda. You can also use '-profile conda' instead of providing this parameter.", - "hidden": true, - "fa_icon": "fas fa-bacon" } } } diff --git a/workflows/nanoseq.nf b/workflows/nanoseq.nf index 76a78f16..b6183985 100644 --- a/workflows/nanoseq.nf +++ b/workflows/nanoseq.nf @@ -82,7 +82,7 @@ workflow NANOSEQ { ch_versions = ch_versions.mix(FASTQC.out.versions.first()) CUSTOM_DUMPSOFTWAREVERSIONS ( - ch_versions.unique{ it.text }.collectFile(name: 'collated_versions.yml') + ch_versions.unique().collectFile(name: 'collated_versions.yml') ) // From 7c105dd363699165a31aad88c47f596ec6db5878 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Thu, 19 Jan 2023 15:47:44 +0800 Subject: [PATCH 09/56] update bambu to v3.0.6 --- modules/local/bambu.nf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/local/bambu.nf b/modules/local/bambu.nf index 6fe8b3e5..d10d5516 100644 --- a/modules/local/bambu.nf +++ b/modules/local/bambu.nf @@ -1,8 +1,10 @@ process BAMBU { label 'process_medium' - conda (params.enable_conda ? "conda-forge::r-base=4.0.3 bioconda::bioconductor-bambu=2.0.0 bioconda::bioconductor-bsgenome=1.62.0" : null) - container "docker.io/yuukiiwa/nanoseq:bambu_bsgenome" //not on biocontainers; does not have a singularity container + conda (params.enable_conda ? "conda-forge::r-base=4.0.3 bioconda::bioconductor-bambu=3.0.6 bioconda::bioconductor-bsgenome=1.62.0" : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bioconductor-bambu:3.0.6--r42hc247a5b_0' : + 'quay.io/biocontainers/bioconductor-bambu:3.0.6--r42hc247a5b_0' }" input: tuple path(fasta), path(gtf) From 593650fc8e2e3dc2d31ca97cde11c60fd80521aa Mon Sep 17 00:00:00 2001 From: Christopher Hakkaart Date: Thu, 19 Jan 2023 08:53:18 +0100 Subject: [PATCH 10/56] Update test_bc_nodx.config Revert fusion test --- conf/test_bc_nodx.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/test_bc_nodx.config b/conf/test_bc_nodx.config index 70617e7c..7ca3d308 100644 --- a/conf/test_bc_nodx.config +++ b/conf/test_bc_nodx.config @@ -23,7 +23,7 @@ params { kit = 'SQK-DCS108' skip_demultiplexing = true skip_quantification = true - skip_fusion_analysis= false + skip_fusion_analysis= true skip_modification_analysis=true // This variable is just for reference and isnt actually required for the tests From 9995520633a474543072e53c77b81cf58afbcaf8 Mon Sep 17 00:00:00 2001 From: Christopher Hakkaart Date: Thu, 19 Jan 2023 08:53:50 +0100 Subject: [PATCH 11/56] Update test_nobc_nodx_noaln.config Revert fusion test --- conf/test_nobc_nodx_noaln.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/test_nobc_nodx_noaln.config b/conf/test_nobc_nodx_noaln.config index 2b77e328..988083c4 100644 --- a/conf/test_nobc_nodx_noaln.config +++ b/conf/test_nobc_nodx_noaln.config @@ -22,6 +22,6 @@ params { skip_basecalling = true skip_demultiplexing = true skip_alignment = true - skip_fusion_analysis= false + skip_fusion_analysis = true skip_modification_analysis=true } From 4b72e551c263efd0725fb83c663b2d2fb54dcaed Mon Sep 17 00:00:00 2001 From: Christopher Hakkaart Date: Thu, 19 Jan 2023 08:55:21 +0100 Subject: [PATCH 12/56] Update test_nobc_nodx_noaln.config Revert fusion test format --- conf/test_nobc_nodx_noaln.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/test_nobc_nodx_noaln.config b/conf/test_nobc_nodx_noaln.config index 988083c4..abec7b05 100644 --- a/conf/test_nobc_nodx_noaln.config +++ b/conf/test_nobc_nodx_noaln.config @@ -22,6 +22,6 @@ params { skip_basecalling = true skip_demultiplexing = true skip_alignment = true - skip_fusion_analysis = true + skip_fusion_analysis= true skip_modification_analysis=true } From 722af665c5e41f0f3c22680dba0fd8bd1e6f4eff Mon Sep 17 00:00:00 2001 From: Christopher Hakkaart Date: Thu, 19 Jan 2023 10:14:09 +0100 Subject: [PATCH 13/56] Update usage.md fix: add --skip_quantification for DNA analysis --- docs/usage.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/usage.md b/docs/usage.md index 2c2f0843..267636b9 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -95,6 +95,7 @@ nextflow run nf-core/nanoseq \ --input_path ./undemultiplexed.fastq.gz \ --barcode_kit 'NBD103/NBD104' \ --skip_basecalling \ + --skip_quantification \ -profile ``` From 3fb13702f0e92e119205294fb005c72252139285 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Wed, 1 Feb 2023 16:56:09 +0800 Subject: [PATCH 14/56] deseq2 bug fix --- bin/run_deseq2.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/run_deseq2.r b/bin/run_deseq2.r index 7f6a705b..f35904fd 100755 --- a/bin/run_deseq2.r +++ b/bin/run_deseq2.r @@ -50,7 +50,7 @@ if (transcriptquant == "stringtie2"){ rownames(countTab) <-count.matrix[,1] } if (transcriptquant == "bambu"){ - countTab <- data.frame(read.table(path,sep="\t",header=TRUE)) + countTab <- data.frame(read.table(path,sep="\t",header=TRUE,row.names = 1)) colnames(countTab) <- unlist(lapply(strsplit(colnames(countTab),"\\."),"[[",1)) countTab[,1:length(colnames(countTab))] <- sapply(countTab, as.integer) } From b4f894183054e7217fe1d57d97f69e1323c63bb6 Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Thu, 9 Feb 2023 08:53:45 +0000 Subject: [PATCH 15/56] update: added sorting to sv calling --- conf/modules.config | 4 +- modules.json | 130 ++++++++++++------ modules/nf-core/bcftools/sort/main.nf | 47 +++++++ modules/nf-core/bcftools/sort/meta.yml | 43 ++++++ .../custom/dumpsoftwareversions/main.nf | 0 .../custom/dumpsoftwareversions/meta.yml | 0 .../templates/dumpsoftwareversions.py | 0 modules/nf-core/{modules => }/fastqc/main.nf | 0 modules/nf-core/{modules => }/fastqc/meta.yml | 0 .../nf-core/{modules => }/nanolyse/main.nf | 0 .../nf-core/{modules => }/nanolyse/meta.yml | 0 modules/nf-core/{modules => }/pycoqc/main.nf | 0 modules/nf-core/{modules => }/pycoqc/meta.yml | 0 .../{modules => }/samtools/faidx/main.nf | 0 .../{modules => }/samtools/faidx/meta.yml | 0 .../{modules => }/samtools/flagstat/main.nf | 0 .../{modules => }/samtools/flagstat/meta.yml | 0 .../{modules => }/samtools/idxstats/main.nf | 0 .../{modules => }/samtools/idxstats/meta.yml | 0 .../{modules => }/samtools/index/main.nf | 0 .../{modules => }/samtools/index/meta.yml | 0 .../{modules => }/samtools/sort/main.nf | 0 .../{modules => }/samtools/sort/meta.yml | 0 .../{modules => }/samtools/stats/main.nf | 0 .../{modules => }/samtools/stats/meta.yml | 0 .../{modules => }/stringtie/merge/main.nf | 0 .../{modules => }/stringtie/merge/meta.yml | 0 .../nf-core/{modules => }/tabix/bgzip/main.nf | 0 .../{modules => }/tabix/bgzip/meta.yml | 0 .../{modules => }/tabix/bgziptabix/main.nf | 0 .../{modules => }/tabix/bgziptabix/meta.yml | 0 .../nf-core/{modules => }/tabix/tabix/main.nf | 0 .../{modules => }/tabix/tabix/meta.yml | 0 modules/nf-core/{modules => }/untar/main.nf | 0 modules/nf-core/{modules => }/untar/meta.yml | 0 subworkflows/local/bam_sort_index_samtools.nf | 4 +- subworkflows/local/prepare_genome.nf | 2 +- .../local/qcbasecall_pycoqc_nanoplot.nf | 2 +- subworkflows/local/qcfastq_nanoplot_fastqc.nf | 2 +- .../local/quantify_stringtie_featurecounts.nf | 2 +- subworkflows/local/rna_fusions_jaffal.nf | 2 +- subworkflows/local/short_variant_calling.nf | 8 +- .../local/structural_variant_calling.nf | 26 ++-- subworkflows/nf-core/bam_stats_samtools.nf | 6 +- workflows/nanoseq.nf | 8 +- 45 files changed, 210 insertions(+), 76 deletions(-) create mode 100644 modules/nf-core/bcftools/sort/main.nf create mode 100644 modules/nf-core/bcftools/sort/meta.yml rename modules/nf-core/{modules => }/custom/dumpsoftwareversions/main.nf (100%) rename modules/nf-core/{modules => }/custom/dumpsoftwareversions/meta.yml (100%) rename modules/nf-core/{modules => }/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py (100%) rename modules/nf-core/{modules => }/fastqc/main.nf (100%) rename modules/nf-core/{modules => }/fastqc/meta.yml (100%) rename modules/nf-core/{modules => }/nanolyse/main.nf (100%) rename modules/nf-core/{modules => }/nanolyse/meta.yml (100%) rename modules/nf-core/{modules => }/pycoqc/main.nf (100%) rename modules/nf-core/{modules => }/pycoqc/meta.yml (100%) rename modules/nf-core/{modules => }/samtools/faidx/main.nf (100%) rename modules/nf-core/{modules => }/samtools/faidx/meta.yml (100%) rename modules/nf-core/{modules => }/samtools/flagstat/main.nf (100%) rename modules/nf-core/{modules => }/samtools/flagstat/meta.yml (100%) rename modules/nf-core/{modules => }/samtools/idxstats/main.nf (100%) rename modules/nf-core/{modules => }/samtools/idxstats/meta.yml (100%) rename modules/nf-core/{modules => }/samtools/index/main.nf (100%) rename modules/nf-core/{modules => }/samtools/index/meta.yml (100%) rename modules/nf-core/{modules => }/samtools/sort/main.nf (100%) rename modules/nf-core/{modules => }/samtools/sort/meta.yml (100%) rename modules/nf-core/{modules => }/samtools/stats/main.nf (100%) rename modules/nf-core/{modules => }/samtools/stats/meta.yml (100%) rename modules/nf-core/{modules => }/stringtie/merge/main.nf (100%) rename modules/nf-core/{modules => }/stringtie/merge/meta.yml (100%) rename modules/nf-core/{modules => }/tabix/bgzip/main.nf (100%) rename modules/nf-core/{modules => }/tabix/bgzip/meta.yml (100%) rename modules/nf-core/{modules => }/tabix/bgziptabix/main.nf (100%) rename modules/nf-core/{modules => }/tabix/bgziptabix/meta.yml (100%) rename modules/nf-core/{modules => }/tabix/tabix/main.nf (100%) rename modules/nf-core/{modules => }/tabix/tabix/meta.yml (100%) rename modules/nf-core/{modules => }/untar/main.nf (100%) rename modules/nf-core/{modules => }/untar/meta.yml (100%) diff --git a/conf/modules.config b/conf/modules.config index fd272ba4..60433ee8 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -518,7 +518,7 @@ if (params.call_variants) { } } process { - withName: SNIFFLES_BGZIP_VCF { + withName: SNIFFLES_SORT_VCF { publishDir = [ path: { "${params.outdir}/variant_calling/sniffles" }, mode: 'copy', @@ -550,7 +550,7 @@ if (params.call_variants) { } } process { - withName: CUTESV_BGZIP_VCF { + withName: CUTESV_SORT_VCF { publishDir = [ path: { "${params.outdir}/variant_calling/cutesv" }, mode: 'copy', diff --git a/modules.json b/modules.json index fba548fb..a0e1f752 100644 --- a/modules.json +++ b/modules.json @@ -2,51 +2,93 @@ "name": "nf-core/nanoseq", "homePage": "https://github.com/nf-core/nanoseq", "repos": { - "nf-core/modules": { - "custom/dumpsoftwareversions": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" + "https://github.com/nf-core/modules.git": { + "modules": { + "nf-core": { + "bcftools/sort": { + "branch": "master", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "installed_by": ["modules"] + }, + "custom/dumpsoftwareversions": { + "branch": "master", + "git_sha": "82501fe6d0d12614db67751d30af98d16e63dc59", + "installed_by": ["modules"] + }, + "fastqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "installed_by": ["modules"] + }, + "nanolyse": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "installed_by": ["modules"] + }, + "pycoqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "installed_by": ["modules"] + }, + "samtools/faidx": { + "branch": "master", + "git_sha": "3eb99152cedbb7280258858e5df08478a4670696", + "installed_by": ["modules"] + }, + "samtools/flagstat": { + "branch": "master", + "git_sha": "bbb99cb8d679555cc01c98766de7869f83283545", + "installed_by": ["modules"] + }, + "samtools/idxstats": { + "branch": "master", + "git_sha": "f0a86eaf5bf6ca73c5571193edd00c25bfa308f5", + "installed_by": ["modules"] + }, + "samtools/index": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "installed_by": ["modules"] + }, + "samtools/sort": { + "branch": "master", + "git_sha": "d5d785b3d8b422cda9c6d84a23f629a8e9ff8cd8", + "installed_by": ["modules"] + }, + "samtools/stats": { + "branch": "master", + "git_sha": "f4eab7945952dc4934224309701a49913ea05ae6", + "installed_by": ["modules"] + }, + "stringtie/merge": { + "branch": "master", + "git_sha": "29568f72ca66fe56d81bde3a97ac2a8c2824926a", + "installed_by": ["modules"] + }, + "tabix/bgzip": { + "branch": "master", + "git_sha": "31c0b49f6527ef196e89eca49a36af2de71711f8", + "installed_by": ["modules"] + }, + "tabix/bgziptabix": { + "branch": "master", + "git_sha": "5e7b1ef9a5a2d9258635bcbf70fcf37dacd1b247", + "installed_by": ["modules"] + }, + "tabix/tabix": { + "branch": "master", + "git_sha": "5e7b1ef9a5a2d9258635bcbf70fcf37dacd1b247", + "installed_by": ["modules"] + }, + "untar": { + "branch": "master", + "git_sha": "b63b9f752dc8e43fc70b0491aad5e0a270ab0e10", + "installed_by": ["modules"] + } + } }, - "fastqc": { - "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" - }, - "nanolyse": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "pycoqc": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "samtools/faidx": { - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/flagstat": { - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/idxstats": { - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/index": { - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/sort": { - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/stats": { - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "stringtie/merge": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "tabix/bgzip": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "tabix/bgziptabix": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "tabix/tabix": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "untar": { - "git_sha": "9ae34a01d1747019fd37753ff4cafb05aec35a2b" + "subworkflows": { + "nf-core": {} } } } diff --git a/modules/nf-core/bcftools/sort/main.nf b/modules/nf-core/bcftools/sort/main.nf new file mode 100644 index 00000000..13d75b27 --- /dev/null +++ b/modules/nf-core/bcftools/sort/main.nf @@ -0,0 +1,47 @@ +process BCFTOOLS_SORT { + tag "$meta.id" + label 'process_medium' + + conda "bioconda::bcftools=1.16" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bcftools:1.16--hfe4b78e_1': + 'quay.io/biocontainers/bcftools:1.16--hfe4b78e_1' }" + + input: + tuple val(meta), path(vcf) + + output: + tuple val(meta), path("*.gz"), emit: vcf + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + bcftools \\ + sort \\ + --output ${prefix}.vcf.gz \\ + $args \\ + $vcf + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$(bcftools --version 2>&1 | head -n1 | sed 's/^.*bcftools //; s/ .*\$//') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + + """ + touch ${prefix}.vcf.gz + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$(bcftools --version 2>&1 | head -n1 | sed 's/^.*bcftools //; s/ .*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/bcftools/sort/meta.yml b/modules/nf-core/bcftools/sort/meta.yml new file mode 100644 index 00000000..0c244a48 --- /dev/null +++ b/modules/nf-core/bcftools/sort/meta.yml @@ -0,0 +1,43 @@ +name: bcftools_sort +description: Sorts VCF files +keywords: + - sorting + - VCF + - variant calling +tools: + - sort: + description: Sort VCF files by coordinates. + homepage: http://samtools.github.io/bcftools/bcftools.html + documentation: http://www.htslib.org/doc/bcftools.html + tool_dev_url: https://github.com/samtools/bcftools + doi: "10.1093/bioinformatics/btp352" + licence: ["MIT"] + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - vcf: + type: file + description: The VCF/BCF file to be sorted + pattern: "*.{vcf.gz,vcf,bcf}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - vcf: + type: file + description: Sorted VCF file + pattern: "*.{vcf.gz}" + +authors: + - "@Gwennid" diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf similarity index 100% rename from modules/nf-core/modules/custom/dumpsoftwareversions/main.nf rename to modules/nf-core/custom/dumpsoftwareversions/main.nf diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/custom/dumpsoftwareversions/meta.yml similarity index 100% rename from modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml rename to modules/nf-core/custom/dumpsoftwareversions/meta.yml diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py similarity index 100% rename from modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py rename to modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py diff --git a/modules/nf-core/modules/fastqc/main.nf b/modules/nf-core/fastqc/main.nf similarity index 100% rename from modules/nf-core/modules/fastqc/main.nf rename to modules/nf-core/fastqc/main.nf diff --git a/modules/nf-core/modules/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml similarity index 100% rename from modules/nf-core/modules/fastqc/meta.yml rename to modules/nf-core/fastqc/meta.yml diff --git a/modules/nf-core/modules/nanolyse/main.nf b/modules/nf-core/nanolyse/main.nf similarity index 100% rename from modules/nf-core/modules/nanolyse/main.nf rename to modules/nf-core/nanolyse/main.nf diff --git a/modules/nf-core/modules/nanolyse/meta.yml b/modules/nf-core/nanolyse/meta.yml similarity index 100% rename from modules/nf-core/modules/nanolyse/meta.yml rename to modules/nf-core/nanolyse/meta.yml diff --git a/modules/nf-core/modules/pycoqc/main.nf b/modules/nf-core/pycoqc/main.nf similarity index 100% rename from modules/nf-core/modules/pycoqc/main.nf rename to modules/nf-core/pycoqc/main.nf diff --git a/modules/nf-core/modules/pycoqc/meta.yml b/modules/nf-core/pycoqc/meta.yml similarity index 100% rename from modules/nf-core/modules/pycoqc/meta.yml rename to modules/nf-core/pycoqc/meta.yml diff --git a/modules/nf-core/modules/samtools/faidx/main.nf b/modules/nf-core/samtools/faidx/main.nf similarity index 100% rename from modules/nf-core/modules/samtools/faidx/main.nf rename to modules/nf-core/samtools/faidx/main.nf diff --git a/modules/nf-core/modules/samtools/faidx/meta.yml b/modules/nf-core/samtools/faidx/meta.yml similarity index 100% rename from modules/nf-core/modules/samtools/faidx/meta.yml rename to modules/nf-core/samtools/faidx/meta.yml diff --git a/modules/nf-core/modules/samtools/flagstat/main.nf b/modules/nf-core/samtools/flagstat/main.nf similarity index 100% rename from modules/nf-core/modules/samtools/flagstat/main.nf rename to modules/nf-core/samtools/flagstat/main.nf diff --git a/modules/nf-core/modules/samtools/flagstat/meta.yml b/modules/nf-core/samtools/flagstat/meta.yml similarity index 100% rename from modules/nf-core/modules/samtools/flagstat/meta.yml rename to modules/nf-core/samtools/flagstat/meta.yml diff --git a/modules/nf-core/modules/samtools/idxstats/main.nf b/modules/nf-core/samtools/idxstats/main.nf similarity index 100% rename from modules/nf-core/modules/samtools/idxstats/main.nf rename to modules/nf-core/samtools/idxstats/main.nf diff --git a/modules/nf-core/modules/samtools/idxstats/meta.yml b/modules/nf-core/samtools/idxstats/meta.yml similarity index 100% rename from modules/nf-core/modules/samtools/idxstats/meta.yml rename to modules/nf-core/samtools/idxstats/meta.yml diff --git a/modules/nf-core/modules/samtools/index/main.nf b/modules/nf-core/samtools/index/main.nf similarity index 100% rename from modules/nf-core/modules/samtools/index/main.nf rename to modules/nf-core/samtools/index/main.nf diff --git a/modules/nf-core/modules/samtools/index/meta.yml b/modules/nf-core/samtools/index/meta.yml similarity index 100% rename from modules/nf-core/modules/samtools/index/meta.yml rename to modules/nf-core/samtools/index/meta.yml diff --git a/modules/nf-core/modules/samtools/sort/main.nf b/modules/nf-core/samtools/sort/main.nf similarity index 100% rename from modules/nf-core/modules/samtools/sort/main.nf rename to modules/nf-core/samtools/sort/main.nf diff --git a/modules/nf-core/modules/samtools/sort/meta.yml b/modules/nf-core/samtools/sort/meta.yml similarity index 100% rename from modules/nf-core/modules/samtools/sort/meta.yml rename to modules/nf-core/samtools/sort/meta.yml diff --git a/modules/nf-core/modules/samtools/stats/main.nf b/modules/nf-core/samtools/stats/main.nf similarity index 100% rename from modules/nf-core/modules/samtools/stats/main.nf rename to modules/nf-core/samtools/stats/main.nf diff --git a/modules/nf-core/modules/samtools/stats/meta.yml b/modules/nf-core/samtools/stats/meta.yml similarity index 100% rename from modules/nf-core/modules/samtools/stats/meta.yml rename to modules/nf-core/samtools/stats/meta.yml diff --git a/modules/nf-core/modules/stringtie/merge/main.nf b/modules/nf-core/stringtie/merge/main.nf similarity index 100% rename from modules/nf-core/modules/stringtie/merge/main.nf rename to modules/nf-core/stringtie/merge/main.nf diff --git a/modules/nf-core/modules/stringtie/merge/meta.yml b/modules/nf-core/stringtie/merge/meta.yml similarity index 100% rename from modules/nf-core/modules/stringtie/merge/meta.yml rename to modules/nf-core/stringtie/merge/meta.yml diff --git a/modules/nf-core/modules/tabix/bgzip/main.nf b/modules/nf-core/tabix/bgzip/main.nf similarity index 100% rename from modules/nf-core/modules/tabix/bgzip/main.nf rename to modules/nf-core/tabix/bgzip/main.nf diff --git a/modules/nf-core/modules/tabix/bgzip/meta.yml b/modules/nf-core/tabix/bgzip/meta.yml similarity index 100% rename from modules/nf-core/modules/tabix/bgzip/meta.yml rename to modules/nf-core/tabix/bgzip/meta.yml diff --git a/modules/nf-core/modules/tabix/bgziptabix/main.nf b/modules/nf-core/tabix/bgziptabix/main.nf similarity index 100% rename from modules/nf-core/modules/tabix/bgziptabix/main.nf rename to modules/nf-core/tabix/bgziptabix/main.nf diff --git a/modules/nf-core/modules/tabix/bgziptabix/meta.yml b/modules/nf-core/tabix/bgziptabix/meta.yml similarity index 100% rename from modules/nf-core/modules/tabix/bgziptabix/meta.yml rename to modules/nf-core/tabix/bgziptabix/meta.yml diff --git a/modules/nf-core/modules/tabix/tabix/main.nf b/modules/nf-core/tabix/tabix/main.nf similarity index 100% rename from modules/nf-core/modules/tabix/tabix/main.nf rename to modules/nf-core/tabix/tabix/main.nf diff --git a/modules/nf-core/modules/tabix/tabix/meta.yml b/modules/nf-core/tabix/tabix/meta.yml similarity index 100% rename from modules/nf-core/modules/tabix/tabix/meta.yml rename to modules/nf-core/tabix/tabix/meta.yml diff --git a/modules/nf-core/modules/untar/main.nf b/modules/nf-core/untar/main.nf similarity index 100% rename from modules/nf-core/modules/untar/main.nf rename to modules/nf-core/untar/main.nf diff --git a/modules/nf-core/modules/untar/meta.yml b/modules/nf-core/untar/meta.yml similarity index 100% rename from modules/nf-core/modules/untar/meta.yml rename to modules/nf-core/untar/meta.yml diff --git a/subworkflows/local/bam_sort_index_samtools.nf b/subworkflows/local/bam_sort_index_samtools.nf index 635f33c1..eb0ab0f7 100644 --- a/subworkflows/local/bam_sort_index_samtools.nf +++ b/subworkflows/local/bam_sort_index_samtools.nf @@ -3,8 +3,8 @@ */ include { SAMTOOLS_VIEW_BAM } from '../../modules/local/samtools_view_bam' -include { SAMTOOLS_SORT } from '../../modules/nf-core/modules/samtools/sort/main' -include { SAMTOOLS_INDEX } from '../../modules/nf-core/modules/samtools/index/main' +include { SAMTOOLS_SORT } from '../../modules/nf-core/samtools/sort/main' +include { SAMTOOLS_INDEX } from '../../modules/nf-core/samtools/index/main' include { SAMTOOLS_SORT_INDEX } from '../../modules/local/samtools_sort_index' include { BAM_STATS_SAMTOOLS } from '../../subworkflows/nf-core/bam_stats_samtools' diff --git a/subworkflows/local/prepare_genome.nf b/subworkflows/local/prepare_genome.nf index 04a8b1e7..e6047cc0 100644 --- a/subworkflows/local/prepare_genome.nf +++ b/subworkflows/local/prepare_genome.nf @@ -4,7 +4,7 @@ include { GET_CHROM_SIZES } from '../../modules/local/get_chrom_sizes' include { GTF2BED } from '../../modules/local/gtf2bed' -include { SAMTOOLS_FAIDX } from '../../modules/nf-core/modules/samtools/faidx/main' +include { SAMTOOLS_FAIDX } from '../../modules/nf-core/samtools/faidx/main' workflow PREPARE_GENOME { take: diff --git a/subworkflows/local/qcbasecall_pycoqc_nanoplot.nf b/subworkflows/local/qcbasecall_pycoqc_nanoplot.nf index 53d76c2e..e0724eb9 100644 --- a/subworkflows/local/qcbasecall_pycoqc_nanoplot.nf +++ b/subworkflows/local/qcbasecall_pycoqc_nanoplot.nf @@ -2,7 +2,7 @@ * Basecalling QC with PycoQC and NanoPlot */ -include { PYCOQC } from '../../modules/nf-core/modules/pycoqc/main' +include { PYCOQC } from '../../modules/nf-core/pycoqc/main' include { NANOPLOT } from '../../modules/local/nanoplot' workflow QCBASECALL_PYCOQC_NANOPLOT { diff --git a/subworkflows/local/qcfastq_nanoplot_fastqc.nf b/subworkflows/local/qcfastq_nanoplot_fastqc.nf index 2c53f14d..3c30e7c6 100644 --- a/subworkflows/local/qcfastq_nanoplot_fastqc.nf +++ b/subworkflows/local/qcfastq_nanoplot_fastqc.nf @@ -3,7 +3,7 @@ */ include { NANOPLOT } from '../../modules/local/nanoplot' -include { FASTQC } from '../../modules/nf-core/modules/fastqc/main' +include { FASTQC } from '../../modules/nf-core/fastqc/main' workflow QCFASTQ_NANOPLOT_FASTQC { take: diff --git a/subworkflows/local/quantify_stringtie_featurecounts.nf b/subworkflows/local/quantify_stringtie_featurecounts.nf index c5055167..0e67cf4b 100644 --- a/subworkflows/local/quantify_stringtie_featurecounts.nf +++ b/subworkflows/local/quantify_stringtie_featurecounts.nf @@ -3,7 +3,7 @@ */ include { STRINGTIE2 } from '../../modules/local/stringtie2' -include { STRINGTIE_MERGE } from '../../modules/nf-core/modules/stringtie/merge/main' +include { STRINGTIE_MERGE } from '../../modules/nf-core/stringtie/merge/main' include { SUBREAD_FEATURECOUNTS } from '../../modules/local/subread_featurecounts' workflow QUANTIFY_STRINGTIE_FEATURECOUNTS { diff --git a/subworkflows/local/rna_fusions_jaffal.nf b/subworkflows/local/rna_fusions_jaffal.nf index 2cef2997..aeac48c9 100644 --- a/subworkflows/local/rna_fusions_jaffal.nf +++ b/subworkflows/local/rna_fusions_jaffal.nf @@ -3,7 +3,7 @@ */ include { GET_JAFFAL_REF } from '../../modules/local/get_jaffal_ref' -include { UNTAR } from '../../modules/nf-core/modules/untar/main' +include { UNTAR } from '../../modules/nf-core/untar/main' include { JAFFAL } from '../../modules/local/jaffal' workflow RNA_FUSIONS_JAFFAL { diff --git a/subworkflows/local/short_variant_calling.nf b/subworkflows/local/short_variant_calling.nf index bb2b3cab..46b3b19e 100644 --- a/subworkflows/local/short_variant_calling.nf +++ b/subworkflows/local/short_variant_calling.nf @@ -3,11 +3,11 @@ */ include { MEDAKA_VARIANT } from '../../modules/local/medaka_variant' -include { TABIX_BGZIP as MEDAKA_BGZIP_VCF } from '../../modules/nf-core/modules/tabix/bgzip/main' -include { TABIX_TABIX as MEDAKA_TABIX_VCF } from '../../modules/nf-core/modules/tabix/tabix/main' +include { TABIX_BGZIP as MEDAKA_BGZIP_VCF } from '../../modules/nf-core/tabix/bgzip/main' +include { TABIX_TABIX as MEDAKA_TABIX_VCF } from '../../modules/nf-core/tabix/tabix/main' include { DEEPVARIANT } from '../../modules/local/deepvariant' -include { TABIX_TABIX as DEEPVARIANT_TABIX_VCF } from '../../modules/nf-core/modules/tabix/tabix/main' -include { TABIX_TABIX as DEEPVARIANT_TABIX_GVCF } from '../../modules/nf-core/modules/tabix/tabix/main' +include { TABIX_TABIX as DEEPVARIANT_TABIX_VCF } from '../../modules/nf-core/tabix/tabix/main' +include { TABIX_TABIX as DEEPVARIANT_TABIX_GVCF } from '../../modules/nf-core/tabix/tabix/main' include { PEPPER_MARGIN_DEEPVARIANT } from '../../modules/local/pepper_margin_deepvariant' workflow SHORT_VARIANT_CALLING { diff --git a/subworkflows/local/structural_variant_calling.nf b/subworkflows/local/structural_variant_calling.nf index ec84742d..2dcf66e4 100644 --- a/subworkflows/local/structural_variant_calling.nf +++ b/subworkflows/local/structural_variant_calling.nf @@ -3,11 +3,13 @@ */ include { SNIFFLES } from '../../modules/local/sniffles' -include { TABIX_BGZIP as SNIFFLES_BGZIP_VCF } from '../../modules/nf-core/modules/tabix/bgzip/main' -include { TABIX_TABIX as SNIFFLES_TABIX_VCF } from '../../modules/nf-core/modules/tabix/tabix/main' +include { BCFTOOLS_SORT as SNIFFLES_SORT_VCF } from '../../modules/nf-core/bcftools/sort/main' +include { TABIX_BGZIP as SNIFFLES_BGZIP_VCF } from '../../modules/nf-core/tabix/bgzip/main' +include { TABIX_TABIX as SNIFFLES_TABIX_VCF } from '../../modules/nf-core/tabix/tabix/main' include { CUTESV } from '../../modules/local/cutesv' -include { TABIX_BGZIP as CUTESV_BGZIP_VCF } from '../../modules/nf-core/modules/tabix/bgzip/main' -include { TABIX_TABIX as CUTESV_TABIX_VCF } from '../../modules/nf-core/modules/tabix/tabix/main' +include { BCFTOOLS_SORT as CUTESV_SORT_VCF } from '../../modules/nf-core/bcftools/sort/main' +include { TABIX_BGZIP as CUTESV_BGZIP_VCF } from '../../modules/nf-core/tabix/bgzip/main' +include { TABIX_TABIX as CUTESV_TABIX_VCF } from '../../modules/nf-core/tabix/tabix/main' workflow STRUCTURAL_VARIANT_CALLING { @@ -35,11 +37,11 @@ workflow STRUCTURAL_VARIANT_CALLING { ch_versions = ch_versions.mix(SNIFFLES.out.versions) /* - * Zip sniffles vcf + * Sort structural variants with bcftools */ - SNIFFLES_BGZIP_VCF( SNIFFLES.out.sv_calls ) - ch_sv_calls_vcf = SNIFFLES_BGZIP_VCF.out.gz - ch_versions = ch_versions.mix(SNIFFLES_BGZIP_VCF.out.versions) + SNIFFLES_SORT_VCF( SNIFFLES.out.sv_calls ) + ch_sv_calls_vcf = SNIFFLES_SORT_VCF.out.vcf + ch_versions = ch_versions.mix(SNIFFLES_SORT_VCF.out.versions) /* * Index sniffles vcf.gz @@ -57,11 +59,11 @@ workflow STRUCTURAL_VARIANT_CALLING { ch_versions = ch_versions.mix(CUTESV.out.versions) /* - * Zip cutesv vcf + * Sort structural variants with bcftools */ - CUTESV_BGZIP_VCF( CUTESV.out.sv_calls ) - ch_sv_calls_vcf = CUTESV_BGZIP_VCF.out.gz - ch_versions = ch_versions.mix(CUTESV_BGZIP_VCF.out.versions) + CUTESV_SORT_VCF( CUTESV.out.sv_calls ) + ch_sv_calls_vcf = CUTESV_SORT_VCF.out.vcf + ch_versions = ch_versions.mix(CUTESV_SORT_VCF.out.versions) /* * Zip cutesv vcf.gz diff --git a/subworkflows/nf-core/bam_stats_samtools.nf b/subworkflows/nf-core/bam_stats_samtools.nf index 04e443ad..d4292db1 100644 --- a/subworkflows/nf-core/bam_stats_samtools.nf +++ b/subworkflows/nf-core/bam_stats_samtools.nf @@ -2,9 +2,9 @@ * Run SAMtools stats, flagstat and idxstats */ -include { SAMTOOLS_STATS } from '../../modules/nf-core/modules/samtools/stats/main' -include { SAMTOOLS_IDXSTATS } from '../../modules/nf-core/modules/samtools/idxstats/main' -include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/modules/samtools/flagstat/main' +include { SAMTOOLS_STATS } from '../../modules/nf-core/samtools/stats/main' +include { SAMTOOLS_IDXSTATS } from '../../modules/nf-core/samtools/idxstats/main' +include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/samtools/flagstat/main' workflow BAM_STATS_SAMTOOLS { take: diff --git a/workflows/nanoseq.nf b/workflows/nanoseq.nf index d55c9376..9e93463b 100644 --- a/workflows/nanoseq.nf +++ b/workflows/nanoseq.nf @@ -15,8 +15,8 @@ checkPathParamList = [ params.input, params.multiqc_config ] for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } // Check mandatory parameters (missing protocol or profile will exit the run.) -if (params.input) { - ch_input = file(params.input) +if (params.input) { + ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } @@ -153,8 +153,8 @@ include { RNA_FUSIONS_JAFFAL } from '../subworkflows/local/rna_fus /* * MODULE: Installed directly from nf-core/modules */ -include { NANOLYSE } from '../modules/nf-core/modules/nanolyse/main' -include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' +include { NANOLYSE } from '../modules/nf-core/nanolyse/main' +include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' /* * SUBWORKFLOW: Consisting entirely of nf-core/modules From b11c68210d47c6a8fff18673fc608f379dd24cba Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Thu, 9 Feb 2023 13:25:50 +0000 Subject: [PATCH 16/56] ran nf-core lint --- .gitattributes | 1 + .github/CONTRIBUTING.md | 16 +++++ .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 3 +- .github/workflows/ci.yml | 29 ++++----- .github/workflows/linting.yml | 54 ++++++++++++----- .github/workflows/linting_comment.yml | 2 +- .prettierignore | 3 + assets/email_template.txt | 1 - lib/NfcoreSchema.groovy | 1 - lib/NfcoreTemplate.groovy | 84 ++++++++++++++++++++++++++- 11 files changed, 156 insertions(+), 40 deletions(-) diff --git a/.gitattributes b/.gitattributes index 050bb120..7a2dabc2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ *.config linguist-language=nextflow +*.nf.test linguist-language=nextflow modules/nf-core/** linguist-generated subworkflows/nf-core/** linguist-generated diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a66e3acd..30e08528 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -101,3 +101,19 @@ If you are using a new feature from core Nextflow, you may bump the minimum requ ### Images and figures For overview images and other documents we follow the nf-core [style guidelines and examples](https://nf-co.re/developers/design_guidelines). + +## GitHub Codespaces + +This repo includes a devcontainer configuration which will create a GitHub Codespaces for Nextflow development! This is an online developer environment that runs in your browser, complete with VSCode and a terminal. + +To get started: + +- Open the repo in [Codespaces](https://github.com/nf-core/nanoseq/codespaces) +- Tools installed + - nf-core + - Nextflow + +Devcontainer specs: + +- [DevContainer config](.devcontainer/devcontainer.json) +- [Dockerfile](.devcontainer/Dockerfile) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index dfcd7148..ec79522f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -42,7 +42,7 @@ body: attributes: label: System information description: | - * Nextflow version _(eg. 21.10.3)_ + * Nextflow version _(eg. 22.10.1)_ * Hardware _(eg. HPC, Desktop, Cloud)_ * Executor _(eg. slurm, local, awsbatch)_ * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter or Charliecloud)_ diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e7000854..329a6614 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,8 +15,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/nano - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! - - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/nanoseq/tree/master/.github/CONTRIBUTING.md) - - [ ] If necessary, also make a PR on the nf-core/nanoseq _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/nanoseq/tree/master/.github/CONTRIBUTING.md)- [ ] If necessary, also make a PR on the nf-core/nanoseq _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2442b2b8..59b359a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,10 @@ on: env: NXF_ANSI_LOG: false - CAPSULE_LOG: none + +concurrency: + group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" + cancel-in-progress: true jobs: test: @@ -20,27 +23,17 @@ jobs: 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" + NXF_VER: + - "22.10.1" + - "latest-everything" steps: - name: Check out pipeline code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - 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/ + uses: nf-core/setup-nextflow@v1 + with: + version: "${{ matrix.NXF_VER }}" - name: Run pipeline with test data run: | diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 77358dee..858d622e 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -4,6 +4,8 @@ name: nf-core linting # that the code meets the nf-core guidelines. on: push: + branches: + - dev pull_request: release: types: [published] @@ -12,9 +14,9 @@ jobs: EditorConfig: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 - name: Install editorconfig-checker run: npm install -g editorconfig-checker @@ -25,9 +27,9 @@ jobs: Prettier: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 - name: Install Prettier run: npm install -g prettier @@ -35,22 +37,48 @@ jobs: - name: Run Prettier --check run: prettier --check ${GITHUB_WORKSPACE} + PythonBlack: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Check code lints with Black + uses: psf/black@stable + + # If the above check failed, post a comment on the PR explaining the failure + - name: Post PR comment + if: failure() + uses: mshick/add-pr-comment@v1 + with: + message: | + ## Python linting (`black`) is failing + + To keep the code consistent with lots of contributors, we run automated code consistency checks. + To fix this CI test, please run: + + * Install [`black`](https://black.readthedocs.io/en/stable/): `pip install black` + * Fix formatting errors in your pipeline: `black .` + + Once you push these changes the test should pass, and you can hide this comment :+1: + + We highly recommend setting up Black in your code editor so that this formatting is done automatically on save. Ask about it on Slack for help! + + Thanks again for your contribution! + repo-token: ${{ secrets.GITHUB_TOKEN }} + allow-repeats: false + nf-core: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Nextflow - env: - CAPSULE_LOG: none - run: | - wget -qO- get.nextflow.io | bash - sudo mv nextflow /usr/local/bin/ + uses: nf-core/setup-nextflow@v1 - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v4 with: - python-version: "3.6" + python-version: "3.7" architecture: "x64" - name: Install dependencies @@ -71,7 +99,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: linting-logs path: | diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 04758f61..0bbcd30f 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -18,7 +18,7 @@ jobs: - name: Get PR number id: pr_number - run: echo "::set-output name=pr_number::$(cat linting-logs/PR_number.txt)" + run: echo "pr_number=$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - name: Post PR comment uses: marocchino/sticky-pull-request-comment@v2 diff --git a/.prettierignore b/.prettierignore index d0e7ae58..437d763d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,6 @@ email_template.html +adaptivecard.json +slackreport.json .nextflow* work/ data/ @@ -7,3 +9,4 @@ results/ testing/ testing* *.pyc +bin/ diff --git a/assets/email_template.txt b/assets/email_template.txt index 88c70f16..5814aa9b 100644 --- a/assets/email_template.txt +++ b/assets/email_template.txt @@ -6,7 +6,6 @@ `._,._,' nf-core/nanoseq v${version} ---------------------------------------------------- - Run Name: $runName <% if (success){ diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy index b3d092f8..33cd4f6e 100755 --- a/lib/NfcoreSchema.groovy +++ b/lib/NfcoreSchema.groovy @@ -46,7 +46,6 @@ class NfcoreSchema { 'quiet', 'syslog', 'v', - 'version', // Options for `nextflow run` command 'ansi', diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 2fc0a9b9..25a0a74a 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -32,6 +32,25 @@ class NfcoreTemplate { } } + // + // Generate version string + // + public static String version(workflow) { + String version_string = "" + + if (workflow.manifest.version) { + def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' + version_string += "${prefix_v}${workflow.manifest.version}" + } + + if (workflow.commitId) { + def git_shortsha = workflow.commitId.substring(0, 7) + version_string += "-g${git_shortsha}" + } + + return version_string + } + // // Construct and send completion email // @@ -61,7 +80,7 @@ class NfcoreTemplate { misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp def email_fields = [:] - email_fields['version'] = workflow.manifest.version + email_fields['version'] = NfcoreTemplate.version(workflow) email_fields['runName'] = workflow.runName email_fields['success'] = workflow.success email_fields['dateComplete'] = workflow.complete @@ -145,6 +164,64 @@ class NfcoreTemplate { output_tf.withWriter { w -> w << email_txt } } + // + // Construct and send a notification to a web server as JSON + // e.g. Microsoft Teams and Slack + // + public static void IM_notification(workflow, params, summary_params, projectDir, log) { + def hook_url = params.hook_url + + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['start'] = workflow.start + misc_fields['complete'] = workflow.complete + misc_fields['scriptfile'] = workflow.scriptFile + misc_fields['scriptid'] = workflow.scriptId + if (workflow.repository) misc_fields['repository'] = workflow.repository + if (workflow.commitId) misc_fields['commitid'] = workflow.commitId + if (workflow.revision) misc_fields['revision'] = workflow.revision + misc_fields['nxf_version'] = workflow.nextflow.version + misc_fields['nxf_build'] = workflow.nextflow.build + misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp + + def msg_fields = [:] + msg_fields['version'] = NfcoreTemplate.version(workflow) + msg_fields['runName'] = workflow.runName + msg_fields['success'] = workflow.success + msg_fields['dateComplete'] = workflow.complete + msg_fields['duration'] = workflow.duration + msg_fields['exitStatus'] = workflow.exitStatus + msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + msg_fields['errorReport'] = (workflow.errorReport ?: 'None') + msg_fields['commandLine'] = workflow.commandLine.replaceFirst(/ +--hook_url +[^ ]+/, "") + msg_fields['projectDir'] = workflow.projectDir + msg_fields['summary'] = summary << misc_fields + + // Render the JSON template + def engine = new groovy.text.GStringTemplateEngine() + // Different JSON depending on the service provider + // Defaults to "Adaptive Cards" (https://adaptivecards.io), except Slack which has its own format + def json_path = hook_url.contains("hooks.slack.com") ? "slackreport.json" : "adaptivecard.json" + def hf = new File("$projectDir/assets/${json_path}") + def json_template = engine.createTemplate(hf).make(msg_fields) + def json_message = json_template.toString() + + // POST + def post = new URL(hook_url).openConnection(); + post.setRequestMethod("POST") + post.setDoOutput(true) + post.setRequestProperty("Content-Type", "application/json") + post.getOutputStream().write(json_message.getBytes("UTF-8")); + def postRC = post.getResponseCode(); + if (! postRC.equals(200)) { + log.warn(post.getErrorStream().getText()); + } + } + // // Print pipeline summary on completion // @@ -154,7 +231,7 @@ class NfcoreTemplate { if (workflow.stats.ignoredCount == 0) { log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" + log.info "-${colors.purple}[$workflow.manifest.name]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" } } else { log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" @@ -242,6 +319,7 @@ class NfcoreTemplate { // public static String logo(workflow, monochrome_logs) { Map colors = logColours(monochrome_logs) + String workflow_version = NfcoreTemplate.version(workflow) String.format( """\n ${dashedLine(monochrome_logs)} @@ -250,7 +328,7 @@ class NfcoreTemplate { ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} ${colors.green}`._,._,\'${colors.reset} - ${colors.purple} ${workflow.manifest.name} v${workflow.manifest.version}${colors.reset} + ${colors.purple} ${workflow.manifest.name} ${workflow_version}${colors.reset} ${dashedLine(monochrome_logs)} """.stripIndent() ) From d3f380128e14f140c19a5b9f4f4e16605491eb44 Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Thu, 9 Feb 2023 14:35:35 +0000 Subject: [PATCH 17/56] fix medaka emit after update --- subworkflows/local/short_variant_calling.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/short_variant_calling.nf b/subworkflows/local/short_variant_calling.nf index 46b3b19e..8d947989 100644 --- a/subworkflows/local/short_variant_calling.nf +++ b/subworkflows/local/short_variant_calling.nf @@ -39,7 +39,7 @@ workflow SHORT_VARIANT_CALLING { * Zip medaka vcf */ MEDAKA_BGZIP_VCF( MEDAKA_VARIANT.out.vcf ) - ch_short_calls_vcf = MEDAKA_BGZIP_VCF.out.gz + ch_short_calls_vcf = MEDAKA_BGZIP_VCF.out.output ch_versions = ch_versions.mix(bgzip_version = MEDAKA_BGZIP_VCF.out.versions) /* From 9233e192fea33d7fb664206e79f9d41f5e45ba4d Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Thu, 9 Feb 2023 19:29:51 +0000 Subject: [PATCH 18/56] increase nextflow version in ci --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6971ae57..963b3273 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,7 @@ jobs: if: "${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/nanoseq') }}" runs-on: ubuntu-latest env: - NXF_VER: "21.10.3" + NXF_VER: "22.10.3" NXF_ANSI_LOG: false strategy: matrix: @@ -73,7 +73,7 @@ jobs: if: "${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/nanoseq') }}" runs-on: ubuntu-latest env: - NXF_VER: "21.10.3" + NXF_VER: "22.10.3" NXF_ANSI_LOG: false strategy: matrix: From f9cb93ad0b9ead2a7ac492b4b09b16560d5256e9 Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Thu, 9 Feb 2023 19:31:55 +0000 Subject: [PATCH 19/56] run black on python scripts --- bin/check_samplesheet.py | 110 +++++++++++++++++++++++---------------- bin/create_yml.py | 42 ++++++++------- 2 files changed, 88 insertions(+), 64 deletions(-) diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 4ea4165b..b5670c42 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -62,9 +62,9 @@ def check_samplesheet(file_in, updated_path, file_out): ## Check header MIN_COLS = 3 - HEADER = ['group', 'replicate', 'barcode', 'input_file', 'fasta', 'gtf'] + HEADER = ["group", "replicate", "barcode", "input_file", "fasta", "gtf"] header = fin.readline().strip().split(",") - if header[:len(HEADER)] != HEADER: + if header[: len(HEADER)] != HEADER: print("ERROR: Please check samplesheet header -> {} != {}".format(",".join(header), ",".join(HEADER))) sys.exit(1) @@ -74,40 +74,40 @@ def check_samplesheet(file_in, updated_path, file_out): ## Check valid number of columns per row if len(lspl) < len(HEADER): - print_error("Invalid number of columns (minimum = {})!".format(len(HEADER)), 'Line', line) + print_error("Invalid number of columns (minimum = {})!".format(len(HEADER)), "Line", line) num_cols = len([x for x in lspl if x]) if num_cols < MIN_COLS: - print_error("Invalid number of populated columns (minimum = {})!".format(MIN_COLS), 'Line', line) + print_error("Invalid number of populated columns (minimum = {})!".format(MIN_COLS), "Line", line) ## Check group name entries - group, replicate, barcode, input_file, fasta, gtf = lspl[:len(HEADER)] + group, replicate, barcode, input_file, fasta, gtf = lspl[: len(HEADER)] if group: if group.find(" ") != -1: - print_error("Group entry contains spaces!", 'Line', line) + print_error("Group entry contains spaces!", "Line", line) else: - print_error("Group entry has not been specified!", 'Line', line) + print_error("Group entry has not been specified!", "Line", line) ## Check replicate entry is integer if replicate: if not replicate.isdigit(): - print_error("Replicate id not an integer!", 'Line', line) + print_error("Replicate id not an integer!", "Line", line) else: - print_error("Replicate id not specified!", 'Line', line) + print_error("Replicate id not specified!", "Line", line) replicate = int(replicate) ## Check barcode entry if barcode: if not barcode.isdigit(): - print_error("Barcode entry is not an integer!", 'Line', line) + print_error("Barcode entry is not an integer!", "Line", line) else: - barcode = 'barcode%s' % (barcode.zfill(2)) + barcode = "barcode%s" % (barcode.zfill(2)) ## Check input file extension - nanopolish_fast5 = '' + nanopolish_fast5 = "" if input_file: if input_file.find(" ") != -1: - print_error("Input file contains spaces!", 'Line', line) + print_error("Input file contains spaces!", "Line", line) if input_file.endswith(".fastq.gz"): input_extensions.append("*.fastq.gz") elif input_file.endswith(".fq.gz"): @@ -116,52 +116,65 @@ def check_samplesheet(file_in, updated_path, file_out): input_extensions.append("*.bam") else: if updated_path != "not_changed": - input_file='/'.join([updated_path,input_file.split("/")[-1]]) - list_dir = os.listdir(input_file) + input_file = "/".join([updated_path, input_file.split("/")[-1]]) + list_dir = os.listdir(input_file) nanopolish_fast5 = input_file - if not (all(fname.endswith('.fast5') for fname in list_dir)): + if not (all(fname.endswith(".fast5") for fname in list_dir)): if "fast5" in list_dir and "fastq" in list_dir: - nanopolish_fast5 = input_file+'/fast5' + nanopolish_fast5 = input_file + "/fast5" ## CHECK FAST5 DIRECTORY - if not (all(fname.endswith('.fast5') for fname in os.listdir(nanopolish_fast5))): - print_error('fast5 directory contains non-fast5 files.') + if not (all(fname.endswith(".fast5") for fname in os.listdir(nanopolish_fast5))): + print_error("fast5 directory contains non-fast5 files.") ## CHECK PROVIDED BASECALLED FASTQ - fastq_path = input_file+'/fastq' - basecalled_fastq = [fn for fn in os.listdir(fastq_path) if fn.endswith(".fastq.gz") or fn.endswith(".fq.gz") ] + fastq_path = input_file + "/fastq" + basecalled_fastq = [ + fn for fn in os.listdir(fastq_path) if fn.endswith(".fastq.gz") or fn.endswith(".fq.gz") + ] if len(basecalled_fastq) != 1: - print_error('Please input one basecalled fastq per sample.') + print_error("Please input one basecalled fastq per sample.") else: - input_file = fastq_path+'/'+basecalled_fastq[0] + input_file = fastq_path + "/" + basecalled_fastq[0] if not basecalled_fastq[0].endswith(".fastq.gz"): if not basecalled_fastq[0].endswith(".fq.gz"): print_error('basecalled fastq input does not end with ".fastq.gz" or ".fq.gz"') else: - print_error('path does not end with ".fastq.gz", ".fq.gz", or ".bam" and is not an existing directory with correct fast5 and/or fastq inputs.') + print_error( + 'path does not end with ".fastq.gz", ".fq.gz", or ".bam" and is not an existing directory with correct fast5 and/or fastq inputs.' + ) ## Check genome entries if fasta: - if fasta.find(' ') != -1: - print_error("Genome entry contains spaces!",'Line', line) - if len(fasta.split('.')) > 1: - if fasta[-6:] != '.fasta' and fasta[-3:] != '.fa' and fasta[-9:] != '.fasta.gz' and fasta[-6:] != '.fa.gz': - print_error("Genome entry does not have extension '.fasta', '.fa', '.fasta.gz' or '.fa.gz'!",'Line', line) + if fasta.find(" ") != -1: + print_error("Genome entry contains spaces!", "Line", line) + if len(fasta.split(".")) > 1: + if ( + fasta[-6:] != ".fasta" + and fasta[-3:] != ".fa" + and fasta[-9:] != ".fasta.gz" + and fasta[-6:] != ".fa.gz" + ): + print_error( + "Genome entry does not have extension '.fasta', '.fa', '.fasta.gz' or '.fa.gz'!", + "Line", + line, + ) ## Check transcriptome entries - #gtf = '' - is_transcripts = '0' + # gtf = '' + is_transcripts = "0" if gtf: - if gtf.find(' ') != -1: - print_error("Transcriptome entry contains spaces!",'Line',line) + if gtf.find(" ") != -1: + print_error("Transcriptome entry contains spaces!", "Line", line) print(gtf[-4:]) - if gtf[-4:] != '.gtf' and gtf[-7:] != '.gtf.gz': - print_error("Transcriptome entry does not have extension '.gtf' or '.gtf.gz'!", 'Line', line) - #if transcriptome[-6:] != '.fasta' and transcriptome[-3:] != '.fa' and transcriptome[-9:] != '.fasta.gz' and transcriptome[-6:] != '.fa.gz' and transcriptome[-4:] != '.gtf' and transcriptome[-7:] != '.gtf.gz': + if gtf[-4:] != ".gtf" and gtf[-7:] != ".gtf.gz": + print_error("Transcriptome entry does not have extension '.gtf' or '.gtf.gz'!", "Line", line) + # if transcriptome[-6:] != '.fasta' and transcriptome[-3:] != '.fa' and transcriptome[-9:] != '.fasta.gz' and transcriptome[-6:] != '.fa.gz' and transcriptome[-4:] != '.gtf' and transcriptome[-7:] != '.gtf.gz': # print_error("Transcriptome entry does not have extension '.fasta', '.fa', '.fasta.gz', '.fa.gz', '.gtf' or '.gtf.gz'!", 'Line', line) - #if transcriptome[-4:] == '.gtf' or transcriptome[-7:] == '.gtf.gz': + # if transcriptome[-4:] == '.gtf' or transcriptome[-7:] == '.gtf.gz': # gtf = transcriptome # if not genome: # print_error("If genome isn't provided, transcriptome must be in fasta format for mapping!", 'Line', line) - #else: + # else: # is_transcripts = '1' # genome = transcriptome @@ -172,11 +185,15 @@ def check_samplesheet(file_in, updated_path, file_out): if replicate not in sample_info_dict[group]: sample_info_dict[group][replicate] = sample_info else: - print_error("Same replicate id provided multiple times!", 'Line', line) + print_error("Same replicate id provided multiple times!", "Line", line) ## Check all input files have the same extension if len(set(input_extensions)) > 1: - print_error("All input files must have the same extension!", 'Multiple extensions found', ', '.join(set(input_extensions))) + print_error( + "All input files must have the same extension!", + "Multiple extensions found", + ", ".join(set(input_extensions)), + ) ## Write validated samplesheet with appropriate columns if len(sample_info_dict) > 0: @@ -184,18 +201,21 @@ def check_samplesheet(file_in, updated_path, file_out): make_dir(out_dir) with open(file_out, "w") as fout: - fout.write(",".join(['sample', 'barcode', 'input_file', 'fasta', 'gtf', 'is_transcripts', 'nanopolish_fast5']) + "\n") + fout.write( + ",".join(["sample", "barcode", "input_file", "fasta", "gtf", "is_transcripts", "nanopolish_fast5"]) + + "\n" + ) for sample in sorted(sample_info_dict.keys()): ## Check that replicate ids are in format 1.. uniq_rep_ids = set(sample_info_dict[sample].keys()) if len(uniq_rep_ids) != max(uniq_rep_ids): - print_error("Replicate ids must start with 1..!", 'Group', sample) + print_error("Replicate ids must start with 1..!", "Group", sample) ### Write to file for replicate in sorted(sample_info_dict[sample].keys()): - sample_id = "{}_R{}".format(sample,replicate) - fout.write(','.join([sample_id] + sample_info_dict[sample][replicate]) + '\n') + sample_id = "{}_R{}".format(sample, replicate) + fout.write(",".join([sample_id] + sample_info_dict[sample][replicate]) + "\n") def main(args=None): @@ -203,5 +223,5 @@ def main(args=None): check_samplesheet(args.FILE_IN, args.UPDATED_PATH, args.FILE_OUT) -if __name__ == '__main__': +if __name__ == "__main__": sys.exit(main()) diff --git a/bin/create_yml.py b/bin/create_yml.py index 9c9034bf..07ddbba8 100755 --- a/bin/create_yml.py +++ b/bin/create_yml.py @@ -1,38 +1,42 @@ #!/usr/bin/env python import sys -outfile_name=sys.argv[1] -samples=sys.argv[2:] -outfile=open(outfile_name,"w") + +outfile_name = sys.argv[1] +samples = sys.argv[2:] +outfile = open(outfile_name, "w") outfile.write( - 'notes: Pairwise comparison without replicates with default parameter setting.'+ '\n'+ - '\n'+ - 'data:'+'\n' + "notes: Pairwise comparison without replicates with default parameter setting." + "\n" + "\n" + "data:" + "\n" ) -dict={} +dict = {} for sample in samples: - sample=sample.strip("[").strip("]").split(",") - path_to_sample,condition=sample[0],sample[1] + sample = sample.strip("[").strip("]").split(",") + path_to_sample, condition = sample[0], sample[1] if condition not in dict: - dict[condition]=[path_to_sample] + dict[condition] = [path_to_sample] else: dict[condition].append(path_to_sample) for condition in dict: - outfile.write(' '+condition+':'+'\n') - r=0 + outfile.write(" " + condition + ":" + "\n") + r = 0 for sample in dict[condition]: - r+=1 - outfile.write(' rep'+str(r)+': '+sample+'\n') + r += 1 + outfile.write(" rep" + str(r) + ": " + sample + "\n") -outfile.write('\n'+'out: ./diffmod_outputs'+'\n'+'\n') +outfile.write("\n" + "out: ./diffmod_outputs" + "\n" + "\n") outfile.write( - 'method:'+'\n'+ - ' prefiltering:'+'\n'+ - ' method: t-test'+'\n'+ - ' threshold: 0.1'+'\n'+'\n' + "method:" + + "\n" + + " prefiltering:" + + "\n" + + " method: t-test" + + "\n" + + " threshold: 0.1" + + "\n" + + "\n" ) outfile.close() From 4e4fc81a3f835dc5e1cc253a2a672f07d08545b0 Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Thu, 9 Feb 2023 20:20:02 +0000 Subject: [PATCH 20/56] Run new version of black --- bin/check_samplesheet.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index b5670c42..a10f4479 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -59,7 +59,6 @@ def check_samplesheet(file_in, updated_path, file_out): input_extensions = [] sample_info_dict = {} with open(file_in, "r") as fin: - ## Check header MIN_COLS = 3 HEADER = ["group", "replicate", "barcode", "input_file", "fasta", "gtf"] @@ -200,13 +199,11 @@ def check_samplesheet(file_in, updated_path, file_out): out_dir = os.path.dirname(file_out) make_dir(out_dir) with open(file_out, "w") as fout: - fout.write( ",".join(["sample", "barcode", "input_file", "fasta", "gtf", "is_transcripts", "nanopolish_fast5"]) + "\n" ) for sample in sorted(sample_info_dict.keys()): - ## Check that replicate ids are in format 1.. uniq_rep_ids = set(sample_info_dict[sample].keys()) if len(uniq_rep_ids) != max(uniq_rep_ids): From 220c232c1af35df95cb21e7cb499355167571cd4 Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Fri, 10 Feb 2023 09:00:13 +0000 Subject: [PATCH 21/56] module updates to fix warnings --- modules/local/bam_rename.nf | 9 ++++++--- modules/local/bambu.nf | 2 +- modules/local/bedtools_bamtobed.nf | 8 ++++---- modules/local/bedtools_genomecov.nf | 2 +- modules/local/cutesv.nf | 2 +- modules/local/deepvariant.nf | 9 ++++++--- modules/local/demux_fast5.nf | 10 ++++------ modules/local/deseq2.nf | 2 +- modules/local/dexseq.nf | 2 +- modules/local/get_jaffal_ref.nf | 13 ++++++++++--- modules/local/get_nanolyse_fasta.nf | 10 ++++++++-- modules/local/ucsc_bed12tobigbed.nf | 10 +++++----- modules/local/xpore_diffmod.nf | 6 +++--- 13 files changed, 51 insertions(+), 34 deletions(-) diff --git a/modules/local/bam_rename.nf b/modules/local/bam_rename.nf index 67f7abde..b9441e4d 100644 --- a/modules/local/bam_rename.nf +++ b/modules/local/bam_rename.nf @@ -2,9 +2,6 @@ process BAM_RENAME { tag "$meta.id" conda (params.enable_conda ? "conda-forge::sed=4.7" : null) - //container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - // 'https://containers.biocontainers.pro/s3/SingImgsRepo/biocontainers/v1.2.0_cv1/biocontainers_v1.2.0_cv1.img' : - // 'quay.io/biocontainers/biocontainers:latest' }" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/sed:4.7.0' : 'quay.io/biocontainers/sed:4.7.0' }" @@ -14,6 +11,7 @@ process BAM_RENAME { output: tuple val(meta), path("*.bam"), emit: bam + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when @@ -21,5 +19,10 @@ process BAM_RENAME { script: """ [ ! -f ${meta.id}.bam ] && ln -s $bam ${meta.id}.bam + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + sed: \$(sed --version 2>&1 | grep "sed (GNU sed)" | sed 's/^.*) //') + END_VERSIONS """ } diff --git a/modules/local/bambu.nf b/modules/local/bambu.nf index 18aafb84..759fbf56 100644 --- a/modules/local/bambu.nf +++ b/modules/local/bambu.nf @@ -1,7 +1,7 @@ process BAMBU { label 'process_medium' - conda (params.enable_conda ? "conda-forge::r-base=4.0.3 bioconda::bioconductor-bambu=3.0.6 bioconda::bioconductor-bsgenome=1.62.0" : null) + conda "conda-forge::r-base=4.0.3 bioconda::bioconductor-bambu=3.0.6 bioconda::bioconductor-bsgenome=1.66.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bioconductor-bambu:3.0.6--r42hc247a5b_0' : 'quay.io/biocontainers/bioconductor-bambu:3.0.6--r42hc247a5b_0' }" diff --git a/modules/local/bedtools_bamtobed.nf b/modules/local/bedtools_bamtobed.nf index e4d14fbc..e836713b 100644 --- a/modules/local/bedtools_bamtobed.nf +++ b/modules/local/bedtools_bamtobed.nf @@ -1,14 +1,11 @@ process BEDTOOLS_BAMBED { label 'process_medium' - conda (params.enable_conda ? "bioconda::bedtools=2.29.2" : null) + conda "bioconda::bedtools=2.29.2" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bedtools:2.29.2--hc088bd4_0' : 'quay.io/biocontainers/bedtools:2.29.2--hc088bd4_0' }" - when: - !params.skip_alignment && !params.skip_bigbed && (params.protocol == 'directRNA' || params.protocol == 'cDNA') - input: tuple val(meta), path(sizes), val(is_transcripts), path(bam), path(bai) @@ -16,6 +13,9 @@ process BEDTOOLS_BAMBED { tuple val(meta), path(sizes), path("*.bed12") , emit: bed12 path "versions.yml" , emit: versions + when: + !params.skip_alignment && !params.skip_bigbed && (params.protocol == 'directRNA' || params.protocol == 'cDNA') + script: """ bedtools \\ diff --git a/modules/local/bedtools_genomecov.nf b/modules/local/bedtools_genomecov.nf index 74978573..147d1b02 100644 --- a/modules/local/bedtools_genomecov.nf +++ b/modules/local/bedtools_genomecov.nf @@ -2,7 +2,7 @@ process BEDTOOLS_GENOMECOV { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::bedtools=2.29.2" : null) + conda "bioconda::bedtools=2.29.2" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bedtools:2.29.2--hc088bd4_0' : 'quay.io/biocontainers/bedtools:2.29.2--hc088bd4_0' }" diff --git a/modules/local/cutesv.nf b/modules/local/cutesv.nf index d2dcaaf8..f0ec7bd7 100644 --- a/modules/local/cutesv.nf +++ b/modules/local/cutesv.nf @@ -2,7 +2,7 @@ process CUTESV { tag "$meta.id" label 'process_high' - conda (params.enable_conda ? "bioconda::cutesv=1.0.12" : null) + conda "bioconda::cutesv=1.0.12" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/cutesv:1.0.12--pyhdfd78af_0' : 'quay.io/biocontainers/cutesv:1.0.12--pyhdfd78af_0' }" diff --git a/modules/local/deepvariant.nf b/modules/local/deepvariant.nf index ca97ece6..3346b72c 100644 --- a/modules/local/deepvariant.nf +++ b/modules/local/deepvariant.nf @@ -2,9 +2,12 @@ process DEEPVARIANT { tag "$meta.id" label 'process_high' - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'docker.io/google/deepvariant:1.3.0' : - 'docker.io/google/deepvariant:1.3.0' }" + container "google/deepvariant:1.4.0" + + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + exit 1, "DEEPVARIANT module does not support Conda. Please use Docker / Singularity / Podman instead." + } input: tuple val(meta), path(sizes), val(is_transcripts), path(input), path(index) diff --git a/modules/local/demux_fast5.nf b/modules/local/demux_fast5.nf index 207f2450..9e888bd1 100644 --- a/modules/local/demux_fast5.nf +++ b/modules/local/demux_fast5.nf @@ -1,12 +1,10 @@ process DEMUX_FAST5 { label 'process_medium' - conda (params.enable_conda ? "bioconda:ont-fast5-api:4.0.0--pyhdfd78af_0" : null) - if (workflow.containerEngine == 'singularity' && !params.singularity_pull_docker_container) { - container "https://depot.galaxyproject.org/singularity/ont-fast5-api:4.0.0--pyhdfd78af_0" - } else { - container "quay.io/biocontainers/ont-fast5-api:4.0.0--pyhdfd78af_0" - } + conda "bioconda::ont-fast5-api=4.0.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/ont-fast5-api:4.0.0--pyhdfd78af_0' : + 'quay.io/biocontainers/ont-fast5-api:4.0.0--pyhdfd78af_0' }" input: path(input_path), stageAs: 'input_path/*' diff --git a/modules/local/deseq2.nf b/modules/local/deseq2.nf index 0953a225..a89c6924 100644 --- a/modules/local/deseq2.nf +++ b/modules/local/deseq2.nf @@ -1,7 +1,7 @@ process DESEQ2 { label "process_medium" - conda (params.enable_conda ? "conda-forge::r-base=4.0.3 bioconda::bioconductor-deseq2=1.28.0" : null) + conda "conda-forge::r-base=4.0.3 bioconda::bioconductor-deseq2=1.28.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-8849acf39a43cdd6c839a369a74c0adc823e2f91:ab110436faf952a33575c64dd74615a84011450b-0' : 'quay.io/biocontainers/mulled-v2-8849acf39a43cdd6c839a369a74c0adc823e2f91:ab110436faf952a33575c64dd74615a84011450b-0' }" diff --git a/modules/local/dexseq.nf b/modules/local/dexseq.nf index 646f0e45..bf25e712 100644 --- a/modules/local/dexseq.nf +++ b/modules/local/dexseq.nf @@ -1,7 +1,7 @@ process DEXSEQ { label "process_medium" - conda (params.enable_conda ? "conda-forge::r-base=4.0.2 bioconda::bioconductor-dexseq=1.36.0 bioconda::bioconductor-drimseq=1.18.0 bioconda::bioconductor-stager=1.12.0" : null) + conda "conda-forge::r-base=4.0.2 bioconda::bioconductor-dexseq=1.36.0 bioconda::bioconductor-drimseq=1.18.0 bioconda::bioconductor-stager=1.12.0" container "docker.io/yuukiiwa/nanoseq:dexseq" // need a multitool container for r-base, dexseq, stager, drimseq and on quay hub diff --git a/modules/local/get_jaffal_ref.nf b/modules/local/get_jaffal_ref.nf index bc38cdf6..70bc3497 100644 --- a/modules/local/get_jaffal_ref.nf +++ b/modules/local/get_jaffal_ref.nf @@ -2,11 +2,13 @@ process GET_JAFFAL_REF { conda (params.enable_conda ? "conda-forge::sed=4.7" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://containers.biocontainers.pro/s3/SingImgsRepo/biocontainers/v1.2.0_cv1/biocontainers_v1.2.0_cv1.img' : - 'biocontainers/biocontainers:v1.2.0_cv1' }" + 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : + 'ubuntu:20.04' }" output: - tuple val(null), path("for_jaffal.tar.gz") , emit: ch_jaffal_ref + tuple val(null), path("for_jaffal.tar.gz"), emit: ch_jaffal_ref + path "versions.yml" , emit: versions + when: task.ext.when == null || task.ext.when @@ -16,5 +18,10 @@ process GET_JAFFAL_REF { curl \\ -L https://ndownloader.figshare.com/files/28168755 \\ -o for_jaffal.tar.gz + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + curl: \$(curl --version | grep "curl" | sed "s/curl //; s/ .*\$//") + END_VERSIONS """ } diff --git a/modules/local/get_nanolyse_fasta.nf b/modules/local/get_nanolyse_fasta.nf index edeede52..ee1479aa 100644 --- a/modules/local/get_nanolyse_fasta.nf +++ b/modules/local/get_nanolyse_fasta.nf @@ -2,11 +2,12 @@ process GET_NANOLYSE_FASTA { conda (params.enable_conda ? "conda-forge::sed=4.7" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://containers.biocontainers.pro/s3/SingImgsRepo/biocontainers/v1.2.0_cv1/biocontainers_v1.2.0_cv1.img' : - 'biocontainers/biocontainers:v1.2.0_cv1' }" + 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : + 'ubuntu:20.04' }" output: path "*fasta.gz" , emit: ch_nanolyse_fasta + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when @@ -16,5 +17,10 @@ process GET_NANOLYSE_FASTA { curl \\ -L https://github.com/wdecoster/nanolyse/raw/master/reference/lambda.fasta.gz \\ -o lambda.fasta.gz + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + curl: \$(curl --version | grep "curl" | sed "s/curl //; s/ .*\$//") + END_VERSIONS """ } diff --git a/modules/local/ucsc_bed12tobigbed.nf b/modules/local/ucsc_bed12tobigbed.nf index e8f20075..88fc2fb6 100644 --- a/modules/local/ucsc_bed12tobigbed.nf +++ b/modules/local/ucsc_bed12tobigbed.nf @@ -7,15 +7,15 @@ process UCSC_BED12TOBIGBED { 'https://depot.galaxyproject.org/singularity/ucsc-bedtobigbed:377--h446ed27_1' : 'quay.io/biocontainers/ucsc-bedtobigbed:377--h446ed27_1' }" - when: - !params.skip_alignment && !params.skip_bigbed && (params.protocol == 'directRNA' || params.protocol == 'cDNA') - input: tuple val(meta), path(sizes), path(bed12) output: - tuple val(meta), path(sizes), path("*.bigBed"), emit: bigbed - path "versions.yml" , emit: versions + tuple val(meta), path(sizes), path("*.bigBed"), emit: bigbed + path "versions.yml" , emit: versions + + when: + !params.skip_alignment && !params.skip_bigbed && (params.protocol == 'directRNA' || params.protocol == 'cDNA') script: def VERSION = '377' diff --git a/modules/local/xpore_diffmod.nf b/modules/local/xpore_diffmod.nf index 3fb4d47f..56dd1402 100644 --- a/modules/local/xpore_diffmod.nf +++ b/modules/local/xpore_diffmod.nf @@ -9,13 +9,13 @@ process XPORE_DIFFMOD { input: val dataprep_dirs - when: - task.ext.when == null || task.ext.when - output: path "diffmod*", emit: diffmod_outputs path "versions.yml" , emit: versions + when: + task.ext.when == null || task.ext.when + script: diffmod_config = "--config $workflow.workDir/*/*/diffmod_config.yml" """ From 73077e3b2af114d49f7be0dc02c3594c1cbb3196 Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Fri, 10 Feb 2023 17:32:59 +0000 Subject: [PATCH 22/56] update modules --- modules/local/bam_rename.nf | 1 + modules/local/get_jaffal_ref.nf | 1 + modules/local/get_nanolyse_fasta.nf | 1 + modules/local/get_test_data.nf | 3 +++ modules/local/jaffal.nf | 9 ++++----- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/modules/local/bam_rename.nf b/modules/local/bam_rename.nf index b9441e4d..57cff789 100644 --- a/modules/local/bam_rename.nf +++ b/modules/local/bam_rename.nf @@ -1,4 +1,5 @@ process BAM_RENAME { + label 'process_medium' tag "$meta.id" conda (params.enable_conda ? "conda-forge::sed=4.7" : null) diff --git a/modules/local/get_jaffal_ref.nf b/modules/local/get_jaffal_ref.nf index 70bc3497..9fe782bc 100644 --- a/modules/local/get_jaffal_ref.nf +++ b/modules/local/get_jaffal_ref.nf @@ -1,4 +1,5 @@ process GET_JAFFAL_REF { + label "process_single" conda (params.enable_conda ? "conda-forge::sed=4.7" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? diff --git a/modules/local/get_nanolyse_fasta.nf b/modules/local/get_nanolyse_fasta.nf index ee1479aa..19ec5ee7 100644 --- a/modules/local/get_nanolyse_fasta.nf +++ b/modules/local/get_nanolyse_fasta.nf @@ -1,4 +1,5 @@ process GET_NANOLYSE_FASTA { + label "process_single" conda (params.enable_conda ? "conda-forge::sed=4.7" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? diff --git a/modules/local/get_test_data.nf b/modules/local/get_test_data.nf index 281b8d07..f96d8905 100644 --- a/modules/local/get_test_data.nf +++ b/modules/local/get_test_data.nf @@ -1,4 +1,7 @@ process GET_TEST_DATA { + label "process_single" + +2.34.1 container "docker.io/yuukiiwa/git:latest" output: diff --git a/modules/local/jaffal.nf b/modules/local/jaffal.nf index 73e7cbd2..061f4668 100644 --- a/modules/local/jaffal.nf +++ b/modules/local/jaffal.nf @@ -2,11 +2,10 @@ process JAFFAL { echo true label 'process_medium' - conda (params.enable_conda ? "bioconda::jaffa=2.0.0" : null) - container "docker.io/yuukiiwa/jaffa:2.0" - //container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - // 'https://depot.galaxyproject.org/singularity/jaffa:2.00--hdfd78af_1' : - // 'quay.io/biocontainers/jaffa:2.00--hdfd78af_1' }"//tried three biocontainers, all of them got command not found for minimap2 + conda "bioconda::jaffa=2.3.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/jaffa:2.3--hdfd78af_0' : + 'quay.io/biocontainers/jaffa:2.3--hdfd78af_0' }" input: tuple val(meta), path(fastq) From 0cf0ea6970e7e9abedb3e1849745f4187d643af7 Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Fri, 10 Feb 2023 17:51:57 +0000 Subject: [PATCH 23/56] update spacing outputs --- modules/local/bambu.nf | 8 ++++---- modules/local/bedtools_bamtobed.nf | 4 ++-- modules/local/cutesv.nf | 4 ++-- modules/local/deepvariant.nf | 8 ++++---- modules/local/demux_fast5.nf | 4 ++-- modules/local/deseq2.nf | 4 ++-- modules/local/dexseq.nf | 4 ++-- modules/local/get_chrom_sizes.nf | 4 ++-- modules/local/get_nanolyse_fasta.nf | 4 ++-- modules/local/get_test_data.nf | 10 ++++++++-- modules/local/graphmap2_align.nf | 2 +- modules/local/graphmap2_index.nf | 2 +- modules/local/gtf2bed.nf | 4 ++-- modules/local/guppy.nf | 8 ++++---- modules/local/jaffal.nf | 6 +++--- modules/local/m6anet_dataprep.nf | 2 +- modules/local/m6anet_inference.nf | 4 ++-- modules/local/medaka_variant.nf | 4 ++-- modules/local/minimap2_align.nf | 2 +- modules/local/minimap2_index.nf | 2 +- modules/local/nanopolish_index_eventalign.nf | 2 +- modules/local/pepper_margin_deepvariant.nf | 6 +++--- modules/local/qcat.nf | 4 ++-- modules/local/samtools_sort_index.nf | 4 ++-- modules/local/samtools_view_bam.nf | 4 ++-- modules/local/sniffles.nf | 4 ++-- modules/local/stringtie2.nf | 4 ++-- modules/local/subread_featurecounts.nf | 10 +++++----- modules/local/xpore_dataprep.nf | 2 +- modules/local/xpore_diffmod.nf | 4 ++-- 30 files changed, 70 insertions(+), 64 deletions(-) diff --git a/modules/local/bambu.nf b/modules/local/bambu.nf index 759fbf56..23bb67c2 100644 --- a/modules/local/bambu.nf +++ b/modules/local/bambu.nf @@ -11,10 +11,10 @@ process BAMBU { path bams output: - path "counts_gene.txt" , emit: ch_gene_counts - path "counts_transcript.txt" , emit: ch_transcript_counts - path "extended_annotations.gtf" , emit: extended_gtf - path "versions.yml" , emit: versions + path "counts_gene.txt" , emit: ch_gene_counts + path "counts_transcript.txt" , emit: ch_transcript_counts + path "extended_annotations.gtf", emit: extended_gtf + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/bedtools_bamtobed.nf b/modules/local/bedtools_bamtobed.nf index e836713b..4eb3b8e6 100644 --- a/modules/local/bedtools_bamtobed.nf +++ b/modules/local/bedtools_bamtobed.nf @@ -10,8 +10,8 @@ process BEDTOOLS_BAMBED { tuple val(meta), path(sizes), val(is_transcripts), path(bam), path(bai) output: - tuple val(meta), path(sizes), path("*.bed12") , emit: bed12 - path "versions.yml" , emit: versions + tuple val(meta), path(sizes), path("*.bed12"), emit: bed12 + path "versions.yml" , emit: versions when: !params.skip_alignment && !params.skip_bigbed && (params.protocol == 'directRNA' || params.protocol == 'cDNA') diff --git a/modules/local/cutesv.nf b/modules/local/cutesv.nf index f0ec7bd7..33cbbf8c 100644 --- a/modules/local/cutesv.nf +++ b/modules/local/cutesv.nf @@ -12,8 +12,8 @@ process CUTESV { path(fasta) output: - tuple val(meta), path("*_cuteSV.vcf") , emit: sv_calls // vcf files - path "versions.yml" , emit: versions + tuple val(meta), path("*_cuteSV.vcf"), emit: sv_calls // vcf files + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/deepvariant.nf b/modules/local/deepvariant.nf index 3346b72c..3c66c740 100644 --- a/modules/local/deepvariant.nf +++ b/modules/local/deepvariant.nf @@ -1,6 +1,6 @@ process DEEPVARIANT { tag "$meta.id" - label 'process_high' + label 'process_medium' container "google/deepvariant:1.4.0" @@ -15,9 +15,9 @@ process DEEPVARIANT { path(fai) output: - tuple val(meta), path("${prefix}.vcf.gz") , emit: vcf - tuple val(meta), path("${prefix}.g.vcf.gz") , emit: gvcf - path "versions.yml" , emit: versions + tuple val(meta), path("${prefix}.vcf.gz") , emit: vcf + tuple val(meta), path("${prefix}.g.vcf.gz"), emit: gvcf + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/demux_fast5.nf b/modules/local/demux_fast5.nf index 9e888bd1..8f7089ef 100644 --- a/modules/local/demux_fast5.nf +++ b/modules/local/demux_fast5.nf @@ -11,8 +11,8 @@ process DEMUX_FAST5 { tuple val(meta), path(input_summary) output: - path "demultiplexed_fast5/*" , emit: fast5 - path "versions.yml" , emit: versions + path "demultiplexed_fast5/*", emit: fast5 + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/deseq2.nf b/modules/local/deseq2.nf index a89c6924..3bc9f4b4 100644 --- a/modules/local/deseq2.nf +++ b/modules/local/deseq2.nf @@ -10,8 +10,8 @@ process DESEQ2 { path counts output: - path "*.txt" , emit: deseq2_txt - path "versions.yml" , emit: versions + path "*.txt" , emit: deseq2_txt + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/dexseq.nf b/modules/local/dexseq.nf index bf25e712..b5c2da7a 100644 --- a/modules/local/dexseq.nf +++ b/modules/local/dexseq.nf @@ -9,8 +9,8 @@ process DEXSEQ { path counts output: - path "*.txt" , emit: dexseq_txt - path "versions.yml" , emit: versions + path "*.txt" , emit: dexseq_txt + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/get_chrom_sizes.nf b/modules/local/get_chrom_sizes.nf index 5efa0804..54742b03 100644 --- a/modules/local/get_chrom_sizes.nf +++ b/modules/local/get_chrom_sizes.nf @@ -11,8 +11,8 @@ process GET_CHROM_SIZES { tuple path(fasta), val(name) output: - tuple path('*.sizes'), val(name) , emit: sizes - path "versions.yml" , emit: versions + tuple path('*.sizes'), val(name), emit: sizes + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/get_nanolyse_fasta.nf b/modules/local/get_nanolyse_fasta.nf index 19ec5ee7..35385b6c 100644 --- a/modules/local/get_nanolyse_fasta.nf +++ b/modules/local/get_nanolyse_fasta.nf @@ -7,8 +7,8 @@ process GET_NANOLYSE_FASTA { 'ubuntu:20.04' }" output: - path "*fasta.gz" , emit: ch_nanolyse_fasta - path "versions.yml" , emit: versions + path "*fasta.gz" , emit: ch_nanolyse_fasta + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/get_test_data.nf b/modules/local/get_test_data.nf index f96d8905..e9f284d8 100644 --- a/modules/local/get_test_data.nf +++ b/modules/local/get_test_data.nf @@ -5,8 +5,10 @@ process GET_TEST_DATA { container "docker.io/yuukiiwa/git:latest" output: - path "test-datasets/fast5/$barcoded/*" , emit: ch_input_fast5s_path - path "test-datasets/modification_fast5_fastq/" , emit: ch_input_dir_path + path "test-datasets/fast5/$barcoded/*" , emit: ch_input_fast5s_path + path "test-datasets/modification_fast5_fastq/", emit: ch_input_dir_path + path "versions.yml" , emit: versions + when: task.ext.when == null || task.ext.when @@ -15,5 +17,9 @@ process GET_TEST_DATA { barcoded = (workflow.profile.contains('test_bc_nodx') || workflow.profile.contains('rnamod')) ? "nonbarcoded" : "barcoded" """ git clone https://github.com/nf-core/test-datasets.git --branch nanoseq --single-branch + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + deepvariant: git --version | sed 's/git version //; s/ .*\$//') """ } diff --git a/modules/local/graphmap2_align.nf b/modules/local/graphmap2_align.nf index f59cda47..7997d5ab 100644 --- a/modules/local/graphmap2_align.nf +++ b/modules/local/graphmap2_align.nf @@ -12,7 +12,7 @@ process GRAPHMAP2_ALIGN { output: tuple val(meta), path(sizes), val(is_transcripts), path("*.sam"), emit: align_sam - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/graphmap2_index.nf b/modules/local/graphmap2_index.nf index 9153d32d..0bf7ba22 100644 --- a/modules/local/graphmap2_index.nf +++ b/modules/local/graphmap2_index.nf @@ -12,7 +12,7 @@ process GRAPHMAP2_INDEX { output: tuple path(fasta), path(sizes), path(gtf), val(bed), val(is_transcripts), path("*.gmidx"), val(annotation_str), emit: index - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/gtf2bed.nf b/modules/local/gtf2bed.nf index d7e9809f..3109da00 100644 --- a/modules/local/gtf2bed.nf +++ b/modules/local/gtf2bed.nf @@ -10,8 +10,8 @@ process GTF2BED { tuple path(gtf), val(name) output: - tuple path('*.bed'), val(name) , emit: gtf_bed - path "versions.yml", emit: versions + tuple path('*.bed'), val(name), emit: gtf_bed + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/guppy.nf b/modules/local/guppy.nf index 72c5dbbb..5cd340b5 100644 --- a/modules/local/guppy.nf +++ b/modules/local/guppy.nf @@ -15,10 +15,10 @@ process GUPPY { path guppy_model output: - path "fastq/*.fastq.gz" , emit: fastq - tuple val(meta), path("basecalling/*.txt") , emit: summary - path "basecalling/*" , emit: called - path "versions.yml" , emit: versions + path "fastq/*.fastq.gz" , emit: fastq + tuple val(meta), path("basecalling/*.txt"), emit: summary + path "basecalling/*" , emit: called + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/jaffal.nf b/modules/local/jaffal.nf index 061f4668..a0668bcb 100644 --- a/modules/local/jaffal.nf +++ b/modules/local/jaffal.nf @@ -12,9 +12,9 @@ process JAFFAL { path jaffal_ref_dir output: - tuple val(meta), path("*.fasta") ,emit: jaffal_fastq - path "*.csv" ,emit: jaffal_results - path "versions.yml" , emit: versions + tuple val(meta), path("*.fasta"), emit: jaffal_fastq + path "*.csv" , emit: jaffal_results + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/m6anet_dataprep.nf b/modules/local/m6anet_dataprep.nf index 78b5f8ba..2f2dda5c 100644 --- a/modules/local/m6anet_dataprep.nf +++ b/modules/local/m6anet_dataprep.nf @@ -10,7 +10,7 @@ process M6ANET_DATAPREP { output: tuple val(meta), path("$meta.id"), emit: dataprep_outputs - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/m6anet_inference.nf b/modules/local/m6anet_inference.nf index 7ca93953..b8f13060 100644 --- a/modules/local/m6anet_inference.nf +++ b/modules/local/m6anet_inference.nf @@ -10,8 +10,8 @@ process M6ANET_INFERENCE { tuple val(meta), path(input_dir) output: - path "*", emit: m6anet_outputs - path "versions.yml" , emit: versions + path "*" , emit: m6anet_outputs + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/medaka_variant.nf b/modules/local/medaka_variant.nf index b5e12f7f..95a32079 100644 --- a/modules/local/medaka_variant.nf +++ b/modules/local/medaka_variant.nf @@ -12,8 +12,8 @@ process MEDAKA_VARIANT { path(fasta) output: - tuple val(meta), path ("$output_vcf") , emit: vcf // vcf files - path "versions.yml" , emit: versions + tuple val(meta), path ("$output_vcf"), emit: vcf // vcf files + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/minimap2_align.nf b/modules/local/minimap2_align.nf index acecfe77..941f94de 100644 --- a/modules/local/minimap2_align.nf +++ b/modules/local/minimap2_align.nf @@ -12,7 +12,7 @@ process MINIMAP2_ALIGN { output: tuple val(meta), path(sizes), val(is_transcripts), path("*.sam"), emit: align_sam - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/minimap2_index.nf b/modules/local/minimap2_index.nf index a793a2bf..66a6cc8e 100644 --- a/modules/local/minimap2_index.nf +++ b/modules/local/minimap2_index.nf @@ -12,7 +12,7 @@ process MINIMAP2_INDEX { output: tuple path(fasta), path(sizes), val(gtf), val(bed), val(is_transcripts), path("*.mmi"), val(annotation_str), emit: index - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/nanopolish_index_eventalign.nf b/modules/local/nanopolish_index_eventalign.nf index 7e754ac3..e4340e79 100644 --- a/modules/local/nanopolish_index_eventalign.nf +++ b/modules/local/nanopolish_index_eventalign.nf @@ -12,7 +12,7 @@ process NANOPOLISH_INDEX_EVENTALIGN { output: tuple val(meta), path(genome), path(gtf), path("*eventalign.txt"), path("*summary.txt"), emit: nanopolish_outputs - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/pepper_margin_deepvariant.nf b/modules/local/pepper_margin_deepvariant.nf index 29188c66..11190c1f 100644 --- a/modules/local/pepper_margin_deepvariant.nf +++ b/modules/local/pepper_margin_deepvariant.nf @@ -14,9 +14,9 @@ process PEPPER_MARGIN_DEEPVARIANT { path(fai) output: - tuple val(meta), path("*vcf.gz") , emit: vcf - tuple val(meta), path("*vcf.gz.tbi") , emit: tbi - path "versions.yml" , emit: versions + tuple val(meta), path("*vcf.gz") , emit: vcf + tuple val(meta), path("*vcf.gz.tbi"), emit: tbi + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/qcat.nf b/modules/local/qcat.nf index 969c32e7..25eace5c 100644 --- a/modules/local/qcat.nf +++ b/modules/local/qcat.nf @@ -11,8 +11,8 @@ process QCAT { path input_path output: - path "fastq/*.fastq.gz" , emit: fastq - path "versions.yml" , emit: versions + path "fastq/*.fastq.gz", emit: fastq + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/samtools_sort_index.nf b/modules/local/samtools_sort_index.nf index 2fb664c2..795c3898 100644 --- a/modules/local/samtools_sort_index.nf +++ b/modules/local/samtools_sort_index.nf @@ -11,8 +11,8 @@ process SAMTOOLS_SORT_INDEX { tuple val(meta), path(bam) output: - tuple val(meta), path("*sorted.bam"), path("*.bai") , optional:true, emit: bam_bai - tuple val(meta), path("*sorted.bam"), path("*.csi") , optional:true, emit: bam_csi + tuple val(meta), path("*sorted.bam"), path("*.bai"), optional:true, emit: bam_bai + tuple val(meta), path("*sorted.bam"), path("*.csi"), optional:true, emit: bam_csi path "versions.yml" , emit: versions when: diff --git a/modules/local/samtools_view_bam.nf b/modules/local/samtools_view_bam.nf index c13914dd..1b4ff141 100644 --- a/modules/local/samtools_view_bam.nf +++ b/modules/local/samtools_view_bam.nf @@ -11,8 +11,8 @@ process SAMTOOLS_VIEW_BAM { tuple val(meta), path(sizes), val(is_transcripts), path(sam) output: - tuple val(meta), path("*.bam") ,emit: bam - path "versions.yml" , emit: versions + tuple val(meta), path("*.bam"), emit: bam + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/sniffles.nf b/modules/local/sniffles.nf index 25086679..c095464a 100644 --- a/modules/local/sniffles.nf +++ b/modules/local/sniffles.nf @@ -12,8 +12,8 @@ process SNIFFLES { output: - tuple val(meta), path("*_sniffles.vcf") , emit: sv_calls // vcf files - path "versions.yml" , emit: versions + tuple val(meta), path("*_sniffles.vcf"), emit: sv_calls + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/stringtie2.nf b/modules/local/stringtie2.nf index 81ca2442..d0b68c3e 100644 --- a/modules/local/stringtie2.nf +++ b/modules/local/stringtie2.nf @@ -12,8 +12,8 @@ process STRINGTIE2 { tuple val(meta), path(fasta), path(gtf), path(bam) output: - path "*.stringtie.gtf" , emit: stringtie_gtf - path "versions.yml" , emit: versions + path "*.stringtie.gtf", emit: stringtie_gtf + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/subread_featurecounts.nf b/modules/local/subread_featurecounts.nf index 4020251a..018a198c 100644 --- a/modules/local/subread_featurecounts.nf +++ b/modules/local/subread_featurecounts.nf @@ -12,11 +12,11 @@ process SUBREAD_FEATURECOUNTS { path bams output: - path "counts_gene.txt" , emit: gene_counts - path "counts_transcript.txt" , emit: transcript_counts - path "counts_gene.txt.summary" , emit: featurecounts_gene_multiqc - path "counts_transcript.txt.summary" , emit: featurecounts_transcript_multiqc - path "versions.yml" , emit: versions + path "counts_gene.txt" , emit: gene_counts + path "counts_transcript.txt" , emit: transcript_counts + path "counts_gene.txt.summary" , emit: featurecounts_gene_multiqc + path "counts_transcript.txt.summary", emit: featurecounts_transcript_multiqc + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/xpore_dataprep.nf b/modules/local/xpore_dataprep.nf index 1054431c..3d0ca20b 100644 --- a/modules/local/xpore_dataprep.nf +++ b/modules/local/xpore_dataprep.nf @@ -12,7 +12,7 @@ process XPORE_DATAPREP { output: tuple val(meta), path("$meta.id"), emit: dataprep_outputs - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/xpore_diffmod.nf b/modules/local/xpore_diffmod.nf index 56dd1402..a84a5783 100644 --- a/modules/local/xpore_diffmod.nf +++ b/modules/local/xpore_diffmod.nf @@ -10,8 +10,8 @@ process XPORE_DIFFMOD { val dataprep_dirs output: - path "diffmod*", emit: diffmod_outputs - path "versions.yml" , emit: versions + path "diffmod*" , emit: diffmod_outputs + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when From 9e9d3c9c70023d85090090c7d64ae2c393f46d57 Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Tue, 14 Feb 2023 10:15:31 +0000 Subject: [PATCH 24/56] fix: improper version --- modules/local/bam_rename.nf | 2 +- modules/local/get_chrom_sizes.nf | 2 +- modules/local/get_jaffal_ref.nf | 2 +- modules/local/get_nanolyse_fasta.nf | 2 +- modules/local/get_test_data.nf | 4 +--- modules/local/graphmap2_align.nf | 2 +- modules/local/graphmap2_index.nf | 2 +- modules/local/gtf2bed.nf | 2 +- modules/local/medaka_variant.nf | 2 +- modules/local/minimap2_align.nf | 2 +- modules/local/minimap2_index.nf | 2 +- modules/local/multiqc.nf | 2 +- modules/local/nanoplot.nf | 2 +- modules/local/nanopolish_index_eventalign.nf | 2 +- modules/local/qcat.nf | 2 +- modules/local/samtools_sort_index.nf | 2 +- modules/local/samtools_view_bam.nf | 2 +- modules/local/sniffles.nf | 2 +- modules/local/stringtie2.nf | 2 +- modules/local/subread_featurecounts.nf | 2 +- modules/local/ucsc_bed12tobigbed.nf | 2 +- modules/local/ucsc_bedgraphtobigwig.nf | 2 +- modules/local/xpore_dataprep.nf | 2 +- modules/local/xpore_diffmod.nf | 2 +- 24 files changed, 24 insertions(+), 26 deletions(-) diff --git a/modules/local/bam_rename.nf b/modules/local/bam_rename.nf index 57cff789..99258144 100644 --- a/modules/local/bam_rename.nf +++ b/modules/local/bam_rename.nf @@ -2,7 +2,7 @@ process BAM_RENAME { label 'process_medium' tag "$meta.id" - conda (params.enable_conda ? "conda-forge::sed=4.7" : null) + conda "conda-forge::sed=4.7" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/sed:4.7.0' : 'quay.io/biocontainers/sed:4.7.0' }" diff --git a/modules/local/get_chrom_sizes.nf b/modules/local/get_chrom_sizes.nf index 54742b03..53c8fd94 100644 --- a/modules/local/get_chrom_sizes.nf +++ b/modules/local/get_chrom_sizes.nf @@ -2,7 +2,7 @@ process GET_CHROM_SIZES { tag "$fasta" label 'process_medium' - conda (params.enable_conda ? "bioconda::samtools=1.10" : null) + conda "bioconda::samtools=1.10" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/samtools:1.13--h8c37831_0' : 'quay.io/biocontainers/samtools:1.13--h8c37831_0' }" diff --git a/modules/local/get_jaffal_ref.nf b/modules/local/get_jaffal_ref.nf index 9fe782bc..c0b8985b 100644 --- a/modules/local/get_jaffal_ref.nf +++ b/modules/local/get_jaffal_ref.nf @@ -1,7 +1,7 @@ process GET_JAFFAL_REF { label "process_single" - conda (params.enable_conda ? "conda-forge::sed=4.7" : null) + conda "conda-forge::sed=4.7" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : 'ubuntu:20.04' }" diff --git a/modules/local/get_nanolyse_fasta.nf b/modules/local/get_nanolyse_fasta.nf index 35385b6c..622c5cd1 100644 --- a/modules/local/get_nanolyse_fasta.nf +++ b/modules/local/get_nanolyse_fasta.nf @@ -1,7 +1,7 @@ process GET_NANOLYSE_FASTA { label "process_single" - conda (params.enable_conda ? "conda-forge::sed=4.7" : null) + conda "conda-forge::sed=4.7" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : 'ubuntu:20.04' }" diff --git a/modules/local/get_test_data.nf b/modules/local/get_test_data.nf index e9f284d8..b922af75 100644 --- a/modules/local/get_test_data.nf +++ b/modules/local/get_test_data.nf @@ -1,7 +1,6 @@ process GET_TEST_DATA { label "process_single" -2.34.1 container "docker.io/yuukiiwa/git:latest" output: @@ -9,7 +8,6 @@ process GET_TEST_DATA { path "test-datasets/modification_fast5_fastq/", emit: ch_input_dir_path path "versions.yml" , emit: versions - when: task.ext.when == null || task.ext.when @@ -20,6 +18,6 @@ process GET_TEST_DATA { cat <<-END_VERSIONS > versions.yml "${task.process}": - deepvariant: git --version | sed 's/git version //; s/ .*\$//') + git: \$(echo \$(git --version | sed 's/git version //; s/ .*\$//') """ } diff --git a/modules/local/graphmap2_align.nf b/modules/local/graphmap2_align.nf index 7997d5ab..41641320 100644 --- a/modules/local/graphmap2_align.nf +++ b/modules/local/graphmap2_align.nf @@ -2,7 +2,7 @@ process GRAPHMAP2_ALIGN { tag "$meta.id" label 'process_high' - conda (params.enable_conda ? "bioconda::graphmap=0.6.3" : null) + conda "bioconda::graphmap=0.6.3" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/graphmap:0.6.3--he513fc3_0' : 'quay.io/biocontainers/graphmap:0.6.3--he513fc3_0' }" diff --git a/modules/local/graphmap2_index.nf b/modules/local/graphmap2_index.nf index 0bf7ba22..b0971e1b 100644 --- a/modules/local/graphmap2_index.nf +++ b/modules/local/graphmap2_index.nf @@ -2,7 +2,7 @@ process GRAPHMAP2_INDEX { tag "$fasta" label 'process_high' - conda (params.enable_conda ? "bioconda::graphmap=0.6.3" : null) + conda "bioconda::graphmap=0.6.3" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/graphmap:0.6.3--he513fc3_0' : 'quay.io/biocontainers/graphmap:0.6.3--he513fc3_0' }" diff --git a/modules/local/gtf2bed.nf b/modules/local/gtf2bed.nf index 3109da00..6ae37e61 100644 --- a/modules/local/gtf2bed.nf +++ b/modules/local/gtf2bed.nf @@ -1,7 +1,7 @@ process GTF2BED { label 'process_low' - conda (params.enable_conda ? "conda-forge::perl=5.26.2" : null) + conda "conda-forge::perl=5.26.2" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/perl:5.26.2' : 'quay.io/biocontainers/perl:5.26.2' }" diff --git a/modules/local/medaka_variant.nf b/modules/local/medaka_variant.nf index 95a32079..0b2f9f59 100644 --- a/modules/local/medaka_variant.nf +++ b/modules/local/medaka_variant.nf @@ -2,7 +2,7 @@ process MEDAKA_VARIANT { tag "$meta.id" label 'process_high' - conda (params.enable_conda ? "bioconda::medaka=1.4.4" : null) + conda "bioconda::medaka=1.4.4" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/medaka:1.4.4--py38h130def0_0' : 'quay.io/biocontainers/medaka:1.4.4--py38h130def0_0' }" diff --git a/modules/local/minimap2_align.nf b/modules/local/minimap2_align.nf index 941f94de..96790e5d 100644 --- a/modules/local/minimap2_align.nf +++ b/modules/local/minimap2_align.nf @@ -2,7 +2,7 @@ process MINIMAP2_ALIGN { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::minimap2=2.17" : null) + conda "bioconda::minimap2=2.17" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/minimap2:2.17--hed695b0_3' : 'quay.io/biocontainers/minimap2:2.17--hed695b0_3' }" diff --git a/modules/local/minimap2_index.nf b/modules/local/minimap2_index.nf index 66a6cc8e..31b1877c 100644 --- a/modules/local/minimap2_index.nf +++ b/modules/local/minimap2_index.nf @@ -2,7 +2,7 @@ process MINIMAP2_INDEX { tag "$fasta" label 'process_high' - conda (params.enable_conda ? "bioconda::minimap2=2.17" : null) + conda "bioconda::minimap2=2.17" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/minimap2:2.17--hed695b0_3' : 'quay.io/biocontainers/minimap2:2.17--hed695b0_3' }" diff --git a/modules/local/multiqc.nf b/modules/local/multiqc.nf index 00026887..d35efb13 100644 --- a/modules/local/multiqc.nf +++ b/modules/local/multiqc.nf @@ -1,7 +1,7 @@ process MULTIQC { label 'process_medium' - conda (params.enable_conda ? 'bioconda::multiqc=1.11' : null) + conda "bioconda::multiqc=1.11" 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' }" diff --git a/modules/local/nanoplot.nf b/modules/local/nanoplot.nf index 941c4b65..571a3232 100644 --- a/modules/local/nanoplot.nf +++ b/modules/local/nanoplot.nf @@ -2,7 +2,7 @@ process NANOPLOT { tag "$meta.id" label 'process_low' - conda (params.enable_conda ? 'bioconda::nanoplot=1.38.0' : null) + conda "bioconda::nanoplot=1.38.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/nanoplot:1.38.0--pyhdfd78af_0' : 'quay.io/biocontainers/nanoplot:1.38.0--pyhdfd78af_0' }" diff --git a/modules/local/nanopolish_index_eventalign.nf b/modules/local/nanopolish_index_eventalign.nf index e4340e79..d5290c03 100644 --- a/modules/local/nanopolish_index_eventalign.nf +++ b/modules/local/nanopolish_index_eventalign.nf @@ -2,7 +2,7 @@ process NANOPOLISH_INDEX_EVENTALIGN { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::nanopolish==0.13.2" : null) + conda "bioconda::nanopolish==0.13.2" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/nanopolish:0.13.2--he3b7ca5_2' : 'quay.io/biocontainers/nanopolish:0.13.2--he3b7ca5_2' }" diff --git a/modules/local/qcat.nf b/modules/local/qcat.nf index 25eace5c..d26e7136 100644 --- a/modules/local/qcat.nf +++ b/modules/local/qcat.nf @@ -2,7 +2,7 @@ process QCAT { tag "$input_path" label 'process_medium' - conda (params.enable_conda ? "bioconda::qcat=1.1.0" : null) + conda "bioconda::qcat=1.1.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/qcat:1.1.0--py_0' : 'quay.io/biocontainers/qcat:1.1.0--py_0' }" diff --git a/modules/local/samtools_sort_index.nf b/modules/local/samtools_sort_index.nf index 795c3898..a542ded8 100644 --- a/modules/local/samtools_sort_index.nf +++ b/modules/local/samtools_sort_index.nf @@ -2,7 +2,7 @@ process SAMTOOLS_SORT_INDEX { tag "$meta.id" label 'process_low' - conda (params.enable_conda ? "bioconda::samtools=1.14" : null) + conda "bioconda::samtools=1.14" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" diff --git a/modules/local/samtools_view_bam.nf b/modules/local/samtools_view_bam.nf index 1b4ff141..4a5eb46e 100644 --- a/modules/local/samtools_view_bam.nf +++ b/modules/local/samtools_view_bam.nf @@ -2,7 +2,7 @@ process SAMTOOLS_VIEW_BAM { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::samtools=1.10" : null) + conda "bioconda::samtools=1.10" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" diff --git a/modules/local/sniffles.nf b/modules/local/sniffles.nf index c095464a..1336392a 100644 --- a/modules/local/sniffles.nf +++ b/modules/local/sniffles.nf @@ -2,7 +2,7 @@ process SNIFFLES { tag "$meta.id" label 'process_high' - conda (params.enable_conda ? "bioconda::sniffles=1.0.12" : null) + conda "bioconda::sniffles=1.0.12" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/sniffles:1.0.12--h8b12597_1' : 'quay.io/biocontainers/sniffles:1.0.12--h8b12597_1' }" diff --git a/modules/local/stringtie2.nf b/modules/local/stringtie2.nf index d0b68c3e..a64a7e82 100644 --- a/modules/local/stringtie2.nf +++ b/modules/local/stringtie2.nf @@ -3,7 +3,7 @@ process STRINGTIE2 { label 'process_medium' // Note: 2.7X indices incompatible with AWS iGenomes. - conda (params.enable_conda ? "bioconda::stringtie=2.1.4" : null) + conda "bioconda::stringtie=2.1.4" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/stringtie:2.1.4--h7e0af3c_0' : 'quay.io/biocontainers/stringtie:2.1.4--h7e0af3c_0' }" diff --git a/modules/local/subread_featurecounts.nf b/modules/local/subread_featurecounts.nf index 018a198c..5da69be6 100644 --- a/modules/local/subread_featurecounts.nf +++ b/modules/local/subread_featurecounts.nf @@ -2,7 +2,7 @@ process SUBREAD_FEATURECOUNTS { label 'process_medium' // Note: 2.7X indices incompatible with AWS iGenomes. - conda (params.enable_conda ? "bioconda::subread=2.0.1" : null) + conda "bioconda::subread=2.0.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/subread:2.0.1--hed695b0_0' : 'quay.io/biocontainers/subread:2.0.1--hed695b0_0' }" diff --git a/modules/local/ucsc_bed12tobigbed.nf b/modules/local/ucsc_bed12tobigbed.nf index 88fc2fb6..296ceb19 100644 --- a/modules/local/ucsc_bed12tobigbed.nf +++ b/modules/local/ucsc_bed12tobigbed.nf @@ -2,7 +2,7 @@ process UCSC_BED12TOBIGBED { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::ucsc-bedtobigbed=377" : null) + conda "bioconda::ucsc-bedtobigbed=377" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/ucsc-bedtobigbed:377--h446ed27_1' : 'quay.io/biocontainers/ucsc-bedtobigbed:377--h446ed27_1' }" diff --git a/modules/local/ucsc_bedgraphtobigwig.nf b/modules/local/ucsc_bedgraphtobigwig.nf index c0df44bc..d3b8d1c7 100644 --- a/modules/local/ucsc_bedgraphtobigwig.nf +++ b/modules/local/ucsc_bedgraphtobigwig.nf @@ -2,7 +2,7 @@ process UCSC_BEDGRAPHTOBIGWIG { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::ucsc-bedgraphtobigwig=377" : null) + conda "bioconda::ucsc-bedgraphtobigwig=377" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/ucsc-bedgraphtobigwig:377--h446ed27_1' : 'quay.io/biocontainers/ucsc-bedgraphtobigwig:377--h446ed27_1' }" diff --git a/modules/local/xpore_dataprep.nf b/modules/local/xpore_dataprep.nf index 3d0ca20b..9c9f4747 100644 --- a/modules/local/xpore_dataprep.nf +++ b/modules/local/xpore_dataprep.nf @@ -2,7 +2,7 @@ process XPORE_DATAPREP { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::xpore=2.1.0" : null) + conda "bioconda::xpore=2.1.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/xpore:2.1--pyh5e36f6f_0' : 'quay.io/biocontainers/xpore:2.1--pyh5e36f6f_0' }" diff --git a/modules/local/xpore_diffmod.nf b/modules/local/xpore_diffmod.nf index a84a5783..2bd6edc2 100644 --- a/modules/local/xpore_diffmod.nf +++ b/modules/local/xpore_diffmod.nf @@ -1,7 +1,7 @@ process XPORE_DIFFMOD { label 'process_medium' - conda (params.enable_conda ? "bioconda::xpore=2.1.0" : null) + conda "bioconda::xpore=2.1.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/xpore:2.1--pyh5e36f6f_0' : 'quay.io/biocontainers/xpore:2.1--pyh5e36f6f_0' }" From 75f2c53e4b8377b8f473a253d8abd4e0517f926b Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Tue, 14 Feb 2023 11:46:10 +0000 Subject: [PATCH 25/56] fix: nanolyse emit --- modules/local/get_nanolyse_fasta.nf | 6 +++--- modules/local/nanoplot.nf | 1 + workflows/nanoseq.nf | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/local/get_nanolyse_fasta.nf b/modules/local/get_nanolyse_fasta.nf index 622c5cd1..736ac64d 100644 --- a/modules/local/get_nanolyse_fasta.nf +++ b/modules/local/get_nanolyse_fasta.nf @@ -3,8 +3,8 @@ process GET_NANOLYSE_FASTA { conda "conda-forge::sed=4.7" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : - 'ubuntu:20.04' }" + 'https://containers.biocontainers.pro/s3/SingImgsRepo/biocontainers/v1.2.0_cv1/biocontainers_v1.2.0_cv1.img' : + 'biocontainers/biocontainers:v1.2.0_cv1' }" output: path "*fasta.gz" , emit: ch_nanolyse_fasta @@ -21,7 +21,7 @@ process GET_NANOLYSE_FASTA { cat <<-END_VERSIONS > versions.yml "${task.process}": - curl: \$(curl --version | grep "curl" | sed "s/curl //; s/ .*\$//") + curl: \$(echo \$(curl --version 2>&1) | grep "curl" | sed "s/curl //; s/ .*\$//") END_VERSIONS """ } diff --git a/modules/local/nanoplot.nf b/modules/local/nanoplot.nf index 571a3232..78690a20 100644 --- a/modules/local/nanoplot.nf +++ b/modules/local/nanoplot.nf @@ -33,6 +33,7 @@ process NANOPLOT { -t $task.cpus \\ $input_file \\ -o $output_dir + cat <<-END_VERSIONS > versions.yml "${task.process}": nanoplot: \$(echo \$(NanoPlot --version 2>&1) | sed 's/^.*NanoPlot //; s/ .*\$//') diff --git a/workflows/nanoseq.nf b/workflows/nanoseq.nf index a15d99ef..ef05cce4 100644 --- a/workflows/nanoseq.nf +++ b/workflows/nanoseq.nf @@ -279,7 +279,9 @@ workflow NANOSEQ{ if (!params.nanolyse_fasta) { if (!isOffline()) { - GET_NANOLYSE_FASTA ().set { ch_nanolyse_fasta } + GET_NANOLYSE_FASTA() + GET_NANOLYSE_FASTA.out.ch_nanolyse_fasta + .set{ ch_nanolyse_fasta } } else { exit 1, "NXF_OFFLINE=true or -offline has been set so cannot download lambda.fasta.gz file for running NanoLyse! Please explicitly specify --nanolyse_fasta." } From dda0577682c8356ab9a6f1f9d9028eabf1fe333c Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Wed, 15 Feb 2023 14:07:13 +0800 Subject: [PATCH 26/56] remove guppy --- conf/base.config | 6 - conf/modules.config | 28 +--- conf/test.config | 38 ----- conf/test_bc_nodx.config | 32 ----- modules/local/demux_fast5.nf | 33 ----- modules/local/guppy.nf | 69 ---------- modules/local/multiqc.nf | 1 - nextflow.config | 14 -- nextflow_schema.json | 63 +-------- .../local/qcbasecall_pycoqc_nanoplot.nf | 56 -------- workflows/nanoseq.nf | 130 ++++-------------- 11 files changed, 32 insertions(+), 438 deletions(-) delete mode 100644 conf/test.config delete mode 100644 conf/test_bc_nodx.config delete mode 100644 modules/local/demux_fast5.nf delete mode 100644 modules/local/guppy.nf delete mode 100644 subworkflows/local/qcbasecall_pycoqc_nanoplot.nf diff --git a/conf/base.config b/conf/base.config index f8978e7d..3fdddd24 100644 --- a/conf/base.config +++ b/conf/base.config @@ -8,12 +8,6 @@ ---------------------------------------------------------------------------------------- */ -// Use this flag if using GPUs with Singularity -if (params.guppy_gpu || params.deepvariant_gpu) { - docker.runOptions = '--gpus all' - singularity.runOptions = '--nv' -} - process { cpus = { check_max( 1 * task.attempt, 'cpus' ) } diff --git a/conf/modules.config b/conf/modules.config index 60433ee8..e47a6a36 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -47,33 +47,7 @@ process { } } -if (!params.skip_basecalling) { - process { - withName: GUPPY { - publishDir = [ - path: { "${params.outdir}/guppy" }, - mode: 'copy', - enabled: true, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } - ] - } - } -} - -if (!params.skip_basecalling && params.output_demultiplex_fast5) { - process { - withName: DEMUX_FAST5 { - publishDir = [ - path: { "${params.outdir}/demux_fast5" }, - mode: 'copy', - enabled: true, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } - ] - } - } -} - -if (params.skip_basecalling && !params.skip_demultiplexing) { +if (!params.skip_demultiplexing) { process { withName: QCAT { publishDir = [ diff --git a/conf/test.config b/conf/test.config deleted file mode 100644 index bf5c101b..00000000 --- a/conf/test.config +++ /dev/null @@ -1,38 +0,0 @@ -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for running minimal tests -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defines input files and everything required to run a fast and simple pipeline test. - - Use as follows: - nextflow run nf-core/nanoseq -profile test, --outdir - ----------------------------------------------------------------------------------------- -*/ - -params { - config_profile_name = 'Test profile' - config_profile_description = 'Minimal test dataset to check pipeline function' - - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' - - // Input data to perform both basecalling and demultiplexing - input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_bc_dx.csv' - protocol = 'cDNA' - flowcell = 'FLO-MIN106' - kit = 'SQK-DCS109' - barcode_kit = 'EXP-NBD103' - trim_barcodes=true - output_demultiplex_fast5 = true - run_nanolyse = true - skip_quantification = true - skip_fusion_analysis= true - skip_modification_analysis=true - - // This variable is just for reference and isnt actually required for the tests - // Files are downloaded and staged using the "GetTestData" process - input_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/fast5/barcoded/' -} diff --git a/conf/test_bc_nodx.config b/conf/test_bc_nodx.config deleted file mode 100644 index 7ca3d308..00000000 --- a/conf/test_bc_nodx.config +++ /dev/null @@ -1,32 +0,0 @@ -/* - * ------------------------------------------------- - * Nextflow config file for running tests - * ------------------------------------------------- - * Defines bundled input files and everything required - * to run a fast and simple test. Use as follows: - * nextflow run nf-core/nanoseq -profile test_bc_nodx, - */ - -params { - config_profile_name = 'Test profile' - config_profile_description = 'Minimal test dataset to check pipeline function' - - // Limit resources so that this can run on Travis - max_cpus = 2 - max_memory = 6.GB - max_time = 12.h - - // Input data to perform basecalling and to skip demultipexing - input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_bc_nodx.csv' - protocol = 'cDNA' - flowcell = 'FLO-MIN106' - kit = 'SQK-DCS108' - skip_demultiplexing = true - skip_quantification = true - skip_fusion_analysis= true - skip_modification_analysis=true - - // This variable is just for reference and isnt actually required for the tests - // Files are downloaded and staged using the "GetTestData" process - input_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/fast5/nonbarcoded/' -} diff --git a/modules/local/demux_fast5.nf b/modules/local/demux_fast5.nf deleted file mode 100644 index 8f7089ef..00000000 --- a/modules/local/demux_fast5.nf +++ /dev/null @@ -1,33 +0,0 @@ -process DEMUX_FAST5 { - label 'process_medium' - - conda "bioconda::ont-fast5-api=4.0.0" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/ont-fast5-api:4.0.0--pyhdfd78af_0' : - 'quay.io/biocontainers/ont-fast5-api:4.0.0--pyhdfd78af_0' }" - - input: - path(input_path), stageAs: 'input_path/*' - tuple val(meta), path(input_summary) - - output: - path "demultiplexed_fast5/*", emit: fast5 - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def fast5_dir_path = workflow.profile.contains('test') ? "input_path" : "$input_path" - """ - demux_fast5 \\ - --input $fast5_dir_path \\ - --save_path ./demultiplexed_fast5 \\ - --summary_file $input_summary - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - demux_fast5: \$(python -c 'import ont_fast5_api;print(ont_fast5_api.__version__)') - END_VERSIONS - """ -} diff --git a/modules/local/guppy.nf b/modules/local/guppy.nf deleted file mode 100644 index 5cd340b5..00000000 --- a/modules/local/guppy.nf +++ /dev/null @@ -1,69 +0,0 @@ -process GUPPY { - label 'process_medium' - - if (params.guppy_gpu) { - container = 'genomicpariscentre/guppy-gpu:5.0.16' - clusterOptions = params.gpu_cluster_options - } else { - container = 'genomicpariscentre/guppy:5.0.16' - } - - input: - path(input_path), stageAs: 'input_path/*' - val meta - path guppy_config - path guppy_model - - output: - path "fastq/*.fastq.gz" , emit: fastq - tuple val(meta), path("basecalling/*.txt"), emit: summary - path "basecalling/*" , emit: called - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def fast5_dir_path = workflow.profile.contains('test') ? "input_path" : "$input_path" - def trim_barcodes = params.trim_barcodes ? "--trim_barcodes" : "" - def barcode_kit = params.barcode_kit ? "--barcode_kits $params.barcode_kit" : "" - def barcode_ends = params.barcode_both_ends ? "--require_barcodes_both_ends" : "" - def proc_options = params.guppy_gpu ? "--device $params.gpu_device --num_callers $task.cpus --cpu_threads_per_caller $params.guppy_cpu_threads --gpu_runners_per_device $params.guppy_gpu_runners" : "--num_callers 2 --cpu_threads_per_caller ${task.cpus/2}" - def config = "--flowcell $params.flowcell --kit $params.kit" - if (params.guppy_config) config = file(params.guppy_config).exists() ? "--config ./$guppy_config" : "--config $params.guppy_config" - def model = "" - if (params.guppy_model) model = file(params.guppy_model).exists() ? "--model ./$guppy_model" : "--model $params.guppy_model" - """ - guppy_basecaller \\ - --input_path $fast5_dir_path \\ - --save_path ./basecalling \\ - --records_per_fastq 0 \\ - --compress_fastq \\ - $barcode_kit \\ - $trim_barcodes \\ - $proc_options \\ - $barcode_ends \\ - $config \\ - $model - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - guppy: \$(echo \$(guppy_basecaller --version 2>&1) | sed -r 's/.{81}//') - END_VERSIONS - - ## Concatenate fastq files - mkdir fastq - cd basecalling - if [ "\$(find . -type d -name "barcode*" )" != "" ] - then - for dir in pass/barcode*/ - do - dir=\$(basename \${dir%*/}) - cat pass/\$dir/*.fastq.gz > ../fastq/\$dir.fastq.gz - done - else - cat pass/*.fastq.gz > ../fastq/${meta.id}.fastq.gz - fi - """ -} - diff --git a/modules/local/multiqc.nf b/modules/local/multiqc.nf index d35efb13..ef2fb27d 100644 --- a/modules/local/multiqc.nf +++ b/modules/local/multiqc.nf @@ -9,7 +9,6 @@ process MULTIQC { input: path ch_multiqc_config path ch_multiqc_custom_config - path ch_pycoqc_multiqc path ch_fastqc_multiqc path ch_sortbam_stats_multiqc path ch_featurecounts_gene_multiqc diff --git a/nextflow.config b/nextflow.config index 4e1f6019..ab5caf83 100644 --- a/nextflow.config +++ b/nextflow.config @@ -15,22 +15,11 @@ params { // Options: Demultiplexing input_path = null - flowcell = null - kit = null barcode_kit = null barcode_both_ends = false trim_barcodes = false - guppy_config = null - guppy_model = null - guppy_gpu = false - guppy_gpu_runners = 6 - guppy_cpu_threads = 1 - gpu_device = 'auto' - gpu_cluster_options = null - output_demultiplex_fast5 = false qcat_min_score = 60 qcat_detect_middle = false - skip_basecalling = false skip_demultiplexing = false // Options: Raw read cleaning @@ -73,7 +62,6 @@ params { // Options: QC skip_qc = false - skip_pycoqc = false skip_nanoplot = false skip_fastqc = false skip_multiqc = false @@ -198,9 +186,7 @@ profiles { executor.cpus = 16 executor.memory = 60.GB } - test { includeConfig 'conf/test.config' } test_full { includeConfig 'conf/test_full.config' } - test_bc_nodx { includeConfig 'conf/test_bc_nodx.config' } test_nobc_dx { includeConfig 'conf/test_nobc_dx.config' } test_nobc_nodx_stringtie { includeConfig 'conf/test_nobc_nodx_stringtie.config' } test_nobc_nodx_noaln { includeConfig 'conf/test_nobc_nodx_noaln.config' } diff --git a/nextflow_schema.json b/nextflow_schema.json index f5d290a8..0e3bf0bb 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -52,8 +52,8 @@ } } }, - "basecalling_demultiplexing_options": { - "title": "Basecalling/demultiplexing options", + "demultiplexing_options": { + "title": "Demultiplexing options", "type": "object", "description": "Options required to basecall and demultiplex samples.", "default": "", @@ -62,19 +62,9 @@ "input_path": { "type": "string", "format": "file-path", - "description": "Path to Nanopore run directory files (e.g. 'fastq_pass/*') or a basecalled fastq file that requires demultiplexing. The latter can only be provided in conjunction with the '--skip_basecalling' parameter.", + "description": "Path to Nanopore run directory files (e.g. 'fastq_pass/*') or a basecalled fastq file that requires demultiplexing.", "fa_icon": "far fa-file-code" }, - "flowcell": { - "type": "string", - "description": "Flowcell used to perform the sequencing e.g. 'FLO-MIN106'. Not required if '--guppy_config' is specified.", - "fa_icon": "fas fa-band-aid" - }, - "kit": { - "type": "string", - "description": "Kit used to perform the sequencing e.g. 'SQK-LSK109'. Not required if '--guppy_config' is specified.", - "fa_icon": "fas fa-barcode" - }, "barcode_kit": { "type": "string", "description": "Barcode kit used to perform the sequencing e.g. 'SQK-PBK004'.", @@ -91,51 +81,6 @@ "fa_icon": "fas fa-barcode", "description": "Whether to trim the barcodes from the output sequences in the FastQ files from Guppy basecaller." }, - "guppy_config": { - "type": "string", - "help_text": "Cannot be used in conjunction with `--flowcell` and `--kit`. This can be a local file (e.g. `/your/dir/guppy_conf.cfg`) or a string specifying a configuration stored in the `/opt/ont/guppy/data/` directory of Guppy.", - "description": "Config file used for basecalling that will be passed to Guppy via the '--config' parameter.", - "fa_icon": "fas fa-fish" - }, - "guppy_model": { - "type": "string", - "description": "Custom basecalling model file in `json` format that will be passed to Guppy via the '--model' parameter.", - "help_text": "Custom basecalling models can be trained with software such as [Taiyaki](https://github.com/nanoporetech/taiyaki). This can also be a string specifying a model stored in the `/opt/ont/guppy/data` directory of Guppy.", - "fa_icon": "fas fa-fish" - }, - "guppy_gpu": { - "type": "boolean", - "description": "Whether to demultiplex with Guppy in GPU mode.", - "fa_icon": "fas fa-fish" - }, - "guppy_gpu_runners": { - "type": "integer", - "default": 6, - "description": "Number of '--gpu_runners_per_device' used for Guppy when using '--guppy_gpu'.", - "fa_icon": "fas fa-fish" - }, - "guppy_cpu_threads": { - "type": "integer", - "default": 1, - "description": "Number of '--cpu_threads_per_caller' used for Guppy when using '--guppy_gpu'.", - "fa_icon": "fas fa-fish" - }, - "gpu_device": { - "type": "string", - "default": "auto", - "description": "Basecalling device specified to Guppy in GPU mode using '--device'.", - "fa_icon": "fas fa-fish" - }, - "gpu_cluster_options": { - "type": "string", - "description": "Cluster options required to use GPU resources (e.g. '--part=gpu --gres=gpu:1').", - "fa_icon": "fas fa-fish" - }, - "output_demultiplex_fast5": { - "type": "boolean", - "description": "Demultiplex fast5 files with demux_fast5.", - "fa_icon": "fas fa-file-code" - }, "qcat_min_score": { "type": "integer", "default": 60, @@ -558,7 +503,7 @@ "$ref": "#/definitions/input_output_options" }, { - "$ref": "#/definitions/basecalling_demultiplexing_options" + "$ref": "#/definitions/demultiplexing_options" }, { "$ref": "#/definitions/alignment_options" diff --git a/subworkflows/local/qcbasecall_pycoqc_nanoplot.nf b/subworkflows/local/qcbasecall_pycoqc_nanoplot.nf deleted file mode 100644 index e0724eb9..00000000 --- a/subworkflows/local/qcbasecall_pycoqc_nanoplot.nf +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Basecalling QC with PycoQC and NanoPlot - */ - -include { PYCOQC } from '../../modules/nf-core/pycoqc/main' -include { NANOPLOT } from '../../modules/local/nanoplot' - -workflow QCBASECALL_PYCOQC_NANOPLOT { - take: - ch_guppy_summary_txt // channel: [ val(meta), [ reads ] ] - skip_pycoqc - skip_nanoplot - - main: - /* - * QC using PycoQC - */ - pycoqc_html = Channel.empty() - pycoqc_multiqc = Channel.empty() - pycoqc_version = Channel.empty() - ch_guppy_summary_txt - .map { it -> [ it[1] ] } - .set { ch_pycoqc_input } - if (!skip_pycoqc){ - PYCOQC ( ch_pycoqc_input ) - pycoqc_html = PYCOQC.out.html - pycoqc_multiqc = PYCOQC.out.json - pycoqc_version = PYCOQC.out.versions - } - - /* - * QC using NanoPlot - */ - nanoplot_png = Channel.empty() - nanoplot_html = Channel.empty() - nanoplot_txt = Channel.empty() - nanoplot_log = Channel.empty() - if (!skip_nanoplot){ - NANOPLOT ( ch_guppy_summary_txt ) - //nanoplot_png = NANOPLOT.out.png - nanoplot_html = NANOPLOT.out.html - nanoplot_txt = NANOPLOT.out.txt - nanoplot_log = NANOPLOT.out.log - nanoplot_versions = NANOPLOT.out.versions - } - - emit: - pycoqc_html - pycoqc_multiqc - pycoqc_version - - nanoplot_png - nanoplot_html - nanoplot_txt - nanoplot_log -} diff --git a/workflows/nanoseq.nf b/workflows/nanoseq.nf index ef05cce4..ba1c377e 100644 --- a/workflows/nanoseq.nf +++ b/workflows/nanoseq.nf @@ -31,48 +31,31 @@ def isOffline() { } } -def ch_guppy_model = Channel.empty() -def ch_guppy_config = Channel.empty() - if (params.protocol != 'DNA' && params.protocol != 'cDNA' && params.protocol != 'directRNA') { exit 1, "Invalid protocol option: ${params.protocol}. Valid options: 'DNA', 'cDNA', 'directRNA'" } -if (!params.skip_basecalling) { - if (!params.guppy_config) { - if (!params.flowcell) { exit 1, "Please specify a valid flowcell identifier for basecalling!" } - if (!params.kit) { exit 1, "Please specify a valid kit identifier for basecalling!" } - } else if (file(params.guppy_config).exists()) { - ch_guppy_config = Channel.fromPath(params.guppy_config) +if (!params.skip_demultiplexing) { + if (!params.barcode_kit) { + params.barcode_kit = 'Auto' } - if (params.guppy_model) { - if (file(params.guppy_model).exists()) { - ch_guppy_model = Channel.fromPath(params.guppy_model) - } - } -} else { - if (!params.skip_demultiplexing) { - if (!params.barcode_kit) { - params.barcode_kit = 'Auto' - } - - def qcatBarcodeKitList = ['Auto', 'RBK001', 'RBK004', 'NBD103/NBD104', - 'NBD114', 'NBD104/NBD114', 'PBC001', 'PBC096', - 'RPB004/RLB001', 'PBK004/LWB001', 'RAB204', 'VMK001', 'DUAL'] + def qcatBarcodeKitList = ['Auto', 'RBK001', 'RBK004', 'NBD103/NBD104', + 'NBD114', 'NBD104/NBD114', 'PBC001', 'PBC096', + 'RPB004/RLB001', 'PBK004/LWB001', 'RAB204', 'VMK001', 'DUAL'] - if (params.barcode_kit && qcatBarcodeKitList.contains(params.barcode_kit)) { - if (params.input_path) { - ch_input_path = Channel.fromPath(params.input_path, checkIfExists: true) - } else { - exit 1, "Please specify a valid input fastq file to perform demultiplexing!" - } + if (params.barcode_kit && qcatBarcodeKitList.contains(params.barcode_kit)) { + if (params.input_path) { + ch_input_path = Channel.fromPath(params.input_path, checkIfExists: true) } else { - exit 1, "Please provide a barcode kit to demultiplex with qcat. Valid options: ${qcatBarcodeKitList}" + exit 1, "Please specify a valid input fastq file to perform demultiplexing!" } + } else { + exit 1, "Please provide a barcode kit to demultiplex with qcat. Valid options: ${qcatBarcodeKitList}" } } + if (!params.skip_alignment) { if (params.aligner != 'minimap2' && params.aligner != 'graphmap2') { exit 1, "Invalid aligner option: ${params.aligner}. Valid options: 'minimap2', 'graphmap2'" @@ -119,8 +102,6 @@ ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multi include { GET_TEST_DATA } from '../modules/local/get_test_data' include { GET_NANOLYSE_FASTA } from '../modules/local/get_nanolyse_fasta' -include { GUPPY } from '../modules/local/guppy' -include { DEMUX_FAST5 } from '../modules/local/demux_fast5' include { QCAT } from '../modules/local/qcat' include { BAM_RENAME } from '../modules/local/bam_rename' include { BAMBU } from '../modules/local/bambu' @@ -132,7 +113,6 @@ include { MULTIQC } from '../modules/local/multiqc' include { INPUT_CHECK } from '../subworkflows/local/input_check' include { PREPARE_GENOME } from '../subworkflows/local/prepare_genome' -include { QCBASECALL_PYCOQC_NANOPLOT } from '../subworkflows/local/qcbasecall_pycoqc_nanoplot' include { QCFASTQ_NANOPLOT_FASTQC } from '../subworkflows/local/qcfastq_nanoplot_fastqc' include { ALIGN_GRAPHMAP2 } from '../subworkflows/local/align_graphmap2' include { ALIGN_MINIMAP2 } from '../subworkflows/local/align_minimap2' @@ -172,16 +152,11 @@ workflow NANOSEQ{ // Pre-download test-dataset to get files for '--input_path' parameter // Nextflow is unable to recursively download directories via HTTPS if (workflow.profile.contains('test') && !workflow.profile.contains('vc')) { - if (!params.skip_basecalling || !params.skip_modification_analysis) { + if (!params.skip_modification_analysis) { if (!isOffline()) { GET_TEST_DATA () - if (params.skip_modification_analysis) { - GET_TEST_DATA.out.ch_input_fast5s_path - .set { ch_input_path } - } else { - GET_TEST_DATA.out.ch_input_dir_path - .set { ch_input_path } - } + GET_TEST_DATA.out.ch_input_dir_path + .set { ch_input_path } } else { exit 1, "NXF_OFFLINE=true or -offline has been set so cannot download and run any test dataset!" } @@ -211,64 +186,27 @@ workflow NANOSEQ{ INPUT_CHECK ( ch_input, ch_input_path ) .set { ch_sample } - if (!params.skip_basecalling) { - ch_sample - .first() - .map { it[0] } - .set { ch_sample_name } + if (!params.skip_demultiplexing) { /* - * MODULE: Basecalling and demultipexing using Guppy + * MODULE: Demultipexing using qcat */ - GUPPY ( ch_input_path, ch_sample_name, ch_guppy_config.ifEmpty([]), ch_guppy_model.ifEmpty([]) ) - ch_guppy_summary = GUPPY.out.summary - ch_software_versions = ch_software_versions.mix(GUPPY.out.versions.ifEmpty(null)) - - if (params.skip_demultiplexing) { - ch_sample - .map { it -> [ it[0], it[0].id, it[2], it[3], it[4], it[5] ] } - .set { ch_sample } - } - - GUPPY.out.fastq + QCAT ( ch_input_path ) + ch_fastq = Channel.empty() + QCAT.out.fastq .flatten() - .map { it -> [ it, it.baseName.substring(0,it.baseName.lastIndexOf('.')) ] } + .map { it -> [ it, it.baseName.substring(0,it.baseName.lastIndexOf('.'))] } .join(ch_sample, by: 1) // join on barcode .map { it -> [ it[2], it[1], it[3], it[4], it[5], it[6] ] } .set { ch_fastq } - if (params.output_demultiplex_fast5) { - - /* - * MODULE: Demultiplex fast5 files using ont_fast5_api/demux_fast5 - */ - DEMUX_FAST5 ( ch_input_path, ch_guppy_summary ) - ch_software_versions = ch_software_versions.mix(DEMUX_FAST5.out.versions.ifEmpty(null)) - } + ch_software_versions = ch_software_versions.mix(QCAT.out.versions.ifEmpty(null)) } else { - ch_guppy_summary = Channel.empty() - - if (!params.skip_demultiplexing) { - - /* - * MODULE: Demultipexing using qcat - */ - QCAT ( ch_input_path ) - ch_fastq = Channel.empty() - QCAT.out.fastq - .flatten() - .map { it -> [ it, it.baseName.substring(0,it.baseName.lastIndexOf('.'))] } - .join(ch_sample, by: 1) // join on barcode - .map { it -> [ it[2], it[1], it[3], it[4], it[5], it[6] ] } + if (!params.skip_alignment) { + ch_sample + .map { it -> if (it[6].toString().endsWith('.gz')) [ it[0], it[6], it[2], it[1], it[4], it[5] ] } .set { ch_fastq } - ch_software_versions = ch_software_versions.mix(QCAT.out.versions.ifEmpty(null)) } else { - if (!params.skip_alignment) { - ch_sample - .map { it -> if (it[6].toString().endsWith('.gz')) [ it[0], it[6], it[2], it[1], it[4], it[5] ] } - .set { ch_fastq } - } else { - ch_fastq = Channel.empty() - } + ch_fastq = Channel.empty() } } @@ -299,26 +237,13 @@ workflow NANOSEQ{ ch_software_versions = ch_software_versions.mix(NANOLYSE.out.versions.first().ifEmpty(null)) } - ch_pycoqc_multiqc = Channel.empty() ch_fastqc_multiqc = Channel.empty() if (!params.skip_qc) { - if (!params.skip_basecalling) { - - /* - * SUBWORKFLOW: Basecalling QC with PycoQC and Nanoplot - */ - QCBASECALL_PYCOQC_NANOPLOT ( ch_guppy_summary , params.skip_pycoqc, params.skip_nanoplot ) - ch_software_versions = ch_software_versions.mix(QCBASECALL_PYCOQC_NANOPLOT.out.pycoqc_version.first().ifEmpty(null)) - ch_pycoqc_multiqc = QCBASECALL_PYCOQC_NANOPLOT.out.pycoqc_multiqc.ifEmpty([]) - } /* * SUBWORKFLOW: Fastq QC with Nanoplot and fastqc */ QCFASTQ_NANOPLOT_FASTQC ( ch_fastq, params.skip_nanoplot, params.skip_fastqc) - if (params.skip_basecalling) { - ch_software_versions = ch_software_versions.mix(QCFASTQ_NANOPLOT_FASTQC.out.nanoplot_version.first().ifEmpty(null)) - } ch_software_versions = ch_software_versions.mix(QCFASTQ_NANOPLOT_FASTQC.out.fastqc_version.first().ifEmpty(null)) ch_fastqc_multiqc = QCFASTQ_NANOPLOT_FASTQC.out.fastqc_multiqc.ifEmpty([]) } @@ -510,7 +435,6 @@ workflow NANOSEQ{ MULTIQC ( ch_multiqc_config, ch_multiqc_custom_config.collect().ifEmpty([]), - ch_pycoqc_multiqc.collect().ifEmpty([]), ch_fastqc_multiqc.ifEmpty([]), ch_samtools_multiqc.collect().ifEmpty([]), ch_featurecounts_gene_multiqc.ifEmpty([]), From 2b60bc9df5a68425f735878d9c718e6936030605 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Wed, 15 Feb 2023 14:19:20 +0800 Subject: [PATCH 27/56] update test configs --- .github/workflows/ci.yml | 10 ++++------ conf/{test_nobc_dx.config => test.config} | 0 ...t_nobc_nodx_noaln.config => test_nodx_noaln.config} | 0 ...nobc_nodx_rnamod.config => test_nodx_rnamod.config} | 0 ...odx_stringtie.config => test_nodx_stringtie.config} | 0 conf/{test_nobc_nodx_vc.config => test_nodx_vc.config} | 0 nextflow.config | 10 +++++----- 7 files changed, 9 insertions(+), 11 deletions(-) rename conf/{test_nobc_dx.config => test.config} (100%) rename conf/{test_nobc_nodx_noaln.config => test_nodx_noaln.config} (100%) rename conf/{test_nobc_nodx_rnamod.config => test_nodx_rnamod.config} (100%) rename conf/{test_nobc_nodx_stringtie.config => test_nodx_stringtie.config} (100%) rename conf/{test_nobc_nodx_vc.config => test_nodx_vc.config} (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 963b3273..5235d1ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,12 +49,10 @@ jobs: strategy: matrix: profiles: - - "test_bc_nodx" - - "test_nobc_dx" - - "test_nobc_nodx_vc" - - "test_nobc_nodx_stringtie" - - "test_nobc_nodx_noaln" - - "test_nobc_nodx_rnamod" + - "test_nodx_vc" + - "test_nodx_stringtie" + - "test_nodx_noaln" + - "test_nodx_rnamod" steps: - name: Check out pipeline code uses: actions/checkout@v3 diff --git a/conf/test_nobc_dx.config b/conf/test.config similarity index 100% rename from conf/test_nobc_dx.config rename to conf/test.config diff --git a/conf/test_nobc_nodx_noaln.config b/conf/test_nodx_noaln.config similarity index 100% rename from conf/test_nobc_nodx_noaln.config rename to conf/test_nodx_noaln.config diff --git a/conf/test_nobc_nodx_rnamod.config b/conf/test_nodx_rnamod.config similarity index 100% rename from conf/test_nobc_nodx_rnamod.config rename to conf/test_nodx_rnamod.config diff --git a/conf/test_nobc_nodx_stringtie.config b/conf/test_nodx_stringtie.config similarity index 100% rename from conf/test_nobc_nodx_stringtie.config rename to conf/test_nodx_stringtie.config diff --git a/conf/test_nobc_nodx_vc.config b/conf/test_nodx_vc.config similarity index 100% rename from conf/test_nobc_nodx_vc.config rename to conf/test_nodx_vc.config diff --git a/nextflow.config b/nextflow.config index ab5caf83..eeace711 100644 --- a/nextflow.config +++ b/nextflow.config @@ -187,11 +187,11 @@ profiles { executor.memory = 60.GB } test_full { includeConfig 'conf/test_full.config' } - test_nobc_dx { includeConfig 'conf/test_nobc_dx.config' } - test_nobc_nodx_stringtie { includeConfig 'conf/test_nobc_nodx_stringtie.config' } - test_nobc_nodx_noaln { includeConfig 'conf/test_nobc_nodx_noaln.config' } - test_nobc_nodx_vc { includeConfig 'conf/test_nobc_nodx_vc.config' } - test_nobc_nodx_rnamod { includeConfig 'conf/test_nobc_nodx_rnamod.config' } + test { includeConfig 'conf/test.config' } + test_nodx_stringtie { includeConfig 'conf/test_nodx_stringtie.config' } + test_nodx_noaln { includeConfig 'conf/test_nodx_noaln.config' } + test_nodx_vc { includeConfig 'conf/test_nodx_vc.config' } + test_nodx_rnamod { includeConfig 'conf/test_nodx_rnamod.config' } } From 96cd16a1c5318e02916b0926c31bc92e26d3d362 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Wed, 15 Feb 2023 14:33:55 +0800 Subject: [PATCH 28/56] update schema --- conf/test.config | 1 - conf/test_full.config | 1 - conf/test_nodx_noaln.config | 1 - conf/test_nodx_rnamod.config | 1 - conf/test_nodx_stringtie.config | 1 - conf/test_nodx_vc.config | 1 - nextflow_schema.json | 10 ---------- 7 files changed, 16 deletions(-) diff --git a/conf/test.config b/conf/test.config index aa9db6e1..b7d54aab 100644 --- a/conf/test.config +++ b/conf/test.config @@ -21,7 +21,6 @@ params { protocol = 'DNA' barcode_kit = 'NBD103/NBD104' input_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/fastq/nondemultiplexed/sample_nobc_dx.fastq.gz' - skip_basecalling = true skip_quantification = true skip_fusion_analysis= true skip_modification_analysis=true diff --git a/conf/test_full.config b/conf/test_full.config index 6c35a60e..ad3ad331 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -17,7 +17,6 @@ params { // Input data for full size test input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_full.csv' protocol = 'cDNA' - skip_basecalling = true skip_demultiplexing = true skip_fusion_analysis= true skip_modification_analysis=true diff --git a/conf/test_nodx_noaln.config b/conf/test_nodx_noaln.config index abec7b05..b3047db4 100644 --- a/conf/test_nodx_noaln.config +++ b/conf/test_nodx_noaln.config @@ -19,7 +19,6 @@ params { // Input data to skip both basecalling and demultiplexing input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_nobc_nodx_noaln.csv' protocol = 'directRNA' - skip_basecalling = true skip_demultiplexing = true skip_alignment = true skip_fusion_analysis= true diff --git a/conf/test_nodx_rnamod.config b/conf/test_nodx_rnamod.config index 2c5e6ee4..47567132 100644 --- a/conf/test_nodx_rnamod.config +++ b/conf/test_nodx_rnamod.config @@ -19,7 +19,6 @@ params { // Input data to skip both basecalling and demultiplexing input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_nobc_nodx_rnamod.csv' protocol = 'directRNA' - skip_basecalling = true skip_demultiplexing = true skip_quantification = true skip_fusion_analysis= true diff --git a/conf/test_nodx_stringtie.config b/conf/test_nodx_stringtie.config index e1ad8007..e8244e0d 100644 --- a/conf/test_nodx_stringtie.config +++ b/conf/test_nodx_stringtie.config @@ -19,7 +19,6 @@ params { // Input data to skip both basecalling and demultiplexing input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_nobc_nodx_stringtie.csv' protocol = 'directRNA' - skip_basecalling = true skip_demultiplexing = true skip_fusion_analysis= true skip_modification_analysis=true diff --git a/conf/test_nodx_vc.config b/conf/test_nodx_vc.config index 20cee84a..8c95f9ef 100644 --- a/conf/test_nodx_vc.config +++ b/conf/test_nodx_vc.config @@ -19,7 +19,6 @@ params { // Input data to skip basecalling and demultiplexing, and variant call input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_nobc_nodx_vc.csv' protocol = 'DNA' - skip_basecalling = true skip_quantification = true skip_demultiplexing = true call_variants = true diff --git a/nextflow_schema.json b/nextflow_schema.json index 0e3bf0bb..3886cab7 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -92,11 +92,6 @@ "description": "Search for adapters in the whole read by applying the '--detect-middle' parameter in qcat.", "fa_icon": "fas fa-cut" }, - "skip_basecalling": { - "type": "boolean", - "description": "Skip basecalling with Guppy.", - "fa_icon": "fas fa-fast-forward" - }, "skip_demultiplexing": { "type": "boolean", "description": "Skip demultiplexing with Guppy/qcat.", @@ -281,11 +276,6 @@ "fa_icon": "fas fa-fast-forward", "description": "Skip BigWig file generation." }, - "skip_pycoqc": { - "type": "boolean", - "fa_icon": "fas fa-fast-forward", - "description": "Skip pycoQC." - }, "skip_nanoplot": { "type": "boolean", "fa_icon": "fas fa-fast-forward", From 2b68a959043619c960fa8a21c29a197a05d10a9b Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Wed, 15 Feb 2023 14:45:52 +0800 Subject: [PATCH 29/56] fix skip_basecalling --- conf/modules.config | 12 ------------ nextflow_schema.json | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index e47a6a36..ba13b442 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -82,18 +82,6 @@ if (params.run_nanolyse) { } if (!params.skip_qc) { - if (!params.skip_basecalling && !params.skip_pycoqc) { - process { - withName: PYCOQC { - publishDir = [ - path: { "${params.outdir}/pycoqc" }, - mode: 'copy', - enabled: true, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } - ] - } - } - } if (!params.skip_nanoplot) { process { withName: NANOPLOT { diff --git a/nextflow_schema.json b/nextflow_schema.json index 3886cab7..4bc408ea 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -68,7 +68,7 @@ "barcode_kit": { "type": "string", "description": "Barcode kit used to perform the sequencing e.g. 'SQK-PBK004'.", - "help_text": "If you would like to skip the basecalling (`--skip_basecalling`) but still perform the demultiplexing please specify a barcode kit that can be recognised by [qcat](https://github.com/nanoporetech/qcat):\n\n| `qcat` barcode kit specifications | description |\n|-----------------------------------|-------------------------------------------------------------------------------|\n| `Auto` | Auto detect barcoding kit |\n| `RBK001` | Rapid barcoding kit |\n| `RBK004` | Rapid barcoding kit v4 |\n| `NBD103/NBD104` | Native barcoding kit with barcodes 1-12 |\n| `NBD114` | Native barcoding kit with barcodes 13-24 |\n| `NBD104/NBD114` | Native barcoding kit with barcodes 1-24 |\n| `PBC001` | PCR barcoding kits with 12 barcodes |\n| `PBC096` | PCR barcoding kits with 96 barcodes |\n| `RPB004/RLB001` | Rapid PCR Barcoding Kit (SQK-RPB004) and Rapid Low Input by PCR Barcoding Kit |\n| `RPB004/LWB001` | Low Input by PCR Barcoding Kit |\n| `RAB204` | 16S Rapid Amplicon Barcoding Kit with 12 Barcodes |\n| `VMK001` | Voltrax Barcoding Kit with 4 barcodes |", + "help_text": "If you would like to perform demultiplexing please specify a barcode kit that can be recognised by [qcat](https://github.com/nanoporetech/qcat):\n\n| `qcat` barcode kit specifications | description |\n|-----------------------------------|-------------------------------------------------------------------------------|\n| `Auto` | Auto detect barcoding kit |\n| `RBK001` | Rapid barcoding kit |\n| `RBK004` | Rapid barcoding kit v4 |\n| `NBD103/NBD104` | Native barcoding kit with barcodes 1-12 |\n| `NBD114` | Native barcoding kit with barcodes 13-24 |\n| `NBD104/NBD114` | Native barcoding kit with barcodes 1-24 |\n| `PBC001` | PCR barcoding kits with 12 barcodes |\n| `PBC096` | PCR barcoding kits with 96 barcodes |\n| `RPB004/RLB001` | Rapid PCR Barcoding Kit (SQK-RPB004) and Rapid Low Input by PCR Barcoding Kit |\n| `RPB004/LWB001` | Low Input by PCR Barcoding Kit |\n| `RAB204` | 16S Rapid Amplicon Barcoding Kit with 12 Barcodes |\n| `VMK001` | Voltrax Barcoding Kit with 4 barcodes |", "fa_icon": "fas fa-barcode" }, "barcode_both_ends": { From cd3a0306dbbc7e1c1feddce69ffc597ac9be96dd Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Wed, 15 Feb 2023 14:54:38 +0800 Subject: [PATCH 30/56] test stuff out --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5235d1ff..db400afd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,7 +76,6 @@ jobs: strategy: matrix: parameters: - - "--aligner graphmap2" - "--skip_alignment" - "--skip_qc" - "--skip_quantification" From 79881effa3a3bbd691aef8d6c9d766ca937a35ba Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Wed, 15 Feb 2023 15:00:25 +0800 Subject: [PATCH 31/56] test stuff out --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db400afd..5235d1ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,6 +76,7 @@ jobs: strategy: matrix: parameters: + - "--aligner graphmap2" - "--skip_alignment" - "--skip_qc" - "--skip_quantification" From f22e28fc4fe76a92bb45f8eba3119674c6c33904 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Wed, 15 Feb 2023 15:04:23 +0800 Subject: [PATCH 32/56] test things out --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5235d1ff..bf28ab82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,6 +93,6 @@ jobs: - name: Run pipeline with different parameters run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,docker ${{ matrix.parameters }} + nextflow run ${GITHUB_WORKSPACE} -profile test_nodx_stringtie,docker ${{ matrix.parameters }} # From b671dd21d461dcd529a62b38919c53a17f17c481 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Wed, 15 Feb 2023 15:16:59 +0800 Subject: [PATCH 33/56] fix test_nodx_rnamod --- modules/local/samplesheet_check.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf index d176773a..4eac940f 100644 --- a/modules/local/samplesheet_check.nf +++ b/modules/local/samplesheet_check.nf @@ -19,7 +19,7 @@ process SAMPLESHEET_CHECK { task.ext.when == null || task.ext.when script: // This script is bundled with the pipeline, in nf-core/nanoseq/bin/ - updated_path = workflow.profile.contains('test_nobc_nodx_rnamod') ? "$input_path" : "not_changed" + updated_path = workflow.profile.contains('test_nodx_rnamod') ? "$input_path" : "not_changed" """ check_samplesheet.py \\ $samplesheet \\ From a62fc6e93f22544684c007318893e33d56bb4690 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Wed, 15 Feb 2023 15:57:58 +0800 Subject: [PATCH 34/56] solve graphmap2 bug --- .github/workflows/ci.yml | 2 +- conf/test.config | 2 ++ subworkflows/local/align_graphmap2.nf | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf28ab82..5235d1ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,6 +93,6 @@ jobs: - name: Run pipeline with different parameters run: | - nextflow run ${GITHUB_WORKSPACE} -profile test_nodx_stringtie,docker ${{ matrix.parameters }} + nextflow run ${GITHUB_WORKSPACE} -profile test,docker ${{ matrix.parameters }} # diff --git a/conf/test.config b/conf/test.config index b7d54aab..38f722a4 100644 --- a/conf/test.config +++ b/conf/test.config @@ -22,6 +22,8 @@ params { barcode_kit = 'NBD103/NBD104' input_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/fastq/nondemultiplexed/sample_nobc_dx.fastq.gz' skip_quantification = true + skip_bigwig = true + skip_bigbed = true skip_fusion_analysis= true skip_modification_analysis=true diff --git a/subworkflows/local/align_graphmap2.nf b/subworkflows/local/align_graphmap2.nf index 7b175c17..75db5921 100644 --- a/subworkflows/local/align_graphmap2.nf +++ b/subworkflows/local/align_graphmap2.nf @@ -21,13 +21,14 @@ workflow ALIGN_GRAPHMAP2 { ch_index .cross(ch_fastq) { it -> it[-1] } .flatten() - .collate(13) + .collate(12) .map { it -> [ it[6], it[7], it[0], it[1], it[2], it[3], it[10], it[4] ] } // [ sample, fastq, fasta, sizes, gtf, bed, is_transcripts, index ] .set { ch_index } /* * Map reads with GRAPHMAP2 */ + GRAPHMAP2_ALIGN ( ch_index ) ch_align_sam = GRAPHMAP2_ALIGN.out.align_sam From 9702f72c206a1ca08d4920a6f8062cbfe48a32ad Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Fri, 17 Feb 2023 15:38:48 +0800 Subject: [PATCH 35/56] address comments from Chris --- conf/base.config | 5 +++++ nextflow.config | 2 ++ nextflow_schema.json | 11 +++++++++++ 3 files changed, 18 insertions(+) diff --git a/conf/base.config b/conf/base.config index 3fdddd24..e925219d 100644 --- a/conf/base.config +++ b/conf/base.config @@ -8,6 +8,11 @@ ---------------------------------------------------------------------------------------- */ +if (params.deepvariant_gpu) { + docker.runOptions = '--gpus all' + singularity.runOptions = '--nv' +} + process { cpus = { check_max( 1 * task.attempt, 'cpus' ) } diff --git a/nextflow.config b/nextflow.config index eeace711..0341d8ed 100644 --- a/nextflow.config +++ b/nextflow.config @@ -18,6 +18,8 @@ params { barcode_kit = null barcode_both_ends = false trim_barcodes = false + gpu_device = 'auto' + gpu_cluster_options = null qcat_min_score = 60 qcat_detect_middle = false skip_demultiplexing = false diff --git a/nextflow_schema.json b/nextflow_schema.json index 4bc408ea..20c4a27c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -81,6 +81,17 @@ "fa_icon": "fas fa-barcode", "description": "Whether to trim the barcodes from the output sequences in the FastQ files from Guppy basecaller." }, + "gpu_device": { + "type": "string", + "default": "auto", + "description": "Basecalling device specified to Guppy in GPU mode using '--device'.", + "fa_icon": "fas fa-fish" + }, + "gpu_cluster_options": { + "type": "string", + "description": "Cluster options required to use GPU resources (e.g. '--part=gpu --gres=gpu:1').", + "fa_icon": "fas fa-fish" + }, "qcat_min_score": { "type": "integer", "default": 60, From 6f71724256607d6aa6681674e1e231d71200e9cc Mon Sep 17 00:00:00 2001 From: christopher-hakkaart Date: Fri, 17 Feb 2023 16:56:04 +0100 Subject: [PATCH 36/56] fix: removing reference to parameters that were removed --- conf/test.config | 2 +- conf/test_nodx_noaln.config | 2 +- conf/test_nodx_rnamod.config | 2 +- conf/test_nodx_stringtie.config | 2 +- conf/test_nodx_vc.config | 2 +- docs/images/pycoqc_readsperbarcode.png | Bin 24100 -> 0 bytes docs/output.md | 37 +++---------------------- docs/usage.md | 37 +++++-------------------- 8 files changed, 16 insertions(+), 68 deletions(-) delete mode 100755 docs/images/pycoqc_readsperbarcode.png diff --git a/conf/test.config b/conf/test.config index 38f722a4..1e7d8f8c 100644 --- a/conf/test.config +++ b/conf/test.config @@ -16,7 +16,7 @@ params { max_memory = 6.GB max_time = 12.h - // Input data to skip basecalling and to only perform demultipexing + // Input data to perform demultipexing input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_nobc_dx.csv' protocol = 'DNA' barcode_kit = 'NBD103/NBD104' diff --git a/conf/test_nodx_noaln.config b/conf/test_nodx_noaln.config index b3047db4..eed15dd4 100644 --- a/conf/test_nodx_noaln.config +++ b/conf/test_nodx_noaln.config @@ -16,7 +16,7 @@ params { max_memory = 6.5.GB max_time = 12.h - // Input data to skip both basecalling and demultiplexing + // Input data to skip demultiplexing and alignment input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_nobc_nodx_noaln.csv' protocol = 'directRNA' skip_demultiplexing = true diff --git a/conf/test_nodx_rnamod.config b/conf/test_nodx_rnamod.config index 47567132..8e721795 100644 --- a/conf/test_nodx_rnamod.config +++ b/conf/test_nodx_rnamod.config @@ -16,7 +16,7 @@ params { max_memory = 6.GB max_time = 12.h - // Input data to skip both basecalling and demultiplexing + // Input data to skip demultiplexing and rna modification analysis input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_nobc_nodx_rnamod.csv' protocol = 'directRNA' skip_demultiplexing = true diff --git a/conf/test_nodx_stringtie.config b/conf/test_nodx_stringtie.config index e8244e0d..86f9b94f 100644 --- a/conf/test_nodx_stringtie.config +++ b/conf/test_nodx_stringtie.config @@ -16,7 +16,7 @@ params { max_memory = 6.GB max_time = 12.h - // Input data to skip both basecalling and demultiplexing + // Input data to skip demultiplexing and stringtie input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_nobc_nodx_stringtie.csv' protocol = 'directRNA' skip_demultiplexing = true diff --git a/conf/test_nodx_vc.config b/conf/test_nodx_vc.config index 8c95f9ef..6b4e8d5c 100644 --- a/conf/test_nodx_vc.config +++ b/conf/test_nodx_vc.config @@ -16,7 +16,7 @@ params { max_memory = 6.GB max_time = 12.h - // Input data to skip basecalling and demultiplexing, and variant call + // Input data to skip demultiplexing and variant call input = 'https://raw.githubusercontent.com/nf-core/test-datasets/nanoseq/3.0/samplesheet/samplesheet_nobc_nodx_vc.csv' protocol = 'DNA' skip_quantification = true diff --git a/docs/images/pycoqc_readsperbarcode.png b/docs/images/pycoqc_readsperbarcode.png deleted file mode 100755 index d62bd3b7ebc107e75ba43cf7d4a77f1a3e8003e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24100 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 Kt5nrG Output files -- `guppy/fastq/.fastq.gz`: merged FASTQ output files for each barcode. -- `guppy/basecalling/pass//.fastq.gz`: passing FASTQ output file for each barcode. -- `guppy/basecalling/pass/unclassified/.fastq.gz`: passing FASTQ files with reads were unassigned to any given barcode. -- `guppy/basecalling/fail//.fastq.gz`: failing FASTQ output file for each barcode. -- `guppy/basecalling/fail/unclassified/.fastq.gz`: failing FASTQ files with reads were unassigned to any given barcode. -- `guppy/basecalling/sequencing_summary.txt`: sequencing summary file generated by _Guppy_. -- `guppy/basecalling/sequencing_telemetry.js`: sequencing telemetry file generated by _Guppy_. -- `guppy/basecalling/guppy_basecaller_log-.log`: log file generated by _Guppy_. -- `demux_fast5/demultiplexed_fast5//`: directory containing `.fast5` and `.txt` file for each barcode. -- `demux_fast5/demultiplexed_fast5/unclassified/`: directory containing `.fast5` and `.txt` file for reads that were not unassigned to any given barcode. - `qcat/fastq/.fastq.gz`: FASTQ output files for each barcode. - `qcat/fastq/none.fastq.gz`: FASTQ file with reads were unassigned to any given barcode. _Documentation_: -[Guppy](https://nanoporetech.com/nanopore-sequencing-data-analysis), [demux_fast5](https://github.com/nanoporetech/ont_fast5_api#demux_fast5), [qcat](https://github.com/nanoporetech/qcat) +[qcat](https://github.com/nanoporetech/qcat) _Description_: -Nanoseq is designed to deal with various input data types. _Guppy_ can be used to basecall raw data which can then be demultiplexed using _demux_. Alternatively, _demux_ can be used to demultiplex FAST5 data that has already been basecalled. Various options are available to customising these steps, including running _Guppy_ on GPUs if they are available. If you already have a pre-basecalled FASTQ file then _qcat_ can used to perform demultiplexing. The `--skip_basecalling` and `--skip_demultiplexing` parameters can be used seperately or together to skip steps depending on your input data type. Please see [`usage.md`](usage.md#--input) for more details about the format of the input samplesheet. All potential outputs are shown here however some may not be produced depending on your inputs and the steps you have chosen to run. +Nanoseq is designed to deal with various input data types. Pre-basecalled FASTQ file can be demuliplexed using _qcat_. Please see [`usage.md`](usage.md#--input) for more details about the format of the input samplesheet. All potential outputs are shown here however some may not be produced depending on your inputs and the steps you have chosen to run. ## Removal of DNA contaminants @@ -56,25 +46,6 @@ _Documentation_: _Description_: If you would like to run NanoLyse on the raw FASTQ files you can provide `--run_nanolyse` when running the pipeline. By default, the pipeline will filter lambda phage reads. However, you can provide your own FASTA file of "contaminants" with `--nanolyse_fasta`. The filtered FASTQ files will contain raw reads without the specified reference sequences (default: lambda phage sequences). -## Sequencing QC - -
    -Output files - -- `pycoqc/pyoqc.html`: HTML file that contains a run summary and graphical representation of various QC metrics. -- `pycoqc/pyoqc.json`: JSON formatted file containing QC data shown in the HTML report. -- `nanoplot/summary/`: directory with various `*.html` files showing QC metrics and a single _NanoPlot_ `.log` file. - -
    - -_Documentation_: -[PycoQC](https://github.com/a-slide/pycoQC), [NanoPlot](https://github.com/wdecoster/NanoPlot) - -_Description_: -_PycoQC_ and _NanoPlot_ can compute QC metrics and generate plots using the sequencing summary information generated by _Guppy_, e.g., distribution of read length, read length over time, number of reads per barcode and other general stats. _NanoPlot_ can also generate QC metrics directly from FASTQ files as described in the next section. - -![PycoQC - Number of reads per barcode](images/pycoqc_readsperbarcode.png) - ## Read QC
    @@ -90,7 +61,7 @@ _Documentation_: [NanoPlot](https://github.com/wdecoster/NanoPlot), [FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/) _Description_: -_NanoPlot_ can be used to produce general quality metrics from the per barcode FASTQ files generated by _Guppy_ e.g. quality score distribution, read lengths, and other general stats. +_NanoPlot_ can be used to produce general quality metrics from the per barcode FASTQ files generated by a basecaller e.g. quality score distribution, read lengths, and other general stats. ![Nanoplot - Read quality vs read length](images/nanoplot_readlengthquality.png) diff --git a/docs/usage.md b/docs/usage.md index b5156d45..22213cbb 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -17,11 +17,11 @@ You will need to create a file with information about the samples in your experi | `fasta` | Genome fasta file or transcriptome fasta file for alignment. This can either be a local path, or the appropriate key for a genome available in [iGenomes config file](../conf/igenomes.config). Must have the extension ".fasta", ".fasta.gz", ".fa" or ".fa.gz". | | `gtf` | Annotation gtf file for transcript discovery and quantification and RNA modification detection. This can either be blank or a local path. Must have the extension ".gtf". | -### Skip basecalling/demultiplexing +### Skip demultiplexing -As shown in the examples below, the accepted format of the file is slightly different if you would like to run the pipeline with or without basecalling/demultiplexing. +As shown in the examples below, the accepted format of the file is slightly different if you would like to run the pipeline with or without demultiplexing. -#### With basecalling and demultiplexing +#### With demultiplexing ##### Example `samplesheet.csv` for barcoded fast5 inputs @@ -35,20 +35,7 @@ WT_LOCAL,2,5,,/path/to/local/genome.fa,/path/to/local/transcriptome.gtf WT_UNKNOWN,3,6,,, ``` -##### Example command for barcoded fast5 inputs - -```bash -nextflow run nf-core/nanoseq \ - --input samplesheet.csv \ - --protocol cDNA \ - --input_path ./fast5/ \ - --flowcell FLO-MIN106 \ - --kit SQK-DCS109 \ - --barcode_kit EXP-NBD103 \ - -profile -``` - -#### With basecalling but not demultiplexing +#### With no demultiplexing ##### Example `samplesheet.csv` for non-barcoded fast5 inputs @@ -65,14 +52,11 @@ SAMPLE,1,1,/path/to/local/genome.fa,, nextflow run nf-core/nanoseq \ --input samplesheet.csv \ --protocol cDNA \ - --input_path ./fast5/ \ - --flowcell FLO-MIN106 \ - --kit SQK-DCS108 \ --skip_demultiplexing \ -profile ``` -#### With demultiplexing but not basecalling +#### With demultiplexing ##### Example `samplesheet.csv` for non-demultiplexed fastq inputs @@ -94,12 +78,11 @@ nextflow run nf-core/nanoseq \ --protocol DNA \ --input_path ./undemultiplexed.fastq.gz \ --barcode_kit 'NBD103/NBD104' \ - --skip_basecalling \ --skip_quantification \ -profile ``` -#### Without both basecalling and demultiplexing +#### Without demultiplexing ##### Example `samplesheet.csv` for demultiplexed fastq inputs @@ -117,12 +100,11 @@ KO,2,,SAM101A4.fastq.gz,hg19, nextflow run nf-core/nanoseq \ --input samplesheet.csv \ --protocol cDNA \ - --skip_basecalling \ --skip_demultiplexing \ -profile ``` -##### Without basecalling, demultiplexing, and alignment +##### Without demultiplexing and alignment ##### Example `samplesheet.csv` for BAM inputs @@ -140,7 +122,6 @@ KO,2,,SAM101A4.bam,hg19, nextflow run nf-core/nanoseq \ --input samplesheet.csv \ --protocol cDNA \ - --skip_basecalling \ --skip_demultiplexing \ --skip_alignment \ -profile @@ -178,7 +159,6 @@ KO,2,,/full/path/to/SAM101A4/,hg19.fasta,hg19.gtf nextflow run nf-core/nanoseq \ --input samplesheet.csv \ --protocol directRNA \ - --skip_basecalling \ --skip_demultiplexing \ -profile ``` @@ -191,9 +171,6 @@ The typical command for running the pipeline is as follows: nextflow run nf-core/nanoseq \ --input samplesheet.csv \ --protocol DNA \ - --input_path ./fast5/ \ - --flowcell FLO-MIN106 \ - --kit SQK-LSK109 \ --barcode_kit SQK-PBK004 \ -profile docker ``` From ca04ff4d349480caa94cef8f9d09640c2353b644 Mon Sep 17 00:00:00 2001 From: christopher-hakkaart Date: Tue, 21 Feb 2023 09:47:28 +0100 Subject: [PATCH 37/56] update schema to remove references to basecalling --- nextflow_schema.json | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 20c4a27c..b2db08a4 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,7 +10,10 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": ["input", "protocol"], + "required": [ + "input", + "protocol" + ], "properties": { "input": { "type": "string", @@ -74,17 +77,17 @@ "barcode_both_ends": { "type": "boolean", "fa_icon": "fas fa-barcode", - "description": "Require barcode on both ends for Guppy basecaller." + "description": "Require barcode on both ends for basecaller." }, "trim_barcodes": { "type": "boolean", "fa_icon": "fas fa-barcode", - "description": "Whether to trim the barcodes from the output sequences in the FastQ files from Guppy basecaller." + "description": "Trim barcodes from the output sequences in the FastQ files from basecaller." }, "gpu_device": { "type": "string", "default": "auto", - "description": "Basecalling device specified to Guppy in GPU mode using '--device'.", + "description": "Device specified in GPU mode using '--device'.", "fa_icon": "fas fa-fish" }, "gpu_cluster_options": { @@ -105,7 +108,7 @@ }, "skip_demultiplexing": { "type": "boolean", - "description": "Skip demultiplexing with Guppy/qcat.", + "description": "Skip demultiplexing with qcat.", "fa_icon": "fas fa-fast-forward" }, "run_nanolyse": { From f7b780ab56b8d0fca62292872d467832c920cdc7 Mon Sep 17 00:00:00 2001 From: christopher-hakkaart Date: Tue, 21 Feb 2023 10:40:23 +0100 Subject: [PATCH 38/56] update subway and edit nanoplot --- README.md | 2 +- docs/images/nanoseq_subwaymap_v3.0.png | Bin 146739 -> 0 bytes docs/images/nanoseq_subwaymap_v3.1.png | Bin 0 -> 139241 bytes ...ap_v3.0.svg => nanoseq_subwaymap_v3.1.svg} | 250 ++++++------------ modules.json | 4 +- modules/nf-core/nanoplot/main.nf | 37 +++ modules/nf-core/nanoplot/meta.yml | 59 +++++ modules/nf-core/pycoqc/main.nf | 35 --- modules/nf-core/pycoqc/meta.yml | 48 ---- subworkflows/local/qcfastq_nanoplot_fastqc.nf | 2 +- 10 files changed, 177 insertions(+), 260 deletions(-) delete mode 100644 docs/images/nanoseq_subwaymap_v3.0.png create mode 100644 docs/images/nanoseq_subwaymap_v3.1.png rename docs/images/{nanoseq_subwaymap_v3.0.svg => nanoseq_subwaymap_v3.1.svg} (83%) create mode 100644 modules/nf-core/nanoplot/main.nf create mode 100644 modules/nf-core/nanoplot/meta.yml delete mode 100644 modules/nf-core/pycoqc/main.nf delete mode 100644 modules/nf-core/pycoqc/meta.yml diff --git a/README.md b/README.md index eaf0bc09..dff7da56 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ On release, automated continuous integration tests run the pipeline on a [full-s A graphical overview of suggested routes through the pipeline depending on the desired output can be seen below.

    - nf-core/nanoseq metro map ## Quick Start diff --git a/docs/images/nanoseq_subwaymap_v3.0.png b/docs/images/nanoseq_subwaymap_v3.0.png deleted file mode 100644 index 9bd085fae6246479992c0da3388ae56bd2c1ca23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 146739 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

  • $_$FnRLr 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 z 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
    ;}B-WB%SrQ?iJ<$uW$LX5wT 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%0A8)fak1DT8iz*A$avx1 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 b01Wm6wr*`}=0ceP00000NkvXXu0mjf)U^!L diff --git a/docs/images/nanoseq_subwaymap_v3.1.png b/docs/images/nanoseq_subwaymap_v3.1.png new file mode 100644 index 0000000000000000000000000000000000000000..4b293a706bc2efbfba5c633df9c5e720b3935c18 GIT binary patch literal 139241 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�P-wCjsP|We&Y&FcwP>2zxVwmU)E*I)5dfQBpq`5 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 literal 0 HcmV?d00001 diff --git a/docs/images/nanoseq_subwaymap_v3.0.svg b/docs/images/nanoseq_subwaymap_v3.1.svg similarity index 83% rename from docs/images/nanoseq_subwaymap_v3.0.svg rename to docs/images/nanoseq_subwaymap_v3.1.svg index 3bc2290f..a7ae4518 100644 --- a/docs/images/nanoseq_subwaymap_v3.0.svg +++ b/docs/images/nanoseq_subwaymap_v3.1.svg @@ -7,7 +7,7 @@ id="svg851" version="1.1" sodipodi:docname="nanoseq_subwaymap_v3.0.svg" - inkscape:version="1.1.1 (c3084ef, 2021-09-22)" + inkscape:version="1.2 (dc2aeda, 2022-05-15)" inkscape:export-filename="/Users/chrishakkaart/Desktop/nanoseq_subwaymap_v3.0.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96" @@ -27,20 +27,27 @@ inkscape:pagecheckerboard="0" inkscape:document-units="mm" showgrid="false" - inkscape:zoom="1.1487264" - inkscape:cx="1382.8358" - inkscape:cy="760.8426" - inkscape:window-width="1440" - inkscape:window-height="784" + inkscape:zoom="0.65946895" + inkscape:cx="592.14312" + inkscape:cy="474.62432" + inkscape:window-width="1920" + inkscape:window-height="1080" inkscape:window-x="0" - inkscape:window-y="23" + inkscape:window-y="0" inkscape:window-maximized="0" inkscape:current-layer="g859" - inkscape:lockguides="false" />image/svg+xmlguppynanolyseONT fast5 apipycoqcnanoplotqcatqcatsamtoolsfastqNanopore basecalling, demultiplexing, QC, alignment, and downstream analysisfast5Nanopore demultiplexing, QC, alignment, and downstream analysis + y="273.8718" /> diff --git a/modules.json b/modules.json index 32aeeddd..cee4bd83 100644 --- a/modules.json +++ b/modules.json @@ -30,9 +30,9 @@ "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", "installed_by": ["modules"] }, - "pycoqc": { + "nanoplot": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "git_sha": "3822e04e49b6d89b7092feb3480d744cb5d9986b", "installed_by": ["modules"] }, "samtools/faidx": { diff --git a/modules/nf-core/nanoplot/main.nf b/modules/nf-core/nanoplot/main.nf new file mode 100644 index 00000000..ca0d8454 --- /dev/null +++ b/modules/nf-core/nanoplot/main.nf @@ -0,0 +1,37 @@ +process NANOPLOT { + tag "$meta.id" + label 'process_low' + + conda "bioconda::nanoplot=1.41.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/nanoplot:1.41.0--pyhdfd78af_0' : + 'quay.io/biocontainers/nanoplot:1.41.0--pyhdfd78af_0' }" + + input: + tuple val(meta), path(ontfile) + + output: + tuple val(meta), path("*.html") , emit: html + tuple val(meta), path("*.png") , optional: true, emit: png + tuple val(meta), path("*.txt") , emit: txt + tuple val(meta), path("*.log") , emit: log + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def input_file = ("$ontfile".endsWith(".fastq.gz")) ? "--fastq ${ontfile}" : + ("$ontfile".endsWith(".txt")) ? "--summary ${ontfile}" : '' + """ + NanoPlot \\ + $args \\ + -t $task.cpus \\ + $input_file + cat <<-END_VERSIONS > versions.yml + "${task.process}": + nanoplot: \$(echo \$(NanoPlot --version 2>&1) | sed 's/^.*NanoPlot //; s/ .*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/nanoplot/meta.yml b/modules/nf-core/nanoplot/meta.yml new file mode 100644 index 00000000..28c8c2d3 --- /dev/null +++ b/modules/nf-core/nanoplot/meta.yml @@ -0,0 +1,59 @@ +name: nanoplot +description: Run NanoPlot on nanopore-sequenced reads +keywords: + - quality control + - qc + - fastq + - sequencing summary + - nanopore +tools: + - nanoplot: + description: | + NanoPlot is a tool for ploting long-read sequencing data and + alignment. + homepage: http://nanoplot.bioinf.be + documentation: https://github.com/wdecoster/NanoPlot + licence: ["GPL-3.0-or-later"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fastq: + type: file + description: | + List of input basecalled-FastQ files. + - summary_txt: + type: file + description: | + List of sequencing_summary.txt files from running basecalling. +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - html: + type: file + description: NanoPlot report + pattern: "*{.html}" + - png: + type: file + description: Plots generated by NanoPlot + pattern: "*{.png}" + - txt: + type: file + description: Stats from NanoPlot + pattern: "*{.txt}" + - log: + type: file + description: log file of NanoPlot run + pattern: "*{.log}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@yuukiiwa" diff --git a/modules/nf-core/pycoqc/main.nf b/modules/nf-core/pycoqc/main.nf deleted file mode 100644 index 62f3215b..00000000 --- a/modules/nf-core/pycoqc/main.nf +++ /dev/null @@ -1,35 +0,0 @@ -process PYCOQC { - tag "$summary" - label 'process_medium' - - conda "bioconda::pycoqc=2.5.2" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pycoqc:2.5.2--py_0' : - 'quay.io/biocontainers/pycoqc:2.5.2--py_0' }" - - input: - path summary - - output: - path "*.html" , emit: html - path "*.json" , emit: json - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - """ - pycoQC \\ - $args \\ - -f $summary \\ - -o pycoqc.html \\ - -j pycoqc.json - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - pycoqc: \$(pycoQC --version 2>&1 | sed 's/^.*pycoQC v//; s/ .*\$//') - END_VERSIONS - """ -} diff --git a/modules/nf-core/pycoqc/meta.yml b/modules/nf-core/pycoqc/meta.yml deleted file mode 100644 index 83748855..00000000 --- a/modules/nf-core/pycoqc/meta.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: pycoqc -description: write your description here -keywords: - - qc - - quality control - - sequencing - - nanopore -tools: - - pycoqc: - description: PycoQC computes metrics and generates interactive QC plots for Oxford Nanopore technologies sequencing data - homepage: https://github.com/tleonardi/pycoQC - documentation: https://tleonardi.github.io/pycoQC/ - tool_dev_url: https://github.com/tleonardi/pycoQC - doi: "10.21105/joss.01236" - licence: ["GNU General Public v3 (GPL v3)"] - -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - summary: - type: file - description: sequencing summary file - pattern: "*.{txt}" - -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - html: - type: file - description: Results in HTML format - - json: - type: file - description: Results in JSON format - pattern: "*.{json}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - -authors: - - "@joseespinosa" - - "@drpatelh" diff --git a/subworkflows/local/qcfastq_nanoplot_fastqc.nf b/subworkflows/local/qcfastq_nanoplot_fastqc.nf index 3c30e7c6..d5ed5c90 100644 --- a/subworkflows/local/qcfastq_nanoplot_fastqc.nf +++ b/subworkflows/local/qcfastq_nanoplot_fastqc.nf @@ -2,7 +2,7 @@ * FastQ QC with NanoPlot and fastqc */ -include { NANOPLOT } from '../../modules/local/nanoplot' +include { NANOPLOT } from '../../modules/nf-core/nanoplot/main' include { FASTQC } from '../../modules/nf-core/fastqc/main' workflow QCFASTQ_NANOPLOT_FASTQC { From 8addc22b00ec96448b9cc015c86ce538b0531344 Mon Sep 17 00:00:00 2001 From: Chris Hakkaart Date: Tue, 21 Feb 2023 13:37:40 +0000 Subject: [PATCH 39/56] Move nanoplot to nf-core, remove references to removed tools --- CITATIONS.md | 6 --- README.md | 19 ++++----- docs/usage.md | 37 +--------------- modules/local/nanoplot.nf | 42 ------------------- nextflow_schema.json | 5 +-- subworkflows/local/qcfastq_nanoplot_fastqc.nf | 2 +- 6 files changed, 10 insertions(+), 101 deletions(-) delete mode 100644 modules/local/nanoplot.nf diff --git a/CITATIONS.md b/CITATIONS.md index 38031c4c..78902f81 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -30,8 +30,6 @@ > Sović I, Šikić M, Wilm A, Fenlon SN, Chen S, Nagarajan N. Fast and sensitive mapping of nanopore sequencing reads with GraphMap. Nat Commun. 2016 Apr 15;7:11307. doi: 10.1038/ncomms11307. PMID: 27079541; PMCID: PMC4835549. -- [Guppy](https://nanoporetech.com/nanopore-sequencing-data-analysis) - - [JAFFAL](https://doi.org/10.1186/s13059-021-02588-5) > Davidson NM, Chen Y, Sadras T, Ryland GL, Blombery P, Ekert PG, Göke J, Oshlack A. JAFFAL: detecting fusion genes with long-read transcriptome sequencing. Genome Biol. 2022 Jan 6;23(1):10. doi: 10.1186/s13059-021-02588-5. PMID: 34991664; PMCID: PMC8739696. @@ -62,10 +60,6 @@ > De Coster W, D'Hert S, Schultz DT, Cruts M, Van Broeckhoven C. NanoPack: visualizing and processing long-read sequencing data. Bioinformatics. 2018 Aug 1;34(15):2666-2669. doi: 10.1093/bioinformatics/bty149. PubMed PMID: 29547981; PubMed Central PMCID: PMC6061794. -- [pycoQC](https://doi.org/10.21105/joss.01236) - - > Leger A, Leonardi T, (2019). pycoQC, interactive quality control for Oxford Nanopore Sequencing. Journal of Open Source Software, 4(34), 1236, https://doi.org/10.21105/joss.01236 - - [qcat](https://github.com/nanoporetech/qcat) - [SAMtools](https://www.ncbi.nlm.nih.gov/pubmed/19505943/) diff --git a/README.md b/README.md index dff7da56..7cff5363 100644 --- a/README.md +++ b/README.md @@ -23,26 +23,24 @@ On release, automated continuous integration tests run the pipeline on a [full-s ## Pipeline Summary -1. Basecalling and/or demultiplexing ([`Guppy`](https://nanoporetech.com/nanopore-sequencing-data-analysis), [`demux_fast5`](https://github.com/nanoporetech/ont_fast5_api#demux_fast5), or [`qcat`](https://github.com/nanoporetech/qcat); _optional_) -2. Sequencing QC ([`pycoQC`](https://github.com/a-slide/pycoQC), [`NanoPlot`](https://github.com/wdecoster/NanoPlot)) -3. Raw read DNA cleaning ([NanoLyse](https://github.com/wdecoster/nanolyse); _optional_) -4. Raw read QC ([`NanoPlot`](https://github.com/wdecoster/NanoPlot), [`FastQC`](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) -5. Alignment ([`GraphMap2`](https://github.com/lbcb-sci/graphmap2) or [`minimap2`](https://github.com/lh3/minimap2)) +1. Raw read cleaning ([NanoLyse](https://github.com/wdecoster/nanolyse); _optional_) +2. Raw read QC ([`NanoPlot`](https://github.com/wdecoster/NanoPlot), [`FastQC`](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) +3. Alignment ([`GraphMap2`](https://github.com/lbcb-sci/graphmap2) or [`minimap2`](https://github.com/lh3/minimap2)) - Both aligners are capable of performing unspliced and spliced alignment. Sensible defaults will be applied automatically based on a combination of the input data and user-specified parameters - Each sample can be mapped to its own reference genome if multiplexed in this way - Convert SAM to co-ordinate sorted BAM and obtain mapping metrics ([`samtools`](http://www.htslib.org/doc/samtools.html)) -6. Create bigWig ([`BEDTools`](https://github.com/arq5x/bedtools2/), [`bedGraphToBigWig`](http://hgdownload.soe.ucsc.edu/admin/exe/)) and bigBed ([`BEDTools`](https://github.com/arq5x/bedtools2/), [`bedToBigBed`](http://hgdownload.soe.ucsc.edu/admin/exe/)) coverage tracks for visualisation -7. DNA specific downstream analysis: +4. Create bigWig ([`BEDTools`](https://github.com/arq5x/bedtools2/), [`bedGraphToBigWig`](http://hgdownload.soe.ucsc.edu/admin/exe/)) and bigBed ([`BEDTools`](https://github.com/arq5x/bedtools2/), [`bedToBigBed`](http://hgdownload.soe.ucsc.edu/admin/exe/)) coverage tracks for visualisation +5. DNA specific downstream analysis: - Short variant calling ([`medaka`](https://github.com/nanoporetech/medaka), [`deepvariant`](https://github.com/google/deepvariant), or [`pepper_margin_deepvariant`](https://github.com/kishwarshafin/pepper)) - Structural variant calling ([`sniffles`](https://github.com/fritzsedlazeck/Sniffles) or [`cutesv`](https://github.com/tjiangHIT/cuteSV)) -8. RNA specific downstream analysis: +6. RNA specific downstream analysis: - Transcript reconstruction and quantification ([`bambu`](https://bioconductor.org/packages/release/bioc/html/bambu.html) or [`StringTie2`](https://ccb.jhu.edu/software/stringtie/)) - bambu performs both transcript reconstruction and quantification - When StringTie2 is chosen, each sample can be processed individually and combined. After which, [`featureCounts`](http://bioinf.wehi.edu.au/featureCounts/) will be used for both gene and transcript quantification. - Differential expression analysis ([`DESeq2`](https://bioconductor.org/packages/release/bioc/html/DESeq2.html) and/or [`DEXSeq`](https://bioconductor.org/packages/release/bioc/html/DEXSeq.html)) - RNA modification detection ([`xpore`](https://github.com/GoekeLab/xpore) and/or [`m6anet`](https://github.com/GoekeLab/m6anet)) - RNA fusion detection ([`JAFFAL`](https://github.com/Oshlack/JAFFA)) -9. Present QC for raw read and alignment results ([`MultiQC`](https://multiqc.info/docs/)) +7. Present QC for raw read and alignment results ([`MultiQC`](https://multiqc.info/docs/)) ### Functionality Overview @@ -81,9 +79,6 @@ The nf-core/nanoseq pipeline comes with documentation about the pipeline [usage] nextflow run nf-core/nanoseq \ --input samplesheet.csv \ --protocol DNA \ - --input_path ./fast5/ \ - --flowcell FLO-MIN106 \ - --kit SQK-LSK109 \ --barcode_kit SQK-PBK004 \ -profile ``` diff --git a/docs/usage.md b/docs/usage.md index 22213cbb..97dd0a5a 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -19,42 +19,7 @@ You will need to create a file with information about the samples in your experi ### Skip demultiplexing -As shown in the examples below, the accepted format of the file is slightly different if you would like to run the pipeline with or without demultiplexing. - -#### With demultiplexing - -##### Example `samplesheet.csv` for barcoded fast5 inputs - -```bash -group,replicate,barcode,input_file,fasta,gtf -WT_MOUSE,1,1,,mm10, -WT_HUMAN,1,2,,hg19, -WT_POMBE,1,3,,/path/to/local/genome.fa, -WT_DENOVO,1,4,,,/path/to/local/transcriptome.fa -WT_LOCAL,2,5,,/path/to/local/genome.fa,/path/to/local/transcriptome.gtf -WT_UNKNOWN,3,6,,, -``` - -#### With no demultiplexing - -##### Example `samplesheet.csv` for non-barcoded fast5 inputs - -```bash -group,replicate,barcode,input_file,fasta,gtf -SAMPLE,1,1,/path/to/local/genome.fa,, -``` - -> Only a single sample can be specified if you would like to skip demultiplexing - -##### Example command for non-barcoded fast5 inputs - -```bash -nextflow run nf-core/nanoseq \ - --input samplesheet.csv \ - --protocol cDNA \ - --skip_demultiplexing \ - -profile -``` +As shown in the examples below, the accepted samplesheet format is different depending on if you would like to run the pipeline with or without demultiplexing. #### With demultiplexing diff --git a/modules/local/nanoplot.nf b/modules/local/nanoplot.nf deleted file mode 100644 index 78690a20..00000000 --- a/modules/local/nanoplot.nf +++ /dev/null @@ -1,42 +0,0 @@ -process NANOPLOT { - tag "$meta.id" - label 'process_low' - - conda "bioconda::nanoplot=1.38.0" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/nanoplot:1.38.0--pyhdfd78af_0' : - 'quay.io/biocontainers/nanoplot:1.38.0--pyhdfd78af_0' }" - - input: - tuple val(meta), path(ontfile) - - output: - tuple val(meta), path("$output_html"), emit: html - tuple val(meta), path("$output_txt") , emit: txt - tuple val(meta), path("$output_log") , emit: log - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def input_file = ("$ontfile".endsWith(".fastq.gz")) ? "--fastq ${ontfile}" : - ("$ontfile".endsWith(".txt")) ? "--summary ${ontfile}" : '' - def output_dir = ("$ontfile".endsWith(".fastq.gz")) ? "fastq/${meta.id}" : - ("$ontfile".endsWith(".txt")) ? "summary" : '' - output_html = output_dir+"/*.html" - output_png = output_dir+"/*.png" - output_txt = output_dir+"/*.txt" - output_log = output_dir+"/*.log" - """ - NanoPlot \\ - -t $task.cpus \\ - $input_file \\ - -o $output_dir - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - nanoplot: \$(echo \$(NanoPlot --version 2>&1) | sed 's/^.*NanoPlot //; s/ .*\$//') - END_VERSIONS - """ -} diff --git a/nextflow_schema.json b/nextflow_schema.json index b2db08a4..5e716045 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,10 +10,7 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": [ - "input", - "protocol" - ], + "required": ["input", "protocol"], "properties": { "input": { "type": "string", diff --git a/subworkflows/local/qcfastq_nanoplot_fastqc.nf b/subworkflows/local/qcfastq_nanoplot_fastqc.nf index d5ed5c90..b2c0f54d 100644 --- a/subworkflows/local/qcfastq_nanoplot_fastqc.nf +++ b/subworkflows/local/qcfastq_nanoplot_fastqc.nf @@ -2,7 +2,7 @@ * FastQ QC with NanoPlot and fastqc */ -include { NANOPLOT } from '../../modules/nf-core/nanoplot/main' +include { NANOPLOT } from '../../modules/nf-core/nanoplot/main' include { FASTQC } from '../../modules/nf-core/fastqc/main' workflow QCFASTQ_NANOPLOT_FASTQC { From 2b824f5795f26e89f7940ce3a9d4b7d5645064f9 Mon Sep 17 00:00:00 2001 From: "Maxime U. Garcia" Date: Fri, 3 Mar 2023 15:37:52 +0100 Subject: [PATCH 40/56] fix custom config for multiqc Not sure this actually ever worked. Thanks to @FranBonath for spotting the issue --- modules/local/multiqc.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/multiqc.nf b/modules/local/multiqc.nf index ef2fb27d..c5ccad28 100644 --- a/modules/local/multiqc.nf +++ b/modules/local/multiqc.nf @@ -27,7 +27,7 @@ process MULTIQC { script: def args = task.ext.args ?: '' - def custom_config = params.multiqc_config ? "--config $multiqc_custom_config" : '' + def custom_config = params.multiqc_config ? "--config $ch_multiqc_custom_config" : '' """ multiqc \\ -f \\ From ae9789a756ac1804a354285a2f446343ae7779ba Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Tue, 7 Mar 2023 13:26:13 +0800 Subject: [PATCH 41/56] Update bambu.nf --- modules/local/bambu.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/bambu.nf b/modules/local/bambu.nf index 23bb67c2..95d46b9a 100644 --- a/modules/local/bambu.nf +++ b/modules/local/bambu.nf @@ -3,8 +3,8 @@ process BAMBU { conda "conda-forge::r-base=4.0.3 bioconda::bioconductor-bambu=3.0.6 bioconda::bioconductor-bsgenome=1.66.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/bioconductor-bambu:3.0.6--r42hc247a5b_0' : - 'quay.io/biocontainers/bioconductor-bambu:3.0.6--r42hc247a5b_0' }" + 'https://depot.galaxyproject.org/singularity/bioconductor-bambu:3.0.8--r42hc247a5b_0' : + 'quay.io/biocontainers/bioconductor-bambu:3.0.8--r42hc247a5b_0' }" input: tuple path(fasta), path(gtf) From d1666b5f483620016ebbeb3602eb4d5e645ec129 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Wed, 8 Mar 2023 13:49:54 +0800 Subject: [PATCH 42/56] Update CITATIONS.md --- CITATIONS.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CITATIONS.md b/CITATIONS.md index 78902f81..45ce499d 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -4,12 +4,20 @@ > Ewels PA, Peltzer A, Fillinger S, Patel H, Alneberg J, Wilm A, Garcia MU, Di Tommaso P, Nahnsen S. The nf-core framework for community-curated bioinformatics pipelines. Nat Biotechnol. 2020 Mar;38(3):276-278. doi: 10.1038/s41587-020-0439-x. PubMed PMID: 32055031. +## [SGNEx](https://www.biorxiv.org/content/10.1101/2021.04.21.440736v1.abstract) + +>Chen, Y., Davidson, N. M., Wan, Y. K., Patel, H., Yao, F., Low, H. M., ... & SG-NEx consortium. (2021). A systematic benchmark of Nanopore long read RNA sequencing for transcript level analysis in human cell lines. BioRxiv, 2021-04. + ## [Nextflow](https://www.ncbi.nlm.nih.gov/pubmed/28398311/) > Di Tommaso P, Chatzou M, Floden EW, Barja PP, Palumbo E, Notredame C. Nextflow enables reproducible computational workflows. Nat Biotechnol. 2017 Apr 11;35(4):316-319. doi: 10.1038/nbt.3820. PubMed PMID: 28398311. ## Pipeline tools +- [bambu](https://www.biorxiv.org/content/10.1101/2022.11.14.516358v2.abstract) + + > Chen, Y., Sim, A. D., Wan, Y. K., Yeo, K., Lee, J. J. X., Ling, M. H., ... & Göke, J. (2022). Context-aware transcript quantification from long read RNA-seq data with Bambu. bioRxiv, 2022-11. + - [BEDTools](https://www.ncbi.nlm.nih.gov/pubmed/20110278/) > Quinlan AR, Hall IM. BEDTools: a flexible suite of utilities for comparing genomic features. Bioinformatics. 2010 Mar 15;26(6):841-2. doi: 10.1093/bioinformatics/btq033. Epub 2010 Jan 28. PubMed PMID: 20110278; PubMed Central PMCID: PMC2832824. @@ -34,9 +42,9 @@ > Davidson NM, Chen Y, Sadras T, Ryland GL, Blombery P, Ekert PG, Göke J, Oshlack A. JAFFAL: detecting fusion genes with long-read transcriptome sequencing. Genome Biol. 2022 Jan 6;23(1):10. doi: 10.1186/s13059-021-02588-5. PMID: 34991664; PMCID: PMC8739696. -- [m6anet](https://www.biorxiv.org/content/10.1101/2021.09.20.461055v1) +- [m6anet](https://pubmed.ncbi.nlm.nih.gov/36357692/) - > Hendra C, et al., Detection of m6A from direct RNA sequencing using a Multiple Instance Learning framework. bioRXiv (2021) + > Hendra, C., Pratanwanich, P. N., Wan, Y. K., Goh, W. S., Thiery, A., & Göke, J. (2022). Detection of m6A from direct RNA sequencing using a multiple instance learning framework. Nature Methods, 1-9. PMID: 36357692; PMCID: PMC9718678. - [PEPPER-Margin-DeepVariant](https://pubmed.ncbi.nlm.nih.gov/34725481/) From 082014304e26cbc5a535873c0f2f618c83cfe775 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Wed, 8 Mar 2023 13:52:17 +0800 Subject: [PATCH 43/56] Update CITATIONS.md --- CITATIONS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CITATIONS.md b/CITATIONS.md index 45ce499d..aa9274ad 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -6,7 +6,7 @@ ## [SGNEx](https://www.biorxiv.org/content/10.1101/2021.04.21.440736v1.abstract) ->Chen, Y., Davidson, N. M., Wan, Y. K., Patel, H., Yao, F., Low, H. M., ... & SG-NEx consortium. (2021). A systematic benchmark of Nanopore long read RNA sequencing for transcript level analysis in human cell lines. BioRxiv, 2021-04. +> Chen, Y., Davidson, N. M., Wan, Y. K., Patel, H., Yao, F., Low, H. M., ... & SG-NEx consortium. (2021). A systematic benchmark of Nanopore long read RNA sequencing for transcript level analysis in human cell lines. BioRxiv, 2021-04. ## [Nextflow](https://www.ncbi.nlm.nih.gov/pubmed/28398311/) From 5f4711e4d3bbb6ed524360dddfa88c2a36ddaea3 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Wed, 8 Mar 2023 13:55:57 +0800 Subject: [PATCH 44/56] Add back demultiplexing --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7cff5363..800f2e93 100644 --- a/README.md +++ b/README.md @@ -23,24 +23,25 @@ On release, automated continuous integration tests run the pipeline on a [full-s ## Pipeline Summary -1. Raw read cleaning ([NanoLyse](https://github.com/wdecoster/nanolyse); _optional_) -2. Raw read QC ([`NanoPlot`](https://github.com/wdecoster/NanoPlot), [`FastQC`](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) -3. Alignment ([`GraphMap2`](https://github.com/lbcb-sci/graphmap2) or [`minimap2`](https://github.com/lh3/minimap2)) +1. Demultiplexing ([`qcat`](https://github.com/nanoporetech/qcat); _optional_) +2. Raw read cleaning ([NanoLyse](https://github.com/wdecoster/nanolyse); _optional_) +3. Raw read QC ([`NanoPlot`](https://github.com/wdecoster/NanoPlot), [`FastQC`](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) +4. Alignment ([`GraphMap2`](https://github.com/lbcb-sci/graphmap2) or [`minimap2`](https://github.com/lh3/minimap2)) - Both aligners are capable of performing unspliced and spliced alignment. Sensible defaults will be applied automatically based on a combination of the input data and user-specified parameters - Each sample can be mapped to its own reference genome if multiplexed in this way - Convert SAM to co-ordinate sorted BAM and obtain mapping metrics ([`samtools`](http://www.htslib.org/doc/samtools.html)) -4. Create bigWig ([`BEDTools`](https://github.com/arq5x/bedtools2/), [`bedGraphToBigWig`](http://hgdownload.soe.ucsc.edu/admin/exe/)) and bigBed ([`BEDTools`](https://github.com/arq5x/bedtools2/), [`bedToBigBed`](http://hgdownload.soe.ucsc.edu/admin/exe/)) coverage tracks for visualisation -5. DNA specific downstream analysis: +5. Create bigWig ([`BEDTools`](https://github.com/arq5x/bedtools2/), [`bedGraphToBigWig`](http://hgdownload.soe.ucsc.edu/admin/exe/)) and bigBed ([`BEDTools`](https://github.com/arq5x/bedtools2/), [`bedToBigBed`](http://hgdownload.soe.ucsc.edu/admin/exe/)) coverage tracks for visualisation +6. DNA specific downstream analysis: - Short variant calling ([`medaka`](https://github.com/nanoporetech/medaka), [`deepvariant`](https://github.com/google/deepvariant), or [`pepper_margin_deepvariant`](https://github.com/kishwarshafin/pepper)) - Structural variant calling ([`sniffles`](https://github.com/fritzsedlazeck/Sniffles) or [`cutesv`](https://github.com/tjiangHIT/cuteSV)) -6. RNA specific downstream analysis: +7. RNA specific downstream analysis: - Transcript reconstruction and quantification ([`bambu`](https://bioconductor.org/packages/release/bioc/html/bambu.html) or [`StringTie2`](https://ccb.jhu.edu/software/stringtie/)) - bambu performs both transcript reconstruction and quantification - When StringTie2 is chosen, each sample can be processed individually and combined. After which, [`featureCounts`](http://bioinf.wehi.edu.au/featureCounts/) will be used for both gene and transcript quantification. - Differential expression analysis ([`DESeq2`](https://bioconductor.org/packages/release/bioc/html/DESeq2.html) and/or [`DEXSeq`](https://bioconductor.org/packages/release/bioc/html/DEXSeq.html)) - RNA modification detection ([`xpore`](https://github.com/GoekeLab/xpore) and/or [`m6anet`](https://github.com/GoekeLab/m6anet)) - RNA fusion detection ([`JAFFAL`](https://github.com/Oshlack/JAFFA)) -7. Present QC for raw read and alignment results ([`MultiQC`](https://multiqc.info/docs/)) +8. Present QC for raw read and alignment results ([`MultiQC`](https://multiqc.info/docs/)) ### Functionality Overview From e8ad21be1c597c126fb75b7432dc7aa532b67a74 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Thu, 9 Mar 2023 16:02:33 +0800 Subject: [PATCH 45/56] update nanoseq version --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index 0341d8ed..11963c22 100644 --- a/nextflow.config +++ b/nextflow.config @@ -244,7 +244,7 @@ manifest { description = """A pipeline to demultiplex, QC and map Nanopore data""" mainScript = 'main.nf' nextflowVersion = '!>=22.10.1' - version = '3.0.0' + version = '3.1.0' doi = '' } From aa0f91f6de8a09aac3c87128f45c86721faebff3 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Thu, 9 Mar 2023 16:11:37 +0800 Subject: [PATCH 46/56] Update CHANGELOG.md --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index be995280..2e7eef45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,33 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.1.0] - 2023-03-10 + +### Major enhancements + +- Removed the `guppy` basecaller as the distribution of `guppy` via a docker container is a breach to EULA +- Bump minimum Nextflow version from 21.10.3 -> 22.10.1 +- Update pipeline template to nf-core/tools `2.7.2` +- Update `bambu` version from `2.0.0` to `3.0.8` + +### Parameters + +- Removed `--flowcell` +- Removed `--kit` +- Removed `--guppy_config` +- Removed `--guppy_model` +- Removed `--guppy_gpu` +- Removed `--guppy_gpu_runners` +- Removed `--guppy_cpu_threads` +- Removed `--output_demultiplex_fast5` +- Removed `--skip_basecalling` + +### Software dependencies + +| Dependency | Old version | New version | +| ------------------------------- | ----------- | ----------- | +| `bioconductor-bambu` | 2.0.0 | 3.0.8 | + ## [3.0.0] - 2022-06-21 ### Major enhancements From 2fac88e97b6d5d04f54bf785ecd63d76e2187ef5 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Thu, 9 Mar 2023 16:27:04 +0800 Subject: [PATCH 47/56] Update test.config --- conf/test.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/test.config b/conf/test.config index 1e7d8f8c..83c5c1bb 100644 --- a/conf/test.config +++ b/conf/test.config @@ -11,7 +11,7 @@ params { config_profile_name = 'Test profile' config_profile_description = 'Minimal test dataset to check pipeline function' - // Limit resources so that this can run on Travis + // Limit resources max_cpus = 2 max_memory = 6.GB max_time = 12.h From 6bb6694cca10ba2d19aaac3a3364297e97a44e21 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Thu, 9 Mar 2023 16:30:54 +0800 Subject: [PATCH 48/56] Update CHANGELOG.md --- CHANGELOG.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e7eef45..ae73a54c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,15 +14,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Parameters -- Removed `--flowcell` -- Removed `--kit` -- Removed `--guppy_config` -- Removed `--guppy_model` -- Removed `--guppy_gpu` -- Removed `--guppy_gpu_runners` -- Removed `--guppy_cpu_threads` -- Removed `--output_demultiplex_fast5` -- Removed `--skip_basecalling` +- Removed `--flowcell` +- Removed `--kit` +- Removed `--guppy_config` +- Removed `--guppy_model` +- Removed `--guppy_gpu` +- Removed `--guppy_gpu_runners` +- Removed `--guppy_cpu_threads` +- Removed `--output_demultiplex_fast5` +- Removed `--skip_basecalling` ### Software dependencies From 8bf6db42ec99dfe18d5b18dfd0be0f2725840032 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Thu, 9 Mar 2023 17:03:48 +0800 Subject: [PATCH 49/56] Update CHANGELOG.md --- CHANGELOG.md | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae73a54c..be995280 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,33 +3,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [3.1.0] - 2023-03-10 - -### Major enhancements - -- Removed the `guppy` basecaller as the distribution of `guppy` via a docker container is a breach to EULA -- Bump minimum Nextflow version from 21.10.3 -> 22.10.1 -- Update pipeline template to nf-core/tools `2.7.2` -- Update `bambu` version from `2.0.0` to `3.0.8` - -### Parameters - -- Removed `--flowcell` -- Removed `--kit` -- Removed `--guppy_config` -- Removed `--guppy_model` -- Removed `--guppy_gpu` -- Removed `--guppy_gpu_runners` -- Removed `--guppy_cpu_threads` -- Removed `--output_demultiplex_fast5` -- Removed `--skip_basecalling` - -### Software dependencies - -| Dependency | Old version | New version | -| ------------------------------- | ----------- | ----------- | -| `bioconductor-bambu` | 2.0.0 | 3.0.8 | - ## [3.0.0] - 2022-06-21 ### Major enhancements From 8f37ff5081dfe2e3d0bf8c88b952df9efdc73d56 Mon Sep 17 00:00:00 2001 From: Daniel Schreyer <2592722S@student.gla.ac.uk> Date: Thu, 9 Mar 2023 10:11:27 +0100 Subject: [PATCH 50/56] Syntax formatting of run_deseq2.r --- bin/run_deseq2.r | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bin/run_deseq2.r b/bin/run_deseq2.r index f35904fd..7b04d9dd 100755 --- a/bin/run_deseq2.r +++ b/bin/run_deseq2.r @@ -42,17 +42,17 @@ path <-args[2] #create a dataframe for all samples if (transcriptquant == "stringtie2"){ - count.matrix <- data.frame(read.table(path,sep="\t",header=TRUE, skip = 1)) + count.matrix <- data.frame(read.table(path, sep="\t", header=TRUE, skip = 1)) count.matrix$Chr <- count.matrix$Start <- count.matrix$End <- count.matrix$Length <- count.matrix$Strand <- NULL - colnames(count.matrix)[2:length(colnames(count.matrix))] <- unlist(lapply(strsplit(colnames(count.matrix)[2:length(colnames(count.matrix))],"\\."),"[[",1)) - count.matrix <- aggregate(count.matrix[,-1],count.matrix["Geneid"],sum) - countTab <- count.matrix[,-1] - rownames(countTab) <-count.matrix[,1] + colnames(count.matrix)[2:length(colnames(count.matrix))] <- unlist(lapply(strsplit(colnames(count.matrix)[2:length(colnames(count.matrix))], "\\."), "[[", 1)) + count.matrix <- aggregate(count.matrix[, -1],count.matrix["Geneid"],sum) + countTab <- count.matrix[, -1] + rownames(countTab) <-count.matrix[, 1] } if (transcriptquant == "bambu"){ - countTab <- data.frame(read.table(path,sep="\t",header=TRUE,row.names = 1)) - colnames(countTab) <- unlist(lapply(strsplit(colnames(countTab),"\\."),"[[",1)) - countTab[,1:length(colnames(countTab))] <- sapply(countTab, as.integer) + countTab <- data.frame(read.table(path, sep="\t", header=TRUE, row.names = 1)) + colnames(countTab) <- unlist(lapply(strsplit(colnames(countTab), "\\."), "[[", 1)) + countTab[, 1:length(colnames(countTab))] <- sapply(countTab, as.integer) } @@ -66,7 +66,7 @@ sample <- colnames(countTab) group <- sub("(^[^-]+)_.*", "\\1", sample) sampInfo <- data.frame(group, row.names = sample) if (!all(rownames(sampInfo) == colnames(countTab))){ - sampInfo <- sampInfo[match(colnames(countTab), rownames(sampInfo)),] + sampInfo <- sampInfo[match(colnames(countTab), rownames(sampInfo)), ] } ################################################ From a49bd8c052192a98f6df96fd2fe364b72b74bf45 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Thu, 9 Mar 2023 17:13:37 +0800 Subject: [PATCH 51/56] Update CHANGELOG.md --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index be995280..044a0e7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,34 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.1.0] - 2023-03-10 + +### Major enhancements + +- Removed the `guppy` basecaller as distributing it via a docker image is a breach to EULA +- Bump minimum Nextflow version from 21.10.3 -> 21.10.3 +- Update pipeline template to nf-core/tools `2.7.2` +- Update `bambu` version from `1.0.2` to `2.0.0` + +### Parameters + +- Removed `--flowcell` as `nanoseq` no longer supports basecalling +- Removed `--kit` as `nanoseq` no longer supports basecalling +- Removed `--guppy_config` as `nanoseq` no longer supports basecalling +- Removed `--guppy_model` as `nanoseq` no longer supports basecalling +- Removed `--guppy_gpu` as `nanoseq` no longer supports basecalling +- Removed `--guppy_gpu_runners` as `nanoseq` no longer supports basecalling +- Removed `--guppy_cpu_threads` as `nanoseq` no longer supports basecalling +- Removed `--output_demultiplex_fast5` as `nanoseq` no longer supports basecalling +- Removed `--skip_basecalling` as `nanoseq` no longer supports basecalling +- Removed `--skip_pycoqc` as `nanoseq` no longer supports basecalling + +### Software dependencies + +| Dependency | Old version | New version | +| ------------------------------- | ----------- | ----------- | +| `bioconductor-bambu` | 2.0.0 | 3.0.8 | + ## [3.0.0] - 2022-06-21 ### Major enhancements From fb733b3b7b9a7f935ba29cb02dbfa2f87807c28c Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Thu, 9 Mar 2023 17:21:00 +0800 Subject: [PATCH 52/56] Add files via upload --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 044a0e7b..ea4a0165 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,9 +27,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Software dependencies -| Dependency | Old version | New version | -| ------------------------------- | ----------- | ----------- | -| `bioconductor-bambu` | 2.0.0 | 3.0.8 | +| Dependency | Old version | New version | +| -------------------- | ----------- | ----------- | +| `bioconductor-bambu` | 2.0.0 | 3.0.8 | ## [3.0.0] - 2022-06-21 From 0748ea479be3819ade134b987880dc6f684cdcf7 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Thu, 9 Mar 2023 18:22:28 +0800 Subject: [PATCH 53/56] annotate .collate(12) --- subworkflows/local/align_graphmap2.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/align_graphmap2.nf b/subworkflows/local/align_graphmap2.nf index 75db5921..50909436 100644 --- a/subworkflows/local/align_graphmap2.nf +++ b/subworkflows/local/align_graphmap2.nf @@ -21,7 +21,7 @@ workflow ALIGN_GRAPHMAP2 { ch_index .cross(ch_fastq) { it -> it[-1] } .flatten() - .collate(12) + .collate(12) // [fasta, fasta sizes, gtf, bed, fasta_index, annotation_string, meta, fastq, fasta, gtf, is_transcript, fasta_gtf_string] .map { it -> [ it[6], it[7], it[0], it[1], it[2], it[3], it[10], it[4] ] } // [ sample, fastq, fasta, sizes, gtf, bed, is_transcripts, index ] .set { ch_index } From a1979c4aef2be027c06e10be0bff7c2cd68afec0 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan Date: Fri, 10 Mar 2023 14:22:37 +0800 Subject: [PATCH 54/56] address suggestions from Daniel --- conf/test_nodx_noaln.config | 2 +- modules.json | 8 +++++++- nextflow_schema.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/conf/test_nodx_noaln.config b/conf/test_nodx_noaln.config index eed15dd4..c42e2309 100644 --- a/conf/test_nodx_noaln.config +++ b/conf/test_nodx_noaln.config @@ -21,6 +21,6 @@ params { protocol = 'directRNA' skip_demultiplexing = true skip_alignment = true - skip_fusion_analysis= true + skip_fusion_analysis = true skip_modification_analysis=true } diff --git a/modules.json b/modules.json index cee4bd83..26e7246d 100644 --- a/modules.json +++ b/modules.json @@ -93,7 +93,13 @@ } }, "subworkflows": { - "nf-core": {} + "nf-core": { + "bam_stats_samtools": { + "branch": "master", + "git_sha": "92eb5091ae5368a60cda58b3a0ced8b36d715b0f", + "installed_by": ["modules"] + } + } } } } diff --git a/nextflow_schema.json b/nextflow_schema.json index 5e716045..6dbb8b4e 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -26,7 +26,7 @@ "protocol": { "type": "string", "description": "Input sample type. Valid options: 'DNA', 'cDNA', and 'directRNA'.", - "format": "file-path", + "format": "sample-type", "mimetype": "text/csv", "schema": "assets/schema_input.json", "help_text": "You will need to specify a protocol based on the sample input type. Valid options are 'DNA', 'cDNA', and 'directRNA'.", From 37293dc9a6aec3b100e0422e7bf85f9b7e5ae13c Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Fri, 10 Mar 2023 15:32:27 +0800 Subject: [PATCH 55/56] leaving nf-core subworkflows as it is now the subworkflow is not updated --- modules.json | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/modules.json b/modules.json index 26e7246d..cee4bd83 100644 --- a/modules.json +++ b/modules.json @@ -93,13 +93,7 @@ } }, "subworkflows": { - "nf-core": { - "bam_stats_samtools": { - "branch": "master", - "git_sha": "92eb5091ae5368a60cda58b3a0ced8b36d715b0f", - "installed_by": ["modules"] - } - } + "nf-core": {} } } } From 3be2a78462638185d6dc3377998bdf14ada202b9 Mon Sep 17 00:00:00 2001 From: Yuk Kei Wan <41866052+yuukiiwa@users.noreply.github.com> Date: Fri, 10 Mar 2023 17:03:32 +0800 Subject: [PATCH 56/56] small fix --- modules/local/bambu.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/bambu.nf b/modules/local/bambu.nf index 95d46b9a..777b0e11 100644 --- a/modules/local/bambu.nf +++ b/modules/local/bambu.nf @@ -1,7 +1,7 @@ process BAMBU { label 'process_medium' - conda "conda-forge::r-base=4.0.3 bioconda::bioconductor-bambu=3.0.6 bioconda::bioconductor-bsgenome=1.66.0" + conda "conda-forge::r-base=4.0.3 bioconda::bioconductor-bambu=3.0.8 bioconda::bioconductor-bsgenome=1.66.0" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bioconductor-bambu:3.0.8--r42hc247a5b_0' : 'quay.io/biocontainers/bioconductor-bambu:3.0.8--r42hc247a5b_0' }"