├── .prettierrc.yml ├── modules ├── nf-core │ ├── fastqc │ │ ├── tests │ │ │ ├── tags.yml │ │ │ ├── main.nf.test │ │ │ └── main.nf.test.snap │ │ ├── environment.yml │ │ ├── meta.yml │ │ └── main.nf │ └── multiqc │ │ ├── tests │ │ ├── tags.yml │ │ ├── nextflow.config │ │ ├── main.nf.test.snap │ │ └── main.nf.test │ │ ├── environment.yml │ │ ├── main.nf │ │ └── meta.yml └── local │ ├── dragen_buildhashtable.nf │ └── dragen.nf ├── .gitignore ├── docs ├── images │ ├── tower_ce_enable_dragen.png │ ├── tower_pipeline_secrets.png │ ├── tower_secrets_dragen_password.png │ └── tower_secrets_dragen_username.png └── usage.md ├── .prettierignore ├── subworkflows ├── nf-core │ ├── utils_nfcore_pipeline │ │ ├── tests │ │ │ ├── tags.yml │ │ │ ├── nextflow.config │ │ │ ├── main.workflow.nf.test.snap │ │ │ ├── main.workflow.nf.test │ │ │ ├── main.function.nf.test │ │ │ └── main.function.nf.test.snap │ │ ├── meta.yml │ │ └── main.nf │ ├── utils_nextflow_pipeline │ │ ├── tests │ │ │ ├── tags.yml │ │ │ ├── nextflow.config │ │ │ ├── main.function.nf.test.snap │ │ │ ├── main.function.nf.test │ │ │ └── main.workflow.nf.test │ │ ├── meta.yml │ │ └── main.nf │ └── utils_nfschema_plugin │ │ ├── tests │ │ ├── nextflow.config │ │ ├── main.nf.test │ │ └── nextflow_schema.json │ │ ├── meta.yml │ │ └── main.nf └── local │ └── utils_nfcore_dragen_pipeline │ └── main.nf ├── .gitattributes ├── tower.yml ├── .github ├── .dockstore.yml ├── ISSUE_TEMPLATE │ ├── feature_request.yml │ └── bug_report.yml ├── PULL_REQUEST_TEMPLATE.md └── CONTRIBUTING.md ├── assets ├── samplesheet.csv ├── multiqc_config.yml └── schema_input.json ├── .pre-commit-config.yaml ├── conf ├── igenomes_ignored.config ├── test_full.config ├── test.config ├── base.config └── modules.config ├── tests └── data │ └── samplesheets │ └── samplesheet_test_illumina_amplicon.csv ├── CHANGELOG.md ├── .editorconfig ├── modules.json ├── .nf-core.yml ├── workflows └── dragen.nf ├── README.md ├── main.nf ├── nextflow.config ├── nextflow_schema.json └── LICENSE /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | printWidth: 120 2 | -------------------------------------------------------------------------------- /modules/nf-core/fastqc/tests/tags.yml: -------------------------------------------------------------------------------- 1 | fastqc: 2 | - modules/nf-core/fastqc/** 3 | -------------------------------------------------------------------------------- /modules/nf-core/multiqc/tests/tags.yml: -------------------------------------------------------------------------------- 1 | multiqc: 2 | - modules/nf-core/multiqc/** 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .nextflow* 2 | work/ 3 | data/ 4 | results/ 5 | .DS_Store 6 | testing/ 7 | testing* 8 | *.pyc 9 | null/ 10 | -------------------------------------------------------------------------------- /docs/images/tower_ce_enable_dragen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seqeralabs/nf-dragen/HEAD/docs/images/tower_ce_enable_dragen.png -------------------------------------------------------------------------------- /docs/images/tower_pipeline_secrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seqeralabs/nf-dragen/HEAD/docs/images/tower_pipeline_secrets.png -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | 2 | .nextflow* 3 | work/ 4 | data/ 5 | results/ 6 | .DS_Store 7 | testing/ 8 | testing* 9 | *.pyc 10 | bin/ 11 | -------------------------------------------------------------------------------- /modules/nf-core/multiqc/tests/nextflow.config: -------------------------------------------------------------------------------- 1 | process { 2 | withName: 'MULTIQC' { 3 | ext.prefix = null 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /modules/nf-core/fastqc/environment.yml: -------------------------------------------------------------------------------- 1 | channels: 2 | - conda-forge 3 | - bioconda 4 | dependencies: 5 | - bioconda::fastqc=0.12.1 6 | -------------------------------------------------------------------------------- /modules/nf-core/multiqc/environment.yml: -------------------------------------------------------------------------------- 1 | channels: 2 | - conda-forge 3 | - bioconda 4 | dependencies: 5 | - bioconda::multiqc=1.25.1 6 | -------------------------------------------------------------------------------- /docs/images/tower_secrets_dragen_password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seqeralabs/nf-dragen/HEAD/docs/images/tower_secrets_dragen_password.png -------------------------------------------------------------------------------- /docs/images/tower_secrets_dragen_username.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seqeralabs/nf-dragen/HEAD/docs/images/tower_secrets_dragen_username.png -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml: -------------------------------------------------------------------------------- 1 | subworkflows/utils_nfcore_pipeline: 2 | - subworkflows/nf-core/utils_nfcore_pipeline/** 3 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml: -------------------------------------------------------------------------------- 1 | subworkflows/utils_nextflow_pipeline: 2 | - subworkflows/nf-core/utils_nextflow_pipeline/** 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.config linguist-language=nextflow 2 | *.nf.test linguist-language=nextflow 3 | modules/nf-core/** linguist-generated 4 | subworkflows/nf-core/** linguist-generated 5 | -------------------------------------------------------------------------------- /tower.yml: -------------------------------------------------------------------------------- 1 | reports: 2 | multiqc_report.html: 3 | display: "MultiQC HTML report" 4 | samplesheet.csv: 5 | display: "Auto-created samplesheet with collated metadata and FASTQ paths" 6 | -------------------------------------------------------------------------------- /.github/.dockstore.yml: -------------------------------------------------------------------------------- 1 | # Dockstore config version, not pipeline version 2 | version: 1.2 3 | workflows: 4 | - subclass: nfl 5 | primaryDescriptorPath: /nextflow.config 6 | publish: True 7 | -------------------------------------------------------------------------------- /assets/samplesheet.csv: -------------------------------------------------------------------------------- 1 | sample,fastq_1,fastq_2 2 | SAMPLE_PAIRED_END,/path/to/fastq/files/AEG588A1_S1_L002_R1_001.fastq.gz,/path/to/fastq/files/AEG588A1_S1_L002_R2_001.fastq.gz 3 | SAMPLE_SINGLE_END,/path/to/fastq/files/AEG588A4_S4_L003_R1_001.fastq.gz, 4 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "nf-schema@2.1.0" 3 | } 4 | 5 | validation { 6 | parametersSchema = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" 7 | monochromeLogs = true 8 | } -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config: -------------------------------------------------------------------------------- 1 | manifest { 2 | name = 'nextflow_workflow' 3 | author = """nf-core""" 4 | homePage = 'https://127.0.0.1' 5 | description = """Dummy pipeline""" 6 | nextflowVersion = '!>=23.04.0' 7 | version = '9.9.9' 8 | doi = 'https://doi.org/10.5281/zenodo.5070524' 9 | } 10 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config: -------------------------------------------------------------------------------- 1 | manifest { 2 | name = 'nextflow_workflow' 3 | author = """nf-core""" 4 | homePage = 'https://127.0.0.1' 5 | description = """Dummy pipeline""" 6 | nextflowVersion = '!>=23.04.0' 7 | version = '9.9.9' 8 | doi = 'https://doi.org/10.5281/zenodo.5070524' 9 | } 10 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/mirrors-prettier 3 | rev: "v3.1.0" 4 | hooks: 5 | - id: prettier 6 | additional_dependencies: 7 | - prettier@3.2.5 8 | 9 | - repo: https://github.com/editorconfig-checker/editorconfig-checker.python 10 | rev: "3.0.3" 11 | hooks: 12 | - id: editorconfig-checker 13 | alias: ec 14 | -------------------------------------------------------------------------------- /conf/igenomes_ignored.config: -------------------------------------------------------------------------------- 1 | /* 2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 | Nextflow config file for iGenomes paths 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | Empty genomes dictionary to use when igenomes is ignored. 6 | ---------------------------------------------------------------------------------------- 7 | */ 8 | 9 | params.genomes = [:] 10 | -------------------------------------------------------------------------------- /assets/multiqc_config.yml: -------------------------------------------------------------------------------- 1 | report_comment: > 2 | This report has been generated by the seqeralabs/dragen 3 | analysis pipeline. 4 | report_section_order: 5 | "seqeralabs-dragen-methods-description": 6 | order: -1000 7 | software_versions: 8 | order: -1001 9 | "seqeralabs-nf-dragen-summary": 10 | order: -1002 11 | 12 | export_plots: true 13 | 14 | disable_version_detection: true 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest an idea for the seqeralabs/nf-dragen pipeline 3 | labels: enhancement 4 | body: 5 | - type: textarea 6 | id: description 7 | attributes: 8 | label: Description of feature 9 | description: Please describe your suggestion for a new feature. It might help to describe a problem or use case, plus any alternatives that you have considered. 10 | validations: 11 | required: true 12 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Should run without failures": { 3 | "content": [ 4 | { 5 | "0": [ 6 | true 7 | ], 8 | "valid_config": [ 9 | true 10 | ] 11 | } 12 | ], 13 | "meta": { 14 | "nf-test": "0.8.4", 15 | "nextflow": "23.10.1" 16 | }, 17 | "timestamp": "2024-02-28T12:03:25.726491" 18 | } 19 | } -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Test Function getWorkflowVersion": { 3 | "content": [ 4 | "v9.9.9" 5 | ], 6 | "meta": { 7 | "nf-test": "0.8.4", 8 | "nextflow": "23.10.1" 9 | }, 10 | "timestamp": "2024-02-28T12:02:05.308243" 11 | }, 12 | "Test Function checkCondaChannels": { 13 | "content": null, 14 | "meta": { 15 | "nf-test": "0.8.4", 16 | "nextflow": "23.10.1" 17 | }, 18 | "timestamp": "2024-02-28T12:02:12.425833" 19 | } 20 | } -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfcore_pipeline/meta.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json 2 | name: "UTILS_NFCORE_PIPELINE" 3 | description: Subworkflow with utility functions specific to the nf-core pipeline template 4 | keywords: 5 | - utility 6 | - pipeline 7 | - initialise 8 | - version 9 | components: [] 10 | input: 11 | - nextflow_cli_args: 12 | type: list 13 | description: | 14 | Nextflow CLI positional arguments 15 | output: 16 | - success: 17 | type: boolean 18 | description: | 19 | Dummy output to indicate success 20 | authors: 21 | - "@adamrtalbot" 22 | maintainers: 23 | - "@adamrtalbot" 24 | - "@maxulysse" 25 | -------------------------------------------------------------------------------- /tests/data/samplesheets/samplesheet_test_illumina_amplicon.csv: -------------------------------------------------------------------------------- 1 | sample,fastq_1,fastq_2 2 | SAMPLE1_PE,https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/illumina/amplicon/sample1_R1.fastq.gz,https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/illumina/amplicon/sample1_R2.fastq.gz 3 | SAMPLE2_PE,https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/illumina/amplicon/sample2_R1.fastq.gz,https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/illumina/amplicon/sample2_R2.fastq.gz 4 | SAMPLE3_SE,https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/illumina/amplicon/sample1_R1.fastq.gz, 5 | SAMPLE3_SE,https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/illumina/amplicon/sample2_R1.fastq.gz, 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # seqeralabs/nf-dragen: Changelog 2 | 3 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) 4 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 5 | 6 | ## v1.0dev - [date] 7 | 8 | Initial release of seqeralabs/nf-dragen, created with the [nf-core](https://nf-co.re/) template. 9 | 10 | ### `Added` 11 | 12 | - (10)[https://github.com/seqeralabs/nf-dragen/pull/10] - Use nf-core template v3.1.1 13 | 14 | ### `Fixed` 15 | 16 | - Fixed error `Access to 'FASTQC.out' is undefined since the workflow 'FASTQC' has not been invoked before accessing the output attribute` when `-skip_fastqc` enabled by adjusting channel generation 17 | 18 | ### `Dependencies` 19 | 20 | ### `Deprecated` 21 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test: -------------------------------------------------------------------------------- 1 | nextflow_workflow { 2 | 3 | name "Test Workflow UTILS_NFCORE_PIPELINE" 4 | script "../main.nf" 5 | config "subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config" 6 | workflow "UTILS_NFCORE_PIPELINE" 7 | tag "subworkflows" 8 | tag "subworkflows_nfcore" 9 | tag "utils_nfcore_pipeline" 10 | tag "subworkflows/utils_nfcore_pipeline" 11 | 12 | test("Should run without failures") { 13 | 14 | when { 15 | workflow { 16 | """ 17 | input[0] = [] 18 | """ 19 | } 20 | } 21 | 22 | then { 23 | assertAll( 24 | { assert workflow.success }, 25 | { assert snapshot(workflow.out).match() } 26 | ) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /conf/test_full.config: -------------------------------------------------------------------------------- 1 | /* 2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 | Nextflow config file for running full-size tests 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | Defines input files and everything required to run a full size pipeline test. 6 | 7 | Use as follows: 8 | nextflow run seqeralabs/nf-dragen -profile test_full, --outdir 9 | 10 | ---------------------------------------------------------------------------------------- 11 | */ 12 | 13 | params { 14 | config_profile_name = 'Full test profile' 15 | config_profile_description = 'Full test dataset to check pipeline function' 16 | 17 | // Input data 18 | input = "${projectDir}/tests/data/samplesheets/samplesheet_test_illumina_amplicon.csv" 19 | 20 | // Genome references 21 | genome = 'R64-1-1' 22 | } 23 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | indent_size = 4 9 | indent_style = space 10 | 11 | [*.{md,yml,yaml,html,css,scss,js}] 12 | indent_size = 2 13 | 14 | # These files are edited and tested upstream in nf-core/modules 15 | [/modules/nf-core/**] 16 | charset = unset 17 | end_of_line = unset 18 | insert_final_newline = unset 19 | trim_trailing_whitespace = unset 20 | indent_style = unset 21 | [/subworkflows/nf-core/**] 22 | charset = unset 23 | end_of_line = unset 24 | insert_final_newline = unset 25 | trim_trailing_whitespace = unset 26 | indent_style = unset 27 | 28 | # ignore Readme 29 | [README.md] 30 | indent_style = unset 31 | 32 | # ignore python and markdown 33 | [*.{py,md}] 34 | indent_style = unset 35 | 36 | # ignore ro-crate metadata files 37 | [**/ro-crate-metadata.json] 38 | insert_final_newline = unset 39 | 40 | [LICENSE.txt] 41 | indent_style = unset 42 | trim_trailing_whitespace = unset 43 | -------------------------------------------------------------------------------- /conf/test.config: -------------------------------------------------------------------------------- 1 | /* 2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 | Nextflow config file for running minimal tests 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | Defines input files and everything required to run a fast and simple pipeline test. 6 | 7 | Use as follows: 8 | nextflow run seqeralabs/nf-dragen -profile test, --outdir 9 | 10 | ---------------------------------------------------------------------------------------- 11 | */ 12 | 13 | process { 14 | resourceLimits = [ 15 | cpus: 8, 16 | memory: '96.GB', 17 | time: '4.h' 18 | ] 19 | } 20 | 21 | params { 22 | config_profile_name = 'Test profile' 23 | config_profile_description = 'Minimal test dataset to check pipeline function' 24 | 25 | // Input data 26 | input = "${projectDir}/tests/data/samplesheets/samplesheet_test_illumina_amplicon.csv" 27 | 28 | // Genome references 29 | genome = 'R64-1-1' 30 | } 31 | -------------------------------------------------------------------------------- /modules/nf-core/multiqc/tests/main.nf.test.snap: -------------------------------------------------------------------------------- 1 | { 2 | "multiqc_versions_single": { 3 | "content": [ 4 | [ 5 | "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" 6 | ] 7 | ], 8 | "meta": { 9 | "nf-test": "0.9.0", 10 | "nextflow": "24.04.4" 11 | }, 12 | "timestamp": "2024-10-02T17:51:46.317523" 13 | }, 14 | "multiqc_stub": { 15 | "content": [ 16 | [ 17 | "multiqc_report.html", 18 | "multiqc_data", 19 | "multiqc_plots", 20 | "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" 21 | ] 22 | ], 23 | "meta": { 24 | "nf-test": "0.9.0", 25 | "nextflow": "24.04.4" 26 | }, 27 | "timestamp": "2024-10-02T17:52:20.680978" 28 | }, 29 | "multiqc_versions_config": { 30 | "content": [ 31 | [ 32 | "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" 33 | ] 34 | ], 35 | "meta": { 36 | "nf-test": "0.9.0", 37 | "nextflow": "24.04.4" 38 | }, 39 | "timestamp": "2024-10-02T17:52:09.185842" 40 | } 41 | } -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nextflow_pipeline/meta.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json 2 | name: "UTILS_NEXTFLOW_PIPELINE" 3 | description: Subworkflow with functionality that may be useful for any Nextflow pipeline 4 | keywords: 5 | - utility 6 | - pipeline 7 | - initialise 8 | - version 9 | components: [] 10 | input: 11 | - print_version: 12 | type: boolean 13 | description: | 14 | Print the version of the pipeline and exit 15 | - dump_parameters: 16 | type: boolean 17 | description: | 18 | Dump the parameters of the pipeline to a JSON file 19 | - output_directory: 20 | type: directory 21 | description: Path to output dir to write JSON file to. 22 | pattern: "results/" 23 | - check_conda_channel: 24 | type: boolean 25 | description: | 26 | Check if the conda channel priority is correct. 27 | output: 28 | - dummy_emit: 29 | type: boolean 30 | description: | 31 | Dummy emit to make nf-core subworkflows lint happy 32 | authors: 33 | - "@adamrtalbot" 34 | - "@drpatelh" 35 | maintainers: 36 | - "@adamrtalbot" 37 | - "@drpatelh" 38 | - "@maxulysse" 39 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfschema_plugin/meta.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json 2 | name: "utils_nfschema_plugin" 3 | description: Run nf-schema to validate parameters and create a summary of changed parameters 4 | keywords: 5 | - validation 6 | - JSON schema 7 | - plugin 8 | - parameters 9 | - summary 10 | components: [] 11 | input: 12 | - input_workflow: 13 | type: object 14 | description: | 15 | The workflow object of the used pipeline. 16 | This object contains meta data used to create the params summary log 17 | - validate_params: 18 | type: boolean 19 | description: Validate the parameters and error if invalid. 20 | - parameters_schema: 21 | type: string 22 | description: | 23 | Path to the parameters JSON schema. 24 | This has to be the same as the schema given to the `validation.parametersSchema` config 25 | option. When this input is empty it will automatically use the configured schema or 26 | "${projectDir}/nextflow_schema.json" as default. The schema should not be given in this way 27 | for meta pipelines. 28 | output: 29 | - dummy_emit: 30 | type: boolean 31 | description: Dummy emit to make nf-core subworkflows lint happy 32 | authors: 33 | - "@nvnieuwk" 34 | maintainers: 35 | - "@nvnieuwk" 36 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | ## PR checklist 15 | 16 | - [ ] This comment contains a description of changes (with reason). 17 | - [ ] If you've fixed a bug or added code that should be tested, add tests! 18 | - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/seqeralabs/dragen/tree/master/.github/CONTRIBUTING.md) 19 | - [ ] Make sure your code lints (`nf-core pipelines lint`). 20 | - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). 21 | - [ ] Check for unexpected warnings in debug mode (`nextflow run . -profile debug,test,docker --outdir `). 22 | - [ ] Usage Documentation in `docs/usage.md` is updated. 23 | - [ ] Output Documentation in `docs/output.md` is updated. 24 | - [ ] `CHANGELOG.md` is updated. 25 | - [ ] `README.md` is updated (including new tool citations and authors/contributors). 26 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test: -------------------------------------------------------------------------------- 1 | 2 | nextflow_function { 3 | 4 | name "Test Functions" 5 | script "subworkflows/nf-core/utils_nextflow_pipeline/main.nf" 6 | config "subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config" 7 | tag 'subworkflows' 8 | tag 'utils_nextflow_pipeline' 9 | tag 'subworkflows/utils_nextflow_pipeline' 10 | 11 | test("Test Function getWorkflowVersion") { 12 | 13 | function "getWorkflowVersion" 14 | 15 | then { 16 | assertAll( 17 | { assert function.success }, 18 | { assert snapshot(function.result).match() } 19 | ) 20 | } 21 | } 22 | 23 | test("Test Function dumpParametersToJSON") { 24 | 25 | function "dumpParametersToJSON" 26 | 27 | when { 28 | function { 29 | """ 30 | // define inputs of the function here. Example: 31 | input[0] = "$outputDir" 32 | """.stripIndent() 33 | } 34 | } 35 | 36 | then { 37 | assertAll( 38 | { assert function.success } 39 | ) 40 | } 41 | } 42 | 43 | test("Test Function checkCondaChannels") { 44 | 45 | function "checkCondaChannels" 46 | 47 | then { 48 | assertAll( 49 | { assert function.success }, 50 | { assert snapshot(function.result).match() } 51 | ) 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /modules/local/dragen_buildhashtable.nf: -------------------------------------------------------------------------------- 1 | process DRAGEN_BUILDHASHTABLE { 2 | tag "$fasta" 3 | label 'dragen' 4 | 5 | secret 'DRAGEN_USERNAME' 6 | secret 'DRAGEN_PASSWORD' 7 | 8 | input: 9 | path(fasta) 10 | 11 | output: 12 | path "$prefix" , emit: index 13 | path "versions.yml", emit: versions 14 | 15 | script: 16 | def args = task.ext.args ?: '' 17 | prefix = task.ext.prefix ?: 'dragen' 18 | """ 19 | mkdir -p $prefix 20 | 21 | /opt/edico/bin/dragen \\ 22 | --build-hash-table true \\ 23 | --output-directory $prefix \\ 24 | --ht-reference $fasta \\ 25 | --lic-server=\$DRAGEN_USERNAME:\$DRAGEN_PASSWORD@license.edicogenome.com \\ 26 | $args 27 | 28 | cat <<-END_VERSIONS > versions.yml 29 | "${task.process}": 30 | dragen: '\$(echo \$(/opt/edico/bin/dragen --version 2>&1) | sed -e "s/dragen Version //g")' 31 | END_VERSIONS 32 | """ 33 | 34 | stub: 35 | def args = task.ext.args ?: '' 36 | prefix = task.ext.prefix ?: 'dragen' 37 | """ 38 | mkdir -p $prefix 39 | 40 | echo /opt/edico/bin/dragen \\ 41 | --build-hash-table true \\ 42 | --output-directory $prefix \\ 43 | --ht-reference $fasta \\ 44 | --lic-server=\$DRAGEN_USERNAME:\$DRAGEN_PASSWORD@license.edicogenome.com \\ 45 | $args 46 | 47 | touch ${prefix}/dragen.ht 48 | cat <<-END_VERSIONS > versions.yml 49 | "${task.process}": 50 | dragen: '\$(echo \$(/opt/edico/bin/dragen --version 2>&1) | sed -e "s/dragen Version //g")' 51 | END_VERSIONS 52 | """ 53 | } 54 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Report something that is broken or incorrect 3 | labels: bug 4 | body: 5 | - type: textarea 6 | id: description 7 | attributes: 8 | label: Description of the bug 9 | description: A clear and concise description of what the bug is. 10 | validations: 11 | required: true 12 | 13 | - type: textarea 14 | id: command_used 15 | attributes: 16 | label: Command used and terminal output 17 | description: Steps to reproduce the behaviour. Please paste the command you used to launch the pipeline and the output from your terminal. 18 | render: console 19 | placeholder: | 20 | $ nextflow run ... 21 | 22 | Some output where something broke 23 | 24 | - type: textarea 25 | id: files 26 | attributes: 27 | label: Relevant files 28 | description: | 29 | Please drag and drop the relevant files here. Create a `.zip` archive if the extension is not allowed. 30 | Your verbose log file `.nextflow.log` is often useful _(this is a hidden file in the directory where you launched the pipeline)_ as well as custom Nextflow configuration files. 31 | 32 | - type: textarea 33 | id: system 34 | attributes: 35 | label: System information 36 | description: | 37 | * Nextflow version _(eg. 23.04.0)_ 38 | * Hardware _(eg. HPC, Desktop, Cloud)_ 39 | * Executor _(eg. slurm, local, awsbatch)_ 40 | * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter, Charliecloud, or Apptainer)_ 41 | * OS _(eg. CentOS Linux, macOS, Linux Mint)_ 42 | * Version of seqeralabs/dragen _(eg. 1.1, 1.5, 1.8.2)_ 43 | -------------------------------------------------------------------------------- /modules.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "seqeralabs/dragen", 3 | "homePage": "https://github.com/seqeralabs/dragen", 4 | "repos": { 5 | "https://github.com/nf-core/modules.git": { 6 | "modules": { 7 | "nf-core": { 8 | "fastqc": { 9 | "branch": "master", 10 | "git_sha": "dc94b6ee04a05ddb9f7ae050712ff30a13149164", 11 | "installed_by": ["modules"] 12 | }, 13 | "multiqc": { 14 | "branch": "master", 15 | "git_sha": "cf17ca47590cc578dfb47db1c2a44ef86f89976d", 16 | "installed_by": ["modules"] 17 | } 18 | } 19 | }, 20 | "subworkflows": { 21 | "nf-core": { 22 | "utils_nextflow_pipeline": { 23 | "branch": "master", 24 | "git_sha": "c2b22d85f30a706a3073387f30380704fcae013b", 25 | "installed_by": ["subworkflows"] 26 | }, 27 | "utils_nfcore_pipeline": { 28 | "branch": "master", 29 | "git_sha": "51ae5406a030d4da1e49e4dab49756844fdd6c7a", 30 | "installed_by": ["subworkflows"] 31 | }, 32 | "utils_nfschema_plugin": { 33 | "branch": "master", 34 | "git_sha": "2fd2cd6d0e7b273747f32e465fdc6bcc3ae0814e", 35 | "installed_by": ["subworkflows"] 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /assets/schema_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://raw.githubusercontent.com/seqeralabs/dragen/master/assets/schema_input.json", 4 | "title": "seqeralabs/dragen pipeline - params.input schema", 5 | "description": "Schema for the file provided with params.input", 6 | "type": "array", 7 | "items": { 8 | "type": "object", 9 | "properties": { 10 | "sample": { 11 | "type": "string", 12 | "pattern": "^\\S+$", 13 | "errorMessage": "Sample name must be provided and cannot contain spaces", 14 | "meta": ["id"] 15 | }, 16 | "seq_type": { 17 | "type": "string", 18 | "enum": ["dna", "rna"], 19 | "errorMessage": "Type of sequencing data must be provided and must be either 'DNA' or 'RNA'", 20 | "meta": ["seq_type"] 21 | }, 22 | "fastq_1": { 23 | "type": "string", 24 | "format": "file-path", 25 | "exists": true, 26 | "pattern": "^\\S+\\.f(ast)?q\\.gz$", 27 | "errorMessage": "FastQ file for reads 1 must be provided, cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" 28 | }, 29 | "fastq_2": { 30 | "type": "string", 31 | "format": "file-path", 32 | "exists": true, 33 | "pattern": "^\\S+\\.f(ast)?q\\.gz$", 34 | "errorMessage": "FastQ file for reads 2 cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" 35 | } 36 | }, 37 | "required": ["sample", "fastq_1"] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfschema_plugin/main.nf: -------------------------------------------------------------------------------- 1 | // 2 | // Subworkflow that uses the nf-schema plugin to validate parameters and render the parameter summary 3 | // 4 | 5 | include { paramsSummaryLog } from 'plugin/nf-schema' 6 | include { validateParameters } from 'plugin/nf-schema' 7 | 8 | workflow UTILS_NFSCHEMA_PLUGIN { 9 | 10 | take: 11 | input_workflow // workflow: the workflow object used by nf-schema to get metadata from the workflow 12 | validate_params // boolean: validate the parameters 13 | parameters_schema // string: path to the parameters JSON schema. 14 | // this has to be the same as the schema given to `validation.parametersSchema` 15 | // when this input is empty it will automatically use the configured schema or 16 | // "${projectDir}/nextflow_schema.json" as default. This input should not be empty 17 | // for meta pipelines 18 | 19 | main: 20 | 21 | // 22 | // Print parameter summary to stdout. This will display the parameters 23 | // that differ from the default given in the JSON schema 24 | // 25 | if(parameters_schema) { 26 | log.info paramsSummaryLog(input_workflow, parameters_schema:parameters_schema) 27 | } else { 28 | log.info paramsSummaryLog(input_workflow) 29 | } 30 | 31 | // 32 | // Validate the parameters using nextflow_schema.json or the schema 33 | // given via the validation.parametersSchema configuration option 34 | // 35 | if(validate_params) { 36 | if(parameters_schema) { 37 | validateParameters(parameters_schema:parameters_schema) 38 | } else { 39 | validateParameters() 40 | } 41 | } 42 | 43 | emit: 44 | dummy_emit = true 45 | } 46 | 47 | -------------------------------------------------------------------------------- /modules/nf-core/multiqc/main.nf: -------------------------------------------------------------------------------- 1 | process MULTIQC { 2 | label 'process_single' 3 | 4 | conda "${moduleDir}/environment.yml" 5 | container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 6 | 'https://depot.galaxyproject.org/singularity/multiqc:1.25.1--pyhdfd78af_0' : 7 | 'biocontainers/multiqc:1.25.1--pyhdfd78af_0' }" 8 | 9 | input: 10 | path multiqc_files, stageAs: "?/*" 11 | path(multiqc_config) 12 | path(extra_multiqc_config) 13 | path(multiqc_logo) 14 | path(replace_names) 15 | path(sample_names) 16 | 17 | output: 18 | path "*multiqc_report.html", emit: report 19 | path "*_data" , emit: data 20 | path "*_plots" , optional:true, emit: plots 21 | path "versions.yml" , emit: versions 22 | 23 | when: 24 | task.ext.when == null || task.ext.when 25 | 26 | script: 27 | def args = task.ext.args ?: '' 28 | def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' 29 | def config = multiqc_config ? "--config $multiqc_config" : '' 30 | def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' 31 | def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' 32 | def replace = replace_names ? "--replace-names ${replace_names}" : '' 33 | def samples = sample_names ? "--sample-names ${sample_names}" : '' 34 | """ 35 | multiqc \\ 36 | --force \\ 37 | $args \\ 38 | $config \\ 39 | $prefix \\ 40 | $extra_config \\ 41 | $logo \\ 42 | $replace \\ 43 | $samples \\ 44 | . 45 | 46 | cat <<-END_VERSIONS > versions.yml 47 | "${task.process}": 48 | multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) 49 | END_VERSIONS 50 | """ 51 | 52 | stub: 53 | """ 54 | mkdir multiqc_data 55 | mkdir multiqc_plots 56 | touch multiqc_report.html 57 | 58 | cat <<-END_VERSIONS > versions.yml 59 | "${task.process}": 60 | multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) 61 | END_VERSIONS 62 | """ 63 | } 64 | -------------------------------------------------------------------------------- /modules/nf-core/fastqc/meta.yml: -------------------------------------------------------------------------------- 1 | name: fastqc 2 | description: Run FastQC on sequenced reads 3 | keywords: 4 | - quality control 5 | - qc 6 | - adapters 7 | - fastq 8 | tools: 9 | - fastqc: 10 | description: | 11 | FastQC gives general quality metrics about your reads. 12 | It provides information about the quality score distribution 13 | across your reads, the per base sequence content (%A/C/G/T). 14 | 15 | You get information about adapter contamination and other 16 | overrepresented sequences. 17 | homepage: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/ 18 | documentation: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/ 19 | licence: ["GPL-2.0-only"] 20 | identifier: biotools:fastqc 21 | input: 22 | - - meta: 23 | type: map 24 | description: | 25 | Groovy Map containing sample information 26 | e.g. [ id:'test', single_end:false ] 27 | - reads: 28 | type: file 29 | description: | 30 | List of input FastQ files of size 1 and 2 for single-end and paired-end data, 31 | respectively. 32 | output: 33 | - html: 34 | - meta: 35 | type: map 36 | description: | 37 | Groovy Map containing sample information 38 | e.g. [ id:'test', single_end:false ] 39 | - "*.html": 40 | type: file 41 | description: FastQC report 42 | pattern: "*_{fastqc.html}" 43 | - zip: 44 | - meta: 45 | type: map 46 | description: | 47 | Groovy Map containing sample information 48 | e.g. [ id:'test', single_end:false ] 49 | - "*.zip": 50 | type: file 51 | description: FastQC report archive 52 | pattern: "*_{fastqc.zip}" 53 | - versions: 54 | - versions.yml: 55 | type: file 56 | description: File containing software versions 57 | pattern: "versions.yml" 58 | authors: 59 | - "@drpatelh" 60 | - "@grst" 61 | - "@ewels" 62 | - "@FelixKrueger" 63 | maintainers: 64 | - "@drpatelh" 65 | - "@grst" 66 | - "@ewels" 67 | - "@FelixKrueger" 68 | -------------------------------------------------------------------------------- /conf/base.config: -------------------------------------------------------------------------------- 1 | /* 2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 | seqeralabs/nf-dragen Nextflow base config file 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | A 'blank slate' config file, appropriate for general use on most high performance 6 | compute environments. Assumes that all software is installed and available on 7 | the PATH. Runs in `local` mode - all jobs will be run on the logged in environment. 8 | ---------------------------------------------------------------------------------------- 9 | */ 10 | 11 | process { 12 | 13 | // TODO nf-core: Check the defaults for all processes 14 | cpus = { 1 * task.attempt } 15 | memory = { 6.GB * task.attempt } 16 | time = { 4.h * task.attempt } 17 | 18 | errorStrategy = { task.exitStatus in ((130..145) + 104) ? 'retry' : 'finish' } 19 | maxRetries = 1 20 | maxErrors = '-1' 21 | 22 | // Process-specific resource requirements 23 | // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors 24 | withLabel:'dragen' { 25 | cpus = 8 26 | memory = 96.GB 27 | time = 24.h 28 | } 29 | withLabel:process_single { 30 | cpus = { 1 } 31 | memory = { 6.GB * task.attempt } 32 | time = { 4.h * task.attempt } 33 | } 34 | withLabel:process_low { 35 | cpus = { 2 * task.attempt } 36 | memory = { 12.GB * task.attempt } 37 | time = { 4.h * task.attempt } 38 | } 39 | withLabel:process_medium { 40 | cpus = { 6 * task.attempt } 41 | memory = { 36.GB * task.attempt } 42 | time = { 8.h * task.attempt } 43 | } 44 | withLabel:process_high { 45 | cpus = { 12 * task.attempt } 46 | memory = { 72.GB * task.attempt } 47 | time = { 16.h * task.attempt } 48 | } 49 | withLabel:process_long { 50 | time = { 20.h * task.attempt } 51 | } 52 | withLabel:process_high_memory { 53 | memory = { 200.GB * task.attempt } 54 | } 55 | withLabel:error_ignore { 56 | errorStrategy = 'ignore' 57 | } 58 | withLabel:error_retry { 59 | errorStrategy = 'retry' 60 | maxRetries = 2 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /.nf-core.yml: -------------------------------------------------------------------------------- 1 | repository_type: pipeline 2 | 3 | nf_core_version: 3.1.1 4 | 5 | lint: 6 | files_exist: 7 | - .github/ISSUE_TEMPLATE/config.yml 8 | - .github/workflows/awsfulltest.yml 9 | - .github/workflows/awstest.yml 10 | - .github/workflows/branch.yml 11 | - .github/workflows/ci.yml 12 | - .github/workflows/linting_comment.yml 13 | - .github/workflows/linting.yml 14 | - assets/email_template.html 15 | - assets/email_template.txt 16 | - assets/nf-core-nf-dragen_logo_light.png 17 | - assets/sendmail_template.txt 18 | - CITATIONS.md 19 | - CODE_OF_CONDUCT.md 20 | - docs/images/nf-core-nf-dragen_logo_light.png 21 | - docs/images/nf-core-nf-dragen_logo_dark.png 22 | - docs/output.md 23 | - docs/README.md 24 | - docs/usage.md 25 | - ro-crate-metadata.json 26 | - LICENSE 27 | files_unchanged: 28 | - .github/CONTRIBUTING.md 29 | - .github/ISSUE_TEMPLATE/bug_report.yml 30 | - .github/ISSUE_TEMPLATE/feature_request.yml 31 | - .github/PULL_REQUEST_TEMPLATE.md 32 | - .prettierignore 33 | - assets/email_template.txt 34 | - assets/nf-core-nf_dragen_logo_light.png 35 | - CODE_OF_CONDUCT.md 36 | - docs/images/nf-core-nf_dragen_logo_dark.png 37 | - docs/images/nf-core-nf_dragen_logo_light.png 38 | - docs/README.md 39 | included_configs: false 40 | multiqc_config: 41 | - report_comment 42 | nextflow_config: 43 | - custom_config 44 | - manifest.homePage 45 | - manifest.name 46 | - params.custom_config_base 47 | - params.custom_config_version 48 | - process.cpus 49 | - process.memory 50 | - process.time 51 | - validation.help.afterText 52 | - validation.help.beforeText 53 | - validation.summary.afterText 54 | - validation.summary.beforeText 55 | 56 | template: 57 | author: Adam Talbot, Harshil Patel, Graham Wright 58 | description: nf-dragen is a simple, proof-of-concept Nextflow pipeline to run the 59 | Illumina DRAGEN licensed suite of tools. 60 | force: false 61 | is_nfcore: false 62 | name: dragen 63 | org: seqeralabs 64 | outdir: . 65 | skip_features: 66 | - ci 67 | - nf_core_configs 68 | - citations 69 | - gitpod 70 | - codespaces 71 | - email 72 | - adaptivecard 73 | - slackreport 74 | - documentation 75 | - rocrate 76 | - vscode 77 | version: 1.0.0dev 78 | -------------------------------------------------------------------------------- /workflows/dragen.nf: -------------------------------------------------------------------------------- 1 | /* 2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 | IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | */ 6 | 7 | include { DRAGEN } from '../modules/local/dragen.nf' 8 | include { DRAGEN_BUILDHASHTABLE } from '../modules/local/dragen_buildhashtable.nf' 9 | 10 | include { paramsSummaryMap } from 'plugin/nf-schema' 11 | include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' 12 | include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' 13 | 14 | /* 15 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 | RUN MAIN WORKFLOW 17 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 | */ 19 | 20 | workflow DRAGEN_WORKFLOW { 21 | 22 | take: 23 | ch_input 24 | index 25 | fasta 26 | 27 | main: 28 | ch_versions = Channel.empty() 29 | if (!index) { 30 | ch_fasta = Channel.fromPath(fasta, checkIfExists: true, type: 'file') 31 | // Use combine to not run the process if ch_input is empty 32 | DRAGEN_BUILDHASHTABLE ( 33 | ch_input.combine(ch_fasta).map { meta, fastq_1, fastq_2, _fasta -> _fasta }.first() 34 | ) 35 | ch_index = DRAGEN_BUILDHASHTABLE.out.index 36 | ch_versions = ch_versions.mix(DRAGEN_BUILDHASHTABLE.out.versions) 37 | } else { 38 | ch_index = Channel.fromPath(index, checkIfExists: true, type: 'dir') 39 | } 40 | 41 | // 42 | // MODULE: Run DRAGEN on DNA samples to generate BAM from FastQ 43 | // 44 | DRAGEN ( 45 | ch_input, 46 | ch_index.collect() 47 | ) 48 | ch_versions = ch_versions.mix(DRAGEN.out.versions.first()) 49 | 50 | 51 | emit: 52 | index = ch_index 53 | bam = DRAGEN.out.bam 54 | fastq = DRAGEN.out.fastq 55 | vcf = DRAGEN.out.vcf 56 | tbi = DRAGEN.out.tbi 57 | vcf_filtered = DRAGEN.out.vcf_filtered 58 | tbi_filtered = DRAGEN.out.tbi_filtered 59 | versions = DRAGEN.out.versions 60 | } 61 | 62 | /* 63 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 64 | THE END 65 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 66 | */ 67 | -------------------------------------------------------------------------------- /modules/nf-core/fastqc/main.nf: -------------------------------------------------------------------------------- 1 | process FASTQC { 2 | tag "$meta.id" 3 | label 'process_medium' 4 | 5 | conda "${moduleDir}/environment.yml" 6 | container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 7 | 'https://depot.galaxyproject.org/singularity/fastqc:0.12.1--hdfd78af_0' : 8 | 'biocontainers/fastqc:0.12.1--hdfd78af_0' }" 9 | 10 | input: 11 | tuple val(meta), path(reads) 12 | 13 | output: 14 | tuple val(meta), path("*.html"), emit: html 15 | tuple val(meta), path("*.zip") , emit: zip 16 | path "versions.yml" , emit: versions 17 | 18 | when: 19 | task.ext.when == null || task.ext.when 20 | 21 | script: 22 | def args = task.ext.args ?: '' 23 | def prefix = task.ext.prefix ?: "${meta.id}" 24 | // Make list of old name and new name pairs to use for renaming in the bash while loop 25 | def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] } 26 | def rename_to = old_new_pairs*.join(' ').join(' ') 27 | def renamed_files = old_new_pairs.collect{ _old_name, new_name -> new_name }.join(' ') 28 | 29 | // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) 30 | // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 31 | // Dividing the task.memory by task.cpu allows to stick to requested amount of RAM in the label 32 | def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB') / task.cpus 33 | // FastQC memory value allowed range (100 - 10000) 34 | def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) 35 | 36 | """ 37 | printf "%s %s\\n" $rename_to | while read old_name new_name; do 38 | [ -f "\${new_name}" ] || ln -s \$old_name \$new_name 39 | done 40 | 41 | fastqc \\ 42 | $args \\ 43 | --threads $task.cpus \\ 44 | --memory $fastqc_memory \\ 45 | $renamed_files 46 | 47 | cat <<-END_VERSIONS > versions.yml 48 | "${task.process}": 49 | fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) 50 | END_VERSIONS 51 | """ 52 | 53 | stub: 54 | def prefix = task.ext.prefix ?: "${meta.id}" 55 | """ 56 | touch ${prefix}.html 57 | touch ${prefix}.zip 58 | 59 | cat <<-END_VERSIONS > versions.yml 60 | "${task.process}": 61 | fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) 62 | END_VERSIONS 63 | """ 64 | } 65 | -------------------------------------------------------------------------------- /modules/nf-core/multiqc/meta.yml: -------------------------------------------------------------------------------- 1 | name: multiqc 2 | description: Aggregate results from bioinformatics analyses across many samples into 3 | a single report 4 | keywords: 5 | - QC 6 | - bioinformatics tools 7 | - Beautiful stand-alone HTML report 8 | tools: 9 | - multiqc: 10 | description: | 11 | MultiQC searches a given directory for analysis logs and compiles a HTML report. 12 | It's a general use tool, perfect for summarising the output from numerous bioinformatics tools. 13 | homepage: https://multiqc.info/ 14 | documentation: https://multiqc.info/docs/ 15 | licence: ["GPL-3.0-or-later"] 16 | identifier: biotools:multiqc 17 | input: 18 | - - multiqc_files: 19 | type: file 20 | description: | 21 | List of reports / files recognised by MultiQC, for example the html and zip output of FastQC 22 | - - multiqc_config: 23 | type: file 24 | description: Optional config yml for MultiQC 25 | pattern: "*.{yml,yaml}" 26 | - - extra_multiqc_config: 27 | type: file 28 | description: Second optional config yml for MultiQC. Will override common sections 29 | in multiqc_config. 30 | pattern: "*.{yml,yaml}" 31 | - - multiqc_logo: 32 | type: file 33 | description: Optional logo file for MultiQC 34 | pattern: "*.{png}" 35 | - - replace_names: 36 | type: file 37 | description: | 38 | Optional two-column sample renaming file. First column a set of 39 | patterns, second column a set of corresponding replacements. Passed via 40 | MultiQC's `--replace-names` option. 41 | pattern: "*.{tsv}" 42 | - - sample_names: 43 | type: file 44 | description: | 45 | Optional TSV file with headers, passed to the MultiQC --sample_names 46 | argument. 47 | pattern: "*.{tsv}" 48 | output: 49 | - report: 50 | - "*multiqc_report.html": 51 | type: file 52 | description: MultiQC report file 53 | pattern: "multiqc_report.html" 54 | - data: 55 | - "*_data": 56 | type: directory 57 | description: MultiQC data dir 58 | pattern: "multiqc_data" 59 | - plots: 60 | - "*_plots": 61 | type: file 62 | description: Plots created by MultiQC 63 | pattern: "*_data" 64 | - versions: 65 | - versions.yml: 66 | type: file 67 | description: File containing software versions 68 | pattern: "versions.yml" 69 | authors: 70 | - "@abhi18av" 71 | - "@bunop" 72 | - "@drpatelh" 73 | - "@jfy133" 74 | maintainers: 75 | - "@abhi18av" 76 | - "@bunop" 77 | - "@drpatelh" 78 | - "@jfy133" 79 | -------------------------------------------------------------------------------- /modules/nf-core/multiqc/tests/main.nf.test: -------------------------------------------------------------------------------- 1 | nextflow_process { 2 | 3 | name "Test Process MULTIQC" 4 | script "../main.nf" 5 | process "MULTIQC" 6 | 7 | tag "modules" 8 | tag "modules_nfcore" 9 | tag "multiqc" 10 | 11 | config "./nextflow.config" 12 | 13 | test("sarscov2 single-end [fastqc]") { 14 | 15 | when { 16 | process { 17 | """ 18 | input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) 19 | input[1] = [] 20 | input[2] = [] 21 | input[3] = [] 22 | input[4] = [] 23 | input[5] = [] 24 | """ 25 | } 26 | } 27 | 28 | then { 29 | assertAll( 30 | { assert process.success }, 31 | { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, 32 | { assert process.out.data[0] ==~ ".*/multiqc_data" }, 33 | { assert snapshot(process.out.versions).match("multiqc_versions_single") } 34 | ) 35 | } 36 | 37 | } 38 | 39 | test("sarscov2 single-end [fastqc] [config]") { 40 | 41 | when { 42 | process { 43 | """ 44 | input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) 45 | input[1] = Channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) 46 | input[2] = [] 47 | input[3] = [] 48 | input[4] = [] 49 | input[5] = [] 50 | """ 51 | } 52 | } 53 | 54 | then { 55 | assertAll( 56 | { assert process.success }, 57 | { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, 58 | { assert process.out.data[0] ==~ ".*/multiqc_data" }, 59 | { assert snapshot(process.out.versions).match("multiqc_versions_config") } 60 | ) 61 | } 62 | } 63 | 64 | test("sarscov2 single-end [fastqc] - stub") { 65 | 66 | options "-stub" 67 | 68 | when { 69 | process { 70 | """ 71 | input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) 72 | input[1] = [] 73 | input[2] = [] 74 | input[3] = [] 75 | input[4] = [] 76 | input[5] = [] 77 | """ 78 | } 79 | } 80 | 81 | then { 82 | assertAll( 83 | { assert process.success }, 84 | { assert snapshot(process.out.report.collect { file(it).getName() } + 85 | process.out.data.collect { file(it).getName() } + 86 | process.out.plots.collect { file(it).getName() } + 87 | process.out.versions ).match("multiqc_stub") } 88 | ) 89 | } 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test: -------------------------------------------------------------------------------- 1 | nextflow_workflow { 2 | 3 | name "Test Subworkflow UTILS_NFSCHEMA_PLUGIN" 4 | script "../main.nf" 5 | workflow "UTILS_NFSCHEMA_PLUGIN" 6 | 7 | tag "subworkflows" 8 | tag "subworkflows_nfcore" 9 | tag "subworkflows/utils_nfschema_plugin" 10 | tag "plugin/nf-schema" 11 | 12 | config "./nextflow.config" 13 | 14 | test("Should run nothing") { 15 | 16 | when { 17 | 18 | params { 19 | test_data = '' 20 | } 21 | 22 | workflow { 23 | """ 24 | validate_params = false 25 | input[0] = workflow 26 | input[1] = validate_params 27 | input[2] = "" 28 | """ 29 | } 30 | } 31 | 32 | then { 33 | assertAll( 34 | { assert workflow.success } 35 | ) 36 | } 37 | } 38 | 39 | test("Should validate params") { 40 | 41 | when { 42 | 43 | params { 44 | test_data = '' 45 | outdir = null 46 | } 47 | 48 | workflow { 49 | """ 50 | validate_params = true 51 | input[0] = workflow 52 | input[1] = validate_params 53 | input[2] = "" 54 | """ 55 | } 56 | } 57 | 58 | then { 59 | assertAll( 60 | { assert workflow.failed }, 61 | { assert workflow.stdout.any { it.contains('ERROR ~ Validation of pipeline parameters failed!') } } 62 | ) 63 | } 64 | } 65 | 66 | test("Should run nothing - custom schema") { 67 | 68 | when { 69 | 70 | params { 71 | test_data = '' 72 | } 73 | 74 | workflow { 75 | """ 76 | validate_params = false 77 | input[0] = workflow 78 | input[1] = validate_params 79 | input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" 80 | """ 81 | } 82 | } 83 | 84 | then { 85 | assertAll( 86 | { assert workflow.success } 87 | ) 88 | } 89 | } 90 | 91 | test("Should validate params - custom schema") { 92 | 93 | when { 94 | 95 | params { 96 | test_data = '' 97 | outdir = null 98 | } 99 | 100 | workflow { 101 | """ 102 | validate_params = true 103 | input[0] = workflow 104 | input[1] = validate_params 105 | input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" 106 | """ 107 | } 108 | } 109 | 110 | then { 111 | assertAll( 112 | { assert workflow.failed }, 113 | { assert workflow.stdout.any { it.contains('ERROR ~ Validation of pipeline parameters failed!') } } 114 | ) 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nextflow_pipeline/tests/main.workflow.nf.test: -------------------------------------------------------------------------------- 1 | nextflow_workflow { 2 | 3 | name "Test Workflow UTILS_NEXTFLOW_PIPELINE" 4 | script "../main.nf" 5 | config "subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config" 6 | workflow "UTILS_NEXTFLOW_PIPELINE" 7 | tag 'subworkflows' 8 | tag 'utils_nextflow_pipeline' 9 | tag 'subworkflows/utils_nextflow_pipeline' 10 | 11 | test("Should run no inputs") { 12 | 13 | when { 14 | workflow { 15 | """ 16 | print_version = false 17 | dump_parameters = false 18 | outdir = null 19 | check_conda_channels = false 20 | 21 | input[0] = print_version 22 | input[1] = dump_parameters 23 | input[2] = outdir 24 | input[3] = check_conda_channels 25 | """ 26 | } 27 | } 28 | 29 | then { 30 | assertAll( 31 | { assert workflow.success } 32 | ) 33 | } 34 | } 35 | 36 | test("Should print version") { 37 | 38 | when { 39 | workflow { 40 | """ 41 | print_version = true 42 | dump_parameters = false 43 | outdir = null 44 | check_conda_channels = false 45 | 46 | input[0] = print_version 47 | input[1] = dump_parameters 48 | input[2] = outdir 49 | input[3] = check_conda_channels 50 | """ 51 | } 52 | } 53 | 54 | then { 55 | expect { 56 | with(workflow) { 57 | assert success 58 | assert "nextflow_workflow v9.9.9" in stdout 59 | } 60 | } 61 | } 62 | } 63 | 64 | test("Should dump params") { 65 | 66 | when { 67 | workflow { 68 | """ 69 | print_version = false 70 | dump_parameters = true 71 | outdir = 'results' 72 | check_conda_channels = false 73 | 74 | input[0] = false 75 | input[1] = true 76 | input[2] = outdir 77 | input[3] = false 78 | """ 79 | } 80 | } 81 | 82 | then { 83 | assertAll( 84 | { assert workflow.success } 85 | ) 86 | } 87 | } 88 | 89 | test("Should not create params JSON if no output directory") { 90 | 91 | when { 92 | workflow { 93 | """ 94 | print_version = false 95 | dump_parameters = true 96 | outdir = null 97 | check_conda_channels = false 98 | 99 | input[0] = false 100 | input[1] = true 101 | input[2] = outdir 102 | input[3] = false 103 | """ 104 | } 105 | } 106 | 107 | then { 108 | assertAll( 109 | { assert workflow.success } 110 | ) 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /conf/modules.config: -------------------------------------------------------------------------------- 1 | /* 2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 | Config file for defining DSL2 per module options and publishing paths 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | Available keys to override module options: 6 | ext.args = Additional arguments appended to command in module. 7 | ext.args2 = Second set of arguments appended to command in module (multi-tool modules). 8 | ext.args3 = Third set of arguments appended to command in module (multi-tool modules). 9 | ext.prefix = File name prefix for output files. 10 | ---------------------------------------------------------------------------------------- 11 | */ 12 | 13 | process { 14 | 15 | publishDir = [ 16 | path: { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" }, 17 | mode: params.publish_dir_mode, 18 | saveAs: { filename -> filename.equals('versions.yml') ? null : filename } 19 | ] 20 | 21 | withName: FASTQC { 22 | ext.args = '--quiet' 23 | } 24 | 25 | withName: '.*:DRAGEN_DNA:DRAGEN_BUILDHASHTABLE' { 26 | ext.prefix = 'dragen_index_dna' 27 | publishDir = [ 28 | path: { "${params.outdir}/genome/index" }, 29 | mode: 'copy', 30 | saveAs: { filename -> filename.equals('versions.yml') ? null : filename } 31 | ] 32 | } 33 | 34 | withName: '.*:DRAGEN_RNA:DRAGEN_BUILDHASHTABLE' { 35 | ext.args = '--ht-build-rna-hashtable true' 36 | ext.prefix = 'dragen_index_rna' 37 | publishDir = [ 38 | path: { "${params.outdir}/genome/index" }, 39 | mode: 'copy', 40 | saveAs: { filename -> filename.equals('versions.yml') ? null : filename } 41 | ] 42 | } 43 | 44 | withName: '.*:DRAGEN_DNA:DRAGEN' { 45 | ext.args = [ 46 | '--enable-map-align true', 47 | '--enable-map-align-output true', 48 | '--enable-bam-indexing true', 49 | '--enable-sort=true', 50 | '--enable-variant-caller true', 51 | '--enable-duplicate-marking true', 52 | '--output-format=BAM' 53 | ].join(" ") 54 | publishDir = [ 55 | path: { "${params.outdir}/dragen/dna_fastq_to_vcf" }, 56 | mode: 'copy', 57 | saveAs: { filename -> filename.equals('versions.yml') ? null : filename } 58 | ] 59 | } 60 | 61 | withName: '.*:DRAGEN_RNA:DRAGEN' { 62 | ext.args = [ 63 | '--enable-rna true', 64 | '--enable-map-align true', 65 | '--enable-map-align-output true', 66 | '--enable-bam-indexing true', 67 | '--enable-sort=true', 68 | '--enable-variant-caller true', 69 | '--enable-duplicate-marking true', 70 | '--output-format=BAM' 71 | ].join(" ") 72 | publishDir = [ 73 | path: { "${params.outdir}/dragen/rna_fastq_to_bam" }, 74 | mode: 'copy', 75 | saveAs: { filename -> filename.equals('versions.yml') ? null : filename } 76 | ] 77 | } 78 | 79 | withName: 'MULTIQC' { 80 | ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } 81 | publishDir = [ 82 | path: { "${params.outdir}/multiqc" }, 83 | mode: params.publish_dir_mode, 84 | saveAs: { filename -> filename.equals('versions.yml') ? null : filename } 85 | ] 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /modules/local/dragen.nf: -------------------------------------------------------------------------------- 1 | process DRAGEN { 2 | tag "$meta.id" 3 | label 'dragen' 4 | 5 | secret 'DRAGEN_USERNAME' 6 | secret 'DRAGEN_PASSWORD' 7 | 8 | input: 9 | tuple val(meta), path(fastq_1, stageAs: "input_S1_L001_R1_???.fastq.gz"), path(fastq_2, stageAs: "input_S1_L001_R2_???.fastq.gz") 10 | path index 11 | 12 | output: 13 | tuple val(meta), path('*.{bam,sam,cram}') , emit: bam , optional:true 14 | tuple val(meta), path('*fastq.gz') , emit: fastq , optional:true 15 | tuple val(meta), path("${prefix}.vcf.gz") , emit: vcf , optional:true 16 | tuple val(meta), path("${prefix}.vcf.gz.tbi") , emit: tbi , optional:true 17 | tuple val(meta), path("${prefix}.hard-filtered.vcf.gz") , emit: vcf_filtered, optional:true 18 | tuple val(meta), path("${prefix}.hard-filtered.vcf.gz.tbi") , emit: tbi_filtered, optional:true 19 | path "versions.yml" , emit: versions 20 | 21 | script: 22 | def args = task.ext.args ?: '' 23 | prefix = task.ext.prefix ?: "${meta.id}" 24 | 25 | def ref = index ? "-r $index" : '' 26 | 27 | 28 | // Check FASTQ numbers match 29 | def num_r1 = fastq_1 instanceof List ? fastq_1.size() : 1 30 | def num_r2 = fastq_2 instanceof List ? fastq_2.size() : 1 31 | 32 | if ( fastq_2 && num_r1 != num_r2 ) { 33 | error "Number of R1 and R2 FASTQ files do not match" 34 | } 35 | 36 | // Generate appropriate parameter for input files 37 | r1_in = fastq_1 ? "-1 input_S1_L001_R1_001.fastq.gz" : "" 38 | r2_in = fastq_2 ? "-2 input_S1_L001_R2_001.fastq.gz" : "" 39 | def rgid = meta.rgid ? "--RGID ${meta.rgid}" : "--RGID ${meta.id}" 40 | def rgsm = meta.rgsm ? "--RGSM ${meta.rgsm}" : "--RGSM ${meta.id}" 41 | """ 42 | /opt/edico/bin/dragen \\ 43 | $ref \\ 44 | --output-directory ./ \\ 45 | --output-file-prefix $prefix \\ 46 | --lic-server=\$DRAGEN_USERNAME:\$DRAGEN_PASSWORD@license.edicogenome.com \\ 47 | $r1_in \\ 48 | $r2_in \\ 49 | $rgid \\ 50 | $rgsm \\ 51 | $args 52 | 53 | cat <<-END_VERSIONS > versions.yml 54 | "${task.process}": 55 | dragen: '\$(echo \$(/opt/edico/bin/dragen --version 2>&1) | sed -e "s/dragen Version //g")' 56 | END_VERSIONS 57 | """ 58 | 59 | stub: 60 | def args = task.ext.args ?: '' 61 | prefix = task.ext.prefix ?: "${meta.id}" 62 | 63 | def ref = index ? "-r $index" : '' 64 | 65 | 66 | // Check FASTQ numbers match 67 | def num_r1 = fastq_1 instanceof List ? fastq_1.size() : 1 68 | def num_r2 = fastq_2 instanceof List ? fastq_2.size() : 1 69 | 70 | if ( fastq_2 && num_r1 != num_r2 ) { 71 | error "Number of R1 and R2 FASTQ files do not match for sample ${prefix}" 72 | } 73 | 74 | // Generate appropriate parameter for input files 75 | r1_in = fastq_1 ? "-1 input_S1_L001_R1_001.fastq.gz" : "" 76 | r2_in = fastq_2 ? "-2 input_S1_L001_R2_001.fastq.gz" : "" 77 | def rgid = meta.rgid ? "--RGID ${meta.rgid}" : "--RGID ${meta.id}" 78 | def rgsm = meta.rgsm ? "--RGSM ${meta.rgsm}" : "--RGSM ${meta.id}" 79 | """ 80 | echo /opt/edico/bin/dragen \\ 81 | $ref \\ 82 | --output-directory ./ \\ 83 | --output-file-prefix $prefix \\ 84 | --lic-server=\$DRAGEN_USERNAME:\$DRAGEN_PASSWORD@license.edicogenome.com \\ 85 | $r1_in \\ 86 | $r2_in \\ 87 | $rgid \\ 88 | $rgsm \\ 89 | $args 90 | 91 | cat <<-END_VERSIONS > versions.yml 92 | "${task.process}": 93 | dragen: '\$(echo \$(/opt/edico/bin/dragen --version 2>&1) | sed -e "s/dragen Version //g")' 94 | END_VERSIONS 95 | """ 96 | } 97 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test: -------------------------------------------------------------------------------- 1 | 2 | nextflow_function { 3 | 4 | name "Test Functions" 5 | script "../main.nf" 6 | config "subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config" 7 | tag "subworkflows" 8 | tag "subworkflows_nfcore" 9 | tag "utils_nfcore_pipeline" 10 | tag "subworkflows/utils_nfcore_pipeline" 11 | 12 | test("Test Function checkConfigProvided") { 13 | 14 | function "checkConfigProvided" 15 | 16 | then { 17 | assertAll( 18 | { assert function.success }, 19 | { assert snapshot(function.result).match() } 20 | ) 21 | } 22 | } 23 | 24 | test("Test Function checkProfileProvided") { 25 | 26 | function "checkProfileProvided" 27 | 28 | when { 29 | function { 30 | """ 31 | input[0] = [] 32 | """ 33 | } 34 | } 35 | 36 | then { 37 | assertAll( 38 | { assert function.success }, 39 | { assert snapshot(function.result).match() } 40 | ) 41 | } 42 | } 43 | 44 | test("Test Function without logColours") { 45 | 46 | function "logColours" 47 | 48 | when { 49 | function { 50 | """ 51 | input[0] = true 52 | """ 53 | } 54 | } 55 | 56 | then { 57 | assertAll( 58 | { assert function.success }, 59 | { assert snapshot(function.result).match() } 60 | ) 61 | } 62 | } 63 | 64 | test("Test Function with logColours") { 65 | function "logColours" 66 | 67 | when { 68 | function { 69 | """ 70 | input[0] = false 71 | """ 72 | } 73 | } 74 | 75 | then { 76 | assertAll( 77 | { assert function.success }, 78 | { assert snapshot(function.result).match() } 79 | ) 80 | } 81 | } 82 | 83 | test("Test Function getSingleReport with a single file") { 84 | function "getSingleReport" 85 | 86 | when { 87 | function { 88 | """ 89 | input[0] = file(params.modules_testdata_base_path + '/generic/tsv/test.tsv', checkIfExists: true) 90 | """ 91 | } 92 | } 93 | 94 | then { 95 | assertAll( 96 | { assert function.success }, 97 | { assert function.result.contains("test.tsv") } 98 | ) 99 | } 100 | } 101 | 102 | test("Test Function getSingleReport with multiple files") { 103 | function "getSingleReport" 104 | 105 | when { 106 | function { 107 | """ 108 | input[0] = [ 109 | file(params.modules_testdata_base_path + '/generic/tsv/test.tsv', checkIfExists: true), 110 | file(params.modules_testdata_base_path + '/generic/tsv/network.tsv', checkIfExists: true), 111 | file(params.modules_testdata_base_path + '/generic/tsv/expression.tsv', checkIfExists: true) 112 | ] 113 | """ 114 | } 115 | } 116 | 117 | then { 118 | assertAll( 119 | { assert function.success }, 120 | { assert function.result.contains("test.tsv") }, 121 | { assert !function.result.contains("network.tsv") }, 122 | { assert !function.result.contains("expression.tsv") } 123 | ) 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://raw.githubusercontent.com/./master/nextflow_schema.json", 4 | "title": ". pipeline parameters", 5 | "description": "", 6 | "type": "object", 7 | "$defs": { 8 | "input_output_options": { 9 | "title": "Input/output options", 10 | "type": "object", 11 | "fa_icon": "fas fa-terminal", 12 | "description": "Define where the pipeline should find input data and save output data.", 13 | "required": ["outdir"], 14 | "properties": { 15 | "validate_params": { 16 | "type": "boolean", 17 | "description": "Validate parameters?", 18 | "default": true, 19 | "hidden": true 20 | }, 21 | "outdir": { 22 | "type": "string", 23 | "format": "directory-path", 24 | "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", 25 | "fa_icon": "fas fa-folder-open" 26 | }, 27 | "test_data_base": { 28 | "type": "string", 29 | "default": "https://raw.githubusercontent.com/nf-core/test-datasets/modules", 30 | "description": "Base for test data directory", 31 | "hidden": true 32 | }, 33 | "test_data": { 34 | "type": "string", 35 | "description": "Fake test data param", 36 | "hidden": true 37 | } 38 | } 39 | }, 40 | "generic_options": { 41 | "title": "Generic options", 42 | "type": "object", 43 | "fa_icon": "fas fa-file-import", 44 | "description": "Less common options for the pipeline, typically set in a config file.", 45 | "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`.", 46 | "properties": { 47 | "help": { 48 | "type": "boolean", 49 | "description": "Display help text.", 50 | "fa_icon": "fas fa-question-circle", 51 | "hidden": true 52 | }, 53 | "version": { 54 | "type": "boolean", 55 | "description": "Display version and exit.", 56 | "fa_icon": "fas fa-question-circle", 57 | "hidden": true 58 | }, 59 | "logo": { 60 | "type": "boolean", 61 | "default": true, 62 | "description": "Display nf-core logo in console output.", 63 | "fa_icon": "fas fa-image", 64 | "hidden": true 65 | }, 66 | "singularity_pull_docker_container": { 67 | "type": "boolean", 68 | "description": "Pull Singularity container from Docker?", 69 | "hidden": true 70 | }, 71 | "publish_dir_mode": { 72 | "type": "string", 73 | "default": "copy", 74 | "description": "Method used to save pipeline results to output directory.", 75 | "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.", 76 | "fa_icon": "fas fa-copy", 77 | "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], 78 | "hidden": true 79 | }, 80 | "monochrome_logs": { 81 | "type": "boolean", 82 | "description": "Use monochrome_logs", 83 | "hidden": true 84 | } 85 | } 86 | } 87 | }, 88 | "allOf": [ 89 | { 90 | "$ref": "#/$defs/input_output_options" 91 | }, 92 | { 93 | "$ref": "#/$defs/generic_options" 94 | } 95 | ] 96 | } 97 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nextflow_pipeline/main.nf: -------------------------------------------------------------------------------- 1 | // 2 | // Subworkflow with functionality that may be useful for any Nextflow pipeline 3 | // 4 | 5 | /* 6 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 | SUBWORKFLOW DEFINITION 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | */ 10 | 11 | workflow UTILS_NEXTFLOW_PIPELINE { 12 | take: 13 | print_version // boolean: print version 14 | dump_parameters // boolean: dump parameters 15 | outdir // path: base directory used to publish pipeline results 16 | check_conda_channels // boolean: check conda channels 17 | 18 | main: 19 | 20 | // 21 | // Print workflow version and exit on --version 22 | // 23 | if (print_version) { 24 | log.info("${workflow.manifest.name} ${getWorkflowVersion()}") 25 | System.exit(0) 26 | } 27 | 28 | // 29 | // Dump pipeline parameters to a JSON file 30 | // 31 | if (dump_parameters && outdir) { 32 | dumpParametersToJSON(outdir) 33 | } 34 | 35 | // 36 | // When running with Conda, warn if channels have not been set-up appropriately 37 | // 38 | if (check_conda_channels) { 39 | checkCondaChannels() 40 | } 41 | 42 | emit: 43 | dummy_emit = true 44 | } 45 | 46 | /* 47 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 48 | FUNCTIONS 49 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 50 | */ 51 | 52 | // 53 | // Generate version string 54 | // 55 | def getWorkflowVersion() { 56 | def version_string = "" as String 57 | if (workflow.manifest.version) { 58 | def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' 59 | version_string += "${prefix_v}${workflow.manifest.version}" 60 | } 61 | 62 | if (workflow.commitId) { 63 | def git_shortsha = workflow.commitId.substring(0, 7) 64 | version_string += "-g${git_shortsha}" 65 | } 66 | 67 | return version_string 68 | } 69 | 70 | // 71 | // Dump pipeline parameters to a JSON file 72 | // 73 | def dumpParametersToJSON(outdir) { 74 | def timestamp = new java.util.Date().format('yyyy-MM-dd_HH-mm-ss') 75 | def filename = "params_${timestamp}.json" 76 | def temp_pf = new File(workflow.launchDir.toString(), ".${filename}") 77 | def jsonStr = groovy.json.JsonOutput.toJson(params) 78 | temp_pf.text = groovy.json.JsonOutput.prettyPrint(jsonStr) 79 | 80 | nextflow.extension.FilesEx.copyTo(temp_pf.toPath(), "${outdir}/pipeline_info/params_${timestamp}.json") 81 | temp_pf.delete() 82 | } 83 | 84 | // 85 | // When running with -profile conda, warn if channels have not been set-up appropriately 86 | // 87 | def checkCondaChannels() { 88 | def parser = new org.yaml.snakeyaml.Yaml() 89 | def channels = [] 90 | try { 91 | def config = parser.load("conda config --show channels".execute().text) 92 | channels = config.channels 93 | } 94 | catch (NullPointerException e) { 95 | log.debug(e) 96 | log.warn("Could not verify conda channel configuration.") 97 | return null 98 | } 99 | catch (IOException e) { 100 | log.debug(e) 101 | log.warn("Could not verify conda channel configuration.") 102 | return null 103 | } 104 | 105 | // Check that all channels are present 106 | // This channel list is ordered by required channel priority. 107 | def required_channels_in_order = ['conda-forge', 'bioconda'] 108 | def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean 109 | 110 | // Check that they are in the right order 111 | def channel_priority_violation = required_channels_in_order != channels.findAll { ch -> ch in required_channels_in_order } 112 | 113 | if (channels_missing | channel_priority_violation) { 114 | log.warn """\ 115 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 116 | There is a problem with your Conda configuration! 117 | You will need to set-up the conda-forge and bioconda channels correctly. 118 | Please refer to https://bioconda.github.io/ 119 | The observed channel order is 120 | ${channels} 121 | but the following channel order is required: 122 | ${required_channels_in_order} 123 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 124 | """.stripIndent(true) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Test Function checkProfileProvided": { 3 | "content": null, 4 | "meta": { 5 | "nf-test": "0.8.4", 6 | "nextflow": "23.10.1" 7 | }, 8 | "timestamp": "2024-02-28T12:03:03.360873" 9 | }, 10 | "Test Function checkConfigProvided": { 11 | "content": [ 12 | true 13 | ], 14 | "meta": { 15 | "nf-test": "0.8.4", 16 | "nextflow": "23.10.1" 17 | }, 18 | "timestamp": "2024-02-28T12:02:59.729647" 19 | }, 20 | "Test Function without logColours": { 21 | "content": [ 22 | { 23 | "reset": "", 24 | "bold": "", 25 | "dim": "", 26 | "underlined": "", 27 | "blink": "", 28 | "reverse": "", 29 | "hidden": "", 30 | "black": "", 31 | "red": "", 32 | "green": "", 33 | "yellow": "", 34 | "blue": "", 35 | "purple": "", 36 | "cyan": "", 37 | "white": "", 38 | "bblack": "", 39 | "bred": "", 40 | "bgreen": "", 41 | "byellow": "", 42 | "bblue": "", 43 | "bpurple": "", 44 | "bcyan": "", 45 | "bwhite": "", 46 | "ublack": "", 47 | "ured": "", 48 | "ugreen": "", 49 | "uyellow": "", 50 | "ublue": "", 51 | "upurple": "", 52 | "ucyan": "", 53 | "uwhite": "", 54 | "iblack": "", 55 | "ired": "", 56 | "igreen": "", 57 | "iyellow": "", 58 | "iblue": "", 59 | "ipurple": "", 60 | "icyan": "", 61 | "iwhite": "", 62 | "biblack": "", 63 | "bired": "", 64 | "bigreen": "", 65 | "biyellow": "", 66 | "biblue": "", 67 | "bipurple": "", 68 | "bicyan": "", 69 | "biwhite": "" 70 | } 71 | ], 72 | "meta": { 73 | "nf-test": "0.8.4", 74 | "nextflow": "23.10.1" 75 | }, 76 | "timestamp": "2024-02-28T12:03:17.969323" 77 | }, 78 | "Test Function with logColours": { 79 | "content": [ 80 | { 81 | "reset": "\u001b[0m", 82 | "bold": "\u001b[1m", 83 | "dim": "\u001b[2m", 84 | "underlined": "\u001b[4m", 85 | "blink": "\u001b[5m", 86 | "reverse": "\u001b[7m", 87 | "hidden": "\u001b[8m", 88 | "black": "\u001b[0;30m", 89 | "red": "\u001b[0;31m", 90 | "green": "\u001b[0;32m", 91 | "yellow": "\u001b[0;33m", 92 | "blue": "\u001b[0;34m", 93 | "purple": "\u001b[0;35m", 94 | "cyan": "\u001b[0;36m", 95 | "white": "\u001b[0;37m", 96 | "bblack": "\u001b[1;30m", 97 | "bred": "\u001b[1;31m", 98 | "bgreen": "\u001b[1;32m", 99 | "byellow": "\u001b[1;33m", 100 | "bblue": "\u001b[1;34m", 101 | "bpurple": "\u001b[1;35m", 102 | "bcyan": "\u001b[1;36m", 103 | "bwhite": "\u001b[1;37m", 104 | "ublack": "\u001b[4;30m", 105 | "ured": "\u001b[4;31m", 106 | "ugreen": "\u001b[4;32m", 107 | "uyellow": "\u001b[4;33m", 108 | "ublue": "\u001b[4;34m", 109 | "upurple": "\u001b[4;35m", 110 | "ucyan": "\u001b[4;36m", 111 | "uwhite": "\u001b[4;37m", 112 | "iblack": "\u001b[0;90m", 113 | "ired": "\u001b[0;91m", 114 | "igreen": "\u001b[0;92m", 115 | "iyellow": "\u001b[0;93m", 116 | "iblue": "\u001b[0;94m", 117 | "ipurple": "\u001b[0;95m", 118 | "icyan": "\u001b[0;96m", 119 | "iwhite": "\u001b[0;97m", 120 | "biblack": "\u001b[1;90m", 121 | "bired": "\u001b[1;91m", 122 | "bigreen": "\u001b[1;92m", 123 | "biyellow": "\u001b[1;93m", 124 | "biblue": "\u001b[1;94m", 125 | "bipurple": "\u001b[1;95m", 126 | "bicyan": "\u001b[1;96m", 127 | "biwhite": "\u001b[1;97m" 128 | } 129 | ], 130 | "meta": { 131 | "nf-test": "0.8.4", 132 | "nextflow": "23.10.1" 133 | }, 134 | "timestamp": "2024-02-28T12:03:21.714424" 135 | } 136 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg?labelColor=000000)](https://www.nextflow.io/) 2 | 3 | > THIS IS A PROOF-OF-CONCEPT REPOSITORY THAT IS UNDER ACTIVE DEVELOPMENT. SYNTAX, ORGANISATION AND LAYOUT MAY CHANGE WITHOUT NOTICE! 4 | 5 | ## Introduction 6 | 7 | **nf-dragen** is a simple, proof-of-concept pipeline to run the [Illumina DRAGEN](https://emea.illumina.com/products/by-type/informatics-products/dragen-bio-it-platform.html) licensed suite of tools. 8 | 9 | The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker containers making installation trivial and results highly reproducible. This pipeline has only been tested on AWS Batch. 10 | 11 | ## Integration with Seqera Platform 12 | 13 | We have streamlined the process of deploying Nextflow workflows that utilise Illumina DRAGEN on AWS Batch via Seqera. 14 | 15 | ### Prerequisites 16 | 17 | #### Credentials 18 | 19 | You will need to obtain the following information from the Illumina DRAGEN team: 20 | 21 | 1. Private AMI id in an AWS region with DRAGEN F1 instance availability 22 | 2. Username to run DRAGEN on the CLI via Nextflow 23 | 3. Password to run DRAGEN on the CLI via Nextflow 24 | 25 | #### Pipeline implementation 26 | 27 | Please see the [dragen.nf](modules/local/dragen.nf) module implemented in this pipeline for reference. 28 | 29 | Any Nextflow processes calling the `dragen` command must have: 30 | 31 | 1. `label dragen` ([see docs](https://www.nextflow.io/docs/latest/process.html?highlight=label#label)). This is how Seqera will determine which processes need to be specifically executed on DRAGEN F1 instances. 32 | 33 | ```nextflow 34 | process DRAGEN { 35 | label 'dragen' 36 | 37 | 38 | } 39 | ``` 40 | 41 | 2. `secret DRAGEN_USERNAME` and `secret DRAGEN_PASSWORD` ([see docs](https://www.nextflow.io/docs/latest/secrets.html?highlight=secrets#secrets)). These Secrets will be provided securely to the `--lic-server` option when running DRAGEN on the CLI to validate the license. 42 | 43 | ```nextflow 44 | process DRAGEN { 45 | secret 'DRAGEN_USERNAME' 46 | secret 'DRAGEN_PASSWORD' 47 | 48 | 49 | 50 | script: 51 | """ 52 | /opt/edico/bin/dragen \\ 53 | --lic-server=\$DRAGEN_USERNAME:\$DRAGEN_PASSWORD@license.edicogenome.com \\ 54 | 55 | """ 56 | } 57 | ``` 58 | 59 | ### Compute Environment 60 | 61 | You can use Seqera Batch Forge to automatically create a separate AWS Batch queue with dedicated F1 instances to run DRAGEN. 62 | 63 | In the Seqera UI, go to `Compute Environments` -> `Add Compute Environment` and fill in the appropriate settings for your AWS Batch environment. Additionally, you will be able to paste your private DRAGEN AMI id as shown in the image below: 64 | 65 | ![Seqera enable DRAGEN](docs/images/tower_ce_enable_dragen.png) 66 | 67 | Click on `Add` to create the Compute Environment. 68 | 69 | > Please ensure that the `Region` you select contains DRAGEN F1 instances. 70 | 71 | ### Secrets 72 | 73 | As outlined in [this blog](https://seqera.io/blog/pipeline-secrets-secure-handling-of-sensitive-information-in-tower/) you can add Secrets to Seqera to safely encrypt the username and password information required to run DRAGEN via Nextflow. 74 | 75 | In the Seqera UI, go to `Secrets` -> `Add Pipeline Secret` and add both of the Secrets as shown in the images below: 76 | 77 | 1. `DRAGEN_USERNAME` 78 | 79 | ![Seqera Secrets DRAGEN username](docs/images/tower_secrets_dragen_username.png) 80 | 81 | 2. `DRAGEN_PASSWORD` 82 | 83 | ![Seqera Secrets DRAGEN password](docs/images/tower_secrets_dragen_password.png) 84 | 85 | ### Pipeline 86 | 87 | In the Seqera UI, go to `Launchpad` -> `Add Pipeline`. Fill in the appropriate details to add your pipeline and ensure that the Compute Environment and Secrets you created previously are both defined for use by the pipeline: 88 | 89 | ![Seqera Pipeline Secrets](docs/images/tower_pipeline_secrets.png) 90 | 91 | Click on `Add` to create the pipeline and launch it when you are ready! 92 | 93 | ## Credits 94 | 95 | nf-dragen was originally written by [Harshil Patel](https://github.com/drpatelh) and [Graham Wright](https://github.com/gwright99) and [Paolo Di Tommasso](https://github.com/pditommaso), [Seqera Labs](https://seqera.io/). 96 | 97 | ## Citations 98 | 99 | The nf-core pipeline template was used to create the skeleton of this pipeline but there are no plans to contribute it to nf-core at this point. 100 | 101 | You can cite the `nf-core` publication as follows: 102 | 103 | > **The nf-core framework for community-curated bioinformatics pipelines.** 104 | > 105 | > Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen. 106 | > 107 | > _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). 108 | -------------------------------------------------------------------------------- /subworkflows/local/utils_nfcore_dragen_pipeline/main.nf: -------------------------------------------------------------------------------- 1 | // 2 | // Subworkflow with functionality specific to the seqeralabs/nf-dragen pipeline 3 | // 4 | 5 | /* 6 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 | IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | */ 10 | 11 | include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' 12 | include { paramsSummaryMap } from 'plugin/nf-schema' 13 | include { samplesheetToList } from 'plugin/nf-schema' 14 | include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' 15 | include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' 16 | include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' 17 | 18 | /* 19 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20 | SUBWORKFLOW TO INITIALISE PIPELINE 21 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | */ 23 | 24 | workflow PIPELINE_INITIALISATION { 25 | 26 | take: 27 | version // boolean: Display version and exit 28 | help // boolean: Display help text 29 | validate_params // boolean: Boolean whether to validate parameters against the schema at runtime 30 | monochrome_logs // boolean: Do not use coloured log outputs 31 | nextflow_cli_args // array: List of positional nextflow CLI args 32 | outdir // string: The output directory where the results will be saved 33 | input // string: Path to input samplesheet 34 | 35 | main: 36 | 37 | ch_versions = Channel.empty() 38 | 39 | // 40 | // Print version and exit if required and dump pipeline parameters to JSON file 41 | // 42 | UTILS_NEXTFLOW_PIPELINE ( 43 | version, 44 | true, 45 | outdir, 46 | workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1 47 | ) 48 | 49 | // 50 | // Validate parameters and generate parameter summary to stdout 51 | // 52 | UTILS_NFSCHEMA_PLUGIN ( 53 | workflow, 54 | validate_params, 55 | null 56 | ) 57 | 58 | // 59 | // Check config provided to the pipeline 60 | // 61 | UTILS_NFCORE_PIPELINE ( 62 | nextflow_cli_args 63 | ) 64 | 65 | // 66 | // Custom validation for pipeline parameters 67 | // 68 | validateInputParameters() 69 | 70 | // 71 | // Create channel from input file provided through params.input 72 | // 73 | 74 | Channel 75 | .fromList(samplesheetToList(params.input, "${projectDir}/assets/schema_input.json")) 76 | .map { meta, fastq_1, fastq_2 -> 77 | return [ 78 | meta + [ seq_type: meta.seq_type ?: params.seq_type], 79 | fastq_1, 80 | fastq_2 81 | ] 82 | } 83 | .groupTuple() 84 | .map { meta, fastq_1, fastq_2 -> 85 | return [ 86 | meta, 87 | fastq_1.flatten(), 88 | fastq_2.flatten() 89 | ] 90 | } 91 | .set { ch_samplesheet } 92 | 93 | emit: 94 | samplesheet = ch_samplesheet 95 | versions = ch_versions 96 | } 97 | 98 | /* 99 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 100 | SUBWORKFLOW FOR PIPELINE COMPLETION 101 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 102 | */ 103 | 104 | workflow PIPELINE_COMPLETION { 105 | 106 | take: 107 | outdir // path: Path to output directory where results will be published 108 | monochrome_logs // boolean: Disable ANSI colour codes in log output 109 | multiqc_report // string: Path to MultiQC report 110 | 111 | main: 112 | summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") 113 | def multiqc_reports = multiqc_report.toList() 114 | 115 | // 116 | // Completion email and summary 117 | // 118 | workflow.onComplete { 119 | 120 | completionSummary(monochrome_logs) 121 | } 122 | 123 | workflow.onError { 124 | log.error "Pipeline failed. Please refer to troubleshooting docs: https://nf-co.re/docs/usage/troubleshooting" 125 | } 126 | } 127 | 128 | /* 129 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 130 | FUNCTIONS 131 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 132 | */ 133 | // 134 | // Check and validate pipeline parameters 135 | // 136 | def validateInputParameters() { 137 | genomeExistsError() 138 | } 139 | 140 | // 141 | // Get attribute from genome config file e.g. fasta 142 | // 143 | def getGenomeAttribute(attribute) { 144 | if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { 145 | if (params.genomes[ params.genome ].containsKey(attribute)) { 146 | return params.genomes[ params.genome ][ attribute ] 147 | } 148 | } 149 | return null 150 | } 151 | 152 | // 153 | // Exit pipeline if incorrect --genome key provided 154 | // 155 | def genomeExistsError() { 156 | if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { 157 | def error_string = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + 158 | " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + 159 | " Currently, the available genome keys are:\n" + 160 | " ${params.genomes.keySet().join(", ")}\n" + 161 | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 162 | error(error_string) 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # `seqeralabs/nf-dragen`: Contributing Guidelines 2 | 3 | Hi there! 4 | Many thanks for taking an interest in improving seqeralabs/nf-dragen. 5 | 6 | We try to manage the required tasks for seqeralabs/nf-dragen using GitHub issues, you probably came to this page when creating one. 7 | Please use the pre-filled template to save time. 8 | 9 | However, don't be put off by this template - other more general issues and suggestions are welcome! 10 | Contributions to the code are even more welcome ;) 11 | 12 | ## Contribution workflow 13 | 14 | If you'd like to write some code for seqeralabs/nf-dragen, the standard workflow is as follows: 15 | 16 | 1. Check that there isn't already an issue about your idea in the [seqeralabs/nf-dragen issues](https://github.com/seqeralabs/nf-dragen/issues) to avoid duplicating work. If there isn't one already, please create one so that others know you're working on this 17 | 2. [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the [seqeralabs/nf-dragen repository](https://github.com/seqeralabs/nf-dragen) to your GitHub account 18 | 3. Make the necessary changes / additions within your forked repository following [Pipeline conventions](#pipeline-contribution-conventions) 19 | 4. Use `nf-core pipelines schema build` and add any new parameters to the pipeline JSON schema (requires [nf-core tools](https://github.com/nf-core/tools) >= 1.10). 20 | 5. Submit a Pull Request against the `dev` branch and wait for the code to be reviewed and merged 21 | 22 | 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/). 23 | 24 | ## Tests 25 | 26 | You have the option to test your changes locally by running the pipeline. For receiving warnings about process selectors and other `debug` information, it is recommended to use the debug profile. Execute all the tests with the following command: 27 | 28 | ```bash 29 | nf-test test --profile debug,test,docker --verbose 30 | ``` 31 | 32 | When you create a pull request with changes, [GitHub Actions](https://github.com/features/actions) will run automatic tests. 33 | Typically, pull-requests are only fully reviewed when these tests are passing, though of course we can help out before then. 34 | 35 | There are typically two types of tests that run: 36 | 37 | ### Lint tests 38 | 39 | `nf-core` has a [set of guidelines](https://nf-co.re/developers/guidelines) which all pipelines must adhere to. 40 | 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 pipelines lint ` command. 41 | 42 | If any failures or warnings are encountered, please follow the listed URL for more documentation. 43 | 44 | ### Pipeline tests 45 | 46 | Each `nf-core` pipeline should be set up with a minimal set of test-data. 47 | `GitHub Actions` then runs the pipeline on this data to ensure that it exits successfully. 48 | If there are any failures then the automated tests fail. 49 | 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. 50 | 51 | ## Patch 52 | 53 | :warning: Only in the unlikely and regretful event of a release happening with a bug. 54 | 55 | - On your own fork, make a new branch `patch` based on `upstream/main` or `upstream/master`. 56 | - Fix the bug, and bump version (X.Y.Z+1). 57 | - Open a pull-request from `patch` to `main`/`master` with the changes. 58 | 59 | ## Pipeline contribution conventions 60 | 61 | To make the `seqeralabs/nf-dragen` code and processing logic more understandable for new contributors and to ensure quality, we semi-standardise the way the code and other contributions are written. 62 | 63 | ### Adding a new step 64 | 65 | If you wish to contribute a new step, please use the following coding standards: 66 | 67 | 1. Define the corresponding input channel into your new process from the expected previous process channel. 68 | 2. Write the process block (see below). 69 | 3. Define the output channel if needed (see below). 70 | 4. Add any new parameters to `nextflow.config` with a default (see below). 71 | 5. Add any new parameters to `nextflow_schema.json` with help text (via the `nf-core pipelines schema build` tool). 72 | 6. Add sanity checks and validation for all relevant parameters. 73 | 7. Perform local tests to validate that the new code works as expected. 74 | 8. If applicable, add a new test command in `.github/workflow/ci.yml`. 75 | 9. Update MultiQC config `assets/multiqc_config.yml` so relevant suffixes, file name clean up and module plots are in the appropriate order. If applicable, add a [MultiQC](https://https://multiqc.info/) module. 76 | 10. Add a description of the output files and if relevant any appropriate images from the MultiQC report to `docs/output.md`. 77 | 78 | ### Default values 79 | 80 | Parameters should be initialised / defined with default values within the `params` scope in `nextflow.config`. 81 | 82 | Once there, use `nf-core pipelines schema build` to add to `nextflow_schema.json`. 83 | 84 | ### Default processes resource requirements 85 | 86 | Sensible defaults for process resource requirements (CPUs / memory / time) for a process should be defined in `conf/base.config`. These should generally be specified generic with `withLabel:` selectors so they can be shared across multiple processes/steps of the pipeline. A nf-core standard set of labels that should be followed where possible can be seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/main/nf_core/pipeline-template/conf/base.config), which has the default process as a single core-process, and then different levels of multi-core configurations for increasingly large memory requirements defined with standardised labels. 87 | 88 | The process resources can be passed on to the tool dynamically within the process with the `${task.cpus}` and `${task.memory}` variables in the `script:` block. 89 | 90 | ### Naming schemes 91 | 92 | Please use the following naming schemes, to make it easy to understand what is going where. 93 | 94 | - initial process channel: `ch_output_from_` 95 | - intermediate and terminal channels: `ch__for_` 96 | 97 | ### Nextflow version bumping 98 | 99 | If you are using a new feature from core Nextflow, you may bump the minimum required version of nextflow in the pipeline with: `nf-core pipelines bump-version --nextflow . [min-nf-version]` 100 | 101 | ### Images and figures 102 | 103 | For overview images and other documents we follow the nf-core [style guidelines and examples](https://nf-co.re/developers/design_guidelines). 104 | -------------------------------------------------------------------------------- /main.nf: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nextflow 2 | /* 3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 | seqeralabs/nf-dragen 5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | Github : https://github.com/seqeralabs/nf-dragen 7 | ---------------------------------------------------------------------------------------- 8 | */ 9 | 10 | /* 11 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 | IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS / WORKFLOWS 13 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 | */ 15 | 16 | include { paramsSummaryMap } from 'plugin/nf-schema' 17 | include { getGenomeAttribute } from './subworkflows/local/utils_nfcore_dragen_pipeline' 18 | include { softwareVersionsToYAML } from './subworkflows/nf-core/utils_nfcore_pipeline' 19 | include { paramsSummaryMultiqc } from './subworkflows/nf-core/utils_nfcore_pipeline' 20 | 21 | include { PIPELINE_INITIALISATION } from './subworkflows/local/utils_nfcore_dragen_pipeline' 22 | include { FASTQC } from './modules/nf-core/fastqc/main' 23 | include { DRAGEN_WORKFLOW as DRAGEN_DNA } from './workflows/dragen' 24 | include { DRAGEN_WORKFLOW as DRAGEN_RNA } from './workflows/dragen' 25 | include { MULTIQC } from './modules/nf-core/multiqc/main' 26 | include { PIPELINE_COMPLETION } from './subworkflows/local/utils_nfcore_dragen_pipeline' 27 | 28 | /* 29 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 30 | GENOME PARAMETER VALUES 31 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 32 | */ 33 | 34 | 35 | /* 36 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 37 | NAMED WORKFLOWS FOR PIPELINE 38 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 39 | */ 40 | 41 | // 42 | // WORKFLOW: Run main analysis pipeline depending on type of input 43 | // 44 | workflow SEQERALABS_DRAGEN { 45 | 46 | take: 47 | input // tuple: [ meta, [fastq_1, ...], [fastq_2, ...] ] 48 | fasta // str: path to fasta file 49 | dna_index // str: path to dragen index directory for dna 50 | rna_index // str: path to dragen index directory for rna 51 | 52 | main: 53 | 54 | ch_versions = Channel.empty() 55 | ch_multiqc_files = Channel.empty() 56 | 57 | // 58 | // FASTQC 59 | // 60 | input 61 | .filter { !params.skip_fastqc } 62 | // Coerce input to format for FASTQC input 63 | .map { meta, fastq_1, fastq_2 -> [meta, fastq_1 + fastq_2]} 64 | | FASTQC 65 | ch_versions = ch_versions.mix(FASTQC.out.versions) 66 | ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.map { it[1] }) 67 | 68 | // 69 | // WORKFLOW: Run DNA pipeline 70 | // 71 | DRAGEN_DNA ( 72 | input.filter { meta, fastq_1, fastq_2 -> meta.seq_type == 'dna' && !params.skip_dragen }, 73 | dna_index, 74 | fasta 75 | ) 76 | ch_versions = ch_versions.mix(DRAGEN_DNA.out.versions) 77 | 78 | // 79 | // WORKFLOW: Run RNA pipeline 80 | // 81 | DRAGEN_RNA ( 82 | input.filter { meta, fastq_1, fastq_2 -> meta.seq_type == 'rna' && !params.skip_dragen }, 83 | rna_index, 84 | fasta 85 | ) 86 | ch_versions = ch_versions.mix(DRAGEN_RNA.out.versions) 87 | 88 | if ( !params.skip_multiqc ) { 89 | // 90 | // MODULE: MultiQC 91 | // 92 | softwareVersionsToYAML(ch_versions) 93 | .collectFile(storeDir: "${params.outdir}/pipeline_info", name: 'nf_core_pipeline_software_mqc_versions.yml', sort: true, newLine: true) 94 | .set { ch_collated_versions } 95 | 96 | // Build custom multiqc content for the repot 97 | ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) 98 | ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config, checkIfExists: true) : Channel.empty() 99 | ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath(params.multiqc_logo, checkIfExists: true) : Channel.empty() 100 | summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") 101 | ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) 102 | ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) 103 | ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) 104 | 105 | MULTIQC ( 106 | ch_multiqc_files.collect(), 107 | ch_multiqc_config.toList(), 108 | ch_multiqc_custom_config.toList(), 109 | ch_multiqc_logo.toList(), 110 | [], 111 | [] 112 | ) 113 | multiqc_report = MULTIQC.out.report.toList() 114 | ch_versions = ch_versions.mix(MULTIQC.out.versions) 115 | } else { 116 | multiqc_report = Channel.empty() 117 | } 118 | 119 | emit: 120 | index = DRAGEN_DNA.out.index 121 | bam = DRAGEN_DNA.out.bam 122 | fastq = DRAGEN_DNA.out.fastq 123 | vcf = DRAGEN_DNA.out.vcf 124 | tbi = DRAGEN_DNA.out.tbi 125 | vcf_filtered = DRAGEN_DNA.out.vcf_filtered 126 | tbi_filtered = DRAGEN_DNA.out.tbi_filtered 127 | multiqc_report = multiqc_report 128 | versions = DRAGEN_DNA.out.versions 129 | } 130 | 131 | /* 132 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 133 | RUN MAIN WORKFLOW 134 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 135 | */ 136 | 137 | workflow { 138 | 139 | main: 140 | // 141 | // SUBWORKFLOW: Run initialisation tasks 142 | // 143 | PIPELINE_INITIALISATION ( 144 | params.version, 145 | params.help, 146 | params.validate_params, 147 | params.monochrome_logs, 148 | args, 149 | params.outdir, 150 | params.input 151 | ) 152 | 153 | // 154 | // WORKFLOW: Run main workflow 155 | // 156 | SEQERALABS_DRAGEN ( 157 | PIPELINE_INITIALISATION.out.samplesheet, 158 | params.fasta ?: getGenomeAttribute('fasta'), 159 | params.dragen_index_dna ?: getGenomeAttribute('dragen_index_dna'), 160 | params.dragen_index_rna ?: getGenomeAttribute('dragen_index_rna') 161 | ) 162 | // 163 | // SUBWORKFLOW: Run completion tasks 164 | // 165 | PIPELINE_COMPLETION ( 166 | params.outdir, 167 | params.monochrome_logs, 168 | SEQERALABS_DRAGEN.out.multiqc_report 169 | ) 170 | } 171 | 172 | /* 173 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 174 | THE END 175 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 176 | */ 177 | -------------------------------------------------------------------------------- /nextflow.config: -------------------------------------------------------------------------------- 1 | /* 2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 | seqeralabs/dragen Nextflow config file 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | Default config options for all compute environments 6 | ---------------------------------------------------------------------------------------- 7 | */ 8 | 9 | // Global default params, used in configs 10 | params { 11 | 12 | // Input options 13 | input = null 14 | seq_type = 'dna' 15 | 16 | // References 17 | genome = null 18 | igenomes_ignore = false 19 | igenomes_base = 's3://ngi-igenomes/igenomes/' 20 | fasta = null 21 | dragen_index_dna = null 22 | dragen_index_rna = null 23 | multiqc_config = null 24 | multiqc_title = null 25 | multiqc_logo = null 26 | max_multiqc_email_size = '25.MB' 27 | multiqc_methods_description = null 28 | 29 | // Tools 30 | skip_fastqc = false 31 | skip_multiqc = false 32 | skip_dragen = false 33 | 34 | // Boilerplate options 35 | outdir = null 36 | publish_dir_mode = 'copy' 37 | monochrome_logs = false 38 | help = false 39 | help_full = false 40 | show_hidden = false 41 | version = false 42 | pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/' 43 | trace_report_suffix = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') 44 | 45 | // Schema validation default options 46 | validate_params = true 47 | } 48 | 49 | // Load base.config by default for all pipelines 50 | includeConfig 'conf/base.config' 51 | 52 | profiles { 53 | debug { 54 | dumpHashes = true 55 | process.beforeScript = 'echo $HOSTNAME' 56 | cleanup = false 57 | nextflow.enable.configProcessNamesValidation = true 58 | } 59 | conda { 60 | conda.enabled = true 61 | docker.enabled = false 62 | singularity.enabled = false 63 | podman.enabled = false 64 | shifter.enabled = false 65 | charliecloud.enabled = false 66 | conda.channels = ['conda-forge', 'bioconda'] 67 | apptainer.enabled = false 68 | } 69 | mamba { 70 | conda.enabled = true 71 | conda.useMamba = true 72 | docker.enabled = false 73 | singularity.enabled = false 74 | podman.enabled = false 75 | shifter.enabled = false 76 | charliecloud.enabled = false 77 | apptainer.enabled = false 78 | } 79 | docker { 80 | docker.enabled = true 81 | conda.enabled = false 82 | singularity.enabled = false 83 | podman.enabled = false 84 | shifter.enabled = false 85 | charliecloud.enabled = false 86 | apptainer.enabled = false 87 | docker.runOptions = '-u $(id -u):$(id -g)' 88 | } 89 | arm { 90 | docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' 91 | } 92 | singularity { 93 | singularity.enabled = true 94 | singularity.autoMounts = true 95 | conda.enabled = false 96 | docker.enabled = false 97 | podman.enabled = false 98 | shifter.enabled = false 99 | charliecloud.enabled = false 100 | apptainer.enabled = false 101 | } 102 | podman { 103 | podman.enabled = true 104 | conda.enabled = false 105 | docker.enabled = false 106 | singularity.enabled = false 107 | shifter.enabled = false 108 | charliecloud.enabled = false 109 | apptainer.enabled = false 110 | } 111 | shifter { 112 | shifter.enabled = true 113 | conda.enabled = false 114 | docker.enabled = false 115 | singularity.enabled = false 116 | podman.enabled = false 117 | charliecloud.enabled = false 118 | apptainer.enabled = false 119 | } 120 | charliecloud { 121 | charliecloud.enabled = true 122 | conda.enabled = false 123 | docker.enabled = false 124 | singularity.enabled = false 125 | podman.enabled = false 126 | shifter.enabled = false 127 | apptainer.enabled = false 128 | } 129 | apptainer { 130 | apptainer.enabled = true 131 | apptainer.autoMounts = true 132 | conda.enabled = false 133 | docker.enabled = false 134 | singularity.enabled = false 135 | podman.enabled = false 136 | shifter.enabled = false 137 | charliecloud.enabled = false 138 | } 139 | wave { 140 | apptainer.ociAutoPull = true 141 | singularity.ociAutoPull = true 142 | wave.enabled = true 143 | wave.freeze = true 144 | wave.strategy = 'conda,container' 145 | } 146 | test { includeConfig 'conf/test.config' } 147 | test_full { includeConfig 'conf/test_full.config' } 148 | } 149 | 150 | 151 | 152 | // Set default registry for Apptainer, Docker, Podman, Charliecloud and Singularity independent of -profile 153 | // Will not be used unless Apptainer / Docker / Podman / Charliecloud / Singularity are enabled 154 | // Set to your registry if you have a mirror of containers 155 | apptainer.registry = 'quay.io' 156 | docker.registry = 'quay.io' 157 | podman.registry = 'quay.io' 158 | singularity.registry = 'quay.io' 159 | charliecloud.registry = 'quay.io' 160 | 161 | // Load igenomes.config if required 162 | includeConfig !params.igenomes_ignore ? 'conf/igenomes.config' : 'conf/igenomes_ignored.config' 163 | 164 | // Export these variables to prevent local Python/R libraries from conflicting with those in the container 165 | // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. 166 | // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. 167 | 168 | env { 169 | PYTHONNOUSERSITE = 1 170 | R_PROFILE_USER = "/.Rprofile" 171 | R_ENVIRON_USER = "/.Renviron" 172 | JULIA_DEPOT_PATH = "/usr/local/share/julia" 173 | } 174 | 175 | // Set bash options 176 | process.shell = """\ 177 | bash 178 | 179 | set -e # Exit if a tool returns a non-zero status/exit code 180 | set -u # Treat unset variables and parameters as an error 181 | set -o pipefail # Returns the status of the last command to exit with a non-zero status or zero if all successfully execute 182 | set -C # No clobber - prevent output redirection from overwriting files. 183 | """ 184 | 185 | // Disable process selector warnings by default. Use debug profile to enable warnings. 186 | nextflow.enable.configProcessNamesValidation = false 187 | 188 | timeline { 189 | enabled = true 190 | file = "${params.outdir}/pipeline_info/execution_timeline_${params.trace_report_suffix}.html" 191 | } 192 | report { 193 | enabled = true 194 | file = "${params.outdir}/pipeline_info/execution_report_${params.trace_report_suffix}.html" 195 | } 196 | trace { 197 | enabled = true 198 | file = "${params.outdir}/pipeline_info/execution_trace_${params.trace_report_suffix}.txt" 199 | } 200 | dag { 201 | enabled = true 202 | file = "${params.outdir}/pipeline_info/pipeline_dag_${params.trace_report_suffix}.html" 203 | } 204 | 205 | manifest { 206 | name = 'seqeralabs/nf-dragen' 207 | author = """Adam Talbot, Harshil Patel, Graham Wright""" // The author field is deprecated from Nextflow version 24.10.0, use contributors instead 208 | contributors = [ 209 | [ 210 | name: 'Adam Talbot', 211 | affiliation: 'Seqera', 212 | email: 'adam.talbot@seqera.io', 213 | github: '@adamrtalbot', 214 | contribution: ['maintainer'], // List of contribution types ('author', 'maintainer' or 'contributor') 215 | orcid: '' 216 | ], 217 | [ 218 | name: 'Harshil Patel', 219 | affiliation: 'Seqera', 220 | email: 'harshil.patel@seqera.io', 221 | github: '@drpatelh', 222 | contribution: ['author'], // List of contribution types ('author', 'maintainer' or 'contributor') 223 | orcid: '' 224 | ], 225 | [ 226 | name: 'Graham Wright', 227 | affiliation: 'Seqera', 228 | email: 'graham.wright@seqera.io', 229 | github: '@gwright99', 230 | contribution: ['contributor'], // List of contribution types ('author', 'maintainer' or 'contributor') 231 | orcid: '' 232 | ], 233 | ] 234 | homePage = 'https://github.com/seqeralabs/nf-dragen' 235 | description = """nf-dragen is a simple, proof-of-concept Nextflow pipeline to run the Illumina DRAGEN licensed suite of tools.""" 236 | mainScript = 'main.nf' 237 | defaultBranch = 'master' 238 | nextflowVersion = '!>=24.04.2' 239 | version = '1.0.0dev' 240 | doi = '' 241 | } 242 | 243 | // Nextflow plugins 244 | plugins { 245 | id 'nf-schema@2.1.1' // Validation of pipeline parameters and creation of an input channel from a sample sheet 246 | } 247 | 248 | validation { 249 | defaultIgnoreParams = ["genomes"] 250 | monochromeLogs = params.monochrome_logs 251 | help { 252 | enabled = true 253 | command = "nextflow run seqeralabs/nf-dragen -profile --input samplesheet.csv --outdir " 254 | fullParameter = "help_full" 255 | showHiddenParameter = "show_hidden" 256 | } 257 | } 258 | 259 | // Load modules.config for DSL2 module specific options 260 | includeConfig 'conf/modules.config' 261 | -------------------------------------------------------------------------------- /nextflow_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://raw.githubusercontent.com/seqeralabs/nf-dragen/master/nextflow_schema.json", 4 | "title": "seqeralabs/nf-dragen pipeline parameters", 5 | "description": "nf-dragen is a simple, proof-of-concept Nextflow pipeline to run the Illumina DRAGEN licensed suite of tools.", 6 | "type": "object", 7 | "$defs": { 8 | "input_output_options": { 9 | "title": "Input/output options", 10 | "type": "object", 11 | "fa_icon": "fas fa-terminal", 12 | "description": "Define where the pipeline should find input data and save output data.", 13 | "required": ["input", "outdir"], 14 | "properties": { 15 | "input": { 16 | "type": "string", 17 | "format": "file-path", 18 | "exists": true, 19 | "schema": "assets/schema_input.json", 20 | "mimetype": "text/csv", 21 | "pattern": "^\\S+\\.csv$", 22 | "description": "Path to comma-separated file containing information about the samples in the experiment.", 23 | "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row.", 24 | "fa_icon": "fas fa-file-csv" 25 | }, 26 | "outdir": { 27 | "type": "string", 28 | "format": "directory-path", 29 | "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", 30 | "fa_icon": "fas fa-folder-open" 31 | }, 32 | "seq_type": { 33 | "type": "string", 34 | "default": "dna", 35 | "description": "Default type of sequencing (dna, rna etc). Can be overridden in the samplesheet using the column `seq_type`.", 36 | "fa_icon": "fas fa-dna", 37 | "enum": ["dna", "rna"] 38 | }, 39 | "multiqc_title": { 40 | "type": "string", 41 | "description": "MultiQC report title. Printed as page header, used for filename if not otherwise specified.", 42 | "fa_icon": "fas fa-file-signature" 43 | } 44 | } 45 | }, 46 | "tools": { 47 | "title": "Tools", 48 | "type": "object", 49 | "description": "Control pipeline behaviour", 50 | "default": "", 51 | "properties": { 52 | "skip_fastqc": { 53 | "type": "boolean", 54 | "description": "Skip running FASTQC" 55 | }, 56 | "skip_multiqc": { 57 | "type": "boolean", 58 | "description": "Skip running MultiQC" 59 | }, 60 | "skip_dragen": { 61 | "type": "boolean", 62 | "description": "Skip running DRAGEN steps" 63 | } 64 | } 65 | }, 66 | "reference_genome_options": { 67 | "title": "Reference genome options", 68 | "type": "object", 69 | "fa_icon": "fas fa-dna", 70 | "description": "Reference genome related files and options required for the workflow.", 71 | "properties": { 72 | "genome": { 73 | "type": "string", 74 | "description": "Name of iGenomes reference.", 75 | "fa_icon": "fas fa-book", 76 | "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." 77 | }, 78 | "fasta": { 79 | "type": "string", 80 | "description": "Path to FASTA file", 81 | "fa_icon": "fas fa-dna" 82 | }, 83 | "dragen_index_dna": { 84 | "type": "string", 85 | "description": "Path to DNA index created by Dragen.", 86 | "help_text": "Use a DNA index created using Dragen with argument '--build-hash-table true'. This parameter is *mandatory* if `--fasta` or `--genome` is not specified.", 87 | "fa_icon": "far fa-file-alt", 88 | "format": "directory-path" 89 | }, 90 | "dragen_index_rna": { 91 | "type": "string", 92 | "description": "Path to RNA index created by Dragen.", 93 | "help_text": "Use a DNA index created using Dragen with argument '--build-hash-table true' and '--ht-build-rna-hashtable true'. This parameter is *mandatory* if `--fasta` or `--genome` is not specified.", 94 | "fa_icon": "far fa-file-alt", 95 | "format": "directory-path" 96 | }, 97 | "igenomes_ignore": { 98 | "type": "boolean", 99 | "description": "Do not load the iGenomes reference config.", 100 | "fa_icon": "fas fa-ban", 101 | "hidden": true, 102 | "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`." 103 | }, 104 | "igenomes_base": { 105 | "type": "string", 106 | "format": "directory-path", 107 | "description": "The base path to the igenomes reference files", 108 | "fa_icon": "fas fa-ban", 109 | "hidden": true, 110 | "default": "s3://ngi-igenomes/igenomes/" 111 | } 112 | } 113 | }, 114 | "generic_options": { 115 | "title": "Generic options", 116 | "type": "object", 117 | "fa_icon": "fas fa-file-import", 118 | "description": "Less common options for the pipeline, typically set in a config file.", 119 | "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`.", 120 | "properties": { 121 | "version": { 122 | "type": "boolean", 123 | "description": "Display version and exit.", 124 | "fa_icon": "fas fa-question-circle", 125 | "hidden": true 126 | }, 127 | "publish_dir_mode": { 128 | "type": "string", 129 | "default": "copy", 130 | "description": "Method used to save pipeline results to output directory.", 131 | "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.", 132 | "fa_icon": "fas fa-copy", 133 | "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], 134 | "hidden": true 135 | }, 136 | "max_multiqc_email_size": { 137 | "type": "string", 138 | "description": "File size limit when attaching MultiQC reports to summary emails.", 139 | "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", 140 | "default": "25.MB", 141 | "fa_icon": "fas fa-file-upload", 142 | "hidden": true 143 | }, 144 | "monochrome_logs": { 145 | "type": "boolean", 146 | "description": "Do not use coloured log outputs.", 147 | "fa_icon": "fas fa-palette", 148 | "hidden": true 149 | }, 150 | "multiqc_config": { 151 | "type": "string", 152 | "format": "file-path", 153 | "description": "Custom config file to supply to MultiQC.", 154 | "fa_icon": "fas fa-cog", 155 | "hidden": true 156 | }, 157 | "multiqc_logo": { 158 | "type": "string", 159 | "description": "Custom logo file to supply to MultiQC. File name must also be set in the MultiQC config file", 160 | "fa_icon": "fas fa-image", 161 | "hidden": true 162 | }, 163 | "multiqc_methods_description": { 164 | "type": "string", 165 | "description": "Custom MultiQC yaml file containing HTML including a methods description.", 166 | "fa_icon": "fas fa-cog", 167 | "hidden": true 168 | }, 169 | "validate_params": { 170 | "type": "boolean", 171 | "description": "Boolean whether to validate parameters against the schema at runtime", 172 | "default": true, 173 | "fa_icon": "fas fa-check-square", 174 | "hidden": true 175 | }, 176 | "pipelines_testdata_base_path": { 177 | "type": "string", 178 | "fa_icon": "far fa-check-circle", 179 | "description": "Base URL or local path to location of pipeline test dataset files", 180 | "default": "https://raw.githubusercontent.com/nf-core/test-datasets/", 181 | "hidden": true 182 | }, 183 | "trace_report_suffix": { 184 | "type": "string", 185 | "fa_icon": "far calendar", 186 | "description": "Suffix to add to the trace report filename. Default is the date and time in the format yyyy-MM-dd_HH-mm-ss.", 187 | "hidden": true 188 | } 189 | } 190 | } 191 | }, 192 | "allOf": [ 193 | { 194 | "$ref": "#/$defs/input_output_options" 195 | }, 196 | { 197 | "$ref": "#/$defs/tools" 198 | }, 199 | { 200 | "$ref": "#/$defs/reference_genome_options" 201 | }, 202 | { 203 | "$ref": "#/$defs/generic_options" 204 | } 205 | ] 206 | } 207 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /modules/nf-core/fastqc/tests/main.nf.test: -------------------------------------------------------------------------------- 1 | nextflow_process { 2 | 3 | name "Test Process FASTQC" 4 | script "../main.nf" 5 | process "FASTQC" 6 | 7 | tag "modules" 8 | tag "modules_nfcore" 9 | tag "fastqc" 10 | 11 | test("sarscov2 single-end [fastq]") { 12 | 13 | when { 14 | process { 15 | """ 16 | input[0] = Channel.of([ 17 | [ id: 'test', single_end:true ], 18 | [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] 19 | ]) 20 | """ 21 | } 22 | } 23 | 24 | then { 25 | assertAll ( 26 | { assert process.success }, 27 | // NOTE The report contains the date inside it, which means that the md5sum is stable per day, but not longer than that. So you can't md5sum it. 28 | // looks like this:
Mon 2 Oct 2023
test.gz
29 | // https://github.com/nf-core/modules/pull/3903#issuecomment-1743620039 30 | { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, 31 | { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, 32 | { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, 33 | { assert snapshot(process.out.versions).match() } 34 | ) 35 | } 36 | } 37 | 38 | test("sarscov2 paired-end [fastq]") { 39 | 40 | when { 41 | process { 42 | """ 43 | input[0] = Channel.of([ 44 | [id: 'test', single_end: false], // meta map 45 | [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), 46 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] 47 | ]) 48 | """ 49 | } 50 | } 51 | 52 | then { 53 | assertAll ( 54 | { assert process.success }, 55 | { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, 56 | { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, 57 | { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, 58 | { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, 59 | { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, 60 | { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, 61 | { assert snapshot(process.out.versions).match() } 62 | ) 63 | } 64 | } 65 | 66 | test("sarscov2 interleaved [fastq]") { 67 | 68 | when { 69 | process { 70 | """ 71 | input[0] = Channel.of([ 72 | [id: 'test', single_end: false], // meta map 73 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) 74 | ]) 75 | """ 76 | } 77 | } 78 | 79 | then { 80 | assertAll ( 81 | { assert process.success }, 82 | { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, 83 | { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, 84 | { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, 85 | { assert snapshot(process.out.versions).match() } 86 | ) 87 | } 88 | } 89 | 90 | test("sarscov2 paired-end [bam]") { 91 | 92 | when { 93 | process { 94 | """ 95 | input[0] = Channel.of([ 96 | [id: 'test', single_end: false], // meta map 97 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) 98 | ]) 99 | """ 100 | } 101 | } 102 | 103 | then { 104 | assertAll ( 105 | { assert process.success }, 106 | { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, 107 | { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, 108 | { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, 109 | { assert snapshot(process.out.versions).match() } 110 | ) 111 | } 112 | } 113 | 114 | test("sarscov2 multiple [fastq]") { 115 | 116 | when { 117 | process { 118 | """ 119 | input[0] = Channel.of([ 120 | [id: 'test', single_end: false], // meta map 121 | [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), 122 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), 123 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), 124 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] 125 | ]) 126 | """ 127 | } 128 | } 129 | 130 | then { 131 | assertAll ( 132 | { assert process.success }, 133 | { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, 134 | { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, 135 | { assert process.out.html[0][1][2] ==~ ".*/test_3_fastqc.html" }, 136 | { assert process.out.html[0][1][3] ==~ ".*/test_4_fastqc.html" }, 137 | { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, 138 | { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, 139 | { assert process.out.zip[0][1][2] ==~ ".*/test_3_fastqc.zip" }, 140 | { assert process.out.zip[0][1][3] ==~ ".*/test_4_fastqc.zip" }, 141 | { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, 142 | { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, 143 | { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, 144 | { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, 145 | { assert snapshot(process.out.versions).match() } 146 | ) 147 | } 148 | } 149 | 150 | test("sarscov2 custom_prefix") { 151 | 152 | when { 153 | process { 154 | """ 155 | input[0] = Channel.of([ 156 | [ id:'mysample', single_end:true ], // meta map 157 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) 158 | ]) 159 | """ 160 | } 161 | } 162 | 163 | then { 164 | assertAll ( 165 | { assert process.success }, 166 | { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, 167 | { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, 168 | { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, 169 | { assert snapshot(process.out.versions).match() } 170 | ) 171 | } 172 | } 173 | 174 | test("sarscov2 single-end [fastq] - stub") { 175 | 176 | options "-stub" 177 | when { 178 | process { 179 | """ 180 | input[0] = Channel.of([ 181 | [ id: 'test', single_end:true ], 182 | [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] 183 | ]) 184 | """ 185 | } 186 | } 187 | 188 | then { 189 | assertAll ( 190 | { assert process.success }, 191 | { assert snapshot(process.out).match() } 192 | ) 193 | } 194 | } 195 | 196 | test("sarscov2 paired-end [fastq] - stub") { 197 | 198 | options "-stub" 199 | when { 200 | process { 201 | """ 202 | input[0] = Channel.of([ 203 | [id: 'test', single_end: false], // meta map 204 | [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), 205 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] 206 | ]) 207 | """ 208 | } 209 | } 210 | 211 | then { 212 | assertAll ( 213 | { assert process.success }, 214 | { assert snapshot(process.out).match() } 215 | ) 216 | } 217 | } 218 | 219 | test("sarscov2 interleaved [fastq] - stub") { 220 | 221 | options "-stub" 222 | when { 223 | process { 224 | """ 225 | input[0] = Channel.of([ 226 | [id: 'test', single_end: false], // meta map 227 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) 228 | ]) 229 | """ 230 | } 231 | } 232 | 233 | then { 234 | assertAll ( 235 | { assert process.success }, 236 | { assert snapshot(process.out).match() } 237 | ) 238 | } 239 | } 240 | 241 | test("sarscov2 paired-end [bam] - stub") { 242 | 243 | options "-stub" 244 | when { 245 | process { 246 | """ 247 | input[0] = Channel.of([ 248 | [id: 'test', single_end: false], // meta map 249 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) 250 | ]) 251 | """ 252 | } 253 | } 254 | 255 | then { 256 | assertAll ( 257 | { assert process.success }, 258 | { assert snapshot(process.out).match() } 259 | ) 260 | } 261 | } 262 | 263 | test("sarscov2 multiple [fastq] - stub") { 264 | 265 | options "-stub" 266 | when { 267 | process { 268 | """ 269 | input[0] = Channel.of([ 270 | [id: 'test', single_end: false], // meta map 271 | [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), 272 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), 273 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), 274 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] 275 | ]) 276 | """ 277 | } 278 | } 279 | 280 | then { 281 | assertAll ( 282 | { assert process.success }, 283 | { assert snapshot(process.out).match() } 284 | ) 285 | } 286 | } 287 | 288 | test("sarscov2 custom_prefix - stub") { 289 | 290 | options "-stub" 291 | when { 292 | process { 293 | """ 294 | input[0] = Channel.of([ 295 | [ id:'mysample', single_end:true ], // meta map 296 | file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) 297 | ]) 298 | """ 299 | } 300 | } 301 | 302 | then { 303 | assertAll ( 304 | { assert process.success }, 305 | { assert snapshot(process.out).match() } 306 | ) 307 | } 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /modules/nf-core/fastqc/tests/main.nf.test.snap: -------------------------------------------------------------------------------- 1 | { 2 | "sarscov2 custom_prefix": { 3 | "content": [ 4 | [ 5 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 6 | ] 7 | ], 8 | "meta": { 9 | "nf-test": "0.9.0", 10 | "nextflow": "24.04.3" 11 | }, 12 | "timestamp": "2024-07-22T11:02:16.374038" 13 | }, 14 | "sarscov2 single-end [fastq] - stub": { 15 | "content": [ 16 | { 17 | "0": [ 18 | [ 19 | { 20 | "id": "test", 21 | "single_end": true 22 | }, 23 | "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" 24 | ] 25 | ], 26 | "1": [ 27 | [ 28 | { 29 | "id": "test", 30 | "single_end": true 31 | }, 32 | "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 33 | ] 34 | ], 35 | "2": [ 36 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 37 | ], 38 | "html": [ 39 | [ 40 | { 41 | "id": "test", 42 | "single_end": true 43 | }, 44 | "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" 45 | ] 46 | ], 47 | "versions": [ 48 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 49 | ], 50 | "zip": [ 51 | [ 52 | { 53 | "id": "test", 54 | "single_end": true 55 | }, 56 | "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 57 | ] 58 | ] 59 | } 60 | ], 61 | "meta": { 62 | "nf-test": "0.9.0", 63 | "nextflow": "24.04.3" 64 | }, 65 | "timestamp": "2024-07-22T11:02:24.993809" 66 | }, 67 | "sarscov2 custom_prefix - stub": { 68 | "content": [ 69 | { 70 | "0": [ 71 | [ 72 | { 73 | "id": "mysample", 74 | "single_end": true 75 | }, 76 | "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" 77 | ] 78 | ], 79 | "1": [ 80 | [ 81 | { 82 | "id": "mysample", 83 | "single_end": true 84 | }, 85 | "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 86 | ] 87 | ], 88 | "2": [ 89 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 90 | ], 91 | "html": [ 92 | [ 93 | { 94 | "id": "mysample", 95 | "single_end": true 96 | }, 97 | "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" 98 | ] 99 | ], 100 | "versions": [ 101 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 102 | ], 103 | "zip": [ 104 | [ 105 | { 106 | "id": "mysample", 107 | "single_end": true 108 | }, 109 | "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 110 | ] 111 | ] 112 | } 113 | ], 114 | "meta": { 115 | "nf-test": "0.9.0", 116 | "nextflow": "24.04.3" 117 | }, 118 | "timestamp": "2024-07-22T11:03:10.93942" 119 | }, 120 | "sarscov2 interleaved [fastq]": { 121 | "content": [ 122 | [ 123 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 124 | ] 125 | ], 126 | "meta": { 127 | "nf-test": "0.9.0", 128 | "nextflow": "24.04.3" 129 | }, 130 | "timestamp": "2024-07-22T11:01:42.355718" 131 | }, 132 | "sarscov2 paired-end [bam]": { 133 | "content": [ 134 | [ 135 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 136 | ] 137 | ], 138 | "meta": { 139 | "nf-test": "0.9.0", 140 | "nextflow": "24.04.3" 141 | }, 142 | "timestamp": "2024-07-22T11:01:53.276274" 143 | }, 144 | "sarscov2 multiple [fastq]": { 145 | "content": [ 146 | [ 147 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 148 | ] 149 | ], 150 | "meta": { 151 | "nf-test": "0.9.0", 152 | "nextflow": "24.04.3" 153 | }, 154 | "timestamp": "2024-07-22T11:02:05.527626" 155 | }, 156 | "sarscov2 paired-end [fastq]": { 157 | "content": [ 158 | [ 159 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 160 | ] 161 | ], 162 | "meta": { 163 | "nf-test": "0.9.0", 164 | "nextflow": "24.04.3" 165 | }, 166 | "timestamp": "2024-07-22T11:01:31.188871" 167 | }, 168 | "sarscov2 paired-end [fastq] - stub": { 169 | "content": [ 170 | { 171 | "0": [ 172 | [ 173 | { 174 | "id": "test", 175 | "single_end": false 176 | }, 177 | "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" 178 | ] 179 | ], 180 | "1": [ 181 | [ 182 | { 183 | "id": "test", 184 | "single_end": false 185 | }, 186 | "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 187 | ] 188 | ], 189 | "2": [ 190 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 191 | ], 192 | "html": [ 193 | [ 194 | { 195 | "id": "test", 196 | "single_end": false 197 | }, 198 | "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" 199 | ] 200 | ], 201 | "versions": [ 202 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 203 | ], 204 | "zip": [ 205 | [ 206 | { 207 | "id": "test", 208 | "single_end": false 209 | }, 210 | "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 211 | ] 212 | ] 213 | } 214 | ], 215 | "meta": { 216 | "nf-test": "0.9.0", 217 | "nextflow": "24.04.3" 218 | }, 219 | "timestamp": "2024-07-22T11:02:34.273566" 220 | }, 221 | "sarscov2 multiple [fastq] - stub": { 222 | "content": [ 223 | { 224 | "0": [ 225 | [ 226 | { 227 | "id": "test", 228 | "single_end": false 229 | }, 230 | "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" 231 | ] 232 | ], 233 | "1": [ 234 | [ 235 | { 236 | "id": "test", 237 | "single_end": false 238 | }, 239 | "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 240 | ] 241 | ], 242 | "2": [ 243 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 244 | ], 245 | "html": [ 246 | [ 247 | { 248 | "id": "test", 249 | "single_end": false 250 | }, 251 | "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" 252 | ] 253 | ], 254 | "versions": [ 255 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 256 | ], 257 | "zip": [ 258 | [ 259 | { 260 | "id": "test", 261 | "single_end": false 262 | }, 263 | "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 264 | ] 265 | ] 266 | } 267 | ], 268 | "meta": { 269 | "nf-test": "0.9.0", 270 | "nextflow": "24.04.3" 271 | }, 272 | "timestamp": "2024-07-22T11:03:02.304411" 273 | }, 274 | "sarscov2 single-end [fastq]": { 275 | "content": [ 276 | [ 277 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 278 | ] 279 | ], 280 | "meta": { 281 | "nf-test": "0.9.0", 282 | "nextflow": "24.04.3" 283 | }, 284 | "timestamp": "2024-07-22T11:01:19.095607" 285 | }, 286 | "sarscov2 interleaved [fastq] - stub": { 287 | "content": [ 288 | { 289 | "0": [ 290 | [ 291 | { 292 | "id": "test", 293 | "single_end": false 294 | }, 295 | "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" 296 | ] 297 | ], 298 | "1": [ 299 | [ 300 | { 301 | "id": "test", 302 | "single_end": false 303 | }, 304 | "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 305 | ] 306 | ], 307 | "2": [ 308 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 309 | ], 310 | "html": [ 311 | [ 312 | { 313 | "id": "test", 314 | "single_end": false 315 | }, 316 | "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" 317 | ] 318 | ], 319 | "versions": [ 320 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 321 | ], 322 | "zip": [ 323 | [ 324 | { 325 | "id": "test", 326 | "single_end": false 327 | }, 328 | "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 329 | ] 330 | ] 331 | } 332 | ], 333 | "meta": { 334 | "nf-test": "0.9.0", 335 | "nextflow": "24.04.3" 336 | }, 337 | "timestamp": "2024-07-22T11:02:44.640184" 338 | }, 339 | "sarscov2 paired-end [bam] - stub": { 340 | "content": [ 341 | { 342 | "0": [ 343 | [ 344 | { 345 | "id": "test", 346 | "single_end": false 347 | }, 348 | "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" 349 | ] 350 | ], 351 | "1": [ 352 | [ 353 | { 354 | "id": "test", 355 | "single_end": false 356 | }, 357 | "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 358 | ] 359 | ], 360 | "2": [ 361 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 362 | ], 363 | "html": [ 364 | [ 365 | { 366 | "id": "test", 367 | "single_end": false 368 | }, 369 | "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" 370 | ] 371 | ], 372 | "versions": [ 373 | "versions.yml:md5,e1cc25ca8af856014824abd842e93978" 374 | ], 375 | "zip": [ 376 | [ 377 | { 378 | "id": "test", 379 | "single_end": false 380 | }, 381 | "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" 382 | ] 383 | ] 384 | } 385 | ], 386 | "meta": { 387 | "nf-test": "0.9.0", 388 | "nextflow": "24.04.3" 389 | }, 390 | "timestamp": "2024-07-22T11:02:53.550742" 391 | } 392 | } -------------------------------------------------------------------------------- /docs/usage.md: -------------------------------------------------------------------------------- 1 | # seqeralabs/nf-dragen: Usage 2 | 3 | > _Documentation of pipeline parameters is generated automatically from the pipeline schema and can no longer be found in markdown files._ 4 | 5 | ## Introduction 6 | 7 | ## Samplesheet input 8 | 9 | You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row as shown in the examples below. 10 | 11 | ```bash 12 | --input '[path to samplesheet file]' 13 | ``` 14 | 15 | ### Multiple runs of the same sample 16 | 17 | The `sample` identifiers have to be the same when you have re-sequenced the same sample more than once e.g. to increase sequencing depth. The pipeline will analyse the raw reads together in the Dragen software before performing any downstream analysis. Below is an example for the same sample sequenced across 3 lanes: 18 | 19 | ```csv title="samplesheet.csv" 20 | sample,fastq_1,fastq_2 21 | CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz 22 | CONTROL_REP1,AEG588A1_S1_L003_R1_001.fastq.gz,AEG588A1_S1_L003_R2_001.fastq.gz 23 | CONTROL_REP1,AEG588A1_S1_L004_R1_001.fastq.gz,AEG588A1_S1_L004_R2_001.fastq.gz 24 | ``` 25 | 26 | ### Sequencing type 27 | 28 | The pipeline can handle RNA or DNA samples, including a mixture of both. By default, every sample will be considered to be the type defined as `--seq_type`, which defaults to `dna`. You can override this on a per-sample basis using the `seq_type` column: 29 | 30 | ```csv 31 | sample,seq_type,fastq_1,fastq_2 32 | dnaSample,dna,dna_R1_001.fastq.gz,dna_R2_001.fastq.gz 33 | rnaSample,rna,rna_R1_001.fastq.gz,rna_R2_001.fastq.gz 34 | ``` 35 | 36 | ### Full samplesheet 37 | 38 | The pipeline will auto-detect whether a sample is single- or paired-end using the information provided in the samplesheet. The samplesheet can have as many columns as you desire, however, there is a strict requirement for the first 3 columns to match those defined in the table below. 39 | 40 | A final samplesheet file consisting of both single- and paired-end data may look something like the one below. This is for 6 samples, where `TREATMENT_REP3` has been sequenced twice. 41 | 42 | ```csv title="samplesheet.csv" 43 | sample,fastq_1,fastq_2 44 | CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz 45 | CONTROL_REP2,AEG588A2_S2_L002_R1_001.fastq.gz,AEG588A2_S2_L002_R2_001.fastq.gz 46 | CONTROL_REP3,AEG588A3_S3_L002_R1_001.fastq.gz,AEG588A3_S3_L002_R2_001.fastq.gz 47 | TREATMENT_REP1,AEG588A4_S4_L003_R1_001.fastq.gz, 48 | TREATMENT_REP2,AEG588A5_S5_L003_R1_001.fastq.gz, 49 | TREATMENT_REP3,AEG588A6_S6_L003_R1_001.fastq.gz, 50 | TREATMENT_REP3,AEG588A6_S6_L004_R1_001.fastq.gz, 51 | ``` 52 | 53 | | Column | Description | 54 | | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 55 | | `sample` | Custom sample name. This entry will be identical for multiple sequencing libraries/runs from the same sample. Spaces in sample names are automatically converted to underscores (`_`). | 56 | | `seq_type` | Sequencing type, currently restricted to `dna` or `rna`. This decides the sequencing pathway to take when running the pipeline. The pipeline can handle a mixture of sequencing types. If this is left empty, it will use `params.seq_type` as the value, default `dna`. | 57 | | `fastq_1` | Full path to FastQ file for Illumina short reads 1. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". | 58 | | `fastq_2` | Full path to FastQ file for Illumina short reads 2. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". | 59 | 60 | An [example samplesheet](../assets/samplesheet.csv) has been provided with the pipeline. 61 | 62 | ## Configuring the genome 63 | 64 | We can configure a genome in multiple ways: 65 | 66 | 1. Supply a `--genome`, which retrieves uses the genome build FASTA automatically and proceeds from step 2. 67 | 2. Supply a `--fasta` and which Dragen will build a genome index for alignment 68 | 3. If you have already performed a pipeline run using `1.` or `.2.`, the reference index will be written to a results directory at `${params.outdir}/genome/index/dragen_index_dna` or `${params.outdir}/genome/index/dragen_index_rna`. You can reuse these indexes by supplying the parameter `--dragen_index_dna` and/or `--dragen_index_rna` which will skip 1 and 2 for DNA and RNA respectively. 69 | 70 | ## Running the pipeline 71 | 72 | The typical command for running the pipeline is as follows: 73 | 74 | ```console 75 | nextflow run seqeralabs/nf-dragen --input samplesheet.csv --genome GRCh37 -profile docker 76 | ``` 77 | 78 | This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. 79 | 80 | Note that the pipeline will create the following files in your working directory: 81 | 82 | ```bash 83 | work # Directory containing the nextflow working files 84 | # Finished results in specified location (defined with --outdir) 85 | .nextflow_log # Log file from Nextflow 86 | # Other nextflow hidden files, eg. history of pipeline runs and old logs. 87 | ``` 88 | 89 | If you wish to repeatedly use the same parameters for multiple runs, rather than specifying each flag in the command, you can specify these in a params file. 90 | 91 | Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. 92 | 93 | :::warning 94 | Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). 95 | ::: 96 | 97 | The above pipeline run specified with a params file in yaml format: 98 | 99 | ```bash 100 | nextflow run seqeralabs/nf-dragen -profile docker -params-file params.yaml 101 | ``` 102 | 103 | with `params.yaml` containing: 104 | 105 | ```yaml 106 | input: './samplesheet.csv' 107 | outdir: './results/' 108 | genome: 'GRCh37' 109 | <...> 110 | ``` 111 | 112 | You can also generate such `YAML`/`JSON` files via [nf-core/launch](https://nf-co.re/launch). 113 | 114 | ### Updating the pipeline 115 | 116 | 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: 117 | 118 | ```bash 119 | nextflow pull seqeralabs/nf-dragen 120 | ``` 121 | 122 | ### Reproducibility 123 | 124 | It is a good idea to specify a pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. 125 | 126 | First, go to the [seqeralabs/nf-dragen releases page](https://github.com/seqeralabs/nf-dragen/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. 127 | 128 | This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. 129 | 130 | To further assist in reproducbility, you can use share and re-use [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. 131 | 132 | :::tip 133 | If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. 134 | ::: 135 | 136 | ## Core Nextflow arguments 137 | 138 | :::note 139 | These options are part of Nextflow and use a _single_ hyphen (pipeline parameters use a double-hyphen). 140 | ::: 141 | 142 | ### `-profile` 143 | 144 | Use this parameter to choose a configuration profile. Profiles can give configuration presets for different compute environments. 145 | 146 | Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Apptainer, Conda) - see below. 147 | 148 | :::info 149 | We highly recommend the use of Docker or Singularity containers for full pipeline reproducibility, however when this is not possible, Conda is also supported. 150 | ::: 151 | 152 | 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). 153 | 154 | Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! 155 | They are loaded in sequence, so later profiles can overwrite earlier profiles. 156 | 157 | If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer enviroment. 158 | 159 | - `test` 160 | - A profile with a complete configuration for automated testing 161 | - Includes links to test data so needs no other parameters 162 | - `docker` 163 | - A generic configuration profile to be used with [Docker](https://docker.com/) 164 | - `singularity` 165 | - A generic configuration profile to be used with [Singularity](https://sylabs.io/docs/) 166 | - `podman` 167 | - A generic configuration profile to be used with [Podman](https://podman.io/) 168 | - `shifter` 169 | - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) 170 | - `charliecloud` 171 | - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) 172 | - `apptainer` 173 | - A generic configuration profile to be used with [Apptainer](https://apptainer.org/) 174 | - `wave` 175 | - A generic configuration profile to enable [Wave](https://seqera.io/wave/) containers. Use together with one of the above (requires Nextflow ` 24.03.0-edge` or later). 176 | - `conda` 177 | - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter, Charliecloud, or Apptainer. 178 | 179 | ### `-resume` 180 | 181 | Specify this when restarting a pipeline. Nextflow will use cached results from any pipeline steps where the inputs are the same, continuing from where it got to previously. For input to be considered the same, not only the names must be identical but the files' contents as well. For more info about this parameter, see [this blog post](https://www.nextflow.io/blog/2019/demystifying-nextflow-resume.html). 182 | 183 | 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. 184 | 185 | ### `-c` 186 | 187 | 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. 188 | 189 | ## Custom configuration 190 | 191 | ### Resource requests 192 | 193 | Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the steps in the pipeline, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher requests (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. 194 | 195 | To change the resource requests, please see the [max resources](https://nf-co.re/docs/usage/configuration#max-resources) and [tuning workflow resources](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources) section of the nf-core website. 196 | 197 | ### Custom Containers 198 | 199 | In some cases you may wish to change which container or conda environment a step of the pipeline uses for a particular tool. By default nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However in some cases the pipeline specified version maybe out of date. 200 | 201 | To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/usage/configuration#updating-tool-versions) section of the nf-core website. 202 | 203 | ### Custom Tool Arguments 204 | 205 | A pipeline might not always support every possible argument or option of a particular tool used in pipeline. Fortunately, nf-core pipelines provide some freedom to users to insert additional parameters that the pipeline does not include by default. 206 | 207 | To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/usage/configuration#customising-tool-arguments) section of the nf-core website. 208 | 209 | ### nf-core/configs 210 | 211 | In most cases, you will only need to create a custom config as a one-off but if you and others within your organisation are likely to be running nf-core pipelines regularly and need to use the same settings regularly it may be a good idea to request that your custom config file is uploaded to the `nf-core/configs` git repository. Before you do this please can you test that the config file works with your pipeline of choice using the `-c` parameter. You can then create a pull request to the `nf-core/configs` repository with the addition of your config file, associated documentation file (see examples in [`nf-core/configs/docs`](https://github.com/nf-core/configs/tree/master/docs)), and amending [`nfcore_custom.config`](https://github.com/nf-core/configs/blob/master/nfcore_custom.config) to include your custom profile. 212 | 213 | See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for more information about creating your own configuration files. 214 | 215 | 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). 216 | 217 | ## Azure Resource Requests 218 | 219 | To be used with the `azurebatch` profile by specifying the `-profile azurebatch`. 220 | We recommend providing a compute `params.vm_type` of `Standard_D16_v3` VMs by default but these options can be changed if required. 221 | 222 | Note that the choice of VM size depends on your quota and the overall workload during the analysis. 223 | For a thorough list, please refer the [Azure Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/sizes). 224 | 225 | ## Running in the background 226 | 227 | Nextflow handles job submissions and supervises the running jobs. The Nextflow process must run until the pipeline is finished. 228 | 229 | 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. 230 | 231 | Alternatively, you can use `screen` / `tmux` or similar tool to create a detached session which you can log back into at a later time. 232 | Some HPC setups also allow you to run nextflow within a cluster job submitted your job scheduler (from where it submits more jobs). 233 | 234 | ## Nextflow memory requirements 235 | 236 | In some cases, the Nextflow Java virtual machines can start to request a large amount of memory. 237 | We recommend adding the following line to your environment to limit this (typically in `~/.bashrc` or `~./bash_profile`): 238 | 239 | ```bash 240 | NXF_OPTS='-Xms1g -Xmx4g' 241 | ``` 242 | -------------------------------------------------------------------------------- /subworkflows/nf-core/utils_nfcore_pipeline/main.nf: -------------------------------------------------------------------------------- 1 | // 2 | // Subworkflow with utility functions specific to the nf-core pipeline template 3 | // 4 | 5 | /* 6 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 | SUBWORKFLOW DEFINITION 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | */ 10 | 11 | workflow UTILS_NFCORE_PIPELINE { 12 | take: 13 | nextflow_cli_args 14 | 15 | main: 16 | valid_config = checkConfigProvided() 17 | checkProfileProvided(nextflow_cli_args) 18 | 19 | emit: 20 | valid_config 21 | } 22 | 23 | /* 24 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25 | FUNCTIONS 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | */ 28 | 29 | // 30 | // Warn if a -profile or Nextflow config has not been provided to run the pipeline 31 | // 32 | def checkConfigProvided() { 33 | def valid_config = true as Boolean 34 | if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { 35 | log.warn( 36 | "[${workflow.manifest.name}] You are attempting to run the pipeline without any custom configuration!\n\n" + "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + "Please refer to the quick start section and usage docs for the pipeline.\n " 37 | ) 38 | valid_config = false 39 | } 40 | return valid_config 41 | } 42 | 43 | // 44 | // Exit pipeline if --profile contains spaces 45 | // 46 | def checkProfileProvided(nextflow_cli_args) { 47 | if (workflow.profile.endsWith(',')) { 48 | error( 49 | "The `-profile` option cannot end with a trailing comma, please remove it and re-run the pipeline!\n" + "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" 50 | ) 51 | } 52 | if (nextflow_cli_args[0]) { 53 | log.warn( 54 | "nf-core pipelines do not accept positional arguments. The positional argument `${nextflow_cli_args[0]}` has been detected.\n" + "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" 55 | ) 56 | } 57 | } 58 | 59 | // 60 | // Generate workflow version string 61 | // 62 | def getWorkflowVersion() { 63 | def version_string = "" as String 64 | if (workflow.manifest.version) { 65 | def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' 66 | version_string += "${prefix_v}${workflow.manifest.version}" 67 | } 68 | 69 | if (workflow.commitId) { 70 | def git_shortsha = workflow.commitId.substring(0, 7) 71 | version_string += "-g${git_shortsha}" 72 | } 73 | 74 | return version_string 75 | } 76 | 77 | // 78 | // Get software versions for pipeline 79 | // 80 | def processVersionsFromYAML(yaml_file) { 81 | def yaml = new org.yaml.snakeyaml.Yaml() 82 | def versions = yaml.load(yaml_file).collectEntries { k, v -> [k.tokenize(':')[-1], v] } 83 | return yaml.dumpAsMap(versions).trim() 84 | } 85 | 86 | // 87 | // Get workflow version for pipeline 88 | // 89 | def workflowVersionToYAML() { 90 | return """ 91 | Workflow: 92 | ${workflow.manifest.name}: ${getWorkflowVersion()} 93 | Nextflow: ${workflow.nextflow.version} 94 | """.stripIndent().trim() 95 | } 96 | 97 | // 98 | // Get channel of software versions used in pipeline in YAML format 99 | // 100 | def softwareVersionsToYAML(ch_versions) { 101 | return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(Channel.of(workflowVersionToYAML())) 102 | } 103 | 104 | // 105 | // Get workflow summary for MultiQC 106 | // 107 | def paramsSummaryMultiqc(summary_params) { 108 | def summary_section = '' 109 | summary_params 110 | .keySet() 111 | .each { group -> 112 | def group_params = summary_params.get(group) 113 | // This gets the parameters of that particular group 114 | if (group_params) { 115 | summary_section += "

