diff --git a/CHANGELOG.md b/CHANGELOG.md index 530200b..25bd82f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Initial release of nf-core/seqinspector, created with the [nf-core](https://nf-c - [#51](https://github.com/nf-core/seqinspector/pull/51) Add nf-test to CI. - [#63](https://github.com/nf-core/seqinspector/pull/63) Contribution guidelines added about displaying results for new tools - [#53](https://github.com/nf-core/seqinspector/pull/53) Add FastQ-Screen database multiplexing and limit scope of nf-test in CI. +- [#67](https://github.com/nf-core/seqinspector/pull/67) Add FASTQ linting for early validation - [#96](https://github.com/nf-core/seqinspector/pull/96) Added missing citations to citation tool ### `Fixed` diff --git a/CITATIONS.md b/CITATIONS.md index 208cfa1..e1811c7 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -10,6 +10,8 @@ ## Pipeline tools +- [FQ](https://github.com/stjude-rust-labs/fq) + - [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) > Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. diff --git a/README.md b/README.md index 6cf36dc..6f25df4 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,10 @@ workflows use the "tube map" design for that. See https://nf-co.re/docs/contributing/design_guidelines#examples for examples. --> +1. Lint FASTQs with ([`fq`](https://github.com/stjude-rust-labs/fq)) 1. Subsample reads ([`Seqtk`](https://github.com/lh3/seqtk)) -2. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) -3. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) +1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) +1. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) ## Usage diff --git a/conf/modules.config b/conf/modules.config index 4a653ed..4e4f33f 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,6 +18,15 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] + withName: 'FQ_LINT' { + ext.args = { params.fq_lint_args } + errorStrategy = { + task.exitStatus in ((130..145) + 104) ? 'retry' : + params.continue_with_lint_fail ? 'ignore' : + 'finish' + } + } + withName: SEQTK_SAMPLE { ext.args = '-s100' } diff --git a/modules.json b/modules.json index 28c9108..91d03f9 100644 --- a/modules.json +++ b/modules.json @@ -26,6 +26,11 @@ "installed_by": ["modules"], "patch": "modules/nf-core/fastqscreen/fastqscreen/fastqscreen-fastqscreen.diff" }, + "fq/lint": { + "branch": "master", + "git_sha": "a1abf90966a2a4016d3c3e41e228bfcbd4811ccc", + "installed_by": ["modules"] + }, "multiqc": { "branch": "master", "git_sha": "f0719ae309075ae4a291533883847c3f7c441dad", diff --git a/modules/nf-core/fq/lint/environment.yml b/modules/nf-core/fq/lint/environment.yml new file mode 100644 index 0000000..74b1460 --- /dev/null +++ b/modules/nf-core/fq/lint/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::fq=0.12.0 diff --git a/modules/nf-core/fq/lint/main.nf b/modules/nf-core/fq/lint/main.nf new file mode 100644 index 0000000..943314c --- /dev/null +++ b/modules/nf-core/fq/lint/main.nf @@ -0,0 +1,33 @@ +process FQ_LINT { + tag "$meta.id" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/fq:0.12.0--h9ee0642_0': + 'biocontainers/fq:0.12.0--h9ee0642_0' }" + + input: + tuple val(meta), path(fastq) + + output: + tuple val(meta), path("*.fq_lint.txt"), emit: lint + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + fq lint \\ + $args \\ + $fastq > ${prefix}.fq_lint.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fq: \$(echo \$(fq lint --version | sed 's/fq-lint //g')) + END_VERSIONS + """ +} diff --git a/modules/nf-core/fq/lint/meta.yml b/modules/nf-core/fq/lint/meta.yml new file mode 100644 index 0000000..7240fb5 --- /dev/null +++ b/modules/nf-core/fq/lint/meta.yml @@ -0,0 +1,43 @@ +name: "fq_lint" +description: fq lint is a FASTQ file pair validator. +keywords: + - lint + - fastq + - validate +tools: + - "fq": + description: "fq is a library to generate and validate FASTQ file pairs." + homepage: "https://github.com/stjude-rust-labs/fq" + documentation: "https://github.com/stjude-rust-labs/fq" + tool_dev_url: "https://github.com/stjude-rust-labs/fq" + licence: ["MIT"] + identifier: "" +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fastq: + type: file + description: FASTQ file list + pattern: "*.fastq{,.gz}" +output: + - lint: + - meta: + type: file + description: Lint output + pattern: "*.fq_lint.txt" + - "*.fq_lint.txt": + type: file + description: Lint output + pattern: "*.fq_lint.txt" + - versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@adamrtalbot" +maintainers: + - "@adamrtalbot" diff --git a/modules/nf-core/fq/lint/tests/main.nf.test b/modules/nf-core/fq/lint/tests/main.nf.test new file mode 100644 index 0000000..ec2eaf8 --- /dev/null +++ b/modules/nf-core/fq/lint/tests/main.nf.test @@ -0,0 +1,63 @@ +nextflow_process { + + name "Test Process FQ_LINT" + script "../main.nf" + process "FQ_LINT" + + tag "modules" + tag "modules_nfcore" + tag "fq" + tag "fq/lint" + + test("test_fq_lint_success") { + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.lint.get(0).get(1) ==~ ".*/test.fq_lint.txt" }, + { assert path(process.out.lint.get(0).get(1)).getText().contains("fq-lint start") }, + { assert path(process.out.lint.get(0).get(1)).getText().contains("read 100 records") }, + { assert path(process.out.lint.get(0).get(1)).getText().contains("fq-lint end") }, + ) + } + + } + + test("test_fq_lint_fail") { + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ] + """ + } + } + + then { + assertAll ( + { assert !process.success }, + { assert snapshot(process.out).match() }, + ) + } + + } + +} diff --git a/modules/nf-core/fq/lint/tests/main.nf.test.snap b/modules/nf-core/fq/lint/tests/main.nf.test.snap new file mode 100644 index 0000000..fec8e52 --- /dev/null +++ b/modules/nf-core/fq/lint/tests/main.nf.test.snap @@ -0,0 +1,25 @@ +{ + "test_fq_lint_fail": { + "content": [ + { + "0": [ + + ], + "1": [ + + ], + "lint": [ + + ], + "versions": [ + + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-10-19T16:37:02.133847389" + } +} \ No newline at end of file diff --git a/modules/nf-core/fq/lint/tests/tags.yml b/modules/nf-core/fq/lint/tests/tags.yml new file mode 100644 index 0000000..9c9c323 --- /dev/null +++ b/modules/nf-core/fq/lint/tests/tags.yml @@ -0,0 +1,2 @@ +fq/lint: + - modules/nf-core/fq/lint/** diff --git a/nextflow.config b/nextflow.config index bb1cb27..a220f59 100644 --- a/nextflow.config +++ b/nextflow.config @@ -13,7 +13,12 @@ params { // Input options input = null sample_size = 0 + + // Options + fq_lint_args = "" + continue_with_lint_fail = false skip_tools = '' + // References genome = null fasta = null diff --git a/nextflow_schema.json b/nextflow_schema.json index 248660b..e5760c7 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -31,7 +31,6 @@ }, "outdir": { "type": "string", - "default": null, "format": "directory-path", "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", "fa_icon": "fas fa-folder-open" @@ -51,7 +50,25 @@ "skip_tools": { "type": "string", "description": "Comma-separated string of tools to skip", - "pattern": "^((fastqc|fastqscreen|seqfu_stats|seqtk_sample)?,?)*(? + [meta, reads] + } + } + // // MODULE: Run Seqtk sample to perform subsampling //