From ebf0deb9310181203393b8d6281e8fcc85604d9d Mon Sep 17 00:00:00 2001 From: KevinMenden Date: Wed, 4 Dec 2019 10:23:46 +0100 Subject: [PATCH 001/107] Changed docker image --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index bec10c6..45ed8b2 100644 --- a/nextflow.config +++ b/nextflow.config @@ -8,7 +8,7 @@ // Global default params, used in configs params { - container='tristankast/cage-seq:latest' + container='kevinmenden/cageseq:latest' // Workflow flags reads = "data/*{1,2}.fastq.gz" From 94b51ac5674e6e857622f6a668dff468c178a8e6 Mon Sep 17 00:00:00 2001 From: KevinMenden Date: Wed, 4 Dec 2019 10:42:55 +0100 Subject: [PATCH 002/107] Updated default process requirements --- conf/base.config | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/conf/base.config b/conf/base.config index 51b2d7a..40689d1 100644 --- a/conf/base.config +++ b/conf/base.config @@ -22,9 +22,20 @@ process { maxRetries = 1 maxErrors = '-1' - // Process-specific resource requirements - // TODO nf-core: Customise requirements for specific processes. - // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors + withName:makeSTARindex { + cpus = { check_max( 32 * task.attempt, 'cpus' ) } + memory = { check_max( 64.GB * task.attempt, 'memory' ) } + time = { check_max( 10.h * task.attempt, 'time' ) } + } + + withName:star { + cpus = { check_max( 16 * task.attempt, 'cpus' ) } + memory = { check_max( 40.GB * task.attempt, 'memory' ) } + time = { check_max( 10.h * task.attempt, 'time' ) } + } + + + } params { From 27728613fe0acf90f03dee9d1bb002b17faca7fb Mon Sep 17 00:00:00 2001 From: KevinMenden Date: Wed, 4 Dec 2019 13:15:24 +0100 Subject: [PATCH 003/107] Removed Paraclu process --- main.nf | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/main.nf b/main.nf index c6e9965..380e542 100644 --- a/main.nf +++ b/main.nf @@ -506,29 +506,6 @@ process get_ctss { } -/** - * STEP 9 - Cluster CTSS files - */ - -process paraclu { - tag "${ctss.baseName}" - publishDir "${params.outdir}/ctss/clusters", mode: 'copy' - - input: - file ctss from ctss_counts - - output: - file "*" into ctss_clusters - - - script: - """ - process_ctss.py $ctss - paraclu $params.min_cluster "${ctss.baseName}.bed_processed" > "${ctss.baseName}_clustered" - paraclu-cut.sh "${ctss.baseName}_clustered" > "${ctss.baseName}_clustered_simplified" - """ -} - /* * STEP 10 - MultiQC */ From f5ae2760508d37e5bfbc60da99ffa407e97fb8a2 Mon Sep 17 00:00:00 2001 From: matthiasho Date: Thu, 5 Dec 2019 16:01:58 +0100 Subject: [PATCH 004/107] fix tests --- conf/test.config | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/conf/test.config b/conf/test.config index 11cd36e..f474f35 100644 --- a/conf/test.config +++ b/conf/test.config @@ -13,7 +13,10 @@ params { max_memory = 6.GB max_time = 48.h // Input data - reads = 'https://github.com/nf-core/test-datasets/blob/cageseq/testdata/cage*.fastq.gz' + reads = [ + 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage1.fastq.gz', + 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage2.fastq.gz' + ] fasta = 'https://github.com/nf-core/test-datasets/raw/cageseq/reference/chr_sub.fasta' gtf = 'https://github.com/nf-core/test-datasets/raw/cageseq/reference/chr_sub.gtf' } From 221045bdbd8d0ce3df0809b288a2383f7025a43d Mon Sep 17 00:00:00 2001 From: matthiasho Date: Fri, 13 Dec 2019 16:06:43 +0100 Subject: [PATCH 005/107] add github workflows --- .github/workflows/branch.yml | 16 +++++++++++ .github/workflows/ci.yml | 27 ++++++++++++++++++ .github/workflows/linting.yml | 53 +++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 .github/workflows/branch.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/linting.yml diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml new file mode 100644 index 0000000..899ef4c --- /dev/null +++ b/.github/workflows/branch.yml @@ -0,0 +1,16 @@ +name: cageseq branch protection +# This workflow is triggered on PRs to master branch on the repository +on: + pull_request: + branches: + - master + +jobs: + test: + runs-on: ubuntu-latest + steps: + # PRs are only ok if coming from an nf-core dev branch + - uses: actions/checkout@v1 + - name: Check PRs + run: | + { [[ $(git remote get-url origin) == *nf-core/cageseq ]] && [[ ${GITHUB_BASE_REF} = "master" ]] && [[ ${GITHUB_HEAD_REF} = "dev" ]]; } || [[ ${GITHUB_HEAD_REF} == patch* ]] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..53c37ae --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: cageseq CI +# This workflow is triggered on pushes and PRs to the repository. +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + nxf_ver: ['19.04.0', ''] + steps: + - uses: actions/checkout@v1 + - name: Get the version + id: get_version + run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) + - name: Install Nextflow + run: | + export NXF_VER=${{ matrix.nxf_ver }} + wget -qO- get.nextflow.io | bash + sudo mv nextflow /usr/local/bin/ + - name: Download and tag image + run: | + docker pull nfcore/cageseq:dev + docker tag nfcore/cageseq:dev nfcore/cageseq:${{ steps.get_version.outputs.VERSION }} + - name: Run test + run: | + nextflow run ${GITHUB_WORKSPACE} -profile test,docker diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml new file mode 100644 index 0000000..fd5781a --- /dev/null +++ b/.github/workflows/linting.yml @@ -0,0 +1,53 @@ +name: cageseq linting +# This workflow is triggered on pushes and PRs to the repository. +on: [push, pull_request] + +jobs: + Markdown: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: '10' + - name: Install markdownlint + run: | + npm install -g markdownlint-cli + - name: Run Markdownlint + run: | + markdownlint ${GITHUB_WORKSPACE} -c ${GITHUB_WORKSPACE}/.github/markdownlint.yml + YAML: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: '10' + - name: Install yamllint + run: | + npm install -g yaml-lint + - name: Run yamllint + run: | + yamllint $(find ${GITHUB_WORKSPACE} -type f -name "*.yml") + nf-core: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Install Nextflow + run: | + wget -qO- get.nextflow.io | bash + sudo mv nextflow /usr/local/bin/ + - uses: actions/setup-python@v1 + with: + python-version: '3.6' + architecture: 'x64' + - name: Install pip + run: | + sudo apt install python3-pip + pip install --upgrade pip + - name: Install nf-core tools + run: | + pip install nf-core + - name: Run nf-core lint + run: | + nf-core lint ${GITHUB_WORKSPACE} From bd36af563acec96766acdd9fc58ee84dfbc07500 Mon Sep 17 00:00:00 2001 From: matthiasho Date: Fri, 13 Dec 2019 16:12:44 +0100 Subject: [PATCH 006/107] change docker hub link to my repo --- .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 53c37ae..823cfab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,8 +20,8 @@ jobs: sudo mv nextflow /usr/local/bin/ - name: Download and tag image run: | - docker pull nfcore/cageseq:dev - docker tag nfcore/cageseq:dev nfcore/cageseq:${{ steps.get_version.outputs.VERSION }} + docker pull mashehu/cageseq:dev + docker tag mashehu/cageseq:dev mashehu/cageseq:${{ steps.get_version.outputs.VERSION }} - name: Run test run: | nextflow run ${GITHUB_WORKSPACE} -profile test,docker From 6de793f0bb20c2c5b7f1980278a0fd6f1cc90c27 Mon Sep 17 00:00:00 2001 From: matthiasho Date: Fri, 13 Dec 2019 16:39:33 +0100 Subject: [PATCH 007/107] fix lint errors --- README.md | 6 +++--- docs/configuration/reference_genomes.md | 3 ++- docs/installation.md | 2 +- docs/output.md | 2 +- docs/usage.md | 4 +--- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 63906b1..eead497 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Docker](https://img.shields.io/docker/automated/nfcore/cageseq.svg)](https://hub.docker.com/r/nfcore/cageseq) ## Introduction -**UNDER DEVELOPMENT** +UNDER DEVELOPMENT This pipeline is currenlty under development. The workflow is not yet finished. @@ -17,7 +17,7 @@ This pipeline is currenlty under development. The workflow is not yet finished. **nf-core/cageseq** is a pipeline built for the analysis of [CAGE-sequencing](https://www.ncbi.nlm.nih.gov/pubmed/22362160) data. -Analysis steps consist of adapter and artefact trimming ([cuatadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), alignment to a reference ([STAR](https://github.com/alexdobin/STAR)) and CAGE tag counting. +Analysis steps consist of adapter and artefact trimming ([cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), alignment to a reference ([STAR](https://github.com/alexdobin/STAR)) and CAGE tag counting. Additionally, several quality control steps ([FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/), [MultiQC](https://multiqc.info/)) are included to allow for easy verification of results after a run. The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It comes with docker / singularity containers making installation trivial and results highly reproducible. @@ -32,7 +32,7 @@ The nf-core/cageseq pipeline comes with documentation about the pipeline, found 2. Pipeline configuration * [Local installation](docs/configuration/local.md) * [Adding your own system](docs/configuration/adding_your_own.md) - * [Reference genomes](docs/configuration/reference_genomes.md) + * [Reference genomes](docs/configuration/reference_genomes.md) 3. [Running the pipeline](docs/usage.md) 4. [Output and how to interpret the results](docs/output.md) 5. [Troubleshooting](docs/troubleshooting.md) diff --git a/docs/configuration/reference_genomes.md b/docs/configuration/reference_genomes.md index ad8b30c..c8eac16 100644 --- a/docs/configuration/reference_genomes.md +++ b/docs/configuration/reference_genomes.md @@ -39,7 +39,8 @@ Multiple reference index types are held together with consistent structure for m We have put a copy of iGenomes up onto AWS S3 hosting and this pipeline is configured to use this by default. The hosting fees for AWS iGenomes are currently kindly funded by a grant from Amazon. The pipeline will automatically download the required reference files when you run the pipeline. -For more information about the AWS iGenomes, see https://ewels.github.io/AWS-iGenomes/ +For more information about the AWS iGenomes, see . + Downloading the files takes time and bandwidth, so we recommend making a local copy of the iGenomes resource. Once downloaded, you can customise the variable `params.igenomes_base` in your custom configuration file to point to the reference location. diff --git a/docs/installation.md b/docs/installation.md index 05f3ed5..8322cd4 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -78,7 +78,7 @@ Be warned of two important points about this default configuration: ### Docker First, install docker on your system: [Docker Installation Instructions](https://docs.docker.com/engine/installation/) -Then, running the pipeline with the option `-profile docker` tells Nextflow to enable Docker for this run. An image containing all of the software requirements will be automatically fetched and used from dockerhub (https://hub.docker.com/r/nfcore/cageseq). +Then, running the pipeline with the option `-profile docker` tells Nextflow to enable Docker for this run. An image containing all of the software requirements will be automatically fetched and used from dockerhub (). ### Singularity If you're not able to use Docker then [Singularity](http://singularity.lbl.gov/) is a great alternative. diff --git a/docs/output.md b/docs/output.md index 0a3c543..9cc6607 100644 --- a/docs/output.md +++ b/docs/output.md @@ -38,4 +38,4 @@ The pipeline has special steps which allow the software versions used to be repo * `Project_multiqc_data/` * Directory containing parsed statistics from the different tools used in the pipeline -For more information about how to use MultiQC reports, see http://multiqc.info +For more information about how to use MultiQC reports, see . diff --git a/docs/usage.md b/docs/usage.md index 096d3cc..8fa25fb 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -178,7 +178,7 @@ All generated reference files will be saved to the results folder if this flag i ## Adapter clipping and trimming -Input fastq files are trimmed in three different steps, which are by default all executed and can be individually deactivated. +Input fastq files are trimmed in three different steps, which are by default all executed and can be individually deactivated. ### `--trimming` @@ -200,8 +200,6 @@ Specifying a file containing artifacts at the 5' end. By default a file with all Specifying a file containing artifacts at the 3' end. By default a file with all possible artifacts is used. -## Adapter clipping and trimming - ### `--min_cluster` Sets the minimum amount of reads for paraclu to build a cluster. Default: 100. From 05f35821f3b6adc06dfe1e81fbb1c00273bcbd04 Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 12 Feb 2020 11:57:45 +0100 Subject: [PATCH 008/107] update software version script --- bin/scrape_software_versions.py | 10 ++++++++++ main.nf | 1 + 2 files changed, 11 insertions(+) diff --git a/bin/scrape_software_versions.py b/bin/scrape_software_versions.py index 98821ce..6586666 100755 --- a/bin/scrape_software_versions.py +++ b/bin/scrape_software_versions.py @@ -9,12 +9,22 @@ 'Nextflow': ['v_nextflow.txt', r"(\S+)"], 'FastQC': ['v_fastqc.txt', r"FastQC v(\S+)"], 'MultiQC': ['v_multiqc.txt', r"multiqc, version (\S+)"], + 'STAR': ['v_star.txt', r"STAR_(\S+)"], + 'bowtie2': ['v_bowtie2.txt', r"version (\S+)"], + 'bedtools': ['v_bedtools.txt', r"bedtools v(\S+)"], + 'cutadapt': ['v_cutadapt.txt', r"(\S+)"], + 'samtools': ['v_samtools.txt', r"samtools (\S+)"], } results = OrderedDict() results['nf-core/cageseq'] = 'N/A' results['Nextflow'] = 'N/A' results['FastQC'] = 'N/A' results['MultiQC'] = 'N/A' +results['bowtie2'] = 'N/A' +results['STAR'] = 'N/A' +results['bedtools'] = 'N/A' +results['cutadapt'] = 'N/A' +results['samtools'] = 'N/A' # Search each file using its regex for k, v in regexes.items(): diff --git a/main.nf b/main.nf index 380e542..61e064e 100644 --- a/main.nf +++ b/main.nf @@ -227,6 +227,7 @@ process get_software_versions { echo $workflow.nextflow.version > v_nextflow.txt fastqc --version > v_fastqc.txt multiqc --version > v_multiqc.txt + bowtie2 --version > v_bowtie2.txt STAR --version > v_star.txt cutadapt --version > v_cutadapt.txt samtools --version > v_samtools.txt From 662dfb6068fe46437e4a38b4f29574e689c98761 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 13:47:27 +0100 Subject: [PATCH 009/107] fix branch protection workflow --- .github/workflows/branch.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 899ef4c..734cee7 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -7,10 +7,10 @@ on: jobs: test: - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: # PRs are only ok if coming from an nf-core dev branch - uses: actions/checkout@v1 - name: Check PRs run: | - { [[ $(git remote get-url origin) == *nf-core/cageseq ]] && [[ ${GITHUB_BASE_REF} = "master" ]] && [[ ${GITHUB_HEAD_REF} = "dev" ]]; } || [[ ${GITHUB_HEAD_REF} == patch* ]] + { [[ $(git remote get-url origin) == *nf-core/cageseq ]] && [[ ${GITHUB_HEAD_REF} = "dev" ]]; } || [[ ${GITHUB_HEAD_REF} == "patch" ]] From 108fccfaeee2d7b8037ccc18d609491ad203834e Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 13:54:46 +0100 Subject: [PATCH 010/107] fix outdated nextflow.config --- nextflow.config | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/nextflow.config b/nextflow.config index 45ed8b2..7b83387 100644 --- a/nextflow.config +++ b/nextflow.config @@ -8,8 +8,6 @@ // Global default params, used in configs params { - container='kevinmenden/cageseq:latest' - // Workflow flags reads = "data/*{1,2}.fastq.gz" outdir = './results' @@ -51,16 +49,16 @@ params { // Alignment options genome = false - params.star_index = false - params.saveReference = false - params.min_aln_length = 15 - + star_index = false + saveReference = false + min_aln_length = 15 + singleEnd = true } // Container slug. Stable releases should specify release tag! // Developmental code should specify :dev -//process.container = 'nfcore/cageseq:dev' +process.container = 'nfcore/cageseq:dev' // Load base.config by default for all pipelines includeConfig 'conf/base.config' From 9358fdd133c50cc610b34756f6591edcf818d3c1 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 14:03:02 +0100 Subject: [PATCH 011/107] remove .travis.yml --- .travis.yml | 43 ------------------------------------------- 1 file changed, 43 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d61ad5f..0000000 --- a/.travis.yml +++ /dev/null @@ -1,43 +0,0 @@ -sudo: required -language: python -jdk: openjdk8 -services: docker -python: '3.6' -cache: pip -matrix: - fast_finish: true - -before_install: - # PRs to master are only ok if coming from dev branch - - '[ $TRAVIS_PULL_REQUEST = "false" ] || [ $TRAVIS_BRANCH != "master" ] || ([ $TRAVIS_PULL_REQUEST_SLUG = $TRAVIS_REPO_SLUG ] && [ $TRAVIS_PULL_REQUEST_BRANCH = "dev" ])' - # Pull the docker image first so the test doesn't wait for this - - docker pull nfcore/cageseq:dev - # Fake the tag locally so that the pipeline runs properly - # Looks weird when this is :dev to :dev, but makes sense when testing code for a release (:dev to :1.0.1) - - docker tag nfcore/cageseq:dev nfcore/cageseq:dev - -install: - # Install Nextflow - - mkdir /tmp/nextflow && cd /tmp/nextflow - - wget -qO- get.nextflow.io | bash - - sudo ln -s /tmp/nextflow/nextflow /usr/local/bin/nextflow - # Install nf-core/tools - - pip install --upgrade pip - - pip install nf-core - # Reset - - mkdir ${TRAVIS_BUILD_DIR}/tests && cd ${TRAVIS_BUILD_DIR}/tests - # Install markdownlint-cli - - sudo apt-get install npm && npm install -g markdownlint-cli - -env: - - NXF_VER='0.32.0' # Specify a minimum NF version that should be tested and work - - NXF_VER='' # Plus: get the latest NF version and check that it works - - COMMAND='' - -script: - # Lint the pipeline code - - nf-core lint ${TRAVIS_BUILD_DIR} - # Lint the documentation - - markdownlint ${TRAVIS_BUILD_DIR} -c ${TRAVIS_BUILD_DIR}/.github/markdownlint.yml - # Run the pipeline with the test profile - - nextflow run ${TRAVIS_BUILD_DIR} -profile test,docker From 9a000037f0d4f8df7ebbdf41c429eca6fb39b537 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 15:03:54 +0100 Subject: [PATCH 012/107] specify nfcore/base version in the Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cee17cd..58a18ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM nfcore/base +FROM nfcore/base:1.7 LABEL authors="Kevin Menden; Tristan Kast" \ description="Docker image containing all requirements for nf-core/cageseq pipeline" From 993ef193317e442b11d12cdbe1c0bfd1522aba82 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 15:55:43 +0100 Subject: [PATCH 013/107] remove `params.container` from base.conf --- conf/base.config | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/conf/base.config b/conf/base.config index 40689d1..e00deb4 100644 --- a/conf/base.config +++ b/conf/base.config @@ -11,8 +11,6 @@ process { - container = params.container - // TODO nf-core: Check the defaults for all processes cpus = { check_max( 1 * task.attempt, 'cpus' ) } memory = { check_max( 8.GB * task.attempt, 'memory' ) } @@ -27,7 +25,7 @@ process { memory = { check_max( 64.GB * task.attempt, 'memory' ) } time = { check_max( 10.h * task.attempt, 'time' ) } } - + withName:star { cpus = { check_max( 16 * task.attempt, 'cpus' ) } memory = { check_max( 40.GB * task.attempt, 'memory' ) } From 5dad8f8f3f60881db29b6682d991091bf43fce91 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 16:04:00 +0100 Subject: [PATCH 014/107] update nextflow.config to snake cas --- nextflow.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nextflow.config b/nextflow.config index 7b83387..3332210 100644 --- a/nextflow.config +++ b/nextflow.config @@ -25,7 +25,7 @@ params { clusterOptions = false awsqueue = false awsregion = 'eu-west-1' - igenomesIgnore = false + igenomes_ignore = false custom_config_version = 'master' custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" hostnames = false @@ -52,7 +52,7 @@ params { star_index = false saveReference = false min_aln_length = 15 - singleEnd = true + single_end = true } From 6c20d932a099c9b386c354bdcc13a2f2cf99f436 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 16:10:11 +0100 Subject: [PATCH 015/107] add bowtie2 to environment.yml --- environment.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/environment.yml b/environment.yml index 5f2c683..ffd9762 100644 --- a/environment.yml +++ b/environment.yml @@ -13,8 +13,7 @@ dependencies: - pandas=0.24.2 - r-markdown=0.9 - samtools=1.9 -- star=2.7.0f +- star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. - multiqc=1.7 - unzip=6.0 - - +- bowtie2=2.3.5 From 9d0ba126adca913a7ff61e68302bfbe77f3e3027 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 16:16:34 +0100 Subject: [PATCH 016/107] fix incorrect igenomesIgnore references --- docs/usage.md | 4 ++-- nextflow.config | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 8fa25fb..4e937b1 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -24,7 +24,7 @@ * [`--fasta`](#--fasta) * [`--gtf`](#--gtf) * [`--star_index`](#--star_index) - * [`--igenomesIgnore`](#--igenomesignore) + * [`--igenomes_ignore`](#--igenomes_ignore) * [Job resources](#job-resources) * [Automatic resubmission](#automatic-resubmission) * [Custom resource requests](#custom-resource-requests) @@ -159,7 +159,7 @@ params { } ``` -### `--igenomesIgnore` +### `--igenomes_ignore` Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`. ### `--fasta` `--gtf` `--star_index` diff --git a/nextflow.config b/nextflow.config index 3332210..2a51ed3 100644 --- a/nextflow.config +++ b/nextflow.config @@ -36,6 +36,7 @@ params { // CAGE-seq specific options // Trimming options (all enabled by default) + remove_phix = true trimming = true cutEcop = true cutLinker = true @@ -86,7 +87,7 @@ profiles { } // Load igenomes.config if required -if(!params.igenomesIgnore){ +if(!params.igenomes_ignore){ includeConfig 'conf/igenomes.config' } From f2941efc889b6a76f69626fc19f7aac52ff0000d Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 16:31:48 +0100 Subject: [PATCH 017/107] update github workflow yml to current nf-core specifications --- .github/workflows/branch.yml | 3 +-- .github/workflows/ci.yml | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 734cee7..e3054f6 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -9,8 +9,7 @@ jobs: test: runs-on: ubuntu-18.04 steps: - # PRs are only ok if coming from an nf-core dev branch - - uses: actions/checkout@v1 + # PRs are only ok if coming from an nf-core `dev` branch or a fork `patch` branch - name: Check PRs run: | { [[ $(git remote get-url origin) == *nf-core/cageseq ]] && [[ ${GITHUB_HEAD_REF} = "dev" ]]; } || [[ ${GITHUB_HEAD_REF} == "patch" ]] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 823cfab..b300cc1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,8 +20,7 @@ jobs: sudo mv nextflow /usr/local/bin/ - name: Download and tag image run: | - docker pull mashehu/cageseq:dev - docker tag mashehu/cageseq:dev mashehu/cageseq:${{ steps.get_version.outputs.VERSION }} + docker pull nfcore/cageseq:dev && docker tag nfcore/cageseq:dev nfcore/cageseq:dev - name: Run test run: | nextflow run ${GITHUB_WORKSPACE} -profile test,docker From 13e51554a46e80d8c32fa32d626c6b035486b68f Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 16:32:43 +0100 Subject: [PATCH 018/107] update base docker image and export conda env in dockerfile --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 58a18ca..afc2364 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,10 @@ -FROM nfcore/base:1.7 +FROM nfcore/base:1.8 LABEL authors="Kevin Menden; Tristan Kast" \ description="Docker image containing all requirements for nf-core/cageseq pipeline" COPY environment.yml / RUN conda env create -f /environment.yml && conda clean -a +RUN conda env export --name nf-core-cageseq-1.0dev > nf-core-cageseq-1.0dev.yml ENV PATH /opt/conda/envs/nf-core-cageseq-1.0dev/bin:$PATH RUN apt-get update; apt-get install -y build-essential g++ From ba9ab04d80a96cca5e4c981bbeb5956004c4a985 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 13 Feb 2020 16:33:19 +0100 Subject: [PATCH 019/107] update nextflow version --- README.md | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eead497..245ea91 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ **CAGE-seq pipeline**. [![Build Status](https://travis-ci.com/nf-core/cageseq.svg?branch=master)](https://travis-ci.com/nf-core/cageseq) -[![Nextflow](https://img.shields.io/badge/nextflow-%E2%89%A50.32.0-brightgreen.svg)](https://www.nextflow.io/) +[![Nextflow](https://img.shields.io/badge/nextflow-%E2%89%A519.04.0-brightgreen.svg)](https://www.nextflow.io/) [![install with bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg)](http://bioconda.github.io/) [![Docker](https://img.shields.io/docker/automated/nfcore/cageseq.svg)](https://hub.docker.com/r/nfcore/cageseq) diff --git a/nextflow.config b/nextflow.config index 2a51ed3..abe8de0 100644 --- a/nextflow.config +++ b/nextflow.config @@ -117,7 +117,7 @@ manifest { homePage = 'https://github.com/nf-core/cageseq' description = 'CAGE-seq pipeline' mainScript = 'main.nf' - nextflowVersion = '>=0.32.0' + nextflowVersion = '>=19.04.0' version = '1.0dev' } From 59f0bf2adee245389a0a775504cb10a3263af2d1 Mon Sep 17 00:00:00 2001 From: MaxUlysse Date: Fri, 14 Feb 2020 10:34:21 +0100 Subject: [PATCH 020/107] update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8395659..f4979f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # nf-core/cageseq: Changelog ## v1.0dev - [date] + Initial release of nf-core/cageseq, created with the [nf-core](http://nf-co.re/) template. From 15d326570564e7859cd0b1078f80b538228145fa Mon Sep 17 00:00:00 2001 From: MaxUlysse Date: Fri, 14 Feb 2020 10:36:32 +0100 Subject: [PATCH 021/107] Add social preview image --- assets/nf-core-cageseq_social_preview.png | Bin 0 -> 61289 bytes assets/nf-core-cageseq_social_preview.svg | 450 ++++++++++++++++++++++ 2 files changed, 450 insertions(+) create mode 100644 assets/nf-core-cageseq_social_preview.png create mode 100644 assets/nf-core-cageseq_social_preview.svg diff --git a/assets/nf-core-cageseq_social_preview.png b/assets/nf-core-cageseq_social_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..dafa778cf10851d8bf29ccee579706352625ccd5 GIT binary patch literal 61289 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + CAGE-sequencing analysis pipeline with trimming,alignment and counting of CAGE tags + cageseq + + + + + + + + + + + + + + + + + + + + + + + + + From bda1579a868ee885bbccf9cabd7708aeeaf50455 Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 17 Feb 2020 11:31:11 +0100 Subject: [PATCH 022/107] remove last traces of travis in documentation --- .github/CONTRIBUTING.md | 4 ++-- conf/test.config | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 7ecd095..7244bdb 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -24,7 +24,7 @@ If you're not used to this workflow with git, you can start with some [basic doc ## Tests -When you create a pull request with changes, [Travis CI](https://travis-ci.org/) will run automatic tests. +When you create a pull request with changes, [GitHub Actions](https://github.com/features/actions) will run automatic tests. Typically, pull-requests are only fully reviewed when these tests are passing, though of course we can help out before then. There are typically two types of tests that run: @@ -37,7 +37,7 @@ If any failures or warnings are encountered, please follow the listed URL for mo ### Pipeline Tests Each nf-core pipeline should be set up with a minimal set of test-data. -Travis CI then runs the pipeline on this data to ensure that it exists successfully. +`GitHub Actions` then runs the pipeline on this data to ensure that it exits successfully. If there are any failures then the automated tests fail. These tests are run both with the latest available version of Nextflow and also the minimum required version that is stated in the pipeline code. diff --git a/conf/test.config b/conf/test.config index f474f35..f2af69f 100644 --- a/conf/test.config +++ b/conf/test.config @@ -8,7 +8,7 @@ */ params { - // Limit resources so that this can run on Travis + // Limit resources so that this can run on GitHub Actions max_cpus = 2 max_memory = 6.GB max_time = 48.h From 5a96cc591f3981eee58c743a7316c50fde0e3892 Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 17 Feb 2020 13:40:16 +0100 Subject: [PATCH 023/107] switch to repository specific docker image for CI testing --- .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 b300cc1..79c8f28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: sudo mv nextflow /usr/local/bin/ - name: Download and tag image run: | - docker pull nfcore/cageseq:dev && docker tag nfcore/cageseq:dev nfcore/cageseq:dev + docker pull ${{github.repository}}:dev && docker tag ${{github.repository}}:dev ${{github.repository}}:dev - name: Run test run: | nextflow run ${GITHUB_WORKSPACE} -profile test,docker From b31591129651d682acc6990c92f0fdcd82039de2 Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 17 Feb 2020 14:18:58 +0100 Subject: [PATCH 024/107] switch back to hard coded docker image names for CI testing --- .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 79c8f28..b300cc1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: sudo mv nextflow /usr/local/bin/ - name: Download and tag image run: | - docker pull ${{github.repository}}:dev && docker tag ${{github.repository}}:dev ${{github.repository}}:dev + docker pull nfcore/cageseq:dev && docker tag nfcore/cageseq:dev nfcore/cageseq:dev - name: Run test run: | nextflow run ${GITHUB_WORKSPACE} -profile test,docker From 6a52dcf3a67d76ccb38c6453a321b3bcc36e7542 Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 17 Feb 2020 14:26:30 +0100 Subject: [PATCH 025/107] add paraclu process and remove unused python scripts and dependencies --- bin/get_ctss.py | 73 --------------------------------------------- bin/process_ctss.py | 27 ----------------- bin/process_ctss.sh | 23 ++++++++++++++ environment.yml | 3 -- main.nf | 32 +++++++++++++++++++- 5 files changed, 54 insertions(+), 104 deletions(-) delete mode 100755 bin/get_ctss.py delete mode 100644 bin/process_ctss.py create mode 100644 bin/process_ctss.sh diff --git a/bin/get_ctss.py b/bin/get_ctss.py deleted file mode 100755 index b7a7cd2..0000000 --- a/bin/get_ctss.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python - -""" -Extract CTSS from bed formatted alignment -""" - -import numpy as np -import pandas as pd -import argparse - -parser = argparse.ArgumentParser() -parser.add_argument("bed", help="The bed file") -parser.add_argument("ctss_file", help="The CTSS file") -args = parser.parse_args() -bedfile = args.bed -ctss_file = args.ctss_file - -ctss_dict = {} -# Count tags -with open(bedfile, "r") as bf: - for line in bf: - sp = line.split() - line_key = "_".join([sp[0], sp[1], sp[5]]) - if line_key in ctss_dict: - ctss_dict[line_key] += 1 - else: - ctss_dict[line_key] = 1 -bf.close() - -no_tags = len(ctss_dict) -chr = np.empty([no_tags, 1], dtype=object) -strand = np.empty([no_tags, 1], dtype=object) -pos = np.empty([no_tags, 1], dtype=int) -count = np.empty([no_tags, 1], dtype=int) - -def extract_ctss(elem): - ekey = elem[1] - idx = elem[0] - sp = ekey.split("_") - ct = ctss_dict[ekey] - chr[idx] = sp[0] - strand[idx] = sp[2] - pos[idx] = sp[1] - count[idx] = ct - - -[extract_ctss(elem) for elem in enumerate(ctss_dict)] - -df = pd.DataFrame(chr) -df['strand'] = strand -df['position'] = pos -df['count'] = count -df.columns = ['chr', 'strand', 'position', 'count'] - -def sort_chrom_df(chrom_df): - sens_df = chrom_df.loc[chrom_df['strand'] == '+'] - as_df = chrom_df.loc[chrom_df['strand'] == '-'] - sens_df = sens_df.sort_values(by=['position']) - as_df = as_df.sort_values(by=['position']) - frames = [sens_df, as_df] - res = pd.concat(frames) - return res - - -uchroms = np.unique(chr) -res_frames = [] -for uc in uchroms: - chrom_df = df.loc[df['chr'] == uc] - cdf = sort_chrom_df(chrom_df) - res_frames.append(cdf) - -merged_frame = pd.concat(res_frames) -merged_frame.to_csv(ctss_file, sep="\t", index=False, header=False) \ No newline at end of file diff --git a/bin/process_ctss.py b/bin/process_ctss.py deleted file mode 100644 index 2dbea15..0000000 --- a/bin/process_ctss.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python - -import argparse -import numpy as np -import csv - -parser = argparse.ArgumentParser() -parser.add_argument("ctss", help="The ctss.bed file") -args = parser.parse_args() -ctssfile = args.ctss - -content = [] -with open(ctssfile)as f: - for line in f: - content.append(line.strip().split()) - -for row in content: - del row[2:4] # 0 for column 1, 1 for column 2, etc. - -for row in content: - row[1], row[3] = row[3], row[1] - row[2], row[3] = row[3], row[2] - - -with open(ctssfile+'_processed', 'w') as f: - w = csv.writer(f, dialect = 'excel-tab') - w.writerows(content) diff --git a/bin/process_ctss.sh b/bin/process_ctss.sh new file mode 100644 index 0000000..a14dc9b --- /dev/null +++ b/bin/process_ctss.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# +if [ $# -eq 0 ] +then + cat < ... +EOF + exit 1; +fi + +CTSS_FILE=$1 + +# get filename without extension +CTSS=${CTSS_FILE%.*} +# split BED into strands +sed '/+/d' $CTSS_FILE > ${CTSS}_allm +grep + $CTSS_FILE > ${CTSS}_allp +# put CTSS output to paraclu format +awk -F "\t" '{print$1"\t"$6"\t"$2"\t"$5}' < ${CTSS}_allm > ${CTSS}_pos_4P +awk -F "\t" '{print$1"\t"$6"\t"$3"\t"$5}' < ${CTSS}_allp > ${CTSS}_neg_4P +# sort the pos and neg strand prior paraclu clustering +sort -k1,1 -k3n ${CTSS}_pos_4P > ${CTSS}_pos_4Ps +sort -k1,1 -k3n ${CTSS}_neg_4P > ${CTSS}_neg_4Ps diff --git a/environment.yml b/environment.yml index ffd9762..57e8040 100644 --- a/environment.yml +++ b/environment.yml @@ -9,9 +9,6 @@ dependencies: - bedtools=2.27.1 - cutadapt=2.1 - fastqc=0.11.8 -- numpy=1.16.2 -- pandas=0.24.2 -- r-markdown=0.9 - samtools=1.9 - star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. - multiqc=1.7 diff --git a/main.nf b/main.nf index 61e064e..ecc6b20 100644 --- a/main.nf +++ b/main.nf @@ -76,7 +76,7 @@ params.fasta = params.genome ? params.genomes[ params.genome ].fasta ?: false : params.gtf = params.genome ? params.genomes[ params.genome ].gtf ?: false : false //params.artifacts5end = params.artifacts5end ? params.artifacts5end[ params.artifacts5end ].fasta ?: false : false //params.artifacts3end = params.artifacts3end ? params.artifacts3end[ params.artifacts3end ].fasta ?: false : false -params.min_cluster = 100 +params.min_cluster = 30 // Validate inputs if( params.star_index ){ @@ -506,6 +506,36 @@ process get_ctss { """ } +/** + * STEP 9 - Cluster CTSS files + */ + +process cluster_ctss { + tag "${ctss.baseName}" + publishDir "${params.outdir}/ctss/clusters", mode: 'copy' + + input: + file ctss from ctss_counts + + output: + file "*.bed" into ctss_clusters + + shell: + ''' + bash process_ctss.sh !{ctss} + + paraclu !{params.min_cluster} "!{ctss.baseName}_pos_4Ps" > "!{ctss.baseName}pos_clustered" + paraclu !{params.min_cluster} "!{ctss.baseName}_neg_4Ps" > "!{ctss.baseName}neg_clustered" + + paraclu-cut.sh "!{ctss.baseName}pos_clustered" > "!{ctss.baseName}pos_clustered_simplified" + paraclu-cut.sh "!{ctss.baseName}neg_clustered" > "!{ctss.baseName}neg_clustered_simplified" + + + cat "!{ctss.baseName}pos_clustered_simplified" "!{ctss.baseName}neg_clustered_simplified" > "!{ctss.baseName}clustered_simplified.bed" + awk -F '\t' '{print $1"\t"$3"\t"$4"\t"$1":"$3".."$4","$2"\t"$6"\t"$2}' "!{ctss.baseName}clustered_simplified.bed" > "!{ctss.baseName}_clustered_simplified.bed" + ''' +} + /* * STEP 10 - MultiQC From f76ada1248e7c3ad163dbbeb82d56827bf202b32 Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 17 Feb 2020 14:29:33 +0100 Subject: [PATCH 026/107] download paraclu from the original creator's website --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index afc2364..18bff41 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,6 @@ RUN conda env export --name nf-core-cageseq-1.0dev > nf-core-cageseq-1.0dev.yml ENV PATH /opt/conda/envs/nf-core-cageseq-1.0dev/bin:$PATH RUN apt-get update; apt-get install -y build-essential g++ -RUN wget https://davetang.org/file/paraclu-9.zip +RUN wget http://cbrc3.cbrc.jp/~martin/paraclu/paraclu-9.zip RUN unzip paraclu-9.zip; cd paraclu-9; make ENV PATH /paraclu-9:$PATH From 62c57937f762b20e9201957dca733bd9afb587fa Mon Sep 17 00:00:00 2001 From: mashehu Date: Tue, 18 Feb 2020 14:28:05 +0100 Subject: [PATCH 027/107] add sample name to channels --- README.md | 2 +- bin/make_ctss.sh | 49 ++++++++--------- bin/scrape_software_versions.py | 1 - conf/test.config | 5 +- docs/configuration/local.md | 4 +- environment.yml | 1 + main.nf | 93 +++++++++++++++++---------------- nextflow.config | 1 + 8 files changed, 79 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 245ea91..8de2d2c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **CAGE-seq pipeline**. -[![Build Status](https://travis-ci.com/nf-core/cageseq.svg?branch=master)](https://travis-ci.com/nf-core/cageseq) + [![Nextflow](https://img.shields.io/badge/nextflow-%E2%89%A519.04.0-brightgreen.svg)](https://www.nextflow.io/) [![install with bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg)](http://bioconda.github.io/) diff --git a/bin/make_ctss.sh b/bin/make_ctss.sh index 82a0c1c..c5150e9 100644 --- a/bin/make_ctss.sh +++ b/bin/make_ctss.sh @@ -1,14 +1,14 @@ -#!/bin/sh +#!/bin/bash -if [ $# -eq 0 ] +if [ $# -eq 0 ] then cat < ... +Usage is : $0 -q ... EOF exit 1; fi -QCUT= +QCUT= while getopts q: opt do @@ -23,27 +23,24 @@ if [ "${QCUT}" = "" ]; then QCUT=10; fi for var in "$@" do if [[ $var =~ bam$ ]]; then -foo=$var -file=${foo##*/} -base=${file%%.*} -echo working on: $base - -TMPFILE="/tmp/$(basename $0).$RANDOM.txt" - samtools view -F 4 -u -q $QCUT -b $var | bamToBed -i stdin > $TMPFILE - cat ${TMPFILE} \ -| awk 'BEGIN{OFS="\t"}{if($6=="+"){print $1,$2,$5}}' \ -| sort -k1,1 -k2,2n \ -| groupBy -i stdin -g 1,2 -c 3 -o count \ -| awk -v x="$base" 'BEGIN{OFS="\t"}{print $1,$2,$2+1, x ,$3,"+"}' >> $var.ctss.bed - -cat ${TMPFILE} \ -| awk 'BEGIN{OFS="\t"}{if($6=="-"){print $1,$3,$5}}' \ -| sort -k1,1 -k2,2n \ -| groupBy -i stdin -g 1,2 -c 3 -o count \ -| awk -v x="$base" 'BEGIN{OFS="\t"}{print $1,$2-1,$2, x ,$3,"-"}' >> $var.ctss.bed - -rm $TMPFILE + file=${var##*/} + base=${file%%.*} + echo "working on: ${base}" + + TMPFILE="/tmp/$(basename $0).$RANDOM.txt" + samtools view -F 4 -u -q $QCUT -b $var | bamToBed -i stdin > $TMPFILE + cat ${TMPFILE} \ + | awk 'BEGIN{OFS="\t"}{if($6=="+"){print $1,$2,$5}}' \ + | sort -k1,1 -k2,2n \ + | groupBy -i stdin -g 1,2 -c 3 -o count \ + | awk -v x="$base" 'BEGIN{OFS="\t"}{print $1,$2,$2+1, x ,$3,"+"}' >> $base.ctss.bed + + cat ${TMPFILE} \ + | awk 'BEGIN{OFS="\t"}{if($6=="-"){print $1,$3,$5}}' \ + | sort -k1,1 -k2,2n \ + | groupBy -i stdin -g 1,2 -c 3 -o count \ + | awk -v x="$base" 'BEGIN{OFS="\t"}{print $1,$2-1,$2, x ,$3,"-"}' >> $base.ctss.bed + + rm $TMPFILE fi done - - diff --git a/bin/scrape_software_versions.py b/bin/scrape_software_versions.py index 6586666..ac3240b 100755 --- a/bin/scrape_software_versions.py +++ b/bin/scrape_software_versions.py @@ -3,7 +3,6 @@ from collections import OrderedDict import re -# TODO nf-core: Add additional regexes for new tools in process get_software_versions regexes = { 'nf-core/cageseq': ['v_pipeline.txt', r"(\S+)"], 'Nextflow': ['v_nextflow.txt', r"(\S+)"], diff --git a/conf/test.config b/conf/test.config index f2af69f..c8d96ff 100644 --- a/conf/test.config +++ b/conf/test.config @@ -13,9 +13,8 @@ params { max_memory = 6.GB max_time = 48.h // Input data - reads = [ - 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage1.fastq.gz', - 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage2.fastq.gz' + readPaths = [['cage1', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage1.fastq.gz'], + ['cage2', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage2.fastq.gz'] ] fasta = 'https://github.com/nf-core/test-datasets/raw/cageseq/reference/chr_sub.fasta' gtf = 'https://github.com/nf-core/test-datasets/raw/cageseq/reference/chr_sub.gtf' diff --git a/docs/configuration/local.md b/docs/configuration/local.md index 89a63b4..e2bb719 100644 --- a/docs/configuration/local.md +++ b/docs/configuration/local.md @@ -37,11 +37,11 @@ First, pull the image file where you have an internet connection: > Make sure that this tag corresponds to the version of the pipeline that you're using ```bash -singularity pull --name nf-core-cageseq-1.0.img docker://nf-core/cageseq:1.0 +singularity pull --name nf-core-cageseq-dev.img docker://nf-core/cageseq:dev ``` Then transfer this file and run the pipeline with this path: ```bash -nextflow run /path/to/nf-core-cageseq -with-singularity /path/to/nf-core-cageseq-1.0.img +nextflow run /path/to/nf-core-cageseq -with-singularity /path/to/nf-core-cageseq-dev.img ``` diff --git a/environment.yml b/environment.yml index 57e8040..d9360be 100644 --- a/environment.yml +++ b/environment.yml @@ -14,3 +14,4 @@ dependencies: - multiqc=1.7 - unzip=6.0 - bowtie2=2.3.5 +- r-rmarkdown=1.12 diff --git a/main.nf b/main.nf index ecc6b20..77657e1 100644 --- a/main.nf +++ b/main.nf @@ -146,11 +146,19 @@ ch_output_docs = Channel.fromPath("$baseDir/docs/output.md") /* * Create a channel for input read files */ -Channel - .fromPath( params.reads) - .ifEmpty { exit 1, "Cannot find any reads matching: ${params.reads}" } - .into { read_files_fastqc; read_files_trimming } +if(params.readPaths){ + Channel + .from(params.readPaths) + .map { row -> [ row[0], file(row[1])] } + .ifEmpty { exit 1, "params.readPaths was empty - no input files supplied" } + .into { read_files_fastqc; read_files_trimming } + } else { + Channel + .fromFilePairs( params.reads ) + .ifEmpty { exit 1, "Cannot find any reads matching: ${params.reads}\nNB: Path needs to be enclosed in quotes!\nNB: Path requires at least one * wildcard!\n" } + .into { read_files_fastqc; read_files_trimming } +} // Header log info log.info nfcoreHeader() @@ -168,7 +176,7 @@ summary['CutG'] = params.cutG summary['CutArtifacts'] = params.cutArtifacts summary['EcoSite'] = params.ecoSite summary['LinkerSeq'] = params.linkerSeq -summary['Min. cluster'] = params.min_cluster +summary['Min. cluster'] = params.min_cluster summary['Save Reference'] = params.saveReference summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" if(workflow.containerEngine) summary['Container'] = "$workflow.containerEngine - $workflow.container" @@ -213,9 +221,6 @@ ${summary.collect { k,v -> "
$k
${v ?: ' filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename"} input: - file reads from read_files_fastqc + set val(sample_name), file(reads) from read_files_fastqc output: file "*_fastqc.{zip,html}" into fastqc_results script: """ - fastqc -q $reads + fastqc --quiet --threads $task.cpus $reads """ } @@ -262,7 +267,7 @@ process fastqc { /* * STEP 2 - Build STAR index */ -if(!params.star_index){ + process makeSTARindex { tag "${fasta.baseName}" @@ -276,6 +281,9 @@ if(!params.star_index){ output: file "star" into star_index + when: + !(params.star_index) + script: """ mkdir star @@ -288,7 +296,7 @@ if(!params.star_index){ --genomeFastaFiles $fasta """ } -} + /* @@ -296,17 +304,17 @@ if(!params.star_index){ */ if(params.trimming){ process trimming { - tag "$prefix" + tag "$sample_name" publishDir "${params.outdir}/trimmed/adapter_trimmed", mode: 'copy', saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" else "$filename" } input: - file reads from read_files_trimming + set val(sample_name), file(reads) from read_files_trimming output: - file "*.fastq.gz" into trimmed_reads_cutG + set val(sample_name), file("*.fastq.gz") into trimmed_reads_cutG file "*.output.txt" into cutadapt_results script: @@ -353,8 +361,6 @@ if(params.trimming){ } - - } else{ read_files_trimming.into{ trimmed_reads_cutG } @@ -366,13 +372,13 @@ if(params.trimming){ */ if (params.cutG){ process cut_5G{ - tag "${reads.baseName}" + tag "$sample_name" input: - file reads from trimmed_reads_cutG + set val(sample_name), file(reads) from trimmed_reads_cutG output: - file "*.fastq.gz" into processed_reads + set val(sample_name), file("*.fastq.gz") into processed_reads script: prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?$/ @@ -393,19 +399,19 @@ if(params.trimming){ */ if (params.cutArtifacts){ process cut_artifacts { - tag "${reads.baseName}" + tag "$sample_name" publishDir "${params.outdir}/trimmed/artifacst_trimmed", mode: 'copy', saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" else "$filename" } input: - file reads from processed_reads + set val(sample_name), file(reads) from processed_reads file artifacts5end from ch_5end_artifacts file artifacts3end from ch_3end_artifacts output: - file "*.fastq.gz" into further_processed_reads + set val(sample_name), file("*.fastq.gz") into further_processed_reads file "*.output.txt" into artifact_cutting_results script: @@ -426,24 +432,24 @@ else{ } // Post trimming QC, only needed if some trimming has been done -if(params.trimming || params.cutG || params.cutArtifacts){ process trimmed_fastqc { - tag "${reads.baseName}" + tag "$sample_name" publishDir "${params.outdir}/trimmed/fastqc", mode: 'copy', saveAs: {filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename"} input: - file reads from further_processed_reads_fastqc + set val(sample_name), file(reads) from further_processed_reads_fastqc output: - file "*_fastqc.{zip,html}" into trimmed_fastqc_results + set val(sample_name), file("*_fastqc.{zip,html}") into trimmed_fastqc_results + when: + params.trimming || params.cutG || params.cutArtifacts script: """ fastqc -q $reads """ } -} /** * STEP 7 - STAR alignment @@ -451,26 +457,25 @@ if(params.trimming || params.cutG || params.cutArtifacts){ process star { - tag "$prefix" + tag "$sample_name" publishDir "${params.outdir}/STAR", mode: 'copy', saveAs: {filename -> if (filename.indexOf(".bam") == -1) "logs/$filename" else filename } input: - file reads from further_processed_reads_star + set val(sample_name), file(reads) from further_processed_reads_star file index from star_index.collect() file gtf from gtf_star.collect() output: - file '*.bam' into star_aligned + set val(sample_name), file("*.bam") into star_aligned file "*.out" into alignment_logs file "*SJ.out.tab" - file "*Log.out" into star_log script: - prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ + prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ """ STAR --genomeDir $index \\ @@ -491,14 +496,14 @@ process star { * STEP 8 - Get CTSS files */ process get_ctss { - tag "${bam_count.baseName}" + tag "$sample_name" publishDir "${params.outdir}/ctss", mode: 'copy' input: - file bam_count from star_aligned + set val(sample_name), file(bam_count) from star_aligned output: - file "*.ctss.bed" into ctss_counts + set val(sample_name), file("*.ctss.bed") into ctss_counts script: """ @@ -511,11 +516,11 @@ process get_ctss { */ process cluster_ctss { - tag "${ctss.baseName}" + tag "${ctss.simpleName}" publishDir "${params.outdir}/ctss/clusters", mode: 'copy' input: - file ctss from ctss_counts + set val(sample_name), file(ctss) from ctss_counts output: file "*.bed" into ctss_clusters @@ -547,10 +552,10 @@ process multiqc { file multiqc_config from ch_multiqc_config file ('fastqc/*') from fastqc_results.collect().ifEmpty([]) file ('software_versions/*') from software_versions_yaml - //if(params.trimming){file ('trimmed/*') from cutadapt_results.collect()} - //if(params.cutArtifacts){file ('artifacts_trimmed/*') from artifact_cutting_results.collect()} - //if(params.trimming || params.cutG || params.cutArtifacts){file ('trimmed/fastqc/*') from trimmed_fastqc_results.collect().ifEmpty([])} - file ('alignment/*') from alignment_logs.collect() + file ('trimmed/*') from cutadapt_results.collect().ifEmpty([]) + file ('artifacts_trimmed/*') from artifact_cutting_results.collect().ifEmpty([]) + file ('trimmed/fastqc/*') from trimmed_fastqc_results.collect().ifEmpty([]) + file ('alignment/*') from alignment_logs.collect().ifEmpty([]) file workflow_summary from create_workflow_summary(summary) output: @@ -562,7 +567,7 @@ process multiqc { rfilename = custom_runName ? "--filename " + custom_runName.replaceAll('\\W','_').replaceAll('_+','_') + "_multiqc_report" : '' """ multiqc . -f $rtitle $rfilename --config $multiqc_config \\ - -m star -m cutadapt -m fastqc -m custom_content + -m custom_content -m fastqc -m star -m cutadapt """ } diff --git a/nextflow.config b/nextflow.config index abe8de0..ab474d8 100644 --- a/nextflow.config +++ b/nextflow.config @@ -10,6 +10,7 @@ params { // Workflow flags reads = "data/*{1,2}.fastq.gz" + readPaths = false // Used for test profiles outdir = './results' // Boilerplate options From 628363540d9ea3f56f205de563ab6b57af3cc48f Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 19 Feb 2020 09:36:33 +0100 Subject: [PATCH 028/107] add empty channels for log files when processes are skipped fix color rendering bug for console output --- main.nf | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/main.nf b/main.nf index 77657e1..40c32ed 100644 --- a/main.nf +++ b/main.nf @@ -198,7 +198,7 @@ if(params.email) { summary['MultiQC maxsize'] = params.maxMultiqcEmailFileSize } log.info summary.collect { k,v -> "${k.padRight(18)}: $v" }.join("\n") -log.info "\033[2m----------------------------------------------------\033[0m" +log.info "-\033[2m----------------------------------------------------\033[0m" // Check the hostnames against configured profiles checkHostname() @@ -355,7 +355,7 @@ if(params.trimming){ -m 15 -M 45 \\ -o "$prefix".trimmed.fastq.gz \\ $reads \\ - > "$prefix"adapter_trimming.output.txt + > "$prefix"_adapter_trimming.output.txt """ } @@ -420,6 +420,7 @@ if (params.cutArtifacts){ cutadapt -a file:$artifacts3end \\ -g file:$artifacts5end -e 0.1 --discard-trimmed \\ --match-read-wildcards -m 15 -O 19 \\ + --cores=${task.cpus} \\ -o "$prefix".artifact_trimmed.fastq.gz \\ $reads \\ > ${reads.baseName}.artifact_trimming.output.txt @@ -429,6 +430,7 @@ if (params.cutArtifacts){ } else{ processed_reads.into{further_processed_reads_star; further_processed_reads_fastqc} + artifact_cutting_results = Channel.empty() } // Post trimming QC, only needed if some trimming has been done @@ -681,15 +683,23 @@ workflow.onComplete { def output_tf = new File( output_d, "pipeline_report.txt" ) output_tf.withWriter { w -> w << email_txt } + c_reset = params.monochrome_logs ? '' : "\033[0m"; c_purple = params.monochrome_logs ? '' : "\033[0;35m"; c_green = params.monochrome_logs ? '' : "\033[0;32m"; c_red = params.monochrome_logs ? '' : "\033[0;31m"; + + if (workflow.stats.ignoredCount > 0 && workflow.success) { + log.info "-${c_purple}Warning, pipeline completed, but with errored process(es) ${c_reset}-" + log.info "-${c_red}Number of ignored errored process(es) : ${workflow.stats.ignoredCount} ${c_reset}-" + log.info "-${c_green}Number of successfully ran process(es) : ${workflow.stats.succeedCountFmt} ${c_reset}-" + } + if(workflow.success){ - log.info "${c_purple}[nf-core/cageseq]${c_green} Pipeline complete${c_reset}" + log.info "-${c_purple}[nf-core/cageseq]${c_green} Pipeline completed successfully${c_reset}-" } else { checkHostname() - log.info "${c_purple}[nf-core/cageseq]${c_red} Pipeline completed with errors${c_reset}" + log.info "-${c_purple}[nf-core/cageseq]${c_red} Pipeline completed with errors${c_reset}-" } } @@ -707,14 +717,14 @@ def nfcoreHeader(){ c_cyan = params.monochrome_logs ? '' : "\033[0;36m"; c_white = params.monochrome_logs ? '' : "\033[0;37m"; - return """ ${c_dim}----------------------------------------------------${c_reset} + return """-${c_dim} ----------------------------------------------------${c_reset} ${c_green},--.${c_black}/${c_green},-.${c_reset} ${c_blue} ___ __ __ __ ___ ${c_green}/,-._.--~\'${c_reset} ${c_blue} |\\ | |__ __ / ` / \\ |__) |__ ${c_yellow}} {${c_reset} ${c_blue} | \\| | \\__, \\__/ | \\ |___ ${c_green}\\`-._,-`-,${c_reset} ${c_green}`._,._,\'${c_reset} ${c_purple} nf-core/cageseq v${workflow.manifest.version}${c_reset} - ${c_dim}----------------------------------------------------${c_reset} + ${c_dim} ----------------------------------------------------${c_reset} """.stripIndent() } From abeec3dc23a86fa66e4a507276e917d5695fba38 Mon Sep 17 00:00:00 2001 From: runner Date: Thu, 20 Feb 2020 15:30:08 +0000 Subject: [PATCH 029/107] Template update for nf-core/tools version 1.9 --- .github/CONTRIBUTING.md | 50 +- .github/ISSUE_TEMPLATE/bug_report.md | 43 +- .github/ISSUE_TEMPLATE/feature_request.md | 18 +- .github/PULL_REQUEST_TEMPLATE.md | 28 +- .github/markdownlint.yml | 4 - .github/workflows/branch.yml | 16 + .github/workflows/ci.yml | 30 ++ .github/workflows/linting.yml | 50 ++ .gitignore | 4 +- .travis.yml | 42 -- CHANGELOG.md | 12 + CODE_OF_CONDUCT.md | 2 +- Dockerfile | 10 +- README.md | 65 ++- assets/email_template.html | 2 + assets/email_template.txt | 29 +- assets/multiqc_config.yaml | 6 +- assets/nf-core-cageseq_logo.png | Bin 0 -> 13292 bytes assets/sendmail_template.txt | 17 + .../scrape_software_versions.cpython-36.pyc | Bin 1277 -> 0 bytes bin/markdown_to_html.py | 100 ++++ bin/markdown_to_html.r | 51 -- bin/scrape_software_versions.py | 27 +- conf/awsbatch.config | 18 - conf/base.config | 37 +- conf/igenomes.config | 451 ++++++++++++++---- conf/test.config | 9 +- docs/README.md | 10 +- docs/configuration/adding_your_own.md | 86 ---- docs/configuration/local.md | 47 -- docs/configuration/reference_genomes.md | 50 -- docs/images/nf-core-cageseq_logo.png | Bin 0 -> 22650 bytes docs/installation.md | 113 ----- docs/output.md | 6 +- docs/troubleshooting.md | 30 -- docs/usage.md | 97 +++- environment.yml | 8 +- main.nf | 276 ++++++----- nextflow.config | 55 ++- 39 files changed, 1081 insertions(+), 818 deletions(-) create mode 100644 .github/workflows/branch.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/linting.yml delete mode 100644 .travis.yml create mode 100644 assets/nf-core-cageseq_logo.png delete mode 100644 bin/__pycache__/scrape_software_versions.cpython-36.pyc create mode 100755 bin/markdown_to_html.py delete mode 100755 bin/markdown_to_html.r delete mode 100644 conf/awsbatch.config delete mode 100644 docs/configuration/adding_your_own.md delete mode 100644 docs/configuration/local.md delete mode 100644 docs/configuration/reference_genomes.md create mode 100644 docs/images/nf-core-cageseq_logo.png delete mode 100644 docs/installation.md delete mode 100644 docs/troubleshooting.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 7ecd095..50a66c9 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,45 +1,57 @@ # nf-core/cageseq: Contributing Guidelines -Hi there! Many thanks for taking an interest in improving nf-core/cageseq. +Hi there! +Many thanks for taking an interest in improving nf-core/cageseq. -We try to manage the required tasks for nf-core/cageseq using GitHub issues, you probably came to this page when creating one. Please use the pre-filled template to save time. +We try to manage the required tasks for nf-core/cageseq using GitHub issues, you probably came to this page when creating one. +Please use the pre-filled template to save time. -However, don't be put off by this template - other more general issues and suggestions are welcome! Contributions to the code are even more welcome ;) +However, don't be put off by this template - other more general issues and suggestions are welcome! +Contributions to the code are even more welcome ;) -> If you need help using or modifying nf-core/cageseq then the best place to go is the Gitter chatroom where you can ask us questions directly: https://gitter.im/nf-core/Lobby +> If you need help using or modifying nf-core/cageseq then the best place to ask is on the nf-core Slack [#cageseq](https://nfcore.slack.com/channels/cageseq) channel ([join our Slack here](https://nf-co.re/join/slack)). ## Contribution workflow -If you'd like to write some code for nf-core/cageseq, the standard workflow -is as follows: -1. Check that there isn't already an issue about your idea in the - [nf-core/cageseq issues](https://github.com/nf-core/cageseq/issues) to avoid - duplicating work. +If you'd like to write some code for nf-core/cageseq, the standard workflow is as follows: + +1. Check that there isn't already an issue about your idea in the [nf-core/cageseq issues](https://github.com/nf-core/cageseq/issues) to avoid duplicating work * If there isn't one already, please create one so that others know you're working on this -2. Fork the [nf-core/cageseq repository](https://github.com/nf-core/cageseq) to your GitHub account +2. [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the [nf-core/cageseq repository](https://github.com/nf-core/cageseq) to your GitHub account 3. Make the necessary changes / additions within your forked repository -4. Submit a Pull Request against the `dev` branch and wait for the code to be reviewed and merged. - -If you're not used to this workflow with git, you can start with some [basic docs from GitHub](https://help.github.com/articles/fork-a-repo/) or even their [excellent interactive tutorial](https://try.github.io/). +4. Submit a Pull Request against the `dev` branch and wait for the code to be reviewed and merged +If you're not used to this workflow with git, you can start with some [docs from GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests) or even their [excellent `git` resources](https://try.github.io/). ## Tests -When you create a pull request with changes, [Travis CI](https://travis-ci.org/) will run automatic tests. + +When you create a pull request with changes, [GitHub Actions](https://github.com/features/actions) will run automatic tests. Typically, pull-requests are only fully reviewed when these tests are passing, though of course we can help out before then. There are typically two types of tests that run: ### Lint Tests -The nf-core has a [set of guidelines](http://nf-co.re/guidelines) which all pipelines must adhere to. + +`nf-core` has a [set of guidelines](https://nf-co.re/developers/guidelines) which all pipelines must adhere to. To enforce these and ensure that all pipelines stay in sync, we have developed a helper tool which runs checks on the pipeline code. This is in the [nf-core/tools repository](https://github.com/nf-core/tools) and once installed can be run locally with the `nf-core lint ` command. If any failures or warnings are encountered, please follow the listed URL for more documentation. ### Pipeline Tests -Each nf-core pipeline should be set up with a minimal set of test-data. -Travis CI then runs the pipeline on this data to ensure that it exists successfully. + +Each `nf-core` pipeline should be set up with a minimal set of test-data. +`GitHub Actions` then runs the pipeline on this data to ensure that it exits successfully. If there are any failures then the automated tests fail. -These tests are run both with the latest available version of Nextflow and also the minimum required version that is stated in the pipeline code. +These tests are run both with the latest available version of `Nextflow` and also the minimum required version that is stated in the pipeline code. + +## Patch + +: warning: Only in the unlikely and regretful event of a release happening with a bug. + +* On your own fork, make a new branch `patch` based on `upstream/master`. +* Fix the bug, and bump version (X.Y.Z+1). +* A PR should be made on `master` from patch to directly this particular bug. ## Getting help -For further information/help, please consult the [nf-core/cageseq documentation](https://github.com/nf-core/cageseq#documentation) and don't hesitate to get in touch on [Gitter](https://gitter.im/nf-core/Lobby) + +For further information/help, please consult the [nf-core/cageseq documentation](https://nf-co.re/nf-core/cageseq/docs) and don't hesitate to get in touch on the nf-core Slack [#cageseq](https://nfcore.slack.com/channels/cageseq) channel ([join our Slack here](https://nf-co.re/join/slack)). diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index d6f261e..e5d32f4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,31 +1,42 @@ +# nf-core/cageseq bug report + Hi there! -Thanks for telling us about a problem with the pipeline. Please delete this text and anything that's not relevant from the template below: +Thanks for telling us about a problem with the pipeline. +Please delete this text and anything that's not relevant from the template below: + +## Describe the bug -#### Describe the bug A clear and concise description of what the bug is. -#### Steps to reproduce +## Steps to reproduce + Steps to reproduce the behaviour: + 1. Command line: `nextflow run ...` 2. See error: _Please provide your error message_ -#### Expected behaviour +## Expected behaviour + A clear and concise description of what you expected to happen. -#### System: - - Hardware: [e.g. HPC, Desktop, Cloud...] - - Executor: [e.g. slurm, local, awsbatch...] - - OS: [e.g. CentOS Linux, macOS, Linux Mint...] - - Version [e.g. 7, 10.13.6, 18.3...] +## System + +- Hardware: +- Executor: +- OS: +- Version + +## Nextflow Installation + +- Version: + +## Container engine -#### Nextflow Installation: - - Version: [e.g. 0.31.0] +- Engine: +- version: +- Image tag: -#### Container engine: - - Engine: [e.g. Conda, Docker or Singularity] - - version: [e.g. 1.0.0] - - Image tag: [e.g. nfcore/cageseq:1.0.0] +## Additional context -#### Additional context Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 1f025b7..b92d059 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,16 +1,24 @@ +# nf-core/cageseq feature request + Hi there! -Thanks for suggesting a new feature for the pipeline! Please delete this text and anything that's not relevant from the template below: +Thanks for suggesting a new feature for the pipeline! +Please delete this text and anything that's not relevant from the template below: + +## Is your feature request related to a problem? Please describe -#### Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. + Ex. I'm always frustrated when [...] -#### Describe the solution you'd like +## Describe the solution you'd like + A clear and concise description of what you want to happen. -#### Describe alternatives you've considered +## Describe alternatives you've considered + A clear and concise description of any alternative solutions or features you've considered. -#### Additional context +## Additional context + Add any other context about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 25971ee..de814a0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,15 +1,19 @@ -Many thanks to contributing to nf-core/cageseq! +# nf-core/cageseq pull request -Please fill in the appropriate checklist below (delete whatever is not relevant). These are the most common things requested on pull requests (PRs). +Many thanks for contributing to nf-core/cageseq! + +Please fill in the appropriate checklist below (delete whatever is not relevant). +These are the most common things requested on pull requests (PRs). ## PR checklist - - [ ] This comment contains a description of changes (with reason) - - [ ] If you've fixed a bug or added code that should be tested, add tests! - - [ ] If necessary, also make a PR on the [nf-core/cageseq branch on the nf-core/test-datasets repo]( https://github.com/nf-core/test-datasets/pull/new/nf-core/cageseq) - - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker`). - - [ ] Make sure your code lints (`nf-core lint .`). - - [ ] Documentation in `docs` is updated - - [ ] `CHANGELOG.md` is updated - - [ ] `README.md` is updated - -**Learn more about contributing:** https://github.com/nf-core/cageseq/tree/master/.github/CONTRIBUTING.md + +- [ ] 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 necessary, also make a PR on the [nf-core/cageseq branch on the nf-core/test-datasets repo](https://github.com/nf-core/test-datasets/pull/new/nf-core/cageseq) +- [ ] Ensure the test suite passes (`nextflow run . -profile test,docker`). +- [ ] Make sure your code lints (`nf-core lint .`). +- [ ] Documentation in `docs` is updated +- [ ] `CHANGELOG.md` is updated +- [ ] `README.md` is updated + +**Learn more about contributing:** [CONTRIBUTING.md](https://github.com/nf-core/cageseq/tree/master/.github/CONTRIBUTING.md) \ No newline at end of file diff --git a/.github/markdownlint.yml b/.github/markdownlint.yml index e052a63..96b12a7 100644 --- a/.github/markdownlint.yml +++ b/.github/markdownlint.yml @@ -1,9 +1,5 @@ # Markdownlint configuration file default: true, line-length: false -no-multiple-blanks: 0 -blanks-around-headers: false -blanks-around-lists: false -header-increment: false no-duplicate-header: siblings_only: true diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml new file mode 100644 index 0000000..9cb261e --- /dev/null +++ b/.github/workflows/branch.yml @@ -0,0 +1,16 @@ +name: nf-core branch protection +# This workflow is triggered on PRs to master branch on the repository +# It fails when someone tries to make a PR against the nf-core `master` branch instead of `dev` +on: + pull_request: + branches: + - master + +jobs: + test: + runs-on: ubuntu-18.04 + steps: + # PRs are only ok if coming from an nf-core `dev` branch or a fork `patch` branch + - name: Check PRs + run: | + { [[ $(git remote get-url origin) == *nf-core/cageseq ]] && [[ ${GITHUB_HEAD_REF} = "dev" ]]; } || [[ ${GITHUB_HEAD_REF} == "patch" ]] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a6471c8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: nf-core CI +# This workflow is triggered on pushes and PRs to the repository. +# It runs the pipeline with the minimal test dataset to check that it completes without any syntax errors +on: [push, pull_request] + +jobs: + test: + env: + NXF_VER: ${{ matrix.nxf_ver }} + NXF_ANSI_LOG: false + runs-on: ubuntu-latest + strategy: + matrix: + # Nextflow versions: check pipeline minimum and current latest + nxf_ver: ['19.10.0', ''] + steps: + - uses: actions/checkout@v2 + - name: Install Nextflow + run: | + wget -qO- get.nextflow.io | bash + sudo mv nextflow /usr/local/bin/ + - name: Pull docker image + run: | + docker pull nfcore/cageseq:dev + docker tag nfcore/cageseq:dev nfcore/cageseq:dev + - name: Run pipeline with test data + run: | + # TODO nf-core: You can customise CI pipeline run tests as required + # (eg. adding multiple test runs with different parameters) + nextflow run ${GITHUB_WORKSPACE} -profile test,docker diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml new file mode 100644 index 0000000..1e0827a --- /dev/null +++ b/.github/workflows/linting.yml @@ -0,0 +1,50 @@ +name: nf-core linting +# This workflow is triggered on pushes and PRs to the repository. +# It runs the `nf-core lint` and markdown lint tests to ensure that the code meets the nf-core guidelines +on: + push: + pull_request: + release: + types: [published] + +jobs: + Markdown: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: '10' + - name: Install markdownlint + run: npm install -g markdownlint-cli + - name: Run Markdownlint + run: markdownlint ${GITHUB_WORKSPACE} -c ${GITHUB_WORKSPACE}/.github/markdownlint.yml + YAML: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: '10' + - name: Install yaml-lint + run: npm install -g yaml-lint + - name: Run yaml-lint + run: yamllint $(find ${GITHUB_WORKSPACE} -type f -name "*.yml") + nf-core: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Nextflow + run: | + wget -qO- get.nextflow.io | bash + sudo mv nextflow /usr/local/bin/ + - uses: actions/setup-python@v1 + with: + python-version: '3.6' + architecture: 'x64' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install nf-core + - name: Run nf-core lint + run: nf-core lint ${GITHUB_WORKSPACE} diff --git a/.gitignore b/.gitignore index 46f69e4..6354f37 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ work/ data/ results/ .DS_Store -tests/test_data +tests/ +testing/ +*.pyc diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c2ae2d6..0000000 --- a/.travis.yml +++ /dev/null @@ -1,42 +0,0 @@ -sudo: required -language: python -jdk: openjdk8 -services: docker -python: '3.6' -cache: pip -matrix: - fast_finish: true - -before_install: - # PRs to master are only ok if coming from dev branch - - '[ $TRAVIS_PULL_REQUEST = "false" ] || [ $TRAVIS_BRANCH != "master" ] || ([ $TRAVIS_PULL_REQUEST_SLUG = $TRAVIS_REPO_SLUG ] && [ $TRAVIS_PULL_REQUEST_BRANCH = "dev" ])' - # Pull the docker image first so the test doesn't wait for this - - docker pull nfcore/cageseq:dev - # Fake the tag locally so that the pipeline runs properly - # Looks weird when this is :dev to :dev, but makes sense when testing code for a release (:dev to :1.0.1) - - docker tag nfcore/cageseq:dev nfcore/cageseq:dev - -install: - # Install Nextflow - - mkdir /tmp/nextflow && cd /tmp/nextflow - - wget -qO- get.nextflow.io | bash - - sudo ln -s /tmp/nextflow/nextflow /usr/local/bin/nextflow - # Install nf-core/tools - - pip install --upgrade pip - - pip install nf-core - # Reset - - mkdir ${TRAVIS_BUILD_DIR}/tests && cd ${TRAVIS_BUILD_DIR}/tests - # Install markdownlint-cli - - sudo apt-get install npm && npm install -g markdownlint-cli - -env: - - NXF_VER='0.32.0' # Specify a minimum NF version that should be tested and work - - NXF_VER='' # Plus: get the latest NF version and check that it works - -script: - # Lint the pipeline code - - nf-core lint ${TRAVIS_BUILD_DIR} - # Lint the documentation - - markdownlint ${TRAVIS_BUILD_DIR} -c ${TRAVIS_BUILD_DIR}/.github/markdownlint.yml - # Run the pipeline with the test profile - - nextflow run ${TRAVIS_BUILD_DIR} -profile test,docker diff --git a/CHANGELOG.md b/CHANGELOG.md index 8395659..5dbc61d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,16 @@ # nf-core/cageseq: Changelog +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + ## v1.0dev - [date] + Initial release of nf-core/cageseq, created with the [nf-core](http://nf-co.re/) template. + +### `Added` + +### `Fixed` + +### `Dependencies` + +### `Deprecated` diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 2109619..cf930c8 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team on the [Gitter channel](https://gitter.im/nf-core/Lobby). The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team on [Slack](https://nf-co.re/join/slack). The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. diff --git a/Dockerfile b/Dockerfile index c4cf70c..778ca02 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,13 @@ -FROM nfcore/base +FROM nfcore/base:1.9 LABEL authors="Kevin Menden" \ - description="Docker image containing all requirements for nf-core/cageseq pipeline" + description="Docker image containing all software requirements for the nf-core/cageseq pipeline" +# Install the conda environment COPY environment.yml / RUN conda env create -f /environment.yml && conda clean -a + +# Add conda installation dir to PATH (instead of doing 'conda activate') ENV PATH /opt/conda/envs/nf-core-cageseq-1.0dev/bin:$PATH + +# Dump the details of the installed packages to a file for posterity +RUN conda env export --name nf-core-cageseq-1.0dev > nf-core-cageseq-1.0dev.yml diff --git a/README.md b/README.md index b1e1e41..1867e68 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,77 @@ -# nf-core/cageseq +# ![nf-core/cageseq](docs/images/nf-core-cageseq_logo.png) **CAGE-seq pipeline**. -[![Build Status](https://travis-ci.com/nf-core/cageseq.svg?branch=master)](https://travis-ci.com/nf-core/cageseq) -[![Nextflow](https://img.shields.io/badge/nextflow-%E2%89%A50.32.0-brightgreen.svg)](https://www.nextflow.io/) +[![GitHub Actions CI Status](https://github.com/nf-core/cageseq/workflows/nf-core%20CI/badge.svg)](https://github.com/nf-core/cageseq/actions) +[![GitHub Actions Linting Status](https://github.com/nf-core/cageseq/workflows/nf-core%20linting/badge.svg)](https://github.com/nf-core/cageseq/actions) +[![Nextflow](https://img.shields.io/badge/nextflow-%E2%89%A519.10.0-brightgreen.svg)](https://www.nextflow.io/) [![install with bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg)](http://bioconda.github.io/) [![Docker](https://img.shields.io/docker/automated/nfcore/cageseq.svg)](https://hub.docker.com/r/nfcore/cageseq) ## Introduction -The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It comes with docker / singularity containers making installation trivial and results highly reproducible. +The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It comes with docker containers making installation trivial and results highly reproducible. + +## Quick Start + +i. Install [`nextflow`](https://nf-co.re/usage/installation) + +ii. Install either [`Docker`](https://docs.docker.com/engine/installation/) or [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/) for full pipeline reproducibility (please only use [`Conda`](https://conda.io/miniconda.html) as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles)) + +iii. Download the pipeline and test it on a minimal dataset with a single command + +```bash +nextflow run nf-core/cageseq -profile test, +``` + +> Please check [nf-core/configs](https://github.com/nf-core/configs#documentation) to see if a custom config file to run nf-core pipelines already exists for your Institute. If so, you can simply use `-profile ` in your command. This will enable either `docker` or `singularity` and set the appropriate execution settings for your local compute environment. + +iv. Start running your own analysis! + + + +```bash +nextflow run nf-core/cageseq -profile --reads '*_R{1,2}.fastq.gz' --genome GRCh37 +``` + +See [usage docs](docs/usage.md) for all of the available options when running the pipeline. ## Documentation + The nf-core/cageseq pipeline comes with documentation about the pipeline, found in the `docs/` directory: -1. [Installation](docs/installation.md) +1. [Installation](https://nf-co.re/usage/installation) 2. Pipeline configuration - * [Local installation](docs/configuration/local.md) - * [Adding your own system](docs/configuration/adding_your_own.md) - * [Reference genomes](docs/configuration/reference_genomes.md) + * [Local installation](https://nf-co.re/usage/local_installation) + * [Adding your own system config](https://nf-co.re/usage/adding_own_config) + * [Reference genomes](https://nf-co.re/usage/reference_genomes) 3. [Running the pipeline](docs/usage.md) 4. [Output and how to interpret the results](docs/output.md) -5. [Troubleshooting](docs/troubleshooting.md) +5. [Troubleshooting](https://nf-co.re/usage/troubleshooting) ## Credits + nf-core/cageseq was originally written by Kevin Menden. + +## Contributions and Support + +If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). + +For further information or help, don't hesitate to get in touch on [Slack](https://nfcore.slack.com/channels/cageseq) (you can join with [this invite](https://nf-co.re/join/slack)). + +## Citation + + + + +You can cite the `nf-core` publication as follows: + +> **The nf-core framework for community-curated bioinformatics pipelines.** +> +> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen. +> +> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). +> ReadCube: [Full Access Link](https://rdcu.be/b1GjZ) diff --git a/assets/email_template.html b/assets/email_template.html index 4ed60b2..5a273e8 100644 --- a/assets/email_template.html +++ b/assets/email_template.html @@ -11,6 +11,8 @@
+ +

nf-core/cageseq v${version}

Run Name: $runName

diff --git a/assets/email_template.txt b/assets/email_template.txt index e73facb..44949d4 100644 --- a/assets/email_template.txt +++ b/assets/email_template.txt @@ -1,6 +1,12 @@ -======================================== - nf-core/cageseq v${version} -======================================== +---------------------------------------------------- + ,--./,-. + ___ __ __ __ ___ /,-._.--~\\ + |\\ | |__ __ / ` / \\ |__) |__ } { + | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-, + `._,._,' + nf-core/cageseq v${version} +---------------------------------------------------- + Run Name: $runName <% if (success){ @@ -17,23 +23,6 @@ ${errorReport} } %> -<% if (!success){ - out << """#################################################### -## nf-core/cageseq execution completed unsuccessfully! ## -#################################################### -The exit status of the task that caused the workflow execution to fail was: $exitStatus. -The full error message was: - -${errorReport} -""" -} else { - out << "## nf-core/cageseq execution completed successfully! ##" -} -%> - - - - The workflow was completed at $dateComplete (duration: $duration) The command used to launch the workflow was as follows: diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index 0dff6b8..0443bdb 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -3,5 +3,9 @@ report_comment: > analysis pipeline. For information about how to interpret these results, please see the documentation. report_section_order: - nf-core/cageseq-software-versions: + software_versions: order: -1000 + nf-core-cageseq-summary: + order: -1001 + +export_plots: true diff --git a/assets/nf-core-cageseq_logo.png b/assets/nf-core-cageseq_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..34a1fd884da6eeab703fbfad4a480994bd6057b8 GIT binary patch literal 13292 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 mtrMpilK;1*F26Hh@eo=I5_!Dk-b!{55Z +Content-Disposition: inline; filename="nf-core-cageseq_logo.png" + +<% out << new File("$baseDir/assets/nf-core-cageseq_logo.png"). + bytes. + encodeBase64(). + toString(). + tokenize( '\n' )*. + toList()*. + collate( 76 )*. + collect { it.join() }. + flatten(). + join( '\n' ) %> + <% if (mqcFile){ def mqcFileObj = new File("$mqcFile") diff --git a/bin/__pycache__/scrape_software_versions.cpython-36.pyc b/bin/__pycache__/scrape_software_versions.cpython-36.pyc deleted file mode 100644 index 7be5b53f485b00de70835150f4708bf78e34d3af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1277 zcmZ`&&2HO95Z)yznxZ8CC~2Bp3PLR)3$?^Ufdp|Gp+$n;>ee-o6odnU=8h!F%O5Y7 zvMg68JwRWeFHoSzK1xr#_LNsBdgzd%fB;RF;LOM2{Oz~1Uv)ZW{Q8f}b%T(<$$P7X z_#1q)e^D^PC?^qhDJ`+Wl}L5f3aeamHKwt~RAG80_n3jW$xM{3-!!)Y>V~*FYlF@@ z4yp8htq*E_=#b?lH0FC7@`}9u@ltUOw+SXR8F@lB^w+0u3tICw=IMYo-$(n=69S!$ z;vT?(_>*<#hj1`IVn-Xgp`e4|kT-;>=j12yGr5W15a_Z88|;4h1?Y8^$90u1dx+5n zG&f4=ar0N@{YiUX*hg)_)(>A1BrV zM21DJ%59*nKE1!Uf+V>PA;_f!F^c^Nto6Du&gx=?zD-^1eP3ogf4S;AS?b4DChs`B z=miN+#OdeHtMzqnd}e>^*rmhxqsfJaOb8qmB6Jk*D2kQ3xL^AYLNjEiR{ukNjd1TE zjt3(FDfa_7?pys6t3T`yu;XEtOysREU|8=l>zf%=6no{SK9Un7t&2L+dc9@my~vq> z2}aJOOtVwlo`!OkUyXt!vOm-yChMCiPoyXB(z4=AM!at_$N~|jYvT{c<`VwJ)A3uF6g4rk`&^CE(=Y7&kAElf1zjKi(pnXB447?Cy78*G^QfS z)1pybgWrjGjCCsU&#f(^)W+c-UgaTYLwG9hrq|Dwc03sdi2&4IrFZvZh;85`NWjzh z-xPask|9g8_1eA)V;hgaPr=(!>+RYcrFVtlL6BKRQriP}|@@XqNHMWo1 TrTd5usYZLMV(7F>AJYE-h1Z1% diff --git a/bin/markdown_to_html.py b/bin/markdown_to_html.py new file mode 100755 index 0000000..57cc426 --- /dev/null +++ b/bin/markdown_to_html.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +from __future__ import print_function +import argparse +import markdown +import os +import sys + +def convert_markdown(in_fn): + input_md = open(in_fn, mode="r", encoding="utf-8").read() + html = markdown.markdown( + "[TOC]\n" + input_md, + extensions = [ + 'pymdownx.extra', + 'pymdownx.b64', + 'pymdownx.highlight', + 'pymdownx.emoji', + 'pymdownx.tilde', + 'toc' + ], + extension_configs = { + 'pymdownx.b64': { + 'base_path': os.path.dirname(in_fn) + }, + 'pymdownx.highlight': { + 'noclasses': True + }, + 'toc': { + 'title': 'Table of Contents' + } + } + ) + return html + +def wrap_html(contents): + header = """ + + + + + +
+ """ + footer = """ +
+ + + """ + return header + contents + footer + + +def parse_args(args=None): + parser = argparse.ArgumentParser() + parser.add_argument('mdfile', type=argparse.FileType('r'), nargs='?', + help='File to convert. Defaults to stdin.') + parser.add_argument('-o', '--out', type=argparse.FileType('w'), + default=sys.stdout, + help='Output file name. Defaults to stdout.') + return parser.parse_args(args) + +def main(args=None): + args = parse_args(args) + converted_md = convert_markdown(args.mdfile.name) + html = wrap_html(converted_md) + args.out.write(html) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/bin/markdown_to_html.r b/bin/markdown_to_html.r deleted file mode 100755 index abe1335..0000000 --- a/bin/markdown_to_html.r +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env Rscript - -# Command line argument processing -args = commandArgs(trailingOnly=TRUE) -if (length(args) < 2) { - stop("Usage: markdown_to_html.r ", call.=FALSE) -} -markdown_fn <- args[1] -output_fn <- args[2] - -# Load / install packages -if (!require("markdown")) { - install.packages("markdown", dependencies=TRUE, repos='http://cloud.r-project.org/') - library("markdown") -} - -base_css_fn <- getOption("markdown.HTML.stylesheet") -base_css <- readChar(base_css_fn, file.info(base_css_fn)$size) -custom_css <- paste(base_css, " -body { - padding: 3em; - margin-right: 350px; - max-width: 100%; -} -#toc { - position: fixed; - right: 20px; - width: 300px; - padding-top: 20px; - overflow: scroll; - height: calc(100% - 3em - 20px); -} -#toc_header { - font-size: 1.8em; - font-weight: bold; -} -#toc > ul { - padding-left: 0; - list-style-type: none; -} -#toc > ul ul { padding-left: 20px; } -#toc > ul > li > a { display: none; } -img { max-width: 800px; } -") - -markdownToHTML( - file = markdown_fn, - output = output_fn, - stylesheet = custom_css, - options = c('toc', 'base64_images', 'highlight_code') -) diff --git a/bin/scrape_software_versions.py b/bin/scrape_software_versions.py index 98821ce..316ee1c 100755 --- a/bin/scrape_software_versions.py +++ b/bin/scrape_software_versions.py @@ -18,15 +18,23 @@ # Search each file using its regex for k, v in regexes.items(): - with open(v[0]) as x: - versions = x.read() - match = re.search(v[1], versions) - if match: - results[k] = "v{}".format(match.group(1)) + try: + with open(v[0]) as x: + versions = x.read() + match = re.search(v[1], versions) + if match: + results[k] = "v{}".format(match.group(1)) + except IOError: + results[k] = False + +# Remove software set to false in results +for k in list(results): + if not results[k]: + del(results[k]) # Dump to YAML print (''' -id: 'nf-core/cageseq-software-versions' +id: 'software_versions' section_name: 'nf-core/cageseq Software Versions' section_href: 'https://github.com/nf-core/cageseq' plot_type: 'html' @@ -35,5 +43,10 @@
''') for k,v in results.items(): - print("
{}
{}
".format(k,v)) + print("
{}
{}
".format(k,v)) print ("
") + +# Write out regexes as csv file: +with open('software_versions.csv', 'w') as f: + for k,v in results.items(): + f.write("{}\t{}\n".format(k,v)) diff --git a/conf/awsbatch.config b/conf/awsbatch.config deleted file mode 100644 index 14af586..0000000 --- a/conf/awsbatch.config +++ /dev/null @@ -1,18 +0,0 @@ -/* - * ------------------------------------------------- - * Nextflow config file for running on AWS batch - * ------------------------------------------------- - * Base config needed for running with -profile awsbatch - */ -params { - config_profile_name = 'AWSBATCH' - config_profile_description = 'AWSBATCH Cloud Profile' - config_profile_contact = 'Alexander Peltzer (@apeltzer)' - config_profile_url = 'https://aws.amazon.com/de/batch/' -} - -aws.region = params.awsregion -process.executor = 'awsbatch' -process.queue = params.awsqueue -executor.awscli = '/home/ec2-user/miniconda/bin/aws' -params.tracedir = './' diff --git a/conf/base.config b/conf/base.config index 15bf12f..e81da25 100644 --- a/conf/base.config +++ b/conf/base.config @@ -13,22 +13,39 @@ process { // TODO nf-core: Check the defaults for all processes cpus = { check_max( 1 * task.attempt, 'cpus' ) } - memory = { check_max( 8.GB * task.attempt, 'memory' ) } - time = { check_max( 2.h * task.attempt, 'time' ) } + memory = { check_max( 7.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } maxRetries = 1 maxErrors = '-1' // Process-specific resource requirements + // NOTE - Only one of the labels below are used in the fastqc process in the main script. + // If possible, it would be nice to keep the same label naming convention when + // adding in your processes. // TODO nf-core: Customise requirements for specific processes. // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors -} - -params { - // Defaults only, expecting to be overwritten - max_memory = 128.GB - max_cpus = 16 - max_time = 240.h - igenomes_base = 's3://ngi-igenomes/igenomes/' + withLabel:process_low { + cpus = { check_max( 2 * task.attempt, 'cpus' ) } + memory = { check_max( 14.GB * task.attempt, 'memory' ) } + time = { check_max( 6.h * task.attempt, 'time' ) } + } + withLabel:process_medium { + cpus = { check_max( 6 * task.attempt, 'cpus' ) } + memory = { check_max( 42.GB * task.attempt, 'memory' ) } + time = { check_max( 8.h * task.attempt, 'time' ) } + } + withLabel:process_high { + cpus = { check_max( 12 * task.attempt, 'cpus' ) } + memory = { check_max( 84.GB * task.attempt, 'memory' ) } + time = { check_max( 10.h * task.attempt, 'time' ) } + } + withLabel:process_long { + time = { check_max( 20.h * task.attempt, 'time' ) } + } + withName:get_software_versions { + cache = false + } + } diff --git a/conf/igenomes.config b/conf/igenomes.config index d19e61f..2de9242 100644 --- a/conf/igenomes.config +++ b/conf/igenomes.config @@ -9,139 +9,412 @@ params { // illumina iGenomes reference file paths - // TODO nf-core: Add new reference types and strip out those that are not needed genomes { 'GRCh37' { - bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "2.7e9" + blacklist = "${baseDir}/assets/blacklists/GRCh37-blacklist.bed" + } + 'GRCh38' { + fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${baseDir}/assets/blacklists/hg38-blacklist.bed" } 'GRCm38' { - bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "1.87e9" + blacklist = "${baseDir}/assets/blacklists/GRCm38-blacklist.bed" } 'TAIR10' { - bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" + mito_name = "Mt" } 'EB2' { - bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" } 'UMD3.1' { - bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" + mito_name = "MT" } 'WBcel235' { - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" + mito_name = "MtDNA" + macs_gsize = "9e7" } 'CanFam3.1' { - bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" + mito_name = "MT" } 'GRCz10' { - bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" + mito_name = "MT" } 'BDGP6' { - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" + mito_name = "M" + macs_gsize = "1.2e8" } 'EquCab2' { - bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" + mito_name = "MT" } 'EB1' { - bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" } 'Galgal4' { - bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" + mito_name = "MT" } 'Gm01' { - bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" } 'Mmul_1' { - bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" + mito_name = "MT" } 'IRGSP-1.0' { - bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" + mito_name = "Mt" } 'CHIMP2.1.4' { - bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" + mito_name = "MT" } 'Rnor_6.0' { - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" + mito_name = "MT" } 'R64-1-1' { - bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" + mito_name = "MT" + macs_gsize = "1.2e7" } 'EF2' { - bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" + mito_name = "MT" + macs_gsize = "1.21e7" } 'Sbi1' { - bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" } 'Sscrofa10.2' { - bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" + mito_name = "MT" } 'AGPv3' { - bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" - fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" - gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" - star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" + fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" + mito_name = "Mt" + } + 'hg38' { + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${baseDir}/assets/blacklists/hg38-blacklist.bed" + } + 'hg19' { + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "2.7e9" + blacklist = "${baseDir}/assets/blacklists/hg19-blacklist.bed" + } + 'mm10' { + fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "1.87e9" + blacklist = "${baseDir}/assets/blacklists/mm10-blacklist.bed" + } + 'bosTau8' { + fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" + mito_name = "chrM" + } + 'ce10' { + fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "9e7" + } + 'canFam3' { + fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" + mito_name = "chrM" + } + 'danRer10' { + fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" + mito_name = "chrM" + } + 'dm6' { + fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" + mito_name = "chrM" + macs_gsize = "1.2e8" + } + 'equCab2' { + fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" + mito_name = "chrM" + } + 'galGal4' { + fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" + mito_name = "chrM" + } + 'panTro4' { + fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" + mito_name = "chrM" + } + 'rn6' { + fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" + mito_name = "chrM" + } + 'sacCer3' { + fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" + readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" + mito_name = "chrM" + macs_gsize = "1.2e7" + } + 'susScr3' { + fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/genome.fa" + bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" + star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" + bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" + gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" + bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" + readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" + mito_name = "chrM" } } } diff --git a/conf/test.config b/conf/test.config index 6daf1fb..bcc4a22 100644 --- a/conf/test.config +++ b/conf/test.config @@ -4,18 +4,21 @@ * ------------------------------------------------- * Defines bundled input files and everything required * to run a fast and simple test. Use as follows: - * nextflow run nf-core/cageseq -profile test + * nextflow run nf-core/cageseq -profile test, */ params { - // Limit resources so that this can run on Travis + 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 = 48.h + // Input data // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets // TODO nf-core: Give any required params for the test so that command line flags are not needed - singleEnd = false + single_end = false readPaths = [ ['Testdata', ['https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R1.tiny.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R2.tiny.fastq.gz']], ['SRR389222', ['https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub1.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub2.fastq.gz']] diff --git a/docs/README.md b/docs/README.md index c4eb1df..37cf4c1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,11 +2,11 @@ The nf-core/cageseq documentation is split into the following files: -1. [Installation](installation.md) +1. [Installation](https://nf-co.re/usage/installation) 2. Pipeline configuration - * [Local installation](configuration/local.md) - * [Adding your own system](configuration/adding_your_own.md) - * [Reference genomes](configuration/reference_genomes.md) + * [Local installation](https://nf-co.re/usage/local_installation) + * [Adding your own system config](https://nf-co.re/usage/adding_own_config) + * [Reference genomes](https://nf-co.re/usage/reference_genomes) 3. [Running the pipeline](usage.md) 4. [Output and how to interpret the results](output.md) -5. [Troubleshooting](troubleshooting.md) +5. [Troubleshooting](https://nf-co.re/usage/troubleshooting) diff --git a/docs/configuration/adding_your_own.md b/docs/configuration/adding_your_own.md deleted file mode 100644 index 624c24b..0000000 --- a/docs/configuration/adding_your_own.md +++ /dev/null @@ -1,86 +0,0 @@ -# nf-core/cageseq: Configuration for other clusters - -It is entirely possible to run this pipeline on other clusters, though you will need to set up your own config file so that the pipeline knows how to work with your cluster. - -> If you think that there are other people using the pipeline who would benefit from your configuration (eg. other common cluster setups), please let us know. We can add a new configuration and profile which can used by specifying `-profile ` when running the pipeline. The config file will then be hosted at `nf-core/configs` and will be pulled automatically before the pipeline is executed. - -If you are the only person to be running this pipeline, you can create your config file as `~/.nextflow/config` and it will be applied every time you run Nextflow. Alternatively, save the file anywhere and reference it when running the pipeline with `-c path/to/config` (see the [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for more). - -A basic configuration comes with the pipeline, which loads the [`conf/base.config`](../../conf/base.config) by default. This means that you only need to configure the specifics for your system and overwrite any defaults that you want to change. - -## Cluster Environment -By default, pipeline uses the `local` Nextflow executor - in other words, all jobs are run in the login session. If you're using a simple server, this may be fine. If you're using a compute cluster, this is bad as all jobs will run on the head node. - -To specify your cluster environment, add the following line to your config file: - -```nextflow -process.executor = 'YOUR_SYSTEM_TYPE' -``` - -Many different cluster types are supported by Nextflow. For more information, please see the [Nextflow documentation](https://www.nextflow.io/docs/latest/executor.html). - -Note that you may need to specify cluster options, such as a project or queue. To do so, use the `clusterOptions` config option: - -```nextflow -process { - executor = 'SLURM' - clusterOptions = '-A myproject' -} -``` - - -## Software Requirements -To run the pipeline, several software packages are required. How you satisfy these requirements is essentially up to you and depends on your system. If possible, we _highly_ recommend using either Docker or Singularity. - -Please see the [`installation documentation`](../installation.md) for how to run using the below as a one-off. These instructions are about configuring a config file for repeated use. - -### Docker -Docker is a great way to run nf-core/cageseq, as it manages all software installations and allows the pipeline to be run in an identical software environment across a range of systems. - -Nextflow has [excellent integration](https://www.nextflow.io/docs/latest/docker.html) with Docker, and beyond installing the two tools, not much else is required - nextflow will automatically fetch the [nfcore/cageseq](https://hub.docker.com/r/nfcore/cageseq/) image that we have created and is hosted at dockerhub at run time. - -To add docker support to your own config file, add the following: - -```nextflow -docker.enabled = true -process.container = "nfcore/cageseq" -``` - -Note that the dockerhub organisation name annoyingly can't have a hyphen, so is `nfcore` and not `nf-core`. - - -### Singularity image -Many HPC environments are not able to run Docker due to security issues. -[Singularity](http://singularity.lbl.gov/) is a tool designed to run on such HPC systems which is very similar to Docker. - -To specify singularity usage in your pipeline config file, add the following: - -```nextflow -singularity.enabled = true -process.container = "nf-core/cageseq" -``` - -If you intend to run the pipeline offline, nextflow will not be able to automatically download the singularity image for you. -Instead, you'll have to do this yourself manually first, transfer the image file and then point to that. - -First, pull the image file where you have an internet connection: - -```bash -singularity pull --name nf-core-cageseq.simg nf-core/cageseq -``` - -Then transfer this file and point the config file to the image: - -```nextflow -singularity.enabled = true -process.container = "/path/to/nf-core-cageseq.simg" -``` - - -### Conda -If you're not able to use Docker or Singularity, you can instead use conda to manage the software requirements. -To use conda in your own config file, add the following: - -```nextflow -process.conda = "$baseDir/environment.yml" -``` diff --git a/docs/configuration/local.md b/docs/configuration/local.md deleted file mode 100644 index 89a63b4..0000000 --- a/docs/configuration/local.md +++ /dev/null @@ -1,47 +0,0 @@ -# nf-core/cageseq: Local Configuration - -If running the pipeline in a local environment, we highly recommend using either Docker or Singularity. - -## Docker -Docker is a great way to run `nf-core/cageseq`, as it manages all software installations and allows the pipeline to be run in an identical software environment across a range of systems. - -Nextflow has [excellent integration](https://www.nextflow.io/docs/latest/docker.html) with Docker, and beyond installing the two tools, not much else is required. The `nf-core/cageseq` profile comes with a configuration profile for docker, making it very easy to use. This also comes with the required presets to use the AWS iGenomes resource, meaning that if using common reference genomes you just specify the reference ID and it will be automatically downloaded from AWS S3. - -First, install docker on your system: [Docker Installation Instructions](https://docs.docker.com/engine/installation/) - -Then, simply run the analysis pipeline: - -```bash -nextflow run nf-core/cageseq -profile docker --genome '' --design '' -``` - -Nextflow will recognise `nf-core/cageseq` and download the pipeline from GitHub. The `-profile docker` configuration lists the [nf-core/cageseq](https://hub.docker.com/r/nfcore/cageseq/) image that we have created and is hosted at dockerhub, and this is downloaded. - -For more information about how to work with reference genomes, see [`docs/configuration/reference_genomes.md`](reference_genomes.md). - -### Pipeline versions -The public docker images are tagged with the same version numbers as the code, which you can use to ensure reproducibility. When running the pipeline, specify the pipeline version with `-r`, for example `-r 1.0`. This uses pipeline code and docker image from this tagged version. - - -## Singularity image -Many HPC environments are not able to run Docker due to security issues. [Singularity](http://singularity.lbl.gov/) is a tool designed to run on such HPC systems which is very similar to Docker. Even better, it can use create images directly from dockerhub. - -To use the singularity image for a single run, use `-with-singularity`. This will download the docker container from dockerhub and create a singularity image for you dynamically. - -If you intend to run the pipeline offline, nextflow will not be able to automatically download the singularity image for you. Instead, you'll have to do this yourself manually first, transfer the image file and then point to that. - -First, pull the image file where you have an internet connection: - -> NB: The "tag" at the end of this command corresponds to the pipeline version. -> Here, we're pulling the docker image for version 1.0 of the nf-core/cageseq pipeline -> Make sure that this tag corresponds to the version of the pipeline that you're using - -```bash -singularity pull --name nf-core-cageseq-1.0.img docker://nf-core/cageseq:1.0 -``` - -Then transfer this file and run the pipeline with this path: - -```bash -nextflow run /path/to/nf-core-cageseq -with-singularity /path/to/nf-core-cageseq-1.0.img -``` diff --git a/docs/configuration/reference_genomes.md b/docs/configuration/reference_genomes.md deleted file mode 100644 index ad8b30c..0000000 --- a/docs/configuration/reference_genomes.md +++ /dev/null @@ -1,50 +0,0 @@ -# nf-core/cageseq: Reference Genomes Configuration - -The nf-core/cageseq pipeline needs a reference genome for alignment and annotation. - -These paths can be supplied on the command line at run time (see the [usage docs](../usage.md)), -but for convenience it's often better to save these paths in a nextflow config file. -See below for instructions on how to do this. -Read [Adding your own system](adding_your_own.md) to find out how to set up custom config files. - -## Adding paths to a config file -Specifying long paths every time you run the pipeline is a pain. -To make this easier, the pipeline comes configured to understand reference genome keywords which correspond to preconfigured paths, meaning that you can just specify `--genome ID` when running the pipeline. - -Note that this genome key can also be specified in a config file if you always use the same genome. - -To use this system, add paths to your config file using the following template: - -```nextflow -params { - genomes { - 'YOUR-ID' { - fasta = '/genome.fa' - } - 'OTHER-GENOME' { - // [..] - } - } - // Optional - default genome. Ignored if --genome 'OTHER-GENOME' specified on command line - genome = 'YOUR-ID' -} -``` - -You can add as many genomes as you like as long as they have unique IDs. - -## illumina iGenomes -To make the use of reference genomes easier, illumina has developed a centralised resource called [iGenomes](https://support.illumina.com/sequencing/sequencing_software/igenome.html). -Multiple reference index types are held together with consistent structure for multiple genomes. - -We have put a copy of iGenomes up onto AWS S3 hosting and this pipeline is configured to use this by default. -The hosting fees for AWS iGenomes are currently kindly funded by a grant from Amazon. -The pipeline will automatically download the required reference files when you run the pipeline. -For more information about the AWS iGenomes, see https://ewels.github.io/AWS-iGenomes/ - -Downloading the files takes time and bandwidth, so we recommend making a local copy of the iGenomes resource. -Once downloaded, you can customise the variable `params.igenomes_base` in your custom configuration file to point to the reference location. -For example: - -```nextflow -params.igenomes_base = '/path/to/data/igenomes/' -``` diff --git a/docs/images/nf-core-cageseq_logo.png b/docs/images/nf-core-cageseq_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ebf73627d77347692ab9387f49f0506ed6c12e94 GIT binary patch literal 22650 zcmdqJ1yfwl(*}yW1a}A!f?IGWNC=DD;_hxCxP{=B1c$}5xa;B$0fNIq&;^3KF3u&t z_kX{`ty?u)yR~)ZOiy>8p6Ti5InnB>3bFR^fOqMv%<%0gzm+AIiIT-J z$Do()k1DCKFw=)($3~%?MT{5^T=lk^=tri_d(Fwqr;%y&u*b^%EqXo5@S5SJSzyqA zef8s&OuF*hBtPjfhU0Y(HZ4$@QeEH+5`cXGZpIE_&vS z{Y6#^`@zazIR+%9|FnUy3fVPN0eG_tBl={A4|IdH+2*k99GzFmXNt{`YY1;TLd6Ww z(F9knf7g3C`%k|LW%@UwR=VZ$@yVnF_s`hYJ#APasR_1SEHfd8o(>QP`bATZV}xWo z^n?`aHu3RkxL8Hv?wg#P8RkpJUg9lIbh_Wt26Wcz9%iMDy8v@_`hpKNhAjmXdj8!f zz^eV|jwxK3)>Yj93Yn&BIwir@M*!zJwIGG}_WqJl8ve2+$&Lze?+`3& z9yI>Q&rtKv!san&aBTcZc`$d=sR)OG$eA_*&;fj01C_-6n{0uXiXED;g0~@;rs0NM zl6Z8{56GackVZ-Ur$=RaRlQj-x|T{Vq9nQ<$bXIvMnrsMJX8Fgu3>B;gHNNQqgDOa zi8Dzq3ctGj>S7tpBJTFMjydPI_dHl=SU%u?0-SCOb!8YIIiEMw9uWtZ$HMwb*mgurxSz3 zH9M;5ajszCQ6EE<#rywsGWm-dcR8->tODPMiD%0~z}e4@R;4naTPDkE!y&9T;CVfg zuF8AnE$4sA|N3E@F^)vW%n8VYIzS>_=H(X~4%eIT1JA|?bSyEs=)^^JXI6aj?sGH= z=_FJ7z6qFuE$;MTnwEPXyx6Y5Owz4xA`rW~dD9W#pSVLcQQ_=9N})}MEMYhsZ|edq z>CC4O8&ejVK^Lk&&z_%eBYV;AoCoRCWA!m2ZDKX+@K$BH?nPuDo^N^Wu`4Q7MPp*6 z(XCt{mEbTz=v+64NiFq^lrcV7tA1|v4#hEYwZz$mwFbdXKC}*E*QP#Vi=da%TtmO| zBS?GiVMS!IGf@f3it%NV#VWKu@YvC<<+|uiu<)gNjZH?KU9x;W?cwm&-wZlFh8oK6 z$1dA+=SHGy1qsC&i7caM#LCzZ6i}Wz6ug0Q>X8%Xm7C(Ak;;|4R|o9EoW0W0%b78O!lfVxHCd)PfP2H9c3<|r7zw>UaRXPiV|fu;fd!E=^zZb~%uYL8 z3W17nr*N*A{rZ1Gx?%AQ?R2uc_sAFX-(KQmD$_eE;Rl2xfw!IXAg_ScHcwZ!lgWI3 zJk8C+zyFka)&6R5mbZ~?jy{5Z6FGd>&3MHJcS0JYx??Mych8ud8R>ojizjqS9{0hK3(I z-74jJRpvAU6>CjhG)>RVy;w+~#p2F^cPu{hV9F0Je)WLi?)=mlk&Lgs=%p@hcsHMi zP>H3-Kj_fjEM0k5*@!L~c&=l}VAu3wE^0d%*^SbnQ%E&(ZcL-RfJLt3cwWo5c}~6} z+sQKQ$^@A+EHirfwvgn^@Y+i9r7yk7mS=j-oVzkp{MD;P#S&223$2b_qtK0B<(|V_ z#V~8T?N4`j*^%}xWf+@0K$HQAWOg0ti`Rg_tbnH?GH=|irY`U4y`?gO&=hsN_Pq+m zWKDd1%W3tPPHbUjFZr#2yYww!Xm8$}B^x-%3j3PCj2&vDt>w_!czr}Xw#Sk}_OdX` z^y*_gpc;j2Vg5pnL~yip*7)6iKH|B+yJR)Bk3#G^REM+Mk0a*0yE62pR?3nS$g15l z*$~*x55L^XG+juA%7(|un;T^A8ZXN8CVgNH9-_Xe*F*!;B1=vskF4GI8 zmG$r_9TTO`x@6y8R3f|h9bZfsc{?O{o6ucUrz-bwcAo`J>`<$hTjyxt#fn|#b4#6kVB|y0FO#P~LnA{N1CE19-Mj+EqF+|uy-a8) zf~D)=Lf<|Vk2wm*VDCHkF+tuO=Rkh1SdPe5q!wFWgI*0`R2>=z4eYDdt#jdTpDnH^ z>O|MI3?lazXDzJ9dCsR0M8w@XyeNyD0GF3mCKa?aR&8J{JADKwa91J3NwB6U279bM zKdE01sq(zUx?kT4a2=Ien#z<`oe&%Lvn6CNQ(j}>#-m9_JiG5lN}D=WMu)EA4v=cz zG3$~3nKo!285>jNw-JHZ%Q#l<9A6DU4<`!-yo2A=t#R)~bpu{Qf5@ketIR28b7K9T ztTOg+34g8pX+=5wpp2TCD!0{5k5s9TC!;aT{Fd_KLmNnBFWOkmU<<%z&a*q$Te2mQkj4jG{mlARKU%|{C3LXnp<;ZO-@uklwrTMr`R{X7y6$F5 ztfBF;wj}kUJA0N*nxrll;{;+yH!!dG^3OL=f4zy6L8z}ZSrr|3;c}X?eOG|}0eTL) zAo78`dqn$5_F|KI+r@5UJ*syCY3icBZ^E>6 z{w!1yrf-JKg})Xt9qjniQ)@WVZ9b1KNFF)dCjFuierBPyW=?*e;jt%2+Z3 zS{PExjIZiwAma@$)S_=x-NdRGmHNFAXv3FmklO?pW2z*p9pw@P&=ky+hPVBikS)hc zcFOi+Kt?l-ES32}A{7}|dDBH_4rgtRXQ55U(*~1=JY^Tz{ z@@8pgXIe-lpQm1fu1pb3B24HbaY|{%>tc2-hY?2&Q5on$1^qI>7sq>`@cDV!B6S>* zSU|Hge-7`S5;jkJL{XKq+OEU>#0vY;-(+aSOt8Zz^5 ztLKYOwVg39$qvR&RdSlLVMF!;sw(jZv|PQ#8_i9jS1}0w8kQ?;`-YB=P1(Jhr+vp+A~w*B}{)`PMI@I4d9Vre7=SD^=K zIsvL_Gc$y!67X!JP26VmD@#A^3qco}My`VUo(-nSm#m$)tD^1xw|F0v0(4a z1cu2N$zY57J4O-+?TE~5L=y!kxr*j=fhea6hWr^Lwl~Q)6<5F-^h%N2GCwIg3+7rR z$8~`di}_9((V6CQdGIVDSY*|}pCgq?PYgS@3H-~3QSOIMA5phXieYn9FVKWQolQ4y z4gs(d(U_)g=Nm94_QZaQ?9jt$+iVZcX$rR($~lPdqON2jTR*mPcb%Z?(>VQ#Z$R*X)b(#3SmXwvdCm zP;U^pyjKG@I#%!8$6;yeIjbs^6fiZ2=T0OXQ7XP#Wa>xDHT8C*M>q{zPS+CE`L6eR z1Sj3-CyjHcW{9RM-E!Mi(T>Tp%3HqSOa_jz;mb>p$wwMfDY}}z!^zmrsSLS{VAG|>Pn+k^wZNL4DWQkg>diyqK{TVq!u26a zp?oDL4izlGnhs1M6(O+zPnmiI2*FLTFt!TU#%42&A<#7H`Mn6H9cXT!3R2o*z(;q( zr1}sP`4{ICb1|JHJT7QWaK$D%fD~ z!WYE<#-hba*Y88DbIuboc$VmM$xSt}O0m%6PA?v0Y|JyIsbo|kMT3p1oZ2zpECJbt zW_POoi$U$6SdjB5s?qDdwRN<1xn&~6sqR1BV{c@Qd|!n63oN*Jp6(uopdzmo*7oaA z3dwsjT@mQgQoxqFZ9k5C1(T2eIEX~d%O_m+TJ6MzRk{%NP$i9=_Xp;nY^{>ap7R!xVuKX^G(K*HueB7 zm1}j}VLu+})#qXH&7eR?5(93(XN^&qRvYu4WPk0d1dM=fs-0)>7R?{zFX?bEV~nr>E6&)S)zu4JPyk}aZrrME0Y9+8j=P-*Cxrycc1 z7xoNoqZior0c{5V=uc4~6|%k+-6u2I#CcH5kPN}boaW(Z^QWNtygT61qs^};tv}kn zjT0>8*{UxZNXe&_c_iQW_=vpR=^VKVIcy1My^JaC| zs|WaCm?8H^O=OTuU1h)FG1%8;&MTr+DCV3MfbPbb)aLpdoN}Aqvtk3Ao z1aJ@92!b6*>;3^FaZi4h?&KuTD1_*XBcm`-pdIrW{?`DOO1?yhU8>T?(phoT{n5m= za;wpKW^CZ%8f<*9lBkzil$D|CuCe13sIF9hd%d0Z>HB`}GpV;ZN$7Y{gGikhCAylU zO;-^=MP);6dXCI@fiT}E!EZCcROD|?I7=w21z+b%DXZl2UY-F48^4MX{x z3=cCTL-*;S#kJTR6E6{m(j(XX{sHUK)~?V4TzyGY5j-IhUi};KDSi2N^c7Mg+O|qz z(=S}a+bJfo9T4U2 z=PhH3#~y>BhY^L~+TO7o3gKEGB2^5;(x9q4yE%cA^}ji{tRJ9{cj%Lh6@4;j4ikmy z`TNz{iMDU*7V(R8SQZKDU5t%Mh;GpgD|ArG$7(*znDG5xvT1ZTQ?luA1S4Qm5*t`* z8o-^oiGe29y-im_a3@p16qi}t!PHpE!u8zV#!nL6Z~URw*{|xF+E??+Cajr{LDPOT z29-UFV`U$^+Hkai_7YT20&9);7@M*?sW}Ap8l|7Ovp;wYk$&vjwC?c#zn zqllXnYam##=zQ_hyWJI1#lNSv9W;}uX^>amAeDNFWC&^VA9>VBZ{ze(~@PEr7fnU zMR>v#((@mNJi<^zRW`@1nX8UG$)DS~2le-Q-H?xsPV5Qdb)O3%?XhWyJLnY?N-Gz0 zA#2rW-27o{wYz?1o-a9K;w67}Ewrhv3lLh>xQMfy0K_+U!UN;?E++AOuB{}NR!#o< zaSxxg8UOJx6&~d2lb~JdQXSK|TFiB)%_i}v$dk78( zueka2Hf?NsYm7o=0Itwp#2yaa=dGMmpkP~u{}Mp;Jp46x>D%c)K4*NNPW2HiSs8Z= zX>2g#1iYujQB!eog~?%7jKnQBm3g@2=>eFaw6Nz9aPgcCy3XOVtw+iHiYb! zK63~PnN~JD#k>RASJHUaP@WJj1g>Uzv2M`7O-Ollt*xa9hKF)X6-uF)HNOdmvD z#F6FZGF{8o37UY(jnqO0keI*P$x`}|jaz84qq)IN8-aYX`rozyLq1OU_x=pRaaa2$ zpn;mMn3KQm1dDBM>||l5s<4CpTxnlHF4v!Ql<)Y%BBw+PE1cOWPz3XCGHKYJAgty0 zXx?}fj#}wo3R(tCoV4zcN6NT0`0F`BpdEUvUE8o!L%o|0_X9hrUBY_LtNBi~h%hYZ zgOWX$o6m2%shC(%IPXsN%Fo(DPgI#CAV|!g^km@$C|NxF$*ppK*J24t^d z+e2JMen@o-HBjqCZHx2gsTSZAMx;p&0!f!2|JnYvUPS!-ktehng?SQ)dgCI{PA0Un zAL+kPpQplaFlEt*bW^3X&oBpCJ-<|3qjQ{J4wdqq@c!g~{XVu+qtOofiS2s& zed25X$x)RPKF7|VjiMcT{B4z7k`{OTkK5P4i-Xmmqn52aVm{5x>hYyCUDaGci)UU< zK`QW^?!~~ed_Df%MnBxiTZpQM19FFqU)C}0s?Hji!I{bDhc)m3@_mfAPq9#c=W?5CGg~f|*1B_8X2D@J;J6 z6)ha%Xy@VQf~le zDf4{EI7uUFzWj9zT`nJjiyU{rH=OUk!`VH={WneDk}`0 zBXv9~-u@IQd0M}j(fpiOvpY}s>_|87*c7LlSjNkT(5Ab&VR2Pc@%1mLZ*jL7!PYl-|-}U<9G8Nd~$omSAq6#FE;Pz z#dOxS+&{v&b6YPRe=}ZQ{+ysN6nZ-rcu>4zu6!mZ;PkD|=hkj*hF43f)^YM-s6Fs1 zF8T9>ek_%G#iH}`kK;Q7?kpix7wu>r*QdAI6w@UHioiE;X~oP!MpIA|Dj2Gds>7_2 z09erGn!!zK_ieWBp4uS2ZS_-VLPisEv0Umvl{ajHleF#VOfSM{lk(YYbt+ zXUXr6kUiggK=Q^8R-Ddp^wA(LysKl{o=eJ1N}}*@#CnP$b|G9rU(>)@Frpk^*z60B zTrbbCU!Je!rJd4P&Iscy!NCqLWyMOxhc_y{SviZIgj*#g;;FeWfiuw;M6SN7?Oe*q zBE*@#R1@#qWjMA=!p4?ONvgqEsmq9(=AtUQ=L|@B7w-2Q0n?%HG(@Pv((=XmMEIKl zah&or5@TtjHpMNUbbCg)h4^t&9^!e4Fm+pm;)OH+l_=U@)I}hlA_(w!&M3$M@ZuBJ zgUA+tQq>4bO%?j^Xj~h=NJm`S(CJs*^7(M?q&NMILyTLxyL=ycZXq$@fgk-0(4>}c zHQ#alP+O(r%1#YjTS1)e;wFpV0hiEeGV=X-iGiroq@BW{o5RGO^Z~5Zh6!ESsMema z_|m29ghq?08~FEYBU^th;V8_42X%~F7~A$L+ETQPmV@EuqA^5l$b8e*_p9&s1V*qn z`qPZqmOX3|=jyG1M3+3Ssz3FphB<9PY4Qk3#BUvbA^CX-tMofmppG2R1F#_Z?6*Z5 zD&m#Qn>a06%)+AHhgm9ceU~X)Sce6Dvpdy`h~b=>b<%aD4IgYZ`;f{s?cy)n0EL;; zmIlbO*GiienD2d)%|`!j{!DViJ9fX76n}pT^5KMpHUp>nHs2~^#N&(?bF%efRD>}& z%4hJMxvsP&S*c725py>1{){+QaMw=XWSKQ?DuLQRmX>4+GJS*+oASi5Pt{_)V63IY?0CQ+J~QXc&>u^(ph?gjpgD|w)f;vXND zU}=owIZo3@2`)UbZGYXo{zvZA7C<>)Jsg5|od_e>a5hgT>)~a?B+Pt|@e6x`3nwpiiqK`=Q<8ro_AboIHEE z<9>=r7rH?3Wr8gna6o|M(4G<|`r=%dr#~w=E5CiZ^2s&!l{RqK;(E{1Z+nC(tG;6& z<=tAJ21^y_`|IJ6%K?RaE)e6khcW6L2BYHAX42C;A$g>pf7`1JfJ-Lo9zSh_CfL{g zdX4cfbNF5}GWx7z%@X21x|u&>HNngOTF!r?!H#tRHt0O=VU07gxNZ*sOWO-fYo<^z z)d6P0afYHcyf_vo~UiAC^wt9UuJ; z`NkTw5Qm+}@bzcZ5uzVE(p_>pFGu0%hcx88*}(G8PRV;c2yaG)B|g^e82nwMa!)wH+rt7=y=CaBd4@buc2d z%=Blk(WYXf+?%N~v~|u6#pq-@)M39SGzB6RQ_-{Bx*;W^H^3x}8c$mX`P%slYntqK zU!N}Ckr~$PiJe$QqurTTZ}#b5vHYozSxxvE@w|pNzsbGlamlG@P-mNPnB$X+xvVLa z+C)hJjC(Vc_BQU7J-y_7NR8^gB1yvgbdJDifLV6vb6U!hdkcCv206gqAZ8FkZ!t^G zYocj;Fqm9W+d}UsTRfOi_GScqR0OK?8;O0ZP<;HlWZmyEc}Qh?appD7t7FkMslV{e zyj++o+_`@~_YZwSWrq0s54gjz*+4aeP|twlgK(Qy2Rd?p(X~Rx@f*`4FeE zYehx<8E_`nnlV^Tw`XN`y_QTgb*Vgh0Y4qLHg-%YCU;YQX3-?k3Qc)V(05^+CoZew z1hci@+6$QYYR8jjANm%&tW0SGy30z`R1t`vdZ$UV!dSP0H<)4B3h6#toWk_Pk;rE~ zC}cstZ`FvsRUn;qMsMI$1@@{ey#_z{pJe&SjqD;I8x1Oo2Dv`dmz^6?71-X$jHb)R znf0|J@6F?nPL7XXGLyDz++375j{BCMDipWs#jBdM15&LfaFuAu(BHDqbQ2IXGOhc^zy@bKwppi<*T$s$)_L~^lY3SlhUY_Hv zwr`|gg<$D?Jacs{{V(cl@mAT9?|2&FlB;zOupVB^y_l1n+)O9x#1WSL-#7#hoTkXt z(N(N{4FsxYm9`$YoZ(*6lHZ335;hrca#>q4hc_eB$fv`LNFALgVf}vZIFBj?hKcns z^QWU%V?VbQpWCs~`0_|y4IUjzVczhquMVm)8AIP8er_xJGi8hPC5; z!NfO)A&tCE)+3rc4QyZ}V+Dg!DAPtTN%~J5^1hdVqd{8H|JL7yh4yWG@I++jyuxHE z3lBsRmE;YDk@iuE9!@*cU*6-`0(#6|1o&6+L382nDUh88e1lNFz+=Pi7jL)7V+D)G z^X`=;Ng$KjTsgN_5L9=`eXF43lCInFu?qJNjW-$mb+e_>_!IHPv0wYbn!XL$AyzT1 z*5K-czKQh>b#`Iu&!a~T{*k~9$Z)&ehaxAwi1G7Gsn>8z5*bAL-td8kO7GQFt!iH- z@T#w`8<}8^U3;?rdi3XXDVMar3)2>XxoN4H&yVeh)v)Ah~oL268AA3KTc7>cm%a_uP>^;Pf z83J~r`MIq6Q2U91%<=WVO;E)#sp)!n%WJ;@>>|kRm27(!`;1>wBCVKOR^;Ck+C~sUmg=d@#D2GHzx?_W zu^YuHimINDrNr(KY9UUTPz@S^KBX{~Z3or`^;!Rk)lWKz@!mv(!h*2_L~u6@EuG;*Kq?gP z$v=M157o{X)Q{WV1nL+^P%Q-EKk%tG=*0F!x7UCovRuTmo+rXYgb(IPzGhLP2nh)5 z7e|U8C=)|P;@dtyMG+Y=Z&nFO?I>@0IM7BC_2Z{B#k$Y*YZwgjkNa)G4esc>==+RxB(n_t+UZo>14K6lMPz3z#=;{ti{vtiHW=!HD9 zZU%u+b)qn{3$S-t@CgbBqa>L8xxUk}(LQX%=33_lc2e7FF*ChnYdK#%ri(ZjUJe9u zD{4qIN7a0n-&9KA{z5oqT_!fA9$l-4fEk{HRnMEqR`F_NyTf5;W)>E<`Dmbm8f(Pn&+plaOA`n$PMd+z3b?UkE59>#SF(&fuHq*x4IvU zTl0}uq48Fj9BS-wIrlHcIgoSd4aaZ}Gf4;J;Y-%R%C{&8-HlBLl?H0Ld#9ULv^dvd zV0!N(YO@AKvIAjanK_ z@eJ;y0}1e+`JiW(h8@C)ijHcQ^;kPKG;dS2HBTP`deO8hQ4K@A2_z-88S8R}J;&m0 zD4xg+D~7;>1Qr&jxxks(WYN|1Q$7l)!L)tg0#R^|a?66F>`PuFQ*!BWUa)dpDxL{Y z;7q#GsP-{M-F^?NRK`;R;@Q$Gdi+A3@E`|I=oOyvoZ|H|9jG$U^*sA{FvSajSJZKw z9HD~?!EqaU&@a>bld0DYyWwo#>74MjDI1!s><3*v=9@+Y+hb1V{ZCX&Wy5#>bVfLm{1G_D`5`(`vSw(1EfK=P+&s zfqwakxv&+JY7Ab0TUSxru^`+9n6pni-{mwbkyG};*#W5hm(DR=niKUbq?- z+rJ|JiJJ*^dG;?S#A>KK%GR$A{YI)g7_oQ*Z3-+$H@phFbK~Utc7V1)@~H!*`R)xb z{H1^gn{!1tL0wh2=^x)Tck5a~?&fx%NzN*H3TQ;w(b3o;LEKLVRp^a-cJOV}eEM7T zJGES@$>u&IP2OWcD&WK^bB0= zmWRxhwG^mk6&houjLj#D_vmfcmSj)p;*XbI27=VZ@oY;C0WEYU zbc0m0?DuJXxYLQ7geLyJ1disF?;!R=JZozE(p?lcY9J|?h0%V2rMrbADP#DV-j4mJ zu69RP8kf6UH3;i&%2%??(NnribKIo9H4egUd@y}ss(~ffQnBSuo6VX}53*XvW0#C+ zQY7_-NBoxM;KC=cvd761S5?YI)t|r!%LA$UfFJA%tp9YVWX07Lw7(W%(1 zn9#pC$0kyuA*!IsOszYA(XF0kqG;}Qlx~~lkPfhRPV$p7kpFlw6Z<#!qZnEG`&(*? z<(36Sk@XuOh^aQRE=8)$6C6tAo@y**gb^T7&`Onq+9jE$Jr%ToL&B{KfETv>GPr*} zzioQ(9PJ|5P2V1VR&v$a7k0dDZ2bH++`uu#R7|*GJz|ySk#0BrkD$`tt@NLieg#6i z%DK0ehwC)Pxl7KJ_md=}!`4N`DXLvmqw^KD^+Py+(xF{1ney6onpRZ~;RMcqWDc1| zjzRst2VqV)5;~ti*l5D=IviBxeKmITg_D?@R<)vHPJ-pCw$uK)Ho-Z&LcDSbeg>?5 zB0cg`P|#w#x|iwU(B^t2CY#FHe0>EsYO^-H-ZKhPUHqX4zJwn8-n-mJQv3;rw(3`m zu)bF#Ez#J*k{7M)YV=Hd>>tIutw0ohDU9Zy=rr)D2au z$upbI>KKo2P8q|Gki|P6B8d$AuK{pdgUrkzZI1L?*^#QQHrLm|L)SFR^FovPmBvs@jIWqgVuHLpGUer1*4KIN)K=GoBNN-8c&~WA`l&aV z=4w8Tr3}~8=0u&$;_w!lUZGTPIXY7DbDB80AZfp#Hro_!jY)TAYxBx-rSPeQ z%X}zKznI(cAFo{y!N10>SWTzPOlxW&t(emjJ1jD(!tO45o)xM&{i`!^&F$!Fe4GCQ zwm>#`cY%$X)Ci4c6`;l{2fgbz_(b5pcNeh#&1ps*ag>5s+3>bzHBz&h4G2jCJ~!(n zHSD6E(f>!*DT#n@Nb&b&L*~FTsDBRe&@#TWQq_E@A|G1hj{vi@5r=D(81c@{HanJ- z>h9$u7Dj#={J}KFQLeodZ`c%n+QO#!L%5Gbo3`tr)XwR^SV9c%e$83T<6c0hGVq|H zY5Bmgeh)RH2wDMkX04ot8q`~sl;r-#ZF=zCsk%J5N4s46jGH56z*HL3+MY2;P`;AA zz!s8C_@w*#Klx78&|Uz#2wV!J?+*v1&CyD2&KXlf6N}o#jga+g^f^2~FS*XfbURR& zcLZvsrgFCA4@fOs66%)cAjLe{v#z8;*<35e4k_Q!3@(yRkU92>vVA5ud0!%}FJ{(= z!SRodM?QwxEt7j+)r-nQ@*zL#Lb`}Kdh~a4qdmuwh?WzbhRNBp4o&sB=|Iu;@5y8W zJuMq9?U!yCV+yBIE=KP+cdp~Yj)gd;HdqNZ5E`5L!H>g z+C^(57i^9b@rg3V=FzQHXp1RKYbzv|$@by{2c0LOhI#TfJdjd7v*>LCi79w&%zGk$pJ@=T}ko8szy7A(HPPwiz!Yo$0eq?vqN4y;K}9wHRZ>qVWHtoy~%v zvs_^t31`s1Dh&{xy{*E}YzS$BSI6n^Hn9GWH77IXdq^WC&+5fkb~v+*ssfi$6mV&w zd^%w|n8UK3fj=HKi?16X2X}ai$K%+OL;he6#i%=FhBzrkV{n&AY7Rb?D%=!|3g6=k5}lghVI{!+zv)G9 zD9=P{(!DQTE`gz|#|X~pZDDENX%M>_&A;Qf9w3S8Cj58b*4kqTUC5kwY4TIMCi#Te z@`aNoNv>?F?v3<-M?f<0@#n0rPVH&L_VTrk?DJ_~R1kPjt_TD5#f|dEsRKqc_83Z) zSTci|0GpA(gUS73;xWFTS~TPrAL5K7n5a}xNs~wN=Q#Dacv~(<8c#rect@81_Z+?= z>@G0PF2^2x;u{R0P#XR9EV{U3U*Pc?>{>tA`E0+`l0xB_Z;L3-Cp}+~!v&M6kSOG6 zD3k1bUtZaL)t!PYcD0$+)Icuz#7QTSP5Hn1e4T9E2%G#NN_itF@Bg(C$gVT;sEZYA z7TJ+K$jw|CY>hSGy}!MO?6`V68b+XCT77wQ)0nI3u&P*H#7*#k<2gRjia$P3LL$! z(8sz3a9}w5&3ArZtBP_#OJel+*k&|#Vn0A>pC?%q+fof_dtF7tAWODX$L=ahb3d_2 zJ>a$T9NTa8{OZy_;=$A2j3@V2GXKYqeDlIrBjwP~h1v&Fr+Om|S?={4ICG*+0(5pc zD$&#fv?%<~w3tm(s*7kt0#|ENn~qdGyT>)Y)k7=%@A7U%Qa`l?0`4)N{$Igu&b;Vs z#KuII>KL6ljad@p%4KUlcTS61#=eaN;{Pe=DAlo@f8P4(8lB{e^uJEHy>)GE`taUZ zt1SOUE~~N4rnJ7L?LEZCu}kr#o+i&OgOj&d|M-*tA89ZmofEX#5aod)C2KU6g3&B;xI!g4o{UqJWpj_*nw~QbW>KLOI8CTSBYj-u>Nb(wA2;!*6Q% zC-JCJsWGYXIJzY+7g@21S=JsNA?UETW;CZLr^2T!$N73n>st~P_{gaUkqE}!;v-?s z;2KI5x?{vnJUz?@0!Y`T_YYJnCW>VdF(lz+k7wJ>pe&AK@gk*rfBbXA57)t*r?xNx zGu+|Bu0h<9A!OJ7D__ZDgX}1z8Vc{6VD#mLHk+hHwUbs8oOaOpt@7r$dBV9!0HU{4 z6|3_jIPgaZ+BU+_`uLykH&V6{=OS%%Hv-3Z%B=`z$BHKztx@NE!)?qRWVrzIt&W?k zjs7iBm?Erp8miziUjF)pMumSv27`CMHe+0f>7MCU3xRK-eHH$NrHOgCv;D zyO87tXIzHJmd+c7R#h`^|EjJ#GPDagwd&AB=FZI+>#&fkMwob7z5E%;bTF5RLlqCX z3ZY4BX=mEhja#4d%v=<(z&@PS>(Z;7@nb z9%h*aiI^i)7?J}szgn+8yThNM;t*?rT`I_hA6jEu6MASaQT5fP3grH0>dqkr>?`>_ zKP`6XL6i&H>)!(Yn!f`{P|R`aAkFQtXMjGZ$5w=dNh~$T{`ZK zS{_Mv<7y{3g=3{TD?b%h&n5D8u9*=3Mh#L7H1RcO!5?cKls8w4EQapYxRiM)j!mS zlg56TU#YTK_R(bm2C6PBLS{BQSm|OoW!j*qNmKV9UDjK2WZYL18y7V>c_Mb#%6E^c z@P&}Y`N6%~kAVApW1JXTF@;e>Q}1>K|DdD}+!|5S^35Y(v zR=N6k-o!8t=Kv(U4hnwPWk`%vp8Z!}uZ#G7*PsRKu$xZ0U0cMW-Z_dnz=Qvk@TzNy zy?L0WhGV?hNi`%WUI7ili}-lnwgTXnw6A#|-%+-P4(FJc zjbDAms>**7y7F1FBGn_c4aMv;`XN+#;7#=g(rAV^+yF^fje&gp``(UG|LNN*skWKd zBspm|gPTRSq+h^0#7B(Q70SAkFY06tH0ZnS>|uH#8z&x zY*4hD;{iD$`Hm2!;&UFZfnQu^Xf8}g--Qv$w>#%v^5PEdT!S6rUNv4nCo~}P0c)|! z@J3J{DrB#MrH?yqz&6^(T^3OHMiau;t7@K-#Pq$TDk6bHoWg|me^aZ*rKgb zJNBlkHYKXW3bh(ln*=rAgj!LfM%1X z$_=)3eiL)JFCq<&MDBY#X|Up?p{Cy;gkqa+cR|WQV6t-eR&6JIve1xmAONmRo7UT+ z{NJLBbJWgDW(0RBNj0uaA*`T*DpTGMcdaJ%*>d9I_w9n$T|GlP*n7~(Y<%1kz7rCu z8$!rS!p~DFys_=Hi#HJN_r>)#;g&;0w;|U}0Uv1uH^}@|VUw^wdQg=t;zVbe`NLJ# z!N(}v!Xycw$OFA%ctD#3n^|@zJ?EP>3IokR zd=>nLKq)&DW>uT6s!J7!9+UcgiZLPXy}MGy7Fcu+xU z1lvj3=Q#O~6erc2(31-}RJhdJl<-1*_8X}xJCB(AqDCv#Y!>(wX#x=DEMeK?Zxo9B z^d(y2VRQ>0h$M$u!*@6xS2Xax;^$Te$x#~%3OS~T&qpxHFRl1JwQzsyOjR#Pm?nv& z^w^>~P_>oI?v&Si%E1|Yr#h~kk25r)dE!IRt}oZh?HM0^d`!H+<&(s)VDm`v>;TF4H56nGvBHpZBZ#9vgN8rwBn${1!lvz5oL`q)cwvhfp^ zW2Fdjtp$*Q`HnHT2pt zP=iwmEKodOsHK@ard!HzE`sPk&GXdpxm51S}u%K z(^KaNMjDPf;17LTO7v@mLo{2Nf5~V(x}C}Mq0&QYDWFXwIlPx{*f};I_&;1s`b;ol zJ$~as;S@r&XW&e1I;MU$-sAn4kqxUx?hzx|aiBzB>{+D&H0~|%(qLDLfpx&;g!kHs zLxZ!P;rWH+UYYv)zwMH-v=z*8=5#CL$1K<5kRPjBS<>pxk*7qsL2qceuO=x}a7v^X zNHVzr0%}5d{Ma2NPuc55`%gZwR~-O?ulMEu%I=r7M+=M3sN|)6evJRGOJGE>Lwt$V zUw-@KzgJ%99ce)aFiLz3A}#gEfa$0Itbk^hAe0Z-M&1^u7N4NqCqZqM@{YRtd&1?l zdn_wki-6Ooj`L_kors>FR7)&<%KsL1w)#D?Vj*+QK+aS_nr((tb?MDl{KssTz0aS1 zx3O??h&A%+&V`@Yi1yH*s-tce?{7Z8QqW@q=s+`s>K$2^JCzCRmE5vPc2=J{(6N`- zE$PjemIt97CB?@m{~@kFY~$vmk}AyvHQ9pDYO-6Y%f%7%&DKC_nY|Pb!cA@vYtx_iEL1|btax1m)Wtp^-lv$XI`)Y5me%3glWm!N-$bvyTa&Vy)`vS^YgjUWO}{eF}mLI+@cLX#ihqqR48s~YMmqz>gvaRWs9EEZPgGk)wi}~A@A{l8=go~ zC4xH1rL<|W&+Qho+f#^^#kc&JTAN1_9GQun7MkLmS*?}SUiAC-ZqE|R3rp!F8=IRW z%U)ip!oMFx_6L}_0ZyuwJDc_OCj$P0=5bw2g9*DyVUavxYA&gdG$KMB^}eU5ELxrIf^O?OS?pMGS| zVGyhC`EBPp^!P%d!rAg z`ZtNrf0xlK8F(Wn6=drmgpU_dvvJ#*y+^d z`fJf;qYnG8J`O7B^+`Tg-%P_yigld@WvLjGR>{OlY zkFg0h*E1}vj%jfFGvqU+Hnlbj#bdkP^g}9bRjDs)0EODN$E%7wjkN|$UtF03^Gd@? z_N3KXnM~l*#V-jj&aTp-GA+x9kMBiU-!|QktocL6rTwN^L>n5XFb4|F6GJ`8_~n^P z_>e2)BZv>odKs+-%yh2$TAJ5;su`WI;+1H|vGh%l&*{&J*pzbq18Ceo?@}T-crBhG zP~X=oIM#)5R^|u4|Ak7-m0ucjE|sD*>%+3L&){{H30t_1ki6ymAP2{8FR}#F@&HAP zyC3dL7aAd+vB$;>0vHSGdpSO-1PpxkAz+AkI|@XNopW7@LCf7~Sy?3BI-Eg~WYF>^ z8&=c4wo7EBXy%U1>5<)g^aky<|C%P|K7$dHo%86VbB^%f=egMAOlz~MP;f$vmO_=& zh+Cckz@@>Cs*Cwl=BPy{h%DzEA1wQ}DXDP5x&OBt1Sd!xC<-Vi)SHeuV-g4TxkHe# zgZBuCiX*V$3S!8jcpk1(n|UswJHA2zF>m-)DI~uc*ctt^T<#~Uw(W~!GJXmK12Mtt-&4=9M5J^?6ceOC?Lw385X z0NzitY5()DZAIc%co_LO!DU5)@)`)Hys-i~uYvF{`=c!s-VMZJ{rCsYWEE6yowCD0 zaM@i8g1Fa(&m_3y0#pBv>|ruD5no$t|x8t6?y*k z@{D39tt~Pa-p!N~TX|u0$*98x^+@bM@L74ZTb&4sJEUENa2QOMpn z(A+IH08;Z&^A#$oZcbu5n9+XFSbi+)I2>>iUdZns-lwsemfWr$!=!4o+q*98Q2#Z^ zi{I5th=K9!YKN?-tXo4EQDYg}XM&Xwox7(!SXu=CzQwz2q?$?bc&Sghi|Yqf2t8a- zYRkky2F)SkzZOG^mk&3Gkq#5@VRY<2P`f@|j6kdafQ+_pa7H=p_aUVNW~TUel(fOj z>nLm0KW$QaPixxUzN6wvfq>AI1B~Z`zB`2Now^m4{GEh+*agF+!QRO}*Y(Zuw#Gne zRm#d~PJaFc(%_E*xAB?;=GWT@W_ z{3y0|VJn5&Xw`Q;(3Z3x_7-42H+bKy73bU8>>j+Aw)l2)t1&ouyFgC*g`N?BBi=>I zY#7-9>bJ!N9yimU!j%lA|I6B;*;%vvv>e>04YHQC+KUG)WZ3!$8OPwC+* zRROo}jwTK-#PT(%+|_w{H2Lxnr@ion%>3>4EoK!}NF(HZ6${j)INPa2BX-E6-_#6F2ESwf{-x*v zmA@csXbx3Gt3(pS}1yanMeHF8yl5Vp_r)t;o945(Eq4LKzDjymc$(w3b< z^sTy-f4!2A+YgF62g8NWP`h-PgJn{v??6w3U?0LEraK=t+Z!K6-VbTSa;p0#q`+p( zHHunr!zRcJ8|Xi^qNkkoJDJV4PBq!D<>}KremFkxihXy*d3&sW>&-=mqKU2xmkP+G zpe>E%Il_z|4m|Ji)IcJ0_I7GK&v~Rv)A2t_KO;ppZ=|;@uLTJY2(1~%6nj9rb)53r z`Cd=CFTQYZ=ZIVtu(QIP6(syST1~ztX-fVLWk)KQ6Z=j*Eq>q7NNJ>-dLgTpw6*Ot z{~1}eG5N_wQEVE_fv^6`P|oMMJT!dNSJj!Tmny20taZ^Zijv0OrLZlSw5a&%GfVQs zmmz88<68@O7YaM0`6Qs5OUg1Yqnhfl;?HMWBP*RU@F#Nf1_ZfgC!Rp+QSGkuS<(ly zB(#0C4W%4 z2&o!=Ie45@sTe0U+`rC!H?T?NlLu?(WL1B&!YR7+Ggrf^1)qUvcwQRB@@G}rcmAfb zJI71o;uUrrpc2GDo~jZlK8@_Cr$k@bmG?=9cV)xE35II6I^atlmQm9DeiO-}$abdt zCK^VuL9yJmjZc-8t>7E2D&ZMC$8GtUe#GWJHe5Rxxpqpjgi9C*tGud2EK$Ry;9PJ< z=eghcPteQ~)Zvm2Zpq3q3iH9Pv^3~39i^WiW5&22GIgZx`t0-!O;jjE&r4Lrsa4NV zBaePonP4{X$!os7$*7`(FZdm1qOomwddbvBuh?s9t1$AycE!od%IU2idCDk4ZmTn! zl~jC29QL1bupPdQ{Yw$2k-Zq7q0{P38iu{Sk`!28>Unr;`h;{J@-E$-f_8dU(z+)k z5GZU{lTtca^RyD|FZ*pW0jOiDC#)=Ekgh>@**!Wgp~uK-W5&!P8$&tN(wej`;WgAJ zYzIqEVS3zlcbsSqT5F$=n~|eGyYn%~n(8XtbwYDBQ8C*r{pkhTXQ8Rk?3thp^#?qn zzl7qt?AKnBo73bsUNC=Ci*e_xs4|m(5~gr{%_TB^pMJ0sbM~n78RQh(XQf#Mmt(P)wBCHCd;Rv`&!lahF?3=wkc1mcdroK zIpyDNdQn#;(RpEE&cFPEjW@U{5=ZIAs5e?|V#83cbuUw@IKZ$`k>ooX%j)|^$ke=@ z>Qvw%aLzjwGgH)-jTKghDxLQ*s5^ls0>uoz{kS_%5`n6(qJ_=6kLekS4;NDHa{pU} zik>GHf$r1=+3;LFT#?T@Y}rJ#OzHfEDr{8b9XNKlGt4&O?r>dvd&obOZ`%_3QsysI z)XTFhXlC{8s88W5cVbZDYO;`f-by&K1s_*8mGLICMNpAS!0_aHlh6h0i`0IadM%}< zI;J`u?UY%1(pgwDnGB;svw5ivW>(gIgyi18mAHOmUrW7!D0g&|$`JgDf9NcOUt77n zQADSvG~YL1F5_}hP7KDrws{;`@t8*yQg-91+7q_*YW2CA}$1*J5|5LZA z9<`78V{=nC_kzGs5Lh{eFYce1 zZ{91{t-Kus)GuGP)TR8bWED}YkOUNw7B&rxeVj^FE3nAiX=L53;?_SxiiY&Ai@P4G z^wA`Z%{uBUW!U`ARNL1hB(SNrZH8JO_+*`m>iqN<<9-$vx2u6o{F|!qJ?eu?RCZ-4 z-QmVpr7sBfh3Q(YvIv(nb1B_`P{nkoU1nkNl#*KoD95@1u*a$jEI(?e_{?2jN{3r# zbx4l+d=jsSd7=C&78Rv}YfQEJ{Ae3;M0#&>^kTs?5efMBm))c|W$H;ZvXo~ETN&j1 z%geL!T7vNMQ01BU?sL-;?)Z6g-}X_Qra4Xg-5LRIy}518D1$b1`gRDG1W$#Ju@vGh z*t^J|@U-B7$bIx^AUV3ZTI0PfHm}zHsj?B5xn`%Cn0jKDg)LYVD!*u8LA5vY@IETh z5LxV*pEzmo$_P+Yh6xj&;~L)Zk^kENj+8NUQPq%XkUurNm_NPL&brxQAhfL&P?&rO z$vaMV1{Hi=P%%}aw38DpbK@vsuIwEc4{XlTxO3gbNNH=tywG@5!m}frx^SYTh_KaF zDg{g@=&l)b@KXZEOXLAm|Edd=j7okmmtS1NrdR#tEn8^Wzby>lBRk1aU^jos-I4_R&gY&<9dV@4qSIy}e$ab?N=14({iEh#ugy{<#xUUuVf;&VohY##k@ zzrL&!s>wEL(1PPyx|E{9cp@&O7WaX_hK*Oh*S?zW+VD$VR6V4QsEvBXmopjI=(z=Y z?N4PlpSb^$@gtBapQ}oVr{+Uk2MNmlv(!-l|I7%l9}LF#g%oXL#OEHS5$!^IVM?l5 z%$++iI#Nv=!d}9K2l$AGgGNTG!@;;lN2T}|9-)UrBO@69D0l3(i`ofsE<_ZF-3-S` z5B&nj$!%y9{`SLq(ws8GL+4aoV6cU+r0Ao(Pq;RVs6U~$Fc_Ma%5K)UmCQ*?xo%`+ zslZ|)gSH-gHeKOH~H#o6{2LDkw9?Vim6)Cn-JB=?@& z<29D-)2qskSGl6V!Z literal 0 HcmV?d00001 diff --git a/docs/installation.md b/docs/installation.md deleted file mode 100644 index 05f3ed5..0000000 --- a/docs/installation.md +++ /dev/null @@ -1,113 +0,0 @@ -# nf-core/cageseq: Installation - -To start using the nf-core/cageseq pipeline, follow the steps below: - - - -* [Install NextFlow](#install-nextflow) -* [Install the pipeline](#install-the-pipeline) - * [Automatic](#automatic) - * [Offline](#offline) - * [Development](#development) -* [Pipeline configuration](#pipeline-configuration) - * [Docker](#docker) - * [Singularity](#singularity) - * [Conda](#conda) - * [Configuration profiles](#configuration-profiles) -* [Reference genomes](#reference-genomes) - - -## Install NextFlow -Nextflow runs on most POSIX systems (Linux, Mac OSX etc). It can be installed by running the following commands: - -```bash -# Make sure that Java v8+ is installed: -java -version - -# Install Nextflow -curl -fsSL get.nextflow.io | bash - -# Add Nextflow binary to your PATH: -mv nextflow ~/bin/ -# OR system-wide installation: -# sudo mv nextflow /usr/local/bin -``` - -See [nextflow.io](https://www.nextflow.io/) for further instructions on how to install and configure Nextflow. - -## Install the pipeline - -### Automatic -This pipeline itself needs no installation - NextFlow will automatically fetch it from GitHub if `nf-core/cageseq` is specified as the pipeline name. - -### Offline -The above method requires an internet connection so that Nextflow can download the pipeline files. If you're running on a system that has no internet connection, you'll need to download and transfer the pipeline files manually: - -```bash -wget https://github.com/nf-core/cageseq/archive/master.zip -mkdir -p ~/my-pipelines/nf-core/ -unzip master.zip -d ~/my-pipelines/nf-core/ -cd ~/my_data/ -nextflow run ~/my-pipelines/nf-core/cageseq-master -``` - -To stop nextflow from looking for updates online, you can tell it to run in offline mode by specifying the following environment variable in your ~/.bashrc file: - -```bash -export NXF_OFFLINE='TRUE' -``` - -### Development - -If you would like to make changes to the pipeline, it's best to make a fork on GitHub and then clone the files. Once cloned you can run the pipeline directly as above. - - -## Pipeline configuration -By default, the pipeline loads a basic server configuration [`conf/base.config`](../conf/base.config) -This uses a number of sensible defaults for process requirements and is suitable for running -on a simple (if powerful!) local server. - -Be warned of two important points about this default configuration: - -1. The default profile uses the `local` executor - * All jobs are run in the login session. If you're using a simple server, this may be fine. If you're using a compute cluster, this is bad as all jobs will run on the head node. - * See the [nextflow docs](https://www.nextflow.io/docs/latest/executor.html) for information about running with other hardware backends. Most job scheduler systems are natively supported. -2. Nextflow will expect all software to be installed and available on the `PATH` - * It's expected to use an additional config profile for docker, singularity or conda support. See below. - -### Docker -First, install docker on your system: [Docker Installation Instructions](https://docs.docker.com/engine/installation/) - -Then, running the pipeline with the option `-profile docker` tells Nextflow to enable Docker for this run. An image containing all of the software requirements will be automatically fetched and used from dockerhub (https://hub.docker.com/r/nfcore/cageseq). - -### Singularity -If you're not able to use Docker then [Singularity](http://singularity.lbl.gov/) is a great alternative. -The process is very similar: running the pipeline with the option `-profile singularity` tells Nextflow to enable singularity for this run. An image containing all of the software requirements will be automatically fetched and used from singularity hub. - -If running offline with Singularity, you'll need to download and transfer the Singularity image first: - -```bash -singularity pull --name nf-core-cageseq.simg nf-core/cageseq -``` - -Once transferred, use `-with-singularity` and specify the path to the image file: - -```bash -nextflow run /path/to/nf-core-cageseq -with-singularity nf-core-cageseq.simg -``` - -Remember to pull updated versions of the singularity image if you update the pipeline. - -### Conda -If you're not able to use Docker _or_ Singularity, you can instead use conda to manage the software requirements. -This is slower and less reproducible than the above, but is still better than having to install all requirements yourself! -The pipeline ships with a conda environment file and nextflow has built-in support for this. -To use it first ensure that you have conda installed (we recommend [miniconda](https://conda.io/miniconda.html)), then follow the same pattern as above and use the flag `-profile conda` - -### Configuration profiles - -See [`docs/configuration/adding_your_own.md`](configuration/adding_your_own.md) - -## Reference genomes - -See [`docs/configuration/reference_genomes.md`](configuration/reference_genomes.md) diff --git a/docs/output.md b/docs/output.md index 0a3c543..daff790 100644 --- a/docs/output.md +++ b/docs/output.md @@ -5,6 +5,7 @@ This document describes the output produced by the pipeline. Most of the plots a ## Pipeline overview + The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: @@ -12,6 +13,7 @@ and processes data using the following steps: * [MultiQC](#multiqc) - aggregate report, describing results of the whole pipeline ## FastQC + [FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your reads. It provides information about the quality score distribution across your reads, the per base sequence content (%T/A/G/C). You get information about adapter contamination and other overrepresented sequences. For further reading and documentation see the [FastQC help](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). @@ -25,8 +27,8 @@ For further reading and documentation see the [FastQC help](http://www.bioinform * `zips/sample_fastqc.zip` * zip file containing the FastQC report, tab-delimited data file and plot images - ## MultiQC + [MultiQC](http://multiqc.info) is a visualisation tool that generates a single HTML report summarising all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in within the report data directory. The pipeline has special steps which allow the software versions used to be reported in the MultiQC output for future traceability. @@ -38,4 +40,4 @@ The pipeline has special steps which allow the software versions used to be repo * `Project_multiqc_data/` * Directory containing parsed statistics from the different tools used in the pipeline -For more information about how to use MultiQC reports, see http://multiqc.info +For more information about how to use MultiQC reports, see [http://multiqc.info](http://multiqc.info) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md deleted file mode 100644 index 0c67d47..0000000 --- a/docs/troubleshooting.md +++ /dev/null @@ -1,30 +0,0 @@ -# nf-core/cageseq: Troubleshooting - - - -## Input files not found - -If only no file, only one input file , or only read one and not read two is picked up then something is wrong with your input file declaration - -1. The path must be enclosed in quotes (`'` or `"`) -2. The path must have at least one `*` wildcard character. This is even if you are only running one paired end sample. -3. When using the pipeline with paired end data, the path must use `{1,2}` or `{R1,R2}` notation to specify read pairs. -4. If you are running Single end data make sure to specify `--singleEnd` - -If the pipeline can't find your files then you will get the following error - -```bash -ERROR ~ Cannot find any reads matching: *{1,2}.fastq.gz -``` - -Note that if your sample name is "messy" then you have to be very particular with your glob specification. A file name like `L1-1-D-2h_S1_L002_R1_001.fastq.gz` can be difficult enough for a human to read. Specifying `*{1,2}*.gz` wont work give you what you want Whilst `*{R1,R2}*.gz` will. - - -## Data organization -The pipeline can't take a list of multiple input files - it takes a glob expression. If your input files are scattered in different paths then we recommend that you generate a directory with symlinked files. If running in paired end mode please make sure that your files are sensibly named so that they can be properly paired. See the previous point. - -## Extra resources and getting help -If you still have an issue with running the pipeline then feel free to contact us. -Have a look at the [pipeline website](https://github.com/nf-core/cageseq) to find out how. - -If you have problems that are related to Nextflow and not our pipeline then check out the [Nextflow gitter channel](https://gitter.im/nextflow-io/nextflow) or the [google group](https://groups.google.com/forum/#!forum/nextflow). diff --git a/docs/usage.md b/docs/usage.md index f4f4e02..012cd5b 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -2,8 +2,6 @@ ## Table of contents - - * [Table of contents](#table-of-contents) * [Introduction](#introduction) * [Running the pipeline](#running-the-pipeline) @@ -12,20 +10,23 @@ * [Main arguments](#main-arguments) * [`-profile`](#-profile) * [`--reads`](#--reads) - * [`--singleEnd`](#--singleend) + * [`--single_end`](#--single_end) * [Reference genomes](#reference-genomes) * [`--genome` (using iGenomes)](#--genome-using-igenomes) * [`--fasta`](#--fasta) - * [`--igenomesIgnore`](#--igenomesignore) + * [`--igenomes_ignore`](#--igenomes_ignore) * [Job resources](#job-resources) * [Automatic resubmission](#automatic-resubmission) * [Custom resource requests](#custom-resource-requests) * [AWS Batch specific parameters](#aws-batch-specific-parameters) * [`--awsqueue`](#--awsqueue) * [`--awsregion`](#--awsregion) + * [`--awscli`](#--awscli) * [Other command line parameters](#other-command-line-parameters) * [`--outdir`](#--outdir) * [`--email`](#--email) + * [`--email_on_fail`](#--email_on_fail) + * [`--max_multiqc_email_size`](#--max_multiqc_email_size) * [`-name`](#-name) * [`-resume`](#-resume) * [`-c`](#-c) @@ -37,10 +38,9 @@ * [`--plaintext_email`](#--plaintext_email) * [`--monochrome_logs`](#--monochrome_logs) * [`--multiqc_config`](#--multiqc_config) - - ## Introduction + Nextflow handles job submissions on SLURM or other environments, and supervises running the jobs. Thus the Nextflow process must run until the pipeline is finished. We recommend that you put the process running in the background through `screen` / `tmux` or similar tool. Alternatively you can run nextflow within a cluster job submitted your job scheduler. It is recommended to limit the Nextflow Java virtual machines memory. We recommend adding the following line to your environment (typically in `~/.bashrc` or `~./bash_profile`): @@ -52,6 +52,7 @@ NXF_OPTS='-Xms1g -Xmx4g' ## Running the pipeline + The typical command for running the pipeline is as follows: ```bash @@ -70,6 +71,7 @@ results # Finished results (configurable, see below) ``` ### Updating the pipeline + When you run the above command, Nextflow automatically pulls the pipeline code from GitHub and stores it as a cached version. When running the pipeline after this, it will always use the cached version if available - even if the pipeline has been updated since. To make sure that you're running the latest version of the pipeline, make sure that you regularly update the cached version of the pipeline: ```bash @@ -77,31 +79,40 @@ nextflow pull nf-core/cageseq ``` ### Reproducibility + It's 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/cageseq releases page](https://github.com/nf-core/cageseq/releases) and find the latest version number - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. - ## Main arguments ### `-profile` -Use this parameter to choose a configuration profile. Profiles can give configuration presets for different compute environments. Note that multiple profiles can be loaded, for example: `-profile docker` - the order of arguments is important! -If `-profile` is not specified at all the pipeline will be run locally and expects all software to be installed and available on the `PATH`. +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, 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. + +The pipeline also dynamically loads configurations from [https://github.com/nf-core/configs](https://github.com/nf-core/configs) when it runs, making multiple config profiles for various institutional clusters available at run time. For more information and to see if your system is available in these configs please see the [nf-core/configs documentation](https://github.com/nf-core/configs#documentation). + +Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! +They are loaded in sequence, so later profiles can overwrite earlier profiles. + +If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended. -* `awsbatch` - * A generic configuration profile to be used with AWS Batch. -* `conda` - * A generic configuration profile to be used with [conda](https://conda.io/docs/) - * Pulls most software from [Bioconda](https://bioconda.github.io/) * `docker` * A generic configuration profile to be used with [Docker](http://docker.com/) * Pulls software from dockerhub: [`nfcore/cageseq`](http://hub.docker.com/r/nfcore/cageseq/) * `singularity` * A generic configuration profile to be used with [Singularity](http://singularity.lbl.gov/) - * Pulls software from DockerHub + * Pulls software from DockerHub: [`nfcore/cageseq`](http://hub.docker.com/r/nfcore/cageseq/) +* `conda` + * Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker or Singularity. + * A generic configuration profile to be used with [Conda](https://conda.io/docs/) + * Pulls most software from [Bioconda](https://bioconda.github.io/) * `test` * A profile with a complete configuration for automated testing * Includes links to test data so needs no other parameters @@ -109,6 +120,7 @@ If `-profile` is not specified at all the pipeline will be run locally and expec ### `--reads` + Use this to specify the location of your input FastQ files. For example: ```bash @@ -123,21 +135,22 @@ Please note the following requirements: If left unspecified, a default pattern is used: `data/*{1,2}.fastq.gz` -### `--singleEnd` -By default, the pipeline expects paired-end data. If you have single-end data, you need to specify `--singleEnd` on the command line when you launch the pipeline. A normal glob pattern, enclosed in quotation marks, can then be used for `--reads`. For example: +### `--single_end` + +By default, the pipeline expects paired-end data. If you have single-end data, you need to specify `--single_end` on the command line when you launch the pipeline. A normal glob pattern, enclosed in quotation marks, can then be used for `--reads`. For example: ```bash ---singleEnd --reads '*.fastq' +--single_end --reads '*.fastq' ``` It is not possible to run a mixture of single-end and paired-end files in one run. - ## Reference genomes The pipeline config files come bundled with paths to the illumina iGenomes reference index files. If running with docker or AWS, the configuration is set up to use the [AWS-iGenomes](https://ewels.github.io/AWS-iGenomes/) resource. ### `--genome` (using iGenomes) + There are 31 different species supported in the iGenomes references. To run the pipeline, you must specify which to use with the `--genome` flag. You can find the keys to specify the genomes in the [iGenomes config file](../conf/igenomes.config). Common genomes that are supported are: @@ -171,33 +184,48 @@ params { ``` + ### `--fasta` + If you prefer, you can specify the full path to your reference genome when you run the pipeline: ```bash --fasta '[path to Fasta reference]' ``` -### `--igenomesIgnore` +### `--igenomes_ignore` + Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`. ## Job resources + ### Automatic resubmission + Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the steps in the pipeline, if the job exits with an error code of `143` (exceeded requested resources) it will automatically resubmit with higher requests (2 x original, then 3 x original). If it still fails after three times then the pipeline is stopped. ### Custom resource requests + Wherever process-specific requirements are set in the pipeline, the default value can be changed by creating a custom config file. See the files hosted at [`nf-core/configs`](https://github.com/nf-core/configs/tree/master/conf) for examples. If you are likely to be running `nf-core` pipelines regularly it may be a good idea to request that your custom config file is uploaded to the `nf-core/configs` git repository. Before you do this please can you test that the config file works with your pipeline of choice using the `-c` parameter (see definition below). You can then create a pull request to the `nf-core/configs` repository with the addition of your config file, associated documentation file (see examples in [`nf-core/configs/docs`](https://github.com/nf-core/configs/tree/master/docs)), and amending [`nfcore_custom.config`](https://github.com/nf-core/configs/blob/master/nfcore_custom.config) to include your custom profile. -If you have any questions or issues please send us a message on [`Slack`](https://nf-core-invite.herokuapp.com/). +If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack). ## AWS Batch specific parameters -Running the pipeline on AWS Batch requires a couple of specific parameters to be set according to your AWS Batch configuration. Please use the `-awsbatch` profile and then specify all of the following parameters. + +Running the pipeline on AWS Batch requires a couple of specific parameters to be set according to your AWS Batch configuration. Please use [`-profile awsbatch`](https://github.com/nf-core/configs/blob/master/conf/awsbatch.config) and then specify all of the following parameters. + ### `--awsqueue` + The JobQueue that you intend to use on AWS Batch. + ### `--awsregion` -The AWS region to run your job in. Default is set to `eu-west-1` but can be adjusted to your needs. + +The AWS region in which to run your job. Default is set to `eu-west-1` but can be adjusted to your needs. + +### `--awscli` + +The [AWS CLI](https://www.nextflow.io/docs/latest/awscloud.html#aws-cli-installation) path in your custom AMI. Default: `/home/ec2-user/miniconda/bin/aws`. Please make sure to also set the `-w/--work-dir` and `--outdir` parameters to a S3 storage bucket of your choice - you'll get an error message notifying you if you didn't. @@ -206,12 +234,23 @@ Please make sure to also set the `-w/--work-dir` and `--outdir` parameters to a ### `--outdir` + The output directory where the results will be saved. ### `--email` + Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run. +### `--email_on_fail` + +This works exactly as with `--email`, except emails are only sent if the workflow is not successful. + +### `--max_multiqc_email_size` + +Threshold size for MultiQC report to be attached in notification email. If file generated by pipeline exceeds the threshold, it will not be attached (Default: 25MB). + ### `-name` + Name for the pipeline run. If not specified, Nextflow will automatically generate a random mnemonic. This is used in the MultiQC report (if not default) and in the summary HTML / e-mail (always). @@ -219,6 +258,7 @@ This is used in the MultiQC report (if not default) and in the summary HTML / e- **NB:** Single hyphen (core Nextflow option) ### `-resume` + Specify this when restarting a pipeline. Nextflow will used cached results from any pipeline steps where the inputs are the same, continuing from where it got to previously. You can also supply a run name to resume a specific run: `-resume [run-name]`. Use the `nextflow log` command to show previous run names. @@ -226,6 +266,7 @@ You can also supply a run name to resume a specific run: `-resume [run-name]`. U **NB:** Single hyphen (core Nextflow option) ### `-c` + Specify the path to a specific config file (this is a core NextFlow command). **NB:** Single hyphen (core Nextflow option) @@ -233,7 +274,8 @@ Specify the path to a specific config file (this is a core NextFlow command). Note - you can use this to override pipeline defaults. ### `--custom_config_version` -Provide git commit id for custom Institutional configs hosted at `nf-core/configs`. This was implemented for reproducibility purposes. Default is set to `master`. + +Provide git commit id for custom Institutional configs hosted at `nf-core/configs`. This was implemented for reproducibility purposes. Default: `master`. ```bash ## Download and use config file with following git commid id @@ -241,6 +283,7 @@ Provide git commit id for custom Institutional configs hosted at `nf-core/config ``` ### `--custom_config_base` + If you're running offline, nextflow will not be able to fetch the institutional config files from the internet. If you don't need them, then this is not a problem. If you do need them, you should download the files from the repo and tell nextflow where to find them with the @@ -261,22 +304,28 @@ nextflow run /path/to/pipeline/ --custom_config_base /path/to/my/configs/configs > files + singularity containers + institutional configs in one go for you, to make this process easier. ### `--max_memory` + Use to set a top-limit for the default memory requirement for each process. Should be a string in the format integer-unit. eg. `--max_memory '8.GB'` ### `--max_time` + Use to set a top-limit for the default time requirement for each process. Should be a string in the format integer-unit. eg. `--max_time '2.h'` ### `--max_cpus` + Use to set a top-limit for the default CPU requirement for each process. Should be a string in the format integer-unit. eg. `--max_cpus 1` ### `--plaintext_email` + Set to receive plain-text e-mails instead of HTML formatted. ### `--monochrome_logs` + Set to disable colourful command line output and live life in monochrome. ### `--multiqc_config` + Specify a path to a custom MultiQC configuration file. diff --git a/environment.yml b/environment.yml index e20a4d3..2c81c55 100644 --- a/environment.yml +++ b/environment.yml @@ -6,6 +6,10 @@ channels: - bioconda - defaults dependencies: + - conda-forge::python=3.7.3 + - conda-forge::markdown=3.1.1 + - conda-forge::pymdown-extensions=6.0 + - conda-forge::pygments=2.5.2 # TODO nf-core: Add required software dependencies here - - fastqc=0.11.8 - - multiqc=1.6 + - bioconda::fastqc=0.11.8 + - bioconda::multiqc=1.7 diff --git a/main.nf b/main.nf index 1460cde..fdb3a01 100644 --- a/main.nf +++ b/main.nf @@ -9,7 +9,6 @@ ---------------------------------------------------------------------------------------- */ - def helpMessage() { // TODO nf-core: Add to this help message with new command line parameters log.info nfcoreHeader() @@ -22,39 +21,41 @@ def helpMessage() { nextflow run nf-core/cageseq --reads '*_R{1,2}.fastq.gz' -profile docker Mandatory arguments: - --reads Path to input data (must be surrounded with quotes) - -profile Configuration profile to use. Can use multiple (comma separated) - Available: conda, docker, singularity, awsbatch, test and more. + --reads [file] Path to input data (must be surrounded with quotes) + -profile [str] Configuration profile to use. Can use multiple (comma separated) + Available: conda, docker, singularity, test, awsbatch, and more Options: - --genome Name of iGenomes reference - --singleEnd Specifies that the input is single end reads + --genome [str] Name of iGenomes reference + --single_end [bool] Specifies that the input is single-end reads - References If not specified in the configuration file or you wish to overwrite any of the references. - --fasta Path to Fasta reference + References If not specified in the configuration file or you wish to overwrite any of the references + --fasta [file] Path to fasta reference Other options: - --outdir The output directory where the results will be saved - --email Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits - --maxMultiqcEmailFileSize Theshold size for MultiQC report to be attached in notification email. If file generated by pipeline exceeds the threshold, it will not be attached (Default: 25MB) - -name Name for the pipeline run. If not specified, Nextflow will automatically generate a random mnemonic. + --outdir [file] The output directory where the results will be saved + --email [email] Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits + --email_on_fail [email] Same as --email, except only send mail if the workflow is not successful + --max_multiqc_email_size [str] Theshold size for MultiQC report to be attached in notification email. If file generated by pipeline exceeds the threshold, it will not be attached (Default: 25MB) + -name [str] Name for the pipeline run. If not specified, Nextflow will automatically generate a random mnemonic AWSBatch options: - --awsqueue The AWSBatch JobQueue that needs to be set when running on AWSBatch - --awsregion The AWS Region for your AWS Batch job to run on + --awsqueue [str] The AWSBatch JobQueue that needs to be set when running on AWSBatch + --awsregion [str] The AWS Region for your AWS Batch job to run on + --awscli [str] Path to the AWS CLI tool """.stripIndent() } -/* - * SET UP CONFIGURATION VARIABLES - */ - -// Show help emssage -if (params.help){ +// Show help message +if (params.help) { helpMessage() exit 0 } +/* + * SET UP CONFIGURATION VARIABLES + */ + // Check if genome exists in the config file if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { exit 1, "The provided genome '${params.genome}' is not available in the iGenomes file. Currently the available genomes are ${params.genomes.keySet().join(", ")}" @@ -62,101 +63,101 @@ if (params.genomes && params.genome && !params.genomes.containsKey(params.genome // TODO nf-core: Add any reference files that are needed // Configurable reference genomes -fasta = params.genome ? params.genomes[ params.genome ].fasta ?: false : false -if ( params.fasta ){ - fasta = file(params.fasta) - if( !fasta.exists() ) exit 1, "Fasta file not found: ${params.fasta}" -} // // NOTE - THIS IS NOT USED IN THIS PIPELINE, EXAMPLE ONLY -// If you want to use the above in a process, define the following: +// If you want to use the channel below in a process, define the following: // input: -// file fasta from fasta +// file fasta from ch_fasta // - +params.fasta = params.genome ? params.genomes[ params.genome ].fasta ?: false : false +if (params.fasta) { ch_fasta = file(params.fasta, checkIfExists: true) } // Has the run name been specified by the user? // this has the bonus effect of catching both -name and --name custom_runName = params.name -if( !(workflow.runName ==~ /[a-z]+_[a-z]+/) ){ - custom_runName = workflow.runName +if (!(workflow.runName ==~ /[a-z]+_[a-z]+/)) { + custom_runName = workflow.runName } - -if( workflow.profile == 'awsbatch') { - // AWSBatch sanity checking - if (!params.awsqueue || !params.awsregion) exit 1, "Specify correct --awsqueue and --awsregion parameters on AWSBatch!" - if (!workflow.workDir.startsWith('s3') || !params.outdir.startsWith('s3')) exit 1, "Specify S3 URLs for workDir and outdir parameters on AWSBatch!" - // Check workDir/outdir paths to be S3 buckets if running on AWSBatch - // related: https://github.com/nextflow-io/nextflow/issues/813 - if (!workflow.workDir.startsWith('s3:') || !params.outdir.startsWith('s3:')) exit 1, "Workdir or Outdir not on S3 - specify S3 Buckets for each to run on AWSBatch!" +if (workflow.profile.contains('awsbatch')) { + // AWSBatch sanity checking + if (!params.awsqueue || !params.awsregion) exit 1, "Specify correct --awsqueue and --awsregion parameters on AWSBatch!" + // Check outdir paths to be S3 buckets if running on AWSBatch + // related: https://github.com/nextflow-io/nextflow/issues/813 + if (!params.outdir.startsWith('s3:')) exit 1, "Outdir not on S3 - specify S3 Bucket to run on AWSBatch!" + // Prevent trace files to be stored on S3 since S3 does not support rolling files. + if (params.tracedir.startsWith('s3:')) exit 1, "Specify a local tracedir or run without trace! S3 cannot be used for tracefiles." } // Stage config files -ch_multiqc_config = Channel.fromPath(params.multiqc_config) -ch_output_docs = Channel.fromPath("$baseDir/docs/output.md") +ch_multiqc_config = file("$baseDir/assets/multiqc_config.yaml", checkIfExists: true) +ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config, checkIfExists: true) : Channel.empty() +ch_output_docs = file("$baseDir/docs/output.md", checkIfExists: true) /* * Create a channel for input read files */ -if(params.readPaths){ - if(params.singleEnd){ +if (params.readPaths) { + if (params.single_end) { Channel .from(params.readPaths) - .map { row -> [ row[0], [file(row[1][0])]] } + .map { row -> [ row[0], [ file(row[1][0], checkIfExists: true) ] ] } .ifEmpty { exit 1, "params.readPaths was empty - no input files supplied" } - .into { read_files_fastqc; read_files_trimming } + .into { ch_read_files_fastqc; ch_read_files_trimming } } else { Channel .from(params.readPaths) - .map { row -> [ row[0], [file(row[1][0]), file(row[1][1])]] } + .map { row -> [ row[0], [ file(row[1][0], checkIfExists: true), file(row[1][1], checkIfExists: true) ] ] } .ifEmpty { exit 1, "params.readPaths was empty - no input files supplied" } - .into { read_files_fastqc; read_files_trimming } + .into { ch_read_files_fastqc; ch_read_files_trimming } } } else { Channel - .fromFilePairs( params.reads, size: params.singleEnd ? 1 : 2 ) - .ifEmpty { exit 1, "Cannot find any reads matching: ${params.reads}\nNB: Path needs to be enclosed in quotes!\nIf this is single-end data, please specify --singleEnd on the command line." } - .into { read_files_fastqc; read_files_trimming } + .fromFilePairs(params.reads, size: params.single_end ? 1 : 2) + .ifEmpty { exit 1, "Cannot find any reads matching: ${params.reads}\nNB: Path needs to be enclosed in quotes!\nIf this is single-end data, please specify --single_end on the command line." } + .into { ch_read_files_fastqc; ch_read_files_trimming } } - // Header log info log.info nfcoreHeader() def summary = [:] +if (workflow.revision) summary['Pipeline Release'] = workflow.revision summary['Run Name'] = custom_runName ?: workflow.runName // TODO nf-core: Report custom parameters here summary['Reads'] = params.reads summary['Fasta Ref'] = params.fasta -summary['Data Type'] = params.singleEnd ? 'Single-End' : 'Paired-End' +summary['Data Type'] = params.single_end ? 'Single-End' : 'Paired-End' summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" -if(workflow.containerEngine) summary['Container'] = "$workflow.containerEngine - $workflow.container" +if (workflow.containerEngine) summary['Container'] = "$workflow.containerEngine - $workflow.container" summary['Output dir'] = params.outdir summary['Launch dir'] = workflow.launchDir summary['Working dir'] = workflow.workDir summary['Script dir'] = workflow.projectDir summary['User'] = workflow.userName -if(workflow.profile == 'awsbatch'){ - summary['AWS Region'] = params.awsregion - summary['AWS Queue'] = params.awsqueue +if (workflow.profile.contains('awsbatch')) { + summary['AWS Region'] = params.awsregion + summary['AWS Queue'] = params.awsqueue + summary['AWS CLI'] = params.awscli } summary['Config Profile'] = workflow.profile -if(params.config_profile_description) summary['Config Description'] = params.config_profile_description -if(params.config_profile_contact) summary['Config Contact'] = params.config_profile_contact -if(params.config_profile_url) summary['Config URL'] = params.config_profile_url -if(params.email) { - summary['E-mail Address'] = params.email - summary['MultiQC maxsize'] = params.maxMultiqcEmailFileSize +if (params.config_profile_description) summary['Config Description'] = params.config_profile_description +if (params.config_profile_contact) summary['Config Contact'] = params.config_profile_contact +if (params.config_profile_url) summary['Config URL'] = params.config_profile_url +if (params.email || params.email_on_fail) { + summary['E-mail Address'] = params.email + summary['E-mail on failure'] = params.email_on_fail + summary['MultiQC maxsize'] = params.max_multiqc_email_size } log.info summary.collect { k,v -> "${k.padRight(18)}: $v" }.join("\n") -log.info "\033[2m----------------------------------------------------\033[0m" +log.info "-\033[2m--------------------------------------------------\033[0m-" // Check the hostnames against configured profiles checkHostname() -def create_workflow_summary(summary) { - def yaml_file = workDir.resolve('workflow_summary_mqc.yaml') - yaml_file.text = """ +Channel.from(summary.collect{ [it.key, it.value] }) + .map { k,v -> "
$k
${v ?: 'N/A'}
" } + .reduce { a, b -> return [a, b].join("\n ") } + .map { x -> """ id: 'nf-core-cageseq-summary' description: " - this information is collected when the pipeline is started." section_name: 'nf-core/cageseq Workflow Summary' @@ -164,21 +165,24 @@ def create_workflow_summary(summary) { plot_type: 'html' data: |
-${summary.collect { k,v -> "
$k
${v ?: 'N/A'}
" }.join("\n")} + $x
- """.stripIndent() - - return yaml_file -} - + """.stripIndent() } + .set { ch_workflow_summary } /* * Parse software version numbers */ process get_software_versions { + publishDir "${params.outdir}/pipeline_info", mode: 'copy', + saveAs: { filename -> + if (filename.indexOf(".csv") > 0) filename + else null + } output: - file 'software_versions_mqc.yaml' into software_versions_yaml + file 'software_versions_mqc.yaml' into ch_software_versions_yaml + file "software_versions.csv" script: // TODO nf-core: Get all tools to print their version number here @@ -187,34 +191,33 @@ process get_software_versions { echo $workflow.nextflow.version > v_nextflow.txt fastqc --version > v_fastqc.txt multiqc --version > v_multiqc.txt - scrape_software_versions.py > software_versions_mqc.yaml + scrape_software_versions.py &> software_versions_mqc.yaml """ } - - /* * STEP 1 - FastQC */ process fastqc { tag "$name" + label 'process_medium' publishDir "${params.outdir}/fastqc", mode: 'copy', - saveAs: {filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename"} + saveAs: { filename -> + filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename" + } input: - set val(name), file(reads) from read_files_fastqc + set val(name), file(reads) from ch_read_files_fastqc output: - file "*_fastqc.{zip,html}" into fastqc_results + file "*_fastqc.{zip,html}" into ch_fastqc_results script: """ - fastqc -q $reads + fastqc --quiet --threads $task.cpus $reads """ } - - /* * STEP 2 - MultiQC */ @@ -222,27 +225,28 @@ process multiqc { publishDir "${params.outdir}/MultiQC", mode: 'copy' input: - file multiqc_config from ch_multiqc_config + file (multiqc_config) from ch_multiqc_config + file (mqc_custom_config) from ch_multiqc_custom_config.collect().ifEmpty([]) // TODO nf-core: Add in log files from your new processes for MultiQC to find! - file ('fastqc/*') from fastqc_results.collect().ifEmpty([]) - file ('software_versions/*') from software_versions_yaml - file workflow_summary from create_workflow_summary(summary) + file ('fastqc/*') from ch_fastqc_results.collect().ifEmpty([]) + file ('software_versions/*') from ch_software_versions_yaml.collect() + file workflow_summary from ch_workflow_summary.collectFile(name: "workflow_summary_mqc.yaml") output: - file "*multiqc_report.html" into multiqc_report + file "*multiqc_report.html" into ch_multiqc_report file "*_data" + file "multiqc_plots" script: rtitle = custom_runName ? "--title \"$custom_runName\"" : '' rfilename = custom_runName ? "--filename " + custom_runName.replaceAll('\\W','_').replaceAll('_+','_') + "_multiqc_report" : '' + custom_config_file = params.multiqc_config ? "--config $mqc_custom_config" : '' // TODO nf-core: Specify which MultiQC modules to use with -m for a faster run time """ - multiqc -f $rtitle $rfilename --config $multiqc_config . + multiqc -f $rtitle $rfilename $custom_config_file . """ } - - /* * STEP 3 - Output Description HTML */ @@ -257,12 +261,10 @@ process output_documentation { script: """ - markdown_to_html.r $output_docs results_description.html + markdown_to_html.py $output_docs -o results_description.html """ } - - /* * Completion e-mail notification */ @@ -270,8 +272,8 @@ workflow.onComplete { // Set up the e-mail variables def subject = "[nf-core/cageseq] Successful: $workflow.runName" - if(!workflow.success){ - subject = "[nf-core/cageseq] FAILED: $workflow.runName" + if (!workflow.success) { + subject = "[nf-core/cageseq] FAILED: $workflow.runName" } def email_fields = [:] email_fields['version'] = workflow.manifest.version @@ -289,21 +291,20 @@ workflow.onComplete { email_fields['summary']['Date Completed'] = workflow.complete email_fields['summary']['Pipeline script file path'] = workflow.scriptFile email_fields['summary']['Pipeline script hash ID'] = workflow.scriptId - if(workflow.repository) email_fields['summary']['Pipeline repository Git URL'] = workflow.repository - if(workflow.commitId) email_fields['summary']['Pipeline repository Git Commit'] = workflow.commitId - if(workflow.revision) email_fields['summary']['Pipeline Git branch/tag'] = workflow.revision - if(workflow.container) email_fields['summary']['Docker image'] = workflow.container + if (workflow.repository) email_fields['summary']['Pipeline repository Git URL'] = workflow.repository + if (workflow.commitId) email_fields['summary']['Pipeline repository Git Commit'] = workflow.commitId + if (workflow.revision) email_fields['summary']['Pipeline Git branch/tag'] = workflow.revision email_fields['summary']['Nextflow Version'] = workflow.nextflow.version email_fields['summary']['Nextflow Build'] = workflow.nextflow.build email_fields['summary']['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp - // TODO nf-core: If not using MultiQC, strip out this code (including params.maxMultiqcEmailFileSize) + // TODO nf-core: If not using MultiQC, strip out this code (including params.max_multiqc_email_size) // On success try attach the multiqc report def mqc_report = null try { if (workflow.success) { - mqc_report = multiqc_report.getVal() - if (mqc_report.getClass() == ArrayList){ + mqc_report = ch_multiqc_report.getVal() + if (mqc_report.getClass() == ArrayList) { log.warn "[nf-core/cageseq] Found multiple reports from process 'multiqc', will use only one" mqc_report = mqc_report[0] } @@ -312,6 +313,12 @@ workflow.onComplete { log.warn "[nf-core/cageseq] Could not attach MultiQC report to summary email" } + // Check if we are only sending emails on failure + email_address = params.email + if (!params.email && params.email_on_fail && !workflow.success) { + email_address = params.email_on_fail + } + // Render the TXT template def engine = new groovy.text.GStringTemplateEngine() def tf = new File("$baseDir/assets/email_template.txt") @@ -324,82 +331,89 @@ workflow.onComplete { def email_html = html_template.toString() // Render the sendmail template - def smail_fields = [ email: params.email, subject: subject, email_txt: email_txt, email_html: email_html, baseDir: "$baseDir", mqcFile: mqc_report, mqcMaxSize: params.maxMultiqcEmailFileSize.toBytes() ] + def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, baseDir: "$baseDir", mqcFile: mqc_report, mqcMaxSize: params.max_multiqc_email_size.toBytes() ] def sf = new File("$baseDir/assets/sendmail_template.txt") def sendmail_template = engine.createTemplate(sf).make(smail_fields) def sendmail_html = sendmail_template.toString() // Send the HTML e-mail - if (params.email) { + if (email_address) { try { - if( params.plaintext_email ){ throw GroovyException('Send plaintext e-mail, not HTML') } - // Try to send HTML e-mail using sendmail - [ 'sendmail', '-t' ].execute() << sendmail_html - log.info "[nf-core/cageseq] Sent summary e-mail to $params.email (sendmail)" + if (params.plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } + // Try to send HTML e-mail using sendmail + [ 'sendmail', '-t' ].execute() << sendmail_html + log.info "[nf-core/cageseq] Sent summary e-mail to $email_address (sendmail)" } catch (all) { - // Catch failures and try with plaintext - [ 'mail', '-s', subject, params.email ].execute() << email_txt - log.info "[nf-core/cageseq] Sent summary e-mail to $params.email (mail)" + // Catch failures and try with plaintext + [ 'mail', '-s', subject, email_address ].execute() << email_txt + log.info "[nf-core/cageseq] Sent summary e-mail to $email_address (mail)" } } // Write summary e-mail HTML to a file - def output_d = new File( "${params.outdir}/pipeline_info/" ) - if( !output_d.exists() ) { - output_d.mkdirs() + def output_d = new File("${params.outdir}/pipeline_info/") + if (!output_d.exists()) { + output_d.mkdirs() } - def output_hf = new File( output_d, "pipeline_report.html" ) + def output_hf = new File(output_d, "pipeline_report.html") output_hf.withWriter { w -> w << email_html } - def output_tf = new File( output_d, "pipeline_report.txt" ) + def output_tf = new File(output_d, "pipeline_report.txt") output_tf.withWriter { w -> w << email_txt } - c_reset = params.monochrome_logs ? '' : "\033[0m"; - c_purple = params.monochrome_logs ? '' : "\033[0;35m"; c_green = params.monochrome_logs ? '' : "\033[0;32m"; + c_purple = params.monochrome_logs ? '' : "\033[0;35m"; c_red = params.monochrome_logs ? '' : "\033[0;31m"; - if(workflow.success){ - log.info "${c_purple}[nf-core/cageseq]${c_green} Pipeline complete${c_reset}" + c_reset = params.monochrome_logs ? '' : "\033[0m"; + + if (workflow.stats.ignoredCount > 0 && workflow.success) { + log.info "-${c_purple}Warning, pipeline completed, but with errored process(es) ${c_reset}-" + log.info "-${c_red}Number of ignored errored process(es) : ${workflow.stats.ignoredCount} ${c_reset}-" + log.info "-${c_green}Number of successfully ran process(es) : ${workflow.stats.succeedCount} ${c_reset}-" + } + + if (workflow.success) { + log.info "-${c_purple}[nf-core/cageseq]${c_green} Pipeline completed successfully${c_reset}-" } else { checkHostname() - log.info "${c_purple}[nf-core/cageseq]${c_red} Pipeline completed with errors${c_reset}" + log.info "-${c_purple}[nf-core/cageseq]${c_red} Pipeline completed with errors${c_reset}-" } } -def nfcoreHeader(){ +def nfcoreHeader() { // Log colors ANSI codes - c_reset = params.monochrome_logs ? '' : "\033[0m"; - c_dim = params.monochrome_logs ? '' : "\033[2m"; c_black = params.monochrome_logs ? '' : "\033[0;30m"; - c_green = params.monochrome_logs ? '' : "\033[0;32m"; - c_yellow = params.monochrome_logs ? '' : "\033[0;33m"; c_blue = params.monochrome_logs ? '' : "\033[0;34m"; - c_purple = params.monochrome_logs ? '' : "\033[0;35m"; c_cyan = params.monochrome_logs ? '' : "\033[0;36m"; + c_dim = params.monochrome_logs ? '' : "\033[2m"; + c_green = params.monochrome_logs ? '' : "\033[0;32m"; + c_purple = params.monochrome_logs ? '' : "\033[0;35m"; + c_reset = params.monochrome_logs ? '' : "\033[0m"; c_white = params.monochrome_logs ? '' : "\033[0;37m"; + c_yellow = params.monochrome_logs ? '' : "\033[0;33m"; - return """ ${c_dim}----------------------------------------------------${c_reset} + return """ -${c_dim}--------------------------------------------------${c_reset}- ${c_green},--.${c_black}/${c_green},-.${c_reset} ${c_blue} ___ __ __ __ ___ ${c_green}/,-._.--~\'${c_reset} ${c_blue} |\\ | |__ __ / ` / \\ |__) |__ ${c_yellow}} {${c_reset} ${c_blue} | \\| | \\__, \\__/ | \\ |___ ${c_green}\\`-._,-`-,${c_reset} ${c_green}`._,._,\'${c_reset} ${c_purple} nf-core/cageseq v${workflow.manifest.version}${c_reset} - ${c_dim}----------------------------------------------------${c_reset} + -${c_dim}--------------------------------------------------${c_reset}- """.stripIndent() } -def checkHostname(){ +def checkHostname() { def c_reset = params.monochrome_logs ? '' : "\033[0m" def c_white = params.monochrome_logs ? '' : "\033[0;37m" def c_red = params.monochrome_logs ? '' : "\033[1;91m" def c_yellow_bold = params.monochrome_logs ? '' : "\033[1;93m" - if(params.hostnames){ + if (params.hostnames) { def hostname = "hostname".execute().text.trim() params.hostnames.each { prof, hnames -> hnames.each { hname -> - if(hostname.contains(hname) && !workflow.profile.contains(prof)){ + if (hostname.contains(hname) && !workflow.profile.contains(prof)) { log.error "====================================================\n" + " ${c_red}WARNING!${c_reset} You are running with `-profile $workflow.profile`\n" + " but your machine hostname is ${c_white}'$hostname'${c_reset}\n" + diff --git a/nextflow.config b/nextflow.config index 8ffcaa7..82d3698 100644 --- a/nextflow.config +++ b/nextflow.config @@ -10,30 +10,35 @@ params { // Workflow flags // TODO nf-core: Specify your pipeline's command line flags + genome = false reads = "data/*{1,2}.fastq.gz" - singleEnd = false + single_end = false outdir = './results' // Boilerplate options name = false - multiqc_config = "$baseDir/conf/multiqc_config.yaml" + multiqc_config = false email = false - maxMultiqcEmailFileSize = 25.MB + email_on_fail = false + max_multiqc_email_size = 25.MB plaintext_email = false monochrome_logs = false help = false - igenomes_base = "./iGenomes" + igenomes_base = 's3://ngi-igenomes/igenomes/' tracedir = "${params.outdir}/pipeline_info" - clusterOptions = false - awsqueue = false - awsregion = 'eu-west-1' - igenomesIgnore = false + igenomes_ignore = false custom_config_version = 'master' custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" hostnames = false config_profile_description = false config_profile_contact = false config_profile_url = false + + // Defaults only, expecting to be overwritten + max_memory = 128.GB + max_cpus = 16 + max_time = 240.h + } // Container slug. Stable releases should specify release tag! @@ -51,19 +56,33 @@ try { } profiles { - awsbatch { includeConfig 'conf/awsbatch.config' } conda { process.conda = "$baseDir/environment.yml" } debug { process.beforeScript = 'echo $HOSTNAME' } - docker { docker.enabled = true } - singularity { singularity.enabled = true } + docker { + docker.enabled = true + // Avoid this error: + // WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap. + // Testing this in nf-core after discussion here https://github.com/nf-core/tools/pull/351 + // once this is established and works well, nextflow might implement this behavior as new default. + docker.runOptions = '-u \$(id -u):\$(id -g)' + } + singularity { + singularity.enabled = true + singularity.autoMounts = true + } test { includeConfig 'conf/test.config' } } // Load igenomes.config if required -if(!params.igenomesIgnore){ +if (!params.igenomes_ignore) { includeConfig 'conf/igenomes.config' } +// Export this variable to prevent local Python libraries from conflicting with those in the container +env { + PYTHONNOUSERSITE = 1 +} + // Capture exit codes from upstream processes when piping process.shell = ['/bin/bash', '-euo', 'pipefail'] @@ -90,16 +109,16 @@ manifest { homePage = 'https://github.com/nf-core/cageseq' description = 'CAGE-seq pipeline' mainScript = 'main.nf' - nextflowVersion = '>=0.32.0' + nextflowVersion = '>=19.10.0' version = '1.0dev' } // Function to ensure that resource requirements don't go beyond // a maximum limit def check_max(obj, type) { - if(type == 'memory'){ + if (type == 'memory') { try { - if(obj.compareTo(params.max_memory as nextflow.util.MemoryUnit) == 1) + if (obj.compareTo(params.max_memory as nextflow.util.MemoryUnit) == 1) return params.max_memory as nextflow.util.MemoryUnit else return obj @@ -107,9 +126,9 @@ def check_max(obj, type) { println " ### ERROR ### Max memory '${params.max_memory}' is not valid! Using default value: $obj" return obj } - } else if(type == 'time'){ + } else if (type == 'time') { try { - if(obj.compareTo(params.max_time as nextflow.util.Duration) == 1) + if (obj.compareTo(params.max_time as nextflow.util.Duration) == 1) return params.max_time as nextflow.util.Duration else return obj @@ -117,7 +136,7 @@ def check_max(obj, type) { println " ### ERROR ### Max time '${params.max_time}' is not valid! Using default value: $obj" return obj } - } else if(type == 'cpus'){ + } else if (type == 'cpus') { try { return Math.min( obj, params.max_cpus as int ) } catch (all) { From b32e994bb3e6f1f3cb40520c5abfa48fb898322b Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 20 Feb 2020 18:16:56 +0100 Subject: [PATCH 030/107] merge run commands in Dockerfile --- Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 18bff41..4dac58b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,11 +3,11 @@ LABEL authors="Kevin Menden; Tristan Kast" \ description="Docker image containing all requirements for nf-core/cageseq pipeline" COPY environment.yml / -RUN conda env create -f /environment.yml && conda clean -a -RUN conda env export --name nf-core-cageseq-1.0dev > nf-core-cageseq-1.0dev.yml +RUN conda env create -f /environment.yml && conda clean -a && \ + conda env export --name nf-core-cageseq-1.0dev > nf-core-cageseq-1.0dev.yml ENV PATH /opt/conda/envs/nf-core-cageseq-1.0dev/bin:$PATH RUN apt-get update; apt-get install -y build-essential g++ -RUN wget http://cbrc3.cbrc.jp/~martin/paraclu/paraclu-9.zip -RUN unzip paraclu-9.zip; cd paraclu-9; make +RUN wget http://cbrc3.cbrc.jp/~martin/paraclu/paraclu-9.zip && \ + unzip paraclu-9.zip; cd paraclu-9; make ENV PATH /paraclu-9:$PATH From 4d6b0a6a17e878b64659d0367f7274fcb06ed81b Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 20 Feb 2020 18:18:04 +0100 Subject: [PATCH 031/107] change `into` operations into `set` --- main.nf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main.nf b/main.nf index 40c32ed..34e69a5 100644 --- a/main.nf +++ b/main.nf @@ -363,7 +363,8 @@ if(params.trimming){ } } else{ - read_files_trimming.into{ trimmed_reads_cutG } + read_files_trimming.set{ trimmed_reads_cutG } + cutadapt_results = Channel.empty() } @@ -391,9 +392,8 @@ if(params.trimming){ } } else { - trimmed_reads_cutG.into{ processed_reads} + trimmed_reads_cutG.set{processed_reads} } - /** * STEP 5 - Remove artifacts */ @@ -456,7 +456,7 @@ else{ /** * STEP 7 - STAR alignment */ - +further_processed_reads_star = further_processed_reads_star.dump(tag:"star") process star { tag "$sample_name" From 08045b9d79626d750483bd76061fcbc847328826 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 21 Feb 2020 10:36:39 +0100 Subject: [PATCH 032/107] fix linting errors --- README.md | 16 +++------------- docs/usage.md | 31 ++----------------------------- environment.yml | 4 ++-- 3 files changed, 7 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index b2aaaed..22c3ddb 100644 --- a/README.md +++ b/README.md @@ -10,24 +10,14 @@ [![Docker](https://img.shields.io/docker/automated/nfcore/cageseq.svg)](https://hub.docker.com/r/nfcore/cageseq) ## Introduction -UNDER DEVELOPMENT -This pipeline is currenlty under development. The workflow is not yet finished. -<<<<<<< HEAD UNDER DEVELOPMENT This pipeline is currenlty under development. The workflow is not yet finished. +UNDER DEVELOPMENT -**nf-core/cageseq** is a pipeline built for the analysis of [CAGE-sequencing](https://www.ncbi.nlm.nih.gov/pubmed/22362160) data. - - - -The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It comes with docker / singularity containers making installation trivial and results highly reproducible. - -Currently, this pipeline only supports CAGE-seq data generated with the old protocol as desribed in [CAGE-seq](https://www.ncbi.nlm.nih.gov/pubmed/22362160). The recently developed new CAGE-seq protocol will however be implemented in future releases. - -======= +This pipeline is currenlty under development. The workflow is not yet finished. The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It comes with docker containers making installation trivial and results highly reproducible. @@ -54,7 +44,6 @@ nextflow run nf-core/cageseq -profile --rea ``` See [usage docs](docs/usage.md) for all of the available options when running the pipeline. ->>>>>>> abeec3dc23a86fa66e4a507276e917d5695fba38 ## Documentation @@ -73,6 +62,7 @@ The nf-core/cageseq pipeline comes with documentation about the pipeline, found This pipeline includes steps for adapter and artefact trimming ([cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), alignment to a reference ([STAR](https://github.com/alexdobin/STAR)) and CAGE tag counting. Additionally, several quality control steps ([FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/), [MultiQC](https://multiqc.info/)) are included to allow for easy verification of results after a run. + ## Credits nf-core/cageseq was originally written by Kevin Menden and Tristan Kast. diff --git a/docs/usage.md b/docs/usage.md index 28b7741..1295f32 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -10,7 +10,6 @@ * [Main arguments](#main-arguments) * [`-profile`](#-profile) * [`--reads`](#--reads) -<<<<<<< HEAD * [`--artifacts5end`](#--artifacts5end) * [`--artifacts3end`](#--artifacts3end) * [`--trimming`](#--trimming) @@ -23,12 +22,7 @@ * [`--fasta`](#--fasta) * [`--gtf`](#--gtf) * [`--star_index`](#--star_index) -======= * [`--single_end`](#--single_end) -* [Reference genomes](#reference-genomes) - * [`--genome` (using iGenomes)](#--genome-using-igenomes) - * [`--fasta`](#--fasta) ->>>>>>> abeec3dc23a86fa66e4a507276e917d5695fba38 * [`--igenomes_ignore`](#--igenomes_ignore) * [Job resources](#job-resources) * [Automatic resubmission](#automatic-resubmission) @@ -131,21 +125,14 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof * A profile with a complete configuration for automated testing * Includes links to test data so needs no other parameters - ### `--reads` -<<<<<<< HEAD -Use this to specify the location of your input FastQ file. For example: -======= Use this to specify the location of your input FastQ files. For example: ->>>>>>> abeec3dc23a86fa66e4a507276e917d5695fba38 ```bash --reads path/to/data/sample.fastq ``` -<<<<<<< HEAD -======= Please note the following requirements: 1. The path must be enclosed in quotes @@ -164,7 +151,6 @@ By default, the pipeline expects paired-end data. If you have single-end data, y It is not possible to run a mixture of single-end and paired-end files in one run. ->>>>>>> abeec3dc23a86fa66e4a507276e917d5695fba38 ## Reference genomes The pipeline config files come bundled with paths to the illumina iGenomes reference index files. If running with docker or AWS, the configuration is set up to use the [AWS-iGenomes](https://ewels.github.io/AWS-iGenomes/) resource. @@ -190,7 +176,6 @@ Note that you can use the same configuration setup to save sets of reference fil The syntax for this reference configuration is as follows: - ```nextflow params { genomes { @@ -204,17 +189,10 @@ params { } ``` -<<<<<<< HEAD -### `--igenomes_ignore` -Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`. - -### `--fasta` `--gtf` `--star_index` -======= -### `--fasta` +### `--fasta` `--gtf` `--star_index` ->>>>>>> abeec3dc23a86fa66e4a507276e917d5695fba38 If you prefer, you can specify the full path to your reference genome when you run the pipeline: ```bash @@ -223,10 +201,10 @@ If you prefer, you can specify the full path to your reference genome when you r --star '[path to STAR index]' ``` -<<<<<<< HEAD The minimum requirements for running the pipeline are the Fasta and GTF files. If a STAR index is not given, it will be automatically build. ### `--saveReference` + All generated reference files will be saved to the results folder if this flag is set. ## Adapter clipping and trimming @@ -257,14 +235,9 @@ Specifying a file containing artifacts at the 3' end. By default a file with all Sets the minimum amount of reads for paraclu to build a cluster. Default: 100. - - - -======= ### `--igenomes_ignore` Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`. ->>>>>>> abeec3dc23a86fa66e4a507276e917d5695fba38 ## Job resources diff --git a/environment.yml b/environment.yml index 4d3af63..fd78b4b 100644 --- a/environment.yml +++ b/environment.yml @@ -16,6 +16,6 @@ dependencies: - bioconda::fastqc=0.11.8 - bioconda::samtools=1.9 - bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. -- bioconda::multiqc=1.7 -- bioconda::unzip=6.0 +- bioconda::multiqc=1.8 +- unzip=6.0 - bioconda::bowtie2=2.3.5 From 26035bc895c20139f3b727babfe9d7ab0e20707d Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 21 Feb 2020 11:00:27 +0100 Subject: [PATCH 033/107] move `mulitqc_config.yaml` into assets --- {conf => assets}/multiqc_config.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {conf => assets}/multiqc_config.yaml (100%) diff --git a/conf/multiqc_config.yaml b/assets/multiqc_config.yaml similarity index 100% rename from conf/multiqc_config.yaml rename to assets/multiqc_config.yaml From c68e73a92b586134fe9e3c6471d5e1040ff0705b Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 24 Feb 2020 16:50:52 +0100 Subject: [PATCH 034/107] fix `cut_artifacts` --- main.nf | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/main.nf b/main.nf index f6d8b37..d569a2d 100644 --- a/main.nf +++ b/main.nf @@ -21,8 +21,6 @@ def helpMessage() { nextflow run nf-core/cageseq --reads /path/to/data.fastq.gz --star_index /path/to/index -profile docker Mandatory arguments: - --reads Path to input data (must be surrounded with quotes) - --reads [file] Path to input data (must be surrounded with quotes) -profile [str] Configuration profile to use. Can use multiple (comma separated) Available: conda, docker, singularity, test, awsbatch, and more @@ -39,7 +37,7 @@ def helpMessage() { --min_cluster Minimum amount of reads to build a cluster with paraclu References If not specified in the configuration file or you wish to overwrite any of the references - --fasta [file] Path to fasta reference + --fasta [file] Path to fasta reference --star_index Path to the star index, if not given the pipeline will automatically try to build one with the given fasta and gtf file --genome Name of iGenomes reference --gtf Path to gtf file @@ -419,8 +417,8 @@ if (params.cutArtifacts){ input: set val(sample_name), file(reads) from processed_reads - file artifacts5end from ch_5end_artifacts - file artifacts3end from ch_3end_artifacts + file artifacts5end from ch_5end_artifacts.collect() + file artifacts3end from ch_3end_artifacts.collect() output: set val(sample_name), file("*.fastq.gz") into further_processed_reads From c872169990b9973860ac193b36a08badfb930b01 Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 24 Feb 2020 17:08:55 +0100 Subject: [PATCH 035/107] fix naming of GitHub actions remove duplicate mention of `--genome` --- .github/workflows/branch.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/linting.yml | 2 +- main.nf | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 9cb261e..a511f9c 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -1,4 +1,4 @@ -name: nf-core branch protection +name: nf-core/cageseq branch protection # This workflow is triggered on PRs to master branch on the repository # It fails when someone tries to make a PR against the nf-core `master` branch instead of `dev` on: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0da5744..8b69934 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: nf-core CI +name: nf-core/cageseq CI # This workflow is triggered on pushes and PRs to the repository. # It runs the pipeline with the minimal test dataset to check that it completes without any syntax errors on: [push, pull_request] diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 1e0827a..7f4dbf5 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -1,4 +1,4 @@ -name: nf-core linting +name: nf-core/cageseq linting # This workflow is triggered on pushes and PRs to the repository. # It runs the `nf-core lint` and markdown lint tests to ensure that the code meets the nf-core guidelines on: diff --git a/main.nf b/main.nf index d569a2d..077126a 100644 --- a/main.nf +++ b/main.nf @@ -26,7 +26,6 @@ def helpMessage() { Available: conda, docker, singularity, test, awsbatch, and more Options: - --genome [str] Name of iGenomes reference --trimming Set to false to skip the file Trimming --cutEcoP Set to false to not cut the EcoP --cutLinker Set to false to not cut the linker @@ -37,7 +36,7 @@ def helpMessage() { --min_cluster Minimum amount of reads to build a cluster with paraclu References If not specified in the configuration file or you wish to overwrite any of the references - --fasta [file] Path to fasta reference + --fasta [file] Path to fasta reference --star_index Path to the star index, if not given the pipeline will automatically try to build one with the given fasta and gtf file --genome Name of iGenomes reference --gtf Path to gtf file From b9dabda34db714c4b9c43f98ef50dc0a1112749d Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 26 Feb 2020 16:44:03 +0100 Subject: [PATCH 036/107] add RSeQC and samtools QC --- Dockerfile | 1 + assets/multiqc_config.yaml | 10 +++ bin/gtf2bed.pl | 123 ++++++++++++++++++++++++++++++ bin/make_ctss.sh | 18 ++--- bin/process_ctss.sh | 0 bin/scrape_software_versions.py | 2 + environment.yml | 1 + main.nf | 128 ++++++++++++++++++++++++-------- 8 files changed, 243 insertions(+), 40 deletions(-) create mode 100755 bin/gtf2bed.pl mode change 100644 => 100755 bin/make_ctss.sh mode change 100644 => 100755 bin/process_ctss.sh diff --git a/Dockerfile b/Dockerfile index f57936f..4fdc6b4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,6 +10,7 @@ RUN conda env create -f /environment.yml && conda clean -a ENV PATH /opt/conda/envs/nf-core-cageseq-1.0dev/bin:$PATH # Dump the details of the installed packages to a file for posterity RUN conda env export --name nf-core-cageseq-1.0dev > nf-core-cageseq-1.0dev.yml +# Setup paraclu RUN apt-get update; apt-get install -y build-essential g++ RUN wget http://cbrc3.cbrc.jp/~martin/paraclu/paraclu-9.zip && \ unzip paraclu-9.zip; cd paraclu-9; make diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index 0443bdb..23ccb43 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -2,6 +2,16 @@ report_comment: > This report has been generated by the nf-core/cageseq analysis pipeline. For information about how to interpret these results, please see the documentation. + +top_modules: + - 'fastqc' + - 'cutadapt' + - 'star' + - 'samtools' + - 'rseqc' +extra_fn_clean_exts: + - '.trimmed.G' + - '.trimmed.G_trimmed.artifact' report_section_order: software_versions: order: -1000 diff --git a/bin/gtf2bed.pl b/bin/gtf2bed.pl new file mode 100755 index 0000000..87829f7 --- /dev/null +++ b/bin/gtf2bed.pl @@ -0,0 +1,123 @@ +#!/usr/bin/perl + +# Copyright (c) 2011 Erik Aronesty (erik@q32.com) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ALSO, IT WOULD BE NICE IF YOU LET ME KNOW YOU USED IT. + +use Getopt::Long; + +my $extended; +GetOptions("x"=>\$extended); + +$in = shift @ARGV; + +my $in_cmd =($in =~ /\.gz$/ ? "gunzip -c $in|" : $in =~ /\.zip$/ ? "unzip -p $in|" : "$in") || die "Can't open $in: $!\n"; +open IN, $in_cmd; + +while () { + $gff = 2 if /^##gff-version 2/; + $gff = 3 if /^##gff-version 3/; + next if /^#/ && $gff; + + s/\s+$//; + # 0-chr 1-src 2-feat 3-beg 4-end 5-scor 6-dir 7-fram 8-attr + my @f = split /\t/; + if ($gff) { + # most ver 2's stick gene names in the id field + ($id) = $f[8]=~ /\bID="([^"]+)"/; + # most ver 3's stick unquoted names in the name field + ($id) = $f[8]=~ /\bName=([^";]+)/ if !$id && $gff == 3; + } else { + ($id) = $f[8]=~ /transcript_id "([^"]+)"/; + } + + next unless $id && $f[0]; + + if ($f[2] eq 'exon') { + die "no position at exon on line $." if ! $f[3]; + # gff3 puts :\d in exons sometimes + $id =~ s/:\d+$// if $gff == 3; + push @{$exons{$id}}, \@f; + # save lowest start + $trans{$id} = \@f if !$trans{$id}; + } elsif ($f[2] eq 'start_codon') { + #optional, output codon start/stop as "thick" region in bed + $sc{$id}->[0] = $f[3]; + } elsif ($f[2] eq 'stop_codon') { + $sc{$id}->[1] = $f[4]; + } elsif ($f[2] eq 'miRNA' ) { + $trans{$id} = \@f if !$trans{$id}; + push @{$exons{$id}}, \@f; + } +} + +for $id ( + # sort by chr then pos + sort { + $trans{$a}->[0] eq $trans{$b}->[0] ? + $trans{$a}->[3] <=> $trans{$b}->[3] : + $trans{$a}->[0] cmp $trans{$b}->[0] + } (keys(%trans)) ) { + my ($chr, undef, undef, undef, undef, undef, $dir, undef, $attr, undef, $cds, $cde) = @{$trans{$id}}; + my ($cds, $cde); + ($cds, $cde) = @{$sc{$id}} if $sc{$id}; + + # sort by pos + my @ex = sort { + $a->[3] <=> $b->[3] + } @{$exons{$id}}; + + my $beg = $ex[0][3]; + my $end = $ex[-1][4]; + + if ($dir eq '-') { + # swap + $tmp=$cds; + $cds=$cde; + $cde=$tmp; + $cds -= 2 if $cds; + $cde += 2 if $cde; + } + + # not specified, just use exons + $cds = $beg if !$cds; + $cde = $end if !$cde; + + # adjust start for bed + --$beg; --$cds; + + my $exn = @ex; # exon count + my $exst = join ",", map {$_->[3]-$beg-1} @ex; # exon start + my $exsz = join ",", map {$_->[4]-$_->[3]+1} @ex; # exon size + + my $gene_id; + my $extend = ""; + if ($extended) { + ($gene_id) = $attr =~ /gene_name "([^"]+)"/; + ($gene_id) = $attr =~ /gene_id "([^"]+)"/ unless $gene_id; + $extend="\t$gene_id"; + } + # added an extra comma to make it look exactly like ucsc's beds + print "$chr\t$beg\t$end\t$id\t0\t$dir\t$cds\t$cde\t0\t$exn\t$exsz,\t$exst,$extend\n"; +} + + +close IN; diff --git a/bin/make_ctss.sh b/bin/make_ctss.sh old mode 100644 new mode 100755 index c5150e9..71c6538 --- a/bin/make_ctss.sh +++ b/bin/make_ctss.sh @@ -27,20 +27,20 @@ if [[ $var =~ bam$ ]]; then base=${file%%.*} echo "working on: ${base}" - TMPFILE="/tmp/$(basename $0).$RANDOM.txt" - samtools view -F 4 -u -q $QCUT -b $var | bamToBed -i stdin > $TMPFILE - cat ${TMPFILE} \ - | awk 'BEGIN{OFS="\t"}{if($6=="+"){print $1,$2,$5}}' \ + TMPFILE="/tmp/$(basename "$0").$RANDOM.txt" + samtools view -F 4 -u -q $QCUT -b "$var" | bamToBed -i stdin > "$TMPFILE" + + awk 'BEGIN{OFS="\t"}{if($6=="+"){print $1,$2,$5}}' "${TMPFILE}" \ | sort -k1,1 -k2,2n \ | groupBy -i stdin -g 1,2 -c 3 -o count \ - | awk -v x="$base" 'BEGIN{OFS="\t"}{print $1,$2,$2+1, x ,$3,"+"}' >> $base.ctss.bed + | awk -v x="$base" 'BEGIN{OFS="\t"}{print $1,$2,$2+1, x ,$3,"+"}' >> "$base".ctss.bed + - cat ${TMPFILE} \ - | awk 'BEGIN{OFS="\t"}{if($6=="-"){print $1,$3,$5}}' \ + awk 'BEGIN{OFS="\t"}{if($6=="-"){print $1,$3,$5}}' "${TMPFILE}" \ | sort -k1,1 -k2,2n \ | groupBy -i stdin -g 1,2 -c 3 -o count \ - | awk -v x="$base" 'BEGIN{OFS="\t"}{print $1,$2-1,$2, x ,$3,"-"}' >> $base.ctss.bed + | awk -v x="$base" 'BEGIN{OFS="\t"}{print $1,$2-1,$2, x ,$3,"-"}' >> "$base".ctss.bed - rm $TMPFILE + rm "$TMPFILE" fi done diff --git a/bin/process_ctss.sh b/bin/process_ctss.sh old mode 100644 new mode 100755 diff --git a/bin/scrape_software_versions.py b/bin/scrape_software_versions.py index 57f3f42..c5b8fe8 100755 --- a/bin/scrape_software_versions.py +++ b/bin/scrape_software_versions.py @@ -13,6 +13,7 @@ 'bedtools': ['v_bedtools.txt', r"bedtools v(\S+)"], 'cutadapt': ['v_cutadapt.txt', r"(\S+)"], 'samtools': ['v_samtools.txt', r"samtools (\S+)"], + 'rseqc': ['v_rseqc.txt', r"read_distribution.py (\S+)"], } results = OrderedDict() results['nf-core/cageseq'] = 'N/A' @@ -24,6 +25,7 @@ results['bedtools'] = 'N/A' results['cutadapt'] = 'N/A' results['samtools'] = 'N/A' +results['rseqc'] = 'N/A' # Search each file using its regex for k, v in regexes.items(): diff --git a/environment.yml b/environment.yml index fd78b4b..b9b6300 100644 --- a/environment.yml +++ b/environment.yml @@ -19,3 +19,4 @@ dependencies: - bioconda::multiqc=1.8 - unzip=6.0 - bioconda::bowtie2=2.3.5 +- bioconda::rseqc=3.0.1 diff --git a/main.nf b/main.nf index 077126a..a3a60dc 100644 --- a/main.nf +++ b/main.nf @@ -86,7 +86,10 @@ if( params.star_index ){ .ifEmpty { exit 1, "STAR index not found: ${params.star_index}" } } else if ( params.fasta ){ - ch_fasta_for_star_index = file(params.fasta, checkIfExists: true) + Channel + .fromPath(params.fasta) + .ifEmpty { exit 1, "fasta file not found: ${params.fasta}" } + .into { ch_fasta_for_star_index; ; fasta_rseqc} } else { exit 1, "No reference genome specified!" @@ -96,7 +99,7 @@ if( params.gtf ){ Channel .fromPath(params.gtf) .ifEmpty { exit 1, "GTF annotation file not found: ${params.gtf}" } - .into { gtf_makeSTARindex; gtf_star} + .into { gtf_makeSTARindex; gtf_star; gtf_rseqc} } else { exit 1, "No GTF annotation specified!" } @@ -190,7 +193,6 @@ if (workflow.profile.contains('awsbatch')) { summary['AWS Region'] = params.awsregion summary['AWS Queue'] = params.awsqueue summary['AWS CLI'] = params.awscli - } summary['Config Profile'] = workflow.profile if (params.config_profile_description) summary['Config Description'] = params.config_profile_description @@ -245,10 +247,24 @@ process get_software_versions { cutadapt --version > v_cutadapt.txt samtools --version > v_samtools.txt bedtools --version > v_bedtools.txt + read_distribution.py --version > v_rseqc.txt scrape_software_versions.py &> software_versions_mqc.yaml """ } +process convert_gtf { + tag "$gtf" + + input: + file gtf from gtf_rseqc + output: + file "${gtf.baseName}.bed" into bed_rseqc + + script: // This script is bundled with the pipeline, in nfcore/cageseq/bin/ + """ + gtf2bed.pl $gtf > ${gtf.baseName}.bed + """ +} /* * STEP 1 - FastQC */ @@ -278,33 +294,33 @@ process fastqc { */ - process makeSTARindex { - tag "${fasta.baseName}" - publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, - saveAs: { params.saveReference ? it : null }, mode: 'copy' +process makeSTARindex { + tag "${fasta.baseName}" + publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, + saveAs: { params.saveReference ? it : null }, mode: 'copy' - input: - file fasta from ch_fasta_for_star_index - file gtf from gtf_makeSTARindex + input: + file fasta from ch_fasta_for_star_index + file gtf from gtf_makeSTARindex.collect() - output: - file "star" into star_index + output: + file "star" into star_index - when: - !(params.star_index) + when: + !(params.star_index) - script: - """ - mkdir star - STAR \\ - --runMode genomeGenerate \\ - --runThreadN ${task.cpus} \\ - --sjdbGTFfile $gtf \\ - --sjdbOverhang 50 \\ - --genomeDir star/ \\ - --genomeFastaFiles $fasta - """ - } + script: + """ + mkdir star + STAR \\ + --runMode genomeGenerate \\ + --runThreadN ${task.cpus} \\ + --sjdbGTFfile $gtf \\ + --sjdbOverhang 50 \\ + --genomeDir star/ \\ + --genomeFastaFiles $fasta + """ +} @@ -494,14 +510,40 @@ process star { --readFilesIn $reads \\ --runThreadN ${task.cpus} \\ --outSAMtype BAM SortedByCoordinate \\ + --outFilterScoreMinOverLread 0 --outFilterMatchNminOverLread 0 \\ + --outFilterMismatchNmax 1 \\ --readFilesCommand zcat \\ --runDirPerm All_RWX \\ --outFileNamePrefix $prefix \\ --outFilterMatchNmin ${params.min_aln_length} """ } +star_aligned.into { bam_stats; bam_star } +process samtools_stats { + tag "$sample_name" + label 'process_medium' + // if (params.save_align_intermeds) { + // publishDir "${params.outdir}/STAR", mode: 'copy', + // saveAs: { filename -> + // if (filename.endsWith(".flagstat")) "samtools_stats/$filename" + // else if (filename.endsWith(".idxstats")) "samtools_stats/$filename" + // else if (filename.endsWith(".stats")) "samtools_stats/$filename" + // else filename + // } + // } + input: + set val(sample_name), file(bam_count) from bam_stats + output: + file "*.{flagstat,idxstats,stats}" into bam_flagstat_mqc + + script: + """ + samtools idxstats $bam_count > ${bam_count}.idxstats + samtools stats $bam_count > ${bam_count}.stats + """ +} /** * STEP 8 - Get CTSS files @@ -511,7 +553,7 @@ process get_ctss { publishDir "${params.outdir}/ctss", mode: 'copy' input: - set val(sample_name), file(bam_count) from star_aligned + set val(sample_name), file(bam_count) from bam_star output: set val(sample_name), file("*.ctss.bed") into ctss_counts @@ -547,12 +589,34 @@ process cluster_ctss { paraclu-cut.sh "!{ctss.baseName}neg_clustered" > "!{ctss.baseName}neg_clustered_simplified" - cat "!{ctss.baseName}pos_clustered_simplified" "!{ctss.baseName}neg_clustered_simplified" > "!{ctss.baseName}clustered_simplified.bed" - awk -F '\t' '{print $1"\t"$3"\t"$4"\t"$1":"$3".."$4","$2"\t"$6"\t"$2}' "!{ctss.baseName}clustered_simplified.bed" > "!{ctss.baseName}_clustered_simplified.bed" + cat "!{ctss.baseName}pos_clustered_simplified" "!{ctss.baseName}neg_clustered_simplified" > "!{ctss.baseName}_clustered_simplified" + awk -F '\t' '{print $1"\t"$3"\t"$4"\t"$1":"$3".."$4","$2"\t"$6"\t"$2}' "!{ctss.baseName}_clustered_simplified" > "!{ctss.baseName}_clustered_simplified.bed" ''' } - +process ctss_qc { + tag "$clusters" + publishDir "${params.outdir}/rseqc" , mode: 'copy', + saveAs: {filename -> + if (filename.indexOf("read_distribution.txt") > 0) "read_distribution/$filename" + else filename + } + + input: + file clusters from ctss_clusters + file gtf from bed_rseqc.collect() + file fasta from fasta_rseqc.collect() + + output: + file "*.txt" into rseqc_results + + shell: + ''' + cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.tmp + bedtools bedtobam -i !{clusters} -g chrom_sizes.tmp > !{clusters.baseName}.bam + read_distribution.py -i !{clusters.baseName}.bam -r !{gtf} > !{clusters.baseName}.read_distribution.txt + ''' + } /* * STEP 10 - MultiQC */ @@ -568,6 +632,8 @@ process multiqc { file ('artifacts_trimmed/*') from artifact_cutting_results.collect().ifEmpty([]) file ('trimmed/fastqc/*') from trimmed_fastqc_results.collect().ifEmpty([]) file ('alignment/*') from alignment_logs.collect().ifEmpty([]) + file ('alignment/samtools_stats/*') from bam_flagstat_mqc.collect().ifEmpty([]) + file ('rseqc/*') from rseqc_results.collect().ifEmpty([]) file workflow_summary from ch_workflow_summary.collectFile(name: "workflow_summary_mqc.yaml") output: @@ -582,7 +648,7 @@ process multiqc { """ multiqc -f $rtitle $rfilename $custom_config_file \\ - -m custom_content -m fastqc -m star -m cutadapt . + -m custom_content -m fastqc -m star -m cutadapt -m rseqc -m samtools . """ } From 701885d0c292a3c2c7832923bdb83086d79f9cfc Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 27 Feb 2020 17:19:26 +0100 Subject: [PATCH 037/107] add bowtie option --- bin/scrape_software_versions.py | 4 +- environment.yml | 2 +- main.nf | 89 +++++++++++++++++++++++++++++---- nextflow.config | 3 ++ 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/bin/scrape_software_versions.py b/bin/scrape_software_versions.py index c5b8fe8..70dac50 100755 --- a/bin/scrape_software_versions.py +++ b/bin/scrape_software_versions.py @@ -9,7 +9,7 @@ 'FastQC': ['v_fastqc.txt', r"FastQC v(\S+)"], 'MultiQC': ['v_multiqc.txt', r"multiqc, version (\S+)"], 'STAR': ['v_star.txt', r"STAR_(\S+)"], - 'bowtie2': ['v_bowtie2.txt', r"version (\S+)"], + 'bowtie': ['v_bowtie.txt', r"version (\S+)"], 'bedtools': ['v_bedtools.txt', r"bedtools v(\S+)"], 'cutadapt': ['v_cutadapt.txt', r"(\S+)"], 'samtools': ['v_samtools.txt', r"samtools (\S+)"], @@ -20,7 +20,7 @@ results['Nextflow'] = 'N/A' results['FastQC'] = 'N/A' results['MultiQC'] = 'N/A' -results['bowtie2'] = 'N/A' +results['bowtie'] = 'N/A' results['STAR'] = 'N/A' results['bedtools'] = 'N/A' results['cutadapt'] = 'N/A' diff --git a/environment.yml b/environment.yml index b9b6300..6ab5300 100644 --- a/environment.yml +++ b/environment.yml @@ -18,5 +18,5 @@ dependencies: - bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. - bioconda::multiqc=1.8 - unzip=6.0 -- bioconda::bowtie2=2.3.5 +- bioconda::bowtie=1.2.3 - bioconda::rseqc=3.0.1 diff --git a/main.nf b/main.nf index a3a60dc..5e69f45 100644 --- a/main.nf +++ b/main.nf @@ -89,7 +89,7 @@ else if ( params.fasta ){ Channel .fromPath(params.fasta) .ifEmpty { exit 1, "fasta file not found: ${params.fasta}" } - .into { ch_fasta_for_star_index; ; fasta_rseqc} + .into { fasta_star_index; fasta_bowtie_index; fasta_rseqc} } else { exit 1, "No reference genome specified!" @@ -242,8 +242,8 @@ process get_software_versions { echo $workflow.nextflow.version > v_nextflow.txt fastqc --version > v_fastqc.txt multiqc --version > v_multiqc.txt - bowtie2 --version > v_bowtie2.txt STAR --version > v_star.txt + bowtie --version > v_bowite.txt cutadapt --version > v_cutadapt.txt samtools --version > v_samtools.txt bedtools --version > v_bedtools.txt @@ -300,14 +300,14 @@ process makeSTARindex { saveAs: { params.saveReference ? it : null }, mode: 'copy' input: - file fasta from ch_fasta_for_star_index + file fasta from fasta_star_index file gtf from gtf_makeSTARindex.collect() output: file "star" into star_index when: - !(params.star_index) + !(params.star_index) || !(params.star_align) script: """ @@ -321,7 +321,29 @@ process makeSTARindex { --genomeFastaFiles $fasta """ } +process makeBowtieindex { + tag "${fasta.baseName}" + publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, + saveAs: { params.saveReference ? it : null }, mode: 'copy' + + input: + file fasta from fasta_bowtie_index + output: + // ${fasta.baseName}.index into bowtie_index + file "${fasta.baseName}.index*" into bowtie_index + when: + !(params.bowtie_index) ||!(params.bowtie_align) + + script: + """ + + + bowtie-build --threads ${task.cpus} ${fasta} ${fasta.baseName}.index + + + """ +} /* @@ -451,10 +473,10 @@ if (params.cutArtifacts){ > ${reads.baseName}.artifact_trimming.output.txt """ } - further_processed_reads.into { further_processed_reads_star; further_processed_reads_fastqc } + further_processed_reads.into { further_processed_reads_star;further_processed_reads_bowtie; further_processed_reads_fastqc } } else{ - processed_reads.into{further_processed_reads_star; further_processed_reads_fastqc} + processed_reads.into{further_processed_reads_star; further_processed_reads_bowtie; further_processed_reads_fastqc} artifact_cutting_results = Channel.empty() } @@ -497,9 +519,12 @@ process star { output: set val(sample_name), file("*.bam") into star_aligned - file "*.out" into alignment_logs + file "*.out" into star_alignment_logs file "*SJ.out.tab" + when: + params.star_align + script: prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ @@ -519,6 +544,51 @@ process star { """ } star_aligned.into { bam_stats; bam_star } + +process bowtie { + tag "$sample_name" + publishDir "${params.outdir}/bowtie", mode: 'copy', + saveAs: {filename -> + if (filename.indexOf(".bam") == -1) "logs/$filename" + else filename } + + input: + set val(sample_name), file(reads) from further_processed_reads_bowtie + file index_array from bowtie_index.collect() + + output: + set val(sample_name), file("*.bam") into bowtie_aligned + file "*.out" into bowtie_alignment_logs + + when: + params.bowtie_align + + script: + + prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ + index = index_array[0].baseName - ~/.\d$/ + """ + bowtie --sam \\ + -m 1 \\ + --best \\ + --strata \\ + -k 1 \\ + --tryhard \\ + --threads ${task.cpus} \\ + --phred33-quals \\ + --chunkmbs 64 \\ + --seedmms 2 \\ + --seedlen 28 \\ + --maqerr 70 \\ + ${index} \\ + -q ${reads} \\ + --un ${reads.baseName}.unAl > ${sample_name}.sam 2> ${sample_name}.out + + samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${sample_name}.sam + """ +} +bowtie_aligned.into { bam_stats; bam_bowtie } + process samtools_stats { tag "$sample_name" label 'process_medium' @@ -631,7 +701,8 @@ process multiqc { file ('trimmed/*') from cutadapt_results.collect().ifEmpty([]) file ('artifacts_trimmed/*') from artifact_cutting_results.collect().ifEmpty([]) file ('trimmed/fastqc/*') from trimmed_fastqc_results.collect().ifEmpty([]) - file ('alignment/*') from alignment_logs.collect().ifEmpty([]) + file ('alignment/*') from star_alignment_logs.collect().ifEmpty([]) + file ('alignment/*') from bowtie_alignment_logs.collect().ifEmpty([]) file ('alignment/samtools_stats/*') from bam_flagstat_mqc.collect().ifEmpty([]) file ('rseqc/*') from rseqc_results.collect().ifEmpty([]) file workflow_summary from ch_workflow_summary.collectFile(name: "workflow_summary_mqc.yaml") @@ -648,7 +719,7 @@ process multiqc { """ multiqc -f $rtitle $rfilename $custom_config_file \\ - -m custom_content -m fastqc -m star -m cutadapt -m rseqc -m samtools . + -m custom_content -m fastqc -m star -m cutadapt -m rseqc -m samtools -m bowtie1 . """ } diff --git a/nextflow.config b/nextflow.config index 0dd6480..145891c 100644 --- a/nextflow.config +++ b/nextflow.config @@ -53,6 +53,9 @@ params { // Alignment options star_index = false + bowtie_index = false + star_align = true + bowtie_align = true saveReference = false min_aln_length = 15 single_end = true From 0d4fc4620d53205ef0a94b296914a48d4d59e55c Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 2 Mar 2020 16:35:31 +0100 Subject: [PATCH 038/107] add option for bowtie aligner --- .github/workflows/ci.yml | 3 ++ conf/base.config | 75 +++++++++++++++++++++------------------- main.nf | 63 ++++++++++++++++++++++++--------- nextflow.config | 57 ++++++++++++++---------------- 4 files changed, 116 insertions(+), 82 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b69934..e16ca25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,9 @@ jobs: matrix: # Nextflow versions: check pipeline minimum and current latest nxf_ver: ['19.10.0', ''] + aligner: ["--aligner 'bowtie'", "--aligner 'star'"] + options: ['--trimming','--cutEcoP','--cutLinker','--cutG','--cutArtifacts' + '--skipQC', '--remove_rRNA', '--saveUnaligned', '--skipTrimming', '--star_index false','--bowtie_index false'] steps: - uses: actions/checkout@v2 - name: Install Nextflow diff --git a/conf/base.config b/conf/base.config index ac58b45..f68f4a0 100644 --- a/conf/base.config +++ b/conf/base.config @@ -10,42 +10,47 @@ */ process { + cpus = { check_max( 2, 'cpus' ) } + memory = { check_max( 8.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } - // TODO nf-core: Check the defaults for all processes - cpus = { check_max( 1 * task.attempt, 'cpus' ) } - memory = { check_max( 7.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } + errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'terminate' } + maxRetries = 1 + maxErrors = '-1' - errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } - maxRetries = 1 - maxErrors = '-1' - - // Process-specific resource requirements - // NOTE - Only one of the labels below are used in the fastqc process in the main script. - // If possible, it would be nice to keep the same label naming convention when - // adding in your processes. - // TODO nf-core: Customise requirements for specific processes. - // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors - withLabel:process_low { - cpus = { check_max( 2 * task.attempt, 'cpus' ) } - memory = { check_max( 14.GB * task.attempt, 'memory' ) } - time = { check_max( 6.h * task.attempt, 'time' ) } - } - withLabel:process_medium { - cpus = { check_max( 6 * task.attempt, 'cpus' ) } - memory = { check_max( 42.GB * task.attempt, 'memory' ) } - time = { check_max( 8.h * task.attempt, 'time' ) } - } - withLabel:process_high { - cpus = { check_max( 12 * task.attempt, 'cpus' ) } - memory = { check_max( 84.GB * task.attempt, 'memory' ) } - time = { check_max( 10.h * task.attempt, 'time' ) } - } - withLabel:process_long { - time = { check_max( 20.h * task.attempt, 'time' ) } - } - withName:get_software_versions { - cache = false - } + // Process-specific resource requirements + withLabel: low_memory { + memory = { check_max( 16.GB * task.attempt, 'memory' ) } + } + withLabel: mid_memory { + cpus = { check_max (4, 'cpus')} + memory = { check_max( 28.GB * task.attempt, 'memory' ) } + time = { check_max( 8.h * task.attempt, 'time' ) } + } + withLabel: high_memory { + cpus = { check_max (10, 'cpus')} + memory = { check_max( 70.GB * task.attempt, 'memory' ) } + time = { check_max( 8.h * task.attempt, 'time' ) } + } + withName: sortmerna { + cpus = { check_max( 16 * task.attempt, 'cpus' ) } + time = { check_max( 24.h * task.attempt, 'time' ) } + maxRetries = 2 + } + withName: 'get_software_versions' { + memory = { check_max( 2.GB * task.attempt, 'memory' ) } + cache = false + } + withName: 'multiqc' { + memory = { check_max( 2.GB * task.attempt, 'memory' ) } + cache = false + } +} +params { + // Defaults only, expecting to be overwritten + max_memory = 128.GB + max_cpus = 16 + max_time = 240.h + igenomes_base = 's3://ngi-igenomes/igenomes/' } diff --git a/main.nf b/main.nf index 5e69f45..bb12444 100644 --- a/main.nf +++ b/main.nf @@ -30,6 +30,8 @@ def helpMessage() { --cutEcoP Set to false to not cut the EcoP --cutLinker Set to false to not cut the linker --cutG Set to false to not cut the additonal G at the 5' end + --star_index Path to STAR index, set to false if igenomes should be used + --bowtie_index Path to bowtie index, set to false if igenomes should be used --cutArtifacts Set to false to not cut artifacts --artifacts5end Path to 5 end artifact file, if not given the pipeline will use a default file with all possible artifacts --artifacts3end Path to 3 end artifact file, if not given the pipeline will use a default file with all possible artifacts @@ -37,10 +39,11 @@ def helpMessage() { References If not specified in the configuration file or you wish to overwrite any of the references --fasta [file] Path to fasta reference - --star_index Path to the star index, if not given the pipeline will automatically try to build one with the given fasta and gtf file --genome Name of iGenomes reference --gtf Path to gtf file + Alignment: + --aligner Specifies the aligner to use (available are: 'star', 'bowtie') Other options: --outdir [file] The output directory where the results will be saved @@ -72,6 +75,7 @@ if (params.genomes && params.genome && !params.genomes.containsKey(params.genome } params.star_index = params.genome ? params.genomes[ params.genome ].star ?: false : false +params.bowtie_index = params.genome ? params.genomes[ params.genome ].bowtie ?: false : false params.fasta = params.genome ? params.genomes[ params.genome ].fasta ?: false : false if (params.fasta) { ch_fasta = file(params.fasta, checkIfExists: true) } params.gtf = params.genome ? params.genomes[ params.genome ].gtf ?: false : false @@ -80,11 +84,19 @@ params.gtf = params.genome ? params.genomes[ params.genome ].gtf ?: false : fals params.min_cluster = 30 // Validate inputs -if( params.star_index ){ +if (params.aligner != 'star' && params.aligner != 'bowtie') { + exit 1, "Invalid aligner option: ${params.aligner}. Valid options: 'star', 'bowtie'" +} +if( params.star_index && params.aligner == 'star' ){ star_index = Channel .fromPath(params.star_index) .ifEmpty { exit 1, "STAR index not found: ${params.star_index}" } } +else if( params.bowtie_index && params.aligner == 'bowtie' ){ + bowtie_index = Channel + .fromPath(params.bowtie_index) + .ifEmpty { exit 1, "STAR index not found: ${params.bowtie_index}" } +} else if ( params.fasta ){ Channel .fromPath(params.fasta) @@ -168,7 +180,17 @@ if(params.readPaths){ log.info nfcoreHeader() def summary = [:] summary['Run Name'] = custom_runName ?: workflow.runName -summary['Reads'] = params.reads +if (params.genome){summary['Reads'] = params.reads} +if (params.aligner == 'star') { + summary['Aligner'] = "STAR" + if (params.star_index)summary['STAR Index'] = params.star_index + else if (params.fasta)summary['Fasta Ref'] = params.fasta +} else if (params.aligner == 'bowtie') { + summary['Aligner'] = "bowtie" + if (params.bowtie_index)summary['bowtie Index'] = params.bowtie_index + else if (params.fasta)summary['Fasta Ref'] = params.fasta + if (params.splicesites)summary['Splice Sites'] = params.splicesites +} summary['Fasta Ref'] = params.fasta summary['GTF Ref'] = params.gtf if(params.artifacts5end){ summary["5' artifacts"] = params.artifacts5end} @@ -265,6 +287,7 @@ process convert_gtf { gtf2bed.pl $gtf > ${gtf.baseName}.bed """ } + /* * STEP 1 - FastQC */ @@ -295,6 +318,7 @@ process fastqc { process makeSTARindex { + label 'high_memory' tag "${fasta.baseName}" publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, saveAs: { params.saveReference ? it : null }, mode: 'copy' @@ -307,18 +331,19 @@ process makeSTARindex { file "star" into star_index when: - !(params.star_index) || !(params.star_align) + params.aligner == 'star' && !params.star_index && params.fasta script: + def avail_mem = task.memory ? "--limitGenomeGenerateRAM ${task.memory.toBytes() - 100000000}" : '' """ mkdir star STAR \\ --runMode genomeGenerate \\ --runThreadN ${task.cpus} \\ --sjdbGTFfile $gtf \\ - --sjdbOverhang 50 \\ --genomeDir star/ \\ - --genomeFastaFiles $fasta + --genomeFastaFiles $fasta \\ + $avail_mem """ } process makeBowtieindex { @@ -333,7 +358,7 @@ process makeBowtieindex { // ${fasta.baseName}.index into bowtie_index file "${fasta.baseName}.index*" into bowtie_index when: - !(params.bowtie_index) ||!(params.bowtie_align) + params.aligner == 'bowtie' && !params.bowtie_index && params.fasta script: """ @@ -504,8 +529,9 @@ else{ * STEP 7 - STAR alignment */ further_processed_reads_star = further_processed_reads_star.dump(tag:"star") - +if (params.aligner == 'star') { process star { + label 'high_memory' tag "$sample_name" publishDir "${params.outdir}/STAR", mode: 'copy', saveAs: {filename -> @@ -522,8 +548,6 @@ process star { file "*.out" into star_alignment_logs file "*SJ.out.tab" - when: - params.star_align script: @@ -542,10 +566,16 @@ process star { --outFileNamePrefix $prefix \\ --outFilterMatchNmin ${params.min_aln_length} """ + } -star_aligned.into { bam_stats; bam_star } +star_aligned.into { bam_stats; bam_aligned } +} else{ + star_alignment_logs = Channel.empty() +} +if (params.aligner == 'bowtie'){ process bowtie { + label 'high_memory' tag "$sample_name" publishDir "${params.outdir}/bowtie", mode: 'copy', saveAs: {filename -> @@ -557,11 +587,9 @@ process bowtie { file index_array from bowtie_index.collect() output: - set val(sample_name), file("*.bam") into bowtie_aligned + set val(sample_name), file("*.bam") into bam_stats, bam_aligned file "*.out" into bowtie_alignment_logs - when: - params.bowtie_align script: @@ -586,8 +614,11 @@ process bowtie { samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${sample_name}.sam """ + +} +}else{ + bowtie_alignment_logs= Channel.empty() } -bowtie_aligned.into { bam_stats; bam_bowtie } process samtools_stats { tag "$sample_name" @@ -623,7 +654,7 @@ process get_ctss { publishDir "${params.outdir}/ctss", mode: 'copy' input: - set val(sample_name), file(bam_count) from bam_star + set val(sample_name), file(bam_count) from bam_aligned output: set val(sample_name), file("*.ctss.bed") into ctss_counts diff --git a/nextflow.config b/nextflow.config index 145891c..2eb9c39 100644 --- a/nextflow.config +++ b/nextflow.config @@ -9,14 +9,36 @@ params { // Workflow flags - // TODO nf-core: Specify your pipeline's command line flags genome = false - reads = "data/*{1,2}.fastq.gz" single_end = false readPaths = false // Used for test profiles outdir = './results' + + + + + + // CAGE-seq specific options + // Alignment options + aligner = 'star' + star_index = false + bowtie_index = false + saveReference = false + min_aln_length = 15 + single_end = true + // Trimming options (all enabled by default) + trimming = true + cutEcop = true + cutLinker = true + cutG = true + cutArtifacts = true + ecoSite = 'CAGCAG' + linkerSeq = 'TCGTATGCCGTCTTC' + artifacts3end = "$baseDir/assets/artifacts_3end.fasta" + artifacts5end = "$baseDir/assets/artifacts_5end.fasta" + // Boilerplate options name = false multiqc_config = false @@ -37,38 +59,12 @@ params { config_profile_url = false - // CAGE-seq specific options - // Trimming options (all enabled by default) - remove_phix = true - trimming = true - cutEcop = true - cutLinker = true - cutG = true - cutArtifacts = true - ecoSite = 'CAGCAG' - linkerSeq = 'TCGTATGCCGTCTTC' - artifacts3end = "$baseDir/assets/artifacts_3end.fasta" - artifacts5end = "$baseDir/assets/artifacts_5end.fasta" - - - // Alignment options - star_index = false - bowtie_index = false - star_align = true - bowtie_align = true - saveReference = false - min_aln_length = 15 - single_end = true - // Defaults only, expecting to be overwritten - max_memory = 128.GB - max_cpus = 16 - max_time = 240.h } // Container slug. Stable releases should specify release tag! // Developmental code should specify :dev -process.container = 'nfcore/cageseq:dev' +process.container = 'mashehu/cageseq:dev' // Load base.config by default for all pipelines includeConfig 'conf/base.config' @@ -96,7 +92,6 @@ profiles { singularity.autoMounts = true } test { includeConfig 'conf/test.config' } - devtest { includeConfig 'conf/devtest.config' } galaxy { includeConfig 'conf/base.config' includeConfig 'conf/galaxy_local.config' @@ -136,7 +131,7 @@ dag { manifest { name = 'nf-core/cageseq' - author = 'Kevin Menden; Tristan Kast.' + author = 'Kevin Menden, Tristan Kast, Matthias Hörtenhuber' homePage = 'https://github.com/nf-core/cageseq' description = 'CAGE-seq pipeline' mainScript = 'main.nf' From 56b47b733ced393ffee0cd93c91b11dea1e7ac5c Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 2 Mar 2020 16:38:19 +0100 Subject: [PATCH 039/107] fix incorrect ci.yml options --- .github/workflows/ci.yml | 3 +-- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e16ca25..9fdbb2f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,8 +14,7 @@ jobs: # Nextflow versions: check pipeline minimum and current latest nxf_ver: ['19.10.0', ''] aligner: ["--aligner 'bowtie'", "--aligner 'star'"] - options: ['--trimming','--cutEcoP','--cutLinker','--cutG','--cutArtifacts' - '--skipQC', '--remove_rRNA', '--saveUnaligned', '--skipTrimming', '--star_index false','--bowtie_index false'] + options: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false', '--star_index false','--bowtie_index false'] steps: - uses: actions/checkout@v2 - name: Install Nextflow diff --git a/nextflow.config b/nextflow.config index 2eb9c39..b8b03e2 100644 --- a/nextflow.config +++ b/nextflow.config @@ -64,7 +64,7 @@ params { // Container slug. Stable releases should specify release tag! // Developmental code should specify :dev -process.container = 'mashehu/cageseq:dev' +process.container = 'nfcore/cageseq:dev' // Load base.config by default for all pipelines includeConfig 'conf/base.config' From 5a368796da6564c539eec46757bd2c7181f521fd Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 5 Mar 2020 15:14:57 +0100 Subject: [PATCH 040/107] fix error for cases of available index files --- main.nf | 101 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/main.nf b/main.nf index bb12444..81418b7 100644 --- a/main.nf +++ b/main.nf @@ -89,27 +89,36 @@ if (params.aligner != 'star' && params.aligner != 'bowtie') { } if( params.star_index && params.aligner == 'star' ){ star_index = Channel - .fromPath(params.star_index) + .fromPath(params.star_index, checkIfExists: true) .ifEmpty { exit 1, "STAR index not found: ${params.star_index}" } } else if( params.bowtie_index && params.aligner == 'bowtie' ){ bowtie_index = Channel - .fromPath(params.bowtie_index) + .fromPath(params.bowtie_index, checkIfExists: true) .ifEmpty { exit 1, "STAR index not found: ${params.bowtie_index}" } } else if ( params.fasta ){ Channel - .fromPath(params.fasta) + .fromPath(params.fasta, checkIfExists: true) .ifEmpty { exit 1, "fasta file not found: ${params.fasta}" } - .into { fasta_star_index; fasta_bowtie_index; fasta_rseqc} + .into { fasta_star_index; fasta_bowtie_index} } else { exit 1, "No reference genome specified!" } + +if( params.fasta ){ + fasta_rseqc = Channel + .fromPath(params.fasta, checkIfExists: true) + .ifEmpty { exit 1, "fasta file not found: ${params.fasta}" } +} else { + exit 1, "No fasta file specified!" +} + if( params.gtf ){ Channel - .fromPath(params.gtf) + .fromPath(params.gtf, checkIfExists: true) .ifEmpty { exit 1, "GTF annotation file not found: ${params.gtf}" } .into { gtf_makeSTARindex; gtf_star; gtf_rseqc} } else { @@ -316,60 +325,62 @@ process fastqc { * STEP 2 - Build STAR index */ +if(params.aligner == 'star' && !params.star_index && params.fasta){ + process makeSTARindex { + label 'high_memory' + tag "${fasta.baseName}" + publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, + saveAs: { params.saveReference ? it : null }, mode: 'copy' -process makeSTARindex { - label 'high_memory' - tag "${fasta.baseName}" - publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, - saveAs: { params.saveReference ? it : null }, mode: 'copy' + input: + file fasta from fasta_star_index + file gtf from gtf_makeSTARindex.collect() - input: - file fasta from fasta_star_index - file gtf from gtf_makeSTARindex.collect() + output: + file "star" into star_index - output: - file "star" into star_index + when: - when: - params.aligner == 'star' && !params.star_index && params.fasta - script: - def avail_mem = task.memory ? "--limitGenomeGenerateRAM ${task.memory.toBytes() - 100000000}" : '' - """ - mkdir star - STAR \\ - --runMode genomeGenerate \\ - --runThreadN ${task.cpus} \\ - --sjdbGTFfile $gtf \\ - --genomeDir star/ \\ - --genomeFastaFiles $fasta \\ - $avail_mem - """ + script: + def avail_mem = task.memory ? "--limitGenomeGenerateRAM ${task.memory.toBytes() - 100000000}" : '' + """ + mkdir star + STAR \\ + --runMode genomeGenerate \\ + --runThreadN ${task.cpus} \\ + --sjdbGTFfile $gtf \\ + --genomeDir star/ \\ + --genomeFastaFiles $fasta \\ + $avail_mem + """ + } } -process makeBowtieindex { - tag "${fasta.baseName}" - publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, - saveAs: { params.saveReference ? it : null }, mode: 'copy' + if(params.aligner == 'bowtie' && !params.bowtie_index && params.fasta){ + process makeBowtieindex { + tag "${fasta.baseName}" + publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, + saveAs: { params.saveReference ? it : null }, mode: 'copy' - input: - file fasta from fasta_bowtie_index + input: + file fasta from fasta_bowtie_index - output: - // ${fasta.baseName}.index into bowtie_index - file "${fasta.baseName}.index*" into bowtie_index - when: - params.aligner == 'bowtie' && !params.bowtie_index && params.fasta + output: + // ${fasta.baseName}.index into bowtie_index + file "${fasta.baseName}.index*" into bowtie_index + when: - script: - """ + script: + """ - bowtie-build --threads ${task.cpus} ${fasta} ${fasta.baseName}.index + bowtie-build --threads ${task.cpus} ${fasta} ${fasta.baseName}.index - """ -} + """ + } +} /* * STEP 3 - Cut Enzyme binding site at 5' and linker at 3' From c8ca52ec3699cb31b391bcd3323248f1d71cf140 Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 11 Mar 2020 16:39:16 +0100 Subject: [PATCH 041/107] fix incorrect nextflow config for index build step --- nextflow.config | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nextflow.config b/nextflow.config index b8b03e2..1d6315e 100644 --- a/nextflow.config +++ b/nextflow.config @@ -12,7 +12,7 @@ params { genome = false single_end = false readPaths = false // Used for test profiles - + reads = false outdir = './results' @@ -23,8 +23,6 @@ params { // CAGE-seq specific options // Alignment options aligner = 'star' - star_index = false - bowtie_index = false saveReference = false min_aln_length = 15 single_end = true From 7d83fd8d73508555d8a0e80721dd912c7f8770e1 Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 11 Mar 2020 16:41:09 +0100 Subject: [PATCH 042/107] improve file name handling inside bash scripts --- bin/make_ctss.sh | 47 +++++++++++++++++++++++---------------------- bin/process_ctss.sh | 20 ++++++++++--------- main.nf | 33 +++++++++++++++---------------- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/bin/make_ctss.sh b/bin/make_ctss.sh index 71c6538..60c8419 100755 --- a/bin/make_ctss.sh +++ b/bin/make_ctss.sh @@ -3,44 +3,45 @@ if [ $# -eq 0 ] then cat < ... +Usage is : $0 -q -i -n EOF exit 1; fi QCUT= -while getopts q: opt +while getopts :i:q:n: opt do case ${opt} in q) QCUT=${OPTARG};; +i) VAR=${OPTARG};; +n) NAME=${OPTARG};; *) usage;; esac done -if [ "${QCUT}" = "" ]; then QCUT=10; fi +if [ "${QCUT}" = "" ]; then QCUT=20; fi -for var in "$@" -do -if [[ $var =~ bam$ ]]; then - file=${var##*/} - base=${file%%.*} - echo "working on: ${base}" - - TMPFILE="/tmp/$(basename "$0").$RANDOM.txt" - samtools view -F 4 -u -q $QCUT -b "$var" | bamToBed -i stdin > "$TMPFILE" +# for VAR in "$@" +# do +# file=${VAR##*/} +echo "working on: ${VAR}" - awk 'BEGIN{OFS="\t"}{if($6=="+"){print $1,$2,$5}}' "${TMPFILE}" \ - | sort -k1,1 -k2,2n \ - | groupBy -i stdin -g 1,2 -c 3 -o count \ - | awk -v x="$base" 'BEGIN{OFS="\t"}{print $1,$2,$2+1, x ,$3,"+"}' >> "$base".ctss.bed +#convert sam to bam and bam to bed +TMPFILE="/tmp/$(basename "$0").$RANDOM.txt" +samtools view -F 4 -u -q $QCUT -b "$VAR.bam" | bamToBed -i stdin > "$TMPFILE" + #generate ctss on the positive strand +awk 'BEGIN{OFS="\t"}{if($6=="+"){print $1,$2,$5}}' "${TMPFILE}" \ +| sort -k1,1 -k2,2n \ +| groupBy -i stdin -g 1,2 -c 3 -o count \ +| awk -v x="$NAME" 'BEGIN{OFS="\t"}{print $1,$2,$2+1, x ,$3,"+"}' >> "$NAME".pos.ctss.bed - awk 'BEGIN{OFS="\t"}{if($6=="-"){print $1,$3,$5}}' "${TMPFILE}" \ - | sort -k1,1 -k2,2n \ - | groupBy -i stdin -g 1,2 -c 3 -o count \ - | awk -v x="$base" 'BEGIN{OFS="\t"}{print $1,$2-1,$2, x ,$3,"-"}' >> "$base".ctss.bed +#generate ctss on the negative strand +awk 'BEGIN{OFS="\t"}{if($6=="-"){print $1,$3,$5}}' "${TMPFILE}" \ +| sort -k1,1 -k2,2n \ +| groupBy -i stdin -g 1,2 -c 3 -o count \ +| awk -v x="$NAME" 'BEGIN{OFS="\t"}{print $1,$2-1,$2, x ,$3,"-"}' >> "$NAME".neg.ctss.bed - rm "$TMPFILE" -fi -done +rm "$TMPFILE" +# done diff --git a/bin/process_ctss.sh b/bin/process_ctss.sh index a14dc9b..466bfb5 100755 --- a/bin/process_ctss.sh +++ b/bin/process_ctss.sh @@ -1,5 +1,7 @@ #!/bin/sh # +set -e + if [ $# -eq 0 ] then cat < ${CTSS}_allm -grep + $CTSS_FILE > ${CTSS}_allp +# sed '/+/d' $CTSS_FILE.bed > ${CTSS}_allm +# grep + $CTSS_FILE.bed > ${CTSS}_allp # put CTSS output to paraclu format -awk -F "\t" '{print$1"\t"$6"\t"$2"\t"$5}' < ${CTSS}_allm > ${CTSS}_pos_4P -awk -F "\t" '{print$1"\t"$6"\t"$3"\t"$5}' < ${CTSS}_allp > ${CTSS}_neg_4P +awk -F "\t" '{print$1"\t"$6"\t"$2"\t"$5}' < $CTSS_POS.bed > ${CTSS_POS}_pos_4P +awk -F "\t" '{print$1"\t"$6"\t"$3"\t"$5}' < $CTSS_NEG.bed > ${CTSS_NEG}_neg_4P # sort the pos and neg strand prior paraclu clustering -sort -k1,1 -k3n ${CTSS}_pos_4P > ${CTSS}_pos_4Ps -sort -k1,1 -k3n ${CTSS}_neg_4P > ${CTSS}_neg_4Ps +sort -k1,1 -k3n ${CTSS_POS}_pos_4P > ${CTSS_POS}_pos_4Ps +sort -k1,1 -k3n ${CTSS_NEG}_neg_4P > ${CTSS_NEG}_neg_4Ps diff --git a/main.nf b/main.nf index 81418b7..7455281 100644 --- a/main.nf +++ b/main.nf @@ -18,7 +18,7 @@ def helpMessage() { The typical command for running the pipeline is as follows: - nextflow run nf-core/cageseq --reads /path/to/data.fastq.gz --star_index /path/to/index -profile docker + nextflow run nf-core/cageseq --reads '*_R{1,2}.fastq.gz' --aligner star --genome GRCh38 -profile docker Mandatory arguments: --reads [file] Path to input data (must be surrounded with quotes) @@ -192,16 +192,14 @@ summary['Run Name'] = custom_runName ?: workflow.runName if (params.genome){summary['Reads'] = params.reads} if (params.aligner == 'star') { summary['Aligner'] = "STAR" - if (params.star_index)summary['STAR Index'] = params.star_index - else if (params.fasta)summary['Fasta Ref'] = params.fasta + if (params.star_index){summary['STAR Index'] = params.star_index} + else if (params.fasta){summary['Fasta Ref'] = params.fasta} } else if (params.aligner == 'bowtie') { summary['Aligner'] = "bowtie" if (params.bowtie_index)summary['bowtie Index'] = params.bowtie_index else if (params.fasta)summary['Fasta Ref'] = params.fasta if (params.splicesites)summary['Splice Sites'] = params.splicesites } -summary['Fasta Ref'] = params.fasta -summary['GTF Ref'] = params.gtf if(params.artifacts5end){ summary["5' artifacts"] = params.artifacts5end} if(params.artifacts3end){ summary["3' artifacts"] = params.artifacts3end} summary['Trimming'] = params.trimming @@ -366,7 +364,6 @@ if(params.aligner == 'star' && !params.star_index && params.fasta){ file fasta from fasta_bowtie_index output: - // ${fasta.baseName}.index into bowtie_index file "${fasta.baseName}.index*" into bowtie_index when: @@ -480,6 +477,7 @@ if(params.trimming){ /** * STEP 5 - Remove artifacts */ + if (params.cutArtifacts){ process cut_artifacts { tag "$sample_name" @@ -672,16 +670,16 @@ process get_ctss { script: """ - bash make_ctss.sh $bam_count + make_ctss.sh -q 20 -i ${bam_count.baseName} -n ${sample_name} """ } /** * STEP 9 - Cluster CTSS files */ - +ctss_counts = ctss_counts.dump(tag:"ctss_counts") process cluster_ctss { - tag "${ctss.simpleName}" + tag "${ctss}" publishDir "${params.outdir}/ctss/clusters", mode: 'copy' input: @@ -692,20 +690,20 @@ process cluster_ctss { shell: ''' - bash process_ctss.sh !{ctss} + bash process_ctss.sh !{ctss[0].baseName} !{ctss[1].baseName} - paraclu !{params.min_cluster} "!{ctss.baseName}_pos_4Ps" > "!{ctss.baseName}pos_clustered" - paraclu !{params.min_cluster} "!{ctss.baseName}_neg_4Ps" > "!{ctss.baseName}neg_clustered" + paraclu !{params.min_cluster} "!{ctss[1].baseName}_pos_4Ps" > "!{ctss[1].baseName}pos_clustered" + paraclu !{params.min_cluster} "!{ctss[0].baseName}_neg_4Ps" > "!{ctss[0].baseName}neg_clustered" - paraclu-cut.sh "!{ctss.baseName}pos_clustered" > "!{ctss.baseName}pos_clustered_simplified" - paraclu-cut.sh "!{ctss.baseName}neg_clustered" > "!{ctss.baseName}neg_clustered_simplified" + paraclu-cut.sh "!{ctss[1].baseName}pos_clustered" > "!{ctss[1].baseName}pos_clustered_simplified" + paraclu-cut.sh "!{ctss[0].baseName}neg_clustered" > "!{ctss[0].baseName}neg_clustered_simplified" - cat "!{ctss.baseName}pos_clustered_simplified" "!{ctss.baseName}neg_clustered_simplified" > "!{ctss.baseName}_clustered_simplified" - awk -F '\t' '{print $1"\t"$3"\t"$4"\t"$1":"$3".."$4","$2"\t"$6"\t"$2}' "!{ctss.baseName}_clustered_simplified" > "!{ctss.baseName}_clustered_simplified.bed" + cat "!{ctss[1].baseName}pos_clustered_simplified" "!{ctss[0].baseName}neg_clustered_simplified" > "!{ctss[0].baseName}_clustered_simplified" + awk -F '\t' '{print $1"\t"$3"\t"$4"\t"$1":"$3".."$4","$2"\t"$6"\t"$2}' "!{ctss[0].baseName}_clustered_simplified" > "!{ctss[0].baseName}_clustered_simplified.bed" ''' } - +ctss_clusters = ctss_clusters.dump(tag:"trim") process ctss_qc { tag "$clusters" publishDir "${params.outdir}/rseqc" , mode: 'copy', @@ -816,7 +814,6 @@ workflow.onComplete { email_fields['summary']['Nextflow Build'] = workflow.nextflow.build email_fields['summary']['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp - // TODO nf-core: If not using MultiQC, strip out this code (including params.max_multiqc_email_size) // On success try attach the multiqc report def mqc_report = null try { From e889d3fe6450589e207a7ddc501e7e3560d08105 Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 11 Mar 2020 16:41:48 +0100 Subject: [PATCH 043/107] update documentation --- README.md | 25 +++++++++++++++---------- docs/usage.md | 29 +++++++++-------------------- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 22c3ddb..d1c2446 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ **CAGE-seq pipeline**. -[![GitHub Actions CI Status](https://github.com/nf-core/cageseq/workflows/nf-core%20CI/badge.svg)](https://github.com/nf-core/cageseq/actions) -[![GitHub Actions Linting Status](https://github.com/nf-core/cageseq/workflows/nf-core%20linting/badge.svg)](https://github.com/nf-core/cageseq/actions) +[![GitHub Actions CI Status](https://github.com/nf-core/cageseq/workflows/cageseq%20CI/badge.svg)](https://github.com/nf-core/cageseq/actions) +[![GitHub Actions Linting Status](https://github.com/nf-core/cageseq/workflows/cageseq%20linting/badge.svg)](https://github.com/nf-core/cageseq/actions) [![Nextflow](https://img.shields.io/badge/nextflow-%E2%89%A519.10.0-brightgreen.svg)](https://www.nextflow.io/) [![install with bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg)](http://bioconda.github.io/) @@ -19,6 +19,18 @@ UNDER DEVELOPMENT This pipeline is currenlty under development. The workflow is not yet finished. +The pipeline includes steps for adapter and artefact trimming +([cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), alignment to +a reference ([STAR](https://github.com/alexdobin/STAR) or +[bowtie](http://bowtie-bio.sourceforge.net/index.shtml)) and CAGE tag counting +and clustering ([paraclu](http://cbrc3.cbrc.jp/~martin/paraclu/)). +Additionally, several quality control steps +([FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/), +[RSeQC](http://rseqc.sourceforge.net/), +[MultiQC](https://multiqc.info/)) +are included to allow for easy verification of results after a run. + + The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It comes with docker containers making installation trivial and results highly reproducible. ## Quick Start @@ -37,10 +49,8 @@ nextflow run nf-core/cageseq -profile test, iv. Start running your own analysis! - - ```bash -nextflow run nf-core/cageseq -profile --reads '*_R{1,2}.fastq.gz' --genome GRCh37 +nextflow run nf-core/cageseq --reads '*_R{1,2}.fastq.gz' --aligner <'star'/'bowtie'> --genome GRCh38 -profile ``` See [usage docs](docs/usage.md) for all of the available options when running the pipeline. @@ -58,11 +68,6 @@ The nf-core/cageseq pipeline comes with documentation about the pipeline, found 4. [Output and how to interpret the results](docs/output.md) 5. [Troubleshooting](https://nf-co.re/usage/troubleshooting) - - -This pipeline includes steps for adapter and artefact trimming ([cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), alignment to a reference ([STAR](https://github.com/alexdobin/STAR)) and CAGE tag counting. -Additionally, several quality control steps ([FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/), [MultiQC](https://multiqc.info/)) are included to allow for easy verification of results after a run. - ## Credits nf-core/cageseq was originally written by Kevin Menden and Tristan Kast. diff --git a/docs/usage.md b/docs/usage.md index 1295f32..37cd230 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -64,7 +64,7 @@ NXF_OPTS='-Xms1g -Xmx4g' The typical command for running the pipeline is as follows: ```bash -nextflow run nf-core/cageseq --reads /path/to/reads.fastq.gz -profile docker --fasta /path/to/genome.fasta --gtf /path/to/genome.gtf +nextflow run nf-core/rnaseq --reads '*_R{1,2}.fastq.gz' --genome GRCh37 aligner star -profile docker ``` This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. @@ -141,16 +141,6 @@ Please note the following requirements: If left unspecified, a default pattern is used: `data/*{1,2}.fastq.gz` -### `--single_end` - -By default, the pipeline expects paired-end data. If you have single-end data, you need to specify `--single_end` on the command line when you launch the pipeline. A normal glob pattern, enclosed in quotation marks, can then be used for `--reads`. For example: - -```bash ---single_end --reads '*.fastq' -``` - -It is not possible to run a mixture of single-end and paired-end files in one run. - ## Reference genomes The pipeline config files come bundled with paths to the illumina iGenomes reference index files. If running with docker or AWS, the configuration is set up to use the [AWS-iGenomes](https://ewels.github.io/AWS-iGenomes/) resource. @@ -170,7 +160,7 @@ You can find the keys to specify the genomes in the [iGenomes config file](../co * _S. cerevisiae_ * `--genome 'R64-1-1'` -> There are numerous others - check the config file for more. +> There are numerous others - check the `igenomes.config` in `conf/` for more. Note that you can use the same configuration setup to save sets of reference files for your own use, even if they are not part of the iGenomes resource. See the [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for instructions on where to save such a file. @@ -189,19 +179,18 @@ params { } ``` - - -### `--fasta` `--gtf` `--star_index` +### `--fasta` `--gtf` `--star_index` `--bowtie_index` If you prefer, you can specify the full path to your reference genome when you run the pipeline: ```bash --fasta '[path to Fasta reference]' \ --gtf '[path to GTF file]' \ ---star '[path to STAR index]' +--star_index '[path to STAR index]' +--bowtie_index '[path to bowite index]' ``` -The minimum requirements for running the pipeline are the Fasta and GTF files. If a STAR index is not given, it will be automatically build. +The minimum requirements for running the pipeline are the Fasta and GTF files. If a STAR or bowtie index is not given, it will be automatically build. ### `--saveReference` @@ -213,7 +202,7 @@ Input fastq files are trimmed in three different steps, which are by default all ### `--trimming` -The first process is regulated by the flag `--trimming`. Here the enzyme binding site at the 5' and linker at the 3' end are cut +The first process is regulated by the flag `--trimming`. Here the enzyme binding site at the 5' and linker at the 3' end are cut. ### `--cutG` @@ -221,7 +210,7 @@ The removing of the added G at the 5' end can be deactivated with this flag. ### `--cutArtifacts` -Artifacts, generated in the sequencing process, are cut if this flag is not set to false. It is possible to specify fasta files containing the belonging adapters with the following arguments. If `--cutArtifacts` is set to falase, `--artifacts5end` and `--artifacts3end` is ignored. +Artifacts, generated in the sequencing process, are cut if this flag is not set to false. It is possible to specify fasta files containing the belonging adapters with the following arguments. If `--cutArtifacts` is set to false, `--artifacts5end` and `--artifacts3end` is ignored. ### `--artifacts5end` @@ -233,7 +222,7 @@ Specifying a file containing artifacts at the 3' end. By default a file with all ### `--min_cluster` -Sets the minimum amount of reads for paraclu to build a cluster. Default: 100. +Sets the minimum amount of reads for paraclu to build a cluster. Default: 20. ### `--igenomes_ignore` From a94d8df318b7d9426c27323086277c1b7c05e993 Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 11 Mar 2020 16:48:38 +0100 Subject: [PATCH 044/107] fix linting errors --- README.md | 1 - bin/process_ctss.sh | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d1c2446..de84580 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,6 @@ Additionally, several quality control steps [MultiQC](https://multiqc.info/)) are included to allow for easy verification of results after a run. - The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It comes with docker containers making installation trivial and results highly reproducible. ## Quick Start diff --git a/bin/process_ctss.sh b/bin/process_ctss.sh index 466bfb5..efd9b5c 100755 --- a/bin/process_ctss.sh +++ b/bin/process_ctss.sh @@ -18,8 +18,8 @@ CTSS_POS=$2 # sed '/+/d' $CTSS_FILE.bed > ${CTSS}_allm # grep + $CTSS_FILE.bed > ${CTSS}_allp # put CTSS output to paraclu format -awk -F "\t" '{print$1"\t"$6"\t"$2"\t"$5}' < $CTSS_POS.bed > ${CTSS_POS}_pos_4P -awk -F "\t" '{print$1"\t"$6"\t"$3"\t"$5}' < $CTSS_NEG.bed > ${CTSS_NEG}_neg_4P +awk -F "\t" '{print$1"\t"$6"\t"$2"\t"$5}' < "${CTSS_POS}.bed" > "${CTSS_POS}_pos_4P" +awk -F "\t" '{print$1"\t"$6"\t"$3"\t"$5}' < "${CTSS_NEG}.bed" > "${CTSS_NEG}_neg_4P" # sort the pos and neg strand prior paraclu clustering -sort -k1,1 -k3n ${CTSS_POS}_pos_4P > ${CTSS_POS}_pos_4Ps -sort -k1,1 -k3n ${CTSS_NEG}_neg_4P > ${CTSS_NEG}_neg_4Ps +sort -k1,1 -k3n "${CTSS_POS}_pos_4P" > "${CTSS_POS}_pos_4Ps" +sort -k1,1 -k3n "${CTSS_NEG}_neg_4P" > "${CTSS_NEG}_neg_4Ps" From d7ddf454e013b613be4078aefca3c696f0059bcf Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 26 Mar 2020 14:55:53 +0100 Subject: [PATCH 045/107] update dependencies --- README.md | 10 ++-------- environment.yml | 27 +++++++++++++-------------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index de84580..d742351 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ![nf-core/cageseq](docs/images/nf-core-cageseq_logo.png) -**CAGE-seq pipeline**. +**Nextflow CAGE-seq analysis pipeline, part of the nf-core community** [![GitHub Actions CI Status](https://github.com/nf-core/cageseq/workflows/cageseq%20CI/badge.svg)](https://github.com/nf-core/cageseq/actions) [![GitHub Actions Linting Status](https://github.com/nf-core/cageseq/workflows/cageseq%20linting/badge.svg)](https://github.com/nf-core/cageseq/actions) @@ -15,13 +15,9 @@ UNDER DEVELOPMENT This pipeline is currenlty under development. The workflow is not yet finished. -UNDER DEVELOPMENT - -This pipeline is currenlty under development. The workflow is not yet finished. - The pipeline includes steps for adapter and artefact trimming ([cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), alignment to -a reference ([STAR](https://github.com/alexdobin/STAR) or +a reference genome ([STAR](https://github.com/alexdobin/STAR) or [bowtie](http://bowtie-bio.sourceforge.net/index.shtml)) and CAGE tag counting and clustering ([paraclu](http://cbrc3.cbrc.jp/~martin/paraclu/)). Additionally, several quality control steps @@ -56,8 +52,6 @@ See [usage docs](docs/usage.md) for all of the available options when running th ## Documentation -The nf-core/cageseq pipeline comes with documentation about the pipeline, found in the `docs/` directory: - 1. [Installation](https://nf-co.re/usage/installation) 2. Pipeline configuration * [Local installation](https://nf-co.re/usage/local_installation) diff --git a/environment.yml b/environment.yml index 6ab5300..1e80ec8 100644 --- a/environment.yml +++ b/environment.yml @@ -6,17 +6,16 @@ channels: - bioconda - defaults dependencies: - -- conda-forge::python=3.7.3 -- conda-forge::markdown=3.1.1 -- conda-forge::pymdown-extensions=6.0 -- conda-forge::pygments=2.5.2 -- bioconda::bedtools=2.27.1 -- bioconda::cutadapt=2.1 -- bioconda::fastqc=0.11.8 -- bioconda::samtools=1.9 -- bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. -- bioconda::multiqc=1.8 -- unzip=6.0 -- bioconda::bowtie=1.2.3 -- bioconda::rseqc=3.0.1 + - conda-forge::python=3.7.3 + - conda-forge::markdown=3.1.1 + - conda-forge::pymdown-extensions=6.0 + - conda-forge::pygments=2.5.2 + - bioconda::bedtools=2.29.2 + - bioconda::cutadapt=2.9 + - bioconda::fastqc=0.11.9 + - bioconda::samtools=1.10 + - bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. + - bioconda::multiqc=1.8 + - unzip=6.0 + - bioconda::bowtie=1.2.3 + - bioconda::rseqc=3.0.1 From f779c791c2ddd285e0bab99423e9a68588f761ae Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 27 Mar 2020 19:18:17 +0100 Subject: [PATCH 046/107] fix clustering, add count matrix generator, add tpm threshold for clustering --- README.md | 3 +- bin/make_ctss.sh | 11 +++--- bin/process_ctss.sh | 67 ++++++++++++++++++++++------------ main.nf | 87 +++++++++++++++++++++++++++++++++++++-------- 4 files changed, 123 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index d742351..ac5869c 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,8 @@ See [usage docs](docs/usage.md) for all of the available options when running th ## Credits -nf-core/cageseq was originally written by Kevin Menden and Tristan Kast. +nf-core/cageseq was originally written by Kevin Menden and Tristan Kast and modified by Matthias Hörtenhuber. + ## Contributions and Support diff --git a/bin/make_ctss.sh b/bin/make_ctss.sh index 60c8419..c96fc10 100755 --- a/bin/make_ctss.sh +++ b/bin/make_ctss.sh @@ -16,15 +16,11 @@ case ${opt} in q) QCUT=${OPTARG};; i) VAR=${OPTARG};; n) NAME=${OPTARG};; -*) usage;; esac done if [ "${QCUT}" = "" ]; then QCUT=20; fi -# for VAR in "$@" -# do -# file=${VAR##*/} echo "working on: ${VAR}" #convert sam to bam and bam to bed @@ -35,13 +31,14 @@ samtools view -F 4 -u -q $QCUT -b "$VAR.bam" | bamToBed -i stdin > "$TMPFILE" awk 'BEGIN{OFS="\t"}{if($6=="+"){print $1,$2,$5}}' "${TMPFILE}" \ | sort -k1,1 -k2,2n \ | groupBy -i stdin -g 1,2 -c 3 -o count \ -| awk -v x="$NAME" 'BEGIN{OFS="\t"}{print $1,$2,$2+1, x ,$3,"+"}' >> "$NAME".pos.ctss.bed +| awk -v x="$NAME" 'BEGIN{OFS="\t"}{print $1,$2,$2+1, x ,$3,"+"}' >> "$NAME".pos_ctss.bed #generate ctss on the negative strand awk 'BEGIN{OFS="\t"}{if($6=="-"){print $1,$3,$5}}' "${TMPFILE}" \ | sort -k1,1 -k2,2n \ | groupBy -i stdin -g 1,2 -c 3 -o count \ -| awk -v x="$NAME" 'BEGIN{OFS="\t"}{print $1,$2-1,$2, x ,$3,"-"}' >> "$NAME".neg.ctss.bed +| awk -v x="$NAME" 'BEGIN{OFS="\t"}{print $1,$2-1,$2, x ,$3,"-"}' >> "$NAME".neg_ctss.bed + +cat "$NAME".pos_ctss.bed "$NAME".neg_ctss.bed > "$NAME".ctss.bed rm "$TMPFILE" -# done diff --git a/bin/process_ctss.sh b/bin/process_ctss.sh index efd9b5c..7d53ef2 100755 --- a/bin/process_ctss.sh +++ b/bin/process_ctss.sh @@ -1,25 +1,46 @@ -#!/bin/sh -# +#!/bin/bash + set -e -if [ $# -eq 0 ] -then - cat < ... -EOF - exit 1; -fi - - -CTSS_NEG=$1 -CTSS_POS=$2 - -# split BED into strands -# sed '/+/d' $CTSS_FILE.bed > ${CTSS}_allm -# grep + $CTSS_FILE.bed > ${CTSS}_allp -# put CTSS output to paraclu format -awk -F "\t" '{print$1"\t"$6"\t"$2"\t"$5}' < "${CTSS_POS}.bed" > "${CTSS_POS}_pos_4P" -awk -F "\t" '{print$1"\t"$6"\t"$3"\t"$5}' < "${CTSS_NEG}.bed" > "${CTSS_NEG}_neg_4P" -# sort the pos and neg strand prior paraclu clustering -sort -k1,1 -k3n "${CTSS_POS}_pos_4P" > "${CTSS_POS}_pos_4Ps" -sort -k1,1 -k3n "${CTSS_NEG}_neg_4P" > "${CTSS_NEG}_neg_4Ps" +while getopts :i:t: opt +do +case ${opt} in +t) TPM=${OPTARG};; +*) echo "Usage is : $0 -t " >&2 + exit 1;; +esac +done +shift $((OPTIND -1)) #throw out the -t parameter from $@ inputs + +FILES=$@ + +# "Pooling ctss" +cat "$FILES" > ctss_all + + +# "Sorting pooled ctss" + sort -k 1,1 -k 2,2n -k 3,3n -k 6,6 ctss_all > ctss_all.Sorted + +# "Grouping and adding ctss" + bedtools groupby -i ctss_all.Sorted -g 1,2,3,6 -c 5 -o sum > ctss_all.SortedGrouped + +# "Formating file" + awk -F "\t" '{print$1"\t"$2"\t"$3"\t"$1":"$2"-"$3"\t"$5"\t"$4}' < ctss_all.SortedGrouped > ctssAll + +# "Filter ctss < $TPM TPM" + counts=$(awk 'FNR==NR{sum+=$5} END {print sum}' ctssAll) + awk -v ctssall="$counts" '{if (($5/ctssall)*1000000>="$TPM") print}' ctssAll > ctssAll_${TPM}_tpm_new + +# "BED into minus and positive" + sed '/+/d' ctssAll_${TPM}_tpm_new > allm + grep + ctssAll_${TPM}_tpm_new > allp + +# "CTSS output to paraclu format" + awk -F "\t" '{print$1"\t"$6"\t"$2"\t"$5}' < allp > ctss_pos_4P + awk -F "\t" '{print$1"\t"$6"\t"$3"\t"$5}' < allm > ctss_neg_4P + +# "Sorting the pos prior paraclu clustering"ls + sort -k1,1 -k3n ctss_pos_4P > ctss_all_pos_4Ps + +# "Sorting the neg prior paraclu clustering" + sort -k1,1 -k3n ctss_neg_4P > ctss_all_neg_4Ps diff --git a/main.nf b/main.nf index 7455281..e185274 100644 --- a/main.nf +++ b/main.nf @@ -36,6 +36,7 @@ def helpMessage() { --artifacts5end Path to 5 end artifact file, if not given the pipeline will use a default file with all possible artifacts --artifacts3end Path to 3 end artifact file, if not given the pipeline will use a default file with all possible artifacts --min_cluster Minimum amount of reads to build a cluster with paraclu + --tpm_cluster_threshold Threshold for expression count of ctss considered in paraclu clustering References If not specified in the configuration file or you wish to overwrite any of the references --fasta [file] Path to fasta reference @@ -82,6 +83,7 @@ params.gtf = params.genome ? params.genomes[ params.genome ].gtf ?: false : fals //params.artifacts5end = params.artifacts5end ? params.artifacts5end[ params.artifacts5end ].fasta ?: false : false //params.artifacts3end = params.artifacts3end ? params.artifacts3end[ params.artifacts3end ].fasta ?: false : false params.min_cluster = 30 +params.tpm_cluster_threshold = 0.2 // Validate inputs if (params.aligner != 'star' && params.aligner != 'bowtie') { @@ -210,6 +212,7 @@ summary['CutArtifacts'] = params.cutArtifacts summary['EcoSite'] = params.ecoSite summary['LinkerSeq'] = params.linkerSeq summary['Min. cluster'] = params.min_cluster +summary['Cluster threshold']= params.tpm_cluster_threshold summary['Save Reference'] = params.saveReference summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" if (workflow.containerEngine) summary['Container'] = "$workflow.containerEngine - $workflow.container" @@ -666,7 +669,8 @@ process get_ctss { set val(sample_name), file(bam_count) from bam_aligned output: - set val(sample_name), file("*.ctss.bed") into ctss_counts + set val(sample_name), file("*.ctss.bed") into ctss_samples + file("*.ctss.bed") into ctss_counts script: """ @@ -677,32 +681,38 @@ process get_ctss { /** * STEP 9 - Cluster CTSS files */ -ctss_counts = ctss_counts.dump(tag:"ctss_counts") +ctss_counts = ctss_counts.collect().dump(tag:"ctss_counts") process cluster_ctss { + label "high_memory" tag "${ctss}" publishDir "${params.outdir}/ctss/clusters", mode: 'copy' input: - set val(sample_name), file(ctss) from ctss_counts + file ctss from ctss_counts.collect() output: - file "*.bed" into ctss_clusters + file "*.bed" into ctss_qc, ctss_clusters + shell: ''' - bash process_ctss.sh !{ctss[0].baseName} !{ctss[1].baseName} - - paraclu !{params.min_cluster} "!{ctss[1].baseName}_pos_4Ps" > "!{ctss[1].baseName}pos_clustered" - paraclu !{params.min_cluster} "!{ctss[0].baseName}_neg_4Ps" > "!{ctss[0].baseName}neg_clustered" + process_ctss.sh -t !{params.tpm_cluster_threshold} !{ctss} - paraclu-cut.sh "!{ctss[1].baseName}pos_clustered" > "!{ctss[1].baseName}pos_clustered_simplified" - paraclu-cut.sh "!{ctss[0].baseName}neg_clustered" > "!{ctss[0].baseName}neg_clustered_simplified" + paraclu !{params.min_cluster} "ctss_all_pos_4Ps" > "ctss_all_pos_clustered" + paraclu !{params.min_cluster} "ctss_all_neg_4Ps" > "ctss_allneg_clustered" + paraclu-cut.sh "ctss_all_pos_clustered" > "ctss_all_pos_clustered_simplified" + paraclu-cut.sh "ctss_all_neg_clustered" > "ctss_all_neg_clustered_simplified" - cat "!{ctss[1].baseName}pos_clustered_simplified" "!{ctss[0].baseName}neg_clustered_simplified" > "!{ctss[0].baseName}_clustered_simplified" - awk -F '\t' '{print $1"\t"$3"\t"$4"\t"$1":"$3".."$4","$2"\t"$6"\t"$2}' "!{ctss[0].baseName}_clustered_simplified" > "!{ctss[0].baseName}_clustered_simplified.bed" + cat "ctss_all_pos_clustered_simplified" "ctss_all_neg_clustered_simplified" > "ctss_all_clustered_simplified" + awk -F '\t' '{print $1"\t"$3"\t"$4"\t"$1":"$3".."$4","$2"\t"$6"\t"$2}' "ctss_all_clustered_simplified" > "ctss_all_clustered_simplified.bed" ''' } + + +/** + * STEP 10 - QC for clustered ctss + */ ctss_clusters = ctss_clusters.dump(tag:"trim") process ctss_qc { tag "$clusters" @@ -713,7 +723,7 @@ process ctss_qc { } input: - file clusters from ctss_clusters + file clusters from ctss_qc file gtf from bed_rseqc.collect() file fasta from fasta_rseqc.collect() @@ -727,8 +737,57 @@ process ctss_qc { read_distribution.py -i !{clusters.baseName}.bam -r !{gtf} > !{clusters.baseName}.read_distribution.txt ''' } + + /* + * STEP 11 - Generate count files + */ + process generate_counts { + tag "${sample_name}" + // publishDir "${params.outdir}/ctss/", mode: 'copy' + + input: + set val(sample_name), file(ctss) from ctss_samples + file clusters from ctss_clusters.collect() + + output: + file "*.txt" into count_files + + shell: + ''' + #intersect ctss files with generated clusters + intersectBed -a !{clusters} -b !{ctss} -loj -s > !{ctss}_counts_tmp + + echo !{sample_name} > !{ctss}_counts.txt + + bedtools groupby -i !{ctss}_counts_tmp -g 1,2,3,4,6 -c 11 -o sum | + awk -v OFS='\t' '{if($6=="-1") $6=0; print $6 }' >> !{ctss}_counts.txt + ''' + } + +/* + * STEP 11 - Generate count matrix + */ +process generate_count_matrix { + tag "${counts}" + publishDir "${params.outdir}/ctss/", mode: 'copy' + + input: + file counts from count_files.collect() + file clusters from ctss_clusters.collect() + + output: + file "*.txt" into count_matrix + + shell: + ''' + awk '{ print $4}' !{clusters} > coordinates + paste -d "\t" coordinates !{counts} >> count_table.txt + ''' +} + + /* - * STEP 10 - MultiQC + * STEP 12 - MultiQC */ process multiqc { publishDir "${params.outdir}/MultiQC", mode: 'copy' From ba0f5277eeefa88bbf04bb41f6ca8f37f80ee57a Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 24 Apr 2020 13:48:53 +0200 Subject: [PATCH 047/107] add `skip_trimming` and update naming scheme for parameters --- main.nf | 149 +++++++++++++++++++++++++----------------------- nextflow.config | 21 +++---- 2 files changed, 87 insertions(+), 83 deletions(-) diff --git a/main.nf b/main.nf index e185274..9c4c4d5 100644 --- a/main.nf +++ b/main.nf @@ -21,32 +21,34 @@ def helpMessage() { nextflow run nf-core/cageseq --reads '*_R{1,2}.fastq.gz' --aligner star --genome GRCh38 -profile docker Mandatory arguments: - --reads [file] Path to input data (must be surrounded with quotes) - -profile [str] Configuration profile to use. Can use multiple (comma separated) - Available: conda, docker, singularity, test, awsbatch, and more - - Options: - --trimming Set to false to skip the file Trimming - --cutEcoP Set to false to not cut the EcoP - --cutLinker Set to false to not cut the linker - --cutG Set to false to not cut the additonal G at the 5' end - --star_index Path to STAR index, set to false if igenomes should be used - --bowtie_index Path to bowtie index, set to false if igenomes should be used - --cutArtifacts Set to false to not cut artifacts - --artifacts5end Path to 5 end artifact file, if not given the pipeline will use a default file with all possible artifacts - --artifacts3end Path to 3 end artifact file, if not given the pipeline will use a default file with all possible artifacts - --min_cluster Minimum amount of reads to build a cluster with paraclu - --tpm_cluster_threshold Threshold for expression count of ctss considered in paraclu clustering - - References If not specified in the configuration file or you wish to overwrite any of the references - --fasta [file] Path to fasta reference - --genome Name of iGenomes reference - --gtf Path to gtf file - - Alignment: - --aligner Specifies the aligner to use (available are: 'star', 'bowtie') - - Other options: + --reads [file] Path to input data (must be surrounded with quotes) + -profile [str] Configuration profile to use. Can use multiple (comma separated) + Available: conda, docker, singularity, test, awsbatch, and more + + Trimming: + --skip_trimming [bool] Set to true to skip all file trimming steps + --trim_ecop [bool] Set to false to not trim the EcoP site + --trim_linker [bool] Set to false to not trim the linker + --trim_5g [bool] Set to false to not trim the additonal G at the 5' end + --trim_artifacts [bool] Set to false to not trim artifacts + --artifacts_5end [file] Path to 5 end artifact file, if not given the pipeline will use a default file with all possible artifacts + --artifacts_3end [file] Path to 3 end artifact file, if not given the pipeline will use a default file with all possible artifacts + + References If not specified in the configuration file or you wish to overwrite any of the references + --fasta [file] Path to fasta reference + --genome [str] Name of iGenomes reference + --gtf [file] Path to gtf file + + Alignment: + --aligner [str] Specifies the aligner to use (available are: 'star', 'bowtie') + --star_index [file] Path to STAR index, set to false if igenomes should be used + --bowtie_index [file] Path to bowtie index, set to false if igenomes should be used + + Clustering: + --min_cluster [int] Minimum amount of reads to build a cluster with paraclu + --tpm_cluster_threshold [int] Threshold for expression count of ctss considered in paraclu clustering + + Other options: --outdir [file] The output directory where the results will be saved --email [email] Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits --email_on_fail [email] Same as --email, except only send mail if the workflow is not successful @@ -54,9 +56,9 @@ def helpMessage() { -name [str] Name for the pipeline run. If not specified, Nextflow will automatically generate a random mnemonic AWSBatch options: - --awsqueue [str] The AWSBatch JobQueue that needs to be set when running on AWSBatch - --awsregion [str] The AWS Region for your AWS Batch job to run on - --awscli [str] Path to the AWS CLI tool + --awsqueue [str] The AWSBatch JobQueue that needs to be set when running on AWSBatch + --awsregion [str] The AWS Region for your AWS Batch job to run on + --awscli [str] Path to the AWS CLI tool """.stripIndent() } @@ -80,8 +82,8 @@ params.bowtie_index = params.genome ? params.genomes[ params.genome ].bowtie ?: params.fasta = params.genome ? params.genomes[ params.genome ].fasta ?: false : false if (params.fasta) { ch_fasta = file(params.fasta, checkIfExists: true) } params.gtf = params.genome ? params.genomes[ params.genome ].gtf ?: false : false -//params.artifacts5end = params.artifacts5end ? params.artifacts5end[ params.artifacts5end ].fasta ?: false : false -//params.artifacts3end = params.artifacts3end ? params.artifacts3end[ params.artifacts3end ].fasta ?: false : false +//params.artifacts_5end = params.artifacts_5end ? params.artifacts_5end[ params.artifacts_5end ].fasta ?: false : false +//params.artifacts_3end = params.artifacts_3end ? params.artifacts_3end[ params.artifacts_3end ].fasta ?: false : false params.min_cluster = 30 params.tpm_cluster_threshold = 0.2 @@ -127,18 +129,18 @@ if( params.gtf ){ exit 1, "No GTF annotation specified!" } -if( params.artifacts5end ){ +if( params.artifacts_5end ){ ch_5end_artifacts = Channel - .fromPath(params.artifacts5end) + .fromPath(params.artifacts_5end) } else { ch_5end_artifacts = Channel .fromPath("$baseDir/assets/artifacts_5end.fasta") } -if( params.artifacts3end ){ +if( params.artifacts_3end ){ ch_3end_artifacts = Channel - .fromPath(params.artifacts3end) + .fromPath(params.artifacts_3end) } else { ch_3end_artifacts = Channel @@ -202,17 +204,16 @@ if (params.aligner == 'star') { else if (params.fasta)summary['Fasta Ref'] = params.fasta if (params.splicesites)summary['Splice Sites'] = params.splicesites } -if(params.artifacts5end){ summary["5' artifacts"] = params.artifacts5end} -if(params.artifacts3end){ summary["3' artifacts"] = params.artifacts3end} -summary['Trimming'] = params.trimming -summary['CutEcoP'] = params.cutEcop -summary['CutLinker'] = params.cutLinker -summary['CutG'] = params.cutG -summary['CutArtifacts'] = params.cutArtifacts +if(params.artifacts_5end){ summary["5' artifacts"] = params.artifacts_5end} +if(params.artifacts_3end){ summary["3' artifacts"] = params.artifacts_3end} +summary['trim_ecop'] = params.trim_ecop +summary['trim_linker'] = params.trim_linker +summary['trim_5g'] = params.trim_5g +summary['trim_artifacts'] = params.trim_artifacts summary['EcoSite'] = params.ecoSite summary['LinkerSeq'] = params.linkerSeq summary['Min. cluster'] = params.min_cluster -summary['Cluster threshold']= params.tpm_cluster_threshold +summary['Cluster Threshold']= params.tpm_cluster_threshold summary['Save Reference'] = params.saveReference summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" if (workflow.containerEngine) summary['Container'] = "$workflow.containerEngine - $workflow.container" @@ -385,8 +386,9 @@ if(params.aligner == 'star' && !params.star_index && params.fasta){ /* * STEP 3 - Cut Enzyme binding site at 5' and linker at 3' */ -if(params.trimming){ - process trimming { + +if(!params.skip_trimming){ + process trim_adapters { tag "$sample_name" publishDir "${params.outdir}/trimmed/adapter_trimmed", mode: 'copy', saveAs: {filename -> @@ -397,46 +399,46 @@ if(params.trimming){ set val(sample_name), file(reads) from read_files_trimming output: - set val(sample_name), file("*.fastq.gz") into trimmed_reads_cutG + set val(sample_name), file("*.fastq.gz") into trimmed_reads_trim_5g file "*.output.txt" into cutadapt_results script: prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?$/ // Cut Both EcoP and Linker - if (params.cutEcop && params.cutLinker){ + if (params.trim_ecop && params.trim_linker){ """ cutadapt -a ${params.ecoSite}...${params.linkerSeq} \\ --match-read-wildcards \\ -m 15 -M 45 \\ - -o "$prefix".trimmed.fastq.gz \\ + -o "$prefix".adapter_trimmed.fastq.gz \\ $reads \\ > "$prefix"_adapter_trimming.output.txt """ } // Cut only EcoP site - else if (params.cutEcop && !params.cutLinker){ + else if (params.trim_ecop && !params.trim_linker){ """ mkdir trimmed cutadapt -g ^${params.ecoSite} \\ -e 0 \\ --match-read-wildcards \\ --discard-untrimmed \\ - -o "$prefix".trimmed.fastq.gz \\ + -o "$prefix".adapter_trimmed.fastq.gz \\ $reads \\ > "$prefix"_adapter_trimming.output.txt """ } // Cut only Linker - else if (!params.cutEcop && params.cutLinker){ + else if (!params.trim_ecop && params.trim_linker){ """ mkdir trimmed cutadapt -a ${params.linkerSeq}\$ \\ -e 0 \\ --match-read-wildcards \\ -m 15 -M 45 \\ - -o "$prefix".trimmed.fastq.gz \\ + -o "$prefix".adapter_trimmed.fastq.gz \\ $reads \\ > "$prefix"_adapter_trimming.output.txt """ @@ -446,7 +448,7 @@ if(params.trimming){ } } else{ - read_files_trimming.set{ trimmed_reads_cutG } + read_files_trimming.set{ trimmed_reads_trim_5g } cutadapt_results = Channel.empty() } @@ -454,12 +456,15 @@ if(params.trimming){ /** * STEP 4 - Remove added G from 5-end */ - if (params.cutG){ - process cut_5G{ + if (params.trim_5g && !params.skip_trimming){ + process trim_5g{ tag "$sample_name" - + publishDir "${params.outdir}/trimmed/g_trimmed", mode: 'copy', + saveAs: {filename -> + if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" + else "$filename" } input: - set val(sample_name), file(reads) from trimmed_reads_cutG + set val(sample_name), file(reads) from trimmed_reads_trim_5g output: set val(sample_name), file("*.fastq.gz") into processed_reads @@ -468,31 +473,33 @@ if(params.trimming){ prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?$/ """ cutadapt -g ^G \\ - -e 0 --match-read-wildcards \\ - -o "$prefix".G_trimmed.fastq.gz \\ - $reads + -e 0 --match-read-wildcards --discard-trimmed \\ + --cores=${task.cpus} \\ + -o "$prefix".g_trimmed.fastq.gz \\ + $reads \\ + > ${reads.baseName}.g_trimming.output.txt """ } } else { - trimmed_reads_cutG.set{processed_reads} + trimmed_reads_trim_5g.set{processed_reads} } /** * STEP 5 - Remove artifacts */ -if (params.cutArtifacts){ - process cut_artifacts { +if (params.trim_artifacts && !params.skip_trimming){ + process trim_artifacts { tag "$sample_name" - publishDir "${params.outdir}/trimmed/artifacst_trimmed", mode: 'copy', + publishDir "${params.outdir}/trimmed/artifacts_trimmed", mode: 'copy', saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" else "$filename" } input: set val(sample_name), file(reads) from processed_reads - file artifacts5end from ch_5end_artifacts.collect() - file artifacts3end from ch_3end_artifacts.collect() + file artifacts_5end from ch_5end_artifacts.collect() + file artifacts_3end from ch_3end_artifacts.collect() output: set val(sample_name), file("*.fastq.gz") into further_processed_reads @@ -501,13 +508,13 @@ if (params.cutArtifacts){ script: prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?(\.processed)?$/ """ - cutadapt -a file:$artifacts3end \\ - -g file:$artifacts5end -e 0.1 --discard-trimmed \\ + cutadapt -a file:$artifacts_3end \\ + -g file:$artifacts_5end -e 0.1 --discard-trimmed \\ --match-read-wildcards -m 15 -O 19 \\ --cores=${task.cpus} \\ - -o "$prefix".artifact_trimmed.fastq.gz \\ + -o "$prefix".artifacts_trimmed.fastq.gz \\ $reads \\ - > ${reads.baseName}.artifact_trimming.output.txt + > ${reads.baseName}.artifacts_trimming.output.txt """ } further_processed_reads.into { further_processed_reads_star;further_processed_reads_bowtie; further_processed_reads_fastqc } @@ -530,7 +537,7 @@ else{ set val(sample_name), file("*_fastqc.{zip,html}") into trimmed_fastqc_results when: - params.trimming || params.cutG || params.cutArtifacts + (params.trim_5g || params.trim_artifacts) && !params.skip_trimming script: """ fastqc -q $reads diff --git a/nextflow.config b/nextflow.config index 1d6315e..9f2fd09 100644 --- a/nextflow.config +++ b/nextflow.config @@ -15,11 +15,6 @@ params { reads = false outdir = './results' - - - - - // CAGE-seq specific options // Alignment options aligner = 'star' @@ -27,15 +22,17 @@ params { min_aln_length = 15 single_end = true // Trimming options (all enabled by default) - trimming = true - cutEcop = true - cutLinker = true - cutG = true - cutArtifacts = true + skip_trimming = false + adapter_trimming = true + trim_ecop = true + trim_linker = true + trim_5g = true + trim_artifacts = false ecoSite = 'CAGCAG' linkerSeq = 'TCGTATGCCGTCTTC' - artifacts3end = "$baseDir/assets/artifacts_3end.fasta" - artifacts5end = "$baseDir/assets/artifacts_5end.fasta" + artifacts_5end = "$baseDir/assets/artifacts_5end.fasta" + artifacts_3end = "$baseDir/assets/artifacts_3end.fasta" + // Boilerplate options name = false From 7472d65f42724b88620be026e6df56d665fbcb51 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 24 Apr 2020 15:39:25 +0200 Subject: [PATCH 048/107] fix incorrect string serialisation in process_ctss --- bin/process_ctss.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/process_ctss.sh b/bin/process_ctss.sh index 7d53ef2..aaf30f4 100755 --- a/bin/process_ctss.sh +++ b/bin/process_ctss.sh @@ -15,7 +15,7 @@ shift $((OPTIND -1)) #throw out the -t parameter from $@ inputs FILES=$@ # "Pooling ctss" -cat "$FILES" > ctss_all +cat $FILES > ctss_all # "Sorting pooled ctss" From e8229819d09c30392fb31d2aa658d54e47c8185f Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 24 Apr 2020 16:59:02 +0200 Subject: [PATCH 049/107] fix code formatting --- main.nf | 266 +++++++++++++++++++++++++++----------------------------- 1 file changed, 130 insertions(+), 136 deletions(-) diff --git a/main.nf b/main.nf index 9c4c4d5..2751608 100644 --- a/main.nf +++ b/main.nf @@ -281,7 +281,7 @@ process get_software_versions { samtools --version > v_samtools.txt bedtools --version > v_bedtools.txt read_distribution.py --version > v_rseqc.txt - scrape_software_versions.py &> software_versions_mqc.yaml + python scrape_software_versions.py &> software_versions_mqc.yaml """ } process convert_gtf { @@ -358,7 +358,8 @@ if(params.aligner == 'star' && !params.star_index && params.fasta){ """ } } - if(params.aligner == 'bowtie' && !params.bowtie_index && params.fasta){ + +if(params.aligner == 'bowtie' && !params.bowtie_index && params.fasta){ process makeBowtieindex { tag "${fasta.baseName}" publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, @@ -393,7 +394,9 @@ if(!params.skip_trimming){ publishDir "${params.outdir}/trimmed/adapter_trimmed", mode: 'copy', saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" - else "$filename" } + else if (!params.save_trimmed) "$filename" + else null + } input: set val(sample_name), file(reads) from read_files_trimming @@ -443,15 +446,11 @@ if(!params.skip_trimming){ > "$prefix"_adapter_trimming.output.txt """ } - - } - } - else{ +} else { read_files_trimming.set{ trimmed_reads_trim_5g } cutadapt_results = Channel.empty() - } - +} /** * STEP 4 - Remove added G from 5-end @@ -462,7 +461,9 @@ if(!params.skip_trimming){ publishDir "${params.outdir}/trimmed/g_trimmed", mode: 'copy', saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" - else "$filename" } + else if (!params.save_trimmed) "$filename" + else null + } input: set val(sample_name), file(reads) from trimmed_reads_trim_5g @@ -489,106 +490,108 @@ if(!params.skip_trimming){ */ if (params.trim_artifacts && !params.skip_trimming){ - process trim_artifacts { - tag "$sample_name" - publishDir "${params.outdir}/trimmed/artifacts_trimmed", mode: 'copy', - saveAs: {filename -> - if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" - else "$filename" } - - input: - set val(sample_name), file(reads) from processed_reads - file artifacts_5end from ch_5end_artifacts.collect() - file artifacts_3end from ch_3end_artifacts.collect() - - output: - set val(sample_name), file("*.fastq.gz") into further_processed_reads - file "*.output.txt" into artifact_cutting_results - - script: - prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?(\.processed)?$/ - """ - cutadapt -a file:$artifacts_3end \\ - -g file:$artifacts_5end -e 0.1 --discard-trimmed \\ - --match-read-wildcards -m 15 -O 19 \\ - --cores=${task.cpus} \\ - -o "$prefix".artifacts_trimmed.fastq.gz \\ - $reads \\ - > ${reads.baseName}.artifacts_trimming.output.txt - """ - } - further_processed_reads.into { further_processed_reads_star;further_processed_reads_bowtie; further_processed_reads_fastqc } + process trim_artifacts { + tag "$sample_name" + publishDir "${params.outdir}/trimmed/artifacts_trimmed", mode: 'copy', + saveAs: {filename -> + if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" + else if (!params.save_trimmed) "$filename" + else null + } + + input: + set val(sample_name), file(reads) from processed_reads + file artifacts_5end from ch_5end_artifacts.collect() + file artifacts_3end from ch_3end_artifacts.collect() + + output: + set val(sample_name), file("*.fastq.gz") into further_processed_reads + file "*.output.txt" into artifact_cutting_results + + script: + prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?(\.processed)?$/ + """ + cutadapt -a file:$artifacts_3end \\ + -g file:$artifacts_5end -e 0.1 --discard-trimmed \\ + --match-read-wildcards -m 15 -O 19 \\ + --cores=${task.cpus} \\ + -o "$prefix".artifacts_trimmed.fastq.gz \\ + $reads \\ + > ${reads.baseName}.artifacts_trimming.output.txt + """ + } + further_processed_reads.into { further_processed_reads_star;further_processed_reads_bowtie; further_processed_reads_fastqc } } else{ - processed_reads.into{further_processed_reads_star; further_processed_reads_bowtie; further_processed_reads_fastqc} - artifact_cutting_results = Channel.empty() + processed_reads.into{further_processed_reads_star; further_processed_reads_bowtie; further_processed_reads_fastqc} + artifact_cutting_results = Channel.empty() } // Post trimming QC, only needed if some trimming has been done - process trimmed_fastqc { - tag "$sample_name" - publishDir "${params.outdir}/trimmed/fastqc", mode: 'copy', - saveAs: {filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename"} - - input: - set val(sample_name), file(reads) from further_processed_reads_fastqc - - output: - set val(sample_name), file("*_fastqc.{zip,html}") into trimmed_fastqc_results - - when: - (params.trim_5g || params.trim_artifacts) && !params.skip_trimming - script: - """ - fastqc -q $reads - """ - } +process trimmed_fastqc { + tag "$sample_name" + publishDir "${params.outdir}/trimmed/fastqc", mode: 'copy', + saveAs: {filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename"} + + input: + set val(sample_name), file(reads) from further_processed_reads_fastqc + + output: + set val(sample_name), file("*_fastqc.{zip,html}") into trimmed_fastqc_results + + when: + (params.trim_5g || params.trim_artifacts) && !params.skip_trimming + script: + """ + fastqc -q $reads + """ +} /** * STEP 7 - STAR alignment */ further_processed_reads_star = further_processed_reads_star.dump(tag:"star") if (params.aligner == 'star') { -process star { - label 'high_memory' - tag "$sample_name" - publishDir "${params.outdir}/STAR", mode: 'copy', - saveAs: {filename -> - if (filename.indexOf(".bam") == -1) "logs/$filename" - else filename } + process star { + label 'high_memory' + tag "$sample_name" + publishDir "${params.outdir}/STAR", mode: 'copy', + saveAs: {filename -> + if (filename.indexOf(".bam") == -1) "logs/$filename" + else filename } - input: - set val(sample_name), file(reads) from further_processed_reads_star - file index from star_index.collect() - file gtf from gtf_star.collect() + input: + set val(sample_name), file(reads) from further_processed_reads_star + file index from star_index.collect() + file gtf from gtf_star.collect() - output: - set val(sample_name), file("*.bam") into star_aligned - file "*.out" into star_alignment_logs - file "*SJ.out.tab" + output: + set val(sample_name), file("*.bam") into star_aligned + file "*.out" into star_alignment_logs + file "*SJ.out.tab" - script: + script: - prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ + prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ - """ - STAR --genomeDir $index \\ - --sjdbGTFfile $gtf \\ - --readFilesIn $reads \\ - --runThreadN ${task.cpus} \\ - --outSAMtype BAM SortedByCoordinate \\ - --outFilterScoreMinOverLread 0 --outFilterMatchNminOverLread 0 \\ - --outFilterMismatchNmax 1 \\ - --readFilesCommand zcat \\ - --runDirPerm All_RWX \\ - --outFileNamePrefix $prefix \\ - --outFilterMatchNmin ${params.min_aln_length} - """ + """ + STAR --genomeDir $index \\ + --sjdbGTFfile $gtf \\ + --readFilesIn $reads \\ + --runThreadN ${task.cpus} \\ + --outSAMtype BAM SortedByCoordinate \\ + --outFilterScoreMinOverLread 0 --outFilterMatchNminOverLread 0 \\ + --outFilterMismatchNmax 1 \\ + --readFilesCommand zcat \\ + --runDirPerm All_RWX \\ + --outFileNamePrefix $prefix \\ + --outFilterMatchNmin ${params.min_aln_length} + """ -} + } -star_aligned.into { bam_stats; bam_aligned } + star_aligned.into { bam_stats; bam_aligned } } else{ star_alignment_logs = Channel.empty() } @@ -642,15 +645,6 @@ process bowtie { process samtools_stats { tag "$sample_name" label 'process_medium' - // if (params.save_align_intermeds) { - // publishDir "${params.outdir}/STAR", mode: 'copy', - // saveAs: { filename -> - // if (filename.endsWith(".flagstat")) "samtools_stats/$filename" - // else if (filename.endsWith(".idxstats")) "samtools_stats/$filename" - // else if (filename.endsWith(".stats")) "samtools_stats/$filename" - // else filename - // } - // } input: set val(sample_name), file(bam_count) from bam_stats @@ -722,53 +716,53 @@ process cluster_ctss { */ ctss_clusters = ctss_clusters.dump(tag:"trim") process ctss_qc { - tag "$clusters" - publishDir "${params.outdir}/rseqc" , mode: 'copy', - saveAs: {filename -> - if (filename.indexOf("read_distribution.txt") > 0) "read_distribution/$filename" - else filename - } - - input: - file clusters from ctss_qc - file gtf from bed_rseqc.collect() - file fasta from fasta_rseqc.collect() - - output: - file "*.txt" into rseqc_results - - shell: - ''' - cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.tmp - bedtools bedtobam -i !{clusters} -g chrom_sizes.tmp > !{clusters.baseName}.bam - read_distribution.py -i !{clusters.baseName}.bam -r !{gtf} > !{clusters.baseName}.read_distribution.txt - ''' + tag "$clusters" + publishDir "${params.outdir}/rseqc" , mode: 'copy', + saveAs: {filename -> + if (filename.indexOf("read_distribution.txt") > 0) "read_distribution/$filename" + else filename + } + + input: + file clusters from ctss_qc + file gtf from bed_rseqc.collect() + file fasta from fasta_rseqc.collect() + + output: + file "*.txt" into rseqc_results + + shell: + ''' + cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.tmp + bedtools bedtobam -i !{clusters} -g chrom_sizes.tmp > !{clusters.baseName}.bam + read_distribution.py -i !{clusters.baseName}.bam -r !{gtf} > !{clusters.baseName}.read_distribution.txt + ''' } /* * STEP 11 - Generate count files */ process generate_counts { - tag "${sample_name}" - // publishDir "${params.outdir}/ctss/", mode: 'copy' + tag "${sample_name}" + // publishDir "${params.outdir}/ctss/", mode: 'copy' - input: - set val(sample_name), file(ctss) from ctss_samples - file clusters from ctss_clusters.collect() + input: + set val(sample_name), file(ctss) from ctss_samples + file clusters from ctss_clusters.collect() - output: - file "*.txt" into count_files + output: + file "*.txt" into count_files - shell: - ''' - #intersect ctss files with generated clusters - intersectBed -a !{clusters} -b !{ctss} -loj -s > !{ctss}_counts_tmp + shell: + ''' + #intersect ctss files with generated clusters + intersectBed -a !{clusters} -b !{ctss} -loj -s > !{ctss}_counts_tmp - echo !{sample_name} > !{ctss}_counts.txt + echo !{sample_name} > !{ctss}_counts.txt - bedtools groupby -i !{ctss}_counts_tmp -g 1,2,3,4,6 -c 11 -o sum | - awk -v OFS='\t' '{if($6=="-1") $6=0; print $6 }' >> !{ctss}_counts.txt - ''' + bedtools groupby -i !{ctss}_counts_tmp -g 1,2,3,4,6 -c 11 -o sum | + awk -v OFS='\t' '{if($6=="-1") $6=0; print $6 }' >> !{ctss}_counts.txt + ''' } /* From e3e6fd7f7dbce7006fc80ef9c09cc2866b50d8fb Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 24 Apr 2020 18:20:24 +0200 Subject: [PATCH 050/107] apply RSeQC per sample --- main.nf | 58 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/main.nf b/main.nf index 2751608..489cf8f 100644 --- a/main.nf +++ b/main.nf @@ -711,33 +711,6 @@ process cluster_ctss { } -/** - * STEP 10 - QC for clustered ctss - */ -ctss_clusters = ctss_clusters.dump(tag:"trim") -process ctss_qc { - tag "$clusters" - publishDir "${params.outdir}/rseqc" , mode: 'copy', - saveAs: {filename -> - if (filename.indexOf("read_distribution.txt") > 0) "read_distribution/$filename" - else filename - } - - input: - file clusters from ctss_qc - file gtf from bed_rseqc.collect() - file fasta from fasta_rseqc.collect() - - output: - file "*.txt" into rseqc_results - - shell: - ''' - cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.tmp - bedtools bedtobam -i !{clusters} -g chrom_sizes.tmp > !{clusters.baseName}.bam - read_distribution.py -i !{clusters.baseName}.bam -r !{gtf} > !{clusters.baseName}.read_distribution.txt - ''' - } /* * STEP 11 - Generate count files @@ -752,6 +725,7 @@ process ctss_qc { output: file "*.txt" into count_files + file "*.bed" into count_qc shell: ''' @@ -760,8 +734,8 @@ process ctss_qc { echo !{sample_name} > !{ctss}_counts.txt - bedtools groupby -i !{ctss}_counts_tmp -g 1,2,3,4,6 -c 11 -o sum | - awk -v OFS='\t' '{if($6=="-1") $6=0; print $6 }' >> !{ctss}_counts.txt + bedtools groupby -i !{ctss}_counts_tmp -g 1,2,3,4,6 -c 11 -o sum > !{ctss}_counts.bed + awk -v OFS='\t' '{if($6=="-1") $6=0; print $6 }' !{ctss}_counts.bed >> !{ctss}_counts.txt ''' } @@ -786,6 +760,32 @@ process generate_count_matrix { ''' } +/** + * STEP 10 - QC for clustered ctss + */ +process ctss_qc { + tag "$clusters" + publishDir "${params.outdir}/rseqc" , mode: 'copy', + saveAs: {filename -> + if (filename.indexOf("read_distribution.txt") > 0) "read_distribution/$filename" + else filename + } + + input: + file clusters from count_qc + file gtf from bed_rseqc.collect() + file fasta from fasta_rseqc.collect() + + output: + file "*.txt" into rseqc_results + + shell: + ''' + cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.tmp + bedtools bedtobam -i !{clusters} -g chrom_sizes.tmp > !{clusters.baseName}.bam + read_distribution.py -i !{clusters.baseName}.bam -r !{gtf} > !{clusters.baseName}.read_distribution.txt + ''' + } /* * STEP 12 - MultiQC From 6e684383423a85637df9cb4811249a89b106c44e Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 29 Apr 2020 15:06:39 +0200 Subject: [PATCH 051/107] switch RSeQC to ctss bed files, add more process to output docs --- assets/multiqc_config.yaml | 6 +- docs/output.md | 122 ++++++++++++++++++++++++++++++++----- main.nf | 19 +++--- nextflow.config | 3 +- 4 files changed, 121 insertions(+), 29 deletions(-) diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index 23ccb43..0a5a490 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -9,9 +9,9 @@ top_modules: - 'star' - 'samtools' - 'rseqc' -extra_fn_clean_exts: - - '.trimmed.G' - - '.trimmed.G_trimmed.artifact' +extra_fn_clean_trim: + - '.adapter_trimmed.g' + report_section_order: software_versions: order: -1000 diff --git a/docs/output.md b/docs/output.md index daff790..5928e23 100644 --- a/docs/output.md +++ b/docs/output.md @@ -9,25 +9,115 @@ This document describes the output produced by the pipeline. Most of the plots a The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: -* [FastQC](#fastqc) - read quality control -* [MultiQC](#multiqc) - aggregate report, describing results of the whole pipeline +- [nf-core/cageseq: Output](#nf-corecageseq-output) + - [Pipeline overview](#pipeline-overview) + - [FastQC](#fastqc) + - [cutadapt](#cutadapt) + - [STAR](#star) + - [RSeQC](#rseqc) + - [Read distribution](#read-distribution) + - [paraclu](#paraclu) + - [MultiQC](#multiqc) -## FastQC +1.**Raw read QC** -[FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your reads. It provides information about the quality score distribution across your reads, the per base sequence content (%T/A/G/C). You get information about adapter contamination and other overrepresented sequences. + [FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your reads. It provides information about the quality score distribution across your reads, the per base sequence content (%T/A/G/C). You get information about adapter contamination and other overrepresented sequences. -For further reading and documentation see the [FastQC help](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). - -> **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. To see how your reads look after trimming, look at the FastQC reports in the `trim_galore` directory. + > **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. To see how your reads look after trimming, look at the FastQC reports in the `trim_galore` directory. **Output directory: `results/fastqc`** -* `sample_fastqc.html` - * FastQC report, containing quality metrics for your untrimmed raw fastq files -* `zips/sample_fastqc.zip` - * zip file containing the FastQC report, tab-delimited data file and plot images +- `sample_fastqc.html` + - FastQC report, containing quality metrics for your untrimmed raw fastq files +- `zips/sample_fastqc.zip` + - zip file containing the FastQC report, tab-delimited data file and plot images + +2.**Trimming** + +[Cutadapt](https://cutadapt.readthedocs.io/en/stable/) finds and removes adapter +sequences, primers, poly-A tails and other types of unwanted sequence from your +high-throughput sequencing reads. + +By default this pipeline trims the cut enzyme binding site at the 5'-end and +linkers at the 3'-end (can be disabled by setting `--trim_ecop` or `--trim_linkers to false`). +Furthermore, to combat the leading-G-bias of CAGE-seq, G's at the 5'-end are removed. Additional artifacts can be removed via the `--trim_artifacts` parameter. + +All the following trimming process are skipped if `--skip_trimming` is set to true. + +**Output directory: `results/trimmed`** + +- `adapter_trimmed/sample.adapter_trimmed.fastq.gz` + - Trimmed FastQ data + - **NB:** Only saved if `--save_trimmed` has been specified. +- `adapter_trimmed/logs/`: Trimming report (describes which parameters that were used) +- if `--trim_5g`: + - `g_trimmed/sample.g_trimmed.fastq.gz` + - 5' G-corrected FastQ data + - **NB:** Only saved if `--save_trimmed` has been specified. + - `g_trimmed/logs/`: Trimming report (describes which parameters that were used) +- if `--trim_artifacts`: + - `artifacts_trimmed/sample.artifact_trimmed.fastq.gz` + - FastQ data after artifact removal + - **NB:** Only saved if `--save_trimmed` has been specified. + - `artifacts_trimmed/logs/`: Trimming report (describes which parameters that were used) + +3.**Alignment** + +The reads are aligned either with STAR or with bowtie. + +### STAR + +*Documentation*: +STAR is a read aligner designed for RNA sequencing. STAR stands for Spliced Transcripts Alignment to a Reference. + +The STAR section of the MultiQC report shows a bar plot with alignment rates: good samples should have most reads as _Uniquely mapped_ and few _Unmapped_ reads. + +### bowtie + +![STAR](images/star_alignment_plot.png) + +**Output directory: `results/STAR`** + +- `Sample_Aligned.sortedByCoord.out.bam` + - The aligned BAM file +- `Sample_Log.final.out` + - The STAR alignment report, contains mapping results summary +- `Sample_Log.out` and `Sample_Log.progress.out` + - STAR log files, containing a lot of detailed information about the run. Typically only useful for debugging purposes. +- `Sample_SJ.out.tab` + - Filtered splice junctions detected in the mapping + +4.**CTSS Clustering** + +## paraclu + +[paraclu](http://cbrc3.cbrc.jp/~martin/paraclu/) finds clusters in data +attached to sequences. It is used to define clusters of cage defined +transcription start sites (CTSS). + +**Output directory: `results/ctss/clusters`** + +## QC + +### RSeQC + +RSeQC is a package of scripts designed to evaluate the quality of RNA seq data. You can find out more about the package at the [RSeQC website](http://rseqc.sourceforge.net/). + +This pipeline only runs the read destribution RSeQC scripts on the CTSS clusters. The results are summarised within the MultiQC report. + +**Output directory: `results/rseqc`** + +#### Read distribution + +**Output: `Sample_read_distribution.txt`** + +This tool calculates how mapped reads are distributed over genomic features. + +![Read distribution](images/rseqc_read_distribution_plot.png) + +RSeQC documentation: [read_distribution.py](http://rseqc.sourceforge.net/#read-distribution-py) -## MultiQC +### MultiQC [MultiQC](http://multiqc.info) is a visualisation tool that generates a single HTML report summarising all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in within the report data directory. @@ -35,9 +125,9 @@ The pipeline has special steps which allow the software versions used to be repo **Output directory: `results/multiqc`** -* `Project_multiqc_report.html` - * MultiQC report - a standalone HTML file that can be viewed in your web browser -* `Project_multiqc_data/` - * Directory containing parsed statistics from the different tools used in the pipeline +- `Project_multiqc_report.html` + - MultiQC report - a standalone HTML file that can be viewed in your web browser +- `Project_multiqc_data/` + - Directory containing parsed statistics from the different tools used in the pipeline For more information about how to use MultiQC reports, see [http://multiqc.info](http://multiqc.info) diff --git a/main.nf b/main.nf index 489cf8f..125b707 100644 --- a/main.nf +++ b/main.nf @@ -27,6 +27,7 @@ def helpMessage() { Trimming: --skip_trimming [bool] Set to true to skip all file trimming steps + --save_trimmed Set to true to Save trimmed FastQ files --trim_ecop [bool] Set to false to not trim the EcoP site --trim_linker [bool] Set to false to not trim the linker --trim_5g [bool] Set to false to not trim the additonal G at the 5' end @@ -206,14 +207,14 @@ if (params.aligner == 'star') { } if(params.artifacts_5end){ summary["5' artifacts"] = params.artifacts_5end} if(params.artifacts_3end){ summary["3' artifacts"] = params.artifacts_3end} -summary['trim_ecop'] = params.trim_ecop -summary['trim_linker'] = params.trim_linker -summary['trim_5g'] = params.trim_5g -summary['trim_artifacts'] = params.trim_artifacts +summary['trim_ecop'] = params.trim_ecop +summary['trim_linker'] = params.trim_linker +summary['trim_5g'] = params.trim_5g +summary['trim_artifacts'] = params.trim_artifacts summary['EcoSite'] = params.ecoSite summary['LinkerSeq'] = params.linkerSeq summary['Min. cluster'] = params.min_cluster -summary['Cluster Threshold']= params.tpm_cluster_threshold +summary['Cluster Threshold [tpm]']= params.tpm_cluster_threshold summary['Save Reference'] = params.saveReference summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" if (workflow.containerEngine) summary['Container'] = "$workflow.containerEngine - $workflow.container" @@ -281,7 +282,7 @@ process get_software_versions { samtools --version > v_samtools.txt bedtools --version > v_bedtools.txt read_distribution.py --version > v_rseqc.txt - python scrape_software_versions.py &> software_versions_mqc.yaml + python bin/scrape_software_versions.py &> software_versions_mqc.yaml """ } process convert_gtf { @@ -671,7 +672,7 @@ process get_ctss { output: set val(sample_name), file("*.ctss.bed") into ctss_samples - file("*.ctss.bed") into ctss_counts + file("*.ctss.bed") into ctss_counts, ctss_counts_qc script: """ @@ -692,7 +693,7 @@ process cluster_ctss { file ctss from ctss_counts.collect() output: - file "*.bed" into ctss_qc, ctss_clusters + file "*.bed" into ctss_clusters shell: @@ -772,7 +773,7 @@ process ctss_qc { } input: - file clusters from count_qc + file clusters from ctss_counts_qc file gtf from bed_rseqc.collect() file fasta from fasta_rseqc.collect() diff --git a/nextflow.config b/nextflow.config index 9f2fd09..c79f7fe 100644 --- a/nextflow.config +++ b/nextflow.config @@ -23,7 +23,7 @@ params { single_end = true // Trimming options (all enabled by default) skip_trimming = false - adapter_trimming = true + save_trimmed = false trim_ecop = true trim_linker = true trim_5g = true @@ -36,6 +36,7 @@ params { // Boilerplate options name = false + clusterOptions = false multiqc_config = false email = false email_on_fail = false From 47156d3df029a18b91737eb15036432e192fc4d4 Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 29 Apr 2020 15:21:32 +0200 Subject: [PATCH 052/107] fix output channel error --- README.md | 3 +-- conf/base.config | 5 ----- main.nf | 4 ++-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ac5869c..d9a9e15 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ![nf-core/cageseq](docs/images/nf-core-cageseq_logo.png) -**Nextflow CAGE-seq analysis pipeline, part of the nf-core community** +Nextflow CAGE-seq analysis pipeline, part of the nf-core community [![GitHub Actions CI Status](https://github.com/nf-core/cageseq/workflows/cageseq%20CI/badge.svg)](https://github.com/nf-core/cageseq/actions) [![GitHub Actions Linting Status](https://github.com/nf-core/cageseq/workflows/cageseq%20linting/badge.svg)](https://github.com/nf-core/cageseq/actions) @@ -65,7 +65,6 @@ See [usage docs](docs/usage.md) for all of the available options when running th nf-core/cageseq was originally written by Kevin Menden and Tristan Kast and modified by Matthias Hörtenhuber. - ## Contributions and Support If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). diff --git a/conf/base.config b/conf/base.config index f68f4a0..cf28203 100644 --- a/conf/base.config +++ b/conf/base.config @@ -32,11 +32,6 @@ process { memory = { check_max( 70.GB * task.attempt, 'memory' ) } time = { check_max( 8.h * task.attempt, 'time' ) } } - withName: sortmerna { - cpus = { check_max( 16 * task.attempt, 'cpus' ) } - time = { check_max( 24.h * task.attempt, 'time' ) } - maxRetries = 2 - } withName: 'get_software_versions' { memory = { check_max( 2.GB * task.attempt, 'memory' ) } cache = false diff --git a/main.nf b/main.nf index 125b707..3f1377b 100644 --- a/main.nf +++ b/main.nf @@ -672,7 +672,7 @@ process get_ctss { output: set val(sample_name), file("*.ctss.bed") into ctss_samples - file("*.ctss.bed") into ctss_counts, ctss_counts_qc + file("*.ctss.bed") into (ctss_counts, ctss_counts_qc) script: """ @@ -683,7 +683,7 @@ process get_ctss { /** * STEP 9 - Cluster CTSS files */ -ctss_counts = ctss_counts.collect().dump(tag:"ctss_counts") +// ctss_counts = ctss_counts.collect().dump(tag:"ctss_counts") process cluster_ctss { label "high_memory" tag "${ctss}" From b845319ac4af367685855ccdd5775802fc191cdf Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 29 Apr 2020 15:29:09 +0200 Subject: [PATCH 053/107] fix scrape_software_version error --- main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.nf b/main.nf index 3f1377b..00d5fd9 100644 --- a/main.nf +++ b/main.nf @@ -282,7 +282,7 @@ process get_software_versions { samtools --version > v_samtools.txt bedtools --version > v_bedtools.txt read_distribution.py --version > v_rseqc.txt - python bin/scrape_software_versions.py &> software_versions_mqc.yaml + scrape_software_versions.py &> software_versions_mqc.yaml """ } process convert_gtf { From 56161ba3f337ef9bbb94a32531a31832dbe76d7e Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 30 Apr 2020 14:36:56 +0200 Subject: [PATCH 054/107] remove samtools stats and fix file extension of the count table --- main.nf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main.nf b/main.nf index 00d5fd9..022345f 100644 --- a/main.nf +++ b/main.nf @@ -656,7 +656,6 @@ process samtools_stats { script: """ samtools idxstats $bam_count > ${bam_count}.idxstats - samtools stats $bam_count > ${bam_count}.stats """ } @@ -757,7 +756,7 @@ process generate_count_matrix { shell: ''' awk '{ print $4}' !{clusters} > coordinates - paste -d "\t" coordinates !{counts} >> count_table.txt + paste -d "\t" coordinates !{counts} >> count_table.tsv ''' } From d02cb82dc7e4f8def3ac222709d8f89d8994a00c Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 30 Apr 2020 14:58:51 +0200 Subject: [PATCH 055/107] fix handling of sample names with spaces --- conf/test.config | 4 ++-- main.nf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/conf/test.config b/conf/test.config index 6ee4daa..22679d1 100644 --- a/conf/test.config +++ b/conf/test.config @@ -17,8 +17,8 @@ params { // Input data single_end = true - readPaths = [['cage1', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage1.fastq.gz'], - ['cage2', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage2.fastq.gz'] + readPaths = [['cage 1', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage1.fastq.gz'], + ['cage 2', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage2.fastq.gz'] ] fasta = 'https://github.com/nf-core/test-datasets/raw/cageseq/reference/chr_sub.fasta' gtf = 'https://github.com/nf-core/test-datasets/raw/cageseq/reference/chr_sub.gtf' diff --git a/main.nf b/main.nf index 022345f..f0e043a 100644 --- a/main.nf +++ b/main.nf @@ -180,7 +180,7 @@ ch_output_docs = file("$baseDir/docs/output.md", checkIfExists: true) if(params.readPaths){ Channel .from(params.readPaths) - .map { row -> [ row[0], file(row[1])] } + .map { row -> [ row[0].replaceAll("\\s","_"), file(row[1])] } .ifEmpty { exit 1, "params.readPaths was empty - no input files supplied" } .into { read_files_fastqc; read_files_trimming } } else { @@ -751,7 +751,7 @@ process generate_count_matrix { file clusters from ctss_clusters.collect() output: - file "*.txt" into count_matrix + file "*.tsv" into count_matrix shell: ''' From 5a04d2c5982be97c893fab7838e4128c340ea497 Mon Sep 17 00:00:00 2001 From: mashehu Date: Tue, 5 May 2020 11:40:34 +0200 Subject: [PATCH 056/107] fix smaller trimming related things --- assets/multiqc_config.yaml | 1 + main.nf | 56 ++++++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index 0a5a490..613e655 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -7,6 +7,7 @@ top_modules: - 'fastqc' - 'cutadapt' - 'star' + - 'bowtie' - 'samtools' - 'rseqc' extra_fn_clean_trim: diff --git a/main.nf b/main.nf index f0e043a..9408799 100644 --- a/main.nf +++ b/main.nf @@ -277,7 +277,7 @@ process get_software_versions { fastqc --version > v_fastqc.txt multiqc --version > v_multiqc.txt STAR --version > v_star.txt - bowtie --version > v_bowite.txt + bowtie --version > v_bowtie.txt cutadapt --version > v_cutadapt.txt samtools --version > v_samtools.txt bedtools --version > v_bedtools.txt @@ -388,14 +388,53 @@ if(params.aligner == 'bowtie' && !params.bowtie_index && params.fasta){ /* * STEP 3 - Cut Enzyme binding site at 5' and linker at 3' */ - + if (!params.skip_trimming) { + process trim_galore { + label 'low_memory' + tag "$sample_name" + publishDir "${params.outdir}/trim_galore", mode: "${params.publish_dir_mode}", + saveAs: {filename -> + if (filename.indexOf("_fastqc") > 0) "fastqc/$filename" + else if (filename.indexOf("trimming_report.txt") > 0) "logs/$filename" + else null + } + + input: + set val(sample_name), file(reads) from read_files_trimming + + output: + set val(sample_name), file("*fq.gz") into trimmed_reads_trim_5g + file "*trimming_report.txt" into trimgalore_results + file "*_fastqc.{zip,html}" into trimgalore_fastqc_reports + + script: + c_r1 = clip_r1 > 0 ? "--clip_r1 ${clip_r1}" : '' + c_r2 = clip_r2 > 0 ? "--clip_r2 ${clip_r2}" : '' + tpc_r1 = three_prime_clip_r1 > 0 ? "--three_prime_clip_r1 ${three_prime_clip_r1}" : '' + tpc_r2 = three_prime_clip_r2 > 0 ? "--three_prime_clip_r2 ${three_prime_clip_r2}" : '' + nextseq = params.trim_nextseq > 0 ? "--nextseq ${params.trim_nextseq}" : '' + if (params.single_end) { + """ + trim_galore --fastqc --gzip $c_r1 $tpc_r1 $nextseq $reads + """ + } else { + """ + trim_galore --paired --fastqc --gzip $c_r1 $c_r2 $tpc_r1 $tpc_r2 $nextseq $reads + """ + } + } + }else{ + raw_reads_trimgalore + .set {trimgalore_reads} + trimgalore_results = Channel.empty() + } if(!params.skip_trimming){ process trim_adapters { tag "$sample_name" publishDir "${params.outdir}/trimmed/adapter_trimmed", mode: 'copy', saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" - else if (!params.save_trimmed) "$filename" + else if (params.save_trimmed) "$filename" else null } @@ -408,10 +447,11 @@ if(!params.skip_trimming){ script: prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?$/ + // Cut Both EcoP and Linker if (params.trim_ecop && params.trim_linker){ """ - cutadapt -a ${params.ecoSite}...${params.linkerSeq} \\ + cutadapt -a ^${params.ecoSite}...${params.linkerSeq} \\ --match-read-wildcards \\ -m 15 -M 45 \\ -o "$prefix".adapter_trimmed.fastq.gz \\ @@ -462,7 +502,7 @@ if(!params.skip_trimming){ publishDir "${params.outdir}/trimmed/g_trimmed", mode: 'copy', saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" - else if (!params.save_trimmed) "$filename" + else if (params.save_trimmed) "$filename" else null } input: @@ -496,7 +536,7 @@ if (params.trim_artifacts && !params.skip_trimming){ publishDir "${params.outdir}/trimmed/artifacts_trimmed", mode: 'copy', saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" - else if (!params.save_trimmed) "$filename" + else if (params.save_trimmed) "$filename" else null } @@ -541,7 +581,7 @@ process trimmed_fastqc { set val(sample_name), file("*_fastqc.{zip,html}") into trimmed_fastqc_results when: - (params.trim_5g || params.trim_artifacts) && !params.skip_trimming + (params.trim_ecop || params.trim_linker || params.trim_5g || params.trim_artifacts) && !params.skip_trimming script: """ fastqc -q $reads @@ -682,7 +722,7 @@ process get_ctss { /** * STEP 9 - Cluster CTSS files */ -// ctss_counts = ctss_counts.collect().dump(tag:"ctss_counts") +ctss_counts = ctss_counts.collect().dump(tag:"ctss_counts") process cluster_ctss { label "high_memory" tag "${ctss}" From e6bed898fc4013bd830c7693f80f9f037588d8b3 Mon Sep 17 00:00:00 2001 From: mashehu Date: Tue, 5 May 2020 11:45:00 +0200 Subject: [PATCH 057/107] remove experimental trim_galore process --- main.nf | 80 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/main.nf b/main.nf index 9408799..86302f7 100644 --- a/main.nf +++ b/main.nf @@ -388,46 +388,46 @@ if(params.aligner == 'bowtie' && !params.bowtie_index && params.fasta){ /* * STEP 3 - Cut Enzyme binding site at 5' and linker at 3' */ - if (!params.skip_trimming) { - process trim_galore { - label 'low_memory' - tag "$sample_name" - publishDir "${params.outdir}/trim_galore", mode: "${params.publish_dir_mode}", - saveAs: {filename -> - if (filename.indexOf("_fastqc") > 0) "fastqc/$filename" - else if (filename.indexOf("trimming_report.txt") > 0) "logs/$filename" - else null - } - - input: - set val(sample_name), file(reads) from read_files_trimming - - output: - set val(sample_name), file("*fq.gz") into trimmed_reads_trim_5g - file "*trimming_report.txt" into trimgalore_results - file "*_fastqc.{zip,html}" into trimgalore_fastqc_reports - - script: - c_r1 = clip_r1 > 0 ? "--clip_r1 ${clip_r1}" : '' - c_r2 = clip_r2 > 0 ? "--clip_r2 ${clip_r2}" : '' - tpc_r1 = three_prime_clip_r1 > 0 ? "--three_prime_clip_r1 ${three_prime_clip_r1}" : '' - tpc_r2 = three_prime_clip_r2 > 0 ? "--three_prime_clip_r2 ${three_prime_clip_r2}" : '' - nextseq = params.trim_nextseq > 0 ? "--nextseq ${params.trim_nextseq}" : '' - if (params.single_end) { - """ - trim_galore --fastqc --gzip $c_r1 $tpc_r1 $nextseq $reads - """ - } else { - """ - trim_galore --paired --fastqc --gzip $c_r1 $c_r2 $tpc_r1 $tpc_r2 $nextseq $reads - """ - } - } - }else{ - raw_reads_trimgalore - .set {trimgalore_reads} - trimgalore_results = Channel.empty() - } + // if (!params.skip_trimming) { + // process trim_galore { + // label 'low_memory' + // tag "$sample_name" + // publishDir "${params.outdir}/trim_galore", mode: "${params.publish_dir_mode}", + // saveAs: {filename -> + // if (filename.indexOf("_fastqc") > 0) "fastqc/$filename" + // else if (filename.indexOf("trimming_report.txt") > 0) "logs/$filename" + // else null + // } + // + // input: + // set val(sample_name), file(reads) from read_files_trimming + // + // output: + // set val(sample_name), file("*fq.gz") into trimmed_reads_trim_5g + // file "*trimming_report.txt" into trimgalore_results + // file "*_fastqc.{zip,html}" into trimgalore_fastqc_reports + // + // script: + // c_r1 = clip_r1 > 0 ? "--clip_r1 ${clip_r1}" : '' + // c_r2 = clip_r2 > 0 ? "--clip_r2 ${clip_r2}" : '' + // tpc_r1 = three_prime_clip_r1 > 0 ? "--three_prime_clip_r1 ${three_prime_clip_r1}" : '' + // tpc_r2 = three_prime_clip_r2 > 0 ? "--three_prime_clip_r2 ${three_prime_clip_r2}" : '' + // nextseq = params.trim_nextseq > 0 ? "--nextseq ${params.trim_nextseq}" : '' + // if (params.single_end) { + // """ + // trim_galore --fastqc --gzip $c_r1 $tpc_r1 $nextseq $reads + // """ + // } else { + // """ + // trim_galore --paired --fastqc --gzip $c_r1 $c_r2 $tpc_r1 $tpc_r2 $nextseq $reads + // """ + // } + // } + // }else{ + // raw_reads_trimgalore + // .set {trimgalore_reads} + // trimgalore_results = Channel.empty() + // } if(!params.skip_trimming){ process trim_adapters { tag "$sample_name" From 7962894a65fed2e7c831a8bab8e55e3b44b982c4 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 7 May 2020 12:30:17 +0200 Subject: [PATCH 058/107] fix sample names in bowtie process --- assets/multiqc_config.yaml | 2 +- main.nf | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index 613e655..0b889e2 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -7,7 +7,7 @@ top_modules: - 'fastqc' - 'cutadapt' - 'star' - - 'bowtie' + - 'bowtie1' - 'samtools' - 'rseqc' extra_fn_clean_trim: diff --git a/main.nf b/main.nf index 86302f7..4112b1e 100644 --- a/main.nf +++ b/main.nf @@ -203,7 +203,6 @@ if (params.aligner == 'star') { summary['Aligner'] = "bowtie" if (params.bowtie_index)summary['bowtie Index'] = params.bowtie_index else if (params.fasta)summary['Fasta Ref'] = params.fasta - if (params.splicesites)summary['Splice Sites'] = params.splicesites } if(params.artifacts_5end){ summary["5' artifacts"] = params.artifacts_5end} if(params.artifacts_3end){ summary["3' artifacts"] = params.artifacts_3end} @@ -669,15 +668,15 @@ process bowtie { --phred33-quals \\ --chunkmbs 64 \\ --seedmms 2 \\ - --seedlen 28 \\ + --seedlen 25 \\ --maqerr 70 \\ ${index} \\ -q ${reads} \\ - --un ${reads.baseName}.unAl > ${sample_name}.sam 2> ${sample_name}.out + --un ${reads.baseName}.unAl > ${prefix}.sam 2> ${prefix}.out - samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${sample_name}.sam + samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${prefix}.sam """ - + } }else{ bowtie_alignment_logs= Channel.empty() From a43fd4db3c1e2bfffa1e8b48fc491b6fc28b1a8e Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 14 May 2020 17:15:32 +0200 Subject: [PATCH 059/107] add bigwig as optional output --- bin/make_ctss.sh | 14 ++-------- environment.yml | 1 + main.nf | 66 +++++++++++++++++++++++++++++++++++++++--------- nextflow.config | 2 ++ 4 files changed, 59 insertions(+), 24 deletions(-) diff --git a/bin/make_ctss.sh b/bin/make_ctss.sh index c96fc10..1898222 100755 --- a/bin/make_ctss.sh +++ b/bin/make_ctss.sh @@ -1,28 +1,18 @@ #!/bin/bash -if [ $# -eq 0 ] -then - cat < -i -n -EOF - exit 1; -fi - -QCUT= - while getopts :i:q:n: opt do case ${opt} in q) QCUT=${OPTARG};; i) VAR=${OPTARG};; n) NAME=${OPTARG};; +*) echo: "Usage is : $0 -q -i -n &2 + exit 1;; esac done if [ "${QCUT}" = "" ]; then QCUT=20; fi -echo "working on: ${VAR}" - #convert sam to bam and bam to bed TMPFILE="/tmp/$(basename "$0").$RANDOM.txt" samtools view -F 4 -u -q $QCUT -b "$VAR.bam" | bamToBed -i stdin > "$TMPFILE" diff --git a/environment.yml b/environment.yml index 1e80ec8..1540def 100644 --- a/environment.yml +++ b/environment.yml @@ -19,3 +19,4 @@ dependencies: - unzip=6.0 - bioconda::bowtie=1.2.3 - bioconda::rseqc=3.0.1 + - bioconda::ucsc-bedgraphtobigwig=357 diff --git a/main.nf b/main.nf index 4112b1e..32d32f8 100644 --- a/main.nf +++ b/main.nf @@ -37,18 +37,20 @@ def helpMessage() { References If not specified in the configuration file or you wish to overwrite any of the references --fasta [file] Path to fasta reference - --genome [str] Name of iGenomes reference + --genome [str] Name of iGenomes reference --gtf [file] Path to gtf file Alignment: - --aligner [str] Specifies the aligner to use (available are: 'star', 'bowtie') + --aligner [str] Specifies the aligner to use (available are: 'star', 'bowtie') --star_index [file] Path to STAR index, set to false if igenomes should be used --bowtie_index [file] Path to bowtie index, set to false if igenomes should be used Clustering: - --min_cluster [int] Minimum amount of reads to build a cluster with paraclu - --tpm_cluster_threshold [int] Threshold for expression count of ctss considered in paraclu clustering + --min_cluster [int] Minimum amount of reads to build a cluster with paraclu + --tpm_cluster_threshold [int] Threshold for expression count of ctss considered in paraclu clustering + Output: + --bigwig [bool] Set to true to get the ctss files also as bigwigs Other options: --outdir [file] The output directory where the results will be saved --email [email] Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits @@ -217,6 +219,7 @@ summary['Cluster Threshold [tpm]']= params.tpm_cluster_threshold summary['Save Reference'] = params.saveReference summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" if (workflow.containerEngine) summary['Container'] = "$workflow.containerEngine - $workflow.container" +summary['bigwig output'] = params.bigwig summary['Output dir'] = params.outdir summary['Launch dir'] = workflow.launchDir summary['Working dir'] = workflow.workDir @@ -298,6 +301,17 @@ process convert_gtf { gtf2bed.pl $gtf > ${gtf.baseName}.bed """ } +process get_chrom_sizes{ + input: + file fasta from fasta_rseqc.collect() + output: + file "*.txt" into (chrom_sizes_ctss,chrom_sizes_bw) + + shell: + ''' + cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.txt + ''' +} /* * STEP 1 - FastQC @@ -668,7 +682,7 @@ process bowtie { --phred33-quals \\ --chunkmbs 64 \\ --seedmms 2 \\ - --seedlen 25 \\ + --seedlen 20 \\ --maqerr 70 \\ ${index} \\ -q ${reads} \\ @@ -676,7 +690,7 @@ process bowtie { samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${prefix}.sam """ - + } }else{ bowtie_alignment_logs= Channel.empty() @@ -704,20 +718,48 @@ process samtools_stats { process get_ctss { tag "$sample_name" publishDir "${params.outdir}/ctss", mode: 'copy' + publishDir "${params.outdir}/ctss", mode: 'copy', + saveAs: {filename -> + if (filename.indexOf(".bed") != -1) "bed/$filename" + else if (filename.indexOf(".bw") != -1) "bigwig/$filename" + else filename } input: set val(sample_name), file(bam_count) from bam_aligned output: - set val(sample_name), file("*.ctss.bed") into ctss_samples + set val(sample_name), file("*.ctss.bed") into (ctss_samples,ctss_bw) file("*.ctss.bed") into (ctss_counts, ctss_counts_qc) + shell: + ''' + make_ctss.sh -q 20 -i !{bam_count.baseName} -n !{sample_name} + + ''' +} + +process make_bigwig{ + tag "$sample_name" + publishDir "${params.outdir}/ctss/bigwig", mode: 'copy' + + input: + set val(sample_name), file(ctss_file) from ctss_bw + file chrom_sizes from chrom_sizes_bw + + output: + file("*.ctss.bw") + // file("*.ctss.bw") into (ctss_counts, ctss_counts_qc) + + when: + params.bigwig script: """ - make_ctss.sh -q 20 -i ${bam_count.baseName} -n ${sample_name} + bedtools genomecov -bg -i ${sample_name}.ctss.bed -g ${chrom_sizes} > ${sample_name}.bedgraph + sort -k1,1 -k2,2n ${sample_name}.bedgraph > ${sample_name}_sorted.bedgraph + bedGraphToBigWig ${sample_name}_sorted.bedgraph ${chrom_sizes} ${sample_name}.ctss.bw """ -} +} /** * STEP 9 - Cluster CTSS files */ @@ -813,15 +855,15 @@ process ctss_qc { input: file clusters from ctss_counts_qc file gtf from bed_rseqc.collect() - file fasta from fasta_rseqc.collect() + file chrom_sizes from chrom_sizes_ctss output: file "*.txt" into rseqc_results shell: ''' - cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.tmp - bedtools bedtobam -i !{clusters} -g chrom_sizes.tmp > !{clusters.baseName}.bam + + bedtools bedtobam -i !{clusters} -g !{chrom_sizes} > !{clusters.baseName}.bam read_distribution.py -i !{clusters.baseName}.bam -r !{gtf} > !{clusters.baseName}.read_distribution.txt ''' } diff --git a/nextflow.config b/nextflow.config index c79f7fe..f57647e 100644 --- a/nextflow.config +++ b/nextflow.config @@ -33,6 +33,8 @@ params { artifacts_5end = "$baseDir/assets/artifacts_5end.fasta" artifacts_3end = "$baseDir/assets/artifacts_3end.fasta" + //Output options + bigwig=false // Boilerplate options name = false From 38f8b99cf615ac22e8c0b55674c8a8a516300e8c Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 14 May 2020 17:36:32 +0200 Subject: [PATCH 060/107] update formatting in output.md add more info about ctss files --- docs/output.md | 110 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 36 deletions(-) diff --git a/docs/output.md b/docs/output.md index 5928e23..672fadb 100644 --- a/docs/output.md +++ b/docs/output.md @@ -9,17 +9,27 @@ This document describes the output produced by the pipeline. Most of the plots a The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: + + - [nf-core/cageseq: Output](#nf-corecageseq-output) - [Pipeline overview](#pipeline-overview) - - [FastQC](#fastqc) - - [cutadapt](#cutadapt) - - [STAR](#star) - - [RSeQC](#rseqc) - - [Read distribution](#read-distribution) - - [paraclu](#paraclu) - - [MultiQC](#multiqc) - -1.**Raw read QC** + - [1. Raw read QC](#1-raw-read-qc) + - [2. Trimming](#2-trimming) + - [3. Alignment](#3-alignment) + - [STAR](#star) + - [Bowtie 1](#bowtie-1) + - [5. CTSS generation](#5-ctss-generation) + - [4. CTSS clustering](#4-ctss-clustering) + - [paraclu](#paraclu) + - [6. Count table generation](#6-count-table-generation) + - [7. QC of results](#7-qc-of-results) + - [RSeQC](#rseqc) + - [Read distribution](#read-distribution) + - [MultiQC](#multiqc) + + + +## 1. Raw read QC [FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your reads. It provides information about the quality score distribution across your reads, the per base sequence content (%T/A/G/C). You get information about adapter contamination and other overrepresented sequences. @@ -32,7 +42,7 @@ and processes data using the following steps: - `zips/sample_fastqc.zip` - zip file containing the FastQC report, tab-delimited data file and plot images -2.**Trimming** +## 2. Trimming [Cutadapt](https://cutadapt.readthedocs.io/en/stable/) finds and removes adapter sequences, primers, poly-A tails and other types of unwanted sequence from your @@ -42,39 +52,46 @@ By default this pipeline trims the cut enzyme binding site at the 5'-end and linkers at the 3'-end (can be disabled by setting `--trim_ecop` or `--trim_linkers to false`). Furthermore, to combat the leading-G-bias of CAGE-seq, G's at the 5'-end are removed. Additional artifacts can be removed via the `--trim_artifacts` parameter. -All the following trimming process are skipped if `--skip_trimming` is set to true. +All the following trimming process are skipped if `--skip_trimming` is set to true and the output below is only available if '--save_trimmed' is set to true. **Output directory: `results/trimmed`** - `adapter_trimmed/sample.adapter_trimmed.fastq.gz` - - Trimmed FastQ data - - **NB:** Only saved if `--save_trimmed` has been specified. -- `adapter_trimmed/logs/`: Trimming report (describes which parameters that were used) + - FastQ file after removal of linkers and EcoP15 site. +- `adapter_trimmed/logs/` + - Trimming report (describes which parameters that were used) - if `--trim_5g`: - `g_trimmed/sample.g_trimmed.fastq.gz` - - 5' G-corrected FastQ data - - **NB:** Only saved if `--save_trimmed` has been specified. - - `g_trimmed/logs/`: Trimming report (describes which parameters that were used) + - 5' G-corrected FastQ file + - `g_trimmed/logs/` + - Trimming report (describes which parameters that were used) - if `--trim_artifacts`: - `artifacts_trimmed/sample.artifact_trimmed.fastq.gz` - - FastQ data after artifact removal - - **NB:** Only saved if `--save_trimmed` has been specified. - - `artifacts_trimmed/logs/`: Trimming report (describes which parameters that were used) + - FastQ file after artifact removal + - `artifacts_trimmed/logs/` + - Trimming report (describes which parameters that were used) -3.**Alignment** +## 3. Alignment -The reads are aligned either with STAR or with bowtie. +The reads are aligned either with STAR or with bowtie, set via `--aligner`. ### STAR -*Documentation*: STAR is a read aligner designed for RNA sequencing. STAR stands for Spliced Transcripts Alignment to a Reference. -The STAR section of the MultiQC report shows a bar plot with alignment rates: good samples should have most reads as _Uniquely mapped_ and few _Unmapped_ reads. +The STAR section of the MultiQC report shows a stacked bar plot with alignment rates: +good samples should have most reads as _Uniquely mapped_ and few _Unmapped_ reads. +![STAR](images/star_alignment_plot.png) -### bowtie +### Bowtie 1 -![STAR](images/star_alignment_plot.png) +[Bowtie 1](http://bowtie-bio.sourceforge.net/index.shtml) is an ultrafast, +memory-efficient short read aligner. + +The bowtie 1 section of the MultiQC report shows a stacked bar plot with +alignment rates: +good samples should have most reads as _aligned_ and few _Not aligned_ reads. +![STAR](images/bowtie1_alignment_plot.png) **Output directory: `results/STAR`** @@ -87,17 +104,40 @@ The STAR section of the MultiQC report shows a bar plot with alignment rates: go - `Sample_SJ.out.tab` - Filtered splice junctions detected in the mapping -4.**CTSS Clustering** +## 5. CTSS generation + +The custom script `bin/make_ctss.sh` generates a bed file for each sample with +unclustered cage defined transcription start sites (CTSS). + +**Output directory: `results/ctss`** + +- `Sample.ctss.bed` + - A BED6 file with the cage defined transcription start sites + +## 4. CTSS clustering -## paraclu +### paraclu [paraclu](http://cbrc3.cbrc.jp/~martin/paraclu/) finds clusters in data -attached to sequences. It is used to define clusters of cage defined -transcription start sites (CTSS). +attached to sequences. It is applied on the pool of all ctss bed files to +cluster and returns a bed file with the clustered CTSSs. **Output directory: `results/ctss/clusters`** -## QC +- `ctss_all_clustered_simplified.bed` + - A BED6 file with the clustered CTSSs and their pooled counts + +## 6. Count table generation + +The ctss files are intersected with the clusteres identified by paraclu and +summarized in a count table. + +**Output directory: `results/ctss/`** + +- `count_table.tsv`: + - Each column of the count table stands for one sample and each row for one tag cluster. The first row of this table is the header with sample names and the first column contains the tag cluster coordinates. + +## 7. QC of results ### RSeQC @@ -109,13 +149,11 @@ This pipeline only runs the read destribution RSeQC scripts on the CTSS clusters #### Read distribution -**Output: `Sample_read_distribution.txt`** - -This tool calculates how mapped reads are distributed over genomic features. +[read_distribution.py](http://rseqc.sourceforge.net/#read-distribution-py) +calculates how mapped reads are distributed over genomic features. ![Read distribution](images/rseqc_read_distribution_plot.png) - -RSeQC documentation: [read_distribution.py](http://rseqc.sourceforge.net/#read-distribution-py) +**Output: `Sample_read_distribution.txt`** ### MultiQC From f3bba648119cd674ab029d6bd24e1391261c2496 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 14 May 2020 17:36:51 +0200 Subject: [PATCH 061/107] update cutadapt --- environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index 1540def..cf3f239 100644 --- a/environment.yml +++ b/environment.yml @@ -11,7 +11,7 @@ dependencies: - conda-forge::pymdown-extensions=6.0 - conda-forge::pygments=2.5.2 - bioconda::bedtools=2.29.2 - - bioconda::cutadapt=2.9 + - bioconda::cutadapt=2.10 - bioconda::fastqc=0.11.9 - bioconda::samtools=1.10 - bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. From 6b9c27a87ab33b723cd95f33e8e391fdebc531ec Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 14 May 2020 17:40:40 +0200 Subject: [PATCH 062/107] update dependencies --- environment.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/environment.yml b/environment.yml index 6ab5300..cf3f239 100644 --- a/environment.yml +++ b/environment.yml @@ -6,17 +6,17 @@ channels: - bioconda - defaults dependencies: - -- conda-forge::python=3.7.3 -- conda-forge::markdown=3.1.1 -- conda-forge::pymdown-extensions=6.0 -- conda-forge::pygments=2.5.2 -- bioconda::bedtools=2.27.1 -- bioconda::cutadapt=2.1 -- bioconda::fastqc=0.11.8 -- bioconda::samtools=1.9 -- bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. -- bioconda::multiqc=1.8 -- unzip=6.0 -- bioconda::bowtie=1.2.3 -- bioconda::rseqc=3.0.1 + - conda-forge::python=3.7.3 + - conda-forge::markdown=3.1.1 + - conda-forge::pymdown-extensions=6.0 + - conda-forge::pygments=2.5.2 + - bioconda::bedtools=2.29.2 + - bioconda::cutadapt=2.10 + - bioconda::fastqc=0.11.9 + - bioconda::samtools=1.10 + - bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. + - bioconda::multiqc=1.8 + - unzip=6.0 + - bioconda::bowtie=1.2.3 + - bioconda::rseqc=3.0.1 + - bioconda::ucsc-bedgraphtobigwig=357 From 812e9701e594d28e33f3788440c744ea7d34eb5e Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 15 May 2020 16:12:16 +0200 Subject: [PATCH 063/107] add sotrmerna rRNA filtering (based on RNA-seq pipeline) updated STAR parameters to allow more shorter reads. --- assets/multiqc_config.yaml | 1 + assets/rrna-db-defaults.txt | 8 ++++++++ environment.yml | 1 + nextflow.config | 5 +++++ 4 files changed, 15 insertions(+) create mode 100644 assets/rrna-db-defaults.txt diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index 0b889e2..56fdf6d 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -6,6 +6,7 @@ report_comment: > top_modules: - 'fastqc' - 'cutadapt' + - 'sortmerna' - 'star' - 'bowtie1' - 'samtools' diff --git a/assets/rrna-db-defaults.txt b/assets/rrna-db-defaults.txt new file mode 100644 index 0000000..609124b --- /dev/null +++ b/assets/rrna-db-defaults.txt @@ -0,0 +1,8 @@ +https://raw.githubusercontent.com/biocore/sortmerna/master/data/rRNA_databases/rfam-5.8s-database-id98.fasta +https://raw.githubusercontent.com/biocore/sortmerna/master/data/rRNA_databases/rfam-5s-database-id98.fasta +https://raw.githubusercontent.com/biocore/sortmerna/master/data/rRNA_databases/silva-arc-16s-id95.fasta +https://raw.githubusercontent.com/biocore/sortmerna/master/data/rRNA_databases/silva-arc-23s-id98.fasta +https://raw.githubusercontent.com/biocore/sortmerna/master/data/rRNA_databases/silva-bac-16s-id90.fasta +https://raw.githubusercontent.com/biocore/sortmerna/master/data/rRNA_databases/silva-bac-23s-id98.fasta +https://raw.githubusercontent.com/biocore/sortmerna/master/data/rRNA_databases/silva-euk-18s-id95.fasta +https://raw.githubusercontent.com/biocore/sortmerna/master/data/rRNA_databases/silva-euk-28s-id98.fasta diff --git a/environment.yml b/environment.yml index cf3f239..ad9c8a3 100644 --- a/environment.yml +++ b/environment.yml @@ -20,3 +20,4 @@ dependencies: - bioconda::bowtie=1.2.3 - bioconda::rseqc=3.0.1 - bioconda::ucsc-bedgraphtobigwig=357 + - sortmerna=2.1b diff --git a/nextflow.config b/nextflow.config index f57647e..d13a449 100644 --- a/nextflow.config +++ b/nextflow.config @@ -33,6 +33,11 @@ params { artifacts_5end = "$baseDir/assets/artifacts_5end.fasta" artifacts_3end = "$baseDir/assets/artifacts_3end.fasta" + // Ribosomal RNA removal + removeRiboRNA = false + save_nonrRNA_reads = false + rRNA_database_manifest = "$baseDir/assets/rrna-db-defaults.txt" + //Output options bigwig=false From e22cb632594eed71ae6f1ef4bb4ab49d8d56a061 Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 1 Jun 2020 11:29:43 +0200 Subject: [PATCH 064/107] add sortmerna rRNA removal --- environment.yml | 2 +- main.nf | 96 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 90 insertions(+), 8 deletions(-) diff --git a/environment.yml b/environment.yml index ad9c8a3..916bade 100644 --- a/environment.yml +++ b/environment.yml @@ -20,4 +20,4 @@ dependencies: - bioconda::bowtie=1.2.3 - bioconda::rseqc=3.0.1 - bioconda::ucsc-bedgraphtobigwig=357 - - sortmerna=2.1b + - sortmerna=4.2.0 diff --git a/main.nf b/main.nf index 32d32f8..2a74fc8 100644 --- a/main.nf +++ b/main.nf @@ -39,7 +39,10 @@ def helpMessage() { --fasta [file] Path to fasta reference --genome [str] Name of iGenomes reference --gtf [file] Path to gtf file - + Ribosomal RNA removal: + --remove_ribo_RNA Removes ribosomal RNA using SortMeRNA + --save_nonrRNA_reads Save FastQ file intermediates after removing rRNA + --rRNA_database_manifest Path to file that contains file paths for rRNA databases, optional Alignment: --aligner [str] Specifies the aligner to use (available are: 'star', 'bowtie') --star_index [file] Path to STAR index, set to false if igenomes should be used @@ -90,6 +93,17 @@ params.gtf = params.genome ? params.genomes[ params.genome ].gtf ?: false : fals params.min_cluster = 30 params.tpm_cluster_threshold = 0.2 +// Get rRNA databases +// Default is set to bundled DB list in `assets/rrna-db-defaults.txt` + +rRNA_database = file(params.rRNA_database_manifest) +if (rRNA_database.isEmpty()) {exit 1, "File ${rRNA_database.getName()} is empty!"} +Channel + .from( rRNA_database.readLines() ) + .map { row -> file(row) } + .set { fasta_sortmerna } + + // Validate inputs if (params.aligner != 'star' && params.aligner != 'bowtie') { exit 1, "Invalid aligner option: ${params.aligner}. Valid options: 'star', 'bowtie'" @@ -116,9 +130,10 @@ else { if( params.fasta ){ - fasta_rseqc = Channel + Channel .fromPath(params.fasta, checkIfExists: true) .ifEmpty { exit 1, "fasta file not found: ${params.fasta}" } + .set{fasta_rseqc} } else { exit 1, "No fasta file specified!" } @@ -214,8 +229,9 @@ summary['trim_5g'] = params.trim_5g summary['trim_artifacts'] = params.trim_artifacts summary['EcoSite'] = params.ecoSite summary['LinkerSeq'] = params.linkerSeq +summary['Remove rRNA'] = params.removeRiboRNA summary['Min. cluster'] = params.min_cluster -summary['Cluster Threshold [tpm]']= params.tpm_cluster_threshold +summary['Cluster Threshold']= params.tpm_cluster_threshold summary['Save Reference'] = params.saveReference summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" if (workflow.containerEngine) summary['Container'] = "$workflow.containerEngine - $workflow.container" @@ -574,10 +590,10 @@ if (params.trim_artifacts && !params.skip_trimming){ > ${reads.baseName}.artifacts_trimming.output.txt """ } - further_processed_reads.into { further_processed_reads_star;further_processed_reads_bowtie; further_processed_reads_fastqc } + further_processed_reads.into{further_processed_reads_fastqc; further_processed_reads_sortmerna } } else{ - processed_reads.into{further_processed_reads_star; further_processed_reads_bowtie; further_processed_reads_fastqc} + processed_reads.into{further_processed_reads_fastqc; further_processed_reads_sortmerna} artifact_cutting_results = Channel.empty() } @@ -600,7 +616,71 @@ process trimmed_fastqc { fastqc -q $reads """ } +/* + * STEP 2+ - SortMeRNA - remove rRNA sequences on request + */ +if (params.remove_ribo_RNA) { + // process sortmerna_index { + // label 'low_memory' + // tag "${fasta.baseName}" + // + // input: + // file(fasta) from fasta_sortmerna + // + // output: + // val("${fasta.baseName}") into sortmerna_db_name + // file("$fasta") into fasta_sortmerna_db + // file("${fasta.baseName}*") into sortmerna_db + // + // script: + // """ + // indexdb_rna --ref $fasta,${fasta.baseName} -m 3072 -v + // """ + // } + + process sortmerna { + tag "$sample_name" + publishDir "${params.outdir}/SortMeRNA", mode: "copy", + saveAs: {filename -> + if (filename.indexOf("_rRNA_report.txt") > 0) "logs/$filename" + else if (params.save_nonrRNA_reads) "reads/$filename" + else null + } + input: + set val(sample_name), file(reads) from further_processed_reads_sortmerna + file(fasta) from fasta_sortmerna + + output: + set val(sample_name), file("*.fq.gz") into further_processed_reads_star, further_processed_reads_bowtie; + file "*_rRNA_report.txt" into sortmerna_logs + + + script: + //concatenate reference files: ${db_fasta},${db_name}:${db_fasta},${db_name}:... + def Refs = '' + for (i=0; i ${sample_name}.fq.gz + mv rRNA-reads.log ${sample_name}_rRNA_report.txt + """ + } +} else { + further_processed_reads_sortmerna + .into {further_processed_reads_star; further_processed_reads_bowtie;} + sortmerna_logs = Channel.empty() + +} /** * STEP 7 - STAR alignment */ @@ -636,11 +716,12 @@ if (params.aligner == 'star') { --runThreadN ${task.cpus} \\ --outSAMtype BAM SortedByCoordinate \\ --outFilterScoreMinOverLread 0 --outFilterMatchNminOverLread 0 \\ + --seedSearchStartLmax 20 \\ --outFilterMismatchNmax 1 \\ --readFilesCommand zcat \\ --runDirPerm All_RWX \\ --outFileNamePrefix $prefix \\ - --outFilterMatchNmin ${params.min_aln_length} + --outFilterMultimapNmax 1 """ } @@ -882,6 +963,7 @@ process multiqc { file ('trimmed/*') from cutadapt_results.collect().ifEmpty([]) file ('artifacts_trimmed/*') from artifact_cutting_results.collect().ifEmpty([]) file ('trimmed/fastqc/*') from trimmed_fastqc_results.collect().ifEmpty([]) + file ('sortmerna/*') from sortmerna_logs.collect().ifEmpty([]) file ('alignment/*') from star_alignment_logs.collect().ifEmpty([]) file ('alignment/*') from bowtie_alignment_logs.collect().ifEmpty([]) file ('alignment/samtools_stats/*') from bam_flagstat_mqc.collect().ifEmpty([]) @@ -900,7 +982,7 @@ process multiqc { """ multiqc -f $rtitle $rfilename $custom_config_file \\ - -m custom_content -m fastqc -m star -m cutadapt -m rseqc -m samtools -m bowtie1 . + -m custom_content -m fastqc -m star -m cutadapt -m rseqc -m sortmerna -m samtools -m bowtie1 . """ } From 23c1dd98b64401307477d6ed388b92a8319479e6 Mon Sep 17 00:00:00 2001 From: mashehu Date: Tue, 2 Jun 2020 13:49:24 +0200 Subject: [PATCH 065/107] add sortmerna and updated MultiQC --- environment.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index cf3f239..b484aa4 100644 --- a/environment.yml +++ b/environment.yml @@ -15,8 +15,9 @@ dependencies: - bioconda::fastqc=0.11.9 - bioconda::samtools=1.10 - bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. - - bioconda::multiqc=1.8 + - bioconda::multiqc=1.9 - unzip=6.0 - bioconda::bowtie=1.2.3 - bioconda::rseqc=3.0.1 - bioconda::ucsc-bedgraphtobigwig=357 + - bioconda::sortmerna=4.2.0 From 373508fa5422b20993cc20dcb566535c8ad7a033 Mon Sep 17 00:00:00 2001 From: mashehu Date: Tue, 2 Jun 2020 15:07:01 +0200 Subject: [PATCH 066/107] follow best practices for multiqc --- assets/multiqc_config.yaml | 12 ++++++++++++ main.nf | 3 +-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index 56fdf6d..1660168 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -3,6 +3,17 @@ report_comment: > analysis pipeline. For information about how to interpret these results, please see the documentation. +# Run only these modules +run_modules: + - custom_content + - fastqc + - star + - cutadapt + - rseqc + - sortmerna + - samtools + - bowtie1 +# Order of modules in the report top_modules: - 'fastqc' - 'cutadapt' @@ -11,6 +22,7 @@ top_modules: - 'bowtie1' - 'samtools' - 'rseqc' +# remove from file name in report extra_fn_clean_trim: - '.adapter_trimmed.g' diff --git a/main.nf b/main.nf index 2a74fc8..d9f2800 100644 --- a/main.nf +++ b/main.nf @@ -981,8 +981,7 @@ process multiqc { custom_config_file = params.multiqc_config ? "--config $mqc_custom_config" : '' """ - multiqc -f $rtitle $rfilename $custom_config_file \\ - -m custom_content -m fastqc -m star -m cutadapt -m rseqc -m sortmerna -m samtools -m bowtie1 . + multiqc . -f $rtitle $rfilename $custom_config_file """ } From f0c62e5c19a1d05c1d2577b2df60b4151cd75fd6 Mon Sep 17 00:00:00 2001 From: mashehu Date: Thu, 4 Jun 2020 16:11:21 +0200 Subject: [PATCH 067/107] fix sortmerna process bugs --- environment.yml | 2 +- main.nf | 92 +++++++++++++++++++++++-------------------------- nextflow.config | 2 +- 3 files changed, 46 insertions(+), 50 deletions(-) diff --git a/environment.yml b/environment.yml index 916bade..8c6fe3f 100644 --- a/environment.yml +++ b/environment.yml @@ -20,4 +20,4 @@ dependencies: - bioconda::bowtie=1.2.3 - bioconda::rseqc=3.0.1 - bioconda::ucsc-bedgraphtobigwig=357 - - sortmerna=4.2.0 + - bioconda::sortmerna=4.2.0 diff --git a/main.nf b/main.nf index d9f2800..53834eb 100644 --- a/main.nf +++ b/main.nf @@ -229,7 +229,7 @@ summary['trim_5g'] = params.trim_5g summary['trim_artifacts'] = params.trim_artifacts summary['EcoSite'] = params.ecoSite summary['LinkerSeq'] = params.linkerSeq -summary['Remove rRNA'] = params.removeRiboRNA +summary['Remove rRNA'] = params.remove_ribo_RNA summary['Min. cluster'] = params.min_cluster summary['Cluster Threshold']= params.tpm_cluster_threshold summary['Save Reference'] = params.saveReference @@ -312,7 +312,7 @@ process convert_gtf { output: file "${gtf.baseName}.bed" into bed_rseqc - script: // This script is bundled with the pipeline, in nfcore/cageseq/bin/ + script: """ gtf2bed.pl $gtf > ${gtf.baseName}.bed """ @@ -417,6 +417,7 @@ if(params.aligner == 'bowtie' && !params.bowtie_index && params.fasta){ /* * STEP 3 - Cut Enzyme binding site at 5' and linker at 3' */ + // if (!params.skip_trimming) { // process trim_galore { // label 'low_memory' @@ -437,26 +438,19 @@ if(params.aligner == 'bowtie' && !params.bowtie_index && params.fasta){ // file "*_fastqc.{zip,html}" into trimgalore_fastqc_reports // // script: - // c_r1 = clip_r1 > 0 ? "--clip_r1 ${clip_r1}" : '' - // c_r2 = clip_r2 > 0 ? "--clip_r2 ${clip_r2}" : '' + // c_r1 = clip_r1 > 0 ? "--clip_r1 ${clip_r1}" : '6' // tpc_r1 = three_prime_clip_r1 > 0 ? "--three_prime_clip_r1 ${three_prime_clip_r1}" : '' - // tpc_r2 = three_prime_clip_r2 > 0 ? "--three_prime_clip_r2 ${three_prime_clip_r2}" : '' // nextseq = params.trim_nextseq > 0 ? "--nextseq ${params.trim_nextseq}" : '' - // if (params.single_end) { - // """ - // trim_galore --fastqc --gzip $c_r1 $tpc_r1 $nextseq $reads - // """ - // } else { + // """ + // trim_galore --fastqc --gzip --cores ${task.cpu} $c_r1 $tpc_r1 $nextseq $reads // """ - // trim_galore --paired --fastqc --gzip $c_r1 $c_r2 $tpc_r1 $tpc_r2 $nextseq $reads - // """ - // } // } // }else{ // raw_reads_trimgalore // .set {trimgalore_reads} // trimgalore_results = Channel.empty() // } + if(!params.skip_trimming){ process trim_adapters { tag "$sample_name" @@ -482,7 +476,9 @@ if(!params.skip_trimming){ """ cutadapt -a ^${params.ecoSite}...${params.linkerSeq} \\ --match-read-wildcards \\ - -m 15 -M 45 \\ + --minimum-length 20 --maximum-length 45 \\ + --discard-untrimmed \\ + --quality-cutoff 30 \\ -o "$prefix".adapter_trimmed.fastq.gz \\ $reads \\ > "$prefix"_adapter_trimming.output.txt @@ -496,7 +492,9 @@ if(!params.skip_trimming){ cutadapt -g ^${params.ecoSite} \\ -e 0 \\ --match-read-wildcards \\ + --minimum-length 20 --maximum-length 45 \\ --discard-untrimmed \\ + --quality-cutoff 30 \\ -o "$prefix".adapter_trimmed.fastq.gz \\ $reads \\ > "$prefix"_adapter_trimming.output.txt @@ -510,7 +508,9 @@ if(!params.skip_trimming){ cutadapt -a ${params.linkerSeq}\$ \\ -e 0 \\ --match-read-wildcards \\ - -m 15 -M 45 \\ + --minimum-length 20 --maximum-length 45 \\ + --discard-untrimmed \\ + --quality-cutoff 30 \\ -o "$prefix".adapter_trimmed.fastq.gz \\ $reads \\ > "$prefix"_adapter_trimming.output.txt @@ -649,7 +649,7 @@ if (params.remove_ribo_RNA) { input: set val(sample_name), file(reads) from further_processed_reads_sortmerna - file(fasta) from fasta_sortmerna + file(fasta) from fasta_sortmerna.collect() output: set val(sample_name), file("*.fq.gz") into further_processed_reads_star, further_processed_reads_bowtie; @@ -658,19 +658,18 @@ if (params.remove_ribo_RNA) { script: //concatenate reference files: ${db_fasta},${db_name}:${db_fasta},${db_name}:... - def Refs = '' - for (i=0; i ${sample_name}.fq.gz mv rRNA-reads.log ${sample_name}_rRNA_report.txt """ @@ -818,28 +817,25 @@ process get_ctss { ''' } +if(params.bigwig){ + process make_bigwig{ + tag "$sample_name" + publishDir "${params.outdir}/ctss/bigwig", mode: 'copy' -process make_bigwig{ - tag "$sample_name" - publishDir "${params.outdir}/ctss/bigwig", mode: 'copy' - - input: - set val(sample_name), file(ctss_file) from ctss_bw - file chrom_sizes from chrom_sizes_bw - - output: - file("*.ctss.bw") - // file("*.ctss.bw") into (ctss_counts, ctss_counts_qc) - - when: - params.bigwig - script: - """ - bedtools genomecov -bg -i ${sample_name}.ctss.bed -g ${chrom_sizes} > ${sample_name}.bedgraph - sort -k1,1 -k2,2n ${sample_name}.bedgraph > ${sample_name}_sorted.bedgraph - bedGraphToBigWig ${sample_name}_sorted.bedgraph ${chrom_sizes} ${sample_name}.ctss.bw - """ + input: + set val(sample_name), file(ctss_file) from ctss_bw + file chrom_sizes from chrom_sizes_bw + output: + file("*.ctss.bw") + // file("*.ctss.bw") into (ctss_counts, ctss_counts_qc) + script: + """ + bedtools genomecov -bg -i ${sample_name}.ctss.bed -g ${chrom_sizes} > ${sample_name}.bedgraph + sort -k1,1 -k2,2n ${sample_name}.bedgraph > ${sample_name}_sorted.bedgraph + bedGraphToBigWig ${sample_name}_sorted.bedgraph ${chrom_sizes} ${sample_name}.ctss.bw + """ + } } /** * STEP 9 - Cluster CTSS files diff --git a/nextflow.config b/nextflow.config index d13a449..4a3e5c2 100644 --- a/nextflow.config +++ b/nextflow.config @@ -34,7 +34,7 @@ params { artifacts_3end = "$baseDir/assets/artifacts_3end.fasta" // Ribosomal RNA removal - removeRiboRNA = false + remove_ribo_RNA = false save_nonrRNA_reads = false rRNA_database_manifest = "$baseDir/assets/rrna-db-defaults.txt" From 2366b2f3b68dfcce323da4a03c2f7d6f295caba2 Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 17 Jun 2020 21:24:32 +0200 Subject: [PATCH 068/107] change filtering lengths --- assets/multiqc_config.yaml | 29 +++++++++++++++++++++++++++++ main.nf | 4 ++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index 1660168..9392f86 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -13,6 +13,7 @@ run_modules: - sortmerna - samtools - bowtie1 + # Order of modules in the report top_modules: - 'fastqc' @@ -22,10 +23,38 @@ top_modules: - 'bowtie1' - 'samtools' - 'rseqc' + # remove from file name in report extra_fn_clean_trim: - '.adapter_trimmed.g' + - '.adapter_trimmed.g_trimmed_fastqc' +module_order: + - fastqc: + name: 'FastQC (raw)' + info: 'This section of the report shows FastQC results before adapter trimming.' + path_filters: + - '*_fastqc.zip' + path_filters_exclude: + - '*val*_fastqc.zip' + - '*trimmed_fastqc.zip' + - cutadapt: + name: 'cutadapt (library)' + info: 'This section of the report shows the length of trimmed reads by cutadapt.' + path_filters: + - '*_trimming_report.txt' + - sortmerna + - fastqc: + name: 'FastQC (library; trimmed)' + info: 'This section of the report shows FastQC results after adapter trimming.' + path_filters: + - '*val*_fastqc.zip' + - '*trimmed_fastqc.zip' + - star + - rseqc + - samtools + - bowtie1 + report_section_order: software_versions: order: -1000 diff --git a/main.nf b/main.nf index 53834eb..83e6060 100644 --- a/main.nf +++ b/main.nf @@ -476,7 +476,7 @@ if(!params.skip_trimming){ """ cutadapt -a ^${params.ecoSite}...${params.linkerSeq} \\ --match-read-wildcards \\ - --minimum-length 20 --maximum-length 45 \\ + --minimum-length 15 --maximum-length 50 \\ --discard-untrimmed \\ --quality-cutoff 30 \\ -o "$prefix".adapter_trimmed.fastq.gz \\ @@ -607,7 +607,7 @@ process trimmed_fastqc { set val(sample_name), file(reads) from further_processed_reads_fastqc output: - set val(sample_name), file("*_fastqc.{zip,html}") into trimmed_fastqc_results + path "*_fastqc.{zip,html}" into trimmed_fastqc_results when: (params.trim_ecop || params.trim_linker || params.trim_5g || params.trim_artifacts) && !params.skip_trimming From fed78dde1c6be67aa0cfd790d7f8aa22c02b1d64 Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 22 Jun 2020 16:17:23 +0200 Subject: [PATCH 069/107] fix g trimming error --- main.nf | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/main.nf b/main.nf index 83e6060..5e03837 100644 --- a/main.nf +++ b/main.nf @@ -476,9 +476,10 @@ if(!params.skip_trimming){ """ cutadapt -a ^${params.ecoSite}...${params.linkerSeq} \\ --match-read-wildcards \\ - --minimum-length 15 --maximum-length 50 \\ + --minimum-length 15 --maximum-length 45 \\ --discard-untrimmed \\ --quality-cutoff 30 \\ + --cores=${task.cpus} \\ -o "$prefix".adapter_trimmed.fastq.gz \\ $reads \\ > "$prefix"_adapter_trimming.output.txt @@ -495,6 +496,7 @@ if(!params.skip_trimming){ --minimum-length 20 --maximum-length 45 \\ --discard-untrimmed \\ --quality-cutoff 30 \\ + --cores=${task.cpus} \\ -o "$prefix".adapter_trimmed.fastq.gz \\ $reads \\ > "$prefix"_adapter_trimming.output.txt @@ -511,6 +513,7 @@ if(!params.skip_trimming){ --minimum-length 20 --maximum-length 45 \\ --discard-untrimmed \\ --quality-cutoff 30 \\ + --cores=${task.cpus} \\ -o "$prefix".adapter_trimmed.fastq.gz \\ $reads \\ > "$prefix"_adapter_trimming.output.txt @@ -544,11 +547,11 @@ if(!params.skip_trimming){ prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?$/ """ cutadapt -g ^G \\ - -e 0 --match-read-wildcards --discard-trimmed \\ + -e 0 --match-read-wildcards \\ --cores=${task.cpus} \\ -o "$prefix".g_trimmed.fastq.gz \\ $reads \\ - > ${reads.baseName}.g_trimming.output.txt + > "$prefix".g_trimming.output.txt """ } } From 446e652ad5de4841b29c9ca7840f3040f4f00928 Mon Sep 17 00:00:00 2001 From: mashehu Date: Tue, 23 Jun 2020 11:10:17 +0200 Subject: [PATCH 070/107] add more cores for sortmerna, reduce max length after trimming --- main.nf | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/main.nf b/main.nf index 5e03837..d573cbf 100644 --- a/main.nf +++ b/main.nf @@ -476,7 +476,7 @@ if(!params.skip_trimming){ """ cutadapt -a ^${params.ecoSite}...${params.linkerSeq} \\ --match-read-wildcards \\ - --minimum-length 15 --maximum-length 45 \\ + --minimum-length 15 --maximum-length 40 \\ --discard-untrimmed \\ --quality-cutoff 30 \\ --cores=${task.cpus} \\ @@ -493,7 +493,7 @@ if(!params.skip_trimming){ cutadapt -g ^${params.ecoSite} \\ -e 0 \\ --match-read-wildcards \\ - --minimum-length 20 --maximum-length 45 \\ + --minimum-length 20 --maximum-length 40 \\ --discard-untrimmed \\ --quality-cutoff 30 \\ --cores=${task.cpus} \\ @@ -510,7 +510,7 @@ if(!params.skip_trimming){ cutadapt -a ${params.linkerSeq}\$ \\ -e 0 \\ --match-read-wildcards \\ - --minimum-length 20 --maximum-length 45 \\ + --minimum-length 20 --maximum-length 40 \\ --discard-untrimmed \\ --quality-cutoff 30 \\ --cores=${task.cpus} \\ @@ -642,6 +642,7 @@ if (params.remove_ribo_RNA) { // } process sortmerna { + label 'high_memory' tag "$sample_name" publishDir "${params.outdir}/SortMeRNA", mode: "copy", saveAs: {filename -> From 4a1b2d55369a0c0615ad513489d94a0f70486b87 Mon Sep 17 00:00:00 2001 From: mashehu Date: Tue, 23 Jun 2020 16:40:54 +0200 Subject: [PATCH 071/107] remove too long process labels --- main.nf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main.nf b/main.nf index d573cbf..404e6ec 100644 --- a/main.nf +++ b/main.nf @@ -847,7 +847,7 @@ if(params.bigwig){ ctss_counts = ctss_counts.collect().dump(tag:"ctss_counts") process cluster_ctss { label "high_memory" - tag "${ctss}" + publishDir "${params.outdir}/ctss/clusters", mode: 'copy' input: @@ -905,7 +905,6 @@ process cluster_ctss { * STEP 11 - Generate count matrix */ process generate_count_matrix { - tag "${counts}" publishDir "${params.outdir}/ctss/", mode: 'copy' input: From af306b35822d3c299ca4cd7f0e0dc5eda27efc8b Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 24 Jun 2020 10:32:52 +0200 Subject: [PATCH 072/107] skip `trim_adapters` if `trim_ecop` and `trim_linker` are false --- assets/multiqc_config.yaml | 20 ++++++++++---------- main.nf | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index 9392f86..c00d392 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -14,15 +14,15 @@ run_modules: - samtools - bowtie1 -# Order of modules in the report -top_modules: - - 'fastqc' - - 'cutadapt' - - 'sortmerna' - - 'star' - - 'bowtie1' - - 'samtools' - - 'rseqc' +# # Order of modules in the report +# top_modules: +# - 'fastqc' +# - 'cutadapt' +# - 'sortmerna' +# - 'star' +# - 'bowtie1' +# - 'samtools' +# - 'rseqc' # remove from file name in report extra_fn_clean_trim: @@ -54,7 +54,7 @@ module_order: - rseqc - samtools - bowtie1 - + report_section_order: software_versions: order: -1000 diff --git a/main.nf b/main.nf index 404e6ec..5c55380 100644 --- a/main.nf +++ b/main.nf @@ -451,7 +451,7 @@ if(params.aligner == 'bowtie' && !params.bowtie_index && params.fasta){ // trimgalore_results = Channel.empty() // } -if(!params.skip_trimming){ +if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ process trim_adapters { tag "$sample_name" publishDir "${params.outdir}/trimmed/adapter_trimmed", mode: 'copy', From 34467a20f914e32f7363f3c2d4a04c4f711a599e Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 26 Jun 2020 11:18:23 +0200 Subject: [PATCH 073/107] add sortmerna version check, fix multiqc module order --- assets/multiqc_config.yaml | 22 +++++++++++----------- bin/scrape_software_versions.py | 2 ++ main.nf | 1 + 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/assets/multiqc_config.yaml b/assets/multiqc_config.yaml index c00d392..016070b 100644 --- a/assets/multiqc_config.yaml +++ b/assets/multiqc_config.yaml @@ -14,15 +14,15 @@ run_modules: - samtools - bowtie1 -# # Order of modules in the report -# top_modules: -# - 'fastqc' -# - 'cutadapt' -# - 'sortmerna' -# - 'star' -# - 'bowtie1' -# - 'samtools' -# - 'rseqc' +# Order of modules in the report +top_modules: + - 'fastqc' + - 'cutadapt' + - 'sortmerna' + - 'star' + - 'bowtie1' + - 'samtools' + - 'rseqc' # remove from file name in report extra_fn_clean_trim: @@ -51,9 +51,9 @@ module_order: - '*val*_fastqc.zip' - '*trimmed_fastqc.zip' - star - - rseqc - - samtools - bowtie1 + - samtools + - rseqc report_section_order: software_versions: diff --git a/bin/scrape_software_versions.py b/bin/scrape_software_versions.py index 70dac50..26b4592 100755 --- a/bin/scrape_software_versions.py +++ b/bin/scrape_software_versions.py @@ -13,6 +13,7 @@ 'bedtools': ['v_bedtools.txt', r"bedtools v(\S+)"], 'cutadapt': ['v_cutadapt.txt', r"(\S+)"], 'samtools': ['v_samtools.txt', r"samtools (\S+)"], + 'sortmerna': ['v_sortmerna.txt', r"SortMeRNA version (\S+)"], 'rseqc': ['v_rseqc.txt', r"read_distribution.py (\S+)"], } results = OrderedDict() @@ -25,6 +26,7 @@ results['bedtools'] = 'N/A' results['cutadapt'] = 'N/A' results['samtools'] = 'N/A' +results['sortmerna'] = 'N/A' results['rseqc'] = 'N/A' # Search each file using its regex diff --git a/main.nf b/main.nf index 5c55380..e56e80a 100644 --- a/main.nf +++ b/main.nf @@ -300,6 +300,7 @@ process get_software_versions { samtools --version > v_samtools.txt bedtools --version > v_bedtools.txt read_distribution.py --version > v_rseqc.txt + sortmerna --version > v_sortmerna.txt scrape_software_versions.py &> software_versions_mqc.yaml """ } From 660fb4e3c5393306e83d3bac152ef27c9808170a Mon Sep 17 00:00:00 2001 From: mashehu Date: Wed, 1 Jul 2020 14:50:23 +0200 Subject: [PATCH 074/107] replace file prefix with sample name --- main.nf | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/main.nf b/main.nf index e56e80a..37c0e73 100644 --- a/main.nf +++ b/main.nf @@ -470,7 +470,7 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ file "*.output.txt" into cutadapt_results script: - prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?$/ + // prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?$/ // Cut Both EcoP and Linker if (params.trim_ecop && params.trim_linker){ @@ -481,9 +481,9 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ --discard-untrimmed \\ --quality-cutoff 30 \\ --cores=${task.cpus} \\ - -o "$prefix".adapter_trimmed.fastq.gz \\ + -o "$sample_name".adapter_trimmed.fastq.gz \\ $reads \\ - > "$prefix"_adapter_trimming.output.txt + > "$sample_name"_adapter_trimming.output.txt """ } @@ -498,9 +498,9 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ --discard-untrimmed \\ --quality-cutoff 30 \\ --cores=${task.cpus} \\ - -o "$prefix".adapter_trimmed.fastq.gz \\ + -o "$sample_name".adapter_trimmed.fastq.gz \\ $reads \\ - > "$prefix"_adapter_trimming.output.txt + > "$sample_name"_adapter_trimming.output.txt """ } @@ -515,9 +515,9 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ --discard-untrimmed \\ --quality-cutoff 30 \\ --cores=${task.cpus} \\ - -o "$prefix".adapter_trimmed.fastq.gz \\ + -o "$sample_name".adapter_trimmed.fastq.gz \\ $reads \\ - > "$prefix"_adapter_trimming.output.txt + > "$sample_name"_adapter_trimming.output.txt """ } } @@ -545,14 +545,14 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ set val(sample_name), file("*.fastq.gz") into processed_reads script: - prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?$/ + // prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?$/ """ cutadapt -g ^G \\ -e 0 --match-read-wildcards \\ --cores=${task.cpus} \\ - -o "$prefix".g_trimmed.fastq.gz \\ + -o "$sample_name".g_trimmed.fastq.gz \\ $reads \\ - > "$prefix".g_trimming.output.txt + > "$sample_name".g_trimming.output.txt """ } } @@ -583,13 +583,13 @@ if (params.trim_artifacts && !params.skip_trimming){ file "*.output.txt" into artifact_cutting_results script: - prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?(\.processed)?$/ + // prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?(\.processed)?$/ """ cutadapt -a file:$artifacts_3end \\ -g file:$artifacts_5end -e 0.1 --discard-trimmed \\ --match-read-wildcards -m 15 -O 19 \\ --cores=${task.cpus} \\ - -o "$prefix".artifacts_trimmed.fastq.gz \\ + -o "$sample_name".artifacts_trimmed.fastq.gz \\ $reads \\ > ${reads.baseName}.artifacts_trimming.output.txt """ @@ -711,7 +711,7 @@ if (params.aligner == 'star') { script: - prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ + // prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ """ STAR --genomeDir $index \\ @@ -724,7 +724,7 @@ if (params.aligner == 'star') { --outFilterMismatchNmax 1 \\ --readFilesCommand zcat \\ --runDirPerm All_RWX \\ - --outFileNamePrefix $prefix \\ + --outFileNamePrefix $sample_name \\ --outFilterMultimapNmax 1 """ @@ -754,7 +754,7 @@ process bowtie { script: - prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ + // prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ index = index_array[0].baseName - ~/.\d$/ """ bowtie --sam \\ @@ -771,9 +771,9 @@ process bowtie { --maqerr 70 \\ ${index} \\ -q ${reads} \\ - --un ${reads.baseName}.unAl > ${prefix}.sam 2> ${prefix}.out + --un ${reads.baseName}.unAl > ${sample_name}.sam 2> ${sample_name}.out - samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${prefix}.sam + samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${sample_name}.sam """ } From a011336fe8c273f96b748a75fe28fd3d5b54e819 Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 13 Jul 2020 15:07:41 +0200 Subject: [PATCH 075/107] update README.md --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d9a9e15..dc24810 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,16 @@ Nextflow CAGE-seq analysis pipeline, part of the nf-core community [![Docker](https://img.shields.io/docker/automated/nfcore/cageseq.svg)](https://hub.docker.com/r/nfcore/cageseq) ## Introduction - +___ UNDER DEVELOPMENT This pipeline is currenlty under development. The workflow is not yet finished. +___ + +**nf-core/cageseq** is a bioinformatics analysis pipeline used for CAGE-seq sequencing data. -The pipeline includes steps for adapter and artefact trimming -([cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), alignment to +The pipeline takes raw demultiplexed reads and includes steps for adapter and artefact trimming +([cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), rRNA removal ([SortMeRNA](https://github.com/biocore/sortmerna), alignment to a reference genome ([STAR](https://github.com/alexdobin/STAR) or [bowtie](http://bowtie-bio.sourceforge.net/index.shtml)) and CAGE tag counting and clustering ([paraclu](http://cbrc3.cbrc.jp/~martin/paraclu/)). @@ -24,7 +27,7 @@ Additionally, several quality control steps ([FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/), [RSeQC](http://rseqc.sourceforge.net/), [MultiQC](https://multiqc.info/)) -are included to allow for easy verification of results after a run. +are included to allow for easy verification of the results after a run. The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It comes with docker containers making installation trivial and results highly reproducible. @@ -32,9 +35,9 @@ The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool i. Install [`nextflow`](https://nf-co.re/usage/installation) -ii. Install either [`Docker`](https://docs.docker.com/engine/installation/) or [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/) for full pipeline reproducibility (please only use [`Conda`](https://conda.io/miniconda.html) as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles)) +ii. Install one of [`docker`](https://docs.docker.com/engine/installation/), [`singularity`](https://www.sylabs.io/guides/3.0/user-guide/) or [`conda`](https://conda.io/miniconda.html) -iii. Download the pipeline and test it on a minimal dataset with a single command +iii. Download the nf-core/cagesq pipeline and test it on a minimal dataset with a single command ```bash nextflow run nf-core/cageseq -profile test, From 34988dd2ba28b1d53e765e380bee79e70ae4ee7c Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 30 Jul 2020 20:05:06 +0000 Subject: [PATCH 076/107] Template update for nf-core/tools version 1.10.1 --- .github/.dockstore.yml | 5 + .github/CONTRIBUTING.md | 2 +- .github/ISSUE_TEMPLATE/bug_report.md | 15 +- .github/ISSUE_TEMPLATE/feature_request.md | 12 +- .github/PULL_REQUEST_TEMPLATE.md | 15 +- .github/workflows/awsfulltest.yml | 40 ++++ .github/workflows/awstest.yml | 40 ++++ .github/workflows/branch.yml | 30 ++- .github/workflows/ci.yml | 47 +++- .github/workflows/linting.yml | 13 +- .github/workflows/push_dockerhub.yml | 39 ++++ .gitignore | 1 + CHANGELOG.md | 6 +- CODE_OF_CONDUCT.md | 6 +- Dockerfile | 10 +- LICENSE | 2 +- README.md | 44 ++-- bin/markdown_to_html.py | 43 ++-- bin/scrape_software_versions.py | 36 +-- conf/igenomes.config | 1 + conf/test.config | 2 +- conf/test_full.config | 22 ++ docs/README.md | 20 +- docs/output.md | 50 ++-- docs/usage.md | 272 +++------------------- main.nf | 53 +++-- nextflow.config | 9 +- nextflow_schema.json | 259 ++++++++++++++++++++ 28 files changed, 684 insertions(+), 410 deletions(-) create mode 100644 .github/.dockstore.yml create mode 100644 .github/workflows/awsfulltest.yml create mode 100644 .github/workflows/awstest.yml create mode 100644 .github/workflows/push_dockerhub.yml create mode 100644 conf/test_full.config create mode 100644 nextflow_schema.json diff --git a/.github/.dockstore.yml b/.github/.dockstore.yml new file mode 100644 index 0000000..030138a --- /dev/null +++ b/.github/.dockstore.yml @@ -0,0 +1,5 @@ +# Dockstore config version, not pipeline version +version: 1.2 +workflows: + - subclass: nfl + primaryDescriptorPath: /nextflow.config diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 50a66c9..f1a6cba 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -54,4 +54,4 @@ These tests are run both with the latest available version of `Nextflow` and als ## Getting help -For further information/help, please consult the [nf-core/cageseq documentation](https://nf-co.re/nf-core/cageseq/docs) and don't hesitate to get in touch on the nf-core Slack [#cageseq](https://nfcore.slack.com/channels/cageseq) channel ([join our Slack here](https://nf-co.re/join/slack)). +For further information/help, please consult the [nf-core/cageseq documentation](https://nf-co.re/cageseq/docs) and don't hesitate to get in touch on the nf-core Slack [#cageseq](https://nfcore.slack.com/channels/cageseq) channel ([join our Slack here](https://nf-co.re/join/slack)). diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index e5d32f4..6b24382 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,24 +1,27 @@ + -## Describe the bug +## Description of the bug -A clear and concise description of what the bug is. + ## Steps to reproduce Steps to reproduce the behaviour: -1. Command line: `nextflow run ...` -2. See error: _Please provide your error message_ +1. Command line: +2. See error: ## Expected behaviour -A clear and concise description of what you expected to happen. + ## System @@ -39,4 +42,4 @@ A clear and concise description of what you expected to happen. ## Additional context -Add any other context about the problem here. + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index b92d059..7db9f20 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,24 +1,26 @@ + ## Is your feature request related to a problem? Please describe -A clear and concise description of what the problem is. + -Ex. I'm always frustrated when [...] + ## Describe the solution you'd like -A clear and concise description of what you want to happen. + ## Describe alternatives you've considered -A clear and concise description of any alternative solutions or features you've considered. + ## Additional context -Add any other context about the feature request here. + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index de814a0..0995718 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,4 @@ + + ## PR checklist - [ ] This comment contains a description of changes (with reason) +- [ ] `CHANGELOG.md` is updated - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If necessary, also make a PR on the [nf-core/cageseq branch on the nf-core/test-datasets repo](https://github.com/nf-core/test-datasets/pull/new/nf-core/cageseq) -- [ ] Ensure the test suite passes (`nextflow run . -profile test,docker`). -- [ ] Make sure your code lints (`nf-core lint .`). - [ ] Documentation in `docs` is updated -- [ ] `CHANGELOG.md` is updated -- [ ] `README.md` is updated - -**Learn more about contributing:** [CONTRIBUTING.md](https://github.com/nf-core/cageseq/tree/master/.github/CONTRIBUTING.md) \ No newline at end of file +- [ ] If necessary, also make a PR on the [nf-core/cageseq branch on the nf-core/test-datasets repo](https://github.com/nf-core/test-datasets/pull/new/nf-core/cageseq) diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml new file mode 100644 index 0000000..5149c40 --- /dev/null +++ b/.github/workflows/awsfulltest.yml @@ -0,0 +1,40 @@ +name: nf-core AWS full size tests +# This workflow is triggered on push to the master branch. +# It runs the -profile 'test_full' on AWS batch + +on: + release: + types: [published] + +jobs: + run-awstest: + name: Run AWS full tests + if: github.repository == 'nf-core/cageseq' + runs-on: ubuntu-latest + steps: + - name: Setup Miniconda + uses: goanpeca/setup-miniconda@v1.0.2 + with: + auto-update-conda: true + python-version: 3.7 + - name: Install awscli + run: conda install -c conda-forge awscli + - name: Start AWS batch job + # TODO nf-core: You can customise AWS full pipeline tests as required + # Add full size test data (but still relatively small datasets for few samples) + # on the `test_full.config` test runs with only one set of parameters + # Then specify `-profile test_full` instead of `-profile test` on the AWS batch command + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + TOWER_ACCESS_TOKEN: ${{ secrets.AWS_TOWER_TOKEN }} + AWS_JOB_DEFINITION: ${{ secrets.AWS_JOB_DEFINITION }} + AWS_JOB_QUEUE: ${{ secrets.AWS_JOB_QUEUE }} + AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} + run: | + aws batch submit-job \ + --region eu-west-1 \ + --job-name nf-core-cageseq \ + --job-queue $AWS_JOB_QUEUE \ + --job-definition $AWS_JOB_DEFINITION \ + --container-overrides '{"command": ["nf-core/cageseq", "-r '"${GITHUB_SHA}"' -profile test --outdir s3://'"${AWS_S3_BUCKET}"'/cageseq/results-'"${GITHUB_SHA}"' -w s3://'"${AWS_S3_BUCKET}"'/cageseq/work-'"${GITHUB_SHA}"' -with-tower"], "environment": [{"name": "TOWER_ACCESS_TOKEN", "value": "'"$TOWER_ACCESS_TOKEN"'"}]}' diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml new file mode 100644 index 0000000..857ca48 --- /dev/null +++ b/.github/workflows/awstest.yml @@ -0,0 +1,40 @@ +name: nf-core AWS test +# This workflow is triggered on push to the master branch. +# It runs the -profile 'test' on AWS batch + +on: + push: + branches: + - master + +jobs: + run-awstest: + name: Run AWS tests + if: github.repository == 'nf-core/cageseq' + runs-on: ubuntu-latest + steps: + - name: Setup Miniconda + uses: goanpeca/setup-miniconda@v1.0.2 + with: + auto-update-conda: true + python-version: 3.7 + - name: Install awscli + run: conda install -c conda-forge awscli + - name: Start AWS batch job + # TODO nf-core: You can customise CI pipeline run tests as required + # For example: adding multiple test runs with different parameters + # Remember that you can parallelise this by using strategy.matrix + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + TOWER_ACCESS_TOKEN: ${{ secrets.AWS_TOWER_TOKEN }} + AWS_JOB_DEFINITION: ${{ secrets.AWS_JOB_DEFINITION }} + AWS_JOB_QUEUE: ${{ secrets.AWS_JOB_QUEUE }} + AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} + run: | + aws batch submit-job \ + --region eu-west-1 \ + --job-name nf-core-cageseq \ + --job-queue $AWS_JOB_QUEUE \ + --job-definition $AWS_JOB_DEFINITION \ + --container-overrides '{"command": ["nf-core/cageseq", "-r '"${GITHUB_SHA}"' -profile test --outdir s3://'"${AWS_S3_BUCKET}"'/cageseq/results-'"${GITHUB_SHA}"' -w s3://'"${AWS_S3_BUCKET}"'/cageseq/work-'"${GITHUB_SHA}"' -with-tower"], "environment": [{"name": "TOWER_ACCESS_TOKEN", "value": "'"$TOWER_ACCESS_TOKEN"'"}]}'cageseq/work-'"${GITHUB_SHA}"' -with-tower"], "environment": [{"name": "TOWER_ACCESS_TOKEN", "value": "'"$TOWER_ACCESS_TOKEN"'"}]}' diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 9cb261e..50513b0 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -3,14 +3,34 @@ name: nf-core branch protection # It fails when someone tries to make a PR against the nf-core `master` branch instead of `dev` on: pull_request: - branches: - - master + branches: [master] jobs: test: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - # PRs are only ok if coming from an nf-core `dev` branch or a fork `patch` branch + # PRs to the nf-core repo master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches - name: Check PRs + if: github.repository == 'nf-core/cageseq' run: | - { [[ $(git remote get-url origin) == *nf-core/cageseq ]] && [[ ${GITHUB_HEAD_REF} = "dev" ]]; } || [[ ${GITHUB_HEAD_REF} == "patch" ]] + { [[ ${{github.event.pull_request.head.repo.full_name}} == nf-core/cageseq ]] && [[ $GITHUB_HEAD_REF = "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] + + + # 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: | + Hi @${{ github.event.pull_request.user.login }}, + + It looks like this pull-request is has been made against the ${{github.event.pull_request.head.repo.full_name}} `master` branch. + The `master` branch on nf-core repositories should always contain code from the latest release. + Because of this, PRs to `master` are only allowed if they come from the ${{github.event.pull_request.head.repo.full_name}} `dev` branch. + + You do not need to close this PR, you can change the target branch to `dev` by clicking the _"Edit"_ button at the top of this page. + + Thanks again for your contribution! + repo-token: ${{ secrets.GITHUB_TOKEN }} + allow-repeats: false + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6471c8..2addbc4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,30 +1,55 @@ name: nf-core CI -# This workflow is triggered on pushes and PRs to the repository. -# It runs the pipeline with the minimal test dataset to check that it completes without any syntax errors -on: [push, pull_request] +# This workflow runs the pipeline with the minimal test dataset to check that it completes without any syntax errors +on: + push: + branches: + - dev + pull_request: + release: + types: [published] jobs: test: + name: Run workflow tests + # Only run on push if this is the nf-core dev branch (merged PRs) + if: ${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/cageseq') }} + runs-on: ubuntu-latest env: NXF_VER: ${{ matrix.nxf_ver }} NXF_ANSI_LOG: false - runs-on: ubuntu-latest strategy: matrix: # Nextflow versions: check pipeline minimum and current latest nxf_ver: ['19.10.0', ''] steps: - - uses: actions/checkout@v2 - - name: Install Nextflow - run: | - wget -qO- get.nextflow.io | bash - sudo mv nextflow /usr/local/bin/ + - name: Check out pipeline code + uses: actions/checkout@v2 + + - name: Check if Dockerfile or Conda environment changed + uses: technote-space/get-diff-action@v1 + with: + PREFIX_FILTER: | + Dockerfile + environment.yml + + - name: Build new docker image + if: env.GIT_DIFF + run: docker build --no-cache . -t nfcore/cageseq:dev + - name: Pull docker image + if: ${{ !env.GIT_DIFF }} run: | docker pull nfcore/cageseq:dev docker tag nfcore/cageseq:dev nfcore/cageseq:dev + + - name: Install Nextflow + run: | + wget -qO- get.nextflow.io | bash + sudo mv nextflow /usr/local/bin/ + - name: Run pipeline with test data + # TODO nf-core: You can customise CI pipeline run tests as required + # For example: adding multiple test runs with different parameters + # Remember that you can parallelise this by using strategy.matrix run: | - # TODO nf-core: You can customise CI pipeline run tests as required - # (eg. adding multiple test runs with different parameters) nextflow run ${GITHUB_WORKSPACE} -profile test,docker diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 1e0827a..eb66c14 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -33,18 +33,29 @@ jobs: nf-core: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + + - name: Check out pipeline code + uses: actions/checkout@v2 + - name: Install Nextflow run: | wget -qO- get.nextflow.io | bash sudo mv nextflow /usr/local/bin/ + - uses: actions/setup-python@v1 with: python-version: '3.6' architecture: 'x64' + - name: Install dependencies run: | python -m pip install --upgrade pip pip install nf-core + - name: Run nf-core lint + env: + GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_PR_COMMIT: ${{ github.event.pull_request.head.sha }} run: nf-core lint ${GITHUB_WORKSPACE} + diff --git a/.github/workflows/push_dockerhub.yml b/.github/workflows/push_dockerhub.yml new file mode 100644 index 0000000..912314d --- /dev/null +++ b/.github/workflows/push_dockerhub.yml @@ -0,0 +1,39 @@ +name: nf-core Docker push +# This builds the docker image and pushes it to DockerHub +# Runs on nf-core repo releases and push event to 'dev' branch (PR merges) +on: + push: + branches: + - dev + release: + types: [published] + +push_dockerhub: + name: Push new Docker image to Docker Hub + runs-on: ubuntu-latest + # Only run for the nf-core repo, for releases and merged PRs + if: ${{ github.repository == 'nf-core/cageseq' }} + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASS: ${{ secrets.DOCKERHUB_PASS }} + steps: + - name: Check out pipeline code + uses: actions/checkout@v2 + + - name: Build new docker image + run: docker build --no-cache . -t nfcore/cageseq:latest + + - name: Push Docker image to DockerHub (dev) + if: ${{ github.event_name == 'push' }} + run: | + echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin + docker tag nfcore/cageseq:latest nfcore/cageseq:dev + docker push nfcore/cageseq:dev + + - name: Push Docker image to DockerHub (release) + if: ${{ github.event_name == 'release' }} + run: | + echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin + docker push nfcore/cageseq:latest + docker tag nfcore/cageseq:latest nfcore/cageseq:${{ github.event.release.tag_name }} + docker push nfcore/cageseq:${{ github.event.release.tag_name }} diff --git a/.gitignore b/.gitignore index 6354f37..aa4bb5b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ results/ .DS_Store tests/ testing/ +testing* *.pyc diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dbc61d..7f1e4fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,11 @@ # nf-core/cageseq: Changelog -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## v1.0dev - [date] -Initial release of nf-core/cageseq, created with the [nf-core](http://nf-co.re/) template. +Initial release of nf-core/cageseq, created with the [nf-core](https://nf-co.re/) template. ### `Added` diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index cf930c8..405fb1b 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -40,7 +40,7 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct/][version] -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ +[homepage]: https://contributor-covenant.org +[version]: https://www.contributor-covenant.org/version/1/4/code-of-conduct/ diff --git a/Dockerfile b/Dockerfile index 778ca02..e0b3ee2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,17 @@ -FROM nfcore/base:1.9 -LABEL authors="Kevin Menden" \ +FROM nfcore/base:1.10.1 +LABEL authors="Kevin Menden, Tristan Kast, Matthias Hörtenhuber" \ description="Docker image containing all software requirements for the nf-core/cageseq pipeline" # Install the conda environment COPY environment.yml / -RUN conda env create -f /environment.yml && conda clean -a +RUN conda env create --quiet -f /environment.yml && conda clean -a # Add conda installation dir to PATH (instead of doing 'conda activate') ENV PATH /opt/conda/envs/nf-core-cageseq-1.0dev/bin:$PATH # Dump the details of the installed packages to a file for posterity RUN conda env export --name nf-core-cageseq-1.0dev > nf-core-cageseq-1.0dev.yml + +# Instruct R processes to use these empty files instead of clashing with a local version +RUN touch .Rprofile +RUN touch .Renviron diff --git a/LICENSE b/LICENSE index 3c79044..8620150 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) Kevin Menden +Copyright (c) Kevin Menden, Tristan Kast, Matthias Hörtenhuber Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 1867e68..14566ba 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,9 @@ [![GitHub Actions Linting Status](https://github.com/nf-core/cageseq/workflows/nf-core%20linting/badge.svg)](https://github.com/nf-core/cageseq/actions) [![Nextflow](https://img.shields.io/badge/nextflow-%E2%89%A519.10.0-brightgreen.svg)](https://www.nextflow.io/) -[![install with bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg)](http://bioconda.github.io/) +[![install with bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg)](https://bioconda.github.io/) [![Docker](https://img.shields.io/docker/automated/nfcore/cageseq.svg)](https://hub.docker.com/r/nfcore/cageseq) +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23cageseq-4A154B?logo=slack)](https://nfcore.slack.com/channels/cageseq) ## Introduction @@ -15,52 +16,43 @@ The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool ## Quick Start -i. Install [`nextflow`](https://nf-co.re/usage/installation) +1. Install [`nextflow`](https://nf-co.re/usage/installation) -ii. Install either [`Docker`](https://docs.docker.com/engine/installation/) or [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/) for full pipeline reproducibility (please only use [`Conda`](https://conda.io/miniconda.html) as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles)) +2. Install either [`Docker`](https://docs.docker.com/engine/installation/) or [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/) for full pipeline reproducibility _(please only use [`Conda`](https://conda.io/miniconda.html) as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles))_ -iii. Download the pipeline and test it on a minimal dataset with a single command +3. Download the pipeline and test it on a minimal dataset with a single command: -```bash -nextflow run nf-core/cageseq -profile test, -``` + ```bash + nextflow run nf-core/cageseq -profile test, + ``` -> Please check [nf-core/configs](https://github.com/nf-core/configs#documentation) to see if a custom config file to run nf-core pipelines already exists for your Institute. If so, you can simply use `-profile ` in your command. This will enable either `docker` or `singularity` and set the appropriate execution settings for your local compute environment. + > Please check [nf-core/configs](https://github.com/nf-core/configs#documentation) to see if a custom config file to run nf-core pipelines already exists for your Institute. If so, you can simply use `-profile ` in your command. This will enable either `docker` or `singularity` and set the appropriate execution settings for your local compute environment. -iv. Start running your own analysis! +4. Start running your own analysis! - + -```bash -nextflow run nf-core/cageseq -profile --reads '*_R{1,2}.fastq.gz' --genome GRCh37 -``` + ```bash + nextflow run nf-core/cageseq -profile --input '*_R{1,2}.fastq.gz' --genome GRCh37 + ``` See [usage docs](docs/usage.md) for all of the available options when running the pipeline. ## Documentation -The nf-core/cageseq pipeline comes with documentation about the pipeline, found in the `docs/` directory: - -1. [Installation](https://nf-co.re/usage/installation) -2. Pipeline configuration - * [Local installation](https://nf-co.re/usage/local_installation) - * [Adding your own system config](https://nf-co.re/usage/adding_own_config) - * [Reference genomes](https://nf-co.re/usage/reference_genomes) -3. [Running the pipeline](docs/usage.md) -4. [Output and how to interpret the results](docs/output.md) -5. [Troubleshooting](https://nf-co.re/usage/troubleshooting) +The nf-core/cageseq pipeline comes with documentation about the pipeline which you can read at [https://nf-core/cageseq/docs](https://nf-core/cageseq/docs) or find in the [`docs/` directory](docs). ## Credits -nf-core/cageseq was originally written by Kevin Menden. +nf-core/cageseq was originally written by Kevin Menden, Tristan Kast, Matthias Hörtenhuber. ## Contributions and Support If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). -For further information or help, don't hesitate to get in touch on [Slack](https://nfcore.slack.com/channels/cageseq) (you can join with [this invite](https://nf-co.re/join/slack)). +For further information or help, don't hesitate to get in touch on the [Slack `#cageseq` channel](https://nfcore.slack.com/channels/cageseq) (you can join with [this invite](https://nf-co.re/join/slack)). ## Citation @@ -73,5 +65,5 @@ You can cite the `nf-core` publication as follows: > > Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen. > -> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). +> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). > ReadCube: [Full Access Link](https://rdcu.be/b1GjZ) diff --git a/bin/markdown_to_html.py b/bin/markdown_to_html.py index 57cc426..a26d1ff 100755 --- a/bin/markdown_to_html.py +++ b/bin/markdown_to_html.py @@ -4,33 +4,23 @@ import markdown import os import sys +import io + def convert_markdown(in_fn): - input_md = open(in_fn, mode="r", encoding="utf-8").read() + input_md = io.open(in_fn, mode="r", encoding="utf-8").read() html = markdown.markdown( "[TOC]\n" + input_md, - extensions = [ - 'pymdownx.extra', - 'pymdownx.b64', - 'pymdownx.highlight', - 'pymdownx.emoji', - 'pymdownx.tilde', - 'toc' - ], - extension_configs = { - 'pymdownx.b64': { - 'base_path': os.path.dirname(in_fn) - }, - 'pymdownx.highlight': { - 'noclasses': True - }, - 'toc': { - 'title': 'Table of Contents' - } - } + extensions=["pymdownx.extra", "pymdownx.b64", "pymdownx.highlight", "pymdownx.emoji", "pymdownx.tilde", "toc"], + extension_configs={ + "pymdownx.b64": {"base_path": os.path.dirname(in_fn)}, + "pymdownx.highlight": {"noclasses": True}, + "toc": {"title": "Table of Contents"}, + }, ) return html + def wrap_html(contents): header = """ @@ -83,18 +73,19 @@ def wrap_html(contents): def parse_args(args=None): parser = argparse.ArgumentParser() - parser.add_argument('mdfile', type=argparse.FileType('r'), nargs='?', - help='File to convert. Defaults to stdin.') - parser.add_argument('-o', '--out', type=argparse.FileType('w'), - default=sys.stdout, - help='Output file name. Defaults to stdout.') + parser.add_argument("mdfile", type=argparse.FileType("r"), nargs="?", help="File to convert. Defaults to stdin.") + parser.add_argument( + "-o", "--out", type=argparse.FileType("w"), default=sys.stdout, help="Output file name. Defaults to stdout." + ) return parser.parse_args(args) + def main(args=None): args = parse_args(args) converted_md = convert_markdown(args.mdfile.name) html = wrap_html(converted_md) args.out.write(html) -if __name__ == '__main__': + +if __name__ == "__main__": sys.exit(main()) diff --git a/bin/scrape_software_versions.py b/bin/scrape_software_versions.py index 316ee1c..d6517ba 100755 --- a/bin/scrape_software_versions.py +++ b/bin/scrape_software_versions.py @@ -5,16 +5,16 @@ # TODO nf-core: Add additional regexes for new tools in process get_software_versions regexes = { - 'nf-core/cageseq': ['v_pipeline.txt', r"(\S+)"], - 'Nextflow': ['v_nextflow.txt', r"(\S+)"], - 'FastQC': ['v_fastqc.txt', r"FastQC v(\S+)"], - 'MultiQC': ['v_multiqc.txt', r"multiqc, version (\S+)"], + "nf-core/cageseq": ["v_pipeline.txt", r"(\S+)"], + "Nextflow": ["v_nextflow.txt", r"(\S+)"], + "FastQC": ["v_fastqc.txt", r"FastQC v(\S+)"], + "MultiQC": ["v_multiqc.txt", r"multiqc, version (\S+)"], } results = OrderedDict() -results['nf-core/cageseq'] = 'N/A' -results['Nextflow'] = 'N/A' -results['FastQC'] = 'N/A' -results['MultiQC'] = 'N/A' +results["nf-core/cageseq"] = 'N/A' +results["Nextflow"] = 'N/A' +results["FastQC"] = 'N/A' +results["MultiQC"] = 'N/A' # Search each file using its regex for k, v in regexes.items(): @@ -30,10 +30,11 @@ # Remove software set to false in results for k in list(results): if not results[k]: - del(results[k]) + del results[k] # Dump to YAML -print (''' +print( + """ id: 'software_versions' section_name: 'nf-core/cageseq Software Versions' section_href: 'https://github.com/nf-core/cageseq' @@ -41,12 +42,13 @@ description: 'are collected at run time from the software output.' data: |
-''') -for k,v in results.items(): - print("
{}
{}
".format(k,v)) -print ("
") +""" +) +for k, v in results.items(): + print("
{}
{}
".format(k, v)) +print(" ") # Write out regexes as csv file: -with open('software_versions.csv', 'w') as f: - for k,v in results.items(): - f.write("{}\t{}\n".format(k,v)) +with open("software_versions.csv", "w") as f: + for k, v in results.items(): + f.write("{}\t{}\n".format(k, v)) diff --git a/conf/igenomes.config b/conf/igenomes.config index 2de9242..caeafce 100644 --- a/conf/igenomes.config +++ b/conf/igenomes.config @@ -340,6 +340,7 @@ params { gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" mito_name = "chrM" + macs_gsize = "1.37e9" } 'dm6' { fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" diff --git a/conf/test.config b/conf/test.config index bcc4a22..09b9dda 100644 --- a/conf/test.config +++ b/conf/test.config @@ -19,7 +19,7 @@ params { // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets // TODO nf-core: Give any required params for the test so that command line flags are not needed single_end = false - readPaths = [ + input_paths = [ ['Testdata', ['https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R1.tiny.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R2.tiny.fastq.gz']], ['SRR389222', ['https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub1.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub2.fastq.gz']] ] diff --git a/conf/test_full.config b/conf/test_full.config new file mode 100644 index 0000000..daa74b6 --- /dev/null +++ b/conf/test_full.config @@ -0,0 +1,22 @@ +/* + * ------------------------------------------------- + * Nextflow config file for running full-size tests + * ------------------------------------------------- + * Defines bundled input files and everything required + * to run a full size pipeline test. Use as follows: + * nextflow run nf-core/cageseq -profile test_full, + */ + +params { + config_profile_name = 'Full test profile' + config_profile_description = 'Full test dataset to check pipeline function' + + // Input data for full size test + // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) + // TODO nf-core: Give any required params for the test so that command line flags are not needed + single_end = false + readPaths = [ + ['Testdata', ['https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R1.tiny.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R2.tiny.fastq.gz']], + ['SRR389222', ['https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub1.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub2.fastq.gz']] + ] +} diff --git a/docs/README.md b/docs/README.md index 37cf4c1..672f93f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,12 +1,12 @@ # nf-core/cageseq: Documentation -The nf-core/cageseq documentation is split into the following files: - -1. [Installation](https://nf-co.re/usage/installation) -2. Pipeline configuration - * [Local installation](https://nf-co.re/usage/local_installation) - * [Adding your own system config](https://nf-co.re/usage/adding_own_config) - * [Reference genomes](https://nf-co.re/usage/reference_genomes) -3. [Running the pipeline](usage.md) -4. [Output and how to interpret the results](output.md) -5. [Troubleshooting](https://nf-co.re/usage/troubleshooting) +The nf-core/cageseq documentation is split into the following pages: + + + +* [Usage](usage.md) + * An overview of how the pipeline works, how to run it and a description of all of the different command-line flags. +* [Output](output.md) + * An overview of the different results produced by the pipeline and how to interpret them. + +You can find a lot more documentation about installing, configuring and running nf-core pipelines on the website: [https://nf-co.re](https://nf-co.re) diff --git a/docs/output.md b/docs/output.md index daff790..61bf222 100644 --- a/docs/output.md +++ b/docs/output.md @@ -2,6 +2,8 @@ This document describes the output produced by the pipeline. Most of the plots are taken from the MultiQC report, which summarises results at the end of the pipeline. +The directories listed below will be created in the results directory after the pipeline has finished. All paths are relative to the top-level results directory. + ## Pipeline overview @@ -9,35 +11,47 @@ This document describes the output produced by the pipeline. Most of the plots a The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: -* [FastQC](#fastqc) - read quality control -* [MultiQC](#multiqc) - aggregate report, describing results of the whole pipeline +* [FastQC](#fastqc) - Read quality control +* [MultiQC](#multiqc) - Aggregate report describing results from the whole pipeline +* [Pipeline information](#pipeline-information) - Report metrics generated during the workflow execution ## FastQC -[FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your reads. It provides information about the quality score distribution across your reads, the per base sequence content (%T/A/G/C). You get information about adapter contamination and other overrepresented sequences. +[FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your sequenced reads. It provides information about the quality score distribution across your reads, per base sequence content (%A/T/G/C), adapter contamination and overrepresented sequences. -For further reading and documentation see the [FastQC help](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). +For further reading and documentation see the [FastQC help pages](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). -> **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. To see how your reads look after trimming, look at the FastQC reports in the `trim_galore` directory. +**Output files:** -**Output directory: `results/fastqc`** +* `fastqc/` + * `*_fastqc.html`: FastQC report containing quality metrics for your untrimmed raw fastq files. +* `fastqc/zips/` + * `*_fastqc.zip`: Zip archive containing the FastQC report, tab-delimited data file and plot images. -* `sample_fastqc.html` - * FastQC report, containing quality metrics for your untrimmed raw fastq files -* `zips/sample_fastqc.zip` - * zip file containing the FastQC report, tab-delimited data file and plot images +> **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. ## MultiQC -[MultiQC](http://multiqc.info) is a visualisation tool that generates a single HTML report summarising all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in within the report data directory. +[MultiQC](http://multiqc.info) is a visualization tool that generates a single HTML report summarizing all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in the report data directory. + +The pipeline has special steps which also allow the software versions to be reported in the MultiQC output for future traceability. + +For more information about how to use MultiQC reports, see [https://multiqc.info](https://multiqc.info). + +**Output files:** + +* `multiqc/` + * `multiqc_report.html`: a standalone HTML file that can be viewed in your web browser. + * `multiqc_data/`: directory containing parsed statistics from the different tools used in the pipeline. + * `multiqc_plots/`: directory containing static images from the report in various formats. -The pipeline has special steps which allow the software versions used to be reported in the MultiQC output for future traceability. +## Pipeline information -**Output directory: `results/multiqc`** +[Nextflow](https://www.nextflow.io/docs/latest/tracing.html) provides excellent functionality for generating various reports relevant to the running and execution of the pipeline. This will allow you to troubleshoot errors with the running of the pipeline, and also provide you with other information such as launch commands, run times and resource usage. -* `Project_multiqc_report.html` - * MultiQC report - a standalone HTML file that can be viewed in your web browser -* `Project_multiqc_data/` - * Directory containing parsed statistics from the different tools used in the pipeline +**Output files:** -For more information about how to use MultiQC reports, see [http://multiqc.info](http://multiqc.info) +* `pipeline_info/` + * Reports generated by Nextflow: `execution_report.html`, `execution_timeline.html`, `execution_trace.txt` and `pipeline_dag.dot`/`pipeline_dag.svg`. + * Reports generated by the pipeline: `pipeline_report.html`, `pipeline_report.txt` and `software_versions.csv`. + * Documentation for interpretation of results in HTML format: `results_description.html`. diff --git a/docs/usage.md b/docs/usage.md index 012cd5b..4ef261c 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,62 +1,15 @@ # nf-core/cageseq: Usage -## Table of contents - -* [Table of contents](#table-of-contents) -* [Introduction](#introduction) -* [Running the pipeline](#running-the-pipeline) - * [Updating the pipeline](#updating-the-pipeline) - * [Reproducibility](#reproducibility) -* [Main arguments](#main-arguments) - * [`-profile`](#-profile) - * [`--reads`](#--reads) - * [`--single_end`](#--single_end) -* [Reference genomes](#reference-genomes) - * [`--genome` (using iGenomes)](#--genome-using-igenomes) - * [`--fasta`](#--fasta) - * [`--igenomes_ignore`](#--igenomes_ignore) -* [Job resources](#job-resources) - * [Automatic resubmission](#automatic-resubmission) - * [Custom resource requests](#custom-resource-requests) -* [AWS Batch specific parameters](#aws-batch-specific-parameters) - * [`--awsqueue`](#--awsqueue) - * [`--awsregion`](#--awsregion) - * [`--awscli`](#--awscli) -* [Other command line parameters](#other-command-line-parameters) - * [`--outdir`](#--outdir) - * [`--email`](#--email) - * [`--email_on_fail`](#--email_on_fail) - * [`--max_multiqc_email_size`](#--max_multiqc_email_size) - * [`-name`](#-name) - * [`-resume`](#-resume) - * [`-c`](#-c) - * [`--custom_config_version`](#--custom_config_version) - * [`--custom_config_base`](#--custom_config_base) - * [`--max_memory`](#--max_memory) - * [`--max_time`](#--max_time) - * [`--max_cpus`](#--max_cpus) - * [`--plaintext_email`](#--plaintext_email) - * [`--monochrome_logs`](#--monochrome_logs) - * [`--multiqc_config`](#--multiqc_config) - ## Introduction -Nextflow handles job submissions on SLURM or other environments, and supervises running the jobs. Thus the Nextflow process must run until the pipeline is finished. We recommend that you put the process running in the background through `screen` / `tmux` or similar tool. Alternatively you can run nextflow within a cluster job submitted your job scheduler. - -It is recommended to limit the Nextflow Java virtual machines memory. We recommend adding the following line to your environment (typically in `~/.bashrc` or `~./bash_profile`): - -```bash -NXF_OPTS='-Xms1g -Xmx4g' -``` - - + ## Running the pipeline The typical command for running the pipeline is as follows: ```bash -nextflow run nf-core/cageseq --reads '*_R{1,2}.fastq.gz' -profile docker +nextflow run nf-core/cageseq --input '*_R{1,2}.fastq.gz' -profile docker ``` This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. @@ -86,7 +39,9 @@ First, go to the [nf-core/cageseq releases page](https://github.com/nf-core/cage 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. -## Main arguments +## Core Nextflow arguments + +> **NB:** These options are part of Nextflow and use a _single_ hyphen (pipeline parameters use a double-hyphen). ### `-profile` @@ -104,11 +59,11 @@ They are loaded in sequence, so later profiles can overwrite earlier profiles. If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended. * `docker` - * A generic configuration profile to be used with [Docker](http://docker.com/) - * Pulls software from dockerhub: [`nfcore/cageseq`](http://hub.docker.com/r/nfcore/cageseq/) + * A generic configuration profile to be used with [Docker](https://docker.com/) + * Pulls software from Docker Hub: [`nfcore/cageseq`](https://hub.docker.com/r/nfcore/cageseq/) * `singularity` - * A generic configuration profile to be used with [Singularity](http://singularity.lbl.gov/) - * Pulls software from DockerHub: [`nfcore/cageseq`](http://hub.docker.com/r/nfcore/cageseq/) + * A generic configuration profile to be used with [Singularity](https://sylabs.io/docs/) + * Pulls software from Docker Hub: [`nfcore/cageseq`](https://hub.docker.com/r/nfcore/cageseq/) * `conda` * Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker or Singularity. * A generic configuration profile to be used with [Conda](https://conda.io/docs/) @@ -117,215 +72,50 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof * A profile with a complete configuration for automated testing * Includes links to test data so needs no other parameters - - -### `--reads` - -Use this to specify the location of your input FastQ files. For example: - -```bash ---reads 'path/to/data/sample_*_{1,2}.fastq' -``` - -Please note the following requirements: - -1. The path must be enclosed in quotes -2. The path must have at least one `*` wildcard character -3. When using the pipeline with paired end data, the path must use `{1,2}` notation to specify read pairs. - -If left unspecified, a default pattern is used: `data/*{1,2}.fastq.gz` - -### `--single_end` - -By default, the pipeline expects paired-end data. If you have single-end data, you need to specify `--single_end` on the command line when you launch the pipeline. A normal glob pattern, enclosed in quotation marks, can then be used for `--reads`. For example: - -```bash ---single_end --reads '*.fastq' -``` - -It is not possible to run a mixture of single-end and paired-end files in one run. - -## Reference genomes - -The pipeline config files come bundled with paths to the illumina iGenomes reference index files. If running with docker or AWS, the configuration is set up to use the [AWS-iGenomes](https://ewels.github.io/AWS-iGenomes/) resource. - -### `--genome` (using iGenomes) +### `-resume` -There are 31 different species supported in the iGenomes references. To run the pipeline, you must specify which to use with the `--genome` flag. +Specify this when restarting a pipeline. Nextflow will used cached results from any pipeline steps where the inputs are the same, continuing from where it got to previously. -You can find the keys to specify the genomes in the [iGenomes config file](../conf/igenomes.config). Common genomes that are supported are: +You can also supply a run name to resume a specific run: `-resume [run-name]`. Use the `nextflow log` command to show previous run names. -* Human - * `--genome GRCh37` -* Mouse - * `--genome GRCm38` -* _Drosophila_ - * `--genome BDGP6` -* _S. cerevisiae_ - * `--genome 'R64-1-1'` +### `-c` -> There are numerous others - check the config file for more. +Specify the path to a specific config file (this is a core NextFlow command). See the [nf-core website documentation](https://nf-co.re/usage/configuration) for more information. -Note that you can use the same configuration setup to save sets of reference files for your own use, even if they are not part of the iGenomes resource. See the [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for instructions on where to save such a file. +#### Custom resource requests -The syntax for this reference configuration is as follows: +Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the steps in the pipeline, if the job exits with an error code of `143` (exceeded requested resources) it will automatically resubmit with higher requests (2 x original, then 3 x original). If it still fails after three times then the pipeline is stopped. - +Whilst these default requirements will hopefully work for most people with most data, you may find that you want to customise the compute resources that the pipeline requests. You can do this by creating a custom config file. For example, to give the workflow process `star` 32GB of memory, you could use the following config: ```nextflow -params { - genomes { - 'GRCh37' { - fasta = '' // Used if no star index given - } - // Any number of additional genomes, key is used with --genome +process { + withName: star { + memory = 32.GB } } ``` - - -### `--fasta` - -If you prefer, you can specify the full path to your reference genome when you run the pipeline: - -```bash ---fasta '[path to Fasta reference]' -``` - -### `--igenomes_ignore` - -Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`. - -## Job resources - -### Automatic resubmission - -Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the steps in the pipeline, if the job exits with an error code of `143` (exceeded requested resources) it will automatically resubmit with higher requests (2 x original, then 3 x original). If it still fails after three times then the pipeline is stopped. - -### Custom resource requests - -Wherever process-specific requirements are set in the pipeline, the default value can be changed by creating a custom config file. See the files hosted at [`nf-core/configs`](https://github.com/nf-core/configs/tree/master/conf) for examples. +See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for more information. If you are likely to be running `nf-core` pipelines regularly it may be a good idea to request that your custom config file is uploaded to the `nf-core/configs` git repository. Before you do this please can you test that the config file works with your pipeline of choice using the `-c` parameter (see definition below). You can then create a pull request to the `nf-core/configs` repository with the addition of your config file, associated documentation file (see examples in [`nf-core/configs/docs`](https://github.com/nf-core/configs/tree/master/docs)), and amending [`nfcore_custom.config`](https://github.com/nf-core/configs/blob/master/nfcore_custom.config) to include your custom profile. -If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack). - -## AWS Batch specific parameters - -Running the pipeline on AWS Batch requires a couple of specific parameters to be set according to your AWS Batch configuration. Please use [`-profile awsbatch`](https://github.com/nf-core/configs/blob/master/conf/awsbatch.config) and then specify all of the following parameters. - -### `--awsqueue` - -The JobQueue that you intend to use on AWS Batch. +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). -### `--awsregion` +### Running in the background -The AWS region in which to run your job. Default is set to `eu-west-1` but can be adjusted to your needs. +Nextflow handles job submissions and supervises the running jobs. The Nextflow process must run until the pipeline is finished. -### `--awscli` +The Nextflow `-bg` flag launches Nextflow in the background, detached from your terminal so that the workflow does not stop if you log out of your session. The logs are saved to a file. -The [AWS CLI](https://www.nextflow.io/docs/latest/awscloud.html#aws-cli-installation) path in your custom AMI. Default: `/home/ec2-user/miniconda/bin/aws`. +Alternatively, you can use `screen` / `tmux` or similar tool to create a detached session which you can log back into at a later time. +Some HPC setups also allow you to run nextflow within a cluster job submitted your job scheduler (from where it submits more jobs). -Please make sure to also set the `-w/--work-dir` and `--outdir` parameters to a S3 storage bucket of your choice - you'll get an error message notifying you if you didn't. +#### Nextflow memory requirements -## Other command line parameters - - - -### `--outdir` - -The output directory where the results will be saved. - -### `--email` - -Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run. - -### `--email_on_fail` - -This works exactly as with `--email`, except emails are only sent if the workflow is not successful. - -### `--max_multiqc_email_size` - -Threshold size for MultiQC report to be attached in notification email. If file generated by pipeline exceeds the threshold, it will not be attached (Default: 25MB). - -### `-name` - -Name for the pipeline run. If not specified, Nextflow will automatically generate a random mnemonic. - -This is used in the MultiQC report (if not default) and in the summary HTML / e-mail (always). - -**NB:** Single hyphen (core Nextflow option) - -### `-resume` - -Specify this when restarting a pipeline. Nextflow will used cached results from any pipeline steps where the inputs are the same, continuing from where it got to previously. - -You can also supply a run name to resume a specific run: `-resume [run-name]`. Use the `nextflow log` command to show previous run names. - -**NB:** Single hyphen (core Nextflow option) - -### `-c` - -Specify the path to a specific config file (this is a core NextFlow command). - -**NB:** Single hyphen (core Nextflow option) - -Note - you can use this to override pipeline defaults. - -### `--custom_config_version` - -Provide git commit id for custom Institutional configs hosted at `nf-core/configs`. This was implemented for reproducibility purposes. Default: `master`. - -```bash -## Download and use config file with following git commid id ---custom_config_version d52db660777c4bf36546ddb188ec530c3ada1b96 -``` - -### `--custom_config_base` - -If you're running offline, nextflow will not be able to fetch the institutional config files -from the internet. If you don't need them, then this is not a problem. If you do need them, -you should download the files from the repo and tell nextflow where to find them with the -`custom_config_base` option. For example: +In some cases, the Nextflow Java virtual machines can start to request a large amount of memory. +We recommend adding the following line to your environment to limit this (typically in `~/.bashrc` or `~./bash_profile`): ```bash -## Download and unzip the config files -cd /path/to/my/configs -wget https://github.com/nf-core/configs/archive/master.zip -unzip master.zip - -## Run the pipeline -cd /path/to/my/data -nextflow run /path/to/pipeline/ --custom_config_base /path/to/my/configs/configs-master/ +NXF_OPTS='-Xms1g -Xmx4g' ``` - -> Note that the nf-core/tools helper package has a `download` command to download all required pipeline -> files + singularity containers + institutional configs in one go for you, to make this process easier. - -### `--max_memory` - -Use to set a top-limit for the default memory requirement for each process. -Should be a string in the format integer-unit. eg. `--max_memory '8.GB'` - -### `--max_time` - -Use to set a top-limit for the default time requirement for each process. -Should be a string in the format integer-unit. eg. `--max_time '2.h'` - -### `--max_cpus` - -Use to set a top-limit for the default CPU requirement for each process. -Should be a string in the format integer-unit. eg. `--max_cpus 1` - -### `--plaintext_email` - -Set to receive plain-text e-mails instead of HTML formatted. - -### `--monochrome_logs` - -Set to disable colourful command line output and live life in monochrome. - -### `--multiqc_config` - -Specify a path to a custom MultiQC configuration file. diff --git a/main.nf b/main.nf index fdb3a01..fe988c3 100644 --- a/main.nf +++ b/main.nf @@ -18,12 +18,12 @@ def helpMessage() { The typical command for running the pipeline is as follows: - nextflow run nf-core/cageseq --reads '*_R{1,2}.fastq.gz' -profile docker + nextflow run nf-core/cageseq --input '*_R{1,2}.fastq.gz' -profile docker Mandatory arguments: - --reads [file] Path to input data (must be surrounded with quotes) - -profile [str] Configuration profile to use. Can use multiple (comma separated) - Available: conda, docker, singularity, test, awsbatch, and more + --input [file] Path to input data (must be surrounded with quotes) + -profile [str] Configuration profile to use. Can use multiple (comma separated) + Available: conda, docker, singularity, test, awsbatch, and more Options: --genome [str] Name of iGenomes reference @@ -34,9 +34,10 @@ def helpMessage() { Other options: --outdir [file] The output directory where the results will be saved + --publish_dir_mode [str] Mode for publishing results in the output directory. Available: symlink, rellink, link, copy, copyNoFollow, move (Default: copy) --email [email] Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits --email_on_fail [email] Same as --email, except only send mail if the workflow is not successful - --max_multiqc_email_size [str] Theshold size for MultiQC report to be attached in notification email. If file generated by pipeline exceeds the threshold, it will not be attached (Default: 25MB) + --max_multiqc_email_size [str] Threshold size for MultiQC report to be attached in notification email. If file generated by pipeline exceeds the threshold, it will not be attached (Default: 25MB) -name [str] Name for the pipeline run. If not specified, Nextflow will automatically generate a random mnemonic AWSBatch options: @@ -73,12 +74,13 @@ params.fasta = params.genome ? params.genomes[ params.genome ].fasta ?: false : if (params.fasta) { ch_fasta = file(params.fasta, checkIfExists: true) } // Has the run name been specified by the user? -// this has the bonus effect of catching both -name and --name +// this has the bonus effect of catching both -name and --name custom_runName = params.name if (!(workflow.runName ==~ /[a-z]+_[a-z]+/)) { custom_runName = workflow.runName } +// Check AWS batch settings if (workflow.profile.contains('awsbatch')) { // AWSBatch sanity checking if (!params.awsqueue || !params.awsregion) exit 1, "Specify correct --awsqueue and --awsregion parameters on AWSBatch!" @@ -93,28 +95,29 @@ if (workflow.profile.contains('awsbatch')) { ch_multiqc_config = file("$baseDir/assets/multiqc_config.yaml", checkIfExists: true) ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config, checkIfExists: true) : Channel.empty() ch_output_docs = file("$baseDir/docs/output.md", checkIfExists: true) +ch_output_docs_images = file("$baseDir/docs/images/", checkIfExists: true) /* * Create a channel for input read files */ -if (params.readPaths) { +if (params.input_paths) { if (params.single_end) { Channel - .from(params.readPaths) + .from(params.input_paths) .map { row -> [ row[0], [ file(row[1][0], checkIfExists: true) ] ] } - .ifEmpty { exit 1, "params.readPaths was empty - no input files supplied" } + .ifEmpty { exit 1, "params.input_paths was empty - no input files supplied" } .into { ch_read_files_fastqc; ch_read_files_trimming } } else { Channel - .from(params.readPaths) + .from(params.input_paths) .map { row -> [ row[0], [ file(row[1][0], checkIfExists: true), file(row[1][1], checkIfExists: true) ] ] } - .ifEmpty { exit 1, "params.readPaths was empty - no input files supplied" } + .ifEmpty { exit 1, "params.input_paths was empty - no input files supplied" } .into { ch_read_files_fastqc; ch_read_files_trimming } } } else { Channel - .fromFilePairs(params.reads, size: params.single_end ? 1 : 2) - .ifEmpty { exit 1, "Cannot find any reads matching: ${params.reads}\nNB: Path needs to be enclosed in quotes!\nIf this is single-end data, please specify --single_end on the command line." } + .fromFilePairs(params.input, size: params.single_end ? 1 : 2) + .ifEmpty { exit 1, "Cannot find any reads matching: ${params.input}\nNB: Path needs to be enclosed in quotes!\nIf this is single-end data, please specify --single_end on the command line." } .into { ch_read_files_fastqc; ch_read_files_trimming } } @@ -124,7 +127,7 @@ def summary = [:] if (workflow.revision) summary['Pipeline Release'] = workflow.revision summary['Run Name'] = custom_runName ?: workflow.runName // TODO nf-core: Report custom parameters here -summary['Reads'] = params.reads +summary['Reads'] = params.input summary['Fasta Ref'] = params.fasta summary['Data Type'] = params.single_end ? 'Single-End' : 'Paired-End' summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" @@ -140,9 +143,10 @@ if (workflow.profile.contains('awsbatch')) { summary['AWS CLI'] = params.awscli } summary['Config Profile'] = workflow.profile -if (params.config_profile_description) summary['Config Description'] = params.config_profile_description -if (params.config_profile_contact) summary['Config Contact'] = params.config_profile_contact -if (params.config_profile_url) summary['Config URL'] = params.config_profile_url +if (params.config_profile_description) summary['Config Profile Description'] = params.config_profile_description +if (params.config_profile_contact) summary['Config Profile Contact'] = params.config_profile_contact +if (params.config_profile_url) summary['Config Profile URL'] = params.config_profile_url +summary['Config Files'] = workflow.configFiles.join(', ') if (params.email || params.email_on_fail) { summary['E-mail Address'] = params.email summary['E-mail on failure'] = params.email_on_fail @@ -174,7 +178,7 @@ Channel.from(summary.collect{ [it.key, it.value] }) * Parse software version numbers */ process get_software_versions { - publishDir "${params.outdir}/pipeline_info", mode: 'copy', + publishDir "${params.outdir}/pipeline_info", mode: params.publish_dir_mode, saveAs: { filename -> if (filename.indexOf(".csv") > 0) filename else null @@ -201,7 +205,7 @@ process get_software_versions { process fastqc { tag "$name" label 'process_medium' - publishDir "${params.outdir}/fastqc", mode: 'copy', + publishDir "${params.outdir}/fastqc", mode: params.publish_dir_mode, saveAs: { filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename" } @@ -222,7 +226,7 @@ process fastqc { * STEP 2 - MultiQC */ process multiqc { - publishDir "${params.outdir}/MultiQC", mode: 'copy' + publishDir "${params.outdir}/MultiQC", mode: params.publish_dir_mode input: file (multiqc_config) from ch_multiqc_config @@ -251,10 +255,11 @@ process multiqc { * STEP 3 - Output Description HTML */ process output_documentation { - publishDir "${params.outdir}/pipeline_info", mode: 'copy' + publishDir "${params.outdir}/pipeline_info", mode: params.publish_dir_mode input: file output_docs from ch_output_docs + file images from ch_output_docs_images output: file "results_description.html" @@ -345,7 +350,11 @@ workflow.onComplete { log.info "[nf-core/cageseq] Sent summary e-mail to $email_address (sendmail)" } catch (all) { // Catch failures and try with plaintext - [ 'mail', '-s', subject, email_address ].execute() << email_txt + def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] + if ( mqc_report.size() <= params.max_multiqc_email_size.toBytes() ) { + mail_cmd += [ '-A', mqc_report ] + } + mail_cmd.execute() << email_html log.info "[nf-core/cageseq] Sent summary e-mail to $email_address (mail)" } } diff --git a/nextflow.config b/nextflow.config index 82d3698..e9d9f2f 100644 --- a/nextflow.config +++ b/nextflow.config @@ -11,9 +11,10 @@ params { // Workflow flags // TODO nf-core: Specify your pipeline's command line flags genome = false - reads = "data/*{1,2}.fastq.gz" + input = "data/*{1,2}.fastq.gz" single_end = false outdir = './results' + publish_dir_mode = 'copy' // Boilerplate options name = false @@ -78,9 +79,11 @@ if (!params.igenomes_ignore) { includeConfig 'conf/igenomes.config' } -// Export this variable to prevent local Python libraries from conflicting with those in the container +// Export these variables to prevent local Python/R libraries from conflicting with those in the container env { PYTHONNOUSERSITE = 1 + R_PROFILE_USER = "/.Rprofile" + R_ENVIRON_USER = "/.Renviron" } // Capture exit codes from upstream processes when piping @@ -105,7 +108,7 @@ dag { manifest { name = 'nf-core/cageseq' - author = 'Kevin Menden' + author = 'Kevin Menden, Tristan Kast, Matthias Hörtenhuber' homePage = 'https://github.com/nf-core/cageseq' description = 'CAGE-seq pipeline' mainScript = 'main.nf' diff --git a/nextflow_schema.json b/nextflow_schema.json new file mode 100644 index 0000000..af70554 --- /dev/null +++ b/nextflow_schema.json @@ -0,0 +1,259 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema", + "$id": "https://raw.githubusercontent.com/nf-core/cageseq/master/nextflow_schema.json", + "title": "nf-core/cageseq pipeline parameters", + "description": "CAGE-seq pipeline", + "type": "object", + "definitions": { + "input_output_options": { + "title": "Input/output options", + "type": "object", + "fa_icon": "fas fa-terminal", + "description": "Define where the pipeline should find input data and save output data.", + "required": [ + "input" + ], + "properties": { + "input": { + "type": "string", + "fa_icon": "fas fa-dna", + "description": "Input FastQ files.", + "help_text": "Use this to specify the location of your input FastQ files. For example:\n\n```bash\n--input 'path/to/data/sample_*_{1,2}.fastq'\n```\n\nPlease note the following requirements:\n\n1. The path must be enclosed in quotes\n2. The path must have at least one `*` wildcard character\n3. When using the pipeline with paired end data, the path must use `{1,2}` notation to specify read pairs.\n\nIf left unspecified, a default pattern is used: `data/*{1,2}.fastq.gz`" + }, + "single_end": { + "type": "boolean", + "description": "Specifies that the input is single-end reads.", + "fa_icon": "fas fa-align-center", + "help_text": "By default, the pipeline expects paired-end data. If you have single-end data, you need to specify `--single_end` on the command line when you launch the pipeline. A normal glob pattern, enclosed in quotation marks, can then be used for `--input`. For example:\n\n```bash\n--single_end --input '*.fastq'\n```\n\nIt is not possible to run a mixture of single-end and paired-end files in one run." + }, + "outdir": { + "type": "string", + "description": "The output directory where the results will be saved.", + "default": "./results", + "fa_icon": "fas fa-folder-open" + }, + "email": { + "type": "string", + "description": "Email address for completion summary.", + "fa_icon": "fas fa-envelope", + "help_text": "Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run.", + "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" + } + } + }, + "reference_genome_options": { + "title": "Reference genome options", + "type": "object", + "fa_icon": "fas fa-dna", + "description": "Options for the reference genome indices used to align reads.", + "properties": { + "genome": { + "type": "string", + "description": "Name of iGenomes reference.", + "fa_icon": "fas fa-book", + "help_text": "If using a reference genome configured in the pipeline using iGenomes, use this parameter to give the ID for the reference. This is then used to build the full paths for all required reference genome files e.g. `--genome GRCh38`.\n\nSee the [nf-core website docs](https://nf-co.re/usage/reference_genomes) for more details." + }, + "fasta": { + "type": "string", + "fa_icon": "fas fa-font", + "description": "Path to FASTA genome file.", + "help_text": "If you have no genome reference available, the pipeline can build one using a FASTA file. This requires additional time and resources, so it's better to use a pre-build index if possible." + }, + "igenomes_base": { + "type": "string", + "description": "Directory / URL base for iGenomes references.", + "default": "s3://ngi-igenomes/igenomes/", + "fa_icon": "fas fa-cloud-download-alt", + "hidden": true + }, + "igenomes_ignore": { + "type": "boolean", + "description": "Do not load the iGenomes reference config.", + "fa_icon": "fas fa-ban", + "hidden": true, + "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`." + } + } + }, + "generic_options": { + "title": "Generic options", + "type": "object", + "fa_icon": "fas fa-file-import", + "description": "Less common options for the pipeline, typically set in a config file.", + "help_text": "These options are common to all nf-core pipelines and allow you to customise some of the core preferences for how the pipeline runs.\n\nTypically these options would be set in a Nextflow config file loaded for all pipeline runs, such as `~/.nextflow/config`.", + "properties": { + "help": { + "type": "boolean", + "description": "Display help text.", + "hidden": true, + "fa_icon": "fas fa-question-circle" + }, + "publish_dir_mode": { + "type": "string", + "default": "copy", + "hidden": true, + "description": "Method used to save pipeline results to output directory.", + "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", + "fa_icon": "fas fa-copy", + "enum": [ + "symlink", + "rellink", + "link", + "copy", + "copyNoFollow", + "mov" + ] + }, + "name": { + "type": "string", + "description": "Workflow name.", + "fa_icon": "fas fa-fingerprint", + "hidden": true, + "help_text": "A custom name for the pipeline run. Unlike the core nextflow `-name` option with one hyphen this parameter can be reused multiple times, for example if using `-resume`. Passed through to steps such as MultiQC and used for things like report filenames and titles." + }, + "email_on_fail": { + "type": "string", + "description": "Email address for completion summary, only when pipeline fails.", + "fa_icon": "fas fa-exclamation-triangle", + "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$", + "hidden": true, + "help_text": "This works exactly as with `--email`, except emails are only sent if the workflow is not successful." + }, + "plaintext_email": { + "type": "boolean", + "description": "Send plain-text email instead of HTML.", + "fa_icon": "fas fa-remove-format", + "hidden": true, + "help_text": "Set to receive plain-text e-mails instead of HTML formatted." + }, + "max_multiqc_email_size": { + "type": "string", + "description": "File size limit when attaching MultiQC reports to summary emails.", + "default": "25.MB", + "fa_icon": "fas fa-file-upload", + "hidden": true, + "help_text": "If file generated by pipeline exceeds the threshold, it will not be attached." + }, + "monochrome_logs": { + "type": "boolean", + "description": "Do not use coloured log outputs.", + "fa_icon": "fas fa-palette", + "hidden": true, + "help_text": "Set to disable colourful command line output and live life in monochrome." + }, + "multiqc_config": { + "type": "string", + "description": "Custom config file to supply to MultiQC.", + "fa_icon": "fas fa-cog", + "hidden": true + }, + "tracedir": { + "type": "string", + "description": "Directory to keep pipeline Nextflow logs and reports.", + "default": "${params.outdir}/pipeline_info", + "fa_icon": "fas fa-cogs", + "hidden": true + } + } + }, + "max_job_request_options": { + "title": "Max job request options", + "type": "object", + "fa_icon": "fab fa-acquisitions-incorporated", + "description": "Set the top limit for requested resources for any single job.", + "help_text": "If you are running on a smaller system, a pipeline step requesting more resources than are available may cause the Nextflow to stop the run with an error. These options allow you to cap the maximum resources requested by any single job so that the pipeline will run on your system.\n\nNote that you can not _increase_ the resources requested by any job using these options. For that you will need your own configuration file. See [the nf-core website](https://nf-co.re/usage/configuration) for details.", + "properties": { + "max_cpus": { + "type": "integer", + "description": "Maximum number of CPUs that can be requested for any single job.", + "default": 16, + "fa_icon": "fas fa-microchip", + "hidden": true, + "help_text": "Use to set an upper-limit for the CPU requirement for each process. Should be an integer e.g. `--max_cpus 1`" + }, + "max_memory": { + "type": "string", + "description": "Maximum amount of memory that can be requested for any single job.", + "default": "128.GB", + "fa_icon": "fas fa-memory", + "hidden": true, + "help_text": "Use to set an upper-limit for the memory requirement for each process. Should be a string in the format integer-unit e.g. `--max_memory '8.GB'`" + }, + "max_time": { + "type": "string", + "description": "Maximum amount of time that can be requested for any single job.", + "default": "240.h", + "fa_icon": "far fa-clock", + "hidden": true, + "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" + } + } + }, + "institutional_config_options": { + "title": "Institutional config options", + "type": "object", + "fa_icon": "fas fa-university", + "description": "Parameters used to describe centralised config profiles. These should not be edited.", + "help_text": "The centralised nf-core configuration profiles use a handful of pipeline parameters to describe themselves. This information is then printed to the Nextflow log when you run a pipeline. You should not need to change these values when you run a pipeline.", + "properties": { + "custom_config_version": { + "type": "string", + "description": "Git commit id for Institutional configs.", + "default": "master", + "hidden": true, + "fa_icon": "fas fa-users-cog", + "help_text": "Provide git commit id for custom Institutional configs hosted at `nf-core/configs`. This was implemented for reproducibility purposes. Default: `master`.\n\n```bash\n## Download and use config file with following git commit id\n--custom_config_version d52db660777c4bf36546ddb188ec530c3ada1b96\n```" + }, + "custom_config_base": { + "type": "string", + "description": "Base directory for Institutional configs.", + "default": "https://raw.githubusercontent.com/nf-core/configs/master", + "hidden": true, + "help_text": "If you're running offline, nextflow will not be able to fetch the institutional config files from the internet. If you don't need them, then this is not a problem. If you do need them, you should download the files from the repo and tell nextflow where to find them with the `custom_config_base` option. For example:\n\n```bash\n## Download and unzip the config files\ncd /path/to/my/configs\nwget https://github.com/nf-core/configs/archive/master.zip\nunzip master.zip\n\n## Run the pipeline\ncd /path/to/my/data\nnextflow run /path/to/pipeline/ --custom_config_base /path/to/my/configs/configs-master/\n```\n\n> Note that the nf-core/tools helper package has a `download` command to download all required pipeline files + singularity containers + institutional configs in one go for you, to make this process easier.", + "fa_icon": "fas fa-users-cog" + }, + "hostnames": { + "type": "string", + "description": "Institutional configs hostname.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_description": { + "type": "string", + "description": "Institutional config description.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_contact": { + "type": "string", + "description": "Institutional config contact information.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + }, + "config_profile_url": { + "type": "string", + "description": "Institutional config URL link.", + "hidden": true, + "fa_icon": "fas fa-users-cog" + } + } + } + }, + "allOf": [ + { + "$ref": "#/definitions/input_output_options" + }, + { + "$ref": "#/definitions/reference_genome_options" + }, + { + "$ref": "#/definitions/generic_options" + }, + { + "$ref": "#/definitions/max_job_request_options" + }, + { + "$ref": "#/definitions/institutional_config_options" + } + ] +} From 875e0a96926c00f7bcc78019f214c42031b25d30 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 31 Jul 2020 10:28:57 +0200 Subject: [PATCH 077/107] add images to output.md, prepare for template update --- README.md | 8 ++++---- docs/images/bowtie1_alignment_plot.png | Bin 0 -> 38608 bytes docs/images/cutadapt_plot.png | Bin 0 -> 76474 bytes docs/images/rseqc_read_distribution_plot.png | Bin 0 -> 56481 bytes docs/images/star_alignment_plot.png | Bin 0 -> 102145 bytes docs/usage.md | 14 ++++++++++++++ main.nf | 6 +++--- nextflow.config | 2 +- 8 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 docs/images/bowtie1_alignment_plot.png create mode 100644 docs/images/cutadapt_plot.png create mode 100644 docs/images/rseqc_read_distribution_plot.png create mode 100644 docs/images/star_alignment_plot.png diff --git a/README.md b/README.md index dc24810..0caa726 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Nextflow CAGE-seq analysis pipeline, part of the nf-core community [![Docker](https://img.shields.io/docker/automated/nfcore/cageseq.svg)](https://hub.docker.com/r/nfcore/cageseq) ## Introduction + ___ UNDER DEVELOPMENT @@ -33,12 +34,11 @@ The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool ## Quick Start -i. Install [`nextflow`](https://nf-co.re/usage/installation) - -ii. Install one of [`docker`](https://docs.docker.com/engine/installation/), [`singularity`](https://www.sylabs.io/guides/3.0/user-guide/) or [`conda`](https://conda.io/miniconda.html) +1. Install [`nextflow`](https://nf-co.re/usage/installation) -iii. Download the nf-core/cagesq pipeline and test it on a minimal dataset with a single command +2. Install one of [`docker`](https://docs.docker.com/engine/installation/), [`singularity`](https://www.sylabs.io/guides/3.0/user-guide/) or [`conda`](https://conda.io/miniconda.html) +3. Download the nf-core/cagesq pipeline and test it on a minimal dataset with a single command: ```bash nextflow run nf-core/cageseq -profile test, ``` diff --git a/docs/images/bowtie1_alignment_plot.png b/docs/images/bowtie1_alignment_plot.png new file mode 100644 index 0000000000000000000000000000000000000000..b889d94a35d2d1436d4732fc29a3721bea0e09ff GIT binary patch literal 38608 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 HaPhwY)|C-M literal 0 HcmV?d00001 diff --git a/docs/images/cutadapt_plot.png b/docs/images/cutadapt_plot.png new file mode 100644 index 0000000000000000000000000000000000000000..edbc6a3c74dea5c7619f6a7f79a0961ee48d15d2 GIT binary patch literal 76474 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 z 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

H^t+g3t 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

Ry`gO^ZYx=%Z-_jo{#jbUd~?Me+)DQ0qn za4QA9E;Y(2ifl=+ed*e6>{U631!!Y)UMjvP5&^Td(pH-T4@V}A6wU%6-jU<-*# z<7O0o>h!hO(C5C1#4(Tz+5yb&Y@?~hk!U#5JoJN^0=*84;@?L`%wP8R)1KPWRlS3Q z%`fTf=n2+DZ(PLu2)1_FY~L}pCzP>0DB5nKA%+yAAi$pDvp7+#$9yDR>e+y3-*@&_M}StQX-)YsZ>C5z?| Mo3}Y!+O#+3FI(kXLI3~& literal 0 HcmV?d00001 diff --git a/docs/usage.md b/docs/usage.md index 37cd230..6184dde 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -228,6 +228,20 @@ Sets the minimum amount of reads for paraclu to build a cluster. Default: 20. Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`. +## Ribosomal RNA removal + +If rRNA removal is desired (for example, metatranscriptomics), add the following command line parameters. +--removeRiboRNA + +Instructs to use SortMeRNA to remove reads related to ribosomal RNA (or any patterns found in the sequences defined by --rRNA_database_manifest). +--saveNonRiboRNAReads + +By default, non-rRNA FastQ files will not be saved to the results directory. Specify this flag (or set to true in your config file) to copy these files when complete. +--rRNA_database_manifest + +By default, rRNA databases in github biocore/sortmerna/rRNA_databases are used. Here the path to a text file can be provided that contains paths to fasta files (one per line, no ' or " for file names) that will be used for database creation for SortMeRNA instead of the default ones. You can see an example in the directory assets/rrna-default-dbs.txt. Consequently, similar reads to these sequences will be removed. + + ## Job resources ### Automatic resubmission diff --git a/main.nf b/main.nf index 37c0e73..45b8023 100644 --- a/main.nf +++ b/main.nf @@ -194,11 +194,11 @@ ch_output_docs = file("$baseDir/docs/output.md", checkIfExists: true) * Create a channel for input read files */ -if(params.readPaths){ +if(params.input){ Channel - .from(params.readPaths) + .from(params.input) .map { row -> [ row[0].replaceAll("\\s","_"), file(row[1])] } - .ifEmpty { exit 1, "params.readPaths was empty - no input files supplied" } + .ifEmpty { exit 1, "params.input was empty - no input files supplied" } .into { read_files_fastqc; read_files_trimming } } else { Channel diff --git a/nextflow.config b/nextflow.config index 4a3e5c2..09d5777 100644 --- a/nextflow.config +++ b/nextflow.config @@ -11,7 +11,7 @@ params { // Workflow flags genome = false single_end = false - readPaths = false // Used for test profiles + input = false // Used for test profiles reads = false outdir = './results' From 1cbd66c2e41456872a60377ef23b7dda1e657076 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Fri, 31 Jul 2020 13:19:33 +0200 Subject: [PATCH 078/107] Template update for nf-core/tools version 1.10.2 --- .github/CONTRIBUTING.md | 2 +- .github/workflows/awsfulltest.yml | 2 +- .github/workflows/branch.yml | 1 + .github/workflows/linting.yml | 9 ++++- .github/workflows/push_dockerhub.yml | 53 ++++++++++++++-------------- Dockerfile | 2 +- conf/test_full.config | 2 +- docs/usage.md | 2 +- main.nf | 2 +- 9 files changed, 42 insertions(+), 33 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index f1a6cba..6877c9d 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -46,7 +46,7 @@ These tests are run both with the latest available version of `Nextflow` and als ## Patch -: warning: Only in the unlikely and regretful event of a release happening with a bug. +:warning: Only in the unlikely and regretful event of a release happening with a bug. * On your own fork, make a new branch `patch` based on `upstream/master`. * Fix the bug, and bump version (X.Y.Z+1). diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 5149c40..9fc4e45 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -21,7 +21,7 @@ jobs: run: conda install -c conda-forge awscli - name: Start AWS batch job # TODO nf-core: You can customise AWS full pipeline tests as required - # Add full size test data (but still relatively small datasets for few samples) + # Add full size test data (but still relatively small datasets for few samples) # on the `test_full.config` test runs with only one set of parameters # Then specify `-profile test_full` instead of `-profile test` on the AWS batch command env: diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 50513b0..69400ad 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -17,6 +17,7 @@ jobs: # If the above check failed, post a comment on the PR explaining the failure + # NOTE - this doesn't currently work if the PR is coming from a fork, due to limitations in GitHub actions secrets - name: Post PR comment if: failure() uses: mshick/add-pr-comment@v1 diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index eb66c14..8e8d5bb 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -57,5 +57,12 @@ jobs: GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_PR_COMMIT: ${{ github.event.pull_request.head.sha }} - run: nf-core lint ${GITHUB_WORKSPACE} + run: nf-core -l lint_log.txt lint ${GITHUB_WORKSPACE} + + - name: Upload linting log file artifact + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: linting-log-file + path: lint_log.txt diff --git a/.github/workflows/push_dockerhub.yml b/.github/workflows/push_dockerhub.yml index 912314d..6b771bd 100644 --- a/.github/workflows/push_dockerhub.yml +++ b/.github/workflows/push_dockerhub.yml @@ -8,32 +8,33 @@ on: release: types: [published] -push_dockerhub: - name: Push new Docker image to Docker Hub - runs-on: ubuntu-latest - # Only run for the nf-core repo, for releases and merged PRs - if: ${{ github.repository == 'nf-core/cageseq' }} - env: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKERHUB_PASS: ${{ secrets.DOCKERHUB_PASS }} - steps: - - name: Check out pipeline code - uses: actions/checkout@v2 +jobs: + push_dockerhub: + name: Push new Docker image to Docker Hub + runs-on: ubuntu-latest + # Only run for the nf-core repo, for releases and merged PRs + if: ${{ github.repository == 'nf-core/cageseq' }} + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASS: ${{ secrets.DOCKERHUB_PASS }} + steps: + - name: Check out pipeline code + uses: actions/checkout@v2 - - name: Build new docker image - run: docker build --no-cache . -t nfcore/cageseq:latest + - name: Build new docker image + run: docker build --no-cache . -t nfcore/cageseq:latest - - name: Push Docker image to DockerHub (dev) - if: ${{ github.event_name == 'push' }} - run: | - echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin - docker tag nfcore/cageseq:latest nfcore/cageseq:dev - docker push nfcore/cageseq:dev + - name: Push Docker image to DockerHub (dev) + if: ${{ github.event_name == 'push' }} + run: | + echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin + docker tag nfcore/cageseq:latest nfcore/cageseq:dev + docker push nfcore/cageseq:dev - - name: Push Docker image to DockerHub (release) - if: ${{ github.event_name == 'release' }} - run: | - echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin - docker push nfcore/cageseq:latest - docker tag nfcore/cageseq:latest nfcore/cageseq:${{ github.event.release.tag_name }} - docker push nfcore/cageseq:${{ github.event.release.tag_name }} + - name: Push Docker image to DockerHub (release) + if: ${{ github.event_name == 'release' }} + run: | + echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin + docker push nfcore/cageseq:latest + docker tag nfcore/cageseq:latest nfcore/cageseq:${{ github.event.release.tag_name }} + docker push nfcore/cageseq:${{ github.event.release.tag_name }} diff --git a/Dockerfile b/Dockerfile index e0b3ee2..79bcb8f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM nfcore/base:1.10.1 +FROM nfcore/base:1.10.2 LABEL authors="Kevin Menden, Tristan Kast, Matthias Hörtenhuber" \ description="Docker image containing all software requirements for the nf-core/cageseq pipeline" diff --git a/conf/test_full.config b/conf/test_full.config index daa74b6..93022b9 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -15,7 +15,7 @@ params { // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) // TODO nf-core: Give any required params for the test so that command line flags are not needed single_end = false - readPaths = [ + input_paths = [ ['Testdata', ['https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R1.tiny.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R2.tiny.fastq.gz']], ['SRR389222', ['https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub1.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub2.fastq.gz']] ] diff --git a/docs/usage.md b/docs/usage.md index 4ef261c..e63db4f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -80,7 +80,7 @@ You can also supply a run name to resume a specific run: `-resume [run-name]`. U ### `-c` -Specify the path to a specific config file (this is a core NextFlow command). See the [nf-core website documentation](https://nf-co.re/usage/configuration) for more information. +Specify the path to a specific config file (this is a core Nextflow command). See the [nf-core website documentation](https://nf-co.re/usage/configuration) for more information. #### Custom resource requests diff --git a/main.nf b/main.nf index fe988c3..2acd755 100644 --- a/main.nf +++ b/main.nf @@ -127,7 +127,7 @@ def summary = [:] if (workflow.revision) summary['Pipeline Release'] = workflow.revision summary['Run Name'] = custom_runName ?: workflow.runName // TODO nf-core: Report custom parameters here -summary['Reads'] = params.input +summary['Input'] = params.input summary['Fasta Ref'] = params.fasta summary['Data Type'] = params.single_end ? 'Single-End' : 'Paired-End' summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" From 0c4bbd6a7396ed9d76b3374d2bd061066f714314 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 31 Jul 2020 14:30:54 +0200 Subject: [PATCH 079/107] fix linting errors --- docs/output.md | 57 +++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/docs/output.md b/docs/output.md index 92d7945..ea795aa 100644 --- a/docs/output.md +++ b/docs/output.md @@ -26,7 +26,6 @@ For further reading and documentation see the [FastQC help pages](http://www.bio * `fastqc/zips/` * `*_fastqc.zip`: Zip archive containing the FastQC report, tab-delimited data file and plot images. - ## 2. Trimming [Cutadapt](https://cutadapt.readthedocs.io/en/stable/) finds and removes adapter @@ -41,20 +40,20 @@ All the following trimming process are skipped if `--skip_trimming` is set to tr **Output directory: `results/trimmed`** -- `adapter_trimmed/sample.adapter_trimmed.fastq.gz` - - FastQ file after removal of linkers and EcoP15 site. -- `adapter_trimmed/logs/` - - Trimming report (describes which parameters that were used) -- if `--trim_5g`: - - `g_trimmed/sample.g_trimmed.fastq.gz` - - 5' G-corrected FastQ file - - `g_trimmed/logs/` - - Trimming report (describes which parameters that were used) -- if `--trim_artifacts`: - - `artifacts_trimmed/sample.artifact_trimmed.fastq.gz` - - FastQ file after artifact removal - - `artifacts_trimmed/logs/` - - Trimming report (describes which parameters that were used) +* `adapter_trimmed/sample.adapter_trimmed.fastq.gz` + * FastQ file after removal of linkers and EcoP15 site. +* `adapter_trimmed/logs/` + * Trimming report (describes which parameters that were used) +* if `--trim_5g`: + * `g_trimmed/sample.g_trimmed.fastq.gz` + * 5' G-corrected FastQ file + * `g_trimmed/logs/` + * Trimming report (describes which parameters that were used) +* if `--trim_artifacts`: + * `artifacts_trimmed/sample.artifact_trimmed.fastq.gz` + * FastQ file after artifact removal + * `artifacts_trimmed/logs/` + * Trimming report (describes which parameters that were used) ## 3. Alignment @@ -80,14 +79,14 @@ good samples should have most reads as _aligned_ and few _Not aligned_ reads. **Output directory: `results/STAR`** -- `Sample_Aligned.sortedByCoord.out.bam` - - The aligned BAM file -- `Sample_Log.final.out` - - The STAR alignment report, contains mapping results summary -- `Sample_Log.out` and `Sample_Log.progress.out` - - STAR log files, containing a lot of detailed information about the run. Typically only useful for debugging purposes. -- `Sample_SJ.out.tab` - - Filtered splice junctions detected in the mapping +* `Sample_Aligned.sortedByCoord.out.bam` + * The aligned BAM file +* `Sample_Log.final.out` + * The STAR alignment report, contains mapping results summary +* `Sample_Log.out` and `Sample_Log.progress.out` + * STAR log files, containing a lot of detailed information about the run. Typically only useful for debugging purposes. +* `Sample_SJ.out.tab` + * Filtered splice junctions detected in the mapping ## 5. CTSS generation @@ -96,8 +95,8 @@ unclustered cage defined transcription start sites (CTSS). **Output directory: `results/ctss`** -- `Sample.ctss.bed` - - A BED6 file with the cage defined transcription start sites +* `Sample.ctss.bed` + * A BED6 file with the cage defined transcription start sites ## 4. CTSS clustering @@ -109,8 +108,8 @@ cluster and returns a bed file with the clustered CTSSs. **Output directory: `results/ctss/clusters`** -- `ctss_all_clustered_simplified.bed` - - A BED6 file with the clustered CTSSs and their pooled counts +* `ctss_all_clustered_simplified.bed` + * A BED6 file with the clustered CTSSs and their pooled counts ## 6. Count table generation @@ -119,8 +118,8 @@ summarized in a count table. **Output directory: `results/ctss/`** -- `count_table.tsv`: - - Each column of the count table stands for one sample and each row for one tag cluster. The first row of this table is the header with sample names and the first column contains the tag cluster coordinates. +* `count_table.tsv`: + * Each column of the count table stands for one sample and each row for one tag cluster. The first row of this table is the header with sample names and the first column contains the tag cluster coordinates. ## 7. QC of results From a5b116bac2f7f0032476337a45cb6b0a9f9f9581 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 31 Jul 2020 16:45:37 +0200 Subject: [PATCH 080/107] add more definitions to the schema --- nextflow_schema.json | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index f93b72a..ccf87cc 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -13,14 +13,17 @@ "fa_icon": "far fa-trash-alt", "properties": { "remove_ribo_RNA": { - "type": "boolean" + "type": "boolean", + "fa_icon": "far fa-trash-alt" }, "save_nonrRNA_reads": { - "type": "boolean" + "type": "boolean", + "fa_icon": "far fa-save" }, "rRNA_database_manifest": { "type": "string", - "default": "$baseDir/assets/rrna-db-defaults.txt" + "default": "$baseDir/assets/rrna-db-defaults.txt", + "fa_icon": "fas fa-database" } } }, @@ -33,21 +36,21 @@ "properties": { "skip_trimming": { "type": "boolean", - "fa_icon": "fas fa-cut" + "fa_icon": "fas fa-fast-forward" }, "save_trimmed": { "type": "boolean", - "fa_icon": "fas fa-cut" + "fa_icon": "far fa-save" }, "trim_ecop": { "type": "boolean", "fa_icon": "fas fa-cut", - "description": "Cut the enzyme binding site at the 5' end?" + "description": "Set to cut the enzyme binding site at the 5' end" }, "trim_linker": { "type": "boolean", "fa_icon": "fas fa-cut", - "description": "Cut the linker at the 3' end?" + "description": "Select to cut the linker at the 3' end?" }, "trim_5g": { "type": "boolean", @@ -62,23 +65,26 @@ "ecoSite": { "type": "string", "default": "CAGCAG", - "description": "Sequence of the ecoP15 site", + "description": "Sequence of the ecoP15 site at the 5' end", "fa_icon": "far fa-hand-scissors" }, "linkerSeq": { "type": "string", "default": "TCGTATGCCGTCTTC", - "fa_icon": "fas fa-link" + "fa_icon": "fas fa-link", + "description": "Sequence of the linker at the 3' end" }, "artifacts_5end": { "type": "string", "default": "$baseDir/assets/artifacts_5end.fasta", - "fa_icon": "far fa-hand-scissors" + "fa_icon": "far fa-hand-scissors", + "description": "Path to 5' end artifacts" }, "artifacts_3end": { "type": "string", "default": "$baseDir/assets/artifacts_3end.fasta", - "fa_icon": "far fa-hand-scissors" + "fa_icon": "far fa-hand-scissors", + "description": "Path to 3' end artifacts" } } }, From 647ae2f09aed23528a968bffc45073f9334b4d12 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 7 Aug 2020 16:51:07 +0200 Subject: [PATCH 081/107] add skipping parameters for the main processes --- main.nf | 711 +++++++++++++++++++++---------------------- nextflow.config | 13 +- nextflow_schema.json | 291 ++++++++++-------- 3 files changed, 523 insertions(+), 492 deletions(-) diff --git a/main.nf b/main.nf index 9184ca5..51bf0f0 100644 --- a/main.nf +++ b/main.nf @@ -22,12 +22,11 @@ def helpMessage() { Mandatory arguments: --input [file] Path to input data (must be surrounded with quotes) - -profile [str] Configuration profile to use. Can use multiple (comma separated) - Available: conda, docker, singularity, test, awsbatch, and more + -profile [str] Configuration profile to use. Can use multiple (comma separated) + Available: docker, singularity, conda, test, awsbatch, and more Trimming: - --skip_trimming [bool] Set to true to skip all file trimming steps - --save_trimmed Set to true to Save trimmed FastQ files + --save_trimmed [bool] Set to true to Save trimmed FastQ files --trim_ecop [bool] Set to false to not trim the EcoP site --trim_linker [bool] Set to false to not trim the linker --trim_5g [bool] Set to false to not trim the additonal G at the 5' end @@ -53,7 +52,17 @@ def helpMessage() { --tpm_cluster_threshold [int] Threshold for expression count of ctss considered in paraclu clustering Output: - --bigwig [bool] Set to true to get the ctss files also as bigwigs + --bigwig [bool] Set this option to get besides ctss files in bed-format also in the bigwig-format + + Skipping options: + --skip_initial_fastqc [bool] Skip FastQC run on input reads + --skip_trimming [bool] Skip all trimming steps + --skip_trimming_fastqc [bool] Skip FastQC run on trimmed reads + --skip_alignment [bool] Skip alignment step + --skip_samtools_stats [bool] Skip samtools stats QC step of aligned reads + --skip_ctss_generation [bool] Skip steps generating CTSS files including clustering, bed/bigwig and count table output generation + --skip_ctss_qc [bool] Skip running RSeQC's read distribution QC step on the clustered CTSS + Other options: --outdir [file] The output directory where the results will be saved --publish_dir_mode [str] Mode for publishing results in the output directory. Available: symlink, rellink, link, copy, copyNoFollow, move (Default: copy) @@ -89,9 +98,6 @@ params.bowtie_index = params.genome ? params.genomes[ params.genome ].bowtie ?: params.fasta = params.genome ? params.genomes[ params.genome ].fasta ?: false : false if (params.fasta) { ch_fasta = file(params.fasta, checkIfExists: true) } params.gtf = params.genome ? params.genomes[ params.genome ].gtf ?: false : false -//params.artifacts_5end = params.artifacts_5end ? params.artifacts_5end[ params.artifacts_5end ].fasta ?: false : false -//params.artifacts_3end = params.artifacts_3end ? params.artifacts_3end[ params.artifacts_3end ].fasta ?: false : false - // Get rRNA databases // Default is set to bundled DB list in `assets/rrna-db-defaults.txt` @@ -200,12 +206,12 @@ if (params.input_paths) { .from(params.input_paths) .map { row -> [ row[0].replaceAll("\\s","_"), file(row[1])] } .ifEmpty { exit 1, "params.input was empty - no input files supplied" } - .into { ch_read_files_fastqc; ch_read_files_trimming } + .into { ch_read_files_fastqc; read_files_trimming } } else { Channel .fromFilePairs( params.input ) .ifEmpty { exit 1, "Cannot find any reads matching: ${params.reads}\nNB: Path needs to be enclosed in quotes!\nNB: Path requires at least one * wildcard!\n" } - .into { ch_read_files_fastqc; ch_read_files_trimming } + .into { ch_read_files_fastqc; read_files_trimming } } @@ -215,27 +221,39 @@ def summary = [:] if (workflow.revision) summary['Pipeline Release'] = workflow.revision summary['Run Name'] = custom_runName ?: workflow.runName summary['Input'] = params.input -if (params.aligner == 'star') { - summary['Aligner'] = "STAR" - if (params.star_index){summary['STAR Index'] = params.star_index} - else if (params.fasta){summary['Fasta Ref'] = params.fasta} -} else if (params.aligner == 'bowtie1') { - summary['Aligner'] = "bowtie" - if (params.bowtie_index) summary['bowtie Index'] = params.bowtie_index - else if (params.fasta) summary['Fasta Ref'] = params.fasta -} +if (params.skip_initial_fastqc) summary['Skip Initial FastQC'] = 'Yes' summary['Data Type'] = params.single_end ? 'Single-End' : 'Paired-End' -if(params.artifacts_5end){ summary["5' artifacts"] = params.artifacts_5end} -if(params.artifacts_3end){ summary["3' artifacts"] = params.artifacts_3end} -summary['trim_ecop'] = params.trim_ecop -summary['trim_linker'] = params.trim_linker -summary['trim_5g'] = params.trim_5g -summary['trim_artifacts'] = params.trim_artifacts -summary['EcoSite'] = params.ecoSite -summary['LinkerSeq'] = params.linkerSeq +if (params.artifacts_5end) summary["5' artifacts"] = params.artifacts_5end +if (params.artifacts_3end) summary["3' artifacts"] = params.artifacts_3end +if (params.skip_trimming) {summary['Skip Trimming'] = 'Yes'} +else{ + summary['trim_ecop'] = params.trim_ecop + summary['trim_linker'] = params.trim_linker + summary['trim_5g'] = params.trim_5g + summary['trim_artifacts'] = params.trim_artifacts + summary['EcoSite'] = params.ecoSite + summary['LinkerSeq'] = params.linkerSeq +} summary['Remove rRNA'] = params.remove_ribo_RNA -summary['Min. cluster'] = params.min_cluster -summary['Cluster Threshold']= params.tpm_cluster_threshold +if (params.skip_trimming_fastqc) summary['Skip Trimming FastQC'] = 'Yes' +if (params.skip_alignment){summary['Skip Alignment'] = 'Yes'} +else { + if (params.aligner == 'star') { + summary['Aligner'] = "STAR" + if (params.star_index){summary['STAR Index'] = params.star_index} + else if (params.fasta){summary['Fasta Ref'] = params.fasta} + } else if (params.aligner == 'bowtie1') { + summary['Aligner'] = "bowtie" + if (params.bowtie_index) summary['bowtie Index'] = params.bowtie_index + else if (params.fasta) summary['Fasta Ref'] = params.fasta + } +} +if(params.skip_ctss_generation) {summary['Skip CTSS generation'] = 'Yes'} +else{ + summary['Min. cluster'] = params.min_cluster + summary['Cluster Threshold']= params.tpm_cluster_threshold +} +if(params.skip_ctss_qc) {summary['Skip CTSS QC'] = 'Yes'} summary['Save Reference'] = params.saveReference summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" if (workflow.containerEngine) summary['Container'] = "$workflow.containerEngine - $workflow.container" @@ -338,37 +356,40 @@ process get_chrom_sizes{ /* * STEP 1 - FastQC */ -process fastqc { - tag "$sample_name" - label 'process_medium' - publishDir "${params.outdir}/fastqc", mode: params.publish_dir_mode, - saveAs: { filename -> - filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename" - } +if(!params.skip_initial_fastqc){ + process fastqc { + tag "$sample_name" + label 'process_medium' + publishDir "${params.outdir}/fastqc", mode: params.publish_dir_mode, + saveAs: { filename -> + filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename" + } - input: - set val(sample_name), file(reads) from ch_read_files_fastqc + input: + set val(sample_name), file(reads) from ch_read_files_fastqc - output: - file "*_fastqc.{zip,html}" into ch_fastqc_results + output: + file "*_fastqc.{zip,html}" into fastqc_results - script: - """ - fastqc --quiet --threads $task.cpus $reads - """ + script: + """ + fastqc --quiet --threads $task.cpus $reads + """ + } +} else { + fastqc_results = Channel.empty() } - /* * STEP 2 - Build STAR index */ -if(params.aligner == 'star' && !params.star_index && params.fasta){ +if(params.aligner == 'star' && !params.star_index && params.fasta && !params.skip_alignment){ process makeSTARindex { label 'high_memory' tag "${fasta.baseName}" publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, - saveAs: { params.saveReference ? it : null }, mode: 'copy' + saveAs: { params.saveReference ? it : null }, mode: params.publish_dir_mode input: file fasta from fasta_star_index @@ -395,11 +416,11 @@ if(params.aligner == 'star' && !params.star_index && params.fasta){ } } -if(params.aligner == 'bowtie1' && !params.bowtie_index && params.fasta){ +if(params.aligner == 'bowtie1' && !params.bowtie_index && params.fasta && !params.skip_alignment){ process makeBowtieindex { tag "${fasta.baseName}" publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, - saveAs: { params.saveReference ? it : null }, mode: 'copy' + saveAs: { params.saveReference ? it : null }, mode: params.publish_dir_mode input: file fasta from fasta_bowtie_index @@ -411,11 +432,7 @@ if(params.aligner == 'bowtie1' && !params.bowtie_index && params.fasta){ script: """ - - bowtie-build --threads ${task.cpus} ${fasta} ${fasta.baseName}.index - - """ } } @@ -424,43 +441,10 @@ if(params.aligner == 'bowtie1' && !params.bowtie_index && params.fasta){ * STEP 3 - Cut Enzyme binding site at 5' and linker at 3' */ - // if (!params.skip_trimming) { - // process trim_galore { - // label 'low_memory' - // tag "$sample_name" - // publishDir "${params.outdir}/trim_galore", mode: "${params.publish_dir_mode}", - // saveAs: {filename -> - // if (filename.indexOf("_fastqc") > 0) "fastqc/$filename" - // else if (filename.indexOf("trimming_report.txt") > 0) "logs/$filename" - // else null - // } - // - // input: - // set val(sample_name), file(reads) from ch_read_files_trimming - // - // output: - // set val(sample_name), file("*fq.gz") into trimmed_reads_trim_5g - // file "*trimming_report.txt" into trimgalore_results - // file "*_fastqc.{zip,html}" into trimgalore_fastqc_reports - // - // script: - // c_r1 = clip_r1 > 0 ? "--clip_r1 ${clip_r1}" : '6' - // tpc_r1 = three_prime_clip_r1 > 0 ? "--three_prime_clip_r1 ${three_prime_clip_r1}" : '' - // nextseq = params.trim_nextseq > 0 ? "--nextseq ${params.trim_nextseq}" : '' - // """ - // trim_galore --fastqc --gzip --cores ${task.cpu} $c_r1 $tpc_r1 $nextseq $reads - // """ - // } - // }else{ - // raw_reads_trimgalore - // .set {trimgalore_reads} - // trimgalore_results = Channel.empty() - // } - if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ process trim_adapters { tag "$sample_name" - publishDir "${params.outdir}/trimmed/adapter_trimmed", mode: 'copy', + publishDir "${params.outdir}/trimmed/adapter_trimmed", mode: params.publish_dir_mode, saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" else if (params.save_trimmed) "$filename" @@ -468,7 +452,7 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ } input: - set val(sample_name), file(reads) from ch_read_files_trimming + set val(sample_name), file(reads) from read_files_trimming output: set val(sample_name), file("*.fastq.gz") into trimmed_reads_trim_5g @@ -527,7 +511,7 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ } } } else { - ch_read_files_trimming.set{ trimmed_reads_trim_5g } + read_files_trimming.set{ trimmed_reads_trim_5g } cutadapt_results = Channel.empty() } @@ -537,7 +521,7 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ if (params.trim_5g && !params.skip_trimming){ process trim_5g{ tag "$sample_name" - publishDir "${params.outdir}/trimmed/g_trimmed", mode: 'copy', + publishDir "${params.outdir}/trimmed/g_trimmed", mode: params.publish_dir_mode, saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" else if (params.save_trimmed) "$filename" @@ -571,7 +555,7 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ if (params.trim_artifacts && !params.skip_trimming){ process trim_artifacts { tag "$sample_name" - publishDir "${params.outdir}/trimmed/artifacts_trimmed", mode: 'copy', + publishDir "${params.outdir}/trimmed/artifacts_trimmed", mode: params.publish_dir_mode, saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" else if (params.save_trimmed) "$filename" @@ -599,361 +583,357 @@ if (params.trim_artifacts && !params.skip_trimming){ > ${reads.baseName}.artifacts_trimming.output.txt """ } - further_processed_reads.into{further_processed_reads_fastqc; further_processed_reads_sortmerna } + further_processed_reads.set{further_processed_reads_sortmerna} } else{ - processed_reads.into{further_processed_reads_fastqc; further_processed_reads_sortmerna} + processed_reads.set{further_processed_reads_sortmerna} artifact_cutting_results = Channel.empty() } -// Post trimming QC, only needed if some trimming has been done -process trimmed_fastqc { +/* + * STEP 2+ - SortMeRNA - remove rRNA sequences on request + */ +if (params.remove_ribo_RNA) { + process sortmerna { + label 'high_memory' tag "$sample_name" - publishDir "${params.outdir}/trimmed/fastqc", mode: 'copy', - saveAs: {filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename"} + publishDir "${params.outdir}/SortMeRNA", mode: params.publish_dir_mode, + saveAs: {filename -> + if (filename.indexOf("_rRNA_report.txt") > 0) "logs/$filename" + else if (params.save_nonrRNA_reads) "reads/$filename" + else null + } input: - set val(sample_name), file(reads) from further_processed_reads_fastqc + set val(sample_name), file(reads) from further_processed_reads_sortmerna + file(fasta) from fasta_sortmerna.collect() output: - path "*_fastqc.{zip,html}" into trimmed_fastqc_results + set val(sample_name), file("*.fq.gz") into further_processed_reads_alignment, further_processed_reads_fastqc; + file "*_rRNA_report.txt" into sortmerna_logs - when: - (params.trim_ecop || params.trim_linker || params.trim_5g || params.trim_artifacts) && !params.skip_trimming script: - """ - fastqc -q $reads - """ + //concatenate reference files: ${db_fasta},${db_name}:${db_fasta},${db_name}:... + def Refs = "" + for (i=0; i ${sample_name}.fq.gz + mv rRNA-reads.log ${sample_name}_rRNA_report.txt + """ + } +} else { + further_processed_reads_sortmerna.into { further_processed_reads_alignment; further_processed_reads_fastqc } + sortmerna_logs = Channel.empty() } -/* - * STEP 2+ - SortMeRNA - remove rRNA sequences on request - */ -if (params.remove_ribo_RNA) { - // process sortmerna_index { - // label 'low_memory' - // tag "${fasta.baseName}" - // - // input: - // file(fasta) from fasta_sortmerna - // - // output: - // val("${fasta.baseName}") into sortmerna_db_name - // file("$fasta") into fasta_sortmerna_db - // file("${fasta.baseName}*") into sortmerna_db - // - // script: - // """ - // indexdb_rna --ref $fasta,${fasta.baseName} -m 3072 -v - // """ - // } - - process sortmerna { - label 'high_memory' +// Post trimming QC, only needed if some trimming has been done +if(!params.skip_trimming_fastqc){ + process trimmed_fastqc { tag "$sample_name" - publishDir "${params.outdir}/SortMeRNA", mode: "copy", - saveAs: {filename -> - if (filename.indexOf("_rRNA_report.txt") > 0) "logs/$filename" - else if (params.save_nonrRNA_reads) "reads/$filename" - else null - } + publishDir "${params.outdir}/trimmed/fastqc", mode: params.publish_dir_mode, + saveAs: {filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename"} input: - set val(sample_name), file(reads) from further_processed_reads_sortmerna - file(fasta) from fasta_sortmerna.collect() + set val(sample_name), file(reads) from further_processed_reads_fastqc output: - set val(sample_name), file("*.fq.gz") into further_processed_reads_star, further_processed_reads_bowtie; - file "*_rRNA_report.txt" into sortmerna_logs - + path "*_fastqc.{zip,html}" into trimmed_fastqc_results + when: + (params.trim_ecop || params.trim_linker || params.trim_5g || params.trim_artifacts) && !params.skip_trimming script: - //concatenate reference files: ${db_fasta},${db_name}:${db_fasta},${db_name}:... - def Refs = "" - for (i=0; i ${sample_name}.fq.gz - mv rRNA-reads.log ${sample_name}_rRNA_report.txt - """ + """ + fastqc -q $reads + """ } } else { - further_processed_reads_sortmerna - .into {further_processed_reads_star; further_processed_reads_bowtie;} - sortmerna_logs = Channel.empty() - + trimmed_fastqc_results = Channel.empty() } /** * STEP 7 - STAR alignment */ -further_processed_reads_star = further_processed_reads_star.dump(tag:"star") -if (params.aligner == 'star') { - process star { +if(!params.skip_alignment){ + if (params.aligner == 'star') { + process star { + label 'high_memory' + tag "$sample_name" + publishDir "${params.outdir}/STAR", mode: params.publish_dir_mode, + saveAs: {filename -> + if (filename.indexOf(".bam") == -1) "logs/$filename" + else filename } + + input: + set val(sample_name), file(reads) from further_processed_reads_alignment + file index from star_index.collect() + file gtf from gtf_star.collect() + + output: + set val(sample_name), file("*.bam") into star_aligned + file "*.out" into alignment_logs + file "*SJ.out.tab" + + + script: + + // prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ + + """ + STAR --genomeDir $index \\ + --sjdbGTFfile $gtf \\ + --readFilesIn $reads \\ + --runThreadN ${task.cpus} \\ + --outSAMtype BAM SortedByCoordinate \\ + --outFilterScoreMinOverLread 0 --outFilterMatchNminOverLread 0 \\ + --seedSearchStartLmax 20 \\ + --outFilterMismatchNmax 1 \\ + --readFilesCommand zcat \\ + --runDirPerm All_RWX \\ + --outFileNamePrefix $sample_name \\ + --outFilterMultimapNmax 1 + """ + + } + + star_aligned.into { bam_stats; bam_aligned } + } else{ + alignment_logs = Channel.empty() + } + if (params.aligner == 'bowtie1'){ + process bowtie { label 'high_memory' tag "$sample_name" - publishDir "${params.outdir}/STAR", mode: 'copy', + publishDir "${params.outdir}/bowtie", mode: params.publish_dir_mode, saveAs: {filename -> if (filename.indexOf(".bam") == -1) "logs/$filename" else filename } input: - set val(sample_name), file(reads) from further_processed_reads_star - file index from star_index.collect() - file gtf from gtf_star.collect() + set val(sample_name), file(reads) from further_processed_reads_alignment + file index_array from bowtie_index.collect() output: - set val(sample_name), file("*.bam") into star_aligned - file "*.out" into star_alignment_logs - file "*SJ.out.tab" + set val(sample_name), file("*.bam") into bam_stats, bam_aligned + file "*.out" into alignment_logs script: // prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ - + index = index_array[0].baseName - ~/.\d$/ """ - STAR --genomeDir $index \\ - --sjdbGTFfile $gtf \\ - --readFilesIn $reads \\ - --runThreadN ${task.cpus} \\ - --outSAMtype BAM SortedByCoordinate \\ - --outFilterScoreMinOverLread 0 --outFilterMatchNminOverLread 0 \\ - --seedSearchStartLmax 20 \\ - --outFilterMismatchNmax 1 \\ - --readFilesCommand zcat \\ - --runDirPerm All_RWX \\ - --outFileNamePrefix $sample_name \\ - --outFilterMultimapNmax 1 + bowtie --sam \\ + -m 1 \\ + --best \\ + --strata \\ + -k 1 \\ + --tryhard \\ + --threads ${task.cpus} \\ + --phred33-quals \\ + --chunkmbs 64 \\ + --seedmms 2 \\ + --seedlen 20 \\ + --maqerr 70 \\ + ${index} \\ + -q ${reads} \\ + --un ${reads.baseName}.unAl > ${sample_name}.sam 2> ${sample_name}.out + + samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${sample_name}.sam """ } + }else{ + alignment_logs= Channel.empty() + } +} else { + further_processed_reads_sortmerna.set{further_processed_reads_alignment} + alignment_logs = Channel.empty() - star_aligned.into { bam_stats; bam_aligned } -} else{ - star_alignment_logs = Channel.empty() -} -if (params.aligner == 'bowtie1'){ -process bowtie { - label 'high_memory' - tag "$sample_name" - publishDir "${params.outdir}/bowtie", mode: 'copy', - saveAs: {filename -> - if (filename.indexOf(".bam") == -1) "logs/$filename" - else filename } - - input: - set val(sample_name), file(reads) from further_processed_reads_bowtie - file index_array from bowtie_index.collect() - - output: - set val(sample_name), file("*.bam") into bam_stats, bam_aligned - file "*.out" into bowtie_alignment_logs - - - script: - - // prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ - index = index_array[0].baseName - ~/.\d$/ - """ - bowtie --sam \\ - -m 1 \\ - --best \\ - --strata \\ - -k 1 \\ - --tryhard \\ - --threads ${task.cpus} \\ - --phred33-quals \\ - --chunkmbs 64 \\ - --seedmms 2 \\ - --seedlen 20 \\ - --maqerr 70 \\ - ${index} \\ - -q ${reads} \\ - --un ${reads.baseName}.unAl > ${sample_name}.sam 2> ${sample_name}.out - - samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${sample_name}.sam - """ - -} -}else{ - bowtie_alignment_logs= Channel.empty() -} - -process samtools_stats { - tag "$sample_name" - label 'process_medium' - - input: - set val(sample_name), file(bam_count) from bam_stats - - output: - file "*.{flagstat,idxstats,stats}" into bam_flagstat_mqc - - script: - """ - samtools idxstats $bam_count > ${bam_count}.idxstats - """ -} - -/** - * STEP 8 - Get CTSS files - */ -process get_ctss { - tag "$sample_name" - publishDir "${params.outdir}/ctss", mode: 'copy' - publishDir "${params.outdir}/ctss", mode: 'copy', - saveAs: {filename -> - if (filename.indexOf(".bed") != -1) "bed/$filename" - else if (filename.indexOf(".bw") != -1) "bigwig/$filename" - else filename } - - input: - set val(sample_name), file(bam_count) from bam_aligned - - output: - set val(sample_name), file("*.ctss.bed") into (ctss_samples,ctss_bw) - file("*.ctss.bed") into (ctss_counts, ctss_counts_qc) - - shell: - ''' - make_ctss.sh -q 20 -i !{bam_count.baseName} -n !{sample_name} - - ''' } -if(params.bigwig){ - process make_bigwig{ +if(!params.skip_samtools_stats){ + process samtools_stats { tag "$sample_name" - publishDir "${params.outdir}/ctss/bigwig", mode: 'copy' + label 'process_medium' input: - set val(sample_name), file(ctss_file) from ctss_bw - file chrom_sizes from chrom_sizes_bw + set val(sample_name), file(bam_count) from bam_stats output: - file("*.ctss.bw") - // file("*.ctss.bw") into (ctss_counts, ctss_counts_qc) + file "*.{flagstat,idxstats,stats}" into bam_flagstat_mqc + script: """ - bedtools genomecov -bg -i ${sample_name}.ctss.bed -g ${chrom_sizes} > ${sample_name}.bedgraph - sort -k1,1 -k2,2n ${sample_name}.bedgraph > ${sample_name}_sorted.bedgraph - bedGraphToBigWig ${sample_name}_sorted.bedgraph ${chrom_sizes} ${sample_name}.ctss.bw + samtools idxstats $bam_count > ${bam_count}.idxstats """ } +} else { + bam_flagstat_mqc = Channel.empty() } + /** - * STEP 9 - Cluster CTSS files + * STEP 8 - Get CTSS files */ -ctss_counts = ctss_counts.collect().dump(tag:"ctss_counts") -process cluster_ctss { - label "high_memory" - - publishDir "${params.outdir}/ctss/clusters", mode: 'copy' +if(!params.skip_ctss_generation){ + process get_ctss { + tag "$sample_name" + publishDir "${params.outdir}/ctss", mode: params.publish_dir_mode + publishDir "${params.outdir}/ctss", mode: params.publish_dir_mode, + saveAs: {filename -> + if (filename.indexOf(".bed") != -1) "bed/$filename" + else if (filename.indexOf(".bw") != -1) "bigwig/$filename" + else filename } - input: - file ctss from ctss_counts.collect() + input: + set val(sample_name), file(bam_count) from bam_aligned - output: - file "*.bed" into ctss_clusters + output: + set val(sample_name), file("*.ctss.bed") into (ctss_samples,ctss_bw) + file("*.ctss.bed") into (ctss_counts, ctss_counts_qc) + shell: + ''' + make_ctss.sh -q 20 -i !{bam_count.baseName} -n !{sample_name} - shell: - ''' - process_ctss.sh -t !{params.tpm_cluster_threshold} !{ctss} + ''' + } + if(params.bigwig){ + process make_bigwig{ + tag "$sample_name" + publishDir "${params.outdir}/ctss/bigwig", mode: params.publish_dir_mode + + input: + set val(sample_name), file(ctss_file) from ctss_bw + file chrom_sizes from chrom_sizes_bw + + output: + file("*.ctss.bw") + script: + """ + bedtools genomecov -bg -i ${sample_name}.ctss.bed -g ${chrom_sizes} > ${sample_name}.bedgraph + sort -k1,1 -k2,2n ${sample_name}.bedgraph > ${sample_name}_sorted.bedgraph + bedGraphToBigWig ${sample_name}_sorted.bedgraph ${chrom_sizes} ${sample_name}.ctss.bw + """ + } + } + /** + * STEP 9 - Cluster CTSS files + */ + ctss_counts = ctss_counts.collect().dump(tag:"ctss_counts") + process cluster_ctss { + label "high_memory" - paraclu !{params.min_cluster} "ctss_all_pos_4Ps" > "ctss_all_pos_clustered" - paraclu !{params.min_cluster} "ctss_all_neg_4Ps" > "ctss_allneg_clustered" + publishDir "${params.outdir}/ctss/clusters", mode: params.publish_dir_mode - paraclu-cut.sh "ctss_all_pos_clustered" > "ctss_all_pos_clustered_simplified" - paraclu-cut.sh "ctss_all_neg_clustered" > "ctss_all_neg_clustered_simplified" + input: + file ctss from ctss_counts.collect() - cat "ctss_all_pos_clustered_simplified" "ctss_all_neg_clustered_simplified" > "ctss_all_clustered_simplified" - awk -F '\t' '{print $1"\t"$3"\t"$4"\t"$1":"$3".."$4","$2"\t"$6"\t"$2}' "ctss_all_clustered_simplified" > "ctss_all_clustered_simplified.bed" - ''' -} + output: + file "*.bed" into ctss_clusters + shell: + ''' + process_ctss.sh -t !{params.tpm_cluster_threshold} !{ctss} - /* - * STEP 11 - Generate count files - */ - process generate_counts { - tag "${sample_name}" - // publishDir "${params.outdir}/ctss/", mode: 'copy' + paraclu !{params.min_cluster} "ctss_all_pos_4Ps" > "ctss_all_pos_clustered" + paraclu !{params.min_cluster} "ctss_all_neg_4Ps" > "ctss_allneg_clustered" - input: - set val(sample_name), file(ctss) from ctss_samples - file clusters from ctss_clusters.collect() + paraclu-cut.sh "ctss_all_pos_clustered" > "ctss_all_pos_clustered_simplified" + paraclu-cut.sh "ctss_all_neg_clustered" > "ctss_all_neg_clustered_simplified" - output: - file "*.txt" into count_files - file "*.bed" into count_qc + cat "ctss_all_pos_clustered_simplified" "ctss_all_neg_clustered_simplified" > "ctss_all_clustered_simplified" + awk -F '\t' '{print $1"\t"$3"\t"$4"\t"$1":"$3".."$4","$2"\t"$6"\t"$2}' "ctss_all_clustered_simplified" > "ctss_all_clustered_simplified.bed" + ''' + } - shell: - ''' - #intersect ctss files with generated clusters - intersectBed -a !{clusters} -b !{ctss} -loj -s > !{ctss}_counts_tmp + /* + * STEP 11 - Generate count files + */ + process generate_counts { + tag "${sample_name}" + // publishDir "${params.outdir}/ctss/", mode: params.publish_dir_mode - echo !{sample_name} > !{ctss}_counts.txt + input: + set val(sample_name), file(ctss) from ctss_samples + file clusters from ctss_clusters.collect() - bedtools groupby -i !{ctss}_counts_tmp -g 1,2,3,4,6 -c 11 -o sum > !{ctss}_counts.bed - awk -v OFS='\t' '{if($6=="-1") $6=0; print $6 }' !{ctss}_counts.bed >> !{ctss}_counts.txt - ''' - } + output: + file "*.txt" into count_files + file "*.bed" into count_qc -/* - * STEP 11 - Generate count matrix - */ -process generate_count_matrix { - publishDir "${params.outdir}/ctss/", mode: 'copy' + shell: + ''' + #intersect ctss files with generated clusters + intersectBed -a !{clusters} -b !{ctss} -loj -s > !{ctss}_counts_tmp - input: - file counts from count_files.collect() - file clusters from ctss_clusters.collect() + echo !{sample_name} > !{ctss}_counts.txt - output: - file "*.tsv" into count_matrix + bedtools groupby -i !{ctss}_counts_tmp -g 1,2,3,4,6 -c 11 -o sum > !{ctss}_counts.bed + awk -v OFS='\t' '{if($6=="-1") $6=0; print $6 }' !{ctss}_counts.bed >> !{ctss}_counts.txt + ''' + } - shell: - ''' - awk '{ print $4}' !{clusters} > coordinates - paste -d "\t" coordinates !{counts} >> count_table.tsv - ''' -} + /* + * STEP 11 - Generate count matrix + */ + process generate_count_matrix { + publishDir "${params.outdir}/ctss/", mode: params.publish_dir_mode -/** - * STEP 10 - QC for clustered ctss - */ -process ctss_qc { - tag "$clusters" - publishDir "${params.outdir}/rseqc" , mode: 'copy', - saveAs: {filename -> - if (filename.indexOf("read_distribution.txt") > 0) "read_distribution/$filename" - else filename - } + input: + file counts from count_files.collect() + file clusters from ctss_clusters.collect() - input: - file clusters from ctss_counts_qc - file gtf from bed_rseqc.collect() - file chrom_sizes from chrom_sizes_ctss + output: + file "*.tsv" into count_matrix - output: - file "*.txt" into rseqc_results + shell: + ''' + awk '{ print $4}' !{clusters} > coordinates + paste -d "\t" coordinates !{counts} >> count_table.tsv + ''' + } - shell: - ''' + /** + * STEP 10 - QC for clustered ctss + */ + if(!params.skip_ctss_qc){ + process ctss_qc { + tag "$clusters" + publishDir "${params.outdir}/rseqc" , mode: params.publish_dir_mode, + saveAs: {filename -> + if (filename.indexOf("read_distribution.txt") > 0) "read_distribution/$filename" + else filename + } + + input: + file clusters from ctss_counts_qc + file gtf from bed_rseqc.collect() + file chrom_sizes from chrom_sizes_ctss + + output: + file "*.txt" into rseqc_results + + shell: + ''' + bedtools bedtobam -i !{clusters} -g !{chrom_sizes} > !{clusters.baseName}.bam + read_distribution.py -i !{clusters.baseName}.bam -r !{gtf} > !{clusters.baseName}.read_distribution.txt + ''' + } + } else { + rseqc_results = Channel.empty() + } - bedtools bedtobam -i !{clusters} -g !{chrom_sizes} > !{clusters.baseName}.bam - read_distribution.py -i !{clusters.baseName}.bam -r !{gtf} > !{clusters.baseName}.read_distribution.txt - ''' + } else { + count_qc = Channel.empty() + rseqc_results = Channel.empty() } - /* * STEP 12 - MultiQC */ @@ -964,13 +944,12 @@ process multiqc { file multiqc_config from ch_multiqc_config file (mqc_custom_config) from ch_multiqc_custom_config.collect().ifEmpty([]) file ('software_versions/*') from ch_software_versions_yaml.collect() - file ('fastqc/*') from ch_fastqc_results.collect().ifEmpty([]) + file ('fastqc/*') from fastqc_results.collect().ifEmpty([]) file ('trimmed/*') from cutadapt_results.collect().ifEmpty([]) file ('artifacts_trimmed/*') from artifact_cutting_results.collect().ifEmpty([]) file ('trimmed/fastqc/*') from trimmed_fastqc_results.collect().ifEmpty([]) file ('sortmerna/*') from sortmerna_logs.collect().ifEmpty([]) - file ('alignment/*') from star_alignment_logs.collect().ifEmpty([]) - file ('alignment/*') from bowtie_alignment_logs.collect().ifEmpty([]) + file ('alignment/*') from alignment_logs.collect().ifEmpty([]) file ('alignment/samtools_stats/*') from bam_flagstat_mqc.collect().ifEmpty([]) file ('rseqc/*') from rseqc_results.collect().ifEmpty([]) file workflow_summary from ch_workflow_summary.collectFile(name: "workflow_summary_mqc.yaml") diff --git a/nextflow.config b/nextflow.config index 63fcccb..8d32114 100644 --- a/nextflow.config +++ b/nextflow.config @@ -21,8 +21,8 @@ params { saveReference = false min_aln_length = 15 single_end = true - // Trimming options (all enabled by default) - skip_trimming = false + + // Trimming options save_trimmed = false trim_ecop = true trim_linker = true @@ -33,6 +33,15 @@ params { artifacts_5end = "$baseDir/assets/artifacts_5end.fasta" artifacts_3end = "$baseDir/assets/artifacts_3end.fasta" + // Skipping options + skip_initial_fastqc = false + skip_alignment = false + skip_trimming = false + skip_trimming_fastqc = false + skip_samtools_stats = false + skip_ctss_generation = false + skip_ctss_qc = false + // Ribosomal RNA removal remove_ribo_RNA = false save_nonrRNA_reads = false diff --git a/nextflow_schema.json b/nextflow_schema.json index ccf87cc..bdb6776 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -5,39 +5,135 @@ "description": "CAGE-seq pipeline", "type": "object", "definitions": { - "ribosomal_rna_removal_options": { - "title": "Ribosomal RNA removal options", + "input_output_options": { + "title": "Input/output options", "type": "object", - "description": "Options to control the ribosomal RNA removal", - "default": "", - "fa_icon": "far fa-trash-alt", + "fa_icon": "fas fa-terminal", + "description": "Define where the pipeline should find input data and save output data.", + "required": [ + "input" + ], "properties": { - "remove_ribo_RNA": { + "input": { + "type": "string", + "fa_icon": "fas fa-dna", + "description": "Input FastQ files.", + "help_text": "Use this to specify the location of your input FastQ files. For example:\n\n```bash\n--input 'path/to/data/sample_*_{1,2}.fastq'\n```\n\nPlease note the following requirements:\n\n1. The path must be enclosed in quotes\n2. The path must have at least one `*` wildcard character\n3. When using the pipeline with paired end data, the path must use `{1,2}` notation to specify read pairs.\n\nIf left unspecified, a default pattern is used: `data/*{1,2}.fastq.gz`", + "default": "data/*R1.fastq.gz" + }, + "single_end": { "type": "boolean", - "fa_icon": "far fa-trash-alt" + "description": "Specifies that the input is single-end reads.", + "fa_icon": "fas fa-align-center", + "help_text": "By default, the pipeline expects paired-end data. If you have single-end data, you need to specify `--single_end` on the command line when you launch the pipeline. A normal glob pattern, enclosed in quotation marks, can then be used for `--input`. For example:\n\n```bash\n--single_end --input '*.fastq'\n```\n\nIt is not possible to run a mixture of single-end and paired-end files in one run.", + "default": true }, - "save_nonrRNA_reads": { + "outdir": { + "type": "string", + "description": "The output directory where the results will be saved.", + "default": "./results", + "fa_icon": "fas fa-folder-open" + }, + "email": { + "type": "string", + "description": "Email address for completion summary.", + "fa_icon": "fas fa-envelope", + "help_text": "Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run.", + "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" + }, + "bigwig": { "type": "boolean", - "fa_icon": "far fa-save" + "description": "Specifies if TSS-bigwigs should be generated, additionally to the TSS-bed files", + "fa_icon": "fas fa-sign-out-alt" + } + } + }, + "alignment_options": { + "title": "Alignment options", + "type": "object", + "description": "Adjust parameters and filtering criteria for read alignments.", + "default": "", + "fa_icon": "fas fa-map-signs", + "properties": { + "aligner": { + "type": "string", + "default": "star", + "fa_icon": "fas fa-map-marked-alt", + "description": "Alignment tool to be used", + "enum": [ + "star", + "bowtie1" + ] }, - "rRNA_database_manifest": { + "min_aln_length": { + "type": "integer", + "default": "15", + "fa_icon": "fas fa-ruler", + "description": "Minimum number of aligned basepairs of a read to be kept" + } + } + }, + "reference_genome_options": { + "title": "Reference genome options", + "type": "object", + "fa_icon": "fas fa-dna", + "description": "Options for the reference genome indices used to align reads.", + "properties": { + "genome": { "type": "string", - "default": "$baseDir/assets/rrna-db-defaults.txt", - "fa_icon": "fas fa-database" + "description": "Name of iGenomes reference.", + "fa_icon": "fas fa-book", + "help_text": "If using a reference genome configured in the pipeline using iGenomes, use this parameter to give the ID for the reference. This is then used to build the full paths for all required reference genome files e.g. `--genome GRCh38`.\n\nSee the [nf-core website docs](https://nf-co.re/usage/reference_genomes) for more details." + }, + "fasta": { + "type": "string", + "fa_icon": "fas fa-font", + "description": "Path to FASTA genome file.", + "help_text": "If you have no genome reference available, the pipeline can build one using a FASTA file. This requires additional time and resources, so it's better to use a pre-build index if possible." + }, + "igenomes_base": { + "type": "string", + "description": "Directory / URL base for iGenomes references.", + "default": "s3://ngi-igenomes/igenomes/", + "fa_icon": "fas fa-cloud-download-alt", + "hidden": true + }, + "igenomes_ignore": { + "type": "boolean", + "description": "Do not load the iGenomes reference config.", + "fa_icon": "fas fa-ban", + "hidden": true, + "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`." + }, + "gtf": { + "type": "string", + "fa_icon": "fas fa-file-invoice", + "description": "Path to gtf file." + }, + "star_index": { + "type": "string", + "fa_icon": "far fa-star", + "description": "Path to star index directory." + }, + "bowtie_index": { + "type": "string", + "fa_icon": "fab fa-black-tie", + "description": "Path to bowtie index directory." + }, + "saveReference": { + "type": "boolean", + "fa_icon": "far fa-save", + "description": "All generated reference files will be saved to the results folder if this flag is set." } } }, "trimming_options": { "title": "Trimming options", "type": "object", - "description": "Options to adjust trimming criteria.", + "description": "Adjust trimming criteria and sequences.", "default": "", "fa_icon": "fas fa-cut", "properties": { - "skip_trimming": { - "type": "boolean", - "fa_icon": "fas fa-fast-forward" - }, "save_trimmed": { "type": "boolean", "fa_icon": "far fa-save" @@ -88,35 +184,32 @@ } } }, - "alignment_options": { - "title": "Alignment options", + "ribosomal_rna_removal_options": { + "title": "Ribosomal RNA removal options", "type": "object", - "description": "Options to adjust parameters and filtering criteria for read alignments.", + "description": "Control the ribosomal RNA removal through SortMeRNA.", "default": "", - "fa_icon": "fas fa-map-signs", + "fa_icon": "far fa-trash-alt", "properties": { - "aligner": { - "type": "string", - "default": "star", - "fa_icon": "fas fa-map-marked-alt", - "description": "Alignment tool to be used", - "enum": [ - "star", - "bowtie1" - ] + "remove_ribo_RNA": { + "type": "boolean", + "fa_icon": "far fa-trash-alt" }, - "min_aln_length": { - "type": "integer", - "default": "15", - "fa_icon": "fas fa-ruler", - "description": "Minimum number of aligned basepairs of a read to be kept" + "save_nonrRNA_reads": { + "type": "boolean", + "fa_icon": "far fa-save" + }, + "rRNA_database_manifest": { + "type": "string", + "default": "$baseDir/assets/rrna-db-defaults.txt", + "fa_icon": "fas fa-database" } } }, "cage_tag_clustering_options": { "title": "CAGE-tag clustering options", "type": "object", - "description": "", + "description": "Define parameters for paraclu clustering.", "default": "", "fa_icon": "fas fa-align-left", "properties": { @@ -134,100 +227,47 @@ } } }, - "input_output_options": { - "title": "Input/output options", + "process_skipping_options": { + "title": "Process skipping options", "type": "object", - "fa_icon": "fas fa-terminal", - "description": "Define where the pipeline should find input data and save output data.", - "required": [ - "input" - ], + "description": "Skip various steps within the workflow.", + "default": "", + "fa_icon": "fas fa-tasks", "properties": { - "input": { - "type": "string", - "fa_icon": "fas fa-dna", - "description": "Input FastQ files.", - "help_text": "Use this to specify the location of your input FastQ files. For example:\n\n```bash\n--input 'path/to/data/sample_*_{1,2}.fastq'\n```\n\nPlease note the following requirements:\n\n1. The path must be enclosed in quotes\n2. The path must have at least one `*` wildcard character\n3. When using the pipeline with paired end data, the path must use `{1,2}` notation to specify read pairs.\n\nIf left unspecified, a default pattern is used: `data/*{1,2}.fastq.gz`", - "default": "data/*R1.fastq.gz" - }, - "single_end": { + "skip_initial_fastqc": { "type": "boolean", - "description": "Specifies that the input is single-end reads.", - "fa_icon": "fas fa-align-center", - "help_text": "By default, the pipeline expects paired-end data. If you have single-end data, you need to specify `--single_end` on the command line when you launch the pipeline. A normal glob pattern, enclosed in quotation marks, can then be used for `--input`. For example:\n\n```bash\n--single_end --input '*.fastq'\n```\n\nIt is not possible to run a mixture of single-end and paired-end files in one run.", - "default": true - }, - "outdir": { - "type": "string", - "description": "The output directory where the results will be saved.", - "default": "./results", - "fa_icon": "fas fa-folder-open" - }, - "email": { - "type": "string", - "description": "Email address for completion summary.", - "fa_icon": "fas fa-envelope", - "help_text": "Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits. If set in your user config file (`~/.nextflow/config`) then you don't need to specify this on the command line for every run.", - "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" + "fa_icon": "fas fa-fast-forward", + "description": "Skip FastQC run on input reads." }, - "bigwig": { + "skip_trimming": { "type": "boolean", - "description": "Specifies if TSS-bigwigs should be generated, additionally to the TSS-bed files", - "fa_icon": "fas fa-sign-out-alt" - } - } - }, - "reference_genome_options": { - "title": "Reference genome options", - "type": "object", - "fa_icon": "fas fa-dna", - "description": "Options for the reference genome indices used to align reads.", - "properties": { - "genome": { - "type": "string", - "description": "Name of iGenomes reference.", - "fa_icon": "fas fa-book", - "help_text": "If using a reference genome configured in the pipeline using iGenomes, use this parameter to give the ID for the reference. This is then used to build the full paths for all required reference genome files e.g. `--genome GRCh38`.\n\nSee the [nf-core website docs](https://nf-co.re/usage/reference_genomes) for more details." - }, - "fasta": { - "type": "string", - "fa_icon": "fas fa-font", - "description": "Path to FASTA genome file.", - "help_text": "If you have no genome reference available, the pipeline can build one using a FASTA file. This requires additional time and resources, so it's better to use a pre-build index if possible." - }, - "igenomes_base": { - "type": "string", - "description": "Directory / URL base for iGenomes references.", - "default": "s3://ngi-igenomes/igenomes/", - "fa_icon": "fas fa-cloud-download-alt", - "hidden": true + "fa_icon": "fas fa-fast-forward", + "description": "Skip all trimming steps." }, - "igenomes_ignore": { + "skip_trimming_fastqc": { "type": "boolean", - "description": "Do not load the iGenomes reference config.", - "fa_icon": "fas fa-ban", - "hidden": true, - "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`." + "fa_icon": "fas fa-fast-forward", + "description": "Skip FastQC run on trimmed reads." }, - "gtf": { - "type": "string", - "fa_icon": "fas fa-file-invoice", - "description": "Path to gtf file." + "skip_alignment": { + "type": "boolean", + "fa_icon": "fas fa-fast-forward", + "description": "Skip alignment step." }, - "star_index": { - "type": "string", - "fa_icon": "far fa-star", - "description": "Path to star index directory." + "skip_samtools_stats": { + "type": "boolean", + "fa_icon": "fas fa-fast-forward", + "description": "Skip samtools stats QC step of aligned reads" }, - "bowtie_index": { - "type": "string", - "fa_icon": "fab fa-black-tie", - "description": "Path to bowtie index directory." + "skip_ctss_generation": { + "type": "boolean", + "fa_icon": "fas fa-fast-forward", + "description": "Skip steps generating CTSS files including clustering, bed/bigwig and count table output generation." }, - "saveReference": { + "skip_ctss_qc": { "type": "boolean", - "fa_icon": "far fa-save", - "description": "All generated reference files will be saved to the results folder if this flag is set." + "fa_icon": "fas fa-fast-forward", + "description": "Skip running RSeQC's read distribution QC step on the clustered CTSS." } } }, @@ -404,22 +444,25 @@ }, "allOf": [ { - "$ref": "#/definitions/ribosomal_rna_removal_options" + "$ref": "#/definitions/input_output_options" }, { - "$ref": "#/definitions/trimming_options" + "$ref": "#/definitions/alignment_options" }, { - "$ref": "#/definitions/alignment_options" + "$ref": "#/definitions/reference_genome_options" }, { - "$ref": "#/definitions/cage_tag_clustering_options" + "$ref": "#/definitions/trimming_options" }, { - "$ref": "#/definitions/input_output_options" + "$ref": "#/definitions/ribosomal_rna_removal_options" }, { - "$ref": "#/definitions/reference_genome_options" + "$ref": "#/definitions/cage_tag_clustering_options" + }, + { + "$ref": "#/definitions/process_skipping_options" }, { "$ref": "#/definitions/generic_options" From 1750fc27028a8626956b8764e1ba18044b428f06 Mon Sep 17 00:00:00 2001 From: matthiasho Date: Thu, 13 Aug 2020 11:15:12 +0200 Subject: [PATCH 082/107] fix `alignment_logs` error --- main.nf | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/main.nf b/main.nf index 51bf0f0..e394a65 100644 --- a/main.nf +++ b/main.nf @@ -677,7 +677,7 @@ if(!params.skip_alignment){ output: set val(sample_name), file("*.bam") into star_aligned - file "*.out" into alignment_logs + file "*.out" into star_alignment_logs file "*SJ.out.tab" @@ -704,7 +704,7 @@ if(!params.skip_alignment){ star_aligned.into { bam_stats; bam_aligned } } else{ - alignment_logs = Channel.empty() + star_alignment_logs = Channel.empty() } if (params.aligner == 'bowtie1'){ process bowtie { @@ -721,7 +721,7 @@ if(!params.skip_alignment){ output: set val(sample_name), file("*.bam") into bam_stats, bam_aligned - file "*.out" into alignment_logs + file "*.out" into bowtie_alignment_logs script: @@ -750,11 +750,12 @@ if(!params.skip_alignment){ } }else{ - alignment_logs= Channel.empty() + bowtie_alignment_logs= Channel.empty() } } else { further_processed_reads_sortmerna.set{further_processed_reads_alignment} - alignment_logs = Channel.empty() + star_alignment_logs= Channel.empty() + bowtie_alignment_logs = Channel.empty() } if(!params.skip_samtools_stats){ @@ -949,7 +950,8 @@ process multiqc { file ('artifacts_trimmed/*') from artifact_cutting_results.collect().ifEmpty([]) file ('trimmed/fastqc/*') from trimmed_fastqc_results.collect().ifEmpty([]) file ('sortmerna/*') from sortmerna_logs.collect().ifEmpty([]) - file ('alignment/*') from alignment_logs.collect().ifEmpty([]) + file ('alignment/*') from star_alignment_logs.collect().ifEmpty([]) + file ('alignment/*') from bowtie_alignment_logs.collect().ifEmpty([]) file ('alignment/samtools_stats/*') from bam_flagstat_mqc.collect().ifEmpty([]) file ('rseqc/*') from rseqc_results.collect().ifEmpty([]) file workflow_summary from ch_workflow_summary.collectFile(name: "workflow_summary_mqc.yaml") From 46f6c701b2fb6c4727369f4f35080751a0e401e9 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 14 Aug 2020 10:05:39 +0200 Subject: [PATCH 083/107] fix `alignment_logs` error --- main.nf | 69 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/main.nf b/main.nf index 51bf0f0..846929d 100644 --- a/main.nf +++ b/main.nf @@ -327,32 +327,35 @@ process get_software_versions { scrape_software_versions.py &> software_versions_mqc.yaml """ } -process convert_gtf { - tag "$gtf" +if(!params.skip_ctss_qc){ + process convert_gtf { + tag "$gtf" - input: - file gtf from gtf_rseqc + input: + file gtf from gtf_rseqc - output: - file "${gtf.baseName}.bed" into bed_rseqc + output: + file "${gtf.baseName}.bed" into bed_rseqc - script: - """ - gtf2bed.pl $gtf > ${gtf.baseName}.bed - """ + script: + """ + gtf2bed.pl $gtf > ${gtf.baseName}.bed + """ + } } -process get_chrom_sizes{ - input: - file fasta from fasta_rseqc.collect() - output: - file "*.txt" into (chrom_sizes_ctss,chrom_sizes_bw) - - shell: - ''' - cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.txt - ''' +if(!params.skip_ctss_generation){ + process get_chrom_sizes{ + input: + file fasta from fasta_rseqc.collect() + output: + file "*.txt" into (chrom_sizes_ctss,chrom_sizes_bw) + + shell: + ''' + cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.txt + ''' + } } - /* * STEP 1 - FastQC */ @@ -568,7 +571,7 @@ if (params.trim_artifacts && !params.skip_trimming){ file artifacts_3end from ch_3end_artifacts.collect() output: - set val(sample_name), file("*.fastq.gz") into further_processed_reads + set val(sample_name), file("*.fastq.gz") into further_processed_reads_sortmerna file "*.output.txt" into artifact_cutting_results script: @@ -583,9 +586,7 @@ if (params.trim_artifacts && !params.skip_trimming){ > ${reads.baseName}.artifacts_trimming.output.txt """ } - further_processed_reads.set{further_processed_reads_sortmerna} -} -else{ +} else{ processed_reads.set{further_processed_reads_sortmerna} artifact_cutting_results = Channel.empty() } @@ -677,7 +678,7 @@ if(!params.skip_alignment){ output: set val(sample_name), file("*.bam") into star_aligned - file "*.out" into alignment_logs + file "*.out" into star_alignment_logs file "*SJ.out.tab" @@ -704,7 +705,7 @@ if(!params.skip_alignment){ star_aligned.into { bam_stats; bam_aligned } } else{ - alignment_logs = Channel.empty() + star_alignment_logs = Channel.empty() } if (params.aligner == 'bowtie1'){ process bowtie { @@ -721,7 +722,7 @@ if(!params.skip_alignment){ output: set val(sample_name), file("*.bam") into bam_stats, bam_aligned - file "*.out" into alignment_logs + file "*.out" into bowtie_alignment_logs script: @@ -750,14 +751,15 @@ if(!params.skip_alignment){ } }else{ - alignment_logs= Channel.empty() + bowtie_alignment_logs= Channel.empty() } } else { - further_processed_reads_sortmerna.set{further_processed_reads_alignment} - alignment_logs = Channel.empty() + further_processed_reads_sortmerna.into{bam_stats; bam_aligned} + star_alignment_logs = Channel.empty() + bowtie_alignment_logs = Channel.empty() } -if(!params.skip_samtools_stats){ +if(!params.skip_samtools_stats && !params.skip_samtools_stats){ process samtools_stats { tag "$sample_name" label 'process_medium' @@ -949,7 +951,8 @@ process multiqc { file ('artifacts_trimmed/*') from artifact_cutting_results.collect().ifEmpty([]) file ('trimmed/fastqc/*') from trimmed_fastqc_results.collect().ifEmpty([]) file ('sortmerna/*') from sortmerna_logs.collect().ifEmpty([]) - file ('alignment/*') from alignment_logs.collect().ifEmpty([]) + file ('alignment/*') from star_alignment_logs.collect().ifEmpty([]) + file ('alignment/*') from bowtie_alignment_logs.collect().ifEmpty([]) file ('alignment/samtools_stats/*') from bam_flagstat_mqc.collect().ifEmpty([]) file ('rseqc/*') from rseqc_results.collect().ifEmpty([]) file workflow_summary from ch_workflow_summary.collectFile(name: "workflow_summary_mqc.yaml") From f647dace0c35100fe7500be474a963533a7e2f72 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 14 Aug 2020 10:06:28 +0200 Subject: [PATCH 084/107] clean up TODOs --- .github/workflows/awstest.yml | 9 ++++++--- .github/workflows/ci.yml | 5 +---- conf/test_full.config | 3 --- docs/README.md | 2 -- docs/images/rseqc_read_distribution_plot.png | Bin 56481 -> 61189 bytes docs/usage.md | 2 +- 6 files changed, 8 insertions(+), 13 deletions(-) diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index 857ca48..c5f14ae 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -21,9 +21,12 @@ jobs: - name: Install awscli run: conda install -c conda-forge awscli - name: Start AWS batch job - # TODO nf-core: You can customise CI pipeline run tests as required - # For example: adding multiple test runs with different parameters - # Remember that you can parallelise this by using strategy.matrix + strategy: + matrix: + # Nextflow versions: check pipeline minimum and current latest + nxf_ver: ['19.10.0', ''] + aligner: ["--aligner 'bowtie1'", "--aligner 'star'"] + options: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false'] env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23a0ce6..c1f906a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: # Nextflow versions: check pipeline minimum and current latest nxf_ver: ['19.10.0', ''] aligner: ["--aligner 'bowtie1'", "--aligner 'star'"] - options: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false', '--star_index false','--bowtie_index false'] + options: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false', '--bigwig'] steps: - name: Check out pipeline code uses: actions/checkout@v2 @@ -50,8 +50,5 @@ jobs: sudo mv nextflow /usr/local/bin/ - name: Run pipeline with test data - # TODO nf-core: You can customise CI pipeline run tests as required - # For example: adding multiple test runs with different parameters - # Remember that you can parallelise this by using strategy.matrix run: | nextflow run ${GITHUB_WORKSPACE} -profile test,docker diff --git a/conf/test_full.config b/conf/test_full.config index 93022b9..60b1aa3 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -12,9 +12,6 @@ params { config_profile_description = 'Full test dataset to check pipeline function' // Input data for full size test - // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) - // TODO nf-core: Give any required params for the test so that command line flags are not needed - single_end = false input_paths = [ ['Testdata', ['https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R1.tiny.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R2.tiny.fastq.gz']], ['SRR389222', ['https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub1.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub2.fastq.gz']] diff --git a/docs/README.md b/docs/README.md index 672f93f..9421703 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,8 +2,6 @@ The nf-core/cageseq documentation is split into the following pages: - - * [Usage](usage.md) * An overview of how the pipeline works, how to run it and a description of all of the different command-line flags. * [Output](output.md) diff --git a/docs/images/rseqc_read_distribution_plot.png b/docs/images/rseqc_read_distribution_plot.png index 6aaf67a0acb4c878bceadfa417d6530c22b66c38..b3c12ded1ba580b4c1d54c92162f4134cdcdab06 100644 GIT binary patch literal 61189 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�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 X;{IQl$~AgKBz#Esuul0w%EkWzJ($4A diff --git a/docs/usage.md b/docs/usage.md index 8b84a8f..a7cb044 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -5,7 +5,7 @@ The typical command for running the pipeline is as follows: ```bash -nextflow run nf-core/cageseq --input '*_R{1,2}.fastq.gz' -profile docker +nextflow run nf-core/cageseq --input '*_R1.fastq.gz' -profile docker ``` This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. From b3fc4b60a13f038037a24f30218378f34d13671d Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 14 Aug 2020 11:44:12 +0200 Subject: [PATCH 085/107] fix formatting --- main.nf | 308 ++++++++++++++++++++++++++------------------------------ 1 file changed, 144 insertions(+), 164 deletions(-) diff --git a/main.nf b/main.nf index 846929d..eac78cd 100644 --- a/main.nf +++ b/main.nf @@ -1,11 +1,11 @@ #!/usr/bin/env nextflow /* ======================================================================================== - nf-core/cageseq + nf-core/cageseq ======================================================================================== - nf-core/cageseq Analysis Pipeline. - #### Homepage / Documentation - https://github.com/nf-core/cageseq +nf-core/cageseq Analysis Pipeline. +#### Homepage / Documentation +https://github.com/nf-core/cageseq ---------------------------------------------------------------------------------------- */ @@ -64,12 +64,12 @@ def helpMessage() { --skip_ctss_qc [bool] Skip running RSeQC's read distribution QC step on the clustered CTSS Other options: - --outdir [file] The output directory where the results will be saved - --publish_dir_mode [str] Mode for publishing results in the output directory. Available: symlink, rellink, link, copy, copyNoFollow, move (Default: copy) - --email [email] Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits - --email_on_fail [email] Same as --email, except only send mail if the workflow is not successful - --max_multiqc_email_size [str] Threshold size for MultiQC report to be attached in notification email. If file generated by pipeline exceeds the threshold, it will not be attached (Default: 25MB) - -name [str] Name for the pipeline run. If not specified, Nextflow will automatically generate a random mnemonic + --outdir [file] The output directory where the results will be saved + --publish_dir_mode [str] Mode for publishing results in the output directory. Available: symlink, rellink, link, copy, copyNoFollow, move (Default: copy) + --email [email] Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits + --email_on_fail [email] Same as --email, except only send mail if the workflow is not successful + --max_multiqc_email_size [str] Threshold size for MultiQC report to be attached in notification email. If file generated by pipeline exceeds the threshold, it will not be attached (Default: 25MB) + -name [str] Name for the pipeline run. If not specified, Nextflow will automatically generate a random mnemonic AWSBatch options: --awsqueue [str] The AWSBatch JobQueue that needs to be set when running on AWSBatch @@ -136,10 +136,10 @@ else { if( params.fasta ){ - Channel - .fromPath(params.fasta, checkIfExists: true) - .ifEmpty { exit 1, "fasta file not found: ${params.fasta}" } - .set{fasta_rseqc} +Channel + .fromPath(params.fasta, checkIfExists: true) + .ifEmpty { exit 1, "fasta file not found: ${params.fasta}" } + .set{fasta_rseqc} } else { exit 1, "No fasta file specified!" } @@ -163,7 +163,7 @@ else { } if( params.artifacts_3end ){ - ch_3end_artifacts = Channel + ch_3end_artifacts = Channel .fromPath(params.artifacts_3end) } else { @@ -202,13 +202,13 @@ ch_output_docs_images = file("$baseDir/docs/images/", checkIfExists: true) * Create a channel for input read files */ if (params.input_paths) { - Channel - .from(params.input_paths) - .map { row -> [ row[0].replaceAll("\\s","_"), file(row[1])] } - .ifEmpty { exit 1, "params.input was empty - no input files supplied" } - .into { ch_read_files_fastqc; read_files_trimming } +Channel + .from(params.input_paths) + .map { row -> [ row[0].replaceAll("\\s","_"), file(row[1])] } + .ifEmpty { exit 1, "params.input was empty - no input files supplied" } + .into { ch_read_files_fastqc; read_files_trimming } } else { - Channel +Channel .fromFilePairs( params.input ) .ifEmpty { exit 1, "Cannot find any reads matching: ${params.reads}\nNB: Path needs to be enclosed in quotes!\nNB: Path requires at least one * wildcard!\n" } .into { ch_read_files_fastqc; read_files_trimming } @@ -239,9 +239,9 @@ if (params.skip_trimming_fastqc) summary['Skip Trimming FastQC'] = 'Yes' if (params.skip_alignment){summary['Skip Alignment'] = 'Yes'} else { if (params.aligner == 'star') { - summary['Aligner'] = "STAR" - if (params.star_index){summary['STAR Index'] = params.star_index} - else if (params.fasta){summary['Fasta Ref'] = params.fasta} + summary['Aligner'] = "STAR" + if (params.star_index){summary['STAR Index'] = params.star_index} + else if (params.fasta){summary['Fasta Ref'] = params.fasta} } else if (params.aligner == 'bowtie1') { summary['Aligner'] = "bowtie" if (params.bowtie_index) summary['bowtie Index'] = params.bowtie_index @@ -303,9 +303,9 @@ Channel.from(summary.collect{ [it.key, it.value] }) process get_software_versions { publishDir "${params.outdir}/pipeline_info", mode: params.publish_dir_mode, saveAs: { filename -> - if (filename.indexOf(".csv") > 0) filename - else null - } + if (filename.indexOf(".csv") > 0) filename + else null + } output: file 'software_versions_mqc.yaml' into ch_software_versions_yaml @@ -345,15 +345,15 @@ if(!params.skip_ctss_qc){ } if(!params.skip_ctss_generation){ process get_chrom_sizes{ - input: - file fasta from fasta_rseqc.collect() - output: - file "*.txt" into (chrom_sizes_ctss,chrom_sizes_bw) - - shell: - ''' - cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.txt - ''' + input: + file fasta from fasta_rseqc.collect() + output: + file "*.txt" into (chrom_sizes_ctss,chrom_sizes_bw) + + shell: + ''' + cat !{fasta} | awk '$0 ~ ">" {if (NR > 1) {print c;} c=0;printf substr($0,2,100) "\t"; } $0 !~ ">" {c+=length($0);} END { print c; }' > chrom_sizes.txt + ''' } } /* @@ -365,7 +365,7 @@ if(!params.skip_initial_fastqc){ label 'process_medium' publishDir "${params.outdir}/fastqc", mode: params.publish_dir_mode, saveAs: { filename -> - filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename" + filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename" } input: @@ -384,7 +384,7 @@ if(!params.skip_initial_fastqc){ } /* - * STEP 2 - Build STAR index + * STEP 2 - Build STAR/bowtie1 index */ if(params.aligner == 'star' && !params.star_index && params.fasta && !params.skip_alignment){ @@ -401,9 +401,6 @@ if(params.aligner == 'star' && !params.star_index && params.fasta && !params.ski output: file "star" into star_index - when: - - script: def avail_mem = task.memory ? "--limitGenomeGenerateRAM ${task.memory.toBytes() - 100000000}" : '' """ @@ -441,7 +438,7 @@ if(params.aligner == 'bowtie1' && !params.bowtie_index && params.fasta && !param } /* - * STEP 3 - Cut Enzyme binding site at 5' and linker at 3' + * STEP 3 - Cut enzyme binding site at 5' and linker at 3' */ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ @@ -462,8 +459,6 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ file "*.output.txt" into cutadapt_results script: - // prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?$/ - // Cut Both EcoP and Linker if (params.trim_ecop && params.trim_linker){ """ @@ -518,52 +513,52 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ cutadapt_results = Channel.empty() } - /** - * STEP 4 - Remove added G from 5-end - */ - if (params.trim_5g && !params.skip_trimming){ - process trim_5g{ - tag "$sample_name" - publishDir "${params.outdir}/trimmed/g_trimmed", mode: params.publish_dir_mode, - saveAs: {filename -> - if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" - else if (params.save_trimmed) "$filename" - else null - } - input: - set val(sample_name), file(reads) from trimmed_reads_trim_5g - - output: - set val(sample_name), file("*.fastq.gz") into processed_reads - - script: - // prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?$/ - """ - cutadapt -g ^G \\ - -e 0 --match-read-wildcards \\ - --cores=${task.cpus} \\ - -o "$sample_name".g_trimmed.fastq.gz \\ - $reads \\ - > "$sample_name".g_trimming.output.txt - """ - } - } - else { - trimmed_reads_trim_5g.set{processed_reads} - } - /** - * STEP 5 - Remove artifacts - */ +/** + * STEP 4 - Remove added G from 5-end + */ +if (params.trim_5g && !params.skip_trimming){ + process trim_5g{ + tag "$sample_name" + publishDir "${params.outdir}/trimmed/g_trimmed", mode: params.publish_dir_mode, + saveAs: {filename -> + if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" + else if (params.save_trimmed) "$filename" + else null + } + + input: + set val(sample_name), file(reads) from trimmed_reads_trim_5g + + output: + set val(sample_name), file("*.fastq.gz") into processed_reads + + script: + """ + cutadapt -g ^G \\ + -e 0 --match-read-wildcards \\ + --cores=${task.cpus} \\ + -o "$sample_name".g_trimmed.fastq.gz \\ + $reads \\ + > "$sample_name".g_trimming.output.txt + """ + } +} +else { + trimmed_reads_trim_5g.set{processed_reads} +} +/** + * STEP 5 - Remove artifacts + */ if (params.trim_artifacts && !params.skip_trimming){ process trim_artifacts { tag "$sample_name" publishDir "${params.outdir}/trimmed/artifacts_trimmed", mode: params.publish_dir_mode, - saveAs: {filename -> - if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" - else if (params.save_trimmed) "$filename" - else null - } + saveAs: {filename -> + if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" + else if (params.save_trimmed) "$filename" + else null + } input: set val(sample_name), file(reads) from processed_reads @@ -575,7 +570,6 @@ if (params.trim_artifacts && !params.skip_trimming){ file "*.output.txt" into artifact_cutting_results script: - // prefix = reads.baseName.toString() - ~/(\.fq)?(\.fastq)?(\.gz)?(\.trimmed)?(\.processed)?$/ """ cutadapt -a file:$artifacts_3end \\ -g file:$artifacts_5end -e 0.1 --discard-trimmed \\ @@ -592,55 +586,54 @@ if (params.trim_artifacts && !params.skip_trimming){ } /* - * STEP 2+ - SortMeRNA - remove rRNA sequences on request + * STEP 6 - SortMeRNA - remove rRNA sequences on request */ if (params.remove_ribo_RNA) { - process sortmerna { - label 'high_memory' - tag "$sample_name" - publishDir "${params.outdir}/SortMeRNA", mode: params.publish_dir_mode, - saveAs: {filename -> - if (filename.indexOf("_rRNA_report.txt") > 0) "logs/$filename" - else if (params.save_nonrRNA_reads) "reads/$filename" - else null - } - - input: - set val(sample_name), file(reads) from further_processed_reads_sortmerna - file(fasta) from fasta_sortmerna.collect() + process sortmerna { + label 'high_memory' + tag "$sample_name" + publishDir "${params.outdir}/SortMeRNA", mode: params.publish_dir_mode, + saveAs: {filename -> + if (filename.indexOf("_rRNA_report.txt") > 0) "logs/$filename" + else if (params.save_nonrRNA_reads) "reads/$filename" + else null + } + input: + set val(sample_name), file(reads) from further_processed_reads_sortmerna + file(fasta) from fasta_sortmerna.collect() - output: - set val(sample_name), file("*.fq.gz") into further_processed_reads_alignment, further_processed_reads_fastqc; - file "*_rRNA_report.txt" into sortmerna_logs + output: + set val(sample_name), file("*.fq.gz") into further_processed_reads_alignment, further_processed_reads_fastqc; + file "*_rRNA_report.txt" into sortmerna_logs - script: - //concatenate reference files: ${db_fasta},${db_name}:${db_fasta},${db_name}:... - def Refs = "" - for (i=0; i ${sample_name}.fq.gz - mv rRNA-reads.log ${sample_name}_rRNA_report.txt - """ - } + script: + //concatenate reference files: ${db_fasta},${db_name}:${db_fasta},${db_name}:... + def Refs = "" + for (i=0; i ${sample_name}.fq.gz + mv rRNA-reads.log ${sample_name}_rRNA_report.txt + """ + } } else { - further_processed_reads_sortmerna.into { further_processed_reads_alignment; further_processed_reads_fastqc } - sortmerna_logs = Channel.empty() + further_processed_reads_sortmerna.into { further_processed_reads_alignment; further_processed_reads_fastqc } + sortmerna_logs = Channel.empty() } // Post trimming QC, only needed if some trimming has been done if(!params.skip_trimming_fastqc){ process trimmed_fastqc { tag "$sample_name" publishDir "${params.outdir}/trimmed/fastqc", mode: params.publish_dir_mode, - saveAs: {filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename"} + saveAs: {filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename"} input: set val(sample_name), file(reads) from further_processed_reads_fastqc @@ -659,7 +652,7 @@ if(!params.skip_trimming_fastqc){ trimmed_fastqc_results = Channel.empty() } /** - * STEP 7 - STAR alignment + * STEP 7 - STAR/bowtie alignment */ if(!params.skip_alignment){ if (params.aligner == 'star') { @@ -681,11 +674,7 @@ if(!params.skip_alignment){ file "*.out" into star_alignment_logs file "*SJ.out.tab" - script: - - // prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ - """ STAR --genomeDir $index \\ --sjdbGTFfile $gtf \\ @@ -700,9 +689,7 @@ if(!params.skip_alignment){ --outFileNamePrefix $sample_name \\ --outFilterMultimapNmax 1 """ - } - star_aligned.into { bam_stats; bam_aligned } } else{ star_alignment_logs = Channel.empty() @@ -724,10 +711,7 @@ if(!params.skip_alignment){ set val(sample_name), file("*.bam") into bam_stats, bam_aligned file "*.out" into bowtie_alignment_logs - script: - - // prefix = reads[0].toString() - ~/(.trimmed)?(\.fq)?(\.fastq)?(\.gz)?(\.processed)?(\.further_processed)?$/ index = index_array[0].baseName - ~/.\d$/ """ bowtie --sam \\ @@ -745,18 +729,16 @@ if(!params.skip_alignment){ ${index} \\ -q ${reads} \\ --un ${reads.baseName}.unAl > ${sample_name}.sam 2> ${sample_name}.out - samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${sample_name}.sam """ - } }else{ bowtie_alignment_logs= Channel.empty() } } else { - further_processed_reads_sortmerna.into{bam_stats; bam_aligned} - star_alignment_logs = Channel.empty() - bowtie_alignment_logs = Channel.empty() + further_processed_reads_sortmerna.into{bam_stats; bam_aligned} + star_alignment_logs = Channel.empty() + bowtie_alignment_logs = Channel.empty() } if(!params.skip_samtools_stats && !params.skip_samtools_stats){ @@ -776,13 +758,14 @@ if(!params.skip_samtools_stats && !params.skip_samtools_stats){ """ } } else { - bam_flagstat_mqc = Channel.empty() + bam_flagstat_mqc = Channel.empty() } -/** - * STEP 8 - Get CTSS files - */ + if(!params.skip_ctss_generation){ + /** + * STEP 8 - Get CTSS files + */ process get_ctss { tag "$sample_name" publishDir "${params.outdir}/ctss", mode: params.publish_dir_mode @@ -802,7 +785,6 @@ if(!params.skip_ctss_generation){ shell: ''' make_ctss.sh -q 20 -i !{bam_count.baseName} -n !{sample_name} - ''' } if(params.bigwig){ @@ -830,7 +812,6 @@ if(!params.skip_ctss_generation){ ctss_counts = ctss_counts.collect().dump(tag:"ctss_counts") process cluster_ctss { label "high_memory" - publishDir "${params.outdir}/ctss/clusters", mode: params.publish_dir_mode input: @@ -855,13 +836,12 @@ if(!params.skip_ctss_generation){ ''' } - /* - * STEP 11 - Generate count files - */ - process generate_counts { + /* + * STEP 10 - Generate count files + */ + process generate_counts { tag "${sample_name}" - // publishDir "${params.outdir}/ctss/", mode: params.publish_dir_mode - + input: set val(sample_name), file(ctss) from ctss_samples file clusters from ctss_clusters.collect() @@ -880,7 +860,7 @@ if(!params.skip_ctss_generation){ bedtools groupby -i !{ctss}_counts_tmp -g 1,2,3,4,6 -c 11 -o sum > !{ctss}_counts.bed awk -v OFS='\t' '{if($6=="-1") $6=0; print $6 }' !{ctss}_counts.bed >> !{ctss}_counts.txt ''' - } + } /* * STEP 11 - Generate count matrix @@ -903,16 +883,16 @@ if(!params.skip_ctss_generation){ } /** - * STEP 10 - QC for clustered ctss + * STEP 12 - QC for clustered ctss */ if(!params.skip_ctss_qc){ process ctss_qc { tag "$clusters" publishDir "${params.outdir}/rseqc" , mode: params.publish_dir_mode, - saveAs: {filename -> - if (filename.indexOf("read_distribution.txt") > 0) "read_distribution/$filename" - else filename - } + saveAs: {filename -> + if (filename.indexOf("read_distribution.txt") > 0) "read_distribution/$filename" + else filename + } input: file clusters from ctss_counts_qc @@ -932,12 +912,12 @@ if(!params.skip_ctss_generation){ rseqc_results = Channel.empty() } - } else { - count_qc = Channel.empty() - rseqc_results = Channel.empty() - } +} else { + count_qc = Channel.empty() + rseqc_results = Channel.empty() +} /* - * STEP 12 - MultiQC + * STEP 13 - MultiQC */ process multiqc { publishDir "${params.outdir}/MultiQC", mode: params.publish_dir_mode @@ -973,7 +953,7 @@ process multiqc { } /* - * STEP 11 - Output Description HTML + * STEP 14 - Output Description HTML */ process output_documentation { publishDir "${params.outdir}/pipeline_info", mode: params.publish_dir_mode @@ -1072,7 +1052,7 @@ workflow.onComplete { // Catch failures and try with plaintext def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] if ( mqc_report.size() <= params.max_multiqc_email_size.toBytes() ) { - mail_cmd += [ '-A', mqc_report ] + mail_cmd += [ '-A', mqc_report ] } mail_cmd.execute() << email_html log.info "[nf-core/cageseq] Sent summary e-mail to $email_address (mail)" From a61680806405427a9ebd1b5b56c0cd4f43b8ba7b Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 14 Aug 2020 11:45:23 +0200 Subject: [PATCH 086/107] add missing parts to output, remove under-development from readme and fix url --- README.md | 14 +++----------- docs/output.md | 27 ++++++++++++++------------- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 90ab868..fe3ea24 100644 --- a/README.md +++ b/README.md @@ -12,18 +12,10 @@ Nextflow CAGE-seq analysis pipeline, part of the nf-core community ## Introduction -___ -UNDER DEVELOPMENT - -This pipeline is currenlty under development. The workflow is not yet finished. -___ - **nf-core/cageseq** is a bioinformatics analysis pipeline used for CAGE-seq sequencing data. -The pipeline takes raw demultiplexed reads and includes steps for adapter and artefact trimming -([cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), rRNA removal ([SortMeRNA](https://github.com/biocore/sortmerna), alignment to -a reference genome ([STAR](https://github.com/alexdobin/STAR) or -[bowtie](http://bowtie-bio.sourceforge.net/index.shtml)) and CAGE tag counting +The pipeline takes raw demultiplexed fastq-files as inputs and includes steps for linker and artefact trimming +([cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), rRNA removal ([SortMeRNA](https://github.com/biocore/sortmerna), alignment to a reference genome ([STAR](https://github.com/alexdobin/STAR) or [bowtie1](http://bowtie-bio.sourceforge.net/index.shtml)) and CAGE tag counting and clustering ([paraclu](http://cbrc3.cbrc.jp/~martin/paraclu/)). Additionally, several quality control steps ([FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/), @@ -57,7 +49,7 @@ See [usage docs](docs/usage.md) for all of the available options when running th ## Documentation -The nf-core/cageseq pipeline comes with documentation about the pipeline which you can read at [https://nf-core/cageseq/docs](https://nf-core/cageseq/docs) or find in the [`docs/` directory](docs). +The nf-core/cageseq pipeline comes with documentation about the pipeline which you can read at [https://nf-co.re/cageseq/usage](https://nf-co.re/cageseq/usage) and [https://nf-co.re/cageseq/output](https://nf-co.re/cageseq/output) or find in the [`docs/` directory](docs). ## Credits diff --git a/docs/output.md b/docs/output.md index ea795aa..9879bd2 100644 --- a/docs/output.md +++ b/docs/output.md @@ -19,6 +19,8 @@ and processes data using the following steps: For further reading and documentation see the [FastQC help pages](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). +This step can be skipped via `--skip_initial_fastqc`. + > **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. To see how your reads look after trimming, look at the FastQC reports in the `trim_galore` directory. * `fastqc/` @@ -34,7 +36,7 @@ high-throughput sequencing reads. By default this pipeline trims the cut enzyme binding site at the 5'-end and linkers at the 3'-end (can be disabled by setting `--trim_ecop` or `--trim_linkers to false`). -Furthermore, to combat the leading-G-bias of CAGE-seq, G's at the 5'-end are removed. Additional artifacts can be removed via the `--trim_artifacts` parameter. +Furthermore, to combat the leading-G-bias of CAGE-seq, G's at the 5'-end are removed. Additional artifacts generated in the sequencing process, can be removed via the `--trim_artifacts` parameter. All the following trimming process are skipped if `--skip_trimming` is set to true and the output below is only available if '--save_trimmed' is set to true. @@ -90,21 +92,22 @@ good samples should have most reads as _aligned_ and few _Not aligned_ reads. ## 5. CTSS generation -The custom script `bin/make_ctss.sh` generates a bed file for each sample with -unclustered cage defined transcription start sites (CTSS). +The custom script `bin/make_ctss.sh` generates a bed file (and a bigWig file with `--bigwig`) for each sample with the 1bp unclustered cage tags. **Output directory: `results/ctss`** * `Sample.ctss.bed` - * A BED6 file with the cage defined transcription start sites + * A BED6 file with the mapped cage tags +* if `--bigwig`: + * `Sample.ctss.bw` + * A bigWig file with the mapped cage tags ## 4. CTSS clustering ### paraclu [paraclu](http://cbrc3.cbrc.jp/~martin/paraclu/) finds clusters in data -attached to sequences. It is applied on the pool of all ctss bed files to -cluster and returns a bed file with the clustered CTSSs. +attached to sequences. It is applied on the pool of all ctss bed files to cluster and returns a bed file with the clustered cage-defined transcription start sites (CTSS). **Output directory: `results/ctss/clusters`** @@ -113,8 +116,8 @@ cluster and returns a bed file with the clustered CTSSs. ## 6. Count table generation -The ctss files are intersected with the clusteres identified by paraclu and -summarized in a count table. +The cage tags are intersected with the clusteres identified by + paraclu and summarized in a count table. **Output directory: `results/ctss/`** @@ -129,15 +132,13 @@ RSeQC is a package of scripts designed to evaluate the quality of RNA seq data. This pipeline only runs the read destribution RSeQC scripts on the CTSS clusters. The results are summarised within the MultiQC report. -**Output directory: `results/rseqc`** - -#### Read distribution - [read_distribution.py](http://rseqc.sourceforge.net/#read-distribution-py) calculates how mapped reads are distributed over genomic features. ![Read distribution](images/rseqc_read_distribution_plot.png) -**Output: `Sample_read_distribution.txt`** +**Output directory : `results/rseqc/read_distribution/`** + * Sample_read_distribution.txt: + * text file with the raw data describing the distribution of the mapped reads. ### MultiQC From 8290b51b101c8134a6cdea6f2865bc519d5ddc61 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 14 Aug 2020 14:08:40 +0200 Subject: [PATCH 087/107] optimize images --- docs/images/bowtie1_alignment_plot.png | Bin 38608 -> 34520 bytes docs/images/cutadapt_plot.png | Bin 76474 -> 25938 bytes docs/images/nf-core-cageseq_logo.png | Bin 22650 -> 11307 bytes docs/images/rseqc_read_distribution_plot.png | Bin 61189 -> 26136 bytes docs/images/sortmerna-detailed_plot.png | Bin 0 -> 29710 bytes docs/images/star_alignment_plot.png | Bin 102145 -> 47523 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/sortmerna-detailed_plot.png diff --git a/docs/images/bowtie1_alignment_plot.png b/docs/images/bowtie1_alignment_plot.png index b889d94a35d2d1436d4732fc29a3721bea0e09ff..5e213dc2c86dcdf75c3fe6089695444385341ab3 100644 GIT binary patch literal 34520 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

hFH6F6rZ<$=xnFjCsWpgMpsmEsuz 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%0AP3l5Y3Bh23e zXQEhKK}DEASJFCOCzvVH-z6ROXlke9{NRUN>inhXjC%rrMGv}=ObrO6e*IO`R`&Z# zjhA|TI%xZtz?jI29LoG8ORO?j2l1{8Q@NDH-HPD5X3!H=>IQMC5tAxh+g4!@0!bn` zdyKHYpjxv%eL8AzBTjg&XN0;Nc^%kq&R%CHFYRwn_M+PR#ic&)UQH_H0L@@Mx|{6= zcILo?v42O4v|BBX^aaMZdE2_m5uXwM<_R_F$w-x-Y8rY)Jh|y_jwpZPkxma8np;;4 zc}wMMd^bay{b)|1=k>$70Q*y&kEeqR!s#;dW;`;Oj_pf71_xjGh~%S=UQ6wn{88GTW(s zS-@2|>LZK{X0-NFe670+#{Z?*Y;VIkd?b}O4-RGYF7`H!nMin4d3i`Wghb>hlZb+V zJ;?th>&6;p&dJchpJ&g9U1?Kkz98hx>~9&l=8(sxH0k7g?aV=Ao!VR}OTMVSF3VYD zO)QB=P>QS}%Ut#sB zhc5h;wMf78x3KmYuT<(1=!Pn?Fv;4EV%r>e^05)LyRLZ+*@TXcMQ9uJobCC4l%@cQKW7cE_HW5*vJ$nYHGOw?UaAYW%JJ7#pQ)Bm6wL>Ts zRbPE4t_A`SuXV5LY(GP*3?@tFl9pSTc@#S-ZPlGis;zjJUP*z;{AbZTxzNYRebs`Y z1uCWN`gXQC5Q&^mMXB*}D$5 z_8d4kq<6BC@6>I_N4h+mXU~Mt5mJiAtZWJqQam!i`dHv*w;`ta48c#2w(VQ-XiS%EG2T24DW|m&C_b5<8S@!IjtKdo*$bL zSjMK7OEgCjiM#6e%_LL5T`qj)$j{w!dW~-JvR|-mQ64<@5EJBatZzbpQNav1OcLtOeGe9Q}N%LO5a*&Ex5S+IX z*kV-Ovw%$ro8^Mj*YhT%lz}A{t>Hzg%9Iun3aMqXNqvgacd^!#!7d;7T_MVtf#=qa zrEdn^EWE$d_H~=SF9n@_FRaYyuC2G44)(#fggxRF8cYE&zs-US)<4PT^UF4960H0M zFfb*(vMxWkCuoV}9V#3E;Y3M`kV4_+4l}!Oe?Db{Gl9RlO-tI{I=t5P79B!`uxwuc zAObRLtd^}SX(9>{r{wKdj3${oAfFmeS9RKKgvZu3;6c-99e3h5Yb4zG^8+bh8(IWbiXCtfmVXOX&3S1Sk4#QMU>(|)|y_oER!ls?zBqzj*cda(xvAe3& zW)R*^Viu&mM@@M*U)7x^xUATEU%!O z6U8WmSP76RYGA-gIai?E+W@mCBic{0J557_<=Ln;zzV>b9hvH{?Rkr5b7DwP``WTB zOz_PlEFxj$gS}NzZcto-9MC&Cd{scrf7@*}8Rg@_Pz*Ns9P#T@CY_h zS=RYV{t@M9k+Gly(ZW?}8N?CHkA17%t(ZBzrmX@snmaIqAqX_TUnB3bqO$4+^nQoSTlU&eb<>!d8RxuSXUr28~$Gq>9+JJEHQ z5+RDo?nkPyJYeec4Q5UyjN;++O6hc6I?p}=|NW`B-qnE!I*GPq*%FaW_t)ebq$lUD zveqxzi$CNtXYZ^nmm|ad&c*a8_|T35_nTxFeNg_t#76>fb}4(MwcnKuo^m}Ml9f`D JtP%$X{tpkNUxxqy literal 38608 zcmeFa2{_b!+doWQbX{$(RwPu~?Fk{Kt4+34vd0jTY}wbD(cPX9We=CiC_7oQ&1fTr z#Do}3g&5PAFk_f8Gyn6a`?~MzUY_UuAMbnopXYgxe;qjvGiH9j@9+Gc>*rj)H%}Zl zT(NY+QV|i66-LJnpAr%IsYFC%@ur`};T?^S>5D`}Hi;M={_S+={jUSwaor>JOdTsW3(8;xHPue<_{(RO_<-U$U`wVfeJxo2h={D5`OYBh$quQt~e`&q1eacp2 zhfqNj)^Omtz>u{Bei0E-P3i{LRlxxI7;DiAC-P&gfc^?a`vkoHq1U z`J%%=URrXE(P1cW)~?Sv!yQElrTN*%m+?4E-)btwmnh5M97CF$9wienyw1iL8S+Rn zIx{>xytBxm_5rHkWQJ}~-VkS^I$*Ssk8RX&(w};xa2eGTE34;k5GnOE*)e>VvVEnJ zLtw`dWumovYfAi=*3`R6s_0BP?Cd92qm1ui++&dw`xmco*jpCP9#10v6!X3{RfGJc zEuBmh@|j~2wKimiM(EoNz2q4NC0Wbs!=3d?Ht*O(-qUsi8NPGuh3PMCvhtj}<_0j_ zhSh0e$Y(lmqcqjj?wo7S9GLV|wJCAxXOg0h+aH6 zJV~WisVzfKyDdfC`RZFssJWxnJ1{bN8wbJcoQX9~78P^LtsdN{!Y z}@;~BD2jiePwPYeMB6tX0lNxw<}7sGue_q z+k}$q;caM-V!t~iu|g0sSm|v)p?cY)fbYke8_mip=U_g+x*1FD(F>W_IKw~*W{1i# zyqQ3HVb$@zCJ~V!H)L%`WlDAK z*D2>-r!`?JF{#R-;zC#QY&>=@P0cAtBSX9Z9yM^e6+@vrRIu*I;`M9P6Bk?Yn9VC> zv`qVW;!${zS5t){>5?J>cRZ=8o?cXY6eE<6{PtV;=bJk^y{iV2REYCadx3;|-QV61 zWOrHTnx$*yIMfCQMT);Wk*@7~9D~6;DK1v^?k#hBmF4N=w8{HJiSsuGkIOwOn}MAp zp;rGe$-mf9cYtBo3#F$S)l6UMaVK-+0U^W12aR zYcWozn^>RmJ2K8-n8DqRNXe?^_LW{nu(szZgH5i@vLym;53#cUX6Y4QOlqwY3KHZLC=cCQ)>+3xP z^K%{pH9?mjHoc=>?qZUB`lvo*CqlR^TA+~6$rW3+{*mp|b2$i`7h@Qn@T|V3#qBIQ zT39oJu}0yEL=<1ZA(~q|1X-r(h4>&VmPAMT+0};!_4LT_zP*$nBg&#KY#Lb|^5yO@_|ByEV?@qBx15rIGmoS&Wa|_MTOrd4+U6(*RUOAUw1P8A2jb8u zR6#Je#hS2Z)-Tp|kGy>rW~R6N?CV>5eFy6nb{6OxNXtpazmAs71rqTH_oSRQ?D;Ea ze0iHenW_ZY>c7E^7=4?eK=?JXYkqE;T)}S!JfVfPy4|MYa+L+gqXyp_k`3@v*w3)yd>~_aXd;= z6^765A-)%-zlm3nefaTMjF!~#B-$RQ3ZWc@fQc~PmGkntL`c8SBj@19Pd1bUPxR{) zQLPWjv_}O2*T&H>j**kE6$n~3yr>HI_RQFJFPS2jrq~>`klW)DP64jI9a_~qud!zx zXG1%#>E=osAsa31V)MNRYAS{_4m7!NCI(ytzII)0t_Fh=U4l{iL@iTpx=AyY=zBcN zU|@1&_$8v=u*+>k$Zu@K3#zEt+96e41&nwDu)Ch%I$xVG8N-?#ip%YBj8JCuKHV{Z z6Y?F<#gF-pEZGAQdDyh{s;ZpRSCYn=1DoX<@O8arHw@$Glg*LPdhhiOEt;3LJNXIt8`P`G}fvdE1E8`RfytCmU7L;NFT8KyX}r=3AP z4n32}*FoJlQ_)q#0^h#!Cv@~m0o*4CB(S2+n@3;g@a$sth-#X~xz;gm>aU2cF2VKc z1bi`Vq97Dj_I>IzP!n5~`X>5WT#!f@Ft^>{L|%T;_^elvKp=>{^pO<$8@peW4*nUf zv`J3p>sZIby8?BC*^if%<%iNVJ?#j%rdU~7qQuO^fZjMSo@id*4Q-h`%$2+}F!4>lK80^OqhcvO zwS^;^kKSgXsOmHGQ^~}yTy@i#toSE&J*NpbB8<^>!F>y)o<(f41W&qjpj;@;q|KcT zlwr~n%w~r8CtmXHs=Rs=z}?dR8khc+s?ETyKgyf37r{#+!rsYH-Se`->G@w+TzYZb zte{VL>RXI&q|2)+;m6Aoy4Xxf$I$E%@Ab-d@2B`6)KuL;bDl6c^8A2-{nu3YOpma1 zkc`41Z~TP@U7R2iXkkU7tl*^n%s{UUnHx!tt(Z?p8`Le zq%vJ4Y?iFtI5x|l?I8++Ud4R^;(CVhCRf_nSNSlwGYsNr@w3mjoKe?&7I#mLko2xa z-8&TyTBR1d5%k*m9u5ZanCcv=CPR0F9vrF1hc_70qC5ED4t*(!3jpItYu=HykGPCD1wV*Ww3rM<(`Gz3PRQ?lZ2Fp+KJ#32RD&k6Gw!e6B;ska1U#T80eoydY%3_g zqkO48)FC(ac$YF&7>%BPFv6>?FY0c^k3(S0(c=&PfVYYSf^XSwW0C`IY;>wW{nHHkgV>M!+K3D z=Yoe9Gkcb1?HD$4LwNo<-Yi`g+e#G*IDR-K3w9{l0|&M()7fn|mRgR=Dgb?M+Abzy zDj}{EFtPgg)yXnB}r11vBj@!oEFUV#sHk1%CJ8Bb{eBR2=Tb;_hQY zJ11W9&`Rx}t^3gL2$U$zb)c)J9MRoTmO8;-ZJOx&DumdtGj4gia$;4NWsT9b%({j! zZex^I@aIkAA}l6(c)rG#2ncohs{@+$c8i`cSg>}T(a*AUgLWf||kuJr8d z8%)ltn`_p{l^o^j_ZT?E%&3;exHY8RLMd2;6{|)x$?l zCcA~eF7&OKe|`QL4s#(-ya2+MJ#)o;G%I^Wb<0V#sv){2Up@e zCLaI(2)wAoQ^w{feqa-m0~=OVXU0o*5kj1p`K}#S&)H?>)xg~&XHNyo6-ZL9TF%pr z7f#9x)oG|5A{I?iz*D!~8;qY!YdBrQYMJmF)cVk_iU>2T0gk@C z;6N3_p#wp;B=dI$Ze;Wsd=LGctbfb9^+4&jZcn)d*auYs<8u!W*>G7 zbWiK+>(g%T$QdO$!%L{lNC8-)a1VZJ}A;w6oLQrIG`RqY{vG8h8h|^9h{0Xl8Vga z(EhL~*QRJMZNCK}M}LW8=c4$#=q_y?0=K{rDkg-);jr03%T?q7Q+bBVe1fgZdK0y7 z@&otl)Ar#0Y(7a#bm#Zy0bd!ytXN_8puwVwID>~P&O#(Ei#kWfo4E+)t^+N1FJ8P@ z`Lbn%YTdUNH{|Vk(K9PC^~IlVyNN7#KvEk0#X1LXLP#B24Gx+gfA+du_~Rj>(B8Mc zYcd%4M}N9iLl(sZD_BEde0q7kR^aJwwy^~Nx&6)Q!F+yu>&2{39JljAYZnSi=4(!} z0pIt&pqLN5!01_#26n+T^xvOJs}=b_U#eW?9_07 zYr4ZcbK}gYul#l-EHsqI?EOlq!fiL}LSl>}Um|!7MZPGP#@i=_sA-1qF9S%Nv5IPt zQ!24(Ks=Gp&ybB~_(^8-@5e_Ja$tIV%^%2+ev}fArl& z;hA|1X8@QgEA;bCAPGd0Cw(w80mdPq~+{i;k?Pc z{mDklImNHrGWGQwuyZ3GgLPpJC<+pL$+B^?A-t*N%*+Y&%A`}qOrlWm%wQ%P9Cym( z5V8*h2p)0~90AN+*-+DMcM+Y79~(-tf;2)V`U6K2t?>|f21YiwWgohJl>eb=JRi*; zzapUc_CNFc!08o8cJ-^~UXWjnz&yXyXZa9Au$)?IMP1wJH|TrAP)oy zqgH~eU&MSmvDnJ^F3;U{Hxt5wCq?q32s{DUKqp`%S|CvOFEnhhgP5)6YZtNW1HX-IV~;49LTO|2Pv zRYR)oE_0G%7US~;88aNR&;G^7AP_0C=0&T-b-S*#88EPLR${Z+D|iMw0vZrAq$h~T zGQfntU>5U(+KRxRPhw`}f&Nw%?}&H2>kUpd4T%aCcY~W#OCW9sGMNn`o~^apeH9)6V80|VO;oD4B4F+iH-&;G zx;-O)wDzfGR3=r)x1$QN0K%914K)_YM^uT@Gb1Lza>?oi-{uA^U%vbiqA*>~(}VNn z1>dgQEHc(3+_hMZ=9304+=RA8YIG)w2(f$ZgmozGbDvyL`?s>GOX)5D%R6ZSHnVjNg#kU*ql*MDPE6z6-V$ zkuoHrH^jXW5s88Hg2>osST~Yj@?Z|uFRTRt@j5+=>yrS+S;Nm371`@j9AXWA?YWsve7p$2~0;_ki9Ku8ghw3etYHSq!);6@Ypi594BAn{$QaY~%H z5rKNYeiEd5-VR!S0& z7G8e;?#qEcE?C-6TrRFuCRK7aY*WmL;E&HpP00QIrfzCZ@vo!SkrsRW{jyCLISXr8 zxQ^;&(P$-DvfQ!1Ulw((_K$VKo6^f|T-BXkPaXIVpT((ROSGtB(vr@%itk)u{M7aOAGHAgg=ERu zP%<%#6Xw4Ww6_&|F6Ctjc|zlatww1Nc8lNp8!NY|aDQ=tck=?)EjCu-{8fm~N%F6# z7$t1&s=g(G?FfXMJ$Y-neCOX(L7D?=O%2@a z^yrV}{-Ev;W&p$VL(~?Wgdds#@lt*;!w+Wo&y28{22!&Gk+LZQov^MaoZ920S^v+L zw!q_~1a9__U2U+pT}_~e-Ls3%$WM)cOMi$exR)TBPx}}1ZnpT)b;ZR=qWO>h#m3_= zA!SEMthxYk1(MCgl@?p6|I;N>x)*m}T_)KH;8G{Vb&v-TmiUH1AQ(9OCO!}_^i@=! z$K+h|T&SIh1=h{g0h^K+>g&&%)B>^Vc8bP*R9 z?}XHO`a&*v2r3Eo(}=3?*2u6bxW zG5V{Yx;=v=OO-g030XZ_jP{_^JaGvulu<>^bi}Z`p8M)SRvNNwN18rB+Ji~pO?<2> zwkh3`0T}%^9#XXEyrdvoo}2~I_;X((XE0(3k^laQ#oge=|MuDPMLoyd?PT|dUOdQj z8Ixj9Hpxq1d4OCkA=XnoZ3@vu0_2D=m0f1q1MjC8fNsk~;wY8g>F=8QVnj(%mZ$#7 z&BM1vX|hZfSwl{ALLLPfp5yoT#mj|$yi}AWZHc-0siMb`!fpzYDY=F(|7 zE{`z(4XI@js)kA-Tx9gmT%@(Q8=(3nO%I^{B!<>hClv5JASWQJ+A`?fkmnf1uch*R zdN^I)4I8-XG4FxTU)G`LfBlcH1r>?nOS1JQp1HiQ5<;#%alNWz|5S}t$Y7YeU6qeR zk7#~4WpcRr-z-k6Z2WScM;Iu!GqsRv?*;6u6*GhW8KRuBdNsujPUgPR|cM+A$e zdm7-uf{~#7?qYNn{7|Q6y4v;L57q;BF_B_6($1t#$>O^~Py%FBd+FcuMHiB%L*PI= z@tho!=)10tvp}ZlI3LHk~Zuy#TRcMS7OvWw25rUDr zJ6|Fc$svU|&v92T7O3i??jso!5BQ#}>QOX?0yPy+2XQMGTm5tRqQ(#}fKrS3$)+Vu z+1UAi8&pusCViG@Hlj($tob(CM3eISAPoaQMd#lGZMXDE&x;HXp zWXZW%*fdCTXv_u#LLR9-P_`MALYf?IezE|~?94GSoVQ+C4Dw&V$$A;}FOiWcNi^S| zHP%rM8@383Y8boGs5XQtx3TgXmIv^B0#aFk&+-Ii;QE&sONA9mPm)9^dZ3fH3R>{7|IQa#(ZSFx$V0w2yJ&Ka zAJpF>TcjQWzZlIYn#um_b~rU$m>!H^=Ah<3Nq9gNG!68a38JlaAq&mAZV4*jpLg&_ z0Qw_d{((mP08f5shVRh!4a8DSnXR zA2Y1^*?FHl%C=nl&oZP|hono!pa00y{xuc$BV`Tg@gLdyzg18CSCPU*(`jH*DCj94 z7xvHBEFHrMm_kKJvl@|ipIs|oKY%XCi>(mErIjrl6kZo&@f&!SWPi$Ac zjIw;jgaT;BHpZJLw`Dp!OA5DwGv> zB2~AuI0-0(hWR4;_0a!+nHmfUOQb(Pwp20a-XL7>xi8Y~YPcO>7 zddrHK%u0$6T?$D_f@rtTcCBE-loa{-vgi3lHM=3becl+GdGl{lZnVm!59xgfWK{I5 zTzRyZDBza(Y6sdN&F3V}3fU462OY@!p)@?9I9VC>1;krs2EDn!01x@;in^Wiu5*wq z)|w4KL66K`fgnKoPmEtEUI0x2%VTvw;Ea$~l#d)pz9~UdpMD06Ey%eiPW3^u$uB#R z%vfNXW>27O9#q$NPt{l=iV1#v!+7JPvKQdym#G|vFRs>YtqCo zq>5?PU^xATFEWON^*LG<54}XU=P>5(f0pY1-8|eLCq%VhIQ2@+X~oI;ornQ?|^jM z8jq2dM3)KpoZ9!YdezDdK>^0my!`5t|Yw}fDFpvHL+zV$Ah}Vq!;1j90nt-gM*lO@>EerwKSU&!CKRQZ|dT#HJ&+ z7C*|+^t74wJJ;6g+09+P`O2>cf4-S>V8v3UX9q7G*;(@Q!aJKw*FOI3l9)BT7F+-Q zovlfWG5gddCgL8%1} z`oU8mBR{0?ho1T$raX@*mi&ISJgXr^su8XH$Nv?L4uAVyxsfWfU@?;Hz8>p3JOB6p zPW^xX{p@`Gr3GW~Z%EF1P^m7EN~V-aQQC2;iMB zFmJ)+$dRk3PoIAC=FN@qwwpR}@~EU+x0cSad(f7?#-^Z1KUY{QJ4S#Gt-r}R5^qs2 zk=t-<^TUS^kqg62JK|PlWiuZtLD|K{B~RPaYN_~Tf6jzMb8G887%OqDZV&=^C4($; zEua2O&lgQnLse0lzsku7Bg>eXSddC;A;n& ztN?$Ikj~W(g`&&#@HHbNqotLh!5d^{6VW)nB~&VJhMx6ghzMI?yvL*bd{VGOBTBcX zrsjpgOvO)&M9JZGGe^F%r8myD&=Od-%-kSL)V7FZ{q?B9BQ?OXN&Etj?1C2UiR0u{VWtw zD6~8krVsWewd1uf9#S~&IrP|goc1oflv z?Csyam3Z|(Qy(TkCAc1*KHVqdkgSSMx^m^GCQjyYw3CKljmDlmTc9-gUOP&7CLtk# zRZ0PJKcgolC+iugLWQZ)bEkK~{8RzqF&=*u=2R#`fbQ`I<6GYSorOfrGxv8;KWy8v zg9PJ4U169JH+IvuZLcR~!cAKxQ1c(3J$%%V7H)T`EOO2tW?4kJy15x$xR59Cy>sWz zCI*91$(9n1+0=(uY=uhzGBP~ee7DS(YJl;=7-V_%l{Z(e^!jd@%1j0@<3{`FQ(4hhvxZB=lEPtjfhNWo+80*! zmN;L=+MYf8fOagKzDs&L4guE;I#);gG`k~Cbjnei2_iM{VwEDqrzt3=HF4r_*mi#<@>UTEJ2gU zy$27rR7Y@B#Jcykw6`b2n9N=kAuTuS1>u9bprfO=mlj&BMfl~HUn+fTL)U0)9yK&H z8`&(@{hqwEpex_nux_Q8F-ys|>~JLEo#8zWheMe`0hhq&hd01e8_9!%D!X>=`aC`7 z3Sa`B9mGT#N z69-VYZ%w3Dy(-L52z@2i?fRW#(?(!{xu{=3_`OIlHYHnCRYk?B;_SM}rGk(w~;2P{<;HY@@7cW!QuTv4qt2s_1A zugCIhu-x~DmleQ7ALD}u|FU)a_G=m6))pUr+OR=N>JH#=hgYv&?F#HO|E^^p45Hg+ zkTva*_DM}(k)NAuh-0+1ww5c8!XpD0u=%qvhS`)<&JlKxio^EBr>Ez~JtRjOH~uBR zq~rwg{$$9Gghie(uzGWxKvF$98g`L80%|EfZ;@xs%%`T5XCm$FeC}~e%S3~jra1X3WeN87xBIf%0Nug|+;uOHja|u) z8GuO|hYxSJbdtvXdP)0Te8M! z&-`DyLT5U>!qIyN#JU3)L`{cr$n4omdPT-_n1o~yW3N?fhHogt^5}srJGNALkhf!$ z%rkUHLS-9K;kT(rFW3?ytHCPkI8wRWiyl6F$s#>gb*xMI5}_90A%?K(lgAmyF1hW` zhy->bSI=n-f@iU9+qNS(vX|*&-_Am@Taz+_b#-;L{&{Iq=#|S!U@Ti;f-y_JxFb_i zR#p}tBrSY`Xc+T6c^{v(pkWm?G{`e&ju{&#$Y}d~C?dh5f}cV+tj@vX(_&}7GMPQ7 zR$ipR9Kf?IH?X;*; z*c9Ke2g|cRb!tzHy=``=ya~US}Vo6%ArxEUmh7ba_KfI6F_ktT_96DfZpV9Q{!G-al#q5)xLERe#gX zIOwT#;x_f0+`fwkp095=ZIsvyZj6dUjjNr{{?%`|zg?Tm+5k=v*JcBb-FFN4S)D+I znfO_b*UryDo0eG*h;=x~MSh%{vGJ{0KDG(Bm{E>h)krP8xz+}aoy!@T;&Q|Jx-g=q zOEv4C9^Z0n?ynm{N-nxT5KB@AHzuo5Im6*E&wmH&ep23q-Y;QwTlijj!-hQ>-R}km zee8T9*SMR4NBBTFGqwC7cJ-PyZeW@5=Y1c*6Yqj4HX8M%YJ`&-FyIUQsXkR7n&j9x znOu4GcT3m0oU*W3=S6FEn@=18`>5k+sJB!fEP9~MkUR$b%I+qA7#`(ZjBM!I_3Oun zax-Rh)zqAH7j--{z0xyyUN7LwZEvN!2??e`Ef{*<0Xdr5HAa_mWW_Gq{*8^=7r-`haT=0m zSuo_uP`(HJO!6KV5ZOurbRXTS3_jP{sQkWI7Dh3VCfoMG1H#gJno4VH^}Ys$fh`5k z@>cukep@zVy4a;D}EKEu#4eAn$-J3i)=~{!t5gj>te^Q9u30DWj`&#%kKvz zdMY&TTpS3%xJx*5P@lYKXqVTD6)W%-K4HqS_h&Y{z<8rr5)9mW!X(Fl7UY7$Voz$k z<*ZqXxCn#S=b+_{78kIhxSsrSUs0n%=y$scTCymP2GNE0988>jsH!dS|AwffjND)I zJ}m4Y;v`f>L$g|`vJeqzU(sLn@AB6nu5VhOFg5f;-cqnQ+-K5pd!!{`_ihKghX~fW3ks10G$xse7> z3JWbun>Au5cTQ(!%2E6oYY%!pe?4oMJSn-U(5-L{D4#<-HTk@~?*$IG#Z-#xEqtAv z4ye8^G-Rp?CJvthL)O*daeO zVb^Hu>R#Y(Ta()<8=rpc(zY#~Ae6cpExNn*-a-o4wTE6maX5}9R#wOQ(YZq zTos`;HZjrN-1=eqw>}x!#vW2ji!r$jyjvQH zAmDoP{SlWoH@8WvngfQ#b#7{eYhw^G(^~%BOE4Mckbh2AvOUXnYl2MJ*wDtGe=?;n z@TP;)O;aWkxro<=PQD0~8s@U;?CCEUg7w|3siV*9Au2OEejEu=$Zu6Z5{dnNgL({+ z!>!lliXCc`4&8dG_I7B!%JJM3H9<#qeYVZhb1`50t1aL_1V#RytoAv{;~9gmZq{+X z_-~i5WNcfbTyppd`N?)?@K+P=-Ft)*^c2{-^l@ycTch_$?%eXlDE02$yE#vv2GmS6 z-VOpcfUHe~4#T@Jh|81+Gbjz77QUP{jPpAGrM|kiWd2#0>o^1 zi*WFSGvSy9hz9OLpS2B?7;FJMw6|WUompAz3{HM=vAJ-$+kIanis6nOJM`XOlKS~4 z7AG6NT^2Tdj+~s={dCdca{}H2gkUab`yGd7^+UgH+D(5l2>kx~hNPbU&3nCokOLFXb5L8emW!JiIh*imZ0cekOQmJ0aTAWG@5 z-SS1-ue!P#@7DdYa@n$Fx%8se-F?Jp@~TQiuA6$e0i15~liR+-PNS^8ymd7Y5{H~I zOn=x)lUxc0K8M-}U5v80D6w;4VPUaCaR@Jh=H~(st8ch>AI2%<1*ogjR#v)#Eh#f{ z)EeOzutE^kecd+!nlToA=7ySJjobbft%{q7PoUS7dPgI5Ifd0&7B=8pJ zub%TQ^^A;+QzuSrf*A5#tfFJe@CbrLz(Fq~ zpsf7)+#nB6Pm6k6b@#x)(-VXBieTarJ3CKN>RcMU*8lv|@aNaj{xIUNI-I?m_q#_Y zTytPa49#w$J~8z%^z zUzZo;!CCP*wy5~U}593g-E_U(#~;u+AO35kh0 zs#FBrpuo{4cY%GLn6;)J{Ak5eQ9!?KK;S%z4lE;VO zdh6!R&jag^wWLliEkM>rf*^m$8$9Y}fW^Gh^*mt|+a4{gbG6t*hb{wXVWfJ$VA?zJ z-n}dRgK+XndhAkicQwfWhedQ~!=3^UM)&QcrH#$LiG89XQK?rE@;RmHBp!<2xZM$n7(`E^`QjfvItIXnKnUAkRyYmA2h+Q4%Uo~Lglkr>-Z)CxljH%;Xu{pQ zvL=QhF@TAVC?rBBqk*p|MuIZwQJYDfn@-HGy}cZq;iF_ zJsKKp(yd#!w$w0Ah;;)&X{_g<@+lpspF5opQh-|k_1d&$3mEw_B)k}aBZgAC5t4z9 zO~Lk-fFp?Qnx>gl1AiX7`N?0#GzW(7=3P=bJq7y zmJEP4#|>T0u9Y_Uw?HL_*_s>~V9_H)M{Db3@axhZWZrsMYS+i_{Nvdc9mYXZ;18o?Q)2mE1?PfdnJ=98a6O155EvD z&9<7CHov(a!!3tJ9o+{fnmKLHMnLG4qwz_HyN%u*lFe})*}J6s-Mc$aOm)E{9;)eX z?m4tgN2j-Zu%RIe#_hid)*teSZd{ZPc8?ed0=$`N@@$c(mzSxq;;751Q>PwPSL-|| zg^Ow|`7RJJueAEnqeo-8?>vsgvG*{97N<_VkkfQqcVRUrFK@R+$HR=W^X1{}3z)fY z-!2};sY)$R+wMs%b-9j69k?L}GY{@lQ~Mn)0Diw#$G9k#gwM`?9ymS}+5@MbX{&_Flw#c3$C79?+fYT5y3H6gkRG(*yOb!nNOpGTpj7?0;NIif-rG0~g zARN#$pu=}5Dc$SuKf^D3@!}w#3ph;TflZshdjzBEl(yLO^{sVy;@zw)-?Sk*2xe!0 zzY+kq8fLo8(@uc-zJU>(X1TvrR#m0PHjGb9WU{1Sx0nlzaN^xM-EKW{80c8BilP9HST%WzVy1QWl z>s@#Uz;ktFn3j;7Z(W>r+;A^~v4OgH18QJPT8PP-<>DjHFE2sVJp>GiU@C6(fM9-C z_lSx9pOD-6e{>b#1OI)Qr~jtaIUS{k^=_$3lQ0>S&2mkI6JG-6h|Su`!gS=t@W5nq z;g^@4(`854=N1j+dCS~$adVjZ^y!@Kv*}CoVVDf$Co=Szt%1ShvA5KTL_#v8wAM8I zw6|h^5Yi|(`*!iEqs>)PfARQ;)5#r2)_?RfQ;r*{e`Oi& zyiP^P5l#!6tt0mAEE5rt0&N;4oh$IjjZQ{U9;vkFT7D>VNo1DEh_R&30Z|Pdx*S7rKsQuHqwqgP%;M-hK38P20I~A zaNVc}aPaP|0Y&>dPdiH82au`#85Mtl`{QSaUma`0b z>hcnaw4~&F_e{IKM6^IPIg7U+h7otAuhG1#KXqYu+^cZbSUk&hP&hK|VNFa*iY>1$b2#4GB5Z3CJ4}CY+8s<9H%L!c z_d(eTN3}uhu)J{gx(8UMk_XBe28D%%c;5ZAw7l@UB2H((*F1M6Gg--!%`*pr<0c_+OA2S+*Mqz)IYarH^mLJ{6aN`7yKp&91r(e z0c0>9l<99+TF~pRWl&t4WO+2Fu5$|FSz&C;eVgvlpvcI&z@Q)=h_QhERAXki@}bCxqkw3U&QOPZYxrCjF%=yc7&w{8&~4q3y4$2xM7 z8myWYBOi!*6DrlUh~7@8Z{^iYFX_Dbv!xSMb?+M1?Uuj*CZ3kI0ZG^v6S&4OE@%sY zb-{HoYwF8bRVkc{@z_UU`#D&taH?nc@p_vD=1;CAJNPD(r*(JjYM!jIuyu;LefyY? zPf;Y08II7rU}Rzv-REt1wvK-c0u7HjaL>wpvX&wQ+yac5*)v_XZG0p#>AY}{GkBIR zzo@yt-3Z+SKUWWiidhw;dCLbr#IO=4Pamv0xXuP*xWrO*Ua=ekO-yph4oK2R$JvLJ0p$zIN7@I$rYcg;f|xDqm&}OL@_HIj!3Hne|TdBCH8QE-0O`iL8MY| zELs*dIuM?s?k3hNs!SR!9?-kywzfoYE8-%AOO`AF$oi;% zK)^OtRr3p;o(j6_TmVpl%KB|^Hs>9Hh#}3pKE9XpTMy$E=L4?<*#={cuU|K} zrE7clw7-2D`?z6ze0(YI1LUwYm8%RKUtqp@d3eOXe}9@h1-_E8i_63P;jA}-df9SA zTZ%Ka8@<&8#|}C;WDE}v9}5bq@HQxMQroGisp&sI>$hw7?u5a?ce&dnR<1OL>o4Q17*>Dk_W|9W&vNA12)Q_VnD2i7|rs1o`msv`mk- zH#w+UW%ej)Gtv?k(Is&663xWfr}^H?*map2?y=x=z7HG#gc=S-frQO27+sf8SGWI3 zQPIk|p)KIpoN{pRu3JT0#6V!P-L2p51tfbA$kJffhZqvH<;&=!05Atfh$8v;QR^RIC(Cf`@FC}tJSOhUGg7kg8 zkRl{1VSV{F5JFv1?X&kw1LPSKpns&#;PE3oz6Crsv*e2Ml(_vGDiOf>Zm_!s^WP3p zyy2wF#>qB+HK}{xDe7WR+=`2nh-evtM4D{RG>?zxX~-Ci3EY}|Ev%emXPXDEkUlL{ z%C&Gp&ab(#v;gq)tC+7aDvn%US60?pzQ5lE^?v4p{JWTfxXFtgK8&?Gb^5fcp6osY z14k+W5>ES6s@{fZ@7=owp&e&wUz4b@uyo`j_WjP}yRJ%U`OAn-fm(kO%Nc=}h(4gO2wx#Y*5>QA zU0Xz|Y3r7VK62#9=42wY4dLO;yZNxgalW|_l44YU7=h8TWpYpY)s zU}yuC?6Zt8ean$9#5sUT{o8B%DldvzojG$q5_&PXK~0J!z~yEE%~x9>C}k_$J^aAl z>1xDs&t6EWd+S$;bwjFYJ3pmTAfp5)7Q61+C@HxE%6IVW+S*z-=udJM;>pAF08@PR ztky)d=^{j%YFi?zR7yrhBV+x;jHKxss%ra; zI1Z0{=gpAIJSmn`QKx3`W#z_wzoUKl+g{L=N&p7%GF%E77aQa^`4cfc(!~vXVqd2F z5~Qc*)M55w)5D#&b7u{3f-`V_g#w(1iU5Ac+}(4L;ukx+G!NO_nF~)4$)~~ z;Co0Rnwcen4o94LIG;${RT=^#uZWCLIL|2uVhLCz%VI!b@=LmJ3m}Pz>gfa>g6Jk2 zoAcoraH=7}TVGqO8zk5(js|h12`IrcHG$1mDlyhhwppBR5}f|%YKMc=2z~^Bje8I; z_080GE9j^~g0GeV6h5AppYJ{7%-3ElQVfyM$1siThTXe%bx?oW5S<3X-o_GFH!v8S z?1|}LYtt;!s`vw&oa|siU@?s@cKJ8*l1_NwlrO(E zx3nys3xT5&&)OkvJ}H$?kQ{BcD{NARhgdgcP)vmeFkY{-I6qMyVR*=4li83TU41ih zb;wW-K4)xZy+uGjujlFlNBq41@3aQ8`hrLTlIaDN6$SGpjgbFj#+c~lkI?0w0jq{mt zsEr(=#uRc$8HX4{4nvKG?_R$5@V)Sy*)A2j4_8K2`87D=iRts6!YA0B9B_0cD-OEzWGi^^S_*04&uySq=yvdm`V@T|>4 zGIRq*?m(@(%_aO%tbi>$zqPw?{L>)XW!{ao5jA2n1LOu~fE>x5_{+kcC`etlC9FYX zjll;yLM@G;*lb(5G0@>73RP1$mbW;GHMCmEivG9R?>dV;(N7{}`8oiu_Yb6cHXLib zDSsgLj#p87dPDv~;^`W{yZ*~}Hfo&;K@W|EW3RQ}%7-6JBSylW%8MbV-PD+tlnA}L z+K_eijE7hm5?U6&b?^_Xxhs!M|M2|w+EcHeS=t1dJkKMd5{d-+Zehp^Y--lLl&CUi)5TU7fZoldQs~f1%T} zoRhUU3yape7QZKi`I7Qy!1vM9(*Z0>G1h3RYB$<37KU3KaX?-~+cgse#YS#ocuJnL zePbT?@1v!8Z@y;aFIu$fl(FHjmJzA+s?v8KzO9&!^xd3I?;n9_YAR#}*YdCk{j;zY zfDAj>q7~+Z!13Na?VWcjY&Dn4-$uga`+X}~8+~qi@FPOp1Kb4&0w5o{Zgp~A6)kyve z1oIf4cXNfF4kimszZmYB`1oc`MjaEM4^^C=wywIS=Fy0^(|^7=C+oLc+#1^Nwv1Vn zE+2p~v+mM8WvwmEy5j|`p7Fd_3yB^_+a!J-o)^(@L5fdTFvVy z|GSOtpi|3N@I$Yw6zu>6W&7aq%kJ+WZklp*OxH}*|kPbgc<{Ff9GveX9_{x*l*w3+Uh!cL!au^?nw()lQ*=H)G|FjCgiZZ0v7_rG_07r6XW^Kc69>PqX|d$q;(Aj#!|&s4}}J z97`DJm{n>Nv37?_glp&#KuFtZG;17IJB+nrx>1*dV4}{ z*q$#){basftA!I-7AD(_Y)5js6qEJC*Pq)>Lyv%joc$09)DEUDH#b+h@??Y+8R26Z z>=FE|B1z27P|r^{+asja=62aqspT2%cT`A%x3bkf;M=MguE-Gw-t=_GT7%m93P2>f zY;Zw8{-|)!@OW3XD5;daB$&PTTf}%8w$J42)gk>^Sy`{9pSANvlWSeZ$H!9!xk%V4 zzV00Tx+XrnJ6lzP*x{OwD=T|^Ji}KUela}BKW*b;+4yvR&Y&l1^nJzn{AVq~bs8?< z^~tSUnvXl2DDkby_k4CyIK}wc?CdP%%wfq0LunbAf^OPl`vAAFA_I^Q0)JOn*Q{b*=tGlv`-xEi~#avXorh#SfmjKUC11UGz4kxk52f0t(dGDI9hi%yTIdm`u<|LeuEoq zikHsFeH2v|8??{&y}{cZ&RZPGGyUdyU+G01_tNP6SC{hRC4<3+FP$$bWg{Q$#}(Pp zxJKL*dC@wgRIE5)N-T8cKBq~NugP?8WiA|)w_FY$fACfP5n25Y7B}*{)M|(R?u^oqT7~j? zTw5R=kx4Q%2JP|W$;&$N+HcO(pQ}!~kI65&))saDzDJ;ms&)3dzRF)0cAvx6)#J{i z5P*oeX|gSFYBM=NE+B}8SWKBm z-9*`O*W*ar!v2-l9e_j&xs8dz>0ZLLIlHW<%*|K42G@aHHo_`|Hp{l4 zVZ0(PF0S*IA8P{XL_HE8O0pC3JZ0Pby6Lgo4sUcIp9rN5-@=G!$hwn0gY z?dY&gd-5b(rhAzRoS%oStQ6n^NjZO)@d0*Q@*_H)-sdi!gHqm)?0w=Bb3J@$R}XNX zNFrtCAx8=bt2hk8NeufgGnGfQ*6F}zNnR~}QK-zYBT`<@N79AMltBkuv~ z2?Jw4+~uvVrKN}i3h*^KC&%Y`L^wQs#0mhfefu>0yn18+p}$n+T)Id6W+{XBcrVsG zqBuJnf|AkPq@ogoCx3196nutVjPn-o5T^KbE^EXF<6&>j=Yn%E@;AmG#p+#Z7 z1&tBlEVAg-O6v=nTJcu~{nqq@5XcI&_|Cx!eDejHDxID%ivhGrzhCy(3up0R-!H50 z<1KIp6149YF^OoMSA}p(;$$x1hz;^RW$Wx;(2-FI-3trJUPsN%Hp*n^qHDw#Ib10h z2yckHy=;||d4hfnXhCCS>bUg72=Ajx)<0;$`t&1Dr9)~~ELujzuou4m7h}x-zuM(s zi#%Z;HWHGswD&8!5!3wq{OS;PEWP&|!tRm`cRJ72WG8Y{^0g8=GI5-sV|yNnDIS1V>*Sj($_Vw+4!)@EgF7 z#t$DH>Nup#0i;86TAF)H2uuv7-)NQKN+W{0VPyyZ8vDz-55>WtyZ};&?F9i}i4^yg zmg-2#$ov>ows~#QKW1Fz#Ls_>&9aAfV@ zyZ4H_e%kx@cJ+02zfVp1S)5k`L5N2jiw4W>wVR`6ksFhR@rjwl7u#zfn6faO*S8H# z7Q~ax!IxVnPbnFnYinyGGwRMQc=~(HF=M3bS*+au#c$}KrNX-7c zkgxp`0zMK4ABF*PTfRTB^T|aAb?sd+b6`KP_U(*OR#Q{!_0Ny0v8{Hi+#3hymc;7X zq|kQ|%2 zp=Je-`^ z#q;_d({rEyT*{|N#_LmUv4Q5iy&3aJfPHj3(%|@zJ+<-p#MrD*kMb+#O*w8G+v`2U zUFk3y)jZD3Z1yX&9e31qRO}iG=qSW$7>)xh>DWT7@m&3%e)?(HNEA3xeAOxxt!c`{ zIP2b1+PKlE@_3mkS8;2qh0uEK%Lk=)bEgcr6{l;gwK}vkG&F{bk_9avh^8;#SiPC#)ifne8}3(V-(S z(lMT0r-A;ptkm?Fn|wVY zC9je0(rKvR(>5@9nnHOyXkQxqHJ4WE3>d1P5Ss@gxl>wBX0pU!MM!8mtF z)eDM}L;xKO?HVa5)&T_$)7?%n8|5O1snmyClrlar;OzU)K_nq^mwy0233rPp1KEXF z+BQOQi@q&2Kj3Ws^P7RQzK`NZ2WMvcQJjX zx3_vpxvq$2QEY%^JL=`Kh^&`xzt%W(hq}7+=Fo}BNuEos{StMvsV%*_Rv$-MmMg8n z5T#Js6uQrD&JHuGbqC!uMQoeR2?naP`KL?f!XJp>(a$~-(ts5!~uf>a4s>r~bWc6+gr9 zQEr*50C0dbDoM8fk@&7e5jxTeYO|sf4i(<^M0jmgOY>b2X4`K5;B?3rH6i~UcnM&s z7{P{1ajds?UF~ipEO|hQEAdrMC3{XV7P52I)(+M0Q<9V4-TGdXjNal22a#O+z3N8W zU)x$+Q|wz|J5fHy+HGsif0QR2lg#BXfdT{-MKrZH*s`N3Wsy2C&Z+6c*~l zI>==ybiP8q8vO06AdBYSQg8V0=z3un%Fc=3P1CFEca%1q|MEGJ+cvAG0~0Jdf|m8yoL2GtAuO HaPhwY)|C-M diff --git a/docs/images/cutadapt_plot.png b/docs/images/cutadapt_plot.png index edbc6a3c74dea5c7619f6a7f79a0961ee48d15d2..6acf7201e475bb5671ead989eb1d075fa50fae23 100644 GIT binary patch literal 25938 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 z z%_A$)qWvd%FHU{zuitd{FCKVYYBf@3U{_3r;!}+E+Kt@({0BJB$rkrmvFX!KTlzoT zm|y3j!PwSzulLEN=KJ@qFxn=e9X4-mU!_3qfzGEPB=>1Pk*ResjVAB@zGl5MyNfyb*Yt(X9zmXSfINEyAx(im zy19ABndH=q^HrScG+A7Z4wbysKiCq!nhcdA z*Atg<;ph0Njt{J^7gnkRs=9w^5L)1`yM5N%HN?1}FN9OZ5p3Mt0$yWySL5D-#|DIT zhFN!@Pw>>$=LgO)l-;|d-ZiOOSu{2C=HZ*qa*=HMR@lKmi=H+&p7hsjRvvy_NI`=c z<21iJVzGnA-?j!`Lyl#I8l>dn+irEiV{Lf7wt%0IgA-ZMHdD3H1-0)NbIJ1=g2R?D z9XpGg^24+ItE#v#m2T$9nf{e#M55F8si;EplQgB%W@he54(uxAgP;$DQ}8SnlMk+} z)MVe`i2@DL0s`3kj{}2)nL#4U@Mr_-06!;r({rDQ)XUPyKnpFyNv+7>E%ix&)N9>|&td~Feoz}7TLo}ElLOn)j zyhe2M$xwB7^W~C4o{=(HL8)j$ozP;Iuv)^Mb7!EyyUmB-2no>GaD?=#;_2QJ7rRbT z=z%lLLS5wKv?7f-4NhCQ@&T z|KYPD-Ca`}%M(Y`-dxh|W3;0?&ON1IYV%^7w zhz-IE#TTm_&-@A_2MylTZljqmyF*u)dD&8hFtt!<&3|Nf0*HuRUC0LEi301TPVjgb z5D7G{rwW&K_Y^T+#O1 zXFINg04sv^K?j9}v4Ls=JIqh2c*u;>)25Rx?T5q?dyM3Z^FqecY=-n$#+WCO0N;fn0N)qD`iqV=Nkuj`9KHx$wn1ml1kSmwoDQWOH80=&$h@lP|QdiYHQ^XzJvDw*!`bS-n*SP3SK*dF?x%lAcaK znTd94^-u(TNwstsBKO7~>ZG&5y{(UR%8GL^XUn>NP^1zeyWI^-x|$tBp5wohf^Jjc2rnT1jypjn z`_%$Ae!j>kEH0r_5Qd_kbo^I&!6EWcgKBEzX2_~rN1P0szNnxl+%>XT_=KzH&O8GZ zz|`Qhd{RYQU1~yt$P%x-fUcsQA52jxbxUgO*$>LFH1T;N3j|gK2zI(~rf4ch`QIl{nbo6q~$4l!zu$l7Od~c<4F`Z&%Z2k$X#C zGjBDc$vSdY@Wamt0qrAuP~?4w9idjm7G z601Wm{OL?+_lkd+me0oxEA`Bvn19|spue$elDhW zicAqm+~EjeUqkHxWQlCKTJ-4RYCYOvsPa{e=h+hCKaRx|j9X89k>^gynf+)v0(x-C z%0El={ho@tv7N!&i5CL%~-EG46?a!b8Gb1 z)dlG##)YL~pvgb{XK$kigh2I9^C}vOZ@jm4T|fxyDaGY?ncO#84%1+k8Er2v_3rHP z#rJWPD0rgWhsVR;l3Pft{pmW!;qbCRYk+_L&z5CJ9^KNA5O%NpM==}AHiQ;`Ix~-l z^<1Io>NHoQnljY5EpOMGw333x4>$2oaCJfKmK!vo!SGvJEB-Fr@!WTqLG`}{FlG*^ z@oFe2G~5&C@0Z-tzvrofN@8lqdM+0hlBK3hnn*5c6c?-F?zd=j6JA(TAtJtUlQ!y0 zs*i)k%0n7V1UYRgI+sH{PlIN6R1+8#juDSS6KBALxwSRJWc8aQ2yoD;-Z|AaU?=Xn zbSKZUiwP;R!x^hrJ=1R{?MUpjublb-NA~KVNi;4g=}t;Y%0+52X}rt#bL&fRo2`en zygd5G#tn*Q)>x{*^0DhQSu;gOJ+YHZ7r+-!IrUNqzq(=v088|kk67T&RNmGH^6PH~ z)_=Sj+Zbd7XHclB4-yfE@>!^NZX!5PN2hOUoN`$(ynz{xsTd41%YQsaPoGuFC7_xT z9;S+Owdqn`onF6S+=-!D*jm3(HF(ETF?sO^7!-d#ee(kOI#>VeQ_R&D21$>RBU|vOn$?-&+4^W{U)g7(8HI&iuQlNA z$|%(3g9i_ev45JFm>9CZPBM0M^~I+3%`9Kk_QGffXl!60{o#gbibIeAek$T0~gv{?F`Wmt)^QM>pO ziRaf_n~t~q9n1Li|Iqc_@l^lq|3*eqqR6O}5uu3eRc5G=aI!~|z4xr_SxJhJN|J*k z+2hDeNXnksGR`4;|E~AZUHAQcJbwPU|F}QB&ud)sc|EV|MTOG-aqNAdcHZx2RH%g9 zQaW#=J&T6~7oD9tR!CF5>P3O_vkUvsz>QdDj)p3rd3_qNUTJ#7iuwjD-{@8PmZ10; zm}LFS_dRIbl}O6YQo|}eD>K-cla&=@@9fCxqD#bn!XMNR9;YTZOEhn(yDnss`~nMZ z+)_;hHa^zfm-l-wHs66zWP>wVj?t#-Lyzr*M=uhk;r(P%*Eh?{%TKcu1?>7SPC`Qr zC5s2ls|w31ecYp4=8+Y)Jo9AXPF13`B>V8XS}!x~and%{YHLtG*NDB}$PtWhC+jhA z#%>LLdAoZ^!}e*DgZC4NvoIKe_u6LCHR>>rsn*8`cTE_E)SYJ0MWOD-M82_H>n(M& z!463>&0;+u{KFax3{j(MLIX~@mr19stX4XuuV z#+8(wOS2@PY^QF))?hpN(Brn`y)1Rk0oPx0Lqp@?yo!^X#&`3@?(Gi-I$ zpr>8`Ns^3TDV*$cF{hD-(M?~!imYO%uf2)aZ)|3v{G6+kqd_~fyIGTQr?&UwS>Iqi zK8QtZ5@)n)OUEO2w6PQ|l`>$}Wplq$qn;l~JmRhM?`rRs_nTWm-lI~sp{juNj>2>* z_8gwRd`tE2Z8(Mrd|w|s)=b0$XW$Z$nZ~>-Xq}#(zPvF2HjE46F+oAPfNgtBvzR*^ z?C!zlcy)E~psy>NwIV}m zi7p9xW|2ZaD~to#jOK2v#jiF24@kSY)MYZJ)Dp_n6L=U=#r{>uXT{b^e-^|=x*6D`uUT_C3 zlm61U<1)U*T|Y>S69p|IkQ))S`0_B?hl%F3S1{(~%a>g~<{d#0aUP?UYzeNDK!--#w&r7n=z$z#_GZKLyF08{QBobv zwv8ZJ^Mrx7B%M~uu3X1c{M$EGf|5snK$1~VBs4rpi0Mq;aoSZyd>r-)&;<*xA?w}_ z@m+g+JErTmQKFD#3~~h*t!{MVq5s3u-!iF13xxTBqutL9#We|sfzKMLsh zC#IEg@k4l;%^vV(&6fOpeAJtM&>z3P3C)GiWsATzHTokYsozf0#_Z)Vfoy#d;`$_6 zm}&ZJG&inX)n4aU7iIp3cAFpz3ro7hApz>M_IcAS{f06A4LvU|yV04}i22bC_ulGi z2LGa>CfE8WSb}&Qne7GR+x%0zKs%rXzPKy8A+D||ZUYGv!Q2ZvjVK7=u09huZT6Fn z78(EPH5A1p1T?cBQ7Vwd;oW|0d^$eqT+$3fC2^0Ie|KB~AsPzUtyuG|T-)`0P#f^} z#*0j~H#U0r7*~$bHV!X;kwt%oD0p{k2Ma>uG}0a|KUTLVB-fWF7sA_lWQfzCz4 zA_~@Ize34{bq%VH-r5UiYRV0G{Y3&2{HMSV?Xn9SW>gUW!Agn}51TuedLMEs|2Z*@a^b=RN3h9g?rgJBFOvLMNUwOB#h>}_#%kz(R{B>j9 zE;dkG15=vXv+2=m3NTI4Kqvm$xh@~s@cCb3WIQGVB{SF7mEY8=)Z|7Yz;u37oM^O(LGDq1k;n&--{K5aJDA{p@bi zN5;H3DA=B!q-G>)cfCL_czL#GF-Ycb=xgm^ ziEm{FptMxn?;aJZEaQYAY3FbH?ETUN=z~c9oE2$jlhz!xDUQKdXj;72#!}|h#EXql zsBoNOkVjJ697BU{50BaU7aj$L+j9k3fPUcXBDJgZDy3wHTe0KL5c9O(;7^lT@z(c! zzZyr``X*Ov(^m&G5n5I4vD zt`(rpa|6I?*~lnot1rO+HaYqcyDVL7L)jfVl)(YD(y#AjiNme#3KBoLJ(4cn~0G5Z*@~^LHq!NHZ1_@Li!Tnu%Ct>;d(!W zu;kvcGGR~M`w|MUUpMuB;i9JWUOn)oUgK2jbMrJ{8qI1$zYh#-*3Y!{_V>PI>#WQ9 zOw2Qb(!a??%Ye30TYFB}1tSmSPznkF&Aw*ScIbk(y3h^Hg#+e{A+Fa9GufV6nr8wS zzFV1dMG^fd)5@A2f_9%HJ6mNq0FXK_cBxefRO9r0^76alC>=7&B_J`n>{8uI@Qzg) zD$|fpn-%C;KnOV@qbr>Y(}0^GFbLhCT{ti<>nEREy}_d&WnaXHbu@wiO%KU+^USfT zYx$)Ai4kWG8TSRi3U%vNIJR?|irhjmmVgL&r^>wh zX&NaLj>(LTqvUn)rt?3uCns_@_Mvlf&Y$JwjYE3cAye^wF@#S5_tyk~_O19}(dsGp z$k8lY`aItZ-Zx`+ASh>LI0maFB!Z3{Tk8!7&;`lREB_(fAxK1KHU~juc-4JfpnDqr zLXh78jMc?B3;5tl(qHkbNj~P|V`Jr?xN6Iq^D}Rf@lC#w`nBXa#;P+0Nyslz2Kqcz zRd3Tv!_2i-8vFL}T09z90>^jVTl=<;kvhCP`xCnY2xVKo>u z4o2$AH264Qd;j^EJSHA9GMwk&{fvMDFGf8v$VbhAoz+Y4lkkdOI{A^*7jfp^d&2v zcdT{j&ATud^)~@){|~^r=%t|WrUXI0=9mtE?VZO-J5;w4PN&L5ZSV6iy~AMCI7Oit za%W%wv`;8*pK`wUAFH5o z8{iV(36gM|zS%wsWpS9Jo@8z((#PVfda0IjU)}S>*K9fiIdMED2!hp90-obq>P}6d z?@p^bptHh8MPXsK*TCLa6l3B9ZDPEtLW_ZZ)fP&NJk%H@2-`8p^a*G{O*B7q zE%73yI#rnGYO*$Q)AK}jzr-~kAzJyo* zh(7_YBqG$cf6AkmI&V4T2GFP*=Cz`N!h5t)!6To=wf&H~F;X$@ zmnDP`+F6H7d{QiG5FB3fcOo%u4J)wUy-bgh z*;zZXpZvjoKl>(|O%wVel%hgyFOvrG46YfBj%_~I%3k?|y6_DZDoq3C4XbWMX-nrW zExE#c`0og`cR6js-6^U?gVtuF5DGdL@yUps{}hjf z^!>+TEOE#gvy#Pz&huaOOFJ+>=zQwIys{yDp7Ha6$% z&e!T}SGUgt%AD0%c(A>TaIGd9P+Z>!zWJ+)7mu0WhYuQx=enHi#XFThe+km#8Kk653h4ndqpNv%<~hDx++PziiB>AHw)??+wF=FQx*CpL51`( z8M?iF|9-!TdYvpPR10yc>*kV5ki`LS+3;^Yb;N}1FR+LLN`Vg{D6jeOnHtr}FEqyL zy$`+m+c|w&=*MWgkFRRxF#ev^NRObBlz#mc z%!F^hR>^PoMB?U{sqp#7Ykuv)i5hu^W@ioVi_9;pM1b$rO*Fz3}&@6$DPvt$6+w(esv z$PY}AGr$_9k#vU9vZ{J`%qG2;op%L4fkpg;PBK0W?DrY{Q#d?9hN?{9{MkmZ+2+Y< zz172xGyG?t@ z^02#BaWG-dYj^t*kD0bk{mJISB4Nm^`X?WiU6X;N=4*s6-EbQF*J3PzUqmM@^-;bsh|wPB=+QNIzj5^TD`j}L0)9pP648XeUcvm4$M7On-g!U;%5 zns94`G43>%7G!{kVO@K0nMrbm7l{`O8@dL zR2odu;I@`_)o)`X)>Yq>=+HXYDPm)H8*ja3)4A1hq^HaSOND|KyXap_@>tp%1hmhe zor9D9>$~f0AB!kPclK&s)C?pH^NBy>^1bPG8WYSs&3p>*>7Zci%)`}8VD=Lor(U{x zcr<~yL5w#3rQn&&Xa+*HVBR(oU#Lo7`DDFmGZsgg+P*fju~#slJ_DZ=wQrzb5aX?- zB&*Apyrzi0H2$@C(rp}fxZxRf=8gy)R{-h}|Djx6XXmGxfiOWL_Cia*n|y8HkDSlw z|L6^>D<%0`C8&$1-zi|vn35kLK5&@U$1n%w5KA{Rr#a$e6jwEHqk_t2v&d}Uh<^4_ zbRJaZb_4=4BT#+z15Y+rS%EjSAg3Q+R6lP6XW<7QM2fD^IZ6oJ_z z8#a*GJ3qsx1hK#)?EQ@7s*cJ!$PNxHk$Z~yr;AM$DH8m@yL4e!FnZ3p=8eK`T2 z#a+Ar7wdhp*x&fLxnS*vMaY&R&Y3=MT2gZSTiOkL2cKwDT+N7nVctVs~9)Tu6JZ=a&L#?UI z^Rm>**r?;{k0MZ$Uk$^&cia#XRxgQvk84L8UL|OeLAYVr@9&9RQlMr(b&aMzE3Bgp z#kbQm144&OO$mhC8I@`cxI@JKHQY?aYE4zGAIt+QIcNWLC`0hPigv+ zy$2-3?rw@j-}gvNX>!0=tsn5ZOvX1er(S1?%?3-%RAFQ zdS2BqS;}X{fDCO~qZHP{FhG?VX$Wv#vP)spvIJnJapHhS82&h>~2(Z!LJp|Z&+%Q#x^}6;j}KtV=^~2&QUEiSvtD02XyRd zVPWradQ2j#`jMdpFHlD>`~F2Ak>d=YF-(=7&m&OaJ&wQ-KUV)W3i>>lsC}ZNoPdpr z%U{0b_#Kj(`z`T2Cc<0dhJq8KO@pK{#n`ubUd&p&M@x`aaTgXFSHvyG>5co&>*$213 zdevKjv;e2&cyYEm+sBOHRE1)WTwxskPgZjZ=cv`}Tt4!b+ z{2bk2Elu8=Lca#L3ygx@iZ14q9IQDEAj5NlA6jgEK}-8+c}5iY5{VLNL*hk+!hmJs z7r(?R_ijKEI%1(~Fhn@lz)zQ|NH*HGJQE{Ob{$7xnFCg4LHC_n<|N$=ufM$ms*qHz z4Ip*h9h*aa&D%ZslYU=4%JZ+0p?MOtsQ8xx=!S=1e=SZSsKMUXhTWt+?dUtXfAtC} z{joM8B$t1E7)DW>#*|kCm+M;Ydn+gRUu1;V?vauC3mT$}d5fy6agcLUfiTp;u<{SGQ zTRXb2B%xc;nnlvtS*RqwSqr(zVhQkICUUJKXL|nYtHchkQ4RsXb(&0T<1q_H$2+yy zxt68(zA|Rt3N4p%@~ohv3clU`4*t&*Vvg^+O3KqTx|MJqwnh*moI42#CwQAiOsYu>0kb za}ew-=A^_j6}rL(#Hf3ac1UK=fR|e#eB4i$GA{P78-N(S4rtH9^jeQ3N&@aPbA}&y zX88wMAVstFw)QyIi!LQpRORf8(kFr?ie~ z{A9g!(K(N#zYYeVUR*yPJ%-_Y^Dnm)UPH(s<0bnzcWsriT(mkjOGo|P_x8#GdnIKb zi>u!Z(4@`Eo)s$CGaa~}H4-X~pMiX~I^{%5TjF0KM~0?lmwAH2;ldWB7N8W~Yf;o# z$nw=+olQ!!lYVuG5ZDHaLabK%xx-(NjL&A7+sQ5fJ{aKT*YCpmLKi|Y?D%-3DWe%< zNYqJb9YttyUQu{a!}KRb;9@NW*4XxiEskp7WR3do#V~`&8rf?o!{^!*==1cx`fph8 z1vAG%z$=}V{VQ%_l|0vResCjs=D_NNX>HeX7t!`PTC_8&4-TP3pN4`N@=lh{u_Q!) zKd(Xb=QQs=)Ru*@kA0jokeWoxt5L$9;}!kzw95x)2-^JJppOF{)O=500ki zuqnqWcGmzm9{657A?)kVl=2!Js@4b4KfoU$1acUx4s+>Wggn9RL^3rly1PvQhfy_ zM%D_E($(@go%LUd^4ZnXR|4iZs&93rZxnJp`U8qM>_fgP@a^nD4;fwBtkEf`Rea*I z98E0BEYTipn#-f&^(aB98$2};;KpNRA!Mnqe~VcNG5!4IB*8X@;v}`J-nUZ9hGVu2 zJYEIt4PYWaj-+_Uqb;B!az?xjaA>NVeJ@bUpSk|x6-np9C>MLo zP-iFbY*n%jp|rhZg8{w7oA_pM?U5eO&_a?QEN5g@zFH80TG2{I_ps1F(ffg9)PcAa zEgq9w4$*X7E61`hz73Og!Wm7IamM2l5JcO3@-A`D25o`Kac4%>k`S|)egbHD*%6L( z!{4_$6?XREpK@A40unzCS1|D=_V(~Nlbv5-{sq0VP^+zgJTk-RVqS)K0a@64aQ8Gy*pI@@a+( zfLn$;OC3CX%I3|BOi;+s(|}S)+LG;ABO_o?UH&v3HY!>m0z$OtcLIZ^1#;Z{x1_1m zJ;y|>2nfZ)AuX=XJ^)q5yJhu|)Oq*!M)8D!JFc7x6_A|7uFgOY+{DMfyTZ)X2%II2 zAz;9{`LC%2Aw;G1y%rRKpOmO7BAZ-(4dSf4kt0qH>vB?@#u39#wNl1FJs{~E;x|6u z>F{A(HWUh)op5epP4p*Ia@-_=;o5~3b(SrZ0mJg$e0bA}usDGy$OjK>%$ZdP=>ev| z9&ohv=>@uX{j^;#QlHpr)7p%_A^Tu4t585S(_0XMacV7xij8V7kj;4d>HO)2JLgV> z@9YimV$^_a_n>2UVP;^5hPZ0KKK5|yibLIenR$wX8bbC;Z8qkK4)}V5IIGxGtGgJd zp+Sa@FVt(4=OY%w@vQjmu?|qx zz^;VWcO_pla&-8S45i~`1V}`?Yt}DSL2T3emGPbzM~;5*q5Y;45HyRF!fiH>jr0(d ze$h8T8Uxz>;#cJD7UdzpMYdO!RRtJj@Pvx8i0n7wtP3tq-9XkzPW!v8Q^>N+7%y9S zKZ6`}rboRl-y&*X>WgTv$|JF?5MlJyHI03lvYHmIo}QL89X;>r2B1O3b%!y3%V6LH zEd`l*!8nG)0R*)qA_wc?`9SLH3`D}q5M(Tuc&@4gW^R^(H`d9%K|8awX6uDjuHren ze~4oztpSWKLlVR*aV*skxkF>GjNzU)Ji8D2u~Rl!KcBV?f8lZB7?yf=`t?&T*>_vB8Rd^GSY-lc0w8&#wn?lLqvBKeel(V)*^;0CeH z%@w*^n{A@N141~+a;GZ-;!PPpe0eMCoa*xmA4lmiXU*~lw7XPIiSnEjmruS^?(H@3 z+vvo%R!rA81lg{01eunz6TZ;0SpFK4*;VI+rp(ri_kI`{$xJ6=pHZO#Jv#K~!2N9+ zV}B6ac+F5aABT&iduj_PESQZVi=k&7J zItMRS&~y$~Y}VAjaPNjX`R==05H=GSa}IZYUGlXfd=a^y!;f+v%2UnW;xU_ZJz7`L z=IwC&n*Ply>vzXFaoNUKKDROckaB?+N{DSbX}np{&CTnk=Jp8tv{xfn)ER4x5ufFd zEAshSxkpzHhp0EerNM`NR=b)dC6ZJmfP3n3h>tPYKL3$eK(S=rdd0wmWC+$7&S`HV z$<;f|1raPn^=$eNs8E(7Cuk(Yzx5twe3yF&S>z=-2+(OZUnIdUOj{quy!5M@z*|ec z5_QE2s~Sk|aD+6_E*}RF0{K-P=! zp5(JW1cdt`B?-f~2fXc^!7ETvEOg6ZsG(ez6{8BFee#xKRJ+!iclRnuyrfy8WxG23 zcJD<^`~w6p#$3?XV}UjWslI;D>B%pW6l0Qm9|VkZK9QnQ-!zxb$Sr}Ud+THaJ)}O~ zPh9cqs?=D?Y4NAVV!0$bz5T}vXmqZB{eZd9AfXT2^4G#Y=nyf2^ub$eInd9Na5r?9 zp)FW!iVuRbp`F*=56;0+E{-zsm=zdo-6ZjNExV3)HiQrxYgB5`xztTz)BG&Ay8fms z7(zX*A8$x>2KXSg{uQiDF}q37Mr6Z>?{SSi?wC7pv$nVQ)~VC%Vy6~2`-K6<03?R5 zAdEJ`-rxAtsoiI(84&&I3bo6i4uxt(XD)iVR(;TehK{7oI0$9l+A}`H?~(pqA=y*P z8ZNj()w9vhx@w|GRv%5G^P@nWV{Oc~eH1&82gQf2%meT#%db-ql!Hg&O|-Uf|CJTp z-@0?upU(7@33d1C9;ea>GJYE6GWQCGyorc&CMO=2kXGKw(+PORrek?4f>Ft}?OpLm zDL9lbdTd8z)&P-)XFjM{f0$|0@{YPjGGPjFrS#zA)Ml#CVuV{c1^)LXjZqEzOs@;< zx;xL{zLLqM2|QXKNHFr_-1|EXBdupEo&wIX}mwS@f6gGG&RoCk|!v>-$>(`z3MsBlh?Kq&@1 zw<1Rm*T^1DP@{OKhQ#OR%KF{`+?F>5G=LN3lBb6DYUm0`2jGj@K~{!5=B)x!!J@_W zGZj=b6Wseh_QzPyw)<^rS0##?KkB8J`9fcjI1}Cl#k5b00O6%vGX`CXu0BHg`vk$^ zT>+gAyFUah)CNGGA|#)xR?VOH=!Em#n+w1tRb;yFP2RK%eco)>YyIE?c$yTdSw@(f za}NsalVwyeLX2UUN1IThsX(PFpq5A92K_;3!vVL{w4Uz*>{w#J@9w1uoPX&xLI$u< zFfi)@j|4&?!pE!R!wB{qaCZevox7iD7XmHZUuxZ&ef75+z&x8)2gt|vhF%Z^@_|rJ zjVW!`S7V`5E~46CceCR&HKSQdyrZGek(uAJSKXgn%-r-q+DI%6ZAC~sR}8g*-A#~c zfp(BUYLXCR5qCZycp3V{tQ|DoeXu#~zm!i1lsx-*H%}xOdfy~NXXY=-po;9Zvo@QO z=in~h*$R^COr*`nQJz?-#qM#D5c_rE13*<-nCq^1HBTeuA;`PD-RR4+??P!wJyh5-9AqK{LJclt3i20a{!v7sNj^jZZ6O_q@DlG^AUn z@9rDRi17tFNg+R7?y$;TBle$1d`bonWG$?qE<{~Q9aTC8A(pU1^>HDS?VZ(K&NPj8 z4f!k*COy^`U-NW?Oa`76fp1Zc3{ahtB*@A`FjzRb0_M?q%_2S0+!Yeh` zV39rFS9v3No34Y`Pl&3sW<`h6ux4%&xY%E$R^dKB#5VvVU&6w)dT6iEk4W)81LssK zpZNK3ypfy>^T|-x7mV2?IyG}`bW~zKCtO~qLD?)ouh8JTa%C@t4N!=tcL*iK3Ehj8 zQ2qmA$hVc2prA?uQci?O+_bT1rCLBX`70ja4QaUNbVus&9=V63iYcg zK9#%IUuP*E4_)R#piIu6HaNHDwP>*Ui5J9cs8Or|QmO+s%RXSJR}37+2IsZG0O5Sp z={95t-{T-;3pTiXu=|6n16S`}AL{Y7D%}W&M5H&pVi3E&#RLZ zoy^UyX67{NdJwkS)eU02?T2$#+1zGr3Dnl}zBz!+>j3CN$qS5O&evYxM$3QdEdG-t zBF9PkhW&0r{K{1*7D;*!74a}vj`nDb5im+ijZBB95ed3#luRL5vg)eR4zF_=NV%|0busD8SHVyeQFtdB^}B;li{H20w| zn=pnLVEqk|=j=;LkVb-2zzIBDHZV9@42;DuFmBMN0-oyHIKDg8#txj}NO(W+1`Len zg6F~BPexn*|GIUsH_J}2KuloO`Xt6=Xt%}ZNU?_kAMdcB^^Jyf@Kj5p9>8RVNVjY*LU!X2Et>r}xW}5vYxY>1s-u8`Pu`7_yfF-gJ4sn&RO;72WS3 z0;!B+C(t!}1sS-O_K=iQM*GmBwlHmRulM&Fyy0{nNUDO+YC!J|V*%M?=J-v3Ny2X% zWy&ZBET_ekbhQLkC#O8*5r&CYwz_wo4e)?q(gKgLur}3!1L-ecRz#m9I?4 zdGXd5aiZs6#MS+C5FzEsrmxs(T_A%YnbrRzBO{5O%x80c95(vC3i^V~T6v!i= zN_|Wuwo&s>r$Wt*iiaOYBvarbCCUK>+;e!1C3w64PX2S#yFja@ZK&MZhMvb)JLOs# z*A=PF;ms_h{RxOn@Gg#s$tcj7knV7J*n{i;^ad^N(#^TpgAN2s%g=s#+RgP_tTx}` zYPU_$$%YP${_aOJ0ENz44M72Vu6KFD&yE=CiY3dSgT`BN(Q%XnU!Za?P&f$q=*^#x zs7MjpKr2#3{abkd;F*hz|CZRWlYLQH>y-kSKaY@=pcNdrFPZ_N#>~3!)O3pYfx}{B zd5=+P)+cD4KPSHM2XF*dHt0=P>37N@3sny=xJ!=y_%VFK?;kYeqF&zp*$>xA2_2q( ziQk3@rZ3R*Fec<%lkN)a^Vq^_9yvNCt5n2c@c4>PYOCdr3_m~ru+!!$UNm6m=cfl4 zCwP%)ZdJI^qfXw~tvf47x8Kq%h3j@U-K5MmvuVx11v5s8!-L-QDDXN4l?MKzzHg|3 zel!>m@CKf|SR9 zX_dFOXS~T@!#faRtL6Patbq`^KbDt|Z`OtER_lC$+f3)X${PNj%a-8)ysWUMbACJe zvqU6WMXWT#lp!PtwkkTb;r>>?J2NkdPT4UbRC2a5Eh3FA!Am$$f zY8^1luX-A|ySu0Ie)jecP2nvX)J}P*29X0K-4I0VXUc=8g0L7py(VLy=x?PGvz1Hn zHUNn_kI>wKuBLTu4Ya#QW?;Mv_ESHF4W1^Q$HeWN!Q=Tqr3e%)CZsAw+GoSi4;n$O zzH_Lkt0y2`kq_gcod>2@9w@`Ud-u6KqoP83HQ~d!!ZS?P75;33vSaA*~=n)Qbde=U_ssC=~p3!mSjoM>6Vr`_cF9mMep$>Xk0fmG@MR> zw!1{EgPmQpSnF(0e#=65j893ZZfj}=E-UL7j4Au=+OVO>4(s^(dZkPo+r6St ze(c9D(B*yWW9jKx;9HiKp5A3~cKWYB&Q;-W(2jT)27cb*{?gdEU;o09Xn0!TxeKgM zc^e0htyH84u6=)URtw>M!vD~nEOH#KerJ4|kDEJe+~!bm+D>TS;(I&a^ESN<@52gm z?84hcl~_ZLb3IiB>;^zRnJ+YD_@RXJ&1EMzL z-jH%6iF8q;WOvK^%JEk$p~kY9TY=bvJJ;C=ITp1vN#`js=x+$ zt{00MeM;bzhM+pkBw`!nyS2c*SUD*ZONCOinKs^s_Ott7(`yQC`=p0W35Fqz4E(YF z$GeZ10z~ZlxnW#|sV?$FSKhr#m$n_?St0uu_CU^rt_o9g9v+_NA$)H^(^g5#9U=MN z7ve7Dwg#yh-vgBn*LULu6DX6&oNE;%#N{n$|sIYck3ezKWVnDVd2OwT~~ z#eNpuTeqxodi9DO)A$UEH6SQxxd4+AD*PwlIq;UvJI&8dgRQ+2#0>m3?ggYa7~U!BsSwPk$iP2$nvLkrTb09Cygo`y%NO=t@i49C<;1X8uWr1_ z2-W!Bw_c74c-^$`C^W5LM~jU)ujsUstv=r@%{gXFMN9Z=Lz@OJ$9&Mso|>MPv$Hz~ zkzy#cQ%QNwn4~1uvsu_UqLE& z?fXuKilrH}IGSMQqzBJ<$EZlhsE^cI1nurPUFh%c&%4`pqhXQxjPNTW-mRQ( zp9lEmKdA&M5dJRaGMdmnTu%@3d)x5CKY9Qiy3@=)zl87;ktVi$i!G!q$kSUFHz%Y}^SWuBe_vCh^!kuT59dFkvi4mmc$U!pEGCT#FD zRpild>j2F#H>cmTAC1lDDu`PYotVldQVm=W4Q+%#eMjd;B| zV)A;j#l)YoQDJT<*SyTXHo!RK%E|npUhx%?&5c_;-d}SxoLJGpk}Kk0C>t8Mh=_E# z+TrMy3cr1pK9%@)T|3CSC^ECDI5J5UPU|cv;GVP=tr*nYO)rkpXmh!;^detbJ%R)s z5ELX%g5KC5C#v$>e#2cA;eC-hm5P4r$k+>oD|^?u7(&d@Ci%X@u_p5g=0`W~cZnR+ zFqJ0ov+!J~me(HLq&6#mJ!S?23XXqcUrw`}Nc3#WP0!ikc`QYNVD8 zLLi9|5|pDl(LWZic9=da0QoO?op2&HwyR)Rcfsk^;hEH-U1U*XW0coM9A?hIKNx#J zyY}S$;lp44>VYhx2NY*)ncuv7V8qSY?ChPg>~v5m>sVwH<>vhpv3(cgP|SR|2g?a= zEW;BMF#~0*q(mWCl{5qCe~5BiWuu<_yE0Z}Wk*(FW9dN;CXCu#X6se%wx07zi*ls3 z)u|X2cOo8)&PZBg;~bIO7b9t{c0R zG5PE~nf!O2^X%Q{Lf6M2fke>;7qGxW4zY-xrE^Hte>}>-1C1;3J<_wX~dAUne69bdHug zY7%_0@n=Hj&%gUShU`yBJke7#ti!taw0D0_m&xy~NQ50|Uj_a1)S=Ag=3GCvs8kiS*y zhuIlnCCJnE@-7jPv{FU!BcE0Q-`0PEPS_Vy#kEL|0&MZ~GR6Mpf$v_l@AY6?-U442 zJS}^@Gy@Ax$sF3aPyEM1v0cOpV;W$6ZyrCMV=k zX7r%()v+&>c>dslJLE*q9Qy0_ERAtOE^^qaYE8sMnZGYPv9B_dZOMy=KP1?zu!)nT ze6Lo&JsfXTODbVGzhO33SRD0DppE3x)PsT{t{X>9{7TJ_fq|zze*6#-_wjf*te;7O zYYm_Oed0LsiJMQ)C>=E`V47Bp)jxUjlAE@Hl98HaX+*M!NY9mh;*~CBNHsYbeDB*Gg2kgm+KL3b>W2PHf z$jz+`g-vnLos~GK2j5!u+~@y`>N*?nzToebcmq-7l=S%f=bM;x^`+zT!J0~Z*K6US? zW#|xDG$)-nnQ;fFl=Nw#*f6Wsv+;mM5RFcaeGw_qdz$b~lWhqJW_x=as>1sm(a(>n zu>1QtpJ}W9Dp>fCly9cpOcbu{I6cU zjUsWULq!E*g`PaQ8TBk0RIAY8@Xr4Ky>^P1zP~?mSG`Y^;`i>?sHCa!Fy>}&_aG)p zq~QRsWL#SZR)fE`K3d^8 zX*41&9L^pgumyDz666rj=;I&nHh@eiZ2oifFU-KW-22vh=0#$O8sCGMhI4ad8W+Jg zG+0z;W~TV<2VZ~L_xR3sT~~LB3;#xxH)6?!f&w-Eo+;&h%h4u2oNBT%9kb7JiG=e*jmHMZcmY|q^f!-~#dp`b7 z*?uAu-4&CMss>8$ro{Kb3FwMaARe$*VN}*0$IZv{iMHoJbpNOY<-wExqEa{H8ZNn) zwPZf`3C*ipD9*VX$6du-xq1XWp?TMx>t~!8#CzD?kBs;3rHN%d1?MoSdiXF;=<%JnkGy&K&)b)kxFUD?$udN(@oly6KGG1NoWh-Be{m>Q2G(zVjG0x-6V`n)> zlyJ9h{8gh{i02^fdWi))e?2yxWDP4={kY&dC_;$Ni=NYP|5-0jfmwWQa2ABeNUHj; zU7kVK`?Efq8H~GXBsGzV{g;q8b6g7-s~@RNEm9s`{iGV!fMxKH%=hR6^

x{ofyD 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 diff --git a/docs/images/nf-core-cageseq_logo.png b/docs/images/nf-core-cageseq_logo.png index ebf73627d77347692ab9387f49f0506ed6c12e94..32a25d62949f90d650a0795a2a2419c3ee4dc27e 100644 GIT binary patch literal 11307 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 literal 22650 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 diff --git a/docs/images/rseqc_read_distribution_plot.png b/docs/images/rseqc_read_distribution_plot.png index b3c12ded1ba580b4c1d54c92162f4134cdcdab06..51ea6d9d81148a86f3b0df2d50a1ed24879f936d 100644 GIT binary patch literal 26136 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 literal 61189 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

H^t+g3t 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

Ry`gO^ZYx=%Z-_jo{#jbUd~?Me+)DQ0qn za4QA9E;Y(2ifl=+ed*e6>{U631!!Y)UMjvP5&^Td(pH-T4@V}A6wU%6-jU<-*# z<7O0o>h!hO(C5C1#4(Tz+5yb&Y@?~hk!U#5JoJN^0=*84;@?L`%wP8R)1KPWRlS3Q z%`fTf=n2+DZ(PLu2)1_FY~L}pCzP>0DB5nKA%+yAAi$pDvp7+#$9yDR>e+y3-*@&_M}StQX-)YsZ>C5z?| Mo3}Y!+O#+3FI(kXLI3~& From 30f388313da3cdde047415aeceb48e1604713fae Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 14 Aug 2020 14:23:35 +0200 Subject: [PATCH 088/107] output docs: add SortMeRNA section, fix bowtie section --- docs/output.md | 56 +++++++++++++++++++++++++++++++++----------------- main.nf | 2 +- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/docs/output.md b/docs/output.md index 9879bd2..932a6f5 100644 --- a/docs/output.md +++ b/docs/output.md @@ -1,18 +1,14 @@ # nf-core/cageseq: Output -This document describes the output produced by the pipeline. Most of the plots are taken from the MultiQC report, which summarises results at the end of the pipeline. +This document describes the output produced by the pipeline. The plots are taken from the MultiQC report, which summarises results at the end of the pipeline. The directories listed below will be created in the results directory after the pipeline has finished. All paths are relative to the top-level results directory. - - ## Pipeline overview The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: - - ## 1. Raw read QC [FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your sequenced reads. It provides information about the quality score distribution across your reads, per base sequence content (%A/T/G/C), adapter contamination and overrepresented sequences. @@ -57,6 +53,14 @@ All the following trimming process are skipped if `--skip_trimming` is set to tr * `artifacts_trimmed/logs/` * Trimming report (describes which parameters that were used) +## 3. Ribomosal RNA removal + +[SortMeRNA](http://bioinfo.lifl.fr/RNA/sortmerna/) is a program for filtering, mapping and OTU-picking NGS reads in metatranscriptomic and metagenomic data. + +The MultiQC report shows the overall percentage of rRNA in the sample in the general statistics section. The SortMeRNA section shows a bar plot of the filtered rRNA types. + +![SortMeRNA](images/sortmerna-detailed_plot.png) + ## 3. Alignment The reads are aligned either with STAR or with bowtie, set via `--aligner`. @@ -67,8 +71,20 @@ STAR is a read aligner designed for RNA sequencing. STAR stands for Spliced Tran The STAR section of the MultiQC report shows a stacked bar plot with alignment rates: good samples should have most reads as _Uniquely mapped_ and few _Unmapped_ reads. + ![STAR](images/star_alignment_plot.png) +**Output directory: `results/STAR`** + +* `Sample_Aligned.sortedByCoord.out.bam` + * The aligned BAM file +* `Sample_Log.final.out` + * The STAR alignment report, contains mapping results summary +* `Sample_Log.out` and `Sample_Log.progress.out` + * STAR log files, containing a lot of detailed information about the run. Typically only useful for debugging purposes. +* `Sample_SJ.out.tab` + * Filtered splice junctions detected in the mapping + ### Bowtie 1 [Bowtie 1](http://bowtie-bio.sourceforge.net/index.shtml) is an ultrafast, @@ -77,22 +93,19 @@ memory-efficient short read aligner. The bowtie 1 section of the MultiQC report shows a stacked bar plot with alignment rates: good samples should have most reads as _aligned_ and few _Not aligned_ reads. -![STAR](images/bowtie1_alignment_plot.png) -**Output directory: `results/STAR`** +![Bowtie 1](images/bowtie1_alignment_plot.png) -* `Sample_Aligned.sortedByCoord.out.bam` +**Output directory: `results/bowtie`** + +* `Sample.bam` * The aligned BAM file -* `Sample_Log.final.out` - * The STAR alignment report, contains mapping results summary -* `Sample_Log.out` and `Sample_Log.progress.out` - * STAR log files, containing a lot of detailed information about the run. Typically only useful for debugging purposes. -* `Sample_SJ.out.tab` - * Filtered splice junctions detected in the mapping +* `logs/Sample.out` + * The bowtie alignment report, contains mapping results summary -## 5. CTSS generation +## 4. CAGE tag grouping -The custom script `bin/make_ctss.sh` generates a bed file (and a bigWig file with `--bigwig`) for each sample with the 1bp unclustered cage tags. +The custom script `bin/make_ctss.sh` generates a bed file (and a bigWig file with `--bigwig`) for each sample with the summed up 1bp unclustered cage tags. **Output directory: `results/ctss`** @@ -102,7 +115,7 @@ The custom script `bin/make_ctss.sh` generates a bed file (and a bigWig file wit * `Sample.ctss.bw` * A bigWig file with the mapped cage tags -## 4. CTSS clustering +## 5. CTSS clustering ### paraclu @@ -111,6 +124,9 @@ attached to sequences. It is applied on the pool of all ctss bed files to cluste **Output directory: `results/ctss/clusters`** +* `ctss_all_clustered_simplified.bed` + A BED6 file with the found clusters and their pooled expression as the score. + * `ctss_all_clustered_simplified.bed` * A BED6 file with the clustered CTSSs and their pooled counts @@ -136,9 +152,11 @@ This pipeline only runs the read destribution RSeQC scripts on the CTSS clusters calculates how mapped reads are distributed over genomic features. ![Read distribution](images/rseqc_read_distribution_plot.png) + **Output directory : `results/rseqc/read_distribution/`** - * Sample_read_distribution.txt: - * text file with the raw data describing the distribution of the mapped reads. + +* Sample_read_distribution.txt: + * text file with the raw data describing the distribution of the mapped reads. ### MultiQC diff --git a/main.nf b/main.nf index eac78cd..17281e5 100644 --- a/main.nf +++ b/main.nf @@ -764,7 +764,7 @@ if(!params.skip_samtools_stats && !params.skip_samtools_stats){ if(!params.skip_ctss_generation){ /** - * STEP 8 - Get CTSS files + * STEP 8 - group CAGE tags */ process get_ctss { tag "$sample_name" From ec5a5f85e5b5871470677f7563e578d33c8e7268 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 14 Aug 2020 15:39:03 +0200 Subject: [PATCH 089/107] incorporate review comments --- .github/workflows/ci.yml | 4 ++-- README.md | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1f906a..1011c30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,8 +21,8 @@ jobs: matrix: # Nextflow versions: check pipeline minimum and current latest nxf_ver: ['19.10.0', ''] - aligner: ["--aligner 'bowtie1'", "--aligner 'star'"] - options: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false', '--bigwig'] + aligner: ["--aligner bowtie1", "--aligner star"] + options: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false', '--bigwig', '--remove_ribo_RNA'] steps: - name: Check out pipeline code uses: actions/checkout@v2 diff --git a/README.md b/README.md index fe3ea24..c4e8d19 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # ![nf-core/cageseq](docs/images/nf-core-cageseq_logo.png) -Nextflow CAGE-seq analysis pipeline, part of the nf-core community - [![GitHub Actions CI Status](https://github.com/nf-core/cageseq/workflows/cageseq%20CI/badge.svg)](https://github.com/nf-core/cageseq/actions) [![GitHub Actions Linting Status](https://github.com/nf-core/cageseq/workflows/cageseq%20linting/badge.svg)](https://github.com/nf-core/cageseq/actions) [![Nextflow](https://img.shields.io/badge/nextflow-%E2%89%A519.10.0-brightgreen.svg)](https://www.nextflow.io/) From e5573cf260bea5959a32cf55f5754c3993cc8e3f Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 14 Aug 2020 16:17:43 +0200 Subject: [PATCH 090/107] bump version to 1.0.0 --- .github/workflows/ci.yml | 4 ++-- CHANGELOG.md | 10 +--------- Dockerfile | 4 ++-- environment.yml | 2 +- nextflow.config | 4 ++-- 5 files changed, 8 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1011c30..a2f7572 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,13 +36,13 @@ jobs: - name: Build new docker image if: env.GIT_DIFF - run: docker build --no-cache . -t nfcore/cageseq:dev + run: docker build --no-cache . -t nfcore/cageseq:1.0.0 - name: Pull docker image if: ${{ !env.GIT_DIFF }} run: | docker pull nfcore/cageseq:dev - docker tag nfcore/cageseq:dev nfcore/cageseq:dev + docker tag nfcore/cageseq:dev nfcore/cageseq:1.0.0 - name: Install Nextflow run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f1e4fb..6838aec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,14 +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). -## v1.0dev - [date] +## v1.0.0 - [2020-08-14] Initial release of nf-core/cageseq, created with the [nf-core](https://nf-co.re/) template. - -### `Added` - -### `Fixed` - -### `Dependencies` - -### `Deprecated` diff --git a/Dockerfile b/Dockerfile index 59433df..13d1526 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,9 +7,9 @@ COPY environment.yml / RUN conda env create --quiet -f /environment.yml && conda clean -a # Add conda installation dir to PATH (instead of doing 'conda activate') -ENV PATH /opt/conda/envs/nf-core-cageseq-1.0dev/bin:$PATH +ENV PATH /opt/conda/envs/nf-core-cageseq-1.0.0/bin:$PATH # Dump the details of the installed packages to a file for posterity -RUN conda env export --name nf-core-cageseq-1.0dev > nf-core-cageseq-1.0dev.yml +RUN conda env export --name nf-core-cageseq-1.0.0 > nf-core-cageseq-1.0.0.yml # Setup paraclu RUN apt-get update; apt-get install -y build-essential g++ RUN wget http://cbrc3.cbrc.jp/~martin/paraclu/paraclu-9.zip && \ diff --git a/environment.yml b/environment.yml index b484aa4..fb01d8b 100644 --- a/environment.yml +++ b/environment.yml @@ -1,6 +1,6 @@ # You can use this file to create a conda environment for this pipeline: # conda env create -f environment.yml -name: nf-core-cageseq-1.0dev +name: nf-core-cageseq-1.0.0 channels: - conda-forge - bioconda diff --git a/nextflow.config b/nextflow.config index 8d32114..7463e9f 100644 --- a/nextflow.config +++ b/nextflow.config @@ -80,7 +80,7 @@ params { // Container slug. Stable releases should specify release tag! // Developmental code should specify :dev -process.container = 'nfcore/cageseq:dev' +process.container = 'nfcore/cageseq:1.0.0' // Load base.config by default for all pipelines includeConfig 'conf/base.config' @@ -154,7 +154,7 @@ manifest { description = 'CAGE-seq pipeline' mainScript = 'main.nf' nextflowVersion = '>=19.10.0' - version = '1.0dev' + version = '1.0.0' } // Function to ensure that resource requirements don't go beyond From 87e1fbe22fb93ff8ee13836403d0586d4e44255e Mon Sep 17 00:00:00 2001 From: matthiasho Date: Tue, 18 Aug 2020 15:43:13 +0200 Subject: [PATCH 091/107] apply changes according to the comments from first review --- .github/workflows/ci.yml | 48 ++++- README.md | 2 +- conf/base.config | 60 +++--- conf/devtest.config | 28 --- conf/galaxy_local.config | 20 -- conf/test.config | 5 +- conf/test_full.config | 6 +- environment.yml | 2 +- main.nf | 416 +++++++++++++++++++++------------------ nextflow.config | 21 +- nextflow_schema.json | 10 +- 11 files changed, 321 insertions(+), 297 deletions(-) delete mode 100644 conf/devtest.config delete mode 100644 conf/galaxy_local.config diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2f7572..e4fc30d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: # Nextflow versions: check pipeline minimum and current latest nxf_ver: ['19.10.0', ''] aligner: ["--aligner bowtie1", "--aligner star"] - options: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false', '--bigwig', '--remove_ribo_RNA'] + options: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false', '--bigwig', '--remove_ribo_rna'] steps: - name: Check out pipeline code uses: actions/checkout@v2 @@ -42,7 +42,7 @@ jobs: if: ${{ !env.GIT_DIFF }} run: | docker pull nfcore/cageseq:dev - docker tag nfcore/cageseq:dev nfcore/cageseq:1.0.0 + docker tag nfcore/cageseq:dev nfcore/cageseq:1.0.0x - name: Install Nextflow run: | @@ -52,3 +52,47 @@ jobs: - name: Run pipeline with test data run: | nextflow run ${GITHUB_WORKSPACE} -profile test,docker + + test_parameters: + name: Test workflow parameters and aligners + # Only run on push if this is the nf-core dev branch (merged PRs) + if: ${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/cageseq') }} + runs-on: ubuntu-latest + env: + NXF_VER: '19.10.0' + NXF_ANSI_LOG: false + strategy: + matrix: + # Nextflow versions: check pipeline minimum and current latest + aligner: ["--aligner bowtie1", "--aligner star"] + parameters: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false', '--bigwig', '--remove_ribo_rna'] + steps: + - name: Check out pipeline code + uses: actions/checkout@v2 + + - name: Check if Dockerfile or Conda environment changed + uses: technote-space/get-diff-action@v1 + with: + PREFIX_FILTER: | + Dockerfile + environment.yml + + - name: Build new docker image + if: env.GIT_DIFF + run: docker build --no-cache . -t nfcore/cageseq:1.0.0 + + - name: Pull docker image + if: ${{ !env.GIT_DIFF }} + run: | + docker pull nfcore/cageseq:dev + docker tag nfcore/cageseq:dev nfcore/cageseq:1.0.0x + + - name: Install Nextflow + run: | + wget -qO- get.nextflow.io | bash + sudo mv nextflow /usr/local/bin/ + + - name: Run pipeline with test data + run: | + nextflow run ${GITHUB_WORKSPACE} -profile test,docker ${{matrix.alginer}} ${{matrix.parameters}} + \ No newline at end of file diff --git a/README.md b/README.md index c4e8d19..eb74aa8 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ The nf-core/cageseq pipeline comes with documentation about the pipeline which y ## Credits -nf-core/cageseq was originally written by Kevin Menden and Tristan Kast and updated by Matthias Hörtenhuber. +nf-core/cageseq was originally written by Kevin Menden ([@KevinMenden](https://github.com/KevinMenden)) and Tristan Kast ([@TrisKast](https://github.com/TrisKast)) and updated by Matthias Hörtenhuber ([@mashehu](https://github.com/mashehu)). ## Contributions and Support diff --git a/conf/base.config b/conf/base.config index cf28203..3e4fe56 100644 --- a/conf/base.config +++ b/conf/base.config @@ -10,42 +10,36 @@ */ process { - cpus = { check_max( 2, 'cpus' ) } - memory = { check_max( 8.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } - - errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'terminate' } - maxRetries = 1 - maxErrors = '-1' - - // Process-specific resource requirements - withLabel: low_memory { - memory = { check_max( 16.GB * task.attempt, 'memory' ) } - } - withLabel: mid_memory { - cpus = { check_max (4, 'cpus')} - memory = { check_max( 28.GB * task.attempt, 'memory' ) } - time = { check_max( 8.h * task.attempt, 'time' ) } - } - withLabel: high_memory { - cpus = { check_max (10, 'cpus')} - memory = { check_max( 70.GB * task.attempt, 'memory' ) } - time = { check_max( 8.h * task.attempt, 'time' ) } - } - withName: 'get_software_versions' { - memory = { check_max( 2.GB * task.attempt, 'memory' ) } - cache = false + cpus = { check_max( 1 * task.attempt, 'cpus' ) } + memory = { check_max( 7.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } + + errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'terminate' } + maxRetries = 1 + maxErrors = '-1' + + // Process-specific resource requirements + withLabel:process_low { + cpus = { check_max( 2 * task.attempt, 'cpus' ) } + memory = { check_max( 14.GB * task.attempt, 'memory' ) } + time = { check_max( 6.h * task.attempt, 'time' ) } + } + withLabel:process_medium { + cpus = { check_max( 6 * task.attempt, 'cpus' ) } + memory = { check_max( 42.GB * task.attempt, 'memory' ) } + time = { check_max( 8.h * task.attempt, 'time' ) } + } + withLabel:process_high { + cpus = { check_max( 12 * task.attempt, 'cpus' ) } + memory = { check_max( 84.GB * task.attempt, 'memory' ) } + time = { check_max( 10.h * task.attempt, 'time' ) } + } + withName: 'get_software_versions' { + memory = { check_max( 2.GB * task.attempt, 'memory' ) } + cache = false } withName: 'multiqc' { memory = { check_max( 2.GB * task.attempt, 'memory' ) } cache = false } } - -params { - // Defaults only, expecting to be overwritten - max_memory = 128.GB - max_cpus = 16 - max_time = 240.h - igenomes_base = 's3://ngi-igenomes/igenomes/' -} diff --git a/conf/devtest.config b/conf/devtest.config deleted file mode 100644 index 310ee76..0000000 --- a/conf/devtest.config +++ /dev/null @@ -1,28 +0,0 @@ -/* - * ------------------------------------------------- - * nf-core/cageseq Nextflow base config file - * ------------------------------------------------- - * Config for testing on local workstation / laptop - */ - -process { - - cpus = { check_max( 1 * task.attempt, 'cpus' ) } - memory = { check_max( 8.GB * task.attempt, 'memory' ) } - time = { check_max( 2.h * task.attempt, 'time' ) } - - errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } - maxRetries = 1 - maxErrors = '-1' - - // Process-specific resource requirements - // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors -} - -params { - // Defaults only, expecting to be overwritten - max_memory = 16.GB - max_cpus = 4 - max_time = 1.h - igenomes_base = 's3://ngi-igenomes/igenomes/' -} diff --git a/conf/galaxy_local.config b/conf/galaxy_local.config deleted file mode 100644 index 3d5b7b3..0000000 --- a/conf/galaxy_local.config +++ /dev/null @@ -1,20 +0,0 @@ -docker { - enabled = true -} - -params { - max_memory = 120.GB - max_cpus = 20 - container='tristankast/cage-seq:latest' -} - -process { - $star{ - cpus = 20 - memory = 120.GB - } - $makeSTARindex{ - cpus = 20 - memory = 120.GB - } -} diff --git a/conf/test.config b/conf/test.config index 8186236..e32f58e 100644 --- a/conf/test.config +++ b/conf/test.config @@ -17,8 +17,9 @@ params { // Input data single_end = true - input_paths = [['cage 1', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage1.fastq.gz'], - ['cage 2', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage2.fastq.gz'] + input_paths = [ + ['cage 1', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage1.fastq.gz'], + ['cage 2', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage2.fastq.gz'] ] fasta = 'https://github.com/nf-core/test-datasets/raw/cageseq/reference/chr_sub.fasta' gtf = 'https://github.com/nf-core/test-datasets/raw/cageseq/reference/chr_sub.gtf' diff --git a/conf/test_full.config b/conf/test_full.config index 60b1aa3..d7fea41 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -13,7 +13,9 @@ params { // Input data for full size test input_paths = [ - ['Testdata', ['https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R1.tiny.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/exoseq/testdata/Testdata_R2.tiny.fastq.gz']], - ['SRR389222', ['https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub1.fastq.gz', 'https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub2.fastq.gz']] + input_paths = [ + ['cage 1', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage1.fastq.gz'], + ['cage 2', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage2.fastq.gz'] + ] ] } diff --git a/environment.yml b/environment.yml index fb01d8b..2d6c9ec 100644 --- a/environment.yml +++ b/environment.yml @@ -16,7 +16,7 @@ dependencies: - bioconda::samtools=1.10 - bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. - bioconda::multiqc=1.9 - - unzip=6.0 + - conda-forge::unzip=6.0 - bioconda::bowtie=1.2.3 - bioconda::rseqc=3.0.1 - bioconda::ucsc-bedgraphtobigwig=357 diff --git a/main.nf b/main.nf index 17281e5..633ce7c 100644 --- a/main.nf +++ b/main.nf @@ -38,10 +38,12 @@ def helpMessage() { --fasta [file] Path to fasta reference --genome [str] Name of iGenomes reference --gtf [file] Path to gtf file + Ribosomal RNA removal: - --remove_ribo_RNA Removes ribosomal RNA using SortMeRNA - --save_nonrRNA_reads Save FastQ file intermediates after removing rRNA + --remove_ribo_rna Removes ribosomal RNA using SortMeRNA + --save_non_ribo_rna_reads Save FastQ file intermediates after removing rRNA --rRNA_database_manifest Path to file that contains file paths for rRNA databases, optional + Alignment: --aligner [str] Specifies the aligner to use (available are: 'star', 'bowtie1') --star_index [file] Path to STAR index, set to false if igenomes should be used @@ -218,65 +220,97 @@ Channel // Header log info log.info nfcoreHeader() def summary = [:] -if (workflow.revision) summary['Pipeline Release'] = workflow.revision -summary['Run Name'] = custom_runName ?: workflow.runName -summary['Input'] = params.input -if (params.skip_initial_fastqc) summary['Skip Initial FastQC'] = 'Yes' -summary['Data Type'] = params.single_end ? 'Single-End' : 'Paired-End' -if (params.artifacts_5end) summary["5' artifacts"] = params.artifacts_5end -if (params.artifacts_3end) summary["3' artifacts"] = params.artifacts_3end -if (params.skip_trimming) {summary['Skip Trimming'] = 'Yes'} -else{ - summary['trim_ecop'] = params.trim_ecop - summary['trim_linker'] = params.trim_linker - summary['trim_5g'] = params.trim_5g - summary['trim_artifacts'] = params.trim_artifacts - summary['EcoSite'] = params.ecoSite - summary['LinkerSeq'] = params.linkerSeq +if (workflow.revision){ + summary['Pipeline Release'] = workflow.revision +} +summary['Run Name'] = custom_runName ?: workflow.runName +summary['Input'] = params.input +if (params.skip_initial_fastqc) { + summary['Skip Initial FastQC'] = 'Yes' +} +summary['Data Type'] = params.single_end ? 'Single-End' : 'Paired-End' +if (params.artifacts_5end){ + summary["5' artifacts"] = params.artifacts_5end +} +if (params.artifacts_3end){ + summary["3' artifacts"] = params.artifacts_3end +} +if (params.skip_trimming) { + summary['Skip Trimming'] = 'Yes' +} else { + summary['trim_ecop'] = params.trim_ecop + summary['trim_linker'] = params.trim_linker + summary['trim_5g'] = params.trim_5g + summary['trim_artifacts'] = params.trim_artifacts + summary['eco_site'] = params.eco_site + summary['linker_seq'] = params.linker_seq +} +summary['Remove rRNA'] = params.remove_ribo_rna +if (params.skip_trimming_fastqc){ + summary['Skip Trimming FastQC'] = 'Yes' +} +if (params.skip_alignment){ + summary['Skip Alignment'] = 'Yes' } -summary['Remove rRNA'] = params.remove_ribo_RNA -if (params.skip_trimming_fastqc) summary['Skip Trimming FastQC'] = 'Yes' -if (params.skip_alignment){summary['Skip Alignment'] = 'Yes'} else { if (params.aligner == 'star') { - summary['Aligner'] = "STAR" - if (params.star_index){summary['STAR Index'] = params.star_index} - else if (params.fasta){summary['Fasta Ref'] = params.fasta} + summary['Aligner'] = 'STAR' + if (params.star_index){ + summary['STAR Index'] = params.star_index + } else if (params.fasta){ + summary['Fasta Ref'] = params.fasta + } } else if (params.aligner == 'bowtie1') { - summary['Aligner'] = "bowtie" - if (params.bowtie_index) summary['bowtie Index'] = params.bowtie_index - else if (params.fasta) summary['Fasta Ref'] = params.fasta + summary['Aligner'] = 'bowtie1' + if (params.bowtie_index){ + summary['bowtie Index'] = params.bowtie_index + } else if (params.fasta){ + summary['Fasta Ref'] = params.fasta + } } } -if(params.skip_ctss_generation) {summary['Skip CTSS generation'] = 'Yes'} -else{ - summary['Min. cluster'] = params.min_cluster - summary['Cluster Threshold']= params.tpm_cluster_threshold +if(params.skip_ctss_generation){ + summary['Skip CTSS generation'] = 'Yes' +} else{ + summary['Min. cluster'] = params.min_cluster + summary['Cluster Threshold'] = params.tpm_cluster_threshold +} +if(params.skip_ctss_qc) { + summary['Skip CTSS QC'] = 'Yes' +} +if(params.bigwig){ + summary['bigwig output'] = 'Yes' } -if(params.skip_ctss_qc) {summary['Skip CTSS QC'] = 'Yes'} -summary['Save Reference'] = params.saveReference -summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" -if (workflow.containerEngine) summary['Container'] = "$workflow.containerEngine - $workflow.container" -summary['bigwig output'] = params.bigwig -summary['Output dir'] = params.outdir -summary['Launch dir'] = workflow.launchDir -summary['Working dir'] = workflow.workDir -summary['Script dir'] = workflow.projectDir -summary['User'] = workflow.userName +summary['Save Reference'] = params.save_reference +summary['Max Resources'] = "$params.max_memory memory, $params.max_cpus cpus, $params.max_time time per job" +if (workflow.containerEngine){ + summary['Container'] = "$workflow.containerEngine - $workflow.container" +} +summary['Output dir'] = params.outdir +summary['Launch dir'] = workflow.launchDir +summary['Working dir'] = workflow.workDir +summary['Script dir'] = workflow.projectDir +summary['User'] = workflow.userName if (workflow.profile.contains('awsbatch')) { - summary['AWS Region'] = params.awsregion - summary['AWS Queue'] = params.awsqueue - summary['AWS CLI'] = params.awscli + summary['AWS Region'] = params.awsregion + summary['AWS Queue'] = params.awsqueue + summary['AWS CLI'] = params.awscli +} +summary['Config Profile'] = workflow.profile +if (params.config_profile_description){ + summary['Config Profile Description'] = params.config_profile_description +} +if (params.config_profile_contact){ + summary['Config Profile Contact'] = params.config_profile_contact +} +if (params.config_profile_url){ + summary['Config Profile URL'] = params.config_profile_url } -summary['Config Profile'] = workflow.profile -if (params.config_profile_description) summary['Config Profile Description'] = params.config_profile_description -if (params.config_profile_contact) summary['Config Profile Contact'] = params.config_profile_contact -if (params.config_profile_url) summary['Config Profile URL'] = params.config_profile_url -summary['Config Files'] = workflow.configFiles.join(', ') +summary['Config Files'] = workflow.configFiles.join(', ') if (params.email || params.email_on_fail) { - summary['E-mail Address'] = params.email - summary['E-mail on failure'] = params.email_on_fail - summary['MultiQC maxsize'] = params.max_multiqc_email_size + summary['E-mail Address'] = params.email + summary['E-mail on failure'] = params.email_on_fail + summary['MultiQC maxsize'] = params.max_multiqc_email_size } log.info summary.collect { k,v -> "${k.padRight(18)}: $v" }.join("\n") log.info "-\033[2m--------------------------------------------------\033[0m-" @@ -361,15 +395,15 @@ if(!params.skip_ctss_generation){ */ if(!params.skip_initial_fastqc){ process fastqc { - tag "$sample_name" - label 'process_medium' + tag "$name" + label 'process_low' publishDir "${params.outdir}/fastqc", mode: params.publish_dir_mode, saveAs: { filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename" } input: - set val(sample_name), file(reads) from ch_read_files_fastqc + set val(name), file(reads) from ch_read_files_fastqc output: file "*_fastqc.{zip,html}" into fastqc_results @@ -389,10 +423,10 @@ if(!params.skip_initial_fastqc){ if(params.aligner == 'star' && !params.star_index && params.fasta && !params.skip_alignment){ process makeSTARindex { - label 'high_memory' + label 'process_high' tag "${fasta.baseName}" - publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, - saveAs: { params.saveReference ? it : null }, mode: params.publish_dir_mode + publishDir path: { params.save_reference ? "${params.outdir}/reference_genome" : params.outdir }, + saveAs: { params.save_reference ? it : null }, mode: params.publish_dir_mode input: file fasta from fasta_star_index @@ -407,7 +441,7 @@ if(params.aligner == 'star' && !params.star_index && params.fasta && !params.ski mkdir star STAR \\ --runMode genomeGenerate \\ - --runThreadN ${task.cpus} \\ + --runThreadN $task.cpus \\ --sjdbGTFfile $gtf \\ --genomeDir star/ \\ --genomeFastaFiles $fasta \\ @@ -419,20 +453,18 @@ if(params.aligner == 'star' && !params.star_index && params.fasta && !params.ski if(params.aligner == 'bowtie1' && !params.bowtie_index && params.fasta && !params.skip_alignment){ process makeBowtieindex { tag "${fasta.baseName}" - publishDir path: { params.saveReference ? "${params.outdir}/reference_genome" : params.outdir }, - saveAs: { params.saveReference ? it : null }, mode: params.publish_dir_mode + publishDir path: { params.save_reference ? "${params.outdir}/reference_genome" : params.outdir }, + saveAs: { params.save_reference ? it : null }, mode: params.publish_dir_mode input: file fasta from fasta_bowtie_index output: file "${fasta.baseName}.index*" into bowtie_index - when: - script: """ - bowtie-build --threads ${task.cpus} ${fasta} ${fasta.baseName}.index + bowtie-build --threads $task.cpus ${fasta} ${fasta.baseName}.index """ } } @@ -443,7 +475,7 @@ if(params.aligner == 'bowtie1' && !params.bowtie_index && params.fasta && !param if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ process trim_adapters { - tag "$sample_name" + tag "$name" publishDir "${params.outdir}/trimmed/adapter_trimmed", mode: params.publish_dir_mode, saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" @@ -452,25 +484,25 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ } input: - set val(sample_name), file(reads) from read_files_trimming + set val(name), file(reads) from read_files_trimming output: - set val(sample_name), file("*.fastq.gz") into trimmed_reads_trim_5g + set val(name), file("*.fastq.gz") into trimmed_reads_trim_5g file "*.output.txt" into cutadapt_results script: // Cut Both EcoP and Linker if (params.trim_ecop && params.trim_linker){ """ - cutadapt -a ^${params.ecoSite}...${params.linkerSeq} \\ - --match-read-wildcards \\ - --minimum-length 15 --maximum-length 40 \\ - --discard-untrimmed \\ - --quality-cutoff 30 \\ - --cores=${task.cpus} \\ - -o "$sample_name".adapter_trimmed.fastq.gz \\ - $reads \\ - > "$sample_name"_adapter_trimming.output.txt + cutadapt -a ^${params.eco_site}...${params.linker_seq} \\ + --match-read-wildcards \\ + --minimum-length 15 --maximum-length 40 \\ + --discard-untrimmed \\ + --quality-cutoff 30 \\ + --cores=$task.cpus \\ + -o "$name".adapter_trimmed.fastq.gz \\ + $reads \\ + > "$name"_adapter_trimming.output.txt """ } @@ -478,16 +510,16 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ else if (params.trim_ecop && !params.trim_linker){ """ mkdir trimmed - cutadapt -g ^${params.ecoSite} \\ - -e 0 \\ - --match-read-wildcards \\ - --minimum-length 20 --maximum-length 40 \\ - --discard-untrimmed \\ - --quality-cutoff 30 \\ - --cores=${task.cpus} \\ - -o "$sample_name".adapter_trimmed.fastq.gz \\ - $reads \\ - > "$sample_name"_adapter_trimming.output.txt + cutadapt -g ^${params.eco_site} \\ + -e 0 \\ + --match-read-wildcards \\ + --minimum-length 20 --maximum-length 40 \\ + --discard-untrimmed \\ + --quality-cutoff 30 \\ + --cores=$task.cpus \\ + -o "$name".adapter_trimmed.fastq.gz \\ + $reads \\ + > "$name"_adapter_trimming.output.txt """ } @@ -495,16 +527,16 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ else if (!params.trim_ecop && params.trim_linker){ """ mkdir trimmed - cutadapt -a ${params.linkerSeq}\$ \\ - -e 0 \\ - --match-read-wildcards \\ - --minimum-length 20 --maximum-length 40 \\ - --discard-untrimmed \\ - --quality-cutoff 30 \\ - --cores=${task.cpus} \\ - -o "$sample_name".adapter_trimmed.fastq.gz \\ - $reads \\ - > "$sample_name"_adapter_trimming.output.txt + cutadapt -a ${params.linker_seq}\$ \\ + -e 0 \\ + --match-read-wildcards \\ + --minimum-length 20 --maximum-length 40 \\ + --discard-untrimmed \\ + --quality-cutoff 30 \\ + --cores=$task.cpus \\ + -o "$name".adapter_trimmed.fastq.gz \\ + $reads \\ + > "$name"_adapter_trimming.output.txt """ } } @@ -518,28 +550,28 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ */ if (params.trim_5g && !params.skip_trimming){ process trim_5g{ - tag "$sample_name" - publishDir "${params.outdir}/trimmed/g_trimmed", mode: params.publish_dir_mode, - saveAs: {filename -> - if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" - else if (params.save_trimmed) "$filename" - else null - } + tag "$name" + publishDir "${params.outdir}/trimmed/g_trimmed", mode: params.publish_dir_mode, + saveAs: {filename -> + if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" + else if (params.save_trimmed) "$filename" + else null + } input: - set val(sample_name), file(reads) from trimmed_reads_trim_5g + set val(name), file(reads) from trimmed_reads_trim_5g output: - set val(sample_name), file("*.fastq.gz") into processed_reads + set val(name), file("*.fastq.gz") into processed_reads script: """ cutadapt -g ^G \\ -e 0 --match-read-wildcards \\ - --cores=${task.cpus} \\ - -o "$sample_name".g_trimmed.fastq.gz \\ + --cores=$task.cpus \\ + -o "$name".g_trimmed.fastq.gz \\ $reads \\ - > "$sample_name".g_trimming.output.txt + > "$name".g_trimming.output.txt """ } } @@ -552,7 +584,7 @@ else { if (params.trim_artifacts && !params.skip_trimming){ process trim_artifacts { - tag "$sample_name" + tag "$name" publishDir "${params.outdir}/trimmed/artifacts_trimmed", mode: params.publish_dir_mode, saveAs: {filename -> if (filename.indexOf(".fastq.gz") == -1) "logs/$filename" @@ -561,23 +593,23 @@ if (params.trim_artifacts && !params.skip_trimming){ } input: - set val(sample_name), file(reads) from processed_reads + set val(name), file(reads) from processed_reads file artifacts_5end from ch_5end_artifacts.collect() file artifacts_3end from ch_3end_artifacts.collect() output: - set val(sample_name), file("*.fastq.gz") into further_processed_reads_sortmerna + set val(name), file("*.fastq.gz") into further_processed_reads_sortmerna file "*.output.txt" into artifact_cutting_results script: """ cutadapt -a file:$artifacts_3end \\ - -g file:$artifacts_5end -e 0.1 --discard-trimmed \\ - --match-read-wildcards -m 15 -O 19 \\ - --cores=${task.cpus} \\ - -o "$sample_name".artifacts_trimmed.fastq.gz \\ - $reads \\ - > ${reads.baseName}.artifacts_trimming.output.txt + -g file:$artifacts_5end -e 0.1 --discard-trimmed \\ + --match-read-wildcards -m 15 -O 19 \\ + --cores=$task.cpus \\ + -o "$name".artifacts_trimmed.fastq.gz \\ + $reads \\ + > ${reads.baseName}.artifacts_trimming.output.txt """ } } else{ @@ -588,22 +620,23 @@ if (params.trim_artifacts && !params.skip_trimming){ /* * STEP 6 - SortMeRNA - remove rRNA sequences on request */ -if (params.remove_ribo_RNA) { +if (params.remove_ribo_rna) { process sortmerna { - label 'high_memory' - tag "$sample_name" + label 'process_high' + tag "$name" publishDir "${params.outdir}/SortMeRNA", mode: params.publish_dir_mode, saveAs: {filename -> if (filename.indexOf("_rRNA_report.txt") > 0) "logs/$filename" - else if (params.save_nonrRNA_reads) "reads/$filename" + else if (params.save_non_ribo_rna_reads) "reads/$filename" else null } + input: - set val(sample_name), file(reads) from further_processed_reads_sortmerna + set val(name), file(reads) from further_processed_reads_sortmerna file(fasta) from fasta_sortmerna.collect() output: - set val(sample_name), file("*.fq.gz") into further_processed_reads_alignment, further_processed_reads_fastqc; + set val(name), file("*.fq.gz") into further_processed_reads_alignment, further_processed_reads_fastqc; file "*_rRNA_report.txt" into sortmerna_logs script: @@ -614,14 +647,14 @@ if (params.remove_ribo_RNA) { sortmerna ${Refs} \\ --reads ${reads} \\ --num_alignments 1 \\ - --threads ${task.cpus} \\ + --threads $task.cpus \\ --workdir . \\ --fastx \\ --aligned rRNA-reads \\ --other non-rRNA-reads \\ -v - gzip --force < non-rRNA-reads.fastq > ${sample_name}.fq.gz - mv rRNA-reads.log ${sample_name}_rRNA_report.txt + gzip --force < non-rRNA-reads.fastq > $name.fq.gz + mv rRNA-reads.log $name_rRNA_report.txt """ } } else { @@ -631,18 +664,19 @@ if (params.remove_ribo_RNA) { // Post trimming QC, only needed if some trimming has been done if(!params.skip_trimming_fastqc){ process trimmed_fastqc { - tag "$sample_name" + tag "$name" publishDir "${params.outdir}/trimmed/fastqc", mode: params.publish_dir_mode, saveAs: {filename -> filename.indexOf(".zip") > 0 ? "zips/$filename" : "$filename"} input: - set val(sample_name), file(reads) from further_processed_reads_fastqc + set val(name), file(reads) from further_processed_reads_fastqc output: path "*_fastqc.{zip,html}" into trimmed_fastqc_results when: (params.trim_ecop || params.trim_linker || params.trim_5g || params.trim_artifacts) && !params.skip_trimming + script: """ fastqc -q $reads @@ -657,20 +691,20 @@ if(!params.skip_trimming_fastqc){ if(!params.skip_alignment){ if (params.aligner == 'star') { process star { - label 'high_memory' - tag "$sample_name" + label 'process_high' + tag "$name" publishDir "${params.outdir}/STAR", mode: params.publish_dir_mode, saveAs: {filename -> if (filename.indexOf(".bam") == -1) "logs/$filename" else filename } input: - set val(sample_name), file(reads) from further_processed_reads_alignment + set val(name), file(reads) from further_processed_reads_alignment file index from star_index.collect() file gtf from gtf_star.collect() output: - set val(sample_name), file("*.bam") into star_aligned + set val(name), file("*.bam") into star_aligned file "*.out" into star_alignment_logs file "*SJ.out.tab" @@ -679,14 +713,14 @@ if(!params.skip_alignment){ STAR --genomeDir $index \\ --sjdbGTFfile $gtf \\ --readFilesIn $reads \\ - --runThreadN ${task.cpus} \\ + --runThreadN $task.cpus \\ --outSAMtype BAM SortedByCoordinate \\ --outFilterScoreMinOverLread 0 --outFilterMatchNminOverLread 0 \\ --seedSearchStartLmax 20 \\ --outFilterMismatchNmax 1 \\ --readFilesCommand zcat \\ --runDirPerm All_RWX \\ - --outFileNamePrefix $sample_name \\ + --outFileNamePrefix $name \\ --outFilterMultimapNmax 1 """ } @@ -695,43 +729,43 @@ if(!params.skip_alignment){ star_alignment_logs = Channel.empty() } if (params.aligner == 'bowtie1'){ - process bowtie { - label 'high_memory' - tag "$sample_name" - publishDir "${params.outdir}/bowtie", mode: params.publish_dir_mode, - saveAs: {filename -> - if (filename.indexOf(".bam") == -1) "logs/$filename" - else filename } + process bowtie { + label 'process_high' + tag "$name" + publishDir "${params.outdir}/bowtie", mode: params.publish_dir_mode, + saveAs: {filename -> + if (filename.indexOf(".bam") == -1) "logs/$filename" + else filename } - input: - set val(sample_name), file(reads) from further_processed_reads_alignment - file index_array from bowtie_index.collect() + input: + set val(name), file(reads) from further_processed_reads_alignment + file index_array from bowtie_index.collect() - output: - set val(sample_name), file("*.bam") into bam_stats, bam_aligned - file "*.out" into bowtie_alignment_logs + output: + set val(name), file("*.bam") into bam_stats, bam_aligned + file "*.out" into bowtie_alignment_logs - script: - index = index_array[0].baseName - ~/.\d$/ - """ - bowtie --sam \\ - -m 1 \\ - --best \\ - --strata \\ - -k 1 \\ - --tryhard \\ - --threads ${task.cpus} \\ - --phred33-quals \\ - --chunkmbs 64 \\ - --seedmms 2 \\ - --seedlen 20 \\ - --maqerr 70 \\ - ${index} \\ - -q ${reads} \\ - --un ${reads.baseName}.unAl > ${sample_name}.sam 2> ${sample_name}.out - samtools sort -@ ${task.cpus} -o ${sample_name}.bam ${sample_name}.sam - """ - } + script: + index = index_array[0].baseName - ~/.\d$/ + """ + bowtie --sam \\ + -m 1 \\ + --best \\ + --strata \\ + -k 1 \\ + --tryhard \\ + --threads $task.cpus \\ + --phred33-quals \\ + --chunkmbs 64 \\ + --seedmms 2 \\ + --seedlen 20 \\ + --maqerr 70 \\ + ${index} \\ + -q ${reads} \\ + --un ${reads.baseName}.unAl > $name.sam 2> $name.out + samtools sort -@ $task.cpus -o $name.bam $name.sam + """ + } }else{ bowtie_alignment_logs= Channel.empty() } @@ -743,11 +777,11 @@ if(!params.skip_alignment){ } if(!params.skip_samtools_stats && !params.skip_samtools_stats){ process samtools_stats { - tag "$sample_name" - label 'process_medium' + tag "$name" + label 'process_low' input: - set val(sample_name), file(bam_count) from bam_stats + set val(name), file(bam_count) from bam_stats output: file "*.{flagstat,idxstats,stats}" into bam_flagstat_mqc @@ -767,8 +801,7 @@ if(!params.skip_ctss_generation){ * STEP 8 - group CAGE tags */ process get_ctss { - tag "$sample_name" - publishDir "${params.outdir}/ctss", mode: params.publish_dir_mode + tag "$name" publishDir "${params.outdir}/ctss", mode: params.publish_dir_mode, saveAs: {filename -> if (filename.indexOf(".bed") != -1) "bed/$filename" @@ -776,33 +809,34 @@ if(!params.skip_ctss_generation){ else filename } input: - set val(sample_name), file(bam_count) from bam_aligned + set val(name), file(bam_count) from bam_aligned output: - set val(sample_name), file("*.ctss.bed") into (ctss_samples,ctss_bw) + set val(name), file("*.ctss.bed") into (ctss_samples,ctss_bw) file("*.ctss.bed") into (ctss_counts, ctss_counts_qc) shell: ''' - make_ctss.sh -q 20 -i !{bam_count.baseName} -n !{sample_name} + make_ctss.sh -q 20 -i !{bam_count.baseName} -n !{name} ''' } if(params.bigwig){ process make_bigwig{ - tag "$sample_name" + tag "$name" publishDir "${params.outdir}/ctss/bigwig", mode: params.publish_dir_mode input: - set val(sample_name), file(ctss_file) from ctss_bw + set val(name), file(ctss_file) from ctss_bw file chrom_sizes from chrom_sizes_bw output: file("*.ctss.bw") + script: """ - bedtools genomecov -bg -i ${sample_name}.ctss.bed -g ${chrom_sizes} > ${sample_name}.bedgraph - sort -k1,1 -k2,2n ${sample_name}.bedgraph > ${sample_name}_sorted.bedgraph - bedGraphToBigWig ${sample_name}_sorted.bedgraph ${chrom_sizes} ${sample_name}.ctss.bw + bedtools genomecov -bg -i $name.ctss.bed -g ${chrom_sizes} > $name.bedgraph + sort -k1,1 -k2,2n $name.bedgraph > $name_sorted.bedgraph + bedGraphToBigWig $name_sorted.bedgraph ${chrom_sizes} $name.ctss.bw """ } } @@ -811,7 +845,7 @@ if(!params.skip_ctss_generation){ */ ctss_counts = ctss_counts.collect().dump(tag:"ctss_counts") process cluster_ctss { - label "high_memory" + label "process_high" publishDir "${params.outdir}/ctss/clusters", mode: params.publish_dir_mode input: @@ -820,7 +854,6 @@ if(!params.skip_ctss_generation){ output: file "*.bed" into ctss_clusters - shell: ''' process_ctss.sh -t !{params.tpm_cluster_threshold} !{ctss} @@ -840,10 +873,10 @@ if(!params.skip_ctss_generation){ * STEP 10 - Generate count files */ process generate_counts { - tag "${sample_name}" + tag "$name" input: - set val(sample_name), file(ctss) from ctss_samples + set val(name), file(ctss) from ctss_samples file clusters from ctss_clusters.collect() output: @@ -852,10 +885,9 @@ if(!params.skip_ctss_generation){ shell: ''' - #intersect ctss files with generated clusters intersectBed -a !{clusters} -b !{ctss} -loj -s > !{ctss}_counts_tmp - echo !{sample_name} > !{ctss}_counts.txt + echo !{name} > !{ctss}_counts.txt bedtools groupby -i !{ctss}_counts_tmp -g 1,2,3,4,6 -c 11 -o sum > !{ctss}_counts.bed awk -v OFS='\t' '{if($6=="-1") $6=0; print $6 }' !{ctss}_counts.bed >> !{ctss}_counts.txt @@ -902,11 +934,11 @@ if(!params.skip_ctss_generation){ output: file "*.txt" into rseqc_results - shell: - ''' - bedtools bedtobam -i !{clusters} -g !{chrom_sizes} > !{clusters.baseName}.bam - read_distribution.py -i !{clusters.baseName}.bam -r !{gtf} > !{clusters.baseName}.read_distribution.txt - ''' + script: + """ + bedtools bedtobam -i $clusters -g $chrom_sizes > ${clusters.baseName}.bam + read_distribution.py -i ${clusters.baseName}.bam -r $gtf > ${clusters.baseName}.read_distribution.txt + """ } } else { rseqc_results = Channel.empty() @@ -924,7 +956,7 @@ process multiqc { input: file multiqc_config from ch_multiqc_config - file (mqc_custom_config) from ch_multiqc_custom_config.collect().ifEmpty([]) + file mqc_custom_config from ch_multiqc_custom_config.collect().ifEmpty([]) file ('software_versions/*') from ch_software_versions_yaml.collect() file ('fastqc/*') from fastqc_results.collect().ifEmpty([]) file ('trimmed/*') from cutadapt_results.collect().ifEmpty([]) diff --git a/nextflow.config b/nextflow.config index 7463e9f..d873a4f 100644 --- a/nextflow.config +++ b/nextflow.config @@ -18,7 +18,7 @@ params { // CAGE-seq specific options // Alignment options aligner = 'star' - saveReference = false + save_reference = false min_aln_length = 15 single_end = true @@ -28,8 +28,8 @@ params { trim_linker = true trim_5g = true trim_artifacts = false - ecoSite = 'CAGCAG' - linkerSeq = 'TCGTATGCCGTCTTC' + eco_site = 'CAGCAG' + linker_seq = 'TCGTATGCCGTCTTC' artifacts_5end = "$baseDir/assets/artifacts_5end.fasta" artifacts_3end = "$baseDir/assets/artifacts_3end.fasta" @@ -43,8 +43,8 @@ params { skip_ctss_qc = false // Ribosomal RNA removal - remove_ribo_RNA = false - save_nonrRNA_reads = false + remove_ribo_rna = false + save_non_ribo_rna_reads = false rRNA_database_manifest = "$baseDir/assets/rrna-db-defaults.txt" //Output options @@ -74,7 +74,11 @@ params { config_profile_contact = false config_profile_url = false - + // Defaults only, expecting to be overwritten + max_memory = 128.GB + max_cpus = 16 + max_time = 240.h + igenomes_base = 's3://ngi-igenomes/igenomes/' } @@ -108,11 +112,6 @@ profiles { singularity.autoMounts = true } test { includeConfig 'conf/test.config' } - galaxy { - includeConfig 'conf/base.config' - includeConfig 'conf/galaxy_local.config' - includeConfig 'conf/igenomes.config' -} } // Load igenomes.config if required diff --git a/nextflow_schema.json b/nextflow_schema.json index bdb6776..67d9f53 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -120,7 +120,7 @@ "fa_icon": "fab fa-black-tie", "description": "Path to bowtie index directory." }, - "saveReference": { + "save_reference": { "type": "boolean", "fa_icon": "far fa-save", "description": "All generated reference files will be saved to the results folder if this flag is set." @@ -158,13 +158,13 @@ "fa_icon": "fas fa-cut", "description": "Artifacts, generated in the sequencing process, are cut if this flag is not set to false." }, - "ecoSite": { + "eco_site": { "type": "string", "default": "CAGCAG", "description": "Sequence of the ecoP15 site at the 5' end", "fa_icon": "far fa-hand-scissors" }, - "linkerSeq": { + "linker_seq": { "type": "string", "default": "TCGTATGCCGTCTTC", "fa_icon": "fas fa-link", @@ -191,11 +191,11 @@ "default": "", "fa_icon": "far fa-trash-alt", "properties": { - "remove_ribo_RNA": { + "remove_ribo_rna": { "type": "boolean", "fa_icon": "far fa-trash-alt" }, - "save_nonrRNA_reads": { + "save_non_ribo_rna_reads": { "type": "boolean", "fa_icon": "far fa-save" }, From a4c6fad3a6e91592dfc012bcfcf8dbcb5e1c604f Mon Sep 17 00:00:00 2001 From: matthiasho Date: Tue, 18 Aug 2020 15:57:42 +0200 Subject: [PATCH 092/107] fix too aggressive find-replace error --- main.nf | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/main.nf b/main.nf index 633ce7c..3ef38ee 100644 --- a/main.nf +++ b/main.nf @@ -500,9 +500,9 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ --discard-untrimmed \\ --quality-cutoff 30 \\ --cores=$task.cpus \\ - -o "$name".adapter_trimmed.fastq.gz \\ + -o "${name}".adapter_trimmed.fastq.gz \\ $reads \\ - > "$name"_adapter_trimming.output.txt + > "${name}"_adapter_trimming.output.txt """ } @@ -517,9 +517,9 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ --discard-untrimmed \\ --quality-cutoff 30 \\ --cores=$task.cpus \\ - -o "$name".adapter_trimmed.fastq.gz \\ + -o "${name}".adapter_trimmed.fastq.gz \\ $reads \\ - > "$name"_adapter_trimming.output.txt + > "${name}"_adapter_trimming.output.txt """ } @@ -534,9 +534,9 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ --discard-untrimmed \\ --quality-cutoff 30 \\ --cores=$task.cpus \\ - -o "$name".adapter_trimmed.fastq.gz \\ + -o "${name}".adapter_trimmed.fastq.gz \\ $reads \\ - > "$name"_adapter_trimming.output.txt + > "${name}"_adapter_trimming.output.txt """ } } @@ -569,9 +569,9 @@ if (params.trim_5g && !params.skip_trimming){ cutadapt -g ^G \\ -e 0 --match-read-wildcards \\ --cores=$task.cpus \\ - -o "$name".g_trimmed.fastq.gz \\ + -o "${name}".g_trimmed.fastq.gz \\ $reads \\ - > "$name".g_trimming.output.txt + > "${name}".g_trimming.output.txt """ } } @@ -607,7 +607,7 @@ if (params.trim_artifacts && !params.skip_trimming){ -g file:$artifacts_5end -e 0.1 --discard-trimmed \\ --match-read-wildcards -m 15 -O 19 \\ --cores=$task.cpus \\ - -o "$name".artifacts_trimmed.fastq.gz \\ + -o "${name}".artifacts_trimmed.fastq.gz \\ $reads \\ > ${reads.baseName}.artifacts_trimming.output.txt """ @@ -653,8 +653,8 @@ if (params.remove_ribo_rna) { --aligned rRNA-reads \\ --other non-rRNA-reads \\ -v - gzip --force < non-rRNA-reads.fastq > $name.fq.gz - mv rRNA-reads.log $name_rRNA_report.txt + gzip --force < non-rRNA-reads.fastq > ${name}.fq.gz + mv rRNA-reads.log ${name}_rRNA_report.txt """ } } else { @@ -762,8 +762,8 @@ if(!params.skip_alignment){ --maqerr 70 \\ ${index} \\ -q ${reads} \\ - --un ${reads.baseName}.unAl > $name.sam 2> $name.out - samtools sort -@ $task.cpus -o $name.bam $name.sam + --un ${reads.baseName}.unAl > ${name}.sam 2> ${name}.out + samtools sort -@ $task.cpus -o ${name}.bam ${name}.sam """ } }else{ @@ -834,9 +834,9 @@ if(!params.skip_ctss_generation){ script: """ - bedtools genomecov -bg -i $name.ctss.bed -g ${chrom_sizes} > $name.bedgraph - sort -k1,1 -k2,2n $name.bedgraph > $name_sorted.bedgraph - bedGraphToBigWig $name_sorted.bedgraph ${chrom_sizes} $name.ctss.bw + bedtools genomecov -bg -i ${name}.ctss.bed -g ${chrom_sizes} > ${name}.bedgraph + sort -k1,1 -k2,2n ${name}.bedgraph > ${name}_sorted.bedgraph + bedGraphToBigWig ${name}_sorted.bedgraph ${chrom_sizes} ${name}.ctss.bw """ } } From 71fd052f254df8f86ad9f292e860de2a63f1e6c0 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 21 Aug 2020 08:35:47 +0200 Subject: [PATCH 093/107] swithc to conda version of paraclu --- Dockerfile | 5 ----- environment.yml | 1 + main.nf | 4 ++-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 13d1526..9b70d32 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,11 +10,6 @@ RUN conda env create --quiet -f /environment.yml && conda clean -a ENV PATH /opt/conda/envs/nf-core-cageseq-1.0.0/bin:$PATH # Dump the details of the installed packages to a file for posterity RUN conda env export --name nf-core-cageseq-1.0.0 > nf-core-cageseq-1.0.0.yml -# Setup paraclu -RUN apt-get update; apt-get install -y build-essential g++ -RUN wget http://cbrc3.cbrc.jp/~martin/paraclu/paraclu-9.zip && \ - unzip paraclu-9.zip; cd paraclu-9; make -ENV PATH /paraclu-9:$PATH # Instruct R processes to use these empty files instead of clashing with a local version RUN touch .Rprofile diff --git a/environment.yml b/environment.yml index 2d6c9ec..3bc5ed5 100644 --- a/environment.yml +++ b/environment.yml @@ -21,3 +21,4 @@ dependencies: - bioconda::rseqc=3.0.1 - bioconda::ucsc-bedgraphtobigwig=357 - bioconda::sortmerna=4.2.0 + - bioconda::paraclu=9 \ No newline at end of file diff --git a/main.nf b/main.nf index 3ef38ee..3f596ae 100644 --- a/main.nf +++ b/main.nf @@ -861,8 +861,8 @@ if(!params.skip_ctss_generation){ paraclu !{params.min_cluster} "ctss_all_pos_4Ps" > "ctss_all_pos_clustered" paraclu !{params.min_cluster} "ctss_all_neg_4Ps" > "ctss_allneg_clustered" - paraclu-cut.sh "ctss_all_pos_clustered" > "ctss_all_pos_clustered_simplified" - paraclu-cut.sh "ctss_all_neg_clustered" > "ctss_all_neg_clustered_simplified" + paraclu-cut "ctss_all_pos_clustered" > "ctss_all_pos_clustered_simplified" + paraclu-cut "ctss_all_neg_clustered" > "ctss_all_neg_clustered_simplified" cat "ctss_all_pos_clustered_simplified" "ctss_all_neg_clustered_simplified" > "ctss_all_clustered_simplified" awk -F '\t' '{print $1"\t"$3"\t"$4"\t"$1":"$3".."$4","$2"\t"$6"\t"$2}' "ctss_all_clustered_simplified" > "ctss_all_clustered_simplified.bed" From 3ff25d60f4b97c206d14e276873344df04be5de4 Mon Sep 17 00:00:00 2001 From: matthiasho Date: Fri, 21 Aug 2020 10:26:38 +0200 Subject: [PATCH 094/107] fix inconsistent option names --- main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.nf b/main.nf index 3ef38ee..ccd91ea 100644 --- a/main.nf +++ b/main.nf @@ -642,7 +642,7 @@ if (params.remove_ribo_rna) { script: //concatenate reference files: ${db_fasta},${db_name}:${db_fasta},${db_name}:... def Refs = "" - for (i=0; i Date: Fri, 21 Aug 2020 10:28:17 +0200 Subject: [PATCH 095/107] clean up `environment.yml` --- environment.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/environment.yml b/environment.yml index 3bc5ed5..95346d5 100644 --- a/environment.yml +++ b/environment.yml @@ -11,14 +11,13 @@ dependencies: - conda-forge::pymdown-extensions=6.0 - conda-forge::pygments=2.5.2 - bioconda::bedtools=2.29.2 + - bioconda::bowtie=1.2.3 - bioconda::cutadapt=2.10 - bioconda::fastqc=0.11.9 - - bioconda::samtools=1.10 - - bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. - bioconda::multiqc=1.9 - - conda-forge::unzip=6.0 - - bioconda::bowtie=1.2.3 + - bioconda::paraclu=9 - bioconda::rseqc=3.0.1 - - bioconda::ucsc-bedgraphtobigwig=357 + - bioconda::samtools=1.10 + - bioconda::star=2.6.1d # Don't upgrade me - 2.7X indices incompatible with iGenomes. - bioconda::sortmerna=4.2.0 - - bioconda::paraclu=9 \ No newline at end of file + - bioconda::ucsc-bedgraphtobigwig=357 From 71d418f69449579924d5ae2e8540d773ab0ff7ca Mon Sep 17 00:00:00 2001 From: matthiasho Date: Fri, 21 Aug 2020 10:56:40 +0200 Subject: [PATCH 096/107] change parameter names in ci tests --- .github/workflows/awstest.yml | 2 +- .github/workflows/ci.yml | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index c5f14ae..b4db19f 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -26,7 +26,7 @@ jobs: # Nextflow versions: check pipeline minimum and current latest nxf_ver: ['19.10.0', ''] aligner: ["--aligner 'bowtie1'", "--aligner 'star'"] - options: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false'] + options: ['--skip_trimming true','--trim_ecop false','--trim_linker false','--trim_5g false','--trim_artifacts false', '--bigwig', '--remove_ribo_rna'] env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4fc30d..136146f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,8 +21,6 @@ jobs: matrix: # Nextflow versions: check pipeline minimum and current latest nxf_ver: ['19.10.0', ''] - aligner: ["--aligner bowtie1", "--aligner star"] - options: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false', '--bigwig', '--remove_ribo_rna'] steps: - name: Check out pipeline code uses: actions/checkout@v2 @@ -42,7 +40,7 @@ jobs: if: ${{ !env.GIT_DIFF }} run: | docker pull nfcore/cageseq:dev - docker tag nfcore/cageseq:dev nfcore/cageseq:1.0.0x + docker tag nfcore/cageseq:dev nfcore/cageseq:1.0.0 - name: Install Nextflow run: | @@ -65,7 +63,7 @@ jobs: matrix: # Nextflow versions: check pipeline minimum and current latest aligner: ["--aligner bowtie1", "--aligner star"] - parameters: ['--trimming false','--cutEcoP false','--cutLinker false','--cutG false','--cutArtifacts false', '--bigwig', '--remove_ribo_rna'] + parameters: ['--skip_trimming true','--trim_ecop false','--trim_linker false','--trim_5g false','--trim_artifacts false', '--bigwig', '--remove_ribo_rna'] steps: - name: Check out pipeline code uses: actions/checkout@v2 @@ -85,7 +83,7 @@ jobs: if: ${{ !env.GIT_DIFF }} run: | docker pull nfcore/cageseq:dev - docker tag nfcore/cageseq:dev nfcore/cageseq:1.0.0x + docker tag nfcore/cageseq:dev nfcore/cageseq:1.0.0 - name: Install Nextflow run: | From 2d8e9b0b8352bb51699fdddbd8404cd4860001b2 Mon Sep 17 00:00:00 2001 From: matthiasho Date: Fri, 21 Aug 2020 11:06:09 +0200 Subject: [PATCH 097/107] remove single_end parameter --- conf/test.config | 1 - main.nf | 1 - nextflow.config | 4 +--- nextflow_schema.json | 7 ------- 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/conf/test.config b/conf/test.config index e32f58e..556f10b 100644 --- a/conf/test.config +++ b/conf/test.config @@ -16,7 +16,6 @@ params { max_time = 48.h // Input data - single_end = true input_paths = [ ['cage 1', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage1.fastq.gz'], ['cage 2', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage2.fastq.gz'] diff --git a/main.nf b/main.nf index d4550a2..e86c52b 100644 --- a/main.nf +++ b/main.nf @@ -228,7 +228,6 @@ summary['Input'] = params.input if (params.skip_initial_fastqc) { summary['Skip Initial FastQC'] = 'Yes' } -summary['Data Type'] = params.single_end ? 'Single-End' : 'Paired-End' if (params.artifacts_5end){ summary["5' artifacts"] = params.artifacts_5end } diff --git a/nextflow.config b/nextflow.config index d873a4f..41b34a6 100644 --- a/nextflow.config +++ b/nextflow.config @@ -11,7 +11,6 @@ params { // Workflow flags genome = false input = 'data/*R1.fastq.gz' - single_end = false outdir = './results' publish_dir_mode = 'copy' @@ -20,8 +19,7 @@ params { aligner = 'star' save_reference = false min_aln_length = 15 - single_end = true - + // Trimming options save_trimmed = false trim_ecop = true diff --git a/nextflow_schema.json b/nextflow_schema.json index 67d9f53..326658c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -21,13 +21,6 @@ "help_text": "Use this to specify the location of your input FastQ files. For example:\n\n```bash\n--input 'path/to/data/sample_*_{1,2}.fastq'\n```\n\nPlease note the following requirements:\n\n1. The path must be enclosed in quotes\n2. The path must have at least one `*` wildcard character\n3. When using the pipeline with paired end data, the path must use `{1,2}` notation to specify read pairs.\n\nIf left unspecified, a default pattern is used: `data/*{1,2}.fastq.gz`", "default": "data/*R1.fastq.gz" }, - "single_end": { - "type": "boolean", - "description": "Specifies that the input is single-end reads.", - "fa_icon": "fas fa-align-center", - "help_text": "By default, the pipeline expects paired-end data. If you have single-end data, you need to specify `--single_end` on the command line when you launch the pipeline. A normal glob pattern, enclosed in quotation marks, can then be used for `--input`. For example:\n\n```bash\n--single_end --input '*.fastq'\n```\n\nIt is not possible to run a mixture of single-end and paired-end files in one run.", - "default": true - }, "outdir": { "type": "string", "description": "The output directory where the results will be saved.", From 72fcf66d57910660a4dbd03c82c63c8474079e4e Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 21 Aug 2020 11:21:41 +0200 Subject: [PATCH 098/107] Update .github/workflows/ci.yml Co-authored-by: Harshil Patel --- .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 136146f..7374005 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,5 +92,5 @@ jobs: - name: Run pipeline with test data run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,docker ${{matrix.alginer}} ${{matrix.parameters}} - \ No newline at end of file + nextflow run ${GITHUB_WORKSPACE} -profile test,docker ${{matrix.aligner}} ${{matrix.parameters}} + From dc791a53a7f5c25f7556b22496e8229c6ac821d9 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 21 Aug 2020 11:28:52 +0200 Subject: [PATCH 099/107] Apply suggestions from code review Co-authored-by: Harshil Patel --- conf/base.config | 4 ---- main.nf | 2 +- nextflow.config | 7 ++++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/conf/base.config b/conf/base.config index 3e4fe56..43e7881 100644 --- a/conf/base.config +++ b/conf/base.config @@ -38,8 +38,4 @@ process { memory = { check_max( 2.GB * task.attempt, 'memory' ) } cache = false } - withName: 'multiqc' { - memory = { check_max( 2.GB * task.attempt, 'memory' ) } - cache = false - } } diff --git a/main.nf b/main.nf index e86c52b..4a695ff 100644 --- a/main.nf +++ b/main.nf @@ -548,7 +548,7 @@ if(!params.skip_trimming && (params.trim_ecop || params.trim_linker)){ * STEP 4 - Remove added G from 5-end */ if (params.trim_5g && !params.skip_trimming){ - process trim_5g{ + process trim_5g { tag "$name" publishDir "${params.outdir}/trimmed/g_trimmed", mode: params.publish_dir_mode, saveAs: {filename -> diff --git a/nextflow.config b/nextflow.config index 41b34a6..dc24a17 100644 --- a/nextflow.config +++ b/nextflow.config @@ -42,8 +42,8 @@ params { // Ribosomal RNA removal remove_ribo_rna = false - save_non_ribo_rna_reads = false - rRNA_database_manifest = "$baseDir/assets/rrna-db-defaults.txt" + save_non_ribo_reads = false + ribo_database_manifest = "$baseDir/assets/rrna-db-defaults.txt" //Output options bigwig=false @@ -109,7 +109,8 @@ profiles { singularity.enabled = true singularity.autoMounts = true } - test { includeConfig 'conf/test.config' } + test { includeConfig 'conf/test.config' } + test_full { includeConfig 'conf/test_full.config' } } // Load igenomes.config if required From 0a43640bd7f187af1a924251cbb82896cf423c0a Mon Sep 17 00:00:00 2001 From: matthiasho Date: Fri, 21 Aug 2020 12:13:29 +0200 Subject: [PATCH 100/107] Apply suggestions from code review manually --- conf/test_full.config | 4 +- main.nf | 98 +++++++++++++++++++++---------------------- nextflow_schema.json | 6 +-- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/conf/test_full.config b/conf/test_full.config index d7fea41..3e1a764 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -13,9 +13,9 @@ params { // Input data for full size test input_paths = [ - input_paths = [ ['cage 1', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage1.fastq.gz'], ['cage 2', 'https://github.com/nf-core/test-datasets/raw/cageseq/testdata/cage2.fastq.gz'] ] - ] + fasta = 'https://github.com/nf-core/test-datasets/raw/cageseq/reference/chr_sub.fasta' + gtf = 'https://github.com/nf-core/test-datasets/raw/cageseq/reference/chr_sub.gtf' } diff --git a/main.nf b/main.nf index 4a695ff..962e929 100644 --- a/main.nf +++ b/main.nf @@ -21,62 +21,62 @@ def helpMessage() { nextflow run nf-core/cageseq --input '*_R1.fastq.gz' -profile docker Mandatory arguments: - --input [file] Path to input data (must be surrounded with quotes) - -profile [str] Configuration profile to use. Can use multiple (comma separated) - Available: docker, singularity, conda, test, awsbatch, and more + --input [file] Path to input data (must be surrounded with quotes) + -profile [str] Configuration profile to use. Can use multiple (comma separated) + Available: docker, singularity, conda, test, awsbatch, and more Trimming: - --save_trimmed [bool] Set to true to Save trimmed FastQ files - --trim_ecop [bool] Set to false to not trim the EcoP site - --trim_linker [bool] Set to false to not trim the linker - --trim_5g [bool] Set to false to not trim the additonal G at the 5' end - --trim_artifacts [bool] Set to false to not trim artifacts - --artifacts_5end [file] Path to 5 end artifact file, if not given the pipeline will use a default file with all possible artifacts - --artifacts_3end [file] Path to 3 end artifact file, if not given the pipeline will use a default file with all possible artifacts - - References If not specified in the configuration file or you wish to overwrite any of the references - --fasta [file] Path to fasta reference - --genome [str] Name of iGenomes reference - --gtf [file] Path to gtf file + --save_trimmed [bool] Set to true to Save trimmed FastQ files + --trim_ecop [bool] Set to false to not trim the EcoP site + --trim_linker [bool] Set to false to not trim the linker + --trim_5g [bool] Set to false to not trim the additonal G at the 5' end + --trim_artifacts [bool] Set to false to not trim artifacts + --artifacts_5end [file] Path to 5 end artifact file, if not given the pipeline will use a default file with all possible artifacts + --artifacts_3end [file] Path to 3 end artifact file, if not given the pipeline will use a default file with all possible artifacts + + References If not specified in the configuration file or you wish to overwrite any of the references + --fasta [file] Path to fasta reference + --genome [str] Name of iGenomes reference + --gtf [file] Path to gtf file Ribosomal RNA removal: - --remove_ribo_rna Removes ribosomal RNA using SortMeRNA - --save_non_ribo_rna_reads Save FastQ file intermediates after removing rRNA - --rRNA_database_manifest Path to file that contains file paths for rRNA databases, optional + --remove_ribo_rna [bool] Removes ribosomal RNA using SortMeRNA + --save_non_ribo_reads [bool] Save FastQ file intermediates after removing rRNA + --ribo_database_manifest [string] Path to file that contains file paths for rRNA databases, optional Alignment: - --aligner [str] Specifies the aligner to use (available are: 'star', 'bowtie1') - --star_index [file] Path to STAR index, set to false if igenomes should be used - --bowtie_index [file] Path to bowtie index, set to false if igenomes should be used + --aligner [str] Specifies the aligner to use (available are: 'star', 'bowtie1') + --star_index [file] Path to STAR index, set to false if igenomes should be used + --bowtie_index [file] Path to bowtie index, set to false if igenomes should be used Clustering: - --min_cluster [int] Minimum amount of reads to build a cluster with paraclu - --tpm_cluster_threshold [int] Threshold for expression count of ctss considered in paraclu clustering + --min_cluster [int] Minimum amount of reads to build a cluster with paraclu + --tpm_cluster_threshold [int] Threshold for expression count of ctss considered in paraclu clustering Output: - --bigwig [bool] Set this option to get besides ctss files in bed-format also in the bigwig-format + --bigwig [bool] Set this option to get besides ctss files in bed-format also in the bigwig-format Skipping options: - --skip_initial_fastqc [bool] Skip FastQC run on input reads - --skip_trimming [bool] Skip all trimming steps - --skip_trimming_fastqc [bool] Skip FastQC run on trimmed reads - --skip_alignment [bool] Skip alignment step - --skip_samtools_stats [bool] Skip samtools stats QC step of aligned reads - --skip_ctss_generation [bool] Skip steps generating CTSS files including clustering, bed/bigwig and count table output generation - --skip_ctss_qc [bool] Skip running RSeQC's read distribution QC step on the clustered CTSS + --skip_initial_fastqc [bool] Skip FastQC run on input reads + --skip_trimming [bool] Skip all trimming steps + --skip_trimming_fastqc [bool] Skip FastQC run on trimmed reads + --skip_alignment [bool] Skip alignment step + --skip_samtools_stats [bool] Skip samtools stats QC step of aligned reads + --skip_ctss_generation [bool] Skip steps generating CTSS files including clustering, bed/bigwig and count table output generation + --skip_ctss_qc [bool] Skip running RSeQC's read distribution QC step on the clustered CTSS Other options: - --outdir [file] The output directory where the results will be saved - --publish_dir_mode [str] Mode for publishing results in the output directory. Available: symlink, rellink, link, copy, copyNoFollow, move (Default: copy) - --email [email] Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits - --email_on_fail [email] Same as --email, except only send mail if the workflow is not successful - --max_multiqc_email_size [str] Threshold size for MultiQC report to be attached in notification email. If file generated by pipeline exceeds the threshold, it will not be attached (Default: 25MB) - -name [str] Name for the pipeline run. If not specified, Nextflow will automatically generate a random mnemonic + --outdir [file] The output directory where the results will be saved + --publish_dir_mode [str] Mode for publishing results in the output directory. Available: symlink, rellink, link, copy, copyNoFollow, move (Default: copy) + --email [email] Set this parameter to your e-mail address to get a summary e-mail with details of the run sent to you when the workflow exits + --email_on_fail [email] Same as --email, except only send mail if the workflow is not successful + --max_multiqc_email_size [str] Threshold size for MultiQC report to be attached in notification email. If file generated by pipeline exceeds the threshold, it will not be attached (Default: 25MB) + -name [str] Name for the pipeline run. If not specified, Nextflow will automatically generate a random mnemonic AWSBatch options: - --awsqueue [str] The AWSBatch JobQueue that needs to be set when running on AWSBatch - --awsregion [str] The AWS Region for your AWS Batch job to run on - --awscli [str] Path to the AWS CLI tool + --awsqueue [str] The AWSBatch JobQueue that needs to be set when running on AWSBatch + --awsregion [str] The AWS Region for your AWS Batch job to run on + --awscli [str] Path to the AWS CLI tool """.stripIndent() } @@ -104,10 +104,10 @@ params.gtf = params.genome ? params.genomes[ params.genome ].gtf ?: false : fals // Get rRNA databases // Default is set to bundled DB list in `assets/rrna-db-defaults.txt` -rRNA_database = file(params.rRNA_database_manifest) -if (rRNA_database.isEmpty()) {exit 1, "File ${rRNA_database.getName()} is empty!"} +ribo_database = file(params.ribo_database_manifest) +if (ribo_database.isEmpty()) {exit 1, "File ${ribo_database.getName()} is empty!"} Channel - .from( rRNA_database.readLines() ) + .from( ribo_database.readLines() ) .map { row -> file(row) } .set { fasta_sortmerna } @@ -566,11 +566,11 @@ if (params.trim_5g && !params.skip_trimming){ script: """ cutadapt -g ^G \\ - -e 0 --match-read-wildcards \\ - --cores=$task.cpus \\ - -o "${name}".g_trimmed.fastq.gz \\ - $reads \\ - > "${name}".g_trimming.output.txt + -e 0 --match-read-wildcards \\ + --cores=$task.cpus \\ + -o "${name}".g_trimmed.fastq.gz \\ + $reads \\ + > "${name}".g_trimming.output.txt """ } } @@ -626,7 +626,7 @@ if (params.remove_ribo_rna) { publishDir "${params.outdir}/SortMeRNA", mode: params.publish_dir_mode, saveAs: {filename -> if (filename.indexOf("_rRNA_report.txt") > 0) "logs/$filename" - else if (params.save_non_ribo_rna_reads) "reads/$filename" + else if (params.save_non_ribo_reads) "reads/$filename" else null } diff --git a/nextflow_schema.json b/nextflow_schema.json index 326658c..cb98a3c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -188,11 +188,11 @@ "type": "boolean", "fa_icon": "far fa-trash-alt" }, - "save_non_ribo_rna_reads": { + "save_non_ribo_reads": { "type": "boolean", "fa_icon": "far fa-save" }, - "rRNA_database_manifest": { + "ribo_database_manifest": { "type": "string", "default": "$baseDir/assets/rrna-db-defaults.txt", "fa_icon": "fas fa-database" @@ -290,7 +290,7 @@ "link", "copy", "copyNoFollow", - "mov" + "move" ] }, "name": { From 5108ba453848893cc56f6cbaf41755bf2acdefd4 Mon Sep 17 00:00:00 2001 From: matthiasho Date: Mon, 12 Oct 2020 15:15:13 +0200 Subject: [PATCH 101/107] fix count matrix headers, fix smaller typos, change process config (uppmax didn't like the older ones) --- conf/base.config | 15 ++++++++++----- conf/igenomes.config | 1 + main.nf | 13 +++++++------ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/conf/base.config b/conf/base.config index 43e7881..604f112 100644 --- a/conf/base.config +++ b/conf/base.config @@ -29,13 +29,18 @@ process { memory = { check_max( 42.GB * task.attempt, 'memory' ) } time = { check_max( 8.h * task.attempt, 'time' ) } } - withLabel:process_high { - cpus = { check_max( 12 * task.attempt, 'cpus' ) } - memory = { check_max( 84.GB * task.attempt, 'memory' ) } - time = { check_max( 10.h * task.attempt, 'time' ) } + withLabel:process_high { + cpus = { check_max (10 * task.attempt, 'cpus')} + memory = { check_max( 70.GB * task.attempt, 'memory' ) } + time = { check_max( 8.h * task.attempt, 'time' ) } } withName: 'get_software_versions' { memory = { check_max( 2.GB * task.attempt, 'memory' ) } cache = false - } + } + withName: sortmerna { + cpus = { check_max( 16 * task.attempt, 'cpus' ) } + time = { check_max( 24.h * task.attempt, 'time' ) } + maxRetries = 2 + } } diff --git a/conf/igenomes.config b/conf/igenomes.config index caeafce..8f822e8 100644 --- a/conf/igenomes.config +++ b/conf/igenomes.config @@ -95,6 +95,7 @@ params { fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/genome.fa" bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" + bowtie1 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BowtieIndex/" star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" diff --git a/main.nf b/main.nf index 962e929..f2ad11e 100644 --- a/main.nf +++ b/main.nf @@ -96,9 +96,8 @@ if (params.genomes && params.genome && !params.genomes.containsKey(params.genome } params.star_index = params.genome ? params.genomes[ params.genome ].star ?: false : false -params.bowtie_index = params.genome ? params.genomes[ params.genome ].bowtie ?: false : false +params.bowtie_index = params.genome ? params.genomes[ params.genome ].bowtie1 ?: false : false params.fasta = params.genome ? params.genomes[ params.genome ].fasta ?: false : false -if (params.fasta) { ch_fasta = file(params.fasta, checkIfExists: true) } params.gtf = params.genome ? params.genomes[ params.genome ].gtf ?: false : false // Get rRNA databases @@ -124,7 +123,7 @@ if( params.star_index && params.aligner == 'star' ){ else if( params.bowtie_index && params.aligner == 'bowtie1' ){ bowtie_index = Channel .fromPath(params.bowtie_index, checkIfExists: true) - .ifEmpty { exit 1, "STAR index not found: ${params.bowtie_index}" } + .ifEmpty { exit 1, "bowtie index not found: ${params.bowtie_index}" } } else if ( params.fasta ){ Channel @@ -421,7 +420,7 @@ if(!params.skip_initial_fastqc){ */ if(params.aligner == 'star' && !params.star_index && params.fasta && !params.skip_alignment){ - process makeSTARindex { + process make_STAR_index { label 'process_high' tag "${fasta.baseName}" publishDir path: { params.save_reference ? "${params.outdir}/reference_genome" : params.outdir }, @@ -450,7 +449,8 @@ if(params.aligner == 'star' && !params.star_index && params.fasta && !params.ski } if(params.aligner == 'bowtie1' && !params.bowtie_index && params.fasta && !params.skip_alignment){ - process makeBowtieindex { + process make_bowtie_index { + label 'process_high' tag "${fasta.baseName}" publishDir path: { params.save_reference ? "${params.outdir}/reference_genome" : params.outdir }, saveAs: { params.save_reference ? it : null }, mode: params.publish_dir_mode @@ -873,7 +873,7 @@ if(!params.skip_ctss_generation){ */ process generate_counts { tag "$name" - + input: set val(name), file(ctss) from ctss_samples file clusters from ctss_clusters.collect() @@ -908,6 +908,7 @@ if(!params.skip_ctss_generation){ shell: ''' + echo 'coordinates' > coordinates awk '{ print $4}' !{clusters} > coordinates paste -d "\t" coordinates !{counts} >> count_table.tsv ''' From bbd9e59a50a9e5b0a4022d386114a3a1225f4aca Mon Sep 17 00:00:00 2001 From: matthiasho Date: Mon, 12 Oct 2020 15:15:13 +0200 Subject: [PATCH 102/107] fix count matrix headers, fix smaller typos, change process config (uppmax didn't like the older ones) only run trimming fastqc if trimming steps before where done. --- conf/base.config | 15 ++++++++++----- conf/igenomes.config | 1 + main.nf | 17 +++++++++-------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/conf/base.config b/conf/base.config index 43e7881..604f112 100644 --- a/conf/base.config +++ b/conf/base.config @@ -29,13 +29,18 @@ process { memory = { check_max( 42.GB * task.attempt, 'memory' ) } time = { check_max( 8.h * task.attempt, 'time' ) } } - withLabel:process_high { - cpus = { check_max( 12 * task.attempt, 'cpus' ) } - memory = { check_max( 84.GB * task.attempt, 'memory' ) } - time = { check_max( 10.h * task.attempt, 'time' ) } + withLabel:process_high { + cpus = { check_max (10 * task.attempt, 'cpus')} + memory = { check_max( 70.GB * task.attempt, 'memory' ) } + time = { check_max( 8.h * task.attempt, 'time' ) } } withName: 'get_software_versions' { memory = { check_max( 2.GB * task.attempt, 'memory' ) } cache = false - } + } + withName: sortmerna { + cpus = { check_max( 16 * task.attempt, 'cpus' ) } + time = { check_max( 24.h * task.attempt, 'time' ) } + maxRetries = 2 + } } diff --git a/conf/igenomes.config b/conf/igenomes.config index caeafce..8f822e8 100644 --- a/conf/igenomes.config +++ b/conf/igenomes.config @@ -95,6 +95,7 @@ params { fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/genome.fa" bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" + bowtie1 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BowtieIndex/" star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" diff --git a/main.nf b/main.nf index 962e929..c0c82df 100644 --- a/main.nf +++ b/main.nf @@ -96,9 +96,8 @@ if (params.genomes && params.genome && !params.genomes.containsKey(params.genome } params.star_index = params.genome ? params.genomes[ params.genome ].star ?: false : false -params.bowtie_index = params.genome ? params.genomes[ params.genome ].bowtie ?: false : false +params.bowtie_index = params.genome ? params.genomes[ params.genome ].bowtie1 ?: false : false params.fasta = params.genome ? params.genomes[ params.genome ].fasta ?: false : false -if (params.fasta) { ch_fasta = file(params.fasta, checkIfExists: true) } params.gtf = params.genome ? params.genomes[ params.genome ].gtf ?: false : false // Get rRNA databases @@ -124,7 +123,7 @@ if( params.star_index && params.aligner == 'star' ){ else if( params.bowtie_index && params.aligner == 'bowtie1' ){ bowtie_index = Channel .fromPath(params.bowtie_index, checkIfExists: true) - .ifEmpty { exit 1, "STAR index not found: ${params.bowtie_index}" } + .ifEmpty { exit 1, "bowtie index not found: ${params.bowtie_index}" } } else if ( params.fasta ){ Channel @@ -421,7 +420,7 @@ if(!params.skip_initial_fastqc){ */ if(params.aligner == 'star' && !params.star_index && params.fasta && !params.skip_alignment){ - process makeSTARindex { + process make_STAR_index { label 'process_high' tag "${fasta.baseName}" publishDir path: { params.save_reference ? "${params.outdir}/reference_genome" : params.outdir }, @@ -450,7 +449,8 @@ if(params.aligner == 'star' && !params.star_index && params.fasta && !params.ski } if(params.aligner == 'bowtie1' && !params.bowtie_index && params.fasta && !params.skip_alignment){ - process makeBowtieindex { + process make_bowtie_index { + label 'process_high' tag "${fasta.baseName}" publishDir path: { params.save_reference ? "${params.outdir}/reference_genome" : params.outdir }, saveAs: { params.save_reference ? it : null }, mode: params.publish_dir_mode @@ -661,7 +661,7 @@ if (params.remove_ribo_rna) { sortmerna_logs = Channel.empty() } // Post trimming QC, only needed if some trimming has been done -if(!params.skip_trimming_fastqc){ +if(!params.skip_trimming_fastqc || (!params.skip_trimming || params.remove_ribo_rna)){ process trimmed_fastqc { tag "$name" publishDir "${params.outdir}/trimmed/fastqc", mode: params.publish_dir_mode, @@ -873,7 +873,7 @@ if(!params.skip_ctss_generation){ */ process generate_counts { tag "$name" - + input: set val(name), file(ctss) from ctss_samples file clusters from ctss_clusters.collect() @@ -908,7 +908,8 @@ if(!params.skip_ctss_generation){ shell: ''' - awk '{ print $4}' !{clusters} > coordinates + echo 'coordinates' > coordinates + awk '{ print $4}' !{clusters} >> coordinates paste -d "\t" coordinates !{counts} >> count_table.tsv ''' } From 2685aaad4490d50b17a82db0778283d6a78dfc5b Mon Sep 17 00:00:00 2001 From: matthiasho Date: Wed, 14 Oct 2020 11:06:20 +0200 Subject: [PATCH 103/107] manually add @jfy133 review changes --- README.md | 2 +- docs/output.md | 35 +++++++++++++++++++++-------------- main.nf | 14 +++++++------- nextflow_schema.json | 20 ++++++++++++-------- 4 files changed, 41 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index eb74aa8..b03fdf1 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ **nf-core/cageseq** is a bioinformatics analysis pipeline used for CAGE-seq sequencing data. -The pipeline takes raw demultiplexed fastq-files as inputs and includes steps for linker and artefact trimming +The pipeline takes raw demultiplexed fastq-files as input and includes steps for linker and artefact trimming ([cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html)), rRNA removal ([SortMeRNA](https://github.com/biocore/sortmerna), alignment to a reference genome ([STAR](https://github.com/alexdobin/STAR) or [bowtie1](http://bowtie-bio.sourceforge.net/index.shtml)) and CAGE tag counting and clustering ([paraclu](http://cbrc3.cbrc.jp/~martin/paraclu/)). Additionally, several quality control steps diff --git a/docs/output.md b/docs/output.md index 932a6f5..2e412e1 100644 --- a/docs/output.md +++ b/docs/output.md @@ -17,11 +17,12 @@ For further reading and documentation see the [FastQC help pages](http://www.bio This step can be skipped via `--skip_initial_fastqc`. - > **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. To see how your reads look after trimming, look at the FastQC reports in the `trim_galore` directory. + > **NB:** The FastQC plots displayed in the MultiQC report shows _untrimmed_ as reads. They may contain adapter sequence and potentially regions with low quality. In parallel it also shows the FastQC results for the trimmed reads (marked with the suffix `.g`) To see how your reads look after trimming, look at the FastQC reports in the `trimmed/` directory. -* `fastqc/` - * `*_fastqc.html`: FastQC report containing quality metrics for your untrimmed raw fastq files. -* `fastqc/zips/` +**Output directory : `results/fastqc`** + +* `*_fastqc.html`: FastQC report containing quality metrics for your untrimmed raw fastq files. +* `zips/` * `*_fastqc.zip`: Zip archive containing the FastQC report, tab-delimited data file and plot images. ## 2. Trimming @@ -34,24 +35,24 @@ By default this pipeline trims the cut enzyme binding site at the 5'-end and linkers at the 3'-end (can be disabled by setting `--trim_ecop` or `--trim_linkers to false`). Furthermore, to combat the leading-G-bias of CAGE-seq, G's at the 5'-end are removed. Additional artifacts generated in the sequencing process, can be removed via the `--trim_artifacts` parameter. -All the following trimming process are skipped if `--skip_trimming` is set to true and the output below is only available if '--save_trimmed' is set to true. +All the following trimming process are skipped if `--skip_trimming` is supplied and the fastq files below are only available if '--save_trimmed' is supplied. **Output directory: `results/trimmed`** * `adapter_trimmed/sample.adapter_trimmed.fastq.gz` * FastQ file after removal of linkers and EcoP15 site. * `adapter_trimmed/logs/` - * Trimming report (describes which parameters that were used) + * Trimming report (describes which parameters were used) * if `--trim_5g`: * `g_trimmed/sample.g_trimmed.fastq.gz` * 5' G-corrected FastQ file * `g_trimmed/logs/` - * Trimming report (describes which parameters that were used) + * Trimming report (describes which parameters were used) * if `--trim_artifacts`: * `artifacts_trimmed/sample.artifact_trimmed.fastq.gz` * FastQ file after artifact removal * `artifacts_trimmed/logs/` - * Trimming report (describes which parameters that were used) + * Trimming report (describes which parameters were used) ## 3. Ribomosal RNA removal @@ -61,7 +62,13 @@ The MultiQC report shows the overall percentage of rRNA in the sample in the gen ![SortMeRNA](images/sortmerna-detailed_plot.png) -## 3. Alignment +**Output directory : `results/SortMeRNA/`** + + * `logs/` + * ribosomal RNA mapping reports (describes which parameters were used) + + +## 4. Alignment The reads are aligned either with STAR or with bowtie, set via `--aligner`. @@ -103,7 +110,7 @@ good samples should have most reads as _aligned_ and few _Not aligned_ reads. * `logs/Sample.out` * The bowtie alignment report, contains mapping results summary -## 4. CAGE tag grouping +## 5. CAGE tag grouping The custom script `bin/make_ctss.sh` generates a bed file (and a bigWig file with `--bigwig`) for each sample with the summed up 1bp unclustered cage tags. @@ -115,7 +122,7 @@ The custom script `bin/make_ctss.sh` generates a bed file (and a bigWig file wit * `Sample.ctss.bw` * A bigWig file with the mapped cage tags -## 5. CTSS clustering +## 6. CTSS clustering ### paraclu @@ -130,9 +137,9 @@ attached to sequences. It is applied on the pool of all ctss bed files to cluste * `ctss_all_clustered_simplified.bed` * A BED6 file with the clustered CTSSs and their pooled counts -## 6. Count table generation +## 7. Count table generation -The cage tags are intersected with the clusteres identified by +The cage tags are intersected with the clusters identified by paraclu and summarized in a count table. **Output directory: `results/ctss/`** @@ -140,7 +147,7 @@ The cage tags are intersected with the clusteres identified by * `count_table.tsv`: * Each column of the count table stands for one sample and each row for one tag cluster. The first row of this table is the header with sample names and the first column contains the tag cluster coordinates. -## 7. QC of results +## 8. QC of results ### RSeQC diff --git a/main.nf b/main.nf index c0c82df..cc22e29 100644 --- a/main.nf +++ b/main.nf @@ -37,7 +37,7 @@ def helpMessage() { References If not specified in the configuration file or you wish to overwrite any of the references --fasta [file] Path to fasta reference --genome [str] Name of iGenomes reference - --gtf [file] Path to gtf file + --gtf [file] Path to gtf file, used to generate the STAR index, for STAR alignment and for the clustering QC Ribosomal RNA removal: --remove_ribo_rna [bool] Removes ribosomal RNA using SortMeRNA @@ -50,11 +50,11 @@ def helpMessage() { --bowtie_index [file] Path to bowtie index, set to false if igenomes should be used Clustering: - --min_cluster [int] Minimum amount of reads to build a cluster with paraclu - --tpm_cluster_threshold [int] Threshold for expression count of ctss considered in paraclu clustering + --min_cluster [int] Minimum amount of reads to build a cluster with paraclu. Default ${params.min_cluster} + --tpm_cluster_threshold [int] --tpm_cluster_threshold [int] Threshold for expression count of ctss considered in paraclu clustering. Default: ${params.tpm_cluster_threshold} Output: - --bigwig [bool] Set this option to get besides ctss files in bed-format also in the bigwig-format + --bigwig [bool] Set this option to get ctss files in bigwig-format, in addition to the default in bed-format Skipping options: --skip_initial_fastqc [bool] Skip FastQC run on input reads @@ -149,9 +149,9 @@ if( params.gtf ){ Channel .fromPath(params.gtf, checkIfExists: true) .ifEmpty { exit 1, "GTF annotation file not found: ${params.gtf}" } - .into { gtf_makeSTARindex; gtf_star; gtf_rseqc} + .into { gtf_make_STAR_index; gtf_star; gtf_rseqc} } else { - exit 1, "No GTF annotation specified!" + exit 1, "No GTF annotation specified! Needed for STAR and clustering QC." } if( params.artifacts_5end ){ @@ -428,7 +428,7 @@ if(params.aligner == 'star' && !params.star_index && params.fasta && !params.ski input: file fasta from fasta_star_index - file gtf from gtf_makeSTARindex.collect() + file gtf from gtf_make_STAR_index.collect() output: file "star" into star_index diff --git a/nextflow_schema.json b/nextflow_schema.json index cb98a3c..b492067 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -82,7 +82,7 @@ "type": "string", "fa_icon": "fas fa-font", "description": "Path to FASTA genome file.", - "help_text": "If you have no genome reference available, the pipeline can build one using a FASTA file. This requires additional time and resources, so it's better to use a pre-build index if possible." + "help_text": "This parameter is mandatory if `--genome` is not specified. If you don't have a bowtie1 or STAR index available, they will be generated for you. Combine with `--save_reference` to save indices for future runs." }, "igenomes_base": { "type": "string", @@ -139,7 +139,7 @@ "trim_linker": { "type": "boolean", "fa_icon": "fas fa-cut", - "description": "Select to cut the linker at the 3' end?" + "description": "Select to cut the linker at the 3' end" }, "trim_5g": { "type": "boolean", @@ -186,16 +186,20 @@ "properties": { "remove_ribo_rna": { "type": "boolean", - "fa_icon": "far fa-trash-alt" + "fa_icon": "far fa-trash-alt", + "description": "Select to remove ribosoamal reads with SortMeRNA" }, "save_non_ribo_reads": { "type": "boolean", - "fa_icon": "far fa-save" + "fa_icon": "far fa-save", + "description": "Select to save the ribosomal-free reads" }, "ribo_database_manifest": { "type": "string", "default": "$baseDir/assets/rrna-db-defaults.txt", - "fa_icon": "fas fa-database" + "fa_icon": "fas fa-database", + "description": "Path to SortMeRNA database file", + "help_text": "The SortMeRNA database file should be a .txt file with a URL/path to a ribisomal fasta file. " } } }, @@ -209,13 +213,13 @@ "min_cluster": { "type": "integer", "fa_icon": "fas fa-sort-amount-down", - "default": "30", - "description": "minimum cluster size" + "default": 30, + "description": "Minimum cluster size" }, "tpm_cluster_threshold": { "type": "number", "fa_icon": "fas fa-chart-bar", - "description": "minimum tags per million a cluster has to have", + "description": "Minimum tags per million a cluster has to have", "default": 0.2 } } From 146b777fb41c4e2271d889570fc4e01fb658ba54 Mon Sep 17 00:00:00 2001 From: matthiasho Date: Wed, 14 Oct 2020 11:13:35 +0200 Subject: [PATCH 104/107] fix linting errors --- docs/output.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/output.md b/docs/output.md index 2e412e1..59c6ad9 100644 --- a/docs/output.md +++ b/docs/output.md @@ -64,9 +64,8 @@ The MultiQC report shows the overall percentage of rRNA in the sample in the gen **Output directory : `results/SortMeRNA/`** - * `logs/` - * ribosomal RNA mapping reports (describes which parameters were used) - +* `logs/` + * ribosomal RNA mapping reports (describes which parameters were used) ## 4. Alignment From 685d53d6459b39119f729e9f23cff69ddd4b8f63 Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 16 Oct 2020 09:39:47 +0200 Subject: [PATCH 105/107] update changelog for release --- CHANGELOG.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6838aec..73d7cd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v1.0.0 - [2020-08-14] +## v1.0.0 - [2020-10-16] Initial release of nf-core/cageseq, created with the [nf-core](https://nf-co.re/) template. + +### Pipeline summary + +1. Input read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) +2. Adapter + EcoP15 + 5'G trimming ([`cutadapt`](https://github.com/OpenGene/fastp)) +3. (optional) rRNA filtering ([`SortMeRNA`](https://github.com/biocore/sortmerna)), +4. Trimmed and filtered read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) +5. Read alignment to a reference genome ([`STAR`](https://github.com/alexdobin/STAR) or [`bowtie1`](http://bowtie-bio.sourceforge.net/index.shtml)) +6. CAGE tag counting and clustering ([`paraclu`](http://cbrc3.cbrc.jp/~martin/paraclu/)) +7. CAGE tag clustering QC ([`RSeQC`](http://rseqc.sourceforge.net/)) +8. Present QC and visualisation for raw read, alignment and clustering results ([`MultiQC`](http://multiqc.info/)) From 32b0c9881ffaec17d24e67af13b62800503fe7ec Mon Sep 17 00:00:00 2001 From: mashehu Date: Fri, 16 Oct 2020 10:07:05 +0200 Subject: [PATCH 106/107] add code name --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73d7cd5..1d6749f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v1.0.0 - [2020-10-16] +## v1.0.0 (Gold Lion) - [2020-10-16] Initial release of nf-core/cageseq, created with the [nf-core](https://nf-co.re/) template. From e46d3b74306c1c4ec4975a682e91a6297cc39f71 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Fri, 16 Oct 2020 10:11:51 +0100 Subject: [PATCH 107/107] Update .github/workflows/awstest.yml --- .github/workflows/awstest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index b4db19f..c4af089 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -40,4 +40,4 @@ jobs: --job-name nf-core-cageseq \ --job-queue $AWS_JOB_QUEUE \ --job-definition $AWS_JOB_DEFINITION \ - --container-overrides '{"command": ["nf-core/cageseq", "-r '"${GITHUB_SHA}"' -profile test --outdir s3://'"${AWS_S3_BUCKET}"'/cageseq/results-'"${GITHUB_SHA}"' -w s3://'"${AWS_S3_BUCKET}"'/cageseq/work-'"${GITHUB_SHA}"' -with-tower"], "environment": [{"name": "TOWER_ACCESS_TOKEN", "value": "'"$TOWER_ACCESS_TOKEN"'"}]}'cageseq/work-'"${GITHUB_SHA}"' -with-tower"], "environment": [{"name": "TOWER_ACCESS_TOKEN", "value": "'"$TOWER_ACCESS_TOKEN"'"}]}' + --container-overrides '{"command": ["nf-core/cageseq", "-r '"${GITHUB_SHA}"' -profile test --outdir s3://'"${AWS_S3_BUCKET}"'/cageseq/results-'"${GITHUB_SHA}"' -w s3://'"${AWS_S3_BUCKET}"'/cageseq/work-'"${GITHUB_SHA}"' -with-tower"], "environment": [{"name": "TOWER_ACCESS_TOKEN", "value": "'"$TOWER_ACCESS_TOKEN"'"}]}

x{ofyD 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 literal 0 HcmV?d00001 diff --git a/docs/images/rseqc_read_distribution_plot.png b/docs/images/rseqc_read_distribution_plot.png new file mode 100644 index 0000000000000000000000000000000000000000..6aaf67a0acb4c878bceadfa417d6530c22b66c38 GIT binary patch literal 56481 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�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 X;{IQl$~AgKBz#Esuul0w%EkWzJ($4A literal 0 HcmV?d00001 diff --git a/docs/images/star_alignment_plot.png b/docs/images/star_alignment_plot.png new file mode 100644 index 0000000000000000000000000000000000000000..56fb850cafb3c4359f2510185c87f9506aae753f GIT binary patch literal 102145 zcmeFZ2T+u2w5CjxdM3P8oB`QHcBuLI62$GR3O;jW(0-^-Tk~1`tGm47j zoRdh-k{ZdgU!3p$_k7>EHB)zHs^(7pr@HEZP51l0PuP3ywbp)KD#%Ha644N$P$*Jq zDRD&<>IfEvBDipz5dMYxM-)B^bpa(Uendwu`xS@Q8F|Hv65YNKGACufdIJi5)nMyz3O^$G25r{;Npk>eZh)IxDfo~H`M1l zo=5-j3l}Ng*?;`}h3AO+KYl*hc~bu$pTB)y?7zYX*!q6`y6)iQq~zp;-dJB(xJvm7 zcLjNd+vg7-IP3^M9_CMSWwrVf6o3^mt*x2wXK3JV> z9I9}0b4xLA8y#h^iOSI~6%7ao;1LwGz-+ZEsHxRi9^^l6Wn-^1@$7DI|CGJltLLFp z(?dX=|7M;F?(z#EGWsVUn47a^YZV8U&l2|*S@eHyt~U5eRJ#^w$`Ri93&%R$Twl+n zv9}t0=W>O(Ro{y98MtyWrv?fz`xdAYFAyf+fQu*7YrXbQ*2%NwD4 z7N5;e!cn^#?(+iQg&G(u9rx-u)ojh=vQInP^SQJA`Hv@7o~9KQg}w6kH?8#{Ekk?G z&dwH?cBWuu`%hoJb?eqo!LMJxQf!VDkGgkOKB%-A_esZGCCGwX9w;z9Z8=mDteUHv zJ#ehZ$k;eiv)ADF;OM^bU=d>tJ}dq+6e$Ubf{YBYgM&kVnMHYy9^A=E+QaF}nVU0H z(LZg~l2yHSXfGRhphYb!rAK%eN3LM8+U| zzKA27L+3`JV1@U|rc-qK>{A=W$gCf3t+Jk6z1Crr<~iE>s}y*ul9I=Yo05_)sVLa} z{`Ii7k^8hhMS5-i(9qD)rC=fB$B$JC74{Dt=6fPEui&#?m$COOeBaB7j0ichn`aaQ zgDj3C7pSq(SH#>K|cJ8mZ=FgCQdrta>###c%# z4VBhfs%dJ{gocM_eiq_3Javu~t6TB(;YYy(^CfGCA-~GP@=`TNTbhN1#eQQ>g~(g< zVX@7lM=!LjbaY~Nhuhjt(uuf73vbUbY33Omz0AzqIn^9B3*XBlB9g1wGhP=oyVfca zUZ<*+Z%mq;oZQ}-Do@%iv%0fft)!xIW^uGSj?bd+HZ0)+t6~0z`uceD-kft7v6SJB zw_(Lj%evjx!8-Er46ub8yY@ed>s7n&ETS_qG7>5(1n)^p$9HF{DJd$RLiU}aqTjl7kHy3YLc_uoF&O@AjeH*n12fhhJG6_#<>AQwCLkd2DUx1RKZ=is>_f|u ziio%G-oazCSOm3=jXf;0pFL${WK=(xZ!>7_Po%=cMbKRM< z<3S=Rum`VQz51c5N?57!2+DKv#GiQ-e*W(L`>P9gYnM=s%bS^mDw|ub%4%wif~9#o+#KN_ND>jAt52+5KN158<$Y?+Z*#ks~v*%?Eg4z4Mbj`L>hyN>lG+FlBQ-2b-fF=mKpDyq=xS zWn|#_&O2U>YDdjCgtBJDI%6zHtK7;4GtcPL2{<j@n1|<8T zSkY*;LLsdpi}=A}>rRMk$Ue%@<+I?X(P#0BotStukY{*oaimgfZAx$1hQr7+*}}Xh zD;`1sEWkGHC0GP1)4d}5E9BjYjwenqU@T|P(b1_aDj6GJ5pv&sUshf|+Y%#?L4Ruu zGYF$FHD!#15LjnVI{WvI$NSBP>(=BO){&JtF47bh6tp4R7lt<^B0{>pzCJRDKweHR zWA6R?_firP66S1P^jbc;d<`vic~znz)kqvx?#I8^|PCNfA0qG(@=U|d~YoeFQc({k*TZS7HY_`30LFBHl2b4XtF z)r8K}{?=XKfz{PEM97#hT<&DoiR>a}S#Dn5iJ8I zt4{@ocrctUGmDFpDKgU1FSRLQryWNU+HG;De$>|-^+(jF(|>0Q=Bu?AcF=?ak@~x|I|~^Cp@~ zT60*?VYb>InxoLZI@P1gsSs|p$grnQpLSqq9IW;bL1&Nj-Owqy7IYA_zDDs zfkJardwXSG%j?w2vI5-PiIGb%c@K^d!` z**AIZ*wbp~HRHb7P@$#*d^V%y_hn`Lkx@~d7SC?iD7<0J(Dgs3FP)`ZU4WmIDj%mg z;M3G}-|Cj8;UiOxYIh-YT+fDtbJlBJ$xy@aEmz^;wUqeyXHmF``ga+V@O$$%{Vm%s zJ$X>n=sO?6`4oV??bZ7moWsS@dmFhPynElHb?|y58Qi|GGY=)+X~1iSaAIO%ao-7( zFN7`l_U2{SJ7#&?!IaGs>R_CHOJQN*!*J`zo(>25ZdNpvHja#zUhOE>q1&tCbK_P# zH66tAmm5%-A3xq$SO-97^!;JVY~{_{%9RNe`V<=F?%mzp=_yg~-(w5hCyB2tjaFNm z2!}U*ZBFf8t6#`t+-?(Sp1XB=NsyC+qbG(L!rCScR3jgbA(NucCn%V8i{rkiC_aK# zyFM-)hdT@_b(jyc>cr5-_jvZced1NJv*+H;q|2(7lQinS)4cB9X9;nqyEXwLQ!xkH zdPKQgK#P1!0stHL<#3{VLoD>z` z#@AI{ay+7bjGSJ(EkIrLv+teU4RH){d=Ir$u;}Zr9~Rml6_S#Z&*#*(pk(^(#vufw z3*wGrO+MAB%Ty4mpJM9eoQ#sFtvq_;)MT0a)+CkK8jH*8sfmfSl)O{=kSEw?qWcR> zmHH+}OYN8!E^I@tSfA@=72}2AGZgkebTDnc^%?!Cx9jY9n- zIJ~)lRiBCWL`k1%9g{y;aUTL3ZLC`6rgu-&_t!_%#RqcV96+U&veP3HOhiOfviQBR zky~)N(q&V5CtghrR#toagU*L(JtaDgTs4YIQSEh{wHjHd`CN~^`RBzB7eDJ%Bfx7k z?xxM>4h$I`{}=Y@Ut_ft(-AQ-D&F^ngoH9?vtSZNbKB8OnvhskIEVb!&mvRn zGaY!KKzgBuX7kAhl#`i@P>ttCe!K6<%grs8shX`gY+qDV6gk3|IX5>~;^48nQkN1Q zfBq)_#fx{=zV$4jWJ(uLoH$VcFdzOPp|teY_Oi!;j9RX4a*)WrI(NlKL)uF+EH#Xb z+q-M6rL$0y7k;=ds$4lWJ*`s5Hsp`r^l@h!2#5HA5#T%`au$)XQuir0mX(!FPw6GD z%_dau?Ci|I3J3}5aP#mPKob5rcr=tV+|Qdz7s7zWp9(eUPCMMXJk+oq6%TPcdyy9< zO-<9&9W+R>1@zg@n@ch24v?119c2s20rw2?7~{i4#Chy%6gI(B&XK7?e!7PgjR*!U zu}PeDQ?TWa87eyfR1u}?^U+BQf+13RrsNC2;~+@F>Sl6xh+)v|M&Qd$l=-7a;v1q~ zup6Op>sW}G0lER=pp%P4w~TolQno>&CNFnQ1W+DwM-5_BtRX0%B4@*Qox6*uD?IHazN^g{MT)u-9xOXLVP!s>Zapf^aP4 z_eZ5@@74BnUh|%`6bcG`AVAXSFL#+kdGo;1OSkp?Q*x}IUyfdNjs~;oNsrV{X<9yu zAMVu{>$uZMy4I1A`hDHx0MLP)TT~qW4t}4!-k@;t4~`uno7jrsGOY#UVh6S0C&P04FpT zYn`c<8+PoeTGa!^T;^8Wo|Zjg3EBC3fGAlp5M-oL-ytkvGOc zkmx{BH~;(Y4(i}1;UqNVq%ev*H~D_Qp$l=i?@6VOe8N4kAkTw3ly8L zIkZb|x5f&Mr#vj?;^KPXq+wh4IKZZx}JT zi^+mTG*Ir8J7>dgG+5!xy$3Zzm$pwDM*7>gZ_3pNQe#0B3AuW(X^F~r0pM*g{28=fD6B&ZZxB6Y}|`#5%UjYR=^SefNQnMlyXDSb?%ZNS=)BY?bEam8VzHXtcqe zeDuvbN=iy$MHDDh7{ei5+5Y9r5dcCDoSknWB#y1Et;y!nu(GD+J^0tI?rx*GY!8%U zRCKiR(Ni_>zof^lvF%^|sb*n#fyrPdf5kxTv7{~8mUTUz3yOKELwRg#w{S5Z-E2g(K^Gd_S5?r($YL!_i zC)a5X0T_>kB_%<0p3U6emqQV4?THmd&ubWt(g5OYm#}RCX z`T{}URIC%p)ASA*>FE>|4#>OM_ehLK-M)`7Oc2r(k(ptVLC9j*ghaUr6G2)9l>`bU z!+@+Ml%F(gD^=20l@L$1fk-iJj^r&P5R+p&=baFO&e&85tKBgquRXu7>dt(IKBgq5dDD{STk#zqoYqKlKbUJ!>saMSRHL z`pF&#eF>#sFM24+c?&t5hs#nO zcT)f5Gg< z*#PkdCGp{Y^K3q;A0N+NeRdHA6|4Gxowvf8U4IDRKmqBtPrA?nVA`5 zZZGYkEZ+4?XLA@JVy^NvwYEwc(dusnx0J4|te9B8vi#d;4r`_te0rPA*Xumlv5n2m z!J;8ZAsM;3sX%#aMT$@oJpggbS&+UIz{i``Y3>S=xK>HHG{UO`y?Y5Et0B@sX?sqy z1wylmnp)?^d@uW=mj(dYi6=KrfZ_E2D4d*^#|1dgsN=)drY9Fs~b>YUbW5?>pSK6SckzJP0B07S#TOklRG1+Qqzq1S(8j>10Aw%!(IEF z;WAe9p4un8|&T)O@V-zvDJ@i9DAZ*XqY&K zfkFos)zB(bV-|zGCii4y#&N9L%SGzPc?~Ys(9qE(<8Y2N^z?xZ+e{~p;7@E|(hCc_ zS8o`Msn-!5Q8zI$S?NfiyL}OaGX*tdlV7a)7!iZMeCEs&Zfa^>$4wO=(P8MA0_Q1TcCWQ(K}`tgBJ9AU z1SMm;wQ4jhDISU!Ry+0qG@|YsP$@%T)h53)>u~^?{OqP`H0;c|+1dF1{(iqs*tKt9 z%l2l<&Ogwq7tLh=1`wH-%*@6oznK?{ku0kN4P(LHG6_A5Wo1{cW;(zb1c12Nl8Iu)VW<# z6O%WstOK7L9G4wO6#X%r+a8ixZZWOI1Q+v9`iAp`oD?P_n@8zl-4Bn`Wn& zpdxu-Y@8yv3>C^`Ycfh^OUew?V03jbDiaoGRNP)n|3zNj&}cbk_;h*|D<>y2R7C0N z=|j^E^RggY_A<4@{<5*jTjF;UjuX@Y+})d)otP+QN6*?D1n>#O>7iRJbm1`FG_u|MB8Q^V1*XpT!|vJCcI8cn!D**7&cHM^in{untxqwQJV5r((dFN%*s zfr54ez6gSa1{qej5|ivquco3h+vAjXp+;0p%l$7=tLH5-Hp$}y@RWLIu1PP}JR`_} zs(rX|7-cb76hJIgfT3n#I0*iB!a&5(g^hx}5(Onx{a7tP=~CyUS#EA_s)EH+6nJM{ zxF>8&m7k@kdVZy6g0NS%^?*=nVcnuF!J=X0+Ss?6kG8^*7Z*EW{z@h_Phf$!m~ied z*1v}r);O5}^iyMJQc8+#khla97FfsgSMGUz%CCE|sPZ^e*$ZT{ZYR(NR|Cpy%abf` zy6=`O*;Ko1=1lSTkC-ztF%3D}gJ{_7oTV+&w`gCgoe?g)(4Q~KOHNBI74LPUO(nKd zwWl`LSFPI2fe?O3tgDgOwr%r^Ys;f&6dV?QC zTxMT2Sm8W8JeTA}`1r2Kd;I!wM+^693FS|!3Rz>a75GI{s49m@FJV{eqY{f?4$+> zt8S-H^CQ9xKsue6t=gKRbuNRz4=mJG56+GIWtfc&<0lWhMG4r_fyLmxsmet5oJzdn^J8M9!1(07TAj8M0S7GJ`cpBjRwh0VSfk$L*+Ik=}-C!RX(6> zKRF0+2a<^D(M8yGVp>^$!LjD`gz6Cy5g9AOnp#?u%OL7N{PHjPW&o;Y~ zw!Ut^l@B$pGkx)(CFUR$#0P|ZTu!FRA7nSRwho`(nN5wGXzgE_vKp<*j%;n2KjzY` z&%lzIn;R~Yn~|Z|Tu1oouGQ{FkJ!3oK#0eY3)|O?gV$%Y?%pNb)G0yvSMsqkScc7I z3O)vy@q1;QVw2?*H=gRKcP4omf8_o3a%l>11Yh z4Q+K|=XX+%Z1ou!7|9-A~2(8LP^q`)={im}tl z;1$?rv!6F=7=Io^$;->9>R+eks{vRRR;?slR*#!8v#{XF-?>H%dxzfr)GU{AHdjlM zE<4N@F-!l5g=WyyfX&`q?EK9S&M_hG{$MmIs_5^y@A#J z2tSZrT{E6N!`mtc*p?oaenvk+h|ogn8?NfD`nfNaSgb;twQ$n-{6Fw95ru6 z&&_gf>*lJ(P9s1(dKxiGR9}$^`oLnHrLL%61Z>$>e)38EJVSkCyH}Mu@yDz-Ble2P z*}`u{d7oQQ^Dx${I2MNCcQ1&s1A~LJV6Vx*OJq8#u36W0-_vNrm4{XF$?ZpiHBgbP z;;@w~pdT{+q#tEtWhJK7mmUkI)K^heZ3u9iFj*d{Je%>$*PBpXvzK<3)T;sIzbN}Q zBBFj#$;jw(uZ--uE9#Z*B;@2u4;}>1C8IPyo!T)LXCJfLZO-z&y6XHsJe;|;F)->Z zM~wl45J_(z*Za=_l8?P3P%_ImX-;4Z=78SR6gmL7*Wi$ccXsD3;Y(FdBOJ9d+(4Y^ zQH&}$yM8G>M-h{fveWz}zp4%$RbMDMFD{;|R~d} zdw#Vd7a$AN_2d;6ZaM0;aJ$jM^K0M6TzpRc6#$e+LX%9VajXcc*SJx>J%g%5*$brUD``)Lo?1*cFp znvxNTVgBKNiD9fu5H{|rU>bXOcPj+RchVUA-Lw_vj@Ae>#&3K-A;6(<=gza;EkzQn z-~RFOz9<{VC&t;5GEE=3Ya-vje^V@L{hA~D51eQKV`YitIw&I71phpr8UjX3NB9<^ zzON&a0fYPRJF&hoajWvQGS%KSSJ;HQ1pWGHc z2F9%tyS9c6v5ers#i=3jLh7!gs`|~1fdi3n09sBs7vg6{M@M5FE-*$$M!ucak&?g7 zQll8iqO7IG$~hW{%FN7UU2qWl+!IRb+pH_ncR}Y|OWvoBzP|Un&VaLbOKk-c!0~bG z!b9ubY*_WX&fm#?=D6P1&>YD#tW#b?lGtW+7p$+2GLCO9$m%XAEUfR$_xKfz4U&aG z+xKk3-{0S1lL~?Y&459X$uWiF*czg)Zs3H}W%z1rAvyl|M6e}LJ<7RB4ZjV2$XU=c z==XSWdIfE_AQC-2JzZM-DNh0lukdQS@?mYx2q?}W@&OjUwhJ~0@Gz!Bb?GwR4bnjA zR??e08JRu$1F&^cPBY7ykQq0B6sR#cM$Ey<32{~G-Me@800ow&yem&U8dY|lX}ehJ zqyq@;yzR~NWJ;9=O@!*IEt2_JNK$@Nq08Cb(_<_23rbWKf(A(fw}GIshl0;)5b_{WbddR$Jq|r3aF#~v;K_94h;)%_b-hwv5$$J;KByO}L5a#q5)?F`;F z!9i~MtuWc@QF-vMX}4;W6R_dP&udQKtvIGGJ{9=vBlBZ7Hz5kQn^Zuqe~PhdnAeq) zBfAwN2aEw2YA0I705iqjJkRj0p7q+bpG7iefPpjiG)ewG1+w7?*#rclh#C6mAG`&S zv~>9EPTev*7c5nwH%X=;2RBu5`dIFoYaAR`iU(z_ilbohB~7&&HuA^|tJxl6fh3arQ=b+cHrmXpkKXGdL69I0?lEawCiy2{@l zRnyJm$Z$aTOiTwg#^!vb;iBANIRZ#%5eia@2=8~ePgt-0qH&QDNMbEDz zCg$u>UjsE90SgsbORRVEa=EQ!ooS_?4Zv46csgsszY(_Ozc%#sf5idJc+Q}RL1%M1)6{x zN7xDy>hzSUrKL(UVhN6njh({3XSy3BRj15Z^Y)ubdzonwMwq71VP3V_?eQ!fEih0Z zVW%ca2AKt_F$I4seML!x(r_xcCyQ8Za%)0va^5-W45=qXVzysS0C%S zZ(T07UeKaX-V*`;HHa{#R$ieSQq`Y^hP0dKBSwBZ2*(9EE)CVox|ZFSwo zQKZOvR1Q+rYQdPhzbbH*nIi_*xK>A>J?VV0vxiiw!XBZJ4KtksUugCI`0-&ESdtjC zhz_UemKY_s$5YfNO?}k?+FXV}ba3$M6_FJ^E_!}uM!~XnX67p5RCZh(kbrB(gS65C z15%1&)wY%j{u}NU!Rd-Yew)jqN@8MO@w9jALAyxD_ zTwSAM1)W8~^!EWwUtk0y2E*rFmwb~aPu{>Ar}EH2kF2Z$VGdzuymT1~0e_!HL#!pE z#w~_Vk>E4L?Ebd7AD!>GhN+C)nK~r!RMxyv&u)8ynQ8{?AEG^p3(`=E%z#$b)!zQ_ zY7!ka^@nfY?gB^E;}(DCI(5?0k`-ok;skJ|G$Z5!_vPi4pmhKtzj*h1Z4IWVUx;3W zKSl&4VgLbX?SXTek${&;Ew>8)8qkGnG>Kp?(~66G6}V|?zR-eCtmLlo=Z2@AYrei1 zHoCj?Mgc_-J`MsIJlX%H5R`1lazwqfwA81Sc~Xn*Vp&q&5N>H$1{|~Cz0RQ-WsejZ z|C@Ot#_M71E4GdkM7bt?tJ1K!<^1c%voV^ltIgQsH$9%F)pg`i;v;6L+Ua*Zs^`A= zJQ*_tjs$##j2VNzfA{#;Y8bbF8P{xYV+0%UP$$O$qNZ0>xj(22@tQQUuy_r|o|&It z{gt(~?*oI{1wNp{XM-Al^SFf*hw_T2`rlpVP_RK+fa&*NCgA_nTL5MCIftnGKxiRw zICJ>=@ANgIAw^xRIYodbM1-H)I)7eB9rZ^Ttua21{ZbR~3|Ln#1+_n~KTI;x{eV4( z&&Kt{P#=UJk}j3Q*C90c^C0_il!E=;HM;+yN_0Sur)p9ApZjtcKpB$%_?e{fdJZO( z6XN3~(ih9PX+m*3-Ur)6*(9006 z`QPNOvoxCPwD?)SpX=Wy`GbJ|-F&fclj5nm-no8(@E?K(GPHbRzyY1z^FgszU7$Wm z@DI@dc?(8eRLtL9%=3)i->P5|)fa1CaULi9@~5i(|7N4DEn)Pe{#U9a1R&V`Rjo5I zX}3O({Ym^k_gMW+(`$%e1*~B^gy#bEV~u%m7Nw+I0q=DC2qj9)U~HRG}+SBqyVTUM%ZnjV>e#G4?N?b z9(~VFP4#sZjvF)j?J5ig>J%g<*S}*?f_{4*C?0VBglMfJ3ii(lq@yETGj>9tq(hm&f8uoHjz$0hTq{8Xa}X*IcZrUZ@ap>uyvjPJ5;MH8UM7D8jT%CLeAf^73WsR zJ}1S3WeOCi%&<%cyTuJm>4#dlC{$-)s(P`yw#LHD>qkt$52^!=h;0d27_b^CbIC&wrS0+0fB{KHoPmC^%xRh4$u4`r5@|o+_yNgUm0bWNQ%KJ` zrMBKXyGWZ7kS*QoP@;u|Z-GHXX2(#xfBJE z)zzTT8#T7&!;wL!Xh^ZpdZPTPU(ur=BRN^(45ePh(+5u5f3&%`Jsv>2Ak()6RN63vv^LtQQdzM< zh`kTA;^N%{Xf}8Y2K~mmds}{K@EAAGhlGcxYWf7D%mJ;;U%a}v%;2%x{&VCNATcrc zE*=2^TAKl{W8`mZ$9`Z6S?0fM&TJSuI)*`A1?G}-WCuxm!J?E*cwwO%*frex`U|=X zBlkT4Oo9ouaeetQARiDTB*6FG0kdI@X18-@cYWk2iuly57mr+ikarpN0Cww7!#5{Jatn3!yhl4NRq(8wD`^U!MN&YfGGuB@yi z9&lH6aVf7Dk_qQvH_?E2g%IU!upJ&C;(;fxpx}L=keR{TP1o7grF@N*RVhXUFwm+q z8r}lEX&v_T_ci23z%FGu2muSkwK>AGP?9FXYWY5E-vO03BB#l1wbJ|)H%R0-A=IgChYk^>JHt}cCIuvHy_7b z;y+IY^;?flYU}j7RG@+?Hg0+o-!E=GL z#ta0?fppB4ah0GclIyM{4YS|g z>%~0r0-%-RTA6*x0sl`=1*fz&HEFjMvF1JN7d@6N zdP>iE1@RL66SQDQd+T@$TGD#s6d#xx1R&OIs1~fkO(&YzA7HaLXbQ({w)pNx>a#cRyG-0>zud2n&P|- z;b)+bwyU?7dGo9S?kU&*gNoLrmw3>m^T!MDUq#*0s`?AwMTAXo=4O1`F|o7^tp;Ca zxJdYZ{GwwyueEBD$C3Plna87kj`Kb2-Gaay1y?_I(Psn8M?dfyDKzCT_U6mhOBzI> zzlY;dm&@yhtLex5bWdIxraVXYMQ5%VBK0@77J4Nl^7ew=g5$LT^jRWAUmvZ0<%K2_ z&oe~c6GnNJ>mhhyt<&RHG|99LQg~tOPnDtFbGLtey+AN%aFMU_;2t!uK<*maR1D}} z1X-wlAJo0o>4m3u;0sZ0emuS5RcVY33hD0cZHxmAJ$=fMK!ORqkD0%?op`rF1plNP zb-ol)KKG3qCCi_I=r7dRGRargo4i#^s1C^?s6;*(8c=WCxWS`mrO#7SW;ac?Nw-6N zWsvEuUrFq9%=|!^1FKUs0$S#2U7A3cEj=k~fTP9+b>6FF(^yy@Ht}=-IUc+AUMNTc zaUJ~=*6evpibWFJtpIxh_KjEi(+~C~)ISTKy+X>?G-6^#O4P_v40_JKD^%5>Hv&!; zUdkOo3=k!k7slUdqW6p;-^991K#Vp0)cD$7JD|$@38ZR5Lc$69i(?p09yB_0DjXwp zm0_@*2#a6{X%G@Cz5HGuQ@4lb!6X0=_mNKy@4OA*6r z8YZ4!alhV41#y`N*j(8#0|`}Isvc+DiQ(xDoR_>xnE+$m0Y@glj2RB*1^qJ98GK#k zeZ2$Yw||p-!`-XHn&a|i?;SyH&#(K!fbvQlf7IYL&nK;G-Itcmn`{n)mIB<@6PV5! z&}f2A$pl@x=HK{JvI#v;smL>se%KFwvB}mj zQBYoK##JyfVs>!Z6>bfZo0rD$v%ssx z|Mb@fvzi%LnLS**r}Z_27@A*Eol^lGpM&lB7HtZ`XKurKUq55b$GmnKWLQYO4sq zIa?hNma3BOBpk|wa09E4HJ`ay5502D(u|r@k=$T#*xn zqd1W*Dc5K748CfjHQc~cVqKEDZsc{o7q_{P=Bav6%69ucbj}u>|7H^Lf4K;zIKN`U z3MBYv;>oA)#a(kbk%4F|{!96IMh&LP3baefvIo8M(qG6j*dHEz(os@MjP!MTr)^}E zd?*0+;W_rx2s*F60H|t5QxDTwJ3`GKQm_D^GNa0{^(gMj8@lK!q_^`i7s!3)(}@}o zn*nsw?v`a`z1|Vl2614$TTQQi&FrW;92@d*{a;Y z^P*bcyw8hlR$8*CN_Xs?vK!HcUWm1IYYl+&mfhr2aqwH%-u^uDTT6rd!SA&&tm%um8 zQ!qLFmueKuFo>TCS|Y!XZtc03*1c(*{7L9wba1M1pDEg}I>PW^Oi)CmwURWDUD3m% zdN&5-Nld-C00JBV&#R32s(SJY2*@BFH`-h{BBZIA*_%XBr;xDIeQ%pL=BCZ_^5DnT zuaYE>6-KtxQ)>2odfwRB$N~*5V2^;NqnG8*53TY0(JJ)Np0uQ+rliE=dmi`)#^97&Q-}a`kaAMm6u*JuR)M_ES&#ipL;^ zwsmz;BJI_Ke4tRmKn2&vFKHxy3H1KfBQjK)vN>o>AUqqK4I0CNs@1@IgpmUj;O7G=qy6c&wXtS_jxwElAQ6t!RBI1bW(B0LcQ2r|pvGg(PVNi)J3XNkN^Yy|qC zB|KxtYy+`b$-b{$8Dsa=v{o`;$W}Lbm@GN)nb!#7KuQq!8FI>B!=mJOn4=5`3YxcS zOqK~Rd85z|MRQ5@=lme27v>;e=qUssYM8Y+a8I;Il82*|_VUmWRt__jc*~FEZLOg z;5#UM)}^9PSMV+zTwpOVF{?HTWQ5JS)>b1G>6%l>p&J*T(QP(fp`;uQcELHW2}IlKht zHgxs%nV8k>xr;!jwgSjZU=fcRfwD|kSWZ4xFdljY+h8>!lKvHD=EO=3=s=NzH(vHd zN!|eKJ`5=EnqP#h?yW!EWix8!3kIK>e)EqX7vM;dn^#&i%AG59o83SSgAS&QEm2P} zL?fqs01ZtFaB1FzG99!WizMvLh)eTd5H>kB>^U640~`o% z*K5M-E8nKq&gBG0U~ka>*d2?fm+=jj)JR0O9cWg#%STSS0S%HNa{Hv)%q{jkt&1We zB1Bp^JS12Ai#5bTg!4R)9UM`XU7;wtpedlwx9b7#@jilK^)S2*ikcp^s9*Ys-S;09Ww-RyY*R?*J@x>|eFN|7$MzF`{)k5i~7?)`zfbV%_qwr@LDM zSaE2}NUUT*`F#1jVQ6M{Z^Q@AS4y)WU=!)Mg%%d3UzE)wg=PCU1Jh_sPA_-?x{E;I zfMWwKwU(NiNPsZtgs9Kn%mA!wd3h8RbVC>n<~u|VT_3mwaE~Gp7fjx7!I2G?l~)4; z1NPzLAo-`H_`vBZGeDZz0|AEF-z`mcyUr>k6a!)qSSGC>^rZ6e@!h2lVm2ly0OIz^ zv{&7DJTPu>h77m8F0}qSR{<$9j2zt|sB@K)sJsbu3_wZiV0!7?Ih_d|))fbkTpp&L zaoD>)zQ4D#%11&%B5p(*<^}HGtqM5$t9>Lo4Qc1PEsnq49vMP_ct7l|2o zRHOj~BE%#(U7@5FM^u83xaCo6Q@z)so@eM?w1KCFbIk&vN5)mK-%uA06Nm(}B1{@D zAD>wc9Pg;2q*TkE`{6@Pky}7YK>?3d_2&&Me{Th*v-rqa8fMnksbgbfh)M)$PB%9k zjN$B@|JH4Wll<5H`oGk^rI~t`U6@{J@3>eN2#y#TOSBA82@h7pu^2TCUs4 zdZgmP#s`<(-(2W`|5dSTF$kn@;eX#+`pO?=Zfo1obyKXPk4f|4{hQFNOksUZV%QTJ z_}g(P8AWYvHjlbM`L8}&uw6ltK~z0fPA3C{&qb5C&CO2O5R(VimuisyiOx<#)94H! zTtKlVCL8va z00nGf#Qt6rIK@H6zIyWb`^cd07|-s(LG!Ihw1|j22uqQ@w5HLe;3$gHocjLVZ|TD< zcyl5AkkaYp*8y;`HM~ARp%17NY&v}F<=SkJmH#E^_Pj;9WG+Dc15>E1q9Osbx~A>IvX?5P^)a5HvmEE0n#{hR|w>;{3kM8HP_(uJ(7^Vx;>1G3v|M|IJ!|->hZ3aPxoEtaZTPGCj~Gj$1rf`&E&9(7AT1W!(NP5flEa*T=8vDjW-a zekbq4lW&bCv)8@SD7_NHypDTI-MM(`YT9v1s-xmpZyu5AIl!x~e7sn7X*LCY@z()dzY4ygm4zlIuI}D{08VRG#UbwdP;g^ki+tb&?G;?HE~ygQ6d6o zMokFv`QX&&W}yoM!82f+YS?ymcJ3M+oY&BYs<^Lc91Lr9yGv(IsvqaXd**Qcw(f>! z#T=gV2GxWT=PhRJ7lt%A7@<(=G6krPVU|$IXWOIT3Y4=C(VxEy?n!o?_}SQG-POqZ ztgx)?+N2m*>OTgkS7WhH)TUduevNqzS!bjxM|>6#i&yy0$g_ClY_;UrlfI5EF5*j7 z!c^>2*Mn50RR|hoTHg233EBrh zM#Q$dn3(t>zO~dicSZi2fO=v#S$-HKS5@h9=;`XFz#t_P)SrW+F(M;rCNbe*VH4ZN z@wLn8CQe8>7aDrTh<^g;*pS8OBVpmVnX~yJJJ2m<3g_kY^z=;dM-Z_IR|ZYLB?iAf zOh@B}`~KGBQeFOM8&IWfl~P9_XLV@VjD-#pv5i6h*XUw$XO zHFTY%)^RSfmqHz>Dge5aTG-hsZB<23EHa%ZW38J7ALoly=Obag<9;O`2f{Glou5DB z120`aX&ezVH?sEF4onhR<$P!~^P0=vwu2GviVmgCWWyPxXKZ7`L0-wTQ}!Z{2zMZZ zh#VM)lAD`l0W%$E8(9hq4>z^2XzIA)u|3NSPLUKCz)9!WIajd0fQ=~V=Ss<>(M4dJ zbgNvYqoSf39E9Dr?bS9t{qq5eeV=SMQ9jol{@=)Z^MD%nwqKm36xlSXP)da+MW!Yt zyMan+kVP|+P&Ah&%hW_^E*dCFq*-ZFB+;lsYL#e|tVSBNs^8~k@BQp;d*10e=Y7vP zzkmD_S?j*P!*zY8E2UIJn0;g!*P{91-ic8Dat1R}E<8*6*^37S5pkLyiLoQ2h>?8W z-LZsrO6CN0KbtqhsM6QT74rlmzS%kG$eZBpaCnC8 z%+cf{!BJl$;^WgjA~ej0t+L&YWj{;LuQ^3=njGoQX$o7sl_ajD)IQcdKYC#*P9M?u zVe2Rl6=60}A;#E1CpbI17148w)@}8wi;Rq1>bK^U`;rOA0~;zs%1Q?DZvY1+w?4Iz ze?6Ch>#^o`bG}7a_HFyN$)*`6UuxDaOhuw|bDEIci-QIX?N8|e8E14@I4)dpQ*TTY zk!U{&&wz0p3+Zk~#+BL_*+lwBK0g)ClqbnLElyuITAn_Al`trw{l-n3^zxWpflqYE zz{4Y7xgOuUw+_oBLTHEHWz!D`_cY#z92&bO#YW|ud zTQ@fa^{V3tkTQEHG7{C4+qrr0Q=CmSII=c7-x(Vp?RMqiScEcEju?;vyp=#EhTpz@ zJHu1kfAHXXp3h*&Y#F$`?ansJX_KmK#WJHpj&jjdR1o*5A)ZmKv=SQOs=Ar4{Zdtm zG=>POd+F+B{GO|a^q!c!)LXAt_MV0EmF zK&7#{YND>2qQ|DVSRka9UylHQ(4egD3T7n(7?Pd{OGF}u`?JR-pA5~Lx1D^lVtx%N zAZU%KgoHsFU?|mPNk<|Un8x$NP!HeCaW~O3vE+`EYB@rCE81)9d>iu0V0_PCmwt^{ zrzt)uXPeA5_6F6m*fK;kdRD8LH+S!5mM9GN#$hp<`Jl8z%9<6gI&b_sez#;c$7xfB zh)_D`cJo#Cn*}l!&wqAz<+pV>bJpWycj*EN)5vqaL;$mGr@^L}ChD>kD})k0d-HPa zS9fRYjw=<^OO_wjRo*f1X1bwd#e*mLYLZU}e%As(6_o4=3!8XH+2Xa7@_z1R7nOmA zU%z;9zU*f8)jiQqDl7eyjag~;N>5`m zJ#9L?@2Wix?PW-tz!;(b*P(h(jqM&N zOHqrAEj?gj5^kTAlVcE_uy6nV6cckdn;_d^O`;aC%=yKeBRUlC9~o>Ztrt($F>=)% z-@kv^UIPR2*`_JG<<^l4QWzq57`q}%I~W^iX(@2!=RPuDe>+DRB|&iFDVfx+ynFX* z3?+sW+MH#a=xr-~dLO6o`4>3!3>u43%9FQ`M6%x`k*drn-D4|Ci(CH;N1D9ar-?u|pX@}FbiQByOx-QFiJqb9*GQr=9jw-@t;#wCZ{9Pl)oaCZX z$vWkI`y#ViTV=m2J1NO(S~{IE1LG$)r>!J?NC+{f!l~r{2DOYxs74MJPeyDY5vJRfo?MO)<*rw0QDaE2foii{nmq|Bz>%?guU_r7JPgKf z-&5K3WdV#^5xXN8e7(Ed5<0Ml4Q}sax6jFyib;AH!>qw22V@f4OTMVS9Kfw-{RE=v&(6Hz3uJw^3#F0sN@JO z!$r+2KVutIHY(X7Cv~*0-was~;?&{ZyCyf>6s7Cv5jA*RX#5P-YQL__m{`K=Y}0ui z^_0tasX_?yHbQ-!TRM<37PiI8Yk+`{7L^Ha!aIGJzvpw!;qeEm`DMIcin zwC`E)80^`z9rcXHZeEApJ*~)-XD2W&6J+P)>zF1lS*Yke^T~A`s(R-r*R`im)X7?v ztq&6%JLrZMB5bu6zUE0<{V%o*h6T4%Qw=^YSkSNll_YdD;#2IT0GAxvSk3#*RfxZc zvY2n+n(69b#MSu5Sv+Hcx}2sK9hK=Gt$Zi9=X0B))5oxpXcLpnQ!-kpN9fj3Qni7KzNu`S+-8`jUB1wsi=#tXZ=rtTVuyX~N6tHBR(kW(E?z$@QY6@76Qp zXy2|N)o@=nyR@S{6gsr-Y*eIFXP$)@!VWk(>n|E7{j-uD*K3wSH-?oURt};cJb>{FcdK!_k?dNr>>*O(`H^U69?iO=`m((WU4N zg8Kuk$=?>gyPaMAh=hcgSOQec1@Md+JHyh{-7;acvi!@|O`Bc-6**D&sLJk%3*@HN zV{Sd0F1R{5g=@#i+(@OqcyT>7yQnCYlcTpu7rGS%Gd)l4;)d6+kGKV-2!whw>D>$c zI7QqQ&0aOgw|J8qY*2AEIyyKWI>O2UudZ)Fup{MFH&vHxtVunP%3^q$qmsa$otOk{#Sxe>%s zVZjiwRgobCC;b64GZ)VRrVF@ri9A*!S^{TIN=ZpPItsofGcx%)-CA*(7xx6^}-ANqgmHzLgd_hEVOhu%=@$2pM~M| z%2P0A?w_M*GPG5EH}9$_d^`gIVOB8oHDH}HiN&kqU?BJg<5oGHGa{g|7X$cvmaC!SKe!*#)rmn?-CxHD(Y(6WE?pR$oyCRpU= z6D8=}KVJdciPXwDb0!usM67(VVF>6CO1OWNtBfQf33E=Vl|aVlGl3MMw)+cG#QObn zE6$@NF*z=xqs#hsyZl}U{^_%AyME{$dWG-58oz|-$XFPNM9n#8>b9Hr&E=a%tgOHE z6$0Ow!Z|bNSarM@hq(Xwe=xCxl{~fLpZ}bAIRC;2@K9q;ops4#q{wX2{d&Ser*n3I zo^BI1+vMH+)ReL~^{3B^)n|i1hVynN!|xB2_;Mr)Qq$+mdAAYOQW*~`S^oOGyZA<#C(RIe_W3qRE4mx0vv~= zDD31^+nYDnp&BA?i)32pb7A7F+O#};14u6563Ye;;eH@I#fStT@(hXCLwp!09USk+ z4-eb9xSO}9Ph)9f9D*@J_ zob(G97%lk~h-3jY&Q83;nfLFj;w%fK228y7;ctjjKYskK@hk+UacQgdv(^zZUu`&n zcih-x7#JV8Q#fSA>*9`8#JH10$M@qS@S+A*L?ara-*fuwE4yME%?2}N?As7JZerHy z^$x*MBUc;lt1_pSm3cjAnqp*@VCZ;<%J9ea|-)OYp_-Diiks0Td<56qPc*#?-AHD)Rb;1h$dn zV6)Q30mZHAse9?^Mq{yBYl!O^34QNe>3CL1WK=RB9Y1p9B4`mr(us&y==iXb(P3wJ zj7^SOAx872eaYL0o_A9Zagl*%JBwM|BHcygykM=p=drzz@~LvR7rNBhO@IF;>=h-j z-4m}0;xChJL4ITE#o5y&1}>7_DbkPolxc_gIw`5bI~#?M1-*G5WuOJu1I^&$$1`v7 z8(k=?Q6_}OL#S;k*=vtjkrVrRy=g6*Wxw|O@O!-w%pk(LVCEW`-N;5pSONIqo)qm@ zs2fDM0+R0ahb<<+C~T&tH2xW8(%iyQazl>WQKOTUn4Uv^Wg)M>43QL#s^Cts#%~xDmUmG;1 zv$Hd|ZiTMZ0J03y#$=V02FaT|QKcQsB&&@#(YEarX4m*dO^Lx!VP$fCef_0}k?xE? zJzDHF2y{St(YZxs*Kt4)8Db%4b>!{Y7b5gHODh&Vrl|Vjn%Y`DOt(o&G}Y5PcgZrJzltCmz7dR*>*8@X1Y7WM z`l*C<_w+&}bzNF;11s|$IFC9vp#SYYjW1H^n~O5H#kRA1G8hXyElt}xwBsRA%X*Li zH0S!GFQvssp7?Qm#*j2Bdf*RR>xCdD#btpHQ(KYuH> zv}0U^cd?P2(hPeebVVL_^j;3~@mk@{W@ z!t)JxhGyTo@N#4?lTzItk;86%zq+~QTdt5?bl!12i;2UvF?-&(i)mw0Ede~68(UjH zMOjH^OiVJJQ&!Ew^J8IQsdO6}6g1n)`lh(FqhjgMlq(8e%WbPN^xBRG=b^c;=maTf zl%{&#O;}jzHF6|u@}47s7IT^^=+{boYzH5q=}a1kYrCJ%MyBU;;1b1MYE2zBMHBG% z!r{M>v6@0k94GUqo$G_wmN0N}i(`!=g>^(4+=e*c&RR50xKu@&3UhLVo3^s>dFiMY zx+DGKUTW$Koc@B57#pMBT)XSrtJ|QNk6|L=c;ZM**_{@eQrgitCPB>YD$EA=lKuqQqXd4AKwmgk~{ zyi-j-b1Fo14cM2)x%v4i%#0foJkOU|bjtu+@*mn1R625+mkq3cGBI`ww;ZJC`K`v> z60eGT>w55x_PY>Me0s(awOYBQqfn#+N|Q~}(mT+}$K9Hfd~L^3uOqz3(#I8~3Fc|U z1803v8*Yt8L_8(!CY(!~wr$%DjHq%{;nieUZ!dD2`O7=)s;YKC>R9YC83INuyx#-3 zVA{Z3ZYxMTf~ykiZ%f~i(x-%@4%#Tevq)@KZT$0R5kVFb3*}AWk2N7dq`Wxu1RN8y#Alk^@Z0nXSoXg7X*vY0XiAJtW zZ+4xx6wAQVZsq1rvig6Fu=+_=Z*ORhFwbYseDxHrM8SzIJ!a<_Jq|>PNL0&Tbyl^Q z^g_lMz+_f3@HRyHE$iMlxKlXc<+}HcYiV-ReebBF1-n#c7Nk0kZ*I(EwFSHY(;F{a z$g$5m5aw;^zTx8|1)B=(Z>TyOpLue;`UIltlr7zWv6t}Us?dOz>W$*sa+eJ}i@uH=(cB8U zLFSP)-&%_0)^M`cu1x`Oav=jUX(_qqs{sVvBiWcmSCyqBPXP0$c0E-$TTsMlm!6Um zOnr0tNb8c5jpu(>gjZ2G$U7>1%|0K>jB0(lD@wt2sC49bR@B)e17y4N67m2HjU!k{ z0ZpaIZVrxhFI#`usviZ3y=P&|mOfU!wa^m-Rb>}E31}x7d97b@Ru~V?5=9riT7R4& zh2b?~k-?4E>aCZHEzK%S24&PV_94Qt;|%z}rI*#ZCx_}?ok;<{VSU$t;aMXZ~5`{R};o?MY66B{OaoNs+< zY^7S-PrG#aGMnyKr9i*b#A0829SqrOjGeeGu*&6=SD%jhn%EU=M}|WezA1D^F1B+;FQmE2MQaS!WTKlB zfSAp z%|WI!GNZ8we3blL*?dwwqxJ1PMUA?FUoHS|dh!Se%3oV+UKz@2xjP-}%&1faJv+Dn<2k`lZfTJJXnE+he=LpiktL-+VA0F&>HdFjUdi zeG@2-T7&d2OUi%O#Au+7kycI5%F-+R&dWs-ih#I*7}@j9KRsZQay*8=Gr}ShiW11 z)VD8RcR^pC)2X+*Js(`14y8+K^-e~Hh!Rp2ZQHxeLhkPF>*C#UskgKLL0pkCU4DcD zBIm8naBW+yD5mcCGFFX!IH83!!{mba15145d@R9y1#VD28C4E1UcE|^*y^HPEO`E+ z*=Ayf)v?J-d5mutbd~pE1WodZY;ID(Gb4A$0RC_Kg7WkgD^`Tp=@Upk0wr{9kFU+p zj#G%1UZSFcj>O(bN@yS%IA+Im9<;Wz z)0O0w+Q-b0`o$OAVv@jnK5r?k{kFw!Y%ZglEHg`x)386+9a$KMt~u^VF3ob6T7YD_K)1toF>jzdZ+NaR_xsiPt(MBY*@#7jeMpy$pwY zYnFMfp1cEnNiUkkZktmIyNCe}*`N|Hg*?wCvd$0lTvYXXvmg~}5}?BS-nu%yf6Qnp zziOF^Db3#+bM{_c58pZXrOWck@^SFef$?|gw;1|ANxzM>&*0dM_ol!e_N3eX^n z%0j1mS9gOg<2R*EI!Qcu=N<{JMAU4S45q^DnVexdYco*G@G-td&S!U)qtM+4doT~S zdK2S9x{WK&O28sJN~XuI+1o-}5~N23>E4UEF!&T=~9H?YQTUaw1?ADWaBJJKi zB1=Tt{`E;px%az_<13g<%-Qk_nR?0o+8bu1exMhDO}O#8?EbefQ}53bmTF(Uyv@mjV^Bnd)qVQtk56|D_IT=$ z_4yvwNo4L(y1QkJ&HZeuZQ2In?DJO-u<_S#*|6aTuNhswblmpk0lVL|0C%(Jb9wuz zpmRqn)vY?uN7+2Tn5n}pIISj{k!v;%A|26q3}a}?E!!h<^JPNzwSx}`B5?7cAEA@g zR*c9Z&67B|nrBhV%v|l9(c|mVsgDvLK72d;>Lb(@5!z&djM0c+3-d&WQXku83|f%jflRHMGMAiR6Th`&cBarW9=f1? zDx~zO)oPoQIuI&l@44X@@x4Y4Uu`jd^FZ7M%o+wFxC@PXSQXS@X~rwOs}di~KvQx0 z%g1n(0@gE`q!aKvYD)gPBSZ# zjM1mJz$Q)3q9&@`QdHwfpQyKAjLyyxAqfQDhA#T_#Ly~KSE_8}6t!PJGW@g6^2FB{ z?(;@)5Yivl6P&9SW!W>X`a zO=t?J+$2D!#P5QcbX~=UAYuQC&d=}5n7$$tMJ>b`1Ud>ya7{0VFUe4{3@h$kx~r^6y_L5BPtX4R}^Ni{aN zw+{h`v(aCRv053p@#aq6{NQk=xjFnxyM$bx9Tq#DI|&!WQ<`7N`8kKK59>Ojl$q{r>C+lb+HzF*Qaj_ z@aO+3$()LbZI`H_xA)E;V@l~d1Zcz)%iwM=)6YI;WDGl5MgHXcPoF+LF~B&pH@!Fr zbgis<<6ei&^9g|TT)XBj?-o%i!!_9trU|0G)CH|B_$!boTQ z=hP7h5zQqZcqSmQ{Z6#}MqvJli8;N!q7-6?@015f6GDvpCr+ec-alu}=uE5P=nLOT z{qz4|h+iOMZ0kS&IY9;e3m;(O5-WLj@GuLBvi*%(U-pH0Y_l%C-Y!em%}y)59BH5Z zwR`r9ndrQO+kew#{fS~?AO%Zit&0P3#CATQ9lYNE`#&3rhD?Z{t#FXRXjM7Z$9oKA zrV3$jKk;()N=;3D=J4k2+uBOmGi5$U9WcqeS#c>r>j<#+2~s;2kXTri zA58r6ZJETo!Ho}>25eH0Fm+SC09o9IKnK>~KI^H&(!0Pmab8xlM6*B?0)By`=6gDB%-+5p*lY*uO`OD%`Lk8@_-SA zU?Hlec`)Y*l+LA=@|KpXt+s~_mDv>oZEVt96Dm3`i>S8xqhV0A7@O63;aaTfhpt;Y zKP|1-XT{9S)JeC+s0;VY`jkQ5^fgX_$${dkAW3cQtO&~XlzTXra$&nbgKBO$2LqSD z*;B(S;0RzPD|T8jea7D~(AWPJ2~PI$NN{U>h!Z=^b4bSd6Hi;Qdz0Ohir25X0L97J zN_Bvf*ps`0mshK>rmO2F@r@wt!Vm_1e5pMmVd0(0LhODwi?*WBu8mh36fq%2U=%>@ z?Wj--M$mW=e>bq-=HyBJ^*pVixtWpBuB)5s7vwTioLt{589!ZuLwdWw;^T*n6qL>9 z3Nmw-e4|*qH+ng1Kpk{coD1v^A`WgsO5L1p(ksUmAetbA$UnqKwmq;rhd4tuNaujf zpHSVshNRgWxq>9Vnf?%=D7rXdQJA?YO>P_f^eN{=-8X&&?mBAcVKHJ%LHINRiKm?J zH495g>Ex#wBvQxDy?nETbR3igLgkLy+Dd{sQU_V_U8xZ_p2v-4lJRq<-N05p~4HkMC&E@)TZ* zaHndLIPYSr_UdW_b2u1`p6pN4xrbXiZzmNw$+BrB{5PL^v64F`pjxT~@dmgvr{9X| zb=xKP8|TLAv-vMahAb=TxSLz^-q=;T?oYIz-aLqj88*p!`;6VY+TwP<|5$n3exSk4eE-JwBDrPo*=oKF`#Rrx6BrakRXnK@n~zGQu%#D$#G(4nU~v7*4=!sn%NrL6 z-YK$~XPT8f>>7ibX5&}WZw?yQ11boQKo7lq7^g=|aOfV_&mV#< zKND%voB(h&}YZli0KU3@PhQIu1m zC5qhlvh^Ptk~ASJN`I-#fhXllWFB_sde2Vh8A~!mxM>^%&6(x7hIAKME6s7VHbZka*~KS)Kv{*95WqpOBwlcYXllpGC`;nqAS%OP zKP+|ahH9gO9pE~{+}}Gdzn4pAh_+58c%fctgoE1$1?s*l`wbGaVMv}l|InqS+2}N6C4A}j8^6|Mhe!A z>MVV9N!vqDqsqJJalxzDPZQ$l84%$Le2vCW+SV_^c1*@0`{{HGU$B@VZuIUED38UY zr1r^Oi6JK1rKISlxd7fwJIN(SkMnmP?|RO0VE_Ibh{jiyEOF=!%!&;y9cftEb}+&o zz_vJHX2QL0ycR%J^7yc^J-|Z88M<5k+d8FLi6+gp88F7KQsNd0U8(4CR9vzMi1F$K zY&;@%;XiDqVq17bWr`V+YdbkPInMXiD=FPyWCRhcuLCJ>PDaLdoY?mH`I6*2?sf4s zAg;3ppaF=f9)xly+~$dk?h_zc@SmMWC%J7~K*N8(nQFVh*k5n|kZi)d^FnX%5auFy zc|jbJZ%n^|si8LV;vGTeGwMp-LM=E(ESh@|J~iT?ND|^^h>(S^QR2SlM0)?h0)HcP zj-u>-&-#q$Q5fxYPEfx{;6HDus`MPzJ$;0Lf$umjSM`yOEoE;^4CIv+jD+l@%I5L= zjQ;+uoj#=mzA%#iY=hFtM=xGnX&r!x(Ox!v>o|CY1G%H4laJz;c`zKdvPw37+tPBZ zIgq7XOKwKHV%68J>OK5(eVvbS`StF=sOgdY!2IKDdQxfxOM14HF}}txYBbfCYh_MF zPB%4j11rjOjc;0*oG3(Q21&o@Zv`6auLnN zvk$HCZ!qW0enlRQ%mnECZ`W8hsUN>0x8HYh4$sm@c^hU0CEhhYRnTc0Douxi{0 zp;M8)XG_HZ*c0x_lGEyfY)Q5Y;uWo%`ot9?eydAYeqPoF*z z$h>Rw=^M!F&MM~lVjh=!Xze$yz;|&*;|GC+YDTU|#}qa24UDBhys|s|R0NYsAr%UZ zk50B7VKV{HVJq4G*p`ut|NUCl#wgmc7(d;0$Qlg}^VoE)?WM6&9RKsfA*exi;J%2M z>bOsHt&uOZGP-qgm6i+KYOuVx?D6PDazd6uI27MO$Z1#&S;2|;(2hc$Me{w~vXfR& z%FSZleh`Vv59#ggYU*F3iRT;-0!*}o+YcliRKW4p_U>_u(Pka!kL<$Z- zyR5%vIc+hMD5=(L|l>X;GQN+tjWvAU_;s##7bn)uS(py9xZRkyQ=De?{h{< z`Ehe%?q6-O1y5G?m+2{&{D&qs*V;;x7rWVbVBUQ2)OwvZj+^XcM9>iN5mnDJ9O2-I zD_|p=QWK3D{N~{y8bV#yTc+OG3`}0{)=79sZ*h`$tXx2O)zBb#PDfVG^J|We1icE- zbK9s|k;My%jESQm;C;KVf-nlxJ$5Ae-IqyX_Aa8JA|gp|{8rB#QIXe!j|N5(Px;h4 zcW?t0Si`E~?RE3tA)^9HZYrA-kLn!3GE{4Sa06*IqW`VJw_o+wqVp68I^+r>HTnuQ zsy~(4wKx{?BteZ?#0om)aO)1>3po{V@Glka3T%^_E_@&FJri8vaJq1>+(jRsrNb6J zp`{&P0#Kx2n$RB1^N6{csQ=wrq!0h^d#6(|46mVt5S;IJ!%{NCb@y$pgO--%`jWn5 z-}qRO&g0TSk4H!7WHNcr2>#fKyQI=lS~B8E*zUE_oi7QzJmE9#g>|J7b|q$MnV8Uc zJg)No&c`Hv{`7Va^G})=;`M*H?Vsm?uBXao!a!+pyrhWQ+#ykRXMJr~lj~?8zcDcN zCDMT|Pu=W}6sD{;MFvIi6hfPFlRXh7_J4|V>c|20CI7Z@ibQ#n9&9trKwV3zf<&MrMF)|n( ziLA@X{W83UYR}OGLV+Z`s7z4l6T|DCo;8>eE`GA8;MDuGS+Q3Z38p)j=d4|`hR807 z2o`Zp^nvjp%z9@}9)AIao5dDcI4Xk55W70g&Uhw`K9;A@cZUNxk4)@G!<*CvLrj`l z`Gck3v=~JTA#PI6Bws@55XR;jyz`0P9>v(wtMTzJoMf{Sukfmd%c&hZEKi+U-^eL4 zl=mLil*Y=+h0{uH}aQHG)mdm|L-@tf>M{94LAe>NA)*ryX_hX2- z*tiqGTxi0Ge1St1?KC^rx2i_Hj5N3DyQr)zEo8FW}nmst+* z`qvs*Sgbcq*wUq9cLXOFdz{9%7^FS@UkiNba1W7f-dPu)ZC?}5^q~0$~Wag!ZDMp zR;at?$OD0xYuAJlUfR_36?%SrDcZfUu;AePQ&9vUv&Cci4OtaMgx?X37&rOg3J0US z!enDxKldl&$KY3tzuy#L|TEuI0!pWJ|`;Bbo?ab>bEnr|~ZXKl;m{fH*oJ6$ug!HHvEaL#M4 zm0*42R&}F|8aDCLzio}7mbK>6o?w=u#)|z14%oMsRp0#5s{S4 zr7x_L*H<92dr%q`R$ey$|1lqBHvH=u*G9?YpYc(jJ}xcz7o1b9zK%a0WfB_%J0PO@ z3=R7wxl3oUn)SgK-(@i~GD?KCb2$&sn^!q`##TQgqAaOSkYy5+vjEs4pi!Mj{lm>a zBrMRd0Wc>{@_Du=u&vkeK zIJibe-S%*|@*J8vFCO3@-$`rGf5U7g|U{C3fs=4QVXUQCLrTZXacwY9a|?ujxj z=EhV>tPy!)PzwqwT}=Ch%+vDTDS0LWHN6>dB491E#CC@F9a|AOV6Xk%xb(^8Cz#8h zTuXn$WBx-wJ6}qgIr~3lclr-=R@EfY&%bK{e#&2+nH6{vYBu-ZBFJXuF}$9c|8Edz zzgwTSM|gdt{r#(T zZ$t@r3&BAEP+{)ypbkELN{nM{fGvNUP5gJaW#rHX@tBQ4#kggvOD`->E& zvKsGe8ZG;U0E`uUFy%Nkrp&_J)6*n3Kt(W^*7#g(*cIw%Xeh0w96jb?cb{6!Eb)%< zkN5~m>BurA`Rh1~3D<>~h{%;GB#^|7-A7Wzr*jp+I6vSr2^3PqxqtiCt*3VGYy?z8 z8%xRE1`X#w<(lIEBV1EhzqYpaz}MyD^N67oO<`&4c9`?694jk+D@7c;K2ic1XSn~! z^Z1RuF-B0Gp@b`iB^3i{VGGJKE39>r;L=wiCL1&~=n*yulS1dq(7f%sXz|AXDiBDR zkL{_@{S~;6OG5k=kJ_#Kq2pXi_;N2Zz{?_1QbE9pisI>UF3!#ea>4V!=YgA(W+%Or z47)_-40KMOg|AOwkPn{toqC%onmv`s)`@E(B1XP*eTbhV$krP-Zlv-m@$E22X8GfhW^@#Nkb!AX zU162T3fymw3YnU69)2*W-veZ-zNGBMwalgKflRZCFXP`>HBH`G)P(zGz2u;!aQ>pO zriK4Y?HCI#*eCB<{<3oZ^Nf@zLjwxsZL!%#zuBiEI+NM|_uHppZndz}W+pT9^LL?( zBE*iFbdDw=VU0DUsw%sQT(DxI{q68!5Os;?*RHQqNYGG)6$TD(6C3p|6LVx@Hv+#h z<_|h*B767wRLs!T)PRsIUJhx(@yS70Q&2lt6xG8U69>uN*wGq zC3xN+4%)6TLZJ#)3fvGHPeiP(S4CZKx+Zp?iZokBWjAGXChtPu{~MF8M8iJbr-O`TAat4B(i-GU~q zwGo&)WY7^~qqzB-2MGKc&Umkh_e}Y*Ae1oMR5lMzEc9xDj~{EgSBGJdzzIckk60xd ze4CZmpw+nzi8O}bwtH7~LqnQ;6OoYOR4c&@LRUze9Isx290hzM;y8%=*HyAG)+)fjcCiadL)j`$J==UY@JeT)OVy3uDzO3&F9neWE4Td^_4ne- zFcCAQ0M-OjF>ZjH^&nB!Ef4oX1{npZje(5TI&S?+l*96*-!p2%KT$P z&wu)gYj5154SFqUuqypNM4DucKW@uH7(<8k$_n8xtl9CZlP1rz(y-+))oe+8$Aed&H zzXK;{&clZT)(cM+h@S7UdWti@53FcTem>&lI4I@RHb}5>KBs6oQHonpS7Bvdk%TaKLbyGw5nGdA3%TaN$Can-#xUF=Ut#%WvBa;qnf+9DD3*ac z7&+;P;2*&(ymjAc?!OeRf1#;@g-Aa)PpvS$9urgw7SfWiN@~*BXZj1G(mLi#Zd4gS z2a4%UyZT~iJ-Z$L!v?Cr-}CB-*s2pZkPYshMTyx!~PX3cNjj|6Rn?4_yY} zQ;Fof7Qg=rE2YE4Z(@gVw4`}?#l`oE>}rqC({eG}=*jXP$|fRT$3gqQN=?}>XlZMs z^^B}TD%~)f7iq)g=Cr5LJg?XnUf|sITs^yacg>eh!m!(i73PRU$9ySMYG6}QwtKE6 zG6o&N`sMM-c`}u|NW!641!c_4G=xTmgs5OlR`g*2K*h+dMj(0UQ zk+469gRKn%#_p9$HzgC|>-cHJbw+r$5Rr9fG^G{4YP?JGb;sUseQLX@)64bRn!op1 z|2{K?`0mw_-DgWXHfO*_aJcvF`bEvnUr~-2x2NUqmc#AYHRik-V55T=Ym7fq44=_z z{%e*guJ~hLF;p01*MlD=^AdxEf90C7%mc&aCiHgwQ7*E_rd^Ou*zZOdV5P|BY^|ZM zbYjLX3|m#2b3Z*{_uiPmmm)V~8~AJ3L%xw-hIs854Rbr$I5F2>ZW(;}Q1njCT(+$O zPIi;G=S#CzOh)>ZO7jP>NX&%Hr^No$F_l?@HpcZ^vdZs?h#gL{zP`}lb#3X96DOIT zw8FG---cN`t;2jYRVY0IcE%1oQD1X%LB&s}K!+RU_WWlkcN3ZBRI4+bREc{*zCA<`i7K3{P5vTV=Kq?26X!?TiT~IE%Rx;MV{g!iS z>9M;<*A<2#=*Kly;*S*gn4-0xmWM=T^$9z~;QI#=-(POG8%NbAkaTl*AeQgYkhMK4 zd1fK8G=dtk-G5z$wO}_v`tjSb^X(muNQVg~|CjiW74I7v%SGlWsy?=@T#(N4q+g~x z0dv#$JsqxTane*-6|IBoM@kzZAM%#hkff*b7H(HM zD;ZI4qFy#DMI$xL+1REhI)m(u*nRwL{o3?hB^o1@=1LsZWCTzj+e}!)# zx*`0(3P)IUj!~H>9+Xn>WEo3?VHX$6a2NX*Hu#AxrU(8>av14XW8md8$zCh zdOU!h!9m9ACq!pO!yhq=xzc%uv~N+%(#E)`sOy-wM^;N1TCRpbrYluVO-?uN9COqBIP&I#%eX2w`sT3+y) zqHXPN#cPR_G)dTADwkEcDE-3I(fB*}WIglp-*M>Yf?W=e-1HgD{1=RH44;yNr$j|Q zE4zRZ|IZ9_8pB2s@_;)=>Sg#+z{cx*~q?|ndf6dmH7Zl zr)}H%pe|_mg%e_PT@hQHR1+QV{#~z1G%!epc7t+>Cd~RKC3K&W(cPFxUwF!^oM;5C z@{=3!?OX`lbi3y9v#ox2vKTyHA{vVBpms!W@6UZNbmfU$k5XWb5D%S`7>0?o7g6La zZ@%y(3t}_Tk(#>8WsDK}4Cj&pND1Tjm^@+lzWV+2|=R~dQQ_3=^BUMtU z2wa?kj-=Ac*{K{Eg}}TjZ6-GDaPakDAl)e)v4{2R$(Ej6Tf|PZvXA=)9laJ6wI@(& zhVR|ftNrr=N>l^^t)QbCNuZPo5Q2^2qMc1W)yUD+sh%~3b?`?E)sNsMRzLFOEZM|y z2ahc|l@M!o+^uc#O4N;k>4y9(R%AOqCQ)L8f1QmlcJMqVwtswR#&srr^b37KuY+O8 zLjN;@^UjSA=jw{Kig0qu1=f<~s@0C%WIeh0od1QWvpa-uWIRrKAR-WQ_SZ9A+xXwK zH5N-gKM*ir{BGQ!c<)B>{;z4ZAzlsBlJIBw>5GqDC2vVuXB4F_=^LvUj9AbLPb7#G zIMbFR5kV%ds@Q#8c-PTD$O)>_hg4M1_UbXIDBNmKIVVVXy|yMGL-oa{PZA|3QQ}7A zA__eB#Aw+Pr58`1UKAGDKOJj4{&JUj=JIvUu}4a9AtBd1v)Gw!EwPzzL&b^cL35+@ zi;q4UcZZM;YBzIkbpCXrcdg)CDJ7vXy_7K3QX~T*uz;szNzcI-9iu&v%H01n3W0aX zPS$>}Ox@kh5W=#V#qTbwd`(ysv05XnEcWhQO3=svKPR)WYIilQ3A}Q+sr~h9HAFRJ zY-3WYuxNjT_MO@rtv_7=gbhu6IEx}GDzdcxa zYIJaWu2Yt$H$v`fsOixV1yZ+!(1?f^dN$S`dF;7jp;LcE_eQDlGtW#95_y}DyiLvm zmeZj6+SI1Sbu=`v6GC1PzQklcLPHm?6am|K5E4n`$`7?cMS--Fken2d`G4P;ztoLd21;D~+Zhoa8%>^*wrS9oQj(jFE2C zoD4X?2;$_!THcggpggW=5464)We<_u`K@z(0MO zJ)pG`5ZWiM^hX>Z@oIk~y+jb{r;E_OaQ@%p0QY`h;RGW#hZCkf5rpaeZ|E@2*~f{jKvX>OWk~x|MpmE#`I^!G{i2^!L~us_ z^qX>yj&y6nV8zMIaP-I#wPvraTelLaZG^|__>|U~UxAS$ge(Z>pvIcev~jf1h;H*G zPT_rN#y5zajZ+d%RO&P=6&e)|3r)<1P=*suB>iM<>t=6BxOfpUxAfk2`0=w^1E386 z0+iNL{`IR|yRCymqg}D1TuoEeVd?$jvN%D%L-t*hr~ShX#LCmX;W6zmD2U@XbshV( zOv$IYx%q5NnX>tzL+A1W9OXVF(82IPq`z+z-`sx@4J``1V2SJLIT zZ7c3QE-`Gj(G8lUOuz2+@Rcb#+QUMYI`Bf-O7tKe( zXf$@bDPLQdJ>&y3CJ7<=bgOOab%Kesv01n5qJ{V|fea0Gb4=;bMN&JMA1|eH_qXls zC!0+<$@tV5H+~|h)6g8jUm8=#Pn)On41PfEoUE^I4iPr^3Og<8+ZsW0PMNdKshKV`4Q-_+Avc z+z-`Y`&|n#D8@~`1gd4G85i(`y{;|h&<*y{Yhq*_E(Xzc_llfGz9F1p)wAuFOOaWe zjE!UFbO)jn4bS|4&~giC9aN8j4=@4+my4`z_eZFPDxu z@Y+%R{QOee-K9w4;TrWgDYkigBiF;)!y^WDVlvH_&XS4@X(ENaw-c`_6S)*Qo^Lbc z9NHgxj^@gdNx9P;~M zlJ}VG>gtNCHR}S9>`~$#efHNJ`LA~Y%Z983(Tpr$gmPde4H5Q-{18VSpX>1C-cI~@xAJ6LT_Nvr0mX`YQQj0l-#-0@`D@t zzww!|d|+(61&;^ca5MrwbU<>^mtlV#A)Hux)zrt2&wf6+2PREKiL%z)u8_Cu zI3Jb`*8e-z^|n~tL>)(=_fzDN?fgb{q3ER=yMpQ}WG_at;eiqi28YeelO+|zBh|ST z7;99!$Ip-0)oU}}@ZZLA&E2`0%c?de^8{kzcBRbQqpQ1W*OEduwVpnuRP8Gdw0JXB z3{DftHTIL{X{zO~(^FGh8}kEBoIE)i7}|D}FWvVKJCIiN<>$1qAsNbRj9e6V_*(&}%_m*R~va=gE)FqU%*D3KV(g=Z>4M%85?XPr6f3RHc z+~f|sWgVUh&`sp5Y_2i_4%j&iG2ObR$B*eJmIgTiexTZ5AUa`K2z%N>w8Zy9r~|n_yn)>5t#$ZurV_sNVF(o}+d8Jt~n9&V^BYHXM*+PpIKvcbW` zXVTG&ynjmx9Ar*K)=cBGXUt}~07MrsZcHUo0{dhf>EmOuf zC@54bm0${lS?$aV%%IPWT{@q0W0|Q{kzyevq{x(6A{i@EC>bK|5JE`id3wK>TI*TUv!`djzr8>2 z=l9=!cFTQV_jz5{c^=2{ouJ8jCd+!*;MS!QQM~V0GUP6Eamb*0 z_6+C#s;FJm{Y-fR9d8xvQA8+Kmbq?NedWRIQ^0tyc`<s~)8mP}YIUH6K@}$SzDBno)_o%IELH#bN&7 zUR@?33~K=!cU$i?PwOa-c*Pizg4Pwbk^&n|_&7Y;T2`mvXf$nkX|WV-^*7DJt&|eG z^;=U`yit(%A>a07IO|jQoMdR28Ebx$N$aDHrY57l-fD{EtgIjcrkN*#tsXq(?if?d zS1aBE^XZoXj~k!&$lV$(dJ3p(Vq!N8az_}pH7N+eJ48FjGG#>@5C(RN9O#atbL+8uL}cv$-lyZb&KC?%W%cjww{t8!$IDJEoCzqk`Jtn7Ue zCF_f~;Jneu2s?B;I`}Ig!wM;As`V>b{|^~fRXo=nc_{{Uh(6U2fpc`1lvJfGHh5o? zXeWxwerbB{@VztF+Y@|Tu^w%}y3U9cs51U-(=icMVx)0(K1RrYX1X^a+A?>#D@>oi znCB6nS+{=(O|S`G3~7C>)fCDp-s5-$TJ!eMUA~Z0`g9W^fSK_yQcwgDb#JfO+Z~e z3I^c;+^hMAx!2IaU2%M~gQMfHiPORAfD*f)XgXprBJ<~#v9gGfWTd;6BL)MsVXG=f zEjFXVC~Pzw74ttNS-p^CIX?~FyTj-8rhNUG!i>DU*Y+lNcYF@RluFU5@Gl zVELrf)SE}&)bM4@lg#2^o-cfo^z*h>q?Zs3wEiVU z*619l7eON=ZEZy$`LzzB>in6%Mp=#TmCIX-vck`ITYeB=$Qhry&s#I<0jW*yXOAGdWoi_0(Y&tO!njRIksp#h3_ebR-1z#yF_tE6~8XxK7=nd0>=@AVklALGd z-b^t;7So)FQynasqedr>R;|NSyld9sVU5Xl*p_mI?ZjlgmZ^}IRnUxe>E0hFs!)NO zISg%b-CPjbdo0dhD7yKikT;{W05irqurm3#H4tG|Jy$I${BBZcaA%ZK^g1;XcAu@( zm!I9Mr=H&@OF}YF#;vxycQ@-~a?$K5pJ(jQh&X>uxM@Ju|2-FKT+x?*LuHmVx_WA z2uDG(k4+HpppHsqbpu~2r!w{epg*UqzePUX7X13WGd+}&v_DCG$U|jVIuibYrBv-6 zDRKcNZtd=Apj-<$WRKINsPJ$y7hBudgvnI%U^xI$F)_vmE3%%$qF-P`PN~rV01$VRy#7MWiJa~$~UCYX4 zRNhu?>ywpxD3efTiIUr3XfHq}C=9=)T0Lo_3T<>178QNo$m%&{=u;ODVT|o57km3h zo#O{_uG#&0ei9Z$xC0(}7zaYh+a;VUDKU9UIc4hb-oTIHjL5WVY6@(n-p*r=Hp>%1 zN!)yzX1~X|U@?K#GH#FF{LqVawN5Ic83fL?FxJbcTjbW1b9)?WiRp>6&mNsDHF^e% zhFfY0=14yP?`ylG9u{#bzQVre?Qo4FjB8F4QC3G|jS5y173WS5;%ttGGz*19?XTdL zvVnl0pycWlwEIIQc?w#-2ThEPORZLOmFBi%pRa9h-Y|~_uQo4~L(dx`2AH25+8VSalG-J&B?Y>UAO8eiw(9lqJX~Jlph*2?@ z8YTcPJ@#-@kIHUTd~4|Fj&PcupyeN4xi&v1vyFg$Tn#qAZbEpCT)x#X?65T=#AGKy z*+T<_wgm$n{kyM?FG{VVbn5?%Jxy0qhy_4qXnzH?$bU0@(#WDv{_2Hh?a0Uhc7`%A z`a&fQQ0~=kDJD|YEIIx68};8_+`Bu#;22*9CaV}%XzpbXJ-0g31O>dtXPtd}7}O0U zFE$Uw^L0FbF6y-h)oaQj5+sky$2fiI!Q^7GkMNx0sKt`IdM z60FYFeVEvhQJTA}`KG7{=j!L6HE~q563_<@n!>RkDOOOoxoxzCAd3V+mbSsPgg~DLFt-(i>dvs`vRE6j|IJN1<1V ztA-)JCE1XdDd=2Hld4G7KV8{m*spVF;V2&1@<}egxZ%2^RH>P{xvksd892hmF|yEn zW#PVavxh}|{ zXq~vVP6`%h{5EpQSZ^4zd9=X`SHMaP$yQC>a4WfY^X3}GV_7p&dEb(PON@4%`YQPb zXQvJ-CnMJZ4mBb!7}yRoV#c23=&iZ@KCgnCsx&f-@9ftPO>d9N73g>HZq9w6!RP12 z2Yx!9P>(HDW%tT@-Vm*AQxDu6xB|B}%p1kt$r?sSP$Uy^H6)clb`dlxQ2iXy2w={{ zqj4WGf#Yj%nyOnRXZ`}9B6N0F1|+5=*3PcQhD}~_2t zpJyGNXd;Xmqn*ENvcQ}scAdrIM~^g{6)f$6hi62-_;=8!zm9;3EzDA`6!hUQ*pAaA zZ`^>46hf>ahj#E3usIQ7Uw%G(%tXu`fF9!6b-|tswIp-~0%PViA3w4Km6Gf++x!yM zB97Y{94F!}x6E=qLY<8x)aJ4ee+s~S2nGiy)U&nUbFE)Rwt$9F9CuX5Q!qqHU3^0v z8ule~K&3bhB86%OsnI(Xkrbi~Ur0bqoBDg=>dXn}K)Cgx4YG6Jw1WtvfbbIzc2V#K zJn+0y`V|IsfTQ4NcdBf?>x(!g^Im2eemN29zqBLH-X~Tg<+KiVRLSRe8cb|_ZCvZ< zU+}78epzz>-H5v6lkkdDX7B~*cq;7+?bQ`i506$td-d&=`9$t>%=2i^pUwZ<{+5Nu)K}{}bQ104w|S}yQGSQ9j-m91m8Rp8`ihA~t8xJMvA(wUAmP6=V|`^w zef75!VdqbPwF{QHr5)4#QgHktIC%Z+%-=(+2z-qAV1!URx*9#M*l+ubstimjYjAqd zy1>Ti@AgOy3O}>SH(uaQ->!hBM*b~?ZIB7~JVt00i61WVc)|&7MLnbdD7TTWc0A+x z0LR~dnBDhqsCyrPaQ^if`_)75{|3yk6r*&H?Qd`M4MC&vPqz?jEN)hQO_Vh9NC3M{3OfJ$OyUVE%#?D~0zf`}+CJTVYehQi~QFw=WE@ zZ6Q}$U#pXIQB z{1w4M-=+a%2(l|82xlT65)HgB4x`2Wh03Z3O zUDs;NRH4z?bMwZH&mXIiGa-+9ln9DJT|%@)d7hk_x9(dcn6`=exvbE+ zKZe{fDAu1P289#bUP8lw9@xVU;Z%i%xJ*@l@}s>DUw$zmL*fIQqg>rZ*aCxpM5r)-p33u)^#T_C9XkClp-;8F;usqZpCN2* z;9T$pnteA<*q0Qgm9L>EH8Bhl0m1}2wU@nnQnR4PiL)EX7GOsMgOZ887<}2-q-Phu ze5qj4cpLBBm<-_W`1;eBSB1J0PoF~U zSfx<$kxJknmAUS)$Q^4!lQ?CX7auYm_m08>4%3*1L*tXZwY-{&k%YlfuG{WiyX5gR zHOLp?HFznXK1^M z3bidkz~N;j;-I%MMaAYzK_hw)J;+yKQNzOjBN za3;Mv0Di{!Y=mSUZX5~FT^G!Y`A2l84_Qq`#aMuTP~HIK7dREi_6$}N#Z5qf=8lk& z>`j55-n&5QLr*{MwlAiIF9*C8gjQ*pe#7wi?nK^`Ctna+1sOZUR>`ydJo9!J4AxmT+?hHJa&?f=6!PWt1pYw{_)QH3?!uw|_ zu_`q15C=p=@ZLPro7h-i|A8lsiAqaZnRZd->uKM|$voS)OK-6U=54cBcT`p}I@8~M zw{yo;jMwnC28{uWt#4}T<;{RyCt>Z!gqf-924A^E)DE>Ctp(06$SoKg5eoPFhptUI z;X;rP()AGlJJgDMSJR@k6u=ycNUkcl7zq6G_~D!FaA0D9sC>i35Q-^V1+|0$Zak%@m(wE1;-}qL2b49^V}AUkj(1njUL&a+Wk#WM?vpJS zf*g8b)v01=GFig^2n*7SJ*oC7V7eU9Q*(kI^D`%&vg$2KuQDOMx}44_BL)MGr2F^1 zWx)(@UJ9I|aaezDWS!iUG7lW9Pe8P}hfnE0uB3d0uj z=47CUWU@sBEvR8;Cu5K)px7UV8Vtp-jrT4Y8EdkCet!O@(FmwU>HmDjg1lqoc@I%l z%^V>lfU_^N24GGew{|}U;9Nhf0W%~IbcouPu2=6}m0~RVy6e!16Cv4abc(aGY8yrB zdb8_^d|jS_uV0Teii(J|TeQ(-0uj2xf3OajSii+rais}eUor|bPF@<3d+QRyw7B^h zhNaQ>w{4eKEg8<}6?XLFmYFLZ7xWHMOUP3(F8fsG%HjWTl(zC2`hX>$z{?kqU{&_E z9S;%`tT3_5DQ7yIjuC^>z!&tpIpis451*c&a1lc8djaQ}Y*c3x?loX}+P!;#xMSI5 zSqmY{dKI{uow+OT&3)HXnC%u9RuXhFuBdBMx=f90C?~+!>=Z4Xy$C-Nb7`K8tQL#V zTo4w^JHZV&m3HNdGuMNQDc}Wvu-1gPEyf-G(|bJE6}Dam-BGzkI^SZHBcrrO4F@^S zy&lW*X@WiVr%Fco|07hYVbb~N(WA-~SLSmeWRx#%;kb_UD3&6(@0rKj9Jk7&`%MIL z{InI9UsR<1#b@%?<9y65YA~FE`(T6+VH225*aX&XE`&`WKm<-Kc`Y_f{c%7?x-p0a--Oh-<#@HlJ`g_9CPf~hR*nTou(4F@>c*D9Cy_V))DrFUa~ z9q^(9Oor?yPmTbDhoMAuSVaFNll;k!M=<-mbM&YliS%i@&}raK_L^D2tS4^MqJ%0E zJkoT&lDv5OJJCN80V-hf)j(e(tG|ar+42JTjp8CAhUUSG0IJNLoI>%Q#`QSoj1sLo zP!hC@p5$e!l!S2!htsVc}J!g>5Y%>X?{-V<bb4ScK5j@F+I)whpeplSfP zY^SFwSU{74YytQL0_OBYa@Sb+-Zh%+42p8KM-C*MA)x)IM>~!W0=;SZ_wgwT^(V*= zir!E6Ww|p!I3uPF#8IYu&GBASB8~0FQK9E_wx`&3^7A{14_tqKeb(ySIZTlc5ci@M z!59zp3poRQj_1ln5=Ma+kSe=-%PR0_;%eko*uI*qHcXrCn-KUJJSd3tDi8l`ys;1( zHRGncH(i8}k~0~XM(d=NAIu%-16{qjm7ZF1X83%j_=J^>caV%aVSqAisJcpXPZ@)* z>!#G)zhYF1O8){zKCAjwTF((wNKt)8l0fl+-rS4(xw2ouRhFv({y`=&yhPtO|7kW zPZ)?emr^2Fk#(JIMGa0dcjI;&>@Z*N?)fTDiFuj7Y$xY4 z6qVMWqc?h+$b2$v&F%a;3eOESbFa5~?g;5^G{+W}uJ|5o48mgHfu}XvsaWiT>~gkOV45 z^7cNjw7R(?5WJm{fv9s1P2bB6B{+DC%MapMZ~p!>PY`?+TerNXdFX>KhGTW`FALOB(giR()51cFu?T0KvLHF^3E zylU^oKNi!oN(R1;5vA%9DY4(ggO2b&d_%wZ>D#~n=Kn>CX~-BMmVle(1GD`QhKlBS zdG>eK3|nbC$q)H1gsui9XxLHJa*+@;xbfsrWis-zBzPiBDqB^Ck|nSh_nDdC6&xu` z$L14P{fJlskfHo-kY|M!|53NMj~U3VHvJd4w$`*+y@4_-Jw0Gh|4IpweA3WEeW)s# z_gbNhtX!aVsC^7+eL^pg-qEgZ7df=Sr+@L;|K;~|c(7upct&tX^yi*k+ol%bv@@gh;K-XdZ~Pl+K{jWv`pfPMI+|XQ+iO`J zFjb9l~~An&gCX}2dpr1}Ej25y2ebL;zSz}g`gm5U#H1)THf{irTDI2;2S z1wI2jo$l536gh`L zTZ_BrCg}YbT@`NzhO*DYx;AKYuMPo^H zu?`w}k;SHFsDgBu+$<{^U^F`xbQRO?k@19tgt%ErXb$A^gYG|kSOH-cfYMfN9ah?A zzd9ep7C#s$?Mc?X?`&%fwLxZ4ks5~4wXd|_6GjQ}6#RMto`M5}ryyJ=7;CI`3f!i% z>IqLl$V-7+fw70}F$}GGs~UxOi=;Co8DVez%D^A(dOAX+>;28?XtXjVK3*YcU55|v zRnp!9Fxp_z^FY=Ek;Uhl6xh8>e`H(T(=b3&1k@`2{9gX|Oh%P}edAu`UbNZof48YVHOjlVBh8>JiZe9y>q$KMiBi{Q1O0r3Z!1 zsZu4td-E$I%_bX9Wm;cj!`#Myy@`?0^V(Iklum7SW|OQBo6wHFqROn> zjxd6b?+I6Fy0L_s%03UzGuPcJbzNO6si21-*kvBOaOMmrBs*XE4*w@4RK7Nb;+?tD zPrJ~o<}?a+a1k0xm_IJ@`}*GtlcJJOYwWM$i!gfWA2l#1S31k>-(jl^o)*n*)N7y~ zbWT1yO?S$zbq*dqq3*~%P+Pyss6}Y^L%xl8cslwYnUj`Y1XtuVjPS#gHwLpsqGi-~ zLV$5^b7}6rtbT+r$6}-TaQAX_XT~6$nhFO-tCBo)Vetdnp>jVsYKr|SX=zGjrDgp9 zd}AM zIT9Y`y5CqRQw=sq0Gj3&vFXKGmF}KI*Iy~YFCYN!&Q1&(YCzcgvM@hO%!L#UOg64b zV*I&%=ZXk5;)i5QU2B9_YnFjbdn8Lgliz|%b~sOMTsB#?Ad{?VxQ_a zZ)z~Uu=npa1lyAksbRLPRHy3e)NdMoIH$Mts4L|HA+gn+7!NizRm5K#Sj%tcT74a}lP&ebpfIWX%lSNJbz zsQxkqSjA6hX}pXGqrpG@V2q*B;L8rO$B1i&lh-vY3BH{^YSA5WHGIul7L>E=`(xDv&)b3aQGjL zzD~43e_omE&eJ2@KQgPt#2zKMBM+q(Em2Zz?Bxv`HW1c;clSAWB%g^`l5xU5u2V!r z~J?mf_lHXC;Bk|St*w>-gzXa`x{xh zx}x*G!=7tu`{muX${d*0CV;JXjB9;+KX9?B3g44|)>zRF-~Ax}1L0B%`>!KhcuaeK z_mtvd6CS{;5&lsq2naV+9H4&SdrlWYc@KV2<1FK^=~fIZPEnZKZu9j=$&M*LF}sE{ z)eh(^2vd* z3X4J+3q5J&MjHOI#J*b&7cLOF^d^A(s;3vQvZn`+GLcY-^Tf0y=^nkiFHo|vyJk1$ zoFSBr7z&!Sg{xeJ=Op1b6Ymi4D6V&~IhUtio@3bat5$y)T78B3~8eqRnh zcOYZ$pgw!+SbbNz^010zm%8!)IGFW^ol^BbAgUU8we95}MOAeI8KkuZN^zDH$pAt< zd7RRqG?^Yjyq$D({#x&l*T%$T{I8lSzx^zMM}8)-rGXx>mgfU?BB7yybDDDF6pS(lpxBdMD&3DLyO ztv5@addxq~E}W9qJixVn8$8+pm5pd0KD-h*UEmS9Q`R1>H*VZG!nuBh_cF9(Qk%uX zRYt}Em_J~!B1l;+FRMp6gI^y5yj9QBDsNBvTh1!1W=gA!qOf1OGhRw z>5TGKA-lmtD$(6GCq3q}4y+V@$H}j0Zy;)jmVz2~?G~BHN1J+x*5{9}*?$jgMH@wd z@rm-xV^`4J#&cpyu=U(4UYPNNlSx_E3FHk-K+adyDC;_r5;S^JAme{tP<4-(;h5lr z%PBYJ4EeyDrNZ+fdLs;V)pSRtDEjB7M^TDA4~J+ zeN8X>@99>Xq!a)W#Q+TRC<1BV!#9k)&57v&&*F5oXDvKa;3K45J!;uQpptm#Zz;un z!DZE&;wc5|M2(;eJ1*cfbA7rpX74O!SJNX1`?=X?zms4AcwVKte4w}O3x1~(2f@cj zi5mCYsTu(w1!Y~R%N8`7bED8zk92)qHvoekvbLcorJv`RpN-rs@G5@t9Lz}P>}@Hp zs$upnnGb1Nf|Wd+1g~FT4JX0jM#tT{Ch3VRBuh%4yhkq$qBwHpKQ@`Ap*S$lyLc3U zfP+3%_S`>lV^L=KSY!#k zyA9*oYts6~KQUAEW1Fq*;Vd*A&Eq2sE(Vn&H5%I5 zs>3c^xS*56cqJy{yNlr4B^SY#JMxx&IuK5cY47&tmWgmjYYbMrbq5p4y8?MmkJ=SGL?(s)yz z=nq?YNm2sB3zX#P4wSK`r_wSp;f|7YRGN7&wchuLqjG6)uv3(WEY>*hTQWJ99ukK- zJRe&af~>}#LxOJNy1Vb$KC5!IC1k~LlR-kw0l9Bfp}f6WH%mBzXuWWZ+^+3)&>{?- zOJpG-Vmj=AI_+Yf8?7tEh%~a)j1|9$s{SRwir^k-eaaX#5@tI-a#mRgnh@Jdb&`N9 zt#^n-1evi6$jO08BS96KC-WY^Veu;vo+Sf8XlHI2cYN7-HJala$}l$~+p276x9Xp_ ztT&JdsZ?a>k1_gEwsnI{metY?X?^D0ovNi|D-M-V_r>{1xA1esdH-O;4)~@OO>`b# z(GNOQfxQhI_2577t93i58c<)^uP(HtumB$V_O7%AA6t~NK~sw+Fd`e*F(pCU{Sc@@ zzU(2>VYW{S^!wVeHxm;RDHMLMIe9V=cz)4G(;s7~UQSxiM<=~aCJPL0*u-i1ZN(K$ zOyV3=@%^<+)`7D`%+ozWldHGdV0&ok9?s^#)Xu>!LQiCP=+KHbt&|7?RMlMf=nCmF zpN_PoESUdllQlO>vMM*uPL}*ffGQN8nfkwVqL2OtrZP1$y5wW`!#(f;w0Gl*rAbHh zUQe(bwEc&$Y90e(aIqCTUaZ~j&D|g*O1E1>^4YIkfXm3XSHs@ucFteTyDJw;$vCKj z52sx2@v&Zk6N6K4)op zOTp^8k*{i#Ly&~pCeL(W7Axw!rm%@CQ6o? zHc_>&H~h-N2jW97;_BfGuv2zV!UkQZC9QUz1_~I}ntUW4Ieq_uAtg!)b+u+2hgFT$ zh)f)KME8(=$bJ;cRTePEkHUk$-l%YktfuKt`1p-f4*(xg)efZfR)vcdtf9VqAZg8v zvquIytSb15;SrEyqWZC56`Farz&B1G3yIG7tPWAu3R>x+{TpP21T^ z$3O#TULo2)H4FE^2`63_+dW4$&(7vw9F8%`mtCBz`z`QlGM_;02%Z2F_8?(-SgH4tg&I6Hl!B}F^661gXw$)b-YN($a4kHZ*oae|B z+rH3V@aPd|;TkoS+NvtLMPw-{#~MRC23Hntg{>Jnd)-`In%4tQ4YfLSpB_#lfm@u2 z>c$UTwXv7UTRf%?H2W)3hn~zgY6f{W1`examPahm>iqu_tA8S~BAVep9*4i8R8Cjk zqA!kHOM+$WSot8BWRL=K{_^36f#7jKwDpQPXxcI@cX|kNz>JrM`f}*Yj3-abdh0h_ zJ;2P&d>oEH?@KfL*@**~0I|M^>6~p`WncL#DCMD&$@m1)_$W9AYB0Fw6u?%la{c@7 z&-W!(?~t7^ncMoF(dhGflAIiv%eN-VP>O&s*JSrit8|=b zItFc9JH^*o^;L7;#S^3#A1?c=2y!?ns;NN=r6?Fybdg|zGBxFw$>~rkb z+=-l}X(nBf$iBw^Ws0glj+7z3H{#@g_FKWGwZQhhp|OgpY7OM?3AFk!*MVUls`YH- zrc8gFq{S9RsF_@*hPFw2%-zPU3)DN7nQRz2`|A~ZMA?h4JA)Y{=zs{lI(EleDO*Pt zvjB~9^X85OX$sFOz*DIEugAQ3$P;+vgPzX!IUJdl0^&B1!^LG}(w6e9;5XG;?0FPL zhLT9Ie*|9$R#SWaejGsEMS%e@^lyh|!pIPH>* zJm}`yap0gE?TIwr&q94y5RXMY&AUnIfC1c$@~w|{=aMcxe||2HaAU;S1qQe;G}=;s z;q3g&tM)GfPk-75vEAg`P=6g9EI+<>*)m=`^fvG!lTF{%Rr1Wp**P3+>O;iP5>`5W zU%x&;`pG3`YgWPo@(SpRxu;=@Gebk)%eR*am5xst+`~R=~;(u97^>@q2*9~hLLJx$28nXD1;RHDqd?MoD zkVDLyFwZ93*V6s1U_S-hJvi%?!$S=Fed8>$S0F%?n;dLQ0MYvxkQY{(~BqZYh_b_VXAa)9X`EdcrQ$3 z^Uty3aB<5Ak)eDX8=}5Y@N46i9;jN;GtP|l2KV&yX#u=1UH}^*rT?Lu$5aoY;w5-8{>IItqEHrjD0z?Q zy=1!)xqg@X9g$DD0DCAU+4-^HST-^oTjS$-$_KRBB^{15r@M0x*trdoO0Wp8L*y;n}^}Rj{Js$8lX|@p8S)} zDlx(Iw2b24iL8v$|N1&YXXU5_mWR2eWmOg`!ydOq%qr3*x35mYL&I3}tv(G7ut%aS zM$IB(4+kh+vN&_*Mb;qHGc{(nJf^!?&57ufFTk)u$J0;eJ)fLL2xVjAr;vZk128O6 zZL)$t1GVkI@q@V($xoj)bG%h@KX*cW!(*Qg81qS{>C1#3CsJ>A|vf_P4{2P?( zA@(isr5j-gR&!=*>K{FW?h9-_SasAqo;!mU`1(ddvD1-*|5}^2)RlpR5{2*soSuCI zSz%{qCuXJl5N)MzpsJ=;3%ElX(N-6(4?wOxFnaZU_$=}Q65J8+B8g}#m}1FswD&Ez z6t3)bIQ8&Z;z2^Rg`y>`C~O*O1>S$%wKX&d?rQK->@PMF&7()xg)wzxb8f#sgfxlD z`aH~0f0E!5g-acQmiW7%y|LiPQG&dQ_GsUzWDu{4+)$D=?Lw(PGT)ki z!RF{}1?$wyIfWSgH?N4E0Xy}cYs#5u_FyTB16(};UkQ3AT4H~RO@KD!ok}S=I z4ryj)hQG%N;!*@RtCOb81FVzM(s*77f9WXm1CuBT;U2Z^PT;Q}x$|`9Ym-<}n?pdA<{C^{&hFYZS02`6$U#u1?%aL)Eo=aB$t-!u$zG zYuDS$?*)0xQ(rj01%-r|xO{wC43JBB{7AjH zD#U*MGj{DGcgd#^)*?hS;a>mj@=B}f%(WrM`&0At$qsZCuU`EE9=z`> z^6ng`fm51Msie&3yH(!L=s||^XiZPUkk>v zSa$SQzP!27ikzmC`_^H3#>HVH%`fdt)Y{h;zl>5Q1tdv_%B|mGK+xkZ&Ibhr`Q+Nu zW`NsqbI9;@5O=)QSWi!P_l%YYgS`REpj=B|8Qc=HsqUyP51skRK{IZ< z%rXTVT6gH#8cqA4ol>nf?h<}?Xr;wH3#+=!f`I0=QF{6|LN4jyh(K&~ z(OSX(cn&_4In&F5KB{ybEB5QN-zBiHOxayOYDNNZf9u#j>5`F|lyMiG9Lw;tNl*1?-(4mv_*Gpu%A9`cpa{9`XVeez!R;UgZXhQeY6l(C za4cgL=1wG%Sqf}Ogmdse6iD#3?ZQ*^@+k`XPA&;4DYAGeN8s{?FJBUS8^7V4_Q^f5 zBIVL0iady%*x__UlMcS9N;-k|?enaQS1p=fhjU-SX1PT`m|4;@B?OrdU-a}WPSMS8 za9Ey1xCVZ0eq1@W2##~@#iCvB)MYgbTZn<3sIc%>LcMjP9Hd@Vavl{aGrQbO`%oSZ zsS0eh#%5-(E~-6P9x7RIG*x+5$$Exq*!bM+!7VDksP|-9Ke*X1T?$PJNe%mDKT_F7 zgWgKea^mvyb>JCxqg*TXRM*s9m!sT;tlGRxq7xgv_m|jyIh7)vfgnEwH$J;)>EKY$ z#7pWO;1m<986NY%=;?Foh$iVlCqr}KCd_g(u@(zlW*9U}uVXIFr zPOL7yleJvS+B(guC;;d3hJM6eDtFq>%i*-F8#a=cU8QvtpiWGbv};4o8$Iq?1 zAxBL*m;MO$(ejT|HyCJ#0qr7p3#xnSHeO3EwK#wN9h2zOHL=%kwXP@?ps5qO&Jk6r zJNPCfD$2^`^t=jS<6e7r2n+abX#BXZNvtK-2S^W=YvE4lDG$V%t|4{-Ro0s`R3=ZB zDR0>v5*&PH-){J)SO!CPKfY+wb=V6qy2+{Z#>`XJQIaYXAmfliDWnSJ*r*S~FTnsZmn!vxL6Z3EFg=!9aEG zCGXOEdh_z`JPo(jWPH3@-OKvUC7s4`W53XINk`Icnam8A`@Q0PDKk&|T9z>~5HsSs zE545tj&jv6+qq}Y$%b@&8{Cbe_8(c+V#HsN;D2hrf(*3bgwG0x3e<_ zsw-9kqn9pC2La8Fn6bBXr~!xjAfbH`E0y?hEzb+cX_ zU&-|ev15lsA5Vq|hAMu%Fwksb*;yYU!u%~>(W~sasPkW+bf@K^n=8H)f62|s*+6z1 zeY3}(9J$ZAcETb{hVqSzVO;HtEbyo{225{ST5a|n@Ld%t^e3|up)fDY+_%yT3+8}s zVY08y+&aPxey-tH&%7j$D#?Aun_;*@I(=C`_)uBqbv)#sYuYLJ6RO4UEZf;I!Ipad znfH;;%Nuaq-yBIS9FC;mXAoJ_whu-Ure1N^4!d|^w?E6@_e-o}e?!?ZT2G%nC3eki zUoNm^<5jZ>`uOp5-6CRQ&i2KfUBhV9;t6tDB^(B<_E4Q)9a=BNDLMRfD4^S2?s@JD zY{zGG99zZHmnm;@`SLi?UfB7~VOBq!6S>tQLCY$WTE{xQHLHt{Q1JJ=CSkpUsiQQ# zm4>oYf#{)Xv8Tf@L-` zsYkmeX>z zxdocedOur7yR!-Rx!Z391Z;dky~2BcmEn!xq9U1COKW=v2`UnbM1?0==icwAqc0TD z$>G{pa{aNiLS_0g3%q~zWQ9V;a2+phjuB+7ZX_p?@#9aWTQsBu-rTsSnZ>avnsoJT zUjYSwA?q*tSeFA&>lU+ZI~8KroW(oVY`{OeuFzjpOiXoLM_s+0jX&xB6UOgLkxHBE zlvpigI{((0iquDcWIUcyk0xVoO-9T-UA+Wn)YX9U^;o8YjJMbLjJ}P_6R*>J*k4MD zR8$_VJdaQMd))ul5PT%+xK6^|^CwZY|m84P?&8#c#ck4LDE%Ck(7;!6D$g#?RNBXfj*gCv{IZVm*t(1qL>nN<>!Q0X1q4Mr)$>=? zQcvz;_jg*nPu<&aUTsY%TI-wT>rlM!vyKWdb94JBZmeBA6wu`^S3tfm>6`C(J8QuO zP5)!7le)SC%{(n!qIe61)FzkhY_7gXlmtaHmjl!`?cQYW6{p5kd|^Eh?x<&kT;G=@p(!f%~Ya3mwQUbq~_|gfjaSpZH80sY%;z z-m+y+%Nn)R2XOB>qkHyjd{WqrEz28VD#u`C)=c(&L2hogtOQ(VMFtv+W+P|l1z!mW zpdmQqZhyP@*m?A9os-L}dyUC;#?2ULkCd_M-xmD*-jBom%e}hw=Id5(?=yaeDlZf? z(%!+rF!T@+f_hl$akY?W&xO32e6U_>X(Yr|{T`lF$zHC-KOk}{lbVD!70!q|h>~Z# zq_UzSOOQNbN0X6b z-Lm7(*+FfSxVKm08;Vcr*w0!gFOQZn?nf~mA0b}<{{2tYklu*7r_E%v!sJ3b%h15~DxN-3^{CYZE+0p56dCqO^k49bTPSI--yQGj z#l618)L`JXwx%X0hYh)dRo~6&NR^fX7Xw_pWC&8mWaW$(W*^mu>&!b<+Ar71^;Cumi0OI}?UTbuzC*7D zdH1<>T=NnQ!DlSiQOi>BKW_AG%rYulP0s0a3E5zfCqNYbFNe@clI5*%J*bzIQFEEA zv5$8g8whECj5CufUUEHyGYGH!{bx-~eqvSWlmCP|JE;nFskm?9!c-8q@{Nqr!DY%^ zITLI*%_vgN<1%zqMpyMdry_B1Kz+2kFm$s)5^J+sda6bbe`R%bKn8VH{p*fYEA1^W zS#Wl@rq(2d`G#zuce-%F&*uVhQ&2KAXTLSq%fvJV76W^7)UPp|Vl9*rf5UE2HX?J* zE6(PORlizv(gy3^=)mUK)VR2^v4t7i{q8MtZ@uGMEYlsFDXN{_(fAM<%KRKMUmN$5>SZVo8NkQRi|FOr%c#ZGm z9@0e%ecC3q6;*LQORW4} z1^Fz76r!jxSM!cfUwG~wkF!bUuwR|Leae7{21-4RbNcjh_A&utB{;zL1}r+n6JC8t(#TO0SptR;BhNYFB*}7{wyU#;)qt6c8agax;cYX`d# z{1?^GFWxAIRzQ`UX!W*tZ4P=KyH6#{wI81gK_90@m}-OHwug$OSGbMw-{?OJ50?VH z1FwJg!+f%|`^<5os(ddigM?kedme9M1^T0UlW0NQO+I2Y94X^|ih#O_e?~-6d>#a+R2qdyUq@7R~Xj|I+R_n!rMTvL`kRB6WWPlh9I zUb~oyyNf53^AyJ#gZPMN&z|}8^WMp@le{;7TYZb>VXi~k!2{SN7;?9d^H3fs!a$t7 zj-JEDRjt2gHQWwN)+J>Oy*-utF|pqp3C^T zQpZ~rtS@}`&x*v##QP`F8-RY!+cEK=`oz`xPs}pF3o0>72|gwB&pIDeO0BIwWyHr{ zz0bbvmkw04+cAC&mP}wj8wxHE?65-+cJ~@ZH6~%l(Z7Ub`;sx);O7s{{Y#z3$7%pu z#|KM=>tEX}tQTZ%)ifC-5|53d(=mCkT@p0Z>o2>EvyO+8C`o|XWH^Zyxq!Rr0Q2&O z&s*7!(Dl97uQxSfAU=0WWnIQ6Awjx1v~1Mlci8GJew_4v%V?J^D>0=c`98biO?1@v z^cXL@sQ%$^Z!Fs>@TvycdwRPhu1) zrJtUc5Z7@m9e;-}UmCK}5YV8Tf>#LJX|^d8=5&4dyT%_q<09ytejxt;!2eYWU9S>mlfk+-%+XxRt=+tj7xVPjf)&{sr%&@^XFBR6 z5+8zHN5Zl1c$S~Yz&ow^^2`d)*L$^y8|(FxA>MIJ0)y}Yari88RYui1+^p9C+xT^# z9v4>)K9Q`&U^H!v^DM^v4yK0;bW;yfQ&nLJY<7o-m{JAlMw(yF>67(8v7p?Ld7XG7 zR4kCc6&M-G-uZdg_U(t&BKK~?F8x}t`BqqXxOx3f+;Cn2fnD$UwrS1bAX0Hu68;ph zX5;SLeIfKaJ+j}Iej;@h8*fS`?paB;BR1U5&*z9yMX-Qs-Di0I9Cczy5P$5ECp=V+ z2q-vVALNgQ;}@>&D_jI~24(TVX2}bkzyBBqn9s$QpHNoz^YOs|zXE%VYVpf&A2KiB zzajz;Tzb_yE>6xD^_4eiFHe0rwkaG$7GIqPIxj2AZ%bw z?Rgu;SvunD(GF)_RpC#;IM03J&4Z$&g{G&ce*i`76>qE0Gbe&nU z?=w7Y!S25<5h%8{S%bUE-=oeK@l-y0wwo*T{JAHtlW7h;5+|}jlbKa2t zC7wbQ%U9f6AD&3Y=fdL3--q7lil&avPKfRAR!ca2y^SSbxt5)tVH+DwEJTvvm3^I# zgwHb!pw`n+8sor{qse^!V=*;`NlQCRJYhkMhg?{9*^{5pnG4b(Vl6>&hhZPAyhYUx zf`%^$CU9Ey`$Hw@rx@Cwm%RD@O4PGeXn?~8*ljou2sExX<#b-{#T)dM;WFXpQ67Pv z$#&rSd-&;cp#VoghiC0N%`>kEyoI>4?#-N~b_zPU=d zAcXSI4jwG!jB}{Z@EpZUZZ8#;LeZ3}w!+)%YfJt~q?lM$x8>SIi-bS&Hz@gv=U?Gs zoFL!=N4n{iz#Wb$3=Avzm@Hk(!_p(~&oD3ToH@v_>g7tocaI~OzChT+{O2PmvW!hl zH#(XY-quAa1Z(f=?3*6T-!(Ov?~B)C!wdP-h7EVVdUD6zx^?Te;OY00;MCe7^jb6E z1|;}3;;OrCS}k2RjX&Rddfkg&loYP&cy z$0s%8v&F=)tecXh94Gd0xC1S0yl= z=shTYu$q{TZ_oQVNx4w?RYgS*5Q?Q5UT(LL&{0%n+c-R{q;lM6o$C70U>`xNa=OS( z;wOB%x)2=zE{oGs$*i=P;DiD6_VrS)d_a1@C z7Zxb%(Icz$5bOq5u3S-^64F>__1=>`c|9j{0BV3`%M6-f9iC*Hd_lF&7&}SMDu)1e ziGwyQD;sDpV-^IzrAKRoNKek+2kP;fhIX9s)Lu;?IwZdEpjFj4e%yFA&J|N)1v1yN zp$2$q*0C88aJ3OdYL(zX@_sBA{g1nJg4 zAbeyoI+IGXe=1DR0EGS)#*YzdM&ogbiDsgH(Lu1DF~3 z)n?~l&bc+zW7D?<^@}X;bSmh=tWqMpEZQ#eAZ8?x2UOxmviCdm*2XCcI*x#l`3gTt z_gYMi))~zcC%PmPxXT}Y_}L;k$>IC1B&GztEB~qNS5D6#pKpKulN8gT;+-H`hW6`T z{U}H$CkK|9G4Pz6yDP-PT~_8oD%02_q08n|Q0R9SbKKO!R~-ez!g+#n`dH|E3ZjOz ziywt*7FNrF?GgfuuMN_?k>5Ubvl#gnY>F?mX_LV_fZ_2+2^$`b!B06Dm^Sv*XvN01 zT4g|MI4r@Q9K&d?qZ;z#^$P^Sgco-zm;iq;{Ze6FE9SeIh9smEbrBcggZD)luT2Um z)9B@dF{8+}lW^Q$L(U;Cy_I?;WJAR5`$<+vS={RVPPTWA>8BnmISn+2yy8eGz)V(Z zLP@*GEpI^0Qg2)6E3#f1Jdna`WT|~_ukcPu;qM(77GEz#txxNUS(c#l$p;AT(Hv+(Kg2ol69D z{dUeOR--o#HPjT6%@1?Up6}dLzQZOn=e_ZkAD?-TM6o;y8$&H)Td!clkW$!J+RMk8 zkLqxiAEPY$1UTW=ITU8A*%`YXC6?8L;T+BpM{p-%rx*dvJP zLjS7FD!@#gt0^6_Pdviw@Ul?$Gs&d;q>k#3I>+ED-~VCnJ^Zom!}np@3!x~YGE$i( zGoztGMv<8n*(=#wlTt}CGE3Q8_AVlX5VAw&m1N6&j*t7kzt8u1{(|4@c|BhD>%Pm) zb$zb)ILC1w=W!y8Q4ovxJp{rM8zPWQ^EMtp364xIZ*=y#!Kb7Km^EyI8G4~8xpM6k z=m5X*!-Qz`vE#>IVEJ8pKXLy9UP8iem=&%XUG14d&W0!3iq(TN74JSudg9Kq7rew=V>fwsR;OCtRJPf z^pvQOkmooO)ff=^6Y}#@(4(qq>r)6p%*Q7o!E@T-*RAkxe+wr{ zY~3OtTdk3ItM5sao>ql;1<{|}{YHk0s%t|q2FPm^*qMH`x*!p_(4q>AkL~nn*NcjL zsf^6bf@8I#srM3>m)!>Pfy>3(yZET6tA~8e`+plKOR)t_EIcTG2(Ib?|Aarddh+DSC+JG4 zd7=IDr7=ZD$=@Nyx2rIlhQNjpotTS36rUZP>(x9CHE&ZEtpRqxU0a|uKkW=Vn+azE zJDY8@ zfmnKUWQ4C34DruM*PqU!;3>m3{*7<%e~%EibtBC2GZF^$Jl(l9&e=yV&KnbvG*ZuJ z&HZXOnE7~)cw?pEbO;0_4%@0Fs~--HmC@GjW(%|$Q@VEtP(sx(IA9F+y}iAX)$HM+ zGrP^}LIs|kHA7+YoCWFW)*lv$*(&R4ld!_i#3pY>q`W3CWKYdPNsi!IX}6Ia?>3*Z zq`53G+o;N_3{CAh5mr{#7XbmZSADWw=YRX$TCZRHie`J-JAJHC^#aDy%F%XQqS*!bBV>qb>DT*)C(Qft zi7M;10h^-HUfw@|W@I7=RL@{(zaSH;-eD%}?Cgy15HXQAje@v>quvv>0d$?#(Vr%Ec*{td?9L$!1*<+@X4U&=mr) zMUGa~*vN>%_A&7EhQk>?T>y2^NFWPX6+Lb@={ZdGEt3>rv!2dfzjEb=txViQSTtPK z1dHy1mfSYE?0*)P>=J>P@*Lmytj`bl3Ss|kNK=q0x=DZR*v#LTIB@VZl`F(EfWiaw zsDaYHkI&EH;Y&=!VtfW%$%gW4UUeBP)S2rw?($M*&H)N(LqwMdFN{W(L-h(kfs?-T8=FE=sf2xHVKKW7@&-o(MZ z4LWC@u5y$$7c1*|Vr2CBV{tr^ont^2@qwxv8s^>Ar>^Nyq~X)bhY5a~4Nd4!-A*72 zvFV7_4Q?BnAN?~k+MK83iqsn7Aa2Kx*`djf-{t%3j`Mn-9`D62BW?LKTY#q#e$aMb zy)hr+0j5?*+^cJAeKGC^vH`SxYr#>L0_~1fm+1tGAY2Zl?I?U0p)KYye$66j9eq*$ zhMxNq7W(+SN*GCsu0tV(RplEWRn8bwq)Dyk^*H>2oN6z$3P$~QbDl(OAuwi&_~`cP zvNI9CPJWjw8U1+kP0Gbe2A%FwPhF{s5q}12#b4K?h^xeRVU&K2U^rDF!Fdv}hIhC$ zqlwUxD4VcFhj7ohk1;CESloHc_Ugt`5n}gWJ?#+ymKD; zm`c0`Aeo+a{`yk{rD4~d*jW%zvcZ}l#gs~GLGeUHM5Hp}lJfp_>$nGG&_0od2NG8o z5Q&wS1TpaZ`kqlf5v~8wc4wMYPrYu8X(*RYk?=1PQ7v@b4<;FpPEklai=w&0hco8p zNt^DSMc(=XEE~G z6k9DKmiISay?2MVbh#F4dWG%zNM0o-yfJ{>VYkNozelOs|+GVV(|ojG@X)1 zT;H6YCIDK?j3|L*LtU67`g6%)!s3M71?BH1$c(8Z@IIdwp1crUP~dV=clRM1ATaMB z#B9HU^&zrCUS7YES%M>c=*LEZeIcWFyi(yRZJ%)#3-u9{mqt>f>dM*c*(9j80Ljfu zZL|JOQ_c1Z&Mp&H_9a!C)H>W1OLQZ^s=;);(B4zlj01#~(jg47Quyd7NEx4VZGt2s)6lj6Fc5Jh*vlASMD{!UQRLPSFOyIsMjG@YauQVz zlr;dqAe?`@#`oGZ)D9t0q42+J{19wa;&5}sBw>f zf-WQNaN3KhT`xP00jMv5&&2&(q6GF{u#p4ZHTQR0K)22}G<#%5gbrF#@>dVA#Sn|QEmXX5d{ zkebj_yE+N%J@TRQ+t=o1gI}};6dCw6oNm;}CiCxCpIyJI6j0pR$B_z`cwbH06i7qJ zun`!6#Oo#?TW#+C6-|*rL_;tMV=YN|^DB&k7JS()>gTvtjCic3Zzx>&cLUK0X49Y8 zs}S~QM*{Ag!NstY_;_gt8@@Usw}sol+J^~RK0a0f;*3xZYtgyrk#P%{wo1M-_4CO{ z$rO|F)Bib32_Rw&R0QIctNbwxQB?N5+nwJ8{|xDqVn< z=nw9=-6W{XWZtZ%!70Xc!or*MCvL1S1sU0HTc4P%8|1z}yM`?!3SBUMH*Va>^bNYQ zzVc*b%fSK_EJf#zXFgPK7B8Y%w*ZI~UsEx%;k(M-6!rK2$lfRH627Pp7k&K3M_bNG z{Vyo}6W|Qct8Hn|r_kGHtmVXhjyM_!TYP-P&_4EOhcZT48f5zNjsE*YWY3%aKlZ1{ zARg`GKwlH~?AgOsc$CcO=s$~d1yI6gT-9}+BA2A3E~0a~7Lu6fs#a^Nw)u5Ii|>a} zPYVKFdp{%Nbm78w$juUFuf)wc(|3d3!*#e8Gq7}YB5^H2n`dDm3jWwaD=VvOY10@3 z*LbSV7S>(~5+XjH<%BtW@${d)S_MDl9Bkc_C%XnRklhoZB}n)2I+rQZk$c3Xr(emj zXlH>V=YOD%Yu(h=HauV2&xvQRzWC1`uGufmS>jBAg=r{8u#xd+&@!W4xCP2;8XAOB z%rO)b2thJ0FYkQJ@*`~hq4s|^_eUw^0pUZq_ZbFNPpW2KW8BNB#5RI-BSlQaOYY4! z4<0rrW-fxm-c{m$9p$}`CG$XAQFTMGAE9N-6MX+aE24yofBIwq1tb6>dy*>gSKLWh zJse!Q24A-D?euy~ryahi>t4I|bAbUt1d(xdc4>eBj*%5NTs;8A6WQ3d@Z@Pr?LvpT z>>|ij3eN6m&L!d~V=sH8$wX{3a6lI@#tqVTGM0ZXx?bh&9o{S&;93xCm|O}-&~gQr zRes`CLHxAC79yV^?3zI*#_)vY6e8tXr~Mk2L&fYbkw#dewyW0>i<mCqPb5W*%;?cvo=F%tsRUHP_`Ahybq$Vs-%`=29N;kt@Zn;G%CiWKR$Z{L20 zBS#P-Ng0@R(xWqYjk8jn~9K(jLb*+f8CBL%+`5(NtNpxS*kV}=&J2Y%QbFbZWb+$Q#-W#R=C>b3U``$fuTy^buAb5S>O-?Z#2BhPpH}^dFFNE(dWvGT})@65KY=!^K5_ zNj0E^$l2b|*qD4PjlJKU{+#%NvbR*w%a@-Q7M$)2Y$oeluUwLa__I(vN)C8kIIEO- zJ9MKt2B7Xaf>APEHrGi%NmeL9#F`dD(2huw#+}E~F9?*O7R1M_OYqRw`uFO|%gOC? zG`|*%_z$DeedANf4juUS;hXRb06seRor~Kl-dZ(-;f(LaUF9|M<@-Hw#g)IlrP8>@ z4YWgDQdE?oafzU@-WR=Y)Zgij@HUX=|I?k#0xeC2#!tBB{t4|2>KW zqs2ipdU~P?tBcSFIABH+ z;mu$Xel0Npi}+sYGW-#}=?2{pZ86o%HECoq=*H?>3~C{W{3f0VAaQUplx+9Tf0v{K zfi!VlP!yQ_4kHbR3Mkt5ul+iM4P2+@TZN&a49$xI=B*(|+$IQ`tvD<<@cBUyL@Et% z(JQCHI8ZjVvI;`1Op!l)d)LM|mwH_CaX(gLZUTS%IJo4Moa=ma}ILUZd+2eemi5 zfhS562NuxZ1x(;p#2@W$9`KAYqUSh^^>BUW7L_rA+1hsaKDg2R4|H3rhfyM8wp}6j zS`Tcoq_K)2sq-wbFdo^O7rv{(DJ+x?`F)bfqQkeL2 zErly!EjLpxOIsy#C`?qub|u5E_<*d#3Gy?dx=(8{lBf1fhg#-}cW~yIn_seMFRQni zZgoc3#@mG}Pm7p$vKNMsc^!S=fm7#~WcYI|cxq^=;ivuNS`DdxEl{Y}^9U=wWbkCH z=jD<4;cA{EWO`dz%4Es4dA)CvMmsO+?X_xmSrj}==k;#HO@Iflz5h;NTV_J0nupUV zx#ye7ls|la{-l+j@s3KK;fxFQSvoR3C9pp<~9%ruev93x34{%fY(G9{s;Ak4`VM`zo(L1zS85l=I#u&DZ{~ znZBExWV6i^q?ld%o{@3Nm@yRgQ>M*)N{duSZ7vg>N&_P0CfOqOd@?-VUDy^p-v%y` zB0`HNgD|Sl8_kSgYu|j7G*bLGTu;#!R&lCqNX9hij%&{tg{&497pp%iSS^MAo+ZLnw5e=9O0McOxkVjNW&o&cwLs+Ag@l3+`_T2B3x#@>h}%NCMNg3i zlH_*?s3+~4nwy`tg-Cjqq#3f6xgg}kiXs8Uir)D3d%tdZQZ8-b#C(i}!qU7X1O-zY zc#j`vDSNC`L{7}GK!fDPRmcq1pmH71G{C*L#;ZEOtWD{W*xW}Z@>VvIi^xw`rx@PJ zo>zSMEThL;918yQ+U-pL?dZ3_tTP%=P*uxa7Ao$VgW;v$BYV+(x!|^e%Nm~mJe?Dk zo@l$Q*kkv22Yr)8M^<%KNkW2YQ?0a@fc(>4f0=dm7pLpwRBDUGt=Ma7h9dp^KKU23 zPk6{xU-tjgtJKM>o_^>oyZrb`y{TK=o2fS>%Q!AB4&2|Y9+!6d;5XJmH7{a}Jam6g z1Oaw8=*Foz0th+?s)VCsw<8P9F=sPth3N2~Cg5P8DoRR9EWj%(yS71F<%FemamYA2 z!dgXELRUZ~HgI=!Ei`As$HDk9Um{G0Xy?z?l*|M$q(93{NtQ~VYi2&v{25rErJ~mNDzgs#; zk;(*6)0V2uFX1;zr}yc!O<^0&gqAv}v{*}m4VyDePfveouU>X;?qv++Bxs+++hX!g zr*bp)-nq(p~!8^lgct*t{MLLrNi zQIeiI_2D9{ghCQ<)4UDIL}^^8*Ug~A12IhH+DPj?q8||RMt%|>ADk8h1<#UlYk}t+ znEy)<+9&%j5Vg!@El@{@2Ok2x!0of22sR&(~td+jyvw55^vYU%Ce&9&-&f%ds-^pg%Es(iGtg%7yp6e+Eg zpk&1WN<{lK8`APA=;bs|e{=ZODmZKXdZ4OeJk|C_cbZS3o7K|%$B*YaZNtLCn4(B@ zdISt>X_@jeFi^(ECL6}v$>antyFB69PSsO9wdkVswH4k>uiw%44d~mJ_ z-Qom0j+R4V{m^2XV&w3g)lwlUH3a7q-71 zE{TA4R1I931?A?-d=FfNajgo{ci)P`WuZ5dN)s-tdu1<%739?nsd)|BWiH`i|29Xh z-aMTzY(MsLJeyU-6pBBoUn0dj=Ul+-&a`LE)v-e~-Nt`&p;mWQzoUm(%z-7>S-x9I z*9B&zFWW|y8zYvjw1u4?S~$Q-GQNuIi7fb}c`H}*z=B_(Nq@#>VTNj*PP;JkF@ys&)>wg*K{C-F4~HM(sP2QmC*&>iY=4J9NIWKJ$Sjf z<$GKw#M^T$!z>TdBp^iin$6tY)MWAI3Wjfe2@`6t_q;tMXW=NK?EMU4lLVS#QT_pL zm<_B(sU96YkrZ9z!{ga0(}^0SI8darJm3>zXLYJhrxjdQR1_+HW*-&*IM?zb4SEje zillDy0QqIb3Z%|v0W@jY8BchgIVNTL?5a+?u#M*L%r1T0knCS0Zxh@w&cD8KuD{`5 zn4-)n(m@3oap8i=3xE?WptQ~LsEQVu@R>h-lxE49ko_8Pv;~(a=b!_6Hvwmg&tJtT z>g>_KxL}c;ZqSBJm9$t=A&xN%3q6n4t>rH>4x<8F#>wFo}FviIixu>Gh_F6EGg}09ph3KrNYwbxQTXzAbLBxlO+rCw714r)h8z> zhm6&XiwZh zf@TW+rarpTjmfZg-tL$c<=By9o79PhzUBg4(aszdZ^@XrxJ%!5p08Ndh(8=+|4PU@ z5*-2gskt8YrE9CMQnL_;7}KDKYf2?uFel9G%7o{<`x07*(+6>>3oHx8UFW2_e#f5o z3XK0_*7BG6@6gbhg$+(uI#D8jKZss4q18wM^Po|+4@6s1_oajGHy6W`$ylCkk|s<0^K5~zI@Ldo<}>< z6`~}V8ka!VkXl|9HTN2vT>-QgT)MV00eVx_+k}037di#Y(dL~~eCuPx&Qk&c&Z`F( zPdfhAy50~3K@3-Bq4188texq{h1j{uT(p-wDi~ zzPfWA?F?>jzK4SC&=;FuC*p!g2qJ@VNHvOGvQb{Z_45Ncs+Q=iiOLV`JbM`I-bwcq zdeWqYE{KDg^VJ+tpNU8W4G|}_KVMfogDtz^+70Fk!AC>c@{~Q!v3$4_ZKtk%PAzr7 zI zyvX*R=}zm?Kw_NbWC$%Hh1OOh&NkPHV&h-EEr%^zCpyv0^Aqs`VVDTX3DfS=6Ga1} z_R`6QK8~I@C?qgO9w`ZD6Jj&WZccA8K-*5m?9u)nc=}DUa6`Z3O~eI@=6hT-^*(IK zzdiVPd9KrX3Xl&bRGwm58mf;l=M3nyAwXmMUEl4{2beS6M?hBQZEbCgq}8e5(h4oL zRs(IZr~qX~P@SKF-1-@o>L+|S0fBcqen}FOK7i;~P(92`(iSGTtQ3PDEv>Tv_K#@*#0WP|M&0!>_ zR+<-rWWiDrQUqNcS+i{I9V)$}g*o_$2JTRI7-zY_bZ*@4gbgaZ2F1z^%Ej|zNQ314 z2;0FID8Dl3fzY#ZK!LV1iT)Rh{?6AlC(vQ~`2#97a-=n!<&aj)T;HQ}@ ziZ0g2NmN%&O-+^5=sk99*^vBmvpQ1n*y$a!cdt{N0d-SsV=~y_RnDm(D9KL*M?{Qk zL}q1;)L-xaOIc~#qhEX|mpK>bdMMv>C&!EJ--y1`wZiP+=d*=|OpEl^`}^B8{f13_BA=S7f`wrV?=J;dBWH23CYw&FUZaw)-DaylI&!f+8>vf;k zZssMZ6tS~}l#AtreUn*n$nC`oZK5-k=(O$@)Z#N3e?d~oMQuSSWep+iQ~NQt8cx;Z z^kTx31JS!7YI0rCji?HA^e}X&^IE0M$eeB27?oX^lFdWl1z}>%E=q=$1{qe?mIJLe z^JBdESj5tOD{BV-DYE(I;&d0h?h50mTyiBtq`b`hK5-Oz%6u8FV+* z@9iTwjt3}8WE2O@zEhwuOI|9rF8N!TQ!H?$Rk5BB=yvH6y%gE85y*C3-bkj0V)(;O zg-Y#hDYnl<JrsDOA(1XEYC63`lhLs&;2;s)Bo4TXXvbh`g|Cfg&R~}@~ zuOR!jpuIB>!Gp*FJNF+Kx?4r>H!cn=Ahon!Jdh&!D+)Ra)5Sn}-yuq$bI)YHp1gG0 ze8F^le=2isiloKJumQ`^!QBX1BjPzq9Z$D@S`yKK7`2w2f6&%P=*6lw8e{u?oJ7ta zN>(fSx8F~4)r9kUG%TxiPY5$ruDa`pQ;Q`qT}xN-ziPZ)T~-IjD@|z}17|Bfii*s@ z9vEs`Q=~&hl$*$@i7?szs6rmp4k9$pZy{BmN$zYzb!T>e;#Lb%n!Ez7yFxCRd7@l@ zYFoCzw$#ML7Xa-UJke8lagQFz3eu{nTBD*3;5{#(;1g|5nwMV*lzg#0DTPBFM~x$9I>&sveQ+P zyqnMcH3<~?&N)o#@iq3iWzk|WC!@`?4w(9s3 zVPKk}kFlo>viIfzt2?=~Zikx+ANYRfuu;>vx1S_(`TY5Nrp2f>ArHau2aR;SJHyKg zkgg!D*1Mz_uJl!REJ4#pN$N{89WVoye$m^BoU^X`CWddW_%EVg&nEDn?NiY83{NK` z&CHH`q~IheG?B=lj5WCUK>nteVfP31DivQgp0Z4b6I8j&7m$>7a2(4KLB#9jsp%aq$w^;}*~PTw(pOiRf1DPm&Q(;mKA06=ApKO~(j zX*zIeyoR-J4`RKF!Jj|(MODKaVqJZAk*a?n*JLqc%-E#fsw)e@nGBv6WadbGVu$z8 z)BE~-28#67tZk7kzxB@t(SvWK`ynp^F^cjpsGRG$^q?5Y%CnJN)y=Zmd`Z1ihplL= zQgo~DtT3;B)Y_#|axZ(UT#y zkK&RB+(c^mpG=p%2JL%j8VFxcXa0u>`r3PJPhz3x$3d{m87{&k;_TncM~P6BB+--d zEV=kT1Z?+BuKk!@1WHA;ZN_&mFzIQ;`4Za%f+Rz4DGX>nrS+4n)Nd0vilUU+EZGor zW)MMVTkRWQPujc#q()-eZ!>*k($3^X^N05JzL4)}Eld#B{>grv*!UbK59GR}=pOb< zY|9GuE>r6{>NnV0e`hwtOd1nIIcR22NJtt=OCR2lLXP`#ANNB%v& zwEwc#ETDnV$oJ4PFwkZr53-NG;U4cZTe&?yKR#C z#A!CEPiD)fjT>0H`u|B}B)OeeC=I&47Kf;nIwRLLu5iogS7_dTvJ0641|?9et=@>Y zPuZ$&B~*CDlh1BRf{Kc&)8+NAp5p7)k(^8aaRES(1ecxrD#hU^b4Bct6MD(R+^ugO zC>TaQA**$nH;QBSYb~%H7qLI@ zKx@TeoYJOFHI#_Vrj=QyRq*xP5nuMQOr1TN!@fTDt|T`>02H?m>=>!&uu8rYEwCIy zNgm|$8R%~B#^mecjca2@fOa*!$<^mKLJBE6*iW>pTD0Afi#%vH*ra%Cp!C8a);&Ag zJM=)+_W52uK|mY6@stq?Rw>ElbORJbstvWd9-S53ot$Cyc~ax93t?Z#%t6VoEI{