${group}

\n" 116 | summary_section += "
\n" 117 | group_params 118 | .keySet() 119 | .sort() 120 | .each { param -> 121 | summary_section += "
${param}
${group_params.get(param) ?: 'N/A'}
\n" 122 | } 123 | summary_section += "
\n" 124 | } 125 | } 126 | 127 | def yaml_file_text = "id: '${workflow.manifest.name.replace('/', '-')}-summary'\n" as String 128 | yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" 129 | yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" 130 | yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" 131 | yaml_file_text += "plot_type: 'html'\n" 132 | yaml_file_text += "data: |\n" 133 | yaml_file_text += "${summary_section}" 134 | 135 | return yaml_file_text 136 | } 137 | 138 | // 139 | // ANSII colours used for terminal logging 140 | // 141 | def logColours(monochrome_logs=true) { 142 | def colorcodes = [:] as Map 143 | 144 | // Reset / Meta 145 | colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" 146 | colorcodes['bold'] = monochrome_logs ? '' : "\033[1m" 147 | colorcodes['dim'] = monochrome_logs ? '' : "\033[2m" 148 | colorcodes['underlined'] = monochrome_logs ? '' : "\033[4m" 149 | colorcodes['blink'] = monochrome_logs ? '' : "\033[5m" 150 | colorcodes['reverse'] = monochrome_logs ? '' : "\033[7m" 151 | colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" 152 | 153 | // Regular Colors 154 | colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" 155 | colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" 156 | colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" 157 | colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" 158 | colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" 159 | colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" 160 | colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" 161 | colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" 162 | 163 | // Bold 164 | colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" 165 | colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" 166 | colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" 167 | colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" 168 | colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" 169 | colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" 170 | colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" 171 | colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" 172 | 173 | // Underline 174 | colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" 175 | colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" 176 | colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" 177 | colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" 178 | colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" 179 | colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" 180 | colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" 181 | colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" 182 | 183 | // High Intensity 184 | colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" 185 | colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" 186 | colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" 187 | colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" 188 | colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" 189 | colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" 190 | colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" 191 | colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" 192 | 193 | // Bold High Intensity 194 | colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" 195 | colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" 196 | colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" 197 | colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" 198 | colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" 199 | colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" 200 | colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" 201 | colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" 202 | 203 | return colorcodes 204 | } 205 | 206 | // Return a single report from an object that may be a Path or List 207 | // 208 | def getSingleReport(multiqc_reports) { 209 | if (multiqc_reports instanceof Path) { 210 | return multiqc_reports 211 | } else if (multiqc_reports instanceof List) { 212 | if (multiqc_reports.size() == 0) { 213 | log.warn("[${workflow.manifest.name}] No reports found from process 'MULTIQC'") 214 | return null 215 | } else if (multiqc_reports.size() == 1) { 216 | return multiqc_reports.first() 217 | } else { 218 | log.warn("[${workflow.manifest.name}] Found multiple reports from process 'MULTIQC', will use only one") 219 | return multiqc_reports.first() 220 | } 221 | } else { 222 | return null 223 | } 224 | } 225 | 226 | // 227 | // Construct and send completion email 228 | // 229 | def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdir, monochrome_logs=true, multiqc_report=null) { 230 | 231 | // Set up the e-mail variables 232 | def subject = "[${workflow.manifest.name}] Successful: ${workflow.runName}" 233 | if (!workflow.success) { 234 | subject = "[${workflow.manifest.name}] FAILED: ${workflow.runName}" 235 | } 236 | 237 | def summary = [:] 238 | summary_params 239 | .keySet() 240 | .sort() 241 | .each { group -> 242 | summary << summary_params[group] 243 | } 244 | 245 | def misc_fields = [:] 246 | misc_fields['Date Started'] = workflow.start 247 | misc_fields['Date Completed'] = workflow.complete 248 | misc_fields['Pipeline script file path'] = workflow.scriptFile 249 | misc_fields['Pipeline script hash ID'] = workflow.scriptId 250 | if (workflow.repository) { 251 | misc_fields['Pipeline repository Git URL'] = workflow.repository 252 | } 253 | if (workflow.commitId) { 254 | misc_fields['Pipeline repository Git Commit'] = workflow.commitId 255 | } 256 | if (workflow.revision) { 257 | misc_fields['Pipeline Git branch/tag'] = workflow.revision 258 | } 259 | misc_fields['Nextflow Version'] = workflow.nextflow.version 260 | misc_fields['Nextflow Build'] = workflow.nextflow.build 261 | misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp 262 | 263 | def email_fields = [:] 264 | email_fields['version'] = getWorkflowVersion() 265 | email_fields['runName'] = workflow.runName 266 | email_fields['success'] = workflow.success 267 | email_fields['dateComplete'] = workflow.complete 268 | email_fields['duration'] = workflow.duration 269 | email_fields['exitStatus'] = workflow.exitStatus 270 | email_fields['errorMessage'] = (workflow.errorMessage ?: 'None') 271 | email_fields['errorReport'] = (workflow.errorReport ?: 'None') 272 | email_fields['commandLine'] = workflow.commandLine 273 | email_fields['projectDir'] = workflow.projectDir 274 | email_fields['summary'] = summary << misc_fields 275 | 276 | // On success try attach the multiqc report 277 | def mqc_report = getSingleReport(multiqc_report) 278 | 279 | // Check if we are only sending emails on failure 280 | def email_address = email 281 | if (!email && email_on_fail && !workflow.success) { 282 | email_address = email_on_fail 283 | } 284 | 285 | // Render the TXT template 286 | def engine = new groovy.text.GStringTemplateEngine() 287 | def tf = new File("${workflow.projectDir}/assets/email_template.txt") 288 | def txt_template = engine.createTemplate(tf).make(email_fields) 289 | def email_txt = txt_template.toString() 290 | 291 | // Render the HTML template 292 | def hf = new File("${workflow.projectDir}/assets/email_template.html") 293 | def html_template = engine.createTemplate(hf).make(email_fields) 294 | def email_html = html_template.toString() 295 | 296 | // Render the sendmail template 297 | def max_multiqc_email_size = (params.containsKey('max_multiqc_email_size') ? params.max_multiqc_email_size : 0) as MemoryUnit 298 | def smail_fields = [email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "${workflow.projectDir}", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes()] 299 | def sf = new File("${workflow.projectDir}/assets/sendmail_template.txt") 300 | def sendmail_template = engine.createTemplate(sf).make(smail_fields) 301 | def sendmail_html = sendmail_template.toString() 302 | 303 | // Send the HTML e-mail 304 | def colors = logColours(monochrome_logs) as Map 305 | if (email_address) { 306 | try { 307 | if (plaintext_email) { 308 | new org.codehaus.groovy.GroovyException('Send plaintext e-mail, not HTML') 309 | } 310 | // Try to send HTML e-mail using sendmail 311 | def sendmail_tf = new File(workflow.launchDir.toString(), ".sendmail_tmp.html") 312 | sendmail_tf.withWriter { w -> w << sendmail_html } 313 | ['sendmail', '-t'].execute() << sendmail_html 314 | log.info("-${colors.purple}[${workflow.manifest.name}]${colors.green} Sent summary e-mail to ${email_address} (sendmail)-") 315 | } 316 | catch (Exception msg) { 317 | log.debug(msg.toString()) 318 | log.debug("Trying with mail instead of sendmail") 319 | // Catch failures and try with plaintext 320 | def mail_cmd = ['mail', '-s', subject, '--content-type=text/html', email_address] 321 | mail_cmd.execute() << email_html 322 | log.info("-${colors.purple}[${workflow.manifest.name}]${colors.green} Sent summary e-mail to ${email_address} (mail)-") 323 | } 324 | } 325 | 326 | // Write summary e-mail HTML to a file 327 | def output_hf = new File(workflow.launchDir.toString(), ".pipeline_report.html") 328 | output_hf.withWriter { w -> w << email_html } 329 | nextflow.extension.FilesEx.copyTo(output_hf.toPath(), "${outdir}/pipeline_info/pipeline_report.html") 330 | output_hf.delete() 331 | 332 | // Write summary e-mail TXT to a file 333 | def output_tf = new File(workflow.launchDir.toString(), ".pipeline_report.txt") 334 | output_tf.withWriter { w -> w << email_txt } 335 | nextflow.extension.FilesEx.copyTo(output_tf.toPath(), "${outdir}/pipeline_info/pipeline_report.txt") 336 | output_tf.delete() 337 | } 338 | 339 | // 340 | // Print pipeline summary on completion 341 | // 342 | def completionSummary(monochrome_logs=true) { 343 | def colors = logColours(monochrome_logs) as Map 344 | if (workflow.success) { 345 | if (workflow.stats.ignoredCount == 0) { 346 | log.info("-${colors.purple}[${workflow.manifest.name}]${colors.green} Pipeline completed successfully${colors.reset}-") 347 | } 348 | else { 349 | log.info("-${colors.purple}[${workflow.manifest.name}]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-") 350 | } 351 | } 352 | else { 353 | log.info("-${colors.purple}[${workflow.manifest.name}]${colors.red} Pipeline completed with errors${colors.reset}-") 354 | } 355 | } 356 | 357 | // 358 | // Construct and send a notification to a web server as JSON e.g. Microsoft Teams and Slack 359 | // 360 | def imNotification(summary_params, hook_url) { 361 | def summary = [:] 362 | summary_params 363 | .keySet() 364 | .sort() 365 | .each { group -> 366 | summary << summary_params[group] 367 | } 368 | 369 | def misc_fields = [:] 370 | misc_fields['start'] = workflow.start 371 | misc_fields['complete'] = workflow.complete 372 | misc_fields['scriptfile'] = workflow.scriptFile 373 | misc_fields['scriptid'] = workflow.scriptId 374 | if (workflow.repository) { 375 | misc_fields['repository'] = workflow.repository 376 | } 377 | if (workflow.commitId) { 378 | misc_fields['commitid'] = workflow.commitId 379 | } 380 | if (workflow.revision) { 381 | misc_fields['revision'] = workflow.revision 382 | } 383 | misc_fields['nxf_version'] = workflow.nextflow.version 384 | misc_fields['nxf_build'] = workflow.nextflow.build 385 | misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp 386 | 387 | def msg_fields = [:] 388 | msg_fields['version'] = getWorkflowVersion() 389 | msg_fields['runName'] = workflow.runName 390 | msg_fields['success'] = workflow.success 391 | msg_fields['dateComplete'] = workflow.complete 392 | msg_fields['duration'] = workflow.duration 393 | msg_fields['exitStatus'] = workflow.exitStatus 394 | msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') 395 | msg_fields['errorReport'] = (workflow.errorReport ?: 'None') 396 | msg_fields['commandLine'] = workflow.commandLine.replaceFirst(/ +--hook_url +[^ ]+/, "") 397 | msg_fields['projectDir'] = workflow.projectDir 398 | msg_fields['summary'] = summary << misc_fields 399 | 400 | // Render the JSON template 401 | def engine = new groovy.text.GStringTemplateEngine() 402 | // Different JSON depending on the service provider 403 | // Defaults to "Adaptive Cards" (https://adaptivecards.io), except Slack which has its own format 404 | def json_path = hook_url.contains("hooks.slack.com") ? "slackreport.json" : "adaptivecard.json" 405 | def hf = new File("${workflow.projectDir}/assets/${json_path}") 406 | def json_template = engine.createTemplate(hf).make(msg_fields) 407 | def json_message = json_template.toString() 408 | 409 | // POST 410 | def post = new URL(hook_url).openConnection() 411 | post.setRequestMethod("POST") 412 | post.setDoOutput(true) 413 | post.setRequestProperty("Content-Type", "application/json") 414 | post.getOutputStream().write(json_message.getBytes("UTF-8")) 415 | def postRC = post.getResponseCode() 416 | if (!postRC.equals(200)) { 417 | log.warn(post.getErrorStream().getText()) 418 | } 419 | } 420 | --------------------------------------------------------------------------